MySQL的快照读(MVCC)和当前读(行锁、间隙锁、Next-Key Lock)解决幻读

2021/7/14 19:05:57

本文主要是介绍MySQL的快照读(MVCC)和当前读(行锁、间隙锁、Next-Key Lock)解决幻读,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

文章目录

  • 前言
  • 一、快照读(snapshot read)
  • 二、当前读(current read)

前言

MySQL的innoDB引擎虽然拥有标准的四级隔离级别,不过它有其他数据库不同,就是在可重复读 RR 级别下面已经可以防止幻读的发生。,所谓幻读,指的是事务A执行过程中,由于事务B并发插入删除了多条新数据,事务A两次读数据的行数不一样,出现了“虚幻”的新纪录(phantom,幽灵)。

一、快照读(snapshot read)

在快照读(snapshot read)的情况下,MySQL通过MVCC(多版本并发控制)来避免幻读。

原理:将历史数据存一份快照,所以其他事务增加与删除数据,对于当前事务来说是不可见的。

快照读,读取的是记录的可见版本 (有可能是历史版本),不用加锁。主要应用于无需加锁的普通查询(select)操作。

快照读sql语句如下

select * from table where ?;

二、当前读(current read)

在当前读(current read)的情况下,当前读,读取的是记录的最新版本,并且会对当前记录加锁,防止其他事务发修改这条记录。MySQL通过next-key lock来避免幻读。

当前读sql语句如下:

select * from table where ? lock in share mode; 
select * from table where ? for update; 
insert; 
update; 
delete;

InnoDB有三种行锁的算法:
1、Record Lock 行锁:单个行记录(索引记录)上的锁。
1、Gap Lock 间隙所:间隙锁,锁定一个范围,但不包括记录本身。GAP锁的目的,是为了防止同一事务的两次当前读,出现幻读的情况。
1、Next-Key Lock1+2,锁定一个范围,并且锁定记录本身。对于行的查询,都是采用该方法,主要目的是解决幻读的问题。

因为InnoDB对于当前读 行的查询都是采用了Next-Key Lock的算法,锁定的不是单个值,而是一个范围(GAP)。
假设索引a有1,3,5,8,11,其记录的GAP的区间如下:是一个左开右闭的空间(原因是默认主键的有序自增的特性,结合后面的例子说明)

(-∞,1],(1,3],(3,5],(5,8],(8,11],(11,+∞)

select * from t where a = 3 for update;

那么锁住的范围有 (1,3)3,(3,5] 即 当前行+两边的间隙 (1,3],(3,5],
这些范围的行数据和索引都被锁住,所以可以防止insert或者delete 带来的幻读

但是注意,对于可重复读默认使用的就是next key lock,但是对于“唯一索引” ,比如主键的索引,next key lock会降级成行锁Record Lock 即仅锁住索引本身,而不会锁住一个区间。



这篇关于MySQL的快照读(MVCC)和当前读(行锁、间隙锁、Next-Key Lock)解决幻读的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程