再有人问你MySql的隔离级别,直接把这篇文章发给他!
作者 l zyz1992
来源 l Hollis(ID:hollischuang)
首先要明白什么是事务?
事务是程序中一系列严密的操作,所有的操作必须完成,否则在所有的操作中所做的所有的更改都会被撤销。也就是事务的原子性,一个事务中的一系列的操作要么全部成功,要么就是失败。
事务的结束有两种,当事务中所有的步骤全部成功执行的时候,事务提交。如果其中一个步骤失败,将会发生回滚操作,撤销到事务开始之前的所有的操作。
事务的ACID
事务具有四个特征
原子性 事务是数据库的逻辑工作单位,事务中包含多个操作,要么都做完,要么都不做
隔离性(隔离性也是本文的重点) 事务彼此之间是不能互相干扰的,即一个事务的操作对该数据库的其他事务操作是隔离的,并发执行的各个事务时间互补干扰
持久性 事务一旦提交,其变更是永久性的
一致性 事务执行的结果必须满足从一个状态变到另一个状态,因此当数据库只包含成功事务提交的结果时,就说数据库处于一致性的状态。如果数据库系统在运行时发生系统故障,有些未完成的事务被迫中止,而有一部分修改已经写入数据库,这个时候数据库就处于一种不正确的状态。
其实以上三个条件(原子性、隔离性、持久性)最终都是为了保持数据库数据的一致性服务的
MySQL的四种隔离级别
SQL标准定义了四种隔离级别,用来限定事务内外的哪些改变是可见的,哪些是不可见的。
读取未提交的数据【Read Uncommitted】 在该隔离级别,所有的事务都可以看到其他事务没有提交的执行结果。(实际生产中不可能使用这种隔离级别的)
读取提交的内容【Read Committed】 该隔离级别是大多数数据库的默认的隔离级别(不是 MySQL 默认的)。它满足了隔离的简单定义:一个事务只能看到其他的已经提交的事务所做的改变。这种隔离级别也支持不可重复读,即同一个 select 可能得到不同的结果
可重读【Repeatable Read】 这是 MySQL 默认的隔离级别,它确保同一个事务在并发读取数据时,会看到同样的数据行。不过理论上会导致另外一个问题,【幻读】。幻读:相同的条件查询一些数据,然后其他事务【新增】或者是【删除】了该条件的数据,然后导致读取的结果不一样多。InnoDB 存储引擎通过多版本控制(MVCC)机制解决了该问题
可串行化【serializable】 这是事务的最高隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决了幻读的问题。它在每个读的数据行上面加上共享锁,。但是可能会导致超时和锁竞争(这种隔离级别太极端,实际生产基本不使用)
这四种隔离级别采用不同的锁类型来实现
脏读 读取了前一个事务未提交的或者是回滚的数据
不可重复度 同样的 select 查询,但是结果不同,过程中有事务更新了原有的数据
幻读 两次查询的结果数量不一样,过程中有事务新增或者是删除数据
下面对不同的隔离级别产生的不同的问题做一个汇总
各个隔离级别的详细测试
查看数据库的隔离级别
show variables like '%isolation%'
设置数据库的隔离级别
set session transaction isolation level Read Uncommitted;
设置数据库的隔离级别为:Read Uncommitted
实验一:Read Uncommitted
Read Uncommitted
即:读取未提交
前置条件:将数据库的隔离级别设置为read uncomitted;
set session transaction isolation level Read Uncommitted;
img
img
第一步:A开启事务:start tracsaction;
img
第二步:A查询数据:select * from test;
img
第三步:B开启事务:start transaction;
img
第四步:B查询数据:select * from test;
img
第五步:B更新数据:update test set num =10 where id = 1
;B没有提交事务
img
第六步:A读取数据----A读取到了B未提交的数据(当前数据库的隔离级别是:Read Uncommitted)
img
第七步:B回滚数据:rollback;
img
第八步:B查询数据:select * from test;
img
第九步:A查询数:select * from test;
img
结论:事务B更新了数据,但是没有提交,事务A读取到的是B未提交的记录。因为造成脏读。Read Uncommitted是最低的隔离级别
实验二:读取已提交-Read Committed
前置条件:将数据库的隔离级别设置为:Read Committed;
set session transaction isolaction level Read Committed;
img
img
第一步:A开始事务:start transaction;
img
第二步:A查询数据:select *from test;
img
第三步:B开启事务:start transaction;
img
第四步:B查询数据:select * from test;
img
第五步:B更新数据:update test set num =10 where id=1
查看结果:
img
第六步:A查询数据:select * from test;
img
第七步:B提交数据:commit;
img
第八步:A查询数据:select * from test;
img
结论:Read Committed
读已提交的隔离级别解决了脏读的问题,但是出现了不可重复读的问题,即事务A在两次查询的结果不一致,因为在两次查询之间事务B更新了一条数据。
读已提交的只允许读取已经提交的记录 ,但是不要求可重复读
实验三:可重读度-Repeatable Read
前置条件:将数据库的级别设置为可重复度
set session transaction isolation level repeatable read;
img
第一步:A开始事务:start transaction;
img
第二步:A查询数据:select * from test;
img
第三步:B开启事务:start transaction;
img
第四步:B查询数据:select * from test;
img
第五步:B更新数据:update test set num=10 where id=1;
img
此时B并没有提交事务
第六步:B查询数据:select * from test;
img
第七步:A查询数据
img
结果仍然是之前的结果(因为B事务还没有提交)
第八步:B提交事务:commit;
img
第九步:A查询数据:select * from test;
此时A查询的记录仍然和之前一样
img
第十步:B插入一条数据并提交事务:inset into test(num) value(4);
img
第十一步:A查询数据,发现结果还是和之前的一样:select * from test;
img
第十二步:A提交事务并查询数据
img
此时发现A查询的数据已经和B查询的结果一致了;
结论:Repeatable Read
隔离级别只允许读取已经提交的事务的记录,
实验四:串行化-Serializable
前置条件:将数据库的隔离级别设置为可串行化
img
第一步:A开始事务并查询数据
img
第二步:B开启事务并insert数据,发现只能等待,并不能执行下去
img
第三步:A提交事务
img
第四步:B插入数据
img
结论:serializable
完全锁定字段,若一个事务来操作同一份数据,那么就必须等待,直到前一个事务完成并解除锁为止。是完整的隔离级别,会锁住对应的数据表,因为会导致效率问题。
本文小结
本片文章并没有深入的去讲解原理,而是让大家能够从更直观的从隔离级别的表面去了解隔离级别,因为我发现我的很多同事对此是模模糊糊,模棱两可的,但是这个是不可以的,因为技术本身是不允许存在这种歧义的,懂就是懂,才能合理运用,如果模棱两可,那么在实际运用中一定也是漏洞百出,所以这也是这篇文章诞生的原因。
我们可以先抛开原理与底层的具体实现,先能够清晰且明了的搞清楚各个专业术语的含义,这未尝不是一种进步。
最后以一句不积跬步无以至千里,不积小流无以成江河与诸君共勉!
往期推荐
厉害了,Spring中bean的12种定义方法!
@Autowired报错的4种解决方案和原因分析!
SpringBoot 中的 3 种条件装配!
再有人问你MySql的隔离级别,直接把这篇文章发给他!相关推荐
- 再有人问你volatile是什么,就把这篇文章发给他
转载自 再有人问你volatile是什么,就把这篇文章发给他 在再有人问你Java内存模型是什么,就把这篇文章发给他中我们曾经介绍过,Java语言为了解决并发编程中存在的原子性.可见性和有序性问题, ...
- 再有人问你synchronized是什么,就把这篇文章发给他。
在<深入理解Java虚拟机>中,有这样一段话: synchronized关键字在需要原子性.可见性和有序性这三种特性的时候都可以作为其中一种解决方案,看起来是"万能"的 ...
- 再有人问你MySQL索引原理,就把这篇文章甩给他!
△Hollis, 一个对Coding有着独特追求的人△ 这是Hollis的第 335 篇原创分享 作者 l zyz1992 来源 l Hollis(ID:hollischuang) 索引,可能让好很多 ...
- 再有人问你Netty是什么,就把这篇文章发给他
点击上方"方志朋",选择"置顶或者星标" 你的关注意义重大! 本文转载于公众号:Hollis 本文基于Netty4.1展开介绍相关理论模型,使用场景,基本组件. ...
- 再有人问你volatile是什么,就把这篇文章发给他,让他哑口无言
本文就围绕volatile展开,主要介绍volatile的用法.volatile的原理,以及volatile是如何提供可见性和有序性保障的等. volatile这个关键字,不仅仅在Java语言中有,在 ...
- 再有人问你什么是ThreadLocal,就把这篇文章甩给他!
本文来自作者投稿,原作者:itlemon ,原文地址:https://blog.csdn.net/Lammonpeter/article/details/105175187 ThreadLocal是J ...
- 再有人问你MySql 的隔离级别是什么,就把这篇文章发给他!
△Hollis, 一个对Coding有着独特追求的人△ 这是Hollis的第 356 篇原创分享 作者 l zyz1992 来源 l Hollis(ID:hollischuang) 首先要明白什么是事 ...
- 再有人问你MySQL是如何查询数据的,请把这篇文章甩给他!
上一篇我们说到了关于MySQL的索引的原理,主要说的是 MySQL 对于索引的字段是怎么去维护的,我们再来简单的回顾下: MySQL 对于主键索引的维护是最简单的,就是根据主键去维护一个 B+ 树,因 ...
- mysql unicode转汉字_如果有人问你 MySql 怎么存取 Emoji,把这篇文章扔给他
01.前言 Emoji 在我们生活中真的是越来越常见了,几乎每次发消息的时候不带个 Emoji,总觉得少了点什么,似乎干巴巴的文字已经无法承载我们丰富的感情了.对于我们开发者来说,如何将 Emoji ...
最新文章
- Android Intent的 Component 使用
- 为什么 HashMap 加载因子一定是0.75?而不是0.8,0.6?
- Cacti Weathermap 高级用法 (二)
- Python 发送 email 的三种方式
- torch view view_as
- GDB调试:观察点(数据断点)【GDB调试】
- ffmpeg中av_strlcpy替换了pstrcpy
- 使用Spring Integration重试RabbitMQ
- linux 下外语学习软件_学习外语如何帮助您学习编码
- OpenShift 4 - DevSecOps - 视频
- centos 7增强命令补全
- SmartSVN无法提交的解决办法:because it was moved from which is not part of the commit; both sides of the move
- python图形绘制星空图_天文星空图谱开源软件Stellarium
- 饿了么分布式服务治理及优化经验(含PPT)
- 2022年3月搜索引擎市场份额排行榜
- 女孩子希望得到,却不会说出来的东西Kiss her slowly
- xp计算机找不到音量调节,WinXP电脑没声音且小喇叭不见了如何解决?
- 这些富人思维,学会任何一种都可以纵横互联网
- uniapp开发app真机调试连接电脑服务器请求失败解决方法
- 真实吐槽点评:华为nova8SE和华为nova7Pro区别-哪个更值得入手-参数对比
热门文章
- python读取字典元素笔记_Python 学习笔记 - 字典
- JDK源码解析之 java.lang.Long
- 五个案例简述Web设计原则:通用一致
- UVA401 ​​​​​​​Palindromes【字符串】
- WPF,Silverlight与XAML读书笔记第三十九 - 可视化效果之3D图形
- rocksdb ubuntu c++源码编译测试
- 统计Apache或Nginx访问日志里的独立IP访问数量的Shell
- Java中的main方法
- HighCharts: 设置时间图x轴的宽度
- linux --常用命令