說明:本來是打算寫一些個人心得的,後來發現文中大量高質量的QA都非常精典,所以粘過來了,如有侵權請聯繫我刪除哈
收穫到的知識點
- 當一個表有更新的時候,跟這個表相關的所有緩存都會失效,所以這條語句就會把表T上所有緩存結果清空。(MySQL8.*版本已去掉了查詢緩存模塊)
- MySQL中的2種日誌類型分別是 redo log(重做日誌) 和 binlog(歸檔日誌)
之所以存在這2種類型的日誌(redo log、binlog),是由於最開始MySQL裏並沒有InnoDB引擎的,MySQL自帶的引擎是MyISAM,但是MyISAM是不支持事務的,也沒有crash-safe的能力,binlog只能用於歸檔,而InnoDB是另一個公司(名叫芬蘭公司Heikki)以插件形式引入MySQL的(集成版本從MySQL4.0開始),
之間的差異點
- redo log是InnoDB引擎特有的日誌,其它引擎不會使用redo log,binlog是MySQL的Server層實現的,其它引擎都可以使用
- redo log(重做日誌) 也叫物理日誌,記錄的是“在某個數據頁做了什麼修改”; binlog(歸檔日誌)也叫邏輯日誌,記錄的是這個語句的原始邏輯
- redo log(重做日誌) 是循環寫的,總大小是固定的,所以每次都會擦除重寫;binlog(歸檔日誌)是追加寫入的,“追加寫”是指 binlog 文件寫到一定大小後會切換到下一個,並不會覆蓋以前的日誌。
既然InnoDB引擎這2種日誌都會寫入,那麼當一sql(比如update)執行時,redo log(重做日誌) 和 binlog(歸檔日誌)他們的寫入順序是怎麼樣呢
從上面的流程中可以看到redo log(重做日誌)的寫入拆成了2個步驟:prepare和commit, 這就是“兩階段提交”
爲什麼要拆成“兩階段提交”
作者已經解釋了很清楚了,無論是先直接寫入哪一個到磁盤,都存在數據不一致的風險,這裏就不展開討論了,這裏想和大家聊的是難道拆成“兩階段提交”都可以解決這個問題嗎?
答案是肯定的。看大師精典回覆
Q:老師,我想問下如果提交事務的時候正好重啓那麼redo log和binlog會怎麼處理?此時redo log處於prepare階段,如果不接受這條log,但是binlog已經接受,還是說binlog會去檢查redo log的狀態,狀態爲prepare的不會恢復?2018-11-16
A:作者回復
好問題👍🏿表示中間那段你都聽明白了👍🏿
Binlog如果已經接受,那麼redolog是prepare, binlog已經完整了對吧,這時候崩潰恢復過程會認可這個事務,提交掉。 (你可以分析下這種情況下,是否符合我們要達到的“用binlog恢復的庫跟原庫邏輯相同” 這個要求)
看來MySQL Server每次啓動都會去檢查binlog的,如果沒有出現異常的話,正常執行是要等到redo log commit纔算完,但是崩潰恢復過程的話,可以接受“redo log prepeare & binlog完整寫入”的數據
InnoDB引擎需要多寫一份redo log產生的磁盤IO性能開銷,怎麼做到優化呢
看大師精典回覆吧
Q: 老師,我這想請教兩個問題:
1.寫redo日誌也是寫io(我理解也是外部存儲)。同樣耗費性能。怎麼能做到優化呢
2.數據庫只有redo commit 之後纔會真正提交到數據庫嗎
2018-11-16
A: 作者回復
- Redolog是順序寫,並且可以組提交,還有別的一些優化,收益最大是是這兩個因素;
2.是這樣,正常執行是要commit 纔算完,但是崩潰恢復過程的話,可以接受“redolog prepare 並且binlog完整” 的情況
2018-11-16
前一個問題中老師提到的“binlog完整”,怎麼纔算完整
Q:老師,有個疑問,怎麼知道binlog是完整的?這個想不通
2018-11-16
A:作者回復
一個事務的完整binlog是有固定格式,也就是說有固定結尾的😄
關於文中提到的WAL,先寫日誌再寫磁盤問題,剛剛update立即select結果能正確嗎
Q: 老師,您好。您說MySQL 使用WAL,先寫日誌再寫磁盤。請教一個問題,
執行一條Update 語句後,馬上又執行一條 select * from table limit 10。
如果剛剛update的記錄,還沒持久化到磁盤中,而偏偏這個時候的查詢條件,又包含了剛剛update的記錄。
那麼這個時候,是從日誌中獲取剛剛update的最新結果,還是說,先把日誌中的記錄先寫磁盤,再返回最新結果?
爲什麼redo log(重做日誌) 也叫物理日誌呢
Q: binlog爲什麼說是邏輯日誌呢?它裏面有內容也會存儲成物理文件,怎麼說是邏輯而不是物理
2018-11-16
A:作者回復
這樣理解哈。
邏輯日誌可以給別的數據庫,別的引擎使用,已經大家都講得通這個“邏輯”;
物理日誌就只有“我”自己能用,別人沒有共享我的“物理格式”
個人理解
redo log(重做日誌)是InnoDB引擎爲事務服務的
binlog(歸檔日誌)是用於故障恢復的(比如異常重啓、恢復臨時庫、擴容增加備庫)
課堂問題
前面我說到定期全量備份的週期“取決於系統重要性,有的是一天一備,有的是一週一備”。那麼在什麼場景下,一天一備會比一週一備更有優勢呢?或者說,它影響了這個數據庫系統的哪個指標?
A: 關於“一天一備會比一週一備更有優勢”我談談的我觀點:
binlog一般情況下是崩潰時用來恢復的,恢復時間越短,對業務的影響越小,一天一備的話只需要利用昨天的備份+今天截止到目前的增量binlog,增量數據相對小一些,恢復的時間自然要高效一些。
反過來說如果一週一備的話,首先binlog需要存儲的至少是一週的數據(binlog如果小於一週的話否則故障發生時就無法恢復了)。所以我認爲影響到的指標是expire_logs_days(可以通過 show variables like '%expire_logs_days%'來進行查看)