ITPub博客

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

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

Oracle 作者:yyp2009 时间:2014-12-30 10:56:13 0 删除 编辑

适用于:

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

文档 ID 1602113.1

用途

本文档旨在解释两个 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 的工作方法,它可能并非最佳方法,但给出了所需操作的一般思路。
    请确保更改程序、、 和 中的以下字符串。
    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

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

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

注册时间:2008-10-17

  • 博文量
    330
  • 访问量
    1094550