一條 Update 語句的執行過程是怎樣的?

前言

通過本文主要了解 Sql 執行流程,包括兩個問題:

  1. 1. MySQL 的一條 Select 語句是怎麼運行的

  2. 2. MySQL 的一條 Update 語句是怎麼運行的

先看第一個問題,這裏做個簡單描述 ,因爲我們着重還是看 Update

MySQL 執行一條 Select 語句是怎麼運行的?

這個問題大家在面試的時候大家都背過類似的題,而且網上也有很多答案,這裏分享一個大致流程介紹,關於下圖的介紹來自這裏 執行一條 select 語句,期間發生了什麼?。

相對於 Select,內容更多和更復雜的是 Update 語句的執行,接下來我們講展開細講,再看本文之前可以先看看之前的分享,這兩篇文章對 Double Write 和 Buffer Pool 有做詳細的介紹:

MySQL 的 Double Write 如何保證可靠性?

InnoDB 的 Buffer Pool 是如何管理數據頁的?

當然最好也瞭解下 redolog、undolog、binlog 的相關知識點,這塊知識我們會在後續繼續分享!

Update 執行邏輯

先把我畫的圖看完,圖中步驟比較多,需要花點時間看,你想我畫這個肯定花了更長時間,如果覺得還不錯的話,謝謝點贊收藏下,不足的話大家指正下!

執行流程圖

整個流程的架構很清晰:Client 客戶端、Server 層、InnoDB 引擎層、磁盤,這裏就不對每個組件的具體功能和細節處理做更詳細的解釋了,文章主要是幫我們把流程理清楚!

核心組成部分

當然這裏也涉及到幾個核心:Buffer Pool、Double Write、Redo Log、Undo Log、BinLog、WAL

Buffer Pool 和 Double Write 可以參考我之前的文章,在開頭就有分享原文鏈接,我們來看以下問題!

Redo Log、Undo Log、BinLog 分別存的什麼內容,分別是做什麼用的?

  1. 1. Redo Log 在引擎層實現,用來恢復數據的,保障已提交事務的持久化特性,記錄的是物理級別的數據頁 (包括 data page 和 undo page) 做的修改

  2. 2. Undo Log 在引擎層實現的邏輯日誌,用於數據回滾到之前狀態,對於每個 UPDATE 語句,對應一條相反的 UPDATE 的 undo log

  3. 3. BinLog 是 Server 實現的邏輯日誌,用於複製和恢復數據,記錄了所有的 DDL 和 DML 語句(除了數據查詢語句 select、show 等)

WAL 是什麼,哪裏用到了它?

WAL 全稱爲 Write-Ahead Logging,預寫日誌系統。主要寫 undo log、redo log、binlog 這些用到了。

真正使用 WAL 的原因是:磁盤的寫操作是隨機 IO,比較耗性能,所以如果把每一次的更新操作都先寫入 log 中,那麼就成了順序寫操作,實際更新操作由後臺線程再根據 log 異步寫入

UndoLog 會存儲在哪些地方?

我們從圖中也可以清晰的知道 UndoLog 在兩個地方:Buffer Pool 中的 undo page 頁,和磁盤中的表共享空間的 Undo log

詳解執行流程

看完執行流程圖大家都有個大概印象了,我們分三個部分進行更具體的文字化描述,一起來看看吧!

Client 客戶端:

  1. 1. 客戶端通過 tcp/ip 發送一條 sql 語句到 server 層

Server 層:

  1. 1. 接收客戶端過來的請求,進行權限驗證

  2. 2. 權限驗證通過後,解析器會對 SQL 語句進行詞法、語法分析等

  3. 3. 經過驗證解析的 SQL 語句會在優化器生成選擇最優執行計劃

  4. 4. 然後執行器將會執行經過優化的 SQL 語句

Server 層和存儲引擎之間怎麼通信的呢?

到這裏用戶發送的一個 SQL 已經經過各種驗證、分析、優化到了執行階段,那麼接下來就是執行器怎麼和 InnoDB 存儲引擎打交道了。

對於 Server 層來說,它是不知道存儲引擎的實現細節的,而是通過定義的 API 接口和存儲引擎通信。可以理解爲存儲引擎是一個類,然後每個實例(InnoDB)都通過一個特殊的處理程序接口與 MySQL 服務器通信。

InnoDB 引擎層:

現在已經到了引擎層了,存儲引擎主要負責數據的存儲和讀取

  1. 1. 調用存儲引擎接口後,會先從 Buffer Pool 獲取數據頁,如果沒有就從磁盤中讀入 Buffer Pool,然後判斷更新前後的記錄是否一樣

  2. 2. 開啓事務,修改數據之前先記錄 undo log,寫入 Buffer Pool 的 undo page

  3. 3. 開始更新 page data 中的記錄,被修改的數據頁稱爲髒頁,修改會被記錄到內存中的 redo log buffer 中,再刷盤到磁盤的 redo log 文件,此時事務是 perpare 階段

  4. 4. 這個時候更新就完成了,當時髒頁不會立即寫入磁盤,而是由後臺線程完成,這裏會用 double write 來保證髒頁刷盤的可靠性

  5. 5. 還沒結束呢,這時候可以通知 Server 層,可以正式提交數據了, 執行器記錄 binlog cache,事務提交時纔會將該事務中的 binglog 刷新到磁盤中

  6. 6. 這個時候 Update 語句完成了 Buffer Pool 中數據頁的修改、undo 日誌、redo log 緩存記錄,以及記錄 binlog cache 緩存

  7. 7. commit 階段,這個階段是將 redo log 中事務狀態標記爲 commit

  8. 8. 此時 binlog 和 redo log 都已經寫入磁盤,如果觸發了刷新髒頁的操作,先把髒頁 copy 到 double write buffer 裏,Double Write Buffer 的內存數據刷到磁盤中的共享表空間 ibdata,再刷到數據磁盤上數據文件 ibd

  9. 9. 流程完結

什麼是二階段提交?

二階段提交,顧名思義,會包含 2 個階段:

prepare 階段,協調器會詢問所有執行器,是否可以提交事務

commit 階段,協調器會通知執行器進行提交操作

update 的執行階段也用到了,比如:

總結

今天的分享就到這了,我們平時一條 Update 語句其實內部會經歷很多流程,語句解析、日誌 WAL,Buffer Pool 等。通過今天這篇文章的分享相信大家對流程已經很清晰了,後續將繼續帶來 Redo Log、UndoLog 等內容,敬請期待!

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/eep-JDNya25ys4DDzuKCww