PostgreSQL外键冲突的原因?

PostgreSQL外键冲突的原因?,postgresql,foreign-keys,postgresql-9.2,corruption,Postgresql,Foreign Keys,Postgresql 9.2,Corruption,我的PostgreSQL(9.2)数据库包含两个带有外键约束的表注册和属性: postgres=# \d+ registrations; Table "public.registrations" Column | Type | Modifiers | Storage | Stats target | Description ---------+-------+-----------+----------+--------------+-----------

我的PostgreSQL(9.2)数据库包含两个带有外键约束的表
注册
属性

postgres=# \d+ registrations;
                Table "public.registrations"
 Column  | Type  | Modifiers | Storage  | Stats target | Description
---------+-------+-----------+----------+--------------+-------------
 name    | text  | not null  | extended |              |
 parent  | text  |           | extended |              |
 storage | bytea |           | extended |              |
Indexes:
    "registrations_pkey" PRIMARY KEY, btree (name)
Referenced by:
    TABLE "attributes" CONSTRAINT "attributes_cname_fkey" FOREIGN KEY (cname) REFERENCES registrations(name) ON DELETE CASCADE
Has OIDs: no

postgres=# \d+ attributes;
                 Table "public.attributes"
 Column | Type  | Modifiers | Storage  | Stats target | Description
--------+-------+-----------+----------+--------------+-------------
 cname  | text  | not null  | extended |              |
 aname  | text  | not null  | extended |              |
 tags   | text  |           | extended |              |
 value  | bytea |           | extended |              |
Indexes:
    "attributes_pkey" PRIMARY KEY, btree (cname, aname)
Foreign-key constraints:
    "attributes_cname_fkey" FOREIGN KEY (cname) REFERENCES registrations(name) ON DELETE CASCADE
Has OIDs: no
postgres=# SELECT COUNT(*) FROM attributes LEFT JOIN registrations ON attributes.cname=registrations.name WHERE registrations.name IS NULL;
 count
-------
    71
(1 row)
在某个时候,我意识到一些行违反了外键约束:

postgres=# \d+ registrations;
                Table "public.registrations"
 Column  | Type  | Modifiers | Storage  | Stats target | Description
---------+-------+-----------+----------+--------------+-------------
 name    | text  | not null  | extended |              |
 parent  | text  |           | extended |              |
 storage | bytea |           | extended |              |
Indexes:
    "registrations_pkey" PRIMARY KEY, btree (name)
Referenced by:
    TABLE "attributes" CONSTRAINT "attributes_cname_fkey" FOREIGN KEY (cname) REFERENCES registrations(name) ON DELETE CASCADE
Has OIDs: no

postgres=# \d+ attributes;
                 Table "public.attributes"
 Column | Type  | Modifiers | Storage  | Stats target | Description
--------+-------+-----------+----------+--------------+-------------
 cname  | text  | not null  | extended |              |
 aname  | text  | not null  | extended |              |
 tags   | text  |           | extended |              |
 value  | bytea |           | extended |              |
Indexes:
    "attributes_pkey" PRIMARY KEY, btree (cname, aname)
Foreign-key constraints:
    "attributes_cname_fkey" FOREIGN KEY (cname) REFERENCES registrations(name) ON DELETE CASCADE
Has OIDs: no
postgres=# SELECT COUNT(*) FROM attributes LEFT JOIN registrations ON attributes.cname=registrations.name WHERE registrations.name IS NULL;
 count
-------
    71
(1 row)

您能帮助我了解这种损坏是如何发生的吗?

如果FK合同是使用无效的
子句创建的(不要这样做):


标记为
NOT VALID
的约束是您可能会看到冲突的一种情况,但是
NOT VALID
子句将显示在psql
\d+
输出中。(我相信可以手动更新目录中的此标志,但为了您的利益,我希望这不是问题所在……)

据我所知,绕过外键检查的唯一受支持的方法是在修改数据之前
将session\u replication\u role设置为replica
。这是为了复制过程的利益,在假设约束已在主服务器上验证的情况下运行-尽管如果复制程序有缺陷或配置错误,这肯定会出错

超级用户也可以手动禁用约束的底层触发器(对于试图加速批量导入的人来说,这通常很诱人)。下面将告诉您触发器当前是否处于活动状态(
tgenabled
应为
'O'
):

我不认为有任何方法可以知道这在过去是否被临时更改,尽管如果启用了语句日志记录,您可能会发现一个
altertable。。。在某个地方禁用触发器
语句


外键强制中也存在漏洞,当然,您总是有可能发现bug…

是否有任何命令来检查此约束是否是使用此子句创建的?不知道。如果有的话,可以查一下日志?注意:pg_dump也发出了
无效的
短语,因此它必须在目录中的某个地方。似乎不是这样,我在日志中看到了以下内容:
创建表属性(cname text NOT null,aname text NOT null,tags text,value bytea,主键(cname,aname),外键(cname)引用注册(name)关于删除级联)
我们的系统实际上涉及两个数据库之间的复制,您认为这可能是问题的原因吗?@fiddler:假设您使用的是某种基于触发器的复制,而不是Postgres的二进制复制模式,那么这不是不可能的。虽然复制过程可能永远不会写入主机,因此数据只会在从机上出错。好吧,我们使用二进制复制(流式复制)OK,流式复制永远不会将此问题发布到@CraigRinger X-post删除。