必须用ash的current_file#和current_block#定位物理块,过滤event in ('buffer busy waits', 'read by other session')且sample_time > sysdate - 1/24,聚合取top5;再通过dba_extents区间匹配查段名,p3值决定根因类型。

热块争用不是SQL写得不好,而是多个会话在抢同一个物理数据块——必须用 v$active_session_history 的 current_file# 和 current_block# 定位到具体块,否则调索引、加 buffer cache 都是白忙。
怎么从ASH里捞出真实的file#/block#?
ASH 不直接暴露“热点块ID”,current_file# 和 current_block# 是唯一能反推物理位置的字段。别查 sql_text 或模糊匹配事件名,那只会绕远路。
- 过滤条件必须是
event IN ('buffer busy waits', 'read by other session'),不能只写'buffer busy waits'——'read by other session'常伴随逻辑读争用,漏掉它会丢关键样本 - 时间范围严格控制在最近 1 小时内:
sample_time > SYSDATE - 1/24,避免历史噪声淹没真实热点 -
current_obj# = 0不代表没对象,可能是刚进入逻辑读、还没绑定段名,这时更要盯紧current_file#和current_block# - 聚合时加
FETCH FIRST 5 ROWS ONLY,避免全表扫:SELECT current_file#, current_block#, COUNT(*) cnt FROM v$active_session_history WHERE event IN ('buffer busy waits', 'read by other session') AND sample_time > SYSDATE - 1/24 GROUP BY current_file#, current_block# ORDER BY cnt DESC FETCH FIRST 5 ROWS ONLY;
如何把file#/block#映射到真实段和对象?
不能用 DBA_OBJECTS.object_id = current_obj# 关联——current_block# 是逻辑块号,而对象 ID 和块号之间没有直接等值关系。必须走 DBA_EXTENTS 做区间匹配。
- 查询条件必须是
&BLOCK_ID BETWEEN block_id AND block_id + blocks - 1,不是= block_id;一个块只属于一个 extent,但可能跨多个 segment(比如分区表) - 记得带上
file_id = &FILE_ID,否则结果不唯一 - 如果查不到结果,说明该块属于系统段:回滚段、临时段或 UNDO 块,此时要转向
v$rollstat或v$tempseg_usage - LOB 段要额外处理:先查
DBA_LOBS找真实段名(如SYS_LOB0000098765X$$),再对其分析;单独改 LOB 列存储参数无效SELECT s.segment_name, s.partition_name, s.segment_type FROM dba_extents s WHERE &BLOCK_ID BETWEEN s.block_id AND (s.block_id + s.blocks - 1) AND s.file_id = &FILE_ID;
P3 值为什么不能跳过?
P3 在 Oracle 12c 中是 class#(块类型编号),不是原因码。跳过这步就动手调参,基本白忙。
-
P3 = 1:普通数据块热,常见于升序主键INSERT或小表全扫 -
P3 = 4:段头争用,说明还在用 MSSM 表空间,FREELIST是单点瓶颈 -
P3 = 220:索引叶块热,不是重建索引就能解决,得看是否因INITRANS不足或PCTFREE过低导致分裂频繁 - 查
P3必须关联原 ASH 记录,不能靠猜:SELECT current_file#, current_block#, p3, COUNT(*) FROM v$active_session_history WHERE event IN ('buffer busy waits', 'read by other session') AND sample_time > SYSDATE - 1/24 AND current_file# = &FILE_ID AND current_block# = &BLOCK_ID GROUP BY current_file#, current_block#, p3;
真正难的不是查出哪几个块热,而是区分这些块属于什么类型、谁在争、争的是什么资源——current_file# 和 current_block# 只是起点,P3 才是分水岭,漏掉它,所有后续动作都可能南辕北辙。











