如何确保Postgres中外键的有效性

时间:2019-01-09 11:50:45

标签: postgresql foreign-keys data-corruption

使用Postgres 10.6

问题:

  • 我的表中的某些数据违反了外键约束(不确定如何)。约束为ON DELETE CASCADE ON UPDATE CASCADE
  • 在数据库的pg_dump上,那些外键被删除(由于处于无效状态?)
  • pg_restore已完成到一个空白数据库,该数据库不再具有外键
  • 新数据库的所有主键都更新为第二个数据库中未使用的有效键。由于现在缺少约束,具有无效数据的表不会更新其外键。
  • 完成pg_dump的新数据库,然后删除数据库
  • pg_restore上另一个具有外键约束的数据库中,数据以无效状态导入,并破坏了新数据库。

我想做的是:每隔几个小时(或每天一次,取决于查询需要多长时间),就是要验证所有具有外键的表中的所有数据都是有效的。

我已阅读有关ALTER TABLE ... VALIDATE CONSTRAINT ...的信息,但这不能解决我的问题,因为该数据当前未标记为NOT VALID。我知道可以做这样的声明:

DELETE FROM a WHERE a.b_id NOT IN ( SELECT b.id )

但是,我有144个带有外键的表,所以这很繁琐。我可能也不想立即删除数据,而是记录问题并通知用户即将发生的更正。

当然,我想知道原始损坏是如何发生的,并防止这种情况的发生;但是目前,我只是想阻止它传播。

示例表:

CREATE TABLE dependencies (
    ...
    from_task int references tasks(id) ON DELETE CASCADE ON UPDATE CASCADE NOT NULL, 
    to_task int references tasks(id) ON DELETE CASCADE ON UPDATE CASCADE NOT NULL, 
    ...
);

依存关系最终将是to_task表中不存在的from_tasktasks的值(参见图片)

enter image description here

注意:

  • 尝试过EXPLAIN ANALYZE没什么奇怪的
  • pg_tablespace,只有两条记录。 pg_default和pg_global
  • relforcerowsecurity,relispartition在两个表上都为“ false”
  • pg_dump的参数(从c ++调用)arguments << "--file=" + fileName << "--username=" + connection.userName() << databaseName << "--format=c"

1 个答案:

答案 0 :(得分:0)

这是索引(或表)损坏的问题,或者创建了约束,使有效性检查推迟到以后。

pg_dump永远不会默默地“放弃”一个约束-在恢复您没有注意到的转储时可能会出错。

正确的解决方法是清理违反约束的数据并重新创建。

如果这是数据损坏问题,请检查硬件。

不需要定期检查数据是否损坏,PostgreSQL本身就没有破坏数据的习惯。

最好的测试方法是定期进行pg_dump并查看还原转储是否引起任何错误。