RR 级别下 update 操作的是快照读还是当前读?

本贴最后更新于 1671 天前,其中的信息可能已经物是人非

我们知道在 RR 级别下,重复的 select 操作,读取的值都会是一致的。即便在两次 select 操作的中间,有一个事务 B 修改了值,但是在事务 A 中 select 读取的值还是一致的。

那么如果是 update 操作呢?之前在网上看到一篇博客说 RR 级别下,CAS 操作是没有意义的。因为 version 值在一个事务中都是一致不变的。于是我有了疑惑打算自己来验证一下。

验证想法

RR 级别下 update 操作的是快照读还是当前读?

准备数据

准备了以下简单的表数据结构。

sid name sex version
1 zhangsan 0 0
2 lisi 1 0

验证思路

  • 通过 version 值做 CAS 版本,修改 sex 值。
  • A 事务先执行,通过 sleep 5 秒延迟最后的 update 操作。
  • B 事务后执行,通过 sleep 1 秒使得它虽然事务 id 更大,但比 A 事务更早执行完成。
  • 查看 A 事务通过 version 字段 CAS 操作能否修改成功 sex 值。
  • 如果能修改成功即 update 语句 where 条件定位的是快照读,反之则定位的是当前读。

事务脚本

事务 A

事务 A 先执行,事务 id 小

begin;

SELECT version from student where sid = 1;   
// 当前获取的version为0
SELECT SLEEP(5);

SELECT version from student where sid = 1;
// 此时获取的version依然为0
update student set sex = 1 , version = version +1 where sid = 1 and version = 0;
// 修改行数为0,修改操作失败,说明version已经不是0了,
commit;
事务 B

事务 B 后执行,事务 id 大

begin;

SELECT version from student where sid = 1;
// 当前获取的version为0
SELECT SLEEP(1);

SELECT version from student where sid = 1;
// 此时获取的version依然为0
update student set sex = 2 , version = version +1 where sid = 1 and version = 0;
// 修改成功,此时当前version为1  
commit;

验证结果

事务 A 的 update 操作失败,说明 update 中的 where 条件定位的记录是当前读而非快照读。

  • MySQL

    MySQL 是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,目前属于 Oracle 公司。MySQL 是最流行的关系型数据库管理系统之一。

    677 引用 • 535 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • valarchie

    嗯 lock in share mode,for update,delete,insert,update 都是当前读。

  • 其他回帖
  • 2501224066

    加锁啊

    1 回复