达梦数据库锁表与阻塞处理

1定义
阻塞:多个线程之间的相互影响,等待临界资源;
死锁:多个线程之间互相等待,形成等待环;

对于死锁,达梦数据库会自动检测,并选择牺牲掉其中的一个事务,保证其它事务正常运行。
死锁一般是由于应用程序bug导致的,当有修改多表的事务时,应尽量保证每个事务以相同的顺序锁定表。
可以通过V$DEADLOCK_HISTORY查询死锁历史,其中记录了产生死锁后被牺牲掉的事务的事务ID、会话ID、执行的SQL语句以及死锁发生时间(没有记录造成死锁的其它事务)。

对于阻塞,达梦数据库不会自动处理,被阻塞的事务会一直挂起,直到获取到所需的资源。
阻塞一般是由应用程序bug造成的,在应用编写中,应尽量形成短事务,快速提交。

2什么情况下会形成阻塞?
在达梦数据库中,默认采用读提交的机制,查询永远不会被阻塞。查询一般情况下也不会阻塞增删改操作,SELECT FOR UPDATE的情况除外。
INSERT语句被阻塞的情况:多个事务同时向有主键或唯一约束的表中插入相同的数据;
删、改语句被阻塞的情况:所需要操作的数据被其它事务修改过,且一直没有提交或回滚;

示例:
job表结构和数据如图
在这里插入图片描述

先执行:update "DMHR"."JOB" set MIN_SALARY='10000' where JOB_ID='73'
在这里插入图片描述

再执行:select * from "DMHR"."JOB" where JOB_ID='73'
在这里插入图片描述

可以看到, select 操作可以正常进行。但是由于之前的事务没有提交,所以查出来的结果还是旧的值。
再执行:delete from "DMHR"."JOB" where JOB_ID='73';
在这里插入图片描述

此时,发生阻塞,因为 delete 操作需要加锁,当前事务被挂起。

3.阻塞的排查
当阻塞发生时,我们可以通过 v$lock 视图查到当前数据库中锁的状态

select * from v$lock;

在这里插入图片描述

结果中我们可以看到,事务 1459 被阻塞了,阻塞他的事务为 1450,同样我们也可以通过 V$TRXWAIT 视图排查阻塞,

select * from v$trxwait;

在这里插入图片描述

得出同样的结果,等待时间是1814645 毫秒。
接下来,通过 V$SESSIONS 视图查找两个事务对应的会话,可以知道是哪些 SQL 语句产生的阻塞。

select sess_id,sql_text,state,trx_id from v$sessions where trx_id in('1459','1450');

在这里插入图片描述

4.阻塞的解决方法
根据需求,可以有两种解决方案。
4.1 提交或回滚产生阻塞的事务。
根据上文,我们可知产生阻塞的事务会话 ID 为 140702994469648。此时,我们只需要在该会话下提交或回滚事务,锁自然会被释放,阻塞解决。

4.2 关闭产生阻塞的会话
同样,我们也可以使用系统过程 SP_CLOSE_SESSION(SESS_ID)来关闭对应的会话
在这里插入图片描述

此时,锁被释放,delete 操作也可以顺利进行下去。

在这里插入图片描述

备注:可以用一条语句查看出被阻塞的操作和事务会话 ID(SESS_ID)

select a.*,b.NAME,c.SESS_ID from v$lock a
left join sysobjects b on b.ID=a.TABLE_ID
left join v$sessions c on a.TRX_ID=c.TRX_ID;

然后直接执行SP_CLOSE_SESSION(SESS_ID) 来关闭对应的会话

参考链接:https://blog.csdn.net/fengxiaozhenjay/article/details/101707104

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值