票务预订场景中是否真的需要Serializable隔离级别?
关于Serializable隔离级别的必要性探讨
有文章指出,在购票场景中需要Serializable隔离级别来避免竞态条件,具体场景如下:
time 1 Alice 启动事务:select ticket_avail from concert where id = 1 time 2 Bob 启动事务:select ticket_avail from concert where id = 1 time 3 Alice 执行更新:update concert set ticket_avail = ticket_avail - 1 where id = 1 time 4 Bob 执行更新:update concert set ticket_avail = ticket_avail - 1 where id = 1
当只剩1张票时,上述操作会引发竞态,导致两张票都被“卖出”,因此文章认为必须使用Serializable隔离级别。
但实际上,数据库的更新操作会自动锁定目标行并检查最新提交的值,我们可以通过优化更新语句来规避这个问题,示例如下:
time 1 Alice 启动事务: select ticket_avail from concert where id = 1 time 2 Bob 启动事务: select ticket_avail from concert where id = 1 time 3 Alice 执行更新: update concert set ticket_avail = ticket_avail - 1 where id = 1 and ticket_avail > 0 time 4 Bob 执行更新: update concert set ticket_avail = ticket_avail - 1 where id = 1 and ticket_avail > 0
在这个方案中,Alice会成功抢到最后一张票,Bob的更新会因ticket_avail > 0条件不满足而失败——因为更新时会重新评估where子句,此时票量已经被Alice减至0。
那么问题来了:在这个购票场景中,真的需要Serializable隔离级别吗?
内容的提问来源于stack exchange,提问作者user21872982
相关产品推荐
相关产品推荐

