SQL事务隔离级别之Read Committed

115 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第17天,点击查看活动详情

✔个人主页:Mr.Darcy8的掘金主页

🎉欢迎关注👀点赞👍收藏⭐留言📝以及交流人生哲理🎈学习心得🎁

引入

上期我们介绍了一个最低的隔离级别——Read Uncommitted。其允许了脏读的发生:

即并行事务中,一个事务可以读取另一个事务更新但未提交的数据

本期我们在了解read uncommitted的基础上,了解一下他的“孪生兄弟”——Read Committed

1.不可重复读

和之前一样,我们先来了解另外一个东西:不可重复读(Non Repeatable Read)

其大意是,一个多次读取同一数据的事务,如果在其读取过程中有其他并行事务修改了该数据,则其读取的同一数据会不一致。

我知道大家对晦涩的解释没有兴趣,其实俺也一样。我们来举个例子:

事务A一直在读取数据库某表中“姓名”为“小明”的“性别”,一般情况下得到的结果一直是“男”,但突然有个事务B(是并行事务,和A一起运作),把“小明”的“性别”改成“女”了。这可以吗?当然可以,因为没人能确定小明到底是男是女。但是问题在于,事务A的隔离级别如果是Read Committed,那它就会把这个修改结果读过去,此时在事务A返回的结果中“小明”既有“男”,也有“女”。这就是个问题了,数据不一致了该信哪个?总不可能既是男的又是女的orz

所以为了避免这个问题,在Read Committed隔离级别下,我们不能进行多次读取的操作(就像错误的名字“不可重复读”一样),读一次数据就必须完成所需要的业务了,再读可能就会出错。

2.数据库案例

举了形象的例子,我们接下来就看一看实际sql语言命令下的“不可重复读”案例。

假设我们用两个终端连接了同一个mysql数据库,按照如下的时刻进行两个终端的事务:

时刻事务A事务B
1SET TRANSACTION ISOLATION LEVEL READ COMMITTED;SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
2BEGIN;BEGIN;
3SELECT * FROM s WHERE name = "小明"; #此时返回"男"
4UPDATE s SET gender = "女" WHERE name = "小明";
5COMMIT;
6SELECT * FROM s WHERE name = "小明"; #此时返回"女"
7COMMIT;

我已经将运行结果也打在了表格里。第3时刻事务B读取的是男,第6时刻却读取出了女,出现数据不一致的问题。

所以在设置Read Committed隔离级别的时候,我们一定要注意,是不是该事务所读取的数据都能一次性读取完,不能出现重复读取同一个数据的情况。如果非得重复读取同一个数据,还请换个高一点的隔离级别,牺牲一下计算机的性能和效率,换来业务的不出错吧~

新人上路,欢迎互相帮扶~Mr_darcy8的掘金主页

可以的话给咱点个赞呗💖