根据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> 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参数。我也尝试了不同的范围)阻塞了整个表?
有什么方法可以让事务独立锁定而无需指定记录的字段(即,不使用 where field = value )?
打开一个终端和一个事务:
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才成功。
让我审视您的情况并解释这些锁的工作方式:
1箱
T1想要更新测试表中的某些行。此事务将IX锁放在所有表上,将X锁放在前5行上。
T2希望更新测试表中的某些行。此事务将IX(因为IX与IX兼容)锁定在所有表上,并尝试到前5行,但由于X与X不兼容而无法执行
所以我们很好。
2.1案例
T2希望从测试表中选择一些行。而且它不会放置任何锁(因为InnoDB提供了非锁定读取)
T2想要更新(选择更新)测试表中的某些行。将IS放在整个表上,并尝试在行上获取S锁,但由于X和S不兼容而失败。
还请始终注意隔离级别:不同的级别会导致不同的机制释放/获取锁
希望能帮助到你