2008年10月6日 星期一

PostgreSQL 如何組織資料

原本上個月,打算寫另一篇文章,但是寫到一半,臨時改變計劃,決定先把這篇文章推出來。
在教授 PostgreSQL 時,我發覺,要讓稍微有點基礎的其它資料庫使用者,最容易上手 PostgreSQL 的方法,就是從說明 PostgreSQL 如何在檔案系統中放置你的資料著手。PostgreSQL 存放資料的邏輯相當簡單,所以進階使用者在了解這個邏輯後,很容易就能了解如何備份、擴充功能等等進階功能,不像 Oracle 等商用資料庫,把資料包在一層厚厚的黑盒子裏,不讓你接觸和了解它的行為;但是很不幸的,它也相當程度的依賴檔案系統。這會出現什麼問題呢?等我介紹完 tablespace 後,我想不用我多做解釋你也自然立刻能夠了解。
在開始介紹前,我要介紹一個環境變數。這個環境變數是 $PGDATA,將來我會找個時間把 PostgreSQL 會用到的環境變數做個整理,再另外發表一篇文章來介紹。垷在先稍微介紹一下 $PGDATA$PGDATA 的值指向某個目錄,而這個目錄其實就是 PostgreSQL 存放資料的目錄。在 FreeBSD 中,$PGDATA 通常是設成 /usr/local/pgsql/data,而在 RHEL/CentOS 則是指向 /var/lib/pgsql/data。但是,在剛安裝好 PostgreSQL Server 時,安裝程式並不會很雞婆的自動幫你把這個環境變數設好;雖然在安裝程式內部的確有一個內部變數 pgdata 指向上述目錄,所以當你在做 initdb 時,如果那時你的 $PGDATA 這個環境變數還沒設定,PostgreSQL 仍然會把資料放在上述目錄中。安裝程式不那麼雞婆的原因在於,PostgreSQL 的開發社群預留給你改變的機會。所以你在安裝好了之後,最好手動把 $PGDATA 設好。如果你是和我一樣,shell 習慣用 BASH,那麼請直接在 /etc/profile 最後面加上一行:
export PGDATA=/usr/local/pgsql/data    <- 如果你是 FreeBSD 的使用者的話
或者是
export PGDATA=/var/lib/pgsql/data        <- 如果是 RHEL/CentOS 的使用者
至於其它 OS 使用者我先略過。至於 $PGDATA 和 initdb,我會找時間另文介紹。 好,讓我們來看看圖一。
圖一
PostgreSQL 有很多系統資料表和系統視觀表(就是 Views,好怪的翻譯詞),就像 ISO 標準的 system catalog,可以讓管理者從文字模式下,沒有使用任何圖形界面工具,仍然可以做管理。pg_database 就是其中之一。pg_database 內儲存了系統中現有資料庫的清單。
psql 是 PostgreSQL 最好用的前端工具,它很像是 Oracle 的 SQL*Plus,當然沒有 SQL*Plus 那麼複雜,功能那麼多。\d 就像 SQL*Plus 的 DESC (describ) 一樣,可以顯示資料表的架構,所以 \d pg_database 就像在 Oracle 的 SQL*Plus 中下達 DESC pg_databse 一樣,可以秀出 pg_database 這個系統資料庫的欄位清單,順便秀出它專屬的索引(indexes)和觸發器(triggers)。我目前想要秀一下 datname 這個欄位個欄位,還有一個隱藏的欄位 oid。datname 是資料庫名稱,oid 則是資料庫的 OID (Object ID)。PostgreSQL 給予它所有的每一個物件一個獨享的 ID,就做 OID,用來識別各個物件,也就是說,每個物件都有它自己獨有的 OID。換句話說,我可以下達 SELECT datname, oid FROM pg_database; SQL 指令,秀出系統中所有現存 database 的名稱和 OID 的對照表:
圖二
從上表可以看到,目前系統只有三個 database,分別是 template0template1 和 postgres。它們的 OID 分別是 115101 和 11511。任何人裝的 PostgreSQL 的編號第一號 OID 的物件一定是 template1。至於這三個資料庫是怎麼來的,它們分別是幹什麼用的,我會另文介紹。
對了,讓我從主題叉開一下,先來談談 PostgreSQL 的系統帳號及資料庫帳號和預設資料庫。
預設安裝的 PostgreSQL 不是由 root 啟動,PostgreSQL process 的 owner 也不是 root,這是為了安全性的緣故。所以你在安裝的時候,安裝程式會幫你建立一個 PostgreSQL 專屬的系統帳號。在 RHEL/CentOS 是 postgres,Win32 版也是 postgres (如果你有安裝 Windows 版本的 PostgreSQL,你可以試著叫出工作管理員看看,postgres.exe 和 pg_ctl.exe 的使用者名稱是什麼),至於 FreeBSD 則是 pgsql;FreeBSD 這樣做會讓使用者很麻煩。
預設的 PostgreSQL 無法由遠端進入,只能從本機登入 psql,而且不能用 root 登入。安裝的預設值是:只要系統中有相同帳號即會「信任」同一使用者。所謂「信任」,代表你不需輸入密碼就可以由 psql 登入資料庫伺服器。還有,postgres 或 pgsql 的密碼你無從得知,因為它是在安裝時亂數隨機取得的。聽到這裏,你可能會問:那麼我要如何切換成 postgres 或 pgsql?不用擔心,在 Unix 系統中,root 的權限很大,你可以先用 su 切成超級使用者模式,這時只需要下達 su - pgsql,不輸入密碼立刻可以切到 pgsql。
如果你是使用 RHEL/CentOS,那麼,當你切成 postgres 帳號時,要登入 postgres,不用下任何參數,只要下達:
$ psql
就可以登入,而 postgres 正是 PostgreSQL 預設 DBA;剛好系統剛裝好預設資料庫也叫 postgres,所以不用另外指定登入資料庫,你就可以直接登入預設而且同名的資料庫 postgres
但是如果你用的是 FreeBSD,那麼就有點麻煩。在 FreeBSD 下的 PostgreSQL 的預設 DBA 是 pgsql,但是預設資料庫卻是 postgres。所以除非你另外在 FreeBSD 的 shell 中,下達 creadb,手動建立一個屬於 pgsql 的同名資料庫,然後用 dropdb postgres,砍掉預裝的預設資料庫,讓 pgsql 變成新預設資料庫,否則就請你煩麻一點,在執行 psql 時指定登入資料庫:
$ psql -d postgres
這樣才能順利登入 PostgreSQL 伺服器。
好,讓我們回到主題。
我們現在知道這三個 database 的 OID,接著跳出 psql,跳出的指令是 \q。跳出後請在系統中跳到 $PGDATA 這個目錄:
$ cd $PGDATA
注意:你必須先定義過 $PGDATA 才行,否則,你就得:
$ cd /usr/local/pgsql/data    <- 如果你是 FreeBSD 的使用者的話
或者是
$ cd /var/lib/pgsql/data        <- 如果是 RHEL/CentOS 的使用者
跳到 $PGDATA 後,接著跳到 base 子目錄,如圖三所示:
圖三
從圖三中我們看到 $PGDATA 下有不少目錄,有空我再來寫一篇文章介紹當中比較重要的幾個,現在回到 base 目錄。當你下達 ls -l 指令後,我們看到在 base 子目錄下只有三個子目錄,而且目錄名稱都是由數字所構成,它們分別是:1、 11510 及 11511!好巧喔!XD
沒錯!就如你所猜想的,PostgreSQL 把所有的物件都以目錄和檔案名稱儲存在檔案系統中。就剛才看到的,1 這個子目錄中儲存的,正是 database template1 的所有物件:
圖四
而同理,11510 子目錄下存的正是 database template0 的物件,11511 則是 database postgres 的物件。
就是因為 PostgreSQL 是以這種方式安排資料維護的方式,所以當開發社群想把它變得「更企業使用化」時,就會遭遇一些問題,尤其是在跨作業系統時。第一個問題就出在 tablespace,它在 Windows 上看起來似乎是沒有辦法使用的。這就等我繼續討論 Tablespace 時再來聊了。


沒有留言:

張貼留言

用 Claude 在 PsotgreSQL 的 Docker Container 中建立一個 database

Claude 是一個很強的 AI 工具,大概是我用過唯一可以和 Gemini 挑戰的 AI 工具。 它對於程式設計的能力相當強大。我這個測試證明了,不止程式設計能力很強,連資料庫的整個架構能力也是很嚇人的。 之前,我不是在 Proxmox VE 上建了一個 Zorin OS 的 ...