带你读《2022技术人的百宝黑皮书》——mysql锁机制的再研究(4)https://developer.aliyun.com/article/1340030?groupCode=taobaotech
问题分析
复现
表中已有数据:
----+---------------------+---------------------+----------+-------------+-------------+ | id | gmt_create | gmt_modified | lock_key | lock_biz | lock_context| +----+---------------------+---------------------+----------+-------------+-------------+ | 12 | 2022-02-15 19:54:42 | 2022-02-15 19:54:42 | 123 | accountUser | 0 | | 50 | 2022-02-15 19:55:05 | 2022-02-15 19:55:05 | 150 | accountUser | 0 | | 75 | 2022-02-15 19:55:19 | 2022-02-15 19:55:19 | 200 | accountUser | 0 |
从死锁日志可以看出,是由于insert操作引发死锁,故重点研究与讲解。
步骤 |
T1 |
T2 |
T3 |
T4 |
1 |
begin; |
|
begin; |
|
2 |
insert into test_lock( `gmt_create` ,`gmt_- modified` ,`lock_key` , `lock_biz` ) VALUE (now(),now(), '140', 'AccountUser'); |
|
insert into test_lock( `gmt_create` ,`gmt_- modified` ,`lock_key` , `lock_biz` ) VALUE (now(),now(), '144', 'AccountUser'); |
|
3 |
|
begin; |
|
begin; |
4 |
|
insert into test_lock`( `gmt_create` ,`gmt_- modified` ,`lock_key` , `lock_biz` ) VALUE (now(),now(), '140', 'AccountUser'); |
|
insert into `test_lock`( `gmt_create` ,`gmt_- modified` ,`lock_key` , `lock_biz` ) VALUE (now(),now(), '144', 'AccountUser'); |
5 |
存 在 lock_key=140, lock_biz='AccoutUser'的X record行锁 |
因为出现唯一性冲突,故加S Next-key Lock,锁住(123-140],(140,150]之间 的空间, |
存 在 lock_key=144, lock_biz='AccoutUser'的X record行锁 |
因为出现唯一性冲突,故加S Next-key Lock,锁住(123-144],(144,150]之间 的空间 |
6 |
rollback; |
申请插入意向锁,阻塞 |
|
|
7 |
|
|
rollback; |
申请插入意向锁,阻塞 |
8 |
|
成功获取锁,并插入 |
|
deadLock |
T1: insetrt后,存在lock_key=140, lock_biz='AccoutUser'的X记录锁
T2: 与T1发生唯一键冲突,故加上S Next-key Lock(也就是lock mode S waiting),锁住(123-140],(140,150]之间的空间。
T3: insert后,存在lock_key=144, lock_biz='AccoutUser'的X记录锁
T4: 与T3发生唯一键冲突,故加上S Next-key Lock(也就是lock mode S waiting),锁住(123-144],(144,150] 之间的空间。
T2:T1 回滚后,T2与T4锁冲突,等待T4 S-Next-key Lock锁释放,然后申请意向锁,在日志中显示lock_- mode X locks gap before rec insert intention waiting.
T4:T3回滚后,T2和T4同时申请意向锁,死锁出现。
通过show engine innodb status;命令查看死锁日志,可以看到与线上表现一致。
------------------------ LATEST DETECTED DEADLOCK 3 ------------------------ 2022 02-15 20:34:19 0x70000ec62000 *** (1) TRANSACTION: TRANSACTION 8501, ACTIVE 10 sec inserting mysql tables in use 1, locked 1 LOCK WAIT 4 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1 MySQL thread id 5, OS thread handle 123145550733312, query id 93 localhost root update insert into `test_lock`( `gmt_create` ,`gmt_modified` ,`lock_key` , `lock_biz` ) VALUE (now(),now(), '144', 'AccountUser') *** (1) WAITING FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 23 page no 4 n bits 80 index idx_uk_lock_name of table `dian- jing_test`.`test_lock` trx id 8501 lock_mode X locks gap before rec insert intention waiting Record lock, heap no 3 PHYSICAL RECORD: n_fields 3; compact format; info bits 0 14 0: len 3; hex 313530; asc 150;; 1: len 11; hex 6163636f756e7455736572; asc accountUser;; 2: len 8; hex 8000000000000032; asc 2;; *** (2) TRANSACTION: TRANSACTION 8495, ACTIVE 31 sec inserting mysql tables in use 1, locked 1 5 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1 MySQL thread id 3, OS thread handle 123145550176256, query id 89 localhost root update insert into `test_lock`( `gmt_create` ,`gmt_modified` ,`lock_key` , `lock_biz` ) VALUE (now(),now(), '140', 'AccountUser') *** (2) HOLDS THE LOCK(S): RECORD LOCKS space id 23 page no 4 n bits 80 index idx_uk_lock_name of table `dian- jing_test`.`test_lock` trx id 8495 lock mode S locks gap before rec Record lock, heap no 3 PHYSICAL RECORD: n_fields 3; compact format; info bits 0 0: len 3; hex 313530; asc 150;; 1: len 11; hex 6163636f756e7455736572; asc accountUser;; 2: len 8; hex 8000000000000032; asc 2;; *** (2) WAITING FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 23 page no 4 n bits 80 index idx_uk_lock_name of table `dian- jing_test`.`test_lock` trx id 8495 lock_mode X locks gap before rec insert intention waiting Record lock, heap no 3 PHYSICAL RECORD: n_fields 3; compact format; info bits 0 0: len 3; hex 313530; asc 150;; 1: len 11; hex 6163636f756e7455736572; asc accountUser;; 2: len 8; hex 8000000000000032; asc 2;;
小注解:mysql的锁,放在系统库information_schema的INNODB_LOCKS和INNODB_LOCK_WAITS两个表中,可直接select查看。
带你读《2022技术人的百宝黑皮书》——mysql锁机制的再研究(6)https://developer.aliyun.com/article/1340028?groupCode=taobaotech