MySQL实现事务隔离的秘诀之锁

本文详细介绍了MySQL中InnoDB引擎的三种行级锁——记录锁、间隙锁和临键锁,以及它们在并发控制、幻读防止和事务隔离中的作用。同时提到了表级锁和页级锁的区别,以及锁粒度对性能的影响。最后预告了关于MySQL死锁解决方案的文章.
摘要由CSDN通过智能技术生成

在MySQL中,有多种锁类型,我们先了解三种概念的锁,以便对接下来的内容有更好理解。

  • 表级锁(Table Lock):对整个表加锁,其他事务无法修改或读取该表的数据,但可以对其他表进行操作。
  • 页级锁(Page Lock):对数据页(通常是连续的几个行)加锁,控制并发事务对该页的访问。适用于数据较大且并发量较高的场景。
  • 行级锁(Row Lock):对单个行加锁,只锁定需要修改的数据行,其他行可以被同时修改或读取。并发性高,但锁管理较复杂。

一般来说,锁的粒度越大,性能就越差。因为粒度一大,那么发生竞争的可能性就越大,进入锁等待的概率也越大。

例如MyISAM引擎主要使用表锁设计,因此它的并发插入性能显然会很慢,因为每次插入都要加表锁,其他对此表进行操作的事务都会受到影响。而SQL Server起初是侧重于页锁,不过后续开始支持行级锁,但因为设计的缘故导致锁的资源很稀有,锁越多开销越大,最后促成锁升级变为表锁。

而InnoDB主要采用行级锁,且行级锁没有相关额外的开销,能够获得很好的并发性。

innoDB的三种行级锁就是本文的重点:行锁(Record Lock)、间隙锁(Gap Lock)、临键锁(Next-Key Lock)。

记录锁(Record Lock)

InnoDB的存储上是一颗聚簇索引树,因此,innoDB的所谓行锁,实际上就是在索引的节点上加锁。记录锁可以防止多个会话同时修改同一条记录,从而保证数据的一致性。

5a49c93707034e349207d70606f02d84.png

间隙锁(Gap Lock)

用来锁住一个范围内的间隙(即两个索引值之间的空隙),但不包括索引记录本身。

一般情况下,间隙锁是在使用范围查询或者使用唯一索引进行插入时自动创建的。在可重复读(REPEATABLE READ)或者串行化(SERIALIZABLE)的隔离级别下,MySQL会自动创建间隙锁。

间隙锁的存在可以防止幻读问题的产生。由于间隙锁会限制一定范围内的插入操作,避免了其他事务在该范围内插入新的记录,从而保证了一致性。

需要注意的是,间隙锁只锁住范围,并不锁记录本身。

202059575f1245bba2c20ce4e68291a5.png

像上图,(E-F)表示锁住E-F之间的记录,但E、F本身并不加锁,如果此时有另外一个事务操作E、F记录是可以成功的,但是如果是在E和F之间插入数据,则会失败。

比较特殊的,由于此时E是最小值,G是最大值,当想锁住比E小的范围时,用(-∞,E)表示;当想锁住比G大的范围时,用(G,+∞)表示。

临键锁(Next-key Lock)

MySQL的临键锁(Next-Key Locks)是一种用于保护事务并发操作的锁机制。它结合了记录锁和间隙锁,能够实现在并发环境下防止幻读的效果。

临键锁的工作原理如下:

  1. 当事务对一个记录进行读取或写入操作时,会对该记录加上记录锁(行锁)。
  2. 若事务需要对一个范围进行操作(比如读取一段记录或者插入新记录),会对这个范围加上间隙锁(区间锁)。
  3. 锁的释放顺序与加锁顺序相反,即先释放间隙锁再释放记录锁。

大白话速记就是:临键锁=记录锁+间隙锁,左开右闭(不锁左边,锁右边)。

3430eb9d7d304b68a9162eb4b5b0fd81.png

临键锁的作用如下:

  1. 防止幻读:在RR(可重复读)隔离级别下,临键锁会对查询范围的间隙进行加锁,以防止其他事务在范围内插入新记录,从而导致幻读现象。
  2. 提高并发度:临键锁的可精确加锁范围带来了更高的并发度,避免了使用传统锁(如表锁、页锁)时的大范围加锁。

不得不多嘴一句,这个临键锁的命名真是太抽象了,刚开始知道的时候,无论如何也不能通过这个名称知道,这是个什么实现。

看到这,可能有人比较疑惑,前面提到的ReadView的存在看起来已经解决了事务隔离,怎么还会有锁的存在?

事实上,ReadView可以理解为第一道关卡,类似于布隆过滤器,如果满足不了ReadView规则的,一定满足不了锁规则;如果满足了ReadView,不一定满足锁。ReadView更多只是从「读」的角度触发,提供一种快速判读的机制,但是解决不了互相写冲突的问题!

因此,锁是一种更为底层同时逻辑偏重的保证机制。

总结:

  • InnoDB有三种锁:记录锁、间隙锁、临键锁。
  • 记录锁只锁住某个具体节点;间隙锁锁住区间但不包含记录本身;临键锁=记录锁+间隙锁,主要用来解决不可重复读的问题

上一篇:诚意满满之MySQL实现事务隔离的秘诀:锁与MVCC

刚好讲到了Record Lock、Gap Lock和Next-Key Lock,那下一篇便讲一讲在实际工作中容易遇到的,如何排查和解决死锁的问题。

下一篇:如何解决MySQL死锁(看懂MySQL锁日志)

欢迎关注~

  • 23
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值