MySQL 技術內幕——存儲引擎

數據庫存儲引擎的選擇會對性能產生直接的影響。MySQL體系結構如下:

MySQL體系結構

存儲引擎是針對於表的而不是針對於庫的(一個庫中的不同表可以使用不同的存儲引擎)。MyISAM 是 MySQL 5.5 之前版本默認的存儲引擎。MySQL 5.5 及之後版本默認存儲引擎改爲了 InnoDB。

MyISAM 和 InnoDB 是最常用的兩種存儲引擎,除了這兩種,還有一些具備特殊功能的存儲引擎:CSV、Archive、Memory、Federated。簡單對比如下:

存儲引擎 事務 鎖粒度 索引和數據存儲 主要應用 忌用
MyISAM 不支持 支持併發插入的表級鎖 會把索引緩存在內存中,而數據通過操作系統來進行緩存 select, insert 讀寫操作頻繁
MRG_MyISAM 不支持 支持併發插入的表級鎖 分段歸檔,數據倉庫 全局查找過多的場景
InnoDB 支持,事務 ACID 特性 支持MVCC的行級鎖 會同時在內存中緩存索引和數據,從而提高數據庫的運行效率 事務處理
Archive 不支持 行級鎖 日誌記錄,只支持insert, select 需要隨機讀取,更新,刪除

1.MyISAM

MySQL 大部分系統表和臨時表(在排序、分組等操作中,當數量超過一定大小後,由查詢優化器建立的臨時表)還是使用的 MyISAM。MyISAM 存儲引擎表由 MYD 和 MYI 組成。

特性:

1、併發性與鎖級別:非事務性存儲引擎,不支持事務,表級鎖。

在讀取數據時,MyISAM 會對整個表加共享鎖,但是共享鎖之間是不會阻塞的。共享鎖就是多個事務對於同一數據可以共享一把鎖,都能訪問到數據,但是隻能讀不能修改。

MyISAM 表在執行查詢操作的時候,其他進程對該表的讀操作沒有影響,但是寫操作會發生阻塞,直到第一個獲得讀鎖的進程操作完成釋放完讀鎖後,寫操作才能進行。

2、表損壞修復:

check table tablename         //對錶進行檢查
repair table tablename         //對錶進行恢復

3、MyISAM 表支持全文索引和空間函數。

4、MyISAM 表支持數據壓縮,myisampack 命令。

限制:

1、版本 < MySQL 5.0 時默認單表最大文件爲 4GB,如需存儲大表則要修改 MAX_Rows 和 AVG_ROW_LENGTH;版本 >= MySQL 5.0 時默認單表最大文件爲 256TB。

適用場景:

1、非事務型應用;
2、只讀類應用(支持數據壓縮,共享鎖之間是不會阻塞);
3、空間類應用(GPS 數據等)。

2.InnoDB

InnoDB 有自己表空間的概念,InnoDB 使用表空間進行數據存儲。具體存在什麼樣的表空間,則由 innodb_file_per_table 這個參數來決定,如果這個參數爲 ON,則會爲每個 InnoDB 表建立一獨立的表空間(tablename.ibd),爲 OFF 時則會把數據存儲到系統的共享表空間(ibdataX,X代表的是一個從1開始的數字)。

在 MySQL 5.6 之前版本 innodb_file_per_table 默認 OFF,MySQL 5.6 及之後版本默認 ON。

系統表空間和獨立表空間要如何選擇?

1、首先比較一下系統文件對錶空間的管理方式:

在一個繁忙的系統中,系統表空間會不斷增長,一旦磁盤空間出現不足,我們爲了釋放磁盤空間,不得不在系統中刪除大量的無效數據(長期不使用的、日誌類的數據),在刪除數據後,系統表空間並不會縮小,在這種情況下,我們想通過複製文件的方式對數據庫進行備份,由於雖然刪除了數據,但是文件大小並不會改變,這就意味着我們每次刪除時都要浪費很大的空間。

而想要收縮系統表空間的唯一方法就是把整個數據庫中的所有 InnoDB 表導出後,然後刪除 InnoDB 相關的表空間文件,再重啓 MySQL 進行表空間的重建,然後再導入數據,這個過程十分複雜,而且十分耗時。這在一個業務繁忙的生產環境中顯然是不可能做到的。

所以我們使用系統表空間進行數據存儲,所面臨的問題就是無法簡單的收縮文件大小,造成大量的空間浪費,並且會產生大量的磁盤碎片,降低系統性能。

而使用獨立表空間這個問題就很好解決了,當對一個大表中的數據進行清理之後,可以很方便的使用 optimize table 命令對這一個表進行收縮系統文件操作,雖然這種方式也會對一個表進行重建,但是對比整個系統進行重建要快的多,而且不需要重啓數據庫服務器,甚至不會影響正常訪問。

2、比較一下這兩種表空間對IO方面有哪些影響:

對於系統表空間,由於只有一個文件,如果同時對多個表進行數據刷新時,實際上在文件系統層面上是順序進行的,會產生I/O瓶頸。

獨立表空間每一個表都有自己的表空間文件,可以同時向多個文件刷新數據。

到此,可以發現,使用獨立表空間要比使用系統表空間好的多,建議對 InnoDB 使用獨立表空間進行數據存儲。

特性:

1、併發性與鎖級別:事務性存儲引擎,完美支持行級鎖(行級鎖比表級鎖支持更大的併發,吞吐量也會越高),事務 ACID 特性。

爲了實現事務的原子性、一致性、持久性,InnoDB 引用了兩個特殊的日誌類型 Redo Log(重做日誌)和 Undo Log(回滾日誌)。

行級鎖可以最大程度的支持併發;

行級鎖是在存儲引擎層實現的。

2、InnoDB 狀態檢查

show engine innodb status

3、MySQL 5.7 及之後版本,InnoDB 表開始支持全文索引和空間函數。

適用場景:

1、InnoDB 適用於大多數 OLTP 應用。

附一:把原來存儲在系統表空間中的錶轉移到獨立表空間中的方法:

  1. 使用 mysqldump 導出所有數據庫表數據;
  2. 停止 MySQL 服務,修改參數,並刪除 InnoDB 相關文件;
  3. 重啓 MySQL 服務,重建 InnoDB 系統表空間;
  4. 重新導入數據。

附二:鎖

鎖是數據庫系統區別於文件系統的一個重要特性,鎖的主要作用是管理共享資源的併發訪問。

鎖用於實現事務的隔離性。對於未提交的事務,鎖定的數據是無法被其他事務所查詢到的,

鎖的類型 說明 索引和數據存儲
共享鎖(也稱爲讀鎖) 讀鎖是共享的,相互之間是不會被阻塞的,多個線程可以在同一時間讀取同一資源
獨佔鎖(也稱爲寫鎖) 寫鎖是排他的,一個寫鎖會阻塞其他的讀鎖和寫鎖,這是出於數據完整性的考慮,保證了在給定的時間裏,只有一個線程能執行寫入並防止其他用戶讀取正在寫入的資源

看下兼容性:

- 寫鎖 讀鎖
寫鎖 不兼容 不兼容
讀鎖 不兼容 兼容

3.CSV

CSV 存儲引擎可以將 CSV 文件作爲 MySQL 的表來處理,存儲格式就是普通的 CSV 文件,CSV 文件如果存儲在 MyISAM 或 InnoDB 中, 數據文件是不能直接查看的,因爲 MyISAM 和 InnoDB 存儲格式都是以二進制格式進行存儲的。

當我們在 MySQL 中建立了一個 CSV 存儲引擎的表時,我們可以看到三個文件系統中的文件,這三個文件是以表名爲文件名的,表數據存儲在 CSV 爲後綴的文件中,表的元數據(如表狀態、數據量 )存儲在 .CSM 爲後綴的文件中,表結構信息存儲在 .frm 爲後綴的文件中。

特點:

1、以 CSV 格式進行數據存儲,CSV 格式中的每一列都是以逗號分割的,文本數據是以雙引號引起來的;
2、在建表時所有列的定義必須非 NULL 的;
3、不支持索引,索引的主要作用就是優化查詢效率,CSV 不支持索引,那麼每次查詢都會進行全表掃描,不適合大表,不適合在線處理;
4、可以對數據文件直接編輯(其他存儲引擎都是以二進制格式來存儲的,不可編輯);

適用場景:

1、適合做爲數據交換的中間表(可以將 Excel 文件存儲爲 CSV 文件,然後複製到 MySQL 數據目錄下,就能在 MySQL 中打開使用了);

4.Archive

Archive 存儲引擎會緩存所有的寫,並且利用 zlib 算法對錶數據進行進行壓縮,磁盤 I/O 更少。比 MyISAM 和 InnoDB 更加節約磁盤空間。

Archive 表數據存儲在 ARZ 爲後綴的文件中,表結構信息存儲在 .frm 爲後綴的文件中。

特點:

1、Archive 只支持 insert 和 select 操作,支持行級鎖和專用的緩衝區,所以可以實現高併發的插入;
2、只允許在自增 ID 列上建立索引。

適用場景:

1、不需要修改和刪除數據的 日誌和數據採集類應用(無法在 OLTP 應用中使用)。

5.Memory

Memory 存儲引擎也稱爲 HEAP 存儲引擎,數據保存在內存中,Memory 表的數據是易丟失的,一旦 MySQL 被重啓,所有 Memory 表中的數據都會消失(表結構會保留)。

Memory 表數據存儲在內存中,表結構信息存儲在 .frm 爲後綴的文件中。

Memory 的 I/O 效率要比 MyISAM 高很多。

特點:

1、支持 HASH 索引(適合等值查找)和 BTree 索引(適合範圍查找);
2、所有字段都爲固定長度,就算我們在定義表時使用了 varchar(10),在存儲表時還是會使用 char(10);
3、不支持 BLOG 和 TEXT 等大字段;
4、Memory 使用的是表級鎖;
5、Memory 表的最大大小是由 max_heap_table_size 參數決定的,默認 16MB(對已經存在的 Memory 表修改大小是無效的,需要重建表)。

適用場景(Memory 數據易丟失,所以要求數據可再生):

1、用於查找或者是映射表,例如郵編和地區的對應表;
2、用於保存數據分析中產生的中間表;
3、用於緩存週期性聚合數據的結果表;

6.Federated

MySQL 中默認是禁止的,啓動 Federated 需要在 MySQL 啓動時增加 federated 參數。

特點:

1、Federated 存儲引擎提供了訪問遠程 MySQL 服務器上表的方法;
2、本地不存儲數據,數據全部放到遠程服務器上;
3、本地需要保存表結構和遠程服務器的連接信息。

適用場景:

1、偶爾的統計分析及手工查詢。

7.如何選擇正確的存儲引擎

無論是否需要事務支持,只要是不需要使用 InnoDB 不支持的特殊功能外,我們都應該在新的應用中使用 InnoDB 存儲引擎。

如果不想使用 InnoDB,非要從衆多存儲引擎中進行篩選,可以參考以下幾個因素:

1、應用是否需要事務支持?

InnoDB 是目前最穩定的支持事務的存儲引擎,所以還是選擇 InnoDB 吧 。

2、備份?

只有 InnoDB 有在線熱備方案,其他存儲引擎要麼不能在線熱備,要麼是收費的方案,所以還是選擇 InnoDB 吧 。

mysqldump 並不是熱備方案,這裏注意一下。

3、崩潰恢復?

一般而言,MyISAM 發生崩潰後損壞數據的概率要比 InnoDB 高很多。MyISAM 恢復速度也慢,因此即使不需要事務支持,很多時候也要選擇 InnoDB 存儲引擎。

4、存儲引擎的特有特性?

比如很多應用依賴聚集索引進行優化,那麼就要選擇 InnoDB。

有些應用需要使用地理空間搜索,如果使用的是 MySQL 5.7 之前的版本,只能使用 MyISAM 了,如果使用得是 MySQL 5.7 及之後的版本,還是應該使用 InnoDB。

一個數據庫中,除非萬不得已,否則不建議混合使用多種存儲引擎,不然可能會帶來一些複雜的問題和潛在的 bug。比如混合使用 MyISAM 和 InnoDB,一旦在一個事務中對兩種存儲引擎的表進行操作,如果出現回滾,只有 InnoDB 表中的數據會回滾,而 MyISAM 不回滾,這樣就會給應用帶來數據邏輯上的一些問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章