首页 > 编程知识 正文

mvcc实现原理,mvcc为啥会幻读

时间:2023-05-06 19:48:18 阅读:166592 作者:2238

mysql多版本并发控制快照读和当前领先的MVCC原理undo logReadViewMVCC实现的整体流程MVCC在RC和RR上的差异MVCC能解决幻读吗

数据库有三种方案:

读取-读取:没有问题,也不需要同时控制

读-写:有线进程的安全问题可能会导致事务分离问题,可能会遇到污读、幻读和不可重复的读取

写入:有线流程安全问题可能会导致更新丢失,例如第一类更新或第二类更新丢失

备注:第1类丢失更新:事务a撤销时,改写了已经提交的事务b的更新数据; 类别2的丢失更新:事务a覆盖事务b提交的数据,丢失事务b进行的操作

快照引线和当前引线

我现在正在读:

读取记录的最新版本。 此外,还必须阻止其他并发事务修改当前记录,读取的记录将被锁定

以下操作是当前读取:

select . lock in share mode,

选择…for update (独占锁定) )。

更新、插入和删除)。

快照引线

快照读的实现基于多版本控制(mvcc ),快照读可能不是数据的最新版本,而是以前的历史版本。 快照读操作假定隔离级别不是串行级别,而串行级别的快照读操作将缩减为当前读操作

未锁定的select操作是快照读取

MVCC原理还原日志主要分为两种:

插入还原日志

表示事务在insert新记录时生成的还原日志,仅在事务回滚时才需要该日志,并且可以在事务提交后立即丢弃

更新还原日志

事务执行update或delete时生成的还原日志; 除了回滚事务外,还需要读取快照。

表中有两个隐式字段:当前正在执行的事务的ID和指向上一条记录的指针

另一方面,例如,某个事务在人员表中插入了新记录。 假设name为xfdld,age为24岁,事务ID和回滚指针为空

nameage事务ID回滚指针xfdld 24 null,当前事务1将此记录的name更改为Tom

当事务1更改该行(记录)中的数据时,数据库首先会对该行施加独占锁

然后,将该行中的数据复制到还原日志中。 作为旧记录,在还原日志中有当前行的副本。 复制完成后,将该行name更改为Tom。 此外,将隐藏字段中的事务ID更改为当前事务1的ID。 默认值从1开始,然后递增,回滚指针指向复制到还原日志中的复制记录。 也就是说,表示我之前的版本就是那个。 事务处理

三.修改事务人员表相同记录,将age修改为30岁

当事务2更改行中的数据时,数据库也会锁定该行

然后,将该行数据复制到undo log,作为旧记录,如果发现该行记录中已经存在undo log,则将最新的旧数据作为链表的标题,插入该行记录的undo log的开头

该行age更改为30岁,隐藏字段中的事务ID更改为当前事务2的ID,并且回滚指针指向刚刚复制到还原日志中的复制记录

提交事务,解除锁定

ReadView ReadView是在事务执行快照读取操作时创建的视图,在事务执行快照读取操作时会生成数据库系统的当前快照,并且是系统的当前活动状态每个事务打开后,都会分配一个ID。 由于此ID会递增,因此最新的事务处理的ID值越大。)

ReadView主要用于判断可视性。 这意味着为该记录创建ReadView读取视图,以确定在事务执行快照读取时,当前事务可以看到哪个版本的数据。 当前事务可能是最新的数据,也可能是该行记录的还原日志中的某个版本的数据。

判断主要是将当前的事务ID与readview中的事务的ID进行比较

如果当前事务ID小于readview中的ID最小值,则当前事务将看到该记录

当前事务ID大于或等于ReadView的事务ID的最大值。 该记录在ReadView生成后出现,它对于当前的事务肯定是不可见的

否则,确定当前事务ID是否位于readview中,如果存在,则表示生成readview时事务仍处于活动状态,没有Commit,并且当前事务不可见。 如果没有,则表示事务在生成ReadView之前已提交,并且当前事务可见

MVCC实现的总体流程事务1事务2事务3事务4事务开始事务开始正在提交、正在进行快照读取、正在进行事务2的行中的数据的快照数据库为该行的数据生成读视图,假设当前事务ID为2,此时事务1和事务3为活动状态,事务4为事务2快照树

在我们的示例中,当前该行的当前数据的还原日志如下图所示,因为只有事务4修改了该行中的记录,并且事务2在执行快照读取之前提交了该事务。

当快照读取该行中的记录时,我们的事务2会将该行中记录的ID与readview中的事务ID进行比较,以确定当前事务2是否可以看到该记录的版本

使用事务ID 4与Read View一起进行,4表示

小于1,所以不符合条件,继续判断 4 是否大于等于5,也不符合条件,最后判断4是否是活跃事务, 最后发现事务4不在当前活跃事务列表中, 符合可见性条件,所以事务4修改后提交的最新结果对事务2快照读时是可见的,所以事务2能读到的最新数据记录是事务4所提交的版本。

MVCC在RC和RR下的区别

mvcc实现RC(读已提交)和RR(可重复读)是因为他们生成readview的策略不同:
在RR级别下,一个事务的对某条记录的第一次快照读会创建一个readview, 将当前系统活跃的其他事务记录起来,此后在调用快照读的时候,还是使用的是同一个readview,对之后的修改不可见;
在RC级别下,一个事务每次快照读都会创建一个readview, 可以看到之后的事务提交的更新

MVCC能否解决幻读

在当前读时,mvcc不能解决幻读,要结合next-key lock才能解决幻读
在快照读时,mvcc可以解决幻读的问题

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。