0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

簡述SQL更新語句的執(zhí)行流程2

jf_78858299 ? 來源:蟬沐風的碼場 ? 作者:蟬沐風的碼場 ? 2023-02-14 15:40 ? 次閱讀

4. undo日志

undo log(撤銷日志或回滾日志)記錄了事務(wù)發(fā)生之前的數(shù)據(jù)狀態(tài),分為insert undo log和update undo log。

如果修改數(shù)據(jù)時出現(xiàn)異常,可以用 undo log來實現(xiàn)回滾操作(保持原子性)。可以理解為undo日志記錄的是反向的操作,比如INSERT操作會記錄DELETE,UPDATE會記錄UPDATE之前的值,和redo日志記錄在哪個物理頁面做了什么操作不同,所以這是一種邏輯格式的日志。

undo日志和redo日志與事務(wù)密切相關(guān),被統(tǒng)稱為「事務(wù)日志」。

圖片

關(guān)于undo日志,我們目前只需要了解這么多即可

5. SQL更新語句的執(zhí)行總結(jié)——初版

有了事務(wù)日志之后,我們來簡單總結(jié)一下更新操作的流程,這是一個簡化的過程。

name 原值是chanmufeng。

update t_user_innodb set name ='chanmufeng1994' where id = 1;
  1. 事務(wù)開始,從內(nèi)存(Buffer Pool)或磁盤取到包含這條數(shù)據(jù)的數(shù)據(jù)頁,返回給 Server 的執(zhí)行器;
  2. Server 的執(zhí)行器修改數(shù)據(jù)頁的這一行數(shù)據(jù)的值為 chanmufeng1994;
  3. 記錄 name=chanmufeng 到undo log;
  4. 記錄 name=chanmufeng1994到redo log;
  5. 調(diào)用存儲引擎接口,記錄數(shù)據(jù)頁到Buffer Pool(修改 name=penyuyan);
  6. 事務(wù)提交。

6. binlog日志

之前我們講過,從MySQL整體架構(gòu)來看,其實可以分成兩部分

  • Server 層,它主要做的是 MySQL功能層面的事情,比如處理連接、解析優(yōu)化等;
  • 存儲引擎層,負責存儲相關(guān)的具體事宜。

redo日志是InnoDB存儲引擎特有的日志,而Server層也有自己的日志,稱為 binlog(歸檔日志),它可以被所有存儲引擎使用。

6.1 為什么有了redo日志還需要 binlog?

我想你可能會問出這個問題,實際上,更準確的問法是為什么有了binlog還需要有redo日志?主要有以下幾個原因。

  1. 因為最開始MySQL里并沒有InnoDB存儲引擎。MySQL自帶的引擎是MyISAM,但是 MyISAM沒有崩潰恢復(fù)的能力,InnoDB后來以插件的形式被引入,順便帶來了redo日志;
  2. binlog日志是用來歸檔的,binlog以事件的形式記錄了所有的 DDL和 DML 語句(因為它記錄的是操作而不是 數(shù)據(jù)值,屬于邏輯日志),但是不具備宕機恢復(fù)的功能,因為可能沒有來得及刷新臟頁,造成臟頁數(shù)據(jù)的丟失,而這些操作也沒有保存到binlog中從而造成數(shù)據(jù)丟失;
  3. binlog記錄的是關(guān)于一個事務(wù)的具體操作內(nèi)容,即該日志是邏輯日志。而redo日志記錄的是關(guān)于每個頁的更改的物理情況。功能壓根不是一回事兒。

6.2 binlog日志的作用

6.2.1 主從復(fù)制

binlog是實現(xiàn)MySQL主從復(fù)制功能的核心組件。

master節(jié)點會將所有的寫操作記錄到binlog中,slave節(jié)點會有專門的I/O線程讀取master節(jié)點的binlog,將寫操作同步到當前所在的slave節(jié)點。

圖片

6.2.2 數(shù)據(jù)恢復(fù)

假如你在閱讀這篇文章的時候覺得我寫得實在太好,拍案叫絕的時候一不小心把公司的數(shù)據(jù)庫給刪了,你該怎么做才能恢復(fù)到你刪庫之前的那個時刻的狀態(tài)?

這個時候就要用到binlog了,前提是binlog沒有被刪除,否則,神仙也救不了你了。

通常情況下,公司會定期對數(shù)據(jù)庫進行全量備份,可能隔一個月,一周,甚至可能每天都備份一次。運氣好的話你可以使用前一天的全量備份,恢復(fù)到前一天的某時刻狀態(tài)(或者一周、一月之前),然后從全量備份的時刻開始,從binlog中提取該時刻之后(前提是你的binlog里面存放了這段時間的日志)的所有寫操作(當然,你得過濾掉你的刪庫操作),然后進行操作回放就可以了。

是不是很簡單?

問題又來了。再看一眼我們的更新語句。

update t_user_innodb set name ='chanmufeng1994' where id = 1;

假如這條更新語句已經(jīng)被寫入到了redo日志,還沒來得及寫binlog的時候,MySQL宕機重啟了,我們看一下會發(fā)生什么。

因為redo日志可以在重啟的時候用于恢復(fù)數(shù)據(jù),所以寫入磁盤的是chanmufeng1994。但是binlog里面沒有記錄這個邏輯日志,所以這時候用binlog去恢復(fù)數(shù)據(jù)或者同步到從庫,就會出現(xiàn)數(shù)據(jù)不一致的情況。

所以在寫兩個日志的情況下,就類似于「分布式事務(wù)」的情況,如果你不清楚分布式事務(wù)是個什么東西也沒關(guān)系,我在之后的文章會介紹到。能夠明確的就是redo日志和binlog日志如果單純依次進行提交是無法保證兩種日志都寫成功或者都寫失敗的。

我們需要「兩階段提交」。

6.3 兩階段提交

兩階段提交不是MySQL的專利,兩階段提交是一種跨系統(tǒng)維持數(shù)據(jù)邏輯一致性的常見方案,尤其在分布式事務(wù)上,所以請讀者重點體會思想

我們把redo日志的提交分成兩步,兩步中redo日志的狀態(tài)分別是preparecommit。步驟如下

  1. InnoDB存儲引擎將更改更新到內(nèi)存中后,同時將這個更新操作記錄到redo日志里面,此時redo日志處于prepare狀態(tài);
  2. 執(zhí)行器生成這個操作的binlog,并將binlog刷盤;
  3. 執(zhí)行器調(diào)用InnoDB的提交事務(wù)接口,InnoDB把剛剛寫入的redo日志改成commit狀態(tài)。至此,所有操作完成。

圖片

加上兩階段提交之后我們再來看一下SQL更新語句的執(zhí)行流程。

7. SQL更新語句的執(zhí)行總結(jié)——終版

圖片

  1. 客戶端發(fā)送更新命令到MySQL服務(wù)器,經(jīng)過處理連接、解析優(yōu)化等步驟;
  2. Server層向InnoDB存儲引擎要id=1的這條記錄;
  3. 存儲引擎先從緩存中查找這條記錄,有的話直接返回,沒有則從磁盤加載到緩存中然后返回;
  4. Server層執(zhí)行器修改這條記錄的name字段值;
  5. 存儲引擎更新修改到內(nèi)存中;
  6. 存儲引擎記錄redo日志,并將狀態(tài)設(shè)置為prepare狀態(tài);
  7. 存儲引擎通知執(zhí)行器,修改完畢,可以進行事務(wù)提交;
  8. Server先寫了個binlog;
  9. Server提交事務(wù);
  10. 存儲引擎將redo日志中和當前事務(wù)相關(guān)的記錄狀態(tài)設(shè)置為commit狀態(tài)。
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
收藏 人收藏

    評論

    相關(guān)推薦

    為什么要動態(tài)sql語句?

    為什么要動態(tài)sql語句?因為動態(tài)sql語句能夠提供一些比較友好的機制1、可以使得一些在編譯過程中無法獲得完整的sql
    發(fā)表于 12-20 06:00

    數(shù)據(jù)庫SQL語句電子教程

    電子發(fā)燒友為您提供了數(shù)據(jù)庫SQL語句電子教程,幫助您了解數(shù)據(jù)庫 SQL語句 ,學習讀懂數(shù)據(jù)庫SQL語句
    發(fā)表于 07-14 17:09 ?0次下載

    sql語句實例講解

    SQL是用來存取關(guān)系數(shù)據(jù)庫的語言,具有查詢、操縱、定義和控制關(guān)系型數(shù)據(jù)庫的四方面功能。常見的關(guān)系數(shù)據(jù)庫有Oracle,SQLServer,DB2,Sybase。開源不收費的有MYSQL,SQLLite等。今天我們主要以MYSQL為例子,講解
    發(fā)表于 11-17 12:39 ?8997次閱讀
    <b class='flag-5'>sql</b><b class='flag-5'>語句</b>實例講解

    MySQL存儲引擎完成更新語句執(zhí)行的方法

    首先肯定是我們的系統(tǒng)通過一個數(shù)據(jù)庫連接發(fā)送到了MySQL上,然后肯定會經(jīng)過SQL接口、解析器、優(yōu)化器、執(zhí)行器幾個環(huán)節(jié),解析SQL語句,生成執(zhí)行
    的頭像 發(fā)表于 10-21 10:40 ?1977次閱讀
    MySQL存儲引擎完成<b class='flag-5'>更新語句</b><b class='flag-5'>執(zhí)行</b>的方法

    select語句和update語句分別是怎么執(zhí)行

    最近有粉絲面試互聯(lián)網(wǎng)公司被問到:你知道select語句和update語句分別是怎么執(zhí)行的嗎?,要我寫一篇這兩者執(zhí)行SQL
    的頭像 發(fā)表于 11-03 09:41 ?3411次閱讀
    select<b class='flag-5'>語句</b>和update<b class='flag-5'>語句</b>分別是怎么<b class='flag-5'>執(zhí)行</b>的

    SQL后悔藥,SQL性能優(yōu)化和SQL規(guī)范優(yōu)雅

    =10086orage=18; 2、操作delete或者update語句,加個limit(SQL后悔藥) 在執(zhí)行刪除或者更新語句,盡量加上l
    的頭像 發(fā)表于 11-14 09:54 ?1738次閱讀

    一條SQL語句是怎么被執(zhí)行

    一直是想知道一條SQL語句是怎么被執(zhí)行的,它執(zhí)行的順序是怎樣的,然后查看總結(jié)各方資料,就有了下面這一篇博文了。 本文將從MySQL總體架構(gòu)---》查詢
    的頭像 發(fā)表于 09-12 09:44 ?1441次閱讀
    一條<b class='flag-5'>SQL</b><b class='flag-5'>語句</b>是怎么被<b class='flag-5'>執(zhí)行</b>的

    簡述SQL更新語句執(zhí)行流程1

    之前我們講過了一條SQL查詢語句是如何執(zhí)行的,那么插入(INSERT)、更新(UPDATE)和刪除(DELETE)操作的流程又是什么樣子呢?
    的頭像 發(fā)表于 02-14 15:40 ?536次閱讀
    <b class='flag-5'>簡述</b><b class='flag-5'>SQL</b><b class='flag-5'>更新語句</b>的<b class='flag-5'>執(zhí)行</b><b class='flag-5'>流程</b>1

    一條SQL更新語句執(zhí)行流程1

    什么是InnoDB頁?緩存頁又是什么?為什么這么設(shè)計? * 什么是表空間?不同存儲引擎的表在文件系統(tǒng)的底層表示上有什么區(qū)別? * Buffer Pool是什么?為什么需要?有哪些我們需要掌握的細節(jié)? * MySQL
    的頭像 發(fā)表于 03-03 10:02 ?497次閱讀
    一條<b class='flag-5'>SQL</b><b class='flag-5'>更新語句</b>的<b class='flag-5'>執(zhí)行</b><b class='flag-5'>流程</b>1

    一條SQL更新語句執(zhí)行流程2

    什么是InnoDB頁?緩存頁又是什么?為什么這么設(shè)計? * 什么是表空間?不同存儲引擎的表在文件系統(tǒng)的底層表示上有什么區(qū)別? * Buffer Pool是什么?為什么需要?有哪些我們需要掌握的細節(jié)? * MySQL
    的頭像 發(fā)表于 03-03 10:02 ?369次閱讀
    一條<b class='flag-5'>SQL</b><b class='flag-5'>更新語句</b>的<b class='flag-5'>執(zhí)行</b><b class='flag-5'>流程</b><b class='flag-5'>2</b>

    oracle更新clob字段sql語句

    在Oracle中,更新CLOB字段可以使用UPDATE語句。CLOB字段是用于存儲大量文本數(shù)據(jù)的數(shù)據(jù)類型,可以存儲最多4GB的數(shù)據(jù)。下面是一些詳細的信息和示例。 UPDATE語法: UPDATE 表
    的頭像 發(fā)表于 11-21 11:29 ?3536次閱讀

    sql where條件的執(zhí)行順序

    SQL語句中的WHERE條件是用來篩選數(shù)據(jù)的,它決定了哪些數(shù)據(jù)會被返回給用戶。WHERE條件的執(zhí)行順序是影響SQL語句性能的一個重要因素,正
    的頭像 發(fā)表于 11-23 11:31 ?1863次閱讀

    oracle執(zhí)行sql查詢語句的步驟是什么

    Oracle數(shù)據(jù)庫是一種常用的關(guān)系型數(shù)據(jù)庫管理系統(tǒng),具有強大的SQL查詢功能。Oracle執(zhí)行SQL查詢語句的步驟包括編寫SQL
    的頭像 發(fā)表于 12-06 10:49 ?774次閱讀

    Oracle如何執(zhí)行sql腳本文件

    如何使用Oracle來執(zhí)行SQL腳本文件。 一、什么是SQL腳本文件 SQL腳本文件是一個包含了一系列SQL
    的頭像 發(fā)表于 12-06 10:51 ?5495次閱讀

    單片機中for語句的運用

    語句,它的基本結(jié)構(gòu)如下: for (初始化語句; 條件表達式; 更新語句) {循環(huán)體;} for語句執(zhí)行
    的頭像 發(fā)表于 01-05 14:02 ?1517次閱讀