Oracle 数据库查看当前正在造成阻塞的 SQL 语句
🎯 方法一:快速定位阻塞源 (最常用)
这是最直接、最高效的方法,通过 VSESSION 视图中的 BLOCKING_SESSION 字段,可以迅速找到阻塞的根源。
1. 找到阻塞者和被阻塞者
运行以下 SQL,它会列出所有正在阻塞他人的会话及其对应的被阻塞会话。重点关注 BLOCKER 相关的列。
SELECT
blocker.sid AS blocker_sid,
blocker.serial# AS blocker_serial,
blocker.username AS blocker_user,
blocker.sql_id AS blocker_sql_id,
waiter.sid AS waiter_sid,
waiter.sql_id AS waiter_sql_id
FROM vsession blocker
JOIN vsession waiter ON blocker.sid = waiter.blocking_session
WHERE waiter.blocking_session IS NOT NULL;
2. 查看阻塞者的 SQL 语句
从上一步的结果中,获取阻塞者的 SQL_ID (即 blocker_sql_id),然后查询 VSQL 视图来获取完整的 SQL 文本。
-- 将 'YOUR_BLOCKER_SQL_ID' 替换为上一步查到的 SQL_ID
SELECT sql_text
FROM vsql
WHERE sql_id = 'YOUR_BLOCKER_SQL_ID';
提示:如果 blocker_sql_id 为空,可以尝试查询 VSESSION 中的 PREV_SQL_ID 字段,它代表了会话上一次执行的 SQL。
🔗 方法二:分析复杂阻塞链
当一个会话被另一个会话阻塞,而后者又被第三个会话阻塞时,就形成了阻塞链。此时需要找到链的源头。
* 使用递归查询追溯根源
以下 SQL 使用 CONNECT BY 语法,可以清晰地展示阻塞的层级关系,帮助你找到最顶层的“罪魁祸首”。
SELECT
sid,
serial#,
username,
blocking_session,
level AS blocking_level,
SYS_CONNECT_BY_PATH(sid, ' -> ') AS blocking_path
FROM vsession
WHERE blocking_session IS NOT NULL
CONNECT BY PRIOR sid = blocking_session
START WITH sid IN (
SELECT blocking_session
FROM vsession
WHERE blocking_session IS NOT NULL
);
执行结果中,blocking_level 值最小的行通常就是阻塞链的源头。找到其 SID 后,再按方法一的步骤2查询其 SQL 即可。
🚨 方法三:使用高级诊断工具 (适用于严重故障)
当系统出现严重的性能问题或大面积会话挂起(Hang)时,可以使用 Oracle 提供的 VHANG_INFO 视图进行深度诊断。
1. 触发 Hang 分析
首先,需要以 SYSDBA 身份执行以下命令来生成分析数据。
-- 需要 SYSDBA 权限
ORADEBUG hanganalyze 3;
2. 查询阻塞信息
执行完上一步后,立即查询 VHANG_INFO 视图。它的 BLOCKING_TREE 列会以树形结构直观地展示阻塞关系。
SELECT blocking_tree, blocked_session, blocking_session, wait_event, sql_id
FROM vhang_info
ORDER BY blocking_tree;
同样,找到顶级的阻塞会话及其 SQL_ID,然后去 VSQL 视图中查询具体语句。
📊
为了方便你理解和记忆,以下是排查阻塞问题时最关键的几个动态性能视图:
视图名称 主要用途
VSESSION 核心视图,包含所有会话的详细信息,BLOCKING_SESSION 字段是定位阻塞的关键。
VSQL 通过 SQL_ID 关联,用于获取会话正在或最近执行的 SQL 文本。
VLOCK 提供更底层的锁信息,如锁类型(TX, TM)、持有模式和请求模式。
VHANG_INFO 高级诊断视图,在执行 ORADEBUG HANGANALYZE 后使用,用于分析复杂的挂起问题。
