PostgreSQL外键冲突的原因?
我的PostgreSQL(9.2)数据库包含两个带有外键约束的表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 ---------+-------+-----------+----------+--------------+-----------
注册
和属性
:
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删除。