ADG备库无法自动分担读负载,必须手动配置应用路由:需为只读业务单独定义SERVICE_NAME(如rac_ro),在备库用srvctl注册并绑定实例,设置service_names、重启监听,客户端须显式连接该服务名而非DB_UNIQUE_NAME,且适配只读语义(如JDBC设oracle.jdbc.readOnly=true)。
ADG备库无法自动分担读负载,必须手动配置应用路由
oracle data guard(dg)本身不提供负载均衡能力,所谓“读写分离”只是把只读请求发到物理备库,但数据库层完全不管流量怎么分。rac + adg组合里,rac负责实例间负载均衡,adg只负责数据同步——两者不打通。所以tnsnames.ora或连接池里若仍指向主库服务名,所有读请求照样打到主库。
- 必须为只读业务单独定义一个
SERVICE_NAME(比如rac_ro),并在备库上用srvctl add service注册,且指定-r参数绑定到备库实例 - 该服务需在备库
init.ora中设置service_names并重启监听,否则lsnrctl status看不到 - 应用不能直连
DB_UNIQUE_NAME,而要使用这个显式声明的只读服务名;否则即使备库open read only,连接也默认走主库 - RAC中若启用了Fast Application Notification(FAN),需确保备库监听也发布FAN事件,否则连接池可能缓存失效节点
备库开启read only后,SELECT报ORA-16000错误的典型原因
ORA-16000 “database open for read-only access”不是报错,是正常提示——但很多ORM或连接池会把它当异常抛出,导致查询失败。根本问题在于客户端未正确识别只读库的响应语义。
- Java JDBC驱动需显式设置
oracle.jdbc.readOnly=true,否则部分版本(如ojdbc8 21.x之前)会在执行setReadOnly(true)时触发额外校验,反向查主库状态 - Python cx_Oracle / oracledb 需在
connection = oracledb.connect(...)后立即调用connection.autocommit = True,避免隐式开启事务(只读库不允许BEGIN TRANSACTION) - SQL*Plus或SQLcl中执行
SELECT前若执行过SET TRANSACTION READ ONLY,会强制走串行化事务路径,在ADG备库上直接报ORA-01456 - 某些中间件(如ShardingSphere、MyCat)默认按主库协议建连,未适配ADG的只读语义,需关闭自动事务检测或改用原生JDBC连接池
DGMGRL切换后,RAC节点服务未自动漂移的排查重点
用DGMGRL执行SWITCHOVER TO后,原主库变备库,但RAC中对应的服务(如rac_ro)没自动停在原节点、也没启动到新备库节点,这是常见断点。
- 检查
srvctl config service -d <db_name>输出,确认该服务是否标记为Management Policy: AUTOMATIC;手工添加的服务默认是MANUAL,不会随角色变化迁移 - 验证Data Guard Broker是否启用:只有
ENABLE CONFIGURATION后,Broker才监听ROLE_CHANGE事件并触发srvctl动作;否则一切靠脚本轮询 - 查看
$ORACLE_HOME/rdbms/log/drc<inst>.log,搜索service和role关键字,常能发现Broker尝试启停服务但权限不足(如grid用户无权操作oracle用户的监听) - 切记:RAC服务漂移依赖OCR中存储的资源配置,Broker不直接操作OCR,而是通过
srvctl间接调用;若srvctl命令本身在目标节点执行失败(如监听未启动),Broker不会重试也不会报错
ADG延迟导致读取到“过期数据”的真实边界在哪
很多人以为APPLY_DELAY设成0就实时,其实从redo传输、归档、应用到buffer cache,全程存在不可消除的微秒级抖动。真正影响业务的是SCN传播延迟,而非网络RTT。
- 用
SELECT MAX(SEQUENCE#) FROM V$ARCHIVED_LOG WHERE DEST_ID=2 AND APPLIED='YES'对比主备归档序列号差,比DELAY_MINS更准;差值>2通常意味着应用线程卡住 - 备库
V$DATAGUARD_STATS中apply lag字段单位是秒,但它是采样值(每5秒更新一次),瞬时延迟可能达数分钟而不被记录 - 若业务要求强一致性读(如报表核对),不能依赖
AS OF SCN,因为备库SCN可能落后;应改用主库FLASHBACK QUERY,或在应用层加分布式锁+主库校验 - 最大可用模式(MAXIMUM AVAILABILITY)下,主库commit等待至少一个备库写入standby redo才能返回,但不保证已应用——
COMMIT成功 ≠ 备库可读
ADG的“读写分离”本质是应用层契约:你承诺只读,它承诺尽力同步。没有自动兜底,也没有跨库事务协调。所有看似透明的切换,背后都要亲手填坑。










