17.Sql是如何執行的

navyum發表於2024-10-28

UPDATE t_user SET name = ‘x’ WHERE id = 1

  1. 執行器負責具體執行,會呼叫儲存引擎的介面,透過主鍵索引樹搜尋獲取 id = 1 這一行記錄:
    • 如果 id=1 這一行所在的資料頁本來就在 buffer pool 中,就直接返回給執行器更新(id非唯一索引的前提下);
    • 如果記錄不在 buffer pool,將資料頁從磁碟讀入到 buffer pool,返回記錄給執行器。
  2. 執行器得到聚簇索引記錄後,會看一下更新前的記錄和更新後的記錄是否一樣:
    • 如果一樣的話就不進行後續更新流程;
    • 如果不一樣的話就把更新前的記錄和更新後的記錄都當作引數傳給 InnoDB 層,讓 InnoDB 真正的執行更新記錄的操作;
  3. 開啟事務,InnoDB 層更新記錄前,首先要記錄相應的 undo log,因為這是更新操作,需要把被更新的列的舊值記下來,也就是要生成一條 undo log,undo log 會寫入 Buffer Pool 中的 Undo 頁面,不過在記憶體修改該 Undo 頁面後,需要記錄對應的 redo log。
  4. InnoDB 層開始更新記錄,先生成對應redo log,並存入redo log buffer裡面。當事務提交時,將該語句生成的redo log按組為單位,寫入redo log file。然後更新buffer pool中的資料頁,將其插入flush 連結串列(如果不在其中),標記為髒頁、記錄當前redo log對應的lsn到該頁的oldest_modification。這個時候更新就算完成了。為了減少磁碟 I/O,不會立即將髒頁寫入磁碟,後續由後臺執行緒選擇一個合適的時機將髒頁寫入到磁碟。(這就是 WAL 技術,MySQL 的寫操作並不是立刻寫到磁碟上,而是先寫 redo 日誌,然後在合適的時間再將修改的行資料寫到磁碟上。但事務提交時必須要將redo log持久化)
  5. 至此,一條記錄更新完了。
  6. 在一條更新語句執行完成後,然後開始記錄該語句對應的 binlog,此時記錄的 binlog 會被儲存到 binlog cache,並沒有重新整理到硬碟上的 binlog 檔案,在事務提交時才會統一將該事務執行過程中的所有 binlog 重新整理到硬碟,然後進行第二階段的提交。
  7. 事務提交(為了方便說明,這裡不說組提交的過程,只說兩階段提交):
    • prepare 階段:將 redo log 對應的事務狀態設定為 prepare,然後將 redo log 重新整理到硬碟;
    • commit 階段:將 binlog 重新整理到磁碟,接著呼叫引擎的提交事務介面,將 redo log 狀態設定為 commit(將事務設定為 commit 狀態後,刷入到磁碟 redo log 檔案);
  8. 至此,一條更新語句執行完成。

相關文章