【问题标题】:How to properly avoid Mysql Race Conditions如何正确避免 Mysql 竞争条件
【发布时间】:2013-08-27 08:08:10
【问题描述】:

我知道以前有人问过这个问题,但我仍然很困惑,如果可能的话,我想在开始编程之前避免任何问题。

我计划在任何给定时间建立一个至少有 100 名活跃用户的内部网站。用户将发布一个项目(以 0 作为其值插入到 db 中),该项目将通过 php 站点(db 查询)显示。然后用户可以选择按下按钮并将该项目锁定为他们的(将该项目的值分配为他们的 id)

如何确保 2 个或更多用户不会同时检索同一个项目。我知道在像 c++ 这样的编程中,我只会使用普通的 ol 互斥锁。它们是 mysql 中的等价物,它只会锁定一个这样的项目条目吗?我已经看到对 LOCK_TABLES 和 GET_LOCK 以及许多其他的引用,所以我仍然对什么是最好的感到非常困惑。

很多人都有可能竞相按下一个按钮,如果多人得到确认,那将是灾难性的。

我知道这是竞争条件的一个典型例子,但 mysql 对我来说是陌生的领域。

我显然会在更新之前查询项目的值并确保它没有写入,但是确保避免这种竞争条件的最佳方法是什么。

提前致谢。

【问题讨论】:

    标签: mysql database locking race-condition


    【解决方案1】:

    要实现这一点,您需要以某种方式锁定记录。 添加一列 LockedBy 默认为 0。

    当有人按下按钮时,执行类似这样的查询:

    UPDATE table SET LockedBy= WHERE LockedBy=0 and id=;

    更新后验证受影响的行(在 php mysql_affected_rows 中)。如果值为 0,则表示查询没有更新任何内容,因为 LockedBy 列不为 0,因此被其他人锁定。

    希望对你有帮助

    【讨论】:

    • 为什么要创建一个全新的列?您不能在现有列上使用相同的策略吗?
    【解决方案2】:

    当您发布一行时,将列设置为 NULL,而不是 0。

    然后当用户更新该行以使其成为自己的行时,更新如下:

    UPDATE MyTable SET ownership = COALESCE(ownership, $my_user_id) WHERE id = ...
    

    COALESCE() 返回它的第一个非空参数。因此,即使您和我同时更新,第一个提交的也可以设置值。第二个不会覆盖该值。

    【讨论】:

      【解决方案3】:

      你可以考虑交易

      BEGING TRANSACTION;
      SELECT ownership FROM ....; 
      UPDATE table .....; // set the ownership if the table not owned yet
      COMMIT;
      

      如果您发现错误,您还可以回滚事务之间的所有查询!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-06-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-30
        • 2010-09-25
        相关资源
        最近更新 更多