經過朋友的開導,了解到單一文件大小有如下幾個因素:
1. 文件系統的限制(如剛存所說EXT3的2TB限制)
2. 某一程序進程所能存取的第一文件最大尺寸(例如apache在Linux EXT3下能存取的最大尺寸為2G,諸如日志)
初步判斷瓶頸就在上述其中第二項。隨後找到myisamchk來顯示一下表信息,證明了瓶頸就在MySQL本身的存取上。
# myisamchk -dv cdb_posts
結果就不貼了,其中有一項Max datafile length的值恰好就是4G。由此產生了瓶頸。
後來翻閱了N多資料,進行了N多嘗試,也走了不少彎路,最終覺得還是官方文檔比較可靠。比較老的文檔裡寫道這是由於tmp_table_size的值造成的,也有提到用BIG-TABLES這個參數。事實證明這些都是歧途。大晚上的確實很累,這裡只給出最終的解決方案吧,中間的就不羅嗦了。
進到MySQL客戶端。
# MySQL -uroot -p
Enter passWord: ******
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 59411 to server version: 4.0.18-standard
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
MySQL> use ******
Database changed
MySQL> ALTER TABLE cdb_posts MAX_ROWS=1000000000 AVG_ROW_LENGTH=15000;
因為這個表非常大,執行時間在雙Athlon的專業服務器上竟然花了30分鐘!
之後再通過myisamchk查看該表的信息:
# myisamchk -dv cdb_posts
MyISAM file: cdb_posts
Record format: Packed
Character set: latin1 (8)
File-version: 1
Creation time: 2004-08-30 22:19:48
Recover time: 2004-08-30 22:42:47
Status: open,changed
Auto increment key: 1 Last value: 1063143
Data records: 619904 Deleted blocks: 5
Datafile parts: 619909 Deleted data: 323872
Datafile pointer (bytes): 6 Keyfile pointer (bytes): 4
Datafile length: 4295287332 Keyfile length: 40421376
Max datafile length: 281474976710654 Max keyfile length: 4398046510079
Recordlength: 149
table description:
Key Start Len Index Type Rec/key Root Blocksize
1 1 4 unique unsigned long 1 4535296 1024
2 5 2 multip. unsigned short 13776 12540928 1024
3 111 4 multip. unsigned long 1 18854912 1024
4 28 3 multip. uint24 18 24546304 1024
5 7 3 multip. uint24 7 32827392 1024
111 4 unsigned long 1
6 7 3 multip. uint24 7 40418304 1024
28 3 uint24
令人振奮的事情發生了,該表的 Max datafile length: 281474976710654 Max keyfile length: 4398046510079,即最大數據尺寸(MYD文件)達到了2TB,最大索引尺寸(MYI)仍然為4G。
由此默認的4G限制被突破了。關於其中的原理,其實很簡單:假設你有一個日記本,上面有10頁紙可以寫東西,編排目錄只需要1個字節(因為0~9就夠了)。如果你把這本子又塞進兩張紙,變成12頁,1個字節的目錄空間就無法尋址到後面的兩頁中,進而產生了錯誤。上面那個ALTER語句中的數值都是我為保證成功,取的比較大的值(因為ALTER一次實在是太慢了,沒時間在那亂試驗),相當於告訴數據庫,這個本子有1000000000頁,每頁平均有15000個字節。