行级安全(Row Filter)

概述

行级安全(Row Filter,又称行访问策略)让你为表绑定一个返回 BOOLEAN 的过滤函数,系统在查询和 DML 时自动应用该函数——只有让函数返回

true
true
的行才对当前操作可见。常用于多租户隔离、按用户/角色做数据权限控制等场景。

行过滤的核心特点:

  • 过滤逻辑封装在一个 SQL 函数里,可在多张表上复用;
  • 函数中可使用
    current_user()
    current_user()
    、
    current_roles()
    current_roles()
    等安全上下文函数,按当前登录身份动态过滤;
  • 对
    SELECT
    SELECT
    、
    UPDATE
    UPDATE
    、
    DELETE
    DELETE
    、聚合查询全面生效;
  • UPDATE
    UPDATE
    /
    DELETE
    DELETE
    只作用于过滤后可见的行,不可见的行不受影响;
  • 可随时通过
    ALTER TABLE ... DROP ROW FILTER
    ALTER TABLE ... DROP ROW FILTER
    解除,数据不受影响。

使用步骤

第一步:创建过滤函数

过滤函数是一个返回

BOOLEAN
BOOLEAN
的 SQL 标量函数(参考 CREATE FUNCTION(SQL)),参数对应表中要参与判断的列。

行级安全最典型的用法是结合

current_user()
current_user()
按当前登录用户过滤——每个用户只能看到属于自己的行:

-- 每个用户只能看到 owner 列等于自己登录名的行 CREATE FUNCTION my_schema.owner_only(owner STRING) RETURNS BOOLEAN AS owner = current_user();

也可以结合

current_roles()
current_roles()
(返回当前用户的角色数组)做基于角色的过滤:

-- admin 角色可见全部行,其他用户只能看到 region = 'east' 的行 CREATE FUNCTION my_schema.role_based(region STRING) RETURNS BOOLEAN AS array_contains(current_roles(), 'admin') OR region = 'east';

过滤条件也可以是与身份无关的固定逻辑:

-- 只允许 region = 'east' 的行可见 CREATE FUNCTION my_schema.only_east(region STRING) RETURNS BOOLEAN AS region = 'east';

函数还可以接收多个参数,实现多列组合判断:

-- 只允许 east 区且金额 >= 200 的行可见 CREATE FUNCTION my_schema.east_big(region STRING, amt INT) RETURNS BOOLEAN AS region = 'east' AND amt >= 200;

第二步:绑定到表

建表时绑定

CREATE TABLE my_schema.docs ( id INT, owner STRING, content STRING ) ROW FILTER my_schema.owner_only ON (owner);

已有表绑定

ALTER TABLE my_schema.docs SET ROW FILTER my_schema.owner_only ON (owner);

ON (...)
ON (...)
中列出的列会按顺序作为参数传给过滤函数,列的类型和数量必须与函数定义匹配。

第三步:验证绑定

DESC EXTENDED my_schema.docs;

输出末尾会出现

# Row Filter
# Row Filter
段:

# Row Filter Function quick_start.my_schema.owner_only Bound Parameters owner

行为示例

以

owner_only
owner_only
(基于
current_user()
current_user()
)为例,假设当前登录用户是
alice
alice
:

INSERT INTO my_schema.docs VALUES (1, 'alice', 'alice doc'), (2, 'bob', 'bob doc'), (3, 'alice', 'another alice doc'); -- alice 查询:只返回 owner = 'alice' 的行 SELECT * FROM my_schema.docs ORDER BY id; -- 1 | alice | alice doc -- 3 | alice | another alice doc

同一条 SQL,不同用户登录时看到的数据不同——

bob
bob
登录时只会看到 id=2 的行。这就是行级安全按身份动态过滤的效果。

行过滤对各类操作的影响:

操作行为
SELECT
SELECT
只返回可见行(过滤函数返回 true 的行)
聚合(
COUNT
COUNT
/
SUM
SUM
等)
只统计可见行
UPDATE
UPDATE
只更新可见行,不可见行不受影响
DELETE
DELETE
只删除可见行,不可见行保留

例如

alice
alice
执行
UPDATE my_schema.docs SET content = 'updated' WHERE id IN (1,2,3)
UPDATE my_schema.docs SET content = 'updated' WHERE id IN (1,2,3)
,实际只有可见的 id=1、id=3 被更新,属于
bob
bob
的 id=2 不受影响。

多列过滤函数示例

CREATE FUNCTION my_schema.east_big(region STRING, amt INT) RETURNS BOOLEAN AS region = 'east' AND amt >= 200; CREATE TABLE my_schema.o2 (id INT, region STRING, amt INT) ROW FILTER my_schema.east_big ON (region, amt); INSERT INTO my_schema.o2 VALUES (1,'east',100), (2,'east',300), (3,'west',300); SELECT * FROM my_schema.o2 ORDER BY id; -- 2 | east | 300 (仅 region='east' 且 amt>=200 的行可见)

移除行过滤

ALTER TABLE my_schema.o2 DROP ROW FILTER;

移除后表中所有数据恢复可见,底层数据不受任何影响。

SELECT * FROM my_schema.o2 ORDER BY id; -- 1 | east | 100 -- 2 | east | 300 -- 3 | west | 300

注意事项

  • 过滤函数必须返回
    BOOLEAN
    BOOLEAN
    ,且
    ON (...)
    ON (...)
    列的类型/数量需与函数参数匹配。
  • 过滤函数建议使用 schema 限定名引用,避免解析失败。
  • 行过滤对写入(INSERT)的数据不做拦截——数据照常写入底层,只是查询/更新/删除时按过滤函数控制可见性。如需在写入侧也做约束,应结合应用层逻辑。
  • 一张表同一时间绑定一个行过滤函数;重新绑定可再次执行
    ALTER TABLE ... SET ROW FILTER
    ALTER TABLE ... SET ROW FILTER
    ,解除用
    ALTER TABLE ... DROP ROW FILTER
    ALTER TABLE ... DROP ROW FILTER
    。

参考

联系我们
预约咨询
微信咨询
电话咨询
邮件咨询