代码之家  ›  专栏  ›  技术社区  ›  ChrisMM

如何保证postgres外键的有效性

  •  0
  • ChrisMM  · 技术社区  · 7 年前

    使用Postgres 10.6

    问题:

    • 我的表中的某些数据违反了外键约束(不确定如何)。约束条件是 ON DELETE CASCADE ON UPDATE CASCADE
    • 在数据库的pg_转储中,这些外键被丢弃(因为处于无效状态?)
    • pg_restore 在一个空白数据库中完成,该数据库不再具有外键
    • 新数据库已将其所有主键更新为第二个数据库中未使用的有效键。由于现在缺少约束,具有无效数据的表没有更新外键。
    • pg_dump 新数据库完成后,将删除该数据库
    • 在一 PGO恢复 在具有外键约束的第二个数据库中,数据将以无效状态导入,并损坏新数据库。

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

    我读过 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_task 不存在于 tasks 表(见图片)

    enter image description here

    注:

    • 尝试过 EXPLAIN ANALYZE 无奇
    • pg_表空间,只有两条记录。PG U默认和PG U全局
    • relforcerowsecurity和relispation在两个表上都是“false”
    • 对PGYDUMP的争论(来自C++调用) arguments << "--file=" + fileName << "--username=" + connection.userName() << databaseName << "--format=c"
    1 回复  |  直到 7 年前
        1
  •  0
  •   Laurenz Albe    7 年前

    这可能是索引(或表)损坏问题,或者约束已 创建 将有效性检查推迟到以后无效。

    pg_dump 永远不会默默地“掉”一个约束——也许有一个错误 恢复 你没注意到的垃圾场。

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

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

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

    最好的测试是 PGI转储 定期查看恢复转储是否会导致任何错误。