重新整理 mysql 基础篇————— 事务隔离级别[四]
前言
简单介绍一下事务隔离的基本
正文
Read Uncommitted(未提交读)
这个就是读未提交。就是说在事务未提交的时候,其他事务也可以读取到未提交的数据。
这里举一个例子,还是前一篇的例子。
假如一个张表A=500,B=300,(500,300)有一个事务a和一个事务b,a事务是给A增加100,然后给B减少100。b事务是给B减少100,给A增加100。
假如步骤如图所示。
-
A 读取到的数据是500。
-
B读取到的数据是300。
-
B读取到的数据是200。
-
A读取到的数据是600
假设a先提交,b后提交。那么就是b事务提交的最后的结果,A为700,B为200。
反过来,如果是b提交,而a后提交,那么就是a最后提交的结果,A为600,B为100。
这个时候是3步骤就出现问题了,因为读取为未提交的事务。
Read Commited(提交读)
一个事务只能看见自己所做的修改,也就是说一个事务在提交之前,所做的修改其他事务看不见。
这样同样会存在问题。
比如说,A B C 分别是10 11 12,有两个事务,a是给A加一,b是两次执行,C=A+B。
-
C=A+B 那么C就是21。
-
A=A+1 那么A就是11
-
A 事务进行提交,那么A就是11了。这个时候b事务可以读取到A。
-
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
执行过程如下:
因为是可重复读,那么第四步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,然后执行下一个。
结
下一节,隔离的实现方式。