目錄
1. MySQL緩存簡介
1. MySQL緩存機制說明
MySQL緩存機制即緩存sql 文本及緩存結果,用KV形式保存再服務器內存中,如果運行相同的sql,服務器直接從緩存中去獲取結果,不需要再去解析、優化、執行sql
2. MySQL緩存失效
- 在表的結構或數據發生改變時,查詢緩存中的數據不再有效,查詢緩存值的相關條目將被清空
- INSERT、UPDATE、 DELETE、TRUNCATE、ALTER TABLE、DROP TABLE或DROP DATABASE會導致緩存數據失效
3. 使用場景
- 對於頻繁更新的表,查詢緩存不合適
- 對於一些不變的數據且有大量相同sql查詢的表,查詢緩存可以大大提高查詢的性能
2. 命中條件
- 緩存的數據結構是hash表
- 以SQL、數據庫名和客戶端協議等作為KEY
- 在判斷命中前,MySQL不會解析SQL,而是使用SQL去查詢緩存,SQL上的任何字符的不同,如空格、注釋等都會導致緩存不命中
- 如果查詢有不確定的數據,如like now()、current_date(),那么查詢完成后結果都不會被緩存
3. 工作流程
- 服務器接收SQL,以SQL和一些其他條件為key查找緩存表
- 如果緩存命中,則直接返回緩存
- 如果緩存沒有命中,則執行SQL查詢,包括SQL解析、優化等。
- 執行完SQL查詢結果以后,將SQL查詢結果寫入緩存表
4. 緩存失敗
- 當某個表正在寫入數據,則這個表的緩存將會處於失效狀態
- 在InnoDB中,如果某個事務修改了表,則這個表的緩存在事務提交前都會處於失效狀態,即在事務提交前,這個表的相關查詢都無法被緩存
5. 緩存的內存管理
- MySQL緩存機制會在內存中開辟一塊內存(query_cache_size)區來維護緩存數據,其中大概有40K的空間是用來維護緩存數據的元數據的,例如空間內存、數據表和查詢結果的映射,SQL和查詢結果的映射。
- MySQL緩存機制將大內存塊分為小內存塊(query_cache_min_res_unit),每個小塊中存儲自身的類型、大小和查詢結果數據,還有前后內存塊的指針。
- MySQL緩存機制會在SQL查詢開始(還未得到結果)時就去申請一塊內存空間,所以即使緩存數據沒有達到這個大小也需要占用申請的內存塊空間(like linux filesystem’s block)。如果超出申請內存塊的大小,則需要再申請一個內存塊。當查詢完成發現申請的內存有富余,則會將富余的內存空間釋放掉,因而可能會造成內存碎片。
6. 緩存的使用時機
1. 通過緩存命中率判斷
緩存命中率 = 緩存命中次數 (Qcache_hits) / 查詢次數 (Com_select)
2. 通過緩存寫入率判斷
寫入率 = 緩存寫入次數 (Qcache_inserts) / 查詢次數 (Qcache_inserts)
3. 通過命中-寫入率判斷
比率 = 命中次數 (Qcache_hits) / 寫入次數 (Qcache_inserts),
高性能MySQL中稱之為比較能反映性能提升的指數,一般來說達到3:1則算是查詢緩存有效,而最好能夠達到10:1
7. 緩存參數配置
1. 查看緩存相關配置
SHOW VARIABLES LIKE '%query_cache%';
2. query_cache_type
- 是否打開緩存,可選參數有:
- OFF(0):關閉 ,不使用查詢緩存
- ON(1):總是打開 ,始終使用查詢緩存
- DEMAND(2):按需使用查詢緩存,只有明確寫了SQL_CACHE的查詢才會寫入緩存
- 如果query_cache_type為1而又不想利用查詢緩存中的數據,可以用下面的SQL:
- SELECT SQL_NO_CACHE * FROM my_table WHERE condition;- 如果值為2,要使用緩存的話,需要使用SQL_CACHE開關參數:
- SELECT SQL_CACHE * FROM my_table WHERE condition;
3. query_cache_size
- 緩存使用的總內存空間大小,單位是字節,這個值必須是1024的整數倍;否則MySQL實際分配可能跟這個數值不同(感覺這個應該跟文件系統的blcok大小有關)
- 默認情況下query_cache_size為0,表示為查詢緩存預留的內存為0,則無法使用查詢緩存
- 設置query_cache_size的值
- SET GLOBAL query_cache_size = 134217728; -- 注意值如果設得太小不會生效
4. query_cache_min_res_unit
分配內存塊時的最小單位大小
5. query_cache_limit
MySQL能夠緩存的最大結果,如果超出,則增加 Qcache_not_cached的值,並刪除查詢結果
6. query_cache_wlock_invalidate
如果某個數據表被鎖住,是否仍然從緩存中返回數據,默認是OFF,表示仍然可以返回
7. GLOBAL STATUS 中關於緩存的參數解釋
- Qcache_free_blocks:緩存池中空閑塊的個數
- Qcache_free_memory:緩存中空閑內存量
- Qcache_hits:緩存命中次數
- Qcache_inserts:緩存寫入次數
- Qcache_lowmen_prunes:因內存不足刪除緩存次數
- Qcache_not_cached:查詢未被緩存次數,例如查詢結果超出緩存塊大小,查詢中包含可變函數等
- Qcache_queries_in_cache:當前緩存中緩存的SQL數量
- Qcache_total_blocks:緩存總block數
8. 減少緩存碎片策略
- 選擇合適的block大小
- 使用 FLUSH QUERY CACHE 命令整理碎片,這個命令在整理緩存期間,會導致其他連接無法使用查詢緩存
清空緩存的命令
RESET QUERY CACHE; // 從查詢緩存中移出所有查詢。
FLUSH TABLES; //關閉所有打開的表,同時該操作將會清空查詢緩存中的內容。
9. InnoDB查詢緩存
- InnoDB存儲引擎會對每個表設置一個事務計數器,里面存儲當前最大的事務ID
- 當一個事務提交時,InnoDB會使用MVCC中系統最大的事務ID更新當前表的計數器
- 只有比這個最大ID大的事務能使用查詢緩存,其他比這個ID小的事務則不能使用查詢緩存
- 在InnoDB中,所有加鎖操作的事務都不使用任何查詢緩存
- 查詢必須是完全相同的(逐字節相同)才能夠被認為是相同的。
- 查詢字符串由於其它原因使用不同的數據庫、不同的協議版本或者不同的默認字符集都會被認為是不同的查詢而分別進行緩存。