Mikhail Shytsko:副本模式不会关闭什么

Mikhail Shytsko:副本模式不会关闭什么

💡 原文英文,约3200词,阅读约需12分钟。
📝

内容提要

本文探讨PostgreSQL中三种绕过外键约束的方法:`session_replication_role=replica`仅关闭外键等触发器,但CHECK、NOT NULL等仍生效;`DISABLE TRIGGER ALL`需超级用户,影响全局且不检查数据;`NOT ENFORCED`(PG18+)可单约束关闭,重新启用时会扫描数据。三者均不绕过行级安全,各有适用场景和风险。

🔎

延伸解读

三种方式的生效范围与副作用

session_replication_role=replica只影响当前会话,且仅关闭外键等内部触发器,CHECK、NOT NULL、UNIQUE等约束依然生效;DISABLE TRIGGER ALL写入目录,影响所有会话,但需要超级用户权限,且不会关闭父表上的级联触发器;NOT ENFORCED(PG18+)可针对单个约束关闭,但重新启用时会扫描数据。选择时需明确需求,避免副作用。

重新启用时的数据检查差异

RESET session_replication_role和ENABLE TRIGGER ALL在恢复时都不会扫描数据,可能留下孤儿数据而不自知;而ALTER CONSTRAINT ... ENFORCED会扫描表并拒绝存在违规的情况,但若行级安全策略隐藏了违规行,扫描可能误报成功。因此,恢复前应手动运行反连接查询确认数据完整性。

行级安全是最后一道防线

无论使用哪种方式绕过外键,行级安全策略始终生效,且强制RLS下COPY FROM会被拒绝。若在启用ENFORCED时,当前会话无法看到所有行(如未设置app.tenant),扫描可能漏掉违规数据。建议在能看见全部数据的会话中操作,或临时关闭FORCE。

Q&A

在PostgreSQL中,session_replication_role = replica 会关闭哪些约束检查?

session_replication_role = replica 会关闭外键约束(因为外键由内部触发器实现),同时也会关闭规则、事件触发器和默认状态的触发器。但 CHECK、NOT NULL、UNIQUE、identity 列和行级安全策略仍然生效。

DISABLE TRIGGER USER 和 DISABLE TRIGGER ALL 有什么区别?

DISABLE TRIGGER USER 只禁用用户创建的触发器,保留内部触发器,因此外键约束仍然有效;DISABLE TRIGGER ALL 会禁用包括内部触发器在内的所有触发器,从而绕过外键约束。但 DISABLE TRIGGER ALL 需要超级用户权限,普通表所有者会被拒绝。

PostgreSQL 18 中新增的 NOT ENFORCED 约束选项有什么特点?

NOT ENFORCED 是 PostgreSQL 18 为外键新增的功能,允许单独关闭某个约束的强制检查。它只影响指定的约束,并且重新启用时会扫描表数据以检查是否违反约束。此外,它需要超级用户权限,并且会获取 AccessExclusiveLock,不适合在线操作。

在 PostgreSQL 中,重新启用被禁用的外键约束时,哪种方法会重新检查数据?

只有 ALTER TABLE ... ALTER CONSTRAINT ... ENFORCED 会重新扫描表数据并检查是否违反约束。RESET session_replication_role 和 ENABLE TRIGGER ALL 都不会重新检查数据,而 VALIDATE CONSTRAINT 对已经有效的约束也不会执行检查。

非超级用户能否设置 session_replication_role 参数?

默认情况下,session_replication_role 参数只能由超级用户设置。但从 PostgreSQL 15 开始,可以通过 GRANT SET ON PARAMETER 将设置该参数的权限授予特定角色。

在 PostgreSQL 中,有哪些方法可以绕过外键约束?它们各自有什么风险?

有三种方法:1) 设置 session_replication_role = replica,仅影响当前会话,但不会关闭 CHECK 等约束;2) 使用 ALTER TABLE ... DISABLE TRIGGER ALL,需要超级用户,影响全局,且不会重新检查数据;3) 使用 ALTER TABLE ... ALTER CONSTRAINT ... NOT ENFORCED(PG18+),可单独关闭约束,但重新启用时会扫描数据。这些方法都不会绕过行级安全,且各有风险,如可能留下孤立数据。

🏷️

标签

➡️

继续阅读