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

达梦数据库事务加锁过程说明

原创 高雪熠 2022-04-19
1240

本文主要描述在出现行级数据DML争用的过程中,达梦数据库是如何处理并发进行加锁的。

一、环境准备

1、首先构造一张事务表

create table t_test (id number, name varchar(20));

insert into t_test(id, name) values(1, DBMS_RANDOM.string('A', 20));

select * from t_test;

行号     ID NAME

---------- -- --------------------

1          1  XWsThNQujDlbdCXGOdtD


2、开启事务

开启一个会话1修改这一行记录,不提交:

update t_test set name='hello' where id=1;

影响行数 1

同时开启另一个新的会话2,修改同一行数据:

SQL> update t_test set name='hello' where id=1;

发现会话hang住


二、锁过程分析

下面我们看一下会话的锁情况。

首先通过select * from v$lock;查找到当前持有锁的事务号为7038,也就是会话1产生的。被锁的事务号是7039,也就是会话2产生的。

首先是7038:

SQL> select * from v$lock where trx_id=7038;


行号     ADDR                 TRX_ID               LTYPE  LMODE BLOCKED     TABLE_ID    ROW_IDX              TID                  IGN_FLAG    HLCK_EP

---------- -------------------- -------------------- ------ ----- ----------- ----------- -------------------- -------------------- ----------- -----------

1          140316362438600      7038                 OBJECT IS    0           302         0                    7027                 1           255

2          140316362439032      7038                 OBJECT IS    0           268435456   0                    7027                 1           255

3          140316362439320      7038                 OBJECT IX    0           1059        0                    7038                 0           255

4          140316362440040      7038                 OBJECT IS    0           0           0                    7027                 1           255

5          140316362440616      7038                 OBJECT IS    0           150994945   0                    7028                 1           255

6          140316362440904      7038                 OBJECT IS    0           150994944   0                    7028                 1           255

7          140316362441336      7038                 OBJECT IS    0           50331649    0                    7027                 1           255

8          140316362700744      7038                 TID    X     0           -1          -1                   7038                 0           255


8 rows got


解释一下7038事务保有的锁:

SQL> select object_id, object_name,OBJECT_TYPE from dba_objects where object_id in (302, 268435456, 1059, 0, 150994945, 150994944, 50331649);


行号     OBJECT_ID OBJECT_NAME OBJECT_TYPE

---------- --------- ----------- -----------

1          150994944 SYS         SCH

2          150994945 SYSDBA      SCH

3          0         SYSOBJECTS  TABLE

4          1059      T_TEST      TABLE

5          268435456 SYSOBJECTS  DSYNOM


已用时间: 3.563(毫秒). 执行号:550.

其中SCH为模式类型,所以显然对模式类型增加了IS锁,意向共享锁

TABLE:表,对sysobjects增加了一个IS锁,对事务表增加了一个IX锁,意向排他锁

DSYNOM是对sysobjects的一个同义词,对TID 7038事务号持有排他锁X。


接下来看一下7039持有锁的情况:

SQL> select * from v$lock where trx_id=7039;


行号     ADDR                 TRX_ID               LTYPE  LMODE BLOCKED     TABLE_ID    ROW_IDX              TID                  IGN_FLAG    HLCK_EP

---------- -------------------- -------------------- ------ ----- ----------- ----------- -------------------- -------------------- ----------- -----------

1          140316362439464      7039                 OBJECT IX    0           1059        0                    7039                 0           255

2          140316362700888      7039                 TID    S     1           1059        1                    7038                 0           255


首先是一个object类型锁,1509,是对t_test表增加了一个IX锁,这印证了IX锁在表级是相容的,同时还有一个TID锁,是事务锁,这个事务锁是一个共享的,此时被X锁阻塞。


接下来,提交7038,查看7039持有的锁情况:

SQL> select * from v$lock where trx_id=7039;

行号     ADDR                 TRX_ID               LTYPE  LMODE BLOCKED     TABLE_ID    ROW_IDX              TID                  IGN_FLAG    HLCK_EP

---------- -------------------- -------------------- ------ ----- ----------- ----------- -------------------- -------------------- ----------- -----------

1          140316362439464      7039                 OBJECT IX    0           1059        0                    7039                 0           255

2          140316362700744      7039                 TID    X     0           -1          -1                   7039                 0           255

3          140316362700888      7039                 TID    S     0           1059        1                    7038                 0           255

已用时间: 1.073(毫秒). 执行号:552.


当7038提交以后,7039会将事务锁从共享转为排他,但这里的转换并不是简单的S和X之间的转换:

首先会话1,在创建事务时,生成7038事务号,并对7038持有X锁。当会话2修改同一行时,创建7039事务,会首先对这一行数据生成新的事务锁,这个锁其实是在7038事务号上面增加了一个S锁的等待,锁对象是7038的事务号。当7038提交之后,会话2便会持有7038事务号的S锁,同时对7039事务号持有X锁。从而完成了S与X的转换。


另外,在本实验中,我们注意到,在7039中,并没有对模式、数据字典持有锁,原因在于7039掌握有对7038的共享锁,而7038事务号中,已经对模式增加了对应的锁了(这在上面对7038的锁信息中有体现),所以显然7039是对模式具有共享锁的。所以在达梦数据库中,新的事务只需要对前一事务号保有共享锁即可,而无需再次对各对象增加锁,减少了行锁模式对系统资源的消耗。



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

评论