一:关于DM的事务:
若事务运行期间出现连接断开,DM 数据库都会自动回滚该连接所产生的事务。
DM 实现的是行级多版本,每一行记录隐含一个 TID 字段,用于事务可见性判断。
只有多个事务同时修改同一行记录时,才会产生新的 TID 锁。
SELECT 操作已经消除了行锁,因此 DM 中不再有行锁的概念。
二:阻塞相关的结论:
1、INSERT 发生阻塞的唯一情况是,当多个事务同时试图向有主键或 UNIQUE 约束的表中插入相同的数据时,其中的一个事务将被阻塞,直到另外一个事务提交或回滚。一个事务提交时,另一个事务将收到唯一性冲突的错误;一个事务回滚时,被阻塞的事务可以继续执行。
2、当 UPDATE 和 DELETE 修改的记录,已经被另外的事务修改过,将会发生阻塞,直到另一个事务提交或回滚。
下边以delete为例来说明:
drop table x cascade;
create table x(id int,y datetime);
insert into x values(1, datatime'2022-05-17 16:37:00');
insert into x values(2, datatime'2022-05-17 16:37:00');
insert into x values(3, sysdate);
insert into x values(4, sysdate);
commit;
select * from x;
select object_id from dba_objects where object_name=upper('X') and owner=upper('SYSDBA'); --1485
SESSION A:
delete from x where id=4;
select * from V$LOCK where table_id=1485 or lmode='X';--查看锁情况
注意:是lmode=X和IX,ign_flag=0(表示锁正在使用中)的哪两条,另个的一条是DM本身自己加的且ign_flag=1不用管它。
SESSION B:
delete from x where id=4;
select * from V$LOCK where table_id=1485 or lmode='X';--查看锁情况; --查看锁情况
可以看出:SESSION B的事务ID: 24488733,是以SESSION A的事务ID 24488625为封锁对象的。换句话说:是事务ID 24488625阻塞了事务ID 24488733 。
结论:可以看出当多个事务delete同一行时:
1、也会产生TID锁,并且还会伴有IX锁。
2、第二个会话封锁对象是用第一个会话的事务ID为封锁对象的。
解决方法:
法一:要么让第一个会话A,rollback或commit;
法二:SP_CLOSE_SESSION(140000029119328);
select * from V$TRXWAIT;
select sess_id from V$TRX where id=24488625;
SP_CLOSE_SESSION(140000029119328); --此时它会断开第一个会话A,并将其会话A的事务全部回滚掉,然后第二个会话,可以继续执行!
核实锁情况:
SQL> select * from V$LOCK where table_id in (select object_id from dba_objects where object_name=upper('X') and owner=upper('SYSDBA')) or lmode='X' order by IGN_FLAG;
可以看到还是存在两个TID,不过现在blocked现在是0,且V$TRXWAIT中已不存在对应关系,但它们的关系仍存在!
更多学习内容参考:达梦数据库 - 新一代大型通用关系型数据库 | 达梦云适配中心