文章目录
环境:
- MySQL版本:8.0.27
- 隔离级别:RR
基础数据
CREATE TABLE t5
(
id int(11) NOT NULL,
c int(11) DEFAULT NULL,
d int(11) DEFAULT NULL,
PRIMARY KEY (id),
KEY c (c)
) ENGINE = InnoDB;
insert into t5
values (0, 0, 0),
(5, 5, 5),
(10, 10, 10),
(15, 15, 15),
(20, 20, 20),
(25, 25, 25);
【1】MySQL 表级锁的四种类型使用示例
表共享读锁 (S锁)
场景:数据库备份时允许其他会话读取但不能修改
-- 会话1
LOCK TABLES t5 READ ; -- 加共享读锁
-- 此时可以执行SELECT但不能执行INSERT/UPDATE/DELETE
-- 会话2 (其他连接)
SELECT * FROM t5; -- 允许执行
UPDATE t5 SET d = d + 1 WHERE id = 5; -- 被阻塞,直到锁释放
注意:SHARED_WRITE 和 SHARED_READ_ONLY 是元数据锁(MDL)。类似 Innodb 锁中的 IX 和 IS 锁。
死锁排查方案:
select * from sys.schema_table_lock_waits;
select *from performance_schema.events_statements_current;
select * from performance_schema.threads where THREAD_ID = 49;
select * from performance_schema.metadata_locks;
表排他写锁 (X锁)
场景:执行数据迁移时需要完全独占表
-- 会话1
LOCK TABLES t5 WRITE; -- 加排他写锁
-- 可以执行任何操作
-- 解锁
UNLOCK TABLES;
-- 会话2 (其他连接)
SELECT * FROM t5; -- 被阻塞
UPDATE t5 SET d = d + 1 WHERE id = 5; -- 被阻塞,直到锁释放
死锁排查:同上述方法一致
意向共享锁 (IS锁)
场景:事务准备读取某些行前的标记
-- 会话1
BEGIN;
SELECT * FROM t5 WHERE id = 5 LOCK IN SHARE MODE;
-- 自动先获取表的IS锁,再获取行的S锁
-- 会话2
SELECT * FROM t5 where id = 5; -- 允许执行
UPDATE t5 SET d = d + 1 WHERE id = 5; -- 被阻塞,直到锁释放
-- 此时在另一个会话可以观察到:
SHOW ENGINE INNODB STATUS\G
...
---TRANSACTION 1234, ACTIVE
... TABLE LOCK table `test`.`orders` trx id 1234 lock mode IS
... RECORD LOCKS space id 56 page no 3 n bits 72 index PRIMARY trx id 1234 lock mode S
死锁排查:
-- 持有锁类型
select * from sys.innodb_lock_waits;
select * from performance_schema.data_locks where ENGINE_TRANSACTION_ID in (31756, 31761);
select * from performance_schema.threads where THREAD_ID in (49, 50);
select * from performance_schema.events_statements_history where THREAD_ID = 49 order by EVENT_ID desc ;
意向排他锁 (IX锁)
场景:事务准备修改某些行前的标记
-- 会话1
BEGIN;
SELECT * FROM t5 WHERE id = 5 FOR UPDATE;
-- 自动先获取表的IX锁,再获取行的X锁
-- 会话2
SELECT * FROM t5 where id = 5; -- 被阻塞
UPDATE t5 SET d = d + 1 WHERE id = 5; -- 被阻塞,直到锁释放
-- 此时在另一个会话可以观察到:
SHOW ENGINE INNODB STATUS\G
...
---TRANSACTION 1235, ACTIVE
... TABLE LOCK table `test`.`orders` trx id 1235 lock mode IX
... RECORD LOCKS space id 56 page no 3 n bits 72 index PRIMARY trx id 1235 lock mode X
死锁排查:同上述方法一致
【2】MySQL 行级锁的类型使用示例
记录锁(Record Lock)
排他记录锁(X锁):
-- 会话1
BEGIN;
SELECT * FROM t5 WHERE id = 5 FOR UPDATE;
-- 自动先获取表的IX锁,再获取行的X锁
-- 会话2
SELECT * FROM t5 where id = 5; --被阻塞
UPDATE t5 SET d = d + 1 WHERE id = 5; -- 被阻塞,直到锁释放
共享记录锁(S锁):
-- 会话1
BEGIN;
SELECT * FROM t5 WHERE id = 10 LOCK IN SHARE MODE;
-- 自动先获取表的IS锁,再获取行的S锁
-- 会话2
SELECT * FROM t5 where id = 10; -- 允许执行
UPDATE t5 SET d = d + 1 WHERE id = 10; -- 被阻塞,直到锁释放
-- 锁分析
select * from performance_schema.data_locks;
会话 2 锁分析
SQL2:
ENGINE | ENGINE_LOCK_ID | ENGINE_TRANSACTION_ID | THREAD_ID | EVENT_ID | OBJECT_SCHEMA | OBJECT_NAME | PARTITION_NAME | SUBPARTITION_NAME | INDEX_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE | LOCK_MODE | LOCK_STATUS | LOCK_DATA |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
INNODB | 140563598155776:1085:140563475153280 | 31810 | 63 | 146 | demo | t5 | null | null | null | 140563475153280 | TABLE | IX | GRANTED | null |
INNODB | 140563598155776:20:4:4:140563475150368 | 31810 | 63 | 146 | demo | t5 | null | null | PRIMARY | 140563475150368 | RECORD | X,REC_NOT_GAP | WAITING | 10 |
INNODB | 140563598154968:1085:140563475147184 | 422038574865624 | 61 | 202 | demo | t5 | null | null | null | 140563475147184 | TABLE | IS | GRANTED | null |
INNODB | 140563598154968:20:4:4:140563475144192 | 422038574865624 | 61 | 202 | demo | t5 | null | null | PRIMARY | 140563475144192 | RECORD | S,REC_NOT_GAP | GRANTED | 10 |
间隙锁(Gap Lock)
防止幻读,锁定记录之间的间隙:
-- 会话1
BEGIN;
SELECT * FROM t5 WHERE id >3 AND id < 7 FOR UPDATE;
-- 会话2
insert into t5 values (2, 2, 2); -- 阻塞
UPDATE t5 SET d = d + 1 WHERE id = 5; -- 阻塞
-- 锁分析
select * from performance_schema.data_locks;
会话 2 锁分析
SQL1:
THREAD_ID | EVENT_ID | OBJECT_SCHEMA | OBJECT_NAME | PARTITION_NAME | SUBPARTITION_NAME | INDEX_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE | LOCK_MODE | LOCK_STATUS | LOCK_DATA |
---|---|---|---|---|---|---|---|---|---|---|---|
63 | 86 | demo | t5 | null | null | null | 140563475153280 | TABLE | IX | GRANTED | null |
63 | 86 | demo | t5 | null | null | PRIMARY | 140563475150368 | RECORD | X,GAP,INSERT_INTENTION | WAITING | 5 |
61 | 173 | demo | t5 | null | null | null | 140563475147184 | TABLE | IX | GRANTED | null |
61 | 173 | demo | t5 | null | null | PRIMARY | 140563475144192 | RECORD | X | GRANTED | 5 |
61 | 173 | demo | t5 | null | null | PRIMARY | 140563475144536 | RECORD | X,GAP | GRANTED | 10 |
SQL2:
ENGINE | ENGINE_LOCK_ID | ENGINE_TRANSACTION_ID | THREAD_ID | EVENT_ID | OBJECT_SCHEMA | OBJECT_NAME | PARTITION_NAME | SUBPARTITION_NAME | INDEX_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE | LOCK_MODE | LOCK_STATUS | LOCK_DATA |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
INNODB | 140563598155776:1085:140563475153280 | 31807 | 63 | 122 | demo | t5 | null | null | null | 140563475153280 | TABLE | IX | GRANTED | null |
INNODB | 140563598155776:20:4:3:140563475150368 | 31807 | 63 | 122 | demo | t5 | null | null | PRIMARY | 140563475150368 | RECORD | X,REC_NOT_GAP | WAITING | 5 |
INNODB | 140563598154968:1085:140563475147184 | 31799 | 61 | 173 | demo | t5 | null | null | null | 140563475147184 | TABLE | IX | GRANTED | null |
INNODB | 140563598154968:20:4:3:140563475144192 | 31799 | 61 | 173 | demo | t5 | null | null | PRIMARY | 140563475144192 | RECORD | X | GRANTED | 5 |
INNODB | 140563598154968:20:4:4:140563475144536 | 31799 | 61 | 173 | demo | t5 | null | null | PRIMARY | 140563475144536 | RECORD | X,GAP | GRANTED | 10 |
临键锁(Next-Key Lock)
InnoDB默认锁机制,锁定记录+前间隙:
BEGIN;
SELECT * FROM t5 WHERE id <= 20 FOR UPDATE;
-- 锁定范围: (-∞,0],(0,5],(5,10],(10,20]
UPDATE t5 SET d = d + 1 WHERE id = 0; -- 阻塞
UPDATE t5 SET d = d + 1 WHERE id = 20; -- 阻塞
UPDATE t5 SET d = d + 1 WHERE id = 25; -- 正常执行
insert into t5 values (2, 2, 2); -- 阻塞
会话 2 锁分析
SQL1:
ENGINE | ENGINE_LOCK_ID | ENGINE_TRANSACTION_ID | THREAD_ID | EVENT_ID | OBJECT_SCHEMA | OBJECT_NAME | PARTITION_NAME | SUBPARTITION_NAME | INDEX_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE | LOCK_MODE | LOCK_STATUS | LOCK_DATA |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
INNODB | 140563598155776:1085:140563475153280 | 31826 | 63 | 247 | demo | t5 | null | null | null | 140563475153280 | TABLE | IX | GRANTED | null |
INNODB | 140563598155776:20:4:2:140563475150368 | 31826 | 63 | 247 | demo | t5 | null | null | PRIMARY | 140563475150368 | RECORD | X,REC_NOT_GAP | WAITING | 0 |
INNODB | 140563598154968:1085:140563475147184 | 31825 | 61 | 260 | demo | t5 | null | null | null | 140563475147184 | TABLE | IX | GRANTED | null |
INNODB | 140563598154968:20:4:2:140563475144192 | 31825 | 61 | 260 | demo | t5 | null | null | PRIMARY | 140563475144192 | RECORD | X | GRANTED | 0 |
INNODB | 140563598154968:20:4:3:140563475144192 | 31825 | 61 | 260 | demo | t5 | null | null | PRIMARY | 140563475144192 | RECORD | X | GRANTED | 5 |
INNODB | 140563598154968:20:4:4:140563475144192 | 31825 | 61 | 260 | demo | t5 | null | null | PRIMARY | 140563475144192 | RECORD | X | GRANTED | 10 |
INNODB | 140563598154968:20:4:5:140563475144192 | 31825 | 61 | 260 | demo | t5 | null | null | PRIMARY | 140563475144192 | RECORD | X | GRANTED | 15 |
INNODB | 140563598154968:20:4:6:140563475144192 | 31825 | 61 | 260 | demo | t5 | null | null | PRIMARY | 140563475144192 | RECORD | X | GRANTED | 20 |
SQL2:
ENGINE | ENGINE_LOCK_ID | ENGINE_TRANSACTION_ID | THREAD_ID | EVENT_ID | OBJECT_SCHEMA | OBJECT_NAME | PARTITION_NAME | SUBPARTITION_NAME | INDEX_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE | LOCK_MODE | LOCK_STATUS | LOCK_DATA |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
INNODB | 140563598155776:1085:140563475153280 | 31827 | 63 | 258 | demo | t5 | null | null | null | 140563475153280 | TABLE | IX | GRANTED | null |
INNODB | 140563598155776:20:4:6:140563475150368 | 31827 | 63 | 258 | demo | t5 | null | null | PRIMARY | 140563475150368 | RECORD | X,REC_NOT_GAP | WAITING | 20 |
INNODB | 140563598154968:1085:140563475147184 | 31825 | 61 | 260 | demo | t5 | null | null | null | 140563475147184 | TABLE | IX | GRANTED | null |
INNODB | 140563598154968:20:4:2:140563475144192 | 31825 | 61 | 260 | demo | t5 | null | null | PRIMARY | 140563475144192 | RECORD | X | GRANTED | 0 |
INNODB | 140563598154968:20:4:3:140563475144192 | 31825 | 61 | 260 | demo | t5 | null | null | PRIMARY | 140563475144192 | RECORD | X | GRANTED | 5 |
INNODB | 140563598154968:20:4:4:140563475144192 | 31825 | 61 | 260 | demo | t5 | null | null | PRIMARY | 140563475144192 | RECORD | X | GRANTED | 10 |
INNODB | 140563598154968:20:4:5:140563475144192 | 31825 | 61 | 260 | demo | t5 | null | null | PRIMARY | 140563475144192 | RECORD | X | GRANTED | 15 |
INNODB | 140563598154968:20:4:6:140563475144192 | 31825 | 61 | 260 | demo | t5 | null | null | PRIMARY | 140563475144192 | RECORD | X | GRANTED | 20 |
SQL4:
ENGINE | ENGINE_LOCK_ID | ENGINE_TRANSACTION_ID | THREAD_ID | EVENT_ID | OBJECT_SCHEMA | OBJECT_NAME | PARTITION_NAME | SUBPARTITION_NAME | INDEX_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE | LOCK_MODE | LOCK_STATUS | LOCK_DATA |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
INNODB | 140563598155776:1085:140563475153280 | 31832 | 63 | 306 | demo | t5 | null | null | null | 140563475153280 | TABLE | IX | GRANTED | null |
INNODB | 140563598155776:20:4:3:140563475150368 | 31832 | 63 | 306 | demo | t5 | null | null | PRIMARY | 140563475150368 | RECORD | X,GAP,INSERT_INTENTION | WAITING | 5 |
INNODB | 140563598154968:1085:140563475147184 | 31825 | 61 | 260 | demo | t5 | null | null | null | 140563475147184 | TABLE | IX | GRANTED | null |
INNODB | 140563598154968:20:4:2:140563475144192 | 31825 | 61 | 260 | demo | t5 | null | null | PRIMARY | 140563475144192 | RECORD | X | GRANTED | 0 |
INNODB | 140563598154968:20:4:3:140563475144192 | 31825 | 61 | 260 | demo | t5 | null | null | PRIMARY | 140563475144192 | RECORD | X | GRANTED | 5 |
INNODB | 140563598154968:20:4:4:140563475144192 | 31825 | 61 | 260 | demo | t5 | null | null | PRIMARY | 140563475144192 | RECORD | X | GRANTED | 10 |
INNODB | 140563598154968:20:4:5:140563475144192 | 31825 | 61 | 260 | demo | t5 | null | null | PRIMARY | 140563475144192 | RECORD | X | GRANTED | 15 |
INNODB | 140563598154968:20:4:6:140563475144192 | 31825 | 61 | 260 | demo | t5 | null | null | PRIMARY | 140563475144192 | RECORD | X | GRANTED | 20 |
【3】加锁原则
- 加锁基本单位都是 next-key lock,查找过程中访问到的对象才会加锁。
- 索引等值查询,给唯一索引加锁时,向右遍历时且最后一个值不满足等值条件的时候,next-key lock 退化为间隙锁。
- 索引等值查询,给唯一索引加锁时,next-key lock 退化为行锁。
注意**BUG: **在唯一索引(主键)的范围查询中,InnoDB会对满足条件的记录加记录锁,并对范围之后的间隙加间隙锁以防止插入。
【4】实战
主键索引等值查询
begin ;
SELECT * FROM t5 WHERE id=5 for update ;
锁分析
ENGINE | ENGINE_LOCK_ID | ENGINE_TRANSACTION_ID | THREAD_ID | EVENT_ID | OBJECT_SCHEMA | OBJECT_NAME | PARTITION_NAME | SUBPARTITION_NAME | INDEX_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE | LOCK_MODE | LOCK_STATUS | LOCK_DATA |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
INNODB | 140563598154968:1085:140563475147184 | 31950 | 85 | 79 | demo | t5 | null | null | null | 140563475147184 | TABLE | IX | GRANTED | null |
INNODB | 140563598154968:20:4:3:140563475144192 | 31950 | 85 | 79 | demo | t5 | null | null | PRIMARY | 140563475144192 | RECORD | X,REC_NOT_GAP | GRANTED | 5 |
主键索引间隙锁
-- session 1
begin ;
select * from t5 where id = 6 for update ; -- (5,10)
-- session 2
UPDATE t5 SET d = d + 1 WHERE id = 10; -- 正常执行
insert into t5 value (4, 4, 4); -- 正常执行
insert into t5 value (7, 7, 7); -- 阻塞
会话 2 锁分析
ENGINE | ENGINE_LOCK_ID | ENGINE_TRANSACTION_ID | THREAD_ID | EVENT_ID | OBJECT_SCHEMA | OBJECT_NAME | PARTITION_NAME | SUBPARTITION_NAME | INDEX_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE | LOCK_MODE | LOCK_STATUS | LOCK_DATA |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
INNODB | 140563598155776:1085:140563475153280 | 31933 | 86 | 50 | demo | t5 | null | null | null | 140563475153280 | TABLE | IX | GRANTED | null |
INNODB | 140563598155776:20:4:4:140563475150368 | 31933 | 86 | 50 | demo | t5 | null | null | PRIMARY | 140563475150368 | RECORD | X,GAP,INSERT_INTENTION | WAITING | 10 |
INNODB | 140563598154968:1085:140563475147184 | 31924 | 85 | 21 | demo | t5 | null | null | null | 140563475147184 | TABLE | IX | GRANTED | null |
INNODB | 140563598154968:20:4:4:140563475144192 | 31924 | 85 | 21 | demo | t5 | null | null | PRIMARY | 140563475144192 | RECORD | X,GAP | GRANTED | 10 |
主键索引范围锁
范围一:
-- session 1:
begin ;
select * from t5 where id >= 5 and id <10 for update ; -- (0,5],(5,10] -> 5,(5,10);
-- session 2:
insert into t5 value (2, 2,2); -- 正常执行
insert into t5 value (7, 7, 7); -- 阻塞
UPDATE t5 SET d = d + 1 WHERE id = 10; -- 正常执行
会话 2 锁分析
ENGINE | ENGINE_LOCK_ID | ENGINE_TRANSACTION_ID | THREAD_ID | EVENT_ID | OBJECT_SCHEMA | OBJECT_NAME | PARTITION_NAME | SUBPARTITION_NAME | INDEX_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE | LOCK_MODE | LOCK_STATUS | LOCK_DATA | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
INNODB | 140563598155776:1085:140563475153280 | 31939 | 86 | 98 | demo | t5 | null | null | null | 140563475153280 | TABLE | IX | GRANTED | null | |
INNODB | 140563598155776:20:4:4:140563475150368 | 31939 | 86 | 98 | demo | t5 | null | null | PRIMARY | 140563475150368 | RECORD | X,GAP,INSERT_INTENTION | WAITING | 10 | |
INNODB | 140563598154968:1085:140563475147184 | 31934 | 85 | 50 | demo | t5 | null | null | null | 140563475147184 | TABLE | IX | GRANTED | null | |
INNODB | 140563598154968:20:4:3:140563475144192 | 31934 | 85 | 50 | demo | t5 | null | null | PRIMARY | 140563475144192 | RECORD | X,REC_NOT_GAP | GRANTED | 5 | |
INNODB | 140563598154968:20:4:4:140563475144536 | 31934 | 85 | 50 | demo | t5 | null | null | PRIMARY | 140563475144536 | RECORD | X,GAP | GRANTED | 10 |
范围二:
-- session1
begin ;
select * from t5 where id > 5 and id <=10 for update ; -- (5,10]
-- session2
insert into t5 value (2, 2,2); -- 正常执行
insert into t5 value (7, 7, 7); -- 阻塞
insert into t5 value (11, 11, 11); -- 正常执行
UPDATE t5 SET d = d + 1 WHERE id = 10; -- 阻塞
UPDATE t5 SET d = d + 1 WHERE id = 5; -- 正常执行
会话 2 锁分析
ENGINE | ENGINE_LOCK_ID | ENGINE_TRANSACTION_ID | THREAD_ID | EVENT_ID | OBJECT_SCHEMA | OBJECT_NAME | PARTITION_NAME | SUBPARTITION_NAME | INDEX_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE | LOCK_MODE | LOCK_STATUS | LOCK_DATA |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
INNODB | 140563598155776:1085:140563475153280 | 31954 | 86 | 122 | demo | t5 | null | null | null | 140563475153280 | TABLE | IX | GRANTED | null |
INNODB | 140563598155776:20:4:4:140563475150368 | 31954 | 86 | 122 | demo | t5 | null | null | PRIMARY | 140563475150368 | RECORD | X,REC_NOT_GAP | WAITING | 10 |
INNODB | 140563598154968:1085:140563475147184 | 31951 | 85 | 108 | demo | t5 | null | null | null | 140563475147184 | TABLE | IX | GRANTED | null |
INNODB | 140563598154968:20:4:4:140563475144192 | 31951 | 85 | 108 | demo | t5 | null | null | PRIMARY | 140563475144192 | RECORD | X | GRANTED | 10 |
范围 3:
begin;
select * from t5 where id <= 10 for update ;
锁分析
ENGINE | ENGINE_LOCK_ID | ENGINE_TRANSACTION_ID | THREAD_ID | EVENT_ID | OBJECT_SCHEMA | OBJECT_NAME | PARTITION_NAME | SUBPARTITION_NAME | INDEX_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE | LOCK_MODE | LOCK_STATUS | LOCK_DATA |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
INNODB | 140697851113472:1085:140697759990144 | 33109 | 58 | 292 | demo | t5 | null | null | null | 140697759990144 | TABLE | IX | GRANTED | null |
INNODB | 140697851113472:20:4:2:140697759987232 | 33109 | 58 | 292 | demo | t5 | null | null | PRIMARY | 140697759987232 | RECORD | X | GRANTED | 0 |
INNODB | 140697851113472:20:4:3:140697759987232 | 33109 | 58 | 292 | demo | t5 | null | null | PRIMARY | 140697759987232 | RECORD | X | GRANTED | 5 |
INNODB | 140697851113472:20:4:4:140697759987232 | 33109 | 58 | 292 | demo | t5 | null | null | PRIMARY | 140697759987232 | RECORD | X | GRANTED | 10 |
非唯一索引等值查询
-- session1:
begin ;
select * from t5 where c=5 for update ;
-- session2:
insert into t5 value (2, 2,2); -- 阻塞
insert into t5 value (7, 7, 7); -- 阻塞
UPDATE t5 SET d = d + 1 WHERE c = 5; -- 阻塞
UPDATE t5 SET d = d + 1 WHERE c = 10; -- 正常执行
UPDATE t5 SET d = d + 1 WHERE id = 5; -- 阻塞
UPDATE t5 SET d = d + 1 WHERE id = 10; -- 正常执行
会话 2 锁分析
ENGINE | ENGINE_LOCK_ID | ENGINE_TRANSACTION_ID | THREAD_ID | EVENT_ID | OBJECT_SCHEMA | OBJECT_NAME | PARTITION_NAME | SUBPARTITION_NAME | INDEX_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE | LOCK_MODE | LOCK_STATUS | LOCK_DATA |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
INNODB | 140697851114280:1085:140697759996128 | 33040 | 50 | 13 | demo | t5 | null | null | null | 140697759996128 | TABLE | IX | GRANTED | null |
INNODB | 140697851114280:20:5:3:140697759993216 | 33040 | 50 | 13 | demo | t5 | null | null | c | 140697759993216 | RECORD | X,GAP,INSERT_INTENTION | WAITING | 5, 5 |
INNODB | 140697851113472:1085:140697759990144 | 33039 | 49 | 78 | demo | t5 | null | null | null | 140697759990144 | TABLE | IX | GRANTED | null |
INNODB | 140697851113472:20:5:3:140697759987232 | 33039 | 49 | 78 | demo | t5 | null | null | c | 140697759987232 | RECORD | X | GRANTED | 5, 5 |
INNODB | 140697851113472:20:4:3:140697759987576 | 33039 | 49 | 78 | demo | t5 | null | null | PRIMARY | 140697759987576 | RECORD | X,REC_NOT_GAP | GRANTED | 5 |
INNODB | 140697851113472:20:5:4:140697759987920 | 33039 | 49 | 78 | demo | t5 | null | null | c | 140697759987920 | RECORD | X,GAP | GRANTED | 10, 10 |
非唯一索引间隙锁
-- session1:
begin ;
select * from t5 where c=6 for update ;
-- session2:
UPDATE t5 SET d = d + 1 WHERE c = 5; -- 正常执行
UPDATE t5 SET d = d + 1 WHERE id = 5; -- 正常执行
UPDATE t5 SET d = d + 1 WHERE id = 10; -- 正常执行
UPDATE t5 SET d = d + 1 WHERE c = 10; -- 正常执行
insert into t5 value (7, 7, 7); -- 阻塞
会话 2 锁分析
ENGINE | ENGINE_LOCK_ID | ENGINE_TRANSACTION_ID | THREAD_ID | EVENT_ID | OBJECT_SCHEMA | OBJECT_NAME | PARTITION_NAME | SUBPARTITION_NAME | INDEX_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE | LOCK_MODE | LOCK_STATUS | LOCK_DATA |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
INNODB | 140697851114280:1085:140697759996128 | 33067 | 50 | 181 | demo | t5 | null | null | null | 140697759996128 | TABLE | IX | GRANTED | null |
INNODB | 140697851114280:20:5:4:140697759993216 | 33067 | 50 | 181 | demo | t5 | null | null | c | 140697759993216 | RECORD | X,GAP,INSERT_INTENTION | WAITING | 10, 10 |
INNODB | 140697851113472:1085:140697759990144 | 33052 | 49 | 107 | demo | t5 | null | null | null | 140697759990144 | TABLE | IX | GRANTED | null |
INNODB | 140697851113472:20:5:4:140697759987232 | 33052 | 49 | 107 | demo | t5 | null | null | c | 140697759987232 | RECORD | X,GAP | GRANTED | 10, 10 |
非唯一索引范围锁
范围一:
-- session1:
begin ;
select * from t5 where c >= 5 and c <10 for update ;
-- session2:
UPDATE t5 SET d = d + 1 WHERE id = 10; -- 正常执行
UPDATE t5 SET d = d + 1 WHERE c = 10; -- 阻塞
insert into t5 value (2, 2,2); -- 阻塞
会话 2 锁分析
ENGINE | ENGINE_LOCK_ID | ENGINE_TRANSACTION_ID | THREAD_ID | EVENT_ID | OBJECT_SCHEMA | OBJECT_NAME | PARTITION_NAME | SUBPARTITION_NAME | INDEX_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE | LOCK_MODE | LOCK_STATUS | LOCK_DATA |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
INNODB | 140697851112664:1085:140697759984048 | 33084 | 57 | 84 | demo | t5 | null | null | null | 140697759984048 | TABLE | IX | GRANTED | null |
INNODB | 140697851112664:20:5:3:140697759981056 | 33084 | 57 | 84 | demo | t5 | null | null | c | 140697759981056 | RECORD | X,GAP,INSERT_INTENTION | WAITING | 5, 5 |
INNODB | 140697851113472:1085:140697759990144 | 33083 | 58 | 108 | demo | t5 | null | null | null | 140697759990144 | TABLE | IX | GRANTED | null |
INNODB | 140697851113472:20:5:3:140697759987232 | 33083 | 58 | 108 | demo | t5 | null | null | c | 140697759987232 | RECORD | X | GRANTED | 5, 5 |
INNODB | 140697851113472:20:5:4:140697759987232 | 33083 | 58 | 108 | demo | t5 | null | null | c | 140697759987232 | RECORD | X | GRANTED | 10, 10 |
INNODB | 140697851113472:20:4:3:140697759987576 | 33083 | 58 | 108 | demo | t5 | null | null | PRIMARY | 140697759987576 | RECORD | X,REC_NOT_GAP | GRANTED | 5 |
范围 2:
begin ;
select * from t5 where c > 5 and c <=10 for update ;
-- sesssion 2:
insert into t5 value (2, 2,2); -- 正常执行
insert into t5 value (7, 7,7); -- 阻塞
insert into t5 value (11, 11,11); -- 阻塞
UPDATE t5 SET d = d + 1 WHERE c = 5; -- 正常执行
UPDATE t5 SET d = d + 1 WHERE c = 10; -- 阻塞
UPDATE t5 SET d = d + 1 WHERE c = 15; -- 阻塞
UPDATE t5 SET d = d + 1 WHERE id = 15; -- 正常执行
ENGINE | ENGINE_LOCK_ID | ENGINE_TRANSACTION_ID | THREAD_ID | EVENT_ID | OBJECT_SCHEMA | OBJECT_NAME | PARTITION_NAME | SUBPARTITION_NAME | INDEX_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE | LOCK_MODE | LOCK_STATUS | LOCK_DATA |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
INNODB | 140697851112664:1085:140697759984048 | 33102 | 57 | 192 | demo | t5 | null | null | null | 140697759984048 | TABLE | IX | GRANTED | null |
INNODB | 140697851112664:20:5:5:140697759981056 | 33102 | 57 | 192 | demo | t5 | null | null | c | 140697759981056 | RECORD | X | WAITING | 15, 15 |
INNODB | 140697851113472:1085:140697759990144 | 33087 | 58 | 137 | demo | t5 | null | null | null | 140697759990144 | TABLE | IX | GRANTED | null |
INNODB | 140697851113472:20:5:4:140697759987232 | 33087 | 58 | 137 | demo | t5 | null | null | c | 140697759987232 | RECORD | X | GRANTED | 10, 10 |
INNODB | 140697851113472:20:5:5:140697759987232 | 33087 | 58 | 137 | demo | t5 | null | null | c | 140697759987232 | RECORD | X | GRANTED | 15, 15 |
INNODB | 140697851113472:20:4:4:140697759987576 | 33087 | 58 | 137 | demo | t5 | null | null | PRIMARY | 140697759987576 | RECORD | X,REC_NOT_GAP | GRANTED | 10 |
范围 3:
begin ;
select * from t5 where c <= 10 for update ;
锁分析
ENGINE | ENGINE_LOCK_ID | ENGINE_TRANSACTION_ID | THREAD_ID | EVENT_ID | OBJECT_SCHEMA | OBJECT_NAME | PARTITION_NAME | SUBPARTITION_NAME | INDEX_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE | LOCK_MODE | LOCK_STATUS | LOCK_DATA |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
INNODB | 140697851113472:1085:140697759990144 | 33108 | 58 | 263 | demo | t5 | null | null | null | 140697759990144 | TABLE | IX | GRANTED | null |
INNODB | 140697851113472:20:5:2:140697759987232 | 33108 | 58 | 263 | demo | t5 | null | null | c | 140697759987232 | RECORD | X | GRANTED | 0, 0 |
INNODB | 140697851113472:20:5:3:140697759987232 | 33108 | 58 | 263 | demo | t5 | null | null | c | 140697759987232 | RECORD | X | GRANTED | 5, 5 |
INNODB | 140697851113472:20:5:4:140697759987232 | 33108 | 58 | 263 | demo | t5 | null | null | c | 140697759987232 | RECORD | X | GRANTED | 10, 10 |
INNODB | 140697851113472:20:5:5:140697759987232 | 33108 | 58 | 263 | demo | t5 | null | null | c | 140697759987232 | RECORD | X | GRANTED | 15, 15 |
INNODB | 140697851113472:20:4:2:140697759987576 | 33108 | 58 | 263 | demo | t5 | null | null | PRIMARY | 140697759987576 | RECORD | X,REC_NOT_GAP | GRANTED | 0 |
INNODB | 140697851113472:20:4:3:140697759987576 | 33108 | 58 | 263 | demo | t5 | null | null | PRIMARY | 140697759987576 | RECORD | X,REC_NOT_GAP | GRANTED | 5 |
INNODB | 140697851113472:20:4:4:140697759987576 | 33108 | 58 | 263 | demo | t5 | null | null | PRIMARY | 140697759987576 | RECORD | X,REC_NOT_GAP | GRANTED | 10 |
【5】performance_schema.data_locks 表
表级锁 (LOCK_TYPE = ‘TABLE’)
锁类型 | LOCK_MODE 显示值 | 说明 |
---|---|---|
表共享读锁 | S | 允许其他会话读但禁止写 |
表排他写锁 | X | 禁止其他会话任何操作 |
意向共享锁 | IS | 表示事务打算在表的某些行上设置共享锁 |
意向排他锁 | IX | 表示事务打算在表的某些行上设置排他锁 |
行级锁 (LOCK_TYPE = ‘RECORD’)
基本行锁类型
锁类型 | LOCK_MODE 显示值 | 锁定范围 | 兼容性 |
---|---|---|---|
记录锁 (X锁) | X,REC_NOT_GAP | 仅锁定单条记录 | 与其他所有锁互斥 |
记录锁 (S锁) | S,REC_NOT_GAP | 仅锁定单条记录 | 允许多个S锁,与X锁互斥 |
间隙锁 | X,GAP 或 S,GAP | 锁定记录之间的间隙 | 允许多个事务持有相同间隙锁 |
临键锁 | X 或 S | 锁定记录+前间隙 (左开右闭) | X锁与其他所有锁互斥 |
插入意向锁 | X,INSERT_INTENTION | 插入操作特有的间隙锁 | 允许多个不冲突的插入意向锁 |
特殊行锁类型
锁类型 | LOCK_MODE 显示值 | 说明 |
---|---|---|
谓词锁 | X,PURGED | 用于空间索引的谓词锁 (MySQL 8.0.17+) |
超级锁 | X,SUPER | 系统内部使用的特殊锁 |