这是我从未完全掌握的事情,我想知道我是否做得正确并检查其是否健全。
...
我有一个数据库链接
,让其保持简单,2 列
ID int(10) PK, Status enum('ready', 'in progress', 'complete'); 1 'ready' 2 'ready' 3 'ready'
...
然后,我有一个 API,当查询时返回“就绪”项目的 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 行,有一个状态索引,提前感谢您的任何建议或指示。
最佳答案
您不需要锁定整个表。
只要这样做:
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;
这些命令将在读提交隔离级别及更高级别下工作。
由于“status”列上有索引,MySql 将在事务期间仅对一个更新的行放置写锁,而使其他行保持解锁状态。
关于php - MySQL 表锁定(读),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18464778/