MySQL表锁定(读取)

时间:2013-08-27 11:59:57

标签: php mysql sql locking innodb

这是我从未完全掌握的东西,想要知道我是否正确行事,并且检查它是否合理。

...

我有一个数据库links,让我们保持简单,2列

ID int(10) PK, Status enum('ready', 'in progress', 'complete');
1 'ready'
2 'ready'
3 'ready'

...

然后我有一个API,当查询返回'ready'项的ID时,可以多次同时调用此API,我想确保ID只发出一次。

...

API MySQL查询..

LOCK TABLES `links` WRITE
SELECT ID FROM links WHERE status = 'ready' LIMIT 1 // gets a ready one
UPDATE links SET status = 'in progress' WHERE ID = 'X' // updates the one just got from line above to be in progress (so not selected by another API call
UNLOCK TABLES

因此,如果两个API调用相隔0.01秒,第一个应该锁定表更新它正在进行中,解锁后第二个获得它的机会并做同样的但是选择不同的ID到第一个得到的

这是对的吗?或者做这种事情的最佳方式?因为它似乎导致MySQL流量的长时间延迟,一些查询等待5分钟左右,然后MySQL命中最大连接,这会导致各种其他问题。

该表是InnoDB,相对较小,行数约为165k,状态为索引,如有任何建议或指示,请提前感谢。

1 个答案:

答案 0 :(得分:0)

您无需锁定整张桌子 只是做:

UPDATE links SET status = 'in progress' 
WHERE status = 'Ready'
LIMIT 1;

或者,如果要检索更新的ID,请使用:

start transaction;
select id into @xx from links
where status = 'Ready'
limit 1 for update;
update links set status = 'in progress'
where id = @xx;
commit;

这些命令将在读取提交的isloation级别和更高级别中起作用 由于'status'列上有索引,MySql将在事务持续期间仅在一个更新的行上放置一个写锁,而其他行则解锁。