人大金仓 KingbaseES 学习 04:用户、角色、数据库、模式和表空间
目标
前三篇已经完成 KingbaseES V9 单机部署、服务验证和 KSQL 基础巡检。这一篇进入对象和权限基础:数据库、角色、schema、表空间,以及这些对象之间的边界。
这一章不追求一下子把权限体系讲完,而是先用一个最小实验跑通:
- 看清楚默认数据库、角色、schema、表空间。
- 创建一个普通学习用户
kb_learn。 - 创建一个独立数据库
kb_learn。 - 创建一个 schema
learn。 - 用普通用户创建表并验证对象拥有者。
- 理解
search_path的临时配置和持久化配置。
默认对象基线
先用 system 用户连接 test 数据库,查看默认对象。
ksql -h 127.0.0.1 -p 54321 -U system -d test数据库列表:
test=# \l
数据库列表
名称 | 拥有者 | 字元编码 | 校对规则 | Ctype | 存取权限
-----------+--------+----------+-------------+-------------+-------------------
kingbase | system | UTF8 | zh_CN.UTF-8 | zh_CN.UTF-8 |
security | system | UTF8 | zh_CN.UTF-8 | zh_CN.UTF-8 |
template0 | system | UTF8 | zh_CN.UTF-8 | zh_CN.UTF-8 | =c/system +
| | | | | system=CTc/system
template1 | system | UTF8 | zh_CN.UTF-8 | zh_CN.UTF-8 | =c/system +
| | | | | system=CTc/system
test | system | UTF8 | zh_CN.UTF-8 | zh_CN.UTF-8 |
(5 行记录)角色列表:
test=# \du
角色列表
角色名称 | 属性 | 成员属于
------------+--------------------------------------------+----------
kcluster | 无法登录 | {}
sao | 没有继承, 建立角色 | {}
sao_oper | 没有继承, 无法登录 | {}
sao_public | 没有继承, 无法登录 | {}
sso | 没有继承, 建立角色 | {}
sso_oper | 没有继承, 无法登录 | {}
sso_public | 没有继承, 无法登录 | {}
system | 超级用户, 建立角色, 建立 DB, 复制, 绕过RLS | {}schema 列表:
test=# \dn
架构模式列表
名称 | 拥有者
------------------+--------
anon | system
dbms_sql | system
perf | system
public | system
src_restrict | system
sys_hm | system
sysaudit | system
sysmac | system
wmsys | system
xlog_record_read | system
(10 行记录)表空间列表:
test=# \db
表空间列表
名称 | 拥有者 | 所在地
-------------+--------+--------
sys_default | system |
sys_global | system |
sysaudit | system |
(3 行记录)当前会话上下文:
test=# select current_user, session_user, current_database(), current_schema();
current_user | session_user | current_database | current_schema
--------------+--------------+------------------+----------------
system | system | test | public
(1 行记录)current_schema() 是 public,说明没有显式指定 schema 时,对象会优先落到当前 schema。后面创建表时我会故意使用 learn.t_demo,避免对象落点不清楚。
sys_roles 比 \du 展示得更完整。比如下面这个查询能看到更多内置 pg_* 和 sys_* 角色:
select rolname, rolsuper, rolcreatedb, rolcreaterole, rolcanlogin
from sys_roles
order by rolname;节选结果:
rolname | rolsuper | rolcreatedb | rolcreaterole | rolcanlogin
----------------------------+----------+-------------+---------------+-------------
kcluster | f | f | f | f
pg_monitor | f | f | f | f
sao | f | f | t | t
sso | f | f | t | t
sys_monitor | f | f | f | f
system | t | t | t | t
(24 行记录)本节小结
这一节只做只读巡检,没有改变环境。当前实例里能看到 5 个数据库、若干默认角色、10 个 schema 和 3 个表空间。
这里最重要的判断是:system 是超级用户,适合做管理操作,但不适合一直拿来模拟业务用户。下一步需要创建一个普通用户来验证真实权限边界。
对象之间的关系
本章后面创建了三个名字相近的对象:
KingbaseES 实例
├── 角色 / 用户:kb_learn
├── 数据库:kb_learn
│ └── schema:learn
│ └── 表:t_demo它们的定位不一样:
| 对象 | 本次名称 | 定位 | 作用 | 作用范围 |
|---|---|---|---|---|
| 角色 / 用户 | kb_learn | 数据库身份 | 登录数据库、拥有对象、被授予权限 | 整个 KingbaseES 实例 |
| 数据库 | kb_learn | 一组数据对象的容器 | 作为连接入口,隔离一套数据对象 | 单个数据库 |
| schema / 模式 | learn | 数据库内部的命名空间 | 组织表、视图、函数,避免对象名冲突 | 只在所属数据库内有效 |
| owner / 属主 | owner kb_learn、authorization kb_learn | 对象所有权 | 决定谁默认管理这个对象 | 绑定在具体对象上 |
角色可以先理解成数据库里的用户。更准确一点说:
能 login 的角色 = 数据库用户
不能 login 的角色 = 权限角色 / 权限组所以 create role kb_learn login ... 创建的是一个可以登录的数据库身份。没有 login 属性的角色不能直接登录,更像权限集合或角色组。
这里最容易混的是 kb_learn 角色和 kb_learn 数据库。它们只是同名,方便学习,不是同一个东西:
角色决定“谁来操作”
数据库决定“进入哪套数据环境”
schema 决定“对象放在哪个命名空间”
表、视图、函数才是真正承载业务数据和逻辑的对象本节小结
这一节建立了本章的对象模型:角色是身份,数据库是环境,schema 是命名空间,owner 是所有权。
后面判断权限问题时,不能只看“我在哪个数据库”,还要看“当前用户是谁”和“对象属于谁”。
创建学习角色、数据库和 schema
先用 system 连接 test 数据库:
ksql -h 127.0.0.1 -p 54321 -U system -d test如果只写 -U system,不指定 -d,会遇到下面的错误:
[kingbase@Kingbase-Server ~]$ ksql -h 127.0.0.1 -p 54321 -U system
用户 system 的口令:
ksql: 错误: could not connect to server: FATAL: database "system" does not exist这个错误不是服务问题,也不是端口问题,而是没有指定数据库名。-U system 只指定登录用户,不指定连接哪个数据库。不写 -d 时,ksql 会尝试连接与用户名同名的数据库,也就是 system 数据库。当前实例没有这个库,所以报错。
正确写法是显式指定数据库:
ksql -h 127.0.0.1 -p 54321 -U system -d test然后创建学习角色和数据库。文章里不记录真实密码,只保留占位符:
create role kb_learn login password '<已隐藏>';
create database kb_learn owner kb_learn;执行结果:
test=# create role kb_learn login password '<已隐藏>';
CREATE ROLE
test=# create database kb_learn owner kb_learn;
CREATE DATABASE检查角色和数据库:
test=# \du kb_learn
角色列表
角色名称 | 属性 | 成员属于
----------+------+----------
kb_learn | | {}
test=# \l kb_learn
数据库列表
名称 | 拥有者 | 字元编码 | 校对规则 | Ctype | 存取权限
----------+----------+----------+-------------+-------------+----------
kb_learn | kb_learn | UTF8 | zh_CN.UTF-8 | zh_CN.UTF-8 |
(1 行记录)再切到 kb_learn 数据库,用管理员身份创建 schema:
\c kb_learn system
create schema learn authorization kb_learn;
\dn输出:
test=# \c kb_learn system
您现在以用户名"system"连接到数据库"kb_learn"。
kb_learn=# create schema learn authorization kb_learn;
CREATE SCHEMA
kb_learn=# \dn
架构模式列表
名称 | 拥有者
------------------+----------
anon | system
dbms_sql | system
learn | kb_learn
perf | system
public | system
src_restrict | system
sys_hm | system
sysaudit | system
sysmac | system
wmsys | system
xlog_record_read | system
(11 行记录)到这里,基础对象已经准备好:
登录角色:kb_learn
数据库:kb_learn
schema:learn
schema 拥有者:kb_learn本节小结
这一节改变了数据库环境:新增了 kb_learn 登录角色、kb_learn 数据库和 learn schema。
需要注意的是,ksql -U system 不等于“连接 system 管理入口”。-U 只是用户,数据库仍然要用 -d 明确指定。
切库不等于切用户
我第一次验证普通用户建表时,其实还没有切到普通用户。证据在会话上下文里:
kb_learn=# select current_user, session_user, current_database(), current_schema();
current_user | session_user | current_database | current_schema
--------------+--------------+------------------+----------------
system | system | kb_learn | public
(1 行记录)这几个字段要分开看:
current_database = kb_learn 当前连接的是 kb_learn 数据库
current_user = system 当前执行 SQL 的仍然是 system 用户
current_schema = public 默认 schema 仍然是 public所以后面虽然在 learn schema 下建了表,但创建者仍然是 system:
kb_learn=# create table learn.t_demo (
id int primary key,
name varchar(50)
);
CREATE TABLE
kb_learn=# insert into learn.t_demo values (1, 'kingbase');
INSERT 0 1
kb_learn=# \dt learn.*
关联列表
架构模式 | 名称 | 类型 | 拥有者
----------+--------+--------+--------
learn | t_demo | 数据表 | system
(1 行记录)这个结果不是普通用户权限验证通过,而是一个很好的提醒:
\c kb_learn system 只是切到 kb_learn 数据库,并继续使用 system 用户
表拥有者是 system 说明对象由 system 创建
要验证 kb_learn 权限 需要重新用 -U kb_learn 登录本节小结
这一节验证了一个容易忽略的边界:切换数据库不等于切换用户。
判断权限实验是否成立,不能只看 SQL 是否执行成功,还要看 current_user 和对象 owner。否则很容易用超级用户跑通了操作,却误以为普通用户也具备同样权限。
普通用户建表验证
先删除上一轮由 system 创建的测试表:
kb_learn=# drop table learn.t_demo;
DROP TABLE然后用 kb_learn 重新登录 kb_learn 数据库:
ksql -h 127.0.0.1 -p 54321 -U kb_learn -d kb_learn会话上下文已经变成普通用户:
kb_learn=> select current_user, session_user, current_database(), current_schema();
current_user | session_user | current_database | current_schema
--------------+--------------+------------------+----------------
kb_learn | kb_learn | kb_learn | public
(1 行记录)注意,当前用户已经是 kb_learn,但默认 schema 仍然是 public。所以建表时继续显式写 learn.t_demo:
kb_learn=> create table learn.t_demo (
id int primary key,
name varchar(50)
);
CREATE TABLE
kb_learn=> insert into learn.t_demo values (1, 'kingbase');
INSERT 0 1
kb_learn=> select * from learn.t_demo;
id | name
----+----------
1 | kingbase
(1 行记录)检查表拥有者:
kb_learn=> \dt learn.*
关联列表
架构模式 | 名称 | 类型 | 拥有者
----------+--------+--------+----------
learn | t_demo | 数据表 | kb_learn
(1 行记录)这次才算普通用户建表验证通过。关键判断点不是 CREATE TABLE 本身,而是:
current_user = kb_learn
\dt learn.* 显示 t_demo 的拥有者 = kb_learn本节小结
这一节完成了真正的普通用户验证:kb_learn 能在自己拥有的 learn schema 下创建表、插入数据并查询数据。
新的问题也出现了:即使用 kb_learn 登录,默认 schema 仍然是 public。如果不想每次都写 learn.t_demo,需要继续处理 search_path。
search_path 的临时设置
先看默认 search_path:
kb_learn=> show search_path;
search_path
-----------------
"$user", public
(1 行记录)这里的 "$user", public 可以先理解为:优先找和当前用户名同名的 schema,如果没有,再找 public。当前没有 kb_learn 这个 schema,所以 current_schema() 显示为 public。
临时设置当前会话的 search_path:
kb_learn=> set search_path to learn, public;
SET
kb_learn=> select current_schema();
current_schema
----------------
learn
(1 行记录)这时可以不写 schema 前缀,直接查询 t_demo:
kb_learn=> select * from t_demo;
id | name
----+----------
1 | kingbase
(1 行记录)但 SET 只对当前连接有效。退出后重新登录,再检查:
kb_learn=> show search_path;
search_path
-----------------
"$user", public
(1 行记录)
kb_learn=> select current_schema();
current_schema
----------------
public
(1 行记录)本节小结
这一节验证了 SET search_path 的作用范围:它只影响当前会话。
临时设置适合排查和临时操作,但不适合长期使用。要让用户后续登录默认进入 learn schema,需要把配置持久化。
search_path 的持久化设置
这里使用范围更小的配置方式:
alter role kb_learn in database kb_learn set search_path to learn, public;它只影响 kb_learn 角色连接 kb_learn 数据库时的默认参数,不影响它连接其他库,也不影响其他用户。
第一次用 system 登录 kb_learn 数据库时,出现过一次口令认证失败:
ksql: 错误: could not connect to server: FATAL: password authentication failed for user "system"这个错误边界很清楚:服务、端口、数据库都不是问题,只是这次输入的 system 口令没有通过认证。重新输入正确口令后,登录成功并完成配置。
执行持久化配置:
kb_learn=# alter role kb_learn in database kb_learn set search_path to learn, public;
ALTER ROLE从系统视图确认配置已经写入:
kb_learn=# select r.rolname, d.datname, s.setconfig
from sys_db_role_setting s
join sys_roles r on r.oid = s.setrole
join sys_database d on d.oid = s.setdatabase
where r.rolname = 'kb_learn'
and d.datname = 'kb_learn';
rolname | datname | setconfig
----------+----------+-------------------------------
kb_learn | kb_learn | {"search_path=learn, public"}
(1 行记录)退出后重新用 kb_learn 登录验证:
kb_learn=> show search_path;
search_path
---------------
learn, public
(1 行记录)
kb_learn=> select current_schema();
current_schema
----------------
learn
(1 行记录)
kb_learn=> select * from t_demo;
id | name
----+----------
1 | kingbase
(1 行记录)到这里可以确认:search_path 已经从临时会话设置变成了角色在指定数据库里的持久化配置。
本节小结
这一节把 search_path 从临时设置变成了持久化设置。
本次使用的是 ALTER ROLE ... IN DATABASE ...,作用范围比较克制:只影响 kb_learn 连接 kb_learn 数据库时的默认 schema 搜索路径。验证点有两个:sys_db_role_setting 里能看到配置,重新登录后 show search_path 和 current_schema() 都符合预期。
本章总结
这一章完成了 KingbaseES 对象与权限基础的第一轮实验。
- 已验证:默认数据库、角色、schema、表空间;普通用户建表;临时和持久化
search_path。 - 已变更:新增
kb_learn角色、kb_learn数据库、learnschema、learn.t_demo表,并为kb_learn连接kb_learn数据库持久化了search_path=learn, public。 - 关键概念:角色决定谁操作,数据库决定进入哪套环境,schema 决定对象放在哪个命名空间,owner 决定对象归属。
- 容易踩坑:切库不等于切用户;SQL 执行成功不代表普通用户权限验证成立;
SET search_path只对当前会话有效。 - 下一步:进入基础 DDL 和 DML,继续练习表结构、约束、插入、更新、删除和查询。