pg_restore 没有禁用触发器

pg_restore is not disabling triggers

使用 PostgreSQL 9.2.8,我试图将我的数据从一个数据库恢复到另一个数据库,但触发器似乎仍然是 运行。我已经编写了如下所示的脚本来进行复制。

基本上我有 dts 作为我的生产数据库,我有 DigitalTrafficSystem 作为我的开发数据库。 table 结构是一样的,但是 dev 有非常不同的存储过程。

当恢复运行时,DigitalTrafficSystem 数据库以一堆额外的 table 行结束,这些行在 dts 数据库中不存在,所以我假设那些由触发器创建。

我收到的与触发器相关的消息,对于每个 table,如下所示:

pg_restore: [archiver (db)] could not execute query: ERROR:  permission denied: "RI_ConstraintTrigger_c_136691" is a system trigger
Command was: ALTER TABLE usage ENABLE TRIGGER ALL;

我假设(错误地?)触发器已关闭,但无法禁用系统级触发器。

这是我的脚本:

#!/bin/sh

PGUSER=dts
FILE=/tmp/.dts.db.$$

# Dump the schema of the DB as we want this to keep
pg_dump -s DigitalTrafficSystem -f $FILE

dropdb -U _postgres DigitalTrafficSystem
if [ $? -ne 0 ]; then
    exit;
fi

createdb -U _postgres -O dts DigitalTrafficSystem
if [ $? -ne 0 ]; then
    exit;
fi

# Restore the schema
psql -d DigitalTrafficSystem -f $FILE

# Dump the data of the real production database
pg_dump -Fc -a dts -f $FILE > /dev/null
if [ $? -ne 0 ]; then
    exit;
fi

# Restore only the data from the real database to our development one
pg_restore -a -d DigitalTrafficSystem --disable-triggers -S dts $FILE

rm $FILE

I'm assuming (wrongly?) that the triggers are off, but just that system level trigger couldn't get disabled.

不,因为 SQL 命令的成功是一个孤注一掷的问题。失败的命令大概是以下形式:

ALTER TABLE usage DISABLE TRIGGER ALL;

如果失败,它将完全失败,而不是只做一半的工作,这将禁用用户级触发器并启用 RI 约束触发器。

pg_restore 医生说:

      Presently, the commands emitted for --disable-triggers must be done
      as superuser. So you should also specify a superuser name with -S
      or, preferably, run pg_restore as a PostgreSQL superuser.

   -S username, --superuser=username
       Specify the superuser user name to use when disabling triggers.
       This is relevant only if --disable-triggers is used.

但是您的 dts 不是超级用户。根据脚本的其余部分,_postgres 似乎是超级用户。在那种情况下,为什么不将其传递给 -S 呢?

另一点是,就像@wildplasser 在评论中指出的那样,被全新数据库中的触发器打扰有点奇怪,因为您的脚本创建了一个数据库并立即运行了仅数据导入。我们可以假设它是包含这些对象的 template1 数据库和这些触发器吗? 但是,请注意 template1 中的表中的数据也被导入到新创建的数据库中,因此还必须考虑在转储源和最终结果之间找到的任何其他行目标数据库。

需要 pg_restore 上的一个选项来仅禁用用户触发器,而不是所有触发器。

pg_restore 问题:ALTER TABLE <table> DISABLE TRIGGER ALL

pg_restore 需要的是发出这个:ALTER TABLE <table> DISABLE TRIGGER USER