迁移与 Flyway
schema 版本化、与 backend 迁移思路。
迁移与 Flyway
这一课你将能做到
- 说明 Flyway versioned migration 的文件命名与「已执行不可改」规则
- 对照本站
backend/src/main/resources/migration/(或db/migration)理解演进方式 - 为 PG 练习库写出
V1__init_app_schema.sql级别的首条迁移,并知道与 MySQL 方言分文件
为什么要学
手改库结构无法协作:谁改了什么、生产有没有跑过、回滚如何追踪,都会糊成一团。Flyway(或 Liquibase)把 schema 变更变成版本化脚本,Spring Boot 启动时可自动迁移。
本站用迁移目录管理 MySQL 变更。学 PG 时,逻辑相同、SQL 方言不同——自增、布尔、注释写法都要改。官方 Flyway 文档与 PostgreSQL DDL 章是本课对标。
先建立图像
resources/db/migration/
V1__init_schema.sql ← 只跑一次,记入历史表
V2__add_track_metadata.sql
V3__index_metadata_gin.sql
启动应用 → Flyway 读 flyway_schema_history
→ 按版本号执行「还没跑过」的脚本
→ 记录成功校验和
| 规则 | 含义 |
|---|---|
V{数字}__{描述}.sql | 版本化迁移命名 |
| 已成功执行的脚本 | 禁止改内容;只能新增更高版本 |
| 校验和 | 文件被改会启动失败(防漂移) |
| baseline | 对已有库可标记基线再往前迁 |
跟着做
步骤 1:浏览本站迁移习惯
打开仓库中的迁移目录(常见为 backend/src/main/resources/migration/ 下 V*.sql)与 schema.sql。笔记:
- 基线 schema 与增量
V*如何分工 - 某次为
cf_track加列的脚本长什么样(MySQL 方言)
步骤 2:理解 Spring 配置意图
spring:
flyway:
enabled: true
locations: classpath:db/migration
baseline-on-migrate: true
依赖:spring-boot-starter-flyway + 对应 JDBC 驱动。实验 PG 时,locations 可指到 classpath:db/migration-pg,与 MySQL 脚本隔离。
步骤 3:编写 PG 版 V1
在练习目录创建(路径按你的实验模块调整):
-- V1__init_app_schema.sql (PostgreSQL)
CREATE SCHEMA IF NOT EXISTS app;
CREATE TABLE app.cf_track (
id BIGSERIAL PRIMARY KEY,
slug VARCHAR(64) NOT NULL,
title VARCHAR(255) NOT NULL,
description TEXT,
category VARCHAR(32) NOT NULL DEFAULT 'language',
level VARCHAR(16) NOT NULL DEFAULT 'beginner',
sort_order INT NOT NULL DEFAULT 0,
is_member BOOLEAN NOT NULL DEFAULT FALSE,
metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uq_track_slug UNIQUE (slug)
);
CREATE TABLE app.cf_lesson (
id BIGSERIAL PRIMARY KEY,
track_id BIGINT NOT NULL REFERENCES app.cf_track (id) ON DELETE CASCADE,
slug VARCHAR(64) NOT NULL,
title VARCHAR(255) NOT NULL,
order_index INT NOT NULL DEFAULT 0,
content_md TEXT,
status VARCHAR(16) NOT NULL DEFAULT 'draft',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uq_lesson_track_slug UNIQUE (track_id, slug)
);
CREATE INDEX idx_track_metadata_gin ON app.cf_track USING GIN (metadata);