Rex*_*Rex 8 mysql transactions
我通过以下查询在一个事务中锁定了一行
START TRANSACTION;
SELECT id FROM children WHERE id=100 FOR UPDATE;
Run Code Online (Sandbox Code Playgroud)
在另一个交易中,我有一个查询如下
START TRANSACTION;
SELECT id FROM children WHERE id IN (98,99,100) FOR UPDATE;
Run Code Online (Sandbox Code Playgroud)
它会超出错误锁定等待超时.
这里100已被锁定(在第一次交易中)但是ids 98,99没有被锁定.如果在上面的查询中只有100行被锁定,那么有任何可能返回98,99的记录.所以结果应该如下
ID
===
98
99
===
应忽略Id 100,因为100被事务锁定.
ake*_*den 11
看起来SKIP LOCKED
以前的答案中提到的选项现在在 MySQL 中可用。它不会等待获取行锁,并允许您处理当前未锁定的行。
从MySQL 8.0.0 发行说明/MySQL 8.0.1 中的更改开始:
InnoDB的现在支持
NOWAIT
,并SKIP LOCKED
有选择SELECT ... FOR SHARE
和SELECT ... FOR UPDATE
锁定读语句。NOWAIT
如果请求的行被另一个事务锁定,则使语句立即返回。SKIP LOCKED
从结果集中删除锁定的行。请参阅使用NOWAIT
和锁定读取并发性SKIP LOCKED
。
示例用法(可以在上面的链接中找到带有输出的完整示例):
START TRANSACTION;
SELECT * FROM tableName FOR UPDATE SKIP LOCKED;
Run Code Online (Sandbox Code Playgroud)
此外,在此处的参考手册中包含警告可能也不错:
跳过锁定行的查询会返回不一致的数据视图。
SKIP LOCKED
因此不适合一般事务性工作。但是,当多个会话访问同一个类似队列的表时,它可以用来避免锁争用。
MySQL没有办法忽略SELECT中的锁定行.您必须找到一种不同的方法将行设置为"已处理".
最简单的方法是在第一个查询中短暂锁定行只是为了将其标记为"已处理",然后将其解锁并再次锁定以进行剩余的处理 - 第二个查询将等待短"标记"查询到完成后,您可以添加显式WHERE条件以忽略已标记的行.如果您不想依赖第一个能够成功完成的操作,则可能需要在时间戳上添加更多复杂性,以便在这些操作失败后进行清理.
归档时间: |
|
查看次数: |
5090 次 |
最近记录: |