MySQL 基础(三)事务与 MVCC
事务
事务是一组原子性的 SQL 操作,或者被称为一个独立的工作单元,如果数据库引擎能够成功地对数据库应用该组的全部 SQL 语句,那么就会全部执行,否则全部不执行。
事务的特性
在关系数据库管理系统中,事务需要满足 ACID 四个基本特征,具体解释如下[1]:
A(Atomicity)原子性
一个事务(transaction)中的所有操作,或者全部完成,或者全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。即,事务不可分割、不可约简
C(Consistency)一致性
在事务开始之前和事务提交之后,数据库的完整性没有被破坏,即在事务发生前后数据依旧满足原有的约束条件、级联回滚等
I(Isolation)隔离性
数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致的数据不一致。事务的隔离级别从低到高分为四个等级:读未提交(read uncommitted)、提交读(read committed)、可重复读(repeatable read)和可串行化(serializable)
D(Duration)持久性
事务处理结束之后,对于数据的修改是永久的,即便系统发生故障也不会丢失
事务的状态
事务的可能状态如下图所示:

- active:表示事务已经开始了,可以通过显式地执行
BEGIN或START TRANSACTION语句来开启一个事务 - partially committed:部分提交状态,此时事务已经执行结束了,但是不会直接将最终结果直接写入到磁盘中,在这一步是将结果写入到内存中
- committed:将数据刷新磁盘上,此步骤完成则表示确实是成功提交了事务
- failed:事务执行过程中失败或者从内存写入到磁盘中的过程失败,此时需要执行回滚操作
- aborted:回滚执行完成之后的状态
事务的隔离级别
事务并发执行时可能会存在的一些一致性问题:
脏读
一个事务读取了另一个事务还 没有提交 的数据,此时读取到的数据是脏数据,因此被称为 “脏读”
不可重复读
一个事务开始时,只能看见已经提交了的事务对数据所做的修改,未提交的事务对数据的修改不可见,当同一个事务两次读取同一个数据时,两次读取到的数据不一致。这是因为在这两次读取的时间间隔中,有其它的事务提交对该数据造成了修改,使得两次读取的数据不一致,这就被称为 ”不可重复读“
幻读
当某个事务在读取某个范围内的记录时,另外一个事务又在该范围内插入了新的记录,此时当前的事务再次读取该范围内的数据时,将会产生 “幻行” 问题,即两次读取出现了数据量不一致的情况,这就被称之为 ”幻读“
SQL 标准定义了以下四种隔离级别:
read uncommitted(读未提交)
最低级别的隔离级别,在这种隔离级别中,即使事务还未提交,对于数据的修改对于其它事务来讲也是可见的,这种情况特别危险,一般情况下不要使用
read committed(提交读)
所有的事务只能看到已经提交的事务对数据的修改,即一个事务从开始直到提交之前,所做的任何修改对于其它事物都是不可见的。在这种隔离级别下,避免了 ”脏读“ 问题的出现, 但是不能解决 ”不可重复读“ 问题
repeatable read(可重复读)
在这种隔离级别下,避免了 ”脏读“ 和 ”不可重复读“ 问题的出现,这也是 MySQL 默认的事务隔离级别。SQL 标准并不要求在这种隔离级别下解决 ”幻读“ 的问题,但是 MySQL 通过 MVCC 的方式在这种隔离级别下解决了 ”幻读“ 的问题[2]
serializable(串行化)
在串行化的隔离级别下,事务与事务之间通过串行的方式执行,从根源上避免了并发执行时出现的一系列问题,缺点在于由于串行化,使得事务的执行效率没有那么高,因此一般情况下也不会采用这种隔离级别
四种隔离级别的比较如下表所示:[4]
| 隔离级别 | 脏读 | 不可重复读 | 幻影读 |
|---|---|---|---|
| 未提交读 | 可能发生 | 可能发生 | 可能发生 |
| 提交读 | - | 可能发生 | 可能发生 |
| 可重复读 | - | - | 可能发生 |
| 可序列化 | - | - | - |
MVCC
MVCC(Multi-Version Concurrency Control):多版本并发控制,通过记录的版本链和 ReadView (一致性视图)来控制并发事务访问相同的记录时的行为。MVCC 没有固定的标准,具体取决于各个数据库管理系统的具体实现
版本链
每次对数据执行操作之后,都会将旧值放入到放入到一条 undo 日志中,随着修改的次数增多,所有的版本都通过 record 的 roll_pointer 属性连接成为一条链表,这个链表就称为 ”版本链“
具体的示意图如下图所示:[3]

假设现在两个事务 T1 和 T2,两者的事务 id 分别为 trx=85 和 trx=90,现在 T1 开启了事务,准备将 tb_student 中 id = 5 的记录的 name 列的值首先更改为 "a",再更改为 "b",T2 也开启了事务,准备将 tb_student 中 id = 5 的记录的 name 的列的值首先修改为 ”c“,再修改为 ”d“。
假设在执行事务之前,id = 5 的记录中 name 属性的值为 "muse",现在按照 执行时刻 的顺序,首先 T1 的两次更新操作将会被执行,同时将记录写入到 undo log 中,形成对应的版本链(trx_id=85 的部分);然后,T2 在按照时间顺序继续执行更新操作,将记录写入到 undo log 中,与之前的 undo log 链形成最终的 undo log 链。注意将当前记录与 undo log 链的整体看做同一个链
ReadView
ReadView 中关键的四个属性:
m_ids:在生成 ReadView 时,当前系统中活跃的读写事务的事务 id 列表min_trx_id:在生成 ReadView 时,当前系统中活跃的读写事务中 最小的事务 id,也就是m_ids中的最小值max_trx_id:在生成 ReadView 时,系统应该分配给下一个事务的事务 id 的值creator_trx_id:生成该 ReadView 的事务的事务 id(当前记录中的trx_id)
版本的可见性的规则:
- 如果
trx_id == creator_trx_id,则表示当前事务正在访问它自己修改过的记录,所以该版本可以被当前的事务所访问 - 如果
trx_id < min_trx_id,则表明生成该版本的事务在当前事务生成 ReadView 之前已经提交,所以该版本可以被当前的事务访问 - 如果
trx_id >= max_trx_id,则表明生成该版本的事务在当前事务生成 ReadView 之后才开始,所以该版本不可以被当前事务访问 - 如果
trx_id在m_ids中,说明创建 ReadView 的时候生成该版本的事务还是活跃的,该版本不可以被访问 - 如果
trx_id不在m_ids中,说明创建 ReadView 时生成该版本的事务已经被提交了,该版本可以被访问
如果某个版本的数据对于当前事务不可见,那么就顺着版本链找到下一个版本的数据,并继续通过以上的规则来判断记录的可见性,直到找到版本链中的最后一个版本
ReadView 的生成时机
Read Committed 和 Repeatable Read 隔离级别在 MVCC 上的最大区别在于 ReadView 的生成时机的不同,这种不同直接导致了这两种隔离级别对于 ”不可重复读“ 问题的处理。
对于 Read Committed,在一个事务中,每次读取数据之前都会生成一个 ReadView,这样的话就会使得其它事务对于数据的修改对于当前事务来讲也是可见的,因此存在 “不可重复读“ 的问题,而对于 Repeatable Read,在一个事务中,只有在第一次读取数据时生成一个 ReadView,这样就保证了在当前事务的执行过程中是无法看到别的事务对于数据的修改,这就避免了 “不可重复读” 问题的出现
参考:
[1] https://zh.wikipedia.org/wiki/ACID
[2] 《高性能 MySQL》(第三版)
[3] https://mp.weixin.qq.com/s/sxlq4kdOaCi5jdsWAnpiBw
[4] https://zh.wikipedia.org/wiki/事務隔離
MySQL 基础(三)事务与 MVCC的更多相关文章
- 04 mysql 基础三 (进阶)
mysql 基础三 阶段一 mysql 单表查询 1.查询所有记录 select * from department; select * from student; select * from ...
- MySQL基础之事务编程学习笔记
MySQL基础之事务编程学习笔记 在学习<MySQL技术内幕:SQL编程>一书,并做了笔记.本博客内容是自己学了<MySQL技术内幕:SQL编程>事务编程一章之后,根据自己的理 ...
- Mysql基础之 事务
MySql事务 Mysql事务主要处理操作量大,复杂度高的数据. Mysql事务需要注意的三点: 1.在mysql中只有使用innodb数据库引擎的数据库或表才支持事务 2.事务处理可以用来维护数据库 ...
- mysql基础三(视图、触发器、函数、存储过程、事务、防注入)
一.视图 视图是一个虚拟表(非真实存在),其本质是[根据SQL语句获取动态的数据集,并为其命名],用户使用时只需使用[名称]即可获取结果集,并可以将其当作表来使用. 1.创建视图 -格式:CREATE ...
- MySQL中的事务和MVCC
本篇博客参考掘金小册--MySQL 是怎样运行的:从根儿上理解 MySQL 以及极客时间--MySQL实战45讲. 虽然我们不是DBA,可能对数据库没那么了解,但是对于数据库中的索引.事务.锁,我们还 ...
- mysql基础(三)——中级查询
创建表 CREATE TABLE DEPT( DEPTNO ) PRIMARY KEY, DNAME ) , LOC ) ) ; ,'ACCOUNTING','NEW YORK'); ,'RESEAR ...
- mysql基础_事务
定义 一个事务其实就是一个完整的业务逻辑,是一个最小的工作单元,不可再分,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败. 例如:王五向赵六的账户上转 ...
- 重新整理 mysql 基础篇————— 事务隔离级别[四]
前言 简单介绍一下事务隔离的基本 正文 Read Uncommitted(未提交读) 这个就是读未提交.就是说在事务未提交的时候,其他事务也可以读取到未提交的数据. 这里举一个例子,还是前一篇的例子. ...
- MySQL 基础三 函数(聚合、字符串、时间、条件判断)
1.聚合 其它:GROUP_CONCAT.avg.sum.count.max.min SELECT typeid,GROUP_CONCAT(goodsname) FROM `goods` GROUP ...
- Mysql基础(三)
#DML语言 /* 数据操作语言 插入:insert insert into 表名(列名,...) values(值1,...); insert into 表名 set 列名=值, 列名=值,... ...
随机推荐
- python系列:argparse详解 外部传参给python的库
一.argparse简介 argparse 模块是 Python 内置的用于命令项选项与参数解析的模块,argparse 模块可以让人轻松编写用户友好的命令行接口,能够帮助程序员为模型定义参数. ar ...
- WPF 中引入依赖注入(.NET 通用主机)
WPF 中引入依赖注入(.NET 通用主机) 在网上看到的文章都是通过 App.cs 中修改配置进行的,这样侵入性很高而且服务主机是通过 App 启动时加载的而不是服务主机加载的 App 有一点违反原 ...
- STM32 + ESP32(AT固件 MQTT协议) + MQTTX(桌面终端) + (EMQX消息服务器)
翻出老物件,搭建一个简单的 IOT 开发环境,也算是废物利用了 ,接下来加传感器.1. STM32 采集数据: RTOS. 资源相对比较丰富,可以根据项目需求定制.2. ESP32 ...
- 【解决】elasticsearch:Could not parse aggregation keyed as [%s]问题
背景 在做elasticsearch集群从原来的2.x版本升级到更新版本如6.x过程中,由于需要在原来的应用中,同时连接2.x的集群以及6.x的集群来做在线动态灰度切流量,保证流量平滑切换,有问题可随 ...
- Linux内存管理 | 一、内存管理的由来及思想
1.前言 <中庸>有:"九层之台,起于垒土" 之说,那么对于我们搞技术的人,同样如此! 对于Linux内存管理,你可以说没有留意过,但是它存在于我们日常开发的方方面面, ...
- Python合并多个Excel文件中的指定sheet
本文将介绍一个用于合并多个Excel文件中指定sheet的Python代码.这个功能可以方便地整理和分析数据.我们将逐步解释代码的每个部分,并提供示例用法. 导入库 首先,我们导入了需要使用的三个库: ...
- 【日常收支账本】【Day03】完成编辑账本界面的新增动账记录功能——通过ElementTree加XPath实现
一.项目地址 https://github.com/LinFeng-BingYi/DailyAccountBook 二.新增 1. 解析xml文件 1.1 功能详述 解析所设计的xml文件格式,并将所 ...
- OpenGL 摄像机视角详解
1. 摄像机 摄像机就好像是我们的眼睛,我们从摄像机的方向观察世界空间中的模型.摄像机远离模型,模型自然就变小了(透视投影下),然而,在GL中事实上并没有摄像机的概念.但是我们可以通过移动世界空间远离 ...
- NLP技术如何为搜索引擎赋能
在全球化时代,搜索引擎不仅需要为用户提供准确的信息,还需理解多种语言和方言.本文详细探讨了搜索引擎如何通过NLP技术处理多语言和方言,确保为不同地区和文化的用户提供高质量的搜索结果,同时提供了基于Py ...
- 【scipy 基础】--图像处理
SciPy库本身是针对科学计算而不是图像处理的,只是图像处理也包含了很多数学计算,所以Scipy也提供了一个专门的模块ndimage用于图像处理. ndimage模块提供的功能包括输入/输出图像.显示 ...