无法将 PostgreSQL10 转储导入 9.6 数据库

Posted

技术标签:

【中文标题】无法将 PostgreSQL10 转储导入 9.6 数据库【英文标题】:Can't import PostgreSQL10 dump into 9.6 database 【发布时间】:2018-09-07 21:52:58 【问题描述】:

我需要以某种方式将 v10 转储文件转换为兼容 9.6 的文件

Google 的 Cloud SQL 运行 PostgreSQL 版本 9.6,而我的数据库自创建以来一直在版本 10 上运行。

问题:尝试将数据库导入 Cloud SQL 时,我收到 an unknown error has occurred. 死亡消息。

我已经尝试在导入 Cloud SQL 时注释掉我的 postgis /其他扩展,但无济于事。

我尝试使用 psql my_96_db < my_10.sql 并得到大量这样的错误:

...
CREATE TABLE
ERROR:  syntax error at or near "AS"
LINE 2:     AS integer
            ^
ERROR:  relation "authentication_phonecontact_id_seq" does not exist
CREATE TABLE
...

我尝试在我的 v10 pg_dump -Fc 命令上使用 postgres 9.6 的 pg_restore,但它无法成功导入 9.6 数据库。输出中的许多故障之一的示例是

pg_restore: [archiver (db)] could not execute query: ERROR:  relation "public.authentication_referral_id_seq" does not exist
LINE 1: SELECT pg_catalog.setval('public.authentication_referral_id_...
                                 ^
    Command was: SELECT pg_catalog.setval('public.authentication_referral_id_seq', 1, false);

【问题讨论】:

【参考方案1】:

从您显示的错误消息来看,您必须编辑 SQL 转储并从所有 CREATE SEQUENCE 语句中删除所有出现的 AS integer

CREATE SEQUENCEAS <em>data_type</em> 子句是 PostgreSQL v10 中新增的,旧的服务器版本无法理解。

【讨论】:

为什么没有向后兼容转储的标志? @grokpot 嗯?您不需要标志来转储较旧的 PostgreSQL 服务器。并且您不允许转储更高版本的 PostgreSQL 服务器。那很好,因为 9.4 服务器应该如何知道如何正确转储 v10 数据库? @LaurenzAlbe v10 应该知道如何转储 v9.x 兼容的备份恕我直言 @Mirko 它应该如何转储旧版本中不存在的东西?只是默默地放下它们?出错了?无论如何,您永远不必降级,因此没有人有足够的动力为此编写支持。这很难,而且会使 pg_dump 更加复杂。 只是为了记录,这也适用于将转储从 postgresql 10 反向移植到 portgresql 9.5【参考方案2】:

根据@"Laurenz Albe" 的建议,这里有一个 python3 sn-p 可用于为 9.x 降级 10.x pg_dump 脚本:

#!/usr/bin/env python3
import sys

#
#  Downgrades pg_dump 10 script to 9.x
#  removing 'AS integer' from 'CREATE SEQUENCE' statement
#
#  Usage:
#       $ python3 pgdump_10_to_9.py < test10.sql > test9.sql
#  or:
#       $ cat test10.sql | ./pgdump_10_to_9.py > test9.sql
#
#  To obtain a compressed 9.x sql script from a compressed 10 sql script:
#
#       $ gunzip -c test10.sql.gz | ./pgdump_10_to_9.py | gzip > test9.sql.gz
#

inside_create_sequence = False
for row in sys.stdin.readlines():

    if inside_create_sequence and row.strip().lower() == 'as integer':
        pass
    else:
        print(row, end='', flush=True)

    inside_create_sequence = row.strip().startswith('CREATE SEQUENCE ')

【讨论】:

感谢您编写此脚本。它使转换文件变得超级容易。 一个不太复杂的解决方案是使用sed,cat test10.sql | sed '/AS integer/d' &gt; test9.sql 你真的想在所有地方删除“作为整数”吗?我的目的是在“创建序列”发生后立即删除该行 我可以确认这个脚本也适用于将 PostgreSQL 11 降级到 9.6!感谢分享。 如果您正在处理 Rails db/structure.sql 文件,这里有一个 Ruby 脚本可以处理一些额外的不兼容性:gist.github.com/reedlaw/25e768d0cb853fc40bbdebfaeabaf360

以上是关于无法将 PostgreSQL10 转储导入 9.6 数据库的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Mac OS 上使用自制软件将 postgresql 从 10.1 降级到 9.6 [关闭]

Docker-Compose Postgresql 导入转储

在Windows 10 x64中设置PostgreSQL 9.6(BigSQL图形安装程序)

将 PostgreSQL SQL 转储转换为 PostgreSQL 自定义格式转储

如何使用 Homebrew 将 Postgis 安装到 Postgres@9.6 的 Keg 安装中?

在RedHat中从postgresql 9.2升级到9.6时unix_socket_directory出错