KingbaseES 实战:深度解析数据库对象访问权限管理
权限管理是数据库安全的基石。如果说用户连接控制是数据库的"大门",那么对象访问权限就是"每一间房门"的钥匙。本文将带您深入金仓数据库 KingbaseES 的对象权限体系,从理论到实战,掌握权限的授予、查看、回收及默认权限管理的完整方法论,并重点剖析隐式角色PUBLIC的权限回收、
search_path参数配置以及系统命名规范这三个关键实践。
在上一篇《KingbaseES实战:深度解析用户、会话与连接控制》中,我们探讨了如何控制谁能进入数据库。但进入之后呢?一个用户能否查询某表?能否在某模式中创建新表?这些进入数据库后的行为控制 ,正是本文要深度解析的对象访问权限管理。
一、权限管理核心概念
1.1 从"门禁"到"房门"
金仓数据库的权限体系遵循"最小权限原则"。一个用户或角色连接到数据库后,默认情况下,除了拥有者(Owner)或超级用户,没有任何操作其他对象的权限。
对象权限的三层模型:
- 数据库级权限 :能否连接到数据库(
CONNECT)、能否在库中创建临时表(TEMP/TEMPORARY)、能否在库中创建模式(CREATE) - 模式级权限 :能否使用模式中的对象(
USAGE)、能否在模式中创建对象(CREATE) - 对象级权限 :对具体表、视图、函数等的操作权,如
SELECT、INSERT、UPDATE、DELETE、EXECUTE等
1.2 理解"拥有者(Owner)"
对象的创建者自动成为拥有者,拥有该对象的"生杀大权"(DROP、GRANT、REVOKE)。这些特殊权限是隐式的,无法被授予或撤销。
1.3 每个数据库都有一个public模式
重要概念 :在KingbaseES中,每个数据库都有一个默认的public模式 。当我们创建一个新数据库时,系统会自动在该数据库中创建一个名为public的模式。这个模式最初属于数据库的创建者(通常是system),并且默认情况下,PUBLIC角色(即所有用户)在该模式中拥有USAGE和CREATE权限。
二、实战准备:构建测试环境
我们将模拟一个名为 edu_platform 的在线教育平台数据库,进行完整的权限管理操作。
sql
-- 以系统管理员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 需要查看课程列表和选课情况,但不能修改任何数据。
sql
-- 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 需要对自己课程表和选课记录有完全的增删改查权限。由于他是表的拥有者,这些权限默认就有。我们来看如何将表的"部分权限"授予他人。
sql
-- 授予对特定列的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 表插入自己的选课记录。
sql
\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模式的默认权限:
sql
-- 查看public模式的默认权限
\c edu_platform system
edu_platform=# \dn+ public
架构模式列表
名称 | 拥有者 | 存取权限 | 描述
--------+--------+------------------+------------------------
public | system | system=UC/system+| standard public schema
| | =UC/system |
(1 行记录)
权限解读 :=UC/system表示PUBLIC角色拥有USAGE和CREATE权限,即任何能连接数据库的用户都可以在public模式下创建对象!
4.2 PUBLIC在数据库中的默认权限
sql
-- 查看数据库的默认权限
\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角色的默认权限
sql
-- 回收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默认权限后,需要按需为特定用户授权:
sql
-- 授予用户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:
sql
-- 查看当前search_path
SHOW search_path;
search_path
-----------------
"$user", public
默认值含义:
"$user":优先查找与当前用户名同名的模式(如果存在且用户有USAGE权限)public:然后查找public模式
5.2 系统目录模式 sys_catalog 的特殊地位
系统目录模式 sys_catalog 总是被搜索,不管它是否在搜索路径中被提及。
搜索路径的实际规则:
- 临时模式
sys_temp_nnn(如果存在)总是最先被搜索(用于表、视图、序列等关系对象) - 系统目录模式
sys_catalog总是在搜索路径中的任何用户模式之前被搜索 search_path中显式列出的模式按顺序搜索
如果
sys_catalog被显式添加到search_path中,它将按照路径中指定的顺序被搜索;如果不在路径中,它将在任何路径项之前被搜索。
这意味着:
sys_catalog的优先级始终高于search_path中除临时模式外的所有用户模式- 当您查询
sys_users时,数据库会先搜索sys_catalog,找到系统视图后直接返回 - 这就是为什么业务表与系统对象同名时,查询结果总是系统对象
5.3 查看search_path的三种方式
sql
-- 方式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. 数据库级别设置
sql
-- 设置:对 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. 用户级别设置
sql
-- 设置:对 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. 用户+数据库级别设置(最高优先级)
sql
-- 设置: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. 会话级别设置(临时测试)
sql
-- 立即生效,仅当前会话有效
SET search_path TO "$user", public, course_schema;
-- 验证
SHOW search_path;
🔍 查看所有search_path配置
sql
-- 查看所有定制化参数(数据库级、用户级、用户+数据库级)
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';
⚠️ 重要说明
sys_reload_conf()的作用 :使ALTER DATABASE/USER的设置写入配置文件并生效,但只影响新连接- 已有连接不受影响:已存在的数据库连接仍使用连接建立时的search_path值
- 优先级规则:用户+数据库级 > 用户级 > 数据库级 > 实例级
- 验证原则 :修改后务必新建连接验证,不能只在当前会话中测试
5.5 为简化SQL书写配置search_path
在我们构建的edu_platform数据库中,已经回收了public模式的PUBLIC权限,业务表都存储在course_schema模式中。为了让学生student_zhang能够更方便地查询课程表,我们可以配置search_path,让他无需每次都在表名前指定模式名。
sql
-- 当前,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"中已经授予了他相应的SELECT和INSERT权限。权限和搜索路径是两个独立的概念,需要分别配置和验证。
5.6 典型案例:同名对象引发的歧义问题
【案例背景】
用户在 public 模式下创建了一张名为 sys_user 的业务表,而 sys_catalog 模式中也存在同名的系统视图。
【问题现象】
执行 SELECT * FROM sys_user; 时,返回的是系统视图 sys_catalog.sys_user 的数据,而非用户期望的业务表。
【原因分析】
根据数据库内核的搜索路径规则:
- 系统目录模式
sys_catalog总是被优先搜索(除非临时模式存在) - 因此,查询
sys_user时,数据库先在sys_catalog中找到系统视图并返回 - 即使
public.sys_user存在,且public在search_path中,也不会被搜索到
【正确解决方案】
1. (推荐)显式指定模式名:
sql
SELECT * FROM public.sys_user; -- 明确查询用户表
2. 避免命名冲突 :
在设计业务表时,避免使用 sys_ 开头的名称,以防止与 KingbaseES 系统对象冲突。
5.7 典型案例:错误配置导致无法创建对象
【故障现象】
修改search_path为"$user", sys_catalog后,创建表时出现权限错误:
sql
test=# CREATE TABLE t01 (id int);
ERROR: 创建 "sys_catalog.t01" 权限不够
描述: 系统表修改是不被同时允许的
【原因分析】
sys_catalog模式用于存储系统对象,普通用户(甚至system用户)不能在sys_catalog中创建用户表。当search_path设置为"$user", sys_catalog时,创建表时会优先尝试在sys_catalog中创建,从而导致权限错误。
【解决方案】
恢复正确的search_path配置:
sql
-- 修改为正确的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_users、sys_class、sys_stat_activity 等)。这些对象由数据库内核或官方扩展管理,是系统运行和监控的基础。
6.2 与权限管理的直接关联
使用 sys_ 前缀命名业务表,不仅会导致查询歧义,还会引发权限管理问题:
- 系统对象权限不可修改 :
sys_catalog中的系统对象权限由内核管理,普通用户无法也不应修改 - 误操作风险:当业务表被误认为系统表时,可能被监控脚本、审计程序错误处理
- 权限模型混乱:系统对象和业务对象混用同一命名空间,破坏权限模型的清晰度
- 未来升级风险 :KingbaseES 新版本可能新增
sys_xxx系统对象,若业务已使用相同名称,可能导致升级失败或应用异常
6.3 禁止行为与推荐做法
🔒 禁止行为
sql
-- ❌ 危险:与系统视图同名
CREATE TABLE sys_users (...);
CREATE VIEW sys_config AS ...;
CREATE FUNCTION sys_get_status();
✅ 推荐做法
-
使用业务语义化前缀 或无前缀命名 :
sql-- ✅ 安全且清晰 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)
配置默认权限,让未来创建的对象自动获得权限,进一步简化权限管理:
sql
-- 设置默认权限: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 权限查询函数
sql
-- 检查数据库权限
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 系统视图查询权限
sql
-- 查看用户的所有表权限
SELECT * FROM information_schema.table_privileges
WHERE grantee = 'student_zhang';
-- 使用aclexplode解码权限字符串(查看详细权限)
SELECT * FROM aclexplode(
(SELECT relacl FROM sys_class WHERE relname='enrollment')
);
8.3 搜索路径有效值查看
sql
-- 查看当前搜索路径的有效解析结果
SELECT current_schemas(true); -- true表示包含隐式模式(sys_catalog、临时模式等)
SELECT current_schemas(false); -- false表示只返回search_path中显式列出的模式
8.4 权限问题排查思路
当用户报告"无法访问某张表"时,按以下顺序排查:
-
用户能否连接数据库?
sqlSELECT has_database_privilege('username', 'edu_platform', 'CONNECT'); -
用户能否使用模式?
sqlSELECT has_schema_privilege('username', 'schemaname', 'USAGE'); -
用户对表有什么权限?
sql-- 使用aclexplode解码权限字符串 SELECT * FROM aclexplode( (SELECT relacl FROM sys_class WHERE relname='enrollment') ); -
检查search_path配置是否正确
sql-- 切换到问题用户查看 \c edu_platform username SHOW search_path; SELECT current_schemas(true); -- 查看实际生效的搜索顺序 -
检查是否存在同名系统对象冲突
sql-- 如果表名以sys_开头,尝试显式指定模式名查询 SELECT * FROM public.sys_mytable;
九、权限管理完整流程图
总结与最佳实践
本文通过 edu_platform 数据库的完整案例,系统介绍了 KingbaseES 对象访问权限管理的核心要点:
-
【必做】回收PUBLIC默认权限
sqlREVOKE ALL ON SCHEMA public FROM PUBLIC; REVOKE CONNECT, TEMP ON DATABASE edu_platform FROM PUBLIC; -
分层授权:数据库→模式→对象,逐级授予必要权限
-
search_path 配置要点
-
保持默认的 "$user", public 顺序
-
业务模式可追加在 public 之后:"$user", public, business_schema
-
不要将 sys_catalog 显式加入 search_path
-
修改后需新建连接验证:SHOW search_path;、SELECT current_schemas(true);
-
牢记:search_path 只简化 SQL 书写,不替代权限授予
-
理解系统目录模式
sys_catalog的特殊性- 默认它优先级高于 search_path 中的用户模式,
- 正确做法 :显式指定模式名(
public.sys_users)或避免使用sys_前缀务对象
-
利用默认权限 :使用
ALTER DEFAULT PRIVILEGES为未来对象自动授权 -
权限诊断 :熟练使用
has_*_privilege函数、information_schema视图、aclexplode解码 -
命名规范 :避免在业务对象中使用
sys_、pg_等系统保留前缀
掌握这些权限管理技能,您就能从"谁能进数据库"的粗粒度控制,提升到"谁能做什么"的精细化管控层面。特别是 PUBLIC 默认权限的回收、search_path 的正确配置和命名规范,是日常运维中需要特别关注的三个关键实践。
