Oracle RAC中的全局资源目录(GRD)与PCM锁管理

在这里插入图片描述


第一部分:官方严谨的详细阐述

一、 核心概念:为什么需要GRD和PCM锁?

在单实例数据库中,缓冲区缓存(Buffer Cache)是私有的。一个数据块在内存中只有一份副本,由本地的锁(如行锁)和闩锁(Latch)来管理并发。

在RAC环境中,同一个数据块可能同时存在于多个实例的缓冲区缓存中。这就带来了严峻的缓存一致性(Cache Coherency) 问题:如何保证一个实例对块的修改能立即被其他持有该块旧版本的实例知晓?GRD和PCM锁就是为解决这个问题而生的。

二、 全局资源目录(GRD - Global Resource Directory)
  1. 定义与作用: GRD是一个分布式的内存结构,其内容分布在所有RAC实例的SGA中。它是RAC的“大脑”,记录着所有被缓存数据块的全局状态信息。没有一个实例拥有完整的GRD,每个实例只负责管理一部分资源(数据块)的目录信息。

  2. 资源主节点(Master Instance)

    • GRD的核心设计是资源主控(Resource Mastery)。每一个数据块(更精确地说,每一个“资源”,通常对应一个数据块)都有一个唯一的主实例(Master Instance)
    • 主实例是该资源的“权威”。它拥有该资源最完整、最新的状态信息(即PCM锁信息),并负责协调所有对此资源的全局并发访问请求。
    • 资源的主节点不是静态的,会根据系统负载进行动态重主控(Dynamic Remastering),例如通过_lm_dynamic_remastering参数控制。
三、 PCM锁(Parallel Cache Management Lock)

PCM锁是GRD中记录的核心信息。它不是传统的行级锁(TX锁),而是用于维护缓存一致性的锁。

  1. 锁的模式(Lock Modes): PCM锁有几种模式,代表了实例对数据块的“访问权限”:

    • N(Null)模式: 实例仅拥有块的只读副本(Past Image)。如果主实例要求,该副本可以被丢弃。这是权限最低的状态。
    • S(Shared)模式: 实例拥有块的一致读副本(Consistent Read)。多个实例可以同时持有同一个块的S锁。可以用于查询。
    • X(Exclusive)模式: 实例拥有块的当前可修改副本(Current Image)。只有一个实例可以持有某个块的X锁。这是进行UPDATE, DELETE, INSERT操作的前提。
    • 其他模式: 如SS(Shared Shared)、SLX(Shared Limited Exclusive)等,用于更细粒度的控制。
  2. 锁的转换(Lock Conversion): RAC中的大多数活动都涉及PCM锁模式的转换。例如:

    • 一个实例想要修改一个当前处于S模式的块,它必须请求将锁模式从S升级到X
    • 这个请求会被发送到该资源的主实例
    • 主实例会检查该资源的全局锁状态。如果没有任何其他实例持有该块的X锁(或SSX等冲突模式),主实例会:
      a) 授予请求实例X锁。
      b) 向所有持有该块S锁或N锁的实例发送无效化消息(Invalidation Message),要求它们降级锁模式或丢弃块的副本(强制其下次访问时重新从磁盘或拥有当前版本的实例获取)。
四、 Cache Fusion的完整工作流程举例

假设一个2节点RAC:实例1(INST1)和实例2(INST2)。一个数据块最初在实例1的缓存中。

  1. 场景: 一个用户在实例2上执行 UPDATE employees SET salary = 10000 WHERE employee_id = 123;,而该行所在的块在实例1的缓存中。

  2. 详细过程

    • 第1步: 实例2的服务器进程在本地缓存中找不到该块。它向该块的主实例(假设是实例1)发出请求,要求以X模式获取该块的PCM锁。
    • 第2步: 主实例(INST1)查看GRD,发现当前实例1正以S模式持有该块(假设之前被查询过)。
    • 第3步: 主实例(INST1)协调锁转换:
      • 它要求实例1将其锁从S模式降级为N模式(Null模式)。
      • 实例1降级成功后,会将其拥有的块的当前副本通过私网互联(Interconnect)直接发送给实例2。这就是 “缓存融合” 的本质——数据块在实例间直接传输,避免了物理读盘。
      • 主实例(INST1)更新GRD中该资源的锁状态,标记为实例2现在以X模式持有。
      • 主实例(INST1)授予实例2 X锁。
    • 第4步: 实例2现在获得了块的当前副本和X锁,可以在内存中修改该块,生成重做日志。此时,实例1的块副本就变成了“Past Image”(PI),它不会被写入磁盘,但会被保留一段时间以防实例2的修改丢失。
五、 场景、争用、排查与解决

RAC的性能问题大多围绕全局缓存等待事件(Global Cache Wait Events)

1. 全局缓存争用(Global Cache Contention)
  • 争用原因: 多个实例频繁请求同一组数据块(热点块)的X锁。
  • 等待事件
    • gc current block busy / gc cr block busy: 请求一个块(Current或Consistent Read版本),但该块正被另一个实例繁忙地处理(例如正在被写入),导致请求必须等待。
    • gc buffer busy: 类似于单实例的buffer busy wait,但发生在全局缓存层面。一个实例正在从另一个实例请求一个块,但目标实例的缓冲区正被另一个进程访问(例如,正在被DBWR写入或正被另一个会话pin住)。
  • 具体影响: 应用程序响应时间变慢,Interconnect网络流量增大,CPU使用率升高。
  • 排查
    • 查询 GV$VIEWGV$SEGMENT_STATISTICS 定位热点对象。
    -- 查找全局缓存等待最多的对象
    SELECT obj.owner, obj.object_name, obj.object_type,
           bh.blocks, bh.status,
           SUM(gc.current_blocks) current_blocks,
           SUM(gc.cr_blocks) cr_blocks
    FROM gv$bh bh, dba_objects obj, gv$segment_statistics gc
    WHERE bh.objd = obj.data_object_id
      AND gc.owner = obj.owner
      AND gc.object_name = obj.object_name
      AND gc.statistic_name IN ('gc current blocks received', 'gc cr blocks received')
    GROUP BY obj.owner, obj.object_name, obj.object_type, bh.blocks, bh.status
    ORDER BY 6 DESC; -- 按current blocks排序
    
    -- 查看全局缓存等待事件
    SELECT inst_id, event, total_waits, time_waited, average_wait
    FROM gv$system_event
    WHERE event LIKE 'gc%' AND total_waits > 0
    ORDER BY time_waited DESC;
    
  • 解决
    • 应用设计: 这是根本。避免热点块!使用序列填充主键而非日期,考虑分区(Partitioning)将数据分散到不同的物理块上。
    • 参数调整: 适当增大 LOG_BUFFERDB_CACHE_SIZE,减少检查点频率。
    • 使用亲和力(Affinity): 如果可能,让修改特定数据的会话总是连接到同一个实例(例如,按分公司ID连接),使PCM锁请求本地化。
2. 资源主节点争用
  • 争用原因: 某个实例成为大量资源的主节点,导致所有锁请求都涌向该实例,使其LMS(Global Cache Service)进程过载。
  • 等待事件gc remaster time 或一般的 gc current/ cr block 2-way/3-way 等待时间过长。
  • 排查: 查看 GV$GCSPFMASTER_INFO 视图,分析资源主节点的分布情况。
    -- 查看每个实例主控的资源数量
    SELECT inst_id, count(*) mastered_count
    FROM gv$gcsresource
    GROUP BY inst_id;
    
  • 解决
    • 确保 _lm_dynamic_remastering 参数为 TRUE(默认是),允许动态重主控。
    • 重启实例可能会触发重平衡。
六、 常用管理SQL语句
-- 1. 查看RAC实例状态和服务
SELECT inst_id, instance_name, host_name, version, status, startup_time FROM gv$instance;

-- 2. 监控全局缓存服务(LMS)进程
SELECT * FROM gv$ges_process;
SELECT * FROM gv$shared_server WHERE name LIKE 'LMS%';

-- 3. 实时查看全局缓存等待的会话
SELECT s.inst_id, s.sid, s.serial#, s.event, s.p1, s.p2, s.p3, s.seconds_in_wait
FROM gv$session s
WHERE s.event LIKE 'gc%'
AND s.wait_class <> 'Idle';

-- 4. 查看数据块在集群中的分布情况
SELECT inst_id, status, count(*) blocks, dirty
FROM gv$bh
WHERE objd = (SELECT data_object_id FROM dba_objects WHERE object_name='YOUR_TABLE')
GROUP BY inst_id, status, dirty
ORDER BY inst_id, status;

-- 5. 查看PCM锁的详细统计信息
SELECT * FROM gv$lock_activity;
SELECT * FROM gv$resource_limit WHERE resource_name LIKE 'ges_%';

第二部分:通俗易懂的解释

让我们用一个比喻来理解这个复杂的机制。

把RAC数据库想象成一个大型图书馆的协作系统。

  • 数据块: 一本本的书。
  • 实例的缓冲区缓存: 每个分馆(实例)自己的阅览区。读者可以在这里看书。
  • 磁盘: 图书馆的中央书库

单实例图书馆(传统数据库): 只有一个分馆。所有读者都来这里。阅览区的书的管理很简单。

RAC图书馆(多实例): 有多个分馆(实例1, 实例2)。读者可以去任何分馆。

GRD(全局资源目录): 这是一个分布式的图书管理系统。这个系统记录了:

  • 每本书《哈利波特》现在在哪个分馆的阅览区?(块在哪个实例的缓存中)
  • 那本《哈利波特》是只能看(S锁),还是正在被批注(X锁)?

PCM锁: 就是图书管理系统里记录的借阅状态

  • S状态(Shared): 书在分馆1的阅览区,可以阅览,但不能批注。其他分馆可以申请复印一份(获得S锁)。
  • X状态(Exclusive): 书在分馆1的阅览区,正在被一位读者用笔批注。其他分馆既不能看也不能批注。

资源主节点: 图书管理系统指定分馆1为《哈利波特》这本书的总负责分馆。所有关于这本书的借阅状态查询和更改申请,都要报到分馆1的馆长(LMS进程)这里来审批。

Cache Fusion工作流程(例子)

  1. 一个读者在分馆2说:“我想批注《哈利波特》。”(实例2要UPDATE)
  2. 分馆2的员工查询图书管理系统(GRD),系统说:“找分馆1的馆长,他是这本书的总负责。”
  3. 分馆2的员工打电话给分馆1的馆长(LMS进程):“我们想批注《哈利波特》。”(请求X锁)
  4. 分馆1的馆长查看记录,发现这本书正在分馆1的阅览区,处于“可以看”的状态(S锁)。
  5. 分馆1的馆长做两件事:
    a) 让分馆1阅览区里的《哈利波特》立刻下架,打包好(锁降级为N)。
    b) 通过馆际快递(Interconnect),直接把这本书寄给分馆2(缓存融合传输)。
  6. 分馆1的馆长在系统(GRD)中更新:《哈利波特》现在在分馆2,状态为“正在批注”(X锁)。
  7. 分馆2收到书,交给读者批注。

争用是什么?

  • gc current block busy: 分馆2打电话申请批注,分馆1的馆长说:“等一下,我们分馆的读者正在书上写字呢,写完了半页才能寄给你。”(另一个实例正在修改块,请求需要等待)
  • 热点块争用: 所有人都想批注《哈利波特》,分馆1的馆长(主实例)的电话被打爆了(LMS进程繁忙)。
  • 解决之道: 图书馆多买几本《哈利波特》(减少热点块),或者规定不同章节的批注去不同的分馆(应用分区和亲和力设计)。

通过这个比喻,GRD作为分布式大脑、PCM锁作为状态机制、Cache Fusion作为高效传输媒介的角色就非常清晰了。RAC的复杂性和高性能都源于这套精巧的设计。任何RAC性能调优,最终都是在优化这套机制的运作效率。

欢迎关注我的公众号《IT小Chen

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值