怎样利用Oracle 12c ASH视图追踪历史阻塞链_编写多级关联查询语句

浅宇小哥_3357

浅宇小哥_3357

2026-05-24

334人浏览

原创

ash视图无“历史阻塞链”字段,需基于blocking_session等三字段递归关联构建多级阻塞链,须限定时间范围、校验实例一致性,并先物化gv$active_session_history数据再用递归cte计算。

ash视图里没有“历史阻塞链”这个现成字段

oracle 12c 的 v$active_session_history(ash)本身不存储完整的阻塞链快照,它只记录每秒采样时会话的瞬时状态,包括 blocking_session、blocking_session_serial#、blocking_inst_id 这三个字段。所谓“多级阻塞链”,比如 a → b → c → d,必须靠递归关联这些字段拼出来——不是查一次就能出结果,得用自连接或递归 cte。

常见错误是直接 JOIN v$ash a ON a.session_id = b.blocking_session 却忽略实例号、序列号、采样时间窗口,导致跨实例匹配错乱,或把不同时间点的阻塞关系强行串成一条“伪链”。

  • 必须限定时间范围:sample_time BETWEEN ... AND ...,否则跨数小时的数据混在一起毫无业务意义
  • 必须校验实例一致性:a.blocking_inst_id = b.inst_id,RAC 环境下漏掉这个条件会把其他节点的会话当成阻塞者
  • 阻塞关系不是全时段持续的,同一对会话可能在不同采样点反复出现/消失,不能简单去重后当“稳定链路”看待

用递归 CTE 构建阻塞层级(LEVEL + CONNECT BY 不适用)

Oracle 12c 支持 WITH RECURSIVE(注意:需 12.1.0.2+ 且启用 COMPATIBLE >= 12.1.0),但 v$active_session_history 是动态性能视图,不能直接用于递归查询的初始集(ORA-32043 不允许在 WITH 子句中引用动态性能视图)。实际可行方案是先物化中间结果:

WITH ash_base AS (
  SELECT inst_id, session_id, session_serial#, blocking_session,
         blocking_session_serial#, blocking_inst_id, sample_time,
         sql_id, event, p1, p2
  FROM gv$active_session_history
  WHERE sample_time >= SYSDATE - 1/24  -- 最近1小时
    AND blocking_session IS NOT NULL
),
block_chain (inst_id, sid, serial#, blocker_sid, blocker_serial#, blocker_inst, lvl, path) AS (
  -- 叶子节点:被阻塞但自己没阻塞别人(即不在 ash_base 的 blocking_session 列中出现)
  SELECT a.inst_id, a.session_id, a.session_serial#, 
         a.blocking_session, a.blocking_session_serial#, a.blocking_inst_id,
         1 AS lvl,
         TO_CHAR(a.session_id) || ' <p>关键点:初始集必须是“终端被阻塞者”,不是随便挑一个会话开始;<code>lvl  是硬性防护,ASH 采样间隔为1秒,长链往往意味着严重锁争用,优先人工介入而非依赖SQL深挖。</code></p><div class="aritcle_card flexRow artxards">
											<div class="artcardd flexRow">
												<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill6971" title="QuantOracle"><img
														src="https://img.php.cn/upload/skill/000/000/081/179120536643782.jpg" alt="QuantOracle" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
												<div class="aritcle_card_info flexColumn">
													<a rel="nofollow" href="/xiazai/skill6971" title="QuantOracle" class="overflowclass">QuantOracle</a>
													<p class="overflowclass">63个确定性量化金融计算器 + 10个通过MCP的复合工作流。期权定价、Greeks、奇异衍生品、风险指标、投资组合优化……</p>
												</div>
												<a rel="nofollow" href="/xiazai/skill6971" title="QuantOracle" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
												</a>
											</div>
										</div><h3>为什么不能用 v$session_longops 或 dba_hist_active_sess_history?</h3><p><code>v$session_longops</code> 记录的是长时间运行操作(如排序、哈希连接),和阻塞无关;<code>dba_hist_active_sess_history</code> 虽然存的是ASH历史快照,但默认只保留1小时(受 <code>statistics_level</code> 和 AWR 保留策略影响),且每分钟才写入一次汇总数据,丢失大量秒级细节——你看到的可能是“A阻塞B持续60秒”,但真实情况是A每5秒阻塞B一次、每次200ms,这种脉冲式阻塞在 <code>dba_hist_active_sess_history</code> 里根本无法还原。</p>
  • 查实时问题,只用 gv$active_session_history(注意是 gv$,非 v$,RAC 必须跨实例看)
  • 查1小时前的问题,先确认 AWR 是否启用了 ASH 采样(SELECT dbms_workload_repository.ash_get_top_sql( ... ) 可间接验证)
  • 想长期追踪阻塞模式,应配合 DBMS_MONITOR.SESSION_TRACE_ENABLE 对可疑会话开启10046跟踪,ASH只是第一响应手段

容易被忽略的采样偏差和锁类型混淆

ASH 每秒采样一次,但只捕获当时处于“等待”或“CPU运行”状态的会话。如果阻塞发生在两次采样之间(比如锁持有时间 event 字段决定阻塞性质,enq: TX - row lock contention 和 enq: TM - contention 处理方式完全不同,但它们在阻塞链里都表现为 blocking_session 非空。

  • 务必检查 event 和 p1text/p2text:用 SELECT event, p1text, p2text FROM v$event_name WHERE name = '...' 解码参数含义
  • 不要假设所有 blocking_session 都指向 DML 语句:可能是 DDL(如 ALTER TABLE)持有 TM 锁,阻塞了后续所有访问该表的会话
  • 对于 library cache lock 类阻塞,blocking_session 可能指向正在做硬解析的会话,此时真正瓶颈是 shared pool 或 SQL 写法,不是锁本身

链越长,越要回到源头看第一个阻塞者的 sql_id 和执行计划,而不是在中间层反复关联。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

oracle

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
C语言变量命名
C语言变量命名

c语言变量名规则是:1、变量名以英文字母开头;2、变量名中的字母是区分大小写的;3、变量名不能是关键字;4、变量名中不能包含空格、标点符号和类型说明符。php中文网还提供c语言变量的相关下载、相关课程等内容,供大家免费下载使用。

2023.06.20

3329

3

c语言入门自学零基础
c语言入门自学零基础

C语言是当代人学习及生活中的必备基础知识,应用十分广泛,本专题为大家c语言入门自学零基础的相关文章,以及相关课程,感兴趣的朋友千万不要错过了。

2023.07.25

2348

9

c语言运算符的优先级顺序
c语言运算符的优先级顺序

c语言运算符的优先级顺序是括号运算符 > 一元运算符 > 算术运算符 > 移位运算符 > 关系运算符 > 位运算符 > 逻辑运算符 > 赋值运算符 > 逗号运算符。本专题为大家提供c语言运算符相关的各种文章、以及下载和课程。

2023.08.02

1300

5

c语言数据结构
c语言数据结构

数据结构是指将数据按照一定的方式组织和存储的方法。它是计算机科学中的重要概念,用来描述和解决实际问题中的数据组织和处理问题。数据结构可以分为线性结构和非线性结构。线性结构包括数组、链表、堆栈和队列等,而非线性结构包括树和图等。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.09

1238

4

c语言random函数用法
c语言random函数用法

c语言random函数用法:1、random.random,随机生成(0,1)之间的浮点数;2、random.randint,随机生成在范围之内的整数,两个参数分别表示上限和下限;3、random.randrange,在指定范围内,按指定基数递增的集合中获得一个随机数;4、random.choice,从序列中随机抽选一个数;5、random.shuffle,随机排序。

2023.09.05

1376

5

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

2023.09.20

2238

7

c语言get函数的用法
c语言get函数的用法

get函数是一个用于从输入流中获取字符的函数。可以从键盘、文件或其他输入设备中读取字符,并将其存储在指定的变量中。本文介绍了get函数的用法以及一些相关的注意事项。希望这篇文章能够帮助你更好地理解和使用get函数 。

2023.09.20

3620

8

c数组初始化的方法
c数组初始化的方法

c语言数组初始化的方法有直接赋值法、不完全初始化法、省略数组长度法和二维数组初始化法。详细介绍:1、直接赋值法,这种方法可以直接将数组的值进行初始化;2、不完全初始化法,。这种方法可以在一定程度上节省内存空间;3、省略数组长度法,这种方法可以让编译器自动计算数组的长度;4、二维数组初始化法等等。

2023.09.22

16655

6

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

2023.09.22

549

3

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程