2008年2月8日 星期五

PostgreSQL 在 FreeBSD 上的大版本升級

唉!升級...升級...升級...這一陣子一直升級,這次輪到 PostgreSQL 大升級。PostgreSQL 不像其它軟體,即使是 8.2 升級到 8.3,也必須大改,所以無法直接用 upgrade 工具直接升。即使是 Windows 版本,也必須勞心費力一番。這次我用 FreeBSD 版本的升級做為例子,來說明最簡單也是最正確的大改版升級步驟。
首先,請先把原本資料庫的資料完全備份下來。如果你是 Windows 的使用者或是 Linux 的使用者,你可以考慮使用 pgAdmin III 的「工具」選單中的「備份」或「備份全域」來做,這樣簡單很多,但是由於 pgAdmin III 的說明太少,我實在看不懂「備份」對話方塊中選項的含意,所以乾脆不用。最正式的方法是使用在 console 下的工具:pg_dump 和 pg_dumpall。兩者的差別在於,前者可以針對某個特定的 database 做備份,而後者一般用來把整個伺服器資料做完整的備份。我建議直接使用 pg_dumpall 比較方便和快速。方法如下:
$ pg_dumpall > filename
而 filename 你可以自己取,比如 host_a.20080206.full.dump 之類的。名稱中加入日期可以讓你更清楚知道這個備份檔備份的日期。加入 full 字眼,可以提醒自己,這是完整備份,而非一般維護時所做的連續性部份備份的一份。如果你所管理的 PostgreSQL 有超過一台以上,那麼最好連資料庫主機名稱都註明。
對了,差點忘了一件極重要的事!在 Windows 上,只要你使用 administrators 群組中的任何一位使用者登入,然後從開始功能表→PostgreSQL 8.3→Command Prompt,就可以打開「命令提示字元」,而且可以下達 pg_dumpall 指令;但是,在 FreeBSD,一般安裝時,預設 root 是不允許執行 PostgreSQL 的相關指令的,所以請先切換成 pgsql 用戶,如果你沒更動 pgsql 的密碼,那麼預設的密碼很「隨機」,也就是任你怎麼猜也都猜不出來,但是你可以先用 su 切成 root,再用 su - pgsql 切換成 pgsql 使用者,不用輸入任何密碼即可,這時就可以執行上述指令。但是請注意,這時最好把這個備份檔移到安全位置,以免繼續進行的安裝過程中不傎誤砍。所以這時候你最好是先跳回 root,請下 exit 指令,然後用 cp 指令把剛才那個 dump 檔 copy 到任何你暫存的位置。
接著正式執行安裝。在安裝新版本之前,必須先移除舊版本,否則兩個 daemon 會搶同一個 TCP port,開機時會有無法預知的狀況出現。首先先看一下你的伺服器中,目前裝了哪些和 PostgreSQL 相關的 package:
# pkg_info | grep postgresql
這時候你至少可以看到兩個 package 出現在清單中,而我多了一個:
postgresql-client-8.2.6_1 PostgreSQL database (client)
postgresql-contrib-8.2.6 The contrib utilities from the PostgreSQL distribution
postgresql-server-8.2.6 The most advanced open-source database available anywhere
一般來說,如果你沒有安裝Server instrumentation 功能,那麼應該只有 client 和 server 兩個 package。但是這個小清單並不完整,如果你還有安裝 php 和 PostgreSQL 相關的驅動程式,那麼這時候並不會出現在這個清單當中。不用擔心,你若移除的順序不對,出現相依的套件,那麼把相依套件移除,再來移除目標套件即可。只是這時候你最好拿隻筆記下你一共移除了哪些套件,將來才能再一一重新安裝回去。我們先以這三個 package 來說好了,如果你沒移除舊版本的 server,那麼直接移除 client 會被提醒,而且停止進行安裝動作。同樣的,如果你沒先移除舊版本的 contrib 和 php 相關 package,你在移除 client 時也會因為相依套件尚未被移除,而被停止移除 client 的動作。所以若以上述三者為例,則移除的順序為:
# /usr/local/etc/rc.d/postgresql stop <-- 先停掉目前的 PostgreSQL server
# pkg_delete postgresql-contrib-8.2.6
# pkg_delete postgresql-server-8.2.6
# pkg_delete postgresql-client-8.2.6_1
這時請把 /usr/local/pgsql/data 整個目錄移走,像我只是把它改個名稱,而讓它繼續留著,說不定哪天還會用到目錄中的某些檔案:mv /usr/local/pgsql/data /usr/local/pgsql/data_8.2。然後就可以開始使用 port 來安裝 PostgreSQL 8.3 了。在安裝前,請先確定你的伺服器上的 port tree 是否已是最新的版本,如果你的 port tree 是在 2008/2/5 天亮前更新的,可能 postgresql-server-8.3 還不是最新版本,請先手動更新 port tree。如果已是最新版本,那麼切到該 port 目錄:
# cd /usr/ports/databases/postgresql83-server
# make install clean
FreeBSD 會自動幫你將 8.3 版的 server 和 client 都一併裝好。接著把 contrib package 也裝起來:
# cd ../postgresql-contrib
# make install clean
如果你曾經把 php5 的 driver 移除掉或 JDBC 等等等之前移除掉的套件,現在也請用同樣的方法把所有新的版本一一裝回去。這樣就好了嗎?還早,請先看一下你的 /usr/local/pgsql 下是否已經建好新的資料庫?
# ls /usr/local/pgsql
如果這個目錄下只出現一個剛才更名的 data_8.2,那麼代表 Makefile 並沒有自動幫你做 initdb,請執行:
# /usr/local/etc/rc.d/postgresql initdb [1]
這時你再下 ls /usr/local/pgsql 指令時,就可以看到多出一個 data 目錄了,這樣才能正確啟動 PostgreSQL:
# /usr/local/etc/rc.d/postgresql start [2]
如果沒出現任何錯誤訊息,那麼先恭喜你,安裝好了。但是工作才完成一半,再來是把原來備份的資料回存回資料庫中:
# su - pgsql
$ psql -f filename postgres
也就是先切成 pgsql 使用者,接著執行 PostgreSQL 的互動式指令輸入工具:psql,然後把剛才你的 dump 檔的名稱(這裏當然是完整路徑名稱)取代上面的 filename。接著一些訊息代表著資料庫回存的動作,正在做什麼動作。如果一切錯誤訊息都沒有出現過,那麼恭喜你,工作完成了 80%。對於 Windows 的使用者來說,只要記住最後一條指令,就可以把剛才 pg_dumpall 所備份的資料回存了。Windows 的使用者真幸福。
什麼?才完成 80%?是的,有兩個檔可能之前的版本你有更動過,分別是 postgresql.conf 和 pg_hba.conf,它們在 FreeBSD 中應該位於 /usr/local/pgsql/data 目錄下,請把之前曾經更動過的改回去,但是請把 release notes 先讀過一遍,因為 postgresql.conf 中很多管理項目都更動過了,可能之前你所更改的項目,8.3 版已經把該項和其它項目合併,並取了新的項目名稱了,先讀過 release notes 的 E.1.2.2. Configuration Parameters 是很重要的。還有,剛才如果把舊的 8.2 版的 /usr/local/pgsql/data 目錄直接刪掉,那此刻就糗了,你必須用你的記憶力回想你曾經更動過的項目和內容,所以我才會建議只需把它更名,保留下來。
若是你對 PostgreSQL 的備份和回存有興趣,英文程式也還可以,那麼請進一步參考 PostgreSQL 的線上說明:Chapter 24. Backup and Restore
 

附註:
[1] 當然囉,如果新的 data 目錄已經生成,也就是 Makefile 已經自動幫你執行 initdb 的動作了,那麼 initdb 這個動作就可以省了。我會特別這樣提的原因是,我現這兩天的搶先版本的 Makefile 怪怪的,有時不會自動執行 initdb 動作。
[2] 如果你沒有像我這麼麻煩的用 pg_dumpall 和 psql 來備份回存,直接升級(還是得先移除舊版本再安裝新版本),表面上看起來還是可以升級,但是,事實上 Makefile 會把你舊版本的 postgresql.conf 和 pg_hba.conf 複製一份到新的 data 目錄中。如我文中所說的,postgresql.conf 在這個版本中有大更動,因此,當你打算啟動資料庫時,會出現 FATAL ERROR!解決方法很簡單,用不著重灌,把新的 data 目錄移走(一樣用更名的),執行 /usr/local/etc/postgresql initdb,重做一次 initdb,就會有一個全新版本的 data 了。
[3] 這篇文章僅適用於負載不大的伺服器上,倘若你的伺服器是 mission critical 的大用量伺服器,雖然基本的升級概念是一樣的,也就是資料庫大升級等同重新安裝,所以服務勢必一定得中斷,但是事前的演練和良好的計劃,可以讓停機服務的時間減少。在這種情況,建議必須得增加備援伺服器,在主伺服器升級的同時,讓備援伺服器先暫時服務。說到這裏,就得牽涉到「資料庫複製」(replication) 的主題了。等我有空再來寫一篇 PostgreSQL 和 replication 相關的文章。

沒有留言:

張貼留言

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

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