我们正在使用MySQL InnoDB。系统支持可同时发生的多个请求。 以下是我们试图实现的简化示例。 假设我们有一个表格,其中包含代表灯泡的实体。这些灯泡可以由用户打开(激活)。用户可以将灯泡添加到最初停用的表中,并且只有10个灯泡可以标记为已激活。所以我们有一个10的限制。由于系统支持并发,基于以下示例存在竞争条件的风险:
会议1:
1:获取活动灯泡的数量
2:检查激活的灯泡数量
3:如果尚未达到限制,请启动灯泡并提交。
4:否则回滚。
这里的问题是,在第2步和第4步中,另一个会话可能会进入并可能最终超过限制。
这是我们当前正在做的事情的SQL表示:
您对此方案的解决方案有何建议? 我们正在考虑“选择更新”但是,如果我没有弄错,锁定选定的行,用户可以在选定的行处于锁定状态时向表中添加灯泡。
谢谢。
答案 0 :(得分:0)
一个想法是保留一个单独的锁定表,您可以在其中管理此限制要求,并仅对活动灯泡的数量进行原子更新,如:
update active_bulb_count
set active_count = active_count + 1
where active_count < limit
and <any other conditions needed>;
如果没有更新行,您知道已达到限制,那么您就不会将灯泡设置为活动状态。
您可能仍应考虑执行此操作的会话的事务设置。查看有关原子更新和事务MySQL Atomic UPDATE in InnoDB vs MyISAM
的更多详细信息答案 1 :(得分:0)
BEGIN; -- start a "transaction"
do the 4 steps
COMMIT; -- or ROLLBACK
注意:任何可能导致SELECTs
的{{1}}需要说UPDATE
。
和/或,研究如何在FOR UPDATE
中完成更多工作(参见churd的回答)。或UPDATE
请注意,INSERT ... ON DUPLICATE KEY UPDATE ...
和INSERT
可以报告受影响的行数。这可以用来“假设任务成功”,然后检查它是否成功,如果失败则采取规避行动。