關于 MyISAM 引擎,你可能不知道的三件事
存在即合理,雖然在互聯網公司中 InnoDB 引擎使用較多,但是 MyISAM 引擎的特性自有它自己的使用場景,今天松哥就來和大家捋一捋 MyISAM,這也是我們 MySQL 進階必經之路。
1.MyISAM
MyISAM 是 MySQL 的默認數據庫引擎(5.5版之前),由早期的 ISAM 所改良。雖然性能極佳,但卻有一個缺點:不支持事務處理(transaction)。最近幾年,MySQL 逐漸使用 InnoDB 代替了 MyISAM,關于 InnoDB 和 MyISAM 的歷史糾葛,松哥在上篇文章中(MySQL 體系架構簡介)已經和大家介紹過了,這里就不再贅述。
每一個使用 MyISAM 存儲引擎的數據表,數據都會存放在兩個文件中 .MYD 和 .MYI,例如我新建一個使用了 MyISAM 存儲引擎的表,名為 user,然后我們找到 user 表的存放位置,可以看到如下三個文件:
user.frm:存儲表結構信息,這個和 MyISAM 引擎沒有關系。
user.MYD:存放表數據。
user.MYI:存放索引信息。
題外話,如何查看數據庫文件位置?
執行命令 show global variables like "%datadir%"; 可以查看數據庫文件位置。
2.特性
那么 MyISAM 都有哪些特性呢?接下來我們就從如下幾個方面來介紹下。
2.1 鎖級別
基本上大家看到所有講 MyISAM 和 InnoDB 區別的資料,都會提到這一點,因為這是它倆最為重要的區別,MyISAM 是表級鎖(table-level locking),而 InnoDB 支持行級鎖(row-level locking),也支持表級鎖,但是默認情況下是行級鎖。
表級鎖的特點是開銷小,加鎖快,不會出現死鎖,但是鎖定粒度較大,發生鎖沖突的概率高,而且并發度也低。
行級鎖的特點是開銷大,加鎖慢,有可能會出現死鎖,但是它的鎖定粒度小,發生鎖沖突的概率低,并發度也高。
根據鎖的特點來看,表級鎖更適合于查詢操作(讀寫混合操作執行效率較低),而行級鎖則更適合并發更新、并發查詢的應用,因為我們今天的主角是 MyISAM,所以我們這里就先不討論行級鎖的問題,表級鎖松哥在上篇文章中也已經介紹過了,這里就不再贅述。沒看上篇的小伙伴可以參考:MySQL 中的表級鎖很差勁嗎?。
2.2 check/repair
可以通過 check table 命令來查看 MyISAM 表是否損壞,也可以通過 repair table 命令來修復一個被損壞的 MyISAM 表。
2.3 全文索引
MyISAM 支持全文索引,曾經這是它非常重要的一個特性。因為從 MySQL5.6 開始,InnoDB 才支持全文索引,在這之前,官方的存儲引擎只有 MyISAM 支持全文索引。
另外需要注意的是,MyISAM 引擎還可以建立前綴索引(InnoDB 也支持),所謂前綴索引說白了就是對文本的前幾個字符(具體是幾個字符在建立索引時指定)建立索引,這樣建立起來的索引更小,所以查詢更快。這有點類似于 Oracle 中對字段使用 Left 函數來建立函數索引,只不過 MySQL 的這個前綴索引在查詢時是內部自動完成匹配的,并不需要使用 Left 函數。
關于前綴索引,松哥之前已經專門寫過文章介紹過了:
這個 MySQL 索引選擇性有點意思!
2.4 表壓縮
MyISAM 表支持數據壓縮。
對于一些很大的只讀表,我們可以對其進行壓縮,這樣可以有效節省磁盤 IO。MyISAM 表在壓縮的時候是對單行數據進行壓縮的,所以我們并不用擔心在讀取一行數據的時候會對表進行解壓。
MyISAM 表壓縮的命令是 myisampack,我們來看一個簡單案例:
首先進入到數據庫文件目錄中查看當前的數據庫文件:
然后我們對 user.MYI 文件進行強制壓縮:
user.OLD 是壓縮之前的文件備份,其他的是壓縮后的文件,由于松哥這里的樣例數據比較少,所以壓縮之后的效果不是很明顯(壓縮后的文件反而變大了,如果數據量比較大,就不會出現這個問題)。
壓縮完成后,我們再對數據表進行操作,如下:
可以看到,只有查詢操作是 OK 的,其他的增刪改都是不可以的,因為壓縮后的 user 表就是一個只讀表。
2.5 單表限制
在 MySQL5.0 之前,使用 MyISAM 引擎的數據表,單表最大大小為 4G,如果我們存儲的數據超過了 4G,就需要在創建表的時候,手動調整可存儲的數據行數以及每行的數據大小。
創建表時我們可以通過如下方式修改這兩個變量:
- CREATE TABLE user2 (
- id INTEGER NOT NULL PRIMARY KEY,
- name CHAR(18) NOT NULL
- ) MAX_ROWS = 1000000000 AVG_ROW_LENGTH = 32;
對于已存在的表,我們可以通過如下方法修改這兩個變量:
- ALTER TABLE user2 MAX_ROWS=1000000000 AVG_ROW_LENGTH=15000;
當然,這都是老黃歷了!
在 MySQL5.0 之后,單表的大小限制變成了 256TB,這基本上夠用了。
3.使用場景
非事務型應用(MyISAM 不支持事務)
只讀數據(可在表壓縮之后使用)
4.小結
好啦,幾天就先和小伙伴們扯這么多~
參考資料:
https://zhuanlan.zhihu.com/p/123962424
https://www.cnblogs.com/studyzy/p/4310653.html
本文轉載自微信公眾號「江南一點雨」,可以通過以下二維碼關注。轉載本文請聯系江南一點雨公眾號。




























