看过很多innodb锁的文章,已经明白的就不写了,简单做个笔记
Innodb 锁的兼容性:
1、意向锁和意向锁之间都是兼容的
2、X(排他锁)与任何锁都是不兼容的
3、排他意向锁 IX 于S锁是不兼容的
4、剩下的锁都是兼容的
三种锁
record lock
gap lock
next-key lock = record + gap
判断锁一定要加上隔离级别,不同级别锁的情况不同
对于Innodb 一般只需要考虑RR 和 RC 隔离级别即可
RR 三种锁
RC 可以认为只有record锁,但是当表存在唯一索引的时候是存在间隙锁(gap lock)只有这一种特殊情况
显示锁 可以是S 或者 X锁
隐式锁只能是X锁
隐式锁的一种理解 begin insert into data 这时候如果没有提交事务,那么该记录应该是隐式锁,当你想要 select * from data for update 时候会锁等待,即等待这个隐式锁。
举例如下:
create table info ( id int primary key , name varchar(20)) engine = innodb;
session1 session 2
start transaction;
insert into info values (1,'name');
select * from info where id = 1 for update;
session1 提交前都是等待隐式锁
commit;
隐式锁的个人理解就是某个激活的事务要更改一个索引值,这个值即将要改变,那么在另一个事务中要想以这个索引值为条件去更新数据,就需要等待,也就是要给这个被隐式锁锁住的索引加X锁,会LOCK_WAIT
书中有这么一段不是很理解:
drop table if exists a ;
create table a (
a int primary key,
b varchar(30)
) engine = innodb;
insert into values (1,'a'),(2,'b'),(3,'c'),(4,'d');
两个会话事务:
A:
begin;
select * from a where a= 4 for update; B:
begin;
select * from a where a <=2 lock in share mode;
delete from a where a = 3;
select * from a where a <=2 lock in share mode;
首先执行A,然后执行B中的前两句,当执行到B中第二个select的时候会发现锁等待了
书中解释:SELECT 游标锁定的最大记录被标记为操所是已经加锁成功的。其实导致这个现象的原因是SELECT游标锁定的最大记录被标记为了删除(未被真正PURGE删除),因此,当第二次再次执行select操作的时候,需要进一步锁定记录,也是a等于4的记录,而该记录已经在会话A中被锁定了。
不理解:
应该是A锁定a=4的记录,然后B的第一个select s锁锁定了a<=2的所有记录,delete 时候锁定了a=3的记录,但是delete的语句只是标记了a=3要删除,但是没有实际PURGE,第二个select 为什么要去锁定 a=4呢?