MySQL 間隙鎖
阿新 • • 發佈:2018-05-23
死鎖分析 des ola ast star del PE ant for
一.根據案例二:不同索引加鎖順序的問題,模擬重現死鎖(詳細操作步驟)
- 1.RR級別下,更新操作默認會加行級鎖,行級鎖會對索引加鎖
- 2.如果更新語句使用多個索引,行級鎖會先鎖定普通索引,再鎖定聚簇索引
- 3.如果兩個SQL用到了不同的普通索引,或者一個用了,另外一個沒用
- 4.會導致這兩個SQL加行級鎖的順序不一致,形成多個事物之間X鎖的循環等待,形成死鎖
1.1表結構
root@slave01 22:28: [sqltest]> create table user_info (id int primary key,username varchar(20), status tinyint,key(username)); Query OK, 0 rows affected (0.03 sec) # root@slave01 22:54: [sqltest]> show create table user_info; +-----------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +-----------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | user_info | CREATE TABLE `user_info` ( `id` int(11) NOT NULL, `username` varchar(20) DEFAULT NULL, `status` tinyint(4) DEFAULT NULL, PRIMARY KEY (`id`), KEY `username` (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 | +-----------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) # insert into user_info values(1,‘yzw1‘,1); insert into user_info values(3,‘yzw3‘,0); insert into user_info values(5,‘yzw5‘,1);
1.2執行計劃
root@master 23:15: [sqltest]> desc update user_info set status=1 where username=‘yzw3‘; +----+-------------+-----------+------------+-------+---------------+----------+---------+-------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-----------+------------+-------+---------------+----------+---------+-------+------+----------+-------------+ | 1 | UPDATE | user_info | NULL | range | username | username | 63 | const | 1 | 100.00 | Using where | +----+-------------+-----------+------------+-------+---------------+----------+---------+-------+------+----------+-------------+ 1 row in set (0.01 sec) # root@master 23:15: [sqltest]> desc update user_info set username=‘yzw33‘ where id=3; +----+-------------+-----------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-----------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+ | 1 | UPDATE | user_info | NULL | range | PRIMARY | PRIMARY | 4 | const | 1 | 100.00 | Using where | +----+-------------+-----------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+ 1 row in set (0.00 sec)
1.3重現
session 1 | session 2 |
---|---|
begin; update user_info set status=1 where username=‘yzw3‘; |
|
此時session除了給索引username加x鎖,還給主鍵索引id=3的行記錄加了x鎖,但是這兩個鎖並不是同時獲取的 | |
第一步先獲取普通索引username上的X鎖 | |
此時session 2進行更新 | begin; update user_info set username=‘yzw33‘ where id=3; |
session 2 第一步需要先獲取聚簇索引,也就是主鍵索引上的X鎖 第二步需要獲取普通索引username上的X鎖 | |
出現死鎖ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction | |
需要session 2的主鍵索引X鎖 | 需要session 1的普通索引username X鎖 |
root@master 23:11: [(none)]> select * from information_schema.innodb_locks;
+-------------------+-------------+-----------+-----------+-----------------------+------------+------------+-----------+----------+-----------+
| lock_id | lock_trx_id | lock_mode | lock_type | lock_table | lock_index | lock_space | lock_page | lock_rec | lock_data |
+-------------------+-------------+-----------+-----------+-----------------------+------------+------------+-----------+----------+-----------+
| 48736590:1135:3:3 | 48736590 | X | RECORD | `sqltest`.`user_info` | PRIMARY | 1135 | 3 | 3 | 3 |
| 48733648:1135:3:3 | 48733648 | X | RECORD | `sqltest`.`user_info` | PRIMARY | 1135 | 3 | 3 | 3 |
+-------------------+-------------+-----------+-----------+-----------------------+------------+------------+-----------+----------+-----------+
2 rows in set, 1 warning (0.00 sec)
1.4重現
1.給status列增加索引
create index idx_status on user_info(status);
2.執行計劃,兩條語句都是走的普通索引
root@master 23:26: [sqltest]> desc update user_info set status=1 where username=‘yzw3‘; +----+-------------+-----------+------------+-------+---------------+----------+---------+-------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-----------+------------+-------+---------------+----------+---------+-------+------+----------+-------------+ | 1 | UPDATE | user_info | NULL | range | username | username | 63 | const | 1 | 100.00 | Using where | +----+-------------+-----------+------------+-------+---------------+----------+---------+-------+------+----------+-------------+ 1 row in set (0.04 sec) # root@master 23:29: [sqltest]> desc update user_info set username=‘yzw33‘ where status=0; +----+-------------+-----------+------------+-------+---------------+------------+---------+-------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-----------+------------+-------+---------------+------------+---------+-------+------+----------+-------------+ | 1 | UPDATE | user_info | NULL | range | idx_status | idx_status | 2 | const | 1 | 100.00 | Using where | +----+-------------+-----------+------------+-------+---------------+------------+---------+-------+------+----------+-------------+ 1 row in set (0.01 sec)
3.兩個會話更新索引
session 1 session 2 begin;
update user_info set status=1 where username=‘yzw3‘;第一步已經獲取了username的普通索引X鎖 begin;
update user_info set username=‘yzw33‘ where status=0;第一步已經獲取status的普通索引X鎖
第二步給主鍵索引加X鎖第二步需要給主鍵索引加X鎖,無法獲取 出現死鎖ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction 因為要更新非主鍵索引username,因此要給username加X鎖,但是無法獲取 root@master 23:30: [sqltest]> select * from information_schema.innodb_locks; +-------------------+-------------+-----------+-----------+-----------------------+------------+------------+-----------+----------+-----------+ | lock_id | lock_trx_id | lock_mode | lock_type | lock_table | lock_index | lock_space | lock_page | lock_rec | lock_data | +-------------------+-------------+-----------+-----------+-----------------------+------------+------------+-----------+----------+-----------+ | 48739611:1135:5:2 | 48739611 | X | RECORD | `sqltest`.`user_info` | idx_status | 1135 | 5 | 2 | 0, 3 | | 48738737:1135:5:2 | 48738737 | X | RECORD | `sqltest`.`user_info` | idx_status | 1135 | 5 | 2 | 0, 3 | +-------------------+-------------+-----------+-----------+-----------------------+------------+------------+-----------+----------+-----------+ 2 rows in set, 1 warning (0.00 sec)
1.5多查詢一次取主鍵,解決死鎖
begin; update user_info set status=1 where id in (select id from (select id from user_info where username=‘yzw3‘) t); begin; update user_info set username=‘yzw33‘ where id in (select id from (select id from user_info where status=0) t);
root@master 23:56: [sqltest]> select * from information_schema.innodb_locks; +-------------------+-------------+-----------+-----------+-----------------------+------------+------------+-----------+----------+-----------+ | lock_id | lock_trx_id | lock_mode | lock_type | lock_table | lock_index | lock_space | lock_page | lock_rec | lock_data | +-------------------+-------------+-----------+-----------+-----------------------+------------+------------+-----------+----------+-----------+ | 48744368:1135:3:3 | 48744368 | X | RECORD | `sqltest`.`user_info` | PRIMARY | 1135 | 3 | 3 | 3 | | 48744353:1135:3:3 | 48744353 | X | RECORD | `sqltest`.`user_info` | PRIMARY | 1135 | 3 | 3 | 3 | +-------------------+-------------+-----------+-----------+-----------------------+------------+------------+-----------+----------+-----------+ 2 rows in set, 1 warning (0.00 sec)
依然存在死鎖,因為都給主鍵id加了X鎖
二.根據方案三:TMS死鎖分析和處理,模擬重現死鎖(詳細操作步驟)
1.構造數據
create table user_info1 (id int primary key,name varchar(10), level tinyint); insert into user_info1 values(1,‘AA‘,0); insert into user_info1 values(3,‘CC‘,0); insert into user_info1 values(5,‘EE‘,2); insert into user_info1 values(7,‘GG‘,5); insert into user_info1 values(9,‘GG‘,7); insert into user_info1 values(11,‘JJ‘,20); session 1 >select * from user_info1; +----+------+-------+ | id | name | level | +----+------+-------+ | 1 | AA | 0 | | 3 | CC | 0 | | 5 | EE | 2 | | 7 | GG | 5 | | 9 | GG | 7 | | 11 | JJ | 20 | +----+------+-------+ 6 rows in set (0.00 sec)
2.過程
session 1 session 2 begin;
insert into user_info1 values(2,‘BB‘,1);delete from user_info1 where name=‘BB‘;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction此時是RC級別 session 2首先插入數據並給這一行加X鎖,因為沒有索引,同時在兩邊加gap鎖 delete from user_info1 where name=‘BC‘;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transactiondelete from user_info1 where level=8;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transactiondelete where條件沒有索引,會對整表掃描並加gap鎖,但是此時session2已經加了gap鎖,session1的delete事務被回退 delete from user_info1 where name=‘BB‘ ------- TRX HAS BEEN WAITING 10 SEC FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 1137 page no 3 n bits 80 index PRIMARY of table `sqltest`.`user_info1` trx id 48906774 lock_mode X locks rec but not gap waiting Record lock, heap no 8 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
3保持RC
set tx_isolation=‘READ-COMMITTED‘;
級別,增加索引session 1 >create index idx_name_level on user_info1(name,level); Query OK, 0 rows affected (0.12 sec) Records: 0 Duplicates: 0 Warnings: 0
session 1 session 2 begin;
insert into user_info1 values(2,‘BB‘,1);delete from user_info1 where name=‘BB‘;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction此時是RC級別 session 2首先插入數據並加gap鎖, session 1 >delete from user_info1 where name=‘BC‘;
Query OK, 0 rows affected (0.00 sec)RC級別下,增加了索引,沒有了gap鎖 session 1 >delete from user_info1 where name=‘BB‘;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
session 1 >delete from user_info1 where level=8;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
session 1 >delete from user_info1 where level=20;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
session 1 >delete from user_info1 where level=7;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
session 1 >delete from user_info1 where level=2;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction索引(a,b),如果where字段使用了索引a,則不存在gap鎖了,猜測是單獨使用索引b還是會存在gap鎖,因為無法使用索引 root@master 16:31: [(none)]> select * from information_schema.innodb_locks; +-------------------+-------------+-----------+-----------+------------------------+------------+------------+-----------+----------+-----------+ | lock_id | lock_trx_id | lock_mode | lock_type | lock_table | lock_index | lock_space | lock_page | lock_rec | lock_data | +-------------------+-------------+-----------+-----------+------------------------+------------+------------+-----------+----------+-----------+ | 48942672:1137:3:8 | 48942672 | X | RECORD | `sqltest`.`user_info1` | PRIMARY | 1137 | 3 | 8 | 2 | | 48942589:1137:3:8 | 48942589 | S | RECORD | `sqltest`.`user_info1` | PRIMARY | 1137 | 3 | 8 | 2 | +-------------------+-------------+-----------+-----------+------------------------+------------+------------+-----------+----------+-----------+ 2 rows in set, 1 warning (0.00 sec)
4增加索引(b),驗證
session 1 >create index idx_level on user_info1(level); Query OK, 0 rows affected (0.08 sec) Records: 0 Duplicates: 0 Warnings: 0
session 1 session 2 begin;
insert into user_info1 values(2,‘BB‘,1);delete from user_info1 where name=‘BB‘;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction此時是RC級別 session 2首先插入數據並加X鎖 session 1 >delete from user_info1 where name=‘BC‘;
Query OK, 0 rows affected (0.00 sec)
session 1 >delete from user_info1 where name=‘BB‘;
ERROR 1205 (HY000): Lock wait timeout xceeded; try restarting transaction
session 1 >delete from user_info1 where level=8;
Query OK, 0 rows affected (0.01 sec)
session 1 >delete from user_info1 where level=20;
Query OK, 1 row affected (0.01 sec)
session 1 >delete from user_info1 where level=7;
Query OK, 1 row affected (0.00 sec)
session 1 >delete from user_info1 where level=2;
Query OK, 1 row affected (0.00 sec)此時b有了索引,RC級別下也就不存在gap鎖了 5更改為RR級別
set tx_isolation=‘REPEATABLE-READ‘;
,先使用索引(a,b)session 2 >drop index idx_level on user_info1; Query OK, 0 rows affected (0.16 sec) Records: 0 Duplicates: 0 Warnings: 0 session 2 >begin; Query OK, 0 rows affected (0.00 sec) # session 2 >insert into user_info1 values(2,‘BB‘,1); Query OK, 1 row affected (0.00 sec) # session 1 >delete from user_info1 where name=‘BB‘; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction session 1 >delete from user_info1 where name=‘BC‘; Query OK, 0 rows affected (0.00 sec) # session 1 >delete from user_info1 where level=8; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction session 1 >delete from user_info1 where level=2; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction session 1 >delete from user_info1 where name=‘CB‘; Query OK, 0 rows affected (0.00 sec) # session 1 >delete from user_info1 where name=‘BA‘; Query OK, 0 rows affected (0.00 sec)
6總結
1) RC和RR級別下如果更新沒有索引的字段,會加gap鎖
2) 必須能用上索引,(a,b)只用b是無效索引
3) RC增加了索引後就不存在gap鎖了
3) RR級別在沒有索引的情況,用不上索引也會產生gap鎖
4) 解決方法,最好使用RC級別+索引,或者RR下修改參數innodb_locks_unsafe_for_binlog=on
5) 間隙鎖只會block住insert操作session 1 >select * from user_info1; +----+------+-------+ | id | name | level | +----+------+-------+ | 1 | AA | 0 | | 3 | BA | 1 | | 5 | EE | 2 | | 7 | GG | 5 | | 9 | GG | 7 | | 11 | JJ | 20 | +----+------+-------+ 6 rows in set (0.00 sec) # session 1 >begin; Query OK, 0 rows affected (0.00 sec) # session 1 >update user_info1 set level=3 where name=‘BA‘; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 session 2 >begin; Query OK, 0 rows affected (0.01 sec) # session 2 >insert into user_info1 values(2,‘AB‘,1); ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
三.根據案例四:MySQL間隙鎖導致的Deadlock分析,模擬重現死鎖(詳細操作步驟)
3.1 造數據
create table t3 (id int auto_increment,coupon_id int,uid int,is_inuse tinyint,primary key(id),key (coupon_id,uid));
insert into t3 (coupon_id,uid,is_inuse) values(16,160825,1);
insert into t3 (coupon_id,uid,is_inuse) values(16,160835,1);
insert into t3 (coupon_id,uid,is_inuse) values(16,160845,1);
insert into t3 (coupon_id,uid,is_inuse) values(16,160855,1);
insert into t3 (coupon_id,uid,is_inuse) values(16,160865,1);
root@master 22:56: [sqltest]> select * from t3;
+----+-----------+--------+----------+
| id | coupon_id | uid | is_inuse |
+----+-----------+--------+----------+
| 1 | 16 | 160825 | 1 |
| 2 | 16 | 160835 | 1 |
| 3 | 16 | 160845 | 1 |
| 4 | 16 | 160855 | 1 |
| 5 | 16 | 160865 | 1 |
+----+-----------+--------+----------+
5 rows in set (0.00 sec)
3.2 行記錄兩邊間隙鎖範圍內無法插入
1.session 1給id=3的行記錄加X鎖,同時加間隙鎖:160835~160845,160845~160855
set tx_isolation=‘REPEATABLE-READ‘; set autocommit=0; start transaction; select * from t3 where (uid=160845 and coupon_id=16 and is_inuse=1) for update; +----+-----------+--------+----------+ | id | coupon_id | uid | is_inuse | +----+-----------+--------+----------+ | 3 | 16 | 160845 | 1 | +----+-----------+--------+----------+ 1 row in set (0.00 sec)
2.session 2插入記錄,在間隙範圍:160835~160845
set tx_isolation=‘REPEATABLE-READ‘; set autocommit=0; start transaction; insert into t3 (coupon_id,uid,is_inuse) values (16,160840,1); ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
3.lock
root@master 23:08: [sqltest]> select * from information_schema.innodb_locks; +-------------------+-------------+-----------+-----------+----------------+------------+------------+-----------+----------+---------------+ | lock_id | lock_trx_id | lock_mode | lock_type | lock_table | lock_index | lock_space | lock_page | lock_rec | lock_data | +-------------------+-------------+-----------+-----------+----------------+------------+------------+-----------+----------+---------------+ | 49020303:1139:4:4 | 49020303 | X,GAP | RECORD | `sqltest`.`t3` | coupon_id | 1139 | 4 | 4 | 16, 160845, 3 | | 49020011:1139:4:4 | 49020011 | X | RECORD | `sqltest`.`t3` | coupon_id | 1139 | 4 | 4 | 16, 160845, 3 | +-------------------+-------------+-----------+-----------+----------------+------------+------------+-----------+----------+---------------+ 2 rows in set, 1 warning (0.00 sec)
4.session 2插入記錄,在間隙範圍:160845~160855
set tx_isolation=‘REPEATABLE-READ‘; set autocommit=0; start transaction; insert into t3 (coupon_id,uid,is_inuse) values (16,160850,1); ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
5.lock
root@master 23:11: [sqltest]> select * from information_schema.innodb_locks; +-------------------+-------------+-----------+-----------+----------------+------------+------------+-----------+----------+---------------+ | lock_id | lock_trx_id | lock_mode | lock_type | lock_table | lock_index | lock_space | lock_page | lock_rec | lock_data | +-------------------+-------------+-----------+-----------+----------------+------------+------------+-----------+----------+---------------+ | 49022356:1139:4:5 | 49022356 | X,GAP | RECORD | `sqltest`.`t3` | coupon_id | 1139 | 4 | 5 | 16, 160855, 4 | | 49020011:1139:4:5 | 49020011 | X,GAP | RECORD | `sqltest`.`t3` | coupon_id | 1139 | 4 | 5 | 16, 160855, 4 | +-------------------+-------------+-----------+-----------+----------------+------------+------------+-----------+----------+---------------+ 2 rows in set, 1 warning (0.00 sec)
3.3 行記錄間隙鎖範圍外可以插入
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction session 2 >insert into t3 (coupon_id,uid,is_inuse) values (16,160860,1); Query OK, 1 row affected (0.01 sec)
3.4 update不存在的記錄,也會加間隙鎖
1.數據
session 1 >select * from t3; +----+-----------+--------+----------+ | id | coupon_id | uid | is_inuse | +----+-----------+--------+----------+ | 1 | 16 | 160825 | 1 | | 2 | 16 | 160835 | 1 | | 3 | 16 | 160845 | 1 | | 4 | 16 | 160855 | 1 | | 5 | 16 | 160865 | 1 | +----+-----------+--------+----------+ 5 rows in set (0.00 sec)
2.update一條不存在的記錄,此時gap鎖範圍:160835~160845,160845~160855
set tx_isolation=‘REPEATABLE-READ‘; set autocommit=0; start transaction; update t3 set is_inuse=0 where coupon_id=16 and uid=160845 and is_inuse=1;
3.在間隙範圍插入新值會產生死鎖
set tx_isolation=‘REPEATABLE-READ‘; set autocommit=0; start transaction; insert into t3 (coupon_id,uid,is_inuse) values (16,160840,1); ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
4.lock
root@master 23:11: [sqltest]> select * from information_schema.innodb_locks; +-------------------+-------------+-----------+-----------+----------------+------------+------------+-----------+----------+---------------+ | lock_id | lock_trx_id | lock_mode | lock_type | lock_table | lock_index | lock_space | lock_page | lock_rec | lock_data | +-------------------+-------------+-----------+-----------+----------------+------------+------------+-----------+----------+---------------+ | 49023844:1139:4:4 | 49023844 | X,GAP | RECORD | `sqltest`.`t3` | coupon_id | 1139 | 4 | 4 | 16, 160845, 3 | | 49023813:1139:4:4 | 49023813 | X | RECORD | `sqltest`.`t3` | coupon_id | 1139 | 4 | 4 | 16, 160845, 3 | +-------------------+-------------+-----------+-----------+----------------+------------+------------+-----------+----------+---------------+ 2 rows in set, 1 warning (0.00 sec)
3.5刪除索引,即使是間隙範圍外的插入也會被block
1.刪除索引
session 2 >drop index coupon_id on t3; Query OK, 0 rows affected (0.09 sec) Records: 0 Duplicates: 0 Warnings: 0 # session 2 >commit; Query OK, 0 rows affected (0.00 sec)
2.事務1加鎖
set tx_isolation=‘REPEATABLE-READ‘; set autocommit=0; start transaction; select * from t3 where (uid=160845 and coupon_id=16 and is_inuse=1) for update;
3.事務2在間隙鎖範圍外插入,此時不是間隙鎖,而是全表鎖,無法插入
set tx_isolation=‘REPEATABLE-READ‘; set autocommit=0; start transaction; select * from t3 where (uid=160850 and coupon_id=16 and is_inuse=1) for update; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
4.lock
root@master 23:27: [sqltest]> select * from information_schema.innodb_locks; +-------------------+-------------+-----------+-----------+----------------+------------+------------+-----------+----------+-----------+ | lock_id | lock_trx_id | lock_mode | lock_type | lock_table | lock_index | lock_space | lock_page | lock_rec | lock_data | +-------------------+-------------+-----------+-----------+----------------+------------+------------+-----------+----------+-----------+ | 49025074:1139:3:2 | 49025074 | X | RECORD | `sqltest`.`t3` | PRIMARY | 1139 | 3 | 2 | 1 | | 49025016:1139:3:2 | 49025016 | X | RECORD | `sqltest`.`t3` | PRIMARY | 1139 | 3 | 2 | 1 | +-------------------+-------------+-----------+-----------+----------------+------------+------------+-----------+----------+-----------+ 2 rows in set, 1 warning (0.00 sec)
3.6 總結
- 1.RR級別下,有索引,更新的時候會給行加X鎖,前後加GAP鎖
- 2.gap鎖範圍內無法插入新數據,避免產生幻讀
- 3.gap鎖範圍外可以正常插入新數據
- 4.如果沒有索引,更新的事務則加的就是全表鎖了
- 5.間隙內或者間隙外都無法插入新數據
MySQL 間隙鎖