mysql的緩存大體分爲2種,一種是對執行計劃的緩存,能夠跳過sql解析和執行計劃階段。這中緩存只有在某些場景下能夠實現。另一種是緩存完整的select查詢。此次主要說說mysql第二種緩存的機制。
先簡單提一下第一種緩存形式。在這以前,先說說mysql的整個執行過程。mysql
這是一個簡單的mysql的執行過程的圖片,mysql緩存的第一種方式就是能夠跳過解析,預處理,執行計劃等階段,直接與用api和底層的存儲引擎進行交互。這種通常用到的比較少。通常能夠不考慮sql
如今重點說一下第二種方式數據庫
第二種方式是Mysql會用一個大小寫不敏感的的檢查看看sql語句是否是以sel開頭,若是是,mysql將考慮將sql語句的結果緩存起來,這裏只是考慮,並非每一個以sel開頭的sql語句都會被緩存起來,mysql的底層緩存邏輯是很複雜的。segmentfault
mysql是如何判斷緩存命中的。mysql判斷緩存命中的方法很簡單,緩存存放到一個引用表中,經過一個哈希引用。每一個哈希引用包括以下因素:查詢自己、當前查詢的數據庫、客戶端的協議版本等等。有2點須要說明一下:
一、 mysql不會只能的檢查兩條sql是否是同樣,也就是說由於一個空格的不同就會致使不能使用緩存。因此運用層的sql編碼規則的統一是很重要的。有一點是意外,sql的大小寫是不敏感的。sel和SEL是同樣的,但這限於檢查是否是能夠緩存的時候,不影響最後的緩存結果,例如:select * from table 和 SELECT * FROM TABLE 是不同的。
二、 當sql語句中含有一些不肯定的數據時是不能被緩存的。例如:CURRENT_USER或者CONNECTION_ID()的查詢。
在這裏要提一下的是,常常會有人說「若是一個查詢裏面包含不肯定的函數時,mysql就不會堅持緩存」。事實上這種說法是不正確的。這種語句mysql是不緩存。也就是說,mysql每次都會檢查。只是包含不肯定函數的sql語句壓根緩存不起來,即便檢查也是查不到的。
InnoDB的處理要複雜一些。InnoDB的事務會限制緩存的使用。當一個語句中在事務中修改了某個表,mysql會將這個表的全部的查詢緩存都設置失效。而事實上,innodb的多版本特性會暫時將這個修改對其餘事務屏蔽。在這個事務提交前,這個表的相關查詢是沒法被緩存的。因此全部在這個表上面的查詢都只能在這個事務提交後才被緩存。所以,長時間的事務運行會致使緩存命中率的降低。api