JeecgBoot icon indicating copy to clipboard operation
JeecgBoot copied to clipboard

分布式事务不生效的问题,求助

Open mutudu95 opened this issue 1 year ago • 1 comments

版本号:

3.7.0

问题描述:

分布式事务

错误截图:

image image

子模块数据库更新了,主模块抛出了异常,子模块的数据并没有回滚 image 这个是我seata的配置

下面这个是我主模块模拟的异常 image 下面是我子模块的代码 image

麻烦有大佬帮我分析下

友情提示:

  • 未按格式要求发帖、描述过于简单的,会被直接删掉;
  • 描述问题请图文并茂,方便我们理解并快速定位问题;
  • 如果使用的不是master,请说明你使用的分支;

mutudu95 avatar Aug 06 '24 10:08 mutudu95

没看出来你两张图片的代码之间的关联关系, 另外需要提醒一点就是主模块的代码需要发起事务才行,主模块的事务传播到子模块中去才行。不能是光子模块有事务,而主模块却没有事务,那样就变成了普通的事务了,而不是分布式事务

EightMonth avatar Aug 16 '24 08:08 EightMonth

主模块是发起了事务,而且主模块的事务id 子模块也能拿到,但是我主模块抛出异常后,子模块的数据并没有回滚

mutudu95 avatar Aug 19 '24 05:08 mutudu95

由于你提供的代码片段不具备参考性,很难帮你分析问题,请参考jeecgboot的中的分布式事务示例代码,我已测试过,是可以正常回滚的 image image

EightMonth avatar Aug 19 '24 07:08 EightMonth

我使用的是seata v1.7.0,jeecgboot 3.7.3, oracle 19c 亲测按照如下修改可以主事务,分支事务一起回滚 参考文章微服务项目中使用seata,以nacos作为配置中心,很详细

1、pom.xml添加依赖

<dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
            <version>3.5.2</version>
        </dependency>

        <dependency>
            <groupId>com.oracle.database.jdbc</groupId>
            <artifactId>ojdbc8</artifactId>
            <version>19.3.0.0</version>
        </dependency>

2、依次按照下面的方式修改三个服务的application.yml

#logging:
#  level:
#    root: DEBUG
server:
  port: 5002
spring:
  application:
    name: seata-account
  main:
    allow-bean-definition-overriding: true
  autoconfigure:
#    exclude: com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration
  datasource:
    dynamic:
      primary: account # 设置默认数据源为 'master'
      strict: false # 严格模式,如果找不到数据源是否报错
      datasource:
        account:
          url: jdbc:oracle:thin:@localhost:1525/ORCLPDB1
          username: seata_account
          password: 123456
          driver-class-name: oracle.jdbc.OracleDriver
      seata: true
  redis:
    database: 0
    host: 127.0.0.1
    port: 6379
    password: 123456
seata:
  enable-auto-data-source-proxy: false
  service:
    grouplist:
      default: 127.0.0.1:8091
    vgroup-mapping:
      springboot-seata-group: default
  # seata 事务组编号 用于TC集群名
  tx-service-group: springboot-seata-group

3、修改reduceBalance返回值 SeataAccountController.java

@PostMapping("/reduceBalance")
    public Result reduceBalance(Long userId, BigDecimal amount) {
        accountService.reduceBalance(userId, amount);
        return Result.ok();
    }

AccountClient.java

/**
   *  扣减余额
   * @param userId
   * @param amount
   * @return
   */
  @PostMapping("/test/seata/account/reduceBalance")
  Result reduceBalance(@RequestParam("userId") Long userId, @RequestParam("amount") BigDecimal amount);

SeataOrderServiceImpl.java

// 扣减库存并计算总价
        BigDecimal amount = productClient.reduceStock(productId, count);
        // 扣减余额
        Result result = accountClient.reduceBalance(userId, amount);
        // feign响应被二次封装,判断使主事务回滚
//        JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(str));
        if (result == null || !result.isSuccess()) {
            throw new RuntimeException();
        }

另外如果使用oracle数据库,undo_log建表语句如下:

CREATE TABLE undo_log (
                          id NUMBER(20) GENERATED BY DEFAULT ON NULL AS IDENTITY (START WITH 1 INCREMENT BY 1) NOT NULL,
                          branch_id NUMBER(20) NOT NULL,
                          xid VARCHAR2(100) NOT NULL,
                          context VARCHAR2(128) NOT NULL,
                          rollback_info BLOB NOT NULL,
                          log_status NUMBER(11) NOT NULL,
                          log_created TIMESTAMP(6) NOT NULL,
                          log_modified TIMESTAMP(6) NOT NULL,
                          PRIMARY KEY (id)
);

ALTER TABLE undo_log ADD CONSTRAINT ux_undo_log UNIQUE (xid, branch_id);

CREATE SEQUENCE UNDO_LOG_SEQ START WITH 1 INCREMENT BY 1;

还有可能遇到这个问题seata1.7.1 oracle oracle.sql.TIMESTAMP 类型数据序列化问题

4ugust1 avatar Aug 01 '25 01:08 4ugust1