1. Oracle DataGuard 部署概述
Oracle DataGuard 是 Oracle 数据库提供的高可用性和灾难恢复解决方案,通过在主库和备库之间同步数据变更,确保在主库发生故障时能够快速切换到备库继续提供服务。我在实际生产环境中部署过多次 Oracle 11g DataGuard,这里将分享一套经过验证的完整部署方案。
DataGuard 的核心原理是通过主库产生的重做日志(Redo Log)传输到备库,备库应用这些日志来保持与主库的数据同步。这种架构不仅能提供灾难恢复能力,还可以分担主库的读负载,因为备库可以配置为只读模式供查询使用。
本次部署环境采用 Redhat 7.6 操作系统,Oracle 11.2.0.4 数据库版本。主库和备库的 Oracle 软件安装路径一致,但实例名不同(主库 Orcl,备库 Orcldg),这是 DataGuard 的标准配置方式。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与基础配置
2.1 系统参数检查与调整
在开始 DataGuard 配置前,需要确保主备库的系统参数满足 Oracle 要求。执行以下检查:
bash复制# 检查内存和交换空间
free -g
# 检查内核参数
sysctl -a | grep shm
sysctl -a | grep sem
如果发现参数不符合 Oracle 11g 的安装要求,需要修改 /etc/sysctl.conf 文件并执行 sysctl -p 使更改生效。典型的内核参数配置如下:
code复制kernel.shmmax = 4294967296
kernel.shmall = 2097152
kernel.shmmni = 4096
kernel.sem = 250 32000 100 128
fs.file-max = 6815744
net.ipv4.ip_local_port_range = 9000 65500
2.2 Oracle 用户环境配置
确保主备库的 oracle 用户环境变量一致,特别是 ORACLE_BASE 和 ORACLE_HOME。编辑 oracle 用户的 .bash_profile 文件:
bash复制export ORACLE_BASE=/u01/app/oracle
export ORACLE_HOME=$ORACLE_BASE/product/11.2.0/dbhome_1
export ORACLE_SID=Orcl # 备库改为 Orcldg
export PATH=$ORACLE_HOME/bin:$PATH
export LD_LIBRARY_PATH=$ORACLE_HOME/lib:/lib:/usr/lib
注意:备库的 ORACLE_SID 应与主库不同,这是 DataGuard 的基本要求。
3. 主库配置
3.1 开启归档模式和强制日志
DataGuard 依赖归档日志进行数据同步,因此必须确保主库处于归档模式。执行以下 SQL 命令:
sql复制-- 检查当前模式
SELECT name, log_mode, force_logging FROM v$database;
-- 开启强制日志(确保所有操作都记录到重做日志)
ALTER DATABASE FORCE LOGGING;
-- 开启归档模式
SHUTDOWN IMMEDIATE;
STARTUP MOUNT;
ALTER DATABASE ARCHIVELOG;
ALTER DATABASE OPEN;
开启归档后,建议配置归档日志删除策略,避免磁盘空间被占满:
sql复制-- 设置归档日志保留策略(保留2天)
CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 2 DAYS;
3.2 配置主库参数
修改主库的 spfile 参数,为 DataGuard 做准备:
sql复制ALTER SYSTEM SET DB_UNIQUE_NAME='Orcl_primary' SCOPE=SPFILE;
ALTER SYSTEM SET LOG_ARCHIVE_CONFIG='DG_CONFIG=(Orcl_primary,Orcl_standby)' SCOPE=SPFILE;
ALTER SYSTEM SET LOG_ARCHIVE_DEST_1='LOCATION=/u01/archivelog VALID_FOR=(ALL_LOGFILES,ALL_ROLES) DB_UNIQUE_NAME=Orcl_primary' SCOPE=SPFILE;
ALTER SYSTEM SET LOG_ARCHIVE_DEST_2='SERVICE=Orcldg LGWR ASYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=Orcl_standby' SCOPE=SPFILE;
ALTER SYSTEM SET LOG_ARCHIVE_DEST_STATE_2='ENABLE' SCOPE=SPFILE;
ALTER SYSTEM SET FAL_SERVER='Orcldg' SCOPE=SPFILE;
ALTER SYSTEM SET FAL_CLIENT='Orcl' SCOPE=SPFILE;
ALTER SYSTEM SET STANDBY_FILE_MANAGEMENT='AUTO' SCOPE=SPFILE;
参数说明:
- DB_UNIQUE_NAME:数据库唯一标识,主备库不能相同
- LOG_ARCHIVE_CONFIG:指定参与 DataGuard 配置的数据库唯一名
- LOG_ARCHIVE_DEST_1:本地归档路径
- LOG_ARCHIVE_DEST_2:指定备库的服务名和传输方式(LGWR ASYNC 表示使用日志写入进程异步传输)
- FAL_SERVER/FAL_CLIENT:用于解决归档间隔的 Fetch Archive Log 配置
修改后需要重启数据库使参数生效:
sql复制SHUTDOWN IMMEDIATE;
STARTUP;
4. 备库配置
4.1 创建必要的目录结构
在备库上创建与主库相同的目录结构:
bash复制mkdir -p /u01/app/oracle/admin/Orcldg/adump
mkdir -p /u01/app/oracle/fast_recovery_area/Orcldg
mkdir -p /u01/archivelog
4.2 准备备库参数文件
从主库复制参数文件并修改:
bash复制# 在主库上创建pfile
SQL> CREATE PFILE='/home/oracle/pfile.ora' FROM SPFILE;
# 将pfile复制到备库
scp /home/oracle/pfile.ora oracle@备库IP:/home/oracle/
在备库上编辑 pfile.ora,修改以下参数:
code复制*.db_unique_name='Orcl_standby'
*.log_archive_config='DG_CONFIG=(Orcl_primary,Orcl_standby)'
*.log_archive_dest_1='LOCATION=/u01/archivelog VALID_FOR=(ALL_LOGFILES,ALL_ROLES) DB_UNIQUE_NAME=Orcl_standby'
*.fal_server='Orcl'
*.fal_client='Orcldg'
*.standby_file_management='AUTO'
然后从 pfile 创建 spfile:
sql复制CREATE SPFILE FROM PFILE='/home/oracle/pfile.ora';
4.3 创建备库控制文件
在主库上为备库创建控制文件:
sql复制ALTER DATABASE CREATE STANDBY CONTROLFILE AS '/home/oracle/standby_control.ctl';
将控制文件复制到备库:
bash复制scp /home/oracle/standby_control.ctl oracle@备库IP:/u01/app/oracle/oradata/Orcldg/control01.ctl
scp /home/oracle/standby_control.ctl oracle@备库IP:/u01/app/oracle/fast_recovery_area/Orcldg/control02.ctl
5. 配置监听和网络连接
5.1 配置主备库监听
在主备库的 $ORACLE_HOME/network/admin/listener.ora 中添加:
code复制SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(GLOBAL_DBNAME = Orcl)
(ORACLE_HOME = /u01/app/oracle/product/11.2.0/dbhome_1)
(SID_NAME = Orcl)
)
)
备库的配置类似,但使用备库的 SID 和 DBNAME。
5.2 配置TNS连接
在主备库的 $ORACLE_HOME/network/admin/tnsnames.ora 中添加对方连接信息:
主库配置:
code复制Orcldg =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 备库IP)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SID = Orcldg)
)
)
备库配置:
code复制Orcl =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 主库IP)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SID = Orcl)
)
)
配置完成后重新加载监听:
bash复制lsnrctl reload
6. 启动备库并验证同步
6.1 启动备库
在备库上启动到 mount 状态:
sql复制STARTUP NOMOUNT;
ALTER DATABASE MOUNT STANDBY DATABASE;
6.2 开启Redo应用
在备库上启动 Redo 应用进程:
sql复制ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;
6.3 验证同步状态
在主库上检查归档日志传输状态:
sql复制SELECT dest_id, status, error FROM v$archive_dest WHERE dest_id=2;
在备库上检查应用进度:
sql复制SELECT sequence#, applied FROM v$archived_log ORDER BY sequence#;
7. 常见问题与解决方案
7.1 归档日志传输失败
问题现象:主库的 v$archive_dest 显示备库状态为 ERROR
排查步骤:
- 检查网络连通性:
tnsping Orcldg - 检查备库监听状态:
lsnrctl status - 检查备库磁盘空间是否充足
- 查看 alert 日志获取详细错误信息
7.2 备库应用延迟
问题现象:备库的 v$archived_log 显示 applied 为 NO
解决方案:
- 增加主库的 LGWR 进程数量
- 调整 LOG_ARCHIVE_DEST_2 使用 SYNC 替代 ASYNC(影响主库性能)
- 检查网络带宽是否充足
7.3 备库无法启动
问题现象:备库启动时报错 ORA-01157 或 ORA-01110
解决方案:
- 检查控制文件路径是否正确
- 确保所有数据文件已从主库复制到备库
- 检查 standby_file_management 参数是否设置为 AUTO
8. 日常维护与监控
8.1 监控脚本
创建以下脚本监控 DataGuard 状态:
bash复制#!/bin/bash
# dg_check.sh
PRIMARY_SID=Orcl
STANDBY_SID=Orcldg
# 检查主库传输状态
primary_status=$(sqlplus -S / as sysdba <<EOF
SET HEADING OFF
SELECT status FROM v\$archive_dest WHERE dest_id=2;
EXIT;
EOF
)
# 检查备库应用状态
standby_status=$(sqlplus -S / as sysdba <<EOF
SET HEADING OFF
SELECT 'Applied: '||MIN(sequence#)||' to '||MAX(sequence#)
FROM v\$archived_log WHERE applied='YES';
EXIT;
EOF
)
echo "Primary传输状态: $primary_status"
echo "Standby应用状态: $standby_status"
8.2 定期切换测试
建议每季度执行一次角色切换测试,确保灾难恢复能力:
sql复制-- 在主库上执行
ALTER DATABASE COMMIT TO SWITCHOVER TO STANDBY;
-- 在原备库上执行
ALTER DATABASE COMMIT TO SWITCHOVER TO PRIMARY;
ALTER DATABASE OPEN;
测试完成后切换回原配置。
8.3 性能优化建议
- 对于大型数据库,考虑使用 Active DataGuard 选项允许备库在应用日志的同时提供只读访问
- 调整主库的 LOG_BUFFER 参数,提高日志生成效率
- 在备库上配置 STANDBY_REDO_LOG,提高故障切换速度
在实际部署中,我发现网络带宽是影响 DataGuard 性能的最关键因素。建议主备库之间使用专用网络连接,至少保证千兆带宽。对于跨机房部署,可以考虑压缩传输的归档日志:
sql复制ALTER SYSTEM SET LOG_ARCHIVE_DEST_2='SERVICE=Orcldg LGWR ASYNC COMPRESSION=ENABLE';
