您好,登錄后才能下訂單哦!
本篇內容介紹了“MySQL中寫操作時保駕護航的三兄弟是什么”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
- 思維導圖 -
兩階段提交
這個名詞你應該聽到過很多次了,在這里再介紹下這位老朋友。
所謂的兩階段提交,從字面意思來看應該是有兩個步驟來進行約束的。事實上也是如此。這兩個步驟中的主角就是我們今天要講的重要角色中的兩位:binlog 和 redo log。
提到兩階段提交,SQL 語句的執行流程就繞不過去了。沒轍,雖然提了很多遍,但還得再拉出來溜溜。只不過這次的側重點和前面的會有些不同。
具體到操作流程上是這樣的:
當執行某個寫操作的 SQL 時,引擎將這行數據更新到內存的同時把對應的操作記錄到 redo log 里面,然后處于 prepare 狀態。并把完成信息告知給執行器。
執行器生成對應操作的 binlog,并把 binlog 寫入磁盤里。然后調用引擎的提交事務接口,變更 redo log 狀態為 commit,這樣操作就算完成了。
好了,知道了兩階段提交后,我們接下來看看這些日志文件的真面目。
重做日志(redo log)
首先出場的是位于存儲引擎層的 redo log,它是用來記錄在"數據頁做了什么修改"的物理日志文件。
WAL 技術
提到 redo log,WAL 技術必然是繞不過去的,全稱是 Write-Ahead Logging。也就是在同步磁盤前先寫日志,然后系統再根據一定的策略將日志里的記錄同步到磁盤里。
存在的必要性
從上邊的兩階段提交的過程里,我們可以看到 WAL 技術的使用場景。不知道你有沒有疑惑,為什么中間非要寫 redo log,直接將更新結果同步到磁盤里不行嗎?傻孩子,同步到磁盤里就意味著每次寫操作就得產生隨機寫盤操作,速度得多慢啊。
機智的你可能會說了,那我能不能一定的時間后從內存再同步到磁盤里,這種方式不行嗎?來,先給你個腦瓜崩,你想想,我服務重啟了,這些數據還在不?內存是易失的,不知道什么異常情況就會導致數據丟失。所以這時候就需要一個能持久化的中間文件,起到"緩沖"的作用,并且寫入速度還不慢。
那么 redo log 就應運而生了。雖然同樣存儲在磁盤上,但是順序寫入在速度上并不受影響(疑惑的同學可以了解下磁盤的隨機與順序讀寫的區別)。
當然 redo log 除了能起到"延遲"同步磁盤文件的作用外,在數據庫服務器宕機時,還可以用來恢復數據。
寫入時機
談到寫入時機,是不是更疑惑了,難倒不是更新完內存就寫入 redo log 文件嗎?答案確實不是,因為中間還有一個 redo log buffer(內存中) 。Mysql 每執行一條語句,會先將記錄寫入 redo log buffer,后續執行 commit 操作時會以一定的時機寫入到 redo log 文件(磁盤上)中。
值得注意的是,redo log buffer 里的數據是在執行 commit 操作時寫入到 redo log 文件中的。
至于寫入的時機,則由下面的參數來控制的:
(圖片源自網絡)
寫入方式
知道了寫入時機,這里簡單介紹下寫入的方式吧。在 Innodb 中,redo log 的大小是固定的,那么就只能是以循環的方式進行寫入了。假如當前我有 4 個文件,從第一個文件開始寫入,直到最后一個文件寫滿為止,再回到開頭將數據同步至文件后擦除掉繼續寫。
圖中的 write pos 表示當前記錄的位置,隨著不斷寫入逐漸后移。當寫到 ib_logfile_3號文件時,整個 redo log 就被寫滿了。此時更新操作就會被阻塞。系統根據 check point 標記位來擦除掉一些記錄(當然前提是把這些記錄同步至磁盤)。
總得來看 redo log 的寫入方式就是一個不斷寫入,寫滿后擦除,又寫入的過程。
二進制日志(binlog)
說完了 redo log,我們再來看看另一個位于服務層的二進制日志文件 binlog,這位大兄弟扮演的角色是存儲邏輯日志的,所謂的邏輯日志就是指修改了什么,都會記錄其中。
例如:對 id = 1 的字段進行更新操作。
當然除了記錄操作過程外,它還有支持主從同步及數據異常恢復的能力。
寫入模式
binlog 中有三種寫入模式,我們分別來看下有什么不同及對應的優缺點:
(圖片源自網絡)
寫入方式
與 redo log 循環寫不同的是, binlog 采用追加的方式寫入,當一個文件寫到一定大小后就會切換到另一個。
與 redo log 的關聯
在上面的兩階段提交里我們有提到過在寫入binlog 后會調用引擎的提交事務接口,變更 redo log 狀態為 commit。那么它是如何找到對應的記錄,或者換句話說,它們兩者是怎么關聯起來的呢?
答案是通過一個共同的字段 XID,不僅在事務提交時,在崩潰恢復的時候如果遇到僅寫入 prepare 而沒有 commit 的 redo log,也可以通過 XID 去尋找對應的事務。
回顧下寫流程
到這里我們有必要回顧下寫流程的操作,以更新某個字段為例:
回滾日志(undo log)
到這里,你可能會疑惑了,通篇里哪有 undo log 的影子,你個渣男!
別急,來了!
根據字面意思,你應該能猜出來它是干啥的。回滾嘛,也就是給你一次后悔的機會。在進行數據修改時,同時記錄 undo log,即同時記錄相反操作的邏輯日志。你可以理解為操作 update 的時候,寫一條對應相反的 update 記錄,操作 delete 的時候,寫一條對應的 insert 記錄。
當事務回滾時。從 undo log 中讀取到對應的邏輯記錄就可以進行回滾操作了。
總結
兩階段提交
兩階段提交過程中,更新內存的同時把對應操作記錄到 redo log 中,并把生成的binlog 寫入磁盤后提交事務。
重做日志
redo log 是位于存儲引擎層的物理日志,用來記錄在“數據頁做了什么修改”的物理日志文件。采用循環寫的方式,記錄數據被修改后的樣子。同時還提供數據恢復的能力。
二進制日志
binlog是位于服務層的邏輯日志,用來記錄“對數據做了什么修改”的日志文件。與 redo log 不同的是,可以一直進行追加寫入。同時還提供主從同步及數據異常恢復的能力。
回滾日志
在數據修改時,同時記錄 undo log,可以確保在事務回滾操作時進行數據還原。
“MySQL中寫操作時保駕護航的三兄弟是什么”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。