PostgreSQL表空間、數據庫、模式、表、用戶/角色之間的關系


看PostgreSQL9的官方文檔,我越看越迷糊,這表空間,數據庫,模式,表,用戶,角色之間的關系怎么在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並沒有限制一張表必須屬於某個特定的表空間,我們之所以會這么認為,是因為在關系遞進時,偷換了一個概念:模式是邏輯存在的,它不受表空間的限制。

 

----

本文為轉載:http://blog.csdn.net/kanon_lgt/article/details/5931522


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM