我们知道在 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 条件定位的记录是当前读而非快照读。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于