You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL软删除与RLS更新、查询策略冲突问题问询

问题原因与解决方案

报错原因

PostgreSQL开启行级安全(RLS)后,执行UPDATE操作时,除了验证UPDATE策略的USING和WITH CHECK条件,默认还会强制检查更新后的行必须对执行操作的用户可见(即符合该表SELECT策略的USING规则)。你的软删除操作会将deleted_at设为当前时间,更新后的行不符合SELECT策略中deleted_at is null的要求,因此触发new row violates row-level security policy错误。

临时方案通过让刚更新的1秒内的行暂时满足SELECT策略绕过检查,但这并非合理的长期解决方案。


合理解决办法

方案1:关闭UPDATE策略的可见性强制检查(推荐)

PostgreSQL 12及以上版本支持WITH CHECK OPTION NOT ENFORCED,添加该选项后,会跳过更新后的行可见性验证,允许普通用户更新自己的行(即使更新后行对自身不可见),完全匹配软删除的业务逻辑。

修改后的UPDATE策略代码:

CREATE POLICY my_table_update_policy ON "my_table" FOR UPDATE
USING (true)
WITH CHECK (
  current_setting('role') = 'app_admin'
  OR
  (
    current_setting('role') = 'app_user'
    AND user_id = get_current_user_id()
  )
)
WITH CHECK OPTION NOT ENFORCED;

方案2:调整SELECT策略,允许用户查看自己的已删除行(按需选择)

如果业务允许用户查看自己标记为删除的行,可以修改SELECT策略,让普通用户能访问自己的所有行(无论是否删除),后续在业务查询时再手动过滤未删除数据:

修改后的SELECT策略代码:

CREATE POLICY my_table_read_policy ON "my_table" FOR SELECT
USING (
  current_setting('role') = 'app_admin'
  OR
  (
    current_setting('role') = 'app_user'
    AND user_id = get_current_user_id()
  )
);

需要展示未删除数据时,在查询语句中添加WHERE deleted_at IS NULL即可。


内容的提问来源于stack exchange,提问作者dknaack

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 00:47:49