查看会话的阻塞链条

如果阻塞有多层,把源头会话kill掉不一定会使所有的会话被释放,因为被锁定的资源不一样:

A->B  A锁定了B要获取的行1

C->A  C锁定了A要获取的行2

C->A->B 如果kill掉C会话,行2被释放,那么A不会再被阻塞,但是B仍然会被阻塞,因为B要的资源行1仍然被A持有,除非A不再持有B需要的资源。

针对这种情况,不是kill了源头就释放了所有被阻塞的会话,还要看下一层是否继续持有资源。

可以把C称为链条头,同时C是A的阻塞源头,A是B的阻塞源头。

具体示例:

WITH w1 AS
(SELECT (CASE
WHEN connect_by_isleaf = 0 THEN
'alter system kill session ''' || s.sid || ',' || s.serial# || ',@' ||
s.inst_id || ''' immediate;'
ELSE
NULL
END) AS kill_ddl, --生成阻塞会话的kill语句
(CASE
WHEN connect_by_root(s.sid || '@' || s.inst_id) =
s.sid || '@' || s.inst_id THEN
'Y'
ELSE
NULL
END) AS block_head, --阻塞头
--connect_by_root(s.sid) top_sid,
lpad(' ', (LEVEL - 1) * 2, ' ') ||
substr(sys_connect_by_path(s.sid || '@' || s.inst_id, '->'), 3) block_chain,
s.inst_id,
s.sid,
s.serial#,
s.blocking_instance AS block_inst_id,
s.blocking_session AS block_sid, --被这个会话阻塞,可以理解成父节点
s.final_blocking_instance AS final_block_inst_id,
s.final_blocking_session AS final_block_sid,
s.status,
s.logon_time,
s.sql_id,
s.event,
s.seconds_in_wait wait_time_s
FROM gv$session s
START WITH EXISTS (SELECT 1
FROM gv$session s2
WHERE s.inst_id = s2.inst_id
AND s.sid = s2.blocking_session) --获取有阻塞的节点
CONNECT BY PRIOR s.inst_id = s.blocking_instance
AND PRIOR s.sid = s.blocking_session)
SELECT * FROM w1;

posted @ 2022-01-13 13:37  HD先生  阅读(103)  评论(0)    收藏  举报