KingbaseES 实战:深度解析数据库对象访问权限管理

0 阅读11分钟

KingbaseES 实战:深度解析数据库对象访问权限管理

权限管理是数据库安全的基石。如果说用户连接控制是数据库的“大门”,那么对象访问权限就是“每一间房门”的钥匙。本文将带您深入金仓数据库 KingbaseES 的对象权限体系,从理论到实战,掌握权限的授予、查看、回收及默认权限管理的完整方法论,并重点剖析隐式角色PUBLIC的权限回收、search_path参数配置以及系统命名规范这三个关键实践。

在上一篇《KingbaseES实战:深度解析用户、会话与连接控制》中,我们探讨了如何控制谁能进入数据库。但进入之后呢?一个用户能否查询某表?能否在某模式中创建新表?这些进入数据库后的行为控制,正是本文要深度解析的对象访问权限管理


一、权限管理核心概念

1.1 从“门禁”到“房门”

金仓数据库的权限体系遵循“最小权限原则”。一个用户或角色连接到数据库后,默认情况下,除了拥有者(Owner)或超级用户,没有任何操作其他对象的权限。

对象权限的三层模型:

  • 数据库级权限:能否连接到数据库(CONNECT)、能否在库中创建临时表(TEMP/TEMPORARY)、能否在库中创建模式(CREATE
  • 模式级权限:能否使用模式中的对象(USAGE)、能否在模式中创建对象(CREATE
  • 对象级权限:对具体表、视图、函数等的操作权,如SELECTINSERTUPDATEDELETEEXECUTE

1.2 理解“拥有者(Owner)”

对象的创建者自动成为拥有者,拥有该对象的“生杀大权”(DROPGRANTREVOKE)。这些特殊权限是隐式的,无法被授予或撤销。

1.3 每个数据库都有一个public模式

重要概念:在KingbaseES中,每个数据库都有一个默认的public模式。当我们创建一个新数据库时,系统会自动在该数据库中创建一个名为public的模式。这个模式最初属于数据库的创建者(通常是system),并且默认情况下,PUBLIC角色(即所有用户)在该模式中拥有USAGECREATE权限。


二、实战准备:构建测试环境

我们将模拟一个名为 edu_platform 的在线教育平台数据库,进行完整的权限管理操作。

-- 以系统管理员SYSTEM连接数据库
[kingbase@node1 ~]$ ksql -Usystem -dtest

-- 1. 创建业务数据库edu_platform
CREATE DATABASE edu_platform;

-- 2. 切换到edu_platform数据库
\c edu_platform system

-- 3. 创建测试用户
CREATE USER instructor_li PASSWORD 'Kingbase_123';  -- 讲师李老师
CREATE USER student_zhang PASSWORD 'Kingbase_123';  -- 学生张同学
CREATE USER ta_wang PASSWORD 'Kingbase_123';        -- 助教王助教

-- 4. 创建业务模式与对象
GRANT CONNECT ON DATABASE edu_platform TO instructor_li;  --授予连接数据库的权限给instructor_li
CREATE SCHEMA course_schema;  -- 课程模式
ALTER SCHEMA course_schema OWNER TO instructor_li;  --将模式的拥有权转移给instructor_li
-- 创建课程表和选课记录表
CREATE TABLE course_schema.course_list (
    course_id INT PRIMARY KEY,
    course_name VARCHAR(100),
    instructor VARCHAR(50)
);

CREATE TABLE course_schema.enrollment (
    enroll_id INT PRIMARY KEY,
    student_name VARCHAR(50),
    course_id INT,
    enroll_date DATE
);

ALTER TABLE course_schema.course_list OWNER TO instructor_li;  --将表的拥有者变更为instructor_li
ALTER TABLE course_schema.enrollment OWNER TO instructor_li;  --将表的拥有者变更为instructor_li

-- 插入测试数据
\c edu_platform instructor_li
INSERT INTO course_schema.course_list VALUES (1, '数据库内核解析', '李老师');
INSERT INTO course_schema.course_list VALUES (2, 'Linux系统调优', '王老师');
INSERT INTO course_schema.enrollment VALUES (1, '张同学', 1, CURRENT_DATE);

三、授权实践:打开正确的“房门”

案例1:助教只读权限授予

助教 ta_wang 需要查看课程列表和选课情况,但不能修改任何数据。

-- 1. 授予连接数据库的权限
GRANT CONNECT ON DATABASE edu_platform TO ta_wang;

-- 2. 授予使用模式的权限
GRANT USAGE ON SCHEMA course_schema TO ta_wang;

-- 3. 授予表的SELECT权限
GRANT SELECT ON course_schema.course_list TO ta_wang;
GRANT SELECT ON course_schema.enrollment TO ta_wang;

-- 4. 验证
\c edu_platform ta_wang
SELECT * FROM course_schema.course_list;  -- 成功
INSERT INTO course_schema.course_list VALUES (3, 'SQL优化', '赵老师');  -- 失败!权限不足

-- 5. 权限查询
edu_platform=# \l edu_platform
                                            数据库列表
     名称     | 拥有者 | 字元编码 |  校对规则   |    Ctype    | ICU 排序 |        存取权限
--------------+--------+----------+-------------+-------------+----------+------------------------
 edu_platform | system | UTF8     | zh_CN.UTF-8 | zh_CN.UTF-8 |          | =Tc/system            +
              |        |          |             |             |          | system=CTc/system     +
              |        |          |             |             |          | instructor_li=c/system+
              |        |          |             |             |          | ta_wang=c/system
(1 行记录)

edu_platform=# \dn+ course_schema
                   架构模式列表
     名称      | 拥有者 |     存取权限     | 描述
---------------+--------+------------------+------
 course_schema | system | system=UC/system+|
               |        | ta_wang=U/system |
(1 行记录)

edu_platform=# \dp+ course_schema.*
                                   存取权限
   架构模式    |    名称     |  类型  |        存取权限        | 列特权 | 策略
---------------+-------------+--------+------------------------+--------+------
 course_schema | course_list | 数据表 | system=arwdDxtp/system+|        |
               |             |        | ta_wang=r/system       |        |
 course_schema | enrollment  | 数据表 | system=arwdDxtp/system+|        |
               |             |        | ta_wang=r/system       |        |
(2 行记录)

核心要点USAGE 权限是进入模式的“钥匙”,而 SELECT 等权限是打开特定“房门”的钥匙,两者缺一不可。

案例2:表列级更新权限授予

讲师 instructor_li 需要对自己课程表和选课记录有完全的增删改查权限。由于他是表的拥有者,这些权限默认就有。我们来看如何将表的“部分权限”授予他人。

-- 授予对特定列的UPDATE权限
\c edu_platform instructor_li
GRANT UPDATE (student_name, course_id) ON course_schema.enrollment TO ta_wang;

-- 验证
\c edu_platform ta_wang
UPDATE course_schema.enrollment SET student_name = '张小凡' WHERE enroll_id = 1;  -- 成功
UPDATE course_schema.enrollment SET enroll_date = '2026-01-01' WHERE enroll_id = 1;  -- 失败!因为未授予enroll_date列的UPDATE权限。
-- 权限查询
edu_platform=> \dp+ course_schema.enrollment
                                                   存取权限
   架构模式    |    名称    |  类型  |               存取权限               |          列特权           | 策略
---------------+------------+--------+--------------------------------------+---------------------------+------
 course_schema | enrollment | 数据表 | instructor_li=arwdDxtp/instructor_li+| student_name:            +|
               |            |        | ta_wang=r/instructor_li              |   ta_wang=w/instructor_li+|
               |            |        |                                      | course_id:               +|
               |            |        |                                      |   ta_wang=w/instructor_li |
(1 行记录)

案例3:学生插入权限授予

学生 student_zhang 需要能查看课程列表,并能向 enrollment 表插入自己的选课记录。

\c edu_platform system

GRANT CONNECT ON DATABASE edu_platform TO student_zhang;
GRANT USAGE ON SCHEMA course_schema TO student_zhang;
GRANT SELECT ON course_schema.course_list TO student_zhang;
-- 授予INSERT权限
GRANT INSERT ON course_schema.enrollment TO student_zhang;

\c edu_platform student_zhang
SELECT * FROM course_schema.course_list;  -- 成功
INSERT INTO course_schema.enrollment (enroll_id, student_name, course_id, enroll_date) 
VALUES (2, '张同学', 2, CURRENT_DATE);  -- 成功
-- 权限查询
edu_platform=# \l edu_platform
                                            数据库列表
     名称     | 拥有者 | 字元编码 |  校对规则   |    Ctype    | ICU 排序 |        存取权限
--------------+--------+----------+-------------+-------------+----------+------------------------
 edu_platform | system | UTF8     | zh_CN.UTF-8 | zh_CN.UTF-8 |          | =Tc/system            +
              |        |          |             |             |          | system=CTc/system     +
              |        |          |             |             |          | instructor_li=c/system+
              |        |          |             |             |          | ta_wang=c/system      +
              |        |          |             |             |          | student_zhang=c/system
(1 行记录)

edu_platform=# \dp+ course_schema.course_list
                                          存取权限
   架构模式    |    名称     |  类型  |               存取权限               | 列特权 | 策略
---------------+-------------+--------+--------------------------------------+--------+------
 course_schema | course_list | 数据表 | instructor_li=arwdDxtp/instructor_li+|        |
               |             |        | ta_wang=r/instructor_li             +|        |
               |             |        | student_zhang=r/instructor_li        |        |
(1 行记录)

edu_platform=# \dp+ course_schema.enrollment
                                                   存取权限
   架构模式    |    名称    |  类型  |               存取权限               |          列特权           | 策略
---------------+------------+--------+--------------------------------------+---------------------------+------
 course_schema | enrollment | 数据表 | instructor_li=arwdDxtp/instructor_li+| student_name:            +|
               |            |        | ta_wang=r/instructor_li             +|   ta_wang=w/instructor_li+|
               |            |        | student_zhang=a/instructor_li        | course_id:               +|
               |            |        |                                      |   ta_wang=w/instructor_li |
(1 行记录)

四、隐式角色PUBLIC:最大的安全隐患

【核心知识点】:在KingbaseES中,所有用户都属于PUBLIC角色。默认情况下,PUBLIC角色拥有一些“过于宽泛”的权限,这是生产环境最大的安全隐患。

4.1 PUBLIC在public模式中的默认权限

每个数据库都有自己的public模式。让我们以刚创建的edu_platform数据库为例,查看其public模式的默认权限:

-- 查看public模式的默认权限
\c edu_platform system
edu_platform=# \dn+ public
                        架构模式列表
  名称  | 拥有者 |     存取权限     |          描述
--------+--------+------------------+------------------------
 public | system | system=UC/system+| standard public schema
        |        | =UC/system       |
(1 行记录)

权限解读=UC/system表示PUBLIC角色拥有USAGECREATE权限,即任何能连接数据库的用户都可以在public模式下创建对象!

4.2 PUBLIC在数据库中的默认权限

-- 查看数据库的默认权限
\l edu_platform

     名称     | 拥有者 | 字元编码 |  校对规则   |    Ctype    |        存取权限        
--------------+--------+----------+-------------+-------------+------------------------
 edu_platform | system | UTF8     | zh_CN.UTF-8 | zh_CN.UTF-8 | =Tc/system            +
              |        |          |             |             | system=CTc/system

权限解读=Tc/system表示PUBLIC角色拥有TEMP(创建临时表)和CONNECT(连接)权限。

4.3 PUBLIC权限回收

【核心操作】:生产环境回收PUBLIC角色的默认权限

-- 回收PUBLIC在public模式中的所有权限
REVOKE ALL ON SCHEMA public FROM PUBLIC;

-- 回收PUBLIC在数据库中的connect和temp权限
REVOKE CONNECT, TEMP ON DATABASE edu_platform FROM PUBLIC;

-- 验证回收结果
\dn+ public
 名称   | 拥有者 |        存取权限         |        描述        
--------+--------+-------------------------+---------------------
 public | system | system=UC/system        | standard public schema

\l edu_platform
     名称     | 拥有者 | 字元编码 |  校对规则   |    Ctype    |        存取权限        
--------------+--------+----------+-------------+-------------+------------------------
 edu_platform | system | UTF8     | zh_CN.UTF-8 | zh_CN.UTF-8 | system=CTc/system
-- 注意:"=Tc/system" 已经消失,只剩下具体的用户授权

4.4 按需授予权限

回收PUBLIC默认权限后,需要按需为特定用户授权:

-- 授予用户ta_wang在public模式中的CREATE权限
GRANT CREATE ON SCHEMA public TO ta_wang;

-- 授予用户student_zhang连接权限
GRANT CONNECT ON DATABASE edu_platform TO student_zhang;

-- 查看授权结果
\dn+ public
 名称   | 拥有者 |        存取权限         |        描述        
--------+--------+-------------------------+---------------------
 public | system | system=UC/system+       | standard public schema
        |        | ta_wang=C/system         |

\l edu_platform
     名称     | 拥有者 | 字元编码 |  校对规则   |    Ctype    |        存取权限        
--------------+--------+----------+-------------+-------------+------------------------
 edu_platform | system | UTF8     | zh_CN.UTF-8 | zh_CN.UTF-8 | system=CTc/system+
              |        |          |             |             | student_zhang=c/system
-- 注意:student_zhang只获得了c(CONNECT)权限,没有TEMP和CREATE权限

五、search_path深度解析与配置

5.1 search_path的作用与默认值

search_path(搜索路径)决定了当SQL语句中未指定模式名时,数据库会按照什么顺序去查找对象。理解并正确配置search_path,对于简化SQL书写、避免对象访问歧义至关重要。

KingbaseES的默认search_path

-- 查看当前search_path
SHOW search_path;
   search_path
-----------------
 "$user", public

默认值含义

  • "$user":优先查找与当前用户名同名的模式(如果存在且用户有USAGE权限)
  • public:然后查找public模式

5.2 系统目录模式 sys_catalog 的特殊地位

系统目录模式 sys_catalog 总是被搜索,不管它是否在搜索路径中被提及

搜索路径的实际规则

  1. 临时模式 sys_temp_nnn(如果存在)总是最先被搜索(用于表、视图、序列等关系对象)
  2. 系统目录模式 sys_catalog 总是在搜索路径中的任何用户模式之前被搜索
  3. search_path 中显式列出的模式按顺序搜索

如果 sys_catalog 被显式添加到 search_path 中,它将按照路径中指定的顺序被搜索;如果不在路径中,它将在任何路径项之前被搜索。

这意味着:

  • sys_catalog 的优先级始终高于 search_path 中除临时模式外的所有用户模式
  • 当您查询 sys_users 时,数据库会先搜索 sys_catalog,找到系统视图后直接返回
  • 这就是为什么业务表与系统对象同名时,查询结果总是系统对象

5.3 查看search_path的三种方式

-- 方式1:通过系统视图查询(显示当前会话值)
SELECT name, setting, source FROM sys_settings WHERE name='search_path';

    name     |     setting     | source
-------------+-----------------+---------
 search_path | "$user", public | default
(1 行记录)
-- source字段显示该值来自哪里(配置文件/数据库/用户/会话)

-- 方式2:通过current_setting函数
SELECT current_setting('search_path');

-- 方式3:使用show命令(最常用)
SHOW search_path;

5.4 search_path的设置级别与生效方式

search_path 的设置与其他参数方式一样

📌 设置级别与生效规则
设置级别命令示例生效范围生效方式验证方法
数据库级ALTER DATABASE ... SET search_path该数据库新建立的连接需新建连接生效,已有连接不受影响查看sys_db_role_setting或新建连接验证
用户级ALTER USER ... SET search_path该用户新建立的连接需新建连接生效,已有连接不受影响查看sys_db_role_setting或新建连接验证
用户+数据库级ALTER USER ... IN DATABASE ... SET特定用户连接特定数据库的新连接需新建连接生效,已有连接不受影响最高优先级,查看sys_db_role_setting
会话级SET search_path TO ...当前会话立即生效SHOW search_path;
实例级修改kingbase.conf文件整个实例的所有连接重启数据库生效查看配置文件或重启后验证
🔧 具体操作与验证

1. 数据库级别设置

-- 设置:对 edu_platform 数据库生效
ALTER DATABASE edu_platform SET search_path TO "$user", public, course_schema;

-- 设置后需要重载配置(使设置写入配置文件)
SELECT sys_reload_conf();

-- 验证方式1:查看数据库级别的定制化参数
SELECT * FROM sys_db_role_setting 
WHERE setdatabase = (SELECT oid FROM sys_database WHERE datname = 'edu_platform');

-- 验证方式2:新建连接测试(必须)
-- 退出当前连接,重新连接后验证
\c edu_platform system
SHOW search_path;

2. 用户级别设置

-- 设置:对 student_zhang 用户生效
ALTER USER student_zhang SET search_path TO "$user", public, course_schema;

-- 验证方式1:查看用户级别的定制化参数
SELECT * FROM sys_db_role_setting 
WHERE setrole = (SELECT oid FROM sys_authid WHERE rolname = 'student_zhang');

-- 验证方式2:新建用户连接测试
\c edu_platform student_zhang
SHOW search_path;

3. 用户+数据库级别设置(最高优先级)

-- 设置:student_zhang 用户连接 edu_platform 时生效
ALTER USER student_zhang IN DATABASE edu_platform 
    SET search_path TO "$user", public, course_schema;

-- 重载配置
SELECT sys_reload_conf();

-- 验证:查看特定用户+数据库的定制化参数
SELECT * FROM sys_db_role_setting 
WHERE setrole = (SELECT oid FROM sys_authid WHERE rolname = 'student_zhang')
  AND setdatabase = (SELECT oid FROM sys_database WHERE datname = 'edu_platform');

4. 会话级别设置(临时测试)

-- 立即生效,仅当前会话有效
SET search_path TO "$user", public, course_schema;

-- 验证
SHOW search_path;
🔍 查看所有search_path配置
-- 查看所有定制化参数(数据库级、用户级、用户+数据库级)
SELECT 
    d.datname AS database_name,
    r.rolname AS role_name,
    s.setconfig
FROM sys_db_role_setting s
LEFT JOIN sys_database d ON s.setdatabase = d.oid
LEFT JOIN sys_authid r ON s.setrole = r.oid;

-- 查看当前会话的search_path及其来源
SELECT 
    name, 
    setting, 
    source  -- 显示值来源(配置文件/数据库/用户/会话)
FROM sys_settings 
WHERE name = 'search_path';
⚠️ 重要说明
  1. sys_reload_conf() 的作用:使 ALTER DATABASE/USER 的设置写入配置文件并生效,但只影响新连接
  2. 已有连接不受影响:已存在的数据库连接仍使用连接建立时的search_path值
  3. 优先级规则:用户+数据库级 > 用户级 > 数据库级 > 实例级
  4. 验证原则:修改后务必新建连接验证,不能只在当前会话中测试

5.5 为简化SQL书写配置search_path

在我们构建的edu_platform数据库中,已经回收了public模式的PUBLIC权限,业务表都存储在course_schema模式中。为了让学生student_zhang能够更方便地查询课程表,我们可以配置search_path,让他无需每次都在表名前指定模式名。

-- 当前,student_zhang查询course_list表需要指定模式名
\c edu_platform student_zhang
SELECT * FROM course_schema.course_list;  -- 需要写模式名,略显繁琐

-- 配置search_path,将course_schema加入搜索路径
\c edu_platform system
ALTER USER student_zhang IN DATABASE edu_platform 
    SET search_path TO "$user", public, course_schema;
SELECT sys_reload_conf();

-- 验证配置
\c edu_platform student_zhang
SHOW search_path;
     search_path     
---------------------
 "$user", public, course_schema

-- 现在可以简化SQL书写
SELECT * FROM course_list;  -- 自动匹配到course_schema.course_list
SELECT * FROM enrollment;   -- 自动匹配到course_schema.enrollment

重要提醒:配置search_path只是简化了SQL书写,并不代表用户自动获得了权限student_zhang能够查询这些表,是因为我们在“案例3”中已经授予了他相应的SELECTINSERT权限。权限和搜索路径是两个独立的概念,需要分别配置和验证。

5.6 典型案例:同名对象引发的歧义问题

【案例背景】
用户在 public 模式下创建了一张名为 sys_user 的业务表,而 sys_catalog 模式中也存在同名的系统视图。

【问题现象】
执行 SELECT * FROM sys_user; 时,返回的是系统视图 sys_catalog.sys_user 的数据,而非用户期望的业务表。

【原因分析】
根据数据库内核的搜索路径规则:

  1. 系统目录模式 sys_catalog 总是被优先搜索(除非临时模式存在)
  2. 因此,查询 sys_user 时,数据库先在 sys_catalog 中找到系统视图并返回
  3. 即使 public.sys_user 存在,且 publicsearch_path 中,也不会被搜索到

【正确解决方案】

1. (推荐)显式指定模式名

SELECT * FROM public.sys_user;    -- 明确查询用户表

2. 避免命名冲突
在设计业务表时,避免使用 sys_ 开头的名称,以防止与 KingbaseES 系统对象冲突。

5.7 典型案例:错误配置导致无法创建对象

【故障现象】
修改search_path为"$user", sys_catalog后,创建表时出现权限错误:

test=# CREATE TABLE t01 (id int);
ERROR:  创建 "sys_catalog.t01" 权限不够
描述:  系统表修改是不被同时允许的

【原因分析】
sys_catalog模式用于存储系统对象,普通用户(甚至system用户)不能在sys_catalog中创建用户表。当search_path设置为"$user", sys_catalog时,创建表时会优先尝试在sys_catalog中创建,从而导致权限错误。

【解决方案】
恢复正确的search_path配置:

-- 修改为正确的search_path
ALTER DATABASE prod SET search_path TO "$user", public;
SELECT sys_reload_conf();

-- 验证
SHOW search_path;
   search_path
-----------------
 "$user", public

六、命名规范深度解析:规避 sys_ 前缀风险

6.1 为什么必须规避 sys_ 前缀

在 KingbaseES 中,所有系统内置的表、视图、函数和扩展对象均采用 sys_ 作为前缀(如 sys_userssys_classsys_stat_activity 等)。这些对象由数据库内核或官方扩展管理,是系统运行和监控的基础。

6.2 与权限管理的直接关联

使用 sys_ 前缀命名业务表,不仅会导致查询歧义,还会引发权限管理问题:

  • 系统对象权限不可修改sys_catalog 中的系统对象权限由内核管理,普通用户无法也不应修改
  • 误操作风险:当业务表被误认为系统表时,可能被监控脚本、审计程序错误处理
  • 权限模型混乱:系统对象和业务对象混用同一命名空间,破坏权限模型的清晰度
  • 未来升级风险:KingbaseES 新版本可能新增 sys_xxx 系统对象,若业务已使用相同名称,可能导致升级失败或应用异常

6.3 禁止行为与推荐做法

🔒 禁止行为
-- ❌ 危险:与系统视图同名
CREATE TABLE sys_users (...);
CREATE VIEW sys_config AS ...;
CREATE FUNCTION sys_get_status();
推荐做法
  • 使用业务语义化前缀无前缀命名
    -- ✅ 安全且清晰
    CREATE TABLE edu_users (...);
    CREATE VIEW course_enrollment_stats AS ...;
    CREATE FUNCTION calc_score(...);
    
  • 如需统一命名空间,可采用项目/模块前缀(如 edu_pay_log_),但不要使用 sys_pg_information_schema 等保留前缀

请将 sys_ 前缀留给数据库,把清晰、安全、可维护的命名空间留给自己


七、默认权限(ALTER DEFAULT PRIVILEGES)

配置默认权限,让未来创建的对象自动获得权限,进一步简化权限管理:

-- 设置默认权限:instructor_li未来在course_schema中创建的表,自动授予ta_wang查询权限
\c edu_platform instructor_li
ALTER DEFAULT PRIVILEGES IN SCHEMA course_schema 
    GRANT SELECT ON TABLES TO ta_wang;

-- 测试
CREATE TABLE course_schema.course_feedback (feedback_id int, content text);
\dp course_schema.course_feedback
                                            存取权限
   架构模式    |      名称       |  类型  |               存取权限               | 列特权 | 策略
---------------+-----------------+--------+--------------------------------------+--------+------
 course_schema | course_feedback | 数据表 | instructor_li=arwdDxtp/instructor_li+|        |
               |                 |        | ta_wang=r/instructor_li              |        |
(1 行记录)

-- 可以看到ta_wang自动获得了SELECT权限,无需手动授予

八、权限诊断与排查

8.1 权限查询函数

-- 检查数据库权限
SELECT has_database_privilege('student_zhang', 'edu_platform', 'CONNECT');

-- 检查模式权限
SELECT has_schema_privilege('student_zhang', 'course_schema', 'USAGE');

-- 检查表权限
SELECT has_table_privilege('ta_wang', 'course_schema.enrollment', 'UPDATE');

-- 检查列权限
SELECT has_column_privilege('ta_wang', 'course_schema.enrollment', 'student_name', 'UPDATE');

8.2 系统视图查询权限

-- 查看用户的所有表权限
SELECT * FROM information_schema.table_privileges 
WHERE grantee = 'student_zhang';

-- 使用aclexplode解码权限字符串(查看详细权限)
SELECT * FROM aclexplode(
    (SELECT relacl FROM sys_class WHERE relname='enrollment')
);

8.3 搜索路径有效值查看

-- 查看当前搜索路径的有效解析结果
SELECT current_schemas(true);  -- true表示包含隐式模式(sys_catalog、临时模式等)
SELECT current_schemas(false); -- false表示只返回search_path中显式列出的模式

8.4 权限问题排查思路

当用户报告“无法访问某张表”时,按以下顺序排查:

  1. 用户能否连接数据库?

    SELECT has_database_privilege('username', 'edu_platform', 'CONNECT');
    
  2. 用户能否使用模式?

    SELECT has_schema_privilege('username', 'schemaname', 'USAGE');
    
  3. 用户对表有什么权限?

    -- 使用aclexplode解码权限字符串
    SELECT * FROM aclexplode(
        (SELECT relacl FROM sys_class WHERE relname='enrollment')
    );
    
  4. 检查search_path配置是否正确

    -- 切换到问题用户查看
    \c edu_platform username
    SHOW search_path;
    SELECT current_schemas(true);  -- 查看实际生效的搜索顺序
    
  5. 检查是否存在同名系统对象冲突

    -- 如果表名以sys_开头,尝试显式指定模式名查询
    SELECT * FROM public.sys_mytable;
    

九、权限管理完整流程图

tongyi-mermaid-2026-02-18-203807.png

总结与最佳实践

本文通过 edu_platform 数据库的完整案例,系统介绍了 KingbaseES 对象访问权限管理的核心要点:

  1. 【必做】回收PUBLIC默认权限

    REVOKE ALL ON SCHEMA public FROM PUBLIC;
    REVOKE CONNECT, TEMP ON DATABASE edu_platform FROM PUBLIC;
    
  2. 分层授权:数据库→模式→对象,逐级授予必要权限

  3. search_path 配置要点

  • 保持默认的 "$user", public 顺序

  • 业务模式可追加在 public 之后:"$user", public, business_schema

  • 不要将 sys_catalog 显式加入 search_path

  • 修改后需新建连接验证:SHOW search_path;、SELECT current_schemas(true);

  • 牢记:search_path 只简化 SQL 书写,不替代权限授予

  1. 理解系统目录模式 sys_catalog 的特殊性

    • 默认它优先级高于 search_path 中的用户模式
    • 正确做法:显式指定模式名(public.sys_users)或避免使用 sys_ 前缀务对象
  2. 利用默认权限:使用ALTER DEFAULT PRIVILEGES为未来对象自动授权

  3. 权限诊断:熟练使用has_*_privilege函数、information_schema视图、aclexplode解码

  4. 命名规范避免在业务对象中使用 sys_pg_ 等系统保留前缀


掌握这些权限管理技能,您就能从“谁能进数据库”的粗粒度控制,提升到“谁能做什么”的精细化管控层面。特别是 PUBLIC 默认权限的回收、search_path 的正确配置和命名规范,是日常运维中需要特别关注的三个关键实践。