【知识积累】阿里分布式事务解决方案Seata实战

一、准备

二、下载seata-server

https://seata.io/zh-cn/docs/user/quickstart.html

步骤 4: 启动服务

从 https://github.com/seata/seata/releases,下载服务器软件包,将其解压缩。

三、修改配置文件

seata\conf\file.conf

service {
  #transaction service group mapping
  #修改,fbs_tx_group随便起名字
  vgroup_mapping.fbs_tx_group = "default"
  #only support when registry.type=file, please don't set multiple addresses
  # seata server的地址
  default.grouplist = "127.0.0.1:8091"
  #disable seata
  disableGlobalTransaction = false
}
## transaction log store, only used in seata-server
store {
  ## store mode: file、db、redis
  #存储模式使用数据库
  mode = "db"

  ## file store property
  file {
    ## store location dir
    dir = "sessionStore"
    # branch session size , if exceeded first try compress lockkey, still exceeded throws exceptions
    maxBranchSessionSize = 16384
    # globe session size , if exceeded throws exceptions
    maxGlobalSessionSize = 512
    # file buffer size , if exceeded allocate new buffer
    fileWriteBufferCacheSize = 16384
    # when recover batch read size
    sessionReloadReadSize = 100
    # async, sync
    flushDiskMode = async
  }

  ## database store property
  #数据库的配置
  db {
    ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp)/HikariDataSource(hikari) etc.
    #连接池
    datasource = "druid"
    ## mysql/oracle/postgresql/h2/oceanbase etc.
    #数据库类型
    dbType = "mysql"
    #数据库驱动
    driverClassName = "com.mysql.cj.jdbc.Driver"
    #数据库地址
    url = "jdbc:mysql://127.0.0.1:3306/seata-server?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai"
    #数据库账号
    user = "root"
    #数据库密码
    password = "1234"
    minConn = 5
    maxConn = 30
    globalTable = "global_table"
    branchTable = "branch_table"
    lockTable = "lock_table"
    queryLimit = 100
    maxWait = 5000
  }

  ## redis store property
  redis {
    host = "127.0.0.1"
    port = "6379"
    password = ""
    database = "0"
    minConn = 1
    maxConn = 10
    queryLimit = 100
  }

}

seata\conf\registry.conf

registry {
  # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
  #注册中心的指定
  type = "eureka"

  nacos {
    application = "seata-server"
    serverAddr = "127.0.0.1:8848"
    group = "SEATA_GROUP"
    namespace = ""
    cluster = "default"
    username = ""
    password = ""
  }
  #eureka的配置 注册地址和微服务保持一致,不要忘记账号和密码
  eureka {
    serviceUrl = "http://root:1234@localhost:8761/eureka/"
    #注册到eureka的名称
    application = "seata-server"
    weight = "1"
  }
  redis {
    serverAddr = "localhost:6379"
    db = 0
    password = ""
    cluster = "default"
    timeout = 0
  }
  zk {
    cluster = "default"
    serverAddr = "127.0.0.1:2181"
    sessionTimeout = 6000
    connectTimeout = 2000
    username = ""
    password = ""
  }
  consul {
    cluster = "default"
    serverAddr = "127.0.0.1:8500"
  }
  etcd3 {
    cluster = "default"
    serverAddr = "http://localhost:2379"
  }
  sofa {
    serverAddr = "127.0.0.1:9603"
    application = "default"
    region = "DEFAULT_ZONE"
    datacenter = "DefaultDataCenter"
    cluster = "default"
    group = "SEATA_GROUP"
    addressWaitTime = "3000"
  }
  file {
    name = "file.conf"
  }
}

config {
  # file、nacos 、apollo、zk、consul、etcd3
  #配置的方式
  type = "file"

  nacos {
    serverAddr = "127.0.0.1:8848"
    namespace = ""
    group = "SEATA_GROUP"
    username = ""
    password = ""
  }
  consul {
    serverAddr = "127.0.0.1:8500"
  }
  apollo {
    appId = "seata-server"
    apolloMeta = "http://192.168.1.204:8801"
    namespace = "application"
  }
  zk {
    serverAddr = "127.0.0.1:2181"
    sessionTimeout = 6000
    connectTimeout = 2000
    username = ""
    password = ""
  }
  etcd3 {
    serverAddr = "http://localhost:2379"
  }
  #指向上面的file.conf文件
  file {
    name = "file.conf"
  }
}

四、启动seata-server

\seata\bin\seata-server.bat

访问:http://localhost:8761/

五、在seata-server库下创建全局事务表、分支事务表、全局锁表

DROP TABLE IF EXISTS `global_table`;
CREATE TABLE `global_table` (
  `xid` varchar(128) NOT NULL,
  `transaction_id` bigint(20) DEFAULT NULL,
  `status` tinyint(4) NOT NULL,
  `application_id` varchar(32) DEFAULT NULL,
  `transaction_service_group` varchar(32) DEFAULT NULL,
  `transaction_name` varchar(128) DEFAULT NULL,
  `timeout` int(11) DEFAULT NULL,
  `begin_time` bigint(20) DEFAULT NULL,
  `application_data` varchar(2000) DEFAULT NULL,
  `gmt_create` datetime DEFAULT NULL,
  `gmt_modified` datetime DEFAULT NULL,
  PRIMARY KEY (`xid`) USING BTREE,
  KEY `idx_gmt_modified_status` (`gmt_modified`,`status`) USING BTREE,
  KEY `idx_transaction_id` (`transaction_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='全局事务表';
DROP TABLE IF EXISTS `branch_table`;
CREATE TABLE `branch_table` (
  `branch_id` bigint(20) NOT NULL,
  `xid` varchar(128) NOT NULL,
  `transaction_id` bigint(20) DEFAULT NULL,
  `resource_group_id` varchar(32) DEFAULT NULL,
  `resource_id` varchar(256) DEFAULT NULL,
  `branch_type` varchar(8) DEFAULT NULL,
  `status` tinyint(4) DEFAULT NULL,
  `client_id` varchar(64) DEFAULT NULL,
  `application_data` varchar(2000) DEFAULT NULL,
  `gmt_create` datetime DEFAULT NULL,
  `gmt_modified` datetime DEFAULT NULL,
  PRIMARY KEY (`branch_id`) USING BTREE,
  KEY `idx_xid` (`xid`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='分支事务表';
DROP TABLE IF EXISTS `lock_table`;
CREATE TABLE `lock_table` (
  `row_key` varchar(128) NOT NULL,
  `xid` varchar(96) DEFAULT NULL,
  `transaction_id` bigint(20) DEFAULT NULL,
  `branch_id` bigint(20) NOT NULL,
  `resource_id` varchar(256) DEFAULT NULL,
  `table_name` varchar(32) DEFAULT NULL,
  `pk` varchar(36) DEFAULT NULL,
  `gmt_create` datetime DEFAULT NULL,
  `gmt_modified` datetime DEFAULT NULL,
  PRIMARY KEY (`row_key`) USING BTREE,
  KEY `idx_branch_id` (`branch_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='全局锁';

六、每个业务数据库下创建回滚日志表

1、seata-rm-one

DROP TABLE IF EXISTS `tbl_one`;
CREATE TABLE `tbl_one` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4;
DROP TABLE IF EXISTS `undo_log`;
CREATE TABLE `undo_log` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `branch_id` bigint(20) NOT NULL,
  `xid` varchar(100) NOT NULL,
  `context` varchar(128) NOT NULL,
  `rollback_info` longblob NOT NULL,
  `log_status` int(11) NOT NULL,
  `log_created` datetime NOT NULL,
  `log_modified` datetime NOT NULL,
  `ext` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

2、seata-rm-two

DROP TABLE IF EXISTS `tbl_two`;
CREATE TABLE `tbl_two` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4;
DROP TABLE IF EXISTS `undo_log`;
CREATE TABLE `undo_log` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `branch_id` bigint(20) NOT NULL,
  `xid` varchar(100) NOT NULL,
  `context` varchar(128) NOT NULL,
  `rollback_info` longblob NOT NULL,
  `log_status` int(11) NOT NULL,
  `log_created` datetime NOT NULL,
  `log_modified` datetime NOT NULL,
  `ext` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

3、seata-rm-three

DROP TABLE IF EXISTS `tbl_three`;
CREATE TABLE `tbl_three` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4;
DROP TABLE IF EXISTS `undo_log`;
CREATE TABLE `undo_log` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `branch_id` bigint(20) NOT NULL,
  `xid` varchar(100) NOT NULL,
  `context` varchar(128) NOT NULL,
  `rollback_info` longblob NOT NULL,
  `log_status` int(11) NOT NULL,
  `log_created` datetime NOT NULL,
  `log_modified` datetime NOT NULL,
  `ext` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

七、每个微服务resources目录下添加file.conf和registry.conf文件

service {
  #transaction service group mapping
  vgroup_mapping.fbs_tx_group= "default"
  #only support when registry.type=file, please don't set multiple addresses
  default.grouplist = "127.0.0.1:8091"
  #disable seata
  disableGlobalTransaction = false
}

client {
  rm {
    async.commit.buffer.limit = 10000
    lock {
      retry.internal = 10
      retry.times = 30
      retry.policy.branch-rollback-on-conflict = true
    }
    report.retry.count = 5
    table.meta.check.enable = false
    report.success.enable = true
  }
  tm {
    commit.retry.count = 5
    rollback.retry.count = 5
  }
  undo {
    data.validation = true
    log.serialization = "jackson"
    log.table = "undo_log"
  }
  log {
    exceptionRate = 100
  }
  support {
    # auto proxy the DataSource bean
    spring.datasource.autoproxy = false
  }
}

## transaction log store, only used in seata-server
store {
  ## store mode: file、db
  mode = "db"

  ## file store property
  file {
    ## store location dir
    dir = "sessionStore"
  }

  ## database store property
  db {
    ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp) etc.
    datasource = "druid"
    ## mysql/oracle/h2/oceanbase etc.
    db-type = "mysql"
    driver-class-name = "com.mysql.cj.jdbc.Driver"
    url = "jdbc:mysql://127.0.0.1:3306/seata-server?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai"
    user = "root"
    password = "1234"
  }
}
registry {
  # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
  type = "eureka"

  nacos {
    serverAddr = "localhost"
    namespace = ""
    cluster = "default"
  }
  eureka {
    serviceUrl = "http://root:root@localhost:8761/eureka/"
    application = "default"
    weight = "1"
  }
  redis {
    serverAddr = "localhost:6379"
    db = "0"
  }
  zk {
    cluster = "default"
    serverAddr = "127.0.0.1:2181"
    session.timeout = 6000
    connect.timeout = 2000
  }
  consul {
    cluster = "default"
    serverAddr = "127.0.0.1:8500"
  }
  etcd3 {
    cluster = "default"
    serverAddr = "http://localhost:2379"
  }
  sofa {
    serverAddr = "127.0.0.1:9603"
    application = "default"
    region = "DEFAULT_ZONE"
    datacenter = "DefaultDataCenter"
    cluster = "default"
    group = "SEATA_GROUP"
    addressWaitTime = "3000"
  }
  file {
    name = "file.conf"
  }
}

config {
  # file、nacos 、apollo、zk、consul、etcd3
  type = "file"

  nacos {
    serverAddr = "localhost"
    namespace = ""
  }
  consul {
    serverAddr = "127.0.0.1:8500"
  }
  apollo {
    app.id = "seata-server"
    apollo.meta = "http://192.168.1.204:8801"
  }
  zk {
    serverAddr = "127.0.0.1:2181"
    session.timeout = 6000
    connect.timeout = 2000
  }
  etcd3 {
    serverAddr = "http://localhost:2379"
  }
  file {
    name = "file.conf"
  }
}

八、每个微服务添加Maven依赖

<!-- alibaba-seata -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-seata</artifactId>
            <version>2.2.0.RELEASE</version>
        </dependency>

九、application.yml配置

spring:
  application:
    name: seata-one
  cloud:
    alibaba:
      seata:
        #和seata server的file.conf(vgroup_mapping.fbs_tx_group= "default")以及每个微服务resources目录下的file.conf(vgroup_mapping.fbs_tx_group= "default")要一致
        tx-service-group: fbs_tx_group

十、访问的方法添加注解@GlobalTransactional(rollbackFor = Exception.class)

1、alibaba-seata-rm-one

package com.darren.center.seata.one.controller;

import com.darren.center.seata.one.service.RmOneService;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * <h3>spring-cloud-2020</h3>
 * <p></p>
 *
 * @author : Darren
 * @date : 2020年09月02日 20:56:03
 **/
@RestController
@RequestMapping("/test")
public class TestController {

    @Autowired
    private RmOneService rmOneService;

    /**
     * 注册中心 http://localhost:8761/
     *
     * http://192.168.229.1:8001/test/rm1
     * @return
     */
    @GlobalTransactional(rollbackFor = Exception.class)
    @GetMapping("/rm1")
    public String rm1(){
        rmOneService.rm1();
        return "rm1 success";
    }

    /**
     * http://192.168.229.1:8001/test/rm1-update
     * @return
     */
    @GlobalTransactional(rollbackFor = Exception.class)
    @GetMapping("/rm1-update")
    public String rm1Update(){
        rmOneService.rm2Update();
        return "rm1 update success";
    }

}
package com.darren.center.seata.one.service;

import com.darren.center.seata.one.dao.OneDao;
import com.darren.center.seata.one.entity.One;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class RmOneService {

    @Autowired
    private OneDao oneDao;

    @Autowired
    private RestTemplate restTemplate;


    public String rm1(){
        rm2();
        rm3();
        One rm1 = new One(1, "rm1");
        oneDao.insertSelective(rm1);
        //异常测试,发生异常时,rm1发生异常时,所有的数据是否回滚
        //int i = 1/0;
        return "";
    }

    public String rm2Update(){
        //rm2 更新
        rm2UpdateRemote();

        One rm1 = new One(1, "rm1");
        oneDao.insertSelective(rm1);
        //异常测试,发生异常时,rm1发生异常时,所有的数据是否回滚
        //int i = 1/0;
        return "";
    }


    /**
     * 调用seata 2 插入一条新数据
     */
    private void rm2() {
        restTemplate.getForEntity("http://seata-two/test/rm2", null);
    }

    /**
     * 调用seata 2 更新数据
     */
    private void rm2UpdateRemote() {
        restTemplate.getForEntity("http://seata-two/test/rm2-update", null);
    }

    /**
     * 调用seata 3
     */
    private void rm3() {
        restTemplate.getForEntity("http://seata-three/test/rm3", null);
    }

}

2、alibaba-seata-rm-two

package com.darren.center.seata.two.controller;

import com.darren.center.seata.two.service.RmTwoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * <h3>spring-cloud-2020</h3>
 * <p></p>
 *
 * @author : Darren
 * @date : 2020年09月02日 20:52:41
 **/
@RestController
@RequestMapping("/test")
public class TestController {

    @Autowired
    private RmTwoService rmTwoService;

    @GetMapping("/rm2")
    public String rm2(){
        rmTwoService.rm2();
        return "rm2 success";
    }

    @GetMapping("/rm2-update")
    public String rm2Update(){
        rmTwoService.rm2Update();
        return "rm2 update success";
    }

}
package com.darren.center.seata.two.service;

import com.darren.center.seata.two.dao.TwoDao;
import com.darren.center.seata.two.entity.Two;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Random;

/**
 * <h3>spring-cloud-2020</h3>
 * <p></p>
 *
 * @author : Darren
 * @date : 2020年09月02日 21:06:00
 **/
@Service
public class RmTwoService {

    @Autowired
    private TwoDao twoDao;

    public String rm2(){
        Two rm2 = new Two(1, "rm2");
        twoDao.insertSelective(rm2);
        //异常测试,发生异常时,rm2发生异常时,所有的数据是否回滚
        //int i = 1/0;
        return "";
    }

    public String rm2Update(){
        List<Two> lists = twoDao.selectAll();
        Two two = lists.get(0);
        two.setName(two.getName() + new Random().nextInt(100));
        twoDao.updateByPrimaryKeySelective(two);
        //异常测试,发生异常时,rm2发生异常时,所有的数据是否回滚
        //int i = 1/0;
        return "";
    }

}

3、alibaba-seata-rm-three

package com.darren.center.seata.three.controller;

import com.darren.center.seata.three.service.RmThreeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * <h3>spring-cloud-2020</h3>
 * <p></p>
 *
 * @author : Darren
 * @date : 2020年09月02日 21:09:04
 **/
@RestController
@RequestMapping("/test")
public class TestController {

    @Autowired
    private RmThreeService rmThreeService;

    @RequestMapping("/rm3")
    public String rm3(){
        rmThreeService.rm3();
        return "rm3 success";
    }

}
package com.darren.center.seata.three.service;

import com.darren.center.seata.three.dao.ThreeDao;
import com.darren.center.seata.three.entity.Three;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * <h3>spring-cloud-2020</h3>
 * <p></p>
 *
 * @author : Darren
 * @date : 2020年09月02日 20:09:38
 **/
@Service
public class RmThreeService {

    @Autowired
    private ThreeDao threeDao;


    public String rm3(){
        Three rm3 = new Three(1, "rm3");
        threeDao.insertSelective(rm3);
        return "";
    }

}

十一、启动项目

十二、测试点

1、rm1、rm2、rm3插入完成,rm1发生异常,那么数据是否会回滚

2、rm2更新完成,rm1插入完成,rm1发生异常,那么数据是否会回滚

3、rm2更新完成,seata-server宕机,然后重启seata-server,那么数据是否会回滚

十三、观察全局事务表、分支事务表、全局锁表、回滚日志表的数据

#全局事务表
INSERT INTO `seata-server`.`global_table` (
	`xid`,
    #全局事务ID
	`transaction_id`,
	#全局事务ID
	`status`,
	#状态
	`application_id`,
	#事务管理器ID
	`transaction_service_group`,
	#事务组
	`transaction_name`,
	#事务名称 - 方法名
	`timeout`,
	#超时时间 60S
	`begin_time`,
	#开始时间
	`application_data`,
	#应用数据
	`gmt_create`,
	#创建时间
	`gmt_modified` #修改时间
)
VALUES
	(
		'192.168.244.1:8091:44731799200337920',
		'44731799200337920',
		'1',
		'seata-one',
		'fbs_tx_group',
		'rm1()',
		'60000',
		'1599100092006',
		NULL,
		'2020-09-03 10:28:12',
		'2020-09-03 10:28:12'
	);

#分支事务表1
INSERT INTO `seata-server`.`branch_table` (
	`branch_id`,
	#分支ID
	`xid`,
	#全局事务ID
	`transaction_id`,
	#全局事务ID
	`resource_group_id`,
	#数据源组ID
	`resource_id`,
	#数据源ID
	`branch_type`,
	#分支类型 AT
	`status`,
	#状态
	`client_id`,
	#客户端ID
	`application_data`,
	#应用数据
	`gmt_create`,
	#创建时间
	`gmt_modified` #修改时间
)
VALUES
	(
		'44731838966534145',
		'192.168.244.1:8091:44731799200337920',
		'44731799200337920',
		NULL,
		'jdbc:mysql://localhost:3306/seata-rm-one',
		'AT',
		'2',
		'seata-one:127.0.0.1:12784',
		NULL,
		'2020-09-03 10:28:22',
		'2020-09-03 10:28:22'
	);

#分支事务表2
INSERT INTO `seata-server`.`branch_table` (
	`branch_id`,
	#分支ID
	`xid`,
	#全局事务ID
	`transaction_id`,
	#全局事务ID
	`resource_group_id`,
	#数据源组ID
	`resource_id`,
	#数据源ID
	`branch_type`,
	#分支类型 AT
	`status`,
	#状态
	`client_id`,
	#客户端ID
	`application_data`,
	#应用数据
	`gmt_create`,
	#创建时间
	`gmt_modified` #修改时间
)
VALUES
	(
		'44731816451510273',
		'192.168.244.1:8091:44731799200337920',
		'44731799200337920',
		NULL,
		'jdbc:mysql://localhost:3306/seata-rm-two',
		'AT',
		'2',
		'seata-two:127.0.0.1:12643',
		NULL,
		'2020-09-03 10:28:16',
		'2020-09-03 10:28:16'
	);

#分支事务表3
INSERT INTO `seata-server`.`branch_table` (
	`branch_id`,
	#分支ID
	`xid`,
	#全局事务ID
	`transaction_id`,
	#全局事务ID
	`resource_group_id`,
	#数据源组ID
	`resource_id`,
	#数据源ID
	`branch_type`,
	#分支类型 AT
	`status`,
	#状态
	`client_id`,
	#客户端ID
	`application_data`,
	#应用数据
	`gmt_create`,
	#创建时间
	`gmt_modified` #修改时间
)
VALUES
	(
		'44731819240722432',
		'192.168.244.1:8091:44731799200337920',
		'44731799200337920',
		NULL,
		'jdbc:mysql://localhost:3306/seata-rm-three',
		'AT',
		'2',
		'seata-three:127.0.0.1:13366',
		NULL,
		'2020-09-03 10:28:17',
		'2020-09-03 10:28:17'
	);



#全局锁1
INSERT INTO `seata-server`.`lock_table` (
	`row_key`,
	`xid`,
	#全局事务ID
	`transaction_id`,
	#全局事务ID
	`branch_id`,
	#分支ID
	`resource_id`,
	#数据源ID
	`table_name`,
	#数据表
	`pk`,
	`gmt_create`,
	#创建时间
	`gmt_modified` #修改时间
)
VALUES
	(
		'jdbc:mysql://localhost:3306/seata-rm-one^^^tbl_one^^^3',
		'192.168.244.1:8091:44731799200337920',
		'44731799200337920',
		'44731838966534145',
		'jdbc:mysql://localhost:3306/seata-rm-one',
		'tbl_one',
		'3',
		'2020-09-03 10:28:21',
		'2020-09-03 10:28:21'
	);

#全局锁2
INSERT INTO `seata-server`.`lock_table` (
	`row_key`,
	`xid`,
	`transaction_id`,
	`branch_id`,
	`resource_id`,
	`table_name`,
	`pk`,
	`gmt_create`,
	`gmt_modified`
)
VALUES
	(
		'jdbc:mysql://localhost:3306/seata-rm-three^^^tbl_three^^^4',
		'192.168.244.1:8091:44731799200337920',
		'44731799200337920',
		'44731819240722432',
		'jdbc:mysql://localhost:3306/seata-rm-three',
		'tbl_three',
		'4',
		'2020-09-03 10:28:16',
		'2020-09-03 10:28:16'
	);

#全局锁3
INSERT INTO `seata-server`.`lock_table` (
	`row_key`,
	`xid`,
	`transaction_id`,
	`branch_id`,
	`resource_id`,
	`table_name`,
	`pk`,
	`gmt_create`,
	`gmt_modified`
)
VALUES
	(
		'jdbc:mysql://localhost:3306/seata-rm-two^^^tbl_two^^^6',
		'192.168.244.1:8091:44731799200337920',
		'44731799200337920',
		'44731816451510273',
		'jdbc:mysql://localhost:3306/seata-rm-two',
		'tbl_two',
		'6',
		'2020-09-03 10:28:16',
		'2020-09-03 10:28:16'
	);

#回滚表,记录在每个业务数据库
INSERT INTO `seata-rm-one`.`undo_log` (
	`id`,
	`branch_id`, 
    #分支事务ID
	`xid`,
    #全局事务ID
	`context`,
	`rollback_info`,
    #回滚信息  记录前置镜像和后置镜像
	`log_status`,
    #回滚日志状态
	`log_created`,
    #回滚日志创建时间
	`log_modified`,
    #回滚日志修改时间
	`ext`
)
VALUES
	(
		'3',
		'44731838966534145',
		'192.168.244.1:8091:44731799200337920',
		'serializer=jackson',
		'{\"@class\":\"io.seata.rm.datasource.undo.BranchUndoLog\",\"xid\":\"192.168.244.1:8091:44731799200337920\",\"branchId\":44731838966534145,\"sqlUndoLogs\":[\"java.util.ArrayList\",[{\"@class\":\"io.seata.rm.datasource.undo.SQLUndoLog\",\"sqlType\":\"INSERT\",\"tableName\":\"tbl_one\",\"beforeImage\":{\"@class\":\"io.seata.rm.datasource.sql.struct.TableRecords$EmptyTableRecords\",\"tableName\":\"tbl_one\",\"rows\":[\"java.util.ArrayList\",[]]},\"afterImage\":{\"@class\":\"io.seata.rm.datasource.sql.struct.TableRecords\",\"tableName\":\"tbl_one\",\"rows\":[\"java.util.ArrayList\",[{\"@class\":\"io.seata.rm.datasource.sql.struct.Row\",\"fields\":[\"java.util.ArrayList\",[{\"@class\":\"io.seata.rm.datasource.sql.struct.Field\",\"name\":\"id\",\"keyType\":\"PrimaryKey\",\"type\":4,\"value\":3},{\"@class\":\"io.seata.rm.datasource.sql.struct.Field\",\"name\":\"name\",\"keyType\":\"NULL\",\"type\":12,\"value\":\"rm1\"}]]}]]}}]]}',
		'0',
		'2020-09-03 10:28:21',
		'2020-09-03 10:28:21',
		NULL
	);

INSERT INTO `seata-rm-two`.`undo_log` (
	`id`,
	`branch_id`, 
    #分支事务ID
	`xid`,
    #全局事务ID
	`context`,
	`rollback_info`,
    #回滚信息  记录前置镜像和后置镜像
	`log_status`,
    #回滚日志状态
	`log_created`,
    #回滚日志创建时间
	`log_modified`,
    #回滚日志修改时间
	`ext`
)
VALUES
	(
		'7',
		'44731816451510273',
		'192.168.244.1:8091:44731799200337920',
		'serializer=jackson',
		'{\"@class\":\"io.seata.rm.datasource.undo.BranchUndoLog\",\"xid\":\"192.168.244.1:8091:44731799200337920\",\"branchId\":44731816451510273,\"sqlUndoLogs\":[\"java.util.ArrayList\",[{\"@class\":\"io.seata.rm.datasource.undo.SQLUndoLog\",\"sqlType\":\"INSERT\",\"tableName\":\"tbl_two\",\"beforeImage\":{\"@class\":\"io.seata.rm.datasource.sql.struct.TableRecords$EmptyTableRecords\",\"tableName\":\"tbl_two\",\"rows\":[\"java.util.ArrayList\",[]]},\"afterImage\":{\"@class\":\"io.seata.rm.datasource.sql.struct.TableRecords\",\"tableName\":\"tbl_two\",\"rows\":[\"java.util.ArrayList\",[{\"@class\":\"io.seata.rm.datasource.sql.struct.Row\",\"fields\":[\"java.util.ArrayList\",[{\"@class\":\"io.seata.rm.datasource.sql.struct.Field\",\"name\":\"id\",\"keyType\":\"PrimaryKey\",\"type\":4,\"value\":6},{\"@class\":\"io.seata.rm.datasource.sql.struct.Field\",\"name\":\"name\",\"keyType\":\"NULL\",\"type\":12,\"value\":\"rm2\"}]]}]]}}]]}',
		'0',
		'2020-09-03 10:28:16',
		'2020-09-03 10:28:16',
		NULL
	);

INSERT INTO `seata-rm-three`.`undo_log` (
	`id`,
	`branch_id`, 
    #分支事务ID
	`xid`,
    #全局事务ID
	`context`,
	`rollback_info`,
    #回滚信息  记录前置镜像和后置镜像
	`log_status`,
    #回滚日志状态
	`log_created`,
    #回滚日志创建时间
	`log_modified`,
    #回滚日志修改时间
	`ext`
)
VALUES
	(
		'3',
		'44731819240722432',
		'192.168.244.1:8091:44731799200337920',
		'serializer=jackson',
		'{\"@class\":\"io.seata.rm.datasource.undo.BranchUndoLog\",\"xid\":\"192.168.244.1:8091:44731799200337920\",\"branchId\":44731819240722432,\"sqlUndoLogs\":[\"java.util.ArrayList\",[{\"@class\":\"io.seata.rm.datasource.undo.SQLUndoLog\",\"sqlType\":\"INSERT\",\"tableName\":\"tbl_three\",\"beforeImage\":{\"@class\":\"io.seata.rm.datasource.sql.struct.TableRecords$EmptyTableRecords\",\"tableName\":\"tbl_three\",\"rows\":[\"java.util.ArrayList\",[]]},\"afterImage\":{\"@class\":\"io.seata.rm.datasource.sql.struct.TableRecords\",\"tableName\":\"tbl_three\",\"rows\":[\"java.util.ArrayList\",[{\"@class\":\"io.seata.rm.datasource.sql.struct.Row\",\"fields\":[\"java.util.ArrayList\",[{\"@class\":\"io.seata.rm.datasource.sql.struct.Field\",\"name\":\"id\",\"keyType\":\"PrimaryKey\",\"type\":4,\"value\":4},{\"@class\":\"io.seata.rm.datasource.sql.struct.Field\",\"name\":\"name\",\"keyType\":\"NULL\",\"type\":12,\"value\":\"rm3\"}]]}]]}}]]}',
		'0',
		'2020-09-03 10:28:16',
		'2020-09-03 10:28:16',
		NULL
	);

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值