ITPub博客

首页 > 数据库 > Oracle > 理解透明应用程序故障转移 (TAF) 和快速连接故障转移 (FCF) (文档 ID 1602113.1)

理解透明应用程序故障转移 (TAF) 和快速连接故障转移 (FCF) (文档 ID 1602113.1)

Oracle 作者:OGG-01161 时间:2015-08-25 09:54:16 0 删除 编辑

适用于:

JDBC - 版本 10.1.0.2 到 11.2.0.3.0 [发行版 10.1 到 11.2]
本文档所含信息适用于所有平台
***Checked for relevance on 24-Apr-2013***


用途

本文档旨在解释两个 RAC 概念,即透明应用程序故障转移 (TAF) 和快速连接故障转移 (FCF)。

 

适用范围

需要了解 JDBC。

详细信息

透明应用程序故障转移 (TAF)

  • TAF 的含义是什么?
    透明应用程序故障转移 (TAF),简称应用程序故障转移,是 OCI 驱动程序的一项功能。当连接到的数据库实例出错时,可利用该功能自动重新连接该数据库。此时,活动事务将回滚。事务回滚将恢复上次提交的事务。无论之前的连接是如何被丧失的,这个新的数据库连接将由另一个节点创建,但与原始连接是完全一样的。
    TAF 总处于活动状态而无需设置。
    TAF 不能用于 thin 驱动程序。 


  • TAF 的确切用途是什么?
    当第一个实例出错时,可以通过 TAF 自动转移到其他实例。
    有关 OCI 和 TAF 的更多详细信息,请参阅 Oracle? Call Interface Programmer's Guide. 


  • 如何将 TAF 用于 JDBC 驱动程序?
    需在 tnsnames.ora 中设置以下服务:
    inst_primary=(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(Host=hostname1)(Port=1521)) (ADDRESS = (PROTOCOL = TCP)(HOST=hostname2)(PORT = 1521))
    (CONNECT_DATA=(SERVICE_NAME=ORCL)(FAILOVER_MODE=(TYPE=SELECT)(METHOD=BASIC))))

    请参阅 Oracle? Database Net Services Administrator's Guide  中Configuring Transparent Application Failover 这一节,了解有关 failover_mode 的更多详细信息。 

    故障转移类型事件 

    以下是 OracleOCI 故障转移接口中可能的故障转移类型:
    • FO_SESSION
      相当于 tnsnames.ora 文件 CONNECT_DATA 标志中的 FAILOVER_MODE=SESSION。其含义是,当 OCI 应用程序中的打开游标需要重新执行时,服务器端仅需重新验证用户会话。

    • FO_SELECT
      相当于 tnsnames.ora 文件 CONNECT_DATA 标志中的 FAILOVER_MODE=SELECT。其含义是,服务器端需重新验证用户会话,而且 OCI 中的打开游标可继续获取。这意味着客户机端逻辑维持每个打开游标的获取状态。

    • FO_NONE
      相当于 tnsnames.ora 文件 CONNECT_DATA 标志中的 FAILOVER_MODE=NONE。这是默认设置,不使用故障转移功能。还可明确指定阻止故障转移的发生。另外,FO_TYPE_UNKNOWN 意味着从 OCI 驱动程序返回了一个错误的故障转移类型。


    以下是 OracleOCI 故障转移接口中可能的故障转移事件:
    • FO_BEGIN
      说明故障转移已检测到一个丢失的连接,故障转移开始启动。

    • FO_END
      说明成功完成故障转移。

    • FO_ABORT
      说明故障转移不成功,没有重试选项。

    • FO_REAUTH
      说明已重新验证用户句柄。

    • FO_ERROR
      说明故障转移暂不成功,但为应用程序提供处理错误并重试故障转移的机会。处理错误的常规方法是发出 sleep() 方法,并通过返回值 FO_RETRY 进行重试。

    • FO_RETRY
      说明应用程序应重试故障转移。

    • FO_EVENT_UNKNOWN
      一个错误的故障转移事件。

    TAF 回调 

    当一个数据库连接故障,故障转移至另一个数据库连接时使用 TAF 回调。TAF 回调是故障转移时注册的回调。故障转移时调用回调,将生成的事件通知 JDBC 应用程序。应用程序也有一些故障转移控制。
  • TAF 回调记录在 Oracle? Database JDBC Developer's Guide 的以下章节:TAF Callbacks 
    注意:回调设置是可选的。


    Java TAF 回调接口 
    OracleOCI 故障转移接口包括 callbackFn() 方法,该方法支持以下类型和事件:
    public interface OracleOCIFailover{

    // Possible Failover Types
    public static final int FO_SESSION = 1;
    public static final int FO_SELECT  = 2;
    public static final int FO_NONE  = 3;
    public static final int;

    // Possible Failover events registered with callback
    public static final int FO_BEGIN   = 1;
    public static final int FO_END     = 2;
    public static final int FO_ABORT   = 3;
    public static final int FO_REAUTH  = 4;
    public static final int FO_ERROR  = 5;
    public static final int FO_RETRY  = 6;
    public static final int FO_EVENT_UNKNOWN = 7;

    public int callbackFn (Connection conn,
                           Object ctxt, // ANy thing the user wants to save
                           int type, // One of the possible Failover Types
                           int event ); // One of the possible Failover Events


  • 用于测试 TAF 的示例代码
    请参阅以下 TAF 示例,它来自于 OTN 上提供的 JDBC 标准示例。
    /* 
     * This sample demonstrates the registration and operation of
     * JDBC OCI application failover callbacks
     * 
     * Note: Before you run this sample, set up the following
     *       service in tnsnames.ora: 
     *       inst_primary=(DESCRIPTION=
     *             (ADDRESS=(PROTOCOL=tcp)(Host=hostname)(Port=1521))
     *             (CONNECT_DATA=(SERVICE_NAME=ORCL)
     *                           (FAILOVER_MODE=(TYPE=SELECT)(METHOD=BASIC))
     *             )
     *           )
     *       Please see Net8 Administrator's Guide for more detail about 
     *       failover_mode
     *
     * To demonstrate the the functionality, first compile and start up the sample,
     *    then log into sqlplus and connect /as sysdba. While the sample is still 
     *    running, shutdown the database with "shutdown abort;". At this moment, 
     *    the failover callback functions should be invoked. Now, the database can
     *    be restarted, and the interrupted query will be continued.
     *
     */

    // You need to import java.sql and oracle.jdbc packages to use
    // JDBC OCI failover callback 

    import java.sql.*;
    import java.net.*;
    import java.io.*;
    import java.util.*;
    import oracle.jdbc.OracleConnection;
    import oracle.jdbc.OracleOCIFailover;
    import oracle.jdbc.pool.OracleDataSource;

    public class OCIFailOver {

      static final String user = "hr";
      static final String password = "hr";

      static final String URL = "jdbc:oracle:oci8:@inst_primary"; 


      public static void main (String[] args) throws Exception {

        Connection conn = null;
        CallBack   fcbk= new CallBack();
        String     msg = null;
        Statement  stmt = null;
        ResultSet rset = null; 
     
        // Create a OracleDataSource instance and set properties
        OracleDataSource ods = new OracleDataSource();
        ods.setUser(user);
        ods.setPassword(password);
        ods.setURL(URL);

        // Connect to the database
        conn = ods.getConnection();

        // register TAF callback function
        ((OracleConnection) conn).registerTAFCallback(fcbk, msg);

        // Create a Statement
        stmt = conn.createStatement ();

        for (int i=0; i<30; i++) {
          // Select the NAMEs column from the EMPLOYEES table
          rset = stmt.executeQuery ("select FIRST_NAME, LAST_NAME from EMPLOYEES");

          // Iterate through the result and print the employee names
          while (rset.next ()) 
            System.out.println (rset.getString (1) + " " +
                                rset.getString (2));

          // Sleep one second to make it possible to shutdown the DB.
          Thread.sleep(1000);
        } // End for
     
        // Close the RseultSet
        rset.close();

        // Close the Statement
        stmt.close();

        // Close the connection
        conn.close();


      } // End Main()

    } // End class jdemofo 


    /*
     * Define class CallBack
     */
    class CallBack implements OracleOCIFailover {
       
       // TAF callback function 
       public int callbackFn (Connection conn, Object ctxt, int type, int event) {

         /*********************************************************************
          * There are 7 possible failover event
          *   FO_BEGIN = 1   indicates that failover has detected a 
          *                  lost connection and faiover is starting.
          *   FO_END = 2     indicates successful completion of failover.
          *   FO_ABORt = 3   indicates that failover was unsuccessful, 
          *                  and there is no option of retrying.
          *   FO_REAUTH = 4  indicates that a user handle has been re-
          *                  authenticated. 
          *   FO_ERROR = 5   indicates that failover was temporarily un-
          *                  successful, but it gives the apps the opportunity
          *                  to handle the error and retry failover.
          *                  The usual method of error handling is to issue 
          *                  sleep() and retry by returning the value FO_RETRY
          *   FO_RETRY = 6
          *   FO_EVENT_UNKNOWN = 7  It is a bad failover event
          *********************************************************************/
         String failover_type = null;

         switch (type) {
           case FO_SESSION: 
             failover_type = "SESSION";
             break;
           case FO_SELECT:
             failover_type = "SELECT";
             break;
           default:
             failover_type = "NONE";
         }

         switch (event) {
           case FO_BEGIN:
             System.out.println(ctxt + ": "+ failover_type + " failing over...");
             break;
           case FO_END:
             System.out.println(ctxt + ": failover ended");
             break;
           case FO_ABORT:
             System.out.println(ctxt + ": failover aborted.");
             break;
           case FO_REAUTH:
             System.out.println(ctxt + ": failover.");
             break;
           case FO_ERROR:
             System.out.println(ctxt + ": failover error gotten. Sleeping...");
             // Sleep for a while 
             try {
               Thread.sleep(100);
             }
             catch (InterruptedException e) {
               System.out.println("Thread.sleep has problem: " + e.toString());
             }
             return FO_RETRY;
           default:
             System.out.println(ctxt + ": bad failover event.");
             break;
           
         }  

         return 0;

       }
    }

快速连接故障转移 (FCF)

  • FCF 的含义是什么?
    快速连接故障转移为 JDBC 应用程序提供一种与驱动程序无关的方法以利用 10g Release 1 (10.1) 中引入的连接故障转移工具。
    当 RAC 服务故障传播到 JDBC 应用程序时,数据库已回滚本地事务。然后,缓存管理器会清空所有无效连接。当一个拥有无效连接的应用程序尝试通过该连接进行工作时,将收到 SQLException ORA-17008, Closed Connection异常。该应用程序有必要处理该异常并重新连接。


  • FCF 的确切用途是什么?
    FCF 提供故障的快速通知,并可使用相同 URL 立刻重新连接。当 RAC 节点失败时,应用程序将收到一个异常。该应用程序有必要处理该异常并重新连接。
    JDBC 驱动程序不会重新瞄准现有连接。当节点失败时,应用程序必须关闭现有连接并获取一个新连接。应用程序通过获取异常来了解节点失败。当节点失败时不止抛出一个 ORA 异常,应用程序必须能处理所有这些错误。
    应用程序可能会调用 OracleConnectionCacheManager 上的 isFatalConnectionError() API 来决定所捕获的 SQLException 是否致命。

    如果该 API 的返回值为 true,则需重试 DataSource.xxxxxx 上的 getConnection


  • 如何将 FCF 用于 JDBC 驱动程序?
    若要将 FCF 用于 JDBC,必须完成以下操作:
    1. 配置并启动 ONS。如果 ONS 未正确设置,则隐式连接缓存创建将失败,并会针对第一个 getConnection() 请求抛出 ONSException。
      请参阅 Oracle? Universal Connection Pool for JDBC Developer's Guide 中的Configuring ONS一节,该节位于 Using Fast Connection Failover 
    2. FCF 目前通过一个启用池的数据源进行配置,并与 UCP 紧密集成。正如在 10g 和 11g R1 中使用的那样,通过隐式连接缓存启用的 FCF 目前已被弃用。
    3. 在向 OracleDataSource 发送第一条 getConnection() 请求前设置 FastConnectionFailoverEnabled 属性。当启用 FastConnection 故障转移时,故障转移适用于池中所有连接。
    4. 设置 OracleDataSource url 属性时,请使用服务名而非 SID。


  • 用于测试 FCF 的示例代码
    以下代码示例显示了 FCF 的工作方法,它可能并非最佳方法,但给出了所需操作的一般思路。
    请确保更改程序、<hostname1>、<hostname2> 和 <service_name> 中的以下字符串。
    PoolDataSource  pds = PoolDataSourceFactory.getPoolDataSource();

    pds.setConnectionPoolName("FCFSamplePool");
    pds.setFastConnectionFailoverEnabled(true);
    pds.setONSConfiguration("nodes=racnode1:4200,racnode2:4200\nwalletfile= /oracle11/onswalletfile");
    pds.setConnectionFactoryClassName("oracle.jdbc.pool.OracleDataSource");pds.setURL("jdbc:oracle:thin@(DESCRIPTION= "+
       "(LOAD_BALANCE=on)"+
       "(ADDRESS=(PROTOCOL=TCP)(HOST=racnode1) (PORT=1521))"+
       "(ADDRESS=(PROTOCOL=TCP)(HOST=racnode2) (PORT=1521))"+
       "(CONNECT_DATA=(SERVICE_NAME=service_name)))");
    ...
    try {  conn = pds.getConnection;  ...}catch (SQLException sqlexc)
    {
       if (conn == null || !((ValidConnection) conn).isValid())
            
       // take the appropriate action
       
    ...
    conn.close();
    }


 

上述示例从 Oracle? Universal Connection Pool for JDBC Developer's Guide 11g Release 2 (11.2) 中的 8 Using Oracle RAC Features 这一节的 FCF 文档摘录。  
基于 ICC 的 FCF 仍记录在 Oracle? Database JDBC Developer's Guide 11g Release 2 (11.2) section 27 Fast Connection Failover 中,然而,本章目前已标记为弃用。
建议使用基于 UCP 的 FCF 实施。
示例请参阅 Note 566573.1 Fast Connection Failover (FCF) Test Client Using 11g JDBC Driver and 11g RAC Cluster

 


Join the Java Development MOS Community forum for general discussions, questions, best practices, and other valuable information on: Oracle JDeveloper and ADF, Oracle WebLogic - JEE Programming (EJB, JMS etc), Oracle JDBC, Oracle Web Services (incl. DBWS Callout Utility), Oracle Web Services Manager (OWSM), Oracle Service Registry (OSR), Oracle Toplink (EclipseLink), Sun NetBeans IDE / Java Studio Creator & Java Studio Enterprise, OC4J, KODO.

参考

NOTE:1064652.1 - How to Verify Universal Connection Pool (UCP) / Fast Connection Failover (FCF) Setup
NOTE:566573.1 - Fast Connection Failover (FCF) Test Client Using 11g JDBC Driver and 11g RAC Cluster

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/27571661/viewspace-1781801/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2012-08-11

  • 博文量
    55
  • 访问量
    157578