mysql 内部xa_MySQL-XA事务(一)简介
01-分布式事务处理机制DTP模型
MySQL XA事务是基于Open Group 的<> 标准来实现的,目的是为了适配分布式事务,允许多个数据库实例参与到一个全局的事务中。XA事务功能在很早之前就被引入了,直到MySQL-5.7版本才趋于完善,很多数据库中间件也开始使用XA事务来实现分布式事务。先来看下Open Group组织所定义的分布式事务处理模型,也被称为DTP模型,如下:
其中涉及到的AP/RM/TM三个角色和定义如下:AP(Application Program):应用程序,主要是定义事务边界以及那些组成事务的特定于应用程序的操作。
RM(Resouces Manager):资源管理器,管理一些共享资源的自治域,如提供对诸如数据库之类的共享资源的访问。
TM(Transaction Manager):事务管理器,管理全局事务,协调事务的提交或者回滚,并协调故障恢复。02-MySQL-XA事务操作
在理解MySQL XA事务的工作原理时,需要将X/Open DTP模型中的各个组件映射到相关的MySQL组件中。MySQL引入binlog存储引擎作为操作日志的存储和传输,binlog和innobase同时参与到事务的提交过程,无论是普通事务操作还是XA事务操作,在MySQL内部都是一个分布式事务的处理过程,不同点在于MySQL XA事务的提交过程中将commit(2pc)操作显示的分为XA prepare 和XA commit两个过程来处理(细节稍有不同),以此来适配全局分布式事务。DTP模型与MySQL内部XA事务的对应关系如下:
而在全局分布式事务中,MySQL实例对应到DTP中的RM,如下:
MySQL对外提供了如下6条命令,供事务管理器来进行调度。xa start 开启一个XA事务
xa end 结束一个XA事务操作
xa prepare 准备提交一个XA事务
xa commit 正式提交一个XA事务
xa rollback 回滚一个XA事务
xa recover 列出所有处于prepared状态的XA事务
实际操作一遍就能明白,如下://开启XA事务
mysql> xa start 'trx1';
Query OK, 0 rows affected (0.00 sec)
//事务操作
mysql> insert into t1(name) values('ashe');
Query OK, 1 row affected (0.00 sec)
//事务操作
mysql> insert into t1(name) values('zed');
Query OK, 1 row affected (0.00 sec)
//结束XA事务操作
mysql> xa end 'trx1';
Query OK, 0 rows affected (0.00 sec)
//预提交XA事务
mysql> xa prepare 'trx1';
Query OK, 0 rows affected (0.00 sec)
//正式提交XA事务
mysql> xa commit 'trx1';
Query OK, 0 rows affected (0.00 sec)查看对应的binlog文件,可以发现,MySQL-5.7版本中引入了XA_prepare_log_event,将binlog日志一分为二,整体占用两个GTID,所以如果是在半同步复制场景下,一个XA事务的提交过程,需要两次ACK的等待(commit one phase除外),如下:SET @@SESSION.GTID_NEXT= '5a28b508-aa9d-11e9-99e8-8f54f8e077b5:4'/*!*/;
# at 299
#190807 21:11:30 server id 110110 end_log_pos 392 CRC32 0x22e49420 Query thread_id=3 exec_time=0 error_code=0
SET TIMESTAMP=1565183490/*!*/;
SET @@session.pseudo_thread_id=3/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1073741824/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8 *//*!*/;
SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=45/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
XA START X'74727831',X'',1
/*!*/;
# at 392
#190807 21:11:30 server id 110110 end_log_pos 451 CRC32 0xf18efdf5 Rows_query
# insert into t1(name) values('ashe')
# at 451
#190807 21:11:30 server id 110110 end_log_pos 499 CRC32 0xae2d7b3e Table_map: `ashe`.`t1` mapped to number 108
# at 499
#190807 21:11:30 server id 110110 end_log_pos 544 CRC32 0x05941ec3 Write_rows: table id 108 flags: STMT_END_F
### INSERT INTO `ashe`.`t1`
### SET
### @1=2 * INT meta=0 nullable=0 is_null=0 */
### @2='ashe' * VARSTRING(40) meta=40 nullable=1 is_null=0 */
# at 544
#190807 21:11:34 server id 110110 end_log_pos 602 CRC32 0x7e7c4788 Rows_query
# insert into t1(name) values('zed')
# at 602
#190807 21:11:34 server id 110110 end_log_pos 650 CRC32 0xdd1eb844 Table_map: `ashe`.`t1` mapped to number 108
# at 650
#190807 21:11:34 server id 110110 end_log_pos 694 CRC32 0x6d7e2039 Write_rows: table id 108 flags: STMT_END_F
### INSERT INTO `ashe`.`t1`
### SET
### @1=3 * INT meta=0 nullable=0 is_null=0 */
### @2='zed' * VARSTRING(40) meta=40 nullable=1 is_null=0 */
# at 694
#190807 21:11:56 server id 110110 end_log_pos 785 CRC32 0xb00e4eb4 Query thread_id=3 exec_time=0 error_code=0
SET TIMESTAMP=1565183516/*!*/;
XA END X'74727831',X'',1
/*!*/;
# at 785
#190807 21:11:56 server id 110110 end_log_pos 825 CRC32 0x239f7336 XA PREPARE X'74727831',X'',1
XA PREPARE X'74727831',X'',1
/*!*/;
# at 825
#190807 21:12:00 server id 110110 end_log_pos 890 CRC32 0x73388f78 GTID last_committed=1 sequence_number=2 rbr_only=no
SET @@SESSION.GTID_NEXT= '5a28b508-aa9d-11e9-99e8-8f54f8e077b5:5'/*!*/;
# at 890
#190807 21:12:00 server id 110110 end_log_pos 984 CRC32 0x04f221b5 Query thread_id=3 exec_time=0 error_code=0
SET TIMESTAMP=1565183520/*!*/;
XA COMMIT X'74727831',X'',1
/*!*/;
ROLLBACK /* added by mysqlbinlog */ /*!*/;
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
03-MySQL-XA事务状态流转
XA事务在MySQL内部共有五种状态,如下:XA_NOTR //未开始
XA_ACTIVE 活跃状态
XA_IDLE //空闲状态
XA_PREPARED //准备提交状态
XA_ROLLBACK_ONLY /只能回滚
状态流转图:
事务状态流转受到InnoDB参数innodb_rollback_on_timeout的影响,这一点会在下一篇文章中解释,关于MySQL XA事务处理的内部细节,也会放在后续的文章中。