事物的隔离性和MVCC
事物的隔离性
mysql的服务端是支持多个客户端同时与之连接的,每个客户端可能还并发了好几个连接,所以mysql是需要同时处理很多事情的,每一件独立的事情就叫做事务。我们知道事务有一个叫隔离性的特性,隔离性理论上是指在某个事物对某个数据进行访问时,其他的事务就应该排队知道访问数据的事务提交才能继续访问该数据。但是这样对性能的影响就太大了,但是我们又必须保持一定的隔离性,所以就需要折中一下。
事务并发可能的问题
先来看看不保证绝对的隔离性会遇到哪些问题呢
- 脏写
如果一个事务修改了另一个未提交事务修改过的数据,这就意味着发生了脏写。
- 脏读
如果一个事务读到了另一个未提交事务修改过的数据,这就意味着发生了脏读。
- 不可重复读
如果同一个事务中能读到其他事务提交后的最新值,这时其他事务对这个数据进行的每次改动都会让该事务读到不同最新值,这就意味着发生了不可重复读。
- 幻读
如果一个事务根据某些查出一些记录,之后另一个事务又向表中插入了符合这些条件的记录,该事务再次用该条件查询的时候,就会查出上次查没查到的数据即另一个事务刚插入的数据,这就是幻读。
小贴士:
不可重复读和幻读确实有点相似,但不可重复读重点在于update和delete,而幻读的重点在于insert。对于前者,要避免只需锁住满足条件的已有记录即可,避免后者就需要锁住满足条件的记录(包括存在的和不存在的),不存在的记录如何才能锁住呢?所以锁的范围需要扩大到满足条件的相邻范围的记录(临键锁)
事务的隔离级别
这时就出现了一个标准用来定义上面说的折中的程度,在SQL标准中定义了4个隔离级别:
- READ UNCOMMITTED:读未提交
- READ COMMITTED:读已提交
- REPEATABLE READ:可重复读
- SERIALIZABLE:可串行化
SQL标准中规定,针对不同的隔离级别并发事务可以发生不同严重程度的问题

MVCC
MVCC解决了事务并发时读和写同时进行互不影响的问题,从而提升系统性能。mvcc并不能解决完全解决脏读和不可重复读的问题,如果innoDB只有mvcc没有锁,那么当前事务确实没办法读取到未提交的数据,但是可以修改。
对于读已提交和可重复读的事务来说,都必须保证读到的记录是已经提交了的事务修改的记录,所以如果想做到读写互不影响,核心问题就是读取记录时需判断版本链中的哪个版本是对当前事务可见。
MVCC原理
对于innoDB存储引擎来说,每张表中都含有两个必要的隐藏列trx_id和roll_pointer。每次对某条记录进行改动时,都会把旧的版本写入到 undo日志中,然后在这个roll_pointer列中存储旧版本在undo日志的地址,可以通过它来找到该记录修改前的信息,同时将进行改动的事务id写入trx_id列。

在可重复读的隔离模式下每个事务都会生成一个 ReadView ,主要包含4个重要的内容:
m_ids :表示在生成 ReadView 时当前系统中活跃的读写事务的 事务id 列表。
min_trx_id :表示在生成 ReadView 时当前系统中活跃的读写事务中最小的 事务id ,也就是
m_ids 中的最 小值。
max_trx_id :表示生成 ReadView 时系统中应该分配给下一个事务的 id 值。
creator_trx_id :表示生成该 ReadView 的事务的 事务id 。
有了这个 ReadView ,这样在访问某条记录时,只需要按照下边的步骤判断记录的某个版本是否可见:
如果被访问版本的 trx_id 属性值与 ReadView 中的 creator_trx_id 值相同,意味着当前事务在访问它自己 修改过的记录,所以该版本可以被当前事务访问。
如果被访问版本的 trx_id 属性值小于 ReadView 中的 min_trx_id 值,表明生成该版本的事务在当前事务生 成 ReadView 前已经提交,所以该版本可以被当前事务访问。
如果被访问版本的 trx_id 属性值大于 ReadView 中的 max_trx_id 值,表明生成该版本的事务在当前事务生 成 ReadView 后才开启,所以该版本不可以被当前事务访问。
如果被访问版本的 trx_id 属性值在 ReadView 的 min_trx_id 和 max_trx_id 之间,那就需要判断一下 trx_id 属性值是不是在 m_ids 列表中,如果在,说明创建 ReadView 时生成该版本的事务还是活跃的,该版本不可以被访问;如果不在,说明创建 ReadView 时生成该版本的事务已经被提交,该版本可以被访问。
如果某个版本的数据对当前事务不可见的话,那就顺着版本链找到下一个版本的数据,继续按照上边的步骤判断 可见性,依此类推,直到版本链中的最后一个版本。如果最后一个版本也不可见的话,那么就意味着该条记录对 该事务完全不可见,查询结果就不包含该记录。
上面两段引用来自于《MySQL是怎样运行的:从根儿上理解MySQL》,我觉得已经很明白了。
我写文章都是力求正确,但水平有限,欢迎大佬斧正。
相关资源:
MySQL是怎样运行的:从根儿上理解MySQL
事物的隔离性和MVCC的更多相关文章
- 事务传播性、隔离性与MVCC
一.事务传播性 1.1 什么是事务的传播性 事务的传播性一般在事务嵌套时候使用,比如在事务A里面调用了另外一个使用事务的方法,那么这俩个事务是各自作为独立的事务执行提交,还是内层的事务合并到外层的事务 ...
- 一文搞懂MySQL事务的隔离性如何实现|MVCC
关注公众号[程序员白泽],带你走进一个不一样的程序员/学生党 前言 MySQL有ACID四大特性,本文着重讲解MySQL不同事务之间的隔离性的概念,以及MySQL如何实现隔离性.下面先罗列一下MySQ ...
- 理解MySQL数据库事务-隔离性
Transaction事务是指一个逻辑单元,执行一系列操作的SQL语句. 事务中一组的SQL语句,要么全部执行,要么全部回退.在Oracle数据库中有个名字,叫做transaction ID 在关系型 ...
- 跟面试官侃半小时MySQL事务隔离性,从基本概念深入到实现
提到MySQL的事务,我相信对MySQL有了解的同学都能聊上几句,无论是面试求职,还是日常开发,MySQL的事务都跟我们息息相关. 而事务的ACID(即原子性Atomicity.一致性Consiste ...
- 数据库ACID、隔离级别与MVCC
首先需要明确事务的概念:一组原子性的SQL查询,如果数据库引擎能够成功的对数据库应用该组查询的全部语句,那么就执行该组语句,否则所有语句都不执行. 事务有ACID四个特性,即: 原子性:一个事务是一个 ...
- MySQL:事务的隔离性
[参考文章]:数据库的事务特性及隔离级别 1. 事务的四大特性 1.1 原子性(Atomicity) 原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成功就必须要完全应用 ...
- MySQL四种隔离级别和MVCC
事务在一个数据库中的地位尤为重要,尤其是高并发的场合.保证数据库操作的原子性和错误出现情况下的回滚,对数据的安全性和可靠性提供了保障.事务有四大原则,即ACID原则.网上关于这个问题的文章有很多,读者 ...
- SpringBoot 事务隔离性和传播性
propergation 传播性 Spring中七种Propagation类的事务属性详解: REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务.这是最常见的选择. SUPPORTS ...
- 事务ACID特性,其中I代表隔离性(Isolation)。
事务ACID特性,其中I代表隔离性(Isolation). 什么是事务的隔离性? 隔离性是指,多个用户的并发事务访问同一个数据库时,一个用户的事务不应该被其他用户的事务干扰,多个并发事务之间要相互隔离 ...
随机推荐
- 3.对互斥事件和条件概率的相互理解《zobol的考研概率论教程》
tag:这篇文章没太多思考的地方,就是做个过渡 1.从条件概率来定义互斥和对立事件 2.互斥事件是独立事件吗? 3.每个样本点都可以看作是互斥事件,来重新看待条件概率 一.从条件概率来定义互斥和对立事 ...
- 基于web3D展示技术的煤矿巷道3D可视化系统
地下开采离不开巷道工程.煤矿的生产.运输.排水.通风等各个环节都少不了巷道的支持.在煤矿智能化建设被提上日程的今天,巷道工程的智能化.可视化建设也成了行业趋势.尤其是复杂的井下作业环境,人员信息安全问 ...
- 关于 GIN 的路由树
GIN 是一个 golang 常用的 Web 框架,它对 API 比较友好,源码注释也很明确明确,使用起来快速灵活,还有极高的容错率.标题中的路由我们可以简单理解为在浏览器中输入的页面地址,而&quo ...
- HDLBits->Verilog Language->Modules:Hierarchy->Modules and vectors
题目要求如上不再赘述,主要关注到最后的四选一多路选择器. 最初编写的选择器代码如下 always@(sel) case(sel) 2'd0:q <= d; 2'd1:q <= in1; 2 ...
- 执行docker一系列命令失败
出现这种情况之后,执行下面的命令即可. systemctl restart docker
- Python实现哈希表(分离链接法)
一.python实现哈希表 只使用list,构建简单的哈希表(字典对象) # 不使用字典构造的分离连接法版哈希表 class HashList(): """ Simple ...
- Tapdata肖贝贝:实时数据引擎系列(三) - 流处理引擎对比
摘要:本文将选取市面上一些流计算框架包括 Flink .Spark .Hazelcast,从场景需求出发,在核心功能.资源与性能.用户体验.框架完整性.维护性等方面展开分析和测评,剖析实时数据框架 ...
- protobuf 的交叉编译使用(C++)
前言 为了提高通信效率,可以采用 protobuf 替代 XML 和 Json 数据交互格式,protobuf 相对来说数据量小,在进程间通信或者设备之间通信能够提高通信速率.下面介绍 protobu ...
- JavaWeb连接MySQL数据库
JavaWeb连接MySQL数据库 JavaWeb连接MySQL数据库的方式有很多,首先我们讲解JDBC的配置方法 一.JDBC的配置方法 1.什么是JDBC 什么是JDBC嘞?JDBC代表Java数 ...
- Qt+ECharts开发笔记(三):ECharts的柱状图介绍、基础使用和Qt封装Demo
前言 上一篇成功是EChart随着Qt窗口变化而变化,本篇将开始正式介绍柱状图介绍.基础使用,并将其封装一层Qt. 本篇的demo实现了隐藏js代码的方式,实现了一个条形图的基本交互方式,即Qt ...