如何让Django加载pg_dump后仅执行新增数据库迁移?
我完全能理解你遇到的这个头疼问题——为了搞定测试套件迁移耗时太长的问题,手动生成了pg_dump文件用来初始化测试数据库,结果后来新增了几个迁移,跑python manage.py migrate的时候Django居然像没见过这个dump似的,把所有迁移从头执行一遍,之前优化的速度又打回原形。
好在你后来找到了问题根源:dump文件没有正确加载到测试数据库中,这确实是这类问题最常见的原因。下面我再把整个逻辑和解决步骤理清楚,方便你后续集成到CI系统里:
核心原因拆解
Django是靠数据库里的django_migrations表来追踪哪些迁移已经执行过的。如果你的测试数据库没有加载包含这个表完整记录的dump,Django就会默认所有迁移都没执行过,自然会从头跑一遍所有迁移。
具体解决步骤
确保dump文件包含关键的迁移记录
手动生成pg_dump时,一定要确保导出了全库数据(至少包含django_migrations表),别用只导出部分表的参数。标准的导出命令是:pg_dump -U 你的数据库用户名 -d 目标数据库名 > test_dump.sql导出后可以检查一下dump文件里有没有
django_migrations相关的插入语句,确认迁移记录都被包含在内。在migrate前完成dump的加载
不管是本地测试还是CI流程里,都要保证在执行migrate命令之前,已经把dump加载到测试数据库中。比如可以写个简单的启动脚本:# 创建测试数据库(如果不存在) createdb -U 测试库用户名 测试库名 # 清空测试库原有数据(可选,确保干净) psql -U 测试库用户名 -d 测试库名 -c "DROP SCHEMA public CASCADE; CREATE SCHEMA public;" # 加载dump文件 psql -U 测试库用户名 -d 测试库名 -f test_dump.sql这一步必须在
python manage.py migrate之前执行,让Django启动时看到的是已经有完整迁移记录的数据库。运行migrate只会执行新增迁移
当dump正确加载后,再执行migrate命令,Django会自动对比django_migrations里的记录和你本地的迁移文件,只会执行那些dump生成之后新增的迁移,不会再从头跑一遍所有流程:python manage.py migrate --settings=你的项目.测试配置文件
后续CI集成建议
等你把这套流程搬到CI系统时,可以把dump的生成也自动化——比如每次主分支合并或者发布后,自动生成最新的pg_dump并存储到CI的缓存或者对象存储里。测试阶段直接拉取这个最新dump加载,再跑新增迁移,这样既能保证测试库和生产/预发布环境的状态一致,又能省去手动维护dump的麻烦。
内容的提问来源于stack exchange,提问作者MyCoolAwsomeName

