暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL的当前读和快照读演练

小度do 2021-10-24
853

        首先执行如下图1中的操作,创建一张测试表,添加两条数据,并查看结果(图2)。


图1

图2

        测试的MySQL版本是8.0, 表默认使用的是InnoDB存储引擎。接下来开启两个MySQL命令窗口客户端,A中开启一个事务并添加一条数据,不提交事务。然后在B客户端分别执行不同方式的查询操作。

图3

图4

        图4中的第一个查询语句正常返回了结果。第二、第三个查询并没有立刻返回查询结果,而是处于阻塞状态。而且第二个查询过了一段时间返回了等待超时。

        图4的第一个查询我们便称为快照读,也可以称为非阻塞读。实质上我们对于MySQL的每个操作都会维护一个事务ID(按照操作的时间线自增长),像第一个查询方式在读取数据过程中,会获取小于当前事务ID的数据。

        图4的第二、第三个查询方式为当前读,当前读是需要读取数据的最新记录,而且会有加X锁的操作,所以二和三两个查询会阻塞,因为这两个查询会根据select语句的查询范围获取数据的锁,但是新添加的那条数据由于没有提交事务,所以就不会释放锁,导致了他们处于阻塞状态。

图5

        下面的操作类似于上面的操作过程,只不过查询的语句中加了条件,然后就不会阻塞了。解释一下,原因是当前读获取锁的范围是查询结果包含的数据,而图7中的查询条件时id<2,这个表中添加的最新数据的ID已经远远大于2了,所以不会有锁的冲突,也就不会阻塞了。那如果条件改成id>2呢?答案是一定会阻塞的。

图6

图7

        一个简单的案例了解当前读、快照读的基本概念,需要注意的是在数据库隔离级别为串行读时,快照读会变成当前读,以上的演示是基于MySQL默认隔离级别-可重复读。

        这个小演练中涵盖了MySQL的一些比较核心的处理手法,像MVCC机制、gap锁机制,这些才是实现当前读、快照读的核心原理。

文章转载自小度do,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论