BAT面試題:一條MySQL更新語句是怎麼執行的?

timg.jpg

做者:NotFound9
連接:
https://www.cnblogs.com/notfo...html

這是在網上找到的一張流程圖,寫的比較好,你們能夠先看圖,而後看詳細閱讀下面的各個步驟。segmentfault

一條MySQL更新語句是怎麼執行的?

執行流程:

1.鏈接驗證及解析

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

2.寫undo log

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

3.從索引中查找數據

根據查詢條件去B+樹中找到這一行數據(若是是惟一性索引,查到第一個數據就能夠了(由於有惟一性約束),若是是普通索引,會把全部數據查找出來。)優化

4.更新數據

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

4.1 若是數據頁在內存中

先判斷更新的索引是普通索引仍是惟一性索引?線程

4.1.1 普通索引

若是更新的索引是普通索引,直接更新內存中的數據頁指針

4.1.2 惟一性索引

若是更新的索引是惟一性索引,判斷更新後是否會破壞數據的惟一性,不會的話就更新內存中的數據頁。日誌

4.2 若是數據頁不在內存中

先判斷更新的索引是普通索引仍是惟一性索引?server

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來將數據恢復到最新狀態。缺點是會形成內存髒頁,後臺線程會自動對髒頁刷盤,或者是淘汰數據頁時刷盤,此時收到的查詢請求須要等待,影響查詢。

若有錯誤或其它問題,歡迎小夥伴留言評論、指正。若有幫助,歡迎點贊+轉發分享。

歡迎你們關注民工哥的公衆號:民工哥技術之路
image.png

相關文章
相關標籤/搜索