最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MySQL和KingbaseES中連接、對象命名空間及用戶權限的區(qū)別

 更新時間:2026年06月13日 11:19:41   作者:一只牛博  
這段文章詳細解釋了KingbaseES中連接數(shù)據(jù)庫、對象命名空間及登錄用戶之間的區(qū)別,指出MySQL習慣的開發(fā)者容易混淆這些概念,文章通過實驗展示了在不同schema和search_path下,同一個表名可能指向不同的對象,強調(diào)開發(fā)者在寫SQL時需明確schema前前綴,以避免查詢錯誤

先準備一個普通用戶 app_user 和一個數(shù)據(jù)庫 app_db。如果按 MySQL 的習慣看,很容易把事情理解成:連上 app_db,表就建在 app_db 下面。

這個理解在日常口頭表達里問題不大,但繼續(xù)寫 SQL 時會很快遇到麻煩。KingbaseES 里,連接目標、對象命名空間、登錄用戶是三件事:

database:連接到哪個數(shù)據(jù)庫
schema:表、視圖、函數(shù)這些對象放在哪個命名空間
user/role:當前是誰在執(zhí)行操作

MySQL 里經(jīng)常把 database 當作命名空間使用,寫 db_name.table_name 很常見。KingbaseES 這里更需要先適應 schema.table 這層關系。不把這件事分清楚,后面很容易出現(xiàn)表明明存在卻查不到、同一個表名查到的不是預期數(shù)據(jù)、換個用戶以后對象顯示不一樣這些問題。

這不是概念潔癖。開發(fā)時最常見的低級問題,往往不是 SQL 函數(shù)不會用,而是連錯庫、建錯位置、查錯對象。MySQL 里執(zhí)行 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,一個數(shù)據(jù)庫 app_db。表名也故意復用 t_schema_demo,讓它分別出現(xiàn)在 publicapp_schema 下面。這樣能把問題壓到最?。和粋€ database、同一個 user、同一個表名,只因為 schema 和 search_path 不同,查詢結(jié)果就會變。

當前連接里不只有數(shù)據(jù)庫名

先用普通用戶連接數(shù)據(jù)庫:

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;

返回結(jié)果里,當前數(shù)據(jù)庫是 app_db,當前用戶是 app_user,當前 schema 是 public。search_path 是:

"$user", public

這里已經(jīng)能看到幾個概念被拆開了。連接命令里的 -d app_db 只決定當前 database;登錄命令里的 -U app_user 決定當前用戶;真正不寫前綴建表時會落到哪里,還要看當前 schema 和 search_path

"$user", public 的意思是:先嘗試找和當前用戶同名的 schema,再找 public。當前環(huán)境里沒有 app_user 這個 schema,所以 current_schema() 返回的是 public。

這一步對 MySQL 用戶很關鍵。連到 app_db 不等于后面所有對象都直接掛在 app_db 這一層,表還會屬于某個 schema。

可以把這組信息拆成一句話:app_user 以某個用戶身份連接到了 app_db,當前默認會在 public schema 里創(chuàng)建和查找對象。三個值分別回答三個問題:

current_database()  當前連接哪個數(shù)據(jù)庫
current_user        當前用哪個用戶執(zhí)行
current_schema()    當前默認使用哪個 schema

show search_path; 則回答另一個問題:沒寫 schema 前綴時,數(shù)據(jù)庫按什么順序找對象。這個配置不只是顯示信息,它會直接影響建表和查表。

不寫 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');

再用 \dt\d 看對象:

\dt
\d t_schema_demo

同時查系統(tǒng)視圖:

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

結(jié)果很直接,t_schema_demopublic 下,owner 是 app_user。

這就是 search_path 生效后的結(jié)果。建表語句沒有寫 public.t_schema_demo,但當前默認 schema 是 public,所以表落到了 public

換成 MySQL 習慣時,這里最容易想當然:已經(jīng)連上 app_db,所以表就在 app_db 里。更準確的說法應該是:當前連接在 app_db,表對象屬于 app_db 里的 public schema。

也就是說,database 是更外層的連接邊界,schema 才是對象命名空間。后面寫 select * from t_schema_demo 時,如果不帶 schema 前綴,數(shù)據(jù)庫會按當前搜索路徑去找。

這里的 \dt 也能看出問題。它列出來的不只是表名,還有 schema。當前結(jié)果里,已有的 t_ksql_conn_demo 和這次新建的 t_schema_demo 都在 public 下,owner 都是 app_user。這說明“誰創(chuàng)建”和“建在哪個 schema”也是兩回事:當前用戶是 app_user,對象 owner 是 app_user,但對象所在 schema 是 public。

寫 DDL 時最好先確認這三件事。只知道“當前連的是 app_db”還不夠,至少還要知道默認 schema 是什么。否則以后清理對象時,可能會發(fā)現(xiàn)同一個庫里散著多個 schema,表名也不一定唯一。

再建一個 app_schema

接著創(chuàng)建一個新的 schema:

create schema app_schema authorization app_user;

再查當前數(shù)據(jù)庫里關心的 schema:

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

結(jié)果里能看到 publicapp_schema

app_schema 不是新數(shù)據(jù)庫,它只是 app_db 里的一個命名空間。authorization app_user 表示這個 schema 歸 app_user 所有。

這一步不用先展開權限體系。先抓住一點就行:同一個 database 里可以有多個 schema。表名、視圖名、函數(shù)名這些對象名,都是在 schema 這一層組織的。

authorization app_user 也不是隨手加的裝飾。它讓 app_schema 這個命名空間歸 app_user 所有。后面在這個 schema 下建表時,邏輯就更接近日常開發(fā):普通用戶連接自己的數(shù)據(jù)庫,在自己的 schema 里放對象。完整權限還可以繼續(xù)細分,這里先把對象層級跑通。

在真實項目里,schema 常用來做隔離。比如一個庫里放業(yè)務表、報表表、中間表,或者遷移時先把舊系統(tǒng)對象放到單獨 schema。這樣不需要每個模塊都拆成一個獨立數(shù)據(jù)庫,也能避免對象名互相撞在一起。

同一個 database 里可以有同名表

現(xiàn)在顯式把表建到 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;

結(jié)果里出現(xiàn)了兩行:

app_schema | t_schema_demo
public     | t_schema_demo

這就是 schema 的作用。同一個 app_db 里,public.t_schema_demoapp_schema.t_schema_demo 可以同時存在。它們名字一樣,但完整對象名不一樣。

這和 MySQL 里常見的 database.table 直覺不一樣。在 KingbaseES 里,寫到對象層面時,更常見的是:

schema_name.table_name

如果只寫表名,數(shù)據(jù)庫不會憑空知道想查哪一個 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

加上 schema.table 前綴以后,查詢目標很明確,不受當前 search_path 順序影響。

平時寫業(yè)務 SQL 時,不一定每條都要帶 schema 前綴。很多項目會通過默認 schema 或連接參數(shù)把環(huán)境固定下來。但在排查問題、寫遷移腳本、做跨 schema 查詢時,顯式寫出 schema 能少很多歧義。

有幾種場景最好直接寫全名:遷移腳本、初始化腳本、定時任務、跨 schema 查詢、臨時排查 SQL。這些 SQL 往往會在不同賬號、不同終端、不同工具里執(zhí)行,不能假設每次會話的 search_path 都一樣。寫成 app_schema.t_schema_demo 雖然長一點,但現(xiàn)場更清楚。

尤其是多人共用測試庫時,寫清 schema 能避免很多無意義的來回確認,也方便后面清理對象和復盤問題。

這也是遷移時很容易踩的點。MySQL 里從 db1.table1 改到 KingbaseES,不一定能機械改成 database.table。更常見的處理是:連接到目標 database,然后把對象放進指定 schema,再用 schema.table 來訪問。具體怎么設計,要看項目是否需要多 schema、是否要保留原庫名、是否要隔離臨時遷移對象。

search_path 會影響未加前綴的查詢

現(xiàn)在不帶 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 里的數(shù)據(jù):

2 | from app_schema

再把 public 放到前面:

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

返回變成 public.t_schema_demo 里的數(shù)據(jù):

1 | from default schema

這一步能解釋很多看起來很怪的問題。表存在,查詢也沒報錯,但結(jié)果不是預期那張表的數(shù)據(jù),原因可能不是 SQL 寫錯,而是未加前綴的表名被 search_path 解析到了另一個 schema。

開發(fā)階段如果只有一個 schema,問題不明顯。一旦出現(xiàn)多 schema、遷移臨時 schema、按用戶隔離 schema,search_path 就會變得很重要。

這個實驗里,兩次查詢的 SQL 都是:

select * from t_schema_demo;

SQL 文本沒有變化,結(jié)果卻變了。變化來自前面的:

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

這類問題在日志里也不好一眼看出來。只看業(yè)務 SQL,會以為查的是同一張表;把當時會話里的 search_path 補上,才能解釋結(jié)果為什么不同。所以排查“查錯表”時,show search_path; 應該和 current_database()、current_user 一起看。

換成 system,再看同一個 app_db

退出 app_user 后,換 system 連接同一個數(shù)據(jù)庫:

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

再查當前位置:

select current_database(), current_user, current_schema();

結(jié)果變成:

app_db | system | public

繼續(xù)查 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

換用戶不等于換數(shù)據(jù)庫,也不等于把對象搬到別的 schema。system 只是換了當前執(zhí)行 SQL 的身份,連接目標仍然是 app_db,對象仍然在 publicapp_schema 下面。

這里先不展開授權。只看這一組結(jié)果已經(jīng)足夠說明:database、schema、user 不是一個概念。

換成 system 后,current_user 變了,但 current_database() 仍然是 app_db,對象歸屬也沒變。這能把 user 和 database 的邊界講清楚。用戶不是數(shù)據(jù)庫,數(shù)據(jù)庫也不是用戶。用戶只是當前會話執(zhí)行 SQL 的身份,它會影響能不能看、能不能改、默認 schema 怎么解析,但不會因為換用戶就把同一個數(shù)據(jù)庫里的對象改名或搬走。

這也是為什么不建議長期拿管理員用戶做日常實驗。管理員用戶能看到更多東西,也能繞過一些權限限制。用它排查問題可以,拿它模擬普通應用連接就不準確。準備 app_userapp_db,就是為了讓這些實驗更接近日常開發(fā)賬號。

和 MySQL 的習慣對一下

如果從 MySQL 過來,可以先用下面這張對照表調(diào)整直覺:

MySQL 常見理解              KingbaseES 里要拆開看
database 常當命名空間        database 是連接目標
database.table              schema.table 更常見
use db                      ksql 里用 \c 切換連接數(shù)據(jù)庫
show tables                 \dt 或 information_schema.tables
當前庫                       current_database()
當前用戶                     current_user
默認 schema                  current_schema()
對象查找路徑                 search_path

這不是說 MySQL 的方式不好,而是兩套對象層級不一樣。MySQL 里很多時候看到“庫”,腦子里會自動想到一組表;KingbaseES 這里連到 database 以后,還要繼續(xù)問:當前 schema 是哪個,表實際在哪個 schema 下,當前用戶有沒有權限訪問它。

前面實驗里的幾個結(jié)果可以串起來看:

app_db                       當前連接的 database
app_user / system            當前執(zhí)行 SQL 的 user
public / app_schema          表所在的 schema
t_schema_demo                兩個 schema 下都可以存在的表名
search_path                  不寫 schema 前綴時的查找順序

后面如果遇到“表不存在”“查到的不是預期數(shù)據(jù)”“換用戶以后看不到對象”,不要只盯著表名。先查 current_database()current_user、current_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 加前綴,還是調(diào)整當前會話的 search_path。不要一上來就懷疑表丟了,也不要直接重建同名表。schema 沒看清時,重建對象反而可能把現(xiàn)場弄得更亂。

比如應用報“表不存在”,先不要急著執(zhí)行 create table。如果表在 app_schema,而連接進來以后默認搜索的是 public,裸寫 select * from t_schema_demo 就可能找不到目標對象。這個時候有兩種處理方式:SQL 里寫成 app_schema.t_schema_demo,或者在連接會話里把 app_schema 放進 search_path。兩種方式都能解決問題,但含義不一樣。前者目標最明確,后者更依賴會話配置。

再比如查出來的數(shù)據(jù)不對,也不一定是數(shù)據(jù)被改壞了。同名表同時存在時,public.t_schema_demoapp_schema.t_schema_demo 都能正常查詢,只是數(shù)據(jù)來源不同。SQL 不帶 schema 前綴時,結(jié)果跟著 search_path 走。這個問題在測試庫里不顯眼,到了遷移驗證、報表庫、臨時表整理時就會很煩。

到此這篇關于MySQL和KingbaseES中連接、對象命名空間及用戶權限的區(qū)別的文章就介紹到這了,更多相關MySQL和KingbaseES的區(qū)別內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

最新評論

邹平县| 米易县| 五台县| 沅陵县| 哈密市| 海安县| 黎川县| 信阳市| 阿克陶县| 玉树县| 泽州县| 中西区| 定安县| 五河县| 长兴县| 剑阁县| 清新县| 松阳县| 诏安县| 余庆县| 保靖县| 岳阳县| 通许县| 九江市| 安庆市| 农安县| 承德县| 开原市| 昔阳县| 馆陶县| 格尔木市| 浦城县| 山阴县| 白沙| 三亚市| 揭阳市| 竹北市| 云南省| 太谷县| 临西县| 札达县|