1. 为什么用ADG:从一次真实需求说起
前几天帮一个客户搭 Oracle 19c ADG,客户的需求很典型:生产库是一台单机 19c,跑着核心业务系统,数据量大概 2TB 左右,每天归档日志量在 80GB 上下。他们之前没有真正的灾备手段,只靠每晚的 RMAN 全备,恢复时间目标(RTO)在 8 小时以上,恢复点目标(RPO)接近 24 小时。老板要求把故障恢复时间压缩到 30 分钟以内,数据丢失最多不能超过 5 分钟。
这种需求一出来,基本就锁定 Active Data Guard 了。Oracle Data Guard(DG)是 Oracle 自带的灾备方案,传统 Data Guard 的备库只能接收日志、应用日志,但不能对外提供只读查询;而 Active Data Guard(ADG)在此基础上开放了实时查询能力,备库在应用日志的同时可以对外提供只读访问,一套环境既做灾备又分担了主库的读压力。而且 19c 的 ADG 功能已经很成熟,配合 Far Sync、备库闪回、DG Broker 这些特性,日常运维比想象中轻松很多。
这篇文章不是纯理论科普,我直接按照这次实际搭建过程来写。内容涵盖环境规划、主备库参数配置、duplicate 建库、DG Broker 配置、日常监控指标,以及我在搭建过程中踩过的坑和排查思路。不管你是第一次接触 DG 还是已经搭过 11g 的 DG,这篇都能给你一些能直接落地的参考。
先说适用范围:Oracle 19c(19.16 以上补丁版本)、Linux 环境、单机到单机架构。RAC 到 RAC 的搭建逻辑类似,但涉及 scan listener 和 ASM 的部分会有差异,这次不展开。如果你正在评估灾备方案或者准备在生产环境上做 ADG,这篇文章可以帮你少走不少弯路。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 整体架构设计与关键参数
2.1 架构选型背后的逻辑
DG 的基础原理其实不难理解:主库持续产生 redo 日志,通过 LGWR 或 ARCH 进程把日志传到备库,备库拿到归档或在线日志后,用 MRP(Managed Recovery Process)进程去应用这些日志,从而保持与主库的数据一致。ADG 和普通 DG 的区别在于,备库在应用日志的同时可以把数据文件打开为只读状态,这就是 19c 的 Active Data Guard。
我在方案选型时重点考虑了三个点。第一,只读分流需求是否强烈。客户有一个报表库每天晚上跑大量统计查询,而这些查询的数据滞后十分钟完全可以接受,这种情况下 ADG 的实时查询功能就能把主库的负载明显降下来。第二,网络链路质量。主备库之间的网络延迟约 5ms,带宽 1000M,DG 默认的 SYNC 传输模式完全能满足,延迟和带宽都远不是瓶颈。第三,是否需要快速切换能力。客户接受备库在必要时以最大性能模式运行,所以我没有把 Data Protection Mode 设置为 Maximum Protection,而是选择 Maximum Performance 配合 SYNC 传输,兼顾安全和性能。
如果你也是第一次做 ADG,建议先明确自己的 RPO/RTO 目标。RPO 要求小于 5 秒,就考虑 SYNC + Maximum Availability;RPO 在 5 分钟以上,用 ASYNC 就足够。不需要一开始就把所有参数都调到最严格,生产环境的稳定比理论上的极致安全更重要。
2.2 主机与目录规划
这次搭建的环境如下,我给出一份可以照着用的配置表:
| 项目 | 主库 | 备库 |
|---|---|---|
| 数据库版本 | 19.16.0.0 | 19.16.0.0 |
| 主机系统 | CentOS 7.6 | CentOS 7.6 |
| 主机名 | db19a | db19b |
| 公共IP | 192.168.56.101 | 192.168.56.102 |
| ORACLE_SID | orcl | orcl |
| DB_UNIQUE_NAME | orcl | orclstd |
| ORACLE_HOME | /u01/app/oracle/product/19.0.0/dbhome_1 | /u01/app/oracle/product/19.0.0/dbhome_1 |
| 数据文件目录 | /u02/oradata/orcl | /u02/oradata/orclstd |
| 归档目录 | /u03/arch/orcl | /u03/arch/orclstd |
这里要强调一个很容易忽略的点:主备库的 ORACLE_HOME 路径必须一致。如果你主库装在 /u01/app/oracle/product/19.0.0/dbhome_1,备库也要用同样的路径,否则后面 duplicate 的时候会因为路径不匹配而报错。如果确实无法统一,也可以在 pfile 里通过 db_file_name_convert 和 log_file_name_convert 参数做路径映射,但能避免就尽量避免,多一层映射就是多一个出错的环节。
DB_UNIQUE_NAME 是 DG 的核心标识,主备库通过这个名称来区分彼此。主库叫 orcl,备库叫 orclstd,这样在 Data Guard Broker 里可以同时管理两个库。注意这里不要误会:两个库的 ORACLE_SID 都可以是 orcl,只要 DB_UNIQUE_NAME 不同就行,SID 相同不影响 DG 部署。数据文件目录建议和 DB_UNIQUE_NAME 一致,这样在备库上看到的是 /u02/oradata/orclstd 而不是 /u02/oradata/orcl,避免自己在操作时搞混。
2.3 主库准备工作的关键清单
主库侧的准备工作,很多人会漏掉 FORCE LOGGING 和补充日志,这两个不做,后面出了问题是要吃大亏的。
先开启归档模式。19c 默认可能是 NOARCHIVELOG,你需要在 mount 阶段执行:
sql复制shutdown immediate;
startup mount;
alter database archivelog;
alter database open;
然后确认归档是否开启:
sql复制archive log list;
接着开启 FORCE LOGGING 和补充日志:
sql复制alter database force logging;
alter database add supplemental log data (primary key, unique index) columns;
为什么要开 FORCE LOGGING?因为生产库里总有一些操作是 nologging 的,比如直接路径加载、索引 rebuild 等。如果这些操作不记录 redo,备库就无法看到这些数据变更,主备数据就会不一致。FORCE LOGGING 从数据库层面强制所有操作写 redo,从根本上杜绝这个风险。补充日志则是为 DG 的 SQL Apply 服务的,特别是备库作为只读库被查询时,需要通过补充日志来正确解析 redo 中的变更内容。
最后,确认主库的 DB_UNIQUE_NAME 和数据库名字:
sql复制show parameter db_name;
show parameter db_unique_name;
主库默认 DB_UNIQUE_NAME 和 DB_NAME 一样,就是 orcl。我们后面会在备库把 db_unique_name 改成 orclstd,但 db_name 保持不变,这样 DG 才认为它们是同一个数据库的副本。
3. 备库侧的软件准备和监听配置
主库准备好了,接下来在备库机器上安装 Oracle 19c 软件。很多人在这里有个误区:以为备库也安装一次数据库软件和建库流程,直接建一个空库,然后再通过 RMAN duplicate 把主库的数据灌过去。这个思路可以走通,但更容易的方式是只在备库安装 Oracle 软件,不建库,然后在配置好 listener 和参数文件之后,用 RMAN duplicate 直接创建备库。整个过程主库会被当作数据源,RMAN 通过网络把备份数据传输到备库并完成恢复。
安装 Oracle 19c 软件这一步,和普通单机安装完全一样。这里只提醒几个细节:预安装包要装全(binutils、compat-libcap1、compat-libstdc++-33 等),内核参数看 19c 官方要求,通常如下:
bash复制fs.aio-max-nr=1048576
fs.file-max=6815744
kernel.shmall=1073741824
kernel.shmmax=4398046511104
kernel.shmmni=4096
kernel.sem=250 32000 100 128
net.ipv4.ip_local_port_range=9000 65500
net.core.rmem_default=262144
net.core.rmem_max=4194304
net.core.wmem_default=262144
net.core.wmem_max=1048576
第一次搭建时很容易忽略的是 shmmax 的值。Linux 默认的 kernel.shmmax 比较小,如果不调大,Oracle 实例启动时可能报 ORA-27102: out of memory。很多人在备库上反复折腾报错,其实就是这个内核参数没调。
软件装完后,我们来配置 listener。备库的 listener 需要同时支持动态注册和静态注册。动态注册用于备库实例起来后自动注册到监听,静态注册则用于 RMAN duplicate 阶段——那时候备库还没有实例,listener 必须能通过静态服务名把连接转发给数据库。静态注册的配置在 $ORACLE_HOME/network/admin/listener.ora 里,类似这样:
bash复制SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(GLOBAL_DBNAME = orclstd)
(ORACLE_HOME = /u01/app/oracle/product/19.0.0/dbhome_1)
(SID_NAME = orcl)
)
)
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = db19b)(PORT = 1521))
)
)
注意 GLOBAL_DBNAME 是 db_unique_name + db_domain 的组合,这里 db_unique_name 是 orclstd,没有配 db_domain,所以就是 orclstd。SID_NAME 是 orcl,因为实例名是 orcl。这个配置完成后,用 lsnrctl status 检查,应该能看到 orclstd 作为静态服务存在。
主备库之间要能互相通过 TNS 连接。我们在两台机器的 tnsnames.ora 中都要配好主库和备库的连接串:
bash复制ORCL =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.56.101)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = orcl)
)
)
ORCLSTD =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.56.102)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = orclstd)
)
)
配完之后用 tnsping 主备库各自验证。我在实际环境里遇到过一个很尴尬的问题:双方 tnsping 都能通,但 RMAN duplicate 时老报 ORA-12154,最后发现是备库的 tnsnames.ora 文件权限不对,Oracle 用户没有读取权限。这个后面在常见问题里细说。
4. 参数文件准备与 RMAN duplicate 建库
4.1 备库参数文件的核心设置
备库不建库,但我们得先给它准备一个初始化参数文件,让实例能起来。注意这里用的是 pfile,不是 spfile,因为备库首次启动时需要指定一些转换参数,用 pfile 更容易编辑和排错。等 duplicate 成功后,再把 pfile 转成 spfile。
备库 pfile 里的核心参数如下:
bash复制*.db_name='orcl'
*.db_unique_name='orclstd'
*.control_files='/u02/oradata/orclstd/control01.ctl','/u02/oradata/orclstd/control02.ctl'
*.db_file_name_convert='/u02/oradata/orcl','/u02/oradata/orclstd'
*.log_file_name_convert='/u02/oradata/orcl','/u02/oradata/orclstd'
*.db_recovery_file_dest='/u03/fast_recovery_area/orclstd'
*.db_recovery_file_dest_size=500G
*.log_archive_format='%t_%s_%r.arc'
*.fal_client='orclstd'
*.fal_server='orcl'
*.standby_file_management='AUTO'
*.local_listener='(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.56.102)(PORT=1521))'
*.remote_listener=''
db_name 必须和主库一致,否则 Oracle 不认为这是同一个数据库。db_unique_name 是备库的独立标识,设为 orclstd。db_file_name_convert 和 log_file_name_convert 用于路径转换:主库的数据文件在 /u02/oradata/orcl,备库要放在 /u02/oradata/orclstd,duplicate 时 RMAN 会根据这个参数把路径替换掉。fal_client 和 fal_server 是备库请求缺失归档时用的配置,fal_server 指向主库的服务名,fal_client 指向自己,缺一不可。
standby_file_management 设为 AUTO 后,主库添加/删除数据文件时,备库会自动同步文件操作,不需要你手工干预,强烈建议开启。
参数文件准备好后,用如下方式启动到 nomount:
bash复制export ORACLE_SID=orcl
sqlplus / as sysdba
startup nomount pfile='/tmp/init_orclstd.ora';
此时实例已经起来,但还没有控制文件和数据文件。接下来我们通过 RMAN duplicate 从主库拉数据过来。
4.2 RMAN duplicate 执行过程
RMAN duplicate 有两种方式:一种是从主库的备份集恢复,另一种是直接从活跃数据库复制。既然我们的主备库网络是好的,我直接用 from active database 方式,不需要先做全备,效率更高。
在备库上执行 rman,注意连接方式:
bash复制rman auxiliary /
然后执行 duplicate 命令:
bash复制DUPLICATE TARGET DATABASE
FOR STANDBY
FROM ACTIVE DATABASE
DBC_FILE_NAME_CONVERT '/u02/oradata/orcl','/u02/oradata/orclstd'
LOG_FILE_NAME_CONVERT '/u02/oradata/orcl','/u02/oradata/orclstd'
SPFILE
SET db_unique_name='orclstd'
SET db_file_name_convert='/u02/oradata/orcl','/u02/oradata/orclstd'
SET log_file_name_convert='/u02/oradata/orcl','/u02/oradata/orclstd'
SET control_files='/u02/oradata/orclstd/control01.ctl','/u02/oradata/orclstd/control02.ctl'
SET local_listener='(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.56.102)(PORT=1521))'
NOFILENAMECHECK;
执行之前我习惯先在主库做一次校验,确认主库没有未归档的日志,并记录当前日志序号,方便 duplicate 结束后对比:
bash复制sqlplus / as sysdba
alter system archive log current;
select max(sequence#) from v$log_history;
执行 duplicate 的过程中,RMAN 会自动完成以下几件事:连接主库,把主库的数据文件、控制文件、归档日志通过网络传输到备库,重新生成备库的控制文件,并通过 SPFILE 子句把你在命令里指定的参数写入备库的 spfile。整个耗时取决于数据量大小和网络带宽。2TB 的库在千兆网络下大约需要 4 到 6 个小时,如果你的数据量只有几百 GB,半小时到一小时就够了。
执行完成后,备库会自动打开并启动 MRP 进程应用日志。你可以通过如下命令验证:
sql复制select name, db_unique_name, database_role, open_mode from v$database;
select process, status from v$managed_standby;
正常情况下,database_role 是 PHYSICAL STANDBY,open_mode 是 READ ONLY WITH APPLY,这里的 WITH APPLY 就是 ADG 的实时查询模式。如果 open_mode 是 MOUNTED,说明 MRP 还没启动,需要手动执行:
sql复制alter database recover managed standby database using current logfile disconnect from session;
实时查询模式要求备库在应用日志的同时保持只读打开,所以 MRP 必须使用 using current logfile 模式,也就是实时应用。如果使用普通模式,备库只能处于 MOUNTED 状态,无法对外提供只读访问,那就退化成普通 DG 了。
5. DG Broker 配置与日常切换演练
5.1 启用 DG Broker
很多 DBA 不喜欢配置 DG Broker,觉得参数太绕,但我的经验是:必须配。DG Broker 把 Data Guard 的配置统一管理起来,无论是查看状态、手动切换还是故障转移,都只需要一条命令,比手动执行一堆 SQL 要靠谱得多。
在配置 Broker 之前,先确认主备库已经在参数文件里写入了 dg_broker_start。如果没有,就手动开启:
sql复制alter system set dg_broker_start=true scope=both;
注意主备库都要执行。然后以 sysdba 身份连接主库的监听,用 dgmgrl 创建配置:
bash复制dgmgrl sys/oracle@orcl
create configuration dg_config as primary database is orcl connect identifier is orcl;
add database orclstd as connect identifier is orclstd maintained as physical;
enable configuration;
这几条命令的执行过程里,Broker 会检查主备库的很多细节,比如 db_unique_name 是否正确、日志传输是否正常、MRP 是否在跑。如果哪一步报错,先别慌,用 show configuration 查看具体错误:
bash复制show configuration;
show database orcl;
show database orclstd;
show configuration 的输出会有一个 Database Status 列,常见值是 SUCCESS、WARNING、ERROR。如果是 ERROR,一般会跟着具体的错误信息,照着解决即可。我还遇到过一种情况:Broker 配置时报 ORA-16525,这通常是因为主备库的 db_unique_name 与 Broker 配置里的不一致,检查一下 db_unique_name 和 tnsnames.ora 中的服务名是否匹配。
配置完成后,正常状态下 show configuration 会显示:
text复制Configuration - dg_config
Protection Mode: MaxPerformance
Members:
orcl - Primary database
orclstd - Physical standby database
Fast-Start Failover: DISABLED
Configuration Status:
SUCCESS
看到 SUCCESS 才说明 DG 整体链路通了。
5.2 主备切换和故障转移演练
切换(Switchover)是计划内的主备角色互换,正常情况下不丢数据。很多 DBA 担心切换时业务中断的时间太长,其实在 19c 里,切换过程是很快的,主要时间花在业务连接的重连上。
使用 Broker 做切换很简单:
bash复制dgmgrl sys/oracle@orcl
switchover to orclstd;
执行过程中,Broker 会自动完成主库转备库、备库转主库的所有步骤,包括日志传输的角色反转、MRP 进程的启停等。切换完成后,用 show configuration 确认新主库状态正常,然后验证数据一致性:
sql复制select database_role, open_mode from v$database;
select max(sequence#) from v$log_history;
我把切换演练放在业务低峰期做,整体耗时 2 分钟左右,其中真正切换动作不到 30 秒,剩下的是我在验证连接和数据。如果你的业务系统对数据库连接有依赖,切换前最好通知应用团队,让他们在窗口期重新建立连接池。
故障转移(Failover)是主库彻底挂了时的强制接管。使用 Broker 也一样:
bash复制dgmgrl sys/oracle@orclstd
failover to orclstd;
注意 failover 是破坏性的操作:原主库会被踢出配置,之后如果需要恢复原主库,要重新做数据库闪回或 rebuild。所以 failover 只能在确认主库短时间内无法恢复时执行,千万别拿它当日常切换用。
我个人建议每季度做一次 switchover 演练。原因很简单:灾备方案不演练等于没有,真到故障发生时手忙脚乱的例子我见得太多了。切换演练还能顺便验证应用连接配置是否支持主备库自由切换,很多业务系统一开始连的是固定 IP,切换后不更新连接串就全乱套。
6. 日常监控与核心运维指标
6.1 关键视图与检查项
ADG 搭好之后,监控比搭建更重要。日常巡检,我一般固定看这几个视图:
- v$database:看 database_role、open_mode、protection_mode,确认角色和状态符合预期。
- v$managed_standby:看 MRP 进程是否 active,这个进程挂了备库就停止应用日志。
- v$dataguard_stats:看主备库的 redo 传输延迟和 apply 延迟,这是判断 DG 健康度的核心指标。
- v$archive_dest_status:看日志传输目的地是否正常,是否存在 error。
- v$standby_log:看 standby redo log 的大小和填充情况,太小会影响日志应用效率。
查询语句也不复杂:
sql复制select database_role, db_unique_name, open_mode, protection_mode
from v$database;
select process, status, sequence#, delay_mins
from v$managed_standby
order by process;
select name, value, unit, time_computed
from v$dataguard_stats
where name in ('transport lag', 'apply lag');
v$dataguard_stats 里的 transport lag 表示主库最新 redo 离备库接收点之间的时间差,apply lag 表示备库应用日志的滞后时间。正常情况下这两个值都应该接近 0 秒。如果 apply lag 持续增长,可能是备库磁盘 IO 太慢,或者 SQL Apply 遇到性能瓶颈。
6.2 归档日志缺口(GAP)处理
说一个高频问题:主备库网络中断半天,恢复后备库可能报 gap,也就是缺失了几个归档日志序列。19c 的自动 gap 修复机制非常成熟,通常网络恢复后,备库的 FAL 进程会自动从主库拉取缺失的日志。但如果主库已经把缺失的归档删了,比如备份任务把归档清掉了,那就需要用 RMAN 增量备份来补。
处理逻辑大致如下:
sql复制-- 备库取消日志应用
alter database recover managed standby database cancel;
-- 在主库做增量备份
backup incremental level 1 database;
-- 把备份传到备库并恢复
restore database;
recover database noredo;
-- 重新启动日志应用
alter database recover managed standby database using current logfile disconnect from session;
这套操作的关键在于,增量备份的起点要覆盖到备库有日志的最后一个序列号。实际操作时,RMAN 会自动根据备库的 scn 信息生成从上一个共同点开始的增量备份,省去了不少麻烦。但如果你发现返回的 gap 范围跨越了主库的旧备份,那说明 gap 太深,增量备份没法自动处理,这时候可能要手工从某个更早的备份点恢复备库,处理起来要复杂得多。
所以我的建议是:主库的归档日志保留策略尽量大于等于一天的量,同时定期做增量备份,确保备库即使 gap 很久也能轻松修复。
6.3 与备份策略的联动
备库不是不用备份。有人觉得备库就是灾备副本,不需要备份了,这个想法很危险。ADG 备库的数据库文件虽然和主库保持一致,但如果你误删了主库上的数据文件,或者主库整库丢失,备库就变成了你的唯一数据来源,这时候没有备份就只能干瞪眼。
我的习惯是:主库保留最近一周的备份,备库保留最近两个月的备份。具体做法是,在主库通过 RMAN 的 backup database plus archivelog 做整库备份,同时定期在备库上做 backup database(注意这里备份的是备库的数据文件,不涉及日志)。由于备库日常承担只读查询,备份对主库的性能影响很小,所以我会把备库备份安排在白天查询高峰后,避开晚间的备份窗口。
另外说一下闪回。如果你的主库闪回开启着,切换演练时出问题可以快速闪回原主库,避免重新搭建。备库同样建议开启闪回,因为 failover 之后原主库恢复时通常需要 flashback database 回到 failover 前的点。
sql复制alter database flashback on;
闪回区大小要提前规划好。我客户这个环境闪回区给了 500G,对 2TB 的库来说,能覆盖大约 6 到 8 小时的闪回窗口,足够应对意外情况。
7. 常见问题与故障排查实录
ADG 搭建过程中我遇到的问题不算多,但每个都挺典型,我整理了四个最常见的,你可以直接对照排查。
7.1 ORA-12154: TNS: could not resolve the connect identifier specified
这是 duplicate 阶段特别常见的问题。表现是 RMAN 执行 duplicate 时报连接主库失败,但 tnsping 明明能通。排查方法是先确认在备库机器上用 sqlplus 能不能连上主库:
bash复制sqlplus sys/oracle@orcl as sysdba
如果 sqlplus 能连、rman 不能连,大概率是 tnsnames.ora 文件权限问题。我当时检查发现 tnsnames.ora 是 root 用户创建的,Oracle 用户没有读权限,导致 RMAN 进程解析不了服务名。解决:
bash复制chmod 644 $ORACLE_HOME/network/admin/tnsnames.ora
chown oracle:oinstall $ORACLE_HOME/network/admin/tnsnames.ora
还有一个原因:RMAN duplicate 时连接主库用的服务名写错,比如把或写成了 orclstd。对照 tnsnames.ora 里的名字逐一检查,一般都能定位。
7.2 备库 open_mode 一直是 MOUNTED,MRP 进程没有启动
这个现象很常见。备库 duplicate 完成后默认是 READ ONLY WITH APPLY,但有时候因为某个进程异常,备库停在 MOUNTED。先看 MRP 状态:
sql复制select process, status from v$managed_standby;
如果没有 MRP0 进程,手动启动:
sql复制alter database recover managed standby database using current logfile disconnect from session;
如果启动时报 ORA-10458: standby database requires recovery,说明控制文件里有未完成的恢复操作,通常重启一下实例就好。如果报 ORA-01153: an active media recovery is required,说明已经有一个恢复会话在运行,用 recover managed standby database cancel 先停掉,再重新启动。
7.3 备库查询总是读到旧数据
ADG 的查询延迟通常和日志应用延迟有关。先看 v$dataguard_stats 里的 apply lag,如果这个值持续很大,说明备库应用日志的速度跟不上主库产生日志的速度。排查点有两个:一是备库的磁盘 IO,redo apply 是典型的顺序读顺序写负载,磁盘性能不足就会拖慢 apply;二是 standby redo log 的大小和数量,如果 standby redo log 组太少或太小,会导致日志切换频繁,影响 apply 效率。
我一般建议备库的 standby redo log 大小和主库的 online redo log 保持一致,组数至少是主库 online redo log 组数加一。比如主库有四组 2G 的 redo,备库就建五组 2G 的 standby redo log。
建 standby redo log 的语句:
sql复制alter database add standby logfile group 11 ('/u02/oradata/orclstd/stdredo11.log') size 2G;
alter database add standby logfile group 12 ('/u02/oradata/orclstd/stdredo12.log') size 2G;
alter database add standby logfile group 13 ('/u02/oradata/orclstd/stdredo13.log') size 2G;
alter database add standby logfile group 14 ('/u02/oradata/orclstd/stdredo14.log') size 2G;
alter database add standby logfile group 15 ('/u02/oradata/orclstd/stdredo15.log') size 2G;
如果你是在建库后才想起来要加,注意要先确认目录存在,组号和数据文件不冲突。
7.4 主库归档目录被写满
这个坑很多人都踩过:DG 配置正常,但主库的归档日志删除策略没配好,归档目录被撑爆,数据库直接 hang 住。监控机制一定要提前设好,主库的归档目录使用率超过 80% 就要告警。归档清理可以通过 RMAN 配置策略来自动完成:
bash复制configure archivelog deletion policy to applied on standby;
这个策略的意思是:只有当归档已经在备库应用完之后,才允许删除主库上的归档。这样既能避免主库归档目录爆满,又不会误删备库还没用到的日志。如果你用的是 Broker 管理,也可以直接在 show database 里看到 Log Archive 策略是否生效。
实际运维中还经常遇到一种情况:备库长时间停机,主库的归档堆积如山,主库的磁盘快满了,但删除策略又要求归档已在备库应用才能删。这时候正确的做法是先恢复备库,把日志补上,等 gap 修复后再清理。千万不要图省事直接强制删归档,万一删了备库缺失的日志,后面补都补不回来。
7.5 duplicate 时报 ORA-17628 / ORA-19505
这类错误多半和路径权限有关。RMAN duplicate from active database 需要在主备库之间传输文件,如果备库的 ORACLE_HOME 权限有问题,或者备库的目录不存在,就会报文件打开或创建失败。解决方法是提前检查备库的所有目标目录是否存在、属主是否是 Oracle 用户:
bash复制mkdir -p /u02/oradata/orclstd
mkdir -p /u03/fast_recovery_area/orclstd
chown -R oracle:oinstall /u02 /u03
另外,如果主库数据文件在 ASM 上,备库本来用文件系统,那 DBC_FILE_NAME_CONVERT 的路径写法要特别注意,格式是 +DATA/ORCL/DATAFILE/file.xxx 到 /u02/oradata/orclstd/file.xxx 的完整映射。我第一次从 ASM 迁移到文件系统时就卡在这里,后来把 convert 参数写完整了才通过。
8. 一些补充的经验细节
-
主库的 redo 日志大小会影响备库的 apply 延迟。如果主库日志切得特别频繁(比如 200M 一组),备库的后面 apply 会伴随大量的小 I/O,效率不高。建议主库 redo 日志改成 1G 或 2G,能明显降低备库的 apply 抖动。
-
从 19c 开始,Data Guard 支持通过 DBCA 把物理备库转成只读的 ADG 库,但依然建议走 RMAN duplicate,因为 DBCA 方式会重建库结构,在复杂环境下容易出偏差。
-
如果主备库之间的网络不太稳定,可以在 Data Guard Broker 中设置 LogXptMode 为 ASYNC,这样主库写入不受网络延迟的影响。代价是备库的 RPO 会略有增加,但一般也不会超过几秒,在绝大多数业务场景下完全可接受。
-
19c 的 Fast-Start Failover(FSFO)配合 Observer 可以实现主库故障自动切换,这个功能很实用,但要注意 Observer 不能和主库放在同一台机器上,否则主库主机一挂,Observer 也没了。生产环境建议把 Observer 放在第三个节点或专门的监控机上。
-
备库上的临时表空间会自动保留主库的临时数据文件配置,但如果你在备库上跑大量报表查询,建议按需增加临时表空间大小,避免临时表空间不够用报 ORA-01537。
我个人在实际搭建过程中最大的体会是:ADG 的成败往往不在配置本身,而在于对原理的理解和对细节的把控。很多问题看起来是命令或参数不对,归根结底是没有想清楚主库日志是怎么到备库的、备库又是怎么应用日志并对外提供查询的。只要把这个链路理清楚,遇到报错时顺着链路逐段排查,基本都能快速定位。
最后再分享一个小技巧:搭建完成后,把主备库的 alert log 都开启 DDL 日志和错误日志的捕获,日常巡检时先看 alert log 有没有 ORA- 开头的错误,再看 v$dataguard_stats 的延迟值,最后用 dgmgrl show configuration 确认 Broker 状态。这三步走完,DG 健不健康基本就有数了。
