Movable Type 驚魂記
我們的部落格是放在家裡的 server 上跑, 而且還是在 server 上的 VMware 裡, 因此總是覺得它的速度不夠快. 再家上 Movable Type 是用 Perl 寫的, 所有的動作都是即時解譯的, 想也知道很沒效率. 架設這個部落格時, 我為了省麻煩, 就直接用 Linux 裡內建的 Berkeley DB 當作資料庫後端, 沒有另外架別的資料庫. 昨天聽信了一帖偏方, 聽說把資料庫換成 MySQL 會讓 Movable Type 的效能大大提升, 就動手試了.
沒想到這是一場惡夢的開始…
事情是這樣開始的: 要用 MySQL 當資料庫, 當然就要先裝 MySQL. 我用 apt-get 去抓 MySQL:
[bird@www bird]$ apt-get install mysql
但是 apt-get 告訴我說, 我的系統裡面同時存在兩套版本不一樣的 db4 套件, 要我先解決這個版本衝突的問題再裝 MySQL. 這個 db4 就是 Berkeley DB 的套件名稱啦, 為什麼會有兩套呢? 我用 rpm 看了一下:
[bird@www bird]$ rpm -qa | grep db4
結果真的看到兩到 db4:
db4-4.1.25-0.rh73.3.1
db4-4.0.14-20
我依稀記得那時裝 Movable Type 時, 去抓了一個 db4 的 rpm 套件回來裝, 後來才發現原來 Linux 裡面原來就有 db4, 而且 rpm 是靠 db4 在運作的. 不過既然這兩個套件並存在系統裡安然無事, 我也就沒有再去管它.
apt-get 還告訴我, 可以用 apt-get instll 後面不加任何套件名稱來嘗試修復這個問題, 我那時沒有很仔細看完它的說明, 就照著打.
這是我犯下最大的錯…
apt-get 不知道拔掉了我系統裡什麼跟資料庫有關的東西, 但一定不是 db4. 因為我等 apt-get 跑完後, 再用 rpm -qa 看一次, 發現還是有兩套 db4, 而更糟的是, Movable Type 不能跑了.
當我執行 mt.cgi 時, 它會自動 redirect 到 mt-upgrade.cgi, 而且不管我用什麼帳號密碼, 都是 invalid login. 也就是說, 我進不了 MT 的管理畫面了.
***
我開始覺得, 事情有點大條. 如果無法登入 MT 的管理畫面, 我什麼事都不能做. 我甚至不知道 MT 賴以工作的資料庫還是不是好的.
幸好我還有整個 /var/www/html 目錄的備份, 而且還是新鮮的. 我先把目前的 html 目錄 mv 成別的名字, 再從 tarball 裡把 html 目陸解過去.
MT 還是不能跑.
所以不會是資料庫損毀的問題, 一定是系統層面的問題. 我試著跑 mt-check.cgi, 看看有沒有什麼 MT 需要的套件掛掉了. 不過它告訴我一切安好. 不過我很意外的發現, mt-check.cgi 並沒有去檢查系統裡有沒有 db4, 它只 check 一個叫 DB_File 的套件. 我查了一下, DB_File 全名叫 perl-DB-File, 它是 db4 對 Perl 的前端.
[bird@www bird]$ rpm -qa | grep perl-DB_File
perl-DB_File-1.804-88.3
我的系統裡面有這個 perl-DB_File 套件, mt-check.cgi 也告訴我沒有問題.
但是 MT 還是不能跑.
***
這時有個小插曲. Sharon 從 MSN 上捎來訊息, 說阿爽日記的留言功能不能用. 因為 MT 產生的頁面基本上是靜態的, 所以已經產生的頁面都還看得到. 但是迴響會用到 mt-comment 這隻 CGI, 也會動到資料庫, 所以會沒辦法跑.
我決定來挖挖看資料庫到底有沒有問題. 問了一下 Google, 有個套件叫 db4-utils, 是 db4 的 command line utility, 有一些工具可以 dump 資料庫的內容. 但是 db4-utils 也有不同的版本, 我的系統裡有兩個 db4, 我該裝哪一版的呢 ? 我叫 apt-get 幫我決定, 結果它抓了 db4-utils-4.0.14-20, 比較舊的那一個. 我開始懷疑我當初到底是怎麼把 db4-4.1.25 那個套件裝上去的…
我用 db4-utils 裡的 db_dump 去看 MT 產生的 .db 檔, 沒想到它給我一個錯誤訊息, 說版的 db4-utils 不支援這個資料庫的 btree 版本. Oh my god, 到底是誰太舊, 誰太新呢 ? 我記得在 MT 的討論區上有看到有人在討論不同版本的 db4 產生的資料庫檔案, 彼此之間不能相容的問題.
開始有一線曙光了. 看來是兩個不同版本的 db4 打架的問題.
我把 db4-utils-4.0.14.20 拔掉, 另外去抓了 db4-utils-4.1.25 裝上. 果然用這個版本的 db4-utils 就可以看到資料庫的內容. 所以至少我確定, 原來我的 MT 用的是 db4-4.1.25 來產生資料庫. 為了確定我的想法正確, 我試著用 rpm 把 db4-4.0.14-20 拔掉, 但是我發現這似乎不可能, 因為這一版的 db4 有一大堆的 dependency, 包括 rpm 在內都是靠它運作的, 因此根本拔不掉.
但是我的系統裡還有一套 4.1.25 版的 db4, 我怎麼知道 MT 會用哪一版的 db4 呢 ? 它是怎麼決定要用哪一版的 db4 呢 ?
***
我突然想到剛剛在跑 mt-check.cgi 時, 它顯示的那個 perl-DB_File 套件, 它是 Perl 用來乎叫 db4 的界面, 會不會是由它決定的呢 ?
我上網路去查 rpm search, 看一下我目前用的這個 perl-DB_File-1.804-88.3 有哪些 dependency. 啊哈! 被我抓到了, 它的 dependency 裡有一個
libdb-4.0.so
看名字也知道這是 db4 4.0 版的 shared object. Shared object 是 Linux 上的動態連結 library, 就像 Windows 的 DLL 一樣. 不過 Linux 的 shared object 除了檔名外, 還用到 soname 這個屬性來識別相容性, 如果不同檔名的 so 檔之間有同樣的 soname, 它們在動態連結時還是可以互相替代的.
[bird@www lib]$ cd /lib
[bird@www lib]$ ls -l libdb*
-r-xr-xr-x 1 root root 5512945 2月 6 2003 libdb-4.0.so
-rwxr-xr-x 1 root root 823045 7月 11 2003 libdb-4.1.so
我的系統裡真的有兩個 libdb, 來看看它們的 soname:
[bird@www lib]$ objdump -p libdb-4.0.so | grep SONAME
SONAME libdb-4.0.so
[bird@www lib]$ objdump -p libdb-4.1.so | grep SONAME
SONAME libdb-4.1.so
好, 這兩個 shared object 的 soname 是不一樣的, 我現在可以合理, 強烈, 高度懷疑, DB_File 乎叫的是 4.0 的這個, 而原來的資料庫是用 4.1 版的建立的. 從 db_dump 4.0 版不能讀 4.1 版的資料庫檔案來推斷, 這兩個版本的資料庫是不相容的.
現在我剩下一個問題: 要去哪裡找可以用 4.1 版資料庫的 DB_File ? 我要找一個會去呼叫 libdb-4.1.so 的 DB_File, 而不是現在這個. 我上 rpm search 去一個一個看, 看看哪一個 perl-DB_File 有 libdb-4.1.so 的 dependency.
有這個 dependency 的 perl-DB_File 還蠻多的, 但是都不是 RedHat 用的, 我裝了 Mandrake 的上來, 發現不能用, MT 根本就認為我沒裝 DB_File. 最後在某個網頁的角落找到 perl-DB_File-1.804-88.4, 而我原來用的是 perl-DB_File-1.804-88.3, 它們真的只差小數點後很多位的一位, 但是卻決定了 Movable Type 的生死.
我把 1.804.88.3 版的 DB_File 拔掉, 裝上 1.804.88.4, MT 就可以跑了.
***
但是我還是沒搞懂的是, 為什麼我的系統裡只剩下 perl-DB_File-1.804.88.3 呢 ? 那原來的資料庫是誰建出來的呢 ? 應該是 apt-get 搞的鬼吧…
整個酷!!
完全看不懂!
阿快日記變成純文字了
那是因為我在修改阿快日記的 CSS 啦… 暫時先把 CSS 拿掉了.