存储引擎 表级锁 行级锁 页级锁
MyISAM √
Memory √
BDB √
InnoDB √ √
锁类型 开销 加锁速度 死锁问题 锁定粒度 发生锁冲突的概率 并发度
表级锁 小 快 不会出现 大 最高 最低
行级锁 大 慢 会出现 小 最低 最高
页级锁 介于表锁和行锁之间 会出现 介于表锁和行锁之间 一般
- 表级锁:开销小,加锁快;不会出现死锁;锁粒度大,发生锁冲突的概率最高,并发度最低。
- 行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高
- 页级锁:开销和加锁时间介于表锁和行锁之间;会出现死锁;并发度一般
- 意向锁(Intention Locks): lock mode IX
- 记录锁(Record Locks): lock_mode X locks rec but not gap
- Gap锁(Gap Locks): lock_mode X locks gap before rec
- Next-Key Locks: lock_mode X
- 插入意向锁(Insert Intention Locks): lock_mode X locks gap before rec insert intention
mysql> SHOW STATUS LIKE 'innodb_row_lock%' ;
+ -------------------------------+-------+
| Variable_name | VALUE |
+ -------------------------------+-------+
| Innodb_row_lock_current_waits | 0 |
| Innodb_row_lock_time | 34843 |
| Innodb_row_lock_time_avg | 5807 |
| Innodb_row_lock_time_max | 21657 |
| Innodb_row_lock_waits | 6 |
+ -------------------------------+-------+
5 ROWS IN SET ( 0.00 sec)
SELECT * FROM information_schema. innodb_locks;
SELECT * FROM information_schema. innodb_lock_waits;
mysql> CREATE TABLE innodb_monitor( a INT ) engine= innodb;
Query OK, 0 ROWS affected ( 0.18 sec)
SET GLOBAL innodb_status_output_locks= ON ;
mysql> BEGIN ;
sQuery OK, 0 ROWS affected ( 2.05 sec)
mysql> SELECT * FROM test_table FOR UPDATE ;
+ ----+-----+
| id | val |
+ ----+-----+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
+ ----+-----+
3 ROWS IN SET ( 4.78 sec)
mysql> SHOW engine innodb STATUS \G
*************************** 1 . ROW ***************************
TYPE : InnoDB
Name:
STATUS :
=====================================
2022 - 04- 15 23 :21 :30 0x7f021c8ae700 INNODB MONITOR OUTPUT
=====================================
......
......
......
------------
TRANSACTIONS
------------
---TRANSACTION 549605684, ACTIVE 10 sec
2 LOCK struct( s) , heap SIZE 1136 , 4 ROW LOCK ( s)
MySQL thread id 3592040 , OS thread handle 139647045527296 , query id 1729758289 10. 10. 183. 226 root starting
SHOW engine innodb STATUS
TABLE LOCK TABLE `okami` . `test_table` trx id 549605684 LOCK mode IX
RECORD LOCKS SPACE id 5466 page no 3 n bits 72 INDEX PRIMARY OF TABLE `okami` . `test_table` trx id 549605684 lock_mode X
Record LOCK , heap no 1 PHYSICAL RECORD: n_fields 1 ; compact format; info bits 0
0 : len 8 ; hex 73757072656d756d; ASC supremum;;
Record LOCK , heap no 2 PHYSICAL RECORD: n_fields 4 ; compact format; info bits 0
0 : len 4 ; hex 80000001 ; ASC ;;
1 : len 6 ; hex 000020c13de4; ASC = ;;
2 : len 7 ; hex ab000001520110; ASC R ;;
3 : len 4 ; hex 80000001 ; ASC ;;
Record LOCK , heap no 3 PHYSICAL RECORD: n_fields 4 ; compact format; info bits 0
0 : len 4 ; hex 80000002 ; ASC ;;
1 : len 6 ; hex 000020c14054; ASC @T;;
2 : len 7 ; hex d80000100d0110; ASC ;;
3 : len 4 ; hex 80000001 ; ASC ;;
Record LOCK , heap no 4 PHYSICAL RECORD: n_fields 4 ; compact format; info bits 0
0 : len 4 ; hex 80000003 ; ASC ;;
1 : len 6 ; hex 000020c18b3a; ASC :;;
2 : len 7 ; hex b7000002f40110; ASC ;;
3 : len 4 ; hex 80000001 ; ASC ;;
......
当前锁模式\请求锁模式 X IX S IS
X 冲突 冲突 冲突 冲突
iX 冲突 兼容 冲突 兼容
S 冲突 冲突 兼容 兼容
IS 冲突 兼容 兼容 兼容
间隙锁锁定一个范围,但不包含记录本身。间隙锁封锁索引记录中的间隔,或者第一条索引记录之前的范围,又或者最后一条索引记录之后的范围。
Gap Locks 的作用是为了阻止多个事务将记录插入到同一范围内,避免幻读问题的产生。
间隙锁唯一的目的是防止其他事务插入到统一范围。间隙锁可以共存,一个事务获取的间隙锁并不阻止另一个事务获取同一间隙的间隙锁。
Next-Key Locks 是Record Lock 和Record之前的间隙的间隙锁的一种结合。
插入意向锁是一种特殊的间隙锁
(所以有的地方把它简写成 II GAP),这个锁表示插入的意向,只有在 INSERT 的时候才会有这个锁。
注意,这个锁虽然也叫意向锁,但是和上面介绍的表级意向锁是两个完全不同的概念,不要搞混淆了。
插入意向锁和插入意向锁之间互不冲突
,所以可以在同一个间隙中有多个事务同时插入不同索引的记录。
插入意向锁只会和间隙锁或 Next-key 锁冲突
,正如上面所说,间隙锁唯一的作用就是防止其他事务插入记录造成幻读,那么间隙锁是如何防止幻读的呢?正是由于在执行 INSERT 语句时需要加插入意向锁,而插入意向锁和间隙锁冲突,从而阻止了插入操作的执行。