当前位置: 首页
数据库
MySQL与KingbaseES连接、对象命名空间及用户权限对比分析

MySQL与KingbaseES连接、对象命名空间及用户权限对比分析

热心网友 时间:2026-07-24
转载

KingbaseES中连接目标、对象命名空间及登录用户三者独立,与MySQL将database作为命名空间的习惯不同。通过实验说明,同一数据库下不同schema可存在同名表,search_path决定未加前缀查询的解析目标。正确区分schema与search_path可避免连错库、查错对象等问题。

先把两个最基本的概念摆出来:一个普通用户 app_user,一个数据库 app_db。如果按照 MySQL 的惯性来理解,很容易认为——连上 app_db,表就建在 app_db 下面。

这个理解在日常口头表达中问题不大,但动手写 SQL 时会很快遇到困惑。在 KingbaseES 里,连接目标、对象命名空间、登录用户是三个独立的概念:

database:连接到哪个数据库
schema:表、视图、函数这些对象放在哪个命名空间
user/role:当前是谁在执行操作

MySQL 中经常把 database 当作命名空间使用,写 db_name.table_name 很常见。但迁移到 KingbaseES 后,更需要先适应 schema.table 这种分层关系。如果不把这一点理清楚,后面很容易出现“表明明存在却查不到”“同一个表名查到的不是预期数据”“换个用户以后对象显示不一样”这类问题。

这绝不是什么概念上的洁癖。开发时最常见的低级问题,往往不是 SQL 函数不会用,而是连错库、建错位置、查错对象。在 MySQL 里执行 use app_db; 之后,再 show tables;,心里通常会默认“当前库里的表就在这里”。到了 KingbaseES,连接到 app_db 以后,还要多看一层:当前 schema 是什么,默认对象查找顺序是怎样的。

如果只是做一个简单的表,这个差别不明显。一旦开始做迁移、按模块拆分 schema、给不同用户分配对象,差别就会变得非常具体。一个库里可能有 public.t_order,也可能有 archive.t_orderreport.t_order。不带 schema 前缀的 select * from t_order 到底查哪张表,不能只靠表名判断。

下面的实验只用两个对象名:一个普通用户 app_user,一个数据库 app_db。表名也故意复用 t_schema_demo,让它分别出现在 publicapp_schema 下面。这样能把问题压缩到最小——同一个 database、同一个 user、同一个表名,只因为 schema 和 search_path 不同,查询结果就会发生变化。

当前连接里,不只是有数据库名

先用普通用户连接数据库:

ksql -h 127.0.0.1 -p 54321 -U app_user -d app_db

进入 ksql 后,查询三个值:

select current_database(), current_user, current_schema();
show search_path;

返回结果中,当前数据库是 app_db,当前用户是 app_user,当前 schema 是 publicsearch_path 是:

"$user", public

MySQL和KingbaseES中连接、对象命名空间及用户权限的区别

这里已经可以看到几个概念被拆开了。连接命令中的 -d app_db 只决定当前 database;登录命令中的 -U app_user 决定当前用户;而真正不写前缀建表时会落到哪里,还要看当前 schema 和 search_path

"$user", public 的意思是:先尝试查找与当前用户同名的 schema,再查找 public。当前环境里没有 app_user 这个 schema,所以 current_schema() 返回的是 public

这一步对 MySQL 用户来说非常关键。连接到 app_db 并不等于后面所有对象都直接挂在 app_db 这一层——表还会属于某个 schema。

可以把这组信息拆成一句话:app_user 以某个用户身份连接到了 app_db,当前默认会在 public schema 里创建和查找对象。三个值分别回答三个问题:

current_database()  当前连接哪个数据库
current_user        当前用哪个用户执行
current_schema()    当前默认使用哪个 schema

show search_path; 则回答另一个问题:没写 schema 前缀时,数据库按什么顺序查找对象。这个配置不只是显示信息,它会直接影响建表和查表的结果。

不写 schema,表会落到默认位置

直接建一张表:

drop table if exists t_schema_demo;
create table t_schema_demo(id int, name varchar(50));
insert into t_schema_demo values (1, 'from default schema');

再用 dtd 查看对象:

\dt
\d t_schema_demo

同时查询系统视图:

select schemaname, tablename, tableowner
from sys_tables
where tablename = 't_schema_demo';

结果非常直接,t_schema_demopublic 下,owner 是 app_user

MySQL和KingbaseES中连接、对象命名空间及用户权限的区别

这就是 search_path 生效后的结果。建表语句没有写 public.t_schema_demo,但当前默认 schema 是 public,所以表落到了 public

换成 MySQL 习惯时,这里最容易理所当然地认为:已经连上 app_db,所以表就在 app_db 里。更准确的说法应该是:当前连接在 app_db,表对象属于 app_db 里的 public schema。

也就是说,database 是更外层的连接边界,schema 才是对象的命名空间。后面写 select * from t_schema_demo 时,如果不带 schema 前缀,数据库会按当前的搜索路径去查找。

这里的 \dt 也能看出问题。它列出来的不只是表名,还有 schema。当前结果里,已有的 t_ksql_conn_demo 和这次新建的 t_schema_demo 都在 public 下,owner 都是 app_user。这说明“谁创建”和“建在哪个 schema”也是两回事:当前用户是 app_user,对象 owner 是 app_user,但对象所在 schema 是 public

写 DDL 时,最好先确认这三件事。只知道“当前连的是 app_db”还不够,至少还要知道默认 schema 是什么。否则以后清理对象时,可能会发现同一个库里散着多个 schema,表名也不一定唯一。

再建一个 app_schema

接着创建一个新的 schema:

create schema app_schema authorization app_user;

再查当前数据库里关心的 schema:

select schema_name
from information_schema.schemata
where schema_name in ('public', 'app_schema');

结果里能看到 publicapp_schema

MySQL和KingbaseES中连接、对象命名空间及用户权限的区别

app_schema 并不是新数据库,它只是 app_db 里的一个命名空间。authorization app_user 表示这个 schema 归 app_user 所有。

这一步不用先展开权限体系。先抓住一点就行:同一个 database 里可以有多个 schema。表名、视图名、函数名这些对象名,都是在 schema 这一层组织的。

authorization app_user 也不是随手加的装饰。它让 app_schema 这个命名空间归 app_user 所有。后面在这个 schema 下建表时,逻辑就更接近日常开发:普通用户连接自己的数据库,在自己的 schema 里存放对象。完整权限还可以继续细分,这里先把对象层级跑通。

在真实项目里,schema 常用来做隔离。比如一个库里放业务表、报表表、中间表,或者迁移时先把旧系统对象放到单独 schema。这样不需要每个模块都拆成一个独立数据库,也能避免对象名互相冲突。

同一个 database 里,可以同时存在同名表

现在显式把表建到 app_schema 下:

create table app_schema.t_schema_demo(
  id int,
  name varchar(50)
);
insert into app_schema.t_schema_demo values (2, 'from app_schema');

再查 information_schema.tables

select table_schema, table_name
from information_schema.tables
where table_name = 't_schema_demo'
order by table_schema;

结果里出现了两行:

app_schema | t_schema_demo
public     | t_schema_demo

MySQL和KingbaseES中连接、对象命名空间及用户权限的区别

这就是 schema 的作用。同一个 app_db 里,public.t_schema_demoapp_schema.t_schema_demo 可以同时存在。它们名字一样,但完整对象名不一样。

这和 MySQL 里常见的 database.table 直觉不同。在 KingbaseES 里,写到对象层面时,更常见的是:

schema_name.table_name

如果只写表名,数据库不会凭空知道你想查哪一个 schema 下的表,它会按 search_path 的顺序查找。

同名表实验很适合用来打破 MySQL 里的一个惯性:同一个“库”里表名必须唯一。这里并不是同一个 schema 里允许同名表,而是同一个 database 里不同 schema 允许同名对象。完整对象名分别是:

public.t_schema_demo
app_schema.t_schema_demo

这两个名字完整写出来以后,就不冲突了。后面做 SQL 排查时,如果只看到一个裸表名,不要马上以为它指向唯一对象。先查对象归属,再看搜索路径。

加上 schema 前缀,目标就明确了

分别查询两张同名表:

select * from public.t_schema_demo;
select * from app_schema.t_schema_demo;

前一张表里是:

1 | from default schema

后一张表里是:

2 | from app_schema

MySQL和KingbaseES中连接、对象命名空间及用户权限的区别

加上 schema.table 前缀以后,查询目标非常明确,不受当前 search_path 顺序影响。

平时写业务 SQL 时,不一定每条都要带 schema 前缀。很多项目会通过默认 schema 或连接参数把环境固定下来。但在排查问题、写迁移脚本、做跨 schema 查询时,显式写出 schema 能减少很多歧义。

有几种场景,最好直接写全名:迁移脚本、初始化脚本、定时任务、跨 schema 查询、临时排查 SQL。这些 SQL 往往会在不同账号、不同终端、不同工具里执行,不能假设每次会话的 search_path 都一样。写成 app_schema.t_schema_demo 虽然长一点,但现场更清楚。

尤其是多人共用测试库时,写清 schema 能避免很多无意义的来回确认,也方便后面清理对象和复盘问题。

这也是迁移时很容易踩的点。MySQL 里从 db1.table1 改到 KingbaseES,不一定能机械地改成 database.table。更常见的处理是:连接到目标 database,然后把对象放进指定 schema,再用 schema.table 来访问。具体怎么设计,要看项目是否需要多 schema、是否要保留原库名、是否要隔离临时迁移对象。

search_path 会影响未加前缀的查询

现在不带 schema 前缀,直接查:

select * from t_schema_demo;

这条 SQL 查哪张表,取决于当前 search_path

先把 app_schema 放到前面:

set search_path to app_schema, public;
show search_path;
select * from t_schema_demo;

返回的是 app_schema.t_schema_demo 里的数据:

2 | from app_schema

再把 public 放到前面:

set search_path to public, app_schema;
show search_path;
select * from t_schema_demo;

返回变成 public.t_schema_demo 里的数据:

1 | from default schema

MySQL和KingbaseES中连接、对象命名空间及用户权限的区别

这一步能解释很多看起来很怪的问题。表存在,查询也没报错,但结果不是预期那张表的数据,原因可能不是 SQL 写错,而是未加前缀的表名被 search_path 解析到了另一个 schema。

开发阶段如果只有一个 schema,问题不明显。一旦出现多 schema、迁移临时 schema、按用户隔离 schema,search_path 就会变得非常重要。

这个实验里,两次查询的 SQL 都是:

select * from t_schema_demo;

SQL 文本没有变化,结果却变了。变化来自前面的:

set search_path to app_schema, public;
set search_path to public, app_schema;

这类问题在日志里也不好一眼看出来。只看业务 SQL,会以为查的是同一张表;把当时会话里的 search_path 补上,才能解释结果为什么不同。所以排查“查错表”时,show search_path; 应该和 current_database()current_user 一起查看。

换成 system,再看同一个 app_db

退出 app_user 后,换 system 连接同一个数据库:

ksql -h 127.0.0.1 -p 54321 -U system -d app_db

再查当前位置:

select current_database(), current_user, current_schema();

结果变成:

app_db | system | public

继续查 t_schema_demo 的归属:

select table_schema, table_name
from information_schema.tables
where table_name = 't_schema_demo'
order by table_schema;

仍然能看到:

app_schema | t_schema_demo
public     | t_schema_demo

MySQL和KingbaseES中连接、对象命名空间及用户权限的区别

换用户不等于换数据库,也不等于把对象搬到别的 schema。system 只是换了当前执行 SQL 的身份,连接目标仍然是 app_db,对象仍然在 publicapp_schema 下面。

这里先不展开授权。只看这一组结果已经足够说明:database、schema、user 不是一个概念。

换成 system 后,current_user 变了,但 current_database() 仍然是 app_db,对象归属也没变。这能把 user 和 database 的边界讲清楚。用户不是数据库,数据库也不是用户。用户只是当前会话执行 SQL 的身份,它会影响你能不能看、能不能改、默认 schema 怎么解析,但不会因为换用户就把同一个数据库里的对象改名或搬走。

这也是为什么不建议长期拿管理员用户做日常实验。管理员用户能看到更多东西,也能绕过一些权限限制。用它排查问题可以,拿它模拟普通应用连接就不准确。准备 app_userapp_db,就是为了让这些实验更接近日常开发账号。

和 MySQL 的习惯对一下

如果从 MySQL 过来,可以先用下面这张对照表调整直觉:

MySQL 常见理解              KingbaseES 里要拆开看
database 常当命名空间        database 是连接目标
database.table              schema.table 更常见
use db                      ksql 里用 \c 切换连接数据库
show tables                 \dt 或 information_schema.tables
当前库                       current_database()
当前用户                     current_user
默认 schema                  current_schema()
对象查找路径                 search_path

这并不是说 MySQL 的方式不好,而是两套对象层级不一样。MySQL 里很多时候看到“库”,脑子里会自动想到一组表;KingbaseES 这里连到 database 以后,还要继续问:当前 schema 是哪个,表实际在哪个 schema 下,当前用户有没有权限访问它。

前面实验里的几个结果可以串起来看:

app_db                       当前连接的 database
app_user / system            当前执行 SQL 的 user
public / app_schema          表所在的 schema
t_schema_demo                两个 schema 下都可以存在的表名
search_path                  不写 schema 前缀时的查找顺序

后面如果遇到“表不存在”“查到的不是预期数据”“换用户以后看不到对象”,不要只盯着表名。先查 current_database()current_usercurrent_schema(),再看 search_path 和对象实际归属,很多问题会直接变得清晰。

可以把排查顺序固定下来:

select current_database(), current_user, current_schema();
show search_path;
select table_schema, table_name
from information_schema.tables
where table_name = '<表名>';

如果对象确实存在,再看权限;如果对象在另一个 schema,先决定是改 SQL 加前缀,还是调整当前会话的 search_path。不要一上来就怀疑表丢了,也不要直接重建同名表。schema 没看清时,重建对象反而可能把现场弄得更乱。

比如应用报“表不存在”,先不要急着执行 create table。如果表在 app_schema,而连接进来以后默认搜索的是 public,裸写 select * from t_schema_demo 就可能找不到目标对象。这个时候有两种处理方式:SQL 里写成 app_schema.t_schema_demo,或者在连接会话里把 app_schema 放进 search_path。两种方式都能解决问题,但含义不一样。前者目标最明确,后者更依赖会话配置。

再比如查出来的数据不对,也不一定是数据被改坏了。同名表同时存在时,public.t_schema_demoapp_schema.t_schema_demo 都能正常查询,只是数据来源不同。SQL 不带 schema 前缀时,结果跟着 search_path 走。这个问题在测试库里不显眼,到了迁移验证、报表库、临时表整理时就会变得很麻烦。

来源:https://www.jb51.net/database/365708z04.htm

游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

同类文章
更多
自增主键值从何而来?深入理解原理,告别只会auto_increment

自增主键值从何而来?深入理解原理,告别只会auto_increment

KingbaseES推荐使用serial、bigserial、显式sequence或identity列实现自增主键。serial创建integer并关联序列,bigserial对应bigint;显式sequence可自定义起始值等参数;identity有generatedbydefault(允许指定值)与always(禁止)两种模式。

时间:2026-07-25 22:22
Linux下瀚高数据库授权文件过期及替换解决方案

Linux下瀚高数据库授权文件过期及替换解决方案

在银河麒麟系统下,瀚高数据库hgdb-4 5试用授权20天到期后需替换正式授权文件。正确操作:停止服务,备份旧文件,将授权文件复制到 opt highgo hgdb-4 5 etc lic 并命名为hgdb lic,设置权限600和属主highgo:highgo,再启动服务。禁止直接修改data目录下的license info文件。

时间:2026-07-25 22:22
Oracle BLOB实时同步的5大技术挑战与难点解析

Oracle BLOB实时同步的5大技术挑战与难点解析

OracleBLOB实时同步面临分片组装、多列隔离、长事务跨窗口、事务回滚及大对象资源控制等技术挑战,必须在日志中精确还原完整字段值,才能保证源端与目标端数据完全一致,这对同步系统的稳健性提出了高要求。

时间:2026-07-25 22:22
MySQL禁用redo日志导致全备失败

MySQL禁用redo日志导致全备失败

MySQL全量备份失败是由于数据定义语言操作触发排序索引构建,禁用重做日志导致XtraBackup无法获取一致性备份。测试验证表明,优化表语句即使无数据也会触发该问题。根本原因在于排序索引构建过程跳过了重做日志记录,破坏了备份的一致性。

时间:2026-07-25 20:35
Kafka架构图优化与改进的全面详细步骤与实践指南

Kafka架构图优化与改进的全面详细步骤与实践指南

Kafka作为实时数据流处理的核心中间件,其底层架构虽已相当成熟,但在实际生产环境中,要充分发挥其性能潜力,仍需落实到具体的调优与架构改造上。核心目标可归纳为三点:如何承载更高的吞吐量、如何保障数据不丢失、以及故障发生时如何快速恢复。本文将从这几个关键方向出发,深入探讨如何真正榨干Kafka集群的性

时间:2026-07-25 20:35
热门专题
更多
刀塔传奇破解版无限钻石下载大全 刀塔传奇破解版无限钻石下载大全
洛克王国正式正版手游下载安装大全 洛克王国正式正版手游下载安装大全
思美人手游下载专区 思美人手游下载专区
好玩的阿拉德之怒游戏下载合集 好玩的阿拉德之怒游戏下载合集
不思议迷宫手游下载合集 不思议迷宫手游下载合集
百宝袋汉化组游戏最新合集 百宝袋汉化组游戏最新合集
jsk游戏合集30款游戏大全 jsk游戏合集30款游戏大全
宾果消消消原版下载大全 宾果消消消原版下载大全
  • 热门数据榜