根据MySql文档,MySql支持多粒度锁定(MGL)。
打开终端-1:
//连接到mysql
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> select id, status from tracking_number limit 5 for update;
+----+--------+
| id | status |
+----+--------+
| 1 | 0 |
| 2 | 0 |
| 3 | 0 |
| 4 | 0 |
| 5 | 0 |
+----+--------+
5 rows in set (0.00 sec)
mysql>
打开并打开终端2:
//连接到mysql
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> select id, status from tracking_number limit 5 for update;
<!-- Hangs here. and after some time it says-->
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
虽然有很多行需要检索,但T2会等到t1完成。
离开终端-1,现在在终端-2中:
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
<!-- case 2.1 -->
mysql> select id, status from tracking_number where id=1;
+----+--------+
| id | status |
+----+--------+
| 1 | 0 |
+----+--------+
1 row in set (0.00 sec)
mysql> select id, status from tracking_number where id=2;
+----+--------+
| id | status |
+----+--------+
| 2 | 0 |
+----+--------+
1 row in set (0.00 sec)
<!-- case 2.2 -->
mysql> select * from tracking_number where id=2 for update;
<!-- Hangs here. and after some time -->
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
但为什么在案例1中,T2会等待T1锁定的同一组行?
这是否意味着无限制的选择查询(即使使用limint参数。我尝试过不同的范围也会阻塞整个表格?
打开终端和交易:
mysql> update tracking_number set status=4 where status=0 limit 5;
Query OK, 5 rows affected (0.00 sec)
Rows matched: 5 Changed: 5 Warnings: 0
把它留在那里并打开另一个终端和交易:
mysql> update tracking_number set status=5 where status=0 limit 5;
在我提交(或回滚)T1之前,T2没有成功。
答案 0 :(得分:23)
让我来看看你的案例并解释这些锁是如何工作的:
1例
T1想要更新测试表中的某些行。此事务将IX锁定放在所有表上,并将X锁定放在前5行。
T2想要更新测试表中的某些行。此事务将IX(因为IX与IX兼容)锁定在所有表上并尝试前5行但由于X与X不兼容而无法执行此操作
所以我们没事。
2.1案例
T1想要更新测试表中的某些行。此事务将IX锁定放在所有表上,X锁定在前5行。
T2想要从测试表中选择一些行。并且它没有放置任何锁(因为InnoDB提供非锁定读取)
2.1案例
T1想要更新测试表中的某些行。此事务将IX锁定放在所有表上,X锁定在前5行。
T2想要更新(选择更新)测试表中的某些行。将IS放在整个表上并尝试对该行进行S锁定并失败,因为X和S不兼容。
还要始终注意隔离级别:不同级别会导致释放/获取锁定的机制不同
希望有所帮助