第 3 章 MySQL 存儲引擎簡介 mysql
前言 sql
MyISAM 存儲引擎是 MySQL 默認的存儲引擎,也是目前 MySQL 使用最爲普遍的存儲引擎之一。他的前身就是咱們在 MySQL 發展歷程中所提到的 ISAM,是 ISAM 的升級版本。在 MySQL 最開始發行的時候是 ISAM 存儲引擎,並且實際上在最初的時候,MySQL 甚至是沒有存儲引擎這個概念的。MySQL 在架構上面也沒有像如今這樣的 sql layer 和 storage engine layer 這兩個結構清晰的層次結構,當時無論是代碼自己仍是系統架構,對於開發者來講都很痛苦的一件事情。到後來,MySQL 意識到須要更改架構,將前 端的業務邏輯和後端數據存儲以清晰的層次結構拆分開的同時,對 ISAM 作了功能上面的擴展和代碼的重構,這就是 MyISAM 存儲引擎的由來。 數據庫
MySQL 在 5.1(不包括)以前的版本中,存儲引擎是須要在 MySQL 安裝的時候就必須和 MySQL 一塊兒被編譯並同時被安裝的。也就是說,5.1 以前的 版本中,雖然存儲引擎層和 sql 層的耦合已經很是少了,基本上徹底是經過接口來實現交互,可是這兩層之間仍然是沒辦法分離的,即便在安裝的時候也是同樣。 後端
可是從 MySQL5.1 開始,MySQL AB 對其結構體系作了較大的改造,並引入了一個新的概念:插件式存儲引擎體系結構。MySQL AB 在架構改造的時候,讓存儲引擎層和 sql 層各自更爲獨立,耦合更小,甚至能夠作到在線加載信的存儲引擎,也就是徹底能夠將一個新的存儲引擎加載到一個正在 運行的 MySQL 中,而不影響 MySQL 的正常運行。插件式存儲引擎的架構,爲存儲引擎的加載和移出更爲靈活方便,也使自行開發存儲引擎更爲方便簡單。在 這一點上面,目前尚未哪一個數據庫管理系統可以作到。 安全
MySQL 的插件式存儲引擎主要包括 MyISAM,Innodb,NDB Cluster,Maria,Falcon, Memory,Archive,Merge,Federated 等,其中最著名並且使用最爲普遍的 MyISAM 和 Innodb 兩種存儲引擎。MyISAM 是 MySQL 最先的 ISAM 存儲引擎的升級版本,也是 MySQL 默認的存儲引擎。而 Innodb 實 際上並非 MySQ 公司的,而是第三方軟件公司 Innobase(在 2005 年被 Oracle 公司所收購)所開發,其最大的特色是提供了事務控制等特性, 因此使用者也很是普遍。 服務器
其餘的一些存儲引擎相對來講使用場景要稍微少一些,都是應用於某些特定的場景,如 NDB Cluster 雖然也支持事務,可是主要是用於分佈式環境,屬於一個 share nothing 的分佈式數據庫存儲引擎。Maria 是 MySQL 最新開發(尚未發佈最終的 GA 版本)的對 MyISAM 的升級版存儲引擎,Falcon 是 MySQL 公司自行研發的爲了替代當前的 Innodb 存儲引擎的一款帶有事務等高級特性的數據庫存儲引擎,目前正在研發階段。Memory 存儲引擎全部數 據和索引均存儲於內存中,因此主要是用於一些臨時表,或者對性能要求極高,可是容許在西噢他嗯 Crash 的時候丟失數據的特定場景下。Archive 是一 個數據通過高比例壓縮存放的存儲引擎,主要用於存放過時並且不多訪問的歷史信息,不支持索引。Merge 和 Federated 在嚴格意義上來講,並不能算 做一個存儲引擎。由於 Merge 存儲引擎主要用於將幾個基表 merge 到一塊兒,對外做爲一個表來提供服務,基表能夠基於其餘的幾個存儲引擎。而 Federated 實際上所作的事情,有點相似於 Oracle 的 dblink,主要用於遠程存取其餘 MySQL 服務器上面的數據。 數據結構
MyISAM 存儲引擎的表在數據庫中,每個表都被存放爲三個以表名命名的物理文件。首先確定會有任何存儲引擎都不可缺乏的存放表結構定義信息的.frm 文件,另外還有.MYD 和.MYI 文件,分別存放了表的數據(.MYD)和索引數據(.MYI)。每一個表都有且僅有這樣三個文件作爲 MyISAM 存儲類型的表的存儲,也就是說無論這個表有多少個索引,都是存放在同一個.MYI 文件中。 架構
MyISAM 支持如下三種類型的索引: 併發
一、B-Tree 索引 分佈式
B-Tree 索引,顧名思義,就是全部的索引節點都按照 balance tree 的數據結構來存儲,全部的索引數據節點都在葉節點。
二、R-Tree 索引
R-Tree 索引的存儲方式和 b-tree 索引有一些區別,主要設計用於爲存儲空間和多
維數據的字段作索引,因此目前的 MySQL 版原本說,也僅支持 geometry 類型的字段做索引。
三、Full-text 索引
Full-text 索引就是咱們長說的全文索引,他的存儲結構也是 b-tree。主要是爲了解決在咱們須要用 like 查詢的低效問題。
MyISAM 上面三種索引類型中,最常用的就是 B-Tree 索引了,偶爾會使用到 Fulltext,可是 R-Tree 索引通常系統中都是不多用到的。另外 MyISAM 的 B-Tree 索引有一個較大的限制,那就是參與一個索引的全部字段的長度之和不能超過 1000 字節。
雖然每個 MyISAM 的表都是存放在一個相同後綴名的.MYD 文件中,可是每一個文件的存放格式實際上可能並非徹底同樣的,由於 MyISAM 的數據存放格式是分爲靜態(FIXED)固定長度、動態(DYNAMIC)可變長度以及壓縮(COMPRESSED)這三種格式。固然三種格式中是否壓縮是徹底能夠任由咱們本身選擇的,能夠在建立表的時候經過 ROW_FORMAT 來指定 {COMPRESSED | DEFAULT},也能夠經過 myisampack 工具來進行壓縮,默認是不壓縮的。而在非壓縮的狀況下,是靜態仍是動態,就和咱們表中個字段的定義相關了。只要表中有可變長度類型的字段存在,那麼該表就確定是 DYNAMIC 格式的,若是沒有任何可變長度的字段,則爲 FIXED 格式,固然,你也能夠經過 alter table 命令,強行將一個帶有 VARCHAR 類型字段的 DYNAMIC 的錶轉換爲 FIXED,可是所帶來的結果是原 VARCHAR 字段類型會被自動轉換成 CHAR 類型。相反若是將 FIXED 轉換爲 DYNAMIC,也會將 CHAR 類型字段轉換爲 VARCHAR 類型,因此你們手工強行轉換的操做必定要謹慎。
MyISAM 存儲引擎的表是否足夠可靠呢?在 MySQL 用戶參考手冊中列出在遇到以下狀況的時候可能會出現表文件損壞:
MyISAM 存儲引擎的某個表文件出錯以後,僅影響到該表,而不會影響到其餘表,更不會影響到其餘的數據庫。若是咱們的出據苦正在運行過程當中發現某個 MyISAM 表出現問題了,則能夠在線經過 check table 命令來嘗試校驗他,並能夠經過 repair table 命令來嘗試修復。在數據庫關閉狀態下,咱們也能夠經過 myisamchk 工具來對數據庫中某個(或某些)表進行檢測或者修復。不過強烈建議不到萬不得已不要輕易對錶進行修復操做,修復以前儘可能作好可能的備份工做,以避免帶來沒必要要的後果。
另外 MyISAM 存儲引擎的表理論上是能夠被多個數據庫實例同時使用同時操做的,可是不管是咱們都不建議這樣作,並且 MySQL 官方的用戶手冊中也有提到,建議儘可能不要在多個 mysqld 之間共享 MyISAM 存儲文件。
在 MySQL 中使用最爲普遍的除了 MyISAM 以外,就非 Innodb 莫屬了。Innodb 作爲第三方公司所開發的存儲引擎,和 MySQL 遵照相同的開源 License 協議。
Innodb 之因此能如此受寵,主要是在於其功能方面的較多特色:
Innodb 在功能方面最重要的一點就是對事務安全的支持,這無疑是讓 Innodb 成爲 MySQL 最爲流行的存儲引擎之一的一個很是重要緣由。並且實現了 SQL92 標準所定義的全部四個級別(READ UNCOMMITTED,READ COMMITTED,REPEATABLE READ 和 SERIALIZABLE)。對事務安全的支持,無疑讓不少以前由於特殊業務要求而不得不放棄使用 MySQL 的用戶轉向支持
MySQL,以及以前對數據庫選型持觀望態度的用戶,也大大增長了對 MySQL 好感。
Innodb 在事務支持的同時,爲了保證數據的一致性已經併發時候的性能,經過對 undo 信息,實現了數據的多版本讀取。
Innodb 改變了 MyISAM 的鎖機制,實現了行鎖。雖然 Innodb 的行鎖機制的實現是經過索引來完成的,但畢竟在數據庫中 99%的 SQL 語句都是要使用索引來作檢索數據的。因此,行鎖定機制也無疑爲 Innodb 在承受高併發壓力的環境下加強了不小的競爭力。
Innodb 實現了外鍵引用這一數據庫的重要特性,使在數據庫端控制部分數據的完整性成爲可能。雖然不少數據庫系統調優專家都建議不要這樣作,可是對於很多用戶來講在數據庫端加如外鍵控制可能仍然是成本最低的選擇。
除了以上幾個功能上面的亮點以外,Innodb 還有不少其餘一些功能特點經常帶給使用者不小的驚喜,同時也爲 MySQL 帶來了更多的客戶。
在物理存儲方賣弄,Innodb 存儲引擎也和 MyISAM 不太同樣,雖然也有.frm 文件來存放表結構定義相關的元數據,可是表數據和索引數據是存放在一塊兒的。至因而每一個表單獨存放仍是全部表存放在一塊兒,徹底由用戶來決定(經過特定配置),同時還支持符號連接。
Innodb 的物理結構分爲兩大部分: 一、數據文件(表數據和索引數據)
存放數據表中的數據和全部的索引數據,包括主鍵和其餘普通索引。在 Innodb 中,存在了表空間(tablespace)這樣一個概念,可是他和 Oracle 的表空間又有較大的不一樣。首先,Innodb 的表空間分爲兩種形式。一種是共享表空間,也就是全部表和索引數據被存放在同一個表空間(一個或多個數據文件)中,經過 innodb_data_file_path 來指定,增長數據文件須要停機重啓。 另一種是獨享表空間,也就是每一個表的數據和索引被存放在一個單獨的.ibd 文件中。
雖然咱們能夠自行設定使用共享表空間仍是獨享表空間來存放咱們的表,可是共享表空間都是必須存在的,由於 Innodb 的 undo 信息和其餘一些元數據信息都是存放在共享表空間裏面的。共享表空間的數據文件是能夠設置爲固定大小和可自動擴展大小兩種形式的,自動擴展形式的文件能夠設置文件的最大大小和每次擴展量。在建立自動擴展的數據文件的時候,建議你們最好加上最大尺寸的屬性,一個緣由是文件系統自己是有必定大小限制的(可是 Innodb 並不知道),還有一個緣由就是自身維護的方便。另外,Innodb 不只可使用文件系統,還可使用原始塊設備,也就是咱們常說的裸設備。
當咱們的文件表空間快要用完的時候,咱們必需要爲其增長數據文件,固然,只有共享表 空 間 有 此 操 做 。 共 享 表 空 間 增 加 數 據 文 件 的 操 做 比 較 簡 單 , 只 需 要 在 innodb_data_file_path 參數後面按照標準格式設置好文件路徑和相關屬性便可,不過這裏有一點須要注意的,就是 Innodb 在建立新數據文件的時候是不會建立目錄的,若是指定目錄不存在,則會報錯並沒有法啓動。另一個較爲使人頭疼的就是 Innodb 在給共享表空間增長數據文件以後,必需要重啓數據庫系統才能生效,若是是使用裸設備,還須要有兩次重啓 。
這也是我一直不太喜歡使用共享表空間而選用獨享表空間的緣由之一。
二、日誌文件
Innodb 的日誌文件和 Oracle 的 redo 日誌比較相似,一樣能夠設置多個日誌組(最少 2 個),一樣採用輪循策略來順序的寫入,甚至在老版本中還有和 Oracle 同樣的日誌歸檔特性 。若是你的數據庫中有建立了 Innodb 的表,那麼千萬別所有刪除 innodb 的日誌文件,由於極可能就會讓你的數據庫 crash,沒法啓動,或者是丟失數據。
因爲 Innodb 是事務安全的存儲引擎,因此係統 Crash 對他來講並不能形成很是嚴重的損失,因爲有 redo 日誌的存在,有 checkpoint 機制的保護,Innodb 徹底能夠經過 redo 日誌將數據庫 Crash 時刻已經完成但尚未來得及將數據寫入磁盤的事務恢復,也可以將全部部分完成並已經寫入磁盤的未完成事務回滾並將數據還原。
Innodb 不只在功能特性方面和 MyISAM 存儲引擎有較大區別,在配置上面也是單獨處理的。在 MySQL 啓動參數文件設置中,Innodb 的全部參數基本上都帶有前綴"innodb_",不管是 innodb 數據和日誌相關,仍是其餘一些性能,事務等等相關的參數都是同樣。和全部 Innodb 相關的系統變量同樣,全部的 Innodb 相關的系統狀態值也一樣所有以"Innodb_" 前綴。固然,咱們也徹底能夠僅僅經過一個參數(skip-innodb)來屏蔽 MySQL 中的 Innodb 存儲引擎,這樣即便咱們在安裝編譯的時候將 Innodb 存儲引擎安裝進去了,使用者也沒法建立 Innodb 的表。
NDB 存儲引擎也叫 NDB Cluster 存儲引擎,主要用於 MySQL Cluster 分佈式集羣環境,
Cluster 是 MySQL 從 5.0 版本纔開始提供的新功能。這部分咱們可能並不只僅只是介紹 NDB 存儲引擎,由於離開了 MySQL CLuster 整個環境,NDB 存儲引擎也將失去太多意義。 因此這一節主要是介紹一下 MySQL Cluster 的相關內容。
簡單的說,Mysql Cluster 實際上就是在無共享存儲設備的狀況下實現的一種內存數據庫 Cluster 環境,其主要是經過 NDB Cluster(簡稱 NDB)存儲引擎來實現的。
通常來講,一個 Mysql Cluster 的環境主要由如下三部分組成: a) 負責管理各個節點的 Manage 節點主機:
管理節點負責整個 Cluster 集羣中各個節點的管理工做,包括集羣的配置,啓動關閉各節點,以及實施數據的備份恢復等。管理節點會獲取整個 Cluster 環境中各節點的狀態和錯誤信息,而且將各 Cluster 集羣中各個節點的信息反饋給整個集羣中其餘的全部節點。因爲管理節點上保存在整個 Cluster 環境的配置,同時擔任了集羣中各節點的基本溝通工做,因此他必須是最早被啓動的節點。
NDB 是一個內存式存儲引擎也就是說,他會將全部的數據和索引數據都 load 到內存中 ,但也會將數據持久化到存儲設備上。不過,最新版本,已經支持用戶本身選擇數據能夠不所有 Load 到內存中了,這對於有些數據量太大或者基於成本考慮而沒有足夠內存空間來存放全部數據的用戶來講的確是一個大好消息。
NDB 節點主要是實現底層數據存儲的功能,保存 Cluster 的數據。每個 NDB 節點保存完整數據的一部分(或者一份完整的數據,視節點數目和配置而定),在 MySQL CLuster 裏面叫作一個 fragment。而每個 fragment,正常狀況來說都會在其餘的主機上面有一份(或者多分)徹底相同的鏡像存在。這些都是經過配置來完成的,因此只要配置得當,Mysql Cluster 在存儲層不會出現單點的問題。通常來講,NDB 節點被組織成一個一個的 NDB Group,一個 NDB Group 實際上就是一組存有徹底相同的物理數據的 NDB 節點羣。
上面提到了 NDB 各個節點對數據的組織,可能每一個節點都存有所有的數據也可能只保存一部分數據,主要是受節點數目和參數來控制的。首先在 Mysql Cluster 主配置文件(在管理節點上面,通常爲 config.ini)中,有一個很是重要的參數叫 NoOfReplicas,這個參數指定了每一份數據被冗餘存儲在不一樣節點上面的份數,該參數通常至少應該被設置成 2,也只須要設置成 2 就能夠了。由於正常來講,兩個互爲冗餘的節點同時出現故障的機率仍是很是小的,固然若是機器和內存足夠多的話,也能夠繼續增大。一個節點上面是保存全部的數據仍是一部分數據,還受到存儲節點數目的限制。NDB 存儲引擎首先保證 NoOfReplicas 參數配置的要求對數據冗餘,來使用存儲節點,而後再根據節點數目將數據分段來繼續使用多餘的 NDB 節點,分段的數目爲節點總數除以 NoOfReplicas 所得。
MySQL Cluster 自己所包含的內容很是之多,出於篇幅考慮,這裏暫時不作很深刻的介紹,在本書的架構設計部分的高可用性設計一章中將會有更爲詳細的介紹與實施細節,你們也能夠經過 MySQL 官方文檔來進一步瞭解部分細節。
MERGE 存儲引擎,在 MySQL 用戶手冊中也提到了,也被你們認識爲 MRG_MyISAM 引擎。
Why?由於 MERGE 存儲引擎能夠簡單的理解爲其功能就是實現了對結構相同的 MyISAM 表 ,經過一些特殊的包裝對外提供一個單一的訪問入口,以達到減少應用的複雜度的目的。要建立
MERGE 表,不只僅基表的結構要徹底一致,包括字段的順序,基表的索引也必須徹底一致。
MERGE 表自己並不存儲數據,僅僅只是爲多個基表提供一個贊成的存儲入口。因此在建立 MERGE 表的時候,MySQL 只會生成兩個較小的文件,一個是.frm 的結構定義文件,還有一
個.MRG 文件,用於存放參與 MERGE 的表的名稱(包括所屬數據庫 schema)。之因此須要有所屬數據庫的 schema,是由於 MERGE 表不只能夠實現將 Merge 同一個數據庫中的表,還能夠
Merge 不一樣數據庫中的表,只要是權限容許,而且在同一個 mysqld 下面,就能夠進行 Merge。
MERGE 表在被建立以後,仍然能夠經過相關命令來更改底層的基表。
MERGE 表不只能夠提供讀取服務,也能夠提供寫入服務。要讓 MERGE 表提供可 INSERT 服務,必須在在表被建立的時候就指明 INSERT 數據要被寫入哪個基表,能夠經過 insert_method 參數來控制。若是沒有指定該參數,任未嘗試往 MERGE 表中 INSERT 數據的操做,都會出錯。此外,沒法經過 MERGE 表直接使用基表上面的全文索引,要使用全文索引 ,必須經過基表自己的存取才能實現。
Memory 存儲引擎,經過名字就很容易讓人知道,他是一個將數據存儲在內存中的存儲引擎。Memory 存儲引擎不會將任何數據存放到磁盤上,僅僅存放了一個表結構相關信息的.frm 文件在磁盤上面。因此一旦 MySQL Crash 或者主機 Crash 以後,Memory 的表就只剩下一個結構了。Memory 表支持索引,而且同時支持 Hash 和 B-Tree 兩種格式的索引。因爲是存放在內存中,因此 Memory 都是按照定長的空間來存儲數據的,並且不支持 BLOB 和 TEXT 類型的字段。Memory 存儲引擎實現頁級鎖定。
既然全部數據都存放在內存中,那麼他對內存的消耗量是可想而知的。在 MySQL 的用戶手冊上面有這樣一個公式來計算 Memory 表實際須要消耗的內存大小:
SUM_OVER_ALL_BTREE_KEYS(max_length_of_key + sizeof(char*) * 4)
+ SUM_OVER_ALL_HASH_KEYS(sizeof(char*) * 2)
+ ALIGN(length_of_row+1, sizeof(char*))
BDB 存儲引擎全稱爲 BerkeleyDB 存儲引擎,和 Innodb 同樣,也不是 MySQL 本身開發實現的一個存儲引擎,而是由 Sleepycat Software 所提供,固然,也是開源存儲引擎,一樣支持事務安全。
BDB 存儲引擎的數據存放也是每一個表兩個物理文件,一個.frm 和一個.db 的文件,數據和索引信息都是存放在.db 文件中。此外,BDB 爲了實現事務安全,也有本身的 redo 日 志 ,和 Innodb 同樣,也能夠經過參數指定日誌文件存放的位置。在鎖定機制方面,BDB 和 Memory 存儲引擎同樣,實現頁級鎖定。
因爲 BDB 存儲引擎實現了事務安全,那麼他確定也須要有本身的 check point 機 制 。BDB 在每次啓動的時候,都會作一次 check point,而且將以前的全部 redo 日誌清空。在運行過程當中,咱們也能夠經過執行 flush logs 來手工對 BDB 進行 check point 操做。
FEDERATED 存儲引擎所實現的功能,和 Oracle 的 DBLINK 基本類似,主要用來提供對遠程 MySQL 服務器上面的數據的訪問藉口。若是咱們使用源碼編譯來安裝 MySQL,那麼必須手工指定啓用
FEDERATED 存儲引擎才行,由於 MySQL 默認是不起用該存儲引擎的。
當咱們建立一個 FEDERATED 表的時候,僅僅在本地建立了一個表的結構定義信息的文件而已,全部數據均實時取自遠程的 MySQL 服務器上面的數據庫。
當咱們經過 SQL 操做 FEDERATED 表的時候,實現過程基本以下: a、SQL 調用被本地發佈 b、MySQL 處理器 API(數據以處理器格式) c、MySQL 客戶端 API(數據被轉換成 SQL 調用)
ARCHIVE 存儲引擎主要用於經過較小的存儲空間來存放過時的不多訪問的歷史數據。 ARCHIVE 表不支持索引,經過一個.frm 的結構定義文件,一個.ARZ 的數據壓縮文件還有一個.ARM 的 meta 信息文件。因爲其所存放的數據的特殊性,ARCHIVE 表不支持刪除,修改操做,僅支持插入和查詢操做。鎖定機制爲行級鎖定。
BLACKHOLE 存儲引擎是一個很是有意思的存儲引擎,功能恰如其名,就是一個"黑洞"。就像咱們 unix 系統下面的"/dev/null"設備同樣,無論咱們寫入任何信息,都是有去無回 。那麼 BLACKHOLE 存儲引擎對咱們有什麼用呢?在我最初接觸 MySQL 的時候我也有過一樣的疑問,不知道 MySQL 提供這樣一個存儲引擎給咱們的用意爲什麼?可是後來在又一次數據的遷移過程當中,正是 BLACKHOLE 給我帶來了很是大的功效。在那次數據遷移過程當中,因爲數據須要通過一箇中轉的 MySQL 服務器作一些相關的轉換操做,而後再經過複製移植到新的服務器上面。可當時我沒有足夠的空間來支持這個中轉服務器的運做。這時候就顯示出 BLACKHOLE 的功效了,他不會記錄下任何數據,可是會在 binlog 中記錄下全部的 sql。而這些 sql 最終都是會被複制所利用,並實施到最終的 slave 端。
MySQL 的用戶手冊上面還介紹了 BLACKHOLE 存儲引擎其餘幾個用途以下: a、SQL 文件語法的驗證。
CSV 存儲引擎實際上操做的就是一個標準的 CSV 文件,他不支持索引。起主要用途就是你們有些時候可能會須要經過數據庫中的數據導出成一份報表文件,而 CSV 文件是不少軟件都支持的一種較爲標準的格式,因此咱們能夠經過先在數據庫中創建一張 CVS 表,而後將生成的報表信息插入到該表,便可獲得一份 CSV 報表文件了。
多存儲引擎是 MySQL 有別於其餘數據庫管理軟件的最大特點,不一樣的存儲引擎有不一樣的特色,能夠應對不一樣的應用場景,這讓咱們在實際的應用中能夠根據不一樣的應用特色來選擇最有利的存儲引擎,給了咱們足夠的靈活性。經過這一章對 MySQL 各個存儲引擎的初步瞭解,我想各位讀者朋友應該已經對 MySQL 的主要存儲引擎有了必定的認識,在後續的章節中對於一些經常使用的存儲引擎還會有更爲深刻的介紹。