awr报告中“global cache and enqueue statistics”是集群汇总值,不显示节点维度;需查dba_hist_system_event按instance_number分组定位各节点等待事件耗时,才能识别哪个实例拖后腿。
awr报告里“global cache and enqueue statistics”不显示节点维度?必须用dba_hist_system_event
默认awr报告里的「global cache and enqueue statistics」是集群汇总值,看不出哪个实例在拖后腿。真正能定位节点间锁争用的,是dba_hist_system_event视图——它按instance_number分组存储了每个快照周期内的等待事件累计时间。
关键操作不是翻报告,而是直接查表:
SELECT instance_number, event, SUM(time_waited_micro)/1000000 time_sec
FROM dba_hist_system_event
WHERE event IN ('gc cr block busy', 'gc current block busy', 'enq: TX - row lock contention')
AND snap_id BETWEEN &start_snap AND &end_snap
GROUP BY instance_number, event
ORDER BY time_sec DESC;
注意点:
- 别用
V$SYSTEM_EVENT,那是当前瞬时值,抓不到持续数分钟的负载倾斜 -
time_waited_micro要除以1000000转成秒,否则数值大得没法比 - 限定
SNAP_ID范围,避开空闲时段,聚焦业务高峰期的连续3–5个快照
看到gc cr block busy在节点1远高于节点2,下一步该查什么
这说明节点1正在替节点2做一致性读(CR)构建,本质是负载分配机制失效,不是GC网络慢。先排除应用层绑定问题:
- 查
DBA_SERVICES中对应service的LOAD_BALANCE和FAILOVER_METHOD是否都为YES - 运行
SELECT inst_id, service_name, COUNT(*) FROM gv$session GROUP BY inst_id, service_name,看连接是否全挤在节点1 - 用
DBA_HIST_SQLSTAT查INSTANCE_NUMBER = 1且LOGICAL_READS_DELTA高的SQL,再确认这些SQL在节点2的执行次数是否接近0
如果节点1逻辑读高但gc cr blocks received更高(比如3倍于节点2),而节点2逻辑读只比节点1低20%,基本可以断定:节点2的查询被路由到节点1执行,本地缓存没起作用。
enq: TX - row lock contention排进Top 5,怎么快速锁定阻塞源头节点
AWR报告里的「Top 5 Timed Foreground Events」只告诉你有行锁争用,但不告诉你谁在锁、谁被锁、发生在哪个节点。必须结合DBA_HIST_ACTIVE_SESS_HISTORY反查:
SELECT sample_time, session_id, blocking_session, blocking_instance, sql_id, p1 FROM dba_hist_active_sess_history WHERE event = 'enq: TX - row lock contention' AND sample_time > SYSDATE - 1/24 ORDER BY sample_time DESC;
重点看blocking_instance字段——它就是引发阻塞的源头节点编号。常见陷阱:
-
blocking_session为空 ≠ 没人锁你,可能是自锁(同一会话update后未commit又update) -
p1值需解码:高位2字节是锁模式(如X锁=6),低位2字节是锁类型(TX=108),不能直接当数字理解 - 若
blocking_instance总为1,但节点1的cpu_count明显高于节点2,先算DB CPU / cpu_count比率,再判断是不是真过载
为什么GV$GES_BLOCKING_ENQUEUE比V$GLOBAL_BLOCKED_LOCKS更可靠
V$GLOBAL_BLOCKED_LOCKS在RAC中默认不可用,需要设置隐含参数_enable_global_blocked_locks=true,而这个参数未获Oracle支持,19c后可能被移除,生产环境不建议启用。
真正稳定可用的是GV$GES_BLOCKING_ENQUEUE,它由LMD进程实时维护,反映全局队列层面的真实阻塞关系:
SELECT inst_id, sid, type, id1, id2, blocking_instance, blocking_sid FROM gv$ges_blocking_enqueue WHERE blocking_instance IS NOT NULL;
这里blocking_instance就是死锁环或长阻塞链的起点节点。注意:
- 该视图只显示“正在阻塞别人”的会话,不展示完整等待链,需配合
GV$SESSION.blocking_instance反向追溯被阻塞端 - 如果查询为空但业务明显卡顿,可能是LMD尚未检测到(默认60秒周期),此时应立即抓取AWR快照或手动触发
oradebug dump global_ckpt 1 - 死锁trace文件在
lmd0_*.trc里,不在_ORA_*.trc中,路径是$ADR_HOME/rdbms/<db_name>/<instance_name>/trace/</instance_name></db_name>
节点间锁争用的复杂性在于:它常是应用连接策略、SQL执行计划、段空间管理三者叠加的结果,单看一个指标容易误判。比如gc cr block busy高,可能是节点1缓存太小,也可能是节点2的SQL被错误地路由过去,还可能是位图索引更新引发的跨节点锁放大——得一层层剥开,不能只盯着“锁”字打转。











