我们正在使用 MySQL InnoDB。系统支持可以同时发生的多个请求。 这是我们想要实现的目标的简化示例。 假设我们有一个表,其中包含代表灯泡的实体。这些灯泡可以由用户打开(激活)。用户可以将灯泡添加到表中,这些灯泡最初是停用的,并且只有 10 个可以标记为启用。因此我们的限制为 10。由于系统支持并发,因此存在竞争条件的风险,如下例所示:
第 1 节:
1:获取事件灯泡数量
2:检查激活灯泡的数量
3:如果尚未达到限制,则激活灯泡并提交。
4:否则回滚。
这里的问题是,在第 2 步和第 4 步期间,另一个 session 可能会进入,并可能最终超出限制。
这是我们当前正在做的事情的 SQL 表示:
- 从 tbl WHERE is_active = 1 中选择 count(id) AS 总计;
- 如果(总计 < 10){
- 激活另一个灯泡; }其他{
- 回滚; }
对于这种情况,您建议采用什么解决方案? 我们正在考虑“选择更新”,但如果我没记错的话,会锁定选定的行,并且用户可以在选定的行处于锁定状态时将灯泡添加到表中。
谢谢。
最佳答案
BEGIN; -- start a "transaction"
do the 4 steps
COMMIT; -- or ROLLBACK
注意:任何可能导致UPDATE
的SELECT
都需要说FOR UPDATE
。
和/或,研究如何在 UPDATE
中完成更多工作(请参阅 chord 的回答)。或者 INSERT ... ON DUPLICATE KEY UPDATE ...
请记住,INSERT
和 UPDATE
可以报告有多少行受到影响。这可以用来“假设任务会成功”,然后检查它是否成功,如果失败则采取规避措施。
关于php - 如何避免 MySQL InnoDB 中的竞争条件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41538165/