Django:将项目从 sqlite 迁移到 PostgreSQL 的最佳实践是啥

Posted

技术标签:

【中文标题】Django:将项目从 sqlite 迁移到 PostgreSQL 的最佳实践是啥【英文标题】: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。

【问题讨论】:

【参考方案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 数据库中。

【讨论】:

小心,这仅适用于较小的数据库大小***.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 answer 和 Stephen's answer 的改进:

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

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

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

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

【讨论】:

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

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

    停止运行服务器 python manage.py 转储数据 更改 settings.py 以指向新创建的 postgres 数据库 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 表相同的编码,至少在导入期间是这样。

【讨论】:

以上是关于Django:将项目从 sqlite 迁移到 PostgreSQL 的最佳实践是啥的主要内容,如果未能解决你的问题,请参考以下文章

Django:将数据从 SQLite 移动到 PostgreSQL

South - 将 django 应用程序从 sqlite 迁移到 mysql

如何将 Django 模型从 mysql 迁移到 sqlite(或在任何两个数据库系统之间)?

Django 1.8 迁移无法将列 ID 转换为整数

Django数据从sqlite迁移数据到MySQL

加载数据转储时,将 Django 项目从 sqlite3 后端切换到 postgresql 失败