17.Sql是如何執行的
navyum發表於2024-10-28
UPDATE t_user SET name =
‘x’ WHERE id = 1
- 執行器負責具體執行,會呼叫儲存引擎的介面,透過主鍵索引樹搜尋獲取 id
= 1 這一行記錄:
- 如果 id=1 這一行所在的資料頁本來就在 buffer pool
中,就直接返回給執行器更新(id非唯一索引的前提下);
- 如果記錄不在 buffer pool,將資料頁從磁碟讀入到 buffer
pool,返回記錄給執行器。
- 執行器得到聚簇索引記錄後,會看一下更新前的記錄和更新後的記錄是否一樣:
- 如果一樣的話就不進行後續更新流程;
- 如果不一樣的話就把更新前的記錄和更新後的記錄都當作引數傳給 InnoDB
層,讓 InnoDB 真正的執行更新記錄的操作;
- 開啟事務,InnoDB 層更新記錄前,首先要記錄相應的
undo log
,因為這是更新操作,需要把被更新的列的舊值記下來,也就是要生成一條
undo log
,undo log 會寫入 Buffer Pool 中的 Undo
頁面,不過在記憶體修改該 Undo 頁面後,需要記錄對應的 redo log。
- 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持久化)
- 至此,一條記錄更新完了。
- 在一條更新語句執行完成後,然後開始記錄該語句對應的
binlog
,此時記錄的 binlog 會被儲存到 binlog
cache,並沒有重新整理到硬碟上的 binlog
檔案,在事務提交時才會統一將該事務執行過程中的所有 binlog
重新整理到硬碟,然後進行第二階段的提交。
- 事務提交(為了方便說明,這裡不說組提交的過程,只說兩階段提交):
- prepare 階段:將 redo log 對應的事務狀態設定為 prepare,然後將 redo
log 重新整理到硬碟;
- commit 階段:將 binlog 重新整理到磁碟,接著呼叫引擎的提交事務介面,將
redo log 狀態設定為 commit(將事務設定為 commit 狀態後,刷入到磁碟 redo
log 檔案);
- 至此,一條更新語句執行完成。