我需要什么样的锁定策略来防止竞争条件?

时间:2015-03-30 11:42:04

标签: mysql sql locking innodb

我正在竞赛网站上工作,其中抽奖逻辑相当简单:每220个参赛作品应该是胜利者。

我在这里简要概述了这个过程:

-- create new entry row
INSERT INTO entries (...) VALUES (...); -- returns 456 as the newly created id

-- get last winner
SELECT id
  FROM entries
 WHERE winner = 1
ORDER
    BY created DESC
 LIMIT 1;

-- see how many entries there have been since
SELECT COUNT(*)
  FROM entries
 WHERE id >  123 -- id selected in last query
   AND id <= 456; -- id of newly created entry

-- if count = 220
UPDATE entries
   SET winner = 1
 WHERE id = 456;

上述逻辑没有考虑竞争条件的可能性。我需要使用什么样的锁定来防止竞争条件发生?

(我正在使用MySQL / InnoDB。)

1 个答案:

答案 0 :(得分:1)

假设您使用的是某种编程语言,这里有一些伪代码:

$last = SELECT MAX(id) FROM tbl WHERE winner=1;
UPDATE tbl SET winner=1 WHERE id > $last LIMIT 1 OFFSET 220; 

没有竞争条件,因为UPDATE在最坏的情况下会设置winner

每次输入行时,您是否正在执行此代码?这可以变成TRIGGER并避免更新。相反,它会根据NEW.winner = 1设置SELECT

相反,如果你是在定期进行,那么你需要重复代码序列,直到它不再更新任何行(rows_affected())。这可以允许自上次更新以来的2 * 220名参赛者。您可以将代码转换为存储过程。

最好有

INDEX(winner, id)