本文档用于解决 SaaS 模式下「代码发版后,数据库字段和表结构如何同步到各租户库」的问题。
当前项目采用「主库 tenant_info + 每租户独立库」模式,方案基于现有 TenantDataSourceManager、TenantTaskRunner、TenantUtils 能力落地。
采用「版本化脚本 + 租户执行记录 + 主库任务编排」模式:
VyyyyMMdd_nn__desc.sql)。tenant_db_migration)。tenant_upgrade_task、tenant_upgrade_task_detail)。表名:tenant_db_migration
CREATE TABLE IF NOT EXISTS `tenant_db_migration` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
`version` VARCHAR(64) NOT NULL COMMENT '脚本版本,如 V20260416_01',
`script_name` VARCHAR(255) NOT NULL COMMENT '脚本文件名',
`checksum` VARCHAR(64) DEFAULT NULL COMMENT '脚本内容 SHA256',
`status` VARCHAR(16) NOT NULL COMMENT 'SUCCESS/FAILED',
`started_at` DATETIME NOT NULL COMMENT '开始时间',
`finished_at` DATETIME DEFAULT NULL COMMENT '结束时间',
`error_msg` TEXT DEFAULT NULL COMMENT '失败错误信息',
`executor` VARCHAR(64) DEFAULT NULL COMMENT '执行器标识',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_version` (`version`),
KEY `idx_status` (`status`),
KEY `idx_started_at` (`started_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='租户库迁移记录表';
表名:tenant_upgrade_task
CREATE TABLE IF NOT EXISTS `tenant_upgrade_task` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
`task_no` VARCHAR(64) NOT NULL COMMENT '任务号',
`scope_type` VARCHAR(16) NOT NULL COMMENT 'ALL/INCLUDE/EXCLUDE',
`target_versions` VARCHAR(512) NOT NULL COMMENT '目标版本范围或列表',
`status` VARCHAR(16) NOT NULL COMMENT 'RUNNING/SUCCESS/PARTIAL/FAILED',
`total_tenants` INT NOT NULL DEFAULT 0 COMMENT '总租户数',
`success_tenants` INT NOT NULL DEFAULT 0 COMMENT '成功租户数',
`failed_tenants` INT NOT NULL DEFAULT 0 COMMENT '失败租户数',
`started_at` DATETIME NOT NULL COMMENT '开始时间',
`finished_at` DATETIME DEFAULT NULL COMMENT '结束时间',
`trigger_by` VARCHAR(64) DEFAULT NULL COMMENT '触发人',
`remark` VARCHAR(500) DEFAULT NULL COMMENT '备注',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_task_no` (`task_no`),
KEY `idx_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='租户库升级任务主表';
表名:tenant_upgrade_task_detail
CREATE TABLE IF NOT EXISTS `tenant_upgrade_task_detail` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
`task_no` VARCHAR(64) NOT NULL COMMENT '任务号',
`tenant_id` BIGINT NOT NULL COMMENT '租户ID',
`tenant_code` VARCHAR(64) NOT NULL COMMENT '租户编码',
`current_version` VARCHAR(64) DEFAULT NULL COMMENT '升级前版本',
`target_version` VARCHAR(64) DEFAULT NULL COMMENT '目标版本',
`status` VARCHAR(16) NOT NULL COMMENT 'SUCCESS/FAILED/SKIPPED',
`error_msg` TEXT DEFAULT NULL COMMENT '失败原因',
`started_at` DATETIME NOT NULL COMMENT '开始时间',
`finished_at` DATETIME DEFAULT NULL COMMENT '结束时间',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_task_tenant` (`task_no`, `tenant_id`),
KEY `idx_task_no` (`task_no`),
KEY `idx_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='租户库升级任务明细';
fs-service/src/main/resources/db/migration/tenant/
V20260416_01__add_column_xxx.sqlV20260416_02__init_data_xxx.sqlIF EXISTS/IF NOT EXISTS、条件插入/更新)。建议在 fs-service 增加以下组件:
TenantMigrationScriptLoader:扫描脚本、解析版本、排序、计算 checksum。TenantMigrationRepository:在当前租户库读写 tenant_db_migration。TenantMigrationExecutor:单租户执行器,串行执行该租户未执行脚本。TenantUpgradeOrchestrator:主编排器,主库查租户并发起升级,汇总结果写主库任务表。可复用当前能力:
tenant_info:租户主数据来源。TenantDataSourceManager:按租户切换数据源。TenantTaskRunner:顺序/并行按租户执行框架。TenantUtils:执行 SQL 脚本的工具能力(已改为 UTF-8 读取脚本)。POST /tenant/upgrade/run入参建议:
scopeType:ALL / INCLUDE / EXCLUDEtenantIds:租户 ID 列表fromVersion:起始版本(可空)toVersion:目标版本(可空)parallel:是否并行threads:线程数remark:备注GET /tenant/upgrade/task/{taskNo}:任务总览GET /tenant/upgrade/task/{taskNo}/failures:失败明细POST /tenant/upgrade/retry/{taskNo}执行前检查建议:
tenant_id 字段。tenant_db_migration(租户库)tenant_upgrade_task(主库)tenant_upgrade_task_detail(主库)db/migration/tenantVyyyyMMdd_nn__desc.sql