DM8锁等待和死锁

本文详细介绍了达梦数据库中如何通过MVCC和锁机制确保事务并发控制和数据一致性。通过实例展示了INSERT、UPDATE、DELETE操作时的锁等待现象,以及解决锁阻塞的方法,包括查看锁等待的动态性能视图v$lock和解决锁等待的技巧。此外,还讨论了死锁的概念和测试场景,以及DDL锁超时问题,强调了解决锁等待问题对于避免死锁和锁超时的重要性。
摘要由CSDN通过智能技术生成

达梦数据库通过多版本并发控制MVCC和锁机制实现事务的并发控制和保持数据的一致性及正确性。在实际工作中,可能出现多个事务同时访问、修改相同数据的情况,当一个事务正在占用某个资源的锁,此时另一个事务正在请求这个资源上与第一个锁相冲突的锁类型时,就会发生阻塞。

本文介绍如何使用动态性能视图查看锁等待以及解决锁阻塞的问题。

DM事务锁

在测试前,新建T_TEST01表,其中ID字段为主键,表结构参考如下:

create table t_test01(id int primary key, name varchar(20));

查询该表:

此时,查询v$lock该表的锁(先查询SYSOBJECTS获取表的ID,使用ID查询该表的锁),可以看到读操作时有IS锁(意向共享锁)。

打开一个新会话(会话一),在T_TEST01表中插入一条测试数据(未提交):

insert into t_test01(id, name) values(1, 'cheng');

此时查看v$lock,新增表对象的IS(意向共享锁)和IX(意向排他锁)

锁等待

01

锁等待测试

场景一:INSERT锁等待

当多个事务同时试图向有主键或UNIQUE约束的表中插入相同的数据时,前一个事务未提交,后面的事务将被阻塞,直到前一个事务提交或回滚。

新增会话二,再插入与会话一相同的数据,因为该表有主键,会话一未提交,此时可以看到会话被阻塞:

查询v$lock可以看到该对象新增了TID共享锁(S锁),并且该锁BLOCKED=1,该锁被33125(会话一)事务阻塞:

此时,如果我们提交会话一插入的数据,执行commit;

再次查询v$lock,可以看到提交之后相关的事务锁已经释放,并且会话二抛出异常:

场景二:UPDATE和DELETE锁等待

当UPDATE和DELETE修改的记录已经被另一个事务修改过(未提交),将会发生阻塞,直到未提交的造成阻塞的事务提交或回滚。

新增会话三:更新id=1的记录:

新增会话四:删除id=1的记录

此时查看v$lock 或v$trxwait,可以看到会话被阻塞:

02

锁等待解决方法

上述场景二测试中,如果提交第一次事务,就可以解决锁等待的问题(同场景一)。

但实际业务中,我们可能无法手工提交阻塞的会话,此时可以强制杀死会话:

使用如下语句查询处于等待的锁(或查询v$trxwait可以查看阻塞事务):

select TRX_ID, LTYPE, LMODE, BLOCKED, TABLE_ID, TID from v$lock where blocked=1;

如上图,根据阻塞的事务ID=33127找到会话ID,可以看到会话id,sql信息:

根据会话ID,使用sp_close_session系统过程即可杀死会话(也可以使用操作系统命令 kill -9 线程ID杀死线程,上图中THRD_ID为线程ID):

再次查询v$lock可以看到会话阻塞问题解决:

死锁

死锁与阻塞的不同之处在于死锁包括两个或者多个已阻塞事务,它们之间形成了等待环,每个都等待其他事务释放锁。例如事务1给表T1上了排他锁,第二个事务给表T2上了排他锁,此时事务1请求T2的排他锁,就会处于等待状态,被阻塞。若此时T2再请求表T1的排他锁,则T2也处于阻塞状态。此时这两个事务发生死锁,DM数据库会选择牺牲掉其中一个事务。

测试场景如下:

新增会话一:对T_TEST01插入一条数据(此时T_TEST01表上有了排他锁)。

新增会话二:新增T_TEST02表,表结构同T_TEST01,并插入相同数据(此时T_TEST02表上有了排他锁):

在会话一上往T_TEST02表插入相同数据,因为有主键,产生锁等待:

在会话二上往T_TEST01表插入相同数据,此时产生死锁,可以看到DM数据库自动检测到死锁的产生,并报出错误:

死锁的本质也是锁等待,所以解决锁等待的问题,就解决了死锁的问题。

DDL锁超时

当我们对某张表执行DDL操作时(比如修改某张表的表结构),若当前表上有排他锁(未提交的DML事务),此时数据库会根据锁的等待时间抛出锁超时的异常。

DM数据库的DDL锁超时时间是由参数DDL_WAIT_TIME指定,默认十秒,可根据实际需要修改。

锁超时场景测试:

新增会话一,在T_TEST01表中插入数据(未提交),产生一个排他锁:

insert into t_test01(id, name) values(2, 'qing');

新增会话二,执行DDL语句(对t_test01新增字段),此时会话处理等待状态:

alter table t_test01 add column info1 varchar(50);

查询v$trxwait可以看到事务处于阻塞等待:

大概十多秒,会话二抛出锁超时的异常:

锁超时的本质原因是锁等待,解决锁等待的问题,就解决了锁超时的问题。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值