ShardingSphere Narayana XA 事务不回滚问题定位

ShardingSphere Narayana XA 事务不回滚问题定位

问题背景

用户反馈,在使用 ShardingSphere + Narayana 执行 XA 事务时,发生报错:java.sql.SQLException: javax.transaction.RollbackException: TransactionImple.enlistResource - ARJUNA016064: The transaction is in an invalid state!
这个报错的含义简单来说就是这个事务已经在其他地方被标记成只可回滚了,不能再进行后续其他的操作。报错信息如下:

Caused by: java.sql.SQLException: javax.transaction.RollbackException: TransactionImple.enlistResource - ARJUNA016064: The transaction is in an invalid state!at org.apache.shardingsphere.transaction.xa.XAShardingSphereTransactionManager.getConnection(XAShardingSphereTransactionManager.java:101)at org.apache.shardingsphere.transaction.ConnectionTransaction.getConnection(ConnectionTransaction.java:102)at org.apache.shardingsphere.driver.jdbc.core.connection.DriverDatabaseConnectionManager.createConnection(DriverDatabaseConnectionManager
.java:416)at org.apache.shardingsphere.driver.jdbc.core.connection.DriverDatabaseConnectionManager.createConnections(DriverDatabaseConnectionManage
r.java:383)at org.apache.shardingsphere.driver.jdbc.core.connection.DriverDatabaseConnectionManager.getConnections(DriverDatabaseConnectionManager.j
ava:357)at org.apache.shardingsphere.driver.jdbc.core.connection.DriverDatabaseConnectionManager.getConnections(DriverDatabaseConnectionManager.j
ava:338)at org.apache.shardingsphere.infra.executor.sql.prepare.driver.DriverExecutionPrepareEngine.group(DriverExecutionPrepareEngine.java:89)at org.apache.shardingsphere.infra.executor.sql.prepare.AbstractExecutionPrepareEngine.prepare(AbstractExecutionPrepareEngine.java:73)at org.apache.shardingsphere.infra.executor.sql.prepare.AbstractExecutionPrepareEngine.prepare(AbstractExecutionPrepareEngine.java:61)at org.apache.shardingsphere.driver.jdbc.core.statement.ShardingSpherePreparedStatement.createExecutionGroupContext(ShardingSpherePrepare
dStatement.java:764)at org.apache.shardingsphere.driver.jdbc.core.statement.ShardingSpherePreparedStatement.useDriverToExecute(ShardingSpherePreparedStatement.java:717)at org.apache.shardingsphere.driver.jdbc.core.statement.ShardingSpherePreparedStatement.executeWithExecutionContexts(ShardingSpherePreparedStatement.java:658)at org.apache.shardingsphere.driver.jdbc.core.statement.ShardingSpherePreparedStatement.execute(ShardingSpherePreparedStatement.java:631)at org.apache.ibatis.executor.statement.PreparedStatementHandler.update(PreparedStatementHandler.java:44)at org.apache.ibatis.executor.statement.RoutingStatementHandler.update(RoutingStatementHandler.java:69)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

问题分析

观察日志里有调用 setRollbackOnly 方法的日志,通过查看 setRollbackOnly 方法的调用链路,再结合报错是在 getConnection 时报的,那么调用 setRollbackOnly 方法应该发生在getConnection之前,极有可能是 enlistResource 地方报的。
![[img-20240123115238.png]]

通过查看 enlistResource 方法的逻辑,注释里写的是 xa start 语句没执行成功时会调用 markRollbackOnly 标识事务只可回滚。
![[img-20240123115315.png]]

开启 narayana trace 日志。
[[sf-xa-log.log]]
看日志 43 行
发现 enlistResource 操作前后有一个可疑日志。

-- xid unset
[2024-01-23 11:10:08,001] [com.arjuna.ats.internal.jta.resources.arjunacore.XAResourceRecord],[<init>],[XNIO-1 task-1],[INFO],[202401231110026b2ab483e6ae4d43bd055383c3d57d30-0],[],[XAResourceRecord.XAResourceRecord ( ARJUNA016100: Xid unset, org.apache.shardingsphere.transaction.xa.spi.SingleXAResource@5c6c9ab9 ), record id=0:ffff0acf077d:837d:65af2e0d:4]|[TID:323d025cef50474aa2ffdd4dc341a97a.316543.17059794010875173]|-- set rollback only
[2024-01-23 11:10:08,357],[eciqs-core],[com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple],[setRollbackOnly],[XNIO-1 task-1],[INFO],[202401231110026b2ab483e6ae4d43bd055383c3d57d30-0],[],[TransactionImple.setRollbackOnly]|[TID:323d025cef50474aa2ffdd4dc341a97a.316543.17059794010875173]|-- 后续自动执行回滚操作日志
[2024-01-23 11:10:09,081],[eciqs-core],[com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction],[rollback],[XNIO-1 task-1],[INFO],[202401231110026b2ab483e6ae4d43bd055383c3d57d30-0],[],[BaseTransaction.rollback]|[TID:323d025cef50474aa2ffdd4dc341a97a.316543.17059794010875173]|[2024-01-23 11:10:09,081],[eciqs-core],[com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple],[rollbackAndDisassociate],[XNIO-1 task-1],[INFO],[202401231110026b2ab483e6ae4d43bd055383c3d57d30-0],[],[TransactionImple.rollbackAndDisassociate]|[TID:323d025cef50474aa2ffdd4dc341a97a.316543.17059794010875173]|[2024-01-23 11:10:09,081],[eciqs-core],[com.arjuna.ats.arjuna.coordinator.BasicAction],[Abort],[XNIO-1 task-1],[INFO],[202401231110026b2ab483e6ae4d43bd055383c3d57d30-0],[],[BasicAction::Abort() for action-id 0:ffff0acf077d:837d:65af2e0d:2]|[TID:323d025cef50474aa2ffdd4dc341a97a.316543.17059794010875173]|

日志显示的是 ARJUNA016100: Xid unset,正常日志应该如下:

2024-01-23 11:48:33.341 [main] TRACE com.arjuna.ats.jta - XAResourceRecord.XAResourceRecord ( < formatId=131077, gtrid_length=29, bqual_length=36, tx_uid=0:ffff7f000101:90ab:65af3711:2, node_name=1, branch_uid=0:ffff7f000101:90ab:65af3711:3, subordinatenodename=null, eis_name=0 >, com.zc.transaction.xa.SingleXACtrlResource@1fc793c2 ), record id=0:ffff7f000101:90ab:65af3711:4

ARJUNA016100: Xid unset

后续分析为什么会出现ARJUNA016100: Xid unset 异常。
搜索 ARJUNA016100 错误码,是在 xidImple.toString 里调用的。

原因,比如一个 xa 事务涉及两个 xa resources,在执行第一个 resource enlist 时候,由于 xid 有问题,start xid 在 mysql 上执行失败了,然后 Naryana 自己调用 com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple#setRollbackOnly 方法将当前全局事务状态设置为 ActionStatus.ABORT_ONLY 状态。
那么当事务内第二个 xa resource 执行 enlist resource 操作时,由于当前事务已经标记为只回滚,所以执行报错。也就是最开始日志里报的错:java.sql.SQLException: javax.transaction.RollbackException: TransactionImple.enlistResource - ARJUNA016064: The transaction is in an invalid state!
相关代码如下:

public boolean enlistResource(XAResource xaRes, Object[] params)  throws RollbackException, IllegalStateException,  jakarta.transaction.SystemException  
{  // ...int status = getStatus();  switch (status)  {    // jakarta.transaction.Status.STATUS_MARKED_ROLLBACK 对应上面的 ActionStatus.ABORT_ONLY 状态,报错 invalid。case jakarta.transaction.Status.STATUS_MARKED_ROLLBACK:  throw new RollbackException(  "TransactionImple.enlistResource - " + jtaLogger.i18NLogger.get_transaction_arjunacore_invalidstate() );  case jakarta.transaction.Status.STATUS_ACTIVE:  break;  default:  throw new IllegalStateException( jtaLogger.i18NLogger.get_transaction_arjunacore_inactive() );  }

当出现报错后,后续 narayana 会自动执行回滚操作,参考 narayana 日志。

XID 为空原因

为什么 xid 会为空。
这个 xid 为空的报错是在 com.arjuna.ats.jta.xa.XidImple#toString 方法中报的,实际上是 com.arjuna.ats.jta.xa.XidImple#_theXid 为空导致。
在 XidImple 所有构造方法中打断点,看创建 xid 过程,哪里导致 _theXid 属性为空。

public XidImple(Uid id, boolean branch, Integer eisName) {  try {  // 可以看到如果创建 _theXid 失败,则捕获了异常_theXid = XATxConverter.getXid(id, branch, eisName);  } catch (Exception e) {  _theXid = null;  jtaLogger.i18NLogger.warn_cant_create_xid_of_branch(id, branch, eisName, e);  // abort or throw exception?  }  hashCode = getHash(_theXid);  
}

后续 debug 看日常信息,发现 xid 为 null,异常信息里有 ARJUNA016111: The node identifier cannot be null 信息,这个明显是没有读取到 jbossts.xml 配置文件导致的报错。

后续通过修改 Transaction Rule, 尝试刷新配置,发现错误依然存在。Debug 发现没有读取到 jbossts.xml 配置文件导致。

使用 arthas 查看应用里 ShardingSphere-JDBC 的 TransactionRule 属性正常,说明 Rule 正常刷新。
但是 arthas 查看 ObjectStoreEnvironmentBean 里的 jdbc 属性为空,说明没有读取到 jbossts.xml 配置文件。

sc -d *TransactionRule
vmtool --action getInstances -c 368239c8 --className org.apache.shardingsphere.transaction.rule.TransactionRule --limit 10 -x 2sc -d *ObjectStoreEnvironmentBean
vmtool --action getInstances -c 368239c8 --className com.arjuna.ats.arjuna.common.ObjectStoreEnvironmentBean --limit 10 -x 2

然后 Debug Narayana 启动逻辑,发现应用目录下并没有 jbossts.xml 配置文件。咨询用户发现应用系统每次部署启动阶段会清除目录下的所有文件,导致读取失败。

问题解决

用于该应用在启动阶段会清理目录下的配置文件,将 jbossts.xml 放到其他 Narayana 可以读取到的目录下即可。

参考

https://u01f1kqxrl.feishu.cn/wiki/YD11wifTiit5RgkmRINcDTxAnmJ

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/712175.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数字后端——DEF文件格式

文章目录 MACRO的不同orientationDEF中在macro orientation定义前需要留空格 MACRO的不同orientation DEF中在macro orientation定义前需要留空格 像下图中这种方向和分号之间没有空格的情况&#xff0c;就是有问题的格式。

C语言清空文件夹、C语言判断文件夹下的文件夹是否存在,如果存在就清空,如果不存在则建立

代码解法不唯一&#xff0c;请在评论区留下你的实现方式和想法&#xff0c;我会将好的解法更新到文章中&#xff01;&#xff01; 要在C语言中判断文件夹下的文件夹是否存在&#xff0c;如果存在就清空&#xff0c;如果不存在则建立&#xff0c;需要使用C标准库中的系统调用或…

数学学习与研究杂志社《数学学习与研究》杂志社编辑部2023年第29期目录

考试研究 提高高三数学二轮复习质量的思考与实践 佘淮青; 2-4 提升高三数学复习质量的策略探究 王飞; 5-7 核心素养背景下的高中数学命题策略研究 陈明发; 8-10 提升中考数学复习课的有效性研讨 韩兴宏; 11-13 中学教学方法《数学学习与研究》投稿&#xff1a;…

将c、c++变为python

1.编写cpp文件 #include "pycpp.h" #include <iostream>using namespace std;PyCpp::PyCpp(){}void PyCpp::sayHello(int a){cout << "Hello Python, I am C."<<a << endl; }2.编写头文件&#xff08;声明变量&#xff09; clas…

SpringBoot之自定义Redis缓存key的生成策略配置

SpringBoot之自定义Redis缓存key的生成策略配置 文章目录 SpringBoot之自定义Redis缓存key的生成策略配置1. SpringBoot版本2. Redis缓存配置类 自定义缓存key生成策略&#xff1b;key与value的序列化&#xff1b;key过期配置管理器 1. SpringBoot版本 <parent><group…

pyuic生成py文件到指定文件夹

pyuic生成py文件到指定文件夹 关于如何在pycharm配置外部工具的方法这里不做赘述&#xff0c;本文主要说明&#xff0c;如何利用pyuic将ui文件生成到指定的项目目录中。 前提条件&#xff1a;已配置的pyuic工具可以正常使用生成文件到目录中。 一、打开外部工具配置页面 打开…

如何用Python检查时间序列数据是否平稳?

时间序列数据通常以其时间性质为特征。这种时间性质为数据增加了趋势或季节性&#xff0c;使其与时间序列分析和预测兼容。如果时间序列数据不随时间变化或没有时间结构&#xff0c;则称其为静态数据。因此&#xff0c;检查数据是否平稳是非常必要的。在时间序列预测中&#xf…

用HTML5的<canvas>元素实现刮刮乐游戏

用HTML5的<canvas>元素实现刮刮乐 用HTML5的<canvas>元素实现刮刮乐&#xff0c;要求&#xff1a;将上面的“图层”的图像可用鼠标刮去&#xff0c;露出下面的“图层”的图像。 示例从简单到复杂。 简单示例 准备两张图像&#xff0c;我这里上面的图像top_imag…

node express实现Excel文档转json文件

有些场景我们需要将Excel文档中的内容抽取出来生成别的文件&#xff0c;作为一个前端&#xff0c;服务框架最应该熟悉的就是node了&#xff0c;以下是基于多语言转换实现代码&#xff0c;看明白原理自己改一改就能用了 1.安装node环境 2.创建一个文件夹&#xff0c;文件夹中创建…

7、Redis-事务、持久化、内存淘汰机制和过期key处理

目录 一、事务 二、持久化 三、内存淘汰机制 四、过期key处理 一、事务 Redis的事务本质上就是一个批量执行命令的操作。分为三个步骤&#xff1a; 开始事务&#xff1a;multi命令入队&#xff1a;正常输入命令即可执行事务&#xff08;依次执行命令&#xff09;&#xf…

掌握java模板方法模式,提升代码复用与扩展的艺术

Java 模板方法模式是一种行为型设计模式&#xff0c;它定义了一个算法的骨架&#xff0c;并将一些步骤延迟到子类中实现。模板方法模式使得子类可以在不改变算法结构的情况下重定义算法中的某些步骤。 使用场景 算法骨架固定&#xff1a;如果一个算法的基本结构已经固定&#…

跨专业考研难度大吗?听听过来人的真实经历

在考研的大潮中&#xff0c;跨专业考研成为了一个不可忽视的现象。许多考生因为对原专业失去兴趣、追求职业梦想或其他原因&#xff0c;选择了跨专业报考。那么&#xff0c;跨专业考研的难度究竟有多大呢&#xff1f;今天&#xff0c;我们就来聊聊这个话题&#xff0c;听听过来…

不是我吹,这8道HashMap面试题让你面试时对答如流

前言 又到了一年一度的金三银四面试季&#xff0c;我们拿着自己的面试秘籍去面试&#xff0c;但是面试官的问题五花八门&#xff0c;让我们摸不清他们的套路。今天我就总结了面试时必问的hashmap面试题&#xff0c;无论面试官怎么问&#xff0c;我们都对答如流。 另外本人整理了…

java小记(2)

IS-A&#xff1a;类的父子继承关系。 default&#xff1a;关键字&#xff0c;与Java中的public&#xff0c;private等关键字一样&#xff0c;都属于修饰符关键字&#xff0c;可以用来修饰属性、方法以及类&#xff0c;但是default一般用来修饰接口中的方法。 接口与抽象类的区…

代码随想录算法训练营第二十四天 | 77. 组合

回溯算法理论基础 https://programmercarl.com/%E5%9B%9E%E6%BA%AF%E7%AE%97%E6%B3%95%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html 回溯法也可以叫做回溯搜索法&#xff0c;它是一种搜索的方式。 回溯是递归的副产品&#xff0c;只要有递归就会有回溯。 回溯法并不是什么高效的…

马斯克正式起诉OpenAI和奥特曼!

就在刚刚&#xff0c;马斯克闹出来一件大事——正式起诉OpenAI和Sam Altman&#xff0c;并要求OpenAI 恢复开源GPT-4等模型&#xff01; 众所周知&#xff0c;马斯克这两年一只在推特上指责 OpenAI是CloseAI(不开源)&#xff0c;但都只是停留在口头上。 而这次马斯克动了真格。…

nginx if 指令

目录 nginx if 指令直接判断变量判断是否等于字符串判断变量是否匹配正则表达式文件及目录判断示例1&#xff1a;判断index.html是否存在示例2&#xff1a;判断URL中是否存在某个参数Parameter示例3&#xff1a;判断URI中是否为某个特定路径示例4&#xff1a;开放白名单内的功能…

从0开始python学习-53.python中flask创建简单接口

目录 1. 创建一个简单的请求,没有写方法时默认为get 2. 创建一个get请求 3. 创建一个post请求&#xff0c;默认可以使用params和表单传参 4. 带有参数的post请求 1. 创建一个简单的请求,没有写方法时默认为get from flask import Flask, request# 初始化一个flask的对象 ap…

RK3566 linux iperf网络测试

一、开发环境 系统:buildroot&#xff1b; 在Linux目标板和Windows PC上运行iperf进行测试&#xff1b; 二、调试 1、查询目标板上的iperf 使用终端助手连接目标板&#xff0c;然后输入命令查询iperf的版本&#xff1a; rootrk3566-buildroot:~# iperf -v iperf version …

图数据库 之 Neo4j - 应用场景3 - 知识图谱(8)

背景 知识图谱的复杂性:知识图谱通常包含大量的实体、关系和属性,以及它们之间的复杂关联。传统的关系型数据库在处理这种复杂性时可能面临性能和灵活性的挑战。 图数据库的优势:图数据库是一种专门用于存储和处理图结构数据的数据库。它们使用节点和边来表示实体和关系,并…