php - 如何避免 MySQL InnoDB 中的竞争条件?

标签 php mysql transactions innodb laravel-5.3

我们正在使用 MySQL InnoDB。系统支持可以同时发生的多个请求。 这是我们想要实现的目标的简化示例。 假设我们有一个表,其中包含代表灯泡的实体。这些灯泡可以由用户打开(激活)。用户可以将灯泡添加到表中,这些灯泡最初是停用的,并且只有 10 个可以标记为启用。因此我们的限制为 10。由于系统支持并发,因此存在竞争条件的风险,如下例所示:

第 1 节:

1:获取事件灯泡数量

2:检查激活灯泡的数量

3:如果尚未达到限制,则激活灯泡并提交。

4:否则回滚。

这里的问题是,在第 2 步和第 4 步期间,另一个 session 可能会进入,并可能最终超出限制。

这是我们当前正在做的事情的 SQL 表示:

  1. 从 tbl WHERE is_active = 1 中选择 count(id) AS 总计;
  2. 如果(总计 < 10){
  3. 激活另一个灯泡; }其他{
  4. 回滚; }

对于这种情况,您建议采用什么解决方案? 我们正在考虑“选择更新”,但如果我没记错的话,会锁定选定的行,并且用户可以在选定的行处于锁定状态时将灯泡添加到表中。

谢谢。

最佳答案

BEGIN;   -- start a "transaction"
do the 4 steps
COMMIT;  -- or ROLLBACK

注意:任何可能导致UPDATESELECT都需要说FOR UPDATE

和/或,研究如何在 UPDATE 中完成更多工作(请参阅 chord 的回答)。或者 INSERT ... ON DUPLICATE KEY UPDATE ...

请记住,INSERTUPDATE 可以报告有多少行受到影响。这可以用来“假设任务会成功”,然后检查它是否成功,如果失败则采取规避措施。

关于php - 如何避免 MySQL InnoDB 中的竞争条件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41538165/

相关文章:

c# - 在 Azure Functions v2 上使用 MySqlDatabase (MySql.Data.MySqlClient) - "Unable to resolve service"

java - Java 中的 MySQL 事务

java - @Transactional 注解属于哪里?

php - Libreoffice headless Process 结果不返回,而是等待超时

php - 通过 PHP 代码访问我的 Gmail 收件箱

php mysql 获取总价

mysql - 如何使用 C# Visual Studio 执行 MySql 存储过程

Mysql事务不起作用

javascript - 在 HTML 中请求时用 PHP 生成 JavaScript 文件

php gnupg get_key 失败错误