一、问题背景

备份是 DBA 的最后一道防线。在生产环境中,无论高可用架构多么完善(Data Guard、RAC、GoldenGate),备份始终是应对逻辑损坏、人为误操作、勒索软件等极端场景的终极保障。

然而,随着数据量不断增长,TB 级别的数据库已经非常普遍。传统的全量备份策略面临巨大的时间窗口问题:一个 5TB 的数据库,即使以 200MB/s 的速度写入备份介质,全量备份也需要约 7 个小时。对于 7×24 不间断的业务系统,这不仅挤占了宝贵的 I/O 资源,还可能影响正常的业务响应。

Oracle RMAN 提供了增量备份机制,配合 Block Change Tracking(BCT) 技术,可以将日常备份的数据量从 TB 级降低到 GB 级,大幅缩短备份窗口。同时,Recovery Catalog 为备份元数据提供了集中管理和长期保留能力,而 RMAN DUPLICATE 则支持基于备份集的跨节点恢复,是容灾和测试环境搭建的利器。

本文将从理论到实战,系统讲解 RMAN 高级备份策略的设计与实施。

阅读全文 »

一、问题背景

为什么需要标准化的角色切换SOP

在生产环境中,Oracle Data Guard 的角色切换(Switchover/Failover)是一项高风险操作。没有标准化的操作手册,DBA 在面对紧急故障时容易犯下不可挽回的错误——跳过检查步骤、遗漏数据一致性验证、在错误的时机执行命令,任何一个小失误都可能导致数小时甚至数天的业务中断。

标准化的 SOP(Standard Operating Procedure)能够确保:

  • 操作可重复:任何具备资质的 DBA 都能按照手册完成切换
  • 风险可控:每一步操作都有明确的前置条件和验证标准
  • 回退可执行:出现异常时能快速恢复到安全状态
  • 审计可追溯:每一次操作都有记录,满足合规要求

切换失败的生产事故案例

以下是一个真实场景的还原:

某金融客户在机房迁移期间执行 Switchover,由于未提前检查 Standby 的归档日志是否连续应用,切换完成后发现新 Primary 缺少 30 分钟的交易数据。更糟糕的是,运维团队在发现问题后尝试回切,却因新旧 Primary 的角色状态混乱导致两个数据库都进入了不可用状态——这就是典型的脑裂(Split Brain)场景。

最终代价:业务中断 4 小时,数据丢失约 15 分钟,事后复盘耗时一周。

脑裂(Split Brain)对数据一致性的致命影响

脑裂是 Data Guard 架构中最危险的状态——Primary 和 Standby 同时以 Primary 角色运行,各自接受写入,导致两份数据库出现数据分叉。一旦脑裂发生:

  • 两份数据库的数据开始分叉,无法简单合并
  • 应用可能连接到错误的数据库,写入不一致的数据
  • 修复过程需要停机比对,业务影响巨大
  • 严重时可能需要从备份恢复,RPO 暴增

因此,理解脑裂的产生机制并建立完善的预防体系,是每一位 DBA 的必修课。


二、理论分析

2.1 Switchover vs Failover

Switchover(计划性切换)

Switchover 是一种有序的角色转换过程。Primary 变为 Standby,Standby 变为 Primary,整个过程零数据丢失

1
2
切换前:  Primary (PROD) ---> Standby (DR)
切换后: Standby (PROD) <--- Primary (DR)

适用场景

  • 计划性维护(硬件升级、操作系统补丁、存储迁移)
  • 定期容灾演练
  • 数据中心迁移
  • 负载均衡需求(读写分离架构调整)

Failover(紧急切换)

Failover 是在 Primary 不可用时的应急操作。Standby 被激活为新的 Primary,原有 Primary 被废弃或降级。

1
2
切换前:  Primary (PROD) [故障]   Standby (DR)
切换后: 废弃/恢复 <--- Primary (DR)

适用场景

  • Primary 数据库所在机房火灾、地震等灾难
  • 存储阵列故障,短时间内无法恢复
  • 数据库严重损坏,无法修复
  • 网络完全中断,Primary 不可达

关键区别

特性 Switchover Failover
触发条件 计划性 紧急/非计划性
数据丢失 可能(取决于保护模式)
可逆性 完全可逆 需重建旧Primary
归档日志间隙 可能存在
操作复杂度

2.2 脑裂(Split Brain)产生的根因

脑裂的本质是分布式系统中的一致性问题——两个节点同时认为自己是 Primary 并接受写入。

场景一:网络分区(Network Partition)

1
2
3
4
5
6
7
8
9
正常状态:
Client --> Primary <==== 心跳/Redo传输 ====> Standby

网络分区:
Client --> Primary <----X----> Standby

网络中断

问题: Standby 如何判断 Primary 是真的挂了,还是仅仅网络不通?

当 Primary 与 Standby 之间的网络中断时,Standby 可能无法确定 Primary 的状态。如果此时贸然将 Standby 提升为 Primary,而原 Primary 其实仍在运行并接受写入,脑裂就产生了。

场景二:角色转换过程中的时序问题

在 Switchover 过程中,如果操作执行到一半(旧 Primary 已经 shutdown,新 Primary 已经 open),但网络故障导致旧 Primary 重新启动后以 Primary 角色恢复运行,也会出现脑裂。

场景三:Fast-Start Failover 的仲裁失败

FSFO 依赖 Observer 进行故障仲裁。如果 Observer 所在网络分区导致无法同时访问两个数据库,Observer 可能做出错误的切换决策。

2.3 脑裂预防机制

FSFO 的 Observer 进程

Observer 是 Fast-Start Failover 的核心仲裁组件。它是一个独立进程,运行在第三方节点上(既不是 Primary 也不是 Standby),持续监控两个数据库的状态。

1
2
3
4
Primary <--- Observer ---> Standby
|
v
第三方主机

Observer 的仲裁逻辑:

  • 定期向 Primary 发送心跳(默认每秒一次)
  • 如果 Primary 失联超过 FastStartFailoverLagLimit,Observer 触发 Failover
  • Observer 同时连接两个数据库,避免单点误判

三种保护模式对脑裂的影响

保护模式 数据保护 性能影响 脑裂风险
Maximum Protection 零丢失 最大 最低
Maximum Availability 尽量零丢失 中等 中等
Maximum Performance 可能丢数据 最小 最高

Maximum Protection 模式下,如果 Standby 不可用,Primary 会自动关闭(SHUTDOWN ABORT),从根本上杜绝了两个数据库同时运行的可能性。但代价是可能造成业务中断。

Maximum Performance 模式下,Primary 不等待 Standby 确认,即使 Standby 离线 Primary 也能正常运行,这在性能上最优,但脑裂风险最高。

推荐方案:在生产环境中使用 Maximum Availability 模式,在可用性和安全性之间取得平衡。

网络冗余与心跳检测

1
2
3
4
5
6
推荐的网络架构:

Standby Host
|-- NIC1 --> 网络A (业务网络) --> Primary Host
|-- NIC2 --> 网络B (专用心跳) --> Primary Host
|-- NIC3 --> 网络C (管理网络) --> Primary Host

关键措施:

  • 使用独立的专用网络传输 Redo 日志
  • 配置多条网络路径,避免单点故障
  • 使用 Oracle Net 的多重地址配置(FAILOVER=ON
  • 配置 OS 级别的心跳检测(如 Oracle Clusterware、Pacemaker)

三、实战操作

3.1 Switchover SOP(标准化操作手册)

切换前检查清单

必须在切换前逐项确认,任何一项不满足则停止操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
=== Switchover 切换前检查清单 ===

□ 1. 确认当前角色
SELECT database_role, open_mode, switchover_status FROM v$database;
-- Primary: switchover_status 必须为 TO STANDBY 或 SESSIONS ACTIVE
-- Standby: 必须为 NOT ALLOWED 或 SESSIONS ACTIVE

□ 2. 检查归档日志是否连续应用
-- 在 Standby 上执行:
SELECT thread#, max(sequence#) FROM v$archived_log WHERE applied='YES' GROUP BY thread#;
-- 在 Primary 上执行:
SELECT thread#, max(sequence#) FROM v$archived_log GROUP BY thread#;
-- 两边的 sequence# 必须一致

□ 3. 检查是否有 GAPS
SELECT * FROM v$archive_gap;
-- 结果必须为空

□ 4. 检查 Standby 的 Redo Apply 是否在运行
SELECT process, status FROM v$managed_standby WHERE process LIKE 'MRP%';
-- MRP0 必须存在且状态为 APPLYING_LOG

□ 5. 检查临时文件是否一致
-- 确保 Standby 的临时表空间文件存在且可访问

□ 6. 检查所有实例(RAC 环境)
-- 所有实例都必须在线,或者只有一个实例在线
-- 确认没有活跃的长事务
SELECT * FROM v$transaction WHERE status != 'INACTIVE';

□ 7. 停止应用连接
-- 通知应用团队停止写入
-- 或者在 Primary 上执行:
ALTER SYSTEM QUIESCE RESTRICTED; -- 可选,需谨慎

□ 8. 创建恢复保证点(可选但推荐)
-- 在 Primary 上:
CREATE RESTORE POINT switchover_guarantee GUARANTEE FLASHBACK DATABASE;

□ 9. 确认网络连通性
-- Primary 到 Standby 的 TNS 连接正常
-- Standby 到 Primary 的 TNS 连接正常

Broker 执行 Switchover 命令

使用 Data Guard Broker 是最推荐的方式,它会自动处理大部分步骤:

1
2
3
4
5
6
7
8
9
10
11
12
13
-- 连接到 DGMGRL
$ dgmgrl sys/password@primary_db

-- 查看当前配置状态
DGMGRL> SHOW CONFIGURATION;
DGMGRL> SHOW DATABASE VERBOSE 'primary_db';
DGMGRL> SHOW DATABASE VERBOSE 'standby_db';

-- 执行 Switchover(Broker 自动处理所有步骤)
DGMGRL> SWITCHOVER TO 'standby_db';

-- 验证切换结果
DGMGRL> SHOW CONFIGURATION;

Broker Switchover 的内部步骤:

  1. 将 Primary 数据库转换为 Standby 角色
  2. 将 Standby 数据库转换为 Primary 角色
  3. 自动重启两个数据库
  4. 重新启用 Redo 传输和应用

手动 Switchover 详细步骤

当 Broker 不可用时,需要手动执行:

Step 1: 在 Primary 上准备切换

1
2
3
4
5
6
7
8
-- 检查切换状态
SQL> SELECT switchover_status FROM v$database;

-- 如果状态为 TO STANDBY,直接执行:
SQL> ALTER DATABASE COMMIT TO SWITCHOVER TO STANDBY WITH SESSION SHUTDOWN;

-- 如果状态为 SESSIONS ACTIVE,需要先杀掉会话或使用:
SQL> ALTER DATABASE COMMIT TO SWITCHOVER TO STANDBY WITH SESSION SHUTDOWN;

Step 2: 在 Standby 上准备切换

1
2
3
4
5
6
7
8
9
10
11
-- 在 Standby 上取消 Redo Apply
SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;

-- 检查状态
SQL> SELECT switchover_status FROM v$database;

-- 将 Standby 转换为 Primary
SQL> ALTER DATABASE COMMIT TO SWITCHOVER TO PRIMARY;

-- 如果是 Physical Standby 且曾以只读方式打开过:
SQL> ALTER DATABASE COMMIT TO SWITCHOVER TO PRIMARY WITH SESSION SHUTDOWN;

Step 3: 打开新 Primary

1
2
-- 在新的 Primary(原 Standby)上:
SQL> ALTER DATABASE OPEN;

Step 4: 在新 Standby 上启动 Redo Apply

1
2
3
-- 在新的 Standby(原 Primary)上:
SQL> STARTUP MOUNT;
SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;

切换后验证步骤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
=== 切换后验证清单 ===

1. 确认角色
SELECT database_role, open_mode FROM v$database;
-- 新 Primary: PRIMARY / READ WRITE
-- 新 Standby: PHYSICAL STANDBY / MOUNTED 或 READ ONLY WITH APPLY

2. 确认 Redo 传输正常
-- 在新 Primary 上:
SELECT dest_id, status, error FROM v$archive_dest WHERE dest_id=2;
-- status 必须为 VALID

3. 确认归档日志序列号连续
-- 新 Primary 最新归档序列号
-- 新 Standby 已应用到的序列号

4. 验证数据一致性
-- 抽样检查关键表的数据条数
SELECT COUNT(*) FROM critical_table;

5. 验证应用连接
-- 应用团队确认连接正常
-- 执行简单的读写测试

回切步骤

如需回切到原 Primary,只需再次执行 Switchover:

1
2
-- 在新 Primary(原 Standby)上:
DGMGRL> SWITCHOVER TO 'original_primary_db';

3.2 Failover SOP

判断是否需要 Failover

Failover 是最后手段,在执行前必须确认以下条件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
=== Failover 决策树 ===

1. Primary 数据库是否真的不可用?
├── 仅网络不通? → 不要 Failover,检查网络
├── 仅数据库实例挂了? → 尝试 STARTUP
├── 存储故障? → 评估恢复时间
└── 机房级灾难? → 确认 Failover

2. 预计恢复时间 (RTO) 是否超出容忍范围?
├── < RTO → 等待恢复
└── > RTO → 执行 Failover

3. 是否有数据丢失?
└── Maximum Protection 模式 → 零丢失,放心 Failover
└── Maximum Performance 模式 → 评估丢失量

手动 Failover 步骤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
-- Step 1: 在 Standby 上检查归档日志应用情况
SQL> SELECT thread#, max(sequence#) FROM v$archived_log WHERE applied='YES' GROUP BY thread#;

-- Step 2: 尝试应用所有可用的归档日志
SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;
SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE FINISH;

-- Step 3: 如果有数据丢失风险(返回 ORA-19909),确认继续
SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE FINISH FORCE;

-- Step 4: 将 Standby 转换为 Primary
SQL> ALTER DATABASE COMMIT TO SWITCHOVER TO PRIMARY;
-- 或者(如果 switchover_status 不允许):
SQL> ALTER DATABASE ACTIVATE STANDBY DATABASE;

-- Step 5: 打开数据库
SQL> ALTER DATABASE OPEN;

-- 注意: ACTIVATE STANDBY DATABASE 是不可逆操作!

Broker Failover 操作

1
2
3
4
5
6
7
$ dgmgrl sys/password@standby_db

-- 执行 Failover
DGMGRL> FAILOVER TO 'standby_db';

-- 验证
DGMGRL> SHOW CONFIGURATION;

Failover 后重建旧 Primary

Failover 后,旧 Primary 不能直接作为 Standby 使用,需要重建:

方法一:使用 Flashback Database

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
-- 在旧 Primary 上(如果能启动):
SQL> STARTUP MOUNT;

-- 记录 Failover 时的 SCN
-- 在新 Primary 上:
SQL> SELECT standby_became_primary_scn FROM v$database;

-- 在旧 Primary 上:
SQL> FLASHBACK DATABASE TO SCN <standby_became_primary_scn>;

-- 转换为 Standby
SQL> ALTER DATABASE CONVERT TO PHYSICAL STANDBY;
SQL> SHUTDOWN IMMEDIATE;
SQL> STARTUP MOUNT;
SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;

方法二:RMAN 重建

1
2
3
4
5
6
7
8
9
# 在旧 Primary 主机上
$ rman target /

RMAN> STARTUP MOUNT;
RMAN> RESTORE DATABASE;
RMAN> RECOVER DATABASE;

# 或者使用 DUPLICATE
RMAN> DUPLICATE TARGET DATABASE FOR STANDBY FROM ACTIVE DATABASE;

3.3 FSFO 配置与演练

Observer 进程配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-- Step 1: 在 Observer 主机上安装 Oracle Client

-- Step 2: 配置 tnsnames.ora,确保 Observer 能连接两个数据库

-- Step 3: 在 Broker 中设置 FSFO 参数
DGMGRL> EDIT DATABASE 'primary_db' SET PROPERTY FastStartFailoverTarget = 'standby_db';
DGMGRL> EDIT DATABASE 'standby_db' SET PROPERTY FastStartFailoverTarget = 'primary_db';
DGMGRL> EDIT CONFIGURATION SET PROPERTY FastStartFailoverLagLimit = 30;
DGMGRL> EDIT CONFIGURATION SET PROPERTY FastStartFailoverThreshold = 30;
DGMGRL> EDIT CONFIGURATION SET PROPERTY ObserverConnectIdentifier = 'observer_host';

-- Step 4: 启动 Observer
$ dgmgrl sys/password@primary_db
DGMGRL> START OBSERVER;
-- Observer 将在前台持续运行

-- 生产环境建议使用 nohup 或 systemd 管理 Observer 进程

FSFO 启用与测试

1
2
3
4
5
6
7
8
-- 确认保护模式(FSFO 要求至少 Maximum Availability)
DGMGRL> EDIT CONFIGURATION SET PROTECTION MODE AS MaxAvailability;

-- 启用 FSFO
DGMGRL> ENABLE FAST_START FAILOVER;

-- 验证 FSFO 状态
DGMGRL> SHOW FAST_START FAILOVER;

模拟故障自动切换

1
2
3
4
5
6
7
8
9
-- 在 Primary 上模拟故障
SQL> SHUTDOWN ABORT;

-- 观察 Observer 日志,等待自动 Failover
-- Observer 会在 FastStartFailoverThreshold 秒后自动执行 Failover

-- 验证自动切换结果
DGMGRL> SHOW CONFIGURATION;
DGMGRL> SHOW DATABASE 'new_primary_db';

3.4 脑裂处理

检测脑裂的方法

1
2
3
4
5
6
7
8
9
10
11
-- 方法一: 检查两个数据库的角色
-- 如果两个数据库都返回 PRIMARY,说明已发生脑裂
SELECT database_role FROM v$database;

-- 方法二: 检查 Broker 状态
DGMGRL> SHOW CONFIGURATION;
-- 如果报错 ORA-16600 或 ORA-16724,可能是脑裂

-- 方法三: 检查 Redo 传输错误
SELECT dest_id, status, error FROM v$archive_dest WHERE target='STANDBY';
-- 如果报 ORA-16009 (invalid redo transport destination),可能是脑裂

脑裂发生后的数据一致性检查

1
2
3
4
5
6
7
8
9
10
11
12
13
-- 在两个数据库上分别执行以下查询,对比结果:

-- 1. 最新 SCN
SELECT current_scn FROM v$database;

-- 2. 最新归档日志序列号
SELECT max(sequence#) FROM v$archived_log;

-- 3. 关键业务表的记录数
SELECT COUNT(*) FROM critical_table;

-- 4. 最新交易时间
SELECT max(create_time) FROM transaction_table;

脑裂修复步骤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
=== 脑裂修复 SOP ===

Step 1: 确定哪个数据库是"正确的"
- 基于 SCN 大小、归档日志完整性、业务数据完整性判断
- 通常选择 SCN 较大的那个作为正确数据库

Step 2: 立即停止"错误"的数据库
SQL> SHUTDOWN ABORT;

Step 3: 在"正确"的数据库上确认角色
SQL> ALTER DATABASE OPEN RESETLOGS; -- 如果需要

Step 4: 重建"错误"的数据库为 Standby
- 使用 RMAN DUPLICATE 或 Flashback Database

Step 5: 验证数据一致性
- 比对关键表数据
- 确认没有数据丢失

Step 6: 事后分析
- 查找脑裂的根本原因
- 加强预防措施
- 更新 SOP 文档

四、结果验证

切换后的角色确认

1
2
3
4
5
6
7
-- 必须执行的验证查询
SELECT database_role, open_mode, protection_mode, switchover_status
FROM v$database;

-- 期望结果:
-- Primary: PRIMARY / READ WRITE / <保护模式> / TO STANDBY
-- Standby: PHYSICAL STANDBY / READ ONLY WITH APPLY / <保护模式> / NOT ALLOWED

数据一致性验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
-- 方法一: SCN 对比
-- 在 Primary 和 Standby 上分别执行
SELECT current_scn FROM v$database;
-- Standby 的 SCN 应接近 Primary 的 SCN

-- 方法二: 归档日志序列号对比
-- Primary: 最新生成的归档日志
SELECT max(sequence#) FROM v$archived_log;
-- Standby: 最新已应用的归档日志
SELECT max(sequence#) FROM v$archived_log WHERE applied='YES';
-- 两个数字应该一致

-- 方法三: 业务数据抽检
-- 选取核心业务表,对比记录数和最新记录
SELECT COUNT(*), MAX(update_time) FROM order_table;

应用连接验证

1
2
3
4
5
6
7
8
9
10
11
# 1. TNS 连接测试
$ tnsping new_primary_tnsname

# 2. SQL*Plus 连接测试
$ sqlplus app_user/password@new_primary_tnsname

# 3. JDBC 连接测试(应用层面)
# 确认应用能正常连接到新 Primary

# 4. 读写测试
# 执行 INSERT + SELECT 验证读写正常

五、经验总结

容灾演练的频率与方法

  • 每月一次:在测试环境执行完整 Switchover 演练
  • 每季度一次:在生产环境的维护窗口执行 Switchover(含回切)
  • 每半年一次:模拟 Failover 场景(在隔离环境)
  • 每年一次:全链路容灾演练(含应用层验证)

切换过程中的常见问题

问题 原因 解决方案
ORA-16009: invalid redo transport destination Standby 的 TNS 配置错误 检查 tnsnames.ora 和 listener.ora
ORA-16416: switchover target has lagged behind Standby 的归档日志应用延迟 等待应用完成或检查 MRP 进程
ORA-16410: switchover target is not a standby 角色状态异常 检查 Broker 配置和数据库角色
MRP0 进程不启动 归档日志丢失或损坏 使用 RMAN 恢复缺失的归档日志
Failover 后无法回切 Failover 是不可逆的 需要重建旧 Primary

文档化的重要性

  1. 每次切换都必须记录:执行时间、操作人、执行步骤、验证结果、异常情况
  2. SOP 文档必须版本化:每次演练后根据实际经验更新 SOP
  3. 建立知识库:将典型案例和解决方案沉淀为团队知识
  4. 定期审查:每季度审查一次 SOP 文档的时效性和准确性

一个优秀的 DBA 不仅能执行 Switchover/Failover,更能确保这个过程标准化、自动化、可审计。把 SOP 落到实处,让每一次切换都像训练有素的消防演习——快、准、稳。

在生产环境中,许多企业部署了 Data Guard 物理备库用于容灾,但备库长期处于 mount 状态,只接收 redo 不提供任何业务服务,造成了严重的硬件资源浪费。Oracle Active Data Guard(ADG)打破了这一限制,允许物理备库在 apply redo 的同时提供只读查询服务,实现真正的读写分离。本文基于 Oracle 19c 环境,完整记录从物理备库搭建、DG Broker 配置到 ADG 读写分离落地的全流程。

阅读全文 »

Oracle RAC(Real Application Clusters)是 Oracle 数据库实现高可用与水平扩展的核心架构。在 RAC 集群中,Cache Fusion 是最核心的技术——它让多个实例通过高速互联网络(Interconnect)直接交换数据块,而无需先写入磁盘。然而,很多 DBA 在遇到 gc buffer busygc cr request 等 Global Cache(GC)等待事件时束手无策,根源在于对 Cache Fusion 底层机制理解不足。与此同时,负载均衡配置不当也是 RAC 环境中的常见问题,经常导致某一节点过载而其他节点闲置,白白浪费集群资源。

本文将从原理出发,结合生产实战经验,深入剖析 Cache Fusion 的工作机制与负载均衡的最佳实践。

阅读全文 »

作为一名 OCM 认证的 DBA,我在职业生涯中部署过上百套 Oracle 数据库。从最初照着 MOS 文档一步步敲命令,到如今用 Ansible 一键完成从 OS 准备到建库的全流程,这个转变让我深刻体会到 Infrastructure as Code (IaC) 的力量。本文将完整记录如何用 Ansible Role 实现 Oracle 数据库的自动化部署,代码可直接用于生产环境。

阅读全文 »

一、问题背景

Oracle RAC (Real Application Clusters) 配合 ASM (Automatic Storage Management) 是目前业界最经典的高可用数据库架构。RAC 解决了计算层的高可用与横向扩展,ASM 则在存储层提供了自动化的卷管理、条带化和镜像能力。然而,很多 DBA 在搭建 RAC 时往往将注意力集中在集群软件和数据库实例上,忽略了存储层——尤其是多路径(Multipath)——的正确配置。

存储层配置不当会导致一系列严重问题:

  • 磁盘路径单点故障:HBA 卡、光纤线缆或存储控制器的任何一环出现故障,都会导致 IO 中断,RAC 节点直接被驱逐。
  • ASM 磁盘发现失败:如果存储映射变更后未正确配置设备发现路径,ASM 实例将无法找到磁盘,导致磁盘组 dismount。
  • 权限问题:在 Linux 环境中,裸设备的 owner/group 权限不正确会导致 Oracle 无法打开磁盘,安装过程直接报错 ORA-15025ORA-27041 等。

在生产环境中,存储阵列通常通过双控制器向主机暴露 LUN,主机端则通过双 HBA 卡连接存储。这就意味着同一块 LUN 在操作系统层面会看到多个 SCSI 设备(如 /dev/sdb/dev/sdc/dev/sdd/dev/sde)。Multipath 的作用正是将这些底层物理路径聚合为一个逻辑设备,同时提供路径故障切换和负载均衡能力。

本文将从理论到实践,完整讲解在 RAC + ASM 架构中如何正确配置 Multipath 存储,并给出磁盘组创建和管理的完整操作指南。


二、理论分析

2.1 Linux Multipath 原理

Linux 下的多路径功能由 DM (Device Mapper) Multipath 提供,它是内核 device-mapper 框架的一部分。其架构可以简单理解为:

1
2
3
4
5
6
7
8
9
应用层 (Oracle ASM)

/dev/mapper/mpathX (Multipath 逻辑设备)

device-mapper 内核模块 (路径选择、故障切换)

/dev/sdX (多个 SCSI 路径设备)

HBA 卡 → FC 交换机 → 存储控制器

Active-Passive 模式下,只有一条路径处于活动状态处理 IO,其余路径处于待命状态。当活动路径故障时,自动切换到备用路径。这种模式的路径切换时间较长(通常需要几秒),但实现简单、稳定性高。

Active-Active 模式下,所有路径同时处理 IO,实现真正的负载均衡。这要求存储阵列支持 ALUA (Asymmetric Logical Unit Access) 或明确支持并发 IO。大多数中高端存储(如 EMC Unity、HDS VSP、华为 OceanStor)都支持 ALUA。

Multipath 的核心配置参数包括:

  • path_checker:路径健康检查方式,常用 tur(TEST UNIT READY 命令)或 readsector0
  • path_grouping_policy:路径分组策略,failover(主备)、multibus(多路径共享)、group_by_prio(按优先级分组)
  • failback:故障恢复策略,immediate(立即回切)、manual(手动)、或指定秒数
  • no_path_retry:所有路径不可用时的重试策略,queue 表示排队等待,数字表示重试次数

2.2 ASM 磁盘发现机制

ASM 在启动时需要发现可用的磁盘,这一过程由 ASM_DISKSTRING 参数控制。该参数支持通配符,例如:

1
2
3
ALTER SYSTEM SET asm_diskstring = '/dev/mapper/mpath*' SCOPE=SPFILE;
-- 或使用 ASMFD
ALTER SYSTEM SET asm_diskstring = 'AFD:*' SCOPE=SPFILE;

ASM 发现磁盘后,会读取磁盘的前两个 AU 来获取 ASM 磁盘头信息。磁盘头结构称为 kfdhdb(Kernel File Directory Header Block),其中包含:

  • 磁盘名称、磁盘编号
  • 所属磁盘组名称和编号
  • AU 大小
  • 版本兼容性信息
  • 分配表(AT)和空闲空间表(FST)的位置

AU (Allocation Unit) 是 ASM 的最小分配单元,默认大小为 1MB(12c 及以后支持 4MB)。ASM 的条带化分为两种粒度:

  • Fine-grained striping:128KB 条带,适合 OLTP 系统的小 IO 随机读写
  • Coarse-grained striping:AU 大小条带,适合数据仓库的大 IO 顺序读写

2.3 ASM 冗余策略

ASM 提供三种冗余策略,每种策略有不同的适用场景:

External Redundancy:不提供 ASM 级别的镜像,完全依赖底层存储的 RAID 保护。适用于已有企业级存储 RAID 保护的场景(RAID 10、RAID 5 等)。空间利用率最高,为 100%。

Normal Redundancy:提供 2-way mirror,ASM 将每个 extent 的两份副本分布在不同的故障组(Failure Group)中。至少需要两个故障组。空间利用率为 50%。适用于没有存储级镜像的场景,或对数据保护有额外要求的场景。

High Redundancy:提供 3-way mirror,三个副本分布在三个故障组中。空间利用率为 33%。适用于对数据可用性要求极高的核心业务系统。

空间计算公式:

1
可用空间 = 磁盘组原始空间 × (1 / 冗余因子) - 文件系统开销

例如,10 块 1TB 磁盘的磁盘组,Normal Redundancy 的可用空间约为 (10 × 1TB × 0.5) - 开销 ≈ 4.5TB

2.4 ASM 权限管理

ASM 访问磁盘设备需要正确的权限配置。Linux 环境下有三种主要方案:

udev rules 方案:通过编写 udev 规则,将 Multipath 设备的 owner 设置为 oracle:oinstall,权限设置为 0660。这是最传统也是最通用的方案,适用于所有 Oracle 版本。

**ASMFD (ASM Filter Driver)**:Oracle 12c 引入的专用驱动,在内核层拦截对 ASM 磁盘的 IO,防止意外覆写 ASM 磁盘头。ASMFD 还简化了磁盘管理,无需手动配置权限。推荐在 12c 及以后版本中使用。

1
2
3
4
-- ASMFD 配置示例
$ asmcmd afd_label DATA01 /dev/mapper/mpathb
$ asmcmd afd_scan
$ asmcmd afd_lslbl

oracleasm 方案:使用 ASMLib 工具包,通过 oracleasm createdisk 命令标记磁盘。适用于 RHEL/OEL 系统,但自 RHEL 8 起不再提供原生 ASMLib 支持,需要第三方源。配置时需注意设置 ORACLEASM_SCANORDER="dm" 以优先扫描 Multipath 设备。


三、实战操作

3.1 多路径配置

获取 SCSI 设备的 WWID

首先需要确定存储映射的 LUN 对应的 SCSI ID(WWID),以便在 multipath.conf 中进行精确配置:

1
2
3
4
5
6
7
8
9
10
# 方法一:使用 scsi_id 命令(RHEL 6/7)
/lib/udev/scsi_id -g -u -d /dev/sdb
# 输出示例:360060160f8a03800c8e6c5b7e3c3e411

# 方法二:使用 /sys 文件系统(RHEL 8+)
/lib/udev/scsi_id --whitelisted --device=/dev/sdb

# 方法三:查看所有 SCSI 设备信息
cat /sys/block/sd*/device/vendor
lsscsi

完整的 multipath.conf 配置

以下是一个适用于 Oracle RAC 环境的 /etc/multipath.conf 完整配置示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# /etc/multipath.conf - Oracle RAC 环境配置
# 适用于 EMC/DELL PowerStore、HDS VSP、华为 OceanStor 等常见存储

defaults {
udev_dir /dev
polling_interval 10
path_selector "round-robin 0"
path_grouping_policy multibus
getuid_callout "/lib/udev/scsi_id -g -u -d /dev/%n"
path_checker tur
rr_min_io 100
rr_min_io_rq 1
max_fds 8192
no_path_retry fail
user_friendly_names yes
find_multipaths yes
}

# 黑名单:排除本地磁盘和 USB 设备
blacklist {
devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*"
devnode "^sd[a-b]$" # 本地系统盘,根据实际环境调整
device {
vendor "Dell"
product "Virtual"
}
device {
vendor "ATA"
}
}

# 黑名单例外:确保存储设备不被误排除
blacklist_exceptions {
wwid "360060160*"
# wwid "36000d310*" # 根据存储厂商的 wwid 前缀调整
}

# 默认配置
multipaths {
multipath {
wwid 360060160f8a03800c8e6c5b7e3c3e411
alias asm_data01
path_grouping_policy group_by_prio
path_selector "round-robin 0"
failback immediate
rr_weight priorities
no_path_retry 12
prio alua
}
multipath {
wwid 360060160f8a03800c8e6c5b7e3c3e412
alias asm_data02
path_grouping_policy group_by_prio
path_selector "round-robin 0"
failback immediate
rr_weight priorities
no_path_retry 12
prio alua
}
multipath {
wwid 360060160f8a03800c8e6c5b7e3c3e501
alias asm_fra01
path_grouping_policy group_by_prio
path_selector "round-robin 0"
failback immediate
rr_weight priorities
no_path_retry 12
prio alua
}
multipath {
wwid 360060160f8a03800c8e6c5b7e3c3e601
alias asm_ocr01
path_grouping_policy group_by_prio
path_selector "round-robin 0"
failback immediate
rr_weight priorities
no_path_retry queue
prio alua
}
}

devices {
device {
vendor "VNX"
product ".*"
path_grouping_policy group_by_prio
path_checker tur
path_selector "round-robin 0"
failback immediate
prio emc
no_path_retry 12
hardware_handler "0"
}
# 华为 OceanStor 配置示例
device {
vendor "HUAWEI"
product "XSG1"
path_grouping_policy group_by_prio
path_checker tur
path_selector "round-robin 0"
failback immediate
prio alua
no_path_retry 12
}
}

验证多路径配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 重载 multipath 配置
systemctl reload multipathd

# 查看多路径状态
multipath -ll

# 输出示例:
# asm_data01 (360060160f8a03800c8e6c5b7e3c3e411) dm-4 VNX,5300
# size=500G features='1 queue_if_no_path' hwhandler='1 alua'
# |- 3:0:0:0 sdb 8:16 active ready running
# |- 3:0:1:0 sdc 8:32 active ready running
# |- 4:0:0:0 sdd 8:48 active ready running
# `- 4:0:1:0 sde 8:64 active ready running

# 查看 multipath 设备拓扑
multipath -v3 -d # dry-run 模式,不实际执行

# 查看 dm 设备信息
dmsetup ls
dmsetup status

3.2 ASM 磁盘准备

方案一:使用 udev 配置磁盘权限

在 RHEL 7/8 中,创建 udev 规则文件 /etc/udev/rules.d/99-oracle-asmdevices.rules

1
2
3
4
5
6
7
8
9
10
# /etc/udev/rules.d/99-oracle-asmdevices.rules
# 方式一:按 wwid 匹配(推荐)
ACTION=="add|change", ENV{DM_UUID}=="mpath-360060160f8a03800c8e6c5b7e3c3e411", OWNER="oracle", GROUP="oinstall", MODE="0660"
ACTION=="add|change", ENV{DM_UUID}=="mpath-360060160f8a03800c8e6c5b7e3c3e412", OWNER="oracle", GROUP="oinstall", MODE="0660"
ACTION=="add|change", ENV{DM_UUID}=="mpath-360060160f8a03800c8e6c5b7e3c3e501", OWNER="oracle", GROUP="oinstall", MODE="0660"
ACTION=="add|change", ENV{DM_UUID}=="mpath-360060160f8a03800c8e6c5b7e3c3e601", OWNER="oracle", GROUP="oinstall", MODE="0660"

# 方式二:按 alias 匹配
# ACTION=="add|change", ENV{DM_NAME}=="asm_data01", OWNER="oracle", GROUP="oinstall", MODE="0660"
# ACTION=="add|change", ENV{DM_NAME}=="asm_data02", OWNER="oracle", GROUP="oinstall", MODE="0660"
1
2
3
4
5
6
7
8
# 重载 udev 规则
udevadm control --reload-rules
udevadm trigger --type=devices --action=change

# 验证权限
ls -l /dev/mapper/asm_*
# brw-rw---- 1 oracle oinstall 253, 4 Jun 5 10:00 /dev/mapper/asm_data01
# brw-rw---- 1 oracle oinstall 253, 5 Jun 5 10:00 /dev/mapper/asm_data02

方案二:ASMFD 配置流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 1. 配置 ASMFD 驱动(在 Grid Infrastructure 安装前执行)
$ asmcmd afd_configure
# 或在 GI 安装过程中选择 "Configure ASM Filter Driver"

# 2. 标记磁盘
$ asmcmd afd_label DATA01 /dev/mapper/asm_data01
$ asmcmd afd_label DATA02 /dev/mapper/asm_data02
$ asmcmd afd_label FRA01 /dev/mapper/asm_fra01
$ asmcmd afd_label OCR01 /dev/mapper/asm_ocr01

# 3. 扫描并验证
$ asmcmd afd_scan
$ asmcmd afd_lslbl
# ------------------------------------------------------------------------------------------------
# Label Duplicate Path
# =================================================================================================
# DATA01 No /dev/mapper/asm_data01
# DATA02 No /dev/mapper/asm_data02
# FRA01 No /dev/mapper/asm_fra01
# OCR01 No /dev/mapper/asm_ocr01

# 4. 在 RAC 的所有节点执行 afd_scan
$ ssh racnode2 "asmcmd afd_scan"

方案三:oracleasm createdisk

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 在所有节点执行
# 1. 配置 oracleasm
$ /etc/init.d/oracleasm configure
# Default user: oracle
# Default group: oinstall
# Start on boot: y
# Scan for disk on boot: y

# 2. 关键:配置扫描顺序,优先扫描 multipath 设备
# 编辑 /etc/sysconfig/oracleasm
ORACLEASM_SCANORDER="mpath dm"
ORACLEASM_SCANEXCLUDE="sd"

# 3. 创建 ASM 磁盘(在任一节点执行)
$ /etc/init.d/oracleasm createdisk DATA01 /dev/mapper/asm_data01
$ /etc/init.d/oracleasm createdisk DATA02 /dev/mapper/asm_data02
$ /etc/init.d/oracleasm createdisk FRA01 /dev/mapper/asm_fra01
$ /etc/init.d/oracleasm createdisk OCR01 /dev/mapper/asm_ocr01

# 4. 在其他节点扫描
$ /etc/init.d/oracleasm scandisks
$ /etc/init.d/oracleasm listdisks

3.3 ASM 磁盘组创建

三种冗余级别的磁盘组创建语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
-- 1. External Redundancy:用于 DATA 磁盘组(存储层已有 RAID 10 保护)
CREATE DISKGROUP DATA EXTERNAL REDUNDANCY
DISK '/dev/mapper/asm_data01' NAME DATA_001,
DISK '/dev/mapper/asm_data02' NAME DATA_002
ATTRIBUTE
'compatible.asm' = '19.0',
'compatible.rdbms' = '19.0',
'au_size' = '4M';

-- 2. Normal Redundancy:用于 FRA 磁盘组
CREATE DISKGROUP FRA NORMAL REDUNDANCY
FAILGROUP FG1 DISK '/dev/mapper/asm_fra01' NAME FRA_001
FAILGROUP FG2 DISK '/dev/mapper/asm_fra02' NAME FRA_002
ATTRIBUTE
'compatible.asm' = '19.0',
'compatible.rdbms' = '19.0',
'au_size' = '4M';

-- 3. High Redundancy:用于 OCR/Voting Disk 磁盘组
CREATE DISKGROUP OCR HIGH REDUNDANCY
FAILGROUP FG1 DISK '/dev/mapper/asm_ocr01' NAME OCR_001
FAILGROUP FG2 DISK '/dev/mapper/asm_ocr02' NAME OCR_002
FAILGROUP FG3 DISK '/dev/mapper/asm_ocr03' NAME OCR_003
ATTRIBUTE
'compatible.asm' = '19.0',
'compatible.rdbms' = '19.0';

兼容性属性说明

  • compatible.asm:ASM 实例的最低兼容版本。设置后不可回退,影响 ASM 集群的功能特性。
  • compatible.rdbms:数据库实例的最低兼容版本。如果数据库版本低于此值,将无法挂载该磁盘组。
  • au_size:Allocation Unit 大小。12c 起支持 4MB,对大表空间能减少 extent map 的碎片化。

条带化与性能优化

ASM 的条带化模式在 11g 以后默认使用 Coarse striping(AU 粒度)。对于 OLTP 系统,可以在文件级别设置 Fine striping:

1
2
-- 在数据库层面创建表空间时使用 Fine-grained striping
-- 需要通过文件属性控制,通常建议让 ASM 自动管理

最佳实践是将数据文件和归档日志放在不同的磁盘组(DATA vs FRA),避免 IO 竞争。

3.4 ASM 管理

asmcmd 常用命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 查看磁盘组状态
asmcmd lsdg

# 查看磁盘信息
asmcmd lsblk
# 或在 SQL 中:
# SQL> SELECT name, path, header_status, state, total_mb, free_mb FROM V$ASM_DISK;

# 查看实例信息
asmcmd lsinst

# 切换到特定磁盘组并浏览文件
asmcmd
ASMCMD> cd +DATA
ASMCMD> ls
ASMCMD> find +DATA -name "*.dbf"

# 手动 rebalance
ASMCMD> rebal -w # 等待 rebalance 完成

# 查看 rebalance 进度
ASMCMD> lsop

磁盘添加/删除/替换流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
-- 1. 添加新磁盘到现有磁盘组
ALTER DISKGROUP DATA ADD
DISK '/dev/mapper/asm_data03' NAME DATA_003
REBALANCE POWER 8;

-- 2. 监控 rebalance 进度
SELECT group_number, operation, state, power, est_minutes
FROM V$ASM_OPERATION;

-- 3. 删除磁盘(rebalance 会自动迁移数据)
ALTER DISKGROUP DATA DROP DISK DATA_003;

-- 4. 替换磁盘(先删后加)
ALTER DISKGROUP DATA
DROP DISK DATA_001
ADD DISK '/dev/mapper/asm_data04' NAME DATA_004
REBALANCE POWER 8;

-- 5. 在线调整 rebalance 功率(0-11,0 表示暂停)
ALTER DISKGROUP ALL REBALANCE POWER 4;

-- 6. 挂载/卸载磁盘组
ALTER DISKGROUP DATA MOUNT;
ALTER DISKGROUP DATA DISMOUNT;

-- 7. 检查磁盘组一致性
ALTER DISKGROUP DATA CHECK ALL;

自动化监控脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
-- 检查所有磁盘组的空间使用率
SELECT name,
type,
total_mb,
free_mb,
ROUND((1 - free_mb / total_mb) * 100, 2) AS used_pct,
ROUND(free_mb / DECODE(type, 'EXTERN', 1, 'NORMAL', 2, 'HIGH', 3), 2) AS effective_free_mb
FROM V$ASM_DISKGROUP
ORDER BY used_pct DESC;

-- 检查磁盘状态异常
SELECT name, path, header_status, mode_status, state
FROM V$ASM_DISK
WHERE header_status != 'MEMBER'
OR mode_status != 'ONLINE'
OR state != 'NORMAL';

四、结果验证

完成所有配置后,需要逐层验证整个存储链路:

4.1 Multipath 层验证

1
2
3
4
5
6
7
8
9
10
11
12
13
# 确认所有路径均为 active/ready
multipath -ll | grep -E "(active|faulty|failed)"
# 所有路径应显示 "active ready running"

# 检查路径数量是否与预期一致
multipath -ll | grep -c "ready"
# 应等于 HBA 卡数 × 存储控制器数(通常为 4 条路径)

# 模拟路径故障测试
echo 1 > /sys/block/sdb/device/delete
# 等待几秒后 multipath -ll 确认路径切换正常
# 然后重新扫描 SCSI 设备恢复
echo "- - -" > /sys/class/scsi_host/host3/scan

4.2 ASM 层验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-- 检查磁盘组状态
SELECT name, state, type, total_mb, free_mb
FROM V$ASM_DISKGROUP;
-- state 应为 MOUNTED

-- 检查磁盘状态
SELECT name, path, header_status, mode_status, state, total_mb, free_mb
FROM V$ASM_DISK
ORDER BY group_number, disk_number;
-- header_status 应为 MEMBER,mode_status 应为 ONLINE

-- 检查 ASM 实例参数
SELECT name, value FROM V$PARAMETER
WHERE name IN ('asm_diskstring', 'asm_power_limit', 'asm_diskgroups');

4.3 ASM Alert 日志检查

1
2
3
4
5
6
7
8
# 查看 ASM alert 日志(12c+ 位置)
$ tail -100 $ORACLE_BASE/diag/asm/+asm/+ASM1/trace/alert_+ASM1.log

# 关注以下关键字:
# - "Disk group XXX mounted successfully"
# - "WARNING: Read Failed" — 表示有 IO 读取失败
# - "ORA-27072" — 文件 IO 错误
# - "rebalance completed" — rebalance 操作完成

4.4 IO 性能验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 使用 fio 测试 Multipath 设备的 IO 性能
fio --name=asm_test \
--filename=/dev/mapper/asm_data01 \
--direct=1 \
--rw=randread \
--bs=8k \
--numjobs=4 \
--size=1G \
--runtime=60 \
--group_reporting

# 使用 Oracle Orion 工具测试
# Orion 是 Oracle 官方提供的 IO 性能测试工具
$ orion -run advanced -testname asm_io \
-num_disks 10 -size_small 8 -size_large 1024 \
-type rand -matrix point \
-num_large 1 -num_small 8

五、经验总结

5.1 存储配置 Checklist

在每次部署 RAC + ASM 环境前,建议按以下清单逐项确认:

检查项 说明 状态
HBA 卡冗余 每个节点至少 2 块 HBA 卡
存储控制器冗余 LUN 映射到双控制器
Multipath 配置 所有存储 LUN 均通过 Multipath 设备访问
路径状态 multipath -ll 所有路径 active
设备权限 oracle:oinstall 0660
ASM_DISKSTRING 指向 Multipath 设备路径
SCSI ID 唯一性 每个 LUN 的 WWID 唯一
udev 规则 所有节点规则一致
I/O 调度器 设置为 noop 或 none
大页内存 配置 HugePages

5.2 ASM 磁盘组命名规范

建议采用统一的命名规范:

1
2
3
4
5
6
磁盘组前缀_用途编号
示例:
+DATA01 — 第一组数据磁盘组
+FRA01 — 闪回恢复区
+OCR01 — OCR 和 Voting Disk
+REDO01 — 专用 Redo 磁盘组(高 IOPS 场景)

5.3 常见存储问题快速定位

问题 1:ASM 实例无法发现磁盘

1
2
3
4
5
6
# 检查步骤:
# 1. 确认 Multipath 设备存在
ls -l /dev/mapper/asm_*
# 2. 确认权限正确
# 3. 确认 asm_diskstring 参数正确
# 4. 检查 ASM 实例参数中是否设置了正确的磁盘发现路径

问题 2:路径切换导致 RAC 节点驱逐

1
2
3
4
# 检查 Multipath 的 no_path_retry 设置
# 建议设置为 queue(排队等待),避免 IO 失败触发 CSS 超时
# 同时检查 CSS misscount 参数
$ crsctl get css misscount # 默认 30 秒

问题 3:磁盘组空间告警

1
2
3
4
5
6
-- 紧急释放空间
-- 1. 删除不需要的归档日志和备份
-- 2. resize 数据文件
ALTER DATABASE DATAFILE '+DATA/prod/users01.dbf' RESIZE 10G;
-- 3. 添加新磁盘
ALTER DISKGROUP DATA ADD DISK '/dev/mapper/asm_data05' NAME DATA_005;

5.4 大规模环境的 ASM 管理经验

在管理超过 50 个节点的 RAC 集群时,以下经验非常有价值:

  1. 使用 ASMFD 替代 udev + oracleasm:ASMFD 提供更好的内核级保护,减少配置不一致的风险。
  2. 磁盘组不要太大:单个磁盘组建议不超过 20TB,避免 rebalance 时间过长。
  3. 合理设置 ASM_POWER_LIMIT:日常使用较低功率(2-4),维护窗口时提高到 8-11。
  4. 定期检查磁盘组一致性:通过 ALTER DISKGROUP ... CHECK 定期验证。
  5. 监控 IO 延迟:关注 V$ASM_DISK_STAT 中的读写延迟指标。
  6. **建立标准操作流程 (SOP)**:所有存储变更必须有文档记录和回滚方案。

写在最后:存储是数据库的根基,RAC + ASM 的高可用架构建立在正确的存储配置之上。Multipath 配置虽然看似简单,但它处于 IO 路径的最底层,一旦出问题,影响面极大。希望本文的内容能帮助大家在实际工作中少踩坑、多避雷。如果遇到复杂的存储问题,欢迎在评论区交流讨论。

Oracle Grid Infrastructure (GI) 是 RAC 架构的基石,负责集群管理、存储管理、网络管理三大核心功能。然而,很多 DBA 对 GI 的理解仅停留在 crsctl start/stop 的层面,一旦遇到 OCR 损坏、Voting Disk 丢失、SCAN IP 漂移等生产故障,往往束手无策。本文将从底层机制出发,深入剖析 GI 的核心组件与启动逻辑,帮助读者建立对 GI 架构的系统性认知。

阅读全文 »

作为 OCM 认证 DBA,在多年的企业级交付实践中,我深刻体会到:数据库环境的标准化交付能力,是衡量一个 DBA 团队工程化水平的核心指标。本文将系统梳理 Oracle 19c 与 23ai 的静默安装最佳实践,从 Response File 参数解析到完整的自动化脚本,帮助你实现”一次编写、到处部署”的标准化交付。

阅读全文 »