MySQL學習筆記(二):MyISAM 存儲引擎

MyISAM 存儲引擎
mysql


MyISAM 基於舊的 (再也不可用) ISAM 存儲引擎, 但有許多有用的擴展。sql

每一個 MyISAM 表都存儲在三個文件中的磁盤上。這些文件具備以表名開頭的名稱, 並具備用於指示文件類型的擴展名。數據庫

.frm文件存儲表定義。緩存

數據文件的擴展名爲.MYD (MYData)。安全

索引文件的擴展名是.MYI (MYIndex)服務器


要明確表示要用一個MyISAM表格,請用ENGINE表選項指出來:架構

CREATE TABLE t (i INT) ENGINE = MYISAM;併發


在 MySQL 5.7 中, 一般須要使用 ENGINE 來指定 MyISAM 存儲引擎, 由於 InnoDB 是默認引擎。ide


可使用 mysqlcheck 客戶端或 myisamchk 實用程序檢查或修復 MyISAM 表。還可使用 myisampack 壓縮 MyISAM 表, 以減小更少的空間。工具


以下是MyISAM存儲引擎的一些特徵:


1. 全部數據值首先以低字節存儲。這使得數據機器和操做系統獨立。二進制可移植性的惟一要求是機器使用兩個補間符號整數和 IEEE 浮點格式。這些要求普遍應用於在主流機器中。二進制兼容性可能不適用於有特殊的處理器的嵌入式系統。


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


3. 全部數字鍵值以高字節爲先被存儲以容許一個更高地索引壓縮


4. 大文件(達63位文件長度)在支持大文件的文件系統和操做系統上被支持


5. MyISAM表最大行數爲 18440000000000000000


6. 每一個MyISAM表最大索引數是64


7. 每一個索引最大的列數是16個


8. 最大的鍵長度是1000字節。這也能夠經過編譯來改變。對於鍵長度超過250字節的狀況,一個超過1024字節的的鍵塊被用上。


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



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


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



12. MyISAM 支持併發插入:若是數據文件中間的表沒有自由塊了,在其它線程從表讀的同時,你能夠INSERT新行到表中。(這被認識爲併發操做 )。自由塊的出現是做爲刪除行的結果,或者是用比當前內容多的數據對動態長度行更新的結果。當全部自由塊被用完(填滿),將來的插入又變成併發。請參閱8.11.3 節 "併發插入"。


13. 你能夠把數據文件和索引文件放在不一樣目錄,用DATA DIRECTORY和INDEX DIRECTORY選項CREATE TABLE以得到更高的速度,請參閱13.3.18節,「CREATE TABLE語法」。



14. BLOB和TEXT列能夠被索引。


15. NULL值被容許在索引的列中。這個佔每一個鍵的0-1個字節


16. 每一個字符列能夠又不一樣的字符集,請參閱第10.1章 :「字符集支持」。


17. 在MyISAM索引文件裏又一個標誌,它代表表是否被正確關閉。若是用--myisam-recover選項啓動mysqld,MyISAM表在打開得時候被自動檢查,若是被表被不恰當地關閉,就修復表。


18. 若是你用--update-state選項運行myisamchk,它標註表爲已檢查。myisamchk --fast只檢查那些沒有這個標誌的表。


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


20. myisampack能夠打包BLOB和VARCHAR列



MyISAM也支持下列特徵:


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


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


3. VARCHAR和CHAR列能夠多達64KB。


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






MyISAM 啓動選項:


mysqld 的如下選項可用於更改 MyISAM 表的行爲。有關其餘信息, 請參見5.1.4 節 "服務器命令選項"。


1. --myisam-recover-options=mode

設置爲崩潰MyISAM表自動恢復的模式


2. --delay-key-write=ALL

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

註釋:若是要這麼作。當MyISAM表在使用中之時,不該該使用另外一個程序來訪問它(好比從另外一個MySQL服務器或用myisamchk)。這麼作會致使索引被破壞。對使用--delay-key-write的表,--external-locking不會生效


如下系統變量會影響 MyISAM 表的行爲。有關其餘信息, 請參見5.1.5 節 "服務器系統變量"。


1. bulk_insert_buffer_size

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


2. myisam_max_sort_file_size

在從新建立 MyISAM 索引 (在修復表、更改表或加載數據 INFILE 期間) 容許 MySQL 使用的臨時文件的最大大小。若是文件大小大於此值, 則使用密鑰緩存來建立索引, 這會比較慢。該值以字節爲單位給出。


3. myisam_sort_buffer_size

設置恢復表時使用的緩衝區大小。



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


1. 表被查錯。


2. 若是服務器發現一個錯誤,它試着作快速表修復(排序且不從新建立數據文件)。


3. 若是修復由於數據文件中的一個錯誤而失敗(例如,一個重複鍵錯誤),服務器會再次嘗試修復,這一次重建數據文件。


4. 若是修復仍然失敗,服務器用舊修復選項方法再重試一次修復(一行接一行地寫,不排序)。這個方法應該能修復任何類型的錯誤,而且須要很低的磁盤空間。


若是恢復不可以從先前完成的語句裏恢復全部行,並且你不能在--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腳本,它自動把這些文件從數據庫目錄移到備份媒質上。




鍵所需的空間


1. MyISAM表使用B型樹索引。你能夠粗略地計算索引文件的大小爲(key_length+4)/0.67, 加上全部的鍵之和。當全部鍵以排序的順序插入而且表沒有任何壓縮的鍵之時,以上估計是對最壞的狀況的。


2. 字符串索引是被空間壓縮的。若是第一個字符串索引部分是字符串,它也被加前綴壓縮。若是字符串列有許多拖曳空間,或字符串 列是一個老是不用徹底長度的VARCHAR列,空間壓縮使得索引文件比最壞狀況時的數值要小。前綴壓縮被用在以字符串開始的鍵上。若是有許多具備同一前綴的字符串,前綴壓縮是有幫助的。


3. 在MyISAM表,你也能夠在建立表的時候經過指定PACK_KEYS=1來前綴壓縮數字。當數字被以高字節優先存儲之時,若你有許多具備同一前綴的整數鍵,上述方法是有幫助的。





MyISAM表的存儲格式

MyISAM 支持三種不一樣的存儲格式。根據所使用的列類型, 將自動選擇其中的兩個, 即固定和動態格式。第三個壓縮格式只能使用 myisampack 實用程序建立 (請參見4.6.5 節 "myisampack 生成壓縮的只讀 MyISAM 表")。


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


有關 ROW_FORMAT 的信息, 請參見13.1.18 節 "建立表語法"。


您可使用 myisamchk --unpack 解壓 (unpack) 壓縮的 MyISAM 表,「myisamchk — MyISAM Table-Maintenance Utility」的詳細信息見4.6.3章節



靜態(固定長度)表特徵


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


2. 在三 MyISAM 存儲格式中, 靜態格式是最簡單、最安全的 (最不受損壞的)。因爲能夠輕鬆地在磁盤上找到數據文件中的行, 所以它也是最快的on-disk格式: 當按照索引中的行號查找一個行時,用行長度乘以行號。一樣,當掃描一個表的時候,很容易用每一個磁盤讀操做讀必定數量的記錄。


3. 若是您的計算機在 MySQL 服務器寫入固定格式的 MyISAM 文件時崩潰, 安全是顯然的。在這種狀況下, myisamchk 能夠很容易地肯定每行的開始和結束位置, 所以它一般能夠回收除了部分寫入以外的全部行(緩衝區中未寫入的全部行)。MyISAM 表索引始終能夠基於數據行進行重建。


注意:固定長度行格式僅適用於沒有 BLOB 或TEXT列的表。使用顯式 ROW_FORMAT 子句建立具備BLOB 或TEXT這些列的表不會引起錯誤或警告; 格式規範將被忽略。



靜態格式表的通常特徵:


1. CHAR 和 VARCHAR 列的空間填充到指定的列寬,儘管列類型未被更改。BINARY和 VARBINARY 列用0x00 字節填充到列寬。


2. NULL 列須要行中的額外空間來記錄它們的值是否爲 NULL。每一個 NULL 列須要一個額外的位, 四捨五入到最近的字節。


3. 很是快。


4. 容易緩存。


5. 在崩潰後易於重建, 由於數據行位於固定位置。


6. 除非刪除大量的行並但願將可用磁盤空間返回給操做系統, 不然無需進行重組。爲此, 請使用 OPTIMIZE TABLE 或 myisamchk -r。


7. 一般比動態格式表須要更多的磁盤空間。


8. 使用如下表達式計算靜態大小行的預期行長度 (以字節爲單位):

row length = 1

+ (sum of column lengths)

+ (number of NULL columns + delete_flag + 7)/8

+ (number of variable-length columns)

對於具備靜態行格式的表, delete_flag 爲1。靜態表在行記錄中使用位, 用於指示是否已刪除行的標誌。delete_flag 是0用於動態表, 由於該標誌存儲在動態行標題中。




動態表特性


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


動態格式比靜態格式稍微複雜一些,由於每行有一個代表行有多長的頭。當一個記錄由於更新的結果被變得更長,該記錄也能夠在超過一個位置處結束。


可使用OPTIMIZE TABLE或myisamchk -r來對一個表整理碎片。若是在一個表中有頻繁訪問或改變的固定長度列,而且表中也有一些可變長度列,爲避免碎片而把這些可變長度列移到其它表多是一個好主意。



動態格式表的通常特徵:


1. 除了長度少於4的列外,全部的字符串列是動態的。


2. 每行前面都有一個位圖, 指示哪些列包含空字符串 (對於字符串列) 或0 (對於數值列)。這不包括包含 NULL 值的列。若是字符串列在尾隨空格後的長度爲0, 或者數值列的值爲0, 則在位圖中標記, 而不保存到磁盤。非空字符串保存爲一個長度字節加上字符串內容。


3. NULL 列須要行中的額外空間來記錄它們的值是否爲 NULL。每一個 NULL 列須要一個額外的位, 四捨五入到最近的字節。


4. 一般比固定長度表須要更少的磁盤空間


5. 每行只使用所需的空間。可是, 若是行變得更大, 則會將其拆分爲所需的多個片段, 從而致使行碎片。例如, 若是使用擴展行長度的信息更新行, 則該行將變得有碎片。在這種狀況下, 您可能須要時不時運行OPTIMIZE TABLE或myisamchk -r以提升性能。使用 myisamchk -ei 獲取表統計信息。


6. 比靜態格式表在崩潰後重建更困難, 由於行可能會被分割成許多片斷和連接 (碎片), 可能會在重建時丟失。


7. 使用如下表達式計算動態大小行的預期行長度:


row length = 3

+ (number of columns + 7) / 8

+ (number of char columns)

+ (packed size of numeric columns)

+ (length of strings)

+ (number of NULL columns + 7) / 8


8. 對每一個連接須要額外的6字節。在一個更新致使一個記錄的擴大之時,一個動態記錄被連接了。每一個新連接至少是20字節,因此下一個擴大可能在一樣的連接裏進行。若是不是,則另外一個連接將被創建。你可使用myisamchk -ed來找出連接的數目。全部的連接能夠用 OPTIMIZE TABLE 或 myisamchk -r來移除。



壓縮表特性


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

已壓縮表能夠用myisamchk來解壓縮。



壓縮表有下列特徵:


1. 已壓縮表佔據很是小的磁盤空間。這最小化了磁盤用量,當使用緩慢的磁盤(如CD-ROM)之時,這是頗有用的。


2. 每一個記錄是被單獨壓縮的,因此只有很是小的訪問開支。依據表中最大的記錄,一個記錄的頭在每一個表中佔據1到3個字節。每一個 列被不一樣地壓縮。一般每一個列有一個不一樣的Huffman樹。一些壓縮類型以下:

 2.1 後綴空間壓縮。

 2.2 前綴空間壓縮。

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

 2.4 若是在一個整型列中的值有一個小的範圍,列被用最小可能的類型來存儲。好比,一個BIGINT列(8字節),若是全部它的值在-128到127範圍內,它能夠被存儲爲TINYINT列(1字節)

 2.5 若是一個列僅有一小組可能的值,列的類型被轉化成ENUM。

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


3. 能夠處理固定長度或動態長度記錄。


注意

雖然壓縮表是隻讀的, 所以不能在表中更新或添加行, 但 DDL (數據定義語言) 操做仍然有效。例如, 您仍然可使用 drop 除去表, 並截斷表以清空表。




MyISAM 表問題


MySQL用來存儲數據的文件格式已經被普遍測試過,但老是有致使數據表變得損壞的環境。


損壞的MyISAM表


即便MyISAM表格式很是可靠(SQL語句對錶作的全部改變在語句返回以前被寫下),若是下列任何事件發生,你依然能夠得到損壞的表:


1. mysqld 進程在寫入過程當中被殺死。


2. 發生意外的計算機關機 (例如, 計算機被關閉)。


3. 硬件故障。


4. 使用外部程序 (如 myisamchk) 修改正在被服務器修改的表。


5. MySQL 或 MyISAM 代碼中的bug。


表損壞的典型症狀爲:


1. 從表中查詢數據時會出現如下錯誤:

Incorrect key file for table: '...'. Try to repair it


2. 查詢在表中找不到行或返回不完整的結果。


可使用 CHECK TABLE語句檢查 MyISAM 表的健康情況, 並用REPAIR TABLE修復損壞的 MyISAM 表。當 mysqld 未運行時, 還可使用 myisamchk 命令檢查或修復表。


參閱 13.7.2.2 章節 「CHECK TABLE Syntax」, 13.7.2.5 章節 「REPAIR TABLE Syntax」, 4.6.3 章節, 「myisamchk — MyISAM Table-Maintenance Utility」.



若是表頻繁損壞, 則應嘗試肯定發生此事件的緣由。最重要的是要知道該表是否因服務器崩潰而損壞。經過在錯誤日誌中查找最近 restarted mysqld 消息, 進行驗證。若是有這樣的消息, 表損壞極可能是服務器崩潰致使的。不然, 損壞可能發生在正常操做期間。這是個 bug。您應該嘗試建立一個可重現的測試用例來演示問題。


參閱 B.5.3.3 章節 「What to Do If MySQL Keeps Crashing」, 28.5 章節 「Debugging and Porting MySQL」.




未正確關閉表的問題


每一個 MyISAM 索引文件 (.MYI文件) 在頭部有一個計數器, 可用於檢查表是否已正確關閉。若是從CHECK TABLE或 myisamchk 獲得如下警告, 則表示此計數器已經不一樣步了:

clients are using or haven't closed the table properly

此警告不必定意味着該表已損壞, 但至少應檢查表。



該計數器的工做原理以下:


1. 第一次在 MySQL 中更新表時, 索引文件頭部中的計數器將遞增。


2. 在將來的更新中, 計數器不會更改。


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


4. 當修復表, 或檢查表時它被發現是好的, 計數器被重置爲零。


5. 爲了不與其它可能檢查表的進程進行交互的問題,若計數器爲零,在關閉時計數器不減一。



換言之, 只有在下列狀況下, 計數器纔會變得不正確:


1. 複製 MyISAM 表, 不先 LOCK TABLES 和 FLUSH TABLES


2.  MySQL在一次更新和最後關閉之間崩潰(注意,表可能依然無缺,由於MySQL老是在每一個語句之間爲每件事發出寫操做)


3. 一個表被mysqld使用的同時,又被myisamchk --recover或myisamchk --update-state修改。


4. 多個 mysqld 服務器正在使用該表, 一臺服務器在其被另外一臺服務器使用時在表上執行了修復表或檢查表。在這個架構中, 使用CHECK TABLE是安全的, 儘管可能從其餘服務器獲得警告。可是, 應避免REPAIR TABLE, 由於當一個服務器用一個新的數據文件替代舊的之時,其餘服務器不知道這一點。


總的來講,在多服務器之間共用一個數據目錄是一個壞主意。

參閱 5.6 章節 「Running Multiple MySQL Instances on One Machine」 得到更多研討。

相關文章
相關標籤/搜索