Flyway:Java 数据库版本控制迁移

FreeGuideOnline 最新 2026-06-30

xml org.flywaydb flyway-maven-plugin 9.22.3 jdbc:mysql://localhost:3306/mydb root secret

- **Gradle** 在 `build.gradle` 中加入:
```groovy
plugins {
    id 'org.flywaydb.flyway' version '9.22.3'
}
flyway {
    url = 'jdbc:mysql://localhost:3306/mydb'
    user = 'root'
    password = 'secret'
}

方式三:Spring Boot 自动配置

Spring Boot 对 Flyway 提供了开箱即用的支持。只需在 application.yml 中配置数据源和 Flyway 基础选项:

spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/mydb
    username: user
    password: pass
  flyway:
    enabled: true
    locations: classpath:db/migration

同时,在 src/main/resources/db/migration 目录下放置迁移脚本,应用启动时便会自动执行迁移。

迁移脚本的命名规则

Flyway 通过严格的命名约定来识别脚本版本、顺序和功能。一个标准的 SQL 迁移文件名格式为:

V<版本号>__<描述>.sql

例如:

V1__Create_person_table.sql
V2__Add_age_column.sql
V3.1__Seed_person_data.sql

命名要点:

  • 前缀V 代表版本迁移(Versioned),R 代表可重复迁移(Repeatable),U 代表撤销迁移(Undo – 商业版)。
  • 版本号:可用数字、点号分隔,如 1, 1.1, 2.0 等。Flyway 按版本号的数值次序执行。
  • 双下划线:版本号与描述之间必须使用两个下划线 __ 分隔。
  • 描述:用下划线或空格分隔单词,清晰表达变更内容。
  • 扩展名.sql,支持占位符替换等特性。

可重复迁移 R

R__描述.sql 命名的脚本会在每次内容(checksum)发生变化时重新执行,适合存储过程、视图等需要反复部署的对象。

第一个 Flyway 迁移演示

假设我们有一个 PostgreSQL 空数据库 mydb

1. 创建迁移脚本

在 Flyway 的 sql 迁移目录(默认安装目录下的 sql 文件夹,或项目中的 db/migration)新建文件: V1__Create_person_table.sql

CREATE TABLE person (
    id SERIAL PRIMARY KEY,
    first_name VARCHAR(50) NOT NULL,
    last_name VARCHAR(50) NOT NULL
);

2. 执行迁移

命令行中执行:

flyway migrate

输出类似:

Database: jdbc:postgresql://localhost:5432/mydb (PostgreSQL 14)
Schema history table "public"."flyway_schema_history" does not exist yet
Successfully validated 1 migration (execution time 00:00.012s)
Creating Schema History table ...
Current version of schema "public": << Empty Schema >>
Migrating schema "public" to version "1 - Create person table"
Successfully applied 1 migration to schema "public" (execution time 00:00.033s)

3. 查看状态

执行 flyway info 可以查看所有迁移的状态:

+-----------+---------+---------------------+------+---------------------+---------+
| Category  | Version | Description         | Type | Installed On        | State   |
+-----------+---------+---------------------+------+---------------------+---------+
| Versioned | 1       | Create person table | SQL  | 2025-03-20 14:25:00 | Success |
+-----------+---------+---------------------+------+---------------------+---------+

常用 Flyway 命令

命令 说明
migrate 扫描迁移目录,执行所有未应用的版本迁移脚本
info 打印所有迁移的详细信息与当前状态
validate 校验已应用的迁移脚本是否被篡改,以及是否有未应用的迁移
baseline 为已有数据库设置一个基准版本,让 Flyway 从该版本开始管理(忽略之前的脚本)
repair 修复元数据表,比如重新计算校验和、删除失败的迁移记录等
clean 清理数据库中的所有对象(表格、视图等),慎用,通常只在开发环境使用

与 Spring Boot 深度集成

在实际的 Spring Boot 项目中,Flyway 几乎是无感的。

目录约定

将 SQL 脚本放在 src/main/resources/db/migration 下,Spring Boot 自动扫描并执行。支持多个位置的配置:

spring.flyway.locations: classpath:db/migration, classpath:db/specific-migration

执行时机

默认情况下,Flyway 在 Spring 应用上下文初始化数据源之后、JPA/Hibernate 等 ORM 生成 DDL 之前执行,确保数据库结构先存在。

自定义配置

spring:
  flyway:
    baseline-on-migrate: true   # 当数据库非空时,自动进行基线操作
    baseline-version: 0
    placeholders:
      app_name: MyApp           # 在SQL中使用 ${app_name}
    out-of-order: false         # 是否允许执行顺序与版本号不一致的脚本
    ignore-migration-patterns: "*:missing"  # 忽略缺失的迁移(谨慎)

使用 Java 迁移

除了 SQL,Flyway 支持基于 Java 的迁移(适用于需要复杂逻辑的变更):

package db.migration;

import org.flywaydb.core.api.migration.BaseJavaMigration;
import org.flywaydb.core.api.migration.Context;

public class V2__Add_initial_data extends BaseJavaMigration {
    public void migrate(Context context) throws Exception {
        // 通过 context.getConnection() 执行自定义操作
    }
}

该类也需要放在 db/migration 包下,命名规则同样遵循 V<version>__Description

实践中的版本控制策略

  1. 版本号递增原则:已合并到主分支的脚本版本号只能新增,不能修改或删除。如需回滚,应编写新的迁移脚本。
  2. 开发分支的脚本命名:多人开发时,不同功能分支使用不同的版本号区间(如 V1000__, V2000__),合并前再统一重编号。
  3. 可重复迁移的使用:存储过程、触发器、视图等频繁变动的对象使用 R__ 前缀脚本,每次修改内容即可重新执行。
  4. 种子数据:测试数据可通过版本迁移脚本插入,也可放在可重复迁移中,但需注意幂等性。

Flyway 的校验与修复

当已执行的迁移脚本内容被修改时,再次运行 migrate 会校验失败:

Migration checksum mismatch for migration version 1
-> Applied to database : -1783829361
-> Resolved locally    : 1890921433