本文是我最初于2017年发表在我的个人微信公众号里面,现发布在这里。
1.1. 概述
TDSQL XA全局事务(global transaction)是指用户客户端连接到TDSQL XA分布式数据库系统后发起和执行的事务,也就是TDSQL XA处理的分布式事务。一个全局事务可能会写入数据到多个后端mysql 数据库实例,每个实例上面的本地事务都是这个全局事务的事务分支(transaction branch)。客户端发起全局事务提交时,运行在TDSQL XA的网关模块中的全局事务管理器会控制该事务访问的所有后端mysql数据库实例完成两阶段提交。
TDSQL XA的全局事务的隔离级别最高可以达到serializable级别,条件是网关与后端MySQL连接中设置隔离级别为serializable。在select 语句总是使用事务锁做并发控制的情况下(本文全部内容均假设mysql使用innodb存储引擎,后文不再赘述),网关与后端mysql的连接中设置的隔离级别就是全局事务的隔离级别。 根据用户在数据库会话中设定的隔离级别的不同,TDSQL XA的全局事务可以达到read committed, repeatable read, 或者serializable隔离级别。
一个TDSQL XA集群中可以有任意多个网关实例,并且连接到每个网关上的客户端连接都可以发起分布式事务。并且我们为了避免网关实例之间的通信开销和因此导致的脆弱性,网关被设计成不做任何实例间通信。但即便如此,只要所有连接都是用serializable隔离级别那么TDSQL XA执行的事务仍然可以达到可串行化隔离级别。
1.2. 全局可串行化
为什么本地事务以serializable隔离级别运行就可以确保全局事务的serializable隔离级别?在介绍如何做到这一点之前,先介绍一下TDSQL XA的网关的两点重要的内部设计:
1. 独立的后端连接
对于连接到网关的每个客户端连接,网关会向这个连接当中的语句访问的每一个后端DB发起一个独立的连接。并且每一个变量设置会传播到后端的所有连接中。比如,如果你在客户端设置了set tx_isolation=”serializable”; 那么这个设置会被网关设置到你的客户端连接对应的每一个网关与后端DB的连接当中。
2. 语句串行执行
网关解析一条SQL语句后如果决定发送处理后的语句到多个后端DB,那么这个发送操作是并行的,也就是不需要等待每个DB返回结果就会发到下一个DB。但是,只有收到全部本条语句的执行结果并且汇集后,才返回结果给