【问题标题】:pg_restore on table failing because of hstore由于 hstore 导致表上的 pg_restore 失败
【发布时间】:2015-01-28 18:54:16
【问题描述】:

背景

我在 Ubuntu 14.04 上使用 PostgreSQL 9.3.5。

在一个错误的脚本之后,我有一个表需要从通过 pg_dump 创建的转储文件中恢复。在这张表上,我有一个审计触发器,它基于 这个wiki page. 可以看到,触发函数使用了一个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)

问题:

  1. 为什么我在数据库安装了这个扩展时会出现这个错误?
  2. 除了删除触发器之外,我还能如何解决这个问题?删除触发器并不是世界上最糟糕的事情,但似乎这应该是可能的,并且在生产数据库中,我希望能够看到有人恢复数据等的审计线索。李>

【问题讨论】:

  • 我唯一能想到的是,hstore 不在用户 postgres 的“search_path”中,而是为您登录检查的任何人。尝试将数据还原到文件而不是直接还原到数据库,如果要检查,请查看 SQL。
  • @RichardHuxton 我已经更新了我的 OP,以包括当我选择为(即 postgres)时我登录的用户的信息。
  • 好吧,要么您更改了默认提示,要么您已经从“postgres”中获取了超级用户权限,因为这对于超级用户来说是错误的提示。
  • 我已经更改了.psqlrc中的默认提示
  • 您要恢复的表在哪个模式中? pg_dump 使用 SET search_pach=.. 更改转储开始处的 search_path,但不处理表中使用的类型(pg_dump 错误?)。如果您的转储是纯文本,请使用文本编辑器查看。

标签: postgresql postgresql-9.3 pg-restore


【解决方案1】:

这似乎是 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;

从 psql 内部使用 \i 运行此行仍然失败,但编辑最后一行以包含公共架构(安装 hstore 的位置)有效。

SET search_path = myschema, pg_catalog, public;

然后我可以使用\i 从 psql 内部运行并导入丢失的数据。

【讨论】:

【解决方案2】:

我在公共定义的两个函数(checksumis_valid)和一个表(master_values)上遇到了同样的问题。这里checksum 正在调用is_validmaster_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;

有关更多信息,请参阅:

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2010-09-20
  • 2021-01-18
  • 1970-01-01
  • 1970-01-01
  • 2015-11-09
  • 2014-12-05
  • 2018-04-22
  • 2014-06-29
相关资源
最近更新 更多