理解PostgreSQL的模式、表、空間、使用者間的關係
在平時的工作中,我們經常接觸到資料庫表
和使用者
以及角色
的使用,由於經常使用預設的資料庫表空間
和模式
(Schema),所以我們往往忽略了資料庫表空間和模式的概念以及作用。
接下來,先介紹一下模式和表空間的定義以及作用。
什麼是Schema?
一個數據庫包含一個或多個已命名的模式,模式又包含表。模式還可以包含其它物件, 包括資料型別
、函式
、操作符
等。同一個物件名可以在不同的模式裡使用而不會導致衝突; 比如,herschema
和myschema
都可以包含一個名為mytable
的表。 和資料庫不同,模式不是嚴格分離的:只要有許可權,一個使用者可以訪問他所連線的資料庫中的任意模式中的物件。
我們需要模式的原因有好多:
- 允許多個使用者使用一個數據庫而不會干擾其它使用者。
- 把資料庫物件組織成邏輯組,讓它們更便於管理。
- 第三方的應用可以放在不同的模式中,這樣它們就不會和其它物件的名字衝突。
模式類似於作業系統層次的目錄,只不過模式不能巢狀。
什麼是表空間?
表空間是實際的資料儲存的地方。一個數據庫schema
可能存在於多個表空間,相似地,一個表空間也可以為多個schema
服務。
通過使用表空間,管理員可以控制磁碟的佈局。表空間的最常用的作用是優化效能,例如,一個最常用的索引可以建立在非常快的硬碟上,而不太常用的表可以建立在便宜的硬碟上,比如用來儲存用於進行歸檔檔案的表。
PostgreSQL表空間、資料庫、模式、表、使用者、角色之間的關係
角色與使用者的關係
在PostgreSQL
中,存在兩個容易混淆的概念:角色/使用者。之所以說這兩個概念容易混淆,是因為對於PostgreSQL來說,這是完全相同的兩個物件。唯一的區別是在建立的時候:
1.我用下面的psql
建立了角色custom
:
CREATE ROLE custom PASSWORD 'custom';
接著我使用新建立的角色custom登入,PostgreSQL給出拒絕資訊:
FATAL:role 'custom' is not permitted to log in.
說明該角色沒有登入許可權,系統拒絕其登入
2.我又使用下面的psql
建立了使用者guest
:
CREATE USER guest PASSWORD 'guest';
接著我使用guest登入,登入成功
難道這兩者有區別嗎?檢視文件,又這麼一段說明:CREATE USER is the same as CREATE ROLE except that it implies LOGIN. ----CREATE USER
除了預設具有LOGIN
許可權之外,其他與CREATE ROLE
是完全相同的。
為了驗證這句話,修改custom
的許可權,增加LOGIN
許可權:
ALTER ROLE custom LOGIN;
再次用custom
登入,成功!那麼事情就明瞭了:
CREATE ROLE custom PASSWORD 'custom' LOGIN 等同於 CREATE USER custom PASSWORD 'custom'.
這就是ROLE/USER
的區別。
資料庫與模式的關係
模式(schema)
是對資料庫(database)邏輯分割。
在資料庫建立的同時,就已經預設為資料庫建立了一個模式--public
,這也是該資料庫的預設模式。所有為此資料庫建立的物件(表、函式、試圖、索引、序列等)都是建立在這個模式中的:
1.建立一個數據庫mars
CREATE DATABASE mars;
2.用custom
角色登入到mars
資料庫,檢視資料庫中的所有模式:\dn
顯示結果只有public
一個模式。
3.建立一張測試表
CREATE TABLE test(id integer not null);
4.檢視當前資料庫的列表:\d;
顯示結果是表test屬於模式public
.也就是test
表被預設建立在了public模式中。
5.建立一個新模式custom
,對應於登入使用者custom
:
CREATE SCHEMA custom;
ALTER SCHEMA custom OWNER TO custom;
6.再次建立一張test
表,這次這張表要指明模式
CREATE TABLE custom.test (id integer not null);
7.檢視當前資料庫的列表: \d
顯示結果是表test
屬於模式custom
.也就是這個test
表被建立在了custom模式
中。
得出結論是:資料庫是被模式(schema)來切分的,一個數據庫至少有一個模式,所有資料庫內部的物件(object)是被創建於模式的。使用者登入到系統,連線到一個數據庫後,是通過該資料庫的search_path來尋找schema的搜尋順序,可以通過命令SHOW search_path
;具體的順序,也可以通過SET search_path TO 'schema_name'
來修改順序。
官方建議是這樣的:在管理員建立一個具體資料庫後,應該為所有可以連線到該資料庫的使用者分別建立一個與使用者名稱相同的模式,然後,將
search_path
設定為$user
,即預設的模式是與使用者名稱相同的模式。
表空間與資料庫的關係
資料庫建立語句:
CREATE DATABASE dbname;
預設的資料庫所有者是當前建立資料庫的角色,預設的表空間是系統的預設表空間pg_default。
為什麼是這樣的呢?
因為在PostgreSQL
中,資料的建立是通過克隆資料庫模板來實現的,這與SQL SERVER是同樣的機制。由於CREATE DATABASE dbname
並沒有指明資料庫模板,所以系統將預設克隆template1
資料庫,得到新的資料庫dbname
。(By default, the new database will be created by cloning the standard system database template1)
template1
資料庫的預設表空間是pg_default
,這個表空間是在資料庫初始化時建立的,所以所有template1
中的物件將被同步克隆到新的資料庫中。
相對完整的語法應該是這樣的:
CREATE DATABASE dbname TEMPLATE template1 TABLESPACE tablespacename;
ALTER DATABASE dbname OWNER TO custom;
1.連線到template1
資料庫,建立一個表作為標記:
CREATE TABLE test(id integer not null);
向表中插入資料
INSERT INTO test VALUES (1);
2.建立一個表空間:
CREATE TABLESPACE tsmars OWNER custom LOCATION '/tmp/data/tsmars';
在此之前應該確保目錄/tmp/data/tsmars存在,並且目錄為空。
3.建立一個數據庫,指明該資料庫的表空間是剛剛建立的tsmars
:
CREATE DATABASE dbmars TEMPLATE template1 OWNERE custom TABLESPACE tsmars;
ALTER DATABASE dbmars OWNER TO custom;
4.檢視系統中所有資料庫的資訊:\l+
可以發現,dbmars
資料庫的表空間是tsmars
,擁有者是custom
;
仔細分析後,不難得出結論:
在PostgreSQL中,表空間是一個目錄,裡面儲存的是它所包含的資料庫的各種物理檔案。
總結
表空間是一個儲存區域,在一個表空間中可以儲存多個數據庫,儘管PostgreSQL不建議這麼做,但我們這麼做完全可行。一個數據庫並不知直接儲存表結構等物件的,而是在資料庫中邏輯建立了至少一個模式,在模式中建立了表等物件,將不同的模式指派該不同的角色,可以實現許可權分離,又可以通過授權,實現模式間物件的共享,並且還有一個特點就是:public模式可以儲存大家都需要訪問的物件。
表空間用於定義資料庫物件在物理儲存裝置上的位置,不特定於某個單獨的資料庫。資料庫是資料庫物件的物理集合,而schema
則是資料庫內部用於組織管理資料庫物件的邏輯集合,schema名字空間之下則是各種應用程式會接觸到的物件,比如表、索引、資料型別、函式、操作符等。
角色(使用者)則是資料庫伺服器(叢集)全域性範圍內的許可權控制系統,用於各種叢集範圍內所有的物件許可權管理。因此角色不特定於某個單獨的資料庫,但角色如果需要登入資料庫管理系統則必須連線到一個數據庫上。角色可以擁有各種資料庫物件。
歡迎訪問我的個人部落格
關注公眾號:JAVA九點半課堂,這裡有一批優秀的技術大牛,為你提供方向,提供資源!加入我們,一起探討技術,共同進步!回覆“資料”獲取 2T 行業最新資料