生产建议 :金融系统用 Maximum Protection 或 Maximum Availability ;一般业务用 Maximum Performance。
二、搭建 Physical Standby
2.1 环境准备
项目
主库
备库
主机名
primary-db
standby-db
IP
192.168.1.101
192.168.1.102
ORACLE_SID
orcl
orcl_stby
DB_UNIQUE_NAME
primary
standby
数据库版本
19c
19c(必须相同)
2.2 主库配置
sql复制代码
-- 1. 开启归档模式
SHUTDOWN IMMEDIATE;
STARTUP MOUNT;
ALTER DATABASE ARCHIVELOG;
ALTER DATABASE OPEN;
-- 验证
ARCHIVE LOG LIST;
-- 2. 开启 Force Logging
ALTER DATABASE FORCE LOGGING;
-- 验证
SELECT FORCE_LOGGING FROM V$DATABASE;
-- 3. 创建 Standby Redo Log(比 Online Redo Log 多一组)
-- 查看当前 Redo Log 大小和组数
SELECT GROUP#, BYTES/1024/1024 AS SIZE_MB FROM V$LOG;
-- 添加 Standby Redo Log(建议与 Online Redo Log 大小一致,多 1-2 组)
ALTER DATABASE ADD STANDBY LOGFILE THREAD 1 GROUP 4 ('/u01/oradata/orcl/srl04.log') SIZE 200M;
ALTER DATABASE ADD STANDBY LOGFILE THREAD 1 GROUP 5 ('/u01/oradata/orcl/srl05.log') SIZE 200M;
ALTER DATABASE ADD STANDBY LOGFILE THREAD 1 GROUP 6 ('/u01/oradata/orcl/srl06.log') SIZE 200M;
ALTER DATABASE ADD STANDBY LOGFILE THREAD 1 GROUP 7 ('/u01/oradata/orcl/srl07.log') SIZE 200M;
-- 验证
SELECT GROUP#, THREAD#, BYTES/1024/1024 AS SIZE_MB, STATUS FROM V$STANDBY_LOG;
-- 4. 配置 Redo 传输参数
ALTER SYSTEM SET LOG_ARCHIVE_CONFIG='DG_CONFIG=(primary,standby)' SCOPE=BOTH;
-- 本地归档
ALTER SYSTEM SET LOG_ARCHIVE_DEST_1='LOCATION=USE_DB_RECOVERY_FILE_DEST VALID_FOR=(ALL_LOGFILES,ALL_ROLES) DB_UNIQUE_NAME=primary' SCOPE=BOTH;
-- 传输到备库
ALTER SYSTEM SET LOG_ARCHIVE_DEST_2='SERVICE=standby LGWR ASYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=standby' SCOPE=BOTH;
-- 5. 配置 FAL(自动缺口解决)
ALTER SYSTEM SET FAL_SERVER='standby' SCOPE=BOTH;
ALTER SYSTEM SET FAL_CLIENT='primary' SCOPE=BOTH;
-- 6. 配置文件路径转换(主备目录不同时)
ALTER SYSTEM SET STANDBY_FILE_MANAGEMENT='AUTO' SCOPE=BOTH;
ALTER SYSTEM SET DB_FILE_NAME_CONVERT='/u01/oradata/orcl/','/u01/oradata/orcl_stby/' SCOPE=BOTH;
ALTER SYSTEM SET LOG_FILE_NAME_CONVERT='/u01/oradata/orcl/','/u01/oradata/orcl_stby/' SCOPE=BOTH;
# 在主库执行
rman target sys/xxxxx@primary
# 1. 备份主库(包含备库控制文件)
RMAN> BACKUP DATABASE PLUS ARCHIVELOG;
RMAN> BACKUP CURRENT CONTROLFILE FOR STANDBY FORMAT '/u01/backup/stby_ctrl_%U';
# 2. 将备份传到备库服务器
scp -r /u01/backup/* standby-db:/u01/backup/
# 在备库执行
rman target sys/xxxxx@standby_stby
# 3. 恢复备库
RMAN> RESTORE STANDBY CONTROLFILE FROM '/u01/backup/stby_ctrl_01';
RMAN> ALTER DATABASE MOUNT;
RMAN> RESTORE DATABASE;
RMAN> RECOVER DATABASE NOREDO; -- 没有归档日志需要应用
或者用 DUPLICATE 从活动数据库直接复制(更简单):
bash复制代码
# 在备库服务器执行
rman target sys/xxxxx@primary auxiliary sys/xxxxx@standby_stby
RMAN> DUPLICATE TARGET DATABASE FOR STANDBY
FROM ACTIVE DATABASE
NOFILENAMECHECK;
2.6 启动 Redo Apply
sql复制代码
-- 在备库启动 Redo Apply
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;
-- 验证同步状态
SELECT PROCESS, STATUS, THREAD#, SEQUENCE#, BLOCK#, BLOCKS
FROM V$MANAGED_STANDBY;
-- 验证传输延迟
SELECT NAME, VALUE, DATUM_TIME
FROM V$DATAGUARD_STATS
WHERE NAME IN ('transport lag', 'apply lag');
2.7 开启 Active Data Guard(可选)
sql复制代码
-- 备库以只读模式打开,同时应用 Redo
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;
ALTER DATABASE OPEN READ ONLY;
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE USING CURRENT LOGFILE DISCONNECT;
-- 验证
SELECT OPEN_MODE, DATABASE_ROLE FROM V$DATABASE;
-- 应显示: READ ONLY WITH APPLY | PHYSICAL STANDBY
三、Data Guard Broker(简化运维)
3.1 启用 Broker
sql复制代码
-- 主库和备库都要执行
ALTER SYSTEM SET DG_BROKER_START=TRUE SCOPE=BOTH;
3.2 配置 Broker
bash复制代码
# 连接 Broker
dgmgrl sys/xxxxx@primary
DGMGRL> CREATE CONFIGURATION dg_config AS
PRIMARY DATABASE IS primary
CONNECT IDENTIFIER IS primary;
DGMGRL> ADD DATABASE standby AS
CONNECT IDENTIFIER IS standby
MAINTAINED AS PHYSICAL;
DGMGRL> ENABLE CONFIGURATION;
DGMGRL> SHOW CONFIGURATION;
-- 查看详细信息
DGMGRL> SHOW DATABASE VERBOSE primary;
DGMGRL> SHOW DATABASE VERBOSE standby;
3.3 用 Broker 切换
bash复制代码
DGMGRL> SWITCHOVER TO standby; -- Switchover(计划切换)
DGMGRL> FAILOVER TO standby; -- Failover(故障切换)
DGMGRL> REINSTATE DATABASE primary; -- 恢复原主库为新备库
四、Switchover 与 Failover
4.1 Switchover(计划性切换)
sql复制代码
-- Switchover:主备角色互换,无数据丢失
-- 适用场景:维护、升级、测试
-- 1. 在主库执行
ALTER DATABASE COMMIT TO SWITCHOVER TO STANDBY;
-- 2. 在备库执行
ALTER DATABASE COMMIT TO SWITCHOVER TO PRIMARY;
ALTER DATABASE OPEN;
-- 3. 在新备库(原主库)启动 Redo Apply
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;
4.2 Failover(故障切换)
sql复制代码
-- Failover:备库提升为主库,主库已不可用
-- 适用场景:主库崩溃、机房灾难
-- 1. 在备库执行
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE FINISH;
ALTER DATABASE COMMIT TO SWITCHOVER TO PRIMARY;
ALTER DATABASE OPEN;
-- 2. 如果原主库恢复后,需要重建为新备库
-- 用 RMAN 从新主库重建备库
RMAN> DUPLICATE TARGET DATABASE FOR STANDBY FROM ACTIVE DATABASE NOFILENAMECHECK;
4.3 切换对比
操作
前提条件
数据丢失
后续操作
Switchover
主库和备库都正常
无
原主库自动变备库
Failover
主库不可用
可能丢失未传输的 Redo
需要重建原主库为新备库
五、监控与告警
5.1 关键监控指标
sql复制代码
-- 1. 检查 Redo 传输延迟
SELECT NAME, VALUE, DATUM_TIME
FROM V$DATAGUARD_STATS
WHERE NAME IN ('transport lag', 'apply lag');
-- transport lag:传输延迟(主库到备库)
-- apply lag:应用延迟(备库应用进度)
-- 2. 检查归档传输状态
SELECT DEST_ID, STATUS, ERROR
FROM V$ARCHIVE_DEST_STATUS
WHERE DEST_ID IN (1, 2);
-- STATUS 应该是 VALID,ERROR 应该为空
-- 3. 查看 Redo Apply 进度
SELECT PROCESS, STATUS, THREAD#, SEQUENCE#, BLOCK#, BLOCKS
FROM V$MANAGED_STANDBY;
-- 4. 检查 GAP(归档缺口)
SELECT * FROM V$ARCHIVE_GAP;
-- 如果有 GAP,说明备库缺失归档日志,需要手动传输
-- 5. 查看 Redo 日志序列号(主备对比)
-- 主库
SELECT THREAD#, MAX(SEQUENCE#) FROM V$ARCHIVED_LOG GROUP BY THREAD#;
-- 备库
SELECT THREAD#, MAX(SEQUENCE#) FROM V$ARCHIVED_LOG GROUP BY THREAD#;
-- 差值就是 GAP
5.2 告警脚本示例
bash复制代码
#!/bin/bash
# dg_monitor.sh - Data Guard 监控脚本
export ORACLE_HOME=/u01/app/oracle/product/19c/dbhome_1
export ORACLE_SID=orcl
export PATH=$ORACLE_HOME/bin:$PATH
# 检查传输延迟
TRANSPORT_LAG=$(sqlplus -s sys/xxxxx@primary <<EOF
SET HEADING OFF FEEDBACK OFF
SELECT VALUE FROM V\$DATAGUARD_STATS WHERE NAME='transport lag';
EXIT;
EOF
)
# 检查应用延迟
APPLY_LAG=$(sqlplus -s sys/xxxxx@standby <<EOF
SET HEADING OFF FEEDBACK OFF
SELECT VALUE FROM V\$DATAGUARD_STATS WHERE NAME='apply lag';
EXIT;
EOF
)
# 检查 GAP
GAP_COUNT=$(sqlplus -s sys/xxxxx@standby <<EOF
SET HEADING OFF FEEDBACK OFF
SELECT COUNT(*) FROM V\$ARCHIVE_GAP;
EXIT;
EOF
)
# 告警阈值(秒)
LAG_THRESHOLD=300 # 5 分钟
# 解析延迟(格式:+00 00:05:30)
parse_lag() {
local lag=$1
echo $lag | awk -F'[+ :]' '{print $2*3600 + $3*60 + $4}'
}
transport_seconds=$(parse_lag "$TRANSPORT_LAG")
apply_seconds=$(parse_lag "$APPLY_LAG")
if [ "$transport_seconds" -gt "$LAG_THRESHOLD" ] || [ "$GAP_COUNT" -gt 0 ]; then
echo "[ALERT] Data Guard Lag! Transport: ${transport_seconds}s, Apply: ${apply_seconds}s, GAP: ${GAP_COUNT}" | \
mail -s "Oracle Data Guard Alert" dba@company.com
fi
echo "[$(date)] DG Monitor: Transport=${transport_seconds}s, Apply=${apply_seconds}s, GAP=${GAP_COUNT}"
-- 快照备库:物理备库临时转为可读写,用于测试
-- 1. 转换为快照备库
ALTER DATABASE CONVERT TO SNAPSHOT STANDBY;
ALTER DATABASE OPEN;
-- 此时备库可读写,用于升级测试、数据验证等
-- 2. 测试完成后,转回物理备库
-- 注意:所有测试数据都会被丢弃!
SHUTDOWN IMMEDIATE;
STARTUP MOUNT;
ALTER DATABASE CONVERT TO PHYSICAL STANDBY;
-- 3. 重新启动 Redo Apply
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;
九、Logical Standby(逻辑备库)
sql复制代码
-- 逻辑备库:通过 SQL Apply,备库可有不同结构
-- 1. 在主库创建 LogMiner 字典
ALTER DATABASE ADD SUPPLEMENTAL LOG DATA (PRIMARY KEY, UNIQUE INDEX) COLUMNS;
EXECUTE LOGSTDBY.BUILD;
-- 2. 在备库转换为逻辑备库
ALTER DATABASE RECOVER TO LOGICAL standby_logical;
ALTER DATABASE OPEN;
-- 3. 启动 SQL Apply
ALTER DATABASE START LOGICAL STANDBY APPLY IMMEDIATE;
-- 4. 在逻辑备库创建额外对象(主库没有的)
CREATE TABLE extra_data (id NUMBER, data VARCHAR2(100));
-- 5. 跳过某些表的同步
EXECUTE DBMS_LOGSTDBY.SKIP('SCHEMA_DDL', 'HR', 'TEMP_TABLES');
EXECUTE DBMS_LOGSTDBY.SKIP_STMT('DML', 'HR', 'TEMP_TABLES');
十、Data Guard 最佳实践
10.1 架构设计
场景
推荐方案
单机容灾
Primary + Physical Standby
读写分离
Primary + Physical Standby + ADG
高可用 + 容灾
RAC + Data Guard
自动故障切换
Data Guard + FSFO
异构同步
Data Guard + GoldenGate
10.2 运维要点
监控告警:设置 transport lag、apply lag 阈值告警
定期演练:每季度做一次 Switchover 演练
密码同步:主库密码修改后同步到备库
归档管理:及时清理备库已应用的归档日志
网络稳定:Redo 传输对网络质量敏感,建议使用专线
版本一致:主备库 Oracle 版本必须一致
补丁同步:主库打补丁后,备库也要同步
10.3 性能优化
sql复制代码
-- 1. 使用异步传输(MAXIMUM PERFORMANCE)
ALTER SYSTEM SET LOG_ARCHIVE_DEST_2='SERVICE=standby LGWR ASYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=standby';
-- 2. 开启 Redo 传输压缩
ALTER SYSTEM SET LOG_ARCHIVE_DEST_2='SERVICE=standby LGWR ASYNC COMPRESSION=ENABLE VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=standby';
-- 3. 增加并行传输(19c+)
ALTER SYSTEM SET LOG_ARCHIVE_DEST_2='SERVICE=standby LGWR SYNC PARALLEL=64 VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=standby';