如何用迁移管理数据库变更?

wen PHP项目 75

本文目录导读:

如何用迁移管理数据库变更?

  1. 核心概念
  2. 为什么使用迁移?
  3. 常用迁移工具(按语言/环境分类)
  4. 通用工作流程(以 Flyway 或通用模式为例)
  5. 最佳实践与注意事项

迁移是一种用于管理数据库结构变更(Schema 变更)的成熟方法,它的核心思想是将数据库的每一次变更(如创建表、添加字段、修改索引)都视为一次代码级别的“版本记录”,像 Git 管理代码一样管理数据库。

以下是关于如何使用迁移管理数据库变更的详细指南,涵盖了核心概念、常用工具、工作流程和最佳实践。

核心概念

  1. 迁移文件:一个包含 SQL 或特定代码的文件,描述了一次具体的数据库变更。
    • Up 操作:执行变更(ALTER TABLE users ADD COLUMN age INT;)。
    • Down 操作:回滚变更(ALTER TABLE users DROP COLUMN age;)。
  2. 版本表:数据库中专门用于记录哪些迁移文件已经被执行过的表(通常叫 _migrationsschema_migrations)。
  3. 状态
    • 待定:迁移文件已创建,但尚未应用到数据库。
    • 已应用:迁移文件已成功执行,并在版本表中记录了版本号。
    • 回滚:撤销已应用的迁移。

为什么使用迁移?

  • 版本控制:数据库变更与应用程序代码一起纳入 Git 等版本控制系统,实现了真正的“基础设施即代码”。
  • 可追溯:任何人都可以查看迁移历史,清楚地知道数据库从创建到现在经历的所有变更。
  • 可复现:从零开始,只需运行所有迁移文件,就能构建出与生产环境一致的数据库结构。
  • 团队协作:团队成员无需手动同步数据库,只需拉取代码并运行迁移命令即可。
  • 可回滚:如果新版本出现问题,可以快速、安全地回滚到前一个数据库状态。

常用迁移工具(按语言/环境分类)

  • 通用 / 云原生
    • Flyway:基于 Java,但兼容性极强,支持 SQL 脚本,社区非常活跃。
    • Liquibase:基于 XML/YAML/JSON/SQL 描述变更,功能强大,适合复杂企业级场景。
  • 后端框架内置
    • Ruby on Rails:Active Record Migrations(最经典的实现)。
    • Djangopython manage.py makemigrationsmigrate
    • Laravelphp artisan make:migration
    • Node.js (Sequelize, TypeORM, Prisma):各有自己的迁移系统。
    • Go (golang-migrate, goose):常用的数据库无关的迁移库。
    • Python:Alembic(专为 SQLAlchemy 设计)。
  • 数据库管理工具
    • Sqitch:纯 SQL,应用名称“版本控制数据库”,设计哲学非常独特。

通用工作流程(以 Flyway 或通用模式为例)

假设你有一个使用 Flyway 管理的项目,数据库是 PostgreSQL。

步骤 1:初始化项目 在你的项目中创建一个目录(如 db/migrations),用于存放所有迁移文件。

步骤 2:创建你的第一个迁移文件 文件命名规则通常包含版本号描述操作(如 up/down),Flyway 的通用命名是 V<版本号>__<描述>.sql

  • 文件名V1__create_users_table.sql
  • (Up)
    CREATE TABLE users (
        id BIGSERIAL PRIMARY KEY,
        name VARCHAR(255) NOT NULL,
        email VARCHAR(255) UNIQUE NOT NULL,
        created_at TIMESTAMP NOT NULL DEFAULT NOW()
    );
  • (Down)
    DROP TABLE IF EXISTS users;

注意:Flyway 社区版原生支持 Up 和 Down 脚本的方式,但通常它直接通过 undo 命令或多文件模式处理回滚,最简方式是 Up 文件单独存在,Down 文件额外创建。

步骤 3:应用迁移 运行命令 flyway migrate,Flyway 会:

  1. 检查数据库的 flyway_schema_history 表(如果不存在则创建)。
  2. 比较本地迁移文件版本和已执行的版本。
  3. 按顺序执行所有未执行的迁移文件(V1__...)。
  4. 记录 V1 已执行,变更生效。

步骤 4:团队协作

  • 团队成员 git pull 获取最新的 V1__create_users_table.sql
  • 他们运行 flyway migrate(或者 flyway info 查看待定状态),系统会自动应用缺失的迁移。
  • 数据库结构保持一致。

步骤 5:处理变更迭代 你需要添加一个 age 字段。

  • 文件 2:V2__add_age_to_users.sql
  • Up
    ALTER TABLE users ADD COLUMN age INT NOT NULL DEFAULT 0;
  • Down
    ALTER TABLE users DROP COLUMN age;
  • 再次运行 flyway migrate,系统会识别出 V1 已应用,只执行 V2

步骤 6:回滚(如果出现问题) 假设你发现 V2 的修改存在错误。

  • 运行 flyway undo(如果工具支持)或手动执行 V2__add_age_to_users.sql 中 Down 部分的 SQL。
  • 数据库恢复为 V1 的状态。
  • 你可以修改 V2 的代码,或者创建一个 V3 来修复问题。

最佳实践与注意事项

  1. 一次只改一件事:每个迁移文件应该只完成一个逻辑变更(只添加一个字段,而不是同时添加字段和修改索引),这有助于排查问题和回滚。
  2. 永远不要修改已合并到主分支的迁移文件:迁移文件是“只追加”的,如果你需要修改一个已上线的变更,请创建一个新的迁移文件V3__fix_age_column_type.sql),而不是去改 V2,否则会导致版本校验失败,团队同事也会遇到冲突。
  3. 保持迁移文件幂等(如果需要):对于像 Flyway 这样支持重复迁移的工具,可以编写幂等的 SQL(CREATE TABLE IF NOT EXISTS),但通常不建议依赖这一点,最好明确版本。
  4. 测试 Down 迁移:在开发环境中,确保你的 Down 脚本真的能够成功撤销 Up 操作,并且不会丢失关键业务数据(Down 脚本会备份或确认无数据冲突)。
  5. 自动化 CI/CD 集成
    • 在持续集成流水线中,每次代码提交后,可以使用测试数据库运行所有的迁移,以确保没有冲突或 SQL 错误。
    • 在生产环境部署时,将迁移作为部署流水线的一个步骤(先迁移数据库,再部署新应用代码,或反过来,取决于具体情况,但通常建议先迁移代码兼容,再迁移数据库结构先迁移数据库结构,再部署新代码)。
  6. 处理数据迁移:迁移也适合处理数据变更(如:UPDATE users SET status='active' WHERE status IS NULL),但要注意,这种迁移需要更谨慎,因为回滚可能更复杂(需要 UPDATE 回去)。
  7. 使用代码版本:迁移文件的版本号通常与代码版本无关,是连续的整数或时间戳,不要用 Git 的 Commit ID 直接用,容易混乱。
传统手动变更 使用迁移管理
在数据库命令行直接 ALTER TABLE 在 IDE 中写 V2__...sql 文件
团队不知道谁改了 代码版本控制,有历史记录
新同事需要手动导入 SQL 文件 运行 migrate 命令自动构建
回滚需要去备份恢复 运行 undo 或对应的 Down 脚本
部署时容易遗漏或顺序错误 按顺序自动执行,有校验机制

一句话总结:迁移就是“将数据库的变更做成代码版本,用工具来按顺序执行和回滚”,选一个你项目语言生态里成熟、文档全的工具(如 Flyway 或框架自带的),严格遵循“只追加不修改”的原则,配合 CI/CD 自动化,就能稳定地驾驭数据库变更。

抱歉,评论功能暂时关闭!