SpringCloudAlibaba+Seata整合Shardingsphere分库分表后分布式事务数据库回滚错乱,有的数据库回滚成功,有的回滚失败问题解决

版本:

 SpringCloudAlibaba2021.0.5

 Seata1.6.1

 Sharding4.1.1

其余SpringCloudAlibaba的版本选择看这里:

https://sca.aliyun.com/zh-cn/docs/2021.0.5.0/overview/version-explain

SpringCloudAlibaba脚手架看这里:

https://start.aliyun.com/

具体的理论概念可以去Shardingsphere先过一遍https://shardingsphere.apache.org/document/current/cn/overview/

依赖:

<dependency>
   <groupId>org.apache.shardingsphere</groupId>
   <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
   <version>4.1.1</version>
</dependency>

<!-- 使用BASE事务时,需要引入此模块 -->
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-transaction-base-seata-at</artifactId>
    <version>4.1.1</version>
</dependency>

加入依赖后必须要在resources下加入seata.conf文件,里面的配置如下:

client {
    ## 应用唯一id
    application.id=order-service
    ## 所属事务组
    transaction.service.group=sharding_tx_group
}

application.yml配置:

spring:
  #sharding
  shardingsphere:
    datasource:
      names: m1,m2     #指定多个虚拟数据库名称
      m1:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/seata-order?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true&useInformationSchema=false
        username: admin
        password: admin
      m2:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/seata-order-slave?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true&useInformationSchema=false
        username: admin
        password: admin
    #分库分表配置
    sharding:
      tables:
        b_order: #指定一个虚拟表名称
          actual-data-nodes: m$->{1..2}.b_order_$->{1..2}     #数据库.表名
          key-generator: #主键自动生成策略
            column: id
            type: SNOWFLAKE     #使用雪花ID
          table-strategy: #分表策略
            inline: #inline策略
              sharding-column: id      #分表字段
              algorithm-expression: b_order_$->{id % 2 + 1}    #分表算法,求模取余算法
          database-strategy: #分库策略
            inline: #inline策略
              sharding-column: product_id     #分库字段
              algorithm-expression: m$->{product_id % 2 + 1}    #分库算法,求模取余算法
    props:
      sql:
        show: true
#seata配置
seata:
  enabled: true
  application-id: ccxi-order
  tx-service-group: sharding_tx_group
  service:
    vgroup-mapping:
      sharding_tx_group: default
  registry:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      namespace: public
      group: SEATA_GROUP
      application: seata-server
      username: nacos #未开启nacos鉴权不用账号密码
      password: nacos
使用时只需要在调用方的方法上加上两个注解就阔以了,以下是我的demo示例:
//A服务加上以上注解,seata的全局事务注解就不用加了,因为已经与Shrding集成了
@Transactional
@ShardingTransactionType(TransactionType.BASE)  // 支持TransactionType.LOCAL, TransactionType.XA, TransactionType.BASE
public List<BOrder> submitOrder3(List<BOrder> order) {
   saveBatch(order);
   //这里发起调用B服务,B服务方法上不必加事务注解也会一起回滚
   //不过本人建议最好在B方法上加seata的@GlobalTransactional全局事务注解
   //这样B服务方法单独运行时会生成一个全局事务,多服务联调时则会以发起方事务为准。
   String s = productFeignService.productInfo(order.get(0).getProductId());
   return order;
}

 
场景描述:

SpringCloudAlibaba+Seata整合Shardingsphere分库分表,新建了两个测试库,

seata-order和seata-order-slave做分库分表。这两个库的表结构都是一样的,表分别是

b_order_1

b_order_2

undo_log(这张表是seata里面的,分库分表如果要实现分布式事务必须将这张表在每个库中生成,用于后续全局事务回滚)

在我把环境都搭建好之后,通过A服务调用B服务,A服务中有分库分表的操作,B服务没有。

我在B服务中抛出了一个自定义异常,正常来说异常抛出后A服务中分库分表插入的数据都应该要回滚,但现实却和我预想的不一致。

实际情况:
1.seata-order和seata-order-slave两个库的数据都正常回滚

2.要么seata-order回滚成功,要么seata-order-slave回滚成功(后续我通过查看日志发现,决定哪个库能回滚成功取决与Shardingsphere分库的最后一条语句走的是哪个数据库

通过第二点可以看出,seata回滚的语句在被Shardingsphere处理后,数据源不是正常的库,所以导致本该回滚seata-order的语句被分配到了seata-order-slave中处理,那么回滚就会出现混乱。

如果有朋友出现了这种问题,不要急不要慌,只需要在上面application.yml的配置中加上一行配置就搞定

配置如下:

default-data-source-name: m1

给sharding指定一个默认数据库就好啦!这样sharding就不会找不到数据源了,保你次次回滚成功。

今天的坑就分享到这了,祝各位好运!散会

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值