Php MySQL表锁定(读取)

Php MySQL表锁定(读取),php,mysql,sql,locking,innodb,Php,Mysql,Sql,Locking,Innodb,这是我从未完全掌握过的东西,我想知道我是否做得对,并检查它是否正常 我有一个数据库链接,让我们保持简单,2列 ID int(10) PK, Status enum('ready', 'in progress', 'complete'); 1 'ready' 2 'ready' 3 'ready' ID int(10)PK,状态枚举(“就绪”、“进行中”、“完成”); 1“准备就绪” 2“准备就绪” 3“准备就绪” 然后,我有一个API,当查询返回“ready”项的ID时,可以同时多次调用该A

这是我从未完全掌握过的东西,我想知道我是否做得对,并检查它是否正常

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

ID int(10) PK, Status enum('ready', 'in progress', 'complete'); 1 'ready' 2 'ready' 3 'ready' ID int(10)PK,状态枚举(“就绪”、“进行中”、“完成”); 1“准备就绪” 2“准备就绪” 3“准备就绪”

然后,我有一个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 锁表`链接`写入 从status='ready'LIMIT 1//获取就绪ID的链接中选择ID 更新链接集状态='in progress',其中ID='X'//将刚从上一行获取的链接更新为正在进行中(因此未被另一个API调用选中 解锁表格 因此,如果两个API调用相隔0.01秒命中它,第一个API调用应该锁定表并将其更新为进行中,在解锁第二个API调用后,第二个API调用获得机会并执行相同操作,但选择与第一个API调用不同的ID

这是正确的吗?还是最好的方法?因为它似乎会导致MySQL流量的长时间延迟,一些查询等待5分钟左右,然后MySQL达到最大连接数,从而导致各种其他问题


该表是InnoDB,相对较小,大约有165k行,状态索引,提前感谢您提供的任何建议或指针。

您不需要锁定整个表。
只要做:

或者,如果要检索更新的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;
这些命令将在读取提交的孤岛级别及更高级别下工作。

由于“状态”列上有索引,MySql将在事务期间只在一个更新的行上放置写锁,而不锁定其他行。

id是唯一的,即与每个访问者创建的,还是设置并分配给访问者的?不,它只是一个满是具有唯一id的内容的数据库,对API的每次调用都应该是唯一的请提供一个不同的ID,不要重复。谢谢,如果我在命令行或phpmyadmin中运行它,这是有意义的,并且是有效的,但是不是在PHP中,因为我需要做两个事务,因此每个事务之后都会发送一个提交。我需要“ID”作为查询之外的变量返回。我对PHP不太了解,但我发现了一个如何在PHP中处理SQL事务的示例,请查看此链接:很好,从该链接中理解了PHP中的事务,这似乎正在工作-早上将再次测试并接受此答案。提前感谢。
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;