| name | java-db-migration |
| description | Use when creating MyBatis Migration scripts for schema changes such as new tables, added columns, and index updates. Covers file format, standard columns, rollback sections, and migration bootstrap patterns. |
数据库迁移脚本
生成符合 MyBatis Migration 规范的数据库迁移脚本。
适用场景
- 新建业务表
- 为现有表新增字段、索引或 JSON 列
- 调整唯一索引 / 普通索引
- 任何需要生成 MyBatis Migration 脚本的 Schema 变更
不适用
- 直接在线手改生产数据库
- 仅写查询 SQL、存储过程或数据修复脚本
- 不使用 MyBatis Migration 管理的项目
快速工作流
- 先确认变更类型:建表、加列、改索引还是初始化迁移体系
- 按标准模板写正向 SQL 和
@UNDO 逆向 SQL
- 检查列注释、逻辑删除字段、索引命名和唯一约束是否符合规范
- 在非生产环境执行迁移并验证回滚
脚本格式
文件命名
YYYYMMDDHHMMSS_description.sql
示例: 20251027082057_create_analysis_task_tables.sql
必需结构
每个脚本必须包含两段:
-- // 和 -- //@UNDO 是 MyBatis Migration 的必需标记,不可省略。
标准列规范
必备列(所有业务表)
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`deleted` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除',
`create_time` DATETIME NOT NULL COMMENT '创建时间',
`update_time` DATETIME NOT NULL COMMENT '更新时间',
可选列(按需添加)
`create_user` BIGINT(20) COMMENT '创建人',
`update_user` BIGINT(20) COMMENT '修改人',
`version_num` INT NOT NULL DEFAULT 1 COMMENT '版本号(乐观锁)',
`sort_num` INT COMMENT '排序序号',
强制要求
- 所有列必须有
COMMENT
- 表必须有
COMMENT
- 使用
ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
索引命名规范
| 类型 | 前缀 | 示例 |
|---|
| 主键 | PRIMARY KEY | PRIMARY KEY (id) |
| 唯一索引 | uk_ | uk_name_version |
| 普通索引 | idx_ | idx_create_time |
关键规则: 唯一约束必须包含 deleted 字段,以支持逻辑删除后重新创建同名记录。
UNIQUE KEY `uk_name` (`name`, `deleted`)
UNIQUE KEY `uk_name` (`name`)
外键字段
- 命名:
{关联表}_id(如 policy_id, task_id)
- 类型:
BIGINT(20) 数字ID 或 VARCHAR(100) 业务ID
- 不使用物理外键约束,通过应用层保证一致性
- 外键字段必须建索引:
KEY idx_{field} ({field})
场景模板
场景 1: 创建表
CREATE TABLE IF NOT EXISTS `alert_policy` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`name` VARCHAR(255) NOT NULL COMMENT '策略名称',
`description` TEXT COMMENT '策略描述',
`enabled` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否启用',
`alert_level` VARCHAR(20) NOT NULL DEFAULT 'LEVEL_3' COMMENT '告警等级',
`storage_plan` VARCHAR(20) NOT NULL DEFAULT '7D' COMMENT '存储计划',
`policy_id` BIGINT(20) COMMENT '关联策略ID',
`deleted` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除',
`create_user` BIGINT(20) COMMENT '创建人',
`update_user` BIGINT(20) COMMENT '修改人',
`create_time` DATETIME NOT NULL COMMENT '创建时间',
`update_time` DATETIME NOT NULL COMMENT '更新时间',
`version_num` COMMENT ,
(`id`),
KEY `uk_name` (`name`, `deleted`),
KEY `idx_alert_level` (`alert_level`),
KEY `idx_policy_id` (`policy_id`),
KEY `idx_create_time` (`create_time`)
) ENGINEInnoDB CHARSETutf8mb4 COMMENT;
IF `alert_policy`;
场景 2: 添加列
ALTER TABLE `alert_records`
ADD COLUMN `handle_status` VARCHAR(32) COMMENT '处置状态' AFTER `message`,
ADD COLUMN `handle_time` DATETIME COMMENT '处置时间' AFTER `handle_status`,
ADD COLUMN `handle_remark` TEXT COMMENT '处置备注' AFTER `handle_time`;
ALTER TABLE `alert_records`
ADD INDEX `idx_handle_status` (`handle_status`);
ALTER TABLE `alert_records`
DROP INDEX `idx_handle_status`,
DROP COLUMN `handle_remark`,
DROP COLUMN `handle_time`,
DROP COLUMN `handle_status`;
场景 3: 修改索引
DROP INDEX `uk_task_source` ON `analysis_sub_task`;
CREATE INDEX `idx_task_source` ON `analysis_sub_task` (`task_id`, `source_id`);
DROP INDEX `idx_task_source` ON `analysis_sub_task`;
CREATE UNIQUE INDEX `uk_task_source` ON `analysis_sub_task` (`task_id`, `source_id`);
回滚脚本要求
- 回滚必须是变更的精确逆操作
- 删表:
DROP TABLE IF EXISTS
- 删列: 按添加的逆序 DROP
- 删索引: 先删索引再删列
- 恢复索引: 重建原来的索引
常用命令
MODULE={module} ENV=dev ./script/migration_new.sh "create_alert_policy"
MODULE={module} ENV=dev ./script/migration_up.sh
MODULE={module} ENV=dev ./script/migration_down.sh
MODULE={module} ENV=dev ./script/migration_status.sh
深入参考
以下内容已拆到 reference.md:
- 新项目从零搭建 MyBatis Migration 的目录结构与 Maven 配置
- 环境配置文件模板、bootstrap.sql 与 shell 脚本模板
- 空白迁移脚本模板
- JSON 字段使用建议
最佳实践
- 一次一变更: 每个脚本只做一个变更(创建表、添加字段等)
- 不可修改已发布脚本: 已部署的脚本不能修改,只能创建新脚本
- 测试回滚: 在非生产环境测试
@UNDO 脚本
- 备份数据: 生产环境执行前备份数据库
Checklist
编写前:
完成后:
常见错误
| 错误做法 | 正确做法 |
|---|
只写正向 SQL,不写 @UNDO | 始终补齐精确逆操作 |
唯一索引不包含 deleted | 逻辑删除场景下把 deleted 纳入唯一约束 |
| 一个脚本混入多类大改动 | 保持一次一变更,便于审计和回滚 |
| 发布后修改旧脚本 | 创建新的迁移脚本修正问题 |