【发布时间】:2019-04-05 18:54:53
【问题描述】:
我正在将一个 Django 站点从 MySQL 迁移到 PostgreSQL。数据量不是很大,所以我采取了一个非常简单的方法:我只是使用内置的Django serialize and deserialize 例程创建JSON记录,然后将它们加载到新实例中,循环对象,并将每个对象保存到新数据库中。
这非常好用,有一个小问题:加载所有记录后,当我在加载旧记录后尝试添加新数据时遇到IntegrityError。 MySQL 自动增量 ID 字段的 Postgres 等效项是串行字段,但是当显式指定 id 值时,串行字段的内部计数器不会递增。结果,Postgres 尝试从 1 开始对记录进行编号——已经使用——导致违反约束。 (这是 Django 中的一个已知问题,标记为 wontfix。)
有很多与此相关的问题和答案,但似乎没有一个答案直接在 Django 的上下文中解决了这个问题。 This answer 给出了您需要运行以更新计数器的查询示例,但我尽量避免在可能的情况下进行显式查询。我可以在保存之前简单地删除 ID 字段并让 Postgres 自己进行编号,但是在这种情况下,ForeignKey 引用将被破坏。其他一切都很好!
如果 Django 提供了一个可以智能地处理任何边缘情况的例程,那就太好了。 (这不会修复错误,但它会允许开发人员以一致且正确的方式解决它。)我们真的必须只使用原始查询来修复它吗?看起来很野蛮。
如果真的没有这样的例程,我将简单地执行以下操作,它直接运行上面链接的答案中建议的查询。但在那种情况下,我很想知道这种方法的任何潜在问题,或者关于我可能做错的任何其他信息。例如,我是否应该只修改记录以使用 UUID,如 this suggests?
这是原始方法(经过编辑以反映我实际完成的简化版本)。这与Pere Picornell 的答案非常接近,但他对我来说看起来更健壮。
table = model._meta.db_table
cur = connection.cursor()
cur.execute(
"SELECT setval('{}_id_seq', (SELECT max(id) FROM {}))".format(table, table)
)
【问题讨论】:
-
您打算进行多少次这种转换,并且您打算再次转换回 MySQL?如果它接近 1 而不是,那么为什么要尝试自动化呢?只需直接在您的查询工具中运行查询,在导入期间关闭 fkey 检查以及书中的任何其他肮脏技巧 - 然后重新打开所有内容并使其漂亮。 (ps:原始 sql 并不野蛮,它很漂亮 :-)
-
@thebjorn,啊,公平点。理论上,在这种情况下它接近 1,但我预计必须为几个不同的项目这样做,所以我希望能够编写一个标准化的导出/导入脚本来处理这个怪癖。 (抱歉——“野蛮”可能不公平。)
标签: python django postgresql