快照读、当前读、幻读和加锁规则

一 一致性读

  1. 一致性读,也就是一致非锁定读,也可以称为快照读,其实就是普通的读取即普通 SELECT 语句。其中普通的 SELECT 操作不包括 select ... lock in share mode,select ... for update。
  2. 所谓的快照读是指,在执行 SELECT 语句的时候,会生成一个快照。
  3. 对于可重复读隔离级别,快照会在事务中第一次 SELECT 语句执行时生成,只有在本事务中对有数据变更才会更新快照。因此,第一次 SELECT 之前已提交事务的变更你可以看到;如果已执行了 SELECT,那么其它事务数据,你SELECT是看不到的。
  4. 对于读提交隔离级别,每次读取都会重新生成一个快照,读取只承认在语句启动前就已经提交完成的数据。

     可重复读隔离级别下,一致性读是通过 MVCC 和 undo log 来实现的。

二 当前读

  1. 更新数据都是先读后写的,而这个读,只能读当前的值,称为“当前读”(current read)。 
  2. select ... lock in share mode、select ... for update、insert、update、delete 都是当前读。
  3. 以 update 为例,假设一个事务 A 修改了数据,如果不是当前读,事务 B 对同一行记录的变更会导致事务 A 的变更。
  4. 事务 A 修改一行记录的时候会添加 next-key 锁,事务 B 需要等待事务 A 释放 next-key 锁。

三 幻读

      1 幻读指的是一个事务在前后两次查询同一个范围的时候,后一次查询看到了前一次查询没有看到的行。

      2 在可重复读隔离级别下,普通的查询是快照读,是不会看到别的事务插入的数据的,幻读只有在“当前读”下才会出现

      当前读出现的幻读是通过对行记录添加 next-key lock 来解决幻读问题的。

四 加锁规则

     原则 1:加锁的基本单位是 next-key lock。希望你还记得,next-key lock 是前开后闭区间。

     原则 2:查找过程中访问到的对象才会加锁。

     优化 1:索引上的等值查询,给唯一索引加锁的时候,next-key lock 退化为行锁。

     优化 2:索引上的等值查询,向右遍历时且最后一个值不满足等值条件的时候,next-key lock 退化为间隙锁。

      一个 bug:唯一索引上的范围查询会访问到不满足条件的第一个值为止。

五 参考文档

      https://dev.mysql.com/doc/refman/5.7/en/innodb-consistent-read.html

      https://dev.mysql.com/doc/refman/5.7/en/innodb-locking-reads.html

      https://time.geekbang.org/column/article/75659

猜你喜欢

转载自blog.csdn.net/jack1liu/article/details/106931988