一、Oracle Data Guard相关概念
DG相关进程:
- ARCH(Archiver):发送归档日志。
- LGWR(Log Writer):当事务提交时,将Redo Buffer中的重做记录写入当前重做日志文件中,并将该记录传递给本地进程LNS。
- LNS(LGWR Net Server):通过网络将重做日志传递给备库。
- RFS(Remote File Server):接收来自主库的归档日志或重做日志,并将其写入备库的归档日志文件或备库联机重做日志文件中。
- MRP(Managed Recovery Process):如果备库类型为物理备,则通过MRP进程应用日志来实现数据同步(也称Redo Apply)。
- LSP:如果备库类型为逻辑备,则LSP进程会将日志转换为SQL语句,通过在备库上执行SQL语句来实现数据同步(也称SQL Apply)。
从上可知ARCH和LWGR都可以用来发送日志,LGWR发送日志又可分为SYNC和ASYNC,下面给出三种日志发送模式下,Data Guard实现数据同步的原理。
1.ARCH发送日志
1.Primary Database不断产生Redo Log,这些日志被LGWR进程写到联机日志。
2.当一组联机日志被写满后,会发生日志切换(Log Switch)并且会触发本地归档。
3.完成本地归档后,联机日志就可以被覆盖重用。
4.ARCH 进程通过Net把归档日志发送给Standby Database的RFS(Remote File Server)进程。
5.Standby Database端的RFS进程把接收的日志写入到归档日志。
6.Standby Database端的MRP(Managed Recovery Process)进程(Redo Apply)或者LSP 进程(SQL Apply)在Standby Database上应用这些日志,进而同步数据。

2.LGWR SYNC方式发送日志
1)Primary Database 产生的Redo 日志要同时写道日志文件和网络。也就是说LGWR进程把日志写到本地日志文件的同时还要发送给本地的LNSn进程(LGWR Network Server Process),再由LNSn(LGWR Network Server process)进程把日志通过网络发送给远程的目的地,每个远程目的地对应一个LNS进程,多个LNS进程能够并行工作。
2)LGWR 必须等待写入本地日志文件操作和通过LNSn进程的网络传送都成功,Primary Database上的事务才能提交,这也是SYNC的含义所在。
3)Standby Database的RFS进程把接收到的日志写入到Standby Redo Log日志中。
4)Primary Database的日志切换也会触发Standby Database上的日志切换,即Standby Database对Standby RedoLog的归档。MRP或者LSP进程根据备库的恢复模式在不同的时机运用日志,若为实时恢复,则在RFS将日志写入备库重做日志之后触发日志应用,若为归档恢复,则在主库发生日志切换后触发日志应用。
备库有两种恢复模式:
- 实时恢复(Real-Time Apply):只要RFS把日志写入Standby Redo Log就会立即进行恢复;
# 以实时恢复的方式在后台启动Redo Apply,去掉DISCONNECT,则为前台启动
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT;
- 归档恢复:在完成对Standby RedoLog归档才触发恢复。
# 以归档恢复的方式在后台启动Redo Apply
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE USING ARCHIVED LOGFILE DISCONNECT;
停止Redo Apply:
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;
SQL Apply的启停方式:
1.启动SQL Apply
ALTER DATABASE START LOGICAL STANDBY APPLY;
2.以实时应用的方式启动SQL Apply
ALTER DATABASE START LOGICAL STANDBY APPLY IMMEDIATE;
3.停止方式
ALTER DATABASE STOP LOGICAL STANDBY APPLY;
3.LGWR ASYNC方式发送日志
1) Primary Database 一段产生Redo 日志后,LGWR 把日志同时提交给日志文件和本地LNS 进程,但是LGWR进程只需成功写入日志文件就可以,不必等待LNSn进程的网络传送成功。
2) LNSn进程异步地把日志内容发送到Standby Database。多个LNSn进程可以并发发送。
3) Primary Database的Online Redo Log 写满后发生Log Switch触发归档操作,也触发Standby Database对Standby Redo Log 的归档;然后触发MRP或者LSP 进程恢复归档日志。备库恢复方式同上一小节一致。
下文将介绍如何通过RMAN DUPLICATE…FROM ACTIVE DATABASE创建物理备。
二、通过RMAN DUPLICATE…FROM ACTIVE DATABASE创建物理备库
1.环境概述
Database Version:Oracle Database 19c Enterprise Edition Release 19.0.0.0.0
Instance Name:cdbtest(主)、cdbtestdg(备)
Database Name : cdb_test
Primary db_unique_name : cdb_test
standby db_unique_name : testdg
Container Database:Yes
2.主库配置
## 确保数据库开启归档
select log_mode from v$database;
## 数据库启用强制日志
alter database force logging;
## 创建备库redo日志,注意主备redo日志大小应该一样
alter database add standby logfile '/u01/app/oracle/oradata/CDB_TEST/onlinelog/standby01.log' size 10M;
## 修改初始化参数
alter system set LOG_ARCHIVE_CONFIG='DG_CONFIG=(cdb_test,testdg)';
alter system set LOG_ARCHIVE_DEST_1='LOCATION=/u01/arch/ VALID_FOR=(ALL_LOGFILES,ALL_ROLES) DB_UNIQUE_NAME=cdb_test';
alter system set LOG_ARCHIVE_DEST_2='SERVICE=testdg LGWR ASYNC VALID_FOR=(ONLINE_LOGFILE,PRIMARY_ROLE) DB_UNIQUE_NAME=testdg';
alter system set LOG_ARCHIVE_DEST_STATE_1=ENABLE;
alter system set FAL_SERVER=testdg;
alter system set FAL_CLIENT=cdb_test;
## 若数据文件存放位置有多个需要指定多个转换关系
alter system set DB_FILE_NAME_CONVERT='/u01/app/oracle/oradata/TESTDG/datafile/','/u01/app/oracle/oradata/CDB_TEST/datafile/','/u01/app/oracle/oradata/TESTDG/F20E4157E91EB61BE0534600000A53DD/datafile' ,'/u01/app/oracle/oradata/CDB_TEST/F20E4157E91EB61BE0534600000A53DD/datafile' scope=spfile;
alter system set LOG_FILE_NAME_CONVERT='/u01/app/oracle/oradata/TESTDG/onlinelog/','/u01/app/oracle/oradata/CDB_TEST/onlinelog/' scope=spfile;
3.网络配置
## 在备库系统中的listener.ora添加如下静态条目
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(GLOBAL_DBNAME = testdg)
(ORACLE_HOME = /u01/app/oracle/product/19.3.0/dbhome_1)
(SID_NAME = cdbtestdg)
)
)
LISTENER =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 10.0.0.100)(PORT = 1521))
)
## 启动监听
lsnrctl start
## 主库和备库的tnsnames.ora都配置如下条目
cdb_test =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 10.0.0.70)(PORT = 1521))
)
(CONNECT_DATA = (SERVICE_NAME = cdb_test))
)
testdg =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 10.0.0.100)(PORT = 1521))
)
(CONNECT_DATA = (SERVICE_NAME = testdg))
)
## 检查网络配置是否正确
tnsping cdb_test
tnsping testdg
4.创建备库
## (1)将主库密码文件拷贝至备库
cd $ORACLE_HOME/dbs
orapwd file="$ORACLE_HOME/dbs/orapwcdbtest" password=1234567z# force=y
scp -rp orapwcdbtest oracle@10.0.0.100:/u01/app/oracle/product/19.3.0/dbhome_1/dbs/orapwcdbtestdg
## (2)创建初始化文件,仅包含db_name参数
[oracle@alldb /u01/app/oracle/product/19.3.0/dbhome_1/dbs]$ vim initcdbtestdg.ora
db_name=cdb_test
db_unique_name=testdg
## (3)创建必要的目录来存放数据库文件和追踪文件
[oracle@alldb /u01/app/oracle]$ mkdir oradata/TESTDG/datafile -p
[oracle@alldb /u01/app/oracle]$ mkdir oradata/TESTDG/onlinelog -p
mkdir /u01/app/oracle/fast_recovery_area
mkdir /u01/arch
mkdir /u01/app/oracle/admin/testdg/adump -p
mkdir /u01/app/oracle/oradata/TESTDG/F20E4157E91EB61BE0534600000A53DD/datafile -p
## (4)启动备库实例
export ADR_HOME=/u01/app/oracle/admin/testdg/adump
export ORACLE_SID=cdbtestdg
sqlplus / as sysdba
startup nomount pfile=$ORACLE_HOME/dbs/initcdbtestdg.ora;
## (5)验证“as sysdba”是否能够正常工作
sqlplus sys/1234567z#@cdb_test as sysdba
sqlplus sys/1234567z#@testdg as sysdba
## (6)在主库上通过rman连接主库和辅助库(备库)
rman target sys/1234567z#@cdb_test auxiliary sys/1234567z#@testdg
run {
allocate channel prmy1 type disk;
allocate channel prmy2 type disk;
allocate channel prmy3 type disk;
allocate channel prmy4 type disk;
allocate auxiliary channel stby type disk;
duplicate target database for standby from active database nofilenamecheck
spfile
parameter_value_convert 'cdb_test','testdg'
set db_unique_name='testdg'
set LOG_ARCHIVE_DEST_1='LOCATION=/u01/arch/ VALID_FOR=(ALL_LOGFILES,ALL_ROLES) DB_UNIQUE_NAME=testdg'
set db_file_name_convert='/u01/app/oracle/oradata/CDB_TEST/datafile/','/u01/app/oracle/oradata/TESTDG/datafile/','/u01/app/oracle/oradata/CDB_TEST/F20E4157E91EB61BE0534600000A53DD/datafile','/u01/app/oracle/oradata/TESTDG/F20E4157E91EB61BE0534600000A53DD/datafile'
set log_file_name_convert='/u01/app/oracle/oradata/CDB_TEST/onlinelog/','/u01/app/oracle/oradata/TESTDG/onlinelog/'
set control_files='/u01/app/oracle/oradata/TESTDG/controlfile/control01.ctl'
set log_archive_max_processes='3'
set fal_client='testdg'
set fal_server='cdb_test'
set standby_file_management='MANUAL'
set log_archive_config='dg_config=(cdb_test,testdg)'
set log_archive_dest_2='service=cdb_test ASYNC valid_for=(ONLINE_LOGFILE,PRIMARY_ROLE) db_unique_name=cdb_test'
;
}
补充:当密码文件名和位置发生改变之后需执行如下命令,以便使用新的密码文件
ALTER SYSTEM FLUSH PASSWORDFILE_METADATA_CACHE;
# 在安装了GRID的环境中,可以使用如下命令来更改指定数据库的密码文件
srvctl modify database -db cdb_test -pwfile '/u01/app/oracle/product/19.3.0.0/dbhome_1/dbs/orapwcdbtest'
5.启动MRP进程
## 使用SQL*Plus连接到备库,并启动MRP (Managed Recovery Process)。
alter database recover managed standby database disconnect;
## 主备上查看DG相关进程,比较主最新的日志序号和MRP应用的日志序号
select process,pid,status,thread#,sequence#,block#,delay_mins from v$managed_standby;
select process,pid,status,thread#,sequence#,block#,delay_mins from v$managed_standby;
## 查看主备最新归档日志序列号信息
SELECT UNIQUE THREAD#, MAX(SEQUENCE#) OVER(PARTITION BY THREAD#) LAST FROM V$ARCHIVED_LOG;
6.以只读模式打开备库(active dataguard)
如果您已获得使用Active Dataguard (ADG)的许可,请以READ ONLY方式打开备库并开始恢复。
alter database recover managed standby database cancel;
alter database open;
alter pluggable database all open;
alter database recover managed standby database disconnect; --实时恢复数据
## 查看DG状态
select * from v$dataguard_stats;
## 查看归档目标状态
select dest_name,type,database_mode,recovery_mode,protection_mode,standby_logfile_count,archived_seq#,applied_seq#,error,gap_status from v$archive_dest_status where dest_name='LOG_ARCHIVE_DEST_2';
7.查看主备之间相关进程建立的TCP连接信息
例如查看备库RFS进程与主库相关进程建立的TCP连接信息:
## 1.备库执行:其中oraclecdbtestdg相应的改为oracle$ORACLE_SID
[root@alldb ~]# for pid in `ps -ef | grep "[o]raclecdbtestdg (LOCAL=NO)" |awk '{print $2}'`;do lsof -np $pid | grep -i tcp;done;
oracle_47 47538 oracle 13u IPv4 879100 0t0 TCP 10.0.0.100:ncube-lm->10.0.0.70:31454 (ESTABLISHED)
oracle_47 47540 oracle 15u IPv4 878531 0t0 TCP 10.0.0.100:ncube-lm->10.0.0.70:31456 (ESTABLISHED)
oracle_47 47542 oracle 13u IPv4 878548 0t0 TCP 10.0.0.100:ncube-lm->10.0.0.70:31458 (ESTABLISHED)
oracle_47 47544 oracle 15u IPv4 878551 0t0 TCP 10.0.0.100:ncube-lm->10.0.0.70:31460 (ESTABLISHED)
oracle_47 47546 oracle 18u IPv4 878554 0t0 TCP 10.0.0.100:ncube-lm->10.0.0.70:31462 (ESTABLISHED)
## 2.根据上面的命令可以找到主库相关进程用于建立TCP连接的端口信息
[root@alldb ~]# (for pid in `ps -ef | grep "[o]raclecdbtestdg (LOCAL=NO)" |awk '{print $2}'`;do lsof -np $pid | grep -i tcp|awk -F':| +' '{print $11}';done;) |xargs|sed -r 's/ /|/g'
31454|31456|31458|31460|31462
## 3.在主库上查看对应的端口的TCP连接信息
netstat -antup | grep -E '31454|31456|31458|31460|31462'
tcp 0 0 10.0.0.70:31454 10.0.0.100:1521 ESTABLISHED 13114/ora_tt00_cdbt
tcp 0 0 10.0.0.70:31458 10.0.0.100:1521 ESTABLISHED 13121/ora_arc1_cdbt
tcp 0 0 10.0.0.70:31462 10.0.0.100:1521 ESTABLISHED 13123/ora_arc2_cdbt
tcp 0 0 10.0.0.70:31456 10.0.0.100:1521 ESTABLISHED 41481/ora_tt05_cdbt
tcp 0 0 10.0.0.70:31460 10.0.0.100:1521 ESTABLISHED 13125/ora_arc3_cdbt
## 4.在主库查看这个TCP连接对应进程名信息
[root@oracle4 ~]# netstat -antup | grep -E '31454|31456|31458|31460|31462' | awk -F'/| +' '{print $(NF-2)}'|xargs|sed "s/ /','/g" |sed "s/^/('/g" |sed "s/$/')/g"
('13114','13121','13123','41481','13125')
SYS@cdbtest> select process,pid,status,thread#,sequence#,block#,delay_mins from v$managed_standby where pid in ('13114','13121','13123','41481','13125');
PROCESS PID STATUS THREAD# SEQUENCE# BLOCK# DELAY_MINS
--------- ------------------------ ------------ ---------- ---------- ---------- ----------
DGRD 13114 ALLOCATED 0 0 0 0
ARCH 13121 CLOSING 1 139 1 0
ARCH 13123 CLOSING 1 137 5607 0
ARCH 13125 CLOSING 1 138 1 0
LNS 41481 WRITING 1 140 10840 0
8.使用RMAN复制遇到的问题
(1)RMAN-05537
执行RMAN数据复制时,报如下错:
RMAN-05537 DUPLICATE without TARGET connection when auxiliary instance is started with spfile cannot use SPFILE clause
处理措施: 备库实例启动时需要使用pfile,不要使用spfile,但我的确是通过pfile来启动数据库的,仍旧报错这个错,后面我发现目录$ORACLE_HOME/dbs/下存在该实例的spfile,将之删除,重启备库,问题解决。
startup nomount pfile=$ORACLE_HOME/dbs/initcdbtestdg.ora;
(2)RMAN-05001
详细报错信息如下所示:
RMAN-05001: auxiliary file name /u01/app/oracle/oradata/CDB_TEST/F20E4157E91EB61BE0534600000A53DD/datafile/o1_mf_system_kvzlo323_.dbf conflicts with a file used by the target database
处理措施:在duplicate语句中加上nofilenamecheck,告诉RMAN不要检查目标数据文件与正在创建的复制文件是否共享相同的名称。
三、主备密码文件不一致问题(ORA-16191)
Oracle数据库自12.2之后当数据库密码文件放置于ASM磁盘组中时,会自动同步主库SYS用户密码的变更信息至从库。本次测试所使用的数据库版本,将密码文件放置于文件系统中,当主库使用alter user修改了SYS用户的密码时,备库的密码文件也会自动更新。
当DG搭建好之后,主备密码文件不一致时,并不影响备库实时恢复主库的变更信息,即使主库进行了日志切换,也是不会出现数据同步中断问题。当出于其它原因导致备库出现日志GAP时,也就是备库最新的日志序列号与主库不一致,然后备库启动FAL进程去主库获取缺失的日志,此时如果密码文件有问题,就会触发ORA-16191报错。恢复备库的密码文件,然后在主库上执行如下操作,即可恢复DG数据实时恢复。
# 主库操作
alter system set log_archive_dest_state_2 = defer;
alter system set log_archive_dest_state_2 = enable;
参考:
1.Step by Step Guide on Creating Physical Standby Using RMAN DUPLICATE…FROM ACTIVE DATABASE (Doc ID 1075908.1)
2.Oracle 11g DG概念与进程详解




