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)
因此,如果我启动一个查询来强制它选择其他行,那很好。
但是有没有办法跳过锁定的行?
我猜这在并发过程中应该是一个冗余的问题,但是我没有找到任何解决方案。
编辑:实际上,我不同的并发进程正在做的事情显然非常简单:
采取第一行(不包含特定标志-例如:“ WHERE myflag_inUse!= 1”)。
一旦获得“选择更新”的结果,就更新标志并提交行。
所以我只想选择尚未锁定的行以及myflag_inUse!= 1 ...
以下链接可帮助我了解为什么会超时,但无法避免超时:
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)
从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修饰符,该修饰符可用于非确定性地从表中读取行,而跳过被锁定的行。我们的预订系统可以使用它跳过待处理的订单。例如:
但是,我认为该版本不一定可以投入生产。