啥是 MySQL 事务隔离级别?
之前发过一篇文章,简单了解 MySQL 中相关的锁,里面提到了,如果我们使用的 MySQL 存储引擎为 InnoDB ,并且其事务隔离级别是 RR 可重复读的话,是可以避免幻读的。
但是没想到,都 1202 年了都还有人杠,说 InnoDB 的 RR 隔离级别下会出现幻读,只能依靠 gap 和 next-key 这两个锁来防止幻读 ,最开始我还以为是他真的不知道这个点,就跟他聊,最后聊下来发现,发现是在钻牛角尖。
这个在下面讲到 可重复读 的隔离级别时会讲。
本来我觉得事务隔离级别这玩意儿太简单没啥可讲的,但是经过了上面这件事,我打算详细的把事务隔离给讲讲。接下来顺便就把 InnoDB 所有的事务隔离级别给搂一遍。
ACID
在聊事务隔离级别之前,我们需要知道 ACID 模型。

分别代表:
Atomicity 原子性 Consistency 一致性 Isolation 隔离型 Durability 持久性
原子性,代表 InnoDB 事务中,所有的操作要么全部成功,要么全部失败,不会处于某个中间状态。说的更通俗一点,如果事务 A 失败,其所做的所有的更改应该全部回滚。
一致性,主要是保护数据的一致性,防止由于数据库的崩溃而导致的数据一致性问题。举个例子,我们更新 MySQL 的数据,更新的数据会先到 InnoDB 的 Buffer Pool 中,如果此时 MySQL 所在的机器突然意外重启了,如果 InnoDB 没有崩溃恢复机制,之前更新的数据就会丢失,数据的一致性问题就出现了。
很多其他的博客写的是事务开要始前后,数据的完整性没有被破坏。我表示看了根本看不懂,太抽象了。
隔离性,主要是指事务之间的隔离,再具体一点,就是我们本篇文章要讨论的事务隔离级别了。
持久性,主要是指我们新增或者删除了某些数据,一旦成功,这些操作应该需要被持久化到磁盘上去。
ACID 模型可以理解成数据库的设计范式,主要关注点在数据数据、及其本身的可靠性。而 MySQL 中的 InnoDB 就完全遵守 ACID 模型,并且在存储引擎层就支持数据一致性的校验和崩溃恢复的机制。
而 ACID 中的隔离型,就是我们这篇文章中讨论的重点。
事务隔离级别
有很多文章上来就直接介绍事务隔离级别的种类,这个种类啥意思,那个种类怎么用。但我认为应该先了解为什么需要事务隔离级别,以及事务隔离级别到底解决了什么问题,这才是关键。
我们知道 InnoDB 中同时会有多个事务对数据进行操作,举一些例子:
假如事务A需要查询 id=1的数据,但是事务A查询完毕之后,事务B对id=1的数据做了更新,那此时事务A再次执行查询,应该看到更新前的数据还是更新后的数据?或者还是上面那个例子,事务A读取了事务B的数据,但是如果事务B进行回滚了怎么办?事务A的数据不就变成了脏数据? 又或者事务A读取了 1-3点的日程安排,有4条,但是事务A读取完成后事务B又向1-3点这个时间段插入了一条新的安排,那么事务A如果再次读取,应该显示4条日程安排还是5条?
以上的这些问题,就需要事务隔离级别来回答了。其实以上的三种情况分别对应不可重复读、脏读和幻读。InnoDB 通过事务隔离级别分别的解决了上面的问题。所有的事务隔离级别如下:
READ UNCOMMITTED 读未提交 READ COMMITTED 读已提交 REPEATABLE READ 可重复读 SERIALIZABLE 串行化
InnoDB 默认的事务隔离级别为 REPEATABLE READ 。
读未提交
事务A读取了事务B还未提交的数据
如果事务B此时出错了进行了回滚,那么事务A读取到的数据就成为了脏数据,从而造成脏读。
如果事务B又更新事务A读取的数据,那么事务A再次读取,读取到了事务B修改的结果,这造成了不可重复读。
而如果事务B又新增了数据,事务A再次读取,会读取到事务B新增的数据,这造成了幻读。

所以总结来说,在读未提交这个隔离级别下,会造成以下的问题:
脏读 不可重复读 幻读
读已提交
事务A读取了事务B已经提交的数据
如果事务B更新了事务A读取到的数据,并且提交,那么当事务A再次进行读取,就会读取到其他事务的变更,就造成了不可重复读。
同理,如果事务B新增了数据并且提交,事务A再次进行读取时拿到了事务B刚刚提交的数据,这就造成了幻读。

所以总结来说,在读已提交的隔离级别下,会造成:
不可重复读 幻读
可重复读
事务A不会读取到事务B更新的数据,也不会读到事务B新增的数据
在可重复读场景下,不会出现脏读、不会出现不可重复读,可能会出现幻读。

无论事务B做了什么操作,事务A查询到的 id=1 的数据都是张三。
但是,在某些情况下,还是可能会出现 幻读。可重复读 只是在某些情况下会产生幻读,但绝对不是 InnoDB 无法避免幻读。首先,InnoDB 在 RR 隔离级别下有很明确的解决幻读的方式,那就是——临键锁,一种组合了 gap 锁和记录锁的锁。
接下来举个例子来看在 RR 隔离级别下,什么情况会出现幻读,什么情况下不会出现幻读。首先是 可能会出现幻读。
SELECT * FROM `student` WHERE `id` > 1
由于 InnoDB 有 MVCC 来进行多事务的并发,此时 SELECT 走的是快照读,不会加锁,那么临键锁就无法发挥其作用,如果有其他事务插入了一条数据,那么事务再次执行上面的语句是有可能会查出 id > 1 的数据。
但是如果显示的进行加锁,则可以避免这个问题。
SELECT * FROM `student` WHERE `id` > 1 FOR UPDATE
至于为什么临键锁可以避免幻读,之前的文章已经聊的很清楚,就不在此赘述了。
串行化
所以事务被强制的串行执行
这样从根本上就避免了并发的问题,但是这样会使得 MySQL 的性能下降。因为现在同一时间只能有一个事务在运行。
EOF
关于事务隔离级别就先介绍到这,之后有时间了就把 事务隔离级别 的底层原理给搂一遍。
本篇文章已放到我的 Github github.com/sh-blog 中,欢迎 Star。微信搜索关注【SH的全栈笔记】,回复【队列】获取MQ学习资料,包含基础概念解析和RocketMQ详细的源码解析,持续更新中。
如果你觉得这篇文章对你有帮助,还麻烦点个赞,关个注,分个享,留个言。

啥是 MySQL 事务隔离级别?的更多相关文章
- [51CTO]新说MySQL事务隔离级别!
新说MySQL事务隔离级别! 事务隔离级别这个问题,无论是校招还是社招,面试官都爱问!然而目前网上很多文章,说句实在话啊,我看了后我都怀疑作者弄懂没!本文所讲大部分内容,皆有官网作为佐证,因此对本文内 ...
- 查询mysql事务隔离级别
查询mysql事务隔离级别 查询mysql事务隔离级别 分类: DB2011-11-26 13:12 2517人阅读 评论(0) 收藏 举报 mysqlsessionjava 1.查看当前会话隔离 ...
- MySQL事务隔离级别测试实例
https://www.cnblogs.com/huanongying/p/7021555.html MySQL事务隔离级别 事务隔离级别 脏读 不可重复读 幻读 读未提交(read-uncommit ...
- Mysql事务-隔离级别
MYSQL事务-隔离级别 事务是什么? 事务简言之就是一组SQL执行要么全部成功,要么全部失败.MYSQL的事务在存储引擎层实现. 事务都有ACID特性: 原子性(Atomicity):一个事务必须被 ...
- MySQL事务隔离级别 解决并发问题
MySQL事务隔离级别 1. 脏读: 骗钱的手段, 两个窗口或线程分别调用数据库转账表,转账后未提交,对方查看到账后,rollback,实际钱没转. 演示方法: mysql默认的事务隔离级别为repe ...
- mysql事务隔离级别、脏读、幻读
Mysql事务隔离级别本身很重要,再加上可能是因为各大公司面试必问的缘故,在博客中出现的概率非常高,但不幸的是,中国的技术博客要么是转载,要么是照抄,质量参差不齐,好多结论都是错的,对于心怀好奇之心想 ...
- mysql事务隔离级别与设置
mysql数据库,当且仅当引擎是InnoDB,才支持事务: 1.隔离级别 事务的隔离级别分为:未提交读(read uncommitted).已提交读(read committed).可重复读(repe ...
- MySQL事务隔离级别(二)
搞清楚MySQL事务隔离级别 首先创建一个表 account.创建表的过程略过(由于 InnoDB 存储引擎支持事务,所以将表的存储引擎设置为 InnoDB).表的结构如下: 为了说明问题,我们打开两 ...
- MySQL事务隔离级别(一)
本文实验的测试环境:Windows 10+cmd+MySQL5.6.36+InnoDB 一.事务的基本要素(ACID) 1.原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做 ...
- 面试突击61:说一下MySQL事务隔离级别?
MySQL 事务隔离级别是为了解决并发事务互相干扰的问题的,MySQL 事务隔离级别总共有以下 4 种: READ UNCOMMITTED:读未提交. READ COMMITTED:读已提交. REP ...
随机推荐
- httprunner的简介、httprunner做接口测试入门知识,使用httprunner模拟get请求及post请求
一.httprunner的简介 HttpRunner 是一款面向 HTTP(S) 协议的通用测试框架,只需编写维护一份 YAML/JSON 脚本,即可实现自动化测试.性能测试.线上监控.持续集成等多种 ...
- Firfox、Chrome之python-selenium环境搭建
公共步骤: 一.文件下载 下载地址: python安装包:https://www.python.org/getit/ PyCharm 安装包:http://www.jetbrains.com/pych ...
- 【VBA】显示所有隐藏的名称管理器中的名称
Excel提示这个 代码: Sub DisplayNames() Dim Na As Name For Each Na In ThisWorkbook.Names Na.Visible = True ...
- Django基础之模型层(02)
1 重要概念 # 多表查询 """ 正向查询 反向查询 当前查询对象是否含有外键字段 如果有就是正向 没有无则是反向 口诀: 正向查询按外键字段 多对多需要额外再加一个. ...
- 聊一聊 Spring Boot 中 RESTful 接口设计规范
在设计接口时,有很多因素要考虑,如接口的业务定位,接口的安全性,接口的可扩展性.接口的稳定性.接口的跨域性.接口的协议规则.接口的路径规则.接口单一原则.接口过滤和接口组合等诸多因素,本篇文章将简要分 ...
- 题解 P3233 [HNOI2014]世界树
题目传送门 解题思路 正解当然是虚树了. 首先对于原树以及虚树各开一个结构体存边,这个不用多说. 然后我们先 DFS 一遍,求出各个节点的时间戳,子树大小,深度以及父亲节点,并初始化倍增 LCA . ...
- 【题解】Luogu P3110 [USACO14DEC]驮运Piggy Back
[题解]Luogu P3110 [USACO14DEC]驮运Piggy Back 题目描述 Bessie and her sister Elsie graze in different fields ...
- .net core Redis消息队列中间件【InitQ】
前言 这是一篇拖更很久的博客,不知不觉InitQ在nuget下载量已经过15K了,奈何胸无点墨也不晓得怎么写(懒),随便在github上挂了个md,现在好好唠唠如何在redis里使用队列 队列缓存分布 ...
- .NET解密得到UnionID
由于微信没有提供.NET的解码示例代码,自己搜索写了一个,下面的代码是可用的 var decryptBytes = Convert.FromBase64String(encrypdata); var ...
- hive学习笔记之三:内部表和外部表
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...