1. 程式人生 > >02 | 日誌系統:一條SQL更新語句是如何執行的?

02 | 日誌系統:一條SQL更新語句是如何執行的?

#<-- 該文章借鑑林曉斌老師mysql實戰45講 ->

一條SQL更新語句是如何執行的?

  1. 更新是建立在查詢之上的,可以說更新==查詢+修改,所以更新操作也會走一遍查詢語句的流程.

  2. mysql的更新操作涉及到兩個重要日誌檔案:redo log(重做日誌)和 binlog(歸檔日誌):
    a. redo log 是屬於innodb引擎的,myisam引擎不存在redo log 所以這也是為啥innodb擁有事務功能,而myisam沒有! 當一條記錄需要更新的時候,innodb引擎會先把記錄寫到redo log中,並更新記憶體,這個時候對客戶端來說更新操作就算是完成了,innodb引擎會在系統空閒的時候將redo log中的操作更新到磁碟中
    (注意:雖然redo log 和 bin log,為了快速響應SQL充當了粉板,不過它們本身也是檔案,在進行日誌記錄的時候也需要讀寫磁碟不過日誌檔案是順序寫,不需要定址,而更新資料需要定址,所以寫日誌效率更高)

    b. redo log 的檔案個數和大小是可以配置的,並且記憶體空間可以迴圈利用,存在於data目錄中,以ib_logfile[number]方式命名,例如 ib_logfile[0]

    c. binlog屬於服務層,只能用於歸檔,binlog是二進位制格式,形式為mysql-bin.000001, mysql-bin.000001 等

  3. 兩種日誌的比較:
    a. redo log 是innodb特有的,二binlog屬於Server層,所有引擎都可以使用

    b. redo log是物理日誌,記錄的是“在某個資料頁上做了什麼修改”,有了redo log 即使資料庫異常重啟,之前提交的資料也不會丟失,這個能力成為crash-safe;binlog是邏輯日誌,記錄的是這個語句的原始邏輯 ,假如你需要將資料庫恢復到一週前的狀態就需要用到binlog了 ;binlog有兩種模式,statement 格式的話是記sql語句, row格式會記錄行的內容,記兩條,更新前和更新後都有;

    c. redo log是迴圈寫的,例如配置redo log 數量為兩個大小為1G,當第二個寫完的時候innodb引擎會將第一個日誌檔案部門空間的日誌寫入磁碟並擦除,以供迴圈使用
    在這裡插入圖片描述

  4. update student set name=‘zhangqi’ where id=2的執行流程:

    a. 執行器先找儲存引擎取id為2的記錄. 如果id=2的記錄所存在的資料頁剛好在記憶體中,則直接返回給執行器,否則需要從磁碟將記錄載入到記憶體再返回給執行器;

    b. 執行器拿到這條記錄後將name改為‘zhangqi’,得到一條新的記錄,然後再將新得到的記錄返回給引擎;

    c. 引擎將得到的記錄更新到記憶體中,並寫入redo log中(寫入磁碟),此時redo log處於perpare狀態,引擎將此狀態通知給執行器;

    d. 執行器接收引擎通知的perpare狀態後,生成更新操作的binlog,並寫入磁碟,然後再調取引擎的提交事務介面;

    e. 引擎將redo log 改為commit狀態,寫入磁碟,更新完成

    f. 下圖為SQL update T set c=c+1 where ID=2; 的執行流程,其中深色框在執行器中執行,淺色則在引擎中.
    在這裡插入圖片描述

  5. 為啥redo log 分兩階段提交?
    目的:確保redo log 和 binlog保持邏輯上的一致
    假如你最近的一次資料庫全量備份是一週前,假如你現在需要恢復到三天前的狀態

    a. 先寫binlog,後寫redo log。也就是說更新語句寫完binlog的時候,資料庫異常重啟,這個時候資料庫中 id 為2 的記錄name值並沒有改為 ‘zhangqi’,當你需要恢復到 三天前的狀態時需要用到binlog,這個時候就會將 id為2的記錄name值改為 ‘zhangqi’, 而我們知道實際並沒有修改.

    b. 先寫redo log,後寫binlog。 也就是說更新語句寫完redo log的時候,資料庫異常重啟,這個時候資料庫中 id 為2 的記錄name值已經改為 ‘zhangqi’,當你需要恢復到三天前的狀態時需要用到binlog,這個時候id為2的記錄name值並沒有改為 ‘zhangqi’, 而我們知道實際上已經修改.

    c. 總結:當資料庫需要還原之前某一個狀態的時候,需要確保redo log 和 binlog 保持邏輯上的一致.

    d. redo log 和 bin log 通過事務ID進行對應

  6. Binlog如果已經接受,那麼redolog是prepare, binlog已經完整了對吧,這時候崩潰恢復過程會認可這個事務,提交掉。

  7. Redo log不是記錄資料頁“更新之後的狀態”,而是記錄這個頁 “做了什麼改動”。
    Binlog有兩種模式,statement 格式的話是記sql語句, row格式會記錄行的內容,記兩條,更新前和更新後都有。