我正在开发一个在线预订系统。简单来说,用户可以预订多个项目,每个项目只能被预订一次。项目首先添加到购物车。
应用程序使用 MySql
/ InnoDB
数据库。根据 MySql 文档, 默认隔离级别为 可重复读取(Repeatable reads)
。
这是目前我想出的结帐过程:
- 开始事务
- 选择在购物车中的项目(使用带有
for update
锁定的方式)
在此步骤中,从cart-item
和items
表中获取记录。- 检查是否有其他人已经预订了这些项目
基本上是检查quantity > 0
。在实际应用中,它更加复杂,因此我将其作为单独的步骤放在这里。- 更新项目,将
quantity = 0
同时执行其他必要的数据库操作。- 进行支付(通过外部 API 如 PayPal 或 Stripe)
由于支付细节可以在结帐之前收集,因此不需要用户交互。- 如果一切顺利,则提交事务或回滚,否则
- 继续进行非关键逻辑
在成功时发送电子邮件等,在错误时重定向。
我不确定是否足够。我担心是否:
- 其他在同时预订相同项目的用户将正确处理。他的事务
T2
会等待直到T1
完成吗? - 使用 PayPal 或 Stripe 进行付款可能需要一些时间。这在性能方面是否会成为问题?
- 项目的可用性是否始终正确显示(项目应该在结帐成功之前一直可用)。这些只读选择是否应使用
共享锁(shared lock)
?
以下是我阅读过的一些资源:处理数据库中的并发更新、MySQL:事务 vs 锁定表、数据库事务是否可以防止竞争条件?、隔离(数据库系统)、InnoDB锁定和事务模型、数据库锁定和丢失更新现象初学者指南。
重新编写我的原始问题,使其更加通用。
添加了后续问题。
SELECT ... FOR UPDATE
语句时,你是选择已经存在的行,还是选择你计划插入的行? - Willem Renzemacart-item
透视表仅选择已存在的行。 - Paul