<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    鷹翔宇空

    學習和生活

    BlogJava 首頁 新隨筆 聯系 聚合 管理
      110 Posts :: 141 Stories :: 315 Comments :: 1 Trackbacks
    下文引自:http://mywelt.net/?q=node/2046

    Uwe Weber
    Informix 和 DB2 UDB 的 IT 專家, IBM Germany

    簡介
    在現代企業環境中,用多個數據庫和多種品牌的數據庫來存儲公司數據已經不足為奇。最終,這些數據將會在不同數據庫外進行比較、合并。

    如果您有一個異構的數據庫環境,并且計劃將不同數據庫中的數據收集到一個單獨的應用程序中,那么您就應該可以使用傳統技術執行該任務。在使用 Java 時,您將通過 JDBC 處理所有的數據庫操作。清單 1 展示了在 Java 應用程序中如何連接 DB2 UDB 和 IDS 的代碼片斷。

    清單 1. 使用 JDBC 建立到不同數據庫的連接
    
      1 try { // load JDBC drivers
      2     Class.forName (JDBC_DRIVER_DB2);
      3     Class.forName (JDBC_DRIVER_IDS);
      4 }
      5 catch (Exception e) {
      6     // error handling
      7 }
      8
      9 try { // establish connection and proceed with operation
     10     con_db2 = DriverManager.getConnection (DBURL_DB2);
     11     con_ids = Drivermanager.getConnection (DBURL_IDS);
     12
     13     Statement stmt_db2 = con_db2.createStatement ();
     14     Statement stmt_ids = con_ids.createStatement ();
     15
     16     ResultSet rs_db2 = stmt_db2.executeQuery (SQL);
     17     ResultSet rs_ids = stmt_ids.executeQuery (SQL);
     18
     19     // do something very important with the result sets...
     20 }
     21 catch (SQLException e) {
     22     // error handling
     23 }
    

    兩階段提交協議簡介
    清單 1 中的演示允許您修改不同數據庫中的數據。代替執行查詢,它可以使用 JDBC 方法 executeUpdate() 執行數據修改。

    但是如果您需要在單個事務中封裝到 DB2 和 IDS 表的新一行的 insert,要做什么呢?
    意思就是說,如果其中一條 insert 語句失敗了,就應該將數據庫(這里:兩種數據庫!)的初始狀態恢復為客戶機未執行任何動作的狀態。該行為可以通過使用兩階段提交(Two-Phase-Commit)協議完成。這一標準化協議描述了如何實現分布式事務(XA)分布式工作單元(Distributed Unit of Work,DUOW)的技術,以達到跨數據庫系統的一致狀態(根據 ACID)。

    常規事務(單階段提交)中,由 COMMITROLLBACK 所執行的事務終止是一種決定性的操作,與之相反,兩階段提交(Two-Phase-Commit)事務是分為兩步(階段)進行的。

    首先,兩階段提交(Two-Phase-Commit)事務的啟動與常規的單階段提交(One-Phase-Commit)事務類似。接著,應用程序/客戶機對該兩階段提交(Two-Phase-Commit)操作中所涉及的所有數據庫執行其修改工作。現在,在最終提交該事務之前,客戶機通知參與的數據庫準備提交(第 1 階段)。如果客戶機從數據庫收到一條“okay”,就發出命令向數據庫提交該事務(第 2 階段)。最后分布式事務(Distributed Transaction)結束。

    兩階段提交(Two-Phase-Commit)中的第 1 階段十分重要。通過首先詢問數據庫是否可以進行提交,一旦某一參與的數據庫報告錯誤,就有機會立即中止整個事務。因而,第 2 階段將由 ROLLBACK,而非 COMMIT 完成。

    圖 1 提供了對于兩階段提交(Two-Phase-Commit)協議如何工作的圖形化印象。正如所演示的,分布式事務(Distributed Transaction)使用由元組表示的描述符(例如:[x,b1])。其意思是,一個分布式事務(Distributed Transaction)包含兩個元素。首先,有一個惟一全局事務 ID(global transaction id) —— 代表分布式事務(Distributed Transaction)的簡單標識符 - 由 x 表示,第二個是分支 ID(branch id),它描述整個事務的一部分。一般,分支指的是一個數據庫連接。如果您有一個將處理兩個參與數據庫的分布式事務(Distributed Transaction),您就可以用諸如 [100,1] 的描述符表示一個數據庫,用諸如 [100,2] 的描述符表示另一數據庫。因此本例中,就有一個編號為 100 的全局事務,其中包含兩個 ID 分別為 1 和 2 的分支。

    “但是”,您或許會問,“如果在兩階段提交(Two-Phase-Commit)協議的第 2 階段中出現錯誤,又將發生什么事情呢?”
    “的確,您將陷入麻煩中!”
    實際上,稍后我們將會討論該主題。

    圖 1. 兩階段提交中的時間線和應用程序流

    請看 清單 2。在第 16-19 行代碼中,您可能錯覺地認為第 17 和 18 行的語句都是屬于由 con_db2.setAutoCommit(false)(第 16 行)所定義的事務邊界的一部分。而事實卻是該行代碼啟動了一個顯式事務,用于連接到由 con_db2.commit()(第 19 行)所提交的 DB2 數據庫。第 18 行中所做的修改不受該事務的影響。本例沒有使用兩階段提交(Two-Phase-Commit)協議,因此,它不是一個分布式事務(Distributed Transaction)。無論是到 DB2 數據庫的連接,還是到 Informix Dynamic Server(IDS)的連接,它們都沒有意識到彼此的存在。

    清單 2. 非“兩階段提交”的應用程序
    
      1 try {
      2     Class.forName (JDBC_DRIVER_DB2);
      3     Class.forName (JDBC_DRIVER_IDS);
      4 }
      5 catch (Exception e) {
      6     // error handling
      7 }
      8
      9 try {
     10     con_db2 = DriverManager.getConnection (DBURL_DB2);
     11     con_ids = Drivermanager.getConnection (DBURL_IDS);
     12
     13     Statement stmt_db2 = con_db2.createStatement ();
     14     Statement stmt_ids = con_ids.createStatement ();
     15   
     16     con_db2.setAutoCommit (false);
     17     stmt_db2.executeUpdate (SQL);
     18     stmt_ids.executeUpdate (SQL);
     19     con_db2.commit ();
     20   
     21     // further processing
     22 }
     23 catch (SQLException e) {
     24    // error handling
     25 }
    

    JTA 和事務管理器(TM)
    Java Transaction API 允許您操作應用程序中的分布式事務(Distributed Transaction)。JTA 中有一組方法,它將傳統的 JDBC 調用封裝到了兩階段提交(Two-Phase-Commit)協議中。

    在異構環境中,您通常會發現一個事務管理器(Transaction Manager),負責處理分布式事務。(實際上,事務管理器可以完成大量的工作負載平衡。)因此,不僅存在到數據庫的直接連接,還有到事務管理器(Transaction Manager)的連接。這就是 JTA 發揮作用的地方:JTA 是 Java 應用程序和事務管理器(Transaction Manager)之間的接口。圖 2 演示了一個包含分布式事務的典型環境。

    由于存在事務管理器(Transaction Manager),它通常包含在應用程序服務器(Application Server)中,就不再有兩層(Two-Tier)架構。傳統的客戶/服務器(Client/Server)架構已經由三層(Tree-Tier)架構所取代,三層架構包含應用程序/客戶機事務管理器(Transaction Manager)/應用程序服務器(Application Server)數據庫服務器,而數據庫服務器一般稱作 XA Resource

    圖 2. 三層架構

    1. 包含 SQL 和 JTA 調用的 Java 應用程序。
    2. 管理分布式事務的應用程序服務器(Application Server)。
    3. 參與分布式事務的數據庫。
    4. Java 應用程序向應用程序服務器(Application Server)提交常規 SQL 語句和通用的 XA 調用。
    5. 應用程序所發送的消息由應用程序服務器(Application Server)進行處理,并使用 SQL 和數據庫供應商特定的 XA 調用發送給數據庫。

    通常,應用程序服務器(Application Server)提供了應用程序可以使用的多種服務。在談到分布式事務時,該服務就稱作 XA Resource。當然,在應用程序可以使用 XA Resource 之前,首先要在應用程序服務器中注冊和配置 XA Resource。

    現在,如果您計劃在應用程序中使用 JTA,就必須修改代碼,以便還可以與應用程序服務器(Application Server)進行通信。這包括一些附加的方法調用和指定的錯誤/異常處理。請參閱 清單 3,以了解如何工作。

    用 JTA 進行兩階段提交的必要條件
    首先,在編寫 JTA 應用程序時,您需要合適的 JDK。好消息就是在使用當前的 JDK 時,不需要任何附加包。大多數的 JTA 相關類都在 javax.transactionjavax.transaction.xa 中。

    您需要用于 DB2 UDB 和 Informix Dynamic Server 的 JDBC 驅動程序。您將需要 Type 4 JDBC 用于 Informix Dynamic Server。DB2 要求您來選擇需要哪個 JDBC 驅動程序。有 Type 2、3 和 4 JDBC。在用 JTA 進行編程時,您必須使用 Type 2 或 4 JDBC 驅動程序。為了方便,本文中所演示的所有例子都使用 Type 4 JDBC 驅動程序用于 DB2。(關于各驅動程序之間差別的解釋,請查閱手冊。)

    以上描述說明了應用程序服務器(Application Server)或事務管理器(Transaction Manager)的存在。在下面的例子中,您不會看到“外部”應用程序服務器(Application Server),因為已經使用 DB2XADataSource 和 IfxXADataSource 類直接將之構建到您的應用程序中了。如果您使用一個真正的應用程序服務器(Application Server),那么該應用程序服務器將使用這些類來連接到數據庫的本地 XA 調用。

    下面的例子(清單 3)演示了一個小型應用程序,該應用程序使用 JTA 實現兩階段提交(Two-Phase-Commit)協議。該例子并不完整,是為了讓代碼更加易讀。

    清單 3. 兩階段提交的應用程序

    
     19 import java.io.BufferedReader;
     20 import java.io.FileInputStream;
     21 import java.io.IOException;
     22 import java.io.InputStreamReader;
     23
     24 import java.sql.Connection;
     25 import java.sql.SQLException;
     26 import java.sql.Statement;
     27
     28 import java.util.Properties;
     29
     30 import javax.sql.XAConnection;
     31 import javax.transaction.xa.XAException;
     32 import javax.transaction.xa.XAResource;
     33 import javax.transaction.xa.Xid;
     34
     35 import com.ibm.db2.jcc.DB2XADataSource;
     36 import com.ibm.db2.jcc.DB2Xid;
     37
     38 import com.informix.jdbcx.IfxXADataSource;
     39 import com.informix.jdbcx.IfxXid;
    

    在第 19-39 行中,您看到了該應用程序中所使用的所有類。大多數類是您所知道的。第 30-33 行中導入的類是使用 JTA 所必要的。同樣有意思的是第 35、36 和 38、39 行中的數據庫供應商的特定類。xyzXADataSource 類包含了用于啟用兩階段提交協議的本地 XA 代碼。

    
     44 class DBX {
     45
     46     private Properties props;
     47     private String propertyfile = "jtadb2ifmx.properties";
     48
     56     DBX () {
     57
     58         Connection      db2con = null;
     59         Connection      ifxcon = null;
     60         DB2XADataSource db2ds = null;
     61         IfxXADataSource ifxds = null;
     62         Xid             db2xid = null;
     63         Xid             ifxxid = null;
     64         XAConnection    db2xacon = null;
     65         XAConnection    ifxxacon = null;
     66         XAResource      db2xares = null;
     67         XAResource      ifxxares = null;
     68
     69
     70         // read the properties
     71         props = new Properties ();
     72
     73         try {
     74             props.load (new FileInputStream (propertyfile));
     75         }
     76         catch (IOException io) {
     77             System.err.println ("Error while accessing the properties file (" +
     78                                 propertyfile + "). Abort.");
     79             System.exit (1);
     80         }
    

    DBX 類僅僅包含一個私有成員,用于負責屬性文件。在該文件中,有一些數據庫特定的設置,例如到引擎的端口或登錄信息。

    該類的構造函數實例化了 SQL 和 XA 相關類:

    • Connection: 表示到數據庫的傳統 SQL(JDBC)連接。
    • DB2XADataSourceIfxXADataSource: 這些類包含到數據庫的本地 XA 調用。使用這些類來啟用兩階段提交協議(Two-Phase-Commit-Protocol)。如果有一個應用程序服務器(Application Server),就不需要在程序中處理這些類,因為應用程序服務器(Application Server)封裝樂應用程序的這部分。
    • Xid: 指一個 XA 事務。本例中,使用了兩個不同的數據庫,所以需要兩個不同的 Xid —— 每個數據庫連接(分支)一個。
    • XAConnection: JTA 中的一部分。該類允許您啟動(提交、準備提交 ...)分布式事務(Distributed Transaction)。
    • XAResource: 該資源指的是應用程序服務器(Application Server)所提供的一個服務。同樣,本例中,我們不使用應用程序服務器(Application Server)。因此,必須在該應用程序中進行創建和初始化。

    
     83         db2ds = initDB2XADataSource ();
     84         ifxds = initIfxXADataSource ();
    

    這些代碼行調用一個方法來設置 XADataSource(參見下面)。

    
    360     IfxXADataSource initIfxXADataSource () {
    361
    362         System.out.print ("Create an IDS XA data source: ");
    363         IfxXADataSource ds = new IfxXADataSource ();
    364         ds.setDescription ("IDS XA data source");
    365         ds.setServerName (props.getProperty ("ifx.connection.instancename"));
    366         ds.setIfxIFXHOST (props.getProperty ("ifx.connection.host"));
    367         ds.setPortNumber (Integer.parseInt
    368             (props.getProperty ("ifx.connection.port")));
    369         ds.setDatabaseName (props.getProperty ("ifx.connection.databasename"));
    370
    371         System.out.println ("Okay.");
    372         return ds;
    373     }
    

    為了方便,這里同時演示了用于 XADataSource 的 IDS 和 DB2 設置,因為它們十分相似。

    在安裝 IfxDataSource(第 363 行)之后,需要將多個設置指定到數據源對象。這些設置是從屬性文件讀取的。在設置傳統的 JDBC 數據庫連接時,所做的這些設置可以與數據庫 URL 相比。請注意,沒有將任何登錄信息指定給數據源對象。登錄信息仍然是數據庫連接本身中的一部分。

    正如上面所提到的,如果存在應用程序服務器(Application Server),還可以由它來進行這一初始化。

    在用正確的參數初始化 XADataSource 之后,就將 XADataSource 返回給方法調用者。

    
     85         db2xacon = initDB2XAConnection (db2ds);
     86         ifxxacon = initIfxXAConnection (ifxds);
    

    在第 85 和 86 行的代碼中,創建了到數據庫的 XA Connection。下面描述了如何初始化這些 XA Connection。

    
    329     XAConnection initIfxXAConnection (IfxXADataSource ifxdatasource) {
    330
    331         XAConnection xacon = null;
    332
    333
    334         try {
    335             System.out.print ("Set up IDS XA connection: ");
    336             xacon = ifxdatasource.getXAConnection (
    337                 props.getProperty ("ifx.connection.username"),
    338                 props.getProperty ("ifx.connection.password"));
    339
    340             System.out.println ("Okay.");
    341         }
    342         catch (SQLException e) {
    343             sqlerr (e);
    344         }
    345
    346         return xacon;
    347     }
    

    為了設置 XAConnection,要使用前面初始化的 DataSource 對象。第 336 行使用 XADataSource 創建了 XAConnection。為了完成 XAConnection,只需要將身份驗證信息傳遞給該對象。

    
     87         db2xares = initXAResource (db2xacon);
     88         ifxxares = initXAResource (ifxxacon);
    

    現在,您準備創建 XAResource 對象了。這些對象將允許您操作兩階段提交(Two-Phase-Commit)。

    
    388     XAResource initXAResource (XAConnection xacon) {
    389
    390         XAResource xares = null;
    391
    392
    393         try {
    394             System.out.print ("Setting up a XA resource: ");
    395             xares = xacon.getXAResource ();
    396             System.out.println ("Okay.");
    397         }
    398         catch (SQLException e) {
    399             sqlerr (e);
    400         }
    401
    402         return xares;
    403     }
    

    XAResource 對象的安裝沒有什么特別的。該對象是通過調用 XAConnection 中的 getXAResource() 來創建的。

    在完成所有關于 XA 的準備之后,就創建到數據庫的 JDBC 連接。

    
     89         db2con = getDatabaseConnection (db2xacon);
     90         ifxcon = getDatabaseConnection (ifxxacon);
    

    getDatabaseConnection() 方法中,建立了一個 JDBC 數據庫連接。

    
    250     Connection getDatabaseConnection (XAConnection xacon) {
    251
    252         Connection con = null;
    253
    254         try {
    255             System.out.print ("Establish database connection: ");
    256             con = xacon.getConnection ();
    257             System.out.println ("Okay.");
    258         }
    259         catch (SQLException e) {
    260             sqlerr (e);
    261         }
    262
    263         return con;
    264     }
    

    這看上去有些混亂。既然已經在第 336 行中設置了 XAConnection,我們為何還需要 JDBC 連接呢?我們為何仍然需要一個“傳統”連接的理由是所有其他 JDBC 操作和類(Statement、ResultSet ...)都基于或使用 Connection 對象。如果您看一看 JDBC 類的層次結構圖,將會發現 XAConnection 并非是 Connection,反之亦然。XAConnection(實際上,它是 ConnectionPool 的子類)使用 Connection(層次化)。

    
     93         db2xid = createDB2XID ();
     94         ifxxid = createIfxXID ();
    

    啟動 XA 事務之前的最后一步就是為數據庫創建 XA ID 對象。在分布式事務(Distributed Transaction)中進行操作時,總是要使用這個 xid

    
    183     Xid createIfxXID () {
    184
    185         Xid xid = null;
    186
    187         byte [] gid = new byte[1];
    188         byte [] bid = new byte[1];
    189
    190         gid[0] =
    191             (Byte.decode (props.getProperty ("xid.global"))).byteValue ();
    192         bid[0] =
    193             (Byte.decode (props.getProperty ("xid.branch.ifx"))).byteValue ();
    194
    195         System.out.print ("Creating an XID (" + Byte.toString (gid[0]) + ", " +
    196                           Byte.toString (bid[0]) + ") for Informix: ");
    197
    198         xid = new IfxXid (0, gid, bid);
    199         System.out.println ("Okay.");
    200         return xid;
    201     }
    

    createIfxXID 方法創建一個 XID(這里:用于 IDS 連接)。正如“兩階段提交協議簡介”小節中提到的,XA 事務包含定義該事務的兩個元素。上面例子中的重要部分在第 198 行中。IDS XID 是同三個參數創建的。第一個參數是 format ID,它描述在什么格式中構建分布式事務(Distributed Transaction)。您可以省略這一格式信息。第二個參數定義了全局事務 ID(global transaction ID)。該 ID 對于所有參與數據庫來說是惟一的。第三個參數表示該全局事務中的事務分支。

    在(為 DB2 和 IDS)構建 XID 之后,我們可以使用它們來修改單個事務中的數據。

    
     98         execBranch (db2con, db2xares, db2xid);
     99         execBranch (ifxcon, ifxxares, ifxxid);
    

    execBranch() 方法包含了上面為每個連接所定義的 XA 事務中的修改。

    
    215     void execBranch (Connection con, XAResource xares, Xid xid) {
    216
    217         String sql = props.getProperty ("sql.statement");
    218
    219         try {
    220             xares.start (xid, javax.transaction.xa.XAResource.TMNOFLAGS);
    221
    222                 Statement stmt = con.createStatement ();
    223                 stmt.executeUpdate (sql);
    224
    225             xares.end (xid, javax.transaction.xa.XAResource.TMSUCCESS);
    226         }
    227         catch (XAException e) {
    228             System.err.println ("XA exception caught:");
    229             System.err.println ("Cause  : " + e.getCause ());
    230             System.err.println ("Message: " + e.getMessage ());
    231             e.printStackTrace ();
    232         }
    233         catch (SQLException e) {
    234             sqlerr (e);
    235         }
    236     }
    

    第 219-226 行代碼包含了分布式事務(Distributed Transaction)中為相應分支所使用的真正 SQL 語句。分支邊界在第 220 行中以 start 方法開始。傳遞給該方法的參數就是我們已經知道的事務 ID,而第二個參數包含了用于該 XA 事務的一些附加信息。因為這是第一個兩階段提交(Two-Phase-Commit)協議操作,所以不需要向該方法傳遞任何特殊信息。TMNOFLAGS 說明了這一事實。分支邊界終止于第 225 行。標志 TMSUCCESS 描述所有操作都成功。

    在 IDS 和 DB2 的分支都執行之后,全局事務就準備提交這些修改。當然,在可以向數據庫傳送最后的提交之前,必須詢問數據庫是否準備進行提交。

    
    104         if (prepareCommit (db2xares, db2xid) == XAResource.XA_OK &&
    105             prepareCommit (ifxxares, ifxxid) == XAResource.XA_OK) {
    106             // both branches are ready to commit
    107             commitBranch (db2xares, db2xid);
    108             commitBranch (ifxxares, ifxxid);
    109         }
    110         else {
    111             // a resource reported an error
    112             rollbackBranch (db2xares, db2xid);
    113             rollbackBranch (ifxxares, ifxxid);
    114         }
    116     } // end of constructor
    

    第 104 和 105 行通知數據庫準備提交。如果數據庫報告 XAResource.XA_OK,就可以提交整個事務。否則,該事務就將被 ROLLBACK 中止。

    
    417     int prepareCommit (XAResource xares, Xid xid) {
    418
    419         int rc = 0;
    420
    421         System.out.print ("Prepare XA branch (" +
    422             Byte.toString ((xid.getGlobalTransactionId ())[0]) + ", " +
    423             Byte.toString ((xid.getBranchQualifier ())[0]) + "): ");
    424
    425         try {
    426             xares.prepare (xid);
    427         }
    428         catch (XAException e) {
    429             xaerr (e);
    430         }
    431
    432         System.out.println ("Okay.");
    433         return rc;
    434     }
    

    prepareCommit() 方法中最重要的一行在第 426 行中。prepare 方法引起數據庫調用兩階段提交協議(Two-Phase-Commit)的“第 1 階段”。

    根據“第 1 階段”的結果,將提交或中止該分布式事務(Distributed Transaction)。下面是將用于發出這些必要操作的兩個方法。

    
    128     void commitBranch (XAResource xares, Xid xid) {
    129
    130         System.out.print ("Commit XA branch (" +
    131             Byte.toString ((xid.getGlobalTransactionId ())[0]) + ", " +
    132             Byte.toString ((xid.getBranchQualifier ())[0]) + "): ");
    133
    134         try {
    135             // second parameter is 'false' since we have a two phase commit
    136             xares.commit (xid, false);
    137         }
    138         catch (XAException e) {
    139             xaerr (e);
    140         }
    141
    142         System.out.println ("Okay.");
    143     }
    

    如果“第 1 階段”未報告任何錯誤,就在第 136 行中為 xid 所描述的事務分支提交“第 2 階段”。方法 commit() 中的第二個參數區分單階段或兩階段提交操作。因為我們具有一個兩階段提交操作,所以必須將該值設置為 false

    下面的例子展示了如何為數據庫回滾事務分支。

    
    446     void rollbackBranch (XAResource xares, Xid xid) {
    447
    448         System.out.print ("Rollback XA branch (" +
    449             Byte.toString ((xid.getGlobalTransactionId ())[0]) + ", " +
    450             Byte.toString ((xid.getBranchQualifier ())[0]) + "): ");
    451
    452         try {
    453             xares.rollback (xid);
    454         }
    455         catch (XAException e) {
    456             xaerr (e);
    457         }
    458
    459         System.out.println ("Okay.");
    460     }
    

    問題解答
    本文中的例子演示了如何在 Java 中使用 JTA 實現兩階段提交(Two-Phase-Commit)協議。在該應用程序中,如果一個事務分支報告了錯誤,您就要負責進行錯誤處理。但是“兩階段提交協議簡介”小節中提到仍然存在一個問題,那就是如果第 2 階段中一個事務分支發生故障,該怎么辦呢?

    如果再次查看程序代碼,您可以看到在“第 1 階段”和“第 2 階段”之間有一個很小的時間間隔。在這一時間間隔中,出于某種理由,其中某一參與數據庫可能崩潰。如果發生了,我們將陷入分布式事務已經部分提交的情形中。

    假定下列情形:在“第 1 階段”之后,您從 DB2 和 IDS 數據庫中都收到了“okay”。在下一步中,應用程序成功提交了 DB2 的事務分支。接著,應用程序通知 DB2 事務分支提交事務。現在,在應用程序可以通知 IDS 事務分支提交它這一部分之前,IDS 引擎由于斷電發生崩潰。這就是一種部分提交全局事務的情形。您現在該怎么辦呢?

    在重啟之后,DB2 和 IDS 都將嘗試恢復打開的事務分支。該引擎等待來自應用程序的提示如何做。如果應用程序沒有準備重新發送“第 2 階段”的提交,該事務分支將被引擎所啟動的試探性回滾中止。這是非常糟糕的,因為這將使該全局事務處于不一致狀態。

    一種解決方案是用一個小型應用程序連接引擎中打開的事務分支,并通知引擎提交或回滾這一打開的事務。如果您使用 IDS 作為后端,那么還有一個隱藏的 onmode 標志,允許您結束打開的事務分支。(onmode -Z xid)。

    在 DB2 UDB 中,您可以發出 LIST INDOUBT TRANSACTIONS 來獲得打開的 XA 事務的有關信息。您必須查看 DB2 Information Center 中的描述來解決該問題。

    上面描述的情形是一個很好的例子,也是使用應用程序服務器(Application Server)或事務監控器(Transaction Monitor)的理由。在使用一個中間層服務器時,就由該服務器負責保持事情正常。

    備選方案
    清單 1   演示了在應用程序中從數據庫讀取數據并處理結果的可行方法。如果您的應用程序是“只讀”應用程序,IBM? 就提供了另一種解決方案,稱作 WebSphere? Information Integrator。WebSphere Information Integrator 使用來自 DB2 UDB(或 DB2 Data Joiner、DB2 Relational Connect)的聯邦數據庫技術,以將多個數據庫(通常:數據源)虛擬化(virtualize)到一個數據庫中。不同的、非本地的數據庫中的表都鏈接到 DB2 UDB 中。該操作對于客戶機應用程序是完全透明的。客戶機可以訪問其他數據庫中的所有遠程表,就像它們是本地 DB2 UDB 表一樣。正如 清單 1  中引用的,不再需要連接兩個數據庫。到 DB2 UDB 的單個連接就已經足夠了,因為 DB2 中可以看到 IDS 數據庫中的所有表。

    目前,WebSphere Information Integrator 不支持兩階段提交,然而,將來的版本將支持兩階段提交協議;這將帶來實現企業應用程序的新方法。

    參考資料

    關于作者
    Uwe Weber 是一位 Informix 和 DB2 UDB 方面的 IT 專家。他居住在德國的慕尼黑。Uwe 的 IT 經歷始于 1997 年,從那時起,他作為一名 Informix 產品講師開始在 Informix 工作。IBM 于 2001 年收購 Informix 之后,他調去了技術預售部門,與 EMEA Central 的客戶一起工作。

    posted on 2006-02-20 14:53 TrampEagle 閱讀(470) 評論(0)  編輯  收藏 所屬分類: datebase
    主站蜘蛛池模板: 中国国语毛片免费观看视频| 亚洲av无码专区国产不乱码 | 日本不卡免费新一二三区| 中文字幕亚洲第一在线| 最近免费2019中文字幕大全| 亚洲男人第一av网站| 最新黄色免费网站| 亚洲av极品无码专区在线观看| 18禁免费无码无遮挡不卡网站| 亚洲人成日本在线观看| 中国在线观看免费国语版| 日韩亚洲人成在线| 人人狠狠综合久久亚洲高清| rh男男车车的车车免费网站| 国产精品亚洲综合一区| 小草在线看片免费人成视久网| 久久精品亚洲一区二区三区浴池| 国产福利视精品永久免费| 亚洲日韩国产AV无码无码精品| 国产大片免费观看中文字幕| 一区二区免费国产在线观看| 亚洲一区二区三区无码中文字幕| 久久99热精品免费观看动漫 | 亚洲视频精品在线观看| 99在线视频免费观看视频 | www.亚洲色图| 日本视频免费高清一本18| 亚洲午夜电影一区二区三区| 国产极品美女高潮抽搐免费网站| 免费人成网上在线观看| 亚洲AV无码日韩AV无码导航| 希望影院高清免费观看视频| 瑟瑟网站免费网站入口| 亚洲视频在线视频| 午夜免费福利网站| 天黑黑影院在线观看视频高清免费 | 97碰公开在线观看免费视频| 国产亚洲视频在线播放大全| 亚洲国产精品高清久久久| 在线免费观看一级毛片| 中国国语毛片免费观看视频|