MySQL中的锁
InnoDB中锁与索引
- 锁是作用在索引上的.
- 只有SQL命中索引时,才触发锁.
- 没有命中索引,则使用表锁.
锁的分类
- 粒度锁: 表锁,行锁.
- 算法锁: 记录锁,间歇锁,临键锁.
- 属性锁: 共享锁,排它锁.
- 状态锁: 意向共享锁,意向排它锁.
表锁
- 上锁时锁住的是整个表.
- 下一个事务访问该表时,必须等待前一个事务释放锁.
- 粒度大,加锁简单,容易冲突.
行锁
- 上锁时锁住的是表的某一行或者多行记录.
- 其他事务不可以访问同一表中被锁定的行,可以访问其他记录.
- 粒度小,加锁麻烦,不易冲突,并发高.
记录锁(Record Lock)
- 锁住的只是表的某一条记录.
- 出现条件:精准命中,且命中字段为唯一索引.
UPDATE user_info SET name = '张三' WHERE id = 1
,其中id
是唯一索引.- 避免重复读和脏读问题.
间歇锁(Gap Lock)
- 锁住的是某一个区间.
- 相邻ID间形成空隙时,遵循左开右闭原则.
- 出现条件:范围查询且未命中索引,只出现在Repeatable read的事务级别.
SELECT * FROM user_id WHERE id>1 AND id<4
,id为唯一索引.- 防止幻读问题.
临键锁(Next-Key Lock)
- 将查询出来的记录锁住的同时,也把该查询内的所有间隙空间页锁住,再把相邻的下一区间也锁定.
SELECT * FROM user_info WHERE id>1 AND id<=13 FOR UPDATE
- 出现条件:范围查询且命中,查询命中索引.
- 作用:避免脏读,重复读,幻读问题.
共享锁(Share Lock)/读锁/S锁
- 对数据加读锁后,其他事务只能对该数据加读锁,不能对数据加写锁.
- 所有事务释放读锁后,才能加写锁.
- 支持并发读取,避免重复读.
排他锁(Exclusive Lock)/写锁/X锁
- 对数据加写锁后,其他请求不能为数据在任何锁,直到写锁释放.
- 避免脏数据和脏读.
意向锁
当一个事务试图对整个表进行加锁时,需要获得对应类型的意向锁.
意向共享锁
一个事务对整个表进行加共享锁前,首先获得表的意向共享锁.
意向排他锁
一个事务试图对整个表加排他锁前,首先获得表的意向排他锁.
参考: