MySQL InnoDB“选择更新”-等同于“跳过锁定”

Bas*_*ast 4 mysql sql concurrency multithreading innodb

当我们使用InnoDB表在MySQL中进行“ SELECT FOR UPDATE”时,有什么方法可以跳过“锁定行”吗?

例如:终端t1

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select id from mytable ORDER BY id ASC limit 5 for update;
+-------+
| id    |
+-------+
|     1 |
|    15 |
| 30217 |
| 30218 |
| 30643 |
+-------+
5 rows in set (0.00 sec)

mysql> 
Run Code Online (Sandbox Code Playgroud)

同时,终端t2:

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select id from mytable where id>30643 order by id asc limit 2 for update;
+-------+
| id    |
+-------+
| 30939 |
| 31211 |
+-------+
2 rows in set (0.01 sec)

mysql> select id from mytable order by id asc limit 5 for update;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> 
Run Code Online (Sandbox Code Playgroud)

因此,如果我启动一个查询来强制它选择其他行,那很好。

但是有没有办法跳过锁定的行?

我猜这在并发过程中应该是一个冗余的问题,但是我没有找到任何解决方案。


编辑:实际上,我不同的并发进程正在做的事情显然非常简单:

  1. 采取第一行(不包含特定标志-例如:“ WHERE myflag_inUse!= 1”)。

  2. 一旦获得“选择更新”的结果,就更新标志并提交行。

所以我只想选择尚未锁定的行以及myflag_inUse!= 1 ...


以下链接可帮助我了解为什么会超时,但无法避免超时:

MySQL“选择更新”行为


mysql> SHOW VARIABLES LIKE "%version%";
+-------------------------+-------------------------+
| Variable_name           | Value                   |
+-------------------------+-------------------------+
| innodb_version          | 5.5.46                  |
| protocol_version        | 10                      |
| slave_type_conversions  |                         |
| version                 | 5.5.46-0ubuntu0.14.04.2 |
| version_comment         | (Ubuntu)                |
| version_compile_machine | x86_64                  |
| version_compile_os      | debian-linux-gnu        |
+-------------------------+-------------------------+
7 rows in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

Vla*_*cea 8

MySQL的8.0引入了两个支持SKIP LOCKEDNO WAIT

SKIP LOCKED 对于实现作业队列(又名批处理队列)很有用,以便您可以跳过已被并发事务锁定的锁。

NO WAIT 对于避免等待直到并发事务释放我们也对锁定感兴趣的锁非常有用。

如果没有NO WAIT,我们要么必须等到锁被释放(在当前持有锁的事务提交或释放时)或锁获取超时。NO WAIT用作锁超时,值为0

如需详细了解SKIP LOCKNO WAIT


AHu*_*ist 5

从8.0.1开始,这似乎已存在于MySQL中:

https://mysqlserverteam.com/mysql-8-0-1-using-skip-locked-and-nowait-to-handle-hot-rows/

从MySQL 8.0.1开始,我们引入了SKIP LOCKED修饰符,该修饰符可用于非确定性地从表中读取行,而跳过被锁定的行。我们的预订系统可以使用它跳过待处理的订单。例如:

但是,我认为该版本不一定可以投入生产。