awr报告中通过「top 5 timed foreground events」和「global cache and enqueue statistics」定位gc等待:gc current block busy高表明修改热点块争用,gc cr block busy高反映cr构建慢,gc buffer busy acquire上升提示本地lru竞争;需结合ash查秒级尖峰,用p1/p2反查争用对象,注意不同事件中p1/p2含义差异;关键调优参数包括_gc_read_mostly_locking、gc_files_to_locks及db_cache_size比例;应用层须避免单点序列和单调主键引发的gc放大。
awr报告里怎么看gc等待事件
oracle rac中性能瓶颈常藏在全局缓存(global cache)层面,而gc buffer busy acquire、gc cr block busy、gc current block busy这几类等待是核心线索。别只盯着db cpu或i/o,先打开awr报告的「top 5 timed foreground events」和「global cache and enqueue statistics」两节。
重点看:
- gc current block busy 高说明某节点频繁修改同一数据块,其他节点在等当前持有者释放;
- gc cr block busy 高往往意味着热点块被反复读取且CR构建慢,可能和高事务并发+低_gc_read_mostly_locking有关;
- gc buffer busy acquire 上升通常指向块争用+本地LRU链竞争,不一定是GC本身问题,但会放大GC延迟。
注意:AWR默认每小时采样一次,若问题只发生在秒级尖峰,需用ASH(v$active_session_history)按分钟甚至秒查,配合sample_time和event过滤。
如何定位具体争用的数据块和对象
光知道有GC等待不够,得锁定物理块。从dba_hist_active_sess_history或实时v$session_wait中提取p1(file#)、p2(block#)后,用以下语句反查对象:
SELECT owner, segment_name, segment_type FROM dba_extents WHERE file_id = &file_id AND &block_id BETWEEN block_id AND block_id + blocks - 1;
常见陷阱:
- p1和p2在不同等待事件中含义不同,比如gc current block busy的p1是file#,但gc buffer busy acquire的p1是class#,必须查v$event_name确认;
- 分区表/索引容易漏掉分区名,建议连partition_name一起查;
- 若块属于undo段,说明是回滚段争用,需检查undo_retention和UNDO表空间自动扩展策略。
调整哪些参数能缓解GC压力
参数不是越多越好,关键三处下手:
- 启用_gc_read_mostly_locking=TRUE(12cR2+默认开启),对只读频繁、更新极少的大表启用“读为主”锁模式,大幅减少CR块传输;
- 调整gc_files_to_locks:默认"_small"="100M"_big="2G",若发现大量小文件争用,可显式设为"100:10000"让每个文件分配更多锁,避免锁资源耗尽;
- 控制db_cache_size与shared_pool_size比例:RAC中过大的buffer cache反而加剧GC消息量,建议db_cache_size不超过物理内存的60%,留足给IPC和GCS进程。
切记:所有带下划线_的参数属隐藏参数,修改前务必在测试环境验证,且需配合ALTER SYSTEM FLUSH BUFFER_CACHE观察效果,不能只看参数值变化。
应用层配合:为什么序列和主键设计影响GC性能
RAC里最隐蔽的GC放大器是单点序列(sequence.NEXTVAL)和单调递增主键。每次取值都触发gc current block 2-way——因为序列高速缓存(cache)太小或未设order,导致各节点频繁跨实例同步。
实操建议:
- 序列必须设CACHE 1000以上,禁用ORDER(除非业务强依赖顺序);
- 主键改用SYS_GUID()或应用层UUID,避开索引右边界争用;
- 若必须用数字主键,考虑用MOD(SEQ.NEXTVAL, N)分片,或直接建N个序列按节点轮询。
这点最容易被DBA忽略:调了一堆底层参数,结果应用还在用seq.nextval每秒生成10万条记录,GC等待纹丝不动。











