2010年11月9日 星期二

PostgreSQL 的版本

這個標題,可能很多人看都不看,就略過這篇文章,就像我在上 PostgreSQL 課程的時候,我的投影片裏有一頁提到查看 PostgreSQL 版本的方法。而這一頁被一些意見比較多的學生私下抱怨,認為我在灌水,增加篇幅。而我想略過不看這篇文章的朋友,大概也是認為這篇文章不重要吧。其實不然,尤其是當你碰到的伺服器,不是由你全新安裝的,而是要幫忙維護的舊系統時,目前所安裝的版本,就要相當當心並注意了!
先提一下,PostgreSQL 安裝時,server 和 client 可以是不同版本。而這種版本的不一致,的確有潛在的危險可能會發生。如果 client 端比較舊,那還無所謂;但是若是 server 端的版本較舊時,你就要當心了。
你想要知道伺服器的版本,那可以從 psql 或 pgAdmin III 直接下 SQL 指令:
postgres=# SELECT version();
即可。如果你使用 psql,等下了指令後,接著會跳出類似下列的結果:
然後你要結束,請按下 q 就可以跳回 psql。看起來這堆資訊似乎「過多」了點。主要的重點在於前面幾個字,也就是 PostgreSQL 8.4.5。在 PostgreSQL 的版本編號,是由 Major.Minor.Maintenance 組成。Major 就是主要版本號碼,Minor 為次要版本編號,Maintenance 則為維護版本編號。其實按照 PostgreSQL 的慣例,只有  Major 是無意義的,PostgreSQL 的版本都是由 Major.Minor 來區分版本版次的。每個版次功能上都會有所不同,資料檔的格式也都多少有變化。而且這些變化在過去 8.x 版間是大得嚇人,等一下我再引用另一篇文章來說明。所以我的另一篇文章「PostgreSQL 在 FreeBSD 上的大版本升級」裏,大版本升級指的就是像 8.2 升級到 8.3 版這樣 Major.Minor 的改版升級。而 Maintenance 則是功能上沒有改變,而是修正被發現的 BUG,尤其出現安全性的漏洞時,會立即更新的版本。所以每當出現新維護版本時,我反而會比較急著通知。相反的,像 9.0 版出來的消息,我反而只是輕描淡寫的帶過。因為功能增加並不意味著有立即升級的急迫性,反而是維護版本的出現,常常是意味著有安全性的漏洞待補。
好了,正式提到主題。為什麼我們接手維護一套舊系統時,知道它的版本版次對管理者那麼重要?先讓我們來看看 PostgreSQL Release Support Policy。這個網頁開宗明義第一段就說了:「The PostgreSQL project aims to fully support a major release for five years, under the terms of the Versioning policy.」喔!原來 PostgreSQL 每一個主要版本只會維護五年!在同一個網頁中,有一個表格,叫做「End Of Life (EOL) dates」,也就是該版次最終維護日期,現在是 2010 年11 月,所以表格目前是這樣的(這篇文章是 2010 年發表,請讀者注意):
Releases which have already reached an EOL release are italicized:
VersionEOL DateRelease Date
PostgreSQL 7.4October 2010 (extended)November 2003
PostgreSQL 8.0October 2010 (extended)January 2005
PostgreSQL 8.1November 2010November 2005
PostgreSQL 8.2December 2011December 2006
PostgreSQL 8.3February 2013February 2008
PostgreSQL 8.4July 2014July 2009
PostgreSQL 9.0September 2015September 2010
Note: Versions 8.1 and earlier are not supported on Windows platforms
這也就難怪目前 PostgreSQL 官方網站的右上角,只有 8.1.22 版以上的版本,已經看不到 8.0 和 7.4 版了:
如果各位有注意到 PostgreSQL 2010-10-05 Security Update 的安全更新通告,會注意到第一段的最後一行有這樣的文字:This is the final update for PostgreSQL versions 7.4 and 8.0. 正式宣告這兩個版本的結束。其實呢,如果按照 PostgreSQL 官方的 Versioning policy 版本控制策略,是早該結束的兩個版次,如今延長到上個月,終於壽終正寢。接著 8.1 版也將在本月宣告結束[1]。所以這幾個版本,即使有安全上的漏洞,將來也不會再去維護、更新,這樣對於在線上的服務而言,是相當危險的事,所以要早早規劃大版本的更新。
事實上,不僅是因為版本控制策略,讓我們非得注意版本的更新。在 8.0 到 8.3 版,這四個版本當中,資料庫核心內部其實也私下做了相當大的變革。我們來看看一篇發表於去年(2009)九月底的一篇報告:PostgreSQL history。這篇文章的標題和目前你在看的這篇文章一樣,會讓你誤以為在介紹 PostgreSQL 早期的歷史,其實不是,它是在介紹從 8.0 版到 8.4 版間的變革。內容詳情,請各位自行點閱,我們來看這篇文章的結論。這篇文章的作者,把 8.0 到 8.4 這五個版本,一一的跑測試數據,得到了兩個表格:

PostgreSQL RO OLTP performance
 Peak TPSPeak performance at # of clients
8.0.2112564
8.1.17562014
8.2.13810918
8.3.71398422
8.4.11354622

PostgreSQL RW OLTP performance
 Peak TPSPeak performance at # of clients
8.0.213612
8.1.1787310
8.2.13135814
8.3.7279518
8.4.1271312
 有沒有注意到,從 8.0 到 8.3 版,效能上已經提昇五點五倍到將近九倍!雖然到了 8.4 版因為一些安全的因素,又把一些功能改變,而讓 RW OLTP 的整體效能又降低了一些,但是還是比 8.0 版快上六倍!所以說,在 8.3 版以前的使用者,應該要早日把系統昇級到最新版本,以得到最好的效能。
好了,恭喜你看到這篇文章。如果你的系統還在 8.3 版以前的,請趁現在一口氣昇到最近的 9.0.1 版吧。搭配 9.0.1 版的 pgAdmin III 1.12 版,有革命性的功能增加,真的值得你去安裝。當然囉,如果你的系統是裝在 Ubuntu 上,那麼你應該目前還只能安裝到 8.4.5 版。最近的 9.0.x 版,必須等到下一個版本 11.04 版 Armel,才會一起出現。如果忍不到那時候的話,那就先昇級到 8.4.5 版吧。

2010年5月6日 星期四

在 Ubuntu 上的 PostgreSQL 預設存取認證方式

在 FreeBSD 和 CentOS 上,第一次著手使用 PostgreSQL 非常容易,因為 root 的密碼你會知道,所以只需要以下列這兩個指令,就可以不用知道安裝程式到底替你的 pgsql 或者 postgres 指定了什麼複雜的密碼,你都可以切成 PostgreSQL 的系統帳號,來執行該有的管理命令:
$ su
# su - pgsql (這是在 FreeBSD ,或者)
# su - postgres (這是在 CentOS 上)
在 FreeBSD 上第一步更輕鬆,因為 FreeBSD 上的 PostgreSQL port 版的預設 pg_hba.conf 設定,把 localhost 和本機使用 Unix domain socket 的權限,設成最寬鬆的 trust,所以就算不用密碼,你還是可以很輕鬆的從本機上,用 postgres 這個資料庫成員進行管理和設定的工作;只是強烈建議你,在正式上線前這些設定都應該要修改,比較安全。只是,這些事情到了 Ubuntu 上就有一點點變得複雜了,原因有二:其一在於 Ubuntu 系統設計上,預設不想讓你知道 root 密碼,故意不讓你用 su 切成 root 來做管理工作,而是希望你利用任一個 wheel 群組的使用者登入後,再用 sudo 來執行 root 才能執行的管理命令。但是上面的第二個指令卻是使用 root 的權限才做得到,所以有些書或網路上的文章,會建議你直接替 postgres 系統帳號設定密碼;但是這種建議,我認為是很蠢的。其二就在 pg_hba.conf 這個檔案的預設值。其實我很反對替 postgresql 系統帳號設密碼,因為要設到又要你自己記得起來,又要複雜到 cracker 破解不了的密碼,實在不是件容易的事。那麼要怎麼著手第一步呢?剛裝好 PostgreSQL 時,我不但不知道 root 的密碼,連 postgres 系統帳號的密碼也不知道,更別說資料庫角色 postgres 的密碼了,那要怎麼進行?我們先從 pg_hba.conf 開始,這個檔案在 Ubuntu 的 PostgreSQL port 是放在 /etc/postgresql/8.4/main/pg_hba.conf [1]。總之,我們先看看預設值這個檔的內容,我只截取有義意的最後幾行:
......(上略)
# Database administrative login by UNIX sockets
local   all         postgres                          ident

# TYPE  DATABASE    USER        CIDR-ADDRESS          METHOD

# "local" is for Unix domain socket connections only
local   all         all                               ident
# IPv4 local connections:
host    all         all         127.0.0.1/32          md5
# IPv6 local connections:
host    all         all         ::1/128               md5
加粗的四行才是有意義的,其餘只是備註;一般來說,實際應用上,大家最後應該還是會開放讓網路上其它主機連線;但是目前還沒有,所以我們目前只需先來討論一下這四條設定。第一條和第二條事實上重覆了,我猜 Ubuntu 的 PostgreSQL 維護者是希望你把第二條改掉;比如改成像 CentOS 預設的 md5[2];第三條和第四條其實指的也是同一件事,就是 IPv4 和 IPv6 的 127.0.0.1 或 ::1/128 這兩個協定的 localhost 會使用 md5 認證方式。看起來這四條都是設定本機連線,事實上有一點點不一樣,差別就在前端程式所使用的協定。如果你有裝 pgAdmin III,那它使用的協定是 TCP/IP,適用的是第三或第四條;但是 psql 用的卻是 Unix domain socket,則是參考第二條設定。在這裏你可以注意到 Unix domain socket 的認證方法是 ident,意思是要再查閱 pg_ident.conf,就可以免密碼直接用 psql 直接連上 PostgreSQL。所以你只需要在系統中切成 postgres,你就可以直接執行管理指令,不用密碼[4]。但是,如果你是用 pgAdmin III 呢?我們看第三條,認證方法是 md5,這代表你必須輸入密碼,只是前端程式不會將你的密碼以明碼在網路上傳送,而是先用 md5 編碼後,等到了伺服器,再比對兩者的 md5 簽章結果是否一致。md5 是比 7.4 版以前的 PostgreSQL 所提供的「password」認證方式更安全的一種認證方式,當然你還可以選 gss, sspi, krb5 這些第三方的認證方式,還可以選像 pam, ldap 這類由目錄服務或是其它 PAM 模組所提供的認證方式,這方面請自行參考手冊。但是一般使用來說,md5 已經夠安全了。
但是,問題出現了,我又不知道 postgres 的密碼,那我怎麼使用 pgAdmin III 管理?答案很簡單,就是直接用 psql 設定 postgres 的資料庫密碼。但是,postgres 的系統帳號密碼我根本就不知道,叫我怎麼執行 psql 呢?其實很簡單,只要一行就可以免密碼切成 postgres:
$ sudo su - postgres
沒錯,就是這麼簡單!接著你就可以執行 psql:

然後你就可以執行更改密碼的指令:
postgres=# alter user postgres with encrypted password '你的新密碼';
ALTER ROLE
postgres=#
來,我們來看看用 pgAdmin III 是不是可以連上?先新增一個伺服器連線:

請輸入剛才設定的密碼:


這時候一定會出現「建議」,不用理會它!


哇哈哈,連上了!


第一步算是完成。再來就要開放讓網路上其它的機器可以讀取。請注意,建議設定得越嚴格越好,不要「假設」防火牆會幫你阻檔攻擊,能在這裏先把關好,就先把關好。
要放啟網路連線,有兩個設定檔要先修改,一個就是剛才的 pg_hba.conf,另一個是 postgresql.conf,兩個檔案都放在 /etc/postgresql/8.4/main 之下[1]。postgresql.conf 要修改的地方只有一處,如下圖所示:

請把上圖那行 #listen_addresses = 'localhost' 前面的「#」號[3]拿掉,把 'losthost' 改成 '*';記住,單引號千萬不要漏掉;然後存起來。這個設定,是代表 PostgreSQL 的 listener 要監聽的網路介面。如果你的伺服器有超過一個以上的網路介面卡,那麼你可以指定只監聽某個介面的查詢請求。有時為了安全,我們常會將伺服器安裝兩個介面卡,其中一個對外連,另一個對內連,而且不轉交對外的那個介面來的任何封包(也就是不讓伺服器另做路由器或防火牆用)。為了安全,我們可以只讓 PostgreSQL 監聽來自內部的查詢請求, 而不理會對外那個介面來的請求。設成 '*' 星號是貪圖方便、偷懶,代表監聽所有的網路介面。通常如果你的伺服器只有唯一一個網路介面卡時,你就可以這樣偷懶。
pg_hba.conf 則是在最後面加上你要開放的 IP。設定的規則很簡單,就像前面那堆註解說明的,請自己參考,更詳細的說明請參考手冊。如果你沒有設定 SSL 連線,那麼第一欄請使用 host 即可,用不著設成 hostnossl。第三欄建議使用 CIDR 表示法,儘量不要再用傳統的 IP network-mask 的格式。也就是說,假如你的打算開放的是 192.168.1.1 ~ 192.168.1.126,以傳統的網路遮罩應該是 255.255.255.128,那麼你可以設成 192.168.1.0/25。如果這部份你看不懂,那麼請找一本 TCP/IP 的書籍,專門翻到 IP 定址的那部份看一下,應該很容易就會懂了。第五欄,如果你的系統沒有安裝其它的第三方認證方式,建議使用 md5,不要使用 trust 或 passwordindent 也儘量不要用,除非你的前端都是 Unix/Linux。以剛才這一個網段為例,這行可以參考第三條,設定成:
host    all         all         192.168.1.0/25          md5

如果是只打算開放給 192.168.2.1 這個 IP,那麼一個 IP 的網路遮罩是 255.255.255.255,CIDR 表示法是 192.168.2.1/32,可以設定成:
host    all         all         192.168.2.1/32          md5
設定好了之後,請重新啟動 PostgreSQL,重新啟動的方法是:
$ sudo service postgresql-8.4 restart
 * Restarting PostgreSQL 8.4 database server                             [ OK ]
$
如上出現 OK 就表示你的設定語法上沒有問題,但是你還是要到前端用 pgAdmin III 連線看看,如果可以連上,那麼恭喜你,成功了。
最後,特別提醒一下,pg_hba.conf 不要設定得太寬鬆。因為雖然 PostgreSQL 很安全,但是只要人做的,就無法保證完全不會出錯。我就見過兩次很嚴重的安全性 bug 的安全通告。有些高手就有辦法在短短一兩天內搞出零時差攻擊。所以這方面再小心也不為過。

[1] 這篇文章假定是在 Ubuntu 10.05 LTS - Lucid Lynx 上,所安裝的 PostgreSQL server 8.4.3_1。其它版本,像是 8.4 換成 9.0 之類的,請自行類推。Ubuntu 在這方面很討厭,把所有設定檔放在 /etc 下,把資料庫檔卻放在 /var/lib 下,不像原始的 PostgreSQL 使用 chroot,把所有檔案全放在一塊。Ubuntu 這樣的安排,卻使得一堆工具使用上出現不少困擾。
[2] 我感到納悶的是,那為何不乾脆預設值就設成 md5?因為已經有了第一行的設定,即使預設改成了 md5 又不會影響 postgres 這個預設 dba 的認證方式。目前這個樣子只是留了一條尾巴,讓使用者事後還要動手改,那何不一開始就設定好?實在令人百思不得其解!
[3] 「#」井字號代表其後是註解,PostgreSQL 會自動忽略其後的文字。
[4] 這裏我跳過了一堆細節。ident 認證方式有好幾種,比如只有單純的 ident 或是有附加的述詞;比如 same user;用以補充說明。這裏如果後面再加上 same user 述詞就代表著,只要你在系統中以某個系統帳號登入,那麼你就可以免密碼以同名的資料庫帳號直接登入資料庫。比如你在 Ubuntu 以 postgres 這個系統帳號登入,這時候你就可以直接執行 psql,而不用使用密碼即可登入資料庫,就像前面本文中的這個例子。但是如果後面沒有述詞來補充呢?預設資料庫會去找和 pg_hba.conf 同一目錄下的 pg_ident.conf。這個檔案列了一個清單,內容就是系統帳號和資料庫帳號的對照表。但是如果清單中沒列的資料庫帳號,就像是加了 same user 述句一樣的認證方式。





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

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