PostgreSQL表空間、模式、表、使用者/角色之間的關係是本文我們主要要介紹的內容,表空間,資料庫,模式,表,使用者,角色之間的關係到底是怎樣的呢?接下來我們就開始介紹這一過程。

 

實驗出角色與使用者的關係

 

在PostgreSQL中,存在兩個容易混淆的概念:角色/使用者。之所以說這兩個概念容易混淆,是因為對於PostgreSQL來說,這是完全相同的兩個物件。唯一的區別是在創建的時候:

 

1.我用下面的psql創建了角色kanon:CREATE ROLE kanon PASSWORD 'kanon';接著我使用新創建的角色kanon登錄,PostgreSQL給出拒絕資訊:FATAL: role 'kanon' is not permitted to log in.說明該角色沒有登入權利,系統拒絕其登錄。

 

2.我又使用下面的psql創建了使用者kanon2:CREATE USER kanon PASSWORD 'kanon2';接著我使用kanon2登錄,登錄成功。難道這兩者有區別嗎?查看文檔,又這麼一段說明:"CREATE USER is the same as CREATE ROLE except that it implies LOGIN."----CREATE USER除了預設具有LOGIN許可權之外,其他與CREATE ROLE是完全相同的。

 

為了驗證這句話,修改kanon的許可權,增加LOGIN許可權:ALTER ROLE kanon LOGIN;再次用kanon登錄,成功!那麼,事情就明瞭了:CREATE ROLE kanon PASSWORD 'kanon' LOGIN 等同于CREATE USER kanon PASSWORD 'kanon'.這就是ROLE/USER的區別。

 

資料庫與模式的關係

 

模式(schema)是對資料庫(database)邏輯分割。

 

在資料庫創建的同時,就已經預設為資料庫創建了一個模式--public,這也是該資料庫的預設模式。所有為此資料庫創建的物件(表、函數、試圖、索引、序列等)都是常見在這個模式中的。
實驗如下:

 

1.創建一個資料庫dbtt----CREATE DATABASE dbtt;

 

2.用kanon角色登錄到dbtt資料庫,查看dbtt資料庫中的所有模式:/dn; 顯示結果是只有public一個模式。

 

3.創建一張測試表----CREATE TABLE test(id integer not null);
 
4.查看當前資料庫的清單: /d; 顯示結果是表test屬於模式public.也就是test表被預設創建在了public模式中。
 
5.創建一個新模式kanon,對應于登錄使用者kanon:CREATE SCHEMA kanon OWNER kanon;
 
6.再次創建一張test表,這次這張表要指明模式----CREATE TABLE kanon.test (id integer not null);
 
7.查看當前資料庫的清單: /d; 顯示結果是表test屬於模式kanon.也就是這個test表被創建在了kanon模式中。得出結論是:資料庫是被模式(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 OWNER kanon TEMPLATE template1 TABLESPACE tablespacename;
 
下面我們來做個實驗驗證一下:
 
1.連接到template1資料庫,創建一個表作為標記:CREATE TABLE tbl_flag(id integer not null);向表中插入資料INSERT INTO tbl_flag VALUES (1);
 
2.創建一個表空間:CREATE TABLESPACE tskanon OWNER kanon LOCATION '/tmp/data/tskanon';在此之前應該確保目錄/tmp/data/tskanon存在,並且目錄為空。
 
3.創建一個資料庫,指明該資料庫的表空間是剛剛創建的tskanon:CREATE DATABASE dbkanon TEMPLATE template1 OWNERE kanon TABLESPACE tskanon;
 
4.查看系統中所有資料庫的資訊:/l;可以發現,dbkanon資料庫的表空間是tskanon,擁有者是kanon;
 
5.連接到dbkanon資料庫,查看所有表結構:/d;可以發現,在剛創建的資料庫中居然有了一個表tbl_flag,查看該表資料,輸出結果一行一列,其值為1,說明,該資料庫的確是從template1克隆而來。
 
仔細分析後,不難得出結論:在PostgreSQL中,表空間是一個目錄,裡面存儲的是它所包含的資料庫的各種物理檔。
 
總結:
 
表空間是一個存儲區域,在一個表空間中可以存儲多個資料庫,儘管PostgreSQL不建議這麼做,但我們這麼做完全可行。一個資料庫並不知直接存儲表結構等物件的,而是在資料庫中邏輯創建了至少一個模式,在模式中創建了表等物件,將不同的模式指派該不同的角色,可以實現許可權分離,又可以通過授權,實現模式間物件的共用,並且,還有一個特點就是:public模式可以存儲大家都需要訪問的物件。
 
這樣,我們的網就形成了。可是,既然一個表在創建的時候可以指定表空間,那麼,是否可以給一個表指定它所在的資料庫表空間之外的表空間呢?答案是肯定的!這麼做完全可以:那這不是違背了表屬於模式,而模式屬於資料庫,資料庫最終存在於指定表空間這個網的模型了嗎?!是的,看上去這確實是不合常理的,但這麼做又是有它的道理的,而且現實中,我們往往需要這麼做:將表的資料存在一個較慢的磁片上的表空間,而將表的索引存在於一個快速的磁片上的表空間。
 
但我們再查看表所屬的模式還是沒變的,它依然屬於指定的模式。所以這並不違反常理。實際上,PostgreSQL並沒有限制一張表必須屬於某個特定的表空間,我們之所以會這麼認為,是因為在關係遞進時,偷換了一個概念:模式是邏輯存在的,它不受表空間的限制。

    全站熱搜

    戮克 發表在 痞客邦 留言(0) 人氣()