CREATE TABLE `person` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(100) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`test` bigint(20) DEFAULT NULL,
`tests` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `person_test_IDX` (`test`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=61 DEFAULT CHARSET=utf8
以下所有不同事务间的sql默认都不作事务提交, gap锁和next key锁不做区分
一 , RC隔离级别
RC 没有gap lock?
事务一:update person set name ='' where test = 25
事务二:
insert into person(test) values(25) 不阻塞
update person set name ='' where test = 25 阻塞
因为RC下,事务一持有test=25索引的record锁, 所以可以执行insert, 而不能执行update(需要查询的那个记录被锁定)
如果RR隔离级别下, 事务二中的两条语句全部阻塞,其中test=25的记录是record锁, (18,+wuqiong)是gap锁
二, RR隔离级别
唯一索引且非范围查询(in查询不算范围查询), 不会产生gap锁
(1)for update/lock in share mode的读, delete, update
(2)非唯一索引, 唯一索引的范围查询
(1)(2)中任一搭配, 都会产生gap lock,
简单的insert into操作不会产生间隙锁
1. test数据8,10,12, 加锁查询test=10, 锁定范围(8,12)
test数据8,9,10, 加锁查询test=9, 只有test=9这个行锁,间隙锁是(8,10),等同于不存在
test数据8, 10, 加锁查询test =10,锁定范围(8, +wuqiong)
test数据8,10, 加锁查询test=9,锁定范围[8,10) 左闭右开
test数据7,8,9,10, 加锁查询test<=8,锁定范围是(-wuqiong,9], 为什么会锁定9
2. 间隙锁阻塞的是insert操作, 不会阻塞update操作(test 数据有 10,15,20)
事务一: update person set name = '' where test =15
事务二:
insert into person(test) values( 16) 阻塞
update person set name = '' where test = 16 不阻塞
3. 非簇拥索引加锁后,会连带对主键加锁;
关于连带加锁的问题??????????????
4.record锁和gap锁的区别: 前者阻塞的是insert和update, 后者只阻塞insert,
换言之两个gap锁可以相交(间隙锁是相互兼容的), 如test数据13,16,18,25, 以下两个事务不会阻塞
事务一: update person set name = '' where test = 18 , 锁定范围(16,25)
事务二: update person set name = '' where test = 16, 锁定范围(13,18)
5. 间隙锁的归并
test数据10,13,15,18,20
事务一: select * from person where test=13 for update 锁定(10,15)
事务二: select * from person where test=18 for update 锁定(15,20)
事务三: delete from person where test =15
此时事务一和事务二的锁定范围都变成(10,20)
其他例子可见 https://blog.csdn.net/asdfsadfasdfsa/article/details/81949604