图解SQL事务隔离等级

来源:互联网 发布:人工智能 杂志 中文 编辑:程序博客网 时间:2024/05/18 03:36

图解SQL事务隔离等级

ACID,指的是数据库事务正确执行的四个基本要素:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。

其中对于我们这些使用数据库而不是开发数据库的人来说,最有必要深入研究的估计就是”隔离性“了。

到了MySQL等具体的数据库软件,事务的隔离性要求被分为多个等级,下面我们依次深入讲解,各等级要解决和防范的问题,以及它又会带来哪些新的麻烦。

1.写法约定

我们用T1和T2来表示下面将要出现的两个事务,它们要执行的动作写法如下:

  1. r1[x] – T1读取变量x的值
  2. w2[y=1] – T2写入变量y,值为1
  3. c1 – T1提交事务
  4. a2 – T2丢弃事务

2.脏写

T1对变量进行了修改,但在它提交或者丢弃该事务之前,T2又对这个变量进行了修改。

脏写

  • {db in state A}
  • w1[x=1]
  • {db in state B}
  • w2[x=2]
  • {db in state C}
  • a1

假如x初始值为0,T1写入了x=1,T2写入了x=2,此时x的临时结果为2,T1回滚,那么x回复为初始值0,那么当T2提交时x仍为0。

又假如说,我们的数据库存在一致性限制x=y,考虑下面出现的情形:

  • w1[x=1]
  • w2[x=2]
  • w2[y=2]
  • c2
  • w1[y=1]
  • c1

T1的操作是x=1,y=1;而T2的操作是x=2,y=2,而上面的结果为x=2,y=1,破坏了数据的一致性限制x=y。

显然,脏写会直接破坏了事务的原子性和一致性,对于绝大部分关系型数据库来说,即使是最低隔离等级也要保证绝不能发生。

3.脏读(与是否回滚无关)

读取了被其他并行事务修改过但还未提交的变量(跟前面一样,未提交数据统一称为“脏”数据)。

脏读

直观上来说,事务2读取了一个“有问题”的数据,它随着事务1的回滚将不复存在,如果事务2基于它做了其他一系列的动作,将有很大可能破坏数据的一致性。

这里再强调一下,即使不发生事务的回滚操作,脏读依然无处不在。

比如说,我们的数据库存在一致性限制x=y,考虑下面出现的情形:

  • w1[x += 100]
  • w2[x *= 2]
  • w2[y *= 2]
  • w1[y += 100]

事务1想给x和y都加100,事务2想给x和y都乘2。假如一开始x和y的值都等于100,那么最后x=400,y=300。x=y的一致性限制再次被破坏。

4.不可重复读和读偏斜

不可重复读指的是,某个事务两次读取同一变量,但前后得到的值并不相等,是因为在这两次读取发生的时间内,存在另一个事务提交了对该变量的修改。

它与脏读的重要区别在于,第二次读取的变量是否已经被另一个事务所提交。如果还没提交就是脏读,如果已经提交就是不可重复读。

不可重复读

读偏斜比不可重复读要更宽泛些,比如我们的数据库存在一致性限制a=b,但出现了下面的情况:

读偏斜

虽然我们的事务1没有两次读取同一变量,事务1读取到的a和b的值并不相等,违反了一致性限制。因此,我们可以认为不可重复读是读偏斜的一种特殊情况。

5.幻读

某一事务两次执行同一个select操作,但返回的行集合却不一样了。原理有点像刚才的不可重复读,但这里强调的是select操作是比单纯地读精确的某一行更加复杂的条件匹配操作,很可能返回多个数据行。

幻读

6.MySQL的事务隔离级别

MySQL提供了4种事务隔离级别,其中最常用的InnoDB存储引擎的默认隔离级别为可重复读。

事务隔离级别 脏读 不可重复读 幻读 读未提交(read-uncommitted) 是 是 是 已提交读(read-committed) 否 是 是 可重复读(repeatable-read) 否 否 是 串行化(serializable) 否 否 否
原创粉丝点击