MyISAM是默認存儲引擎(MySQL5.1前)。它基于更老的ISAM代碼,但有很多有用的擴展。(注意MySQL 5.1不支持ISAM)。每個MyISAM在磁盤上存儲成三個文件,每一個文件的名字均以表的名字開始,擴展名指出文件類型。
.frm文件存儲表定義;
·MYD (MYData)文件存儲表的數據;
.MYI (MYIndex)文件存儲表的索引。
簡介
要明確表示你想要用一個MyISAM表格,請用ENGINE表選項指出來:
CREATE TABLE t (i INT) ENGINE = MYISAM;
注釋:老版本的MySQL使用TYPE而不是ENGINE(例如,TYPE = MYISAM)。MySQL 5.1為向下兼容而支持這個語法,但TYPE現(xiàn)在被輕視,而ENGINE是首先的用法。
一般地,ENGINE選項是不必要的;除非默認已經被改變了,InnoDB是默認存儲引擎(Mysql 5.1后)。
你可以用myisamchk工具來檢查或修復MyISAM表。請參閱MySQL 5.1參考手冊5.9.5.6節(jié),“使用myisamchk做崩潰恢復”。你也可以用myisampack來壓縮MyISAM表,讓它們占更少的空間。請參閱MySQL 5.1參考手冊8.2節(jié),“myisampack,產生壓縮、只讀的MyISAM表”。
特征
MyISAM存儲引擎的一些特征
1. 所有數據值先存儲低字節(jié)。這使得數據機和操作系統(tǒng)分離。二進制輕便性的唯一要求是機器使用補碼(如最近20年的機器有的一樣)和IEEE浮點格式(在主流機器中也完全是主導的)。唯一不支持二進制兼容性的機器是嵌入式系統(tǒng)。這些系統(tǒng)有時使用特殊的處理器。
先存儲數據低字節(jié)并不嚴重地影響速度;數據行中的字節(jié)一般是未聯(lián)合的,從一個方向讀未聯(lián)合的字節(jié)并不比從反向讀更占用更多的資源。服務器上的獲取列值的代碼與其它代碼相比并不顯得時間緊。
2.大文件(達63位文件長度)在支持大文件的文件系統(tǒng)和操作系統(tǒng)上被支持。
3. 當把刪除和更新及插入混合的時候,動態(tài)尺寸的行更少碎片。這要通過合并相鄰被刪除的塊,以及若下一個塊被刪除,就擴展到下一塊來自動完成。
7. NULL值被允許在索引的列中。這個占每個鍵的0-1個字節(jié)。
8. 所有數字鍵值以高字節(jié)為先被存儲以允許一個更高地索引壓縮。
9. 當記錄以排好序的順序插入(就像你使用一個AUTO_INCREMENT列之時),索引樹被劈開以便高節(jié)點僅包含一個鍵。這改善了索引樹的空間利用率。
10.每表一個AUTO_INCREMENT列的內部處理。MyISAM為INSERT和UPDATE操作自動更新這一列。這使得AUTO_INCREMENT列更快(至少10%)。在序列頂的值被刪除之后就不能再利用。(當AUTO_INCREMENT列被定義為多列索引的最后一列,可以出現(xiàn)重使用從序列頂部刪除的值的情況)。AUTO_INCREMENT值可用ALTER TABLE或myisamch來重置。
11. 如果數據文件中間的表沒有自由塊了,在其它線程從表讀的同時,你可以INSERT新行到表中。(這被認識為并發(fā)操作)。自由塊的出現(xiàn)是作為刪除行的結果,或者是用比當前內容多的數據對動態(tài)長度行更新的結果。當所有自由塊被用完(填滿),未來的插入又變成并發(fā)。
12.你可以把數據文件和索引文件放在不同目錄,用DATA DIRECTORY和INDEX DIRECTORY選項CREATE TABLE以獲得更高的速度,請參閱13.1.5節(jié),“CREATE TABLE語法”。
a.每個字符列可以有不同的字符集,請參閱第10章:“字符集支持”。
b.在MyISAM索引文件里有一個標志,它表明表是否被正確關閉。如果用--myisam-recover選項啟動MySQLd,MyISAM表在打開得時候被自動檢查,如果被表被不恰當地關閉,就修復表。
c.如果你用--update-state選項運行myisamchk,它標注表為已檢查。myisamchk --500米口徑球面射電望遠鏡只檢查那些沒有這個標志的表。
d. myisamchk --analyze為部分鍵存儲統(tǒng)計信息,也為整個鍵存儲統(tǒng)計信息。
e. myisampack可以打包BLOB和VARCHAR列。
MyISAM也支持下列特征
1.支持true VARCHAR類型;VARCHAR列以存儲在2個字節(jié)中的長度來開始。
2.有VARCHAR的表可以有固定或動態(tài)記錄長度。
3. VARCHAR和CHAR列可以多達64KB。
4. 一個被搞亂的已計算索引對可對UNIQUE來使用。這允許你在表內任何列的合并上有UNIQUE。(盡管如此,你不能在一個UNIQUE已計算索引上搜索)。
對MyISAM存儲引擎,有一個更詳細的論壇在
15.1.1. MyISAM啟動選項
下列對mysqld 的選項可用來改變MyISAM表的行為:
· --myisam-recover=mode
設置為崩潰MyISAM表自動恢復的模式。
· --delay-key-write=ALL
對任何MyISAM表的寫操作之間不要刷新鍵緩沖區(qū)。
注釋:如果你要這么做。當表在使用中之時,你應該不使用來自另一個程序的MyISAM表(比如從另一個MySQL服務器或用myisamchk)。這么做會導致索引被破壞。
對使用--delay-key-write的表,使用--external-locking沒有幫助。
請參閱5.3.1節(jié),“mysqld命令行選項”。
下列系統(tǒng)變量影響MyISAM表的行為:
· bulk_insert_buffer_size
用在塊插入優(yōu)化中的樹緩沖區(qū)的大小。注釋:這是一個per thread的限制。
· (OBSOLETE) myisam_max_extra_sort_file_size
這個參數已經不在MySQL中使用。
· myisam_max_sort_file_size
如果臨時文件會變得超過索引,不要使用快速排序索引方法來創(chuàng)建一個索引。注釋:這個參數以字節(jié)的形式給出。
· myisam_sort_buffer_size
設置恢復表之時使用的緩沖區(qū)的尺寸。
請參閱5.3.3節(jié),“服務器系統(tǒng)變量”。
如果用--myisam-recover選項啟動mysqld,自動恢復被激活。在這種情況下,當服務器打開一個MyISAM表之時,服務器會檢查是否表被標注為崩潰,或者表的打開計數變量是否不為0且你正用--skip-external-locking運行服務器。如果這些條件的任何一個為真,下列情況發(fā)生:
· 表被查錯。
· 如果服務器發(fā)現(xiàn)一個錯誤,它試著做快速表修復(排序且不重新創(chuàng)建數據文件)。
· 如果修復因為數據文件中的一個錯誤而失敗(例如,一個重復鍵錯誤),服務器會再次嘗試修復,這一次重建數據文件。
· 如果修復仍然失敗,服務器用舊修復選項方法再重試一次修復(一行接一行地寫,不排序)。這個方法應該能修復任何類型的錯誤,并且需要很低的磁盤空間。
如果恢復不能夠從先前完成的語句里恢復所有行,而且你不能在--myisam-recover選項值指定FORCE,自動修復會終止,并在錯誤日志里寫一條錯誤信息:
Error: Couldn't repair table: test.g00pages
如果你指定FORCE,取而代之地,類似這樣的一個警告被給出:
Warning: Found 344 of 354 rows when repairing ./test/g00pages
注釋:如果自動恢復值包括BACKUP,恢復進程創(chuàng)建文件并用tbl_name-datetime.BAK形式取名。你應該有一個cron腳本,它自動把這些文件從數據庫目錄移到備份媒質上。
15.1.2.鍵所需的空間
MyISAM表使用B型樹索引。你可以粗略地計算索引文件的大小為(key_length+4)/0.67, 加上所有的鍵之和。當所有鍵以排序的順序插入并且表沒有任何壓縮的鍵之時,以上估計是對最壞的情況的。
字符串索引是被空間壓縮的。如果第一個字符串索引部分是字符串,它也被加前綴壓縮。如果字符串列有許多拖曳空間,或字符串列是一個總是不用完全長度的VARCHAR列,空間壓縮使得索引文件比最壞情況時的數值要小。前綴壓縮被用在以字符串開始的鍵上。如果有許多具有同一前綴的字符串,前綴壓縮是有幫助的。
在MyISAM表,你也可以在創(chuàng)建表的時候通過指定PACK_KEYS=1來前綴壓縮數字。當數字被以高字節(jié)優(yōu)先存儲之時,若你有許多具有同一前綴的整數鍵,上述方法是有幫助的。
存儲格式
MyISAM支持三種不同存儲格式。
其中兩個(固定格式和動態(tài)格式)根據正使用的列的類型來自動選擇。第三個,即已壓縮格式,只能使用myisampack工具來創(chuàng)建。
當你CREATE或ALTER一個沒有BLOB或TEXT列的表,你可以用ROW_FORMAT表選項強制表的格式為FIXED或DYNAMIC。這會導致CHAR和VARCHAR列因FIXED格式變成CHAR,或因DYNAMIC格式變成VARCHAR。
靜態(tài)表
(固定長度)
靜態(tài)格式是MyISAM表的默認存儲格式。當表不包含變量長度列(VARCHAR, BLOB, 或TEXT)時,使用這個格式。每一行用固定字節(jié)數存儲。
MyISAM的三種存儲格式中,靜態(tài)格式就最簡單也是最安全的(至少對于崩潰而言)。靜態(tài)格式也是最快的on-disk格式。快速來自于數據文件中的行在磁盤上被找到的容易方式:當按照索引中的行號查找一個行時,用行長度乘以行號。同樣,當掃描一個表的時候,很容易用每個磁盤讀操作讀一定數量的記錄。
當MySQL服務器正往一個固定格式MyISAM文件寫的時候,如果計算機崩潰了,安全是顯然的。在這種情況下,myisamchk可以容易地決定每行從哪里開始到哪里結束,所以它通常可以收回所有記錄,除了寫了一部分的記錄。注意,基于數據行,MyISAM表索引可以一直被重新構建。
靜態(tài)格式表的一般特征:
· CHAR列對列寬度是空間填補的。
· 非常快。
· 容易緩存。
· 崩潰后容易重建,因為記錄位于固定位置。
· 重新組織是不必要的,除非你刪除巨量引擎的記錄并且希望為操作系統(tǒng)騰出磁盤空間。為此,可使用OPTIMIZE TABLE或者myisamchk -r。
· 通常比動態(tài)格式表需要更多的磁盤空間。
動態(tài)表
如果一個MyISAM表包含任何可變長度列(VARCHAR, BLOB或TEXTDynamic),或者如果一個表被用ROW_FORMAT=DYNAMIC選項來創(chuàng)建,動態(tài)存儲格式被使用。
這個格式更為復雜一點,因為每行有一個表明行有多長的頭。當一個記錄因為更新的結果被變得更長,該記錄也可以在超過一個位置處結束。
你可以使用OPTIMIZE TABLE或myisamchk來對一個表整理碎片。如果在一個表中有你頻繁訪問或改變的固定長度列,表中也有一些可變長度列,僅為避免碎片而把這些可變長度列移到其它表可能是一個好主意。
動態(tài)格式表的一般特征:
· 除了長度少于4的列外,所有的字符串列是動態(tài)的。
· 在每個記錄前面是一個位圖,該位圖表明哪一列包含空字符串(對于字符串列)或者0(對于數字列)。注意,這并不包括包含NULL值的列。如果一個字符列在拖曳空間移除后長度為零,或者一個數字列為零值,這都在位圖中標注了且列不被保存到磁盤。非空字符串被存為一個長度字節(jié)加字符串的內容。
· 通常比固定長度表需要更少的磁盤空間。
· 每個記錄僅使用必需大小的空間。盡管如此,如果一個記錄變大,它就按需要被分開成多片,造成記錄碎片的后果。比如,你用擴展行長度的信息更新一行,該行就變得有碎片。在這種情況下,你可以時不時運行OPTIMIZE TABLE或myisamchk -r來改善性能。可使用myisamchk -ei來獲取表的統(tǒng)計數據。
· 動態(tài)格式表在崩潰后要比靜態(tài)格式表更難重建,因為一個記錄可能被分為多個碎片且鏈接(碎片)可能被丟失。
· 動態(tài)尺寸記錄期望的行長度用下列表達式來計算:
· 3
· + (number of columns + 7) / 8
· + (number of char columns)
· + (packed size of numeric columns)
· + (length of strings)
· + (number of NULL columns + 7) / 8
對每個鏈接需要額外的6字節(jié)。在一個更新導致一個記錄的擴大之時,一個動態(tài)記錄被鏈接了。每個新鏈接至少是20字節(jié),所以下一個擴大可能在同樣的鏈接里進行。如果不是,則另一個鏈接將被建立。你可以使用myisamchk -ed來找出鏈接的數目。所有的鏈接可以用myisamchk -r來移除。
已壓縮表
已壓縮存儲格式是由myisampack工具創(chuàng)建的只讀格式。
所有MySQL分發(fā)版里都默認包括myisampack。已壓縮表可以用myisamchk來解壓縮。
已壓縮表有下列特征:
· 已壓縮表占據非常小的磁盤空間。這最小化了磁盤用量,當使用緩慢的磁盤(如CD-ROM)之時,這是很有用的。
· 每個記錄是被單獨壓縮的,所以只有非常小的訪問開支。依據表中最大的記錄,一個記錄的頭在每個表中占據1到3個字節(jié)。每個列被不同地壓縮。通常每個列有一個不同的Huffman樹。一些壓縮類型如下:
o 后綴空間壓縮。
- 前綴空間壓縮。
- 零值的數用一個位來存儲。
- 如果在一個整型列中的值有一個小的范圍,列被用最小可能的類型來存儲。比如,一個BIGINT列(8字節(jié)),如果所有它的值在-128到127范圍內,它可以被存儲為TINYINT列(1字節(jié))
- 如果一個列僅有一小組可能的值,列的類型被轉化成ENUM。
- 一個列可以使用先前壓縮類型的任意合并。
· 可以處理固定長度或動態(tài)長度記錄。
問題
MySQL用來存儲數據的文件格式已經被廣泛測試過,但總是有導致數據表變得損壞的環(huán)境。
損壞的MyISAM表
即使MyISAM表格式非常可靠(SQL對表做的所有改變在語句返回之前被寫下),如果下列任何事件發(fā)生,你依然可以獲得損壞的表:
· mysqld進程在寫中間被殺掉。
· 發(fā)生未預期的計算機關閉(例如,計算機被關閉)。
· 硬件故障。
· 你可以同時在正被服務器修改的表上使用外部程序(如myisamchk)。
· MySQL或MyISAM代碼的軟件缺陷。
一個損壞的表的典型癥狀如下:
· 當在從表中選擇數據之時,你得到如下錯誤:
· Incorrect key file for table: '...'. Try to repair it
· 查詢不能在表中找到行或返回不完全的數據。
你可以用CHECK TABLE statement語句來檢查MyISAM表的健康,并用REPAIR TABLE修復一個損壞的MyISAM表。當mysqld不運行之時,你也可以用myisamchk命令檢查或修理一個表。請參閱13.5.2.3節(jié),“CHECK TABLE語法”, 13.5.2.6節(jié),“REPAIR TABLE語法”,和5.9.5節(jié),“myisamchk — MyISAM表維護工具”。
如果你的表變得頻繁損壞,你應該試著確定為什么會這樣的原因。要明白的最重要的事是表變得損壞是不是因為服務器崩潰的結果。你可以在錯誤日志中查找最近的restarted mysqld消息來早期驗證這個。如果存在這樣一個消息,則表損壞是服務器死掉的一個結果是很有可能的。否則,損壞可能在正常操作中發(fā)生。這是一個缺陷。你應該試著創(chuàng)建一個展示這個問題的可重復生成的測試案例。請參閱A.4.2節(jié),“如果MySQL保持崩潰,該怎么做”及E.1.6節(jié),“如果出現(xiàn)表崩潰,請生成測試案例”。
未被適當關閉的表的問題
每個MyISAM索引文件(.MYI)在頭有一個計數器,它可以被用來檢查一個表是否被恰當地關閉。如果你從CHECK TABLE或myisamchk得到下列警告,意味著這個計數器已經不同步了:
clients are using or haven't closed the table properly
這個警告并不是完全意味著表已被破壞,但你至少應該檢查表。
計數器的工作方式如下:
· 表在MySQL中第一次被更新,索引文件頭的計數器加一。
· 在未來的更新中,計數器不被改變。
· 當表的最后實例被關閉(因為一個操作FLUSH TABLE或因為在表緩沖區(qū)中沒有空間)之時,若表已經在任何點被更新,則計數器減一。
· 當你修理或檢查表并且發(fā)現(xiàn)表完好之時,計數器被重置為零。
· 要避免與其它可能檢查表的進程進行事務的問題,若計數器為零,在關閉時計數器不減一。
換句話來說,計數器只有在下列情況會不同步:
· MyISAM表不隨第一次發(fā)出的LOCK TABLES和FLUSH TABLES被復制。
· MySQL在一次更新和最后關閉之間崩潰(注意,表可能依然完好,因為MySQL總是在每個語句之間為每件事發(fā)出寫操作)。
· 一個表被myisamchk --recover或myisamchk --update-state修改,同時被mysqld使用。
· 多個mysqld服務器正使用表,并且一個服務器在一個表上執(zhí)行REPAIR TABLE或CHECK TABLE,同時該表也被另一個服務器使用。在這個結構中,使用CHECK TABLE是安全的,雖然你可能從其它服務器上得到警告。盡管如此,REPAIR TABLE應該被避免,因為當一個服務器用一個新的數據文件替代舊的之時,這并沒有發(fā)送信號到其它服務器上。
總的來說,在多服務器之間分享一個數據目錄是一個壞主意。
參考資料 >