<p>查不到 enq: TX - index contention 并不表示无索引分裂,因该事件仅在右侧热点(如递增主键+高并发插入)引发ITL争用时高频出现;50-50分裂、分支节点分裂等多数分裂不触发此等待,真实痕迹常体现为buffer busy waits、gc current block 2-way或db file sequential read配合异常高BLKS_GETS_PER_ACCESS。</p>

查不到 enq: TX - index contention 就代表没分裂?
不是。这个事件只在右侧热点(比如递增主键+高并发插入)触发 ITL 争用时才高频出现;很多索引分裂根本不会产生它,尤其 5-5 分裂或枝节点分裂。更常见的运行时痕迹是:buffer busy waits(集中在索引段头块或叶块)、gc current block 2-way(RAC 环境下新右块跨节点读取)、db file sequential read 配合异常高的 BLKS_GETS_PER_ACCESS(说明叶块物理不连续)。别盯着一个 event,要组合 current_obj#、sql_id 和 session_state = 'ON CPU' 看是否真在索引维护路径上。
为什么 V$ACTIVE_SESSION_HISTORY 查不到最近的分裂线索?
三个常见原因都和采样机制与内存有关:
• 没加时间过滤:默认只保留约 1 小时数据,高负载下缓冲区满得快,必须显式写 WHERE sample_time > SYSDATE - 1/1440(过去 1 分钟);
• _ash_size 太小:查 SELECT * FROM v$sgastat WHERE name LIKE '%ASH%',如果 bytes 长期低于 10MB,采样丢失率就很高;
• 分裂太短:单次 90-10 分裂可能仅耗几毫秒,而 ASH 是每秒采样一次,大概率错过。这时得退一步,用 ANALYZE INDEX VALIDATE STRUCTURE 查 INDEX_STATS,看 DEL_LF_ROWS_LEN / LF_ROWS_LEN 是否 >20%,这才是空间未复用的铁证。
怎么把 ASH 数据和具体索引真正关联起来?
不能只靠 current_obj# 对应到索引名就结束,必须验证访问是否真落在叶块上:
• 先查出可疑 sql_id 涉及的索引:SELECT object_name, object_type FROM dba_objects WHERE object_id IN (SELECT current_obj# FROM v$active_session_history WHERE sql_id = '84m7xzxz0181g' AND sample_time > SYSDATE - 1/24 GROUP BY current_obj#);
• 再确认该索引是否正在被 DML 访问:SELECT index_name, monitoring FROM dba_indexes WHERE table_name = 'YOUR_TABLE',若 monitoring = 'YES',说明近期有大量更新;
• 最后看执行计划里是否用了该索引做范围扫描或唯一扫描——如果只是 INDEX FAST FULL SCAN,那等待大概率跟分裂无关。
哪些参数或配置会让分裂更隐蔽、更难诊断?
几个容易被忽略但影响诊断的关键点:
• PCTFREE 在分裂时会被忽略,所以即使设了 20%,9-1 分裂仍会把旧块塞到接近 100%;
• 反向索引(REVERSE KEY)能缓解 enq: TX - index contention,但会导致 CLUSTERING_FACTOR 恶化,引发大量 db file sequential read,掩盖真实分裂信号;
• RAC 环境下,gc cr request 和 gc current request 等待常与分裂交织,但它们本身不等于分裂——需结合 current_obj# 和 sql_id 确认是否同一批会话;
• Oracle 11.2.0.4 存在 Bug 24555417,MMON 异常留下的 pin 锁会让后续分裂 hang 住,表现为长时间 gc buffer busy acquire,此时 AW R 中分裂次数并不高,但等待延时极高。


















