恢复Postgres数据库时出现无法解决的问题

时间:2014-05-29 17:42:41

标签: database postgresql backup restore

我想将另一个数据库名称下的特定数据库还原到另一个服务器。到目前为止,非常好。

我使用了这个命令:

pg_dump -U postgres -F c -O -b -f maindb.dump maindb

将主数据库转储到生产服务器上。我使用这个命令:

 pg_restore --verbose -O -l -d restoredb maindb.dump

在我们的测试服务器上的另一个数据库中恢复数据库。它恢复大多没问题,但有一些错误,如:

pg_restore: [archiver (db)] Error while PROCESSING TOC:
pg_restore: [archiver (db)] Error from TOC entry 3595; 1259 213452 INDEX idx_clientnomclient maindbuser
pg_restore: [archiver (db)] could not execute query: ERROR:  function unaccent(text) does not exist
LINE 1:  SELECT unaccent(lower($1)); 
                ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
QUERY:   SELECT unaccent(lower($1)); 
CONTEXT:  SQL function "cyunaccent" during inlining
Command was: CREATE INDEX idx_clientnomclient ON client USING btree (public.cyunaccent((lower((nomclient)::text))::character varying));

cyunaccent是一个在公共场景中的功能,并且可以通过恢复来创建。

恢复后,我可以使用相同的sql完全重新创建这些索引,没有任何错误。

我还尝试使用pg_restore的-i选项进行恢复以执行单个事务,但它没有帮助。

我做错了什么?

1 个答案:

答案 0 :(得分:2)

我刚刚发现了问题,我能够将其缩小到一个简单的测试用例。

CREATE SCHEMA intranet;
CREATE EXTENSION IF NOT EXISTS unaccent WITH SCHEMA public;
SET search_path = public, pg_catalog;
CREATE FUNCTION cyunaccent(character varying) RETURNS character varying
    LANGUAGE sql IMMUTABLE
    AS $_$ SELECT unaccent(lower($1)); $_$;
SET search_path = intranet, pg_catalog;
CREATE TABLE intranet.client (
    codeclient character varying(10) NOT NULL,
    noclient character varying(7),
    nomclient character varying(200) COLLATE pg_catalog."fr_CA"
 );
ALTER TABLE ONLY client ADD CONSTRAINT client_pkey PRIMARY KEY (codeclient);
CREATE INDEX idx_clientnomclient ON client USING btree (public.cyunaccent((lower((nomclient)::text))::character varying));

此测试用例来自以纯文本形式完成的pg_dump。

正如您所看到的,cyunaccent函数是在公共shcema中创建的,因为它后来被其他模式中的其他表使用。

psql / pg_restore不会重新创建索引,因为它无法找到该函数,尽管指定了shcema名称来引用它。

是问题所在
SET search_path = intranet, pg_catalog;

呼叫。将其更改为

SET search_path = intranet, public, pg_catalog;

解决了这个问题。我已经向postgres提交了一份关于此问题的错误报告,尚未列入队列。