简体   繁体   English

如何正确避免Mysql竞争条件

[英]How to properly avoid Mysql Race Conditions

I know this has been asked before, but I'm still confused and would like to avoid any problems before I go into programming if possible. 我知道之前已经问过这个问题,但是如果可能的话,我仍然很困惑并希望避免任何问题。

I plan on having an internal website with at least 100 users active at any given time. 我打算建立一个内部网站,在任何给定时间内至少有100个用户活跃。 Users would post an item (inserted into db with a 0 as its value) and that item would be shown via a php site (db query). 用户将发布一个项目(插入到db中,其值为0),该项目将通过php站点(db query)显示。 Users then get the option to press a button and lock that item as theirs (assign the value of that item as their id) 然后,用户可以选择按下按钮并将该项目锁定为他们的项目(将该项目的值指定为其ID)

How do I ensure that 2 or more users don't retrieve the same item at the same time. 如何确保2个或更多用户不能同时检索同一个项目。 I know in programming like c++ I would just use plain ol mutex lock. 我知道在c ++这样的编程中我只会使用普通的ol互斥锁。 Is their an equivalent in mysql where it will lock just one item entry like that? 他们是mysql中的等价物,它会锁定一个项目条目吗? I've seen references to LOCK_TABLES and GET_LOCK and many others so I'm still very confused on what would be best. 我已经看过对LOCK_TABLES和GET_LOCK以及其他许多人的引用,所以我仍然对最好的东西感到困惑。

There is potential for many people all racing to press that one button and it would be disastrous if multiple people get a confirmation. 许多人都有可能竞相按下那个按钮,如果多人得到确认,那将是灾难性的。

I know this is a prime example of a race condition, but mysql is foreign territory for me. 我知道这是竞争条件的一个主要例子,但mysql对我来说是外国领土。

I obviously will query the value of the item before I update it and make sure it hasn't written, but what is the best way to ensure that this race condition is avoided. 我显然会在更新它之前查询该项的值并确保它没有写入,但是确保避免这种竞争条件的最佳方法是什么。

Thanks in advance. 提前致谢。

To achieve this, you will need to lock the record somehow. 要实现这一点,您需要以某种方式锁定记录。 Add a column LockedBy defaulting to 0. 添加一列LockedBy默认为0。

When someone pushes the button execute a query resembling this: 当有人按下按钮时执行类似这样的查询:

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

After the update verify the affected rows (in php mysql_affected_rows). 更新后验证受影响的行(在php mysql_affected_rows中)。 If the value is 0 it means the query did not update anything because the LockedBy column is not 0 and thus locked by someone else. 如果值为0,则表示查询未更新任何内容,因为LockedBy列不为0,因此被其他人锁定。

Hope this helps 希望这可以帮助

When you post a row, set the column to NULL, not 0. 发布行时,将列设置为NULL,而不是0。

Then when a user updates the row to make it their own, update it as follows: 然后,当用户更新行以使其成为自己的行时,请按如下所示进行更新:

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

COALESCE() returns its first non-null argument. COALESCE()返回其第一个非null参数。 So even if you and I are updating concurrently, the first one to commit gets to set the value. 因此,即使您和我同时更新,第一个提交的设置也可以设置该值。 The second one will not override that value. 第二个不会覆盖该值。

You may consider Transactions 您可以考虑交易

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

and also you can ROLLBACK all the queries between the transaction if you caught an error ! 如果您发现错误,也可以在事务之间回滚所有查询!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM