具有dumpdata和迁移的Django备份策略

时间:2016-01-16 00:11:17

标签: python django backup django-migrations dumpdata

this question一样,我为我的数据库设置了一个基于dumpdata的备份系统。该设置类似于运行调用dumpdata的cron脚本并将备份移动到远程服务器,目的是简单地使用loaddata来恢复数据库。但是,我not sure this plays well with migrationsloaddata现在有一个ignorenonexistent开关来处理已删除的模型/字段,但它无法解决使用一次性默认值添加列或应用RunPython代码的情况。

我看到它的方式,有两个子问题需要解决:

  • 使用每个应用的当前版本标记每个dumpdata输出文件
  • 将灯具拼接到迁移路径

我很难解决如何在不引入大量开销的情况下解决第一个问题。是否足以为每个包含{app_name: migration_number}映射的备份保存额外的文件?

第一个问题解决后,我认为第二个问题更容易解决,因为这个过程大致是:

  1. 创建新数据库
  2. 将迁移向前运行到每个应用的适当位置
  3. 使用给定的夹具文件
  4. 调用loaddata
  5. 运行其余迁移
  6. this question中有一些代码(从错误报告中链接),我认为可以为此目的进行调整。

    由于这些是数据库的相当规则/大型快照,因此我不希望将它们作为数据迁移使迁移目录混乱。

1 个答案:

答案 0 :(得分:4)

我正在采取以下步骤在项目的任何实例之间备份,恢复或传输postgresql数据库:

我们的想法是尽可能减少迁移,就像在空数据库中第一次运行manage.py makemigrations一样。

假设我们的开发环境有一个可用的数据库。此数据库是生产数据库的当前副本,不应对任何更改开放。我们添加了模型,更改了属性等,这些操作已经生成了额外的迁移。

现在数据库已准备好迁移到生产环境 - 如前所述 - 不向公众开放,因此不会以任何方式进行更改。为了实现这个目标:

  • 我在开发环境中执行正常过程
  • 我将项目复制到生产环境。
  • 我执行正常程序到生产环境

但是,这意味着在我们的开发环境中进行更改时,生产数据库不会发生任何更改,因为它们将被覆盖

正常程序

在其他任何事情之前,我有项目目录的备份(包括requirements.txt文件),数据库的备份 - 当然 - git是我的朋友。

  1. 我需要dumpdata备份以备不时之需,但它有一些 serius limitations有关内容类型,权限或其他情况{应该使用{3}}:

    ./manage.py dumpdata --exclude auth.permission --exclude contenttypes  --exclude admin.LogEntry --exclude sessions --indent 2 > db.json
    
  2. 我使用pg_dump备份:

    pg_dump -U $user -Fc $database --exclude-table=django_migrations > path/to/backup-dir/db.dump
    
  3. 我从每个应用程序中删除所有迁移。

    在我的情况下,migrations文件夹是符号链接,因此我使用以下脚本:

    #!/bin/bash
    for dir in $(find -L -name "migrations")
    do
      rm -Rf $dir/*
    done
    
  4. 我删除并重新创建数据库:

    例如,bash脚本可以包含以下命令:

    su -l postgres -c "PGPASSWORD=$password psql -c 'drop database $database ;'"
    su -l postgres -c "createdb --owner $username $database"
    su -l postgres -c "PGPASSWORD=$password psql $database -U $username -c 'CREATE EXTENSION $extension ;'"
    
  5. 我从转储中恢复数据库:

    pg_restore -Fc -U $username -d $database path/to/backup-dir/db.dump
    
  6. 我按以下方式创建迁移:

    ./manage.py makemigrations <app1> <app2> ... <appn>
    

    ...使用以下脚本:

    #!/bin/bash
    apps=()
    for app in $(find ./ -maxdepth 1 -type d ! -path "./<project-folder> ! -path "./.*" ! -path "./")
    do
      apps+=(${app#??})
    done
    all_apps=$(printf "%s "  "${apps[@]}")
    
    ./manage.py makemigrations $all_apps
    
  7. 我使用虚假迁移进行迁移:

    ./manage.py migrate --fake
    
  8. 如果出现问题,一切都是***,(确实可能发生这种情况),我可以使用备份将所有内容恢复到以前的工作状态。如果我想使用第一步中的db.json文件,它会是这样的:

    当pg_dump或pg_restore失败时

    我执行了以下步骤:

    • 3(删除迁移)
    • 4(删除并重新创建数据库)
    • 6(makemigrations)

    然后:

    • 应用迁移:

      ./manage.py migrate
      
    • 从db.json加载数据:

      ./manage.py loaddata path/to/db.json
      

    然后我试着找出为什么我以前的努力没有成功。

    成功执行步骤后,我将项目复制到服务器并对该框执行相同的操作。

    这样,我始终保持最少的迁移次数,并且我可以将pg_dumppg_restore用于共享同一项目的任何框。