oracle 12c rac 本身不支持自动读写分离,service 无法识别sql类型路由,role属性在纯rac中无效;可行方案是应用层显式区分读写service,或采用adg实现真正读写分离。
oracle 12c rac 本身不提供自动读写分离路由能力,service 只能按策略分发连接,不能识别 sql 类型(如 select vs insert)并据此路由。
Service 的 role=PRIMARY / role=PHYSICAL_STANDBY 不适用于 RAC 内部节点间读写分离
很多人误以为给 RAC 中不同节点配置 role=PRIMARY 和 role=PHYSICAL_STANDBY 的 Service 就能实现读写分离,这是错的。RAC 没有物理备库角色——所有实例都连向同一套共享存储,v$database.open_mode 在所有节点上都是 READ WRITE。Service 的 role 属性只在 Data Guard 环境中生效,对纯 RAC 无效,强行设置会被忽略。
- 执行
srvctl add service -d db_name -s rw_svc -r "inst1" -l PRIMARY后,role字段在gv$active_services中显示为空或NULL - 客户端连接该 Service 仍可能被负载均衡到任意节点,包括你“指定”的 inst1 或 inst2
- Oracle 不会拦截并重写你的
SELECT语句去另一个节点执行
instance_mode=read-only 在 12.2+ RAC 中受限且危险
从 Oracle 12.2 开始,instance_mode 参数允许设为 read-only,但仅在 Data Guard Logical Standby 场景下受支持。在 RAC 中硬设该参数会导致实例无法启动,或启动后因违反“至少一个实例必须为 READ WRITE”的强制约束而报错 ORA-01102: cannot mount database in EXCLUSIVE mode 或 ORA-600 [krsv_pmon_detach_2]。
-
instance_mode控制的是实例级只读状态,不是数据库级;它不改变 SQL 执行路径,也不触发跨节点重定向 - RAC 要求至少一个实例处于
READ WRITE模式才能打开数据库,否则 CRS 会反复尝试重启实例 - 若已在 spfile 中错误设置了
instance_mode=read-only,需用sqlplus / as sysdba连接 idle 实例,执行create pfile from spfile,手动编辑 pfile 清除该行,再重建 spfile
真正可行的 RAC 内部读写分离:靠应用层显式控制
如果你坚持不用 DG/ADG,只在一套 RAC 内做读写分离,唯一可靠方式是让应用自己决定连哪个 Service,并配合严格的 SQL 规范:
- 为写操作创建专用 Service:
srvctl add service -d orcl -s write-svc -r "orcl1,orcl2" -P BASIC -e SELECT -m BASIC -z 180 -w 5,并在应用连接串中固定使用该 Service - 为读操作创建另一组 Service:
srvctl add service -d orcl -s read-svc -r "orcl3" -l PRIMARY -P BASIC -e NONE -m TIME -z 300 -w 10,把只读流量导向指定节点(如 orcl3) - 应用代码中必须显式区分:写请求走
write-svc,报表/列表查询走read-svc;JDBC 连接串里不能依赖 TNS alias 的随机负载均衡 - 注意:节点 orcl3 若宕机,
read-svc会失败,除非你配置了-r "orcl3,orcl4"并接受跨节点读取带来的缓存融合开销
为什么 Cache Fusion 不是读写分离的解药
RAC 的核心机制是 Cache Fusion,它让所有节点能访问同一份数据块——写操作由当前持有块的实例完成,其他节点读该块时通过私网拉取最新版本。这本质是“多写多读”,不是“一写多读”。一旦你试图把读强绑定到某节点,反而会因频繁跨节点传输 block image 导致性能下降,尤其在高并发小查询场景下,gc cr block 2-way 和 gc current block busy 等等待会飙升。
真正需要读写分离的场景,应该直接上 ADG(Active Data Guard):主库写,ADG 物理备库开 OPEN READ ONLY 或 OPEN READ ONLY WITH APPLY,再配客户端 TAF 或中间件路由。RAC 内部强行切分,只是把问题从数据库推给了应用和 DBA,还牺牲了 RAC 原生的弹性与一致性保障。











