1. 程式人生 > >MySQL架構三:如何選擇合適的儲存引擎

MySQL架構三:如何選擇合適的儲存引擎

上一篇中說到了很多村吃醋引擎,那麼我們應該如何選擇呢,大部分情況下,InnoDB都是正確的選擇,所以Oracle在MySQL5.5版本時終於將InnoDB作為預設的儲存引擎了。對於如何選擇儲存引擎,可以見到的歸納為一句話:除非必須要用到某些InnoDB佈局被的特性,並且沒有其他更好的方式可以實現,否則都應該選擇InnoDB引擎。例如,如果要用到全文索引,建議優先考慮InnoDB加上Sphinx的組合,而不是使用支援全文索引的MyISAM。當然,如果不需要用到InnoDB的特性,同時其他引擎的疼能夠更好的滿足需求,也可以考慮一下其他儲存引擎。例如,如果不在乎可擴充套件能力和併發能力,也不在乎崩毀資料丟失問題,卻對InnoDB佔用的空間過多比較敏感,這種情況下選擇MyISAM就比較合適。

但是,除非萬不得已,不建議使用多種儲存引擎混合使用,否則可能會帶來一系列的問題,以及一些潛在的bug和邊界問題。儲存引擎層和伺服器的互動已經比較複雜,更不用說混合使用多個了。至少,混合儲存對一致性備份和伺服器引數配合都帶來了一些麻煩。

如果應用需要不同的儲存引擎時,請先考慮以下幾個因素。

① 事務:

如果引用需要事務支援,那麼InnoDB或者XtraDB是目前最穩定並且經過驗證的選擇。如果不需要事務,並且主要是select和insert操作,那麼MyISAM是不錯的選擇。一般日之星的應用比較符合這一特性。

② 備份:

備份的需要也會影響儲存引擎的選擇。如果可以定期的關閉伺服器來執行備份,那麼備份的因素可以忽略(但是這種情況應該不存在了吧,反正我沒聽說過定期關伺服器備份的)。反之,如果需要線上熱備份,那麼選擇InnoDB就是基本的要求。

③ 崩潰恢復

資料量比較大的時候,系統崩潰後如何快速的恢復是一個需要考慮的問題。相對而言,MyISAM崩潰後發生損壞的概率比InnoDB要高很多,而且恢復速度也比InnoDB要慢很多。因此,即使不需要事務支援,也有很多人選擇InnoDB,這也是一個重要的原因。

④ 特有的特性

有些應用可能依賴一些村吃醋引擎所獨有的特性或者優化,比如很多應用依賴聚簇索引的優化。另外,MySQL中也只有MyISAM支援地理空間搜尋。如果一個村吃醋引擎擁有一些關鍵的特性,同時又缺乏一些必要的特性,那麼不得不進行折中考慮,或者在架構設計上進行取捨。某些儲存引擎無法直接支援的特性,有時候通過變通也可以滿足需求。

日誌型應用

假設你需要實時的記錄大量的日誌到MySQL中,或者通過Apache的mod_log_sql模組將網站的所有訪問資訊直接記錄到表中(百度有一個訪問者埋點也可以實現這類功能,還不需要自己提供伺服器,有興趣的可以自行了解下,很簡單的配置就可以實現。但是不能儲存到資料庫中)。這一類引用的插入速度有很高的要求,資料庫不能成為瓶頸。MyISAM或者Archive儲存引擎對這類引用比較和二十,因為它們的開銷低,插入速度非常快。

如果需要對記錄的日誌做分析報表,生成報表的SQL很有可能會導致插入效率明顯降低,這時候怎麼辦?

一種解決方法是利用MySQL內建的賦值方案將資料複製一份到備庫,然後在備庫上執行比較消耗時間和CPU的查詢。這樣主庫只用於高效的插入工作,而備份庫上執行查詢頁無需擔心影響到日誌的插入效能。當然也可以在系統負載較低的時候執行報表查詢操作,但應用在不斷變化,如果依賴這個策略可能會導致後續產生問題。

另一種方法,在日誌記錄表的名字中包含年月的資訊,比如web_logs_2019_01或者web_logs_2019_jan。這樣可以在已經沒有插入操作的歷史表上做頻繁的查詢操作,而不會干擾到最新的當前表上的插入操作。

只讀或大部分情況下只讀的表

有些表的資料用於編制類目或者分類清單,這種應用場景是典型的讀多寫少的業務。如果不介意MyISAM的崩潰恢復問題,選用MyISAM引擎是最合適的。不過永遠不要低估崩潰回覆問題的重要性,有些儲存引擎不會保證將資料安全的寫入磁碟中,而許多使用者實際上並不清楚這樣有多大的風險(MyISAM只將資料寫到記憶體中,然後等待作業系統定期將資料刷出到磁碟上)。

我們可以在一個擬真的測試環境下執行應用然後斷電,以此來測試崩潰回覆問題,也可以定期進行演練,以避免真正遇到問題時不知道如何處理。

不要輕易相信MyISAM比InnoDB快這樣的經驗之談,這個結論並不是絕對的。在很多已知的場景中,InnoDB的速度都可以讓MyISAM望塵莫及,尤其是使用到聚簇索引,或者需要訪問的資料都可以放入記憶體的應用。

當涉及到上述型別的應用時,建議採用InnoDB。MyISAM引擎在一開始可能沒有任何問題,但隨著應用壓力的上升,可能會迅速惡化。各種鎖爭用、崩潰資料丟失問題都會隨之而來。

訂單處理

如果涉及訂單處理,那麼支援事務就是必要選項。半完成的訂單是無法用來吸引使用者的。另外一個重要考慮點是儲存引擎對外來鍵的支援情況。InnoDB是訂單處理類應用的最佳選擇(當然,現在我們一般情況都不會在表中指定外來鍵這個屬性了)。

主題討論論壇

對於MySQL使用者,主體討論去屎個很有意思的話題。當前有成百上千的PHP或Perl的免費系統可以支援主題討論。其中大部分的資料庫操作效率都不高,因為它們大多傾向於在一次請求中執行儘可能多的查詢。另外還有部分系統設計為不採用內資料庫,當然也就無法利用到資料庫提供的一些方便的特性。主題討論去一般都有更新計數器,並且會為各個主題計算訪問統計資訊。多數應用只涉及了幾張表來儲存所有的資料,所以核心表的讀寫壓力可能非常大。為保證這些核心表的資料一致性,鎖稱為資源爭用的主要因素。

儘管有這些設計缺陷,但大多數引用在中低負載時可以工作的很好。如果Web站點的規模迅速擴充套件,流量隨之猛增,則資料庫訪問可能變得非常慢。此時一個典型的解決方案是更改為支援更高讀寫的儲存引擎,但有時使用者會發現這麼做反而更慢了。

可能大家並沒有意識到這是由於某些特殊查詢的緣故,例如:

select count(*) from table;

這個問題在於不是所有儲存引擎執行上述查詢都很快,對於MyISAM確實會很快,但其他的可能鬥毆不行。每種村吃醋引擎都能找出類似的例子。

CD-ROM應用

如果要釋出一個基於CD-ROM或者DVD-ROM並且使用MySQL資料檔案的應用,可以考慮使用MyISAM表或者MyISAM壓縮表,這樣表之間可以隔離並且可以在不同介質上相互拷貝。MyISAM壓縮表比未壓縮的表要節約很多空間,但壓縮表是隻讀的。在某些應用中這可能是個大問題。但如果資料放到只讀介質的場景下,壓縮表的只讀特性就不是問題,就沒有理由不採用壓縮表了。

大資料量

什麼樣的資料量算大?我們建立或者管理的很多InnoDB資料庫的資料量在3~5TB或更大,這是單臺機器上的量,不是一個分片的量(shard)。這些系統執行得還不錯,要做到這一點需要合理的選擇硬體,做好物理設計,併為伺服器的I/O瓶頸做好規劃。在這樣的資料量下,如果採用MyISAM,崩潰回覆就是一個噩夢。

如果資料量繼續增長到10TB以上的解,可能就要建立資料倉庫。Infobright是MySQL資料倉庫最成功的解決方案。也有一些大資料庫不適合Infobright,卻可能適合使用TokuDB。