如何使用Policy与RLS实现表查询自动过滤deleted=true的行
RLS 过滤已删除行实现方案
RLS是实现该需求的最优方案,你写的策略逻辑本身没有问题,未生效通常是几个常见的配置疏漏导致的。
常见不生效原因排查
- 执行查询的账号是超级用户:PostgreSQL超级用户默认会绕过所有RLS规则,你可以切换普通用户测试,或者手动开启当前会话的RLS强制校验:
set row_security = on; - 未对表所有者开启RLS强制校验:默认表的创建者不受RLS限制,如果你需要所有者也遵守策略,你写的
force row level security配置已经满足该要求,确认该语句执行成功即可。 - 数据库全局RLS开关未开启:执行
show row_security;检查参数值是否为on,默认该配置是开启状态,若为off需要修改postgresql.conf配置文件重启生效。
完整正确实现步骤
-- 1. 先确保deleted字段有默认值,避免NULL值导致的逻辑异常 ALTER TABLE my_table ALTER COLUMN deleted SET DEFAULT false; -- 2. 开启表的行级安全 ALTER TABLE my_table ENABLE ROW LEVEL SECURITY; -- 可选:强制表所有者也受RLS限制,不需要可以删除该行 ALTER TABLE my_table FORCE ROW LEVEL SECURITY; -- 3. 创建查询过滤策略,你原来的逻辑可以正常使用 CREATE policy hide_deleted_rows ON my_table FOR SELECT TO public USING (deleted IS NOT true);
配置完成后用普通用户执行select * from my_table where deleted = true;就会返回空结果,符合你的预期。
为什么不推荐用触发器实现
PostgreSQL本身没有BEFORE SELECT类型的触发器,你无法通过触发器直接拦截SELECT查询做行过滤。如果不用RLS,替代方案是创建带过滤条件的视图,给所有用户开放视图查询权限、收回基表的直接访问权限,但这种方案需要改上层业务的查询逻辑,也容易出现权限漏配的问题,远不如RLS易用可靠。
内容的提问来源于stack exchange,提问作者Denis Yakovenko
相关产品推荐
相关产品推荐

