DM数据库事务、锁、多版本机制

一、事务:

概念:事务是指作为单个逻辑工作单元的一系列操作的集合。
(MySQL:一组数据操作执行步骤,这些步骤被视为一个工作单元,用于对多个语句进行分组,可以在多个客户机并发访问同一个表中的数据时使用,如果所有步骤正常,则执行,如果步骤出现错误或不完整,则取消。)
事务的开始: DM8没有提供显式定义事务开始的语句,第一个可执行的SQL语句隐含事务的开始;
事务的结束: 用户可以使用提交或回滚语句显式的结束一个事务,也可以使用隐式的方式结束一个事务。

1.1、隐式的事务结束:

当连接的属性设置为自动提交时,每执行一条语句提交事务;
(MySQL:5.7、8的版本默认隐式事务(自动提交);
可以手动开始事务:START TRANSACTION/BEGIN命令)

当连接的属性设置为手动提交,而DDL自动提交开关(DDL_AUTO_COMMIT)打开时,遇到任一DDL语句系统会自动提交该DDL语句及之前的DML操作;而当该开关关闭时,只有CREATE TABLESPACE和ALTER DATABASE两种DDL语句,物化视图刷新语句以及之前的DML和DDL操作会自动提交;
事务所在的程序正常结束和用户退出;
系统非正常终止时。

1.2、保存点:SAVEPOINT(Oracle、MySQL通用)

保存点:事务在执行中可以部分回滚到某个用户设置的保存点,在该保存点以前的操作有效,而以后的操作均会被回滚掉。
用户在事务内可以声明多个保存点,从而将一个大事务划分为几个较小的片段,用户在对事务进行回滚操作时,可以选择从当前执行位置回滚到事务内的任意一个保存点。
被部分回滚的事务依然处于活动状态,可以继续执行,用户可以使用savepoint命令创建保存点,使用rollback to savepoint命令回滚到指定保存点。

1.3、事务的状态和ID:

每个事务都有一系列状态,主要包括:

Not_start未启动
active活动
Lock_wait锁等待
Trx4_pre_commit预提交

解释:事务ID,也就是事务号,每个事务都对应一个唯一标识TRXID,初始化为0;
事务ID在该事务启动之后从IID(V$IID)系统自动分配。当事务提交或回滚后,该事务ID就会被重置。事务再次启动时,重新分配TRXID。

1.4、事务分类:

普通事务和虚事务:
虚事务是系统内部事务,不属于任何会话,始终驻留在事务系统中,用于回滚段清理。
活动事务和非活动事务:
非活动事务:TRXID为0且状态为Not_start的事务;
活动事务:TRXID大于0且状态为active、lock_wait的事务。
读写事务和只读事务:
数据库标准的事务的隔离级别:

隔离级别脏写脏读不可重复读幻读
读未提交Read Uncommitted不可能可能可能可能
读已提交Read Commited不可能不可能可能可能
可重复读Repeatable Read不可能不可能不可能可能
串行化Serializable不可能不可能不可能不可能

MySQL支持以上四种隔离级别,默认可重复读;
Oracle支持读已提交、串行化、自定义的Read Only三种级别,默认读已提交。
DM8支持读未提交、读已提交、串行化三种级别,可单独设置只读事务,但并不会改变原有的隔离级别,默认读已提交。
DMRWC的备机不允许设置串行化隔离级别。
隔离级别产生的问题:
脏读: 对于两个事物 T1,T2。T1 读取了已经被 T2 更新但还没有被提交的字段,之后,若 T2 回滚,T1 读取的内容就是临时且无效的。
不可重复读: T1 读取一个字段,然后 T2 更新了该字段,之后,T1 再次读取同一个字段,值就不同了。
幻读: T1 从一个表中读取了一个字段,然后 T2 在该表中插入了一些新的行,之后,如果 T1 再次读取同一个表,就会多出几行。
总结: 不可重复读和脏读的区别是,脏读是某一事务读取了另一个事务未提交的脏数据,而不可重复读则是读取了前一事务提交的数据。
幻读和不可重复读都是读取了另一条已经提交的事务,不同的是不可重复读的重点是修改,幻读的重点在于新增或者删除。

1.5、事务与会话:

一个事务只属于一个会话;
一般情况下一个会话上有一个事务,但自治事务会使一个会话上有多个事务。
通过将一个DMSQL语句块定义成自治事务,可以将该块中的DML语句和调用程序的事务环境隔离开。如此一来,该语句块就成为一个由掐事务启动的独立的事务,前一个事务称为主事务。在自治事务块中,主事务是挂起的,等待自治事务完成后,会话自动切换回主事务。
语法如下:
PRAGMA AUTONOMOUS_TRANSACTION;
自治事务一定要提交,否则报错。即使主事务rollback,并不影响自治事务的变化 。
例如:
CREATE TABLE test(c VARCHAR);

INSERT INTO testVALUES('主事务');

DECLARE

PRAGMA AUTONOMOUS_TRANSACTION;

BEGIN

INSERT INTO test VALUES('自治事务');

COMMIT; --一定要提交,否则会报错。

END;

/

ROLLBACK;

SELECT * FROM test;
行号 C


1 自治事务

二、锁:

2.1、锁概念:

锁是实现数据库并发控制的重要手段,可以保证数据库在多人同时操作时能够正 常运行。
周期:一般事务结束时释放锁。

2.2、锁模式:

共享锁(Shared lock),简称S锁
排他锁(Exclusive lock),简称X锁
意向锁:
解决解决共享锁和排他锁相容性查的问题;
意向共享锁:(Intent Shared lock),简称IS锁;
意向排他锁:(Intent Exclusive lock),简称IX锁;
锁相容矩阵:

ISIXSX
ISYYYN
IXYYNN
SYNYN
XNNNN

2.3、锁的类型分为三类:

表锁:
一般的,表上只上IS锁和IX锁,用于DML语句执行时,对表进行上锁,协调表级的并发访问,如果上S/X类型的表锁,必须显式调用相应的上锁语句。
字典锁, 用于防止在DML的过程中,访问对象的定义被修改。四种锁类型均采用。
TID锁, 每个事务(trx)启动时创建一把独占的TID锁,并持有到事务结束。S锁和X锁。
执行INSERT、DELETE、UPDATE 操作时,设置事务号到TID字段。这相当于隐式地对记录上了一把TID锁,
INSERT、DELETE、UPDATE 操作不再需要额外的行锁,避免了大量行锁对系统资源的消耗。
只有多个事务同时修改同一行记录时,才会产生新的TID 锁。同时多版本写不阻塞读的特性,SELECT 操作已经消除了行锁,因此DM8中不再有行锁的概念。
字典锁(DM8独有):
用于对数据字典信息的封锁,用于保护数据库对象的结构,如表、索引等的结构定义。通过字典锁减少DDL操作对DML操作的干扰,提高并发性能。
字典锁是一种多粒度的上锁机制,数据库对象按照“数据库-表空间-模式-表/视图”的顺序自上而下排列,这种层次结构可以图形化的表示为树。当操作某一数据字典对象时,自上而下进行封锁。
对象锁:
DM8 新引入的一种锁,通过统一的对象 ID 进行封锁,将对数据字典的封锁和表锁合并为对象锁,以达到减少封锁冲突、提升系统并发性能的目的。
表锁
表锁用来保护表数据的完整性。
DML语句执行时,对表进行上锁,协调表级的并发访问。
隐含上IS,IX锁,X锁(列存储表)。
字典锁
防止在DML/DDL的过程中,访问对象的定义被修改。
四种锁类型均采用。
MySQL锁: 提供了全局锁、行级锁、表级锁。其中 InnoDB 支持表级锁和 行级锁,MyISAM 只支持表级锁
Oracle锁: 数据锁(TX、TM)、字典锁、内部锁与闩、分布式锁、并行告诉缓冲管理锁。

三、MVCC:

3.1、概念:

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

物理记录TIDRPTR

回滚记录:

回滚记录TIDRPTR

TID保存修改记录的事务号,RPTR保存回滚段中上一个版本回滚记录的物理地址。
更新之前的值保存在回滚记录中,回滚ROLL表空间中;

3.3、可见性原则:

实现多版本控制的关键是可见性判断,找到对当前事务可见的特定版本数据。DM通过活动事务表,确定事务的可见性。根据事务隔离级的不同,在事务启动时(串行化),或者语句执行时(读提交),收集这一时刻所有活动事务,并记录系统中即将产生的事务号NEXT_TID。DM多版本可见性原则:
物理记录的TRXID等于当前事务号,说明是本事务修改的物理记录,物理记录可见;
物理记录的TRXID不在活动事务表中,并且TRXID小于NEXT_TID,物理记录可见;
物理记录的TRXID包含在活动事务表中,或者TRXID大于等于NEXT_TID,物理记录不可见。

3.4、历史数据的获取:

当物理记录对当前事务不可见时,根据物理记录和回滚记录的RPTR指针,向前回溯一个历史版本记录,通过此历史版本记录的TID字段,依据事务可见性原则判断此版本的记录对当前事务是否可见。如可见即获取到了满足当前事务的历史版本数据;如不可见则根据RPTR指针继续向前回溯。如果一直不能找到对当前事务的可见版本(例如此记录是一个活动事务插入的新记录),则此记录将不会添加到查询结果集中。

3.5、回滚段的清理与回收:

DM8的每个工作线程都唯一对应一个回滚段
在事务启动时,如果该事务没有绑定回滚段,则通过执行该事务的工作线程来确定对应的回滚段
DM8回滚段系统设计可以管理65个回滚段
回滚段仍然采用段-簇-页结构
回滚段的扩展和数据段的扩展一样
回滚段的空闲回滚页以栈的形式进行管理
DM8系统通过回滚块实现对回滚段的分片使用:
每个事务对应有一个回滚块,因此一个回滚段中可以同时包含多个事务的回滚记录
回滚块由回滚段中的多个回滚页构成,回滚页通过页间指针串联起来
回滚块通过first_fpa保存事务初次申请的回滚页地址,通过last_fpa保存事务最后申请的回滚页地址。
回滚页的申请和回收:
事务总是从其回滚块的last_fpa获取当前待写入回滚记录的回滚页;
如果该页不存在或者页内空白空间不够写入回滚记录,则从回滚段的空闲页栈中申请新的回滚页;
通过purge清理出来的回滚页将重新压入到回滚段的空闲页栈
因为回滚段存在扩展,purg系统会以固定时间间隔回收空闲页栈中的超出系统配置范围的空闲页。
DM8通过purg系统清理并回收回滚页来实现回滚段的重复利用
清理模式:
PURG_NORMAL:普通模式,只purg完整的簇,purg系统定义有一个专门的purg线程按需清理,工作线程通过信号量与purg线程交互
PURG_ALL:强制模式,purge所有回滚记录,只在挂起所有工作线程,确保没有其它活动事务干扰时调用。
清理时机:
普通模式:配置项UNDO_RETENTION(回滚页保持时间)为0时,在事务提交后;purg系统退出时,所有事务提交/回滚后
强制模式:在服务器首次启动,完成系统初始化后;服务器正常退出时,在所有事务提交/回滚后;系统异常退出,恢复启动时;backup、mount系统时
清理过程:
找到所有回滚段中已提交尚未清理,并且超出UNDO_RETENTION的可清理事务
根据事务号找到相应的回滚页回收,并压入该回滚段的空闲回滚页栈
对于强制模式,不需要考虑UNDO_RETENTION的配置所有已提交尚未清理的事务立即清理
在系统处于压力(内存紧张)状态并且未清理的事务数较多等情况下,系统将缩短UNDO_RETENTION,提前清理
如果并发的阻塞事务进行了回滚,被阻塞的事务无论在何种隔离级下都可以继续其写操作。
如果并发的阻塞事务进行了提交,则:
脏读、读提交级别的事务可以继续其写操作。
可串行化级别的事务则由于并发事务对数据库进行的修改破坏了该事务的串行化要求,DM8将报串行化事务被打断的错误。
多版本相关配置参数:
UNDO_RETENTION,事务提交后回滚页保持时间,单位为秒,缺省值为900
[-7120]:回滚记录版本太旧,无法获取用户记录

MVCC_RETRY_TIMES,指定发生 MVCC 冲突时的最大重试次数,缺省值为5
[-7067]:多版本操作冲突过多。
Oracle:redo存储修改之后的值,undo存储修改之前的值;
当用户查询时通过serverprocess进程运载到对应的版本中,寻找对应undo块位置(块头、表信息区、行信息区、free区、空闲数据区),模拟的指针技术。

四、相关视图:

相关动态视图:

显示会话的具体信息:V$ SESSIONS 
显示所有活动事务的信息:V$TRX
显示事务等待信息:V$TRXWAIT
显示活动事务视图信息:V$TRX_VIEW
显示当前系统中锁的状态:V$LOCK
显示死锁的历史信息:V$DEADLOCK_HISTORY
查询当前事务的ID:
SELECT TRX_ID FROM V$SESSIONS WHERE SESS_ID = SESSID();
定位锁等待问题
查看被挂起的事务:
	SELECT VTW.ID AS TRX_ID, VS.SESS_ID, VS.SQL_TEXT, VS.APPNAME, VS.CLNT_IP FROM V$TRXWAIT VTW LEFT JOIN V$TRX VT ON(VTW.ID=VT.ID) LEFT JOIN V$SESSIONS VS ON(VT.SESS_ID=VS.SESS_ID);

在这里插入图片描述

通过挂起事务ID找到它等待的事务:
SELECT WAIT_FOR_ID,WAIT_TIME FROM V$TRXWAIT WHERE ID=321646;

在这里插入图片描述

通过等待事务ID定位到连接以及执行的语句:
SELECT VT.ID AS TRX_ID, VS.SESS_ID, VS.SQL_TEXT, VS.APPNAME, VS.CLNT_IP FROM V$TRX VT LEFT JOIN V$SESSIONS VS ON(VT.SESS_ID=VS.SESS_ID) WHERE VT.ID = 321643;

在这里插入图片描述

SP_CLOSE_SESSION关闭等待事务
SP_CLOSE_SESSION(142344256);

更多达梦技术分享尽在:https://eco.dameng.com/

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值