Primer
From Mysql5 start, innoDB protocol engine supports XA distributed transactions. DTP model, a TM (Transaction Manager) to manage multiple RM (resource manager), each RM maintains its own transaction branch. Before we look at the source code to see the underlying DB mysql support for XA transactions.
1. XA grammar
官网:13.3.8.1 XA Transaction SQL Syntax
. 1 XA {the START | the BEGIN} XID [ the JOIN | the RESUME ] Open XA transaction using begin to use join / resume, start do not support 2 . 3 XA the END XID [ the SUSPEND [the FOR the MIGRATE ] ] does not support the SUSPEND [the FOR the MIGRATE] . 4 . 5 XA pREPARE preparation phase of two-phase commit protocol xid 6 7 XA COMMIT xid [ ONE the pHASE ] submitted two-phase commit protocol stage, ONE behalf of the pHASE one-phase commit if only one participant rm, then the two-phase commit protocol optimization to submit a stage 8 9 XA rOLLBACK XID rollback 10 . 11 the RECOVER XA [ the CONVERT an XID ] lists all transactions in a prepared state
上面的语法中都有xid官方解释如下:
xid: gtrid [, bqual [, formatID ]]
among them,
gtrid:全局事务ID,不得超过64,建议使用十六进制数。
bqual:分支限定符(branch qualifier),如果没有提供bqual,那么默认值为空字符串'',长度不超过64
,建议使用十六进制数。
formatID:是一个无符号整数,用于标记gtrid和bqual值的格式,默认为1,长度不超过64.
对应java接口:
1 public interface Xid {
2 int MAXGTRIDSIZE = 64; 3 int MAXBQUALSIZE = 64; 4 5 int getFormatId(); 6 7 byte[] getGlobalTransactionId(); 8 9 byte[] getBranchQualifier(); 10 }
2. XA state
Official website: 13.3.8.2 XA Transaction States
XA transaction state, the following steps are expanded
1. Use XA START to start an XA transaction and put it in ACTIVE
the state.
2. For a the ACTIVE XA transaction status, we can execute SQL statements constitute matters, then publish a XA END statement. XA END the transaction enters IDLE
state.
3. For an IDLE state XA transaction, you can perform an XA PREPARE statement or an XA COMMIT ... ONE PHASE statement:
-
XA PREPARE puts the transaction in
PREPARED
the state. XA RECOVER statement at this point will include the transaction's xid value in its output, because XA RECOVER lists all XA transactions in the PREPARED state. -
XA COMMIT ... ONE PHASE (optimized for one-phase commit) to prepare and submit the transaction. xid value will not be listed XA RECOVER, because the transaction is terminated.
4. For a PREPARED state XA transaction performed XA a COMMIT statement to commit and terminate the transaction, or to perform XA ROLLBACK to roll back and terminate the transaction.
note:
With a client database connection, XA transactions and non-XA transaction (that is, local transactions) are mutually exclusive. For example, it has been carried out "XA START" command to open an XA transaction, local transaction can not be started until the XA transaction has been committed or rolled back. Conversely, if you have a local transaction started using START TRANSACTION, the XA statement can not be used until the transaction is committed or rolled back.
3. Test
1 package study.xa; 2 3 import com.mysql.jdbc.jdbc2.optional.MysqlXAConnection; 4 import com.mysql.jdbc.jdbc2.optional.MysqlXid; 5 6 import javax.sql.XAConnection; 7 import javax.transaction.xa.XAException; 8 import javax.transaction.xa.XAResource; 9 import javax.transaction.xa.Xid; 10 import java.sql.Connection; 11 import java.sql.DriverManager; 12 import java.sql.PreparedStatement; 13 importjava.sql.SQLException; 14 15 / ** * 16 * Distributed Transaction XAConnection analog @Description MySQL . 17 * @author Denny 18 is * Morning @date 2019/4/3 9:15 . 19 * / 20 is public class MysqlXaConnectionTest { 21 is 22 is public static void main (String [] args) throws SQLException { 23 is // to true indicates XA print statements for debug ,, 24 Boolean logXaCommands = to true ; 25 // operator interface to obtain resource manager instance RMl 26 is Connection conn1 = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "12345"); 27 XAConnection xaConn1 = new MysqlXAConnection((com.mysql.jdbc.Connection)conn1, logXaCommands); 28 XAResource rm1 = xaConn1.getXAResource(); 29 30 // 获得资源管理器操作接口实例 RM2 31 Connection conn2 = DriverManager.getConnection("jdbc:mysql://localhost:3306/test2", "root", "12345"); 32 XAConnection xaConn2 = new MysqlXAConnection((com.mysql.jdbc.Connection)conn2, logXaCommands); 33 XAResource rm2 =xaConn2.getXAResource (); 34 is // the AP performs a distributed transaction request TM, TM generates a global transaction ID 35 byte [] = the gtrid "g12345" .getBytes (); 36 int formatid =. 1 ; 37 [ the try { 38 is // = ============= each transaction performed on the branches RM1 and RM2 ==================== 39 // the TM is generated rm1 branch transaction ID 40 byte [] = bqual1 "b00001" .getBytes (); 41 is Xids Xid1 = new new MysqlXid (the gtrid, bqual1, formatid); 42 is // . One branch of the transaction execution of TMNOFLAGS to RM1, neither TMJOIN, or TMRESUME is 43 is rm1.start (xid1, XAResource.TMNOFLAGS); 44 @ Business 1: Insert user table 45 the PreparedStatement PS1 = conn1.prepareStatement ( "the INSERT INTO user the VALUES ( '99', 'user99')" ); 46 is ps1.execute (); 47 rm1.end (Xid1, the XAResource. TMSUCCESS is); 48 49 // (TM) generates the transaction branch ID rm2 50 byte [] = bqual2 "b00002" .getBytes (); 51 is Xids Xid2 = new new ; MysqlXid (the gtrid, bqual2, formatid) 52 is // performed on the rm2 transaction branch 53 is rm2.start (Xid2, XAResource.TMNOFLAGS); 54 is // service 2: insert user_msg table 55 PreparedStatement ps2 = conn2.prepareStatement ( "INSERT into user_msg VALUES ( '88', '99', 'user99 notes')" ); 56 is ps2.execute (); 57 is rm2.end (Xid2, XAResource.TMSUCCESS); 58 59 // =================== two-phase commit ========================= ======= 60 // phase1: RM ask all ready to commit a transaction branch 61 int rm1Prepare = rm1.prepare (Xid1); 62 int rm2Prepare = rm2.prepare (Xid2); 63 // Phase2: commit all transaction branch 64 Boolean onePhase is = to false ; 65 // (TM) is determined there are two transaction branch can not be optimized for one-phase commit 66 IF (rm1Prepare == XAResource.XA_OK 67 && rm2Prepare == XAResource.XA_OK 68 ) { 69 // all branches prepare a successful transaction, commit all transaction branch 70 rm1.commit (Xid1, onePhase); 71 rm2.commit (Xid2 , onePhase is); 72 } the else { 73 is // if the transaction branch was not successful, the rollback 74 rm1.rollback (Xid1); 75 rm1.rollback (Xid2); 76 } 77 } the catch (XAException with E) { 78 // If an exception occurs, but also rollback 79 e.printStackTrace (); 80 } 81 } 82 }
Print log:
1 Tue Jun 04 17:08:18 CST 2019 DEBUG: Executing XA statement: XA START 0x673132333435,0x623030303031,0x1 2 Tue Jun 04 17:08:18 CST 2019 DEBUG: Executing XA statement: XA END 0x673132333435,0x623030303031,0x1 3 Tue Jun 04 17:08:18 CST 2019 DEBUG: Executing XA statement: XA START 0x673132333435,0x623030303032,0x1 4 Tue Jun 04 17:08:18 CST 2019 DEBUG: Executing XA statement: XA END 0x673132333435,0x623030303032,0x1 5 Tue Jun 04 17:08:18 CST 2019 DEBUG: Executing XA statement: XA PREPARE 0x673132333435,0x623030303031,0x1 6 Tue Jun 04 17:08:18 CST 2019 DEBUG: Executing XA statement: XA PREPARE 0x673132333435,0x623030303032,0x1 7 Tue Jun 04 17:08:18 CST 2019 DEBUG: Executing XA statement: XA COMMIT 0x673132333435,0x623030303031,0x1 8 Tue Jun 04 17:08:18 CST 2019 DEBUG: Executing XA statement: XA COMMIT 0x673132333435,0x623030303032,0x1
===== Reference ======
http://www.tianshouzhi.com/api/tutorials/distributed_transaction/384