背景:
我在 Ubuntu 14.04 上使用 PostgreSQL 9.3.5。
在一个糟糕的脚本之后,我有一个表,我需要从通过pg_dump创建的转储文件中恢复。 在此表上,我有一个基于此维基页面。如您所见,触发器函数使用 hstore。
错误:
当我尝试还原时,我得到:
$ pg_restore -a --dbname=a193 -Fc --host=localhost --port=5434 --username=postgres -W --table=foo ~/tmp/a193.dump
Password:
pg_restore: [archiver (db)] Error while PROCESSING TOC:
pg_restore: [archiver (db)] Error from TOC entry 4600; 0 26146 TABLE DATA foo u2su8s81ul0a52
pg_restore: [archiver (db)] COPY failed for table "foo": ERROR: type "hstore" does not exist
LINE 6: h_old hstore;
扩展肯定存在。
=> dx
List of installed extensions
+--------------------+---------+------------+--------------------------------------------------------------+
| Name | Version | Schema | Description |
+--------------------+---------+------------+--------------------------------------------------------------+
| dblink | 1.1 | public | connect to other PostgreSQL databases from within a database |
| hstore | 1.2 | public | data type for storing sets of (key, value) pairs |
| isn | 1.0 | public | data types for international product numbering standards |
| pg_stat_statements | 1.1 | public | track execution statistics of all SQL statements executed |
| pgcrypto | 1.0 | public | cryptographic functions |
| plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language |
| plpythonu | 1.0 | pg_catalog | PL/PythonU untrusted procedural language |
| postgres_fdw | 1.0 | public | foreign-data wrapper for remote PostgreSQL servers |
| uuid-ossp | 1.0 | public | generate universally unique identifiers (UUIDs) |
+--------------------+---------+------------+--------------------------------------------------------------+
(9 rows)
我可以在查询中使用它(作为 postgres 用户 - 与我上面用于恢复的角色相同):
=> select current_user;
+--------------+
| current_user |
+--------------+
| postgres |
+--------------+
(1 row)
=> du
List of roles
+----------------+------------------------------------------------+-----------+
| Role name | Attributes | Member of |
+----------------+------------------------------------------------+-----------+
| postgres | Superuser, Create role, Create DB, Replication | {} |
| u2su8s81ul0a52 | | {} |
+----------------+------------------------------------------------+-----------+
=> select 'a=>1'::hstore;
+----------+
| hstore |
+----------+
| "a"=>"1" |
+----------+
(1 row)
问题:
- 为什么在数据库安装了此扩展时出现此错误?
- 除了放弃触发器,我该如何解决这个问题?丢弃触发器并不是世界上最糟糕的事情,但似乎这应该是可能的,并且在生产数据库中,我希望能够看到有人对数据进行了还原等的审计跟踪。
似乎是pg_dump或pg_restore中的错误。根据理查德·赫克斯顿(Richard Huxton)上面的建议,我恢复了一个文件。
pg_restore --data-only --table=foo -f ~/tmp/foo.sql ~/tmp/a193.dump
当我查看内容时,我发现它在顶部执行以下操作:
SET statement_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SET check_function_bodies = false;
SET client_min_messages = warning;
SET search_path = myschema, pg_catalog;
使用 i
从 psql 内部运行此行仍然失败,但编辑最后一行以包含公共架构(安装 hstore 的位置)是有效的。
SET search_path = myschema, pg_catalog, public;
然后,我可以使用i
从 psql 内部运行并导入丢失的数据。
我对两个函数(checksum
和is_valid
)和一个公开定义的表(master_values
)有同样的问题。在这里,checksum
调用is_valid
,master_values
有一个检查约束:
"master_values_master_id_check" CHECK(is_valid(master_id))"
请注意,其中没有使用任何search_path
或架构引用。
尝试还原转储时,我在还原过程中得到了这个:
pg_restore: [archiver (db)] COPY failed for table "master_values": ERROR: function checksum(integer) does not exist
奇怪的是,还原后,功能和表都在那里并按预期工作。唯一缺少的是未还原的master_values
中的数据。
这是通过指定is_valid
search_path
来解决的:
ALTER FUNCTION is_valid SET search_path = public;
有关此内容的详细信息,请参阅:
- 文档:https://www.postgresql.org/docs/current/sql-alterfunction.html
- 文章 1: https://www.postgresonline.com/article_pfriendly/279.html
- 第2条:https://www.endpoint.com/blog/2012/11/15/postgresql-searchpath-behaviour