☰
Oracle 11g DataGuard物理备库从部署到切换的实战指南
2026/10/13 7:45:51 网站建设 项目流程

好久没写DataGuard的手工部署了,正好最近帮朋友搭了一套Oracle 11g的物理备库,从环境检查到switchover演练全程走了一遍。网上关于DataGuard的文档虽然多,但大多是官方概念罗列,真正实操时遇到的坑往往没人提前说。这次我把自己部署的完整思路、命令细节和踩过的雷整理出来,希望能给准备上手或者正在折腾DataGuard的朋友省点时间。

这篇内容围绕Oracle 11g物理备库的搭建展开,覆盖架构选型、参数配置、RMAN duplicate建备库、日常监控和switchover切换测试,最后还有一份排查实战记录。无论你是刚接触DataGuard的新手,还是已经维护过一段时间但没从零搭建过的人,都可以照着这份思路走一遍。

1. 部署前必须想清楚的三件事

1.1 为什么选物理备库而不是逻辑备库

很多人一上来就问我用哪种备库好,我的建议很简单:除非你有特殊需求,否则默认选物理备库。物理备库的原理是把主库产生的归档日志直接拿过来做redo apply,也就是通过恢复机制在备库上重现主库的每一个数据块变化。这种方式性能和一致性最好,备库和主库的数据物理结构完全一致,切换时几乎不会有数据丢失的风险。

逻辑备库则是把归档日志里的SQL操作提取出来,在备库上重新执行一遍,数据组织方式可以和主库不同。听起来灵活,但实际上要面对很多限制,比如某些数据类型、索引组织表、在线重定义操作在逻辑备库上会出问题,维护成本和排查难度都高不少。我用过的真实案例里,逻辑备库出问题的概率明显高于物理备库,很多团队最后都因为它维护太累而放弃。除非你需要把备库当作报表库,允许部分表结构和主库不一致,否则别折腾逻辑备库。

还有一个容易忽略的选择是快照备库。它本质上是一个可以做读写操作的物理备库,启动快照后可以临时在上面修改数据、跑测试,然后通过flashback恢复回物理备库状态。很多人不知道11g支持这个功能,实际用处很大,比如你想在备库上跑个应用兼容性测试,又不想影响主库,快照备库就是正道。不过快照备库在激活期间会停止redo应用,所以一般只在需要临时操作时开启,测完马上恢复。

这三种模式完全可以用一张表来对比:

备库类型应用方式一致性级别可读性主要场景
物理备库Redo Apply物理块级一致只读容灾、主备切换、备份
逻辑备库SQL Apply逻辑级一致可读写报表、部分数据分发
快照备库临时读写后恢复物理块级一致临时读写测试、演练、预发布

1.2 硬件与网络规划的几个要点

DataGuard对硬件的要求不算离谱,但有几个点很容易被低估。备库所在机器的CPU、内存和磁盘性能不能和主库差距太大,很多人觉得备库只是天天接收日志做恢复,负载很低,于是把备库放在一台老旧机器上。等真到切换那天,业务一上来备库立刻扛不住,主备切换变成了主库崩溃后的二次灾难。

网络方面,主备库之间的带宽和延迟要提前测试。11g的DataGuard支持异步传输、同步传输以及最大保护、最大性能、最大可用性三种数据保护模式。如果你追求最高性能,归档日志传输通常跑在异步模式下,网络抖动和延迟影响还能接受;但如果你要开最大保护或者最大可用性,主库的每次提交都要等待redo数据被传输到备库并写入standby redo log,这种情况下网络每增加1毫秒延迟,主库的写入性能就会明显下降。

我习惯在规划阶段用ping测延迟,用简单的方式测带宽,至少要保证传输归档日志的速度跟得上主库产生归档的速度。还有一个经常被忽视的点:主备库之间最好用独立的网卡和VLAN,不要把DataGuard流量和数据备份流量混在一起。曾经遇到过一个客户,主备库之间走的是共享交换机,跑备份任务时把网络带宽占满,导致归档日志传输延迟越来越大,最终备库落后主库好几个小时,差点失去容灾意义。

另外,主库和备库的磁盘规划也要提前设计好。DataGuard只传输redo数据,但备库的磁盘空间要能容纳和主库同等规模的数据文件、在线日志和归档日志。如果主库数据文件500GB,备库磁盘至少要有700GB以上比较稳妥,再算上standby redo log、控制文件和后续的归档日志积累,空间不够时会触发ORA-00257之类的归档日志写满错误,整个备库应用就会停止。

1.3 归档模式与强制日志是底线

部署DataGuard之前,主库必须开启归档模式,这一点没有任何讨价还价的余地。没有归档日志,DataGuard根本没有数据源可以传输和应用。还有个容易漏掉的步骤是开启force logging,也就是强制日志模式。

Oracle里有一些操作可以标记为nologging,例如直接加载(direct path load)、创建索引的nologging选项、某些表空间操作。如果这些操作走了nologging路径,redo里就不会记录完整的数据变化,传到备库后可能产生数据不一致,甚至导致备库恢复失败。开启force logging后,所有操作都会强制写入redo日志,为的就是确保备库拿到完整的变化记录。

检查主库是否满足基本条件,可以用下面几条命令:

-- 查看归档模式 SELECT log_mode, force_logging, supplemental_log_data_pk, supplemental_log_data_all FROM v$database; -- 查看当前归档日志生成频率(估算日志量的一个参考) SELECT name, value FROM v$sysstat WHERE name IN ('redo size', 'archive logged');

如果log_mode显示ARCHIVELOG说明归档已开启,如果force_logging显示NO,你需要执行:

-- 开启强制日志 ALTER DATABASE FORCE LOGGING; -- 确认修改生效 SELECT force_logging FROM v$database;

这一步做完,后面的部署才有安全基础。别看它们简单,很多部署到一半出问题,回头查原因,发现是主库没开force logging,排查过程极其痛苦。

注意:即使主库已经开启了force logging,某些异常情况下Oracle仍然可能不生成完整redo,所以备库环境里最好定期做一次一致性校验,后面会专门讲。

2. 参数配置与关键概念拆解

2.1 主库参数:不是改完就完事

DataGuard相关的初始化参数有不少,但真正核心的就那几个。主库要重点配置的参数包括:

-- 主库唯一名称,和数据文件中的DB_NAME可以不同 DB_UNIQUE_NAME=ORCL -- 日志归档的目标列表,这里配置备库 LOG_ARCHIVE_CONFIG='DG_CONFIG=(ORCL,STDORCL)' -- 本地归档目录 LOG_ARCHIVE_DEST_1='LOCATION=USE_DB_RECOVERY_FILE_DEST' -- 远程归档目标,指向备库 LOG_ARCHIVE_DEST_2='SERVICE=STDORCL LGWR ASYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=STDORCL' -- 日志传输失败后允许主库继续运行 LOG_ARCHIVE_DEST_STATE_2=ENABLE -- 备库文件转换,如果备库目录结构不同则需要配置 DB_FILE_NAME_CONVERT='ORCL','STDORCL' LOG_FILE_NAME_CONVERT='ORCL','STDORCL' -- 备用文件管理自动开启 STANDBY_FILE_MANAGEMENT=AUTO -- 远端归档路径 FAL_SERVER=STDORCL

这里最需要理解的是LOG_ARCHIVE_DEST_2里的几个选项。SERVICE指向的是备库的Oracle Net服务名,主库通过网络服务名找到备库。LGWR表示使用LGWR进程直接把redo写入备库的standby redo log,相比ARCH进程方式,LGWR方式延迟更低,对最大保护模式的支持也更好。ASYNC表示异步传输,主库commit不需要等待备库确认,性能影响最小。

很多人在配置参数时喜欢直接复制网上的模板,但忽视了VALID_FOR这个条件。一个目标位置通常只会接收特定角色的redo,如果不小心配错,可能导致主备切换后日志传输方向混乱。像我上面写的VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE),意思就是当前库作为主库角色时,只传输在线日志产生的redo。切换后,原主库变成备库角色,这个传输目标就不会起作用,而角色对应的另一个配置会接管。

DB_FILE_NAME_CONVERT和LOG_FILE_NAME_CONVERT这两个参数是坑最多的一个点。它们用于指定主备库数据文件和日志文件路径的转换规则。如果你的主备库路径完全一样,可以不设;但大部分环境下,主备库的挂载点或者目录名可能有差异。这里注意一个易错点:转换规则里的第一个值是主库路径,第二个值是备库路径,一旦写反,duplicate过程中会报文件无法找到的错误。

关于DB_UNIQUE_NAME,我多说一句。这个参数是11g里DataGuard配置的核心标识,主备库各自必须不同。很多新手容易把DB_NAME和DB_UNIQUE_NAME混淆。DB_NAME是数据库名称,主备库通常一致;而DB_UNIQUE_NAME是唯一实例名,运维上用来区分不同角色。配置LOG_ARCHIVE_CONFIG时要把双方DB_UNIQUE_NAME都列进去,否则DG_CONFIG校验不过。

2.2 备库参数的几个关键细节

备库的参数配制虽然和主库类似,但存在一些专有参数,而且初始阶段需要通过pfile启动,这一点很多人会忘记。备库需要重点配置的参数有:

DB_UNIQUE_NAME=STDORCL LOG_ARCHIVE_CONFIG='DG_CONFIG=(ORCL,STDORCL)' LOG_ARCHIVE_DEST_1='LOCATION=USE_DB_RECOVERY_FILE_DEST' LOG_ARCHIVE_DEST_2='SERVICE=ORCL LGWR ASYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=ORCL' LOG_ARCHIVE_DEST_STATE_2=ENABLE STANDBY_FILE_MANAGEMENT=AUTO FAL_SERVER=ORCL DB_FILE_NAME_CONVERT='ORCL','STDORCL' LOG_FILE_NAME_CONVERT='ORCL','STDORCL'

注意备库的LOG_ARCHIVE_DEST_2指向的是主库的DB_UNIQUE_NAME,因为备库在主备切换后也要能把本地的redo传给对方。虽然切换前备库不需要传输日志,但参数提前配置好,切换过程就会顺畅很多。

FAL_SERVER参数是备库主动向主库请求缺失归档日志时使用的主机服务名。11g中备库通过FAL(Fetch Archived Log)机制向主库请求日志。这里一个容易踩坑的点是FAL_SERVER配置的是Oracle Net服务名,不是主机IP,你需要确认tnsnames.ora里有对应的条目。如果FAL请求失败,备库的日志应用会中断,报ORA-12528之类的网络错误。

备库在尚未应用日志之前,最好先把DB_NAME和DB_UNIQUE_NAME都准备好。RMAN duplicate创建备库时,会按照参数文件里指定的DB_NAME来重建控制文件,如果你的参数文件里DB_UNIQUE_NAME是STDORCL,那么备库的控制文件也会用这个名字来标识,一切都要协调一致。

2.3 standby redo log 的数量与大小计算

很多部署文档对standby redo log一笔带过,但我可以负责任地说,这个配置直接决定备库的容错能力。standby redo log是备库用来接收主库传过来的redo数据的日志文件。它的大小要尽量和主库的在线redo log大小一致,组数至少要能覆盖redo log的组数,再加一组最稳妥。

具体怎么算?假设主库有4组在线redo log,每组200MB,那么备库的standby redo log组数通常建议为主库在线redo组数 + 1,也就是5组,每组200MB。多出来的这一组是为了避免备库LGWR写入时,主库redo切换导致备库standby log全部被占用而无法接收新数据。如果主库在线redo有8组,备库standby redo至少要有9组。

创建standby redo log的SQL大概是这样的:

-- 在备库上执行,假设日志文件放在 +DATA 或者具体目录 ALTER DATABASE ADD STANDBY LOGFILE GROUP 10 ('/u01/oradata/stdorcl/std_redo01a.log') SIZE 200M; ALTER DATABASE ADD STANDBY LOGFILE GROUP 11 ('/u01/oradata/stdorcl/std_redo02a.log') SIZE 200M; -- 以此类推,加够 主库redo组数+1 组

如果你用的是ASM,路径写成'+DATA/stdorcl/standby_redo01.log'这种格式,道理相同。组号不要和主库在线redo组号冲突,避免切换时内部混淆。大小不一致的话,备库也能工作,但容易出现无法接收LGWR同步传输的情况,典型报错是ORA-00354。提前把这些细节做好,后面运行就轻松很多。

创建standby redo log之后,我还要强调一点:创建时机应该是在备库尚未开始恢复之前。如果备库已经应用了日志再补加standby redo log,虽然可以加,但切换时可能会遇到资源竞争,不如在最开始就配好。

3. 从零开始:物理备库的完整部署流程

3.1 主库侧:tnsnames、密码文件与静态监听

一切参数就绪后,先从网络层面打通主备库的连接。DataGuard传输归档日志依赖Oracle Net服务,所以tnsnames.ora必须配置完整。我习惯在主备库的tnsnames.ora中都维护双方的服务名条目,这样可以避免切换后还要临时补配置。

示例配置如下(假设主库主机名为orclhost,备库主机名为stdhost):

ORCL = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.20)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = ORCL) ) ) STDORCL = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.21)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = STDORCL) ) )

再用tnsping命令验证互相都能连通:

tnsping ORCL tnsping STDORCL

接下来是密码文件和静态监听。DataGuard在搭建和运行过程中需要通过SYS用户远程连接,所以主备库的SYS用户密码必须一致,同时密码文件要存在。Oracle Net监听这里建议配置静态监听服务,而不是只靠动态注册。动态注册的数据库实例在备库尚未启动到mount状态时可能无法被远程访问到,而RMAN duplicate阶段恰恰需要备库处于mount状态且能接受连接。

一个典型的listener.ora静态监听配置片段:

SID_LIST_LISTENER = (SID_LIST = (SID_DESC = (GLOBAL_DBNAME = STDORCL) (ORACLE_HOME = /u01/app/oracle/product/11.2.0/dbhome_1) (SID_NAME = STDORCL) ) )

在备库启动到nomount或者mount阶段,静态监听可以让RMAN通过SYS口令顺利连入,减少很多不必要的麻烦。

3.2 用RMAN创建备库:duplicate是首选

创建备库有两种常见方式:一种是从零开始,先在备库机上建好实例目录,再把主库的数据文件拷贝过去;另一种是直接用RMAN的active database duplicate,自动完成文件拷贝和控制文件重建。我强烈推荐第二种方式,不仅省事,而且能保证数据文件一致。

active database duplicate的核心命令大致如下:

rman target sys/password@ORCL auxiliary sys/password@STDORCL RMAN> DUPLICATE TARGET DATABASE FOR STANDBY FROM ACTIVE DATABASE DORELLOVER;

在11g中,如果主库和备库的目录结构存在差异,我需要提前在备库参数文件中设置好DB_FILE_NAME_CONVERT和LOG_FILE_NAME_CONVERT,这样RMAN在复制文件时会自动完成路径转换。DORELLOVER表示备库创建后直接进入日志应用状态,省去手动执行ALTER DATABASE RECOVER MANAGED STANDBY DATABASE的步骤。

整个duplicate过程中,RMAN会做几件事:读取主库的数据文件信息、通过网络将数据文件内容拷贝到备库、创建备库控制文件、把主库的在线日志归档传到备库、最后将备库置于managed recovery状态。整个过程耗时取决于数据量大小和网络带宽。我第一次做5TB数据库的duplicate时,等了将近十个小时,这个时间成本要在工单或变更窗口里提前预估好。

值得注意的一点:如果主库数据文件非常大,active database duplicate会占用主库IO和网络IO。在业务高峰期做duplicate会明显拖慢主库性能,所以尽量安排在维护窗口里执行。如果对停机窗口有严格要求,可以用备机上先放一个全量备份,再RMAN duplicate FROM BACKUP的方式,这样主库只额外承担传输归档日志的压力,而不是直接做全量文件读取。

3.3 配置DataGuard架构:从mount到managed recovery

duplicate完成之后,备库还处于mount状态,需要启动日志应用才能跟上主库变化。执行下面命令即可:

ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;

这条命令会让备库以后台方式开始应用归档日志。执行之后,检查备库日志应用状态:

SELECT process, status, thread#, sequence# FROM v$managed_standby; SELECT name, value FROM v$dataguard_stats;

正常情况下,v$managed_standby里能看到MRP0进程,状态是APPLYING_LOG,说明备库正在应用日志。v$dataguard_stats里可以看到主备库的日志差异,当transport lag和apply lag都趋近于0时,DataGuard部署就基本成功了。

到这里,DataGuard的一整套主备逻辑已经跑通:主库产生redo,通过LGWR异步传给备库,备库写入standby redo log,再由MRP0进程应用。如果中途出现任何一步不对,都可以在v$dataguard_status里查到详细消息。

4. 部署完才是开始:日常运维与监控

4.1 日志应用状态检查

DataGuard部署好之后,不要以为就万事大吉了。备库的日志应用可能因为网络波动、归档日志缺失、磁盘空间不足等原因随时中断。我通常会在监控系统里加入如下SQL脚本,每天定时检查:

-- 检查备库是否在应用日志 SELECT process, status, client_pid FROM v$managed_standby WHERE process IN ('MRP0','MRP1'); -- 检查日志传输和应用延迟 SELECT name, value, unit FROM v$dataguard_stats WHERE name IN ('transport lag','apply lag','startup time');

还有一个关键视图是v$archive_dest_status,可以看到每个归档目标的状态。如果某个目标显示ERROR或者DEFERRED,那说明日志传输失败了。我见过很多人只看apply lag,忽略了transport lag,结果备库本地standby redo log应用正常,但主库的日志根本传不过来,直到切换时才发现备库还是几小时前的状态。

除了视图查询,我还会检查alert日志。备库的alert日志会记录MRP0进程每一次停止和重新应用,以及ORA-错误信息。很多问题在alert日志里早就暴露了,直接看alert日志,比等监控告警再排查能提前不少时间。特别是ORA-16086、ORA-00313这一类的日志应用错误,alert日志里的描述往往比网上搜索到的例子更贴合你的实际数据环境。

4.2 备库的只读访问和备份策略

物理备库默认是可以以只读方式打开的。你可以把它用来跑报表查询,把主库的统计查询压力分担一部分,这是很多团队部署物理备库的隐藏用途。但有一个操作顺序问题必须记住:备库要在应用日志的managed recovery状态和只读状态之间切换时,必须先取消恢复再打开只读,查完后再重新启动managed recovery。

比如这样操作:

-- 取消日志应用 ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL; -- 把备库打开为只读 ALTER DATABASE OPEN READ ONLY; -- 查询业务数据 SELECT count(*) FROM some_big_table; -- 恢复日志应用 ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;

这个操作看起来简单,但有一点容易被忽略:如果你在只读状态下执行了某些查询产生了临时表或排序,备库的数据字典不会受影响,但如果你不小心在只读状态下做了DML操作,Oracle会直接报ORA-16000。备库在只读打开时受到严格保护,不允许任何写入操作。

另一个经常出现的问题是有人想在备库上做RMAN备份。这是官方推荐的最佳实践之一,备份备库可以分担主库的备份负载。备库上执行RMAN备份时,必须使用BACKUP DATABASE命令,不要加PLUS ARCHIVELOG,因为备库没有在线redo log,加了会导致备份不一致。备库备份出来的数据文件是一个有效的物理备份,可以用于恢复主库,我实际验证过。

4.3 快照备库:一个被低估的测试工具

快照备库这个概念,很多人听过但没用过。它本质上是从物理备库切换成临时读写状态,同时保留回到备库状态的路径。部署快照备库的目的很简单:你可以在一个和生产环境几乎一模一样的数据集上做各种测试,而不用再额外搭建一套开发和测试环境。

激活快照备库的方式:

-- 取消日志应用 ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL; -- 切换为快照备库 ALTER DATABASE CONVERT TO SNAPSHOT STANDBY; -- 打开数据库进行读写 ALTER DATABASE OPEN;

此时备库可以进行任意的DML和DDL操作,测试完以后,再转换回物理备库。回转时数据库会执行Flashback操作,丢弃你在快照状态下做的所有修改。这对应用联调、报表SQL优化测试来说非常实用,而且不需要额外申请存储空间搭建测试库。

不过我建议只在需要测试时才把备库转成快照模式,测试结束立即恢复。因为快照模式期间备库不再应用主库日志,如果时间长了,备库会明显落后。另外,快照备库不能作为switchover的目标,这点要心里有数。

5. 故障切换:先演练,别等出事

5.1 切换演练前的准备工作

很多人搭建完DataGuard就把它放在那里,从未做过切换演练。等到生产环境真要切换时,才发现备库落后太多、参数没配对、归档断档等一堆问题。强烈建议定期做switchover演练,至少一季度一次。

切换前需要确认的几件事:

  1. 备库的standby redo log和归档配置都正常,日志应用没有中断。
  2. 主备库的DB_UNIQUE_NAME、DG_CONFIG配置和tnsnames都能正确识别对方。
  3. 备库磁盘空间足够,因为切换后它要接收来自原主库的方向相反的日志传输。
  4. 确认业务连接串或者应用配置能够切换到新主库的VIP或服务名。

检查日志应用同步情况的命令:

SELECT name, value FROM v$dataguard_stats WHERE name IN ('transport lag','apply lag');

当transport lag和apply lag都显示0的时候,说明主备库已经完全同步,可以安全执行切换。如果备库有延迟,强烈建议先等它追平,再开始切换。等不及的话,可以让备库应用所有可用归档,把丢失的数据量控制在可接受范围内。

5.2 switchover操作的完整步骤

Oracle DataGuard的switchover是无损切换,主备角色互换,不影响数据一致性。先说明一下,我不建议在生产环境直接使用failover(故障强制切换)代替switchover,除非主库真的挂了。failover会把备库变成新的主库,但原主库再恢复时不能简单并入DataGuard,需要重新配置。

一次标准的switchover流程如下:

第一步,在主库上发起切换:

-- 在主库执行,检查是否可以切换 SELECT switchover_status FROM v$database; -- 如果状态显示TO STANDBY,执行下面命令 ALTER DATABASE COMMIT TO SWITCHOVER TO STANDBY WITH SESSION SHUTDOWN;

执行完这条SQL后,主库会清理在线日志并转为备库角色。此时再在主库上启动实例到mount状态:

STARTUP MOUNT; ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;

第二步,在备库上执行切换:

-- 查看备库切换状态,应显示TO PRIMARY SELECT switchover_status FROM v$database; -- 把备库切换成主库 ALTER DATABASE COMMIT TO SWITCHOVER TO PRIMARY; -- 打开新主库 ALTER DATABASE OPEN;

切换完成后,检查新主库是否正常提供服务,旧主库是否已经作为备库开始应用日志。此时整个DataGuard的角色已经互换,新的主备关系建立。

这个流程看起来不复杂,但执行时一定要注意顺序。若先切备库为主库,原主库还没完成到备库的角色转换,两个库会有冲突风险。官方推荐先切主库为备库,再切备库为主库,实操下来是最稳妥的。有时候业务允许短暂停机,可以直接把主库的会话断开再切,避免WITH SESSION SHUTDOWN带来的等待。

提示:switchover之后不要忘记确认应用的连接串是否指向新主库。数据库层的切换只是第一步,应用层如果还连着旧主库,业务依然会中断。很多演练失败不是数据库切换没成功,而是应用没有及时切流。

还有一种常见需求:只想在备库上做一次只读查询,但发现备库处于挂起状态,无法打开。这种情况多半是备库还没有执行OPEN READ ONLY,而是保持在mount状态应用日志。只需要在取消恢复后打开只读就可以,操作在上文已经写过了,不需要切角色。

6. 实战问题排查:那些年我踩过的坑

6.1 ORA-16086、ORA-16032等常见报错的定位思路

先说ORA-16086,这个错误表示备库没有有效的standby redo log或者日志应用异常。我第一次遇到时第一反应是看归档传输是否正常,但最后发现是备库没有创建足够大的standby redo log,主库传过来的redo大小超过了standby log的大小,导致无法写入。解决办法就是按我前面说的方法重新创建standby redo log,大小要和主库redo log匹配。

ORA-16032是归档日志目标不可用。通常原因是主库的LOG_ARCHIVE_DEST_2指向的服务名解析失败,或者备库监听没有正常注册。先检查一下tnsnames.ora中的SERVICE_NAME是否和备库DB_UNIQUE_NAME一致,再确认备库监听状态。这种问题大多出在备库刚重启完、监听还没完全注册好的时候。

ORA-00313则是打开日志文件失败,常见于备库日志应用过程中日志文件被意外删除或者路径不可访问。如果在备库上碰到这个错误,先确认日志文件所在路径是否正确。如果文件真的丢了,只能通过重新创建standby redo log来修复,前提是主备库归档日志还能继续传输。

我在实际排查时习惯按下面的顺序来:

  1. 先查v$dataguard_stats看延迟指标,定位是传输问题还是应用问题。
  2. 再查v$archive_dest_status看归档目标状态,确认日志传输是否中断。
  3. 最后看alert日志,找到具体的ORA-错误码。
  4. 如果是网络问题,先tnsping和检查监听,如果是文件问题,先检查磁盘和文件权限。

这套流程基本能覆盖90%以上的DataGuard故障场景。真正复杂的是那种日志传输正常、应用也正常,但备库数据依然和主库不一致的情况,这种情况比较少见,一旦遇到,就需要启用DBVERIFY或RMAN验证备份等手段做深度校验。

6.2 归档日志断档的补救办法

备库中途宕机或者网络断开时间太长,可能导致备库缺失某些归档日志。如果缺失的归档日志在主库上还存在,备库会自动通过FAL机制去拉取。但如果主库已经清理了对应的归档,也就是归档日志断档了,备库就无法继续应用日志,MRP0进程会停留在某一条sequence等待。

遇到这种情况,先确认主库还有没有那些归档日志:

-- 在主库查询归档序列范围 SELECT sequence#, archived, deleted FROM v$archived_log ORDER BY sequence#;

如果缺失的归档已经被删除,备库就不可能通过正常恢复流程追上主库。此时有两个选择:一是重新基于最新数据做一次增量备份并应用到备库,也就是重新搭建备库;二是在允许丢失部分数据的前提下,通过跳过缺失归档的方式让备库直接跳到当前可用的下一个日志,但这样做备库数据就会不完整。我不建议在生产环境用第二种方式,因为备库的意义就是数据完整保护,跳过日志等于把容灾底线主动放弃。

正规做法是用RMAN增量备份恢复备库到最新状态,然后重新开启日志应用。由于整个过程比较复杂,主要针对的就是“断档”修复场景。日常维护中,尽量保证主库的归档日志不要清理得太激进,应该配置合理的归档删除策略,确保备库有足够的时间同步。很多生产和容灾环境之间的断档,根本原因就是主库的RMAN删除策略太激进,归档还没传到备库就被清掉了。

6.3 备库恢复时ORA-01152错误

ORA-01152这个错误比较有迷惑性,报错信息类似“file 3 was not restored from a sufficiently old backup”。它通常发生在你尝试把备库打开为只读,但备库还没有完全应用完所有归档日志的时候。因为备库的数据文件尚未恢复到一致状态,不能直接打开。

解决办法很简单:先确保MRP0进程已经把日志应用到位,然后取消恢复,再执行OPEN READ ONLY。如果你确实需要在备库尚未完全追平时打开只读,Oracle会要求你将备库设置成flashback状态,否则无法。但生产环境中我一般不会这么做,除非业务上明确可以容忍备库数据落后一段时间。

如果是误操作导致备库数据文件状态不一致,必须先确认主库是否存在可用的数据文件备份。如果有备份且归档齐全,可以用RMAN执行RECOVER DATABASE来修复;如果没有备份,那这个备库可能只能重建了。

6.4 一个小习惯:定期做一次数据库校验

DataGuard的备库长期应用日志,理论上数据应该和主库一致。但实际运行中,磁盘坏块、网络传输异常、NOLOGGING操作遗漏等问题,都可能让备库在某些数据块上悄悄出现差异。我建议每个季度在备库上做一次RMAN BACKUP VALIDATE CHECK LOGICAL校验,或者用DBMS_REDEFINITION等方式抽查关键业务表的数据。

RMAN校验命令:

RMAN> BACKUP VALIDATE CHECK LOGICAL DATABASE;

这个命令会检查所有数据文件是否可读、是否包含逻辑损坏。如果在备库上跑完整校验,IO负载较高,建议选业务低峰期。校验完成后如果发现损坏,可以追溯到具体的数据文件号,再决定是重建还是用主库的备份去恢复。我自己经历过一次磁盘扇区损坏,备库的某几个数据块在校验时被识别出问题,如果不做校验,等到真正切换时才发现,那后果就很严重了。

最后说两句

DataGuard部署本身并不算难,难的是对每一个细节的理解和坚持。比如standby redo log的大小和组数,以及VALID_FOR条件的正确设置,这些在部署时多花十分钟,后面能省下好几个小时的排障时间。我个人在操作中最深的一点体会是:不要跳过部署后的巡检和切换演练,尤其是switchover流程,不演练就等于没有部署。只有亲手做一遍完整的切换,你才会发现监听配置缺了什么、应用连接串有没有指向新主库、归档清理策略是否合理。把这些跑顺了,DataGuard才真正成为你数据库环境里那道可靠的后防线。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询