高可用 & 容灾16 分钟阅读
实战篇:Oracle 26ai DataGuard 搭建与 SwitchOver 切换
@TOC目录 这两天正好安装了 Oracle 26ai 的单机和 RAC 环境,想着正好可以搭建一套 DataGuard 环境玩玩,说干就干! 数据库安装可参考以下两篇: - 《首发|Oracle 26ai 本地安装包与
2026年1月30日阅读—点赞—收藏—
oracleracdataguard
在知识库中专注阅读,并随时返回相关工具与课程
@TOC目录 这两天正好安装了 Oracle 26ai 的单机和 RAC 环境,想着正好可以搭建一套 DataGuard 环境玩玩,说干就干! 数据库安装可参考以下两篇: - 《首发|Oracle 26ai 本地安装包与
本章目标:掌握本章核心知识点 前置要求:完成前序章节学习 预计时长:60 分钟
这两天正好安装了 Oracle 26ai 的单机和 RAC 环境,想着正好可以搭建一套 DataGuard 环境玩玩,说干就干!

数据库安装可参考以下两篇:
本文不再赘述数据库安装相关内容。
依然采用使用 Duplicate 在线复制的方式搭建 ADG,无需 RMAN 备份,可以通过 RMAN Duplicate 直接在线从主库拷贝文件。
本文搭建步骤均来自 100天精通Oracle 实战系列 课程。
1# 所有节点配置 hosts 解析2cat << EOF >> /etc/hosts310.168.1.165 rac-scan410.168.1.25 orcldg5EOF搭建 DataGuard 必须要开启归档模式和强制日志模式:
1-- 检查当前状态2SELECT log_mode, force_logging FROM v$database;34-- 开启归档模式(如未开启)5SHUTDOWN IMMEDIATE;6STARTUP MOUNT;7ALTER DATABASE ARCHIVELOG;8ALTER DATABASE OPEN;910-- 开启强制日志11ALTER DATABASE FORCE LOGGING;1213-- 确认配置生效14SELECT log_mode, force_logging FROM v$database;
Standby Redo Logs 数量为 (Online Redo Logs + 1) × Threads:
1-- 查看在线日志配置2SELECT thread#, group#, bytes/1024/1024 size_mb, members 3FROM v$log 4ORDER BY thread#, group#;56-- 为每个线程添加Standby Redo Logs7-- Thread 1 (假设在线日志组数=7,大小=1GB)8ALTER DATABASE ADD STANDBY LOGFILE THREAD 19GROUP 20 ('+DATA', '+DATA') SIZE 1G,10GROUP 21 ('+DATA', '+DATA') SIZE 1G,11GROUP 22 ('+DATA', '+DATA') SIZE 1G,12GROUP 23 ('+DATA', '+DATA') SIZE 1G,13GROUP 24 ('+DATA', '+DATA') SIZE 1G,14GROUP 25 ('+DATA', '+DATA') SIZE 1G,15GROUP 26 ('+DATA', '+DATA') SIZE 1G,16GROUP 27 ('+DATA', '+DATA') SIZE 1G;1718-- Thread 219ALTER DATABASE ADD STANDBY LOGFILE THREAD 220GROUP 30 ('+DATA', '+DATA') SIZE 1G,21GROUP 31 ('+DATA', '+DATA') SIZE 1G,22GROUP 32 ('+DATA', '+DATA') SIZE 1G,23GROUP 33 ('+DATA', '+DATA') SIZE 1G,24GROUP 34 ('+DATA', '+DATA') SIZE 1G,25GROUP 35 ('+DATA', '+DATA') SIZE 1G,26GROUP 36 ('+DATA', '+DATA') SIZE 1G,27GROUP 37 ('+DATA', '+DATA') SIZE 1G;2829-- 验证Standby Redo Logs30SELECT thread#, group#, bytes/1024/1024 size_mb, status 31FROM v$standby_log 32ORDER BY thread#, group#;
rac 的密码文件通常存放于 ASM 盘中,查看对应的密码文件位置:
1srvctl config database -d orcl | grep PASSWORD
使用 asmcmd 进入到 ASM 磁盘组:
1# 从 ASM 复制到文件系统2asmcmd -p3ASMCMD [+] > pwcopy +DATA/RPTDB/PASSWORD/pwdrptdb.256.1180304871 /home/grid/
将密码文件拷贝到备库,并且重命名,命名规则为 orapw+sid:
1chown oracle:oinstall /home/grid/pwdorcl.256.12237618252mv /home/grid/pwdorcl.256.1223761825 /home/oracle/orapworcldg3scp /home/oracle/orapworcldg oracle@10.168.1.25:/u01/app/oracle/product/26.1.0/db/dbs/
使用 RMAN 备份在备库恢复,需要在主库生成参数文件:
1-- 在主库生成参数文件2CREATE PFILE='/home/oracle/pfile_orcl.ora' FROM SPFILE;
将主库生成并修改后的参数文件在备库创建初始化参数文件(这里建议源端目标端均使用 OMF):
1## 在备库创建初始化参数文件2cat<<-\EOF>$ORACLE_HOME/dbs/initorcldg.ora3*._b_tree_bitmap_plans=FALSE4*._cleanup_rollback_entries=20005*._optimizer_adaptive_cursor_sharing=FALSE6*._optimizer_extended_cursor_sharing='NONE'7*._optimizer_extended_cursor_sharing_rel='NONE'8*._optimizer_use_feedback=FALSE9*._undo_autotune=FALSE10*.compatible='23.6.0'11*.control_file_record_keep_time=3112*.control_files='/oradata/ORCL/CONTROLFILE/control01.ctl','/oradata/ORCL/CONTROLFILE/control02.ctl'13*.db_block_size=819214*.db_create_file_dest='/oradata'15*.db_files=500016*.db_name='orcl'17*.deferred_segment_creation=FALSE18*.diagnostic_dest='/u01/app/oracle'19*.dispatchers='(PROTOCOL=TCP) (SERVICE=orcldgXDB)'20*.enable_pluggable_database=true21*.event='28401 trace name context forever,level 1','10949 trace name context forever,level 1'22*.log_archive_format='%t_%s_%r.dbf'23*.nls_language='SIMPLIFIED CHINESE'24*.nls_territory='CHINA'25*.open_cursors=100026*.parallel_force_local=TRUE27*.parallel_max_servers=6428*.pga_aggregate_target=264346009629*.processes=200030*.remote_login_passwordfile='exclusive'31*.session_cached_cursors=30032*.sga_max_size=1057593753633*.sga_target=1057593753634*.undo_retention=1080035*.undo_tablespace='UNDOTBS1'36*.db_unique_name='orcldg'37*.fal_client='ORCL_STB'38*.fal_server='ORCL_PRI'39*.log_archive_config='dg_config=(orcl,orcldg)'40*.log_archive_dest_1='LOCATION=/oradata/archivelog VALID_FOR=(ALL_LOGFILES,ALL_ROLES) DB_UNIQUE_NAME=ORCLDG'41*.log_archive_dest_2='SERVICE=ORCL_PRI VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=ORCL'42*.standby_file_management='AUTO'43EOF备库根据参数文件在两个节点均创建必要的目录:
1# 创建必要目录2mkdir -p /oradata/ORCL/{CONTROLFILE,DATAFILE,ONLINELOG}3mkdir -p /oradata/archivelog4chown -R oracle:oinstall /oradata5chmod -R 755 /oradata打开备库到 nomount 状态:
1-- 创建SPFILE2CREATE SPFILE FROM PFILE;34-- 启动到NOMOUNT状态5STARTUP NOMOUNT;
备库启动监听:
1# 启动监听2lsnrctl start3## 等一段时间或者手动注册监听,再次查看监听状态4lsnrctl stat

配置 TNSNAMES.ORA:
1## 所有节点均配置 TNS2cat >> $ORACLE_HOME/network/admin/tnsnames.ora << 'EOF'3ORCL_PRI =4 (DESCRIPTION =5 (ADDRESS = (PROTOCOL = TCP)(HOST = 10.168.1.165)(PORT = 1521))6 (CONNECT_DATA =7 (SERVER = DEDICATED)8 (SERVICE_NAME = orcl)9 )10 )1112ORCL_STB =13 (DESCRIPTION =14 (ADDRESS = (PROTOCOL = TCP)(HOST = 10.168.1.25)(PORT = 1521))15 (CONNECT_DATA =16 (SERVER = DEDICATED)17 (SERVICE_NAME = orcldg)18 (UR=A)19 )20 )21EOF2223# 测试连接24tnsping ORCL_PRI25tnsping ORCL_STB2627# 验证数据库连接28sqlplus sys/oracle@ORCL_PRI as sysdba29sqlplus sys/oracle@ORCL_STB as sysdba
rman 同时连接主备库:
1[oracle@orcldg:/home/oracle]$ rman target sys/oracle@ORCL_PRI AUXILIARY sys/oracle@ORCL_STB
执行 duplicate 命令:
1RMAN> run {2allocate channel prmy1 type disk;3allocate channel prmy2 type disk;4allocate channel prmy3 type disk;5allocate channel prmy4 type disk;6allocate channel prmy5 type disk;7allocate channel prmy6 type disk;8allocate auxiliary channel aux1 type disk;9allocate auxiliary channel aux2 type disk;10allocate auxiliary channel aux3 type disk;11allocate auxiliary channel aux4 type disk;12allocate auxiliary channel aux5 type disk;13allocate auxiliary channel aux6 type disk;14duplicate target database for standby from active database dorecover nofilenamecheck;15}
等待 RMAN duplicate 复制完成即可。
1SQL> alter database open read only;2SQL> alter pluggable database all open;
1SQL> alter database recover managed standby database using current logfile disconnect;23Database altered.
1alter system set log_archive_config='DG_CONFIG=(orcl,orcldg)';2alter system set log_archive_dest_1='LOCATION=+DATA VALID_FOR=(ALL_LOGFILES,ALL_ROLES) DB_UNIQUE_NAME=ORCL';3alter system set log_archive_dest_2='SERVICE=ORCL_STB VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=ORCLDG';4alter system set fal_client='ORCL_PRI';5alter system set fal_server='ORCL_STB';6alter system set log_archive_dest_state_2=defer;7alter system set log_archive_dest_state_2=enable;
1-- 主库2SQL> set line2222 pages10003col status for a104col type for a105col error for a206col gap_status for a207col synchronization_status for a308col recovery_mode for a609select inst_id,status,DEST_ID,TYPE,ERROR,GAP_STATUS,SYNCHRONIZED,SYNCHRONIZATION_STATUS,RECOVERY_MODE from GV$ARCHIVE_DEST_STATUS where STatus <> 'INACTIVE' and type = 'PHYSICAL';
备库:
1SQL> set line222 pages10002select process,thread#,group#,sequence#,status from v$managed_standby;34SQL> col member for a1005select t2.thread#,t1.group#,t1.member,t2.STATUS,t2.ARCHIVED,t2.bytes/1024/1024 from v$logfile t1,v$standby_log t2 where t1.group#=t2.group# order by 1,2;
至此,ADG 搭建完成,备库可用于报表查询。
在主库创建一个 PDB:
1-- 创建PDB2CREATE PLUGGABLE DATABASE testpdb ADMIN USER admin IDENTIFIED BY oracle;34-- 打开PDB5ALTER PLUGGABLE DATABASE testpdb OPEN;6ALTER PLUGGABLE DATABASE testpdb SAVE STATE;78-- 连接到新创建的 PDB9ALTER SESSION SET CONTAINER=testpdb;1011-- 创建测试用户12CREATE USER testuser IDENTIFIED BY oracle;13GRANT dba TO testuser;1415-- 创建测试表16CREATE TABLE testuser.employees (17 id NUMBER PRIMARY KEY,18 name VARCHAR2(50),19 department VARCHAR2(30),20 salary NUMBER,21 hire_date DATE22);2324-- 插入测试数据25INSERT INTO testuser.employees VALUES (1, 'John Doe', 'IT', 5000, SYSDATE-100);26INSERT INTO testuser.employees VALUES (2, 'Jane Smith', 'HR', 4500, SYSDATE-50);27INSERT INTO testuser.employees VALUES (3, 'Bob Johnson', 'Sales', 4000, SYSDATE-30);2829COMMIT;3031-- 验证数据32SELECT * FROM testuser.employees;33SELECT COUNT(*) FROM testuser.employees;
备库验证数据:
1-- 启动 PDB2SQL> alter pluggable database testpdb open;34-- 查看 PDB5SQL> show pdbs67-- 切换到 PDB8ALTER SESSION SET CONTAINER=testpdb;910-- 查询数据11SELECT * FROM testuser.employees;12SELECT COUNT(*) FROM testuser.employees;
查看主备库同步进程状态:
1-- 主库2SQL> set line22223col status for a104col type for a105col error for a206col gap_status for a207col synchronization_status for a308col recovery_mode for a609select inst_id,status,DEST_ID,TYPE,database_mode,ERROR,GAP_STATUS,SYNCHRONIZED,SYNCHRONIZATION_STATUS,RECOVERY_MODE from GV$ARCHIVE_DEST_STATUS where STatus <> 'INACTIVE' and type = 'PHYSICAL';1011SQL> set line222212col name for a1013col database_role for a2014col switchover_status for a2015col PROTECTION_MODE for a2516select inst_id,name,database_role,protection_mode,switchover_status from gv$database;
备库:
1SQL> SELECT 2 (SELECT MAX(sequence#) FROM v$archived_log WHERE applied='YES') last_applied_seq,3 (SELECT MAX(sequence#) FROM v$archived_log) last_received_seq,4 (SELECT MAX(sequence#) FROM v$archived_log) - 5 (SELECT MAX(sequence#) FROM v$archived_log WHERE applied='YES') gap6FROM dual;78SQL> set line2229col database_role for a2010col switchover_status for a2011col PROTECTION_MODE for a2512select inst_id,name,database_role,protection_mode,switchover_status from gv$database;
主库切换为备库 (期间观察主库 alert 日志):
1SQL> alter database commit to switchover to physical standby with session shutdown;
备库下检查是否可以切换为主库:
1SQL> set line2222col database_role for a203col switchover_status for a204col PROTECTION_MODE for a255select name,database_role,protection_mode,switchover_status from gv$database;
备库切换主库:
1SQL> alter database commit to switchover to primary with session shutdown;23Database altered.
打开新的主库:
1SQL> alter database open;23Database altered.45SQL> select name,open_mode,database_role from v$database;67NAME OPEN_MODE DATABASE_ROLE8--------- -------------------- ----------------9ORADB READ WRITE PRIMARY
打开新的备库:
1[oracle@rac01:/home/oracle]$ srvctl start db -d orcl23SQL> alter database recover managed standby database using current logfile disconnect from session;4SQL> select name,open_mode,database_role from gv$database;
检查主备同步情况:
1-- 主库2SQL> set line22223col status for a104col type for a105col error for a206col gap_status for a207col synchronization_status for a308col recovery_mode for a609select inst_id,status,DEST_ID,TYPE,database_mode,ERROR,GAP_STATUS,SYNCHRONIZED,SYNCHRONIZATION_STATUS,RECOVERY_MODE from GV$ARCHIVE_DEST_STATUS where STatus <> 'INACTIVE' and type = 'PHYSICAL';
切换后主备同步正常,操作流程也较为简单。
这篇文章是使用经典的架构去搭建和切换 ADG,所以还是比较顺利,但是我看 26ai 支持 PDB 级别的 ADG,后面有时间再学习一下。