MySQL的锁
# 锁类型
# 共享锁 Share Lock
select ... lock in share mode;
不阻塞其他事务的读操作,其他事务也可以申请获得该共享锁。
阻塞写操作,修改数据需要先加排它锁,所以要等到共享锁释放后。
当两个事务同时对一行数据加了共享锁后,又都修改同一行数据时,会出现都在等待释放共享锁的情况,造成死锁。
begin ;
select * from user where id = 1 lock in share mode;
update user set name = 't1' where id =1;
commit;
2
3
4
begin ;
select * from user where id = 1 lock in share mode;
update user set name = 't2' where id =1;
commit;
2
3
4
当where条件在无索引的字段时,
# 排它锁 Exclusive Lock
select ... for update;
在查询语句后面增加FOR UPDATE,MySQL 就会对查询结果中的每行都加排他锁,当没有其他线程对查询结果集中的任何一行使用排他锁时,可以成功申请排他锁,否则会被阻塞。
# 意向锁 Intention Lock
意向锁是表级锁,其设计目的主要是为了在一个事务中揭示下一行将要被请求锁的类型。InnoDB 中的两个表锁:
意向共享锁(IS):表示事务准备给数据行加入共享锁,也就是说一个数据行加共享锁前必须先取得该表的IS锁;
意向排他锁(IX):类似上面,表示事务准备给数据行加入排他锁,说明事务在一个数据行加排他锁前必须先取得该表的IX锁。
意向锁是 InnoDB 自动加的,不需要用户干预。用于MySQL快速判断能否给表加表锁,提高加表锁的效率。(如果没有意向锁,那么MySQL需要确定每一行数据上是否有锁)。
# 锁算法
# 行锁 Record Lock
锁在索引记录上,可以阻止其它事务对该数据的增删改。
如果表没有索引,MySQL会创建一个隐藏的默认行号索引,使用这个索引来加锁。
# 间隙锁 Gap Lock
锁住两个索引之间的间隙,是一个开区间。用于锁住不存在的数据,防止其他事务插入。
REPEATABLE-READ级别才有,READ-COMMITED级别没有间隙锁。
# 临键锁 Next-key Lock
行锁与间隙锁的结合。左开右闭区间。
# 插入意向锁 Insert Intention Lock
插入意向锁是一种在插入行之前由 INSERT 操作设置的间隙锁。此锁表示插入的意图,即如果插入到同一索引间隙中的多个事务未插入到间隙内的同一位置,则它们无需相互等待。假设有值为 4 和 7 的索引记录。分别尝试插入值 5 和 6 的单独事务,在获得插入行的排他锁之前,每个使用插入意图锁锁定 4 和 7 之间的间隙,但不要相互阻塞,因为行是不冲突的。