php - MySQL 表锁定(读)

标签 php mysql sql locking innodb

这是我从未完全掌握的事情,我想知道我是否做得正确并检查其是否健全。

...

我有一个数据库链接,让其保持简单,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/

相关文章:

php - 如何使用php生成随机人名?

php - 2个mysql表,单行链接到另一个表中的多个条目。我怎样才能只获得单行一次而不是每个其他条目

mysql - 错误 : function crashed. 详细信息:连接 ECONNREFUSED/cloudsql/<实例连接名称>>

MySQL:Select then Update 和 UPDATE 哪个更好?

sql - 外键引用跨多个表的主键?

php - 将从 XML 文件中提取的数据插入到 MySQL 表中

PHP:我得到一个完全空白的页面,我不知道如何在 PHP 中调试它

MySql 多个数据库。如何插入?

SQL 脚本出错需要帮助恢复导致问题的列名称中的 '[' 字符

sql - 将 PL/SQL 代码转换为 SQLite