Files
SuperBizAgent-java/knowledge_base/infrastructure/flyway-best-practices.md
T
zhuyongxin 3956426c97 docs(knowledge): 添加测试知识库文档
新增 6 个知识库文档,用于测试 L0+L1 混合检索功能:

API 类:
- payment-errors.md - 支付网关错误码定义

领域知识类:
- spring-ai-tool-best-practices.md - Spring AI 工具定义最佳实践

基础设施类:
- redis-config.md - Redis 缓存配置指南
- mysql-connection-pool.md - MySQL 连接池配置
- flyway-best-practices.md - Flyway 数据库迁移最佳实践

故障排查类:
- fault-diagnosis-process.md - 故障诊断流程规范

所有文档均包含:
- 标准 frontmatter 元数据 (title, keywords, summary, category)
- 实用配置示例和代码片段
- 支持 L0 精确匹配的关键词
2026-06-24 16:19:10 +08:00

6.5 KiB
Raw Blame History

title, keywords, summary, category
title keywords summary category
Flyway 数据库迁移最佳实践
Flyway
数据库迁移
版本管理
schema
migration
Flyway 数据库迁移的命名规范、编写技巧、回滚策略和常见问题处理 infrastructure

Flyway 数据库迁移最佳实践

命名规范

标准格式

V{version}__{description}.sql

示例:
V001__create_user_table.sql
V002__add_email_to_user.sql
V003__create_order_table.sql
V004__add_metadata_to_api_document.sql

规则:

  • V 大写,表示 Versioned migration
  • 版本号用 3 位数字(001, 002...)
  • 两个下划线 __ 分隔版本号和描述
  • 描述用小写字母和下划线

版本号管理

V001 - 初始表结构
V002 - 添加字段
V003 - 创建索引
V004 - 修改字段类型
...

建议:

  • 预留版本号空间(001, 010, 020...)
  • 紧急修复用中间号(V005_hotfix__...)

SQL 编写规范

添加列

-- ✅ 好的写法 - 包含默认值和注释
ALTER TABLE user 
ADD COLUMN email VARCHAR(100) DEFAULT '' COMMENT '用户邮箱';

-- ❌ 不好的写法 - 缺少默认值
ALTER TABLE user 
ADD COLUMN email VARCHAR(100);  -- 已有数据会是 NULL

修改列

-- ✅ 先添加新列,再迁移数据,最后删除旧列
ALTER TABLE user ADD COLUMN new_status VARCHAR(20) DEFAULT 'active';
UPDATE user SET new_status = old_status WHERE old_status IS NOT NULL;
ALTER TABLE user DROP COLUMN old_status;
ALTER TABLE user CHANGE COLUMN new_status status VARCHAR(20);

-- ❌ 直接修改 - 可能导致数据丢失
ALTER TABLE user MODIFY COLUMN status INT;

创建索引

-- ✅ 指定索引名称
CREATE INDEX idx_user_email ON user(email);
CREATE INDEX idx_order_user_id ON `order`(user_id);

-- ❌ 不指定名称 - 自动生成的名称难以管理
CREATE INDEX ON user(email);

外键约束

-- ✅ 命名规范
ALTER TABLE `order`
ADD CONSTRAINT fk_order_user_id 
FOREIGN KEY (user_id) REFERENCES user(id)
ON DELETE CASCADE;

-- ❌ 不指定名称
ALTER TABLE `order`
ADD FOREIGN KEY (user_id) REFERENCES user(id);

幂等性保证

检查表是否存在

-- 创建表前检查
CREATE TABLE IF NOT EXISTS user (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) NOT NULL
);

检查列是否存在

-- 添加列前检查
ALTER TABLE user 
ADD COLUMN IF NOT EXISTS email VARCHAR(100);

-- 或使用存储过程(MySQL < 8.0)
SET @col_exists = (
    SELECT COUNT(*) FROM information_schema.columns 
    WHERE table_name = 'user' AND column_name = 'email'
);

SET @query = IF(@col_exists = 0, 
    'ALTER TABLE user ADD COLUMN email VARCHAR(100)', 
    'SELECT "Column exists" AS msg'
);

PREPARE stmt FROM @query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

检查索引是否存在

CREATE INDEX IF NOT EXISTS idx_user_email ON user(email);

数据迁移

分批处理大表

-- ❌ 一次更新全部 - 可能锁表很久
UPDATE large_table SET status = 'active' WHERE status IS NULL;

-- ✅ 分批更新
UPDATE large_table 
SET status = 'active' 
WHERE status IS NULL 
LIMIT 1000;

-- 重复执行直到影响行数为 0

使用事务(DDL 语句除外)

START TRANSACTION;

UPDATE user SET status = 'active' WHERE status = 'enabled';
UPDATE user SET status = 'inactive' WHERE status = 'disabled';

COMMIT;

回滚策略

不支持自动回滚

Flyway 社区版不支持自动回滚,需要手动编写撤销脚本:

-- V005__add_email_to_user.sql
ALTER TABLE user ADD COLUMN email VARCHAR(100);

-- V005__add_email_to_user.undo.sql (手动执行)
ALTER TABLE user DROP COLUMN email;

建议使用新版本修复

-- V005 出错了,不要回滚
-- 而是创建 V006 修复

-- V006__fix_user_email.sql
ALTER TABLE user MODIFY COLUMN email VARCHAR(200);

常见问题

问题 1: 迁移失败后状态卡住

症状:

FlywayException: Migration failed!
Schema history table shows failed migration.

解决:

-- 查看迁移历史
SELECT * FROM flyway_schema_history ORDER BY installed_rank DESC;

-- 删除失败记录
DELETE FROM flyway_schema_history WHERE version = '005' AND success = 0;

-- 修复 SQL 脚本后重新启动

问题 2: Checksum 不匹配

症状:

FlywayException: Checksum mismatch for migration version 005

原因:迁移脚本被修改了

解决:

-- 方案 1: 修复 checksum(仅开发环境)
UPDATE flyway_schema_history 
SET checksum = NULL 
WHERE version = '005';

-- 方案 2: 创建新版本(推荐)
-- 不要修改已执行的迁移脚本,创建 V006

问题 3: 多个开发者同时创建迁移

场景:

  • 开发者 A 创建 V005
  • 开发者 B 创建 V005
  • 冲突!

预防:

使用时间戳版本号:
V20260624001__add_user_email.sql
V20260624002__add_order_index.sql

生产环境最佳实践

1. 先验证后应用

# 开发环境测试
mvn flyway:migrate

# 预生产环境验证
mvn flyway:migrate -Dflyway.url=jdbc:mysql://pre-prod-db:3306/db

# 生产环境应用
mvn flyway:migrate -Dflyway.url=jdbc:mysql://prod-db:3306/db

2. 备份数据库

# 应用迁移前备份
mysqldump -u root -p superbiz_agent > backup_before_v005.sql

# 应用迁移
mvn spring-boot:run

# 出问题时恢复
mysql -u root -p superbiz_agent < backup_before_v005.sql

3. 限制自动迁移

# 生产环境配置
spring:
  flyway:
    enabled: false  # 禁用自动迁移

# 手动触发
mvn flyway:migrate -Dspring.profiles.active=prod

4. 监控迁移时间

SELECT version, description, type, installed_on, execution_time
FROM flyway_schema_history
ORDER BY installed_rank DESC
LIMIT 10;

工具和命令

Maven 命令

# 查看迁移信息
mvn flyway:info

# 执行迁移
mvn flyway:migrate

# 验证迁移
mvn flyway:validate

# 清空数据库(危险!仅开发环境)
mvn flyway:clean

配置文件

spring:
  flyway:
    enabled: true
    baseline-on-migrate: true  # 已有数据库时从当前版本开始
    locations: classpath:db/migration
    table: flyway_schema_history
    validate-on-migrate: true

团队协作规范

  1. 迁移脚本不可修改:已合并的脚本禁止修改
  2. 版本号递增:新脚本必须比最新版本号大
  3. 命名规范统一:遵循 V{version}__{description}.sql
  4. Code Review:迁移脚本必须经过审查
  5. 测试覆盖:每个迁移都要测试(空库 + 有数据)