DM的事务以及锁

本文详细介绍了数据库事务的概念,包括事务的开始、结束以及提交和回滚。讨论了事务的隔离级别,如读未提交、读提交和串行化,以及它们在并发控制中的作用,如防止脏读、不可重复读和幻像读。此外,还提到了DM7中的事务ID、保存点、锁机制和回滚段管理,以及如何处理阻塞和死锁问题。最后,介绍了数据可见性和多版本并发控制的实现策略。
摘要由CSDN通过智能技术生成

数据库事务是指作为单个逻辑工作单元的一系列操作的集合。
事务的开始:DM7没有提供显式定义事务开始的语句,第一个可执行的SQL语句隐含事务的开始。
事务的结束:用户可以使用提交(COMMIT)或回滚(ROLLBACK)语句显式的结束一个事务,也可以使用隐式的方式结束一个事务。

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

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

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

普通事务和虚事务
虚事务是系统内部事务,不属于任何会话,始终驻留在事务系统中,用于回滚段清理。
活动事务和非活动事务
非活动事务是TRXID为0且状态为NOT_START的事务。
活动事务是TRXID大于0的事务,状态可以是ACTIVE或者LOCK_WAIT。
读写事务和只读事务
只读事务:只能访问数据,但不能修改数据。

三种类型的读数据现象:
脏读:如果一个事务在提交操作结果之前,另一个事务可以看到该结果,就会发生脏读。

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

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

DM7支持三种事务隔离级别:读未提交、读提交和串行化。
读提交是DM7默认使用的事务隔离级别,可重复读则升级为更严格的串行化隔离级别。
读写分离的备机不允许设置为串行化隔离级别。

一个事务只会属于一个会话。
一般情况下一个会话上有一个事务,但自治事务会使一个会话上有多个事务。
DM7支持通过将一个PL/SQL语句块定义成自治事务,将该块中的DML语句和调用程序的事务环境隔离开,该语句块成为由其它事务(主事务)启动的独立事务。
在自治事务块中,主事务是挂起的;等待自治事务完成后,会话自动切换回主事务。
自治块中可以调用其它被定义自治事务的过程,从而产生嵌套的自治事务。

是否自动提交的设置
DISQL缺省是非自动提交的。可使用 set auto [on|off]设置,使用show auto查看当前自动提交的设置。管理工具缺省是自动提交的,通过界面可修改。编程接口一般都会提供自动提交开关的设置函数,通常缺省为自动提交。
DDL是否自动提交,INI参数DDL_AUTO_COMMIT。
事务隔离级别设置,编程接口提供设置,INI参数ISOLATION_LEVEL决定缺省设置。
未启动事务的隔离级和读写特性可以通过SQL语句更改:
SET TRANSACTION ISOLATION LEVEL [READ COMMITTED | READ UNCOMMITTED | SERIALIZABLE];
SET TRANSACTION READ ONLY | WRITE;

按照封锁对象的不同,锁可以分为 TID 锁(事务锁)和对象锁。
TID锁
TID锁以事务号为封锁对象,系统为每个活动事务生成一把TID锁,代替了其他数据库行锁的功能,防止多个事务同时修改同一行记录。
每个事务启动时创建一把独占的TID锁,锁模式为X锁,并持有到事务结束。
DM7实现的是行级多版本,每一行记录隐含一个 TID 字段,用于事务可见性判断,协调行级的多版本并发控制。

对象锁是 DM7 新引入的一种锁,通过统一的对象 ID 进行封锁,将对数据字典的封锁和表锁合并为对象锁,以达到减少封锁冲突、提升系统并发性能的目的。
表锁
表锁用来保护表数据的完整性。
DML语句执行时,对表进行上锁,协调表级的并发访问。
隐含上IS,IX锁,X锁(列存储表)。
字典锁
防止在DML/DDL的过程中,访问对象的定义被修改。
四种锁类型均采用。

隐式上锁
在执行SELECT、INSERT、DELETE、UPDATE等DML语句时,隐式上意向锁。
查询上IS锁。
插入、删除和更新行存储表上IX锁,列存储表上X锁。

INI参数FAST_RELEASE_SLOCK决定是否启用快速释放共享锁(除表空间锁S锁之外的所有类型为LOCK_TABLE的S锁或者IS锁),即在计划执行完后就释放,缺省启用。

字典的上锁和解锁操作在执行计划的准备阶段和执行阶段阶段各自进行。

根节点必须首先加锁,仅当持有父对象的锁时,才可以对子对象上锁。

DDL语句会转成对相应系统表的DML操作语句,系统会拼接SF_LOCK_DICT等内部SQL上锁函数语句插入到DML语句前。

INI参数DDL_WAIT_TIME决定DDL语句锁等待的超时时间10秒,为0会一直等待。

阻塞和死锁是会与并发事务一起发生的两个事件,它们都与锁相关。当一个事务正在占用某个资源的锁,此时另一个事务正在请求这个资源上与第一个锁相冲突的锁类型时,就会发生阻塞。被阻塞的事务将一直挂起,直到持有锁的事务放弃锁定的资源为止。
死锁与阻塞的不同之处在于死锁包括两个或者多个已阻塞事务,它们之间形成了等待环,每个都等待其他事务释放锁。
例如事务 1 给表 T1 上了排他锁,第二个事务给表 T2 上了排他锁,此时事务 1 请求 T2 的排它锁,就会处于等待状态,被阻塞。若此时 T2 再请求表 T1 的排他锁,则T2 也处于阻塞状态。此时这两个事务发生死锁,DM 7会选择牺牲掉其中一个事务。

对数据的每次更新形成数据的新版本,老版本保存在回滚段中。

读操作将不需要上锁,读操作与写操作不会相互阻塞,并发度大幅度提高。

物理记录结构
TRXID:最近一次修改或者创建本记录的事务ID
ROLLPTR: 回滚记录指针,指向本记录的上一个版本

每个活动事务都对应有一个活动事务视图

活动事务视图主要记录该事务启动时:
从IID系统获取的该事务新TRXID
当前事务系统中的所有其它活动事务的TRXID
当前IID系统的下一TRXID——NEXT_TRXID
该事务及其活动事务视图中的最小TRXID——MIN_TRXID

事务的活动事务视图一般在事务的每次数据库操作前都要重构, 并重新计算NEXT_TRXID, MIN_TRXID。NEXT_TRXID计算方法如下:
如果该事务已经是活动事务,则其TRXID不变,NEXT_TRXID重新从IID系统获取。
如果该事务是非活动事务,则从IID系统获取该事务TRXID,NEXT_TRXID为该事务TRXID+1。

实现多版本控制的关键是数据可见性判断,找到对当前事务可见的特定版本数据。
如果当前物理记录不可见,则按照该记录的ROLLPTR指示,找到其上一个版本,并再次判断该版本可见性,直到找到可见版本为止。
DM7通过活动事务视图来判定数据的可见性。
对于串行化隔离级,仅在事务启动时,构造事务的活动事务视图。
对于读提交隔离级,在事务启动和语句执行时,都需要构造或重构活动事务视图。

在读未提交隔离级下,数据都是可见的。
对于其它隔离级:
若物理记录的 TRXID 小于当前事务的活动事务视图的MIN_TRXID,则该物理记录可见;
若物理记录的 TRXID 等于当前事务ID,说明是本事务修改的物理记录,则该物理记录可见;
若物理记录的 TRXID 大于等于当前事务的活动事务视图的NEXT_TRXID,则该物理记录不可见;
若物理记录的 TRXID 包含在当前事务的活动事务视图中,则该物理记录不可见。

数据可见原则与多版本读相同
如果要写的记录对自己可见,则更新之,产生一个新的版本,TRXID为自己的事务ID,老版本保存到回滚段
如果要写的记录对自己不可见,不会向回找到记录的历史版本,因为更新必须在最新的版本上进行。
不可见时,对占据当前版本的事务TRXID上一把X锁,这个X锁必然与那个事务启动时对自己的TRXID上的X锁冲突,导致当前事务被挂起,直到占据数据的事务提交或者回滚为止。

DM7的每个工作线程都唯一对应一个回滚段
在事务启动时,如果该事务没有绑定回滚段,则通过执行该事务的工作线程来确定对应的回滚段
DM7回滚段系统设计可以管理65个回滚段
回滚段仍然采用段-簇-页结构
回滚段的扩展和数据段的扩展一样
回滚段的空闲回滚页以栈的形式进行管理

清理过程:
找到所有回滚段中已提交尚未清理,并且超出UNDO_RETENTION的可清理事务
根据事务号找到相应的回滚页回收,并压入该回滚段的空闲回滚页栈
对于强制模式,不需要考虑UNDO_RETENTION的配置所有已提交尚未清理的事务立即清理
在系统处于压力(内存紧张)状态并且未清理的事务数较多等情况下,系统将缩短UNDO_RETENTION,提前清理

如果并发的阻塞事务进行了回滚,被阻塞的事务无论在何种隔离级下都可以继续其写操作。

如果并发的阻塞事务进行了提交,则:
脏读、读提交级别的事务可以继续其写操作。
可串行化级别的事务则由于并发事务对数据库进行的修改破坏了该事务的串行化要求,DM7将报串行化事务被打断的错误。

显示会话的具体信息:V S E S S I O N S 显 示 所 有 活 动 事 务 的 信 息 : V SESSIONS 显示所有活动事务的信息:V SESSIONSVTRX
显示事务等待信息:V T R X W A I T 显 示 活 动 事 务 视 图 信 息 : V TRXWAIT 显示活动事务视图信息:V TRXWAITVTRX_VIEW
显示当前系统中锁的状态:V L O C K 显 示 死 锁 的 历 史 信 息 : V LOCK 显示死锁的历史信息:V LOCKVDEADLOCK_HISTORY

详细手册可参考达梦官方网站,或登录社区进行交流学习
https://eco.dameng.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值