ac在oracle 19c rac中失效主因是服务配置错误:必须使用用户定义服务(非默认服务),并显式设置failover_type='transaction'、commit_outcome=true、drain_timeout≥300秒,且客户端连接串需启用acenabled=true,同时执行lsnrctl reload和服务重启。
ac 在 oracle 19c rac 中不起作用,绝大多数情况是服务配置错了,而不是功能本身失效。 它不会报错,也不会抛异常,只是静默退化为普通连接 —— 所以你查日志、看会话、测切换,都“看起来正常”,唯独故障时事务不重放、用户看到报错。
必须用用户定义的服务,不能用默认服务
Oracle 默认服务(如 SERVICE_NAME 为 ORCL 或 ORCLPDB1)不启用 Application Continuity 支持。TAC 的会话跟踪、语句捕获、重放上下文全依赖服务级元数据注册,而默认服务在创建时未设置 COMMIT_OUTCOME=TRUE、RETENTION_TIMEOUT 等关键属性。
- 检查当前服务是否为用户定义:运行
SELECT NAME, NETWORK_NAME, FAILOVER_METHOD, FAILOVER_TYPE, GOAL, CLB_GOAL, TAF_POLICY FROM DBA_SERVICES;,确认NAME不是系统自动生成的(如ORCL$SEED、PDB$SEED或带$符号的名称) - 新建服务时必须显式指定:
DBMS_SERVICE.CREATE_SERVICE中传入FAILOVER_METHOD => 'BASIC'、FAILOVER_TYPE => 'TRANSACTION'、COMMIT_OUTCOME => TRUE、RETENTION_TIMEOUT => 86400 - 已存在服务可修改:
DBMS_SERVICE.MODIFY_SERVICE更新上述参数,改完需执行DBMS_SERVICE.START_SERVICE
排水超时(Drain Timeout)设太短导致重放被截断
当节点计划维护(如滚动补丁)时,RAC 先对目标实例发起 Drain 操作:拒绝新连接、等待活跃事务完成、超时后强制终止未完成请求并触发重放。如果 DRCP_DRAIN_TIMEOUT 或服务级 QUEUE_TIMEOUT 设得太小(比如默认的 30 秒),大量长事务还没来得及提交或回滚就被中断,TAC 来不及捕获完整上下文,重放直接失败。
- 查看当前 Drain 超时值:
SELECT NAME, DRAIN_TIMEOUT FROM V$SERVICES; - 建议最小值设为 300 秒(5 分钟),复杂业务可设至 1800 秒(30 分钟):
DBMS_SERVICE.MODIFY_SERVICE(..., DRAIN_TIMEOUT => 1800) - 注意:该值不是越长越好 —— 过长会导致维护窗口不可控;但低于最慢事务执行时间,就必然丢请求
客户端连接串漏了关键参数
TAC 不是数据库单方面能开启的特性,它需要客户端配合提供可重放的会话上下文。JDBC Thin、ODP.NET、OCI 都要求连接串中明确声明支持 AC,并启用 session state tracking。
- JDBC Thin 必须包含:
oracle.net.CONNECT_TIMEOUT=60000、oracle.net.RECEIVE_TIMEOUT=60000、oracle.jdbc.fanEnabled=true、oracle.jdbc.acEnabled=true - ODP.NET 需在连接字符串加:
Connection Timeout=60;Enable App Continuity=True; - 所有客户端必须使用 Oracle 连接池(UCP / ODP.NET Session Pool / OCI Session Pool),直连(
DriverManager.getConnection)不支持 TAC
最容易被忽略的是:服务属性改了、超时调高了、连接串也加了参数,但没重启监听器或没重新注册服务 —— lsnrctl reload 和 srvctl stop service/srvctl start service 缺一不可。TAC 的元数据只在服务注册进监听器那一刻加载一次,后续修改不 reload 就永远不生效。











