Oracle RAC的多节点架构让数据库层具备了实例级冗余,但客户端连接并不会天然地在故障发生时自动切换。若没有配置TAF,应用会话会在当前实例崩溃时直接收到ORA-03113或连接中断错误,正在执行的查询需要人工重新发起。TAF的作用就是把这种实例故障对应用隐藏起来,由客户端或连接池在感知到故障后,将会话切换到健康的节点上继续运行。

不过,TAF并不是把整个数据库连接完全恢复到崩溃前的状态,它主要针对读操作和会话状态进行保护,对未提交事务的处理要区分对待。理解这一点对后续参数选择非常重要,尤其是生产环境中大量DML操作时,盲目依赖TAF可能造成数据不一致的误判。
一、TAF的两种工作模式与核心参数
TAF的全称是Transparent Application Failover,它通过在客户端连接描述符中嵌入FAILOVER_MODE配置来生效。其核心原理是客户端维护主连接与备用连接之间的关系,当主连接对应的实例发生故障时,客户端根据配置自动将会话切换到备用实例。根据备用连接建立时机不同,TAF分为BASIC和PRECONNECT两种模式。BASIC模式只在故障发生时才去建立备用连接,切换过程中会有一定的连接重建时间,但平时不占用额外资源。PRECONNECT模式则在初始连接建立的同时,提前在另一个可用实例上创建备用连接,故障切换速度更快,但会额外消耗实例上的会话和进程资源。
TAF的关键参数都位于连接描述符的FAILOVER_MODE小节中,常用参数如下:
TYPE:指定故障转移的粒度,SESSION表示只恢复会话状态,SELECT表示除了会话外还会恢复当前正在执行的查询,让查询自动重新执行。METHOD:指定故障转移方式,取值为BASIC或PRECONNECT。RETRIES:指定故障后尝试连接备用实例的次数,每失败一次间隔一段时间后重试。DELAY:指定每次重试之间的等待秒数,与RETRIES配合使用。BACKUP:指定PRECONNECT模式下备用连接的完整连接描述符,用于明确备用实例地址。
从实际业务角度看,如果应用以只读报表为主,建议将TYPE设置为SELECT,这样当一个节点宕机时,正在执行的SELECT语句会被重新提交到新节点执行,用户几乎无感知。但对于更新频繁的交易系统,TAF不能恢复已经执行但未提交的DML,TYPE=SELECT也无法重放DML语句,此时更合理的做法是将TYPE设置为SESSION,并在应用层实现幂等重试。另一个容易忽略的点是,DELAY和RETRIES共同决定了最长切换等待时间,设置过大会导致应用在故障期间长时间阻塞,设置过小又可能在网络抖动时过早放弃,需要结合业务容忍度调整。
二、在tnsnames.ora中配置TAF
tnsnames.ora是Oracle客户端最常用的网络配置方式,也是测试TAF最直接的入口。配置TAF时,关键在于把FAILOVER_MODE正确嵌套在CONNECT_DATA内部,并确保ADDRESS_LIST中至少包含两个不同节点的VIP地址,否则故障转移没有可用的目标。下面是一个典型的BASIC模式配置示例,适用于只读业务。
RAC_TAF =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = rac1-vip)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = rac2-vip)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = app_svc)
(FAILOVER_MODE =
(TYPE = SELECT)
(METHOD = BASIC)
(RETRIES = 20)
(DELAY = 2)
)
)
)
上述配置中,客户端会优先通过rac1-vip连接app_svc服务,当第一个节点异常时,客户端按照RETRIES和DELAY策略反复尝试rac2-vip,切换成功后重新执行当前SELECT语句。如果希望故障切换速度更快,可以使用PRECONNECT模式,但需要额外定义BACKUP连接串,并注意初始连接时的负载均衡。
RAC_TAF_PRE =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = rac1-vip)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = rac2-vip)(PORT = 1521))
)
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVICE_NAME = app_svc)
(FAILOVER_MODE =
(TYPE = SESSION)
(METHOD = PRECONNECT)
(BACKUP = RAC_TAF_PRE_BACKUP)
)
)
)
RAC_TAF_PRE_BACKUP =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = rac2-vip)(PORT = 1521))
(CONNECT_DATA =
(SERVICE_NAME = app_svc)
)
)
使用PRECONNECT模式时,BACKUP指向的连接串可以只包含一个备用节点,但生产环境建议把备用节点地址写清楚,避免解析歧义。还需要注意,PRECONNECT会在连接主实例的同时连接备用实例,因此数据库侧的会话数会增加一倍,对于连接数非常敏感的应用环境,应评估资源消耗后再决定是否启用。配置完成后,客户端直接使用sqlplus app_user/app_password@RAC_TAF即可测试连接。
三、JDBC与程序侧的TAF配置
Java应用使用JDBC连接Oracle时,TAF的支持程度取决于驱动类型和版本。OCI驱动对tnsnames.ora的支持最完整,可以直接读取其中的FAILOVER_MODE配置。而thin驱动在较旧版本中对TAF的支持有限,很多项目通过JDBC URL直接写入DESCRIPTION结构来实现类似效果。下面是一个thin驱动的URL示例,等价于在tnsnames.ora中配置BASIC+SELECT。
jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=rac1-vip)(PORT=1521))(ADDRESS=(PROTOCOL=TCP)(HOST=rac2-vip)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=app_svc)(FAILOVER_MODE=(TYPE=SELECT)(METHOD=BASIC)(RETRIES=20)(DELAY=2))))
不过,这种直接写在URL里的方式可读性较差,连接串一旦变长就容易出现括号不匹配的问题。更推荐的做法是在应用服务器上维护一份tnsnames.ora文件,然后通过OracleDataSource指定TNS别名连接。Java代码可以这样写:
OracleDataSource ods = new OracleDataSource();
ods.setTNSEntryName("RAC_TAF");
ods.setUser("app_user");
ods.setPassword("app_password");
Connection conn = ods.getConnection();
这种方式把网络细节从代码中剥离出来,DBA可以独立调整TAF参数而无需修改应用代码。如果应用使用了连接池,还需要确认连接池是否在连接失效时重新获取连接。部分连接池会缓存失效连接,或者自行处理故障转移,反而绕过TAF,因此在集成时要测试连接池与Oracle TAF的协同行为。
四、故障切换测试与生效验证
验证TAF是否生效不能只看配置,必须做真实的故障注入测试。测试时应避免使用正常的shutdown immediate,因为这种关闭方式可能给客户端足够的时间完成切换,不一定能暴露真实问题。更接近生产故障的方式是直接终止实例进程,例如在节点1上执行shutdown abort,或者使用kill命令终止pmon进程。
SQL> conn / as sysdba Connected. SQL> shutdown abort; ORACLE instance shut down.
实例崩溃后,在应用端持续执行查询,观察是否出现短暂阻塞后自动恢复。同时可以在数据库幸存节点上查询会话状态,确认连接是否已经迁移。
SELECT inst_id, username, service_name, failover_type, failover_method, failed_over FROM gv$session WHERE username = 'APP_USER' ORDER BY inst_id;
结果中如果failed_over列显示YES,说明该会话经历了TAF切换;failover_type和failover_method则反映当前连接实际生效的TAF策略。如果会话仍然停留在原实例,或者应用直接报连接中断错误,则需要检查tnsnames.ora配置、客户端版本以及Service是否在目标实例上运行。对于DML操作,TAF切换后应用可能收到ORA-25408错误,这表示事务不能安全重放,需要应用捕获并处理。
五、配置建议与常见误区
第一个常见误区是认为TAF可以恢复未提交事务。实际上TAF只能恢复会话和SELECT语句,对未提交的DML无法自动回滚或重放。如果应用在故障切换后没有处理事务状态,可能会出现提交时才发现事务已经丢失的情况。因此交易类系统不应只依赖TAF,还需要配合应用层重试、幂等设计或使用Oracle的Application Continuity功能。
第二个误区是连接串中只配置一个节点地址。虽然RAC的SCAN监听器可以在一定程度上把连接路由到可用节点,但TAF的FAILOVER_MODE仍然需要明确的备用目标。若ADDRESS_LIST中只有一个节点,或者FAILOVER_MODE配置缺少BACKUP,故障转移就失去了基础。此外,使用Service而不是裸SID非常重要,RAC中的Service可以定义优先实例和可用实例,能让TAF切换后的会话落在正确的节点上。
综合来看,生产环境可以遵循以下基本原则:只读报表业务使用TYPE=SELECT配合METHOD=BASIC,在资源和切换时间之间取得平衡;对连接延迟极度敏感的查询业务使用TYPE=SELECT配合METHOD=PRECONNECT;事务应用使用TYPE=SESSION,把恢复事务的逻辑放在应用层;所有连接串至少包含两个节点地址,并通过Service连接而不是SID。遵循这些原则,TAF才能在Oracle RAC高可用架构中真正发挥透明切换的价值。
Oracle RACTAF配置透明应用故障转移修改时间:2026-09-26 13:34:09