如何正确避免Mysql竞争条件

时间:2012-12-18 04:06:40

标签: mysql database locking race-condition

我知道之前已经问过这个问题,但是如果可能的话,我仍然感到很困惑并希望避免任何问题。

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

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

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

我知道这是竞争条件的一个主要例子,但mysql对我来说是外国领土。

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

提前致谢。

3 个答案:

答案 0 :(得分:2)

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

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

UPDATE表SET LockedBy = WHERE LockedBy = 0和id =;

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

希望这有帮助

答案 1 :(得分:2)

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

然后,当用户更新行以使其成为自己的行时,请按如下所示进行更新:

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

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

答案 2 :(得分:0)

您可以考虑交易

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

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