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 我遇到了同样的问题。我可以将您的修复编辑到答案中,但是当答案不一定有任何问题时,我不确定编辑的礼仪。 @matandkeddumpdata --natural-primary --natural-foreign
会避免你这个问题,将它添加到答案中【参考方案2】:
以下是对 Django 1.7+ 的 Nimo's answer 和 Stephen's answer 的改进:
./manage.py dumpdata --natural-primary --natural-foreign > dump.json
将 settings.py
中的 DATABASES
更改为指向新的 (PostgreSQL) 数据库。
./manage.py migrate
./manage.py loaddata dump.json
我遇到的一个问题是,SQLite 似乎并没有真正强制CharField
s 的最大长度。就我而言,这使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