MySQL的儲存引擎是MySQL體系架構中的重要組成部分,也是MySQL體系結構的核心,而插件式的儲存引擎更是它區別於其它資料庫的重要特徵。它處於MySQL體系架構中Server端底層,是底層物理結構的實現,用於將資料以各種不同的技術方式儲存到檔案或記憶體中,不同的儲存引擎具備不同的儲存機制、索引技巧和鎖定水平。常見的MySQL儲存引擎有InnoDB、MyISAM、Memory、Archive等等,它們具備各自的特徵,我們可以根據不同的特定應用來建立對應的儲存引擎表。
在談論不同的儲存引擎之前,我們需要先理解幾個基本概念:
(1) 事務
事務是一組原子性的SQL語句或者說是一個獨立的工作單元,如果資料庫引擎能夠成功對資料庫應用這組SQL語句,那就執行,如果其中有任何一條語句因為崩潰或其它原因無法執行,那麼所有的語句都不會執行。也就是說,事務內的語句,要麼全部執行成功,要麼全部執行失敗。
舉個銀行應用的典型例子:
假設銀行的資料庫有兩張表:支票表和儲蓄表,現在某個客戶A要從其支票帳戶轉移2000元到其儲蓄帳戶,那麼至少需求三個步驟:
a.檢查A的支票帳戶餘額高於2000元;
b.從A的支票帳戶餘額中減去2000元;
c.在A的儲蓄帳戶餘額中增加2000元。
這三個步驟必須要打包在一個事務中,任何一個步驟失敗,則必須要回滾所有的步驟,否則A作為銀行的客戶就可能要莫名損失2000元,就出問題了。這就是一個典型的事務,這個事務是不可分割的最小工作單元,整個事務中的所有操作要么全部提交成功,要么全部失敗回滾,不可能只執行其中一部分,這也是事務的原子性特徵。
(2) 讀鎖定與寫鎖
無論何時,只要有多個SQL需要在同一時刻修改數據,都會產生同時控制的問題。
假設一個公共郵箱,用戶A正在讀取郵箱,同時,用戶B正在刪除郵箱中的某個郵件,會產生什麼結果呢?客戶A可能讀取時會報錯退出,也可能讀取到不一致的郵箱資料。如果把郵箱當作資料庫中的一張表,可見其存在同樣的問題。
解決這類經典問題的方法是並發控制,即在處理並發讀或寫時,可以透過實現一個由兩種類型的鎖組成的鎖定係統來解決問題。這兩種鎖就是共享鎖和排他鎖,也叫讀鎖和寫鎖。
讀鎖是共享的,即相互不阻塞的,多個客戶在同一時刻可以讀取相同資源,互不干擾。寫鎖是排他的,即一個寫鎖會阻塞其它的寫鎖和讀鎖,只有這樣,才能確保給定時間內,只有一個用戶能執行寫入,防止其它用戶讀取正在寫入的同一資源。寫鎖優先權高於讀鎖。
(3) 行鎖和表鎖
實際資料庫系統中每時每刻都在發生鎖定,鎖也是有粒度的,提高共享資源並發行的方式就是讓鎖更有選擇性,盡量只鎖定需要修改的部分數據,而不是所有的資源,因此要進行精確的鎖定。但由於加鎖也需要消耗資源,包括取得鎖、檢查鎖是否解除、釋放鎖等,都會增加系統的開銷。所謂的鎖策略就是要在鎖的開銷和資料的安全性之間尋求平衡,而這種平衡也會影響效能。
每種MySQL儲存引擎都有自己的鎖定策略和鎖定粒度,最常用的兩種重要的鎖定策略分別是表鎖和行鎖。
表鎖是開銷最小的策略,會鎖定整個表,用戶對錶做寫操作時,要先獲得寫鎖,這會阻塞其它用戶對該表的所有讀寫操作。沒有寫鎖時,其它讀取的使用者才能獲得讀鎖,讀鎖之間是不互相阻塞的。行鎖可以最大成都支援並發處理,但也帶來了最大的鎖開銷,它只對指定的記錄加鎖,其它進程還是可以對同一表中的其它記錄進行操作。表級鎖定速度快,但衝突多,行級鎖定衝突少,但速度慢。
了解上述幾個概念,我們就可以分辨不同儲存引擎之間的差異了。
InnoDB儲存引擎
MySQL儲存引擎可分為官方儲存引擎和第三方儲存引擎,InnoDB就是強大的第三方儲存引擎,具備較好的效能和自動崩潰復原特性,目前應用極為廣泛,是目前MySQL儲存引擎中的主流,它在事務型儲存和非事務型儲存中都很流行。
InnoDB儲存引擎支援交易、支援行鎖、支援非鎖定讀取、支援外鍵。
如非特別原因,應用建表時都可以首選考慮使用InnoDB。 InnoDB也是一個非常好的值得花時間去深入學習的儲存引擎,後續計畫專題研究這個儲存引擎,這裡就暫不贅述其詳細內容了。
2. MyISAM儲存引擎
MyISAM儲存引擎是MySQL官方提供的儲存引擎,它在InnoDB出現並完善之前是MySQL儲存引擎的主流,但目前逐漸被淘汰主要因為其不支援事務,這或許源自於MySQL的開發者認為不是所有的應用都需要事務,以便存在了這種不支援事務的儲存引擎。
MyISAM不支援事務,不支援行級鎖,支援表鎖,支援全文索引,最大的缺陷是崩潰後無法安全恢復。
MyISAM因設計簡單,資料以緊密格式存儲,所以某些場景下性能很好,但是它的表鎖又帶來了性能問題,如果你發現所有的查詢都長期處於“Locked”狀態,表鎖就是罪魁禍首了。
因此,對於只讀數據,或者表比較小,可以忍受修復操作的可以依然使
用MyISAM,對於不需要事務的應用,選擇MyISAM存儲引擎,或許可以獲得更高的性能,MySQL自帶的預設的information_schema庫中就存在使用MyISAM儲存引擎的表。
| TRIGGERS | CREATETEMPORARY TABLE `TRIGGERS` ( `TRIGGER_CATALOG` varchar(512) NOT NULLDEFAULT '', `TRIGGER_SCHEMA` varchar(64) NOT NULL DEFAULT'', `TRIGGER_NAME` varchar(64) NOT NULL DEFAULT'', `EVENT_MANIPULATION` varchar(6) NOT NULLDEFAULT '', `EVENT_OBJECT_CATALOG` varchar(512) NOT NULLDEFAULT '', `EVENT_OBJECT_SCHEMA` varchar(64) NOT NULLDEFAULT '', `EVENT_OBJECT_TABLE` varchar(64) NOT NULLDEFAULT '', `ACTION_ORDER` bigint(4) NOT NULL DEFAULT'0', `ACTION_CONDITION` longtext, `ACTION_STATEMENT` longtext NOT NULL, `ACTION_ORIENTATION` varchar(9) NOT NULLDEFAULT '', `ACTION_TIMING` varchar(6) NOT NULL DEFAULT'', `ACTION_REFERENCE_OLD_TABLE` varchar(64)DEFAULT NULL, `ACTION_REFERENCE_NEW_TABLE` varchar(64)DEFAULT NULL, `ACTION_REFERENCE_OLD_ROW` varchar(3) NOTNULL DEFAULT '', `ACTION_REFERENCE_NEW_ROW` varchar(3) NOTNULL DEFAULT '', `CREATED` datetime DEFAULT NULL, `SQL_MODE` varchar(8192) NOT NULL DEFAULT '', `DEFINER` varchar(77) NOT NULL DEFAULT '', `CHARACTER_SET_CLIENT` varchar(32) NOT NULLDEFAULT '', `COLLATION_CONNECTION` varchar(32) NOT NULLDEFAULT '', `DATABASE_COLLATION` varchar(32) NOT NULLDEFAULT '' )ENGINE=MyISAM DEFAULT CHARSET=utf8 |
3. Memory儲存引擎
Memory儲存引擎將表中資料放在記憶體中,因此速度非常快,但因其支援表鎖,所以並發效能較差,最糟糕的是這個儲存引擎在資料庫重新啟動或崩潰之後表中的資料將全部遺失,它只適用於儲存臨時資料的臨時表,MySQL中一般使用這個儲存引擎來存放查詢的中間結果集,如MySQL自帶的預設的information_schema函式庫中就存在較多使用Memory儲存引擎的表。
|TABLES | CREATE TEMPORARY TABLE `TABLES` ( `TABLE_CATALOG` varchar(512) NOT NULL DEFAULT'', `TABLE_SCHEMA` varchar(64) NOT NULL DEFAULT'', `TABLE_NAME` varchar(64) NOT NULL DEFAULT '', `TABLE_TYPE` varchar(64) NOT NULL DEFAULT '', `ENGINE` varchar(64) DEFAULT NULL, `VERSION` bigint(21) unsigned DEFAULT NULL, `ROW_FORMAT` varchar(10) DEFAULT NULL, `TABLE_ROWS` bigint(21) unsigned DEFAULTNULL, `AVG_ROW_LENGTH` bigint(21) unsigned DEFAULTNULL, `DATA_LENGTH` bigint(21) unsigned DEFAULTNULL, `MAX_DATA_LENGTH` bigint(21) unsigned DEFAULTNULL, `INDEX_LENGTH` bigint(21) unsigned DEFAULTNULL, `DATA_FREE` bigint(21) unsigned DEFAULT NULL, `AUTO_INCREMENT` bigint(21) unsigned DEFAULTNULL, `CREATE_TIME` datetime DEFAULT NULL, `UPDATE_TIME` datetime DEFAULT NULL, `CHECK_TIME` datetime DEFAULT NULL, `TABLE_COLLATION` varchar(32) DEFAULT NULL, `CHECKSUM` bigint(21) unsigned DEFAULT NULL, `CREATE_OPTIONS` varchar(255) DEFAULT NULL, `TABLE_COMMENT` varchar(2048) NOT NULLDEFAULT '' ) ENGINE=MEMORY DEFAULT CHARSET=utf8|
4. Archive儲存引擎
Archive儲存引擎置只支援INSERT和SELECT操作,支援行鎖,但本身並不是事務安全的儲存引擎,其最大的優點是其具有較好的壓縮比,壓縮比一般可達到1:10,可以將相同的資料以更小的磁碟空間佔用來儲存。
Archive儲存引擎非常適合儲存歸檔數據,如歷史資料、日誌資訊資料等等,這類資料往往資料量非常大,基本上只有INSERT和SELECT操作,而使用這個儲存引擎可以非常節約磁碟空間。
以某一庫裡的有2.5億筆記錄的歷史表為例:
mysql> select TABLE_ROWSfrom TABLES where TABLE_NAME='history'; +------------+ | TABLE_ROWS | +------------+ | 251755162 | +------------+ 1 row in set (0.01 sec)
原先其預設為InnoDB儲存引擎時,此表大小為12G。
mysql> select concat(round(sum(DATA_LENGTH/1024/1024), 2),'MB')as data from TABLES where TABLE_NAME='history'; +------------+ | data | +------------+ | 12918.88MB | +------------+ 1 row in set (0.00 sec)
當使用Archive儲存引擎重建上述表,並且重新插入相同的資料後,該表的大小變為少於2G,可見該儲存引起具有良好的壓縮比。
其它儲存引擎使用較少,這裡就不談了。
以上就是談談MySQL的儲存引擎的內容,更多相關內容請關注PHP中文網(www.php.cn)!