暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL-XA事务(一)简介

MySQLLabs 2019-08-08
6137



01-分布式事务处理机制DTP模型

 


MySQL XA事务是基于Open Group 的<<Distributed Transaction Processing:The XA Specification>> 标准来实现的,目的是为了适配分布式事务,允许多个数据库实例参与到一个全局的事务中。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事务处理的内部细节,也会放在后续的文章中。 






      本文分享自微信公众号 - MySQLLabs,如有侵权,请联系 service001@enmotech.com 删除。
      最后修改时间:2019-12-20 11:49:14
      文章转载自MySQLLabs,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

      评论