Oracle Data Guard如何有效缓解主库压力,将只读查询分流至备库?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1127个文字,预计阅读时间需要5分钟。
相关专题:
oracle data guard 本身不支持备库直接处理只读查询——只有启用 active data guard(adg)选项后,备库才能在应用重做日志的同时保持 open read only 状态。这是分流只读流量的前提,不是配置对了 dg 就自动能扛查询。
ALTER DATABASE OPEN READ ONLY 执行失败:备库卡在 MOUNT 状态
常见错误是执行 ALTER DATABASE OPEN READ ONLY 时收到 ORA-16004: backup database requires recovery 或 ORA-01153: an incompatible media recovery is active。这说明:
- 日志应用进程(MRP)仍在运行,但数据库尚未完全同步到一致 SCN
- 或者备库未启用实时应用(Real-Time Apply),归档日志还没被应用完
必须先确认同步状态:
-
SELECT PROCESS, STATUS, THREAD#, SEQUENCE#, BLOCK#, BLOCKS FROM V$MANAGED_STANDBY;中 MRP 进程应为APPLYING_LOG且无积压 -
SELECT MAX(SEQUENCE#) FROM V$ARCHIVED_LOG WHERE APPLIED='YES';与主库SELECT MAX(SEQUENCE#) FROM V$LOG_HISTORY;应基本一致(延迟 ≤ 数秒)
真正可安全打开的信号是:
-
SELECT DATABASE_ROLE, OPEN_MODE, PROTECTION_MODE FROM V$DATABASE;返回PHYSICAL STANDBY+MOUNTED→ 此时才可执行ALTER DATABASE OPEN READ ONLY - 若已启用 ADG,该命令会立即成功;否则会报错,需检查是否购买并启用 ADG 许可
tnsnames.ora 里 SERVICE_NAME 指向备库后,应用仍连到主库
这不是网络配置问题,而是客户端连接字符串没做服务名隔离。默认情况下,主备库可能共用同一个 SERVICE_NAME(比如都叫 orcl),导致 TNS 解析后负载仍打到主库。
必须为备库单独注册一个只读服务:
- 在备库上执行:
ALTER SYSTEM SET SERVICE_NAMES='orcl_ro' SCOPE=BOTH; - 确保监听器已加载该服务:
lsnrctl services输出中能看到orcl_ro对应的实例和服务状态为READY - 客户端
tnsnames.ora单独配一段:ORCL_RO = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = standby-host)(PORT = 1521)) (CONNECT_DATA = (SERVICE_NAME = orcl_ro) (SERVER = DEDICATED) ) )
注意:不能复用主库的 SERVICE_NAME,否则 Oracle 不会区分路由意图;也不要依赖 FAILOVER=ON 自动切——它只用于故障转移,不是读写分离策略。
查询报 ORA-00313 或 ORA-00314:备库 SCN 落后太多
这类错误本质是查询需要访问某个数据块的旧版本(undo),但备库重做应用滞后,对应 undo 信息尚未到达或已被覆盖。
典型诱因:
- 备库 I/O 性能弱于主库,MRP 进程追不上主库生成 redo 的速度
- 主库开启大量长事务(如大表更新、未提交的批量导入),产生巨量 undo,而备库
UNDO_RETENTION设置过小 - 归档日志传输使用异步模式(
ASYNC),网络抖动加剧延迟
缓解方式优先级从高到低:
- 检查
V$DATAGUARD_STATS中apply lag和transport lag是否持续 > 30 秒 - 在备库调大
UNDO_RETENTION(例如设为 3600),并确保UNDOTBS1数据文件足够大 - 主库避免超长事务;必要时拆成小批次提交
- 若硬件允许,将传输模式改为
SYNC(需主备间网络 RTT < 5ms)
ADG 的“实时查询”不是零延迟,它依赖重做流的连续性。一旦 lag 突然拉大,正在执行的查询就可能因找不到一致性读镜像而失败。
ADG 分流效果能否达到 80%,取决于三个硬约束:许可是否激活、备库硬件资源是否 ≥ 主库 70%、以及应用层是否真正把 SELECT 流量导向 orcl_ro 服务。最容易被忽略的是第三点——很多 DBA 配好了 ADG,却没改应用连接池配置,结果所有只读请求仍走主库连接串,白忙一场。
本文共计1127个文字,预计阅读时间需要5分钟。
相关专题:
oracle data guard 本身不支持备库直接处理只读查询——只有启用 active data guard(adg)选项后,备库才能在应用重做日志的同时保持 open read only 状态。这是分流只读流量的前提,不是配置对了 dg 就自动能扛查询。
ALTER DATABASE OPEN READ ONLY 执行失败:备库卡在 MOUNT 状态
常见错误是执行 ALTER DATABASE OPEN READ ONLY 时收到 ORA-16004: backup database requires recovery 或 ORA-01153: an incompatible media recovery is active。这说明:
- 日志应用进程(MRP)仍在运行,但数据库尚未完全同步到一致 SCN
- 或者备库未启用实时应用(Real-Time Apply),归档日志还没被应用完
必须先确认同步状态:
-
SELECT PROCESS, STATUS, THREAD#, SEQUENCE#, BLOCK#, BLOCKS FROM V$MANAGED_STANDBY;中 MRP 进程应为APPLYING_LOG且无积压 -
SELECT MAX(SEQUENCE#) FROM V$ARCHIVED_LOG WHERE APPLIED='YES';与主库SELECT MAX(SEQUENCE#) FROM V$LOG_HISTORY;应基本一致(延迟 ≤ 数秒)
真正可安全打开的信号是:
-
SELECT DATABASE_ROLE, OPEN_MODE, PROTECTION_MODE FROM V$DATABASE;返回PHYSICAL STANDBY+MOUNTED→ 此时才可执行ALTER DATABASE OPEN READ ONLY - 若已启用 ADG,该命令会立即成功;否则会报错,需检查是否购买并启用 ADG 许可
tnsnames.ora 里 SERVICE_NAME 指向备库后,应用仍连到主库
这不是网络配置问题,而是客户端连接字符串没做服务名隔离。默认情况下,主备库可能共用同一个 SERVICE_NAME(比如都叫 orcl),导致 TNS 解析后负载仍打到主库。
必须为备库单独注册一个只读服务:
- 在备库上执行:
ALTER SYSTEM SET SERVICE_NAMES='orcl_ro' SCOPE=BOTH; - 确保监听器已加载该服务:
lsnrctl services输出中能看到orcl_ro对应的实例和服务状态为READY - 客户端
tnsnames.ora单独配一段:ORCL_RO = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = standby-host)(PORT = 1521)) (CONNECT_DATA = (SERVICE_NAME = orcl_ro) (SERVER = DEDICATED) ) )
注意:不能复用主库的 SERVICE_NAME,否则 Oracle 不会区分路由意图;也不要依赖 FAILOVER=ON 自动切——它只用于故障转移,不是读写分离策略。
查询报 ORA-00313 或 ORA-00314:备库 SCN 落后太多
这类错误本质是查询需要访问某个数据块的旧版本(undo),但备库重做应用滞后,对应 undo 信息尚未到达或已被覆盖。
典型诱因:
- 备库 I/O 性能弱于主库,MRP 进程追不上主库生成 redo 的速度
- 主库开启大量长事务(如大表更新、未提交的批量导入),产生巨量 undo,而备库
UNDO_RETENTION设置过小 - 归档日志传输使用异步模式(
ASYNC),网络抖动加剧延迟
缓解方式优先级从高到低:
- 检查
V$DATAGUARD_STATS中apply lag和transport lag是否持续 > 30 秒 - 在备库调大
UNDO_RETENTION(例如设为 3600),并确保UNDOTBS1数据文件足够大 - 主库避免超长事务;必要时拆成小批次提交
- 若硬件允许,将传输模式改为
SYNC(需主备间网络 RTT < 5ms)
ADG 的“实时查询”不是零延迟,它依赖重做流的连续性。一旦 lag 突然拉大,正在执行的查询就可能因找不到一致性读镜像而失败。
ADG 分流效果能否达到 80%,取决于三个硬约束:许可是否激活、备库硬件资源是否 ≥ 主库 70%、以及应用层是否真正把 SELECT 流量导向 orcl_ro 服务。最容易被忽略的是第三点——很多 DBA 配好了 ADG,却没改应用连接池配置,结果所有只读请求仍走主库连接串,白忙一场。

