达梦数据库定位阻塞方法举例

Source

背景介绍:

当使用达梦数据库时,可能会遇到这样的场景,某个DML操作被阻塞,但是查询阻塞源头的v$session会话并没有发现有能引起IX锁的SQL语句,那怎么来定位发生的阻塞原因呢?举个例子:

1.更新表TEST3时发生了阻塞

2.查询被阻塞的源头是trx_id=5087的事务

3.查询trx_id=5087对应的会话,发现引发此表update的事务记录的sql竟然是select

4.那再查询此表对应的锁情况呢

5.到了这一步,我们可以看出来此表对应的两个IX锁,一般在修改数据时才会上IX锁,trx_id=5085是IX锁我们可以理解,那么除了被阻塞的update以外,我们发现阻塞源头trx_id=5087也是IX锁,而第3步我们知道此事务记录的select操作,难道说select会上IX锁?NO!其实v$sessions中SQL_TEXT字段记录是最近执行的一条SQL语句,也就是说当一个事务中由多个语句组成时,v$sessions记录的是事务中当前正在执行的语句(事务正在执行)或事务中最后一条语句(事务完成)。根据这个思路我们就可以判断:虽然trx_id=5085对应的会话sql记录的select,但是此这个事务中select操作之前必定有各修改数据的操作没有提交。为了验证这个思想,我们看一下log_commit日志。

6.搜索到SQL_TEXT对应的语句,找到事务号为5087

7.紧接着搜索上一个trx_id=5087的操作,果然看到有一个update操作,并且没有提交

8.这时候这个思路就通畅了,并非select语句对TEST3表上IX锁,而是select上一个update操作没有提交导致的,那么我们可以将TRX_ID=5087的事务提交或回滚即可,一般这种场景是人工手动在客户端工具执行忘记提交导致,因为无论disql或是管理工具,默认都是不开启自动提交功能的。