MySQL事务(二)事务隔离的实现原理:一致性读
今天我们来学习一下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事务(二)事务隔离的实现原理:一致性读的更多相关文章
- MySQL事务和事务隔离级别
1.概述 事务就是对数据库数据进行更改(包括insert.update.delete等)操作的一个执行单元,通常有一条或多条更改语句组成.在同一个事务中的更改操作要么同时成功,要么同时失败. 事务具有 ...
- MySQL学习(三)MySQL锁与事务
本章我们着重讨论MySQL锁机制的特点,常见的锁问题,以及解决MySQL锁问题的一些方法或建议. 一.MySQL锁概述 相对其他数据库而言,MySQL的锁机制比较简单,其最显著的特点是不同的存储引擎支 ...
- MySQL中的事务和MVCC
本篇博客参考掘金小册--MySQL 是怎样运行的:从根儿上理解 MySQL 以及极客时间--MySQL实战45讲. 虽然我们不是DBA,可能对数据库没那么了解,但是对于数据库中的索引.事务.锁,我们还 ...
- MySQL 一致性读 深入研究
一致性读,又称为快照读.使用的是MVCC机制读取undo中的已经提交的数据.所以它的读取是非阻塞的. 相关文档:http://dev.mysql.com/doc/refman/5.6/en/innod ...
- MySQL 一致性读 深入研究 digdeep博客学习
http://www.cnblogs.com/digdeep/p/4947694.html 一致性读,又称为快照读.使用的是MVCC机制读取undo中的已经提交的数据.所以它的读取是非阻塞的. 相关文 ...
- [MySQL] 一致性读分析
MySQL MVCC MySQL InnoDB存储引起实现的是基于多版本的并发控制协议---MVCC(Multi-Version Concurrency Control),基于锁的并发控制,Lock- ...
- 谈谈MySQL支持的事务隔离级别,以及悲观锁和乐观锁的原理和应用场景?
在日常开发中,尤其是业务开发,少不了利用 Java 对数据库进行基本的增删改查等数据操作,这也是 Java 工程师的必备技能之一.做好数据操作,不仅仅需要对 Java 语言相关框架的掌握,更需要对各种 ...
- 第36讲 谈谈MySQL支持的事务隔离级别,以及悲观锁和乐观锁的原理和应用场景
在日常开发中,尤其是业务开发,少不了利用 Java 对数据库进行基本的增删改查等数据操作,这也是 Java 工程师的必备技能之一.做好数据操作,不仅仅需要对 Java 语言相关框架的掌握,更需要对各种 ...
- MySQL 温故知心(二) 事务的隔离级别
事务的隔离级别 A事务做了操作 没有提交 对B事务来说 就等于没做 获取的都是之前的数据但是 在A事务中查询的话 查到的都是操作之后的数据没有提交的数据只有自己看得到,并没有update到数据库 查看 ...
随机推荐
- 《JavaScript高级程序设计》读书笔记 ---继承
继承是OO 语言中的一个最为人津津乐道的概念.许多OO 语言都支持两种继承方式:接口继承和实现继承.接口继承只继承方法签名,而实现继承则继承实际的方法.如前所述,由于函数没有签名,在ECMAScrip ...
- Jmeter 添加 计数器
第一步: 添加 > 配置元件 > 计数器 如下图所示: 第二步: 设置递增值与引用名称 第三步:使用引用名称 第四步:执行脚本,查看结果
- apiAutoTest-更新2020/11/23
原始版本 简书:https://www.jianshu.com/p/6bfaca87a93b 博客园:https://www.cnblogs.com/zy7y/p/13426816.html test ...
- 图创图书管理SQL注入漏洞
payload root@kali:~# sqlmap -u http://2*0.*6.***.3:8080/opac/recommend/recommendBookList/list --data ...
- [web安全原理分析]-SSRF漏洞入门
SSRF漏洞 SSRF漏洞 SSRF意为服务端请求伪造(Server-Side Request Forge).攻击者利用SSRF漏洞通过服务器发起伪造请求,就这样可以访问内网的数据,进行内网信息探测或 ...
- 面试官:小伙子,你给我说一下Java Exception 和 Error 的区别吧?
前言 昨天在整理粉丝给我私信的时候,发现了一个挺有意思的事情.是这样的,有一个粉丝朋友私信问我Java 的 Exception 和 Error 有什么区别呢?说他在面试的时候被问到这个问题卡壳了,最后 ...
- FL Studio进行侧链的三种方式(上)
在本系列教程中,我们将学习如何在FL Studio中进行侧链.侧链是一种信号处理技术,通过它我们可以使用一个信号波形的振幅(音量)来控制另一个信号的某些参数.在电子音乐中,例如trance,house ...
- Java基础教程——方法引用
方法引用 Lambda表达式的代码,是否可以再简洁?--方法引用 对象/类名::方法名 参数都不用写明. import java.util.function.Consumer; public clas ...
- SQL注入步骤
1.判断是否存在注入,注入是字符型还是数字型2.猜解SQL查询语句中的字段数3.确定回显的字段数4.获取当前数据库5.获取表中字段名6.下载数据
- java中的强引用(Strong reference),软引用(SoftReference),弱引用(WeakReference),虚引用(PhantomReference)
之前在看深入理解Java虚拟机一书中第一次接触相关名词,但是并不理解,只知道Object obj = new Object()类似这种操作的时候,obj就是强引用.强引用不会被gc回收直到gc roo ...