直接用SQL文件名做版本号不可靠,因重命名、手动修改内容未更新版本号、多分支编号冲突等问题频发;Flyway核心在于记录已执行版本并校验内容一致性。

为什么直接用 SQL 文件名做版本号不可靠
很多人以为给迁移文件起名 V1__init.sql、V2__add_user_index.sql 就算版本管理了,但实际运行时会出问题:SQL 文件被重命名、手动修改内容却没改版本号、多个分支并行开发导致编号冲突——Flyway 的核心不是“有编号”,而是“记录已执行的版本+校验内容一致性”。PHP 项目里若只靠文件名和人工维护,schemas_history 表缺失或错乱后,flyway repair 这类操作根本不存在,只能删库重跑。
用 phinx 替代手写迁移逻辑更稳妥
phinx 是 PHP 社区最接近 Flyway 行为的工具:它自动生成带时间戳的迁移文件(如 20230405123456_add_posts_table.php),强制要求实现 up() 和 down() 方法,并在数据库中维护 phoenix_migrations 表记录执行状态与 checksum。它不依赖 SQL 文件内容文本比对,而是对迁移类的 getVersion() 返回值做唯一索引,避免重复执行。
- 安装:
composer require robmorgan/phinx - 初始化配置:
vendor/bin/phinx init,编辑phinx.yml填好environments.development的host/name/user - 生成迁移:
vendor/bin/phinx create AddPostsTable,然后在生成的 PHP 类里写 Schema 操作 - 执行迁移:
vendor/bin/phinx migrate -e development
注意:不要手动修改已提交的迁移文件内容,checksum 不匹配会导致 Migration has been modified after being run 报错;要修复必须用 vendor/bin/phinx rollback -t 20230405123456 回退再重写。
如果坚持手撸迁移器,必须实现 checksum 校验
自己写迁移管理器时,最容易忽略的是“同一版本 SQL 被二次修改却未触发重执行”。Flyway 用 SHA256 对 SQL 内容哈希并存入 installed_rank 表的 checksum 字段。PHP 中可用 hash_file('sha256', $sqlPath) 实现,但要注意:
- SQL 文件末尾换行符、BOM、注释变动都会改变哈希值
- 不能只校验文件存在,得比对数据库中该版本的
checksum是否一致 - 执行前必须先查
SELECT checksum FROM schema_version WHERE version = ?,不一致就中止并报错Checksum mismatch for version X - 首次插入记录时,
type字段应设为SQL,description取文件注释里的第一行(如-- Add index on user.email)
phinx 不支持跨库迁移,多租户场景需额外隔离
当一个 PHP 应用服务多个客户(每个客户独立数据库),phinx 默认只认一个 environments 配置。强行切换 DB 连接后执行迁移,phoenix_migrations 表会写到错误库中。解决方案只有两个:
- 为每个租户生成独立
phinx.yml配置文件,用-c参数指定:vendor/bin/phinx migrate -c phinx_tenant_a.yml -e production - 改写
Phinx\Db\Adapter\PdoAdapter子类,在getConnection()中动态注入租户 DB 连接,并确保getSchemaTableName()返回带库前缀的表名(如tenant_a.phoenix_migrations)
别指望用 USE tenant_db 切库来绕过——phinx 的 DDL 操作(如 CREATE TABLE)不走当前连接上下文,它会显式拼接库名。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











