Home

人大金仓 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_learnauthorization 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_pathcurrent_schema() 都符合预期。

本章总结

这一章完成了 KingbaseES 对象与权限基础的第一轮实验。

  • 已验证:默认数据库、角色、schema、表空间;普通用户建表;临时和持久化 search_path
  • 已变更:新增 kb_learn 角色、kb_learn 数据库、learn schema、learn.t_demo 表,并为 kb_learn 连接 kb_learn 数据库持久化了 search_path=learn, public
  • 关键概念:角色决定谁操作,数据库决定进入哪套环境,schema 决定对象放在哪个命名空间,owner 决定对象归属。
  • 容易踩坑:切库不等于切用户;SQL 执行成功不代表普通用户权限验证成立;SET search_path 只对当前会话有效。
  • 下一步:进入基础 DDL 和 DML,继续练习表结构、约束、插入、更新、删除和查询。
数据库 KingbaseES 人大金仓 Linux 权限 技术分享