Mysql InnoDB多版本并发控制MVCC详解

目录
  • 一丶为什么需要事务隔离级别
    • 1.实现事务隔离的方式:串行执行
    • 2.实现事务隔离的方式:可串行执行
  • 二丶并发事务执行的问题:脏写,脏读,不可重复读,幻读
    • 1.脏写
    • 2.脏读
    • 3.不可重复读
    • 4.幻读
  • 三丶隔离级别
    • 1.Read UnCommitted 读未提交
    • 2.Read Committed 读已提交
    • 3.Repeatable Read 可重复读
    • 4.Serializable 可串行化
  • 四丶Mysql设置隔离级别
    • 1.设置全局隔离级别
    • 2.设置会话隔离级别
    • 3.设置下一个事务的隔离级别
    • 4.指定服务器的隔离级别
  • 五丶MVCC原理
    • 1.版本链
    • 2.Read View
      • 2.1 read view 的结构
      • 2.2 read view
      • 2.3 Read Committed和 Repeatable Read的不同
      • 2.4 二级索引与MVCC

一丶为什么需要事务隔离级别

mysql是一个客户端/服务端软件,对于同一个服务器来说,可以有多个客户端进行连接,每一个客户端进行连接之后就形成一个会话,每一个客户端都可以在自己的会话中向服务器发出请求语句,一个请求语句可能是某一个事务的一部分,服务器可以同时处理多个事务。

如果事务时一个接着一个进行,那么下一个事务是在上一个事务的一致性前提下进行的,就没用一致性的问题,但是事务是并发进行且可能访问到相同的数据这时候就会出现如下问题

可以看到AB最开始总和13元,最后AB总和18元,银行血亏五元,这显然违背了一致性——钱的总量不变。这就是并发情况下两个事务的影响,所以需要事务隔离让事务隔离的进行,互不干涉。

1.实现事务隔离的方式:串行执行

最简单直接的方式,同一时间只能有一个事务运行,这样必然不会有上述不一致的情况,但是大大降低了吞吐率并增加了事务的等待时间

2.实现事务隔离的方式:可串行执行

并发事务之所以出现不一致的情况,就是由于多个事务访问相同的数据,需要实现多个事务在访问相同数据的时候进行限制,比方说上图中事务2想访问A账户的值需要等待事务提交事务之后,这样可以让并发事务的执行如同串行执行的效果一样。

二丶并发事务执行的问题:脏写,脏读,不可重复读,幻读

1.脏写

一个事务修改了另外一个未提交事务修改过的数据

脏写导致一致性无法保证

上图事务A和事务B都更新紫色数据,其中事务A首先更新为A,然后事务B过来更新为B,这时候事务A回滚后更新为Null,事务 B 明明正常写了一行数据,但是写完之后发现值变了,有点丢失更新的意思。(比如A表示余额,这时候在将余额A判断是否足以支付,判断得到可以,事务B执行扣费写入A-5,商家收到5元,结果这时候回滚了,A变成Null,事务A中转钱的一方钱变为A,钱的总额变为A+5了)

脏写导致原子性受到破坏

假如上述的事务B还操作了另外的数据,比如插入一条数据C,并且更改为B写入C是在一个事务下面的,需要具备原子性,但是脏写让B的更改需要部分回滚为Null,这样插入C和更改B就不具备原子性(比如A表示余额,这时候在将余额A判断是否足以支付,判断得到可以,事务B执行扣费写入A-5,商家收到5元,结果这时候回滚了,A变成Null,这时候部分回滚,商家的5元没用回滚,商家的库存也没用回滚,原子性被破坏)

2.脏读

如果一个事务读取到另外一个事务未提交的数据,意味着发生了脏读

比如事务A先写数据A,然后事务B督导数据A后在内存中使用A进行一系列操作(比如A表示余额,这时候在将余额A判断是否足以支付,判断得到可以)但是事务A这时候回滚了,事务B再次读取数据发现为null,这就是脏读。

脏读可能引发一致性的问题:比如事务操作时修改x和y的值,并且二者总是相等的,A修改x为1,还没来得及修改y也没用提交事务,这时候事务B读取x=1,y=0,二者不等,事务B读取到了数据库不一致的状态,读取到未提交事务的值

3.不可重复读

假如一个事务修改了另外一个事务未提交的数据,意味发生了不可重复读

比如事务A第一次读取到值为A,接着事务B修改为B,并且提交了事务B,然后事务A再次读取得到的数据是B,同一行数据多次读取值并不相同,这称作不可重复读。它是指在同一个事务里面查询同一行数据,每次查到的数据都不一样。和脏读区别在于脏读是由于别的事务回滚导致,而不可重复读读到的其实是已经提交的数据。

事务A读到事务B提交后的数据似乎很合理,但是我们想象这样一种场景:你有一个流水表和用户余额,其中记录用户每天的流水,你在月初0点的时候核对流水和库存,但是流水很多,你的程序选择一个一个用户的进行核对,核对用户甲,甲没做任何消费,但是当你核对B的时候,你将B的流水load到内存中,但是B这时候(0点30分,这一笔数据新的一个余额)进行了扣除余额的操作,导致B余额和流水对不上了。

4.幻读

如果一个事务A先根据没用搜索条件查询到一些记录,在该事务未提交前,另外一个事务写入(delete,update,insert)了符合搜索条件的记录,这时候事务A再次读取,发现数据条数和第一次读取的不同,如同出现了幻觉,称之为幻读

事务A读到事务B提交后的数据似乎很合理,但是我们想象这样一种场景:你有一个需求将会公司的男性员工了女性员工查询进行展示,你先查询了总数为100人,然后查询男性的总数50人,后查询女性人数准备在页面展示共100人,其中男50人,女50人,结果这是管理信息的人发现有一位员工性别错误录入了,将其从男修改为女,这时候你读取事务就是女51人了,你在主页显示了共100人,其中男50人,女51人

三丶隔离级别

1.Read UnCommitted 读未提交

在此隔离级别下,会发生脏读,不可重复读,和幻读

2.Read Committed 读已提交

在此隔离级别下,会发生不可重复读,和幻读

3.Repeatable Read 可重复读

在此隔离级别下,可能发生幻读

4.Serializable 可串行化

在此隔离级别下,不会发生脏读,不可重复读,和幻读

其中脏写是对一致性影响最严重的,无论是何种隔离级别,都不允许脏写发生,innodb使用锁保证不会出现脏写现象,第一个事务更新某条记录的时候,会给这条记录加锁,另外一个事务在此更新的时候,需要等待第一个事务提交释放锁后更新。隔离级别越高,其并发能力越低。

四丶Mysql设置隔离级别

默认隔离级别可重复读

1.设置全局隔离级别

SET GLOBAL TRANSACTION ISOLATION LEVEL 期望的隔离级别(可选READ UNCOMMITED,READ COMMITED,REPEATABLE READ,SERIALIZABLE),此命令只对执行语句后新产生的会话有效,对当前已经存在的会话无效

2.设置会话隔离级别

SET SESSION TRANSACTION ISOLATION LEVEL 期望的隔离级别(可选READ UNCOMMITED,READ COMMITED,REPEATABLE READ,SERIALIZABLE),对当前会话后续事务有效,该语句可以在已开启的事务中执行,但是不会影响当前正在执行的事务,如果在事务之间执行,只会对后续的事务有效

3.设置下一个事务的隔离级别

SET TRANSACTION ISOLATION LEVEL 期望的隔离级别(可选READ UNCOMMITED,READ COMMITED,REPEATABLE READ,SERIALIZABLE) 只对当前会话的下一个即将开启的事务有效,下一个事务执行完后,后续事务将恢复到之前的隔离级别,该语句不能再已经开启的事务中执行,否则会报错。

4.指定服务器的隔离级别

在启动的时候使用--transaction-isolation=xxx即可执行默认隔离级别

五丶MVCC原理

下面讨论记录对当前事务是否可见都是基于当前事务中执行的查询是快照读(普通查询),对于当前读(select xxx for update,select xxx lock in share mode)是不通用的

1.版本链

对于InnoDB存储引擎来说,其聚簇索引记录中包含两个隐藏列:

trx_id:一个事务每次对聚簇索引记录做出改动的时候,都会把该事务的事务id复制给此列 roll_point:每次对某条聚簇索引记录进行改动的时,都会把旧的版本写入到undo 日志中,此列相当于一个指针,指向修改前的信息

每次修改都会形成Undo 日志,所有版本的数据会通过roll_point串联成一个链表,称之为版本链,头节点是当前记录的最新值。利用版本链控制多个并发事务访问相同记录时的行为称为MVCC多版本并发控制。

其实在undo日志中,只记录被更新列的信息,而不是记录全部的信息,对于没有记录的列,会通过版本链找少一个版本中的对应列的信息,直到找到聚簇索引叶子节点中的内容

2.Read View

对于使用Read Uncommitted隔离级别的事务,可以读取到没提交的数据,那么直接读取最新的版本即可。对于Serializable隔离级别,innodb直接通过加锁来访问记录。对于read committed 和 repeatable read隔离级别的事务,都必须保证督导的数据是已经提交事务修改过的记录,那么如何判断版本链中的哪个版本的数据是当前事务可见的昵?

innodb 使用的Read View

2.1 read view 的结构

  • m_ids:在生成read view时,当前系统中活跃的读写事务id列表
  • min_trx_id:生成read view时,当前系统中活跃的读写事务中最小事务id,也就是m_ids中的最小值
  • max_trx_id:生成read view时,系统应该分配给下一个事务的事务id值
  • creator_trx_id:生成该read view的事务的事务id

2.2 read view

  • 如果被访问版本的trx_idcreator_trx_id相同,意味着当前事务在访问自己修改的记录,自然可见
  • 如果访问版本的trx_id属性值小于read view中的min_trx_id 表明此版本是生成read view之前已经提交的事务,那么自然可见
  • 如果访问版本的trx_id,大于等于read view中的max_trx_id说明,当前版本数据是生成read view后开启事务产生的,那么自然不可见
  • 如果访问版本的trx_id 介于min_trx_idmax_trx_id之间,需要判断trx_id是否位于m_ids列表中,如果在说明创建read view时生成该版本的事务还是活跃的,那么该版本,不可被访问,如果不在说明创建read view 时生成该版本的事务已经提交,可以被访问到

如果某个版本数据对当前事务不可见那么需要一直顺着版本链找上一个版本的数据,并通过上述步骤判断是否可见,直到找到可见的版本,如果一直找不到说明该条记录对当前事务不可见,查询结果将不包含该记录。

2.3 Read Committed和 Repeatable Read的不同

Read Committed——每次读取数据前都生成一个Read View

这样可以保证生成Read view 中的m_ids是实时活跃事务id集合,也许第一次读取的时候事务A没提交,其id位于m_ids中,但是第二次读取的时候事务A提交了,事务A将不位于m_ids中,这样在第二次读取的时候,通过m_ids判断事务A是否提交的时候,可以得到事务A已经提交了,然后让事务A版本产生的数据可见(见2.2.4中的内容)。

Repeatable Read——如果使用begin开启事务那么在第一次查询的时候生成Read view,如果使用start transaction with consistent snapshot 那么执行的时候就会生成read view

这样可以保证当前事务从头到尾都是read view中记录的内容是一致的,第一次读取的时候事务A没有提交,那么不可见,但是第二次读取的时候事务A提交了,但是read view的m_idsmax_trx_id可以判断事务A不可见,比如事务A事务id小于max_trx_id意味着生成read view是事务A启动但是没提交,即使第二次读事务A提交了,但是m_ids中还是包含事务A,那么不可见。如果事务A事务id大于max_trx_id,那么自然第二次还是大于max_trx_id,也是不可见的,从而实现了可重复读。

2.4 二级索引与MVCC

上面我们提到,innodb聚簇索引组织的记录才具备trx_idroll_point,那么我们使用二级索引进行查询的时候,如何判断数据是否可见昵?

  • 二级索引页面的page header中存在page_max_trx_id属性,每当有事务对其中的记录进行增删改查操作的时候,如果事务的事务id,大于page_max_trx_id,那么会更新page_max_trx_id属性值为其事务id,这意味着page_max_trx_id记录了修改该二级索引页面最大的事务id是多少。当select通过二级索引首先看下对于read view的min_trx_id是否大于该页面的page_max_trx_id,如果大于那么页面中所有记录都对该read view可见,否则就进行下面的第二步
  • 利用二级索引中的主键值,进行回标,得到对应的聚簇索引记录然后进行回表,然后通过2.2中步骤拿到第一个可见版本的数据,然后比对此纪录和通过二级索引查询得到记录的值是否相同,如果相同那么发送给客户端,否则跳过该记录。

到此这篇关于Mysql InnoDB多版本并发控制MVCC详解的文章就介绍到这了,更多相关Mysql InnoDB多版本并发控制MVCC内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • MySQL多版本并发控制MVCC底层原理解析

    目录 1 事务并发中遇到的问题 1.1 脏读 1.2 不可重复读 1.3 幻读 2 隔离级别 3 版本链 4 ReadView 4.1 ReadView 定义 4.2 访问控制 4.3 再谈隔离 4.3.1 READ COMMITTED(读已提交) 4.3.2 REPEATABLE READ(可重读) 5 幻读 6 总结 1 事务并发中遇到的问题 1.1 脏读 当一个事务读取到了另外一个事务修改但未提交的数据,被称为脏读. 1.2 不可重复读 当事务内相同的记录被检索两次,且两次得到的结果不同时

  • MySQL系列之十 MySQL事务隔离实现并发控制

    目录 一.并发访问控制 二.事务Transactions 1.事务遵循ACID原则: 2.事务的生命周期 3.事务的隔离级别 4.死锁 一.并发访问控制 实现的并发访问的控制技术是基于锁: 锁分为表级锁和行级锁,MyISAM存储引擎不支持行级锁:InnoDB支持表级锁和行级锁: 锁的分类有读锁和写锁,读锁也被称为共享锁,加读锁的时候其他的人可以读:写锁也称为独占锁或排它锁,一个写锁会阻塞其他读操作和写操作: 锁还分为隐式锁和显式锁,隐式锁由存储引擎自行管理,显式锁是用户手动添加锁: 锁策略:在锁

  • 详解MySQL多版本并发控制机制(MVCC)源码

    目录 一.前言 二.MVCC(多版本并发控制机制) 2.1.Repeatable Read 2.2.Read Commit 2.3.MVCC的优势 三.MVCC(实现机制) 3.1.select运行栈 3.2.read_view的创建过程 3.3.行版本可见性 3.4.undolog搜索可见版本的过程 3.5.read_view创建时机再讨论 四.MVCC和锁的同时作用导致的一些现象 五.总结 一.前言 作为一个数据库爱好者,自己动手写过简单的SQL解析器以及存储引擎,但感觉还是不够过瘾.<<

  • mysql的MVCC多版本并发控制的实现

    1 什么是MVCC MVCC全称是: Multiversion concurrency control,多版本并发控制,提供并发访问数据库时,对事务内读取的到的内存做处理,用来避免写操作堵塞读操作的并发问题. 举个例子,程序员A正在读数据库中某些内容,而程序员B正在给这些内容做修改(假设是在一个事务内修改,大概持续10s左右),A在这10s内 则可能看到一个不一致的数据,在B没有提交前,如何让A能够一直读到的数据都是一致的呢? 有几种处理方法,第一种: 基于锁的并发控制,程序员B开始修改数据时,

  • MySQL的多版本并发控制MVCC的实现

    目录 什么是MVCC MVCC的实现 MVCC 有没有解决幻读? 什么是MVCC MVCC就是多版本并发控制. MySQL的事务型存储引擎通过多版本并发控制(MVCC)来提升并发性能. 可以认为MVCC是行级锁的一个变种,但是它在大多数情况下避免了加锁操作,同时实现非阻塞的读操作,因此开销更低. MVCC是通过保存数据在某个时间点的快照来实现的,核心思想就是保存数据的历史版本,通过对数据行的多个版本管理来实现数据库的并发控制. 这样我们就可以通过比较版本号决定数据是否显示出来,读取数据的时候不需

  • MySQL中大对象的多版本并发控制详解

    MySQL 8.0:InnoDB中大对象的MVCC 在本文中,我将解释MySQL InnoDB存储引擎中大对象(LOB)设计的多版本并发控制(MVCC) . MySQL 8.0有一个新功能,允许用户部分更新大型对象,包括JSON文档 . 使用此部分更新功能,当LOB部分更新时,MVCC对LOB的工作方式已发生变化. 对于正常更新(完整更新),MVCC将像以前的版本一样工作. 让我们看一下MVCC在不涉及部分更新时的工作原理,然后考虑对LOB进行部分更新的用例. MVCC 常规更新 我使用术语常规

  • mysql并发控制原理知识点

    Mysql是主流的开源关系型数据库,提供高性能的数据存储服务.在做后端开发时,有时会遇到性能瓶颈,这些瓶颈有时并不是来自应用本身,而是来自数据库层面. 所以所以掌握Mysql的一些底层原理有助于我们更好地理解Mysql,对Mysql进行性能调优, 从而开发高性能的后端服务. 1.mysql的逻辑框架 mysql逻辑框架图如下: 最上层是处理客户端过来的连接的. 主要做连接处理.授权认证.安全等.Mysql在这一层维护了一个线程池,用于处理来自客户端的连接.Mysql可以使用用户名密码认证, 也可

  • mysql多版本并发控制MVCC的实现

    事务隔离级别设置 set global transaction isolation level read committed; //全局的 set session transaction isolation level read committed; //当前会话 修改事务提交方式(是否自动提交,mysql默认自动提交) SET AUTOCOMMIT = 1; //自动提交,为0手动提交 不同数据库引擎MVCC模式各不相同,典型有乐观和悲观并发控制. innodb 说明: InnoDB的MVCC

  • MySQL多版本并发控制MVCC深入学习

    MVCC MVCC(Multi-Version Concurrency Control),即多版本并发控制.是 innodb 实现事务并发与回滚的重要功能.锁机制可以控制并发操作,但是其系统开销较大,而MVCC可以在大多数情况下代替行级锁,使用MVCC,能降低其系统开销. 具体实现是在数据库的每一行中,额外添加三个字段: DB_TRX_ID : 记录插入或更新该行的最后一个事务的事务ID DB_ROLL_PTR : 指向改行对应undolog 的指针 DB_ROW_ID : 单调递增的ID,他就

  • Mysql InnoDB多版本并发控制MVCC详解

    目录 一丶为什么需要事务隔离级别 1.实现事务隔离的方式:串行执行 2.实现事务隔离的方式:可串行执行 二丶并发事务执行的问题:脏写,脏读,不可重复读,幻读 1.脏写 2.脏读 3.不可重复读 4.幻读 三丶隔离级别 1.Read UnCommitted 读未提交 2.Read Committed 读已提交 3.Repeatable Read 可重复读 4.Serializable 可串行化 四丶Mysql设置隔离级别 1.设置全局隔离级别 2.设置会话隔离级别 3.设置下一个事务的隔离级别 4

  • MySQL多版本并发控制MVCC详解

    目录 1.什么是MVCC 2快照读与当前读 2.1 快照读 2.2当前读 3.复习 3.1 再谈隔离级别 3.2 隐藏字段.Undo Log版本链 4.MVCC实现原理之ReadView 4.1什么是ReadView 4.2 设计思路 4.3 ReadView的规则 5.举例说明 5.1 READ COMMITTED 5.2 REPEATABLE READ 5.3 如何解决幻读 6.总结 1.什么是MVCC MVCC (Multiversion Concurrency Control),多版本并

  • MySQL InnoDB引擎的缓存特性详解

    目录 1. 背景 2. 存储器性能差异 3. Buffer Pool 4. Free链表 5. Flush链表 6. LRU链表 7. 其它 1. 背景 对于各种用户数据.索引数据等各种数据都是需要持久化存储到磁盘,然后以“页”为单位进行读写. 相对于直接读写缓存,磁盘IO的成本相当高昂. 对于读取的页面数据,并不是使用完就释放掉,而是放到缓冲区,因为下一次操作有可能还需要读区该页面. 对于修改过的页面数据,也不是马上同步到磁盘,也是放到缓冲区,因为下一次有可能还会修改该页面的数据. 但是缓存的

  • Mysql InnoDB的锁定机制实例详解

    1.InnoDB的锁定机制 InnoDB存储引擎支持行级锁,支持事务处理,事务是有一组SQL语句组成的逻辑处理单元,他的ACID特性如下: 原子性(Atomicity): 事务具有原子不可分割的特性,要么一起执行,要么都不执行. 一致性(Consistency): 在事务开始和事务结束时,数据都保持一致状态. 隔离性(Isolation): 在事务开始和结束过程中,事务保持着一定的隔离特性,保证事务不受外部并发数据操作的影响. 持久性(Durability): 在事务完成后,数据将会被持久化到数

  • MySQL InnoDB表空间加密示例详解

    前言 从 MySQL5.7.11开始,MySQL对InnoDB支持存储在单独表空间中的表的数据加密 .此功能为物理表空间数据文件提供静态加密.该加密是在引擎内部数据页级别的加密手段,在数据页写入文件系统时加密,加密用的是AES算法,而其解密是在从文件读到内存中时进行. 1 配置加密插件 1.1 修改配置文件 在mysql配置文件[mysqld]x项中添加如下内容 plugin_dir=/usr/local/mysql5.7/lib/mysql/plugin # 插件路径,根据实际情况修改 ear

  • MySQL InnoDB之事务与锁详解

    引题:为何引入事务? 1>.数据完整性 2>.数据安全性 3>.充分利用系统资源,提高系统并发处理的能力 1. 事务的特征 事务具有四个特性:原子性(Atomiocity).一致性(Consistency).隔离性(Isolation)和持久性(Durability),这四个特性简称ACID特性. 1.1原子性 事务是数据库的逻辑工作单位,事务中包括的所有操作要么都做,要么都不做. 1.2 一致性 事务执行的结果必须是使数据库从一个一致性的状态变到另外一个一致性状态. 1.3 隔离性 一

  • MySQL MVVC多版本并发控制的实现详解

    目录 一.概述 二.快照读与当前读 1.当前读 2.快照读 三.隔离级别与版本链复习 四.Read View 1.实现原理 2.Read View规则 3.整体流程 五.举例 1.READ 2.REPEATABLE READ隔离级别下 3.如何解决幻读 一.概述 MVCC(Multiversion Concurrency Control),多版本并发控制.它和undo log中的版本链息息相关,MVVC通过数据行的多个版本来实现数据库的并发控制. 简单的说就是当前事务查询另一个事务正在更改的行(

  • MySql事务及ACID实现原理详解

    目录 逻辑架构和存储引擎 自动提交 特殊操作 ACID 特性 原子性 持久性 隔离性 脏读.不可重复读和幻读 事务隔离级别 MVCC 一致性 逻辑架构和存储引擎 自动提交 MySQL 中默认采用的是自动提交(autocommit)模式,如下所示: 在自动提交模式下,如果没有 start transaction 显式地开始一个事务,那么每个 sql 语句都会被当做一个事务执行提交操作. 通过如下方式,可以关闭 autocommit;需要注意的是,autocommit 参数是针对连接的,在一个连接中

随机推荐