简介:面向Oracle DBA及架构师的跨数据中心高可用部署参考文档,针对RAC依赖共享存储、ADG偏重容灾无法双活的短板,梳理存储双活配置的完整思路与操作步骤。文档覆盖磁盘规划(AA/BB机房OCR与数据盘、ZC仲裁盘)、Grid Infrastructure安装、创建Normal冗余磁盘组、OCR与votedisk迁移、ASM SPFILE迁移及性能测试等关键环节。内容以docx格式呈现,压缩包共1个文件,大小约104KB,适合已有Oracle RAC基础、正在规划双活方案的运维与架构人员查阅。目前已有150人学习下载。文档中不仅给出CREATE DISKGROUP、ocrconfig、crsctl等命令示例,还包含跨机房Interconnect时延与IO性能测试要点,可帮助读者评估双活架构风险并快速搭建验证环境。
1. 存储双活不是炫技:先说清楚它到底解决 Oracle 的什么问题
我见过太多采购了双活存储却只在存储层做演练的项目:存储工程师把阵列切换玩得很熟练,真到数据库切换时,应用连不上、ASM 磁盘组起不来,最后只能灰溜溜做传统恢复。存储双活的本质是让两台存储同时承载生产 IO,任何一台故障时另一台无缝接管,而 Oracle 这层能不能跟上,才是双活配置真正要解决的核心问题。这篇笔记只讨论一件事:Oracle 数据库在双活存储架构下的配置路径、关键参数和落地验证方法。适合正在选型或已经拿到双活存储、准备把核心库迁上去的 DBA、存储工程师和架构师。读完你能得到的不是一个"存储双活"的概念,而是一套从多路径到 ASM 再到集群层面可抄作业的配置方法。
2. 给 Oracle 选一条双活路径:存储镜像、Data Guard 还是集群
2.1 双活存储加 ASM 的组合是主流:为什么不是文件系统
双活存储(也叫存储镜像双活)的核心是把同一份数据在两台存储阵列上各写一份,主机看到的是一套逻辑卷,写 IO 由存储阵列负责同步复制到对端。对 Oracle 来说,无论底层的盘是文件系统还是裸设备,最终数据库进程只感知到"一块盘"。为什么主流方案都选择 ASM(自动存储管理)来管理这块盘?因为 ASM 天生就是为共享存储设计的:它自己管理数据文件的分布和冗余,支持在线加盘、删除盘,还提供 rebalance 机制。双活存储本身已经做了数据冗余,ASM 这边不需要再开 normal redundancy 做镜像,用 external redundancy 反而更简单、性能损耗更小。文件系统方案也不是不行,但当你面对 RAC 多节点共享、动态扩容这些场景时,ASM 的运维成本明显更低。
ASM 和双活存储的配合还有一个关键点:ASM 以磁盘组为单位管理盘,双活存储的 LUN 映射到主机后以多路径设备形式存在。ASM 眼里只有路径,并不关心路径背后是单台存储还是双活架构。这意味着你把 LUN 从单存储迁到双活存储,数据库层几乎不用改结构,只需要重新识别磁盘、重建磁盘组或者做数据迁移。这也是我倾向于推荐"双活存储 + ASM + RAC"组合的根本原因:每个层面只负责自己最擅长的事,故障域清晰,切换逻辑简单。
2.2 三种方案边界对比:存储镜像双活、Data Guard、Oracle Real Application Clusters
如果把"双活"理解成广义的高可用,行业内其实有三条路线:存储镜像双活、Data Guard 物理备库、Oracle Real Application Clusters(简称 RAC)。这三者解决的问题不一样,经常被混淆。
| 对比维度 | 存储镜像双活 | Data Guard | Oracle Real Application Clusters |
|---|---|---|---|
| 数据同步粒度 | 存储块级 | 日志级 | 缓存融合(实例级) |
| 切换单位 | 存储/主机 | 数据库 | 实例/节点 |
| RPO | 零丢失(取决于链路质量) | 零丢失(最大保护模式)/可配置 | 零丢失 |
| RTO | 分钟级(取决于切换脚本) | 秒到分钟级(需手动或依赖额外工具) | 秒级自动 |
| 应用透明性 | 完全透明 | 需要切换连接串 | 完全透明 |
| 适用场景 | 存储单点故障防御 | 容灾、迁移、报表分流 | 计算层高可用 + 横向扩展 |
实际生产中最常见的组合是:存储镜像双活打底解决存储层单点故障,RAC 解决实例层故障,Data Guard 再做跨机房容灾。三者不是互斥关系。如果你的预算只够做一项,优先考虑什么?我的看法是:如果数据库业务连续性要求是"机房断电 5 分钟内恢复",存储双活 + RAC 是可靠组合;如果只接受"恢复时间目标半小时以内",单独的 Data Guard 也能覆盖。
2.3 以某公司核心库为例的选型思路:延迟、距离和预算
曾经帮某公司做过一个选型评估,他们有一套 7×24 小时生产库,计划把两套存储放在同城两个机房,机房间专线延迟约 0.8 毫秒。A 方案是纯 Data Guard,B 方案是存储双活 + RAC。从成本看 A 方案少买一套存储,但从切换复杂度看,Data Guard 需要应用层配合修改连接串,核心业务方强烈反对任何登录跳变。最终选择存储双活 + RAC,理由有三:延迟低于 1 毫秒,双活存储的同步复制可以承受;RAC 切换对应用完全透明,无需改造;两机房带宽足够承载同步复制流量。
如果你的机房距离超过 50 公里或者延迟超过 2 毫秒,我不建议硬上存储双活。同步复制对延迟极其敏感,延迟高了不仅影响业务 IO 性能,还可能导致复制链路频繁超时。这个阈值不是玄学,是双活存储厂商普遍承认的工程边界。选型时还要注意一个细节:存储双活本身不解决任何数据库层的问题,比如坏块、逻辑损坏、误删除。这些必须靠备份或 Data Guard 兜底,不要以为有了双活就不需要备份。
3. 配置前的两项基础工作:多路径一致性与存储认盘
3.1 存储双活环境下的 Linux 多路径绑定:关键参数与配置示例
双活存储最常见的翻车点不在存储,而在操作系统层的多路径配置。双活架构下每台主机会从两台阵列各看到一条路径访问同一个 LUN,多路径软件负责把这两条路径聚合成一个设备。如果多路径策略不对,切换时数据库 IO 可能卡死,甚至出现"脑裂"后双写冲突。我一般用 device-mapper-multipath,配置前先确认三件事:两端的 LUN WWID 一致、链路速率一致、多路径版本一致。
# /etc/multipath.conf 核心配置片段 defaults { user_friendly_names no # 用 WWID 命名,不用 dm-0 这种 find_multipaths yes path_grouping_policy multibus # 所有路径在一个组,故障组内均衡 path_selector "round-robin 0" # 轮询分发 IO failback immediate # 路径恢复后立即回切 rr_min_io 100 # 切换 IO 数量阈值 polling_interval 5 # 路径检测间隔(秒) } multipaths { multipath { wwid "3600a098038303044452b466d44376b43" alias "asm_disk1" path_grouping_policy failover # 按阵列分组,主备模式 path_selector "round-robin 0" failback 10 } }注意path_grouping_policy这里我写了两处不同值,这是刻意的。双活存储有两种主流 IO 路径策略:multibus表示所有路径平等轮询;failover表示按存储端分组,组内轮询、组间主备。选哪种取决于你的双活存储是否支持"双活同时读写"。大多数双活阵列支持两端同时读写,multibus能提高链路利用率;但如果你使用某款存储的主备模式(同一时刻只有一端承担生产 IO),就必须用failover分组,否则故障切换时会出现 IO 抖动。这块配置没有通用答案,要跟存储工程师确认阵列的实际工作模式。
配置完成后重启 multipathd 服务,或者直接systemctl reload multipathd让配置生效。验证是否认到了正确的盘:
multipath -ll # 输出里应该有 2 条 active 路径,且 WWID 相同 # 例如:3600a098038303044452b466d44376b43 dm-2 某存储,VRAID # size=2.0T features='0' hwhandler='0' wp=rw # `-+- policy='round-robin 0' prio=1 status=active3.2 udev 规则与磁盘权限:为什么 ASM 总是扫不到盘
多路径设备认出来了,但 Oracle 装 ASM 时经常报"找不到候选磁盘",十有八九是权限问题。ASM 要求磁盘属主是oracle:asmadmin,权限是0660。Linux 在重启后设备节点会重新分配,/dev/mapper/asm_disk1这个设备文件默认属主是root:disk,必须用 udev 规则固定。
# /etc/udev/rules.d/99-oracle-asm.rules # 按 WWID 匹配多路径设备,固定属主和权限 KERNEL=="dm-*", ENV{DM_UUID}=="mpath-3600a098038303044452b466d44376b43", OWNER="oracle", GROUP="asmadmin", MODE="0660" KERNEL=="dm-*", ENV{DM_UUID}=="mpath-3600a098038303044452b466d44376b44", OWNER="oracle", GROUP="asmadmin", MODE="0660"这里有个容易被忽略的坑:DM_UUID的值必须以mpath-开头,后面跟 LUN 的 WWID。multipath -ll输出里能直接看到。如果你用user_friendly_names yes把设备命名成了mpatha这种别名,udev 规则里匹配DM_UUID依然有效,但要注意dm-*的KERNEL名称每次重启可能变化,所以规则只认DM_UUID不认设备名。
写完 udev 规则后执行udevadm trigger重载设备节点,然后用ls -l /dev/mapper/asm_disk1确认属主已经变成oracle:asmadmin。我见过有人在规则里写对了但没触发重载,重启十几台机器后发现 ASM 还是扫不到盘,原因就是这个。
3.3 存储侧映射清单与多路径核对:确认两端路数一致
配置前的最后一项工作是核对清单,不要跳过这一步。双活存储最常见的交付问题是:A 端阵列映射了 LUN,B 端阵列漏映射了,主机上只能看到一条路径。表面上看数据库能正常跑,但实际上双活已经"降级"成了单活,你还不知道。
# 查看每条路径对应的 HBA 端口和控制器 # 在 Linux 上可以通过 sysfs 查看路径详情 cat /sys/class/fc_transport/target*/port_name # 用 scsi_id 查看每个 scsi 设备的 WWID /usr/lib/udev/scsi_id -g -u /dev/sdb拿到的 WWID 和存储管理界面上的 LUN 做比对,确保每个 LUN 在两台阵列上都有映射。同时还要查路径数:正常情况下每个 LUN 在主机上至少应该有 4 条路径(两台阵列各 2 个控制器)。如果只有 2 条,要么是存储控制器配置问题,要么是光纤交换机 zone 没放通。不要急着进下一步,路径数量不对就继续排查,否则后面 ASM 磁盘组建得再漂亮,切换一发作全盘皆输。
4. ASM 双活配置的完整动作:从磁盘组到集群相关参数
4.1 创建 ASM 磁盘组:external redundancy 与兼容性参数
完成多路径认盘后,进入 ASM 配置阶段。双活存储下我一般选择EXTERNAL REDUNDANCY,原因前面说过:存储层已经做了镜像,ASM 层再做镜像属于重复投资,浪费容量还增加 rebalance 开销。但这里有一个例外:如果你的双活存储没有开启"同步复制"而只是异步复制,那存储层实际上没有实时镜像,ASM 内部仍然需要故障组来保护数据。配置前跟存储团队确认复制模式是同步还是异步,这直接影响 ASM 的冗余级别选择。
-- 用 sqlplus 或 asmcmd 执行,创建磁盘组 CREATE DISKGROUP DATA EXTERNAL REDUNDANCY DISK '/dev/mapper/asm_disk1' NAME data_disk1, '/dev/mapper/asm_disk2' NAME data_disk2 ATTRIBUTE 'compatible.asm' = '19.0.0', 'compatible.rdbms' = '19.0.0', 'disk_repair_time' = '8h';compatible.asm和compatible.rdbms不是随便填的,它们决定了这组磁盘能不能享受新版本特性,同时也决定了旧版本集群能不能挂载这个磁盘组。升级场景中常见报错是磁盘组compatible.asm高于集群版本导致无法挂载,所以配置前先确认集群版本。disk_repair_time这个参数在双活架构里尤其重要:它控制了 ASM 在磁盘离线后等多久才把它从磁盘组里驱逐。双活存储切换时可能出现一端存储短暂不可达,ASM 会标记对应磁盘离线,如果disk_repair_time太短,ASM 可能直接把盘踢出去触发 rebalance,白白消耗 IO。我习惯设成 8 小时以上,给存储故障恢复留足窗口。
4.2 跨阵列的故障组设计:避免 ASM 把副本放在同一台存储上
刚才提到的"存储异步复制用 ASM 冗余"场景,以及未来可能存在的"一台存储完全损坏"容灾需求,都要靠 ASM 故障组(failure group)来隔离数据副本的物理位置。故障组的意义是告诉 ASM:"这些盘在物理上是同一个故障域",ASM 在写入镜像时会把两个副本放在不同故障组,避免单点故障同时损坏所有副本。
-- 两个故障组分别对应两台存储阵列 CREATE DISKGROUP DATA NORMAL REDUNDANCY FAILGROUP fg_storeA DISK '/dev/mapper/asm_disk1' NAME storeA_disk1, DISK '/dev/mapper/asm_disk2' NAME storeA_disk2 FAILGROUP fg_storeB DISK '/dev/mapper/asm_disk3' NAME storeB_disk1, DISK '/dev/mapper/asm_disk4' NAME storeB_disk2 ATTRIBUTE 'compatible.asm' = '19.0.0', 'compatible.rdbms' = '19.0.0';这里最关键的坑是:故障组必须按"真实物理故障域"划分,不是按主机名或随意分组。你的映射清单上记录了每个 LUN 来自哪台存储的哪个控制器,故障组就要按存储阵列分组。如果两台存储各自只有 2 个 LUN 以上,每个故障组至少有 2 块盘,才能保证某个故障组里一块盘坏掉时还有同组盘可以继续承载。只有 1 块盘一个故障组的用法可以,但重建时间很长,因为必须从另一个故障组全量复制。
4.3 RAC 场景下的双活配置注意点:OCR、表决盘与缓存策略
存储双活加 RAC 的组合下,OCR(Oracle 集群注册表)和表决盘(voting disk)通常放在 ASM 磁盘组里。这两个文件的 IO 量不大,但对延迟和一致性要求极高,恰好戳中双活存储的软肋。双活存储的同步复制会增加写延迟,如果专线质量不好,会有概率触发集群件的心跳超时导致节点被驱逐。建议把 OCR 和表决盘单独建一个NORMAL REDUNDANCY的小磁盘组(比如 3 块盘,三副本),与数据文件磁盘组分隔管理,即使数据磁盘组出问题也不影响集群件判断。
还有一个容易被忽视的参数是存储阵列的写缓存策略。双活存储下两端阵列必须保持一致的写缓存策略——要么都用 write-back,要么都用 write-through。我曾经遇到过一次存储工程师调整了 A 端缓存策略没同步 B 端,导致某一时间窗口内 A 端性能正常、B 端写入极慢,数据库出现周期性 IO 尖刺。这类问题排查起来极痛苦,因为数据库层的 AWR 报告看不出任何明显异常。因此配置清单里应当明确记录两端阵列的缓存策略,并在变更后主动核对。
| 检查项 | 建议值 | 说明 |
|---|---|---|
| ASM 冗余级别 | EXTERNAL(同步复制时)/ NORMAL(异步复制时) | 以存储复制模式为准 |
| disk_repair_time | 8h | 给存储切换留恢复窗口 |
| OCR/表决盘磁盘组 | NORMAL REDUNDANCY 独立建组 | 避免与数据争用和相互影响 |
| 多路径策略 | multibus 或按存储分组 failover | 以阵列工作模式为准 |
| 存储写缓存 | 两端一致 | 不一致会导致性能尖刺 |
| 专线延迟 | 小于 1ms | 超过则不建议同步双活 |
5. 双活配置避坑:我见过的 5 个翻车现场
5.1 路径权重不一致:切换后 IO 全部挤到同一条劣化链路
现象:存储切换演练时,业务系统没有中断,但数据库等待事件里出现大量db file sequential read的异常增长,IOPS 明显下降。
原因:配置多路径时用了multibus模式,但两端阵列到主机的链路速率不一致。A 端 16Gbps 光纤,B 端 8Gbps 光纤,多路径轮询分发了相同比例 IO,8G 链路成了瓶颈,性能反而比单链路还差。
解决:路径速率不一致时改用按阵列分组的主备模式,或者把rr_min_io调大,让 IO 更倾向于高性能链路。更彻底的做法是统一两端 HBA 速率。这个坑的核心教训是:双活链路之间的性能对称性比路径数量更重要。
5.2 ASM 磁盘头覆盖导致磁盘组无法挂载
现象:某公司把 LUN 从单存储迁移到双活存储后,ASM 磁盘组挂载时报"无法验证磁盘头",所有磁盘都不可用。
原因:迁移过程中,存储工程师把双活 LUN 的映射顺序调换了,ASM 按 WWID 识别磁盘,但磁盘头里的 ASM 磁盘名和实际预期的名称对不上。更糟的是有人在没确认外部冗余的情况下重新初始化了磁盘,把原磁盘头覆盖了。
解决:迁移前先用kfed read /dev/mapper/asm_disk1备份所有磁盘的磁盘头信息;迁移后用kfed逐一比对。如果已经被覆盖,用kfed repair从备份恢复。这类问题没有快捷修复路径,磁盘组一旦起不来,只能重新建组导入数据。所以任何涉及盘符顺序、映射关系的变更,第一件事就是把kfed read的结果保存下来。
5.3 一端存储离线触发 ASM 重新平衡风暴
现象:正常运维时拔掉一台存储的控制器,存储双活自动切换,但数据库紧接着出现大量ASM rebalance后台任务,IO 长时间处于高负载。
原因:disk_repair_time设置太短(默认 3.6 小时),存储切换还没完成,ASM 就已经判定磁盘离线并触发 rebalance。双活存储的控制器切换通常只需要几分钟,但因为存储链路抖动被 ASM 误判为磁盘损坏,导致它启动了数据重分布。
解决:把disk_repair_time调大,一般建议 8 小时以上。另外要在存储侧配合配置"链路抖动抑制",让存储切换时不产生长时间 IO 超时。ASM 的 rebalance 可以通过ALTER DISKGROUP DATA REBALANCE POWER 1降低优先级,但这个只是事后补救,真正要做的是避免触发。
5.4 测试只做存储切换,没有做数据库层验证
现象:存储团队报告"双活切换演练成功",但隔了一个月真实故障时数据库磁盘组直接 DISMOUNT,应用全部中断。
原因:演练流程只验证了存储管理界面的切换,没有验证操作系统多路径能否感知、ASM 能否保持磁盘组在线、数据库会话是否持续可用。存储层切换和数据库层可用是两回事。
解决:把验证脚本做成三层:第一层multipath -ll确认路径切换;第二层asmcmd ls -l确认磁盘组 ONLINE;第三层跑一个持续查询的 SQL(比如SELECT COUNT(*) FROM dual CONNECT BY LEVEL <= 100000),在存储切换过程中观察 SQL 是否中断。三层全过了才算真双活。
5.5 忽视时钟同步:双活存储的日志时间戳错乱
现象:存储双活链路正常,数据库无忧,但查看存储复制日志时发现两端写入事件的时间差越来越大,偶尔还出现"过去时间修改"的告警。
原因:两机房 NTP 服务器不一致,时钟漂移导致存储复制引擎判断同步进度异常。某些双活存储依赖时间戳做冲突仲裁,时钟偏移会导致错误的冲突判定。
解决:两机房统一使用同一 NTP 时间源,并配置存储管理用户权限受控,避免人工调整时间。配置后通过存储管理界面的时间同步状态确认两端时间差小于 100 毫秒。这个问题平时看不出来,一出事就是灾难级别的数据不一致,值得在配置清单里单独列一行。
6. 验证与进阶:用故障演练把双活变成可信承诺
配置完成不等于双活可用,真正让团队放心的是反复演练后得出的结论。我习惯在每次双活配置变更后做一套三层验证流程,耗时约 30 分钟,能覆盖九成以上风险场景。
# 演练脚本核心逻辑:模拟存储控制器切换,观察数据库连续性 # 步骤1:记录当前多路径状态 multipath -ll > /tmp/mp_before.txt # 步骤2:在存储管理界面触发一端控制器故障切换 # 步骤3:持续监控多路径状态,等待路径切换完成 # 步骤4:验证 ASM 磁盘组状态 asmcmd ls -l DATA # 步骤5:验证数据库会话连续性(在另一终端执行) sqlplus -S / as sysdba <<EOF SET PAGESIZE 0 SELECT COUNT(*) FROM dual CONNECT BY LEVEL <= 50000; EOF这套脚本最好的价值不是自动化,而是让每个参与者都亲眼看到切换过程。演练时记录三个时间点:切换开始时间、多路径恢复时间、数据库会话恢复时间。如果第二个时间点超过 10 秒,先查存储链路;如果第三个时间点超过 5 秒,查 ASM 的I/O路径和磁盘组状态。把每次演练结果存档,形成历史基线,下次配置变更后对比基线就能快速发现性能劣化。
进阶技巧方面,双活存储下值得深入研究的是 ASM 的优先读取(prefer-read)设置。如果你的数据库实例都在机房 A,可以把 ASM 配置成优先读取机房 A 对应故障组的磁盘副本,避免跨机房读延迟。在支持该特性的 ASM 版本中,通过ALTER DISKGROUP DATA SET PREFERRED READ FAILGROUP fg_storeA即可设置。这个动作能显著降低正常情况下的读延迟,但对于没有开启 ASM 层冗余的 EXTERNAL 磁盘组不适用。
最后说一个我自己的教训:第一次给某公司配置双活存储时,我觉得配置完成、存储管理界面显示"同步正常"就算大功告成,结果一个月后真实切换时数据库直接不可用。从那时起我养成了一个习惯——任何高可用架构交付后的两周内,至少做一次完整的故障演练,并把演练记录发到项目群,让所有人知道这套系统在故障面前的真实表现。存储双活配置到最后,拼的不是参数调得多漂亮,而是你敢于主动制造故障并且能从故障中恢复。希望这篇笔记对你有用。
本文还有配套的精品资源,点击获取