08事务到底是隔离还是不隔离的笔记

本文详细解析了数据库事务隔离级别的实现原理,包括一致性读视图和当前读的概念。一致性读视图用于支持读提交和可重复读,通过快照读实现事务间数据的隔离。可重复读通过记录事务启动时的系统状态来实现,而读提交则在每次查询时生成新的视图。当前读则用于获取最新的数据,涉及行级锁的使用。此外,还介绍了二阶段锁协议在事务操作中的作用,以及在实际场景中可能出现的问题和解决方案。
摘要由CSDN通过智能技术生成

事务隔离的具体原理实现

创建时间:2021年11月12日15:16:58

编辑时间:2021年11月13日19:23:27 (最后一问错误,重新解释了下)


——————————————————————————————
要素:串联一致性读、当前读和行锁

事务隔离原理——一致性读视图

问:什么是视图?

答:

一个指代视图虚拟表,调用时执行查询语句并生成结果;

一个指代MVCC的一致性读视图,用于支持读提交和可重复读的实现。

问:介绍下一致性读视图(快照)的生成原理。

答:是基于全库生成的。每个事务会严格按照诞生顺序向系统申请一个递增式事务id,各个事务对数据的操作会产生对应的数据版本(row),并标记该版本的事务id(row trax_id),流程如下例图所示:
在这里插入图片描述

(箭头相当于undo log的回滚段)各版本的数据通过回滚段和当前最新数据计算得来。

问:可重复读怎么利用快照实现的?

答:可重复读要求视图内容为启动那一刻所有已提交的事务以及自己后续的操作内容,所以在可重复读事务启动时,会记录当前系统所有处于未提交状态的事务,组成数组,其中最小值为低水位,当前系统已知最大的事务值+1为高水位,组成视图。

举例:全库事务id有1、2、3、4、5、6、7

活跃事务id有[3,4,5],则低水位为3,高水位为8

此时,

低水位以前的数据可见,低水位到高水位之间,处于活跃的事务是不可见的,非活跃的事务可见的;

高水位之后的事务不可见;

——————————————————————

(1、2、3、4、5、6、7)

1、2可见;3、4、5不可见;6、7可见;7之后的事务不可见。

——————————————————————

问:与可重复读相比,读提交是怎么实现的?

答:简单类比,读提交是在每次执行sql前都会计算出新的视图。(PS:对读提交来说,start transaction with consistent snapshot等同start transaction)

问:什么时候清理这些数据版本?

答:(个人未知)

更新——当前读

问:什么是当前读?哪里用到?

答:为了保证MVCC下的事务操作不丢失数据更新,所以更行数据时采用当前读——获取要更新的最新的记录;其根本原因是表结构没有对应的行数据,也没有事务id,但是MySQL的8.0版本已经支持可重复读的逻辑了(DDL不会终止程序)。

此外,对select也可进行当前读操作

-- 共享锁
 select k from t where id=1 lock in share mode;
 -- 排他锁
 select k from t where id=1 for update;

实战题

问:下图事务B查询结果是多少?为什么?

在这里插入图片描述
事务B快照时获取的k值是1,但更新时的读是当前读,获取的k值是事务C修改后的值——2,所以k被赋予2+1,此时对于事务B的快照内容来说,k即为3

假如事务C没有立刻提交,而是在事务B的更新语句发起后再提交,那根据二阶段锁协议,此时占据该行数据写锁的事务C还没释放,事务B要进行当前读,需要获取读锁,因此会等待写锁释放。

问:简单说下一致性读、当前读、二阶段锁协议之间的关系。

答:一致性读原理确保可重复读、读提交事务的实现,更新数据时只能是当前读,防止数据更新丢失,但要先遵循二阶段锁协议。

问:有个场景,开启一个事务后,需要对特定数据进行更新,在同一个事务内发现旧值没变化,求原因。

start transaction with consistent snapshot;

update t set k = 3 where  k = 2;

SELECT * from t where  k = 3;

commit;

答:当事务启动命令为即时性(start transaction with consistent snapshot),则可能在执行本事务第一个update语句之前,存在其他事务对该数据进行了更新,导致本事务的更新判定条件无法命中,由于本事务还没释放便进行了一次查询,得出的结果是数据没变化(启动事务的命令执行时便产生了一致性读视图),所以就产生了更新失效的错觉。

(例子为立即启动事务视图的命令,如果是start tansaction的话,则在执行第一条sql时才会生成视图)

解决思路:

改成开启事务后先检查符合条件的数据条数,然后更新时判定影响条数是否等于查询条数,不等于则结束事务,再发起一次事务。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陈镇坤27

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值