【问题标题】:MySQL Table Locking (Read)MySQL 表锁定(读取)
【发布时间】:2013-08-27 11:59:56
【问题描述】:

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

....

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

ID int(10) PK, Status enum('ready', 'in progress', 'complete'); 1“准备好” 2'准备好了' 3'准备好了'

....

然后我有一个 API,当查询返回“就绪”项目的 ID 时,该 API 可以同时调用多次,我想确保 ID 只给出一次。

....

API MySQL 查询..

锁定表`链接`写 SELECT ID FROM links WHERE status = 'ready' LIMIT 1 // 得到一个准备好的 UPDATE links SET status = 'in progress' WHERE ID = 'X' // 更新刚刚从上面一行获得的链接正在进行中(因此未被另一个 API 调用选择 解锁桌子

因此,如果两个 API 调用相隔 0.01 秒,第一个应该锁定表更新它进行中,解锁后第二个有机会并做同样的事情,但选择与第一个不同的 ID .

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

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

【问题讨论】:

  • ID 是唯一的,即由每个访问者创建还是设置并分配给访问者?
  • 不,它只是一个充满了具有唯一 ID 的资料的数据库,并且对 API 的每次调用都应该提供不同的 ID,不要欺骗。

标签: php mysql sql locking innodb


【解决方案1】:

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

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 将在事务期间仅在一个更新的行上放置写锁,而其他行未锁定。

【讨论】:

  • 谢谢,如果我在命令行或 phpmyadmin 中运行它,这是有道理的并且有效,但不是在 PHP 中,因为我需要执行两个事务,因此每个事务之后都会发送一个提交。我还需要将“id”作为查询之外的变量返回。
  • 我不是很了解PHP,但是我找到了一个如何在PHP中处理SQL事务的例子,看看这个链接:stackoverflow.com/questions/2708237/…
  • 很好,从那个链接理解了 PHP 中的事务,这似乎现在可以工作了 - 应该在早上再次测试并接受这个答案。提前致谢。
猜你喜欢
  • 2012-08-08
  • 1970-01-01
  • 2012-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多