1 原理
成都一家集口碑和实力的网站建设服务商,拥有专业的企业建站团队和靠谱的建站技术,10余年企业及个人网站建设经验 ,为成都数千家客户提供网页设计制作,网站开发,企业网站制作建设等服务,包括成都营销型网站建设,高端网站设计,同时也为不同行业的客户提供成都网站建设、做网站的服务,包括成都电商型网站制作建设,装修行业网站制作建设,传统机械行业网站建设,传统农业行业网站制作建设。在成都做网站,选网站制作建设服务商就选创新互联。关于MySQL数据库的分布式事务XA,分布式事务实现的原理,可见[3];关于MySQL XA的说明,可见[1][2]。
MySQL XA分为两类,内部XA与外部XA;内部XA用于同一实例下跨多个引擎的事务,由大家熟悉的Binlog作为协调者;外部XA用于跨多MySQL实例的分布式事务,需要应用层介入作为协调者(崩溃时的悬挂事务,全局提交还是回滚,需要由应用层决定,对应用层的实现要求较高);
本文,假设读者已经知道MySQL数据库外部分布式事务XA的使用,而将重点放在MySQL数据库,如何处理外部分布式事务XA的crash recover,以及面对不同的crash recover的情形,应用程序如何处理,才能够保证分布式事务的一致性。最后,本文简单分析一下目前MySQL数据库外部XA支持存在的问题,以及可选的解决方案。
源代码分析基于MySQL 5.1.49,MySQL 5.5.16。
2 MySQL处理流程
2.1 MySQL 外部XA – 正常处理流程
MySQL数据库外部XA的正常处理流程,这里不准备介绍,可以参考[1][2][3]。接下来我重点描述一下MySQL数据库外部分布式事务XA的崩溃恢复流程,毕竟此流程跟应用程序如何正确使用外部XA息息相关。
2.2 MySQL外部XA – 崩溃恢复流程
若一个运行外部XA分布式事务的MySQL数据库节点发生崩溃,那么其重启之后的崩溃恢复,涉及到外部XA处理的流程如下:
Crash recover:
// 1. 读取binlog文件,将文件中的xid存入commit_list hash表
// 顾名思义,所谓的commit_list,就是说此list中对应prepare状态的xid // 在崩溃恢复过程中均可以被提交,而不在commit_list中的xid,均须回滚 // binlog中的xid,都是属于内部xid,由MySQL产生,用于内部XA Log.cc::TC_LOG_BINLOG::recover // 2. 遍历底层所有的事务引擎,收集处于XA_PREPARED状态的所有xid // 这些xid列表,既包括内部xid,也包括外部xid,存储引擎内部不做区分 Handler.cc::ha_recover(commit_list) // 执行各引擎层面提供的recover方法,收集所有的处于prepared状态的xid // 根据xid分类: // 3. 若xid属于内部xid,那么在commit_list中查找此xid, // 若存在,则提交此xid对应的事务;否则,回滚此事务 // 4. 若xid属于外部xid,那么则将xid插入xid_cache hash表 // xid_cache中的所有xid,将会通过xa recover命令返回,等待外部程序决策 Handler.cc::xarecover_handlerton // 5. 收集InnoDB存储引擎中,处于prepare状态的所有xid,并返回 got = hton->recover (innobase_xa_recover) my_xid x = info->list[i].get_my_xid(); if (!x) // 若当前为外部xid,那么将xid插入xid_cache hash表 xid_cache_insert(&xid_cache, x); else if (x in commit_list) // 若当前为内部xid,同时此xid在binlog中存在,则提交 hton->commit_by_xid(); else // 若当前为内部xid,同时此xid在binlog中不存在,则回滚 hton->rollback_by_xid(); |