mysql事务隔离级别、脏读、幻读

时间:2023-01-25 09:28:36

Mysql事务隔离级别本身很重要,再加上可能是因为各大公司面试必问的缘故,在博客中出现的概率非常高,但不幸的是,中国的技术博客要么是转载,要么是照抄,质量参差不齐,好多结论都是错的,对于心怀好奇之心想弄明白问题的同学来说,这些博客是很危险的。我当时也是看了各种版本的博客之后,翻官网,做实验,最终搞明白了一些事情,写在这里,希望对后来人有所帮助。

事务隔离级别
先说什么叫做“事务隔离”,事务隔离是指多个事务同时在进行中(如果只有一个事务,那就无所谓隔离不隔离了)时,各个事务被隔离开来,相互之间的影响和事物的隔离级别有关,按照“读未提交”–>“读已提交”–>“可重复读”–>“串行化”的顺序,越往后面隔离级别越高,事务之间的影响越小。
下面的内容都以这个数据表为例进行说明:

id money
1 10
2 20
4 40
读未提交和脏读
两个同时进行的事务A、B,A会读到B还未提交的的数据,这种事务隔离级别会存在脏读的问题,举个例子:
B修改id=2的money为200,但是尚未提交,然后A读取id为2的money,这是读到的值是200,然后B因为某种原因(比如系统异常)导致事务回滚了,此时2最终的money仍然是20。说明A读到了脏数据。
    A                        B
                             begin
                    update table set money = 200 where id = 2
select money from table where id = 2
                           rollback

读已提交和不可重复读
为了解决脏读的问题,可以将事务隔离级别调整到“读已提交”,这种隔离级别下,事务A只能读到事务B提交后的数据,但是这种隔离级别虽然解决了脏读的问题,但是无法解决可重复读的问题,即在事务A中,两次执行相同的读取语句,读到的内容却是不一样的。举例如下
      A                        B
      begin                       begin
                    update table set money = 200 where id = 2
select money from table where id = 2
                           commit
select money from table where id = 2
     commit

事务A中第一次select时,读到的值是20,第二次再执行select时,读取到的值是200。这就是不可重复读。

可重复读
为了解决不可重复读的问题,可以将事务隔离级别调整到“可重复读”,这种隔离级别下,可以保证在同一个事务中只会读取到当前事务对数据的修改,其他事务修改的数据不会影响到当前事务的任何一次读取。还是上面的例子,事务A两次select读取到的结果都是20,即可重复读.

幻读
可重复读虽然解决了不可重复读的问题,但是仍然存在幻读的问题。

错误的说法
对于幻读的解释,大多数博客中都是有问题的,甚至《高性能mysql》中,也没有详细解释幻读的问题
我们先来看看网上出现最多的幻读的解释,务必注意,这种解释是错误的:
       A                        B
       begin                      begin
select money from table where id > 2
                           inser into table values(3,30)
                              commit
select money from table where id > 2
       commit

网上多数观点认为,当A进行范围查询时,B在其中插入一条数据,A再次执行该范围查询是,就会比第一次查询时多出来B刚才插入的那条数据,像幻影一样,所以出现了幻读。
为什么这种说法是不对的呢?
从实践上看,直接去msql中试试就会发现,其实A连个执行的查询结果仍然是一样的,并不会出现幻读的现象。
从原理上看,可重复读是靠MVCC(多版本并发控制)保证的,该模式下,保证事务只能读取到当前事务开启之前已经提交的事务进行的修改以及当前事务本身对数据的修改。按照这个定义,上述实验中的B事务并不会影响到A的读取。

真正的幻读
那么什么事真正的幻读呢?来看下面的例子
A                        B
       begin                      begin
select money from table where id > 2
                           inser into table values(3,30)
                              commit
update table set money = 0 where id > 2
select money from table where id > 2
       commit

在B事务提交之后,A事务第二次select之前,先进行一次update操作,然后A再次执行select时,id=3的行就会出现,而且money的值是0.出现了幻读。

出现幻读的原因
MVCC只对读有效,对写操作无效,由于update是写操作,所以为更新B已经插入的id=3的行,将money更新成0,此时id=3的行被A事务(当前事务)修改了,所以A事务中第二次select时,是可以看到被当前事务修改(update)的数据的,所以id=3的行会出现在select的结果中,这就是幻读出现的原因。

串行
串行将所有的事务一个接一个的进行,不存在多个事务同事进行的情况,所以串行的事务隔离级别不会出现上面提到的脏读、不可重复读、幻读等任何一种问题。代价是,严重影响了数据库的性能。

事务隔离级别的选择
事务隔离级别需要根据具体的业务场景来选择,并没有哪一个级别是万能的。
有些场景下,甚至根本不需要事务,这时候,也许MyIsam引擎才是最合适的。
Oracle的默认事务隔离级别是读已提交,而mysql的默认事务隔离级别是可重复读,根据也无需要,可以把mysql的隔离级别调整到“度已提交”。
“读未提交”和“串行”这两种隔离级别因为脏读和性能的问题,业内用的很少。

mysql事务隔离级别、脏读、幻读的更多相关文章

  1. MySQL进阶15--TCL事务控制语言--建立结束事务/设置断点--默认隔离级别--脏读/幻读/不可重复读

    #TCL事物控制语言 : /* Transaction control language : 事物控制语言 事务: 一个或者一组sql语句组成一个执行单元,这个执行单元要么全部执行,要么全部不执行; ...

  2. [51CTO]新说MySQL事务隔离级别!

    新说MySQL事务隔离级别! 事务隔离级别这个问题,无论是校招还是社招,面试官都爱问!然而目前网上很多文章,说句实在话啊,我看了后我都怀疑作者弄懂没!本文所讲大部分内容,皆有官网作为佐证,因此对本文内 ...

  3. 查询mysql事务隔离级别

    查询mysql事务隔离级别 查询mysql事务隔离级别 分类: DB2011-11-26 13:12 2517人阅读 评论(0) 收藏 举报 mysqlsessionjava   1.查看当前会话隔离 ...

  4. MySQL事务隔离级别测试实例

    https://www.cnblogs.com/huanongying/p/7021555.html MySQL事务隔离级别 事务隔离级别 脏读 不可重复读 幻读 读未提交(read-uncommit ...

  5. Mysql事务-隔离级别

    MYSQL事务-隔离级别 事务是什么? 事务简言之就是一组SQL执行要么全部成功,要么全部失败.MYSQL的事务在存储引擎层实现. 事务都有ACID特性: 原子性(Atomicity):一个事务必须被 ...

  6. MySQL事务隔离级别 解决并发问题

    MySQL事务隔离级别 1. 脏读: 骗钱的手段, 两个窗口或线程分别调用数据库转账表,转账后未提交,对方查看到账后,rollback,实际钱没转. 演示方法: mysql默认的事务隔离级别为repe ...

  7. 在?MySQL事务隔离级别了解一下?

    事务的四大ACID 属性:Atomicity 原子性.Consistency 一致性.Isolation 隔离性.Durability 持久性. 原子性: 事务是最小的执行单位不可分割,强调事务的不可 ...

  8. MySQL事务隔离级别(二)

    搞清楚MySQL事务隔离级别 首先创建一个表 account.创建表的过程略过(由于 InnoDB 存储引擎支持事务,所以将表的存储引擎设置为 InnoDB).表的结构如下: 为了说明问题,我们打开两 ...

  9. MySQL事务隔离级别(一)

    本文实验的测试环境:Windows 10+cmd+MySQL5.6.36+InnoDB 一.事务的基本要素(ACID) 1.原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做 ...

随机推荐

  1. XIV Open Cup named after E.V. Pankratiev. GP of SPb

    A. Bracket Expression 直接按题意模拟即可. 时间复杂度$O(n)$. #include<stdio.h> #include<algorithm> #inc ...

  2. CentOS更新yum源

    CentOS更新yum源 1.备份 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup 2.下载 ...

  3. Mysql的Error 1364

    在安装mysql 5.5.8的最后一步,应用安全配置时, 弹出错误对话框, Error Nr.1364 authentication_string 解决办法: 1.暂时不要关闭该窗口,cmd命令,执行 ...

  4. OpenJudge Trans

    #include<iostream>#include<cstdio>#include<algorithm>#include<cmath>#include ...

  5. 通过 jdbc 分析数据库中的表结构和主键外键

    文章转自:http://ivan4126.blog.163.com/blog/static/20949109220137753214811/ 在某项目中用到了 hibernate ,大家都知道 hib ...

  6. pig hive hbase比较

    Pig 一种操作hadoop的轻量级脚本语言,最初又雅虎公司推出,不过现在正在走下坡路了.当初雅虎自己慢慢退出pig的维护之后将它开源贡献到开源社区由所有爱好者来维护.不过现在还是有些公司在用,不过我 ...

  7. 如何抓取电商的数据 &amp&semi; Python

    如何抓取电商的数据 & Python https://www.zhihu.com/question/40720286 https://www.zhihu.com/question/382455 ...

  8. Razor视图基本语法

    <!--Razor C#--> @for (int i = 0; i < 10; i++) {     <baobao>good</baobao> } &lt ...

  9. Codeforces Round &num;369 &lpar;Div&period; 2&rpar; E&period; ZS and The Birthday Paradox 数学

    E. ZS and The Birthday Paradox 题目连接: http://www.codeforces.com/contest/711/problem/E Description ZS ...

  10. input文本框在div中居中

    {display:block;margin-left:auto;margin-right:auto;}