<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          面試官:你說說一條更新SQL的執(zhí)行過程?

          共 2203字,需瀏覽 5分鐘

           ·

          2021-08-18 10:12

          在上一篇《面試官:你說說一條查詢SQL的執(zhí)行過程?》中描述了Mysql的架構分層,通過解析器、優(yōu)化器和執(zhí)行引擎完成一條SQL查詢的過程,那這一篇續(xù)上繼續(xù)說明一條更新SQL的執(zhí)行過程。

          對于一個SQL語句的更新來說,前面的流程都可以說類似的,通過解析器進行語法分析,優(yōu)化器優(yōu)化,執(zhí)行引擎去執(zhí)行,這個都沒有什么問題,重點在于多了一點東西,那就是redo_logundo_logbinlog

          執(zhí)行流程大致如下:

          1. 首先客戶端發(fā)送請求到服務端,建立連接。
          2. 服務端先看下查詢緩存,對于更新某張表的SQL,該表的所有查詢緩存都失效。
          3. 接著來到解析器,進行語法分析,一些系統(tǒng)關鍵字校驗,校驗語法是否合規(guī)。
          4. 然后優(yōu)化器進行SQL優(yōu)化,比如怎么選擇索引之類,然后生成執(zhí)行計劃。
          5. 執(zhí)行引擎去存儲引擎查詢需要更新的數(shù)據(jù)。
          6. 存儲引擎判斷當前緩沖池中是否存在需要更新的數(shù)據(jù),存在就直接返回,否則去從磁盤加載數(shù)據(jù)。
          7. 執(zhí)行引擎調用存儲引擎API去更新數(shù)據(jù)。
          8. 存儲引擎更新數(shù)據(jù),同時寫入undo_log、redo_log信息。
          9. 執(zhí)行引擎寫binlog,提交事務,流程結束。

          可以看到相比于查詢流程,實際上更新多了關于undo_log和redo_log的流程,接下來再具體探討一下這幾個流程的執(zhí)行過程是什么樣子。

          redo_log

          redo_log按照字面翻譯稱為重做日志,是InnoDB存儲引擎特有的,用于保證事務的原子性和持久性。怎么理解呢?簡單來說就是保存我們執(zhí)行的更新語句的記錄,如果服務器或者Mysql宕機,通過redo_log可以恢復更新的數(shù)據(jù)。

          按照上述流程來舉例的話,比如update user set age=20 where id=1這樣的簡單更新SQL,我們不管執(zhí)行引擎怎么拿到的數(shù)據(jù),不管是從緩沖池拿的還是磁盤拿到的,這條現(xiàn)在數(shù)據(jù)都在緩沖池里面,然后去緩沖池的數(shù)據(jù)把age改成10。

          緩沖池內存中的數(shù)據(jù)已經(jīng)更新好了,那么接下來就該開始寫redo_log了,只是redo_log也不是直接寫文件的,一般都是這樣對吧,直接寫的話性能太差了,所以就有redo_log_buffer叫做redo_log緩沖。

          在寫redo_log的時候先把數(shù)據(jù)寫到redo_log緩沖區(qū),然后異步寫入磁盤,很顯然,極端情況下會有丟失數(shù)據(jù)的可能。

          控制這個刷盤策略的的參數(shù)叫做innodb_flush_log_at_trx_commit

          這個參數(shù)有3個值:0|1|2,默認的話是1。

          0代表提交事務時不會寫入磁盤,這樣的話性能當然最好,但是在Mysql宕機的情況會丟失上一秒的事務的數(shù)據(jù)。

          1代表提交事務一定會進行一次刷盤,同步當然性能最差,但是也最安全。

          2代表寫入文件系統(tǒng)的緩存,不進行刷盤。這個選項性能略差于1,Mysql宕機的話對數(shù)據(jù)沒有任何影響,只有在操作系統(tǒng)宕機才會丟失數(shù)據(jù),這種情況下默認Mysql每秒會執(zhí)行一次刷盤。

          使用0或者2雖然提高了性能,但是變相的也喪失了事務的持久性。

          undo_log

          重做日志保證了事務的持久性,保證能夠在宕機后恢復事務的數(shù)據(jù),那么另外一種情況就是事務在需要回滾的時候怎么辦?這時候就是undo_log的作用了,它保證了事務的一致性。

          對于undo_log來說,簡單理解就是做了逆向操作。

          比如insert一條數(shù)據(jù),就對應生成deleteupdate語句則生成相反的更新語句,這樣做到將數(shù)據(jù)修改回之前的狀態(tài)。

          binlog

          binlog稱為二進制日志,大家都很熟悉,記錄了改變數(shù)據(jù)庫的那些SQL語句,對于這里來說,更新語句當然是了。

          通過不同于redo_log是獨屬于存儲引擎獨有的東西,binlog則是Mysql本身產(chǎn)生的日志。

          不同于redo_log是物理日志,binlog和undo_log都屬于邏輯日志。

          這有什么區(qū)別呢?

          簡單來說,邏輯日志可以認為就是存儲的SQL本身,而物理日志看看redo_log存儲的是啥就知道了,關于page_id頁ID,offset偏移量啊這些東西,記錄的是對頁的修改。

          另外物理日志可以保證冪等性,而邏輯日志則不一定能,除非本身SQL就是冪等的。

          上面我們提到了redo_log的刷盤策略,binlog就和它非常類似了,控制參數(shù)是sync_binlog

          默認值為0,相當于是innodb_flush_log_at_trx_commit的值為2,由文件系統(tǒng)控制,同樣如果服務器宕機,binlog丟失,當然我們也可以改成1,就和redo_log的效果是一樣,每1次事務提交都同步寫入磁盤。

          事務

          為了保證寫redo_log和binlog的一致性,實際采用了二階段提交的方式。

          prepare階段:根據(jù)innodb_flush_log_at_trx_commit設置的刷盤策略決定是否寫入磁盤,標記為prepare狀態(tài)。

          commit階段:寫入binlog日志,事務標記為提交狀態(tài)。

          總結

          ·················END·················



          往期推薦

          聽說你對explain 很懂?

          面試官:你說說一條查詢SQL的執(zhí)行過程?| 文末送書

          不管卷不卷,面試還是得問問你G1原理!


          瀏覽 113
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  www.伊人大香蕉 | 蜜桃久久网 | 五月天婷婷社区 | 九色视频自拍 | 在线亚洲欧洲 |