【问题标题】:Django: What are the best practices to migrate a project from sqlite to PostgreSQLDjango:将项目从 sqlite 迁移到 PostgreSQL 的最佳实践是什么
【发布时间】:2011-03-29 10:38:18
【问题描述】:

我需要将一个复杂的项目从 sqlite 迁移到 PostgreSQL。 很多人似乎都有外键、数据截断等问题......

  • 是否有全自动实用程序?
  • 迁移前是否需要检查一些数据或架构?

编辑:我试过 django-command-extensions DumpScript 但它不能在我的 带有我当前数据集的 2GB RAM PC。

【问题讨论】:

    标签: django sqlite postgresql data-migration


    【解决方案1】:

    根据我的经验,从 SQL 转储和恢复无法正常工作。

    您应该遵循以下顺序:

    1.将数据库内容转储到 json

    $ ./manage.py dumpdata > dump.json
    

    2。在settings.py中切换后端

    DATABASES = {
        # COMMENT OUT:
        # 'default': dj_database_url.config(default='sqlite:////full/path/to/your/database/file.sqlite'),
        # ADD THIS INSTEAD:
        'default': dj_database_url.config(default='postgres://localhost:5432/postgres_db_name'),
    }
    

    3.同步db并将新数据库迁移到同一个表结构

    $ ./manage.py syncdb
    $ ./manage.py migrate
    

    4.将 json 加载到新的数据库中。

    $ ./manage.py loaddata dump.json
    

    5.恭喜!现在新数据在您的 postgres 数据库中。

    【讨论】:

    • 小心,这仅适用于较小的数据库大小stackoverflow.com/questions/23047766。 loaddata 似乎将整个 json 加载到 RAM 中
    • 这会导致错误:django.db.utils.IntegrityError: 安装夹具“dump.json”时出现问题:无法加载 contenttypes.ContentType(pk=3):重复键值违反唯一约束“django_content_type_app_label_76bd3d3b_uniq " DETAIL: Key (app_label, model)=(auth, group) 已经存在。
    • 关于我上次评论中的错误,您似乎 需要 应用 'TRUNCATE django_content_type CASCADE;' 之前 使用加载数据。 @Nimo 你能更新你的答案吗?
    • @matandked 我遇到了同样的问题。我可以将您的修复编辑到答案中,但是当答案不一定有任何问题时,我不确定编辑的礼仪。
    • @matandked dumpdata --natural-primary --natural-foreign 会避免你这个问题,将它添加到答案中
    【解决方案2】:

    以下是对 Django 1.7+ 的 Nimo's answerStephen's answer 的改进:

    1. ./manage.py dumpdata --natural-primary --natural-foreign > dump.json
    2. settings.py 中的 DATABASES 更改为指向新的 (PostgreSQL) 数据库。
    3. ./manage.py migrate
    4. ./manage.py loaddata dump.json

    我遇到的一个问题是,SQLite 似乎并没有真正强制CharFields 的最大长度。就我而言,这使loaddata 步骤失败。我能够通过以下方式找到(并删除)CharField 值过长的模型实例:

    MyModel.objects.extra(where=["LENGTH(text) > 20"]).delete()
    

    一旦我在上述第 1 步之前执行此操作,一切正常。

    【讨论】:

    • 这里的一个问题是迁移写入数据(例如默认内容类型)。我迁移,然后刷新,然后将索引截断回零,然后加载数据。有很多东西要记住——我总是忘记一些东西——但效果很好。
    • 这个答案比大多数人都好,因为使用dumpdata > dump.json 并不适用于所有情况。
    【解决方案3】:

    我从来不需要这样做,但我会尝试的是。

    1. 停止运行服务器
    2. python manage.py 转储数据
    3. 更改 settings.py 以指向新创建的 postgres 数据库
    4. python manage.py 加载数据

    【讨论】:

    • python manage.py dumpdata -> 我的 PC 内存不足...如果我逐个尝试应用程序会更好,但导入不起作用。
    【解决方案4】:

    根据@Nimo 的回答,使用"syncdb",在Django 1.9 及更高版本中不起作用(适用于Django 1.7

    改为使用以下命令:

    python manage.py migrate


    这里是 Postgres 设置配置:

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'NAME': 'myproject',
            'USER': 'myprojectuser',
            'PASSWORD': 'password',
            'HOST': 'localhost',
            'PORT': '',
        }
    }
    

    【讨论】:

      【解决方案5】:

      另一种方法是使用多个数据库。

      http://docs.djangoproject.com/en/dev/topics/db/multi-db/

      阅读本节很重要。

      http://docs.djangoproject.com/en/dev/topics/db/multi-db/#moving-an-object-from-one-database-to-another

      据我了解,这意味着如果您的新数据库中没有数据,例如您可以从固定装置中获取数据

      queryset = MyModel.objects.using("old-db").all()
      for obj in queryset:
          obj.save(using="new-db")
      

      因为应该保留主键,所以我认为不会有任何外键问题。

      【讨论】:

        【解决方案6】:

        对我有用的是从 ruby​​ 运行续集。 只需运行命令:

        gem install sequel
        

        您需要在系统上安装 postgres 、 sqlite 和 ruby​​ 的开发包 运行命令:

        gem install pg sqlite3
        

        在 postgresql 上创建一个空数据库,比如说 testDB 并为用户分配授予权限 从命令提示符运行:

        sequel -C sqlite:///path/to/sqlitedb.db postgres://user:password@host/testDB
        

        这将毫无错误地运行。

        更改 django 项目中的设置以使用 postgres 数据库 运行

        ./manage migrate (not necessary)

        运行服务器

        【讨论】:

        • 让我开心,谢谢 :)
        【解决方案7】:

        首先我会尝试一个简单的:

        sqlite3 sqllitedb .dump | psql postgresdb
        

        到那时,只需测试一下即可。在 Django 中编写一些测试脚本,为每个应用程序输出一组示例记录,然后进行 diff 以确保它们相同。如果是,那么您的转换可能没问题。

        如果这不起作用...

        我建议不要使用 Django 转储和加载数据,因为我猜它没有优化到这样做。

        相反,我会使用正确的 PostgreSQL 数据库设置创建您的应用程序的第二个版本,运行 syncdb 以创建所有表,然后使用其他工具将数据从 mysqllite 复制到 PostgreSQL。

        问题是,转换数据时的大多数问题都在表定义等中。这些似乎是最特殊的。如果您可以生成一个仅转储表内容的 SQL 脚本,那应该是非常标准的 SQL INSERT INTO 命令。

        老实说,我不明白为什么会有外键问题。假设 sqlite 正在创建准确的外键(为什么不呢?)那么就没有办法不能正确复制。实际上,外键不是特殊形式的数据。与UserProfile.photo 字段相比,UserProfile.user_id 字段包含错误值的可能性不大。如果外键问题是字段本身没有被正确识别为外键字段(即没有约束),那么首先使用syncdb 创建数据库的选项将解决该问题。

        根据截断:据我了解,如果数据即将被截断,PostgreSQL 会抛出一个硬错误。我不知道 sqlite 是否是这种情况,或者它是否只是默默地截断。无论哪种方式,再次假设 sqlite 没有以某种方式在导出时修改数据,字段应该包含的数据是它要进入的字段的正确长度。我能想到的唯一可能影响这一点的是字符编码,所以让确保 PostgreSQL 字段具有与 sqlite 表相同的编码,至少在导入期间是这样。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-03-03
          • 1970-01-01
          • 2019-01-01
          • 2016-02-20
          • 2022-01-04
          • 1970-01-01
          • 1970-01-01
          • 2017-12-07
          相关资源
          最近更新 更多