文档

常见问题

更新时间:

本文主要介绍在操作分布式事务过程中的常见问题。

SOFAStack 是否可以部署在虚拟机、物理机上?

可以,SOFAStack 部署支持物理机、虚机机 VM。

SOFAStack 当前是否只支持阿里云飞天 ACK?

SOFAStack 部署支持多云异构、目前支持华为云、开源 Openstack 等。

分布式事务支持哪些数据库?

目前支持 MySQL、Oracle、RDS MySQL、PostgreSQL 等主流数据库。

分布式事务是否支持 VPC 私有云部署?

支持,如有需要,请咨询售后技术支持。

在分布式事务服务挂掉的情况下,事务是否能正常回滚?

分布式事务的服务端会记录下事务的状态并持久化,即使服务挂掉,在服务重新启动后,事务仍然能够正常回滚。

建表时,是否可以使用 SQL 的关键字作为列的名称?

不可以,建表时列名不能使用 SQL 的关键字,如 DESC、TABLE 等。

接入分布式事务时需要依赖什么?

如果您使用的是数据访问代理中的分布式事务,因为数据访问代理和分布式事务已经深度集成,部署时是不需要任何依赖的,仅需一行事务开启 SQL 语句就能开启事务。

如果您是基于 SDK 方式使用分布式事务,就需要在引入的分布式事务 SDK 的 pom.xml 中加入相关依赖,详见开发指南。

开通分布式事务之后,SOFABoot、Dubbo、消息队列、数据访问代理、RDS、MySQL、Oracle、OceanBase 能否都加入分布式事务?

可以,分布式事务已经打通了 SOFABoot、Dubbo、消息队列、数据访问代理、RDS、MySQL、Oracle、OceanBase 之间的事务。

服务 A 调用服务 B,服务 A 上加了分布式事务并开启事务注解,服务 B 没有注解,那么 A 和 B 是否在同一个分布式事务中?

服务 A 和 B 在一个事务中。只要服务 A 的函数上加入了分布式事务的注解,那么服务 A 注解函数下面所有的被调用的服务及其子调用的服务都会加入到这个服务 A 的事务中。

分布式事务是否支持多机房高可用?

分布式事务支持同城、异地多活,高可用。当一个机房由于断网、停电等突发状况造成全机房不可用时,分布式事务能切换到备用机房继续提供服务。

如何判断分布式事务 SDK 与事务云服务的网络连接是否正常?

在事务云服务上执行 netstat -an | grep 14200,看是否存在 TCP 连接。如果存在 TCP 连接,说明事务云服务启动正常;否则说明事务云服务已宕机或者网络已中断。

分布式事务 SDK 与事务云服务网络连接正常,但是通信失败,是什么原因?

TCP 连接正常,说明事务云服务启动正常。

分布式事务 SDK 与事务云服务通信返回失败消息,说明 SDK 发送给事务云服务的消息违反某些约束条件,可以根据事务 ID 在 dtx-rpc.log 中查询事务云服务返回的具体失败信息。

如何查看分布式事务的日志?

分布式事务的事务日志存放路径为 ${user.home}/logs/dtx-xxx.log,其中 ${user.home} 为启动分布式事务 SDK 的用户账户的根目录。不同的日志文件,打印的日志内容也不同,具体如下:

  • dtx-client.log 打印 SDK 启动和所有事务执行情况的日志。

  • dtx-rpc.log 打印 SDK 与分布式事务服务端的所有通信信息。

  • dtx-parser.log 打印 SQL 语句语法解析日志。

  • dtx-rm.log 打印所有参与者(TCC、FMT)的二阶段执行日志。

  • dtx-datasource.log 打印 FMT 模式下的事务执行日志。

查看日志时,可以按照分布式事务的事务 ID 去查看这个事务在该 SDK 都操作了哪些资源及其提交和回滚情况。

分布式事务 TCC @TwoPhaseBusinessAction 放到接口的实现类上是否有效?

没有效果,不能放到实现类上,必须放在接口上。

   public interface UserFacade{

        @TwoPhaseBusinessAction(name ="sendMessage", commitMethod="commit", rollbackMethod ="cancel")
        public boolean sendMessage(final BusinessActionContext businessActionContext,@BusinessActionContextParameter(paramName ="userId")String userId);

        public boolean commit(final BusinessActionContext businessActionContext);

        public boolean cancel(final BusinessActionContext businessActionContext);

    }

如何传递参数给二阶段方法 Commit/Cancel?

可以通过以下任一方式:

  • 使用额外的存储来记录 txid 和业务数据的关系。

  • 使用 BusinessActionContext 传递。

    说明

    不能通过直接设置 BusinessActionContext 来传递,此种方式不会被保存。需要使用@BusinessActionContextParameter 注解。

DTX 发起方和参与方同属一个应用,能否不使用 RPC?

可以在参与方接口上添加 @InjvmRemoting 注解,这样发起方去调用参与方就是 JVM 内调用。而且这种情况下,DTX 服务端来远程调用二阶段方法也不会通过注册中心,而是 DTX 自闭环寻址处理。

以 TCC 模式为例:

 // 注解InjvmRemoting用于当发起方与参与方是同一个应用,也就是说参与方不需要被其他应用通过注册中心寻址来进行RPC调用
    @InjvmRemoting
    public interface AcctDepositTccService{

        /**
         * <p>
         * 贷记记账接口 TCC模式
         * </p>
         *
         * <p>
         * 结合账户的余额方向来对账户的资金进行流入 or 流出操作
         * </p>
         *
         * @param accountTransRequest   请求对象参数,详情请见{@link AccountTransRequest}
         * @param businessActionContext dtx框架中请求的上下文信息,框架级别参数,调用者不需传递,由dtx自动注入。
         * @return AccountTransResult 交易处理结果
         */
        @TwoPhaseBusinessAction(name ="creditAction", commitMethod ="commit", rollbackMethod ="rollback", antiSuspend =true)
        public AccountTransResult credit(AccountTransRequest accountTransRequest,@ShardingKeyString accountNo,
                BusinessActionContext businessActionContext);

        /**
         * 二阶段提交
         *
         * @param businessActionContext xts上下文
         * @return TwoPhaseResult#isSuccess() 是否成功,true-成功,false-失败
         */
        public boolean commit(BusinessActionContext businessActionContext);

        /**
         * 二阶段回滚
         *
         * @param businessActionContext xts上下文
         * @return TwoPhaseResult#isSuccess() 是否成功,true-成功,false-失败
         */
        public boolean rollback(BusinessActionContext businessActionContext);

    }

DTX 创建事务分支时出现“Data too long for column ‘log_Info’”报错

问题现象

DTX 创建事务分支报错:Data too long for column ‘log_Info’。

问题原因

业务代码更新的数据库内容太多,超过了 log_info 的最大长度。

解决方案

需要优化业务代码,最好是业务优化 SQL 逻辑,或者修改表中该字段的类型,比如 LONGBLOB

客户端启动分布式事务时出现“invoke dtx-server to create Activity failed”报错

问题现象

  • 客户端启动 DTX 失败,报错:DTX-037: invoke dtx-server to create Activity failed.

  • 在 DTX server 端,实际错误码为 error code: 101,如下图所示:代码

  • 在控制台转换字符编码,可以看到实际的错误是:数据源最大连接数已满,并且在超时时间范围内没有新的连接释放,如下图所示:控制台信息

问题原因

DTX server 与 DTX DB 的数据库连接数设置成了 2。

解决方案

如有需要,您可以咨询售后技术支持。

事务进行过程中发生“DTX-036 activity record is not exist”报错

问题现象

  • 报错:DTX-036 activity record is not exist。

  • 详细的错误信息下图所示:代码2#

问题原因

根据上图所示的错误信息,事务的请求者和事务的参与者的 instance ID 不匹配。例如事务 ds:jdbc:mysql://10.10.29.212:XXXX配置错误,instance ID 配置成了 00000X,使得事务请求方 instance ID = 00000X。而事务的真实 instance ID 其实是 8PCDDO6YXXXX

解决方案

排查事务的参与方的 application.properties 配置,确保事务的请求者和事务的参与者的 instance ID 匹配。

DTX 2.2.1 版本,支持 Saga 模式吗?

不支持,如有需要,请咨询售后科技支持。

分布式事务二阶段请求未执行

问题现象

使用时出现报错:“com.alipay.dtx.common.exception.DtxException:DTX-032:TCC prepare menthod must have a parameter who's type isBusinessActionContext”。

启动时出现报错:“DTX-302:initdtx-servers' tcp long-conections failed”。

问题原因

  • dtxserver 未发起二阶段请求。

  • 客户端收到二阶段请求但执行失败。

解决方案

针对以上两种情况有两种解决方案:

  • dtxserver 未发起二阶段请求

    登录 dtxserver 机器,在 /home/admin/logs/dtxserver/dtx-remote.log 日志中搜索事务 ID,查找该异常事务相关信息。

    • 若未找到该异常事务的恢复日志,说明该事务的二阶段任务未开始执行,可能是未正常执行或出现事务积压,需重新发起事务。

    • 若找到该异常事务的恢复日志,说明执行过程出错,在 dtx-remote.logcommen-error.log 中查看出错原因,在改进后重新发起任务。

  • 客户端收到二阶段请求但执行失败

    1. 查询客户端是否收到二阶段的请求。

      在客户端 /home/admin/logs/dtx/dtx-rpc.log 日志中搜索事务 ID,若找到“BranchCommitRequest”或“BranchrollbackRequest”的消息,说明客户端收到了二阶段请求。

    2. 查看二阶段请求是否成功执行。

      /home/admin/logs/dtx/dtx-rm.log 日志中搜索事务 ID,若找到“branch commit result”或“branch rollback result”相关内容,且返回结果为 true ,则表示执行成功;反之,执行失败,根据报错信息排查执行失败的原因,在改进后回滚事务重新执行。