【大廠面試04期】講講一條MySQL更新語句是怎麼執行的?

流程圖

這是在網上找到的一張流程圖,寫的比較好,大家可以先看圖,然後看詳細閱讀下面的各個步驟。

執行流程:

1.連接驗證及解析

客戶端與MySQL Server建立連接,發送語句給MySQL Server,接收到後會針對這條語句創建一個解析樹,然後進行優化,(解析器知道語句是要執行什麼,會評估使用各種索引的代價,然後去使用索引,以及調節表的連接順序)然後調用innodb引擎的接口來執行語句。

2.寫undo log

innodb 引擎首先開啓事務,對舊數據生成一個UPDATE的語句(如果是INSERT會生成UPDATE語句),用於提交失敗後回滾,寫入undo log,得到回滾指針,並且更新這個數據行的回滾指針和版本號(會設置爲更新的事務id)。

3.從索引中查找數據

根據查詢條件去B+樹中找到這一行數據(如果是唯一性索引,查到第一個數據就可以了(因爲有唯一性約束),如果是普通索引,會把所有數據查找出來。)

4.更新數據

首先判斷數據頁是否在內存中?

4.1 如果數據頁在內存中

先判斷更新的索引是普通索引還是唯一性索引?

4.1.1 普通索引

如果更新的索引是普通索引,直接更新內存中的數據頁

4.1.2 唯一性索引

如果更新的索引是唯一性索引,判斷更新後是否會破壞數據的唯一性,不會的話就更新內存中的數據頁。

4.2 如果數據頁不在內存中

先判斷更新的索引是普通索引還是唯一性索引?

4.2.1 普通索引

如果是更新的索引是普通索引,將對數據頁的更新操作記錄到change buffer,change buffer會在空閒時異步更新到磁盤。

4.2.2 唯一性索引

如果是更新的索引是唯一性索引,因爲需要保證更新後的唯一性,所以不能延遲更新,必須把數據頁從磁盤加載到內存,然後判斷更新後是否會數據衝突,不會的話就更新數據頁。

5.寫undo log(prepare狀態)

將對數據頁的更改寫入到redo log,將redo log設置爲prepare狀態。

6.寫bin log(commit狀態),提交事務

通知MySQL server已經更新操作寫入到redo log 了,隨時可以提交,將執行的SQL寫入到bin log日誌,將redo log改成commit狀態,事務提交成功。(一個事務是否執行成功的判斷依據是是否在bin log中寫入成功。寫入成功後,即便MySQL Server崩潰,之後恢復時也會根據bin log, redo log進行恢復。具體可以看看下面的崩潰恢復原則)

補充資料:

二段提交制是什麼?

更新時,先改內存中的數據頁,將更新操作寫入redo log日誌,此時redo log進入prepare狀態,然後通知MySQL Server執行完了,隨時可以提交,MySQL Server將更新的SQL寫入bin log,然後調用innodb接口將redo log設置爲提交狀態,更新完成。
如果只是寫了bin log就提交,那麼忽然發生故障,主節點可以根據redo log恢復數據到最新,但是主從同步時會丟掉這部分更新的數據。
如果只是寫binlog,然後寫redo log,如果忽然發生故障,主節點根據redo log恢復數據時就會丟掉這部分數據。
MySQL崩潰後,事務恢復時的判斷規則是怎麼樣的?(以redolog是否commit或者binlog是否完整來確定)
如果 redo log 裏面的事務是完整的,也就是已經有了 commit 標識,則直接提交;

如果 redo log 裏面的事務只有完整的 prepare,則判斷對應的事務 binlog 是否存在並完整:a. 如果是,則提交事務;b. 否則,回滾事務。

undo log是什麼?

undo log主要是保證事務的原子性,事務執行失敗就回滾,用於在事務執行失敗後,對數據回滾。undo log是邏輯日誌,記錄的是SQL。(可以認爲當delete一條記錄時,undo log中會記錄一條對應的insert記錄,反之亦然,當update一條記錄時,它記錄一條對應相反的update記錄。)
在事務提交後,undo log日誌不會立即刪除,會放到一個待刪除的鏈表中,有purge線程判斷是否有其他事務在使用上一個事務之前的版本信息,然後決定是否可以清理,簡單的來說就是前面的事務都提交成功了,這些undo才能刪除。
change buffer是什麼(就是將更新數據頁的操作緩存下來)
在更新數據時,如果數據行所在的數據頁在內存中,直接更新內存中的數據頁。
如果不在內存中,爲了減少磁盤IO的次數,innodb會將這些更新操作緩存在change buffer中,在下一次查詢時需要訪問這個數據頁時,在執行change buffer中的操作對數據頁進行更新。
適合寫多讀少的場景,因爲這樣即便立即寫了,也不太可能會被訪問到,延遲更新可以減少磁盤I/O,只有普通索引會用到,因爲唯一性索引,在更新時就需要判斷唯一性,所以沒有必要。

redo log 是什麼?

redo log就是爲了保證事務的持久性。因爲change buffer是存在內存中的,萬一機器重啓,change buffer中的更改沒有來得及更新到磁盤,就需要根據redo log來找回這些更新。
優點是減少磁盤I/O次數,即便發生故障也可以根據redo log來將數據恢復到最新狀態。
缺點是會造成內存髒頁,後臺線程會自動對髒頁刷盤,或者是淘汰數據頁時刷盤,此時收到的查詢請求需要等待,影響查詢。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章