Hi,大家好!我是白日夢!本文是MySQL專題的第 26 篇。
下文還是白日夢以自導自演的方式,圍繞“組提交”展開本話題。看看你能抗到第幾問吧
換一種寫作風格,自導自演面試現場!感覺這樣還是比較有趣的,歡迎大家訂閱我的MySQL專題,公眾號首發!持續更新中~
公眾號後臺回覆:資料庫 可以參與抽獎活動,3本《MySQL技術內幕-InnoDB儲存引擎》
歡迎關注白日夢,公眾號首發!持續連載中
庫尼奇瓦,同學,聽說你上一面表現的還可以,這一面要不我們繼續?
嗯,好啊!
好,你瞭解MySQL的兩階段提交不?說說看
嗯,瞭解。 簡單來說兩階段提交就是將事務提交分成兩部分,經過這兩步處理後,我們稱這個事務被提交了。
嗯,那兩個階段呢?你說說看!
可以看下面這張圖:我們當執行commit命令時,會按照如下進行。
第一階段:寫redo log,並標識上prepare。
-- 中間穿插寫binlog --
第二階段:寫redo log,完成事務的最終提交。
嗯,那你知不知道為什麼事務的提交要分成兩個階段?
嗯,你看上圖中的兩階段是redolog-prepare、redolog-commit這兩個階段,然後在這兩個階段中又寫了binlog。
這個redolog主要提供的能力是對事務進行rollback、並且redolog是儲存引擎層面記錄的日誌。
而binlog的作用是方面我們進行資料的備份以及MySQL叢集主從之間的資料同步使用,並且binlog是MySQL上層,也就是Server層面記錄的日誌。
綜上:MySQL的兩階段提交是為了保證redolog、binlog兩者在邏輯上的一致性。才能進一步保證。事務的回滾、資料備份、已經MySQL叢集之間的資料才是安全可靠的
嗯,那你能不能舉個例子,更直觀的告訴我,redolog、binlog兩者在邏輯一致的必要性以及用途?
嗯,好啊!,比如這個例子:
在這個例子中,進行完第三步之後,沒來得及寫binlog,然後主庫就掛了,事務也沒來得及提交。
這時主庫從新啟動之後會選擇將這個事務丟棄,因為如果它將事務提交了,從庫們相對主庫來說就少了這條資料,造成了主從資料不一致問題
嗯,在看這個例子
在這個例子中主庫當機前雖然也沒有完成對事務對提交,但是它已經寫了redolog-prepare、還寫了binlog,binlog寫完之後很可能從庫已經收到這個最新的binlog,並且將這個binlog中的資料回放到自己身上了。
所以主庫重新啟動之後呢,會選擇按照redolog將當機前的事務狀態從記憶體中恢復出來,也就是說把記憶體中的快取頁改成髒資料頁,然後提交事務
這時主庫如果不提交事務,那主庫就比從庫少了一條資料,同時會造成主從不一致的情況出現。
嗯,你說的沒錯。我有個問題哈,你看你畫的這張圖,事務提交時寫了好幾次日誌。
而且一般我們線上的資料庫都有這兩個配置
# 該引數控制binlog的落盤時機# 設定為1表示當事務被提交時將binlog落盤# 設定為0表示由檔案系統自己控制binlog的落盤時機sync_binlog=1# 該引數控制redolog的落盤時機 # 設定為1表示當事務被提交時將redolog落盤innodb_flush_log_at_trx_commit=1
那你有沒有想過:即使寫日誌是磁碟的順序IO速度極快,即使固態硬碟的效能很?,那終究也還是在跟磁碟打交道啊!
那你是否瞭解MySQL針對這個現狀有什麼優化的落地實現方案嗎?
我提醒你一下,比如:組提交
哦!我還真瞭解一些group commit的概念!
在MySQL早期的設計中,所謂的組提交,也就是 group commit 實際上提交的是group commit redolog。(而不是binlog)
而且MySQL寫redolog並不是產生一條redolog就寫一條redo log的!而是以redo log block為單位寫入磁碟,而且在redo log block 之上還有個redo log buffer的概念
總結來說就是:寫redolog要分成2大步:
Step1:將redolog寫入記憶體buffer中。
Step2:將redolog fsync到磁碟中。
而組提交的概念是說:當進行fsync時,一下子將多個事務日誌寫入到磁碟中。 通俗來講,假如說你寫一次磁碟需要10ms,如果我們按條每個redolog都寫一次磁碟的話,10條redolog就需要100ms的耗時。
現在我們有了組提交,可以一次fsync將10條redolog一次磁碟IO就持久化到磁碟中,耗時可能也就十幾ms的樣子。效能是有所提升的。
嗯,你說的沒錯!而且我還注意到了你說的一個細節問題,你上面說,原來的group commit針對的是redolog,而不是binlog。這個緣由你能展開說一下嗎?
我.....
好的,這個問題就得從binlog的作用說起了。MySQL不可能無緣無故的就寫binlog,它之所以記錄binlog是因為它想獲取到寫binlog帶給它的紅利。
那什麼紅利呢?其實前面說了很多遍了,主要的紅利就是:binlog給了MySQL搭建叢集的可能性,以及資料備份的能力。
而且預設情況下binlog是不會開啟的。其實說白了,如果你不需要binlog帶給我們的能力,比如你偏偏就不需要做資料的備份、或者搭建叢集,那麼其實你直接使用預設配置不開啟binlog就好了。此時的兩階段提交也不復存在。
但是事實並不是這樣的,線上的資料庫都是以叢集的形式存在、並且也需要資料備份。也就是說binlog是開啟的狀態。事務的提交也是走的兩階段提交。
那,回到我們組提交的話題來看,其實在早期的MySQL中,並沒有一個很好的機制讓 組提交和兩階段提交共存的!
嗯,為什麼這麼說?
嗯,其實你大概一想就知道為什麼了。根本原因就在用 binlog是MySQL的上層(Server層)記錄的。而redolog是下層的儲存引擎層記錄的。
所以你突然整一個redolog的組提交出來,那兩階段提交怎麼辦?你為了效能哐當一下將記憶體中的redolog全落盤了,但是兩階段提交中每一步寫日誌的順序是有要求的呀。它倆正好相違背。
所以其實在InnoDB1.2版本之前,當開啟binlog使用兩階段提交時,組提交會失效....
嗯,你說的沒錯。那後來沒有比較好的解決方式呢?
嗯,其實是有的,早在2010年facebook的MySQL技術組,Percona公司就給出瞭解決方案。後來由MariaDB資料庫的開發人員Kristian Nielsen完成了最終的完美解決方案。
所以如果你使用的是MySQL5.6或者更好的版本,它就在兩階段提交的概念上,還加持上了組提交的buff,效能相對之前有了很多的提升。
嗯,那你可否大概說一下如何實現的?
嗯嗯,想了解它的具體的實現可以看這張圖:
我稍微解讀一下這張圖:總體來說分為三個部分,分別是Flush階段、Sync階段、Commit階段
並且它引入了一個新的概念:佇列,事務按提交的順序進入佇列中,佇列有先進先出的概念,最先進入佇列的事務被成為leader
在Flush階段就是將當前佇列中的所有事務的binlog統一寫入記憶體中,Sync就是將當前佇列中的所有事務的binlog通過一次fsync統一寫入到磁碟中。(相當於批量將binlog落盤)
最後的commit階段,由佇列中的leader根據一定的順序呼叫儲存引擎層的事務提交,完成兩階段的第二階段提交。事務結束...
這時就會形成一個比較理想的狀態,當一組事務發生Commit時,新的事務可以去Flush。讓整個過程中的組提交不斷的生效。
嗯,你繼續說!
但是如果每次佇列中都只有一個事務,那可能會導致效能還不如之前沒有這種佇列的設計
嗯,你繼續往下說。
還有就是我還了解關於組提交相關的一個控制引數
binlog_max_flush_queue_time
這個引數可以控制Flush階段的等待時間。預設情況下該引數設定為0,推薦設定也為0。
如果我們不把它設定為0,意思就是說想讓佇列中的事務攢一攢,攢多了再統一處理,想獲取到一次fsync將大量日誌落盤帶來的速度快的紅利。但是這樣同樣會導致事務的響應時間變慢。
嗯!你說的沒問題,整體上看你的回答的還可以!
我沒有問題了,你還有什麼想問我的嗎?
沒有問題了,感謝大佬百忙抽空來給我面試!
哈哈,客氣!好好準備,期待你下一面優秀的表現
推薦閱讀
- MySQL的修仙之路,圖文談談如何學MySQL、如何進階!(已釋出)
- 面前突擊!33道資料庫高頻面試題,你值得擁有!(已釋出)
- 大家常說的基數是什麼?(已釋出)
- 講講什麼是慢查!如何監控?如何排查?(已釋出)
- 對NotNull欄位插入Null值有啥現象?(已釋出)
- 能談談 date、datetime、time、timestamp、year的區別嗎?(已釋出)
- 瞭解資料庫的查詢快取和BufferPool嗎?談談看!(已釋出)
- 你知道資料庫緩衝池中的LRU-List嗎?(已釋出)
- 談談資料庫緩衝池中的Free-List?(已釋出)
- 談談資料庫緩衝池中的Flush-List?(已釋出)
- 瞭解髒頁刷回磁碟的時機嗎?(已釋出)
- 用十一張圖講清楚,當你CRUD時BufferPool中發生了什麼!以及BufferPool的優化!(已釋出)
- 聽說過表空間沒?什麼是表空間?什麼是資料表?(已釋出)
- 談談MySQL的:資料區、資料段、資料頁、資料頁究竟長什麼樣?瞭解資料頁分裂嗎?談談看!(已釋出)
- 談談MySQL的行記錄是什麼?長啥樣?(已釋出)
- 瞭解MySQL的行溢位機制嗎?(已釋出)
- 說說fsync這個系統呼叫吧! (已釋出)
- 簡述undo log、truncate、以及undo log如何幫你回滾事物! (已釋出)
- 我勸!這位年輕人不講MVCC,耗子尾汁! (已釋出)
- MySQL的崩潰恢復到底是怎麼回事? (已釋出)
- MySQL的binlog有啥用?誰寫的?在哪裡?怎麼配置 (已釋出)
- MySQL的bin log的寫入機制 (已釋出)
- 刪庫後!除了跑路還能幹什麼?(已釋出)
- 自導自演的面試現場,趣學資料庫的10種檔案(已釋出)
- 大型面試現場:一條update sql執行都經歷什麼?(已釋出)
- 大型翻車現場:如何實現記錄存在的話就更新,如果記錄不存在的話就插入。(已釋出)
最後,歡迎關注白日夢的公號哦~
換一種寫作風格,自導自演面試現場!感覺這樣還是比較有趣的,歡迎大家訂閱我的MySQL專題,公眾號首發!持續更新中~