粗谈MySQL事务的特性和隔离级别

网上对于此类的文章已经十分饱和了,那还写的缘由很简单——做为本身的理解笔记。数据库

前言

​  此篇文章做为本身学习MySQL的一些我的理解,使用的引擎是InnoDb。首先先讲讲事务的概念,在《高性能MySQL》第三版中其对事务的描述是这样的:性能

事务就是一组原子性的SQL查询,或者说一个独立的工做单元。若是数据库引擎可以成功地对数据库应用该组查询的所有语句,那么就执行该组查询。若是其中有任何一条语句由于崩溃或其余缘由没法执行,那么全部的语句都不会执行。学习

​​  换句话说,事务就是一个总体单位,里面的SQL语句不会单独执行,就像某些商品通常,由多个组件组成,可是我绝对不单独卖组件,要买就买整个商品,否则就不卖。.net

​​  简单的理解了事务以后,还须要知道事务的目的就是为了保证数据的正确性和一致性,那么为此则诞生出其4个特性(后面再细讲),而为了实现这四个特性又须要许多具体的实现,其中就包括为了隔离性而产生的四个隔离级别,这四种隔离级别又产生了三个问题脏读不可重复读幻读),这就是其大体的关系,接下来让咱们来看看这些具体究竟是个什么东西。3d

1 四种特性(ACID)

​​  提及事务的特性,那确定张口就来ACID,然而除了ACID四个字母以外咱们仍是须要说点其余东西的。code

​​  原子性(Atomicity):意思是说一个事务应看成为一个不可分割的最小单位,整个事务的操做要么所有执行成功要么所有不执行,像原子同样不可分割(别跟我提夸克),这里的执行是指执行成功,若是有一个操做执行失败了那么就所有不执行,这也是咱们平时见到的回滚。blog

​​  一致性(Consistency):书上给出的意思是事务老是从一个一致性的状态跳到另外一个一致性的状态。个人理解是在涉及到的数据范围内是守恒的,也就是说,总体的数据是不变的,拿万能的转钱例子来讲,A帐户转给B``200元,那么由AB组成的这个数据范围来讲数据并无发生改变(-200+200=0)只是数据的组成方式变化了,因此是从一个一致性状态—>另外一个一致性状态。事务

​​  隔离性(Isolation)一般来讲,一个事务的操做对于其余的事务的不可见的,也就是说通常而言事务都是独立的。可是这跟数据库的隔离级别有关,除了某个(没错,就是你——读未提交同窗)隔离级别以外,其余的都是不可见的,而这种事务可见的级别不多用到,因此说的是'一般来讲'。ci

​​  持久性(Durability)事务一旦完成,那么该事务引发的数据变化将永久生效,不会改变(除非被另一个事务改动)。不过书上提到这其实跟实行的策略相关,但这貌似就有点走远了(是的,我不懂!)。get

​​  以上就是事务的四种特性,然而其中隔离性的实现则是要看数据库的隔离级别。

2 数据库的隔离级别

​​  在MySQL中隔离级别有四种,每种隔离级别对应的事务体现不一样,可能出现的问题也各自不一样。

​​  未提交读(read uncommited):在这个隔离级别中,在一个事务执行的操做就算不提交也能被其余的事务看到。在这个级别中一个事务可能读到其余事务还没提交的脏数据,便可能出现脏读。以下图所示,序号表示执行的顺序。

img

​​  能够看到,在界面1的事务中往test表插入了一条数据,此时就算还没提交在页面2的另外一个事务中也能够看到提交的数据。

​​  提交读(read commited)在一个事务提交以后,其余事务才能够看到事务的修改。此隔离级别可能会出现同一个事务中执行相同的查询却读到不一样的数据,即不可重复读nonrepeatable read),另未提交读也可能出现不可重复读。例子以下

img

​​  可重复读(repeatable read)这是MySQL的默认隔离级别在事务开始的时候会保存此刻的一个快照(这里啰嗦一下,其实是开启事务后执行第一条语句的时候准备的快照,准备快照的方法则是记录当前事务的版本号,没有进行数据的复制,不明白事务版本号或隐藏字段的能够看看MySQLMVCC),而后接下来这个事务的全部数据读取都是从这个快照读,因此不会出现不可重复读的状况,可是仍是有可能出现幻读。意思就是读取的是快照表数据不会变化,可是进行写操做如更新的时候更新的数量可能会跟预期的不一样。如图

img

​​  能够看到,在界面1插入一条记录而且提交以后,界面2仍是没有读到这个提交的数据,由于他是从事务开始时的快照表读取的因此天然是读不到的,可是在进行更新操做的时候则是更新了意料以外的记录,这就是一种幻读的现象。

​​  可串行化(serializable):意思就是事务要一个一个来,若是在一个事务中进行读操做,那么其余事务在该事务完成前只能进行读操做;若是进行写操做,那么其余事务的操做都进入等待(直到当前事务提交)。这种级别就能够防范目前出现的脏读、不可重复读、幻读等现象。如图

img

上图演示的是事务读时,其余事务不可写,下图是写时不可操做。

img

3 三个问题—脏读、不可重复读、幻读。

​​  这是采起事务的不一样隔离级别可能产生的几个问题,在上面隔离级别已经说起到了,可是为了不混淆仍是单独拿出来。

  • 脏读:指在一个事务中读到了其余事务还没提交的脏数据,发生在读未提交级别。
  • 不可重复读:在一个事务中一样的查询可能出现不一样的结果,发生在读未提交、读提交级别。(我的以为不必特地去理解为叫什么叫不可重复,容易混淆)
  • 幻读:在一个事务中进行写操做的时候修改的数量跟预期的数量不一样,例如修改到了以前查询不出来的数据。

​​  再啰嗦一些不可重复读幻读的区别:能够理解为不可重复读是那条记录的字段值改变了,例如id1的记录中name的两次值都不一样;而幻读则是数量上的不一样,例如我查询的时候共有2条记录,可是执行修改操做的时候却更新了3条。






参考:《高性能MySQL》,http://www.zsythink.net/archives/1233/

或许我只是简单的想被承认。

相关文章
相关标签/搜索