这是我从未完全掌握的东西,想要知道我是否正确行事,并且检查它是否合理。
...
我有一个数据库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,状态为索引,如有任何建议或指示,请提前感谢。
答案 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将在事务持续期间仅在一个更新的行上放置一个写锁,而其他行则解锁。