TDSQL XA 全局死锁处理

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 本文是我最初于2017年发表在我的个人微信公众号里面,现发布在这里。1.概述TDSQL XA的全局事务(global transaction)就是用户客户端连接到TDSQL XA分布式数据库系统后发起和执行的事务,也就是TDSQL XA处理的分布式事务。一个全局事务可能会写入数据到多个后端mysql 数据库实例,每个实例上面的本地事务都是这个全局事务的事务分支(transaction branch)。客户端发起全局事务提交时,运行在TDSQL XA的网关模块中的全局事务管理器会控制该事务访问的所有后端mysql数据库实例完成两阶段提交。全局事务执行过程中可能发生两类死锁,第一类就是

本文是我最初于2017年发表在我的个人微信公众号里面,现发布在这里。

1.概述
TDSQL XA的全局事务(global transaction)就是用户客户端连接到TDSQL XA分布式数据库系统后发起和执行的事务,也就是TDSQL XA处理的分布式事务。一个全局事务可能会写入数据到多个后端mysql 数据库实例,每个实例上面的本地事务都是这个全局事务的事务分支(transaction branch)。客户端发起全局事务提交时,运行在TDSQL XA的网关模块中的全局事务管理器会控制该事务访问的所有后端mysql数据库实例完成两阶段提交。
全局事务执行过程中可能发生两类死锁,第一类就是每个mysql的innodb(本文只讨论MySQL使用innodb存储引擎的情形,下同)实例内部产生的死锁,innodb现有的死锁检测和处理机制就可以处理这样的死锁;第二类就是全局死锁,这是单一的innodb实例无法解除的死锁,也就是本文要讨论的主要内容。
2.全局死锁示例
GT1和GT2分别在set1上更新数据行R1,在set2上更新数据行R2,事务分支:
GT1:
{
T11: update t1 set t1.age=11 where pk=1,
T12: update t1 set t1.age=22 where pk=2;
}

GT2:
{
T21: update t1 set t1.age=22 where pk=2,
T22: update t1 set t1.age=11 where pk=1
}
执行流程是GT1.T11在set1上执行,同时GT2.T21在set2上面执行,然后GT1.T12在set2上面执行被GT2.T21阻塞,GT2.T22在set1上面执行也被GT1.T11阻塞,此时的等待关系:
T11锁住R1, T22等待R1行锁:T22->T11,即GT2->GT1
T21锁住R2, T12等待R2行锁:T12->T21,即GT1->GT2

对于set1或者set2上面的innodb来说,它们都认为没有死锁发生,因为set1上面T22在等待T11的行锁,没有环路;set2上面T21在等待T22的行锁,也没有环路。但是全局来看,GT1和GT2确实产生了环路等待,并且每个事务分支在结束前都不会释放其已经持有的行锁,因而构成了QQ号卖号全局死锁。这种全局死锁是任何一个TDSQL XA的MySQL实例无法解除的,必须在TDSQL XA的TM(事务管理器)也就是网关中来解除。
3.全局死锁的检测和解除
与innodb或者其他事务存储引擎的全局死锁检测机制都类似,在TDSQL XA的网关中,我们使用定期检测结合语句超时触发检测。在网关中触发全局死锁检测后,全局死锁检测的具体做法是:

  1. 从每个后端set上查询 innodb_trx(加列xid) 和innodb_lock_waits表,得到每个set上面的事务分支的等待关系图。由于这些事务分支各自所属的全局事务也有相同的等待关系,所以可以得到每个set上的全局事务等待关系图。
  2. 合并全局事务的等待关系图得到GTG。
  3. 在GTG中寻找环路,kill掉环路当中某个连接,给它的客户端返回死锁错误。

在原始的MySQL 中, information_schema.innodb_trx表并没有XA事务ID列,但是为了第#1步从每个set的事务分支等待关系推出全局事务等待关系,就必须修改mysql和innodb的代码给这个表加上这一列。另外还需要对该表做其他一些改造方可正确完成全局死锁检测。
4.结论
全局死锁检测机制是TDSQL XA的重要组成部分:实际测试中可以看出没有全局死锁检测的话TDSQL XA在大量并发负载的情况下很容易产生很多因为全局死锁而阻塞的事务。由于TDSQL XA并不会非常频繁地执行死锁检测,其运行开销可以忽略不计。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
6月前
|
存储 Java Nacos
Seata常见问题之xa模式出现错误xid is not valid如何解决
Seata 是一个开源的分布式事务解决方案,旨在提供高效且简单的事务协调机制,以解决微服务架构下跨服务调用(分布式场景)的一致性问题。以下是Seata常见问题的一个合集
192 4
|
6月前
|
NoSQL Java 数据库
Seata常见问题之xa模式下插入一条数据再更新这条数据会报错如何解决
Seata 是一个开源的分布式事务解决方案,旨在提供高效且简单的事务协调机制,以解决微服务架构下跨服务调用(分布式场景)的一致性问题。以下是Seata常见问题的一个合集
188 2
|
6月前
|
Java 数据库连接 API
seata回滚问题之全局异常如何解决
Seata是一款开源的分布式事务解决方案,旨在提供高效且无缝的分布式事务服务;在集成和使用Seata过程中,开发者可能会遇到不同的异常问题,本合集针对Seata常见异常进行系统整理,为开发者提供详细的问题分析和解决方案,助力高效解决分布式事务中的难题。
908 8
|
6月前
|
SQL Oracle 关系型数据库
MySQL事务 【事务操作丨事务四大特性丨事务隔离级别丨事务原理】
MySQL事务 【事务操作丨事务四大特性丨事务隔离级别丨事务原理】
99 0
|
SQL 存储 Oracle
19 PostgreSQL 锁类型,锁模式,锁冲突,死锁检测的介绍|学习笔记
快速学习19 PostgreSQL 锁类型,锁模式,锁冲突,死锁检测的介绍
19 PostgreSQL 锁类型,锁模式,锁冲突,死锁检测的介绍|学习笔记
|
SQL 关系型数据库 MySQL
MySQL 事务原理:事务概述、隔离级别、MVCC-2
MySQL 事务原理:事务概述、隔离级别、MVCC
75 0
|
SQL 存储 关系型数据库
MySQL 事务原理:事务概述、隔离级别、MVCC-1
MySQL 事务原理:事务概述、隔离级别、MVCC
83 0
|
SQL 关系型数据库 数据库
Seata中的四种不同的事务模式之一XA
Seata中的四种不同的事务模式XA篇
103 0
|
SQL 存储 关系型数据库
一文搞懂MySQL事务的隔离性如何实现|MVCC
MySQL有ACID四大特性,本文着重讲解MySQL不同事务之间的隔离性的概念,以及MySQL如何实现隔离性。下面先罗列一下MySQL的四种事务隔离级别,以及不同隔离级别可能会存在的问题。
350 0
一文搞懂MySQL事务的隔离性如何实现|MVCC
|
SQL 安全 算法
精通Java事务编程(7)-可串行化隔离级别之两阶段锁定(2PL,two-phase locking)
近30年,DB只有一种广泛使用的串行化算法:两阶段加锁 1 2PL不是2PC 请注意,虽然两阶段锁定(2PL)听起来非常类似于两阶段提交(2PC),但是完全不同概念
223 0