广告
返回顶部
首页 > 资讯 > 数据库 >InnoDB 事务加锁分析
  • 472
分享到

InnoDB 事务加锁分析

2024-04-02 19:04:59 472人浏览 独家记忆
摘要

本文首发于 vivo互联网技术 微信公众号  链接:https://mp.weixin.qq.com/s/S7MhlsZveBHRSQhq5aTIJA 作者:何志创 一般大家对数据库事务的了解可能停

本文首发于 vivo互联网技术 微信公众号 
链接:https://mp.weixin.qq.com/s/S7MhlsZveBHRSQhq5aTIJA
作者:何志创

一般大家对数据库事务的了解可能停留在事务的ACID特性以及事务4种不同的隔离级别层面上,而对于事务 4 种不同隔离级别如何实现了解相对较少。

本文以 Mysql 数据库 InnoDB 引擎为例,为大家分析 InnoDB数据库引擎对默认的隔离级别可重复读(RR)的具体实现。

整文知识点介绍:事务4种隔离级别、不同隔离级别解决的问题、mvcC、的类型、加锁案例分析;阅读完整文相信大家对事务隔离级别的具体实现有了一定的认识。

一、事务的隔离级别

1、4 种隔离级别

(1)未提交读(Read uncommitted):一个事务读取到其他事务未提交的数据,是级别最低的隔离机制;

(2)提交读(Read committed):一个事务读取到其他事务提交后的数据;

(3)可重复读(Repeatable read):一个事务对同一份数据读取到的相同,不在乎其他事务对数据的修改;

(4)序列化(Serializable) :事务串行化执行,隔离级别最高,牺牲了系统的并发性。

2、不同隔离级别解决的问题

若不考虑事务的隔离级别,则事务的并发会造成以下问题:

(1)脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据。

(2)不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。

(3)幻读:同一事务中对同一范围的数据进行读取,结果却多出了数据或者少了数据,这就叫幻读。(如同一事务对id<10的范围进行2次查询,第一次出现id=8、9的两条数据,第二次出现id=7、8、9的3条数据)。

不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表。

不同的隔离级别针对上述3个问题的解决能力,如下表:

InnoDB 事务加锁分析

二、MVCC

上文提到 InnoDB 默认的隔离级别是可重复读(RR),InnoDB是通过MVCC(多版本并发控制)来实现可重复读的,下面为大家介绍MVCC。

1、概念

在InnoDB中,给每行增加两个隐藏字段来实现MVCC,一个用来记录数据行的创建时间,另一个用来记录行的过期时间(删除时间)。在实际操作中,存储的并不是时间,而是事务的版本号,每开启一个新事务,事务的版本号就会递增。

于是乎,默认的隔离级别(REPEATABLE READ)下,增删查改变成了这样:

(1)SELECT

  • 读取创建版本小于或等于当前事务版本号,并且删除版本为空或大于当前事务版本号的记录。这样可以保证在读取之前记录是存在的。

(2)INSERT

  • 将当前事务的版本号保存至行的创建版本号。

(3)UPDATE

  • 新插入一行,并以当前事务的版本号作为新行的创建版本号,同时将原记录行的删除版本号设置为当前事务版本号。

(4)DELETE

  • 将当前事务的版本号保存至行的删除版本号。

2、快照读和当前读

(1)快照读:读取的是快照版本,也就是历史版本;

(2)当前读:读取的是最新版本。

普通的SELECT就是快照读,而UPDATE、DELETE、INSERT、SELECT ...  LOCK IN SHARE MODE、SELECT ... FOR UPDATE是当前读。

(3)结论:如果隔离级别是REPEATABLE READ,那么在同一个事务中的所有普通select读读到的都是事务第一个读到的快照,如此实现了可重复读;而对于当前读(UPDATE、DELETE、INSERT、SELECT ... LOCK IN SHARE MODE、SELECT ... FOR UPDATE),InnoDB 通过加锁来实现可重复读,且InnoDB 加锁同时解决了幻读问题。

三、锁的类型

InnoDB 引入以下三种锁类型:

  • Record Locks(记录锁):索引记录上加锁,即行锁,锁住当前行。

  • Gap Locks(间隙锁):在索引记录之间加锁,或者在第一个索引记录之前加锁,或者在最后一个索引记录之后加锁。

  • Next-Key Locks:在索引记录上加锁,并且在索引记录之前的间隙加锁。它相当于是Record Locks与Gap Locks的一个结合。

假设一个索引包含以下几个值:10,11,13,20。那么这个索引的next-key锁将会覆盖以下区间:(-oo, 10]、(10, 11]、(11, 13]、(13, 20]、(20, +oo)。

mysql InnoDB 通过间隙锁解决了幻读问题。以下通过实际的案例分析来介绍InnoDB 是如果解决幻读问题的。

四、案例分析

在对sql进行加锁分析前,需要明确表的结构和索引类型。在不知道索引的情况下直接给出一条SQL来分析如果加锁是没有任何意义的。

以下以用户表(t_user)为例(id为主键,name为唯一索引,age为一般索引,address无索引)分析不同索引条件的加锁表现。

InnoDB 事务加锁分析

1、主键索引

例:delete from t_user where id=120;
条件为主键,此时锁住聚簇索引中对应的行记录:即Record Locks锁住id=120的行记录。

InnoDB 事务加锁分析

此种情况下,其他事务除了不能删除、更新此条记录外,其他插入其他行、更新其他行都行。

SQL验证:

InnoDB 事务加锁分析

2、唯一索引

例:delete from t_user where name='n20';
条件为唯一索引,锁住索引记录,同时锁住聚簇索引中的对应行记录:

InnoDB 事务加锁分析

SQL验证:

InnoDB 事务加锁分析

3、一般索引

例:delete from t_user where age=20;
与主键和唯一索引不同的是,一般索引的记录是允许重复的;换句话说,如果我们单纯地给索引加记录锁时,其他事务依然可以插入,也就有可能出现幻读问题了。

所以除了给对应索引记录加上记录锁之外,还要给Gap加上锁。

InnoDB 事务加锁分析

从上面知识点我们可以预估这个操作一共需要的锁:

  • age索引记录锁(Record Lock) :

    20_120, 20_130(以下均用age_id这种形式表示索引值)

  • age索引间隙锁(Gap X-Lock):

    (10, 20)、(20, 20)、(20, 40)

  • 聚簇索引上的记录锁(Record X-Lock):

    id=120/130对应的行记录

SQL验证:

InnoDB 事务加锁分析

根据实际情况,3-6均符合我们预期,然而7和8则超出了我们预期的锁范围。为什么会超出我们预期呢?此次我们进行分析一下:

从7、8插入语句来看,由于id为自增主键,会自动递增,语句7插入值预计为:10_141;

语句8插入值预计为:40_141,为什么只有后者能插入呢?
其实我们可以将B+树中的间隙理解得更加精准一点:

InnoDB 事务加锁分析

age=20的三个间隙应该为:(10_110, 20_120)、(20_120, 20_130)、(20_130, 40_140);

从上图可以看出语句7插入值10_141 无法插入,因为间隙被锁住了;而语句8插入 40_141值因为在间隙之外了,无锁冲突,允许插入。

所以最终的加锁情况应该这样表示:

  • age索引记录锁(Record Lock) :20_120, 20_130

  • age索引间隙锁(Gap X-Lock):(10_110, 20_120)、(20_120, 20_130)、(20_130, 40_140)

  • 聚簇索引上的记录锁(Record X-Lock):id=120/130对应的行记录

4、无索引

delete from t_user where address='a20',因为无法精准定位,InnoDB选择将聚簇索引中的所有行以及间隙都锁起来,功能上已经等于锁表了:

InnoDB 事务加锁分析

SQL验证:

InnoDB 事务加锁分析

5、结论

InnoDB 在RC(READ COMMITTED)隔离级别中,只会在对应的索引/行记录上加Record Lock,而不会加Gap锁,原因也很简单,因为该隔离级别是允许存在幻读问题的。

在RR级别下的加锁方式称之为Next-Key Locks,其实就是上述Record Locks和Gap Locks的结合。比如Gap Lock为(10,20) ,record lock为20,结合的Next-Key lock 为:(10, 20]。

分析Next-Key Locks其实就是要分析Record Locks和Gap Locks。MySQL InnoDB的可重复读并不保证避免幻读,需要应用使用加锁读来保证。而这个加锁读使用到的机制就是next-key locks。

如果使用普通的读,会得到一致性的结果,如果使用了加锁的读,就会读到“最新的”“提交”读的结果。本身,可重复读和提交读是矛盾的。在同一个事务里,如果保证了可重复读,

就会看不到其他事务的提交,违背了提交读;如果保证了提交读,就会导致前后两次读到的结果不一致,违背了可重复读。可以这么讲,InnoDB提供了这样的机制,在默认的可重复读的隔离级别里,可以使用加锁读去查询最新的数据。

您可能感兴趣的文档:

--结束END--

本文标题: InnoDB 事务加锁分析

本文链接: https://www.lsjlt.com/news/44809.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • InnoDB 事务加锁分析
    本文首发于 vivo互联网技术 微信公众号  链接:https://mp.weixin.qq.com/s/S7MhlsZveBHRSQhq5aTIJA 作者:何志创 一般大家对数据库事务的了解可能停...
    99+
    2022-10-18
  • MySQL InnoDB 事务锁源码分析
    目录1. Lock 与 Latch2. Repeatable Read3. Insert加锁流程3.1 lock mode3.2 加锁流程3.3 隐式锁4. Select 加锁流程本...
    99+
    2022-11-12
  • InnoDB事务锁之行锁-insert加锁-隐式锁
    ...
    99+
    2022-10-18
  • InnoDB事务锁之行锁-delete流程update阶段加锁
    1、介绍 delete流程分search和update两个阶段。在search阶段对聚集索引记录加锁,参考上一篇文章。在update阶段会对聚集索引记录打上delete标签,然后search二级索引...
    99+
    2022-10-18
  • MySQL中InnoDB事务锁阅读锁信息状态的示例分析
    这篇文章主要介绍了MySQL中InnoDB事务锁阅读锁信息状态的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。 ...
    99+
    2022-10-18
  • InnoDB事务锁之行锁-insert加锁原理图-聚集索引
    ...
    99+
    2022-10-18
  • InnoDB事务锁之行锁-insert二级索引加锁原理图
    ...
    99+
    2022-10-18
  • InnoDB事务锁之行锁-delete的update阶段加锁流程图
    ...
    99+
    2022-10-18
  • Mysql-InnoDB锁的示例分析
    小编给大家分享一下Mysql-InnoDB锁的示例分析,希望大家阅读完这篇文章后大所收获,下面让我们一起去探讨吧!锁类型行级锁锁模式只有LOCK_S 和LOCK_X,其他的 FLAG 用于锁的描述,如前述 ...
    99+
    2022-10-18
  • MySQL中InnoDB锁机制分析
    本篇内容介绍了“MySQL中InnoDB锁机制分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! ...
    99+
    2022-10-19
  • mysql innodb的行锁举例分析
    这篇文章主要讲解了“mysql innodb的行锁举例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“mysql innodb的行锁举例分析”吧! ...
    99+
    2022-10-19
  • innodb查询锁的示例分析
    这篇文章主要为大家展示了“innodb查询锁的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“innodb查询锁的示例分析”这篇文章吧。 ...
    99+
    2022-10-18
  • InnoDB事务锁之行锁-delete search阶段加锁原理图-聚集索引
    ...
    99+
    2022-10-18
  • MySQL之InnoDB中锁的情况分析
    这篇文章主要讲解了“MySQL之InnoDB中锁的情况分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“MySQL之InnoDB中锁的情况分析”吧!mysq...
    99+
    2022-10-19
  • 分析MySQL数据库Innodb中的事务隔离级别和锁的关系
    本篇内容主要讲解“分析MySQL数据库Innodb中的事务隔离级别和锁的关系”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“分析MySQL数据库Innodb中的事...
    99+
    2022-10-18
  • Mysql-InnoDB事物的示例分析
    这篇文章给大家分享的是有关Mysql-InnoDB事物的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。事物基本概念事物的特性(ACID)原子性 atomicity一致性 ...
    99+
    2022-10-18
  • MySQL事务和InnoDB锁类型介绍
    这篇文章为大家带来有关MySQL事务和InnoDB锁类型的介绍。文章涵盖MySQL事务和InnoDB锁类型的知识点,希望大家通过这篇文章能有所收获。一、事务的隔离级别1、4 种隔离级别(1)未提交读(Rea...
    99+
    2022-10-18
  • MySQL InnoDB锁介绍及不同SQL语句分别加什么样的锁的示例分析
    今天就跟大家聊聊有关MySQL InnoDB锁介绍及不同SQL语句分别加什么样的锁的示例分析,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。文章正文开...
    99+
    2022-10-19
  • MySQL与InnoDB下共享锁与排他锁实例分析
    这篇文章主要介绍“MySQL与InnoDB下共享锁与排他锁实例分析”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“MySQL与InnoDB下共享锁与排他锁实例分析”文...
    99+
    2022-10-19
  • MySQL InnoDB事务与锁的详细讲解
    这篇文章主要介绍“MySQL InnoDB事务与锁的详细讲解”,在日常操作中,相信很多人在MySQL InnoDB事务与锁的详细讲解问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解...
    99+
    2022-10-18
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作