
# 行级访问控制
行级访问控制特性将数据库访问控制精确到数据表行级别，使数据库达到行级访问控制的能力。不同用户执行相同的SQL查询操作，读取到的结果是不同的。
用户可以在数据表创建行访问控制(Row Level Security)策略，该策略是指针对特定数据库用户、特定SQL操作生效的表达式。当数据库用户对数据表访问时，若SQL满足数据表特定的Row Level Security策略，在查询优化阶段将满足条件的表达式，按照属性(PERMISSIVE \| RESTRICTIVE)类型，通过AND或OR方式拼接，应用到执行计划上。
行级访问控制的目的是控制表中行级数据可见性，通过在数据表上预定义Filter，在查询优化阶段将满足条件的表达式应用到执行计划上，影响最终的执行结果。当前受影响的SQL语句包括SELECT、UPDATE和DELETE。
例如：某表中汇总了不同用户的数据，但是不同用户只能查看自身相关的数据信息，不能查看其他用户的数据信息。
- 非透明多写特性下：
  ```
  --创建用户alice, bob, peter
  gaussdb=# CREATE USER alice PASSWORD '********';
  gaussdb=# CREATE USER bob PASSWORD '********';
  gaussdb=# CREATE USER peter PASSWORD '********';
  --创建表all_data，包含不同用户数据信息
  gaussdb=# CREATE TABLE all_data(id int, role varchar(100), data varchar(100));
  --向数据表插入数据
  gaussdb=# INSERT INTO all_data VALUES(1, 'alice', 'alice data');
  gaussdb=# INSERT INTO all_data VALUES(2, 'bob', 'bob data');
  gaussdb=# INSERT INTO all_data VALUES(3, 'peter', 'peter data');
  --将表all_data的读取权限赋予alice，bob和peter用户
  gaussdb=# GRANT SELECT ON all_data TO alice, bob, peter;
  --打开行访问控制策略开关
  gaussdb=# ALTER TABLE all_data ENABLE ROW LEVEL SECURITY;
  --创建行访问控制策略，当前用户只能查看用户自身的数据
  gaussdb=# CREATE ROW LEVEL SECURITY POLICY all_data_rls ON all_data USING(role = CURRENT_USER);
  --查看表详细信息
  gaussdb=# \d+ all_data
                                 Table "public.all_data"
   Column |          Type          | Modifiers | Storage  | Stats target | Description
  --------+------------------------+-----------+----------+--------------+-------------
   id     | integer                |           | plain    |              |
   role   | character varying(100) |           | extended |              |
   data   | character varying(100) |           | extended |              |
  Row Level Security Policies:
      POLICY "all_data_rls" FOR ALL
        TO public
        USING (((role)::name = "current_user"()))
  Has OIDs: no
  Distribute By: HASH(id)
  Location Nodes: ALL DATANODES
  Options: orientation=row, compression=no, enable_rowsecurity=true
  --切换至用户alice，执行SQL"SELECT * FROM public.all_data"
  gaussdb=# SELECT * FROM public.all_data;
   id | role  |    data
  ----+-------+------------
    1 | alice | alice data
  (1 row)
  gaussdb=# EXPLAIN(COSTS OFF) SELECT * FROM public.all_data;
                             QUERY PLAN
  ----------------------------------------------------------------
   Streaming (type: GATHER)
     Node/s: All datanodes
     ->  Seq Scan on all_data
           Filter: ((role)::name = 'alice'::name)
   Notice: This query is influenced by row level security feature
  (5 rows)
  --切换至用户peter，执行SQL"SELECT * FROM public.all_data"
  gaussdb=# SELECT * FROM public.all_data;
   id | role  |    data
  ----+-------+------------
    3 | peter | peter data
  (1 row)
  gaussdb=# EXPLAIN(COSTS OFF) SELECT * FROM public.all_data;
                             QUERY PLAN
  ----------------------------------------------------------------
   Streaming (type: GATHER)
     Node/s: All datanodes
     ->  Seq Scan on all_data
           Filter: ((role)::name = 'peter'::name)
   Notice: This query is influenced by row level security feature
  (5 rows)
  ```
  
![](https://support.huaweicloud.com/distributed-devg-v10-gaussdb/public_sys-resources/notice_3.0-zh-cn.png)
- PG_STATISTIC系统表和PG_STATISTIC_EXT系统表存储了统计对象的一些敏感信息，如高频值MCV。若创建行级访问控制后，将这两张系统表的查询权限授予普通用户，则普通用户仍然可以通过访问这两张系统表，获取统计对象里的敏感信息。
- PG_STATS、PG_EXT_STATS、PG_GTT_STATS为统计信息查询视图，校验用户对列的SELECT权限。若普通用户拥有SELECT权限且表上存在行级访问控制，可能查询到无权限查询但刚好出现在统计信息高频值里的部分数据（非整行数据，仅是某列的一个值，统计信息是按列收集计算的）。
 
