如何分析RAC中的GCS与GES进程_全局缓存服务与全局队列服务机制


GCS 和 GES 是 Oracle RAC 中由 lms 和 lmd 进程动态承担的全局缓存与队列服务职责,非独立进程;其实际工作负载需通过 V$SYSSTAT 等视图观测,而非进程数量或内核栈。

怎么看 GCS 和 GES 进程在 RAC 里实际干了啥

oracle rac 中的 gcs_server_process(gcs)和 ges_server_process(ges)不是独立可配置的服务,而是由后台进程 lms(global cache service)和 lmd(global enqueue service)动态承担的职责。它们不单独启停,也不对应独立进程名——ps -ef | grep lms 看到的每个 lms0lms1 都同时处理 gcs 请求;同理,lmd0 是 ges 的主协调者。

  • 查当前活跃角色:用 SELECT * FROM V$PROCESS WHERE PROGRAM LIKE '%lms%' OR PROGRAM LIKE '%lmd%';,注意 PROGRAM 字段里的 lms 就是 GCS,lmd 就是 GES
  • 别去 /proc/<pid>/stack 里翻调用栈找“GCS”字样——内核态堆栈里不会出现这种业务层标签,只会看到 kslwtbctxkjmx... 这类内部函数
  • 真正反映工作负载的是 V$SYSSTAT 里的 gc cr block received(GCS)、global enqueue gets sync(GES),不是进程数

为什么 lms 进程数突然涨到 8 个还持续高 CPU

这不是异常,是 Oracle 根据实例负载自动派生的。默认 gcs_server_processes 参数为 0,表示“按需启动”,上限由 _lm_lms_max(隐含参数,通常 8~16)控制。当出现大量跨实例块请求(比如频繁的 SELECT /*+ FULL(t) */ 扫描同一张表)、或某个节点频繁做 block cleanout,lms 就会 fork 新线程分担压力。

  • 确认是否真过载:先看 V$SYSMETRICGlobal Cache Average CR Get Time (ms) 是否持续 > 5ms,而不是只盯 lms 数量
  • 常见诱因:未绑定分区的全局索引 DML、RAC 中使用 SEQUENCE.NEXTVAL 无缓存、大事务未及时提交导致 GES 锁队列堆积
  • 别手动设死 gcs_server_processes=4——这会把所有 GCS 工作压给固定几个 lms,反而造成单点瓶颈和更高延迟

GES 死锁检测日志里出现 “kjzdupt: kjzdupt: kjzdupt: …” 循环

这是 lmd0 在反复尝试解析一个复杂分布式锁依赖图时触发的内部重试,不是死循环 bug。典型场景是多个实例同时对同一组数据块(比如一个父表+多个子表)执行 DML,且事务隔离级别为 SERIALIZABLE 或用了 SELECT FOR UPDATE

  • 关键线索藏在 trace 文件名里:ora_<pid>_<inst>.trc 中的 <inst> 表示哪个实例最先卡住,不是本机
  • 检查 V$GES_BLOCKING_ENQUEUE 而不是只看 V$LOCK——后者只显示本地锁,前者才体现跨实例持有/等待关系
  • 避免该现象:应用层减少长事务,改用 FOR UPDATE SKIP LOCKED,或者对热点行加应用级 hash 分片(如按 user_id % 4 分库逻辑)

AWR 报告里 GCS 和 GES 相关等待事件占比高,但 SQL 没明显问题

说明瓶颈不在 SQL 执行计划,而在数据物理分布或缓存策略。比如 gc current block 2-way 高,大概率是两个实例反复争抢同一数据块;enq: TX - row lock contention 高但没查到阻塞 SQL,则可能是 GES 在协调分布式事务回滚时卡住。

  • 优先查 V$SEGMENT_STATISTICS,过滤 STATISTIC_NAME IN ('gc cr blocks received', 'gc current blocks served'),定位具体对象(表/索引)
  • 对比 DBA_HIST_SEG_STAT 历史趋势,确认是最近上线功能引入的访问模式变化,还是统计信息过期导致 CBO 选错执行路径(从而引发更多远程块请求)
  • 别一上来就调 _gc_policy_time_gc_undo_affinity——这些隐含参数改动风险高,且 Oracle 12c 后多数已自动优化,先做对象级分析更稳妥

真正难的从来不是数清有几个 lms,而是判断这些进程是在高效搬运块,还是在无效地推着同一块来回跑。很多性能问题表面是 GCS/GES 慢,根子其实在应用没做实例亲和,或者 DBA 忘了某张表根本没做分区。