生产库与开发库迁移进度不一致的本质是doctrine_migration_versions表状态不同步,解决关键在于统一迁移历史与实际结构的对应关系,而非直接拉平结构;需先用doctrine:migrations:status和doctrine:schema:validate验证真实差异,再按场景执行migrate、execute或sync-metadata-storage等命令修正。

生产库和开发库迁移进度不一致,本质是两个环境的 doctrine_migration_versions 表状态不同步,而不是“数据库结构差异”本身。解决的关键不是强行拉平结构,而是统一迁移历史记录与实际结构的对应关系。
先确认真实差异在哪
别猜,用命令验证:
- 在开发库运行:
php bin/console doctrine:migrations:status --show-versions,记下已执行的最新版本号(如Version20260310190500) - 在生产库同样执行该命令,对比“Executed migrations”列表——缺了哪些?多了哪些?
- 再跑
php bin/console doctrine:schema:validate,看是否提示“mapping”或“database”不一致。只有这里报错,才说明结构真有问题;如果只报“migration list is not up to date”,那只是版本表没对齐。
常见场景及对应处理方式
场景一:生产库漏执行了某些迁移
开发库有 VersionA、VersionB、VersionC,生产库只执行到 VersionB。
- 直接在生产环境执行:
php bin/console doctrine:migrations:migrate --no-interaction --allow-no-migration --env=prod - 务必提前备份生产库,并确保迁移文件在生产部署包中存在(检查
migrations/目录) - 若某次迁移含数据变更(如 UPDATE),需确认 SQL 在生产数据量下是否安全;必要时改用手动 SQL 或分批脚本
场景二:生产库多执行了某次迁移(比如临时手动改表后又生成了迁移)
开发库没这个版本,但生产库已标记为“executed”。
- 禁止删
doctrine_migration_versions表里的记录——这会破坏迁移链完整性 - 正确做法:在开发环境补上对应迁移文件(可从生产服务器复制),再执行
doctrine:migrations:execute --up [version]标记为已执行(不执行 SQL),保持两边版本表一致 - 后续 diff 时 Doctrine 才能正确识别起点
场景三:两边结构一致,但版本表混乱(如空迁移被误执行、版本号跳变)
- 运行
php bin/console doctrine:migrations:sync-metadata-storage,强制将版本表状态与当前 migrations 目录对齐(仅当确认结构无误时使用) - 该命令不会改动数据库结构,只修正
doctrine_migration_versions表中的 version 和 executed_at 字段 - 执行前确保所有迁移文件都存在于代码仓库且未被修改哈希值
预防下次再出问题
迁移不一致几乎全是流程问题,不是技术问题:
- 所有迁移必须通过 CI/CD 流水线自动执行,禁止人工登录生产服务器跑 migrate 命令
- 每次上线前,在部署脚本里加入校验步骤:
php bin/console doctrine:migrations:status --no-interaction | grep "No available migrations",失败则中断发布 - 开发环境每次
git pull后,先跑doctrine:migrations:sync-metadata-storage再开始写新功能,避免本地版本表滞后 - 团队约定:迁移文件生成后立即提交,绝不“先存着等上线一起跑”











