XA规范解读(2)

XA规范

XA接口是提供事务管理器和资源管理器之间互相调用的规范,实际上有两组C API 组成,ax类函数是事务管理器提供给资源管理器的调用,xa类函数是资源管理器提供给事务管理器的调用:

     int ax_reg(int rmid, XID *xid, long flags)
     资源管理器调用此函数在事务管理器上动态注册自己加入事务分支。资源管理器有两种方式加入一个全局事务,静态或动态。静态加入是由事务管理器在每个全局事务开始前,调用每个资源管理器的xa_start来开始每个事务分支。这种方式比较简单,但是系统开销比较大,因为可能并不是每个事务都会牵涉所有的资源管理器,而静态方式会将未用资源管理器也加入此全局事务,增加无用开销。而动态注册,可以当资源管理器被应用程序调用时才申请加入此事务分支,不会产生额外开销。

     int ax_unreg(int rmid, long flags)
     资源管理器调用此函数在事务管理器上动态取消事务分支的注册。

     这两个函数都是由事务管理器提供给资源管理器调用的,资源管理器在每次产生事务分支时,必须调用ax_reg,而在此事务分支结束时必须调用ax_unreg。通常,事务管理器通过动态连接库的形式将这两个函数提供给资源管理器,而资源管理器必须配置使用此动态连接库和事务管理器交互。

     int xa_open (char *xa_info, int rmid, long flags)
     为应用程序调用资源管理器做出初始化,一般是初始化与数据库的连接,xa_info包括和数据库连接所需信息。例如,DB2数据库所需的数据库连接字符串格式为“数据库名,用户名,口令”,Oracle数据库所需的数据库连接字符串格式为“Oracle_XA+Acc=P/用户名/口令”。

     int xa_close (char *xa_info, int rmid, long flags)
     结束应用程序使用资源管理器。

     int xa_start (XID *xid, int rmid, long flags)
     在资源管理器上开始一个事务分支,在使用静态方式注册事务分支时,必须在每个事务分支开始前,既应用程序开始对此资源管理器进行任何操作前,调用此程序。

     int xa_end (XID *xid, int rmid, long flags)
     在资源管理器上结束一个事务分支。

     int xa_prepare (XID *xid, int rmid, long flags)
     告诉资源管理器准备提交一个事务分支。

     int xa_commit (XID *xid, int rmid, long flags)
     要求资源管理器最终提交已经准备好的事务分支。

     int xa_rollback (XID *xid, int rmid, long flags)
     要求资源管理器回滚已经准备好的事务分支。

     int xa_recover (XID *xids, long count, int rmid, long flags)
     要求资源管理器返回所有已准备好的事务分支的列表。在故障恢复时,事务管理器得到这个列表后,可以根据各事务分支状况决定做相应动作。注意,此列表必须包含探索性完成分支的完成情况,就是说,即使资源管理器在没有接收到事务管理器的命令,而自行决定提交或回滚已准备好的事务分支后,也必须保持此事务分支状态,直到事务管理器发出xa_forget为止。

     int xa_forget (XID *xid, int rmid, long flags)
     允许资源管理器可以放弃探索性完成分支的状态。

     int xa_complete (int *handle, int *retval, int rmid, long flags)
     等待异步操作完成。上述xa函数如果采用异步调用,必须调用此函数来知道最终此操作是否完成。
     
     对于这些xa函数,一般是资源管理器提供一个包含各函数指针的结构,我们称之为 xa switch,数据库会提供一个调用函数返回此结构。例如在CICS系统中,每种资源管理器在注册到系统中,会使用一个叫做Switch Load File的动态连接库来得到此数据库的xa switch结构。此结构定义如下:

struct xa_switch_t {
     char name[RMNAMESZ];            /* 资源管理器名称 */
     long flags;                        /* 资源管理器特定选项 */
     long version;                        /* 必须为 0 */
     int ( *xa_open_entry) (char *, int, long);
     int ( *xa_close_entry) (char *, int, long);
     int ( *xa_start_entry) (XID *, int, long);
     int ( *xa_end_entry) (XID *, int, long);
     int ( *xa_rollback_entry) (XID *, int, long);
     int ( *xa_prepare_entry) (XID *, int, long);
     int ( *xa_commit_entry) (XID *, int, long);
     int ( *xa_recover_entry) (XID *, long, int, long);
     int ( *xa_forget_entry) (XID *, int, long);
     int ( *xa_complete_entry) (int *, int *, int, long);
};
     
     所以,在采用实现XA接口规范的事务管理器时,应用程序可以简化为如下(使用静态注册):


图 1-3-2

准备:事务管理器必须事先执行xa_open,准备好和所有相关资源管理器的数据库连接,这种连接可以在事务管理器启动时调用,而不必每次应用程序调用资源管理器时调用;
1.      当客户应用要开始一个全局事务连接前,事务管理器调用所有资源管理器的xa_start开始各自的事务分支;
2.      客户应用机开始执行业务有关的所有SQL操作,先读取 SAVINGS_ACCOUNT 表,然后,以正常数据库处理方式发出对 FEE_DB 数据库 SQL 语句;对 SAVINGS_DB、CHECKING_DB 执行其余 SQL 语句;
3.      如果所有数据库操作都成功,则向事务管理器发出提交命令;
4.      事务管理器向各数据库发出准备提交指令——xa_prepare,注意,准备之前,必须发出xa_end通知各数据库此事务分支不会再有其他数据库操作;
5.      如果所有数据库准备成功,则向所有数据库最终发出提交命令——xa_commit,提交成功后,向应用程序返回此全局事务的提交结果。

     这样,应用程序可以完全不用意识到其中的二阶段提交,甚至不用做数据库的连接,只需要用各种数据库的接口来处理相关业务,最后,调用事务管理器的提交命令,事务管理器会处理所有的协调工作。

你可能感兴趣的:(oracle,sql,数据库,struct,api,db2)