面试必会 MySql的锁机制(InnoDB)

1. 引言

开发多用户、数据库驱动的应用时,最大的一个难点是:一方面要最大程度地利用数据库的并发访问,另一方面还要确保每个用户能以一致的方式读取和修改数据。为此就有了锁的机制 [1]

2. 锁的分类

2.1. 按粒度

锁按粒度可分为表锁、页锁和行锁

  • 表锁:直接锁定整个数据表。开销小,加锁快,不会发生死锁。锁冲突几率大,并发性能低。
  • 行锁:锁定某个或某些行。开销大,加锁慢,会发生死锁。锁冲突几率小,并发性能高。
  • 页表:介于表锁和行锁之间。

不难发现,表锁和行锁的特点基本是相反的,从应用场景上来说,表锁更适合以查询为主,只有少量按索引条件更新数据的应用;而行锁更适合有大量按索引条件并发更新少量不同数据,同时又有并发查询的应用。

MyISAM支持表锁;InnoDB支持表锁和行锁

  • 开销:维护锁是要占用内存的。
  • 加锁速度:如果是表锁,咔嚓一下就锁住了;如果是行锁,要找到需要加锁的行,再加锁。
  • 关于死锁,后面会详细讲

2.2. 按加锁方式

按加锁方式可分为共享锁(S Lock)和排他锁(X Lock);共享锁是读锁,排他锁是写锁,所以有人如是说:共享读锁,排他写锁。表、页和行都可以加共享锁和排他锁,下面以行锁为例说明规则

  • 如果一个事务T获得了行R的共享锁,那么其他事务可以获得该行的共享锁,但是不能获得该行的排他锁
  • 如果一个事务T获得了行R的共享锁,那么事务T只能对行R进行读操作
  • 如果一个事务T获得了行R的排他锁,那么其他事务不能获得该行的任和锁
  • 如果一个事务T获得了行R的排他锁,那么事务T能对行R进行读和写操作

2.3. 多粒度锁定--意向锁

InnoDB支持多粒度锁定,这种锁定允许事务在行级上锁和表级上的锁同时存在。为此,InnoDB支持一种额外的锁方式,即意向锁。在InnoDB中,意向锁是表级别的锁,有意向共享锁(IS Lock)和意向排他锁(IX Lock)两种。规定在事务在请求S锁和X锁前,需要先获得对应的IS、IX锁。意向锁是由存储引擎自己维护的,用户无需手动操作意向锁。

意向锁的作用:意向锁用于快速判断表锁和行锁之间是否有冲突。事务T在加表锁之前,要检查此表上是否已经有表锁或行锁,如果已经存在表锁,事务T立即阻塞。如果没有表锁,就要检查是否有行锁,这个过程效率很低,因为需要遍历整张表一行一行地检查。如果有了意向锁,任何事务在获取行锁之前必须先获得意向锁(表级别的),那么事务T发现表上已经被加了意向锁,就知道表中的某些行必然已经被锁,也就避免了遍历全表去检查。

3. InnoDB的行锁

InnoDB的行锁是加在索引之上的,这意味着只有通过索引条件检索数据,才会使用行锁,否则将使用表锁;不同的是Oracle数据库的行锁加在数据行上[2]。主要注意的是,不能仅仅通过where子句判断是否会用到索引,而是要看具体的执行计划。另外,当按照辅助索引检索数据时,对应的主键索引的索引项也会加上锁。

3.1. 行锁的3种算法

InnoDB存储引擎有3种行锁的算法,分别是

  • Record Lock:单个行记录上的锁
  • Gap Lock:间隙锁,锁定一个范围,但不包括记录本身
  • Next-Key Lock:Gap Lock + Record Lock,锁定一个范围,包括记录本身

3.2. Next-Key Lock

采用Next-Key Lock的锁定技术称为Next-Key Locking,锁定命中的区间+下一个区间。Next-Key Lock是范围查找且命中记录时,InnoDB的默认行锁算法,可以把Record Lock和Gap Lock看作是它的降级/退化。其设计目的是为了解决幻读问题。例如有一个索引有10,11,13和20这四个值,那么可能被锁定的区间为:

如果一个事务T通过辅助索引查询11,那么锁定的范围是(10,11 ]和(11,13 ];如果通过辅助索引查询20,那么锁定的范围是(13,20 ]和(20,+\infty ]。注意,当通过主键索引/聚簇索引/唯一索引查询时候,因为此索引不允许有重复值,所以不必担心插入重复值导致幻读,所以InnoDB会对Next-Key Lock进行优化,将其降级为Record Lock,只锁查询记录本身。使用不存在的检索条件进行等值查询,使用Gap Lock,左开右开区间。对于范围查询,则会用Next-Key Lock。【这些的前提是用到了索引,即用到了行锁】

4. 死锁TODO

5. 总结

(1)InnoDB的行锁是加在索引之上的,这意味着只有通过索引条件检索数据,才会使用行锁,否则将使用表锁;

(2)InnoDB在可重复度隔离级别下,通过Next-Key Lock解决幻读问题;

(3)当通过主键索引/聚簇索引/唯一索引查询时候,InnoDB会对Next-Key Lock进行优化,将其降级为Record Lock。

引用资料

[1]《MySql技术内幕--InnoDB存储引擎》第二版.姜承尧

[2] MySQL中的锁(表锁、行锁)

[3] 阿里P6+的Mysql锁机制二面试总结,值得收藏

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值