暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

达梦MVCC的实现原理

得一阳阳 2024-12-18
155

一、什么是MVCC

MVCC,全称 Multi-Version Concurrency Control,即多版本并发控制。是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务内存。

MVCC可以维护一行数据的多个版本,做到即使有读写冲突也能不加锁。在数据库并发场景中无非就三种读读、读写、写写。读读不需要并发控制,写写冲突是采用锁的方式解决,达梦采用的就是悲观锁,读写冲突就是用MVCC来解决的。MVCC只是一个标准,没有具体的实现方法,不同的数据库有不同的实现方法。在DM数据库中是基于物理记录和回滚记录实现行级多版本支持,数据页中只保留物理记录的最新版本,通过回滚记录维护历史版本,所有事务针对特定的版本进行操作。

MVCC 具有以下优点:

提高并发性能:读操作不加锁,所以读操作不会阻塞写操作,写操作也不会阻塞读操作,有效地提高数据库的并发性能。

降低死锁风险:由于无需使用显式锁来进行并发控制,MVCC可以降低死锁的风险。

MVCC的前提条件:

1、MVCC只在READ COMMITTED(已读提交)这隔离级别下适用,DM只支持数据库修改为读提交和可串行化。

2、MVCC实现原理是由俩个隐藏字段、undo日志、读视图来实现的。

二、隐藏字段

在DM中,除了一些行数据之外,还有一些隐藏的的字段,它们是在DM内部使用的,默认情况下是不会显示给用户查看的,如果想看可以额外指定列ROWID,TRXID。

select *, ROWID,TRXID from TEST.USERS ;

image.png

以下是DM数据库的三个隐藏字段,分别是:TRXID、RPTR和ROWID。隐藏字段TRXID、RPTR用于实现MVCC,ROWID是表中没有主键或唯一索引时,索会自动按ROWID来产生聚集索引树来存储数据。

image.png

三、undolog

Undo 日志是 MVCC 能够得以实现的核心所在。不同的事务或者相同的事务对同一个记录做修改,undo log会成为一条记录版本的线性表,也就是事务链,链表的头部是最新的旧记录,链表的尾部是最早的旧记录,

举个例子:

比如我们先插入一条记录

事务1:insert into users(id,name) values (1,'张三');

image.png

因为是第一条记录它没有上一个版本,所以回滚指针RPTR是NULL。

事务2:update  users set name = '李四' where id =1;

接下来我们开启第二个事务,将张三改为李四。在事务2修改该行数据时,数据库会对该事务号TID=1加排它锁,在达梦中是采用TID锁进行锁事务号来代替行锁。然后把该行数据拷贝到 undo log 中作为旧记录,即在 undo log 中有当前行的拷贝副本,并将回滚指针指向拷贝到 undo log 的副本记录,即表示我的上一个版本就是它,事务提交后,释放锁。如下图,张三的记录存在undo log中。

image.png

此时,我们开启一个事务3,将李四改为王五,修改该行数据时,跟上面一样数据库也先将该事务行加TID锁,然后把该行数据拷贝到 undo log 中,作为旧记录,发现该行记录已经有 undo log 了,那么最新的旧数据李四作为链表的表头,插在该行记录的 undo log 最前面,最早的旧数据张三做链表的尾部,如下图:

事务3:update  users set name = '王五' where id =1;

image.png

通过 RPTR 和 Undo日志 的配合,DM能够有效地管理事务的一致性和隔离性,从而提供了高并发环境下的读取一致性和事务隔离性。

四、可见性原则

在DM中,判断事务的可见性是通过读视图来实现的。事务进行快照读操作的时候生产的一个读视图,在该事务执行的快照读的那一刻,会生成数据库系统当前的一个快照,记录并维护系统当前活跃事务的ID。它主要包含三个字段:TRX_ID、NEXTID和MIN_ACTIVE_ID。

image.png

通过视图 v$trx 可以看到这几个字段

select * from v$trx;

image.png

那么其可见性算法具体是如何计算判断的呢?

1、首先比较TRX_ID < MIN_ACTIVE_ID, 如果小于,那肯定是已经提交了,当前事务能看到这个TRX_ID 所在的记录,如果大于等于进入下一个判断

2、接下来判断 TRX_ID 是否大于等于 NEXTID, 如果大于等于则代表TRX_ID 所在的记录是在事务开始生成后才出现的,那对当前事务肯定不可见,如果小于则进入下一个判断。

3、最后判断TRX_ID 是否在活跃事务之中,如果在并且等于当前事务号,说明是本事务修改的记录,那么该记录肯定可见;如果在并且不等于当前事务号,则代表该事务生成时刻,其他事务还在活跃,还没有Commit,那么其修改的数据,我当前事务是看不见的;如果不在活跃事务列表中,则说明,在事务生成之前就已经Commit了,你修改的结果,我当前事务是能看见的。

总结

MVCC在高并发下起到至关重要的作用,理解MVCC的原理是开发和DBA必不可少的知识点,希望通过本文能够让读者加深对MVCC的理解。

达梦社区技术https://eco.dameng.com

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论