事务到底是隔离的还是不隔离的?

  在之前很长一段时间内,对事务的隔离机制都仅仅局限在“背”这个字上,但是对于底层如何实现解决的可重复读和幻读等一系列问题还是云里雾里。这篇文章,主要还是讲述的是在不可重复读隔离级别下,多事务之间实现的一致性读和当前读以及多事务版本并发控制的细节原理,以便于加深对mysql隔离机制的理解,当然后面还会引入对mysql锁、索引机制等等的问题,慢慢来吧!

  首先我们先以当前事务隔离级别为可重复读级别,在这个隔离级别中,每个事务在操作时,好像都和其他事务完全没有任何干系。。我一开始对这个一致性读的理解是,既然是隔离那是不是每一个事务都需要copy一份当前数据快照来为这个作为隔离基础,但是想了下,感觉太夸张了,这数据量得多大,因为要copy那么多份,后来看了一位技术大佬的专栏,才恍然大悟,不禁感叹道mysql的设计者是如此的聪明“绝顶”!

  既然用copy数据的方式太浮夸,那么是否可以利用一种操作日志的方式来代表每一次操作时他能够读到的数据并且允许读取的数据,就是说当前这个事务在操作时,其他还未提交的事务所产生的日志当前事务是无法读取的,这样是不是就完成了隔离的操作,这个就是mysql事务隔离技术的宏观操作,当然,细节还是比较繁琐的。。

  按照可重复读的定义,一个事务启动的时候,能够看到所有已经提交的事务,而那些未提交的事务是不应该看见的,而这部分未提交的部分,需要被当前事务用一个数组记录下来。。

  可以认为一个事务会记录这些东西:已提交事务--》未提交事务--》还未开始的事务,当前事务所要读取的某一行数据如果它的事务id在中间(未提交事务),那么代表当前这个数据是应该被隔离的,也就是当前事务不应该看见的,而在左边(已提交事务),是属于可见范围内的,如果说当前事务读取到一个数据行trx_id,该id属于中间的,那么就继续往前查找,知道找到第一个属于左边范围的数据行,以该数据行作为当前事务所能看到的,这个也就是所谓的“一致性读”,除开一致性读之外,还有一个是当前读,就是必须读取到最新的数据,这个一般是发生在更新语句和加锁读语句时,当前需要读取或者更改的数据行必须要最新值!

  这里要说明的一点是,所有的事务都是在执行第一个语句时才启动,start transaction with consistent snapshot命令做的事就是在可重复读级别下,做到事务一开启就立马创建一个全事务内共享的视图,但是在RC级别下就不行了,因为RC级别只能是在每一次sql执行开始时建视图...其实想想,这也是为什么RC级别下,只能解决脏读而不能解决不可重复读的问题所在:

  例如有俩事务A、B,A开始执行事务未提交,此时B开启事务,ok,B读到第一条sql,开启一个视图,这个视图里A的数据还属于已提交事务--》未提交事务--》还未开始的事务中的未提交事务,因此只要A一直不提交,B就一直读不到A的数据,因此脏读解决,但是问题来了,只要A提交了事务,那么此时B的一条sql在创建视图时,A的数据处于已提交事务--》未提交事务--》还未开始的事务中的已提交事务,因此不可重复读问题产生!!而RR级别因为一旦视图产生就全事务内不变,因此不可重复读就避免了!!

posted @ 2019-09-16 00:42  Booker808  阅读(308)  评论(0编辑  收藏  举报