如何避免MySQL中的竞争条件

时间:2014-03-21 14:12:46

标签: mysql sql transactions race-condition

在我正在开发的应用程序中,我有潜在的竞争条件,我希望在我的查询中考虑并避免。

总结申请流程......

  1. entries表中创建一个新行:

    INSERT INTO entries ( name, email ) VALUES ( 'Foo Bar', 'foo@example.com' );

  2. 通过查看时间敏感的prizes表,了解Bar先生是否是赢家:

    SELECT id FROM prizes WHERE various_time_conditions = 'met' AND id NOT IN ( SELECT prize_id FROM entries );

  3. 如果他是胜利者,请相应更新他的输入行:

    UPDATE entries SET prize_id = [prize id] WHERE id = [entry id];

  4. 由于每个奖项只能发出一次,我需要消除任何竞争条件的可能性,其中另一个进程可以查询奖品表并更新上述步骤2和3之间的条目表。

    我一直在做一些研究,发现了很多关于交易的信息(我所有的表都使用InnoDB)和使用MySQL的SELECT ... FOR UPDATE语法,但我对此感到困惑。这对我来说是最合适的解决方案。

1 个答案:

答案 0 :(得分:4)

您将要锁定奖品记录。因此,如果您不打算使用像winner_id这样的东西,请在奖品表上添加一些可用性标志(可能带有默认值)。像这样:

SELECT id FROM prizes WHERE ... AND available = 1 FOR UPDATE

如果您确定了奖品,请设置可用性:

UPDATE prizes SET available = 0 WHERE id = ...

当然,你需要将它包装在一个事务中。

确保每次检查奖品是否可用,您为查询添加了AND available = 1 FOR UPDATE,因为SELECT没有FOR UPDATE不要等待锁定。