zoukankan      html  css  js  c++  java
  • MySQL事务--两阶段提交

    MySQL事务协调器

    MySQL支持多种存储引擎,并在MySQL Server层实现Binlog机制来进行主从数据同步。每种存储引擎相互独立,使用不同的数据文件和日志文件,当MySQL实例内部一个事务涉及到多个事务存储引擎表时,需要使用2PC来保证数据一致性。

    ## 文件sqlmysqld.cc
    static int init_server_components() {
        tc_log = &tc_log_dummy;
        if (total_ha_2pc > 1 || (1 == total_ha_2pc && opt_bin_log)) {
        	if (opt_bin_log)
          		tc_log = &mysql_bin_log;
          	else
          		tc_log = &tc_log_mmap;
    	}
    }
    
    ## 等价于
    static int init_server_components() {
        tc_log = &tc_log_dummy;
    	if (total_ha_2pc > 0 && opt_bin_log) {
    		tc_log = &mysql_bin_log;
      	}
        if (total_ha_2pc > 1 && !opt_bin_log) {
        	tc_log = &tc_log_mmap;
      	}
    }
    
    • 默认使用tc_log_dummy来作为事务协调者
    • 当事务引擎超过1个且开启Binlog,则使用binlog来作为事务协调者。
    • 当事务引擎大于1个且未开启binlog,则使用tc_log_mmap作为事务协调者。

    无论tc_log_dummy还是Binlog或tc_log_mmap都基于TC_LOG这个基类来实现:

    class TC_LOG {
    	public:
    		virtual int open(const char *opt_name) = 0;
    		virtual void close() = 0;
    		virtual enum_result commit(THD *thd, bool all) = 0;
    		virtual int rollback(THD *thd, bool all) = 0;
    		virtual int prepare(THD *thd, bool all) = 0;
    };
    

    tc_log_dummy是一个空实现,不会记录事务日志。

    tc_log_mmap是一个标准的事务协调者实现,它会创建一个名为 tc.log 的日志并使用操作系统的内存映射(memory-map,mmap)机制将内容映射到内存中。tc.log 文件中分为一个一个 PAGE,每个 PAGE 上有多个XID。

    binlog同样基于TC_LOG来实现事务协调者功能,会递增生成mysql-binlog.xxxxx的文件,每个文件中包含多个事务产生的binlog event,并在binlog event中包含XID。

    tc_log_mmap和binlog都基于XID来确定事务是否已提交。

    InnoDB事务存储引擎

    MySQL存储引擎会在初始化时将相应方法注册到MySQL Server层,以InnoDB事务存储引擎为例,在初始化时会注册prepare、commit、rollback、recover等函数到MySQL Server层,供事务协调者调用。

    ## 文件 storageinnobasehandlerha_innodb.cc
    /** Initialize the InnoDB storage engine plugin.
    @param[in,out]	p	InnoDB handlerton
    @return error code
    @retval 0 on success */
    static int innodb_init(void *p) {
        handlerton *innobase_hton = (handlerton *)p;
    	innodb_hton_ptr = innobase_hton;
        innobase_hton->commit = innobase_commit;
    	innobase_hton->rollback = innobase_rollback;
        innobase_hton->prepare = innobase_xa_prepare;
        innobase_hton->recover = innobase_xa_recover;
    }
    

    在使用Binlog作为事务协调器的2PC过程中:

    • 在prepare阶段,使用MYSQL_BIN_LOG::prepare调用InnoDB存储引擎的innobase_xa_prepare方法,将InnoDB的事务日志Redo Log持久化。
    • 在Commit阶段,使用MYSQL_BIN_LOG::commit先将Binlog日志进行持久化,然后调用innobase_commit方法,将事务在InnoDB存储引擎层进行提交。

    MySQL两阶段提交

    无论时MySQL 外部XA事务还是内部XA事务,都需要通过两阶段事务提交2PC的方式来保证数据一致性。在大部分的使用场景中,都会开启MySQL Binlog来进行主从数据同步,同时InnoDB事务存储引擎成为主流选择,因此在讨论MySQL两阶段提交时更多的会关注在MySQL Server层的Binlog日志和InnoDB事务日志(Redo Log)。

    参考资料

    无处不在的 MySQL XA 事务

  • 相关阅读:
    iCloud文件同步至Mac本地磁盘
    hive多分区写入
    清理hdfs小文件shell脚本
    大数据应用建设开源工具-update2019-07
    手机号码段:中国工信.三大运营商号段-update2019-09
    sparkf:spark-sql替换hive查询引擎
    hivef:hive 执行 sql 文件
    azkaban 工作流2.0开发示例
    MySQL-时间+日期函数
    大数据仓库对业务数据的几个基本要求
  • 原文地址:https://www.cnblogs.com/gaogao67/p/15111682.html
Copyright © 2011-2022 走看看