1、MySQL锁的概念
MySQL中的锁的概念主要有:行锁、表锁、意向锁;共享锁(读锁)、排他锁(写锁);悲观锁、乐观锁、两阶段锁协议;间隙锁、next-key;
行锁、表锁、意向锁
- 行锁:只锁定一行记录的锁。
- 表锁:锁定整张表的锁。
- 意向锁:使用表锁时,表中可能存在行锁,行锁与表锁互斥,所以表锁加锁首先要扫描全表判断有没有行锁,这样会有很大系统性能损耗。为了解决这个问题引入意向锁,行锁加锁时也会对整个表加意向锁,表锁只需要根据能否获得意向锁来判断表中是否存在行锁。即意向锁是用来行锁阻塞表锁的。
共享锁、排他锁、读写锁
- 共享锁(读锁):多个事务读取可以重复获取共享锁,即只做读取不做更新操作,也称为读锁。
- 排他锁(写锁):一次只能有一个事务获取到排他锁,用于更新操作,也称为写锁。
两阶段锁协议、悲观锁、乐观锁
-
两阶段锁协议:分为加锁阶段和解锁阶段。
- 加锁阶段:所有读操作之前那要申请并获得读锁;所有写操作之前要申请并获得写锁;加锁不成功则事务进入等待状态,直到加锁成功才继续执行
- 解锁阶段:直到事务完成后再进行解锁
即事务需要加锁时再加锁,直达事务提交后一次性解锁。
-
两阶段锁协议的意义?
若并发执行的所有事务均遵守两阶段锁协议,则对这些事务的任何并发调度策略都是可串行化的。
-
两阶段锁可以避免死锁吗?
不能避免死锁,但是mysql可以利用死锁检测算法检测到死锁并进行事务解除。
-
悲观锁:数据库的所有操作都进行加锁,防止并发竞争问题。性能很低
-
乐观锁:添加版本号version字段,并遵守两阶段锁协议。
间隙锁、next-key
-
间隙锁:MVCC解决了快照读(查询)的幻读问题,但是无法解决当前读(修改)的幻读问题。为了解决这个问题,MySQL不仅在修改的数据上加锁,还锁定了一个范围,保证范围内的数据锁定,解决幻行问题。根据索引划分范围,根据需要锁定范围。
- 实现:如存在1,3,6三个索引,则会得到如下范围:
( − ∞ , 1 ] , ( 1 , 3 ] , ( 3 , 6 ] , ( 6 , + ∞ ] (-\infty, 1],(1, 3],(3,6],(6,+\infty] (−∞,1],(1,3],(3,6],(6,+∞]
当插入索引为2的数据时,mysql会锁定(1,3]范围,特别注意的是,InnoDB也会在下一个区间之间加锁锁定(3,6]区间。
- 实现:如存在1,3,6三个索引,则会得到如下范围:
-
next-key:行锁+间隙锁一起使用。当索引具有唯一属性时InnoDB会将next-key锁降级为行锁