今天我们来学习一下MySQL的事务隔离是如何实现的。如果你对事务以及事务隔离级别还不太了解的话,这里左转

好的,下面正式进入主题。事务隔离级别有4种:读未提交、读提交、可重复读和串行化。首先我们来说一下读未提交和串行化。

  • 读未提交:性能最好,因为不加锁,所以可以理解为没有隔离。
  • 串行化:读加共享锁,其他事务可并发读,但不能写;写加排他锁,其他事务不能并发写也不能并发读。

这两种方式要么啥都不管,并发性能最好,但也最多问题;要么管得很严,无法并发处理,实现简单。

另外两种,读提交和可重复读,的实现方式就有考究了。

可重复读

首先我们来看一下可重复读是如何实现的。

在可重复读隔离级别下,事务在启动的时候就“拍了个快照”,并且这个快照是基于整个库的。而“快照”在计算机里是拷贝了一份当前的副本文件,但在数据库并发访问场景下,不可能真的拷贝一份数据副本。

实际上,这个快照是基于InnoDB在实现MVCC时用到的一致性读视图来实现的。

MVCC的全称是“多版本并发控制”。这项技术使得InnoDB的事务隔离级别下执行一致性读操作有了保证,换言之,就是为了查询一些正在被另一个事务更新的行,并且可以看到它们被更新之前的值。这是一个可以用来增强并发性的强大的技术,因为这样的一来的话查询就不用等待另一个事务释放锁。这项技术在数据库领域并不是普遍使用的。一些其它的数据库产品,以及MySQL其它的存储引擎并不支持它。

如何实现“快照”

InnoDB里面每个事务有一个唯一的事务ID,叫作transaction id。它是在事务开始的时候向InnoDB的事务系统申请的,是按申请顺序严格递增的。

数据表中的一行记录,其实可能有多个版本(row),每个版本都有自己的row trx_id。如图1所示:




图1 行状态变更图

图中虚线框里是同一行数据的4个版本,当前最新版本是V4,k的值是22,它是被transaction id为25的事务更新的,因此它的row trx_id是25。

其实除了最新版本V4外,其他三个版本实际上是不存在的,它们是由undo log和最新版本数据计算得到的。其中undo段就是图中的虚线箭头的U1、U2、U3,例如V1版本就是根据V4依次执行U3、U2、U1计算得到的。

undo log是回滚日志,保存的是逻辑格式的日志,可用于事务回滚,也可以用于MVCC。

按照可重复读的定义,一个事务启动的时候,能够看到所有已经提交的事务结果。但之后在这个事务执行期间,其他事务的更新对它不可见。

InnoDB为每个事务构成一个数组,用来保存这个事务启动瞬间,当前正在“活跃”的所有事务ID。“活跃”指启动了但还没有提交。

数组里事务ID的最小值记为低水位,当前系统里面已经创建过的事务ID的最大值加1记为高水位。这个视图数组加高水位就组成了当前事务的一致性视图(read-view)。

而数据版本的可见性规则,就是基于数据的row trx_id和这个一致性视图的对比结果得到的。




图2 数据可见性规则

对于当前事务的启动瞬间来说,一个数据版本的row trx_id有以下几种可能:

  • 如果落在绿色部分,表示这个版本是已经提交的事务或者是当前事务自己生成的,这个数据是可见的。
  • 如果落在红色部分,表示这个版本是由将来启动的事务生成的,不可见。
  • 如果落在橙色部分,就有两种情况:
    • 若row trx_id在数组中,表示这个版本是由还没提交的事务生成的,不可见。
    • 若row trx_id不在数组中,表示这个版本是已经提交了的事务生成的,可见。

比如图1中的数据来说,如果有一个事务,它的低水位是18,那么当它访问这一行数据时,就会从V4通过U3计算出V3,所以在它看来,这一行的值是11。

在更新时如何使用一致性读




图3 示例1

我们来看示例1,如果事务B在事务C更新之前查询,这个查询返回值是1。但是当它要去更新数据时,就不能在历史版本上更新了,否则事务事务C的更新就会丢失。

这里就用到一条规则:更新数据都是先读后写,而这个读只能是读当前的值,称为“当前读”(current read)。

因此事务B更新时,当前读拿到的数据是(1, 2),更新后是(1, 3),并且row trx_id是101。

事务B后续查询时,看到最新数据的版本号是101,而自己也是101,就直接返回,得到的k值是3。




图4 示例2

我们再来看示例2,示例2与示例1的区别在于,事务C'在事务B的写读操作后提交。

事务C'在提交前对行加写锁。而事务B是当前读,而且必须要加锁,因此被锁住了,必须等到事务C'释放这个锁,才能继续它的当前读。

到这里,把一致性读、当前读和行锁串起来了。

小结

本节问题,事务的可重复读隔离级别是如何实现的?

可重复读的核心就是一致性读;而事务更新数据的时候,只能用当前读。如果当前的记得的行锁被其他事务占用的话,就需要进入锁等待。

读提交

读提交的实现方式跟可重复读类似,它们最主要的区别是:

  • 在可重复读隔离级别下,只需要在事务开始的时候创建一致性视图,之后事务里的其他查询都共用这个一致性视图;
  • 在读提交隔离级别下,每个语句执行前都会重新算出一个新的视图。

参考资料

MySQL事务(二)事务隔离的实现原理:一致性读的更多相关文章

  1. MySQL事务和事务隔离级别

    1.概述 事务就是对数据库数据进行更改(包括insert.update.delete等)操作的一个执行单元,通常有一条或多条更改语句组成.在同一个事务中的更改操作要么同时成功,要么同时失败. 事务具有 ...

  2. MySQL学习(三)MySQL锁与事务

    本章我们着重讨论MySQL锁机制的特点,常见的锁问题,以及解决MySQL锁问题的一些方法或建议. 一.MySQL锁概述 相对其他数据库而言,MySQL的锁机制比较简单,其最显著的特点是不同的存储引擎支 ...

  3. MySQL中的事务和MVCC

    本篇博客参考掘金小册--MySQL 是怎样运行的:从根儿上理解 MySQL 以及极客时间--MySQL实战45讲. 虽然我们不是DBA,可能对数据库没那么了解,但是对于数据库中的索引.事务.锁,我们还 ...

  4. MySQL 一致性读 深入研究

    一致性读,又称为快照读.使用的是MVCC机制读取undo中的已经提交的数据.所以它的读取是非阻塞的. 相关文档:http://dev.mysql.com/doc/refman/5.6/en/innod ...

  5. MySQL 一致性读 深入研究 digdeep博客学习

    http://www.cnblogs.com/digdeep/p/4947694.html 一致性读,又称为快照读.使用的是MVCC机制读取undo中的已经提交的数据.所以它的读取是非阻塞的. 相关文 ...

  6. [MySQL] 一致性读分析

    MySQL MVCC MySQL InnoDB存储引起实现的是基于多版本的并发控制协议---MVCC(Multi-Version Concurrency Control),基于锁的并发控制,Lock- ...

  7. 谈谈MySQL支持的事务隔离级别,以及悲观锁和乐观锁的原理和应用场景?

    在日常开发中,尤其是业务开发,少不了利用 Java 对数据库进行基本的增删改查等数据操作,这也是 Java 工程师的必备技能之一.做好数据操作,不仅仅需要对 Java 语言相关框架的掌握,更需要对各种 ...

  8. 第36讲 谈谈MySQL支持的事务隔离级别,以及悲观锁和乐观锁的原理和应用场景

    在日常开发中,尤其是业务开发,少不了利用 Java 对数据库进行基本的增删改查等数据操作,这也是 Java 工程师的必备技能之一.做好数据操作,不仅仅需要对 Java 语言相关框架的掌握,更需要对各种 ...

  9. MySQL 温故知心(二) 事务的隔离级别

    事务的隔离级别 A事务做了操作 没有提交 对B事务来说 就等于没做 获取的都是之前的数据但是 在A事务中查询的话 查到的都是操作之后的数据没有提交的数据只有自己看得到,并没有update到数据库 查看 ...

随机推荐

  1. linux开机启动及运行级别、root密码丢失、单用户模式只读的处理方法

    linux系统启动大致步骤如下:  加电自检-->根据BIOS中的设置从指定的设备启动-->找到设备MBR中的bootloader引导启动系统-->启动kernel-->启动i ...

  2. Vue 组件化开发

    组件化开发 基本概念 在最开始的时候,已经大概的聊了聊Vue是单页面开发,用户总是在一个页面上进行操作,看到的不同内容也是由不同组件构成的. 通过用户的操作,Vue将会向用户展示某些组件,也会隐藏某些 ...

  3. 画echart图时,安卓手机正常,苹果手机上tooltip 在坐标轴下一层

    问题: 解决: 在tooltip 中添加如下代码: tooltip:{ position:function(point, params , dom, rect, size){ dom.style.tr ...

  4. 玩转百度地图API(地图,坐标,标记,添加控件,2D图,混合图,智能搜索,地址解析器,信息窗口)

    1.注册得到appkey 2.直接上代码 <!DOCTYPE html> <html> <head> <meta http-equiv="Conte ...

  5. 云计算之路-出海记:建一个免费仓库 Amazon RDS for SQL Server

    上周由于园子后院起火,不得不调兵回去救火,出海记暂时停更,这周继续更新,"出海记"记录的是我们在 AWS 上建设博客园海外站的历程. 在这一记中记录的是我们基于 AWS 免费套餐( ...

  6. vue路由参数的获取、添加和替换

    获取路由参数 getUrlKey(name){//获取url 参数 return decodeURIComponent((new RegExp('[?|&]'+name+'='+'([^&am ...

  7. 企业级工作流解决方案(八)--微服务Tcp消息传输模型之服务端处理

    服务端启动 服务端启动主要做几件事情,1. 从配置文件读取服务配置(主要是服务监听端口和编解码配置),2. 注册编解码器工厂,3. 启动dotnetty监听端口,4. 读取配置文件,解析全局消息处理模 ...

  8. FL studio系列教程(一):什么是FL水果音乐制作软件

    如今,越来越多的音乐人选择使用音乐制作软件来进行音乐的创作,一台电脑.一款软件以及一个外接MIDI就是一个小型的音乐工作站.FL Studio成了音乐界萌新的首选,目前最新的版本为FL Studio2 ...

  9. js控制某个div在页面加载完成5秒后隐藏

    <div id="k">测试</div><script>setTimeout("document.getElementById('k' ...

  10. spring框架:(一) 技术说明(技术介绍,技术优势以及发展史等)

    一.技术说明(技术介绍,技术优势以及发展史等) 1.1.什么是spring 1.2.spring由来(发展历程) 1.3.spring核心 1.4.spring优点 1.5.spring体系结构 1. ...