您当前的位置:首页 > 电脑百科 > 程序开发 > 程序员

最详细MySQL事务隔离级别及原理讲解!(二)

时间:2020-06-26 11:50:02  来源:  作者:

 

 

上一篇MySQL的文章讲了事务的特性和原理(

最详细的MySQL事务特性及原理讲解!(一)

) 作为基础,小伙伴们自行查看。

关于MySQL隔离级别的讲解,网上已经很多了。和大家一样,我也看过很多很多,但是发现看完之后还是晕晕乎乎,学习走了很多弯路。事务特性的原理是什么?什么隔离级别可以解决什么问题?具体什么原理?这些似乎都没有讲清楚,无非是抄来抄取,甚至都抄错了,我查了近10篇文章每篇都有各种各样的错误!比如下面这个举例:

最详细MySQL事务隔离级别及原理讲解!(二)

 

作者说RR解决了幻读的问题,并且还不止一个人这样说。还有说未提交读级别下不加锁。

最详细MySQL事务隔离级别及原理讲解!(二)

 

那么事实是这样吗?(阅读提醒:点收藏前先点「在看」,记忆效果翻倍!)

隔离性

与原子性、持久性侧重于研究事务本身不同,隔离性研究的是不同事务之间的相互影响。隔离性是指,事务内部的操作与其他事务是隔离的,并发执行的各个事务之间不能互相干扰。

严格的隔离性,对应了事务隔离级别中的Serializable (可串行化),但实际应用中出于性能方面的考虑很少会使用可串行化。隔离性追求的是并发情形下事务之间互不干扰。SQL标准定义了4类隔离级别:Read Uncommitted(读取未提交内容)、Read Committed(读取提交内容)、Repeatable Read(可重读)、Serializable(可串行化)。

对于隔离性的探讨,主要可以分为两个方面:

1.锁机制保证隔离性

2.MVCC保证隔离性。

隔离级别原理及问题

严格的隔离性,对应了事务隔离级别中的Serializable (可串行化),但实际应用中出于性能方面的考虑很少会使用可串行化。所以,共有四种隔离级别来对应不同的业务性能需求。然而正是由于不同的隔离级别,便产生了不同的问题。

我们不妨带着几个问题去继续阅读:

1.可重复读和幻读的区别是什么?

2.每个隔离级别解决了怎样的问题?怎么解决的?

1、读未提交(READ_UNCOMMITTED)

顾名思义,该隔离级别下可以读取到另一个事务未提交的数据。严谨一点,我们给出官方定义:

The isolation level that provides the least amount of protection between transactions. Queries employ a locking strategy that allows them to proceed in situations where they would normally wait for another transaction. However, this extra performance comes at the cost of less reliable results, including data that has been changed by other transactions and not committed yet (known as dirty read). Use this isolation level with great caution, and be aware that the results might not be consistent or reproducible, depending on what other transactions are doing at the same time. Typically, transactions with this isolation level only do queries, not insert, update, or delete operations.

如文档所说,它提供了最低的隔离级别,查询时采用无需等待其他事务的锁策略。所以,在这个隔离级别下,基本上什么问题都会产生了。于是文档建议,通常具有此隔离级别的事务仅执行查询,而不执行插入,更新或删除操作。

但是,这并不代表他一无是处。其实RU隔离级别解决了一个问题——当A事务修改数据n,B事务也修改数据n,后执行的语句会把另一个事务的结果覆盖。如文章开头提到的反例,如果读未提交隔离级别下不加锁,这是不可能实现的。

为了解决丢失修改的写覆盖问题,未提交读规定:

1.事务A对当前被读取的数据不加锁,事务B读取也不加锁。

2.事务A开始更新一行数据时,必须先对其加排他锁,直到事务结束才释放。

如何证明呢?

事务A事务B

最详细MySQL事务隔离级别及原理讲解!(二)

 


最详细MySQL事务隔离级别及原理讲解!(二)

 


最详细MySQL事务隔离级别及原理讲解!(二)

 


最详细MySQL事务隔离级别及原理讲解!(二)

 


最详细MySQL事务隔离级别及原理讲解!(二)

 

发生脏读 和 等待

最详细MySQL事务隔离级别及原理讲解!(二)

 

图中左边为事务A,右边为事务B,可见事务A更新时加排他锁,事务未提交,所以事务B更新数据发生阻塞。但是B却可以读取到A修改后的数据,说明B在读取时并未加任何锁。

最详细MySQL事务隔离级别及原理讲解!(二)

 

如图,证明两个事务在更新时发生了排他锁竞争。

脏读(DIRTY READ)

那么未提交读会产生什么问题?刚才的例子依旧说明了,发生了脏读。如图:

最详细MySQL事务隔离级别及原理讲解!(二)

 

右边事务读取到了左边事务更改后的数据 a=11,但左边事务还未提交。

我们依旧给出脏读的定义:

An operation that retrieves unreliable data, data that was updated by another transaction but not yet committed. It is only possible with the isolation level known as read uncommitted.

检索不可靠数据的操作,该数据是由另一个事务更新但尚未提交的数据。只有在隔离级别称为未提交读的情况下才有可能。

划重点!读出来的数据不可靠,是可以被其他事务修改后未提交的数据。脏读只可能出现在未提交读情况下。

2、读已提交(READ_COMMITTED)

读已提交和读未提交最大的区别如名字所说,可以读到另一个事务已提交读数据。官方定义如下:

An isolation level that uses a locking strategy that relaxes some of the protection between transactions, in the interest of performance. Transactions cannot see uncommitted data from other transactions, but they can see data that is committed by another transaction after the current transaction started. Thus, a transaction never sees any bad data, but the data that it does see may depend to some extent on the timing of other transactions.

事务无法看到来自其他事务的未提交的数据,但是它们可以看到在当前事务开始后另一个事务提交的数据。因此,一个事务永远不会看到任何不良数据,但是它所看到的数据可能在某种程度上取决于其他事务的时间安排。

实验前,更改数据库隔离级别为RC。

mysql> set session transaction isolation level read committed;Query OK, 0 rows affected (0.01 sec)
mysql> SELECT @@tx_isolation;+----------------+| @@tx_isolation |+----------------+| READ-COMMITTED |+----------------+1 row in set, 1 warning (0.00 sec)

事务A
事务B

最详细MySQL事务隔离级别及原理讲解!(二)

 


最详细MySQL事务隔离级别及原理讲解!(二)

 


最详细MySQL事务隔离级别及原理讲解!(二)

 


最详细MySQL事务隔离级别及原理讲解!(二)

 

脏读被解决

最详细MySQL事务隔离级别及原理讲解!(二)

 


最详细MySQL事务隔离级别及原理讲解!(二)

 


最详细MySQL事务隔离级别及原理讲解!(二)

 

不可重复读出现

如上表AB事务可知,在B事务更改数据 a=11 且事务未提交时,A事务读取到的还是旧数据 a=9,可见RC隔离级别很好的解决了脏读的问题。

但是紧接着在B事务提交后,A事务再次读取数据,a=11。在同一事务中两次查询出现了结果不一样的情况,这就是不可重复读。官方定义:

non-repeatable read:The situation when a query retrieves data, and a later query within the same transaction retrieves what should be the same data, but the queries return different results (changed by another transaction committing in the meantime).

查询检索数据,而同一事务中的前后查询检索应为相同的数据,但实际查询返回不同的结果(数据同时被其他提交的事务更改)。

很关键的一点,不可重复读是同一事务前后同样的查询返回了不同的数据!一定有人有这样的疑惑,那脏读不也是前后不一致吗,怎么区分这两者?很多文章只甩出了几个脏读、不可重复读、幻读的例子,却并没有解释清楚到底什么是什么。

现在我可以肯定的说,脏读的条件不可重复读一定满足,但是如果是不可重复读,脏读却不一定满足,脏读属于不可重复读。可以这么理解,RC级别下,相当于只解决了一部分不可重复读的问题。

他是如何解决脏读的呢,锁机制:

1.事务A对当前被读取的数据加共享锁,一旦读完该行,立即释放该共享锁(注意是读完立即释放

2.事务A在更新某行数据时,必须对其加上排他锁,直到事务结束才释放(注意是事务结束才释放

 

3、可重复读(REPEATABLE_READ)

听起来,可重复读解决了不可重复读的问题。事实是这样。官方定义:

The default isolation level for InnoDB. It prevents any rows that are queried from being changed by other transactions, thus blocking non-repeatable reads but not phantom reads. It uses a moderately strict locking strategy so that all queries within a transaction see data from the same snapshot, that is, the data as it was at the time the transaction started.

InnoDB的默认隔离级别它可防止查询的任何行被其他事务更改,从而阻止不可重复的读取,但不会阻止幻读。它使用中等严格的锁定策略,以便事务中的所有查询都可以查看来自同一快照的数据,即事务开始时的数据。

看重点!RR隔离级别是InnoDB默认隔离级别,他可以解决不可重复读,但不能解决幻读!这就是为什么我说很多文章错了,官方已经给出了明确定义。

mysql> set session transaction isolation level repeatable read;Query OK, 0 rows affected (0.00 sec)
mysql> SELECT @@tx_isolation;+-----------------+| @@tx_isolation  |+-----------------+| REPEATABLE-READ |+-----------------+1 row in set, 1 warning (0.00 sec)

如表格所示,不可重复读是被解决了,但很明显还有一个问题,没有解决幻读。

事务A事务B

最详细MySQL事务隔离级别及原理讲解!(二)

 


最详细MySQL事务隔离级别及原理讲解!(二)

 


最详细MySQL事务隔离级别及原理讲解!(二)

 


最详细MySQL事务隔离级别及原理讲解!(二)

 

已解决不可重复读
此时我们再来一次,回到B事务提交前但状态,执行一条insert语句。

最详细MySQL事务隔离级别及原理讲解!(二)

 


最详细MySQL事务隔离级别及原理讲解!(二)

 

回到更新前状态。
在B事务执行 insert 后再次查询

最详细MySQL事务隔离级别及原理讲解!(二)

 


最详细MySQL事务隔离级别及原理讲解!(二)

 

B事务提交后出现了奇怪的情况。A事务查询到的数据前后一致,但是在UPDATE条件下符合的数据却变成两条。

最详细MySQL事务隔离级别及原理讲解!(二)

 

A row that Appears in the result set of a query, but not in the result set of an earlier query. For example, if a query is run twice within a transaction, and in the meantime, another transaction commits after inserting a new row or updating a row so that it matches the WHERE clause of the query.

在查询的结果集中出现的行,但在较早的查询的结果集中没有出现。例如,如果一个查询在一个事务中运行两次,同时,另一个事务将在插入新行或更新一行以使其与查询的WHERE子句匹配之后提交。

请看上方幻读定义。重点是,同样的条件同一事务前后结果中出现了和之前不一样的行。与不可重复读的区别是什么:幻读的条件也符合不可重复读,但是不可重复读不一定符合幻读。前后检索出不一样的行当然查询前后查询结果不同,但是查询结果不同不一定有新的行。

为什么很多文章错误的认为RR可以解决幻读呢?我也不知道,可能是被快照读迷惑了?MVCC能解决快照读下的幻读问题,但是没法保证当前读下的幻读问题(这个我们下一篇细说,内容太多了)。但是幻读确实在一定条件下解决,这个条件就是 next-key locks。

By default, InnoDB operates in REPEATABLE READ transaction isolation level. In this case, InnoDB uses next-key locks for searches and index scans, which prevents phantom rows

默认情况下,InnoDB以REPEATABLE READ事务隔离级别运行。在这种情况下,InnoDB使用next-key locks 锁定进行搜索和索引扫描,从而防止幻读

使用效果如下:

select count(*) from test where id>=9 lock in share mode;

最详细MySQL事务隔离级别及原理讲解!(二)

 

执行 insert 发生阻塞,如此便使用了 next-key locks 防止幻读。

锁原理:

1.事务A在读取某数据时,必须先对其加共享锁,直到事务结束才释放(注意是事务结束才释放)

2.事务A在更新某数据时,必须先对其加排他锁,直到事务结束才释放(注意是事务结束才释放)

 

4、串行读(SERIALIZABLE_READ)

The isolation level that uses the most conservative locking strategy, to prevent any other transactions from inserting or changing data that was read by this transaction, until it is finished. This way, the same query can be run over and over within a transaction, and be certain to retrieve the same set of results each time. Any attempt to change data that was committed by another transaction since the start of the current transaction, cause the current transaction to wait.

最严格的隔离级别,防止其他任何事务插入或更改此事务读取的数据,直到完成为止。这样,可以在一个事务中一遍又一遍地运行相同的查询,并确保每次都检索相同的结果集。自当前事务开始以来,任何尝试更改另一事务提交的数据的尝试都会导致当前事务等待。

这个我就简单演示下,因为不会出现任何问题,但是效率也最低。

最详细MySQL事务隔离级别及原理讲解!(二)

 

如图,执行串行读级别下,insert 发生阻塞,隔离级别最严格。

锁机制:

1.事务在读取数据时,必须先对其加表级共享锁(注意这里是表级) ,直到事务结束才释放。

2.事务在更新数据时,必须先对其加表级排他锁(注意这里是表级) ,直到事务结束才释放。

总结

到这里,我们之前的问题也有了答案。

1.不同隔离级别解决怎样的问题:

隔离级别脏读不可重复读幻读读未提交发生发生发生读已提交✅发生发生可重复读✅✅可以在 next-key lock下解决
串行读✅✅✅

2.脏读、不可重复读、幻读关系

最详细MySQL事务隔离级别及原理讲解!(二)

 

 



Tags:MySQL   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
作者:雷文霆 爱可生华东交付服务部 DBA 成员,主要负责Mysql故障处理及相关技术支持。爱好看书,电影。座右铭,每一个不曾起舞的日子,都是对生命的辜负。 本文来源:原创投稿 *爱可生...【详细内容】
2021-12-24  Tags: MySQL  点击:(7)  评论:(0)  加入收藏
一、为什么要搭建主从架构呢1.数据安全,可以进行数据的备份。2.读写分离,大部分的业务系统来说都是读数据多,写数据少,当访问压力过大时,可以把读请求给到从服务器。从而缓解数据...【详细内容】
2021-12-15  Tags: MySQL  点击:(12)  评论:(0)  加入收藏
生成间隙(gap)锁、临键(next-key)锁的前提条件 是在 RR 隔离级别下。有关Mysql记录锁、间隙(gap)锁、临键锁(next-key)锁的一些理论知识之前有写过,详细内容可以看这篇文章...【详细内容】
2021-12-14  Tags: MySQL  点击:(18)  评论:(0)  加入收藏
binlog 基本认识 MySQL的二进制日志可以说是MySQL最重要的日志了,它记录了所有的DDL和DML(除了数据查询语句)语句,以事件形式记录,还包含语句所执行的消耗的时间,MySQL的二...【详细内容】
2021-12-14  Tags: MySQL  点击:(13)  评论:(0)  加入收藏
为查询优化你的查询 大多数的MySQL服务器都开启了查询缓存。这是提高性最有效的方法之一,而且这是被MySQL的数据库引擎处理的。当有很多相同的查询被执行了多次的时候,这些查...【详细内容】
2021-12-09  Tags: MySQL  点击:(15)  评论:(0)  加入收藏
测试的目的和原因,公司有很多程序员,每个程序员对数据库和表结构都有自己的理解。而且每个程序员的理解往往是以效率考虑。既然都是为了效率考虑,那么我就来测试一下究竟哪种使...【详细内容】
2021-12-08  Tags: MySQL  点击:(14)  评论:(0)  加入收藏
当你们考虑项目并发的时候,我在部署环境,当你们在纠结使用ArrayList还是LinkedArrayList的时候,我还是在部署环境。所以啊,技术不止境,我在部环境。今天这篇文章缕一下在同一台服...【详细内容】
2021-12-08  Tags: MySQL  点击:(17)  评论:(0)  加入收藏
对于数据分析来说,MySQL使用最多的是查询,比如对数据进行排序、分组、去重、汇总及字符串匹配等,如果查询的数据涉及多个表,还需要要对表进行连接,本文就来说说MySQL中常用的查询...【详细内容】
2021-12-06  Tags: MySQL  点击:(21)  评论:(0)  加入收藏
在学习SQL语句之前,首先需要区分几个概念,我们常说的数据库是指数据库软件,例如MySQL、Oracle、SQL Server等,而本文提到的数据库是指数据库软件中的一个个用于存储数据的容器。...【详细内容】
2021-11-24  Tags: MySQL  点击:(23)  评论:(0)  加入收藏
概述以前参加过一个库存系统,由于其业务复杂性,搞了很多个应用来支撑。这样的话一份库存数据就有可能同时有多个应用来修改库存数据。比如说,有定时任务域xx.cron,和SystemA域...【详细内容】
2021-11-05  Tags: MySQL  点击:(31)  评论:(0)  加入收藏
▌简易百科推荐
我 2010 年开始在 Github 上开源自己的代码。在 push 代码之前我根本没想过为什么。只是因为我当时学了 git,而且我又觉得 Github 很方便,可以用来备份自己的代码。而后我就参...【详细内容】
2021-12-28  程序员的喵    Tags:Github   点击:(2)  评论:(0)  加入收藏
JAVA开发工程师(北京)本科 3-5年经验 面议 (招1人)岗位职责:1.负责我行应用系统的设计,完成软件编码工作,负责管理代码设计规范等工作;2.根据应用需求分析说明书,评估需求研发的可行...【详细内容】
2021-12-27  just do丶IT公众号    Tags:国企   点击:(2)  评论:(0)  加入收藏
今天聊聊编程的本质。程序就是数据结构+控制+逻辑,程序员编程工作的本质是翻译,翻译机要来了,程序员怎么办?黑客帝国中的程序黑客帝国4就要上映了,不知道前三部你看懂了么?值得多...【详细内容】
2021-12-17  博士聊IT    Tags:程序员   点击:(9)  评论:(0)  加入收藏
梦醒之后,每个人对于这份职业的未来、互联网行业的未来,以及更重要的,自己的未来都有了更现实的判断 文 | 祝颖丽编辑 | 黄俊杰一个生于 1986 年的人,他所走过的前半生:从出生起,...【详细内容】
2021-12-03    财经杂志  Tags:程序员   点击:(16)  评论:(0)  加入收藏
前些天在头条看到一个八二年的哥们,述说自己找工作屡次被拒的问题,在网上引起了广泛的讨论,这件事给我留下了很深的印象,因为这哥们和我同是程序员,都人到中年,上有老下有小。唯一...【详细内容】
2021-12-01  云南贤哥在深圳    Tags:程序员   点击:(20)  评论:(0)  加入收藏
很多读者都问过一个问题:程序员如何实现高速成长?之前也写过相关的文章,强调的主要是夯实计算机体系基础知识。 再说另一个诀窍:多看经典开源项目,这些项目大多是众多顶尖程序员...【详细内容】
2021-11-30  findyi    Tags:程序员   点击:(15)  评论:(0)  加入收藏
近日,一位45岁的网民在中国政府网留言求职,引发关注。该网民自称是一名软件开发人员,今年45岁,精通各种技术体系,“而我辞职回家半年后再回来寻找工作机会的时候,却发现连个面试...【详细内容】
2021-11-17  郭主任    Tags:程序员   点击:(42)  评论:(0)  加入收藏
即使在安全技术取得进步之后,网络犯罪仍在不断增加。据统计,网络犯罪每分钟给企业造成约 290 万美元的损失。主要是因为新技术不断涌现,难以维护安全。随着网络威胁的增加,网络...【详细内容】
2021-11-04  章大千    Tags:编程语言   点击:(40)  评论:(0)  加入收藏
北漂小伙李强(化名),在北京互联网大厂工作7年,月薪3万,离职回老家开摄影店,亏了200万。李强出生于山西一座名不经传的小城市,互联网专业大学毕业的他,没有听父母的劝言回到家乡考公...【详细内容】
2021-10-29  霸王课  今日头条  Tags:程序员   点击:(53)  评论:(0)  加入收藏
程序员是青春饭,这在国内似乎是公认的。所以很多公司不愿招大龄程序员,很多程序员也“知趣”地及早转型。有的做管理,有的做架构,我还见过改行卖保险的。总之,年龄大了不想敲代码...【详细内容】
2021-10-27  编程的艺术    Tags:   点击:(30)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条