MySQL管理之緩存機制

緩存機制簡單的說就是緩存sql查詢語句及查詢結果,若是匹配到相同的查詢,服務器則直接從緩存中取到結果。mysql

緩存的數據之因此有用是由於數據沒有發生過改變,若是改變原來的數據則緩存當即失效。redis

因此很是頻繁讀寫小請求的場景,尤爲是對innodb來說 沒有任何意義,關閉反而會提升性能sql

若是在此場景中若是有些場景查詢操做很是大,緩存下來又很是有效:數據庫

mysql在提供緩存方面提供三個分隔:緩存


1、開啓 凡是能緩存則緩存服務器

其中,涉及到用戶私有信息,則不緩存,所以並非全部場景都使用緩存的session

·定義最大緩存數據ide

好比一次查詢數據200M,但不能將這200M所有緩存至內存函數


2、若是不想使用緩存則能夠OFF掉,將最大空間調整爲0性能


3、按需分配 DEMAND

一旦定義爲此類型並非全部查詢都被緩存進來,而是隻有在查詢的時候明確說明緩存的對象,它纔會去緩存


以第一點爲例,要實現內存的高效利用,通常要使用限制的,最小的對象無論數據有多大,則使用內存空間最小分配單元、以及最大緩存對象(以加強緩存有效利用率),在不一樣的場景中緩存的意義不盡相同,那麼對於緩存來說緩存對象和大小也不盡相同

而內存空間確定是有限的,確定不能將全部的數據都放入到內存裏實現緩存效果

所以總體緩存大小都是事先定義好的

若是緩存起不到最佳效果,那麼關閉是最佳解決方案

緩存是本地的,若是有多臺mysql數據庫,那麼查詢會被輪詢到多臺節點上,本地緩存命中率則低得多,那麼則使用公共緩存提升命中率 好比memcache、redis等

可是因爲memcache是在mysql以外的另臺主機上,比起本地緩存性能要差,但因爲是公共緩存又彌補了命中率低的場景,若是隻是單臺mysql則不用考慮公共緩存,用mysql自我管理緩存性能效果會更好


mysql緩存相關服務器變量

與緩存相關的服務器變量

mysql> showglobal variables like '%query_cache%';

+------------------------------+----------+

|Variable_name                | Value    |

+------------------------------+----------+

|have_query_cache             | YES      |

| query_cache_limit            | 1048576  |

|query_cache_min_res_unit     | 4096     |

|query_cache_size             | 16777216 |

|query_cache_type             | ON       |

|query_cache_wlock_invalidate | OFF      |

+------------------------------+----------+

6 rows in set (0.00sec)

參數解釋:

query_cache_size: 查詢緩存的內存總大小,其必須是1024的整數倍,單位爲字節。MySQL啓動時,一次性分配而且初始化這裏指定大小的內存空間。改變其值,MySQL會馬上刪除全部的緩存對象並從新配置其大小及初始化。在性能較強的通用服務器上,查詢緩存可能會成影響服務器擴展的因素,由於它存在成爲服務器資源競爭單點的可能性,在多核心的服務器上甚至還有可能致使服務進程宕掉。

#這個值不能隨意改變,每次改變都會致使mysql將全部緩存對象通通刪除,並從新創建緩存的


query_cache_min_res_unit:存儲緩存的最小內存塊;這個值太小,會減小空間浪費,但會致使更頻繁的內存塊申請操做;設置的過大,會有着更高的碎片產生率。能夠經過(query_cache_size-Qcache_free_memory)/Qcache_queryes_in_cache來得到一個接近理想的值。同時,若是Qcache_free_blocks存在空閒塊,但Qcache_lowmem_prunes的值仍然在增加,則代表碎片過多致使了緩存結果會過早刪除。

#查詢緩存中空閒的內存空間(已經用了多少)

好比已經使用了10M空間,而這10M空間緩存了100個查詢所以

10m 除以100 得出來的則是每一個查詢所佔的空間,而這就是每一個最小可分配的空間


查看與qure相關的統計值

mysql> showglobal status like '%qcache%';

+-------------------------+----------+

|Variable_name           | Value    |

+-------------------------+----------+

|Qcache_free_blocks      | 1        |

|Qcache_free_memory      | 16759696 |

| Qcache_hits             | 0        |

|Qcache_inserts          | 0        |

|Qcache_lowmem_prunes    | 0        |

| Qcache_not_cached       | 9        |

|Qcache_queries_in_cache | 0        |

|Qcache_total_blocks     | 1        |

+-------------------------+----------+

8 rows in set (0.00sec)

參數解釋:

query_cache_type: 是否打開查詢緩存,其可用值有OFF、ON和DEMAND。DEMAND僅在查詢語句中顯式使用SQL_CACHE時纔會使用緩存。

query_cache_limit: MySQL容許緩存的單個緩存對象的最大值。不過,MySQL只有在查詢的全部結果都返回後才知道其是否超出此大小,但其在查詢一開始便會嘗試使用緩存存儲查詢結果,一旦發現超時可緩存最大值則會從緩存中將其刪除,並增大Qcache_not_cached的值。所以,若是知道某查詢的結果會超出可緩存的最大對象,則應該在查詢語句中使用SQL_NO_CACHE。

query_cache_wlock_invalidate:若是某個數據表被其它的鏈接鎖住,是否仍然從查詢緩存中返回結果。

OFF表示返回。

#當查詢的時候,所關係的表被事物鎖住了,有可能事物會更改裏面的值,那咱們仍然會從緩存中緩存結果很確定會有錯誤,那麼這裏意思爲將表鎖住的時候是否還容許在緩存中返回數據,OFF爲容許 ON反而不容許,通常不用關心


返回狀態變量

mysql>  show global status like '%qcache%';

+-------------------------+----------+

|Variable_name           | Value    |

+-------------------------+----------+

|Qcache_free_blocks      | 1        |

|Qcache_free_memory      | 16759696 |

| Qcache_hits             | 0        |

|Qcache_inserts          | 0        |

|Qcache_lowmem_prunes    | 0        |

| Qcache_not_cached       | 9        |

|Qcache_queries_in_cache | 0        |

|Qcache_total_blocks     | 1        |

+-------------------------+----------+

8 rows in set (0.00sec)


參數解釋:

Qcache_free_blocks :在內存中已經分配出去的塊,但塊卻沒有被使用存儲緩存對象的

Qcache_free_memory :沒有被劃分爲塊的

Qcache_hits:命中次數

Qcache_inserts :插入緩存對象

#既然是緩存那麼確定是緩存對象,既然創建了一次緩存對象,就表示向緩存中插入一次數據(緩存對象)


Qcache_not_cached : 查詢語句沒有被緩存的個數

Qcache_queries_in_cache: 保存在緩存中的查詢個數

Qcache_total_blocks : 已經劃分好的塊數


mysql如何查詢緩存

只要啓動了緩存功能,處理任何一個查詢語句都會先去查找緩存


mysql的緩存工做流程

mysql 在創建緩存的時候都會使用鍵值緩存的工做機制

每一個緩存都會有一個"鍵"(key) 緩存的結果是值(value)

將查詢語句當作鍵(key);

將返回結果當作值(value);


當一個查詢語句請求到來的時候查詢鍵裏是否存在這個語句,若是存在則命中,反之。

大部分鍵都是以哈希方式進行對比的,哈希自己是區分字符大小寫,因此若是啓動緩存之後若是想讓緩存命中率提升,必須養成習慣:

統一使用分割,要麼所有大寫,要麼所有小寫,無論誰寫的代碼查詢風格(字母大小寫)必須統一

緩存鍵的生成不包括語句的自己,還包括生成的時間,還包括mysql數據庫的協議版本等

它將衆多元素柔和起來生成鍵,因此若是使用不一樣的客戶端去查詢可能都沒法命中

所以建議使用相同版本的mysql 客戶端接口等


不肯定性的內容

如下信息都爲敏感信息都不緩存的:

·用戶自動函數

·用戶自定義變量

·臨時表

·mysql庫中的系統表

·列級別(某個查詢,用戶都在列級別下都不會被緩存)

·存數函數

·不肯定數據


判斷這些瓶頸,能夠在服務器級別將抓包將查詢語句都抓出來並對其分析使用風格是否統一,再經過這些變量來分析緩存是否發生做用了,若是很低,則不建議使用緩存。


命中率的計算

公式:hits rate = Qcache_hists/(Qcache_hits+Com_select)

#命中的次數除以 (命中的次數 + select語句的個數【只要沒命中 都會增長這個值的,若是命中則增長的是Qcache_hits】) = 大體命中率

下面以咱們單位一臺測試機爲例

mysql> showglobal status like '%qcache%';

+-------------------------+-----------+

|Variable_name           | Value     |

+-------------------------+-----------+

|Qcache_free_blocks      | 692       |

|Qcache_free_memory      | 518259760 |

| Qcache_hits             | 232464273 |

|Qcache_inserts          | 30710570  |

|Qcache_lowmem_prunes    | 0         |

| Qcache_not_cached       | 153693403 |

|Qcache_queries_in_cache | 17670     |

|Qcache_total_blocks     | 36043     |

+-------------------------+-----------+

8 rows in set (0.00sec)

查看com_select

mysql> showsession status like 'com_select';

+---------------+-------+

| Variable_name |Value |

+---------------+-------+

| Com_select    | 3    |

+---------------+-------+

1 row in set (0.00sec)


232464273    /      (232464273 + 1+3 ) 約等於 0.9


通常來說命中率的結果能在30%以上就說明緩存可以帶來幫助,此外還要關注另外的指標:

「命中和寫入」的比率:即Qcache_hits和Qcache_inserts的比值

此比值大於3:1時一般查詢緩存是有效的,能達到甚至大於10:1就更好了


若是咱們發現緩存不太有效,那麼則關閉緩存

若是咱們發現所以碎片才致使命中率低,那麼則可使用碎片整理


mysql> flushquery cache ;

Query OK, 0 rowsaffected (0.57 sec)


可是整理的過程可能致使緩存沒法使用,由於mysql任何查詢都須要先查緩存,而緩存沒法用,因此可能會致使阻塞,相似於卡一段時間,查詢很大的話可能會等待好久,若是訪問很是頻繁的話那麼後果會很是嚴重


清理緩存

reset query cahche

Query OK, 0 rowsaffected (0.57 sec)


有必要的時候,尤爲是對於很是複雜的統計操做,就算是命中率低也要啓動緩存,只是咱們要啓動DEMAND方式,明確指定只緩存的類型



通用緩存優化思路
1
、批量寫入而非單個寫入。批量寫入僅一次性影響緩存。

由於一次插入一行,和每次插入操做都會致使緩存失效一次,而批量插入則使一批失效


2、過大的緩存空間,會使得在大量緩存對象過時失效時致使服務器假死。

緩存不管如何不要太大


3、必要時,使用SQL_CACHE和SQL_NO_CACHE手動控制緩存動做。


4、對寫密集型的場景來講,禁用緩存能夠提升性能。

失效太多,意義則不大了,所以則禁用緩存則能夠提升性能,也就是以前一直強調的

相關文章
相關標籤/搜索