三分钟小短文:一致性非锁定读与一致性锁定读

飞天小牛肉

共 2443字,需浏览 5分钟

 ·

2021-09-21 09:45

台上三分钟,台下三小时,兄弟们,今天咱们花三分钟了解下数据库中的两种读(select)操作:一致性非锁定读一致性锁定读

一致性非锁定读

一致性非锁定读是什么?这里我先给出一个最最最简单的解释:一致性非锁定读就是读快照

快照即当前行数据之前的历史版本,每行记录可能存在多个历史版本,或者说每行记录可能有不止一个快照数据,一般我们将这种技术称为 行多版本技术。而由于一个行记录可能对应着多个快照(历史版本),为此不可避免地会带来一系列的并发问题,如何解决这些并发问题,就是所谓的 多版本并发控制(MVCC),当然,这不是本文的重点。

在不同事务隔离级别下,读取的方式不同。只有在事务隔离级别 READ COMMITTED 和 REPEATABLE READ(默认)下,InnoDB 存储引擎才会使用非锁定的一致性读。并且,即使都是使用非锁定的一致性读,它俩对于快照数据的定义也各不相同

  • 在 READ COMMITTED 事务隔离级别下,总是读取行的最新版本;如果行被锁定了,非一致性读不会因此去等待行上锁的释放,而是去读取该行版本的最新一个快照,如下图所示:

    img
  • 在 REPEATABLE READ 事务隔离级别下,对于快照数据,非一致性读总是读取事务开始时的行数据版本

这么说可能还不是很好理解,举个例子,这个时候又得掏出我们经典的 user 表了(滑稽),表中包含三个字段 id、username、age,已存在一行记录:

id = 1, username = 'Jack', age = 20;

1)第一步,我们开启一个事务,执行如下语句:

事务 1:
 begin;
 select * from user where id = 1;

2)可以看到,第一个事务并没有提交,这时,我们开启第二个事务模拟并发,执行如下语句:

事务 2:
 begin;
 update user set id = 100 where id = 1;

3)在第二个事务中,将表中 id 为 1 的记录修改为了 id=100,但是事务同样没有提交(即此时 id = 1 的行记录被事务 2 加上了行锁)。这时如果在第一个事务中再次读取 id 为 1 的记录,那显然还是 1 对吧:

事务 1:
 select * from user where id = 1;

4)接着,我们再来提交下第 2 个事务中所作的修改:

事务 2:
 commit;

由于当前 id = 1 的数据被修改成了 100,也就是说,当前 id = 100 的行记录拥有了一个 id = 1 的历史版本

5)这个时候,再去事务 1 中读取 id 为 1 的记录,在 READ COMMITTED 和 REPEATABLE 事务隔离级别下得到结果就不一样了:

  • 对于 READ COMMITTED 的事务隔离级别,由于事务 2 已经提交了,也就是说 id = 1 的行记录没有被事务 2 锁定,所以就会去读取该行的最新版本,即 id = 100,So, 在 READ COMMITTED 的事务隔离级别下,此时查询 id = 1 的结果是 Empty Set;

  • 而在 REPEATABLE READ 事务隔离级别下,非一致性读总是读取事务开始时的行数据版本。也就是说,在事务 1 刚开始的时候,id = 1 的数据行是什么样,现在读到的就是什么样的:

可以结合下面这张图来回顾下上述的过程:

一致性锁定读

其实从名字上也能看出来,非一致性锁定读适用于对数据一致性要求不是很高的情况,比如在 READ COMMITTED 隔离级别下,即使行被锁定了,非一致性读也可以读到该行版本的最新一个快照。也即,非锁定读机制极大地提高了数据库的并发性

而一致性锁定读适用于对数据一致性要求比较高的情况,这个时候我们需要对读操作进行加锁以保证数据逻辑的一致性。

InnoDB 存储引擎对读操作支持两种一致性锁定读方式,或者说对读操作支持两种加锁方式:

  • SELECT ... FOR UPDATE,对于读取的行记录加一个 X 排它锁,其他事务不能对锁定的行加任何锁
  • SELECT ... LOCK IN SHARE MODE,对于读取的行记录添加一个 S 共享锁。其它事务可以向被锁定的行加 S 锁,但是不允许添加 X 锁,否则会被阻塞住

So,如何用大白话解释一致性锁定读?上面这两条特殊的 select 语句就是一致性锁定读!一致性锁定读就是给行记录加 X 锁或 S 锁!

简单不?

我是小牛肉,长风破浪会有时,小伙伴们下篇文章再见 👋


  • 博主小硕在读,深耕 Java,目前在维护一个教程类仓库 CS-Wiki「Gitee 官方推荐项目,现已 1.9k+ star,仓库地址:https://gitee.com/veal98/CS-Wiki」,公众号上的文章也会在此同步更新,欢迎各位前来交流学习

  • 准备春招秋招的小伙伴可以参考我的这个论坛项目 Echo「Gitee 官方推荐项目,现已 1.1k+ star,仓库地址:https://gitee.com/veal98/Echo」。配套教程正在同步更新中,公众号后台回复 "Echo" 即可免费获取。

浏览 10
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报