为什么 AWR 报告里 DB Time 高但 CPU 不高? 这是一个非常典型的信号:数据库的“时间”都花在等待上了,而不是消耗在 CPU 运算上。简单说,系统正被一些非 CPU 资源卡住了脖子。常见的“堵点”包括 I/O 读写、各类锁(Lock)、闩锁(Latch),或者在 RAC 环境下,网络延
这是一个非常典型的信号:数据库的“时间”都花在等待上了,而不是消耗在 CPU 运算上。简单说,系统正被一些非 CPU 资源卡住了脖子。常见的“堵点”包括 I/O 读写、各类锁(Lock)、闩锁(Latch),或者在 RAC 环境下,网络延迟和全局资源争用会成为更突出的问题。
尤其在 RAC 架构中,一些在单实例环境中不明显的等待事件,比如 gc buffer busy acquire(全局缓存忙等待)或 enq: tx - row lock contention(行锁争用),会因为跨节点通信而被显著放大,成为性能瓶颈的罪魁祸首。
长期稳定更新的攒劲资源: >>>点此立即查看<<<
那么,具体该怎么排查呢?
Top 5 Timed Foreground Events 部分,重点筛选那些带有 gc(Global Cache)或 ges(Global Enqueue Service)前缀的等待事件,它们直接指向了跨实例的资源争用。SELECT * FROM GV$SYSTEM_EVENT WHERE EVENT LIKE 'gc%' OR EVENT LIKE 'ges%';,这能帮你看清各个节点上实时发生的全局等待事件分布,定位热点。CLUSTER_DATABASE 参数已设置为 TRUE,并且所有实例的 INSTANCE_NUMBER 是唯一的。听起来很基础,但配置错误恰恰是导致 GES(全局队列服务)队列异常堆积的常见原因之一。这两个属于 Oracle RAC 的隐含参数,它们直接影响着“缓存融合”(Cache Fusion)的核心行为,调整起来需要格外谨慎。
_gc_policy_time 控制着数据块在节点间自动迁移的触发频率,默认是 300 秒。而 gc_files_to_locks 则决定了为每个数据文件分配多少全局锁(global locks),这个数量会直接影响并发 DML 操作的效率。
这里有个常见的误区:一看到全局锁争用,就想着调大 gc_files_to_locks 来“缓解”。这种做法非常危险,很可能导致 GES 队列过载,甚至引发整个实例挂起(hang)。
安全的调整策略应该是:
SHOW PARAMETER gc_files_to_locks 查看当前值。如果结果显示为 *,恭喜你,这表示系统正在使用默认的自动计算模式,在大多数情况下,保留这个设置是最稳妥的选择。enq: HW - contention(高水平锁争用)或 enq: SQ - contention(序列缓存争用)这类等待事件,高度集中在少数几个特定数据文件上时,才考虑为这些文件单独指定锁的数量。例如:ALTER SYSTEM SET gc_files_to_locks='1=200,3=500' SCOPE=SPFILE;。_gc_policy_time,原则上不建议修改。如果业务数据访问具备极强的局部性特征(例如,某个节点固定处理某一批客户的数据),可以尝试将其增大到 600 至 1800 秒,以减少不必要的块迁移。但切记,这必须建立在私网连接(通过 CLUSTER_INTERCONNECTS 参数设置)绝对稳定可靠的前提下。看到这个状态先别慌,它通常意味着 RAC 集群中某个实例发生了意外崩溃,而其他存活实例正在协同回滚该崩溃实例上未提交的事务。本质上,这是 RAC 高可用性机制的一部分。
所以,这并非系统“卡住”,而是一个正常的恢复过程。当然,如果这个过程持续数小时仍未完成,那就不正常了。其根本原因,往往出在 undo 表空间不足、undo_retention 设置过短,或者存在超长事务,阻塞了回滚段的清理工作。
遇到这种情况,可以按以下步骤快速应对:
SELECT * FROM GV$TRANSACTION WHERE STATUS = 'ACTIVE' AND START_TIME < SYSDATE - 1/24;,找出那些运行时间超过 1 小时的活跃事务,它们很可能是恢复缓慢的元凶。SELECT TABLESPACE_NAME, ROUND((BYTES-FREE_BYTES)/BYTES*100,2) USED_PCT FROM GV$TABLESPACE_USAGE;。空间不足会严重拖慢恢复。ALTER SYSTEM SET "_smu_debug_mode" = 4 SCOPE=MEMORY;。这个隐藏参数(仅适用于 Oracle 11gR2 及以上版本)可以加速 SMU(System Monitor Undo)进程对回滚段的清理。请注意,这是内存级修改,重启后失效,仅作为临时救急之用。这是 RAC 调优中最容易踩坑的地方。RAC 是一个“共享一切但调度独立”的复杂架构。举个例子,GV$SESSION 视图可能显示某条 SQL 在节点 1 上执行缓慢,但真正的瓶颈却可能藏在节点 2——因为这条 SQL 要访问的表分区,其数据块主要缓存在节点 2 的本地 Buffer Cache 中,导致节点 1 不得不频繁发起 gc current request 来远程获取数据块。
如果只盯着单个实例的视图看,就相当于只看了一张网络拓扑图的一半,结论必然是片面的。
正确的分析姿势应该是:
GV$(全局视图)而非 V$(实例视图),并且一定要加上 INST_ID 进行分组统计。例如:SELECT INST_ID, EVENT, COUNT(*) FROM GV$SESSION_WAIT GROUP BY INST_ID, EVENT ORDER BY COUNT(*) DESC;,这样才能看清等待事件在集群中的分布。SELECT * FROM GV$SQL_MONITOR WHERE STATUS = 'EXECUTING' ORDER BY ELAPSED_TIME DESC;,可以帮助你快速发现同一条 SQL 在不同节点上执行时间差异巨大的情况,这往往是数据分布或参数设置不均导致的。GV$LOCK 和 GV$ENQUEUE_LOCK 这些视图中,那些 INST_ID 不同但 ADDR(锁地址)相同的记录,这清晰地标示出了一条跨节点的锁等待链条。说到底,RAC 性能问题的复杂性,往往不在于某个参数的具体值,而在于参数生效范围与多个实例间状态同步的滞后性。修改任何一个参数前,一个黄金法则是:先确认它是否真的在所有节点上被识别、加载并生效了。执行一句 SELECT NAME, VALUE, ISDEFAULT FROM GV$PARAMETER WHERE NAME = 'xxx'; 进行核对,远比盲目重启所有实例要节省得多的时间,也稳妥得多。
侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述