mysql-事务隔离级别

mysql-事务隔离级别

事务的隔离级别比我们想象的还要复杂,在sql标准中一共定义了4中隔离级别,每一种都定义了事务所做的的修改,比如哪些事务内和事务间是可见的,哪些是不可以见的。下面是四种事务的隔离级别:

1、读未提交(Read UnCommited)

               在此事务内已经修改了数据,但是没有提交事务,对其他事务都是可见的,其他事务可以读取到刚才那个修改数据没有提交的事务。我们称为这种为 “脏读”。这种可能导致很多问题出现,在一般的实际应用中很少使用。

2、读已提交(Read Commited) 

              这个事务隔离级别是大多数数据库默认采用的事务隔离级别,但是mysql没有默认采用,在一个修改的事务,还没有提交事务,对于其他事务内的操作都是不可见的。也就是一个事务只能看到已经提交事务的数据。这种我们称为“不可重复读”,因为2此读取的时候可能得到不同的结果。

3、可重复读(Repeatable Read) 

             可重复读解决了脏读的问题,该隔离级别保证在一个事务里读取的数据记录是一致的,但是理论上又会出现幻读的问题发生,比如我们在读取某个访问记录,另外一个事务正好插入数据了。之前的那个事务再次读取会产生幻行。值得庆幸的是mysql采用的Innodb 和XtraDB存储引擎通过多版本进行并发控制的,来解决这个幻读问题。

4 可串行化(Serializable) 

      强制事务进行串行化执行,读取的每一行都加锁,避免幻读现象产生可能导致锁的争夺和超时消耗,是事务隔离级别最大的一个,一般在实际的项目中很少用到。

 多版本并发控制

      mysql 的大多数数据库事务存储引擎大多不是简单的行级锁,基于提高并发性考虑,一般采用多版本控制实现,不仅仅是mysql ,oracle也是如此,可以认为多版本并发控制是行级别锁的变种,大多情况下避免了加锁的操作,因此开销更低,大部分实现非阻塞的读操作,和写操作也只锁定必要的行。多版本并发控制通过保存数据在某个时间点的快照来实现的,也就是说,不管执行多长时间,每个事务看到的数据是一致的,根据事务的开始时间不同,每个事务对应同一张表,同一时刻可能看到的数据不一样。实现版本并发控制包括乐观并发控制和悲观并发控制。

     InnoDB存储引擎是通过每一行记录后面保存两个隐藏的列来实现的,默认采用可重复读隔离级别。这两列,一列保存行的创建时间,另外一列保存行的过期时间,时间不是系统时间 而是系统版本号,每当开始一个事务系统版本号就会开始递增,事务开始的时刻的系统版本号作为事务的版本号,与用来查询到的每行记录的版本号进行做对比,在可重复读的隔离级别的下版本并发控制解决幻读的问题:

       SELECT(查询) 

     innodb 会根据只查询早于当前事务查询的版本号的数据行并且行的过期时间(删除版本号)要么未定义要么大于当前版本号才能返回查询结果。

     INSERT(插入)

 InnoDB为新插入的每一行记录保存当前系统版本号作为行版本号

  UPDATE(更新)

InnoDB为插入一行新记录,保存当前版本号作为开始时间的版本号,同时,保存当前版本号到原来行的结束列作为行删除标识。

 DELETE (删除)

  Innodb 为每一行要删除的行,保存当前版本号作为行删除标识。

总结

     InnoDB存储引擎使每一行记录保存额外的两个系统版本号列,使大多读操作都可以不加锁,这样设计使读操作非常简单,性能很好防止了幻读的情况发生,但是每一行要维护2列系统版本号需要额外的空间,并且也要进行检查工作及一些维护的操作。

猜你喜欢

转载自qq466862016.iteye.com/blog/2261081