參考
陳Chuan大佬系列,簡書過500贊的博客
http://www.itdecent.cn/p/d7665192aaaf
Mysql緩存原理
https://blog.csdn.net/qzqanzc/article/details/80418125
https://blog.csdn.net/songjianyue12345/article/details/77340168
Mysql的緩存功能
https://blog.csdn.net/songjianyue12345/article/details/77340168
對于一個并沒有那么復(fù)雜的系統(tǒng),但是某幾個表特別大的時候,緩存是一個很實用的一個功能,是SQL優(yōu)化和查詢提速的常用操作,開啟Mysql自帶的此功能,實現(xiàn)查詢結(jié)果緩存的同時,緩存失效的維護由數(shù)據(jù)庫自己完成,而不像一般的Spring框架要通過代碼或者過期自動超時來維護。當然,這個功能并不適合海量數(shù)據(jù)緩存,Mysql緩存還設(shè)計內(nèi)存碎片的問題,需要定期手動維護。也不適合高性能數(shù)據(jù)緩存的業(yè)務(wù)場景,專業(yè)的緩存還是要用redis、ehcache來處理。
mysql緩存維護的方式簡單暴力,只要查詢涉及的表中有更新操作,就清空該表相關(guān)的所有緩存(多表關(guān)聯(lián)查詢就更嚴重,但凡有一個表更新了,該SQL緩存就失效了),基于這種邏輯就可以保證所有的數(shù)據(jù)是最新的,不用涉及超時時間的概念。當然使用緩存功能會增加一部分數(shù)據(jù)的開銷,來實現(xiàn)熱點數(shù)據(jù)的緩存快速查詢,從而提升用戶的體驗。
結(jié)合業(yè)務(wù)場景,一般都是開啟DEMAND模式,使用在不需要頻繁變動的表上。頻繁變更的表上如果開啟緩存功能,會影響數(shù)據(jù)庫的維護性能。
- MySQL將緩存存放在一個引用表(不要理解成table,可以認為是類似于HashMap的數(shù)據(jù)結(jié)構(gòu)),通過一個哈希值索引,這個哈希值通過查詢本身、當前要查詢的數(shù)據(jù)庫、客戶端協(xié)議版本號等一些可能影響結(jié)果的信息計算得來。所以兩個查詢在任何字符上的不同(例如:空格、注釋),都會導(dǎo)致緩存不會命中。
- 既然是緩存,肯定是保存在內(nèi)存當中,重啟后會失效。
- 如果這個表修改了,那么使用這個表中的所有緩存將不再有效,查詢緩存值得相關(guān)條目將被清空。表中得任何改變是值表中任何數(shù)據(jù)或者是結(jié)構(gòu)的改變,包括insert,update,delete,truncate,alter table,drop table或者是drop database 包括那些映射到改變了的表的使用merge表的查詢,
- 對于頻繁更新的表,查詢緩存不合適,對于一些不變的數(shù)據(jù)且有大量相同sql查詢的表,查詢緩存會節(jié)省很大的性能
- 緩存不可用的情況:
- 使用緩存必須確保SQL完全一樣,SQL字母大小寫、空格、注釋等都會導(dǎo)致緩存匹配失敗
- SQL中包含不確定的函數(shù),則緩存功能不可用,比如 now(),CURRENT_DATE() ,比如 select * from wx_ib where war_exp_date=CURRENT_DATE();
- 緩存要查詢的表,正在被另外一個事務(wù)修改數(shù)據(jù)
- 注意事項:
- 比較遺憾的是,緩存清空的機制是目標表有任何更新操作,都會導(dǎo)致該表的所有緩存失效,而不能實現(xiàn)行級別的緩存清空
- 事務(wù)隔離級別為:Serializable情況下,所有查詢語句都不能緩存;
PK 其它緩存
- Mysql清除緩存的方式太過暴力,只要緩存查詢的SQL查詢,涉及到的表有更新操作,那么這個緩存查詢就會失效,無法實現(xiàn)行級的緩存清除
- Spring集成第三方緩存工具和相關(guān)注解,可以實現(xiàn)更靈活的緩存處理,比如清除某個key的緩存,而不是整個表的緩存都清除
- 專業(yè)的緩存工具一般都支持,緩存數(shù)據(jù)持久化、FIFO策略等功能
Mysql緩存功能的開啟
- 配置和啟動:修改mysql安裝目錄下面的my.ini文件,添加query_cache_type=2(開啟DEMAD模式),然后重啟mysql(windows重啟的話,admin模式 net stop mysql ,net start mysql。 linux: service mysql restart)
緩存開啟的設(shè)置:query_cache_type - OFF: 關(guān)閉,默認 值為0
- ON: 總是打開,值為1
- DEMAND: 只有明確寫了SQL_CACHE的查詢才會進入緩存,值為2
- query_cache_type 這個參數(shù)windows下必須在my.ini文件里配置,默認是0 表示關(guān)閉緩存功能,設(shè)置為1 表示開啟全部的緩存,設(shè)置為2表示DEMAND模式
- query_cache_limit 限制查詢緩存區(qū)最大能緩存的查詢記錄集,可以避免一個大的查詢記錄集占去大量的內(nèi)存區(qū)域,而且往往小查詢記錄集是最有效的緩存記錄集,默認設(shè)置為1M,建議修改為16k~1024k之間的值域,不過最重要的是根據(jù)自己應(yīng)用的實際情況進行分析、預(yù)估來設(shè)置;,支持在線配置,立即生效
- query_cache_min_res_unit 設(shè)置查詢緩存分配內(nèi)存的最小單位,要適當?shù)卦O(shè)置此參數(shù),可以做到為減少內(nèi)存塊的申請和分配次數(shù),但是設(shè)置過大可能導(dǎo)致內(nèi)存碎片數(shù)值上升。默認值為4K,建議設(shè)置為1k~16K
- Qcache_hits 查看命中緩存查詢的次數(shù)
#my.ini里面配置
query_cache_type=2
set global query_cache_limit = 1024 * 1024 * 5;
show status like '%qcache_hits%';
- 緩存的使用: SQL_NO_CACHE/ SQL_CACHE
select SQL_CACHE * from wx_ib where product_id=1246 and war_exp_date='2016-08-07';
select SQL_NO_CACHE * from wx_ib where product_id=1246 and war_exp_date='2016-08-07';
緩存開啟的時機:
- 緩存開啟帶來的必要開銷:
- 該表發(fā)生事務(wù)操作的時候,都要清空相關(guān)的緩存
- 在query_cache_type為ON的模式下,該數(shù)據(jù)庫全部的查詢都會先嘗試緩存,不管該查詢是否會有熱點數(shù)據(jù),而實際的業(yè)務(wù)場景并不是這樣。所以更建議使用DEMAND模式。
- 開啟緩存后,所有的Query完成之后,都要把查詢結(jié)果插入到緩存當中