1. 程式人生 > 其它 >MySQL快取機制詳解

MySQL快取機制詳解

眾所周知,快取的設定是所有現代計算機系統發揮高效能的重要因素之一。對於MySQL資料庫來說,也是得益於MySQL快取機制,才能夠提高MySQL資料庫的效能,減少資料的記憶體佔比。

MySQL快取機制簡單的說就是快取SQL文字及查詢結果,如果執行相同的SQL,伺服器直接從快取中取到結果,而不需要再去解析和執行SQL。如果表更改了,那麼使用這個表的所有快取查詢將不再有效,查詢快取中值相關條目被清空。這裡的更改指的是表中任何資料或是結構發生改變,包括INSERT、UPDATE、 DELETE、TRUNCATE、ALTER TABLE、DROP TABLE或DROP DATABASE等,也包括那些對映到改變了的表使用MERGE表的查詢。顯然,這對於頻繁更新的表,查詢快取是不適合的,而對於一些不常改變資料且有大量相同SQL查詢的表,查詢快取會節約很大的效能。

一、MySQL快取規則

1.開啟了快取,MySQL Server會自動將查詢語句和結果集返回到記憶體,下次再查直接從記憶體中取;

2.快取的結果是通過sessions共享的,所以一個client查詢的快取結果,另一個client也可以使用。

3.MySQL Query Cache內容為 select 的結果集, cache 使用完整的SQL字串做 key, 並區分大小寫,空格等。即兩個SQL必須完全一致才會導致cache命中。即檢查查詢快取時,MySQL Server不會對SQL做任何處理,它精確的使用客戶端傳來的查詢,只要字元大小寫或註釋有點不同,查詢快取就認為是不同的查詢;

4.prepared statement永遠不會cache到結果,即使引數完全一樣。在 5.1 之後會得到改善。

5.where條件中如包含任何一個不確定的函式將永遠不會被cache, 比如current_date, now等。

6.date 之類的函式如果返回是以小時或天級別的,最好先算出來再傳進去。

select * from foo where date1=current_date -- 不會被 cache

select * from foo where date1='2008-12-30' -- 被cache, 正確的做法

7.太大的result set不會被cache (< query_cache_limit)

8.MySQL快取在分庫分表環境下是不起作用的

9.執行SQL裡有觸發器,自定義函式時,MySQL快取也是不起作用的

二、快取失效

在表的結構或資料發生改變時,查詢快取中的資料不再有效。如INSERT、UPDATE、 DELETE、TRUNCATE、ALTER TABLE、DROP TABLE或DROP DATABASE會導致快取資料失效。所以查詢快取適合有大量相同查詢的應用,不適合有大量資料更新的應用。

一旦表資料進行任何一行的修改,基於該表相關cache立即全部失效。

  • 手動清理快取

手動清理快取可以使用下面三個SQL

1.FLUSH QUERY CACHE; #清理查詢快取記憶體碎片

2.RESET QUERY CACHE;#從查詢快取中移除所有查詢

3.FLUSH TABLES; #關閉所有開啟的表,同時該操作會清空查詢快取中的內容

四、快取機制中的記憶體管理

MySQL Query Cache 使用記憶體池技術,自己管理記憶體釋放和分配,而不是通過作業系統。記憶體池使用的基本單位是變長的block, 用來儲存型別、大小、資料等資訊;一個result set的cache通過連結串列把這些block串起來。block最短長度為query_cache_min_res_unit。

當伺服器啟動的時候,會初始化快取需要的記憶體,是一個完整的空閒塊。當查詢結果需要快取的時候,先從空閒塊中申請一個數據塊為引數query_cache_min_res_unit配置的空間,即使快取資料很小,申請資料塊也是這個,因為查詢開始返回結果的時候就分配空間,此時無法預知結果多大。

分配記憶體塊需要先鎖住空間塊,所以操作很慢,MySQL會盡量避免這個操作,選擇儘可能小的記憶體塊,如果不夠,繼續申請,如果儲存完時有空餘則釋放多餘的。

但是如果併發的操作,餘下的需要回收的空間很小,小於query_cache_min_res_unit,不能再次被使用,就會產生碎片。

MySQL快取機制從某種程度上來說,和其他的系統快取有類似的作用:提高系統的效能,釋放系統的記憶體空間。但MySQL快取機制又有著其獨特的特性,對於資料重複性比較高的查詢有著顯著的作用。