MySQL 中 QueryCache 的鎖模型

2021-06-08 09:33:07 字數 1580 閱讀 3941

原文:

有同學在問 mysql中 querycache(qc)的鎖是 「全域性鎖」還是 「表鎖」。這裡簡要說明一下。

1、qc基本概念

這個是實現在mysql層(非引擎層)的乙個記憶體結構,基本規則是將滿足一定條件的查詢結果快取在記憶體中,若同樣的查詢再執行第二次,而且快取沒有失效,則可以直接返回查詢結果,無需到引擎獲取資料。

幾個說明:

a) qc的結構是hash,key為查詢字串的原文,因此若想命中qc,要求查詢語句與之前的一模一樣,包括大小寫必須一致、不能增減空格等等。

b) qc可以快取乙個表中的多個查詢語句和結果。

c) 對乙個表的dml或ddl操作都會將與這個表有關的快取都從qc中刪除。

2、鎖模型

於是說到鎖的粒度。整個qc在記憶體中只有乙個例項query_cache query_cache;

我們來看上面c中說到的失效邏輯的部分**

cpp**  

void query_cache::invalidate_table(thd *thd, uchar * key, uint32 key_length)   

可以看到這裡lock()沒有引數,函式內部用一額全域性訊號量cond_cache_status_changed,來控制。

因此即使兩個dml更新的是不同的表,也會由於都要失效本表在qc中的快取項而互鎖。

因此是「全域性鎖」。

3、鎖策略

得到上述結論後我們有點擔心,作為乙個全域性變數,是否也會鎖住「查詢」。試想如果我們在作乙個ddl時,需要失效這個表的快取項,而這個鎖的時間就會持續很長。 這期間其他表的普通查詢,是否也會受影響。 如果是,這個損失太大了。

我們知道,查詢過程中的對qc的訪問包含兩部分 :查詢開始之前從qc中判斷當前query的結果是否已經快取; 若沒有,則查詢執行完成後,(可能)需要將這個結果插入到qc中。

這兩個操作都其實也都需要對qc加鎖。這樣說來, 這個鎖的頻度如此之高,以至於我們會擔心是否會得不償失?

更新時失效快取項是必要的操作,但查詢時對qc的操作則不是必須的。mysql中使用try_lock的策略。簡單來說,就是在上面的兩個階段中,試圖去加鎖,若超時,則放棄。

這個超時時間寫死在**中是50ms,所以若乙個 查詢期間的兩次對qc的操作都出現鎖超時,則這個查詢會額外耗費100ms的時間。

當然若是dml操作需要失效qc中的項,而碰上鎖等待,就必須等了。

4、小結

從上面描述中可以得出一些結論,對於更新操作比較小的服務,開啟qc的效果會不錯,因為查詢期間使用的try_lock策略使得不會出現查詢在qc階段互鎖的問題。(這個50ms如果覺得太大,可以在原始碼中去掉個0)。

當然若是更新頻繁的表,還是建議關閉qc。現在主幹版本上用引數關閉qc不夠徹底,還是會有一些cpu消耗。有興趣的同學可以看 這篇。

php中mysql函式 php中mysql有關函式

1.mysql query 一般是用來查詢資料裡面的資料。如 username post name sql select from members where login name username result mysql query sql 以上程式是檢測資料庫中是否存在表單傳送過來的使用者名稱...

mysql中 變數 mysql中的變數

toc 變數 mysql本質是一種程式語言,需要很多變數來儲存資料。mysql中很多的屬性控制都是通過mysql中固有的變數來實現的。系統變數 系統內部定義的變數,系統變數針對所有使用者 mysql客戶端 有效。檢視系統所有變數 show variables like pattern mysql允許...

mysql中 變數 MYSQL中的變數 MySQL

bitscn.com 只記很基礎的知識,細節東西太麻煩了,而且我也用不到。變數分為使用者變數與系統變數。使用者變數 使用者變數與資料庫連線有關,在這個連線中宣告的變數,在連線斷開的時候,就會消失。在此連線中宣告的變數無法在另一連線中使用。使用者變數的變數名的形式為 varname的形式。名字必須以 ...