关系型数据库的数据隔离级别Read Committed与Repeatable Read

一、背景

数据库隔离级别会影响到我们的查询,本文试图以生产中的示例,给你一个直观的认识。

所谓,理论要结合实践,才能让我们理解得更加透彻。

另外,隔离级别的知识面很大,本文也不可能俱全,下面给出本文要阐述的目标:

二、目标

  • Read Committed与Repeatable Read的区别
  • 实际编程中的使用场景
  • 什么是Phamtom
  • 什么是Write Skew

三、隔离级别

1、可重复读

可以重复读的意思是,在同一个事务中,多次读取同一条记录,返回的数据是相同的;不会因为其他的事务修改它而变化。

必须要先理解这个默认隔离级别,才好反过来理解读已提交的级别。

最后,在你实际的应用中,要决定是否降低隔离级别。(以我实际的使用经验看,降低到读已提交级别,不仅符合程序的要求,而且提升了数据库的性能)
我们都知道,隔离级别越低,数据库的读写性能就越高,所谓“鱼与熊掌不可兼得”~~

下面摘引一个示例:

-- 事务A查询主键ID=7的姓名,返回是Aaron
session1> BEGIN;
session1> SELECT firstname FROM names WHERE id = 7;
Aaron-- 事务B查询主键ID=7的姓名,返回是Aaron
-- 随后,把它修改为Bob,最后提交事务
session2> BEGIN;
session2> SELECT firstname FROM names WHERE id = 7;
Aaron
session2> UPDATE names SET firstname = 'Bob' WHERE id = 7;
session2> SELECT firstname FROM names WHERE id = 7;
Bob
session2> COMMIT;-- 事务A二次查询主键ID=7的姓名,返回仍然是Aaron
session1> SELECT firstname FROM names WHERE id = 7;
Aaron
session1> COMMIT;

上述的过程与结论好理解,在实际编程中,你一定要考虑,现实场景会是需要如此吗?

如果更新换成账户余额、库存和积分等变化频繁的场景呢。。。

把问题先留在这里,我们继续另外一个问题:

  • 因为 Phamtom 而导致的 Write Skew现象

再举一个示例:
在这里插入图片描述
重复演示一遍,什么是可重复读的隔离级别。。

那么怎么会导致幻影Phamtom呢?

所谓幻影是指第一次查询的时候没有它,而更新的时候,却把它更新成功了。

在这里插入图片描述
事务A,期望是更新Alice/Bob/Carol这三个人的积分+1
当事务B,新增了一个人Frank,其积分也大于740。
结果,事务A按更新条件(score > 740)执行,导致不在期望中的Frank也被更改了。

这就是Write Skew。
换句话说,可重复读,虽然可以避免查询的可重复,但是它解决不了幻影带来的写倾斜Write Skew。

  • 怎么解决幻影现象
    批量更新记录,更新条件是上一步查询出来的记录ID集合。
select * from gamer where score >= 740;
# 100
# 101
# 102
# 103
update gamer a set a.credit = credit + 1 where a.id in (100,101,102,103);-- 不要使用区间比较
update gamer a set a.credit = credit + 1 where a.score >= 740;

2、读已提交

和可重复读相比,它会读取到其他事务提交的记录。

这里,以第一个示例进行修改举例。

-- 事务A查询主键ID=7的姓名,返回是Aaron
session1> BEGIN;
session1> SELECT firstname FROM names WHERE id = 7;
Aaron-- 事务B查询主键ID=7的姓名,返回是Aaron
-- 随后,把它修改为Bob,最后提交事务
session2> BEGIN;
session2> SELECT firstname FROM names WHERE id = 7;
Aaron
session2> UPDATE names SET firstname = 'Bob' WHERE id = 7;
session2> SELECT firstname FROM names WHERE id = 7;
Bob
session2> COMMIT;-- 事务A二次查询主键ID=7的姓名,返回变成了Bob
session1> SELECT firstname FROM names WHERE id = 7;
Bob
session1> COMMIT;

同一个事务的两次相同查询,返回的记录会因为其他事务的提交而变化。

那么它的适用场景是什么呢?

  • sql乐观锁更新的自旋

sql乐观锁更新,不外乎以下两种写法:

-- version机制, 先查询出version, 每次更新记录的时候,version值自动加1
select version as old_version from gamer where id = 101;
# 1
int new_score = 1000;
update gamer a set a.score = {new_score}, a.version = a.verson + 1 
where id = 101 and version={old_version}
-- 实际执行语句:
update gamer a set a.score = 1000, a.version = a.verson + 1 
where id = 101 and version=1;-- 更新条件, 将查询出来的score作为查询条件,保证在更新的时候,被更新的值是前面查询出来的值。
select score as old_score from gamer where id = 101;
# 980int new_score = 1000;
update gamer a set a.score={new_score} where id = 101 and score={old_score};
-- 实际执行语句:
update gamer a set a.score=1000 where id = 101 and score=980;

这里有一个问题,如果更新的并发度比较大的时候,会出现频繁的更新失败。
所以,建议你在更新的外围,使用一个自旋。

下面是一个java语言实现的伪代码:

// 自旋3次
boolean flag = false;
int newScore = 1000;
for (int i = 0; i < 3; i++)
{// 每次自旋,都再次查询数据库,因为其他事务可能修改该记录。所以隔离级别必须是读已提交。// 如果是可重复读,这里的自旋就没有任何意义。Game game = gameService.findById(101);falg = gameService.update(game.getScore(), game.getId(), newScore);//或者 falg = gameService.update(game.getScore(), game.getId());// 更新成功,提前退出if (flag) {break;}
}

四、查询和设置事务隔离级别

show variables like 'transaction_isolation';
show variables like 'tx_isolation';

在这里插入图片描述

-- 设置全局事务级别为 READ-COMMITTED
set global transaction isolation level read committed;

阿里云的RDS,支持修改该参数,不过需要重启生效。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/245043.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python+OpenCV实现最强自动扫雷

文章目录 准备实现思路窗体截取雷块分割雷块识别扫雷算法实现关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②Python实战案例③Python小游戏源码五、面试资料六、Python兼职渠道 用…

平价的开放式耳机怎么选?推荐几款平价好用的耳机,亲测对比

是不是也在为如何在有限的预算内找到一款性价比高的开放式耳机而烦恼呢&#xff1f;别着急&#xff0c;小编为你精心挑选了几款平价好用的开放式耳机&#xff0c;并亲自进行了对比测试&#xff0c;在这个音乐时代&#xff0c;不需要花大价钱就能拥有高品质的音乐体验&#xff0…

YOLOv8 区域计数 | 入侵检测 | 人员闯入

大家好,昨天的 YOLOv8 新增加了一个功能,区域计数,用这个功能我们能实现很多的任务, 比如入侵检测,流量统计,人员闯入等,使用方式也非常的方便,但是一定要使用最新版的 YOLOv8 代码(2023/12/03更新的代码)。 低版本是不具备这个功能的,上面是演示效果。 使用非常的方…

多要素环境监测一体机-生态环境的守护者

随着人类活动的不断增加&#xff0c;环境问题日益凸显。为了实时了解环境状况&#xff0c;保护生态环境&#xff0c;一款多要素环境监测一体机应运而生。 一、实时监测&#xff0c;掌握环境动态 WX-CSQX12 多要素环境监测一体机能够实时监测空气质量、温湿度、噪音、风速等多…

为什么SSL证书要设有有效期?

在当今的数字化时代&#xff0c;网络安全已经成为了每个企业和个人都必须关注的重要问题。为了保护网站数据的安全传输&#xff0c;SSL证书应运而生。然而&#xff0c;你是否注意到&#xff0c;SSL证书并不是永久有效的&#xff0c;而是有一定的有效期。那么&#xff0c;为什么…

2.1 Linux C 编程

一、Hello World 1、在用户根目录下创建一个C_Program&#xff0c;并在这里面创建3.1文件夹来保存Hellow World程序&#xff1b; 2、安装最新版nvim ①sudo apt-get install ninja-build gettext cmake unzip curl ②sudo apt install lua5.1 ③git clone https://github.…

低噪声,带内置 ALC 回路的双通道均衡放大器,应用于立体声收录机和盒式录音机的芯片D3308的描述

D3308 是一块带有 ALC 的双通道前置放大器。它适用于立体声收录机和盒式录音机。采用 SIP9、SOP14 的封装形式封装。 主要特点 带内置 ALC 回路的双通道均衡放大器 低噪声: VNIl.OuV(典型值)。开环电压增益高: 80dB (典型值)工作电源电压范围宽: 通道间的…

【JVM系列】Class文件分析

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

园区无线覆盖方案(智慧园区综合解决方案)

​ 李经理正苦恼头疼的工业园区数字化改造项目。近年企业快速增长,园区内Argent工业设备激增,IT部门应接不暇。为确保生产系统稳定运行,IT管理团队经过反复摸索,决定进行全面的数字化升级。然而改造之艰巨远超想象——混杂的接入环境、复杂的专线部署、长达数月的建设周期,种种…

电脑监控软件是隐藏安装吗?

电脑监控软件通常可以隐藏安装。 这种类型的软件可能是通过企业管理者下载或拷贝到员工的电脑上的。因为程序包比较小&#xff0c;安装过程也比较简单&#xff0c;所以操作起来也很方便。 企业管理者的这种操作基本上是为了更好管控公司的电脑运行、防止员工恶意泄露公司的机密…

LeetCode | 572. 另一棵树的子树

LeetCode | 572. 另一棵树的子树 OJ链接 我们需要判断两棵二叉树是否相同&#xff0c;如果再判断的的时候不同我们就直接返回false&#xff0c;否则就返回true然后再检查左子树和右子树里面是否存在subRoot子树~~ bool isSameTree(struct TreeNode* q, struct TreeNode* p) {…

树莓派Python程序开机自启动(Linux下Python程序开机自启动)

前一阵子用python编写了一个驱动I2C程序读写屏幕&#xff0c;输出IP的小程序&#xff0c;程序编好后需要树莓派使能程序开机自启动。其实这些方法对任何Linux系统都适用。 方法一&#xff1a;此方法的缺点是不进入默认pi的账号&#xff0c;甚至不开hdmi开启桌面的话&#xff0…