一、查詢緩存是什么?
MySQL 查詢緩存保存查詢返回的完整結(jié)果,當(dāng)查詢命中該緩存,MySQL 會(huì)立刻返回結(jié)果,跳過解析、優(yōu)化和執(zhí)行過程。
查詢緩存系統(tǒng)會(huì)跟蹤查詢中涉及的每個(gè)表,如果這些表發(fā)生變化,那么和這個(gè)表相關(guān)的所有的緩存數(shù)據(jù)都將失效,這種機(jī)制效率看起來比較低,因?yàn)閿?shù)據(jù)表變化時(shí)可能對查詢結(jié)果并沒有影響,但是這種簡單實(shí)現(xiàn)代價(jià)很小,而這點(diǎn)對于一個(gè)非常繁忙的系統(tǒng)來說非常重要。
二、MySQL 如何判斷緩存命中
判斷是否命中時(shí),MySQL 不會(huì)解析,而是直接使用 SQL 語句和客戶端發(fā)送過來的其他原始信息。任何字符上的不同,例如空格、注釋,丟回導(dǎo)致緩存的不命中。通常使用統(tǒng)一的編碼規(guī)則是一個(gè)好的習(xí)慣,會(huì)讓你的系統(tǒng)運(yùn)行的更快。
當(dāng)查詢語句中有一些不確定的數(shù)據(jù)時(shí),不會(huì)被緩存,比如函數(shù) now ()。實(shí)際上,如果緩存中包含任何用戶自定義函數(shù)、存儲(chǔ)函數(shù)、用戶變量、臨時(shí)表、MySQL 系統(tǒng)表、或者任何包含列級(jí)別權(quán)限的表,都不會(huì)被緩存。
三、使用查詢緩存需謹(jǐn)慎
打開查詢緩存對讀和寫操作都會(huì)帶來額外的消耗:
- 讀查詢在執(zhí)行之前要先檢查是否命中緩存;
- 如果讀查詢可以被緩存,那么當(dāng)完成執(zhí)行后,MySQL 如果發(fā)現(xiàn)緩存中沒有這個(gè)查詢,會(huì)將其結(jié)果存入查詢緩存,這會(huì)帶來額外的系統(tǒng)消耗;
- 對寫操作也有影響,因?yàn)楫?dāng)向某個(gè)表寫入數(shù)據(jù)的時(shí)候,MySQL 必須將對應(yīng)表的所有緩存設(shè)置失效。如果查詢緩存非常大或者碎片很多,這個(gè)操作就可能會(huì)帶來很大的系統(tǒng)消耗。
雖然如此,查詢緩存仍然會(huì)給系統(tǒng)帶來性能的提升。但是,上述的額外消耗也可能不斷增加,再加上對查詢緩存操作是一個(gè)加鎖排它操作,這個(gè)消耗也不小。
對 InnoDB 用戶來說,事務(wù)的一些特性會(huì)限制查詢緩存的使用。當(dāng)一個(gè)語句在事務(wù)中修改了某個(gè)表,在事務(wù)提交前,MySQL 都會(huì)將這個(gè)表對應(yīng)的查詢緩存設(shè)置失效,因此,長時(shí)間運(yùn)行的事務(wù),會(huì)大大降低查詢緩存的命中率。
四、InnoDB 和查詢緩存
因?yàn)?InnoDB 有自己的 MVCC 機(jī)制,所以相比其他存儲(chǔ)引擎,InnoDB 和查詢緩存的交互要更加復(fù)雜。
MVCC 是多版本并發(fā)控制,是為了在讀取數(shù)據(jù)時(shí)不加鎖來提高讀取效率和并發(fā)性的一種手段。MVCC 解決的是讀寫時(shí)的線程安全問題,線程不用去爭搶讀寫鎖。
MVCC 所提到的讀是快照讀,也就是普通的 select 語句,快照讀在讀寫時(shí)不用加鎖,不過可能會(huì)讀到歷史數(shù)據(jù)。
另一種讀的方式是當(dāng)前讀,是一種悲觀鎖的操作,它會(huì)對當(dāng)前讀取的數(shù)據(jù)進(jìn)行加鎖,所以讀到的數(shù)據(jù)都是最新的,主要包括以下操作:
- select lock in share mode,共享鎖。
- select for update,排它鎖。
- insert,排它鎖。
- update,排它鎖。
- delete,排它鎖。
InnoDB 會(huì)控制在一個(gè)事務(wù)中是否可以使用查詢緩存,InnoDB 會(huì)同時(shí)控制對查詢緩存的讀寫操作。事務(wù)是否可以訪問查詢緩存取決于當(dāng)前事務(wù)的 ID,以及對應(yīng)的數(shù)據(jù)表上是否有鎖。每一個(gè) InnoDB 表的內(nèi)存數(shù)據(jù)字典都保存了一個(gè)事務(wù) ID 號(hào),如果當(dāng)前事務(wù) ID 小于該事務(wù) ID,則無法訪問查詢緩存。
如果表上有任何的鎖,那么對這個(gè)表的任何查詢語句都是無法被緩存的。例如,某個(gè)事務(wù)執(zhí)行了 select for update 語句,那么在這個(gè)鎖釋放之前,任何其他的事務(wù)都無法從查詢緩存中讀取與這個(gè)表相關(guān)的緩存結(jié)果。
當(dāng)事務(wù)提交時(shí),InnoDB 持有鎖,并使用當(dāng)前的一個(gè)系統(tǒng)事務(wù) ID 更新當(dāng)前表的計(jì)數(shù)器。InnoDB 將每個(gè)表的計(jì)數(shù)器設(shè)置成某個(gè)事務(wù) ID,而這個(gè)事務(wù) ID 就代表了當(dāng)前存在的且修改了該表的最大的事務(wù) ID。
特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺(tái)“網(wǎng)易號(hào)”用戶上傳并發(fā)布,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.