下面我们以 Seata 作为分布式事务协调器为例,介绍其核心数据库表结构及作用。这些表构成了 Seata 的存储层,用于记录全局事务、分支事务、锁信息、回滚日志、TCC 防护日志以及一些扩展配置信息。下面分别给出各表的 DDL 示例、字段说明以及对应的功能介绍。
1. 全局事务表(global_table)
作用说明
用于记录全局事务的基本信息,包括全局事务 ID(xid)、状态、发起应用信息、超时时间及业务扩展数据。每启动一个分布式事务,事务管理器会在该表中生成一条记录,从而实现对整笔全局事务的跟踪和管理。
DDL 示例
DROP TABLE IF EXISTS `global_table`;
CREATE TABLE `global_table` (
`xid` varchar(128) NOT NULL COMMENT '全局事务ID',
`transaction_id` bigint(20) DEFAULT NULL COMMENT '事务内部分配的ID(可选)',
`status` tinyint(4) NOT NULL COMMENT '事务状态(如:0-Begin,1-Committed,2-Rollback)',
`application_id` varchar(32) DEFAULT NULL COMMENT '发起事务的应用ID',
`transaction_service_group` varchar(32) DEFAULT NULL COMMENT '事务服务组',
`transaction_name` varchar(128) DEFAULT NULL COMMENT '事务名称或描述',
`timeout` int(11) DEFAULT NULL COMMENT '超时时间(毫秒)',
`begin_time` bigint(20) DEFAULT NULL COMMENT '事务开始时间(时间戳)',
`application_data` varchar(2000) DEFAULT NULL COMMENT '应用扩展数据',
`gmt_create` datetime DEFAULT NULL COMMENT '记录创建时间',
`gmt_modified` datetime DEFAULT NULL COMMENT '记录最后修改时间',
PRIMARY KEY (`xid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='全局事务表';
字段说明
字段名称 | 数据类型 | 说明 |
---|---|---|
xid | varchar(128) | 全局事务唯一标识 |
transaction_id | bigint(20) | 事务内部ID(可选),用于业务内部关联 |
status | tinyint(4) | 事务状态(例如 0:待提交、1:已提交、2:回滚) |
application_id | varchar(32) | 发起事务的应用编号 |
transaction_service_group | varchar(32) | 事务所属的服务组标识 |
transaction_name | varchar(128) | 事务名称或描述 |
timeout | int(11) | 事务超时时间 |
begin_time | bigint(20) | 事务开始时间戳 |
application_data | varchar(2000) | 应用端传入的额外数据,用于扩展 |
gmt_create | datetime | 数据创建时间 |
gmt_modified | datetime | 最后修改时间 |
2. 分支事务表(branch_table)
作用说明
全局事务中往往包含多个分支事务,每个分支事务记录实际调用资源管理器(RM)进行操作的细节。该表存储各分支事务的标识、所属全局事务、资源信息以及操作状态,便于在发生异常时对各分支事务进行补偿或回滚。
DDL 示例
DROP TABLE IF EXISTS `branch_table`;
CREATE TABLE `branch_table` (
`xid` varchar(128) NOT NULL COMMENT '关联的全局事务ID',
`branch_id` bigint(20) NOT NULL COMMENT '分支事务ID',
`resource_group_id` varchar(32) DEFAULT NULL COMMENT '资源组标识',
`resource_id` varchar(256) DEFAULT NULL COMMENT '实际操作的资源ID',
`branch_type` varchar(32) DEFAULT NULL COMMENT '事务分支类型(AT、TCC、XA等)',
`status` tinyint(4) NOT NULL COMMENT '分支事务当前状态',
`client_id` varchar(64) DEFAULT NULL COMMENT '客户端(资源管理器)标识',
`application_data` varchar(2000) DEFAULT NULL COMMENT '额外应用数据',
`gmt_create` datetime DEFAULT NULL COMMENT '创建时间',
`gmt_modified` datetime DEFAULT NULL COMMENT '最后修改时间',
PRIMARY KEY (`branch_id`),
KEY `idx_branch_table_xid` (`xid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='分支事务表';
字段说明
字段名称 | 数据类型 | 说明 |
---|---|---|
xid | varchar(128) | 关联的全局事务 ID |
branch_id | bigint(20) | 分支事务 ID,唯一标识每个分支事务 |
resource_group_id | varchar(32) | 资源组标识 |
resource_id | varchar(256) | 操作资源的具体标识 |
branch_type | varchar(32) | 分支事务类型,如 AT、TCC、XA |
status | tinyint(4) | 分支事务状态 |
client_id | varchar(64) | 客户端或 RM 的标识 |
application_data | varchar(2000) | 业务扩展数据 |
gmt_create | datetime | 数据创建时间 |
gmt_modified | datetime | 最后修改时间 |
3. 全局锁表(lock_table)
作用说明
在全局事务执行过程中,为防止多个事务同时操作同一资源,Seata 会在全局锁表中记录锁定信息。该表确保在事务处理期间,指定资源(例如数据表中的某行)不会被其他事务并发修改,从而维护数据一致性。
DDL 示例
DROP TABLE IF EXISTS `lock_table`;
CREATE TABLE `lock_table` (
`xid` varchar(128) NOT NULL COMMENT '全局事务ID',
`transaction_id` bigint(20) DEFAULT NULL COMMENT '事务内部编号',
`branch_id` bigint(20) DEFAULT NULL COMMENT '分支事务ID',
`resource_id` varchar(256) DEFAULT NULL COMMENT '锁定的资源标识',
`table_name` varchar(64) DEFAULT NULL COMMENT '资源所属表名',
`pk` varchar(64) DEFAULT NULL COMMENT '数据主键(业务唯一标识)',
PRIMARY KEY (`xid`,`branch_id`,`resource_id`,`table_name`,`pk`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='全局锁表';
字段说明
字段名称 | 数据类型 | 说明 |
---|---|---|
xid | varchar(128) | 全局事务ID |
transaction_id | bigint(20) | 内部事务编号(可选) |
branch_id | bigint(20) | 关联分支事务ID |
resource_id | varchar(256) | 被锁定的资源标识 |
table_name | varchar(64) | 资源所在的数据表名称 |
pk | varchar(64) | 数据主键,用于精确定位锁记录 |
4. 回滚日志表(undo_log)
作用说明
用于 AT 模式下记录数据修改前的快照信息。每次业务操作前,Seata 会将旧数据写入此表;在全局事务回滚时,通过读取 undo_log
中的快照信息,对数据进行恢复,确保事务原子性和一致性。
DDL 示例
DROP TABLE IF EXISTS `undo_log`;
CREATE TABLE `undo_log` (
`branch_id` bigint(20) NOT NULL COMMENT '分支事务ID',
`xid` varchar(128) NOT NULL COMMENT '全局事务ID',
`context` varchar(128) NOT NULL COMMENT '上下文信息(如序列化类型)',
`rollback_info` longblob NOT NULL COMMENT '回滚前的数据信息快照',
`log_status` int(11) NOT NULL COMMENT '日志状态(0 正常,1 已处理)',
`log_created` datetime(6) NOT NULL COMMENT '日志创建时间',
`log_modified` datetime(6) NOT NULL COMMENT '日志最后修改时间',
UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='AT事务模式下的UNDO日志表';
字段说明
字段名称 | 数据类型 | 说明 |
---|---|---|
branch_id | bigint(20) | 分支事务ID |
xid | varchar(128) | 全局事务ID |
context | varchar(128) | 附加上下文信息,例如序列化和压缩的方式 |
rollback_info | longblob | 回滚前的数据快照,供数据恢复使用 |
log_status | int(11) | 日志状态:0表示未处理,1表示完成回滚 |
log_created | datetime(6) | 日志创建时间 |
log_modified | datetime(6) | 日志最后修改时间 |
5. TCC防护日志表(tcc_fence_log)
作用说明
在 TCC 模式下,为防止重复执行、悬挂或补偿误差问题,Seata 记录 TCC 防护日志,对每一次 Try/Confirm/Cancel 操作进行标记。该日志帮助确保 TCC 方法的幂等性和安全性。
DDL 示例
DROP TABLE IF EXISTS `tcc_fence_log`;
CREATE TABLE `tcc_fence_log` (
`trans_id` bigint(20) NOT NULL COMMENT '全局事务ID',
`branch_id` bigint(20) NOT NULL COMMENT '分支事务ID',
`phase` varchar(32) NOT NULL COMMENT '事务阶段(TRY/CONFIRM/CANCEL)',
`time_created` datetime NOT NULL COMMENT '日志创建时间',
PRIMARY KEY (`trans_id`,`branch_id`,`phase`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='TCC防护日志表';
字段说明
字段名称 | 数据类型 | 说明 |
---|---|---|
trans_id | bigint(20) | 全局事务ID |
branch_id | bigint(20) | 分支事务ID |
phase | varchar(32) | 当前 TCC 阶段,如 TRY、CONFIRM 或 CANCEL |
time_created | datetime | 日志生成时间 |
6. 分布式锁表(distributed_lock)
作用说明
针对业务层自定义实现的分布式锁场景,记录了每个锁定操作的详细信息。利用唯一约束保证同一业务标识或资源在同一时刻只被一个事务占用,从而避免并发冲突。
DDL 示例
DROP TABLE IF EXISTS `distributed_lock`;
CREATE TABLE `distributed_lock` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
`transaction_id` varchar(128) NOT NULL COMMENT '事务或业务标识',
`lock_key` varchar(64) NOT NULL COMMENT '锁键,标识被锁定的具体资源',
`create_time` datetime NOT NULL COMMENT '记录创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_lock_key` (`transaction_id`, `lock_key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='分布式锁表';
字段说明
字段名称 | 数据类型 | 说明 |
---|---|---|
id | bigint(20) | 自增主键,用于唯一标识记录 |
transaction_id | varchar(128) | 事务或业务标识,用于区分不同业务场景 |
lock_key | varchar(64) | 锁定的资源标识 |
create_time | datetime | 记录的创建时间 |
7. 元数据表(meta_table)
作用说明
用于保存 Seata 运行时相关的配置信息或元数据,便于系统在初始化或动态变更时加载必要信息。该表适合作为系统扩展的数据版本控制和配置存储。
DDL 示例
DROP TABLE IF EXISTS `meta_table`;
CREATE TABLE `meta_table` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
`key_name` varchar(128) NOT NULL COMMENT '配置键名称',
`value` varchar(512) DEFAULT NULL COMMENT '配置值',
`gmt_create` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_key_name` (`key_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='元数据表';
字段说明
字段名称 | 数据类型 | 说明 |
---|---|---|
id | int(11) | 自增主键,记录的唯一标识 |
key_name | varchar(128) | 配置项名称或元数据项标识 |
value | varchar(512) | 配置项对应的值 |
gmt_create | datetime | 数据创建时间 |
gmt_modified | datetime | 最后修改时间 |
总结
上述各张表分别承担了:
- global_table:记录全局事务整体的状态和信息。
- branch_table:记录全局事务下各分支事务的细节。
- lock_table:保存事务过程中对业务数据资源的锁定状态,防止并发冲突。
- undo_log:实现 AT 模式下的回滚恢复,保存数据修改前的快照。
- tcc_fence_log:为 TCC 模式提供防重复与悬挂保护日志,确保方法幂等。
- distributed_lock:支持应用层分布式锁的实现,记录锁定操作。
- meta_table:存储系统元数据和扩展配置信息,方便动态调整或版本控制。
这些表协同工作,构成了 Seata 分布式事务处理和协调的核心数据库架构,确保在跨服务、跨数据库的事务环境下实现数据的一致性和可靠回滚。
如果你还对各表之间的关联以及在具体事务流程中的调用细节感兴趣,我们可以进一步探讨 Seata 的事务协调流程和补偿机制。
小彩蛋:saga模式的状态机相关表
--
-- Licensed to the Apache Software Foundation (ASF) under one or more
-- contributor license agreements. See the NOTICE file distributed with
-- this work for additional information regarding copyright ownership.
-- The ASF licenses this file to You under the Apache License, Version 2.0
-- (the "License"); you may not use this file except in compliance with
-- the License. You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-- -------------------------------- The script used for sage --------------------------------
CREATE TABLE IF NOT EXISTS `seata_state_machine_def`
(
`id` VARCHAR(32) NOT NULL COMMENT 'id',
`name` VARCHAR(128) NOT NULL COMMENT 'name',
`tenant_id` VARCHAR(32) NOT NULL COMMENT 'tenant id',
`app_name` VARCHAR(32) NOT NULL COMMENT 'application name',
`type` VARCHAR(20) COMMENT 'state language type',
`comment_` VARCHAR(255) COMMENT 'comment',
`ver` VARCHAR(16) NOT NULL COMMENT 'version',
`gmt_create` DATETIME(3) NOT NULL COMMENT 'create time',
`status` VARCHAR(2) NOT NULL COMMENT 'status(AC:active|IN:inactive)',
`content` TEXT COMMENT 'content',
`recover_strategy` VARCHAR(16) COMMENT 'transaction recover strategy(compensate|retry)',
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4;
CREATE TABLE IF NOT EXISTS `seata_state_machine_inst`
(
`id` VARCHAR(128) NOT NULL COMMENT 'id',
`machine_id` VARCHAR(32) NOT NULL COMMENT 'state machine definition id',
`tenant_id` VARCHAR(32) NOT NULL COMMENT 'tenant id',
`parent_id` VARCHAR(128) COMMENT 'parent id',
`gmt_started` DATETIME(3) NOT NULL COMMENT 'start time',
`business_key` VARCHAR(48) COMMENT 'business key',
`start_params` TEXT COMMENT 'start parameters',
`gmt_end` DATETIME(3) COMMENT 'end time',
`excep` BLOB COMMENT 'exception',
`end_params` TEXT COMMENT 'end parameters',
`status` VARCHAR(2) COMMENT 'status(SU succeed|FA failed|UN unknown|SK skipped|RU running)',
`compensation_status` VARCHAR(2) COMMENT 'compensation status(SU succeed|FA failed|UN unknown|SK skipped|RU running)',
`is_running` TINYINT(1) COMMENT 'is running(0 no|1 yes)',
`gmt_updated` DATETIME(3) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `unikey_buz_tenant` (`business_key`, `tenant_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4;
CREATE TABLE IF NOT EXISTS `seata_state_inst`
(
`id` VARCHAR(48) NOT NULL COMMENT 'id',
`machine_inst_id` VARCHAR(128) NOT NULL COMMENT 'state machine instance id',
`name` VARCHAR(128) NOT NULL COMMENT 'state name',
`type` VARCHAR(20) COMMENT 'state type',
`service_name` VARCHAR(128) COMMENT 'service name',
`service_method` VARCHAR(128) COMMENT 'method name',
`service_type` VARCHAR(16) COMMENT 'service type',
`business_key` VARCHAR(48) COMMENT 'business key',
`state_id_compensated_for` VARCHAR(50) COMMENT 'state compensated for',
`state_id_retried_for` VARCHAR(50) COMMENT 'state retried for',
`gmt_started` DATETIME(3) NOT NULL COMMENT 'start time',
`is_for_update` TINYINT(1) COMMENT 'is service for update',
`input_params` TEXT COMMENT 'input parameters',
`output_params` TEXT COMMENT 'output parameters',
`status` VARCHAR(2) NOT NULL COMMENT 'status(SU succeed|FA failed|UN unknown|SK skipped|RU running)',
`excep` BLOB COMMENT 'exception',
`gmt_updated` DATETIME(3) COMMENT 'update time',
`gmt_end` DATETIME(3) COMMENT 'end time',
PRIMARY KEY (`id`, `machine_inst_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4;
注:关于saga模式的相关表,可以参考SEATA官方
https://github.com/apache/incubator-seata/blob/2.x/script/client/saga/db/mysql.sql