行级安全(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

参考

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