前言

简单介绍一下事务隔离的基本

正文

Read Uncommitted(未提交读)

这个就是读未提交。就是说在事务未提交的时候,其他事务也可以读取到未提交的数据。

这里举一个例子,还是前一篇的例子。

假如一个张表A=500,B=300,(500,300)有一个事务a和一个事务b,a事务是给A增加100,然后给B减少100。b事务是给B减少100,给A增加100。

重新整理 mysql 基础篇————— 事务隔离级别[四]-LMLPHP

假如步骤如图所示。

  1. A 读取到的数据是500。

  2. B读取到的数据是300。

  3. B读取到的数据是200。

  4. A读取到的数据是600

假设a先提交,b后提交。那么就是b事务提交的最后的结果,A为700,B为200。

反过来,如果是b提交,而a后提交,那么就是a最后提交的结果,A为600,B为100。

这个时候是3步骤就出现问题了,因为读取为未提交的事务。

Read Commited(提交读)

一个事务只能看见自己所做的修改,也就是说一个事务在提交之前,所做的修改其他事务看不见。

这样同样会存在问题。

重新整理 mysql 基础篇————— 事务隔离级别[四]-LMLPHP

比如说,A B C 分别是10 11 12,有两个事务,a是给A加一,b是两次执行,C=A+B。

  1. C=A+B 那么C就是21。

  2. A=A+1 那么A就是11

  3. A 事务进行提交,那么A就是11了。这个时候b事务可以读取到A。

  4. C=A+B,那么C等于22了。

这种情况要看是否符合你的需求。比如说,一个数据库就是一直来计算一些数的总值的。那么是符合你的需求的。

但是如果是第四步,C=C+B,那么是可能不符合你的需求的。因为C要计算的是C=A+B+A。也就是C=2*A+B,因为A中间变换了,那么结果不符合预期是不符的。

这种看需求。

repeatable 可重复读

该级别保证了同一个事物多次读取同样记录的结果一致。

比如说,上面Read Commited(提交读)的例子中,两次读取A都是一致的,在同一个事物中,多次读取结果不变。

这里可能有人会提出另一个疑问,比如说有两个事务,同样是事务a和事务b。

疑问如下:

比如A=1

执行过程如下:

重新整理 mysql 基础篇————— 事务隔离级别[四]-LMLPHP

因为是可重复读,那么第四步A中,A还是1,所以最终A结果是2。

是啊,这样不就出问题了吗?是的,如果数据库像这么简单,那么的确出问题了,因为数据库在执行过程中会做一些判断,会给数据加上锁,有了锁那么可能上面第2步,就会阻塞,而去执行第四步了。

锁,后面介绍。

serializable 可串行化

serializable会在读取的每一行加上锁,强制事务串行执行。这里需要注意的是串行化,并不是说事务一条一条执行。

比如说,事务a只修改A数据,然后事务b只修改B数据,这时候依然是并发的,因为他们数据并不冲突。

串行化,因为加了锁,所以会变得串行。比如事务a修改A然后修改B,事务b修改B然后修改了A。假如因为a修改了A,给A加了锁,后面事务b修改了B给B加了锁。故而a事务在等待B释放锁,b事务在等A释放锁。故而系统会检查到死锁,故而只能执行A或B,然后执行下一个。

下一节,隔离的实现方式。

06-13 08:28