問了幾人,MySQL changebuffer 這點都沒答對

張哥說技術發表於2023-02-28

你好,我是yes。

有位同學問了我兩個關於 change buffer 的問題:

問了幾人,MySQL changebuffer 這點都沒答對

隨後我又挑了幾個問答的使用者提問這兩個問題,發現對 change buffer 的理解都有偏差,於是決定操作一篇。

之前我寫過一篇關於 mysql innodb 所有 buffer 的內容 :總結 mysql 的所有 buffer,一網打盡就這篇了!

裡面有提到 change buffer,這篇算是之前那篇的補充吧。

如果對 mysql innodb buffer 不太熟悉,建議先看下我之前總結的內容,這個還是需要點前置知識的。

簡單回顧 change buffer

簡單來說 change buffer 就是一塊記憶體,存在於 buffer pool 中,當需要修改資料時候,如果這個資料所在頁在 buffer pool,那麼萬事大吉,直接在記憶體也修改。

那假設 buffer pool 裡沒有要修改的那個資料頁,這時候該修改怎麼辦呢?

假設要執行這個 sql:update table set a= 'yes' where b = 1

第一直覺就是找到 b =1 的資料所在的資料頁,載入到 buffer pool 中,然後進行修改,這裡就涉及了從磁碟拉取資料到記憶體這個動作,我們都知道讀盤的開銷是比較大的。

所以 mysql innodb 搞了個 change buffer,當資料頁不存在 buffer pool 時,mysql innodb 先把更新動作快取在 change buffer 中,當下次 select b=1 這個資料的時候,將資料載入到 buffer pool 中,同時應用上 change buffer 的修改,這就得到正確的資料了。

問了幾人,MySQL changebuffer 這點都沒答對

重點

上述的原理不難理解,不過我之前文章提到了一點:

問了幾人,MySQL changebuffer 這點都沒答對

這就是重點,理解了這個就能解答上面那位同學的提問。

change buffer 只能應用非唯一二級索引

聚蔟索引和唯一索引都需要檢查資料的一致性,這就不好先把更新、插入、刪除先快取在 change buffer 中。

假設現在有一張名為 yes 表,裡面有聚蔟索引以及一個(a,b) 的非唯一二級索引,現要執行如下語句:

update yes set b= 'yes的練級攻略' where a = 'yesyes'

思考下,此時能用上 change buffer 嗎?

原則上這條更新語句,mysql 可以選擇聚蔟索引掃,或者應用 (a,b)這個索引。

假設走(a,b)索引。

那問題來了,要走(a,b)索引,不就是要掃描(a,b)的資料嗎,也就是需載入(a,b)索引資料頁到 buffer pool 中,那還用啥 change buffer?

聽起來 change buffer 好像沒啥用啊?

我再加點條件:假設這個表不僅僅有 (a,b)這個索引,還有(c,b)、(d,b)等等這些索引,那麼如果我們要修改 b 欄位的值,是不是除了聚蔟索引,還需要修改(c,b)、(d,b)等等這些索引?

那 change buffer 的用處就來了!我們可以快取這些修改,後面再應用,這就大量減少了此次 sql 的隨機磁碟 I/O,提高了效能。

看到這,相信你對 change buffer 應該已經有點感覺了,你可以藉著這些感覺,去看下官網的介紹,理解起來更容易:

https://dev.mysql.com/doc/refman/5.7/en/innodb-change-buffer.html

回答問題

第一個問題:insert 用 chang buffer 如何確定主鍵不衝突?

主鍵索引和唯一索引都需要掃描校驗,change buffer 只會快取那些非唯一二級索引的插入操作。

第二個問題:用 chang buffer 不訪問磁碟,如何得到實際修改行數?

chang buffer 無法應用在主鍵索引(聚蔟索引)和唯一二級索引上,所以這兩個得改,主鍵索引都改了,影響行數就有了。

好了,今天的文章就到這了,如果有收穫不妨點給贊。

關於問答我還提供 1v1 個人問答服務,詳細可以看這裡:我的一對一專屬問答服務,簡單來說就是你有任何面試、技術上的問題都可以直接微信向我提問。

我是yes,從一點點到億點點我們下篇見~

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70024923/viewspace-2937366/,如需轉載,請註明出處,否則將追究法律責任。

相關文章