ADG备库默认只读,读写分离需应用或中间件实现;主库须启用FORCE LOGGING和ARCHIVELOG;RAC多节点需统一配置;ADG需独立服务名与连接配置,负载均衡依赖客户端策略。

ADG备库默认不支持写操作,读写分离必须靠应用层或中间件控制
Oracle ADG(Active Data Guard)物理备库在OPEN READ ONLY状态下,任何INSERT、UPDATE、DELETE或DDL都会直接报错 ORA-16000: database open for read-only access。这不是配置问题,是物理备库的底层限制——Redo Apply机制只做块级重放,不支持反向同步或逻辑冲突解决。所以“在ADG上实现读写分离”,本质是把读请求路由到ADG,写请求强制走RAC主库,这个分流动作不在数据库内完成,而在客户端或中间件侧。
常见踩坑点:
- 误以为给ADG配置
service_name并设为READONLY就能自动分流——Oracle本身不拦截写语句,应用发过去照样报错 - 用JDBC连接串加
oracle.jdbc.Readonly=true,但该参数仅影响驱动行为,不阻止应用代码里执行DML - 在RAC集群里把ADG节点加入SCAN监听——无效,SCAN只负责RAC内部实例间负载,不识别外部ADG节点
RAC主库侧必须启用FORCE LOGGING和归档,否则ADG无法持续同步
ADG依赖主库持续生成可传输的归档日志。如果主库没开归档(ARCHIVELOG)或没启强制日志(FORCE LOGGING),ADG会在应用日志时卡住,报错 ORA-16766: Redo Apply is stopped 或 ORA-16826: unable to apply redo。RAC环境还要注意:所有节点都得统一配置,不能只在node1上执行ALTER DATABASE FORCE LOGGING就完事。
关键检查项:
- 确认所有RAC实例都处于
ARCHIVELOG模式:SELECT log_mode FROM v$database; - 验证强制日志已全局生效:
SELECT force_logging FROM v$database;(必须返回YES) - 检查
LOG_ARCHIVE_DEST_2是否指向ADG且状态正常:SELECT status, error FROM v$archive_dest WHERE dest_id = 2; - RAC中必须用
sid='*'指定参数作用于所有实例,例如:ALTER SYSTEM SET LOG_ARCHIVE_DEST_2='SERVICE=orcldg ...' SCOPE=BOTH SID='*';
ADG节点需单独配SCAN或DNS轮询,不能复用RAC的SCAN
RAC的SCAN(Single Client Access Name)是专为RAC多实例设计的虚拟IP池,绑定的是本地节点上的LISTENER_SCAN,它只感知RAC集群内的实例(orcl1、orcl2)。ADG是独立服务器,不在RAC集群内,它的监听器是普通单实例监听(LISTENER),必须单独暴露服务名供应用连接。
实操建议:
- 在ADG服务器上创建专用service:
srvctl add service -d orcldg -s adg_readonly -r orcldg -P BASIC -l PRIMARY -y AUTOMATIC - 启动该service:
srvctl start service -d orcldg -s adg_readonly - 在客户端TNSNAMES.ORA中定义两个独立条目:
rac_rw = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = rac-scan)(PORT = 1521)) (CONNECT_DATA = (SERVICE_NAME = orcl)))adg_ro = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = db100)(PORT = 1521)) (CONNECT_DATA = (SERVICE_NAME = adg_readonly))) - 应用代码里根据SQL类型选择连接源,或用Sharding-JDBC、MyCat等中间件做自动路由
负载均衡不是DB自动做的,而是靠客户端连接策略+ADG节点数扩展
Oracle不提供跨RAC与ADG的统一负载均衡器。所谓“ADG负载均衡”,实际是指:当有多个ADG节点(比如一主两备)时,把读请求按权重或轮询分发到不同ADG实例上。这需要你在应用侧或网关层实现,比如:
- 用Nginx或HAProxy做TCP层负载,后端指向多个ADG IP + 端口
- 在Java应用里用
HikariCP配置多个数据源,结合AbstractRoutingDataSource按方法名路由 - 使用Oracle自带的
Connection Pooling配合TNS别名中的(LOAD_BALANCE=on),但仅限同个TNS条目下的多个地址(不跨RAC/ADG)
容易被忽略的细节:ADG之间没有共享缓存,每个节点的Buffer Cache完全独立。如果读请求分布不均,可能某个ADG节点Buffer Hit Ratio很低,而另一个很高——这不是数据库问题,是负载策略没对齐业务访问热点。上线前务必用真实查询压测各ADG节点的v$sysstat中physical reads和buffer gets比例。











