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)!