myisam

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現在被輕視,而ENGINE是首先的用法。

一般地,ENGINE選項是不必要的;除非默認已經被改變了,InnoDB是默認存儲引擎(Mysql 5.1後)。

你可以用myisamchk工具來檢查或修復MyISAM表。請參閱MySQL 5.1參考手冊5.9.5.6節,“使用myisamchk做崩潰恢復”。你也可以用myisampack來壓縮MyISAM表,讓它們占更少的空間。請參閱MySQL 5.1參考手冊8.2節,“myisampack,產生壓縮、唯讀的MyISAM表”。

特徵

MyISAM存儲引擎的一些特徵

1. 所有數據值先存儲低位元組。這使得數據機和作業系統分離。二進制輕便性的唯一要求是機器使用補碼(如最近20年的機器有的一樣)和IEEE浮點格式(在主流機器中也完全是主導的)。唯一不支持二進制兼容性的機器是嵌入式系統。這些系統有時使用特殊的處理器。

先存儲數據低位元組並不嚴重地影響速度;數據行中的位元組一般是未聯合的,從一個方向讀未聯合的位元組並不比從反向讀更占用更多的資源。伺服器上的獲取列值的代碼與其它代碼相比並不顯得時間緊。

2.大檔案(達63位檔案長度)在支持大檔案的檔案系統和作業系統上被支持。

3. 當把刪除和更新及插入混合的時候,動態尺寸的行更少碎片。這要通過合併相鄰被刪除的塊,以及若下一個塊被刪除,就擴展到下一塊來自動完成。

7. NULL值被允許在索引的列中。這個占每個鍵的0-1個位元組。

8. 所有數字鍵值以高位元組為先被存儲以允許一個更高地索引壓縮。

9. 當記錄以排好序的順序插入(就像你使用一個AUTO_INCREMENT列之時),索引樹被劈開以便高節點僅包含一個鍵。這改善了索引樹的空間利用率。

10.每表一個AUTO_INCREMENT列的內部處理。MyISAM為INSERT和UPDATE操作自動更新這一列。這使得AUTO_INCREMENT列更快(至少10%)。在序列頂的值被刪除之後就不能再利用。(當AUTO_INCREMENT列被定義為多列索引的最後一列,可以出現重使用從序列頂部刪除的值的情況)。AUTO_INCREMENT值可用ALTER TABLE或myisamch來重置。

11. 如果數據檔案中間的表沒有自由塊了,在其它執行緒從表讀的同時,你可以INSERT新行到表中。(這被認識為並發操作)。自由塊的出現是作為刪除行的結果,或者是用比當前內容多的數據對動態長度行更新的結果。當所有自由塊被用完(填滿),未來的插入又變成並發。

12.你可以把數據檔案和索引檔案放在不同目錄,用DATA DIRECTORY和INDEX DIRECTORY選項CREATE TABLE以獲得更高的速度,請參閱13.1.5節,“CREATE TABLE語法”。

a.每個字元列可以有不同的字元集,請參閱第10章:“字元集支持”。

b.在MyISAM索引檔案里有一個標誌,它表明表是否被正確關閉。如果用--myisam-recover選項啟動mysqld,MyISAM表在打開得時候被自動檢查,如果被表被不恰當地關閉,就修復表。

c.如果你用--update-state選項運行myisamchk,它標註表為已檢查。myisamchk --fast只檢查那些沒有這個標誌的表。

d. myisamchk --analyze為部分鍵存儲統計信息,也為整個鍵存儲統計信息。

e. myisampack可以打包BLOB和VARCHAR列。

MyISAM也支持下列特徵

1.支持true VARCHAR類型;VARCHAR列以存儲在2個位元組中的長度來開始。

2.有VARCHAR的表可以有固定或動態記錄長度。

3. VARCHAR和CHAR列可以多達64KB。

4. 一個被搞亂的已計算索引對可對UNIQUE來使用。這允許你在表內任何列的合併上有UNIQUE。(儘管如此,你不能在一個UNIQUE已計算索引上搜尋)。

對MyISAM存儲引擎,有一個更詳細的論壇在

15.1.1. MyISAM啟動選項

下列對mysqld 的選項可用來改變MyISAM表的行為:

· --myisam-recover=mode

設定為崩潰MyISAM表自動恢復的模式。

· --delay-key-write=ALL

對任何MyISAM表的寫操作之間不要刷新鍵緩衝區。

注釋:如果你要這么做。當表在使用中之時,你應該不使用來自另一個程式的MyISAM表(比如從另一個MySQL伺服器或用myisamchk)。這么做會導致索引被破壞。

對使用--delay-key-write的表,使用--external-locking沒有幫助。

請參閱5.3.1節,“mysqld命令行選項”。

下列系統變數影響MyISAM表的行為:

· bulk_insert_buffer_size

用在塊插入最佳化中的樹緩衝區的大小。注釋:這是一個per thread的限制。

· (OBSOLETE) myisam_max_extra_sort_file_size

這個參數已經不在MySQL中使用。

· myisam_max_sort_file_size

如果臨時檔案會變得超過索引,不要使用快速排序索引方法來創建一個索引。注釋:這個參數以位元組的形式給出。

· myisam_sort_buffer_size

設定恢復表之時使用的緩衝區的尺寸。

請參閱5.3.3節,“伺服器系統變數”。

如果用--myisam-recover選項啟動mysqld,自動恢復被激活。在這種情況下,當伺服器打開一個MyISAM表之時,伺服器會檢查是否表被標註為崩潰,或者表的打開計數變數是否不為0且你正用--skip-external-locking運行伺服器。如果這些條件的任何一個為真,下列情況發生:

· 表被查錯。

· 如果伺服器發現一個錯誤,它試著做快速表修復(排序且不重新創建數據檔案)。

· 如果修復因為數據檔案中的一個錯誤而失敗(例如,一個重複鍵錯誤),伺服器會再次嘗試修復,這一次重建數據檔案。

· 如果修復仍然失敗,伺服器用舊修複選項方法再重試一次修復(一行接一行地寫,不排序)。這個方法應該能修復任何類型的錯誤,並且需要很低的磁碟空間。

如果恢復不能夠從先前完成的語句里恢復所有行,而且你不能在--myisam-recover選項值指定FORCE,自動修復會終止,並在錯誤日誌里寫一條錯誤信息:

Error: Couldn't repair table: test.g00pages

如果你指定FORCE,取而代之地,類似這樣的一個警告被給出:

Warning: Found 344 of 354 rows when repairing ./test/g00pages

注釋:如果自動恢復值包括BACKUP,恢復進程創建檔案並用tbl_name-datetime.BAK形式取名。你應該有一個cron腳本,它自動把這些檔案從資料庫目錄移到備份媒質上。

15.1.2.鍵所需的空間

MyISAM表使用B型樹索引。你可以粗略地計算索引檔案的大小為(key_length+4)/0.67, 加上所有的鍵之和。當所有鍵以排序的順序插入並且表沒有任何壓縮的鍵之時,以上估計是對最壞的情況的。

字元串索引是被空間壓縮的。如果第一個字元串索引部分是字元串,它也被加前綴壓縮。如果字元串列有許多拖曳空間,或字元串列是一個總是不用完全長度的VARCHAR列,空間壓縮使得索引檔案比最壞情況時的數值要小。前綴壓縮被用在以字元串開始的鍵上。如果有許多具有同一前綴的字元串,前綴壓縮是有幫助的。

在MyISAM表,你也可以在創建表的時候通過指定PACK_KEYS=1來前綴壓縮數字。當數字被以高位元組優先存儲之時,若你有許多具有同一前綴的整數鍵,上述方法是有幫助的。

存儲格式

MyISAM支持三種不同存儲格式。

其中兩個(固定格式和動態格式)根據正使用的列的類型來自動選擇。第三個,即已壓縮格式,只能使用myisampack工具來創建。

當你CREATE或ALTER一個沒有BLOB或TEXT列的表,你可以用ROW_FORMAT表選項強制表的格式為FIXED或DYNAMIC。這會導致CHAR和VARCHAR列因FIXED格式變成CHAR,或因DYNAMIC格式變成VARCHAR。

靜態表

(固定長度)

靜態格式是MyISAM表的默認存儲格式。當表不包含變數長度列(VARCHAR, BLOB, 或TEXT)時,使用這個格式。每一行用固定位元組數存儲。

MyISAM的三種存儲格式中,靜態格式就最簡單也是最安全的(至少對於崩潰而言)。靜態格式也是最快的on-disk格式。快速來自於數據檔案中的行在磁碟上被找到的容易方式:當按照索引中的行號查找一個行時,用行長度乘以行號。同樣,當掃描一個表的時候,很容易用每個磁碟讀操作讀一定數量的記錄。

當MySQL伺服器正往一個固定格式MyISAM檔案寫的時候,如果計算機崩潰了,安全是顯然的。在這種情況下,myisamchk可以容易地決定每行從哪裡開始到哪裡結束,所以它通常可以收回所有記錄,除了寫了一部分的記錄。注意,基於數據行,MyISAM表索引可以一直被重新構建。

靜態格式表的一般特徵:

· CHAR列對列寬度是空間填補的。

· 非常快。

· 容易快取。

· 崩潰後容易重建,因為記錄位於固定位置。

· 重新組織是不必要的,除非你刪除巨量的記錄並且希望為作業系統騰出磁碟空間。為此,可使用OPTIMIZE TABLE或者myisamchk -r。

· 通常比動態格式表需要更多的磁碟空間。

動態表

如果一個MyISAM表包含任何可變長度列(VARCHAR, BLOB或TEXTDynamic),或者如果一個表被用ROW_FORMAT=DYNAMIC選項來創建,動態存儲格式被使用。

這個格式更為複雜一點,因為每行有一個表明行有多長的頭。當一個記錄因為更新的結果被變得更長,該記錄也可以在超過一個位置處結束。

你可以使用OPTIMIZE TABLE或myisamchk來對一個表整理碎片。如果在一個表中有你頻繁訪問或改變的固定長度列,表中也有一些可變長度列,僅為避免碎片而把這些可變長度列移到其它表可能是一個好主意。

動態格式表的一般特徵:

· 除了長度少於4的列外,所有的字元串列是動態的。

· 在每個記錄前面是一個點陣圖,該點陣圖表明哪一列包含空字元串(對於字元串列)或者0(對於數字列)。注意,這並不包括包含NULL值的列。如果一個字元列在拖曳空間移除後長度為零,或者一個數字列為零值,這都在點陣圖中標註了且列不被保存到磁碟。 非空字元串被存為一個長度位元組加字元串的內容。

· 通常比固定長度表需要更少的磁碟空間。

· 每個記錄僅使用必需大小的空間。儘管如此,如果一個記錄變大,它就按需要被分開成多片,造成記錄碎片的後果。比如,你用擴展行長度的信息更新一行,該行就變得有碎片。在這種情況下,你可以時不時運行OPTIMIZE TABLE或myisamchk -r來改善性能。可使用myisamchk -ei來獲取表的統計數據。

· 動態格式表在崩潰後要比靜態格式表更難重建,因為一個記錄可能被分為多個碎片且連結(碎片)可能被丟失。

· 動態尺寸記錄期望的行長度用下列表達式來計算:

· 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位元組。在一個更新導致一個記錄的擴大之時,一個動態記錄被連結了。每個新連結至少是20位元組,所以下一個擴大可能在同樣的連結里進行。如果不是,則另一個連結將被建立。你可以使用myisamchk -ed來找出連結的數目。所有的連結可以用myisamchk -r來移除。

已壓縮表

已壓縮存儲格式是由myisampack工具創建的唯讀格式。

所有MySQL分發版里都默認包括myisampack。已壓縮表可以用myisamchk來解壓縮。

已壓縮表有下列特徵:

· 已壓縮表占據非常小的磁碟空間。這最小化了磁碟用量,當使用緩慢的磁碟(如CD-ROM)之時,這是很有用的。

· 每個記錄是被單獨壓縮的,所以只有非常小的訪問開支。依據表中最大的記錄,一個記錄的頭在每個表中占據1到3個位元組。每個列被不同地壓縮。通常每個列有一個不同的Huffman樹。一些壓縮類型如下:

o 後綴空間壓縮。

- 前綴空間壓縮。

- 零值的數用一個位來存儲。

- 如果在一個整型列中的值有一個小的範圍,列被用最小可能的類型來存儲。比如,一個BIGINT列(8位元組),如果所有它的值在-128到127範圍內,它可以被存儲為TINYINT列(1位元組)

- 如果一個列僅有一小組可能的值,列的類型被轉化成ENUM。

- 一個列可以使用先前壓縮類型的任意合併。

· 可以處理固定長度或動態長度記錄。

問題

MySQL用來存儲數據的檔案格式已經被廣泛測試過,但總是有導致數據表變得損壞的環境。

損壞的MyISAM表

即使MyISAM表格式非常可靠(SQL語句對表做的所有改變在語句返回之前被寫下),如果下列任何事件發生,你依然可以獲得損壞的表:

· mysqld進程在寫中間被殺掉。

· 發生未預期的計算機關閉(例如,計算機被關閉)。

· 硬體故障。

· 你可以同時在正被伺服器修改的表上使用外部程式(如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節,“CHECK TABLE語法”, 13.5.2.6節,“REPAIR TABLE語法”,和5.9.5節,“myisamchk — MyISAM表維護工具”。

如果你的表變得頻繁損壞,你應該試著確定為什麼會這樣的原因。要明白的最重要的事是表變得損壞是不是因為伺服器崩潰的結果。你可以在錯誤日誌中查找最近的restarted mysqld訊息來早期驗證這個。如果存在這樣一個訊息,則表損壞是伺服器死掉的一個結果是很有可能的。否則,損壞可能在正常操作中發生。這是一個缺陷。你應該試著創建一個展示這個問題的可重複生成的測試案例。請參閱A.4.2節,“如果MySQL保持崩潰,該怎么做” 及E.1.6節,“如果出現表崩潰,請生成測試案例”。

未被適當關閉的表的問題

每個MyISAM索引檔案(.MYI)在頭有一個計數器,它可以被用來檢查一個表是否被恰當地關閉。如果你從CHECK TABLE或myisamchk得到下列警告,意味著這個計數器已經不同步了:

clients are using or haven't closed the table properly

這個警告並不是完全意味著表已被破壞,但你至少應該檢查表。

計數器的工作方式如下:

· 表在MySQL中第一次被更新,索引檔案頭的計數器加一。

· 在未來的更新中,計數器不被改變。

· 當表的最後實例被關閉(因為一個操作FLUSH TABLE或因為在表緩衝區中沒有空間)之時,若表已經在任何點被更新,則計數器減一。

· 當你修理或檢查表並且發現表完好之時,計數器被重置為零。

· 要避免與其它可能檢查表的進程進行事務的問題,若計數器為零,在關閉時計數器不減一。

換句話來說,計數器只有在下列情況會不同步:

· MyISAM表不隨第一次發出的LOCK TABLES和FLUSH TABLES被複製。

· MySQL在一次更新和最後關閉之間崩潰(注意,表可能依然完好,因為MySQL總是在每個語句之間為每件事發出寫操作)。

· 一個表被myisamchk --recover或myisamchk --update-state修改,同時被mysqld使用。

· 多個mysqld伺服器正使用表,並且一個伺服器在一個表上執行REPAIR TABLE或CHECK TABLE,同時該表也被另一個伺服器使用。在這個結構中,使用CHECK TABLE是安全的,雖然你可能從其它伺服器上得到警告。儘管如此,REPAIR TABLE應該被避免,因為當一個伺服器用一個新的數據檔案替代舊的之時,這並沒有傳送信號到其它伺服器上。

總的來說,在多伺服器之間分享一個數據目錄是一個壞主意。

相關詞條

相關搜尋

熱門詞條

聯絡我們