详解 Mysql 分布式事务 XA(跨数据库事务)

简介: 详解 Mysql 分布式事务 XA(跨数据库事务)

在开发中,为了降低单点压力,通常会根据业务情况进行分表分库,将表分布在不同的库中(库可能分布在不同的机器上)。在这种场景下,事务的提交会变得相对复杂,因为多个节点(库)的存在,可能存在部分节点提交失败的情况,即事务的 ACID 特性需要在各个不同的数据库实例中保证。比如更新 db1 库的 A 表时,必须同步更新 db2 库的 B 表,两个更新形成一个事务,要么都成功,要么都失败。

 

那么我们如何利用 mysql 实现分布式数据库的事务呢?

Mysql 为我们提供了分布式事务解决方案(https://dev.mysql.com/doc/refman/5.7/en/xa.html 这是 mysql5.7 的文档)

这里先声明两个概念:

资源管理器(resource manager):用来管理系统资源,是通向事务资源的途径。数据库就是一种资源管理器。资源管理还应该具有管理事务提交或回滚的能力。

事务管理器(transaction manager):事务管理器是分布式事务的核心管理者。事务管理器与每个资源管理器(resource manager)进行通信,协调并完成事务的处理。事务的各个分支由唯一命名进行标识。

mysql 在执行分布式事务(外部 XA)的时候,mysql 服务器相当于 xa 事务资源管理器,与 mysql 链接的客户端相当于事务管理器。

 

分布式事务原理:分段式提交

分布式事务通常采用 2PC 协议,全称 Two Phase Commitment Protocol。该协议主要为了解决在分布式数据库场景下,所有节点间数据一致性的问题。分布式事务通过 2PC 协议将提交分成两个阶段:

  1. prepare;
  2. commit/rollback;

阶段一为准备(prepare)阶段。即所有的参与者准备执行事务并锁住需要的资源。参与者 ready 时,向 transaction manager 报告已准备就绪。

阶段二为提交阶段(commit)。当 transaction manager 确认所有参与者都 ready 后,向所有参与者发送 commit 命令。

如下图所示:

事务协调者 transaction manager

因为 XA 事务是基于两阶段提交协议的,所以需要有一个事务协调者(transaction manager)来保证所有的事务参与者都完成了准备工作 (第一阶段)。如果事务协调者(transaction manager)收到所有参与者都准备好的消息,就会通知所有的事务都可以提交了(第二阶段)。MySQL 在这个 XA 事务中扮演的是参与者的角色,而不是事务协调者(transaction manager)。

 

Mysql 的 XA 事务分为外部 XA 和内部 XA

外部 XA 用于跨多 MySQL 实例的分布式事务,需要应用层作为协调者,通俗的说就是比如我们在 PHP 中写代码,那么 PHP 书写的逻辑就是协调者。应用层负责决定提交还是回滚,崩溃时的悬挂事务。MySQL 数据库外部 XA 可以用在分布式数据库代理层,实现对 MySQL 数据库的分布式事务支持,例如开源的代理工具:网易的 DDB,淘宝的 TDDL 等等。

内部 XA 事务用于同一实例下跨多引擎事务,由 Binlog 作为协调者,比如在一个存储引擎提交时,需要将提交信息写入二进制日志,这就是一个分布式内部 XA 事务,只不过二进制日志的参与者是 MySQL 本身。Binlog 作为内部 XA 的协调者,在 binlog 中出现的内部 xid,在 crash recover 时,由 binlog 负责提交。(这是因为,binlog 不进行 prepare,只进行 commit,因此在 binlog 中出现的内部 xid,一定能够保证其在底层各存储引擎中已经完成 prepare)。

MySQL XA 事务基本语法

XA {START|BEGIN} xid [JOIN|RESUME] 启动 xid 事务 (xid 必须是一个唯一值;不支持 [JOIN|RESUME] 子句)

XA END xid [SUSPEND [FOR MIGRATE]] 结束 xid 事务 ( 不支持 [SUSPEND [FOR MIGRATE]] 子句)

XA PREPARE xid 准备、预提交 xid 事务

XA COMMIT xid [ONE PHASE] 提交 xid 事务

XA ROLLBACK xid 回滚 xid 事务

XA RECOVER 查看处于 PREPARE 阶段的所有事务

 

PHP 调用 MYSQL XA 事务示例

1、首先要确保 mysql 开启 XA 事务支持

SHOW VARIABLES LIKE '%xa%'

如果 innodb_support_xa 的值是 ON 就说明 mysql 已经开启对 XA 事务的支持了。如果不是就执行:

SET innodb_support_xa = ON

2、代码如下:

<?PHP
$dbtest1 = new mysqli("172.20.101.17","public","public","dbtest1")or die("dbtest1 连接失败");
$dbtest2     = new mysqli("172.20.101.18","public","public","dbtest2")or die("dbtest2 连接失败");
//为XA事务指定一个id,xid 必须是一个唯一值。
$xid = uniqid("");
//两个库指定同一个事务id,表明这两个库的操作处于同一事务中
$dbtest1->query("XA START '$xid'");//准备事务1
$dbtest2->query("XA START '$xid'");//准备事务2
try {
    //$dbtest1
    $return = $dbtest1->query("UPDATE member SET name='唐大麦' WHERE id=1") ;
    if($return == false) {
       throw new Exception("库dbtest1@172.20.101.17执行update member操作失败!");
    }
    //$dbtest2
    $return = $dbtest2->query("UPDATE memberpoints SET point=point+10 WHERE memberid=1") ;
    if($return == false) {
       throw new Exception("库dbtest1@172.20.101.18执行update memberpoints操作失败!");
    }
    //阶段1:$dbtest1提交准备就绪
    $dbtest1->query("XA END '$xid'");
    $dbtest1->query("XA PREPARE '$xid'");
    //阶段1:$dbtest2提交准备就绪
    $dbtest2->query("XA END '$xid'");
    $dbtest2->query("XA PREPARE '$xid'");
    //阶段2:提交两个库
    $dbtest1->query("XA COMMIT '$xid'");
    $dbtest2->query("XA COMMIT '$xid'");
} 
catch (Exception $e) {
    //阶段2:回滚
    $dbtest1->query("XA ROLLBACK '$xid'");
    $dbtest2->query("XA ROLLBACK '$xid'");
    die($e->getMessage());
}
$dbtest1->close();
$dbtest2->close();
?>

XA 的性能问题

XA 的性能很低。一个数据库的事务和多个数据库间的 XA 事务性能对比可发现,性能差 10 倍左右。因此要尽量避免 XA 事务,例如可以将数据写入本地,用高性能的消息系统分发数据。或使用数据库复制等技术。只有在这些都无法实现,且性能不是瓶颈时才应该使用 XA。

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
10月前
|
缓存 关系型数据库 BI
使用MYSQL Report分析数据库性能(下)
使用MYSQL Report分析数据库性能
594 158
|
10月前
|
关系型数据库 MySQL 数据库
自建数据库如何迁移至RDS MySQL实例
数据库迁移是一项复杂且耗时的工程,需考虑数据安全、完整性及业务中断影响。使用阿里云数据传输服务DTS,可快速、平滑完成迁移任务,将应用停机时间降至分钟级。您还可通过全量备份自建数据库并恢复至RDS MySQL实例,实现间接迁移上云。
|
10月前
|
关系型数据库 MySQL 数据库
阿里云数据库RDS费用价格:MySQL、SQL Server、PostgreSQL和MariaDB引擎收费标准
阿里云RDS数据库支持MySQL、SQL Server、PostgreSQL、MariaDB,多种引擎优惠上线!MySQL倚天版88元/年,SQL Server 2核4G仅299元/年,PostgreSQL 227元/年起。高可用、可弹性伸缩,安全稳定。详情见官网活动页。
1584 152
|
10月前
|
关系型数据库 MySQL 数据库
阿里云数据库RDS支持MySQL、SQL Server、PostgreSQL和MariaDB引擎
阿里云数据库RDS支持MySQL、SQL Server、PostgreSQL和MariaDB引擎,提供高性价比、稳定安全的云数据库服务,适用于多种行业与业务场景。
1101 156
|
10月前
|
缓存 监控 关系型数据库
使用MYSQL Report分析数据库性能(中)
使用MYSQL Report分析数据库性能
639 156
|
10月前
|
缓存 监控 关系型数据库
使用MYSQL Report分析数据库性能(上)
最终建议:当前系统是完美的读密集型负载模型,优化重点应放在减少行读取量和提高数据定位效率。通过索引优化、分区策略和内存缓存,预期可降低30%的CPU负载,同时保持100%的缓冲池命中率。建议每百万次查询后刷新统计信息以持续优化
756 161
|
10月前
|
关系型数据库 MySQL 分布式数据库
阿里云PolarDB云原生数据库收费价格:MySQL和PostgreSQL详细介绍
阿里云PolarDB兼容MySQL、PostgreSQL及Oracle语法,支持集中式与分布式架构。标准版2核4G年费1116元起,企业版最高性能达4核16G,支持HTAP与多级高可用,广泛应用于金融、政务、互联网等领域,TCO成本降低50%。
|
10月前
|
关系型数据库 分布式数据库 数据库
阿里云数据库收费价格:MySQL、PostgreSQL、SQL Server和MariaDB引擎费用整理
阿里云数据库提供多种类型,包括关系型与NoSQL,主流如PolarDB、RDS MySQL/PostgreSQL、Redis等。价格低至21元/月起,支持按需付费与优惠套餐,适用于各类应用场景。
|
10月前
|
SQL 关系型数据库 MySQL
Mysql数据恢复—Mysql数据库delete删除后数据恢复案例
本地服务器,操作系统为windows server。服务器上部署mysql单实例,innodb引擎,独立表空间。未进行数据库备份,未开启binlog。 人为误操作使用Delete命令删除数据时未添加where子句,导致全表数据被删除。删除后未对该表进行任何操作。需要恢复误删除的数据。 在本案例中的mysql数据库未进行备份,也未开启binlog日志,无法直接还原数据库。
|
10月前
|
Ubuntu 安全 关系型数据库
安装与配置MySQL 8 on Ubuntu,包括权限授予、数据库备份及远程连接指南
以上步骤提供了在Ubuntu上从头开始设置、配置、授权、备份及恢复一个基础但完整的MySQL环境所需知识点。
1129 7

推荐镜像

更多