Mysql 将使用范围谓词“UPDATE语句”;“更喜欢”;非锁定行

Mysql 将使用范围谓词“UPDATE语句”;“更喜欢”;非锁定行,mysql,sql-update,mysql-5.7,Mysql,Sql Update,Mysql 5.7,给定一个名为workers的表和一个包含列leaderId,lastUpdated的架构。当多个DB连接运行此UPDATE语句时,是否会首先考虑更新满足谓词(WHERE子句)的未锁定行,还是将查询块放在已锁定的匹配行上?如果不首先考虑解锁,有没有办法做到这一点 BEGIN UPDATE workers SET leaderId = ?, lastUpdated = NOW(6) WHERE lastUpdated IS NULL OR lastUpdated < DATE_SUB(NOW

给定一个名为
workers
的表和一个包含列
leaderId
lastUpdated
的架构。当多个DB连接运行此
UPDATE
语句时,是否会首先考虑更新满足谓词(
WHERE
子句)的未锁定行,还是将查询块放在已锁定的匹配行上?如果不首先考虑解锁,有没有办法做到这一点

BEGIN
UPDATE workers SET leaderId = ?, lastUpdated = NOW(6) 
WHERE lastUpdated IS NULL OR lastUpdated < DATE_SUB(NOW(6),INTERVAL 3 SECOND)
LIMIT 1;

SELECT * FROM workers WHERE leaderId = ?;
COMMIT
开始
更新工人集leaderId=?,lastUpdated=NOW(6)
其中lastUpdated为NULL或lastUpdated
简短回答:否

长答覆:

要么全部,要么一个也没有。这是InnoDB“交易”的首要任务。您的
BEGIN
COMMIT
控制事务的范围

DATE\u SUB(现在(6),间隔3秒)
NOW(6)
将在
UPDATE
语句的开头计算一次

您有
限制1
,但没有
订购人
。这意味着您无法预测将拾取哪一行。但是,优化器不会根据执行查询的速度以外的任何其他因素来选择行,而不考虑可能锁定的内容

看起来您正在实现一个“队列”?
UPDATE
“抓取”一行,然后
SELECT
获取该行中的数据

优化效果不佳。一般来说,没有索引是有用的,因此
UPDATE
将以某种方便的顺序扫描整个表,在发现满足一个或另一个条件时停止

通常的优化是将其分为两个查询。这可能意味着更改总体逻辑,使主代码获取一个
NULL
。还有一个单独的“收割机”流程,围绕着抓取任何“旧”物品(可能是由于工人崩溃而成为孤儿)运行

(我不太愿意建议重写,因为我不完全理解您的逻辑。我希望表
队列
将被执行,而不是
工作者
。因此,请解释您的代码。我可能有其他提示。)

mysql8.0的
选择…进行更新
语法的一部分。但是,它在MySQL-5.7中不可用