Oracle RAC(Real Application Clusters)允许多个实例在不同节点上同时打开同一个数据库,那么当两个实例都要修改同一份数据时,数据一致性是如何保证的?答案藏在缓存融合(Cache Fusion)机制中,而支撑缓存融合的两大核心服务就是GCS(Global Cache Service,全局缓存服务)和GES(Global Enqueue Service,全局队列服务)。理解这两个服务以及背后的后台进程,是排查RAC性能问题和理解其内部运行逻辑的基础。

一、GCS是什么:负责数据块的全局协调
GCS的全称是Global Cache Service,即全局缓存服务。它的核心职责是管理数据块在各个实例之间的传递和一致性控制。在单实例数据库中,一个数据块只存在于一个SGA中,一致性读只需要构造回滚信息即可;但在RAC环境中,同一个数据块可能同时被多个实例的Buffer Cache持有,这时就必须有一个全局的仲裁者来记录:某个块当前在哪个实例、以什么模式被持有、是否是最新版本。
GCS维护的就是这样一份全局信息,实际数据由其中的GRD(Global Resource Directory,全局资源目录)来记录。当实例A需要读取一个数据块,而这个块最新的版本在实例B的缓存中时,GCS会协调实例B通过网络直接把这个块传给实例A,这就是缓存融合中读操作的实现,块在实例间流动而不需要落盘再读。
对于写操作,GCS通过Past Image(PI)和SCN版本链来保证一致性。一个块可以被多个实例以共享模式持有,但只能有一个实例以排他模式修改。当块需要写盘时,GCS会确保持有最新版本的实例执行写入,并协调持有旧版本镜像的实例释放资源。GCS相关的工作主要由LMSn进程完成,这也是RAC中最繁忙的后台进程之一。
二、GES是什么:负责锁与队列的全局管理
GES的全称是Global Enqueue Service,即全局队列服务。如果说GCS管的是“数据块”,那么GES管的就是“除数据块之外的所有资源”,包括库缓存锁、行级锁的队列、事务队列、DDL锁等。比如两个会话在不同实例上更新同一行记录,行锁的申请与等待就是由GES来协调的。
GES同样依赖GRD来记录资源的状态,包括资源的属主(Master)节点、持有者和等待者信息。当某个资源发生争用时,GES负责在实例间传递锁请求、转换锁模式,并在适当时候执行死锁检测。GES的存在让原本单实例中的锁机制扩展到了集群层面,保证多实例并发操作时的事务隔离性。
支撑GES的进程主要有两个:LMD负责处理来自其他实例的锁资源请求消息,也就是全局队列的日常事务;LMON则负责监控整个集群和GES的健康状态,当节点发生故障或加入离开时,LMON驱动重新配置流程,重新分布GRD资源并恢复集群一致性,这个动作也就是常见的Instance Recovery的一部分触发来源。
三、支撑GCS与GES的关键后台进程
RAC环境中有一组特有的后台进程,与传统的单实例进程共同工作。除了前面提到的LMS、LMD、LMON,还有LCK、LMSH等,下面逐一说明它们的分工。
LMSn(Lock Manager Server):这是GCS的执行者,负责在实例间传递数据块。当远端实例请求块时,LMS进程从本实例的Buffer Cache中找到块并打包发送过去。LMS进程的默认数量与CPU数量相关,高负载的OLTP系统经常能看到LMS进程CPU占用较高。可以通过以下SQL查看当前实例的LMS进程:
-- 查看当前实例的LMS进程 SELECT pid, spid, pname FROM v$process WHERE pname LIKE 'LMS%';
LMD(Lock Manager Daemon):这是GES的执行者,处理全局锁请求消息。当会话申请的行锁或队列资源被其他实例持有时,请求会被发给资源Master节点的LMD进程进行仲裁。LMD繁忙往往意味着跨实例的锁争用比较严重。
LMON(Lock Monitor):集群的监控者,持续检测节点间心跳。一旦发现节点异常,LMON会发起重新配置,配合其他节点重新分配GRD,保证故障节点持有的资源被正确清理。日志中的"Reconfiguration"事件通常就是LMON驱动的。
LCK(Lock Process):负责管理非缓存融合类型的资源请求,比如库缓存对象、数据字典锁、结果缓存等。它处理的资源粒度比LMS更大,通常不是块级别的。可以用下面语句观察各进程的负载情况:
-- 观察RAC各后台进程的活动情况
SELECT pname, COUNT(*) AS cnt
FROM v$bgprocess
WHERE pname IN ('LMS','LMD','LMON','LCK','LMSH')
GROUP BY pname;
四、从等待事件看GCS与GES的运行状态
日常运维中,判断GCS和GES是否成为瓶颈,最直接的入口是等待事件。GCS相关的典型等待是gc buffer busy acquire、gc buffer busy release、gc cr grant 2-way、gc current block busy等,这些等待高通常说明块在实例间争抢激烈,常见原因包括热点块、应用设计导致同一数据被多个实例频繁访问。
GES相关的典型等待包括enq: TX - row lock contention、DFS lock handle、gc enqueue等。其中TX行锁争用如果发生在跨实例之间,往往需要从应用层面排查,比如不同节点上的会话互相更新同一批行,形成交叉锁等待,严重时会触发全局死锁检测,由LMON和LMD协同发现并终止其中一个会话。
排查时可以结合v$segment_statistics和gc相关视图定位热点对象:
-- 查找gc等待较高的段对象 SELECT owner, object_name, statistic_name, VALUE FROM v$segment_statistics WHERE statistic_name LIKE 'gc%' AND VALUE > 10000 ORDER BY VALUE DESC;
处理思路一般是三类:一是通过分区、Hash分布改造热点块;二是利用服务(Service)将访问相同数据的应用固定到同一节点,减少跨实例传输;三是检查应用事务顺序,避免跨实例的死锁交叉。理解了GCS与GES的分工,再看这些等待事件时就有了明确的指向性:gc开头的等待往GCS和块传递上查,enq和锁相关的等待往GES和应用逻辑上查。
总的来说,GCS与GES是RAC缓存融合的两条主线:GCS管数据块的流动与一致性,由LMSn执行;GES管锁与队列的协调,由LMD执行、LMON守护。掌握这两个服务的职责边界和对应进程,无论是读AWR报告还是处理节点间争用,都会清晰很多。
Oracle RACGCS进程GES进程修改时间:2026-09-06 09:22:36