理解透明應用程式故障轉移 (TAF) 和快速連線故障轉移 (FCF)

yyp2009發表於2014-12-30

適用於:

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部落格 ” ,連結:http://blog.itpub.net/13750068/viewspace-1384662/,如需轉載,請註明出處,否則將追究法律責任。

相關文章