忽略MySQL查询中的锁定行

时间:2010-11-05 19:40:03

标签: mysql locking race-condition

我有一个表由不同的线程同时读取。

每个线程必须选择100行,在每行上执行一些任务(与数据库无关),然后他们必须从表中删除所选行。

使用此查询选择

行:

SELECT id FROM table_name FOR UPDATE;

我的问题是:如何忽略(或跳过)先前在MySQL中使用select语句锁定的行?

2 个答案:

答案 0 :(得分:15)

我通常创建一个默认为NULL的process_id列,然后让每个线程使用唯一标识符来执行以下操作:

UPDATE table_name SET process_id = #{process.id} WHERE process_id IS NULL LIMIT 100;

SELECT id FROM table_name WHERE process_id = #{process.id} FOR UPDATE;

确保每个线程从表中选择一组唯一的行。

希望这有帮助。

答案 1 :(得分:0)

即使它不是最好的解决方案,因为我无法忽略锁定的行,我选择一个随机的并尝试获取锁定。

START TRANSACTION;
SET @v1 =(SELECT myId FROM tests.table WHERE status is NULL LIMIT 1);
SELECT * FROM tests.table WHERE myId=@v1 FOR UPDATE; #<- lock

为事务设置一个小超时,如果该行被锁定,则事务被中止,我尝试另一个。如果我获得了锁,我会处理它。如果(运气不好)该行被锁定,它会被处理并且在我的超时之前释放锁,然后我选择一个已被“处理​​”的行!但是,我检查了我的进程设置的字段(例如状态):如果其他进程事务结束正常,该字段告诉我工作已经完成,我不再处理该行。

没有事务的每个其他可能的解决方案(例如,如果行没有状态设置另一个字段等等)可以轻松提供竞争条件和错过的进程(例如,一个线程突然死亡,分配的数据仍然被标记,而交易到期;参考评论here

希望有所帮助