达梦数据库系列—32.多版本并发控制MVCC

embedded/2024/10/22 16:33:04/

        在多版本控制以前,数据库仅通过锁机制来实现并发控制。数据库对读操作上共享锁,写操作上排他锁,这种锁机制虽然解决了并发问题,但影响了并发性。

        DM 数据库基于物理记录和回滚记录实现行级多版本支持,数据页中只保留物理记录的最新版本,通过回滚记录维护历史版本,所有事务针对特定的版本进行操作。

两个隐藏字段

在DM8中,索引组织表会为每个使用索引组织表的表添加三个隐藏字段,分别是:TRXID、ROLPTR和ROWID。隐藏字段TRXID、ROLPTR用于实现多版本并发控制(MVCC)。

物理记录

TID

RPTR

回滚记录

TID

RPTR

RPTR 指向操作生成的undo log的物理地址

TID是事务号

  1. TRXID(本行数据的事务版本):记录最近更新或插入这条记录的事务ID。当一个事务对表中的一行数据进行修改时,TRXID会被设置为当前事务的ID值。删除操作在内部也被当作一次更新,并在行的特殊位置设置一个删除标记。
  2. ROLPTR(回滚指针,指向上一次事务ID):指向被写在Rollback Segment中的Undo Log记录。当事务回滚时,可以通过ROLPTR找到之前版本的数据。该行记录上所有的旧版本,在Undo Log中通过链表的形式组织,将多个版本的值串联在一起,方便其他事务查找时保持事务的一致性。
  3. ROWID(隐藏单调自增ID):随着新行插入而单调递增的隐藏行ID。索引组织表使用聚集索引,数据存储以聚集索引字段的大小顺序进行存储。当表面没有主键或唯一非空索引时,索引组织表会自动生成一个隐藏主键产生聚集索引。ROWID与MVCC无关。

Undo Log一方面可用于MVCC读时构建记录,在MVCC多版本控制中,通过读取Undo Log的历史版本数据可以实现不同事务版本号都拥有自己独立的数据版本。

可见性原则

实现多版本控制的关键是可见性判断,找到对当前事务可见的特定版本数据。

每个事务都记录在活动事务视图中,记录系统中即将产生的事务号 NEXT_TID。

1.物理记录的 TRXID 等于当前事务号,说明是本事务修改的物理记录,物理记录可见;

2.物理记录的 TRXID 不在活动事务表中,并且 TRXID 小于 NEXT_TID,物理记录可见;

3.物理记录的 TRXID 包含在活动事务表中,或者 TRXID 大于等于 NEXT_TID,物理记录不可见;

如果当前物理记录不可见,则按照该记录的ROLLPTR指示,找到其上一个版本,并再次判断该版本可见性,直到找到可见版本为止。

事务隔离级别

脏读

脏数据所指的就是未提交的已修改数据,一个事务在提交前,另一个事务可以看到结果,就会发生脏读。

不可重复读

一个事务先后读取同一条记录,两次读取的数据不同,我们称之为不可重复读。

幻读

一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种现象就称为幻读。

DM 数据库支持三种事务隔离级别:读未提交、读提交和串行化。默认是读提交。

设定事务为读提交隔离级:

  SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

设定事务为读未提交隔离级:

  SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

设定事务为串行化隔离级:

  SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

读未提交(Read Uncommitted)

读未提交情况下,可以读取到其他事务还未提交的数据,多次读取结果不一样,出现了脏读。

读已提交(Read Committed)

读已提交情况下,无法读取到其他事务还未提交的数据,可以读取到其他事务已经提交的数据。

可重复读(REPEATABLE

可重复读是Innodb的默认隔离级别,使用MVCC实现,可重复读情况下,不会出现脏读,不会读取到其他事务已提交的数据,多次读取结果一致,即可重复读。但是可能导致“幻读”。

MVCC的快照策略+undolog解决不了幻读问题,mysql中可以用select where for update(间隙锁)的办法对表的部分数据锁定,间隙锁的目的是为了防止其他事务在这个范围内插入新的数据,从而保证事务的隔离性,解决幻读问题。

串行化(SERIALIZABLE

串行化严格的事务顺序控制在串行化隔离级别下,‌数据库管理系统会严格控制事务的执行顺序,通过加锁来实现的,‌如果一个事务正在修改数据,‌其他试图select或修改同一数据的事务将被阻塞,‌直到第一个事务完成。

串行化隔离级别通过限制并发访问,‌避免了读未提交、‌读已提交和可重复读隔离级别中可能出现的问题,‌如脏读、‌不可重复读和幻读。‌这是因为串行化隔离级别确保了每个事务在执行期间,‌其他事务不会对其造成干扰。

当一个串行化事务试图更新或删除数据时,而这些数据在此事务开始后被其他事务修改并提交时,DM 数据库将报“串行化事务被打断”错误。

如果系统中存在长时间运行的写事务,并且该长事务所操作的数据还会被其他短事务频繁更新的话,最好避免使用串行化事务。


http://www.ppmy.cn/embedded/87412.html

相关文章

ChatGPT:宽列数据库是什么?

ChatGPT:宽列数据库是什么? 宽列数据库(Wide-Column Store)是一种 NoSQL 数据库,它的设计灵感来自于 Google 的 Bigtable。宽列数据库适用于处理大规模的分布式数据存储,特别是在需要高性能读写、灵活的数据…

服务器是否需要安装杀毒软件

现在许多服务器都自带杀毒软件,这些软件可以更好的保护服务器的安全,防止使用者的信息被泄露。那么服务器是否需要杀毒软件,这里壹基比小鑫就和大家一起看看。 一、为什么要装服务器杀毒软件? 装服务器杀毒软件主要是保护服务器安…

CSA笔记9-磁盘管理(2)

分区挂载 挂载:将该文件系统中的内容与指定的目录关联起来,使得你可以通过该目录来访问文件系统中的文件和目录。 mount 命令用来挂载文件系统 #挂载/dev/sda1和/dev/sda2 [rootlocalhost ~]# mkdir test{1..2} [rootlocalhost ~]# ll test1 te…

UPLOAD-LABS靶场[超详细通关教程,通关攻略]

---------------------------------------- 靶场环境: 下载链接: https://codeload.github.com/c0ny1/upload-labs/zip/refs/heads/master 使用小皮集成环境来完成这个靶场 将文件放到WWW目录下就可以进行访问 ------------------------------------…

python静态方法以及静态方法引用类属性和类的实例属性

在Python中,静态方法是与类相关联的一种方法,但它不接收类或实例的引用作为第一个参数。这意味着它们不能访问或修改类的状态,即类属性或实例属性。静态方法可以通过staticmethod装饰器来定义。 静态方法的使用场景通常是那些不需要访问类或…

Java-Swing开发-003布局

文章目录 布局管理器常用布局BorderLayoutFlowLayoutGridLayoutGridBagLayout 布局管理器 Swing里负责布局的玩意,方便调整组件位置,一般是container里设置 1.JFrame默认布局为BorderLayout 2.JPanle默认布局为FlowLayout 常用布局 BorderLayout 东…

C++类与对象-六大成员函数

默认成员函数就是用户没有显式实现,编译器会⾃动⽣成的成员函数称为默认成员函数。⼀个空类编译器会默认⽣成8个默认成员函数。本文只介绍其中6个,C11增加两个函数见后续博客。 目录 一、构造函数 1.1 概念 1.2 特性 1.3 使用举例 1.4 初始化列表 1…

针对datax-web 中Swagger UI接口未授权访问

application.yml 添加以下配置 实现访问doc.html 以及/v2/api-docs 接口时需要进行简单的校验 swagger:basic:enable: trueusername: adminpassword: 12345 配置重启后再进行相关访问则需要输入用户名和密码