前言:
Next-Key Locks译称Next-Key锁,本文参考官方文档进行学习说明外加实验例子
数据库版本:
SELECT VERSION();
±-----------+
| version() |
±-----------+
| 5.6.34-log |
±-----------+
数据库引擎:
show variables like ‘%engine%’;
±---------------------------±-------+
| Variable_name | Value |
±---------------------------±-------+
| default_storage_engine | InnoDB |
| default_tmp_storage_engine | InnoDB |
| storage_engine | InnoDB |
±---------------------------±-------+
根据版本信息参考官方文档:
1.MySQL 5.6 Reference Manual-InnoDB Next-Key Locks(next-key锁)
next-key锁
next-key锁是记录锁与间隙锁的组合,会封锁索引记录本身,以及索引记录之前的区间
A next-key lock is a combination of a record lock on the index record and a gap lock on the gap before the index record.
如果一个会话占有了索引记录R的共享/排他锁,其他会话不能立刻在R之前的区间插入新的索引记录。
If one session has a shared or exclusive lock on record R in an index, another session cannot insert a new index record in the gap immediately before R in the index order.
针对官方文档说的这一点,我经过测试发现,next-key锁并非只锁记录之前的区间,记录之后的区间也会锁定,下面是测试例子:
1.创建表:
CREATE TABLE `test_user` (
`user_id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` char(10) NOT NULL,
PRIMARY KEY (`user_id`),
KEY `index_user` (`name`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;
2.插入数据:
INSERT INTO `test_user` VALUES (1,'a');
INSERT INTO `test_user` VALUES (3,'c');
3.测试开始:
事务1:
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from test_user where name='c' for update;
+---------+------+
| user_id | name |
+---------+------+
| 3 | c |
+---------+------+
1 row in set (0.00 sec)
事务2:
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into test_user(user_id,name) values(4,'d');
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
查看show engine innodb stauts\G;
insert into test_user(user_id,name) values(4,'d')
------- TRX HAS BEEN WAITING 10 SEC FOR THIS LOCK TO BE GRANTED:
等待事务1释放锁
RECORD LOCKS space id 6631 page no 4 n bits 72 index `index_user` of table `testdata`.`test_user` trx id 117917549 lock_mode X locks gap before rec insert intention waiting
结果:事务2在记录之后的区间内执行insert会阻塞超时。
个人总结:
1.next-key锁应该就是间隙锁+行锁,所以改变事物隔离级别为RC级别或开启innodb_locks_unsafe_for_binlog参数,next-key锁也会失效