# 无 ORM 遗留项目的数据库迁移系统
在没有 ORM 的遗留系统中,管理 DDL/DML 脚本迁移需要严格控制。这种方法通过组织仓库和状态表,实现变更在测试和生产环境中的一致应用。它确保可追溯性、数据完整性和在支持 ACID 的事务型关系数据库上的可预测部署。
该方法减少了脚本中的样板代码,自动化验证和日志记录。脚本分为四种类型:初始化、基线、版本化和可重复。每种类型遵循特定规则,避免重复并保持版本单调递增。
Git 仓库结构
脚本按类型分组,并按固定顺序应用:
- 环境初始化 — 仅运行一次,用于创建用户、角色、数据库和模式。环境特定(测试/生产),通过 psql 执行。
- 基线 — 在空模式上仅运行一次,建立初始生产版本和控制表。
- 版本化 — 按升序整数版本顺序应用,仅一次,在记录时间戳和用户的交易中执行。
- 可重复 — 如果 SHA256 发生变化或无记录,则在版本化脚本后应用,用于不修改数据的视图/存储过程/触发器。
对象类型:
- 初始化:用户、角色、数据库、模式。
- 基线:表、数据、视图、存储过程、触发器。
- 版本化:模式变更、数据迁移。
- 可重复:视图、存储过程、触发器。
这种结构受 Flyway 启发,但针对无外部工具的手动流程进行了定制。
模式中的状态表
每个模式都有服务表用于跟踪:
- dbmigration_versions (version_id, is_baseline, created_at, created_by, created_from) — 跟踪基线和版本化脚本历史。
- dbmigration_repeatable (sha256sum, relative_path, created_at, created_by, created_from) — 跟踪可重复脚本,支持变更时重新应用。
这些表在运行脚本前强制检查:仅当无记录或校验和变化时才执行脚本。日志捕获用户和时间戳,提供完整审计轨迹。
开发部署
在 CI/CD(GitLab 流水线)中,克隆变更分支,然后针对每个模式:
$ git clone <包含数据库模式变更的 URL>
$ USER_PASSWORD=topsecret123 dbmigration.py update --host <host> --port <port> --dbname <db> --user <user_name> schema1 ./db/schema1
$ USER_PASSWORD=topsecret123 dbmigration.py update --host <host> --port <port> --dbname <db> --user <user_name> schema2 ./db/schema2
这会自动应用待处理脚本,同时保留数据。
生产流程
支持零宕机热部署。在 UAT 中预测试,包括烟雾测试。
步骤:
- 解压归档:
tar xzvf system-x.y.z.tar.gz。 - 进入模式目录:
cd system-x.y.z/schema1。 - 生成迁移脚本:
USER_PASSWORD=topsecret123 dbmigration.py verify --host <host> --port <port> --dbname <db> --user <user_name> --build-update-script ./schema1_migrate.sql schema1 ./db/schema1。 - 检查 schema1_migrate.sql 中的破坏性变更。
- 应用:
PGPASSWORD=topsecret123 psql -h <host> -p <port> -U <user> -d <database> -v schema_name=<schema1> -f "schema1_migrate.sql"。
对每个模式重复。验证模式预览变更而不应用。
关键实践
- 正向修复:使用新迁移修正错误,而非回滚,保留数据。
- 非破坏性变更:先添加表/列,后续发布后移除未用部分。支持同一数据库多版本共存。
- 模式级跟踪:版本按模式跟踪,而非按数据库。
- 预检查:生成脚本供审查。
- 数据保留:增量更新避免 drop/recreate。
关键要点
- 自动化跟踪消除手动样板和脚本错误。
- 带事务的单调版本确保一致状态。
- 通过版本化脚本支持跨版本(生产/UAT/开发)的热修复。
- 表提供完整审计:谁/何时/应用了什么。
- 适用于任何支持 ACID 的 RDBMS。
— Editorial Team
暂无评论。