吴忠躺衫网络科技有限公司

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

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

3天內不再提示

一條SQL更新語句的執行流程1

jf_78858299 ? 來源:蟬沐風的碼場 ? 作者:蟬沐風 ? 2023-03-03 10:02 ? 次閱讀

這是圖解MySQL的第2篇文章,這篇文章會通過一條SQL更新語句的執行流程讓大家清楚地明白:

  • 什么是InnoDB頁?緩存頁又是什么?為什么這么設計?
  • 什么是表空間?不同存儲引擎的表在文件系統的底層表示上有什么區別?
  • Buffer Pool是什么?為什么需要?有哪些我們需要掌握的細節?
  • MySQL的三種日志文件redo日志、undo日志、binlog分別是什么?為什么需要這么多種類型的日志?

正文開始!


之前我們講過了一條SQL查詢語句是怎么去執行的,那么插入(INSERT)、更新(UPDATE)和刪除(DELETE)操作的流程又是什么樣子呢?

其實對于MySQL而言,只有兩種通常意義的操作,一種是Query(查詢),另一種是Update(更新),后者包含了我們平常使用的INSERT、UPDATE和DELETE操作。

那么MySQL的更新流程和查詢流程有什么區別呢?

其實基本的流程是一致的,也要經過 處理連接 、 解析優化 、存儲引擎幾個步驟。主要區別在更新操作涉及到了MySQL更多的細節。

圖片

注:我們接下來的所有描述,針對的都是InnoDB存儲引擎,如果涉及到其他存儲引擎,將會特殊說明

1. 一些需要知道的概念

對于MySQL任何存儲引擎來說,數據都是存儲在磁盤中的,存儲引擎要操作數據,必須先把磁盤中的數據加載到內存中才可以。

那么問題來了,一次性從磁盤中加載多少數據到內存中合適呢?當獲取記錄時,InnoDB存儲引擎需要一條條地把記錄從磁盤中讀取出來嗎?

當然不行!我們知道磁盤的讀寫速度和內存讀寫速度差了幾個數量級,如果我們需要讀取的數據恰好運行在磁盤的不同位置,那就意味著會產生多次I/O操作。

因此,無論是操作系統也好,MySQL存儲引擎也罷,都有一個預讀取的概念。概念的依據便是統治計算機界的局部性原理。

空間局部性:如果當前數據是正在被使用的,那么與該數據空間地址臨近的其他數據在未來有更大的可能性被使用到,因此可以優先加載到寄存器或主存中提高效率

就是當磁盤上的一塊數據被讀取的時候,我們干脆多讀一點,而不是用多少讀多少。

1.1 InnoDB頁

InnoDB存儲引擎將數據劃分為若干個頁,以頁作為磁盤和內存之間交互的最小單位。InnoDB中頁的大小默認為16KB。也就是默認情況下,一次最少從磁盤中讀取16KB的數據到內存中,一次最少把內存中16KB的內容刷新到磁盤上。

圖片

對于InnoDB存儲引擎而言,所有的數據(存儲用戶數據的索引、各種元數據、系統數據)都是以頁的形式進行存儲的。

1.2 表空間

為了更好地管理頁,MySQL又設計了「表空間」的概念。表空間又有很多類型,具體類型我們不需要知道,我們只需要知道,一個表空間可以劃分成很多個InnoDB頁,InnoDB表數據都存儲在某個表空間的頁中。

為了方便我們定位,MySQL貼心地為表空間設計了一個唯一標識——表空間ID(space ID)。同理,InnoDB頁也有自己的唯一編號——頁號(page number)。

因此,我們可以這么認為。給定表空間ID和頁號以及頁的偏移量,我們就可以定位到InnoDB頁的某條記錄,也就是數據庫表的某條記錄。

1.2.1 數據表在文件系統中的表示

為了更好地讓大家理解這個抽象的概念,我創建了名為test的數據庫,在其下分別創建了3張表t_user_innodb,t_user_myisam,t_user_memory,對應的存儲引擎分別為InnoDB、MyISAMMEMORY。

進入MySQL的數據目錄,找到test目錄,看一下test數據庫下所有表對應的本地文件目錄

drwxr-x--- 2 mysql mysql  4096 Jan 26 09:28 .
drwxrwxrwt 6 mysql mysql  4096 Jan 26 09:24 ..
-rw-r----- 1 mysql mysql    67 Jan 26 09:24 db.opt
-rw-r----- 1 mysql mysql  8556 Jan 26 09:28 t_user_innodb.frm
-rw-r----- 1 mysql mysql 98304 Jan 26 09:28 t_user_innodb.ibd
-rw-r----- 1 mysql mysql  8556 Jan 26 09:27 t_user_memory.frm
-rw-r----- 1 mysql mysql     0 Jan 26 09:28 t_user_myisam.MYD
-rw-r----- 1 mysql mysql  1024 Jan 26 09:28 t_user_myisam.MYI
-rw-r----- 1 mysql mysql  8556 Jan 26 09:28 t_user_myisam.frm

1.2.2 InnoDB是如何存儲表數據的

「表空間」是InnoDB存儲引擎獨有的概念。

我們看到t_user_innodb表在數據庫對應的test目錄下會生成以下兩個文件

  • t_user_innodb.frm
  • t_user_innodb.ibd

其中,t_user_innodb.ibd就是t_user_innodb表對應的表空間在文件系統上的表示;t_user_innodb.frm用來描述表的結構,如表有哪些列,列的類型是什么等。

1.2.3 MyISAM是如何存儲表數據的

和InnoDB不同,MyISAM沒有表空間的概念,表的數據和索引全都直接存放在對應的數據庫子目錄下,可以看到t_user_myisam對應了三個文件

  • t_user_myisam.MYD
  • t_user_myisam.MYI
  • t_user_myisam.frm

其中,t_user_myisam.MYD表示表的數據文件,也就是我們實際看到的數據表的內容;t_user_myisam.MYI表示表的索引文件,為該表創建的索引都會存放在這個文件中;t_user_myisam.frm用來描述表的結構。

1.2.4 MEMORY是如何存儲表數據的

MEMORY存儲引擎對應的數據表只有一個描述表結構的文件t_user_memory.frm。

2. 緩沖池Buffer Pool

為了更好的利用局部性原理帶給我們的優勢,InnoDB在處理客戶端請求時,如果需要訪問某個頁的數據,會把該數據所在的頁的全部數據加載到內存中。哪怕是只需要訪問一個頁中的一條數據,也需要加載整個頁。

從磁盤中加載數據到內存中的操作太昂貴了!有什么辦法可以提高數據操作的效率呢?緩存!

為了緩存磁盤的頁,InnoDB在MySQL服務器啟動時會向操作系統申請一片連續的內存區域,這片內存區域就是 Buffer Pool 。

很容易理解,為了更好地緩存頁數據,Buffer Pool對應的一片連續內存空間也被劃分為若干個頁,而且默認情況下,Buffer Pool頁的大小和InnoDB頁大小一樣,都是16KB。為了區分兩種不同的頁,我們將Buffer Pool中的頁面稱為緩沖頁。

圖片

讀取數據的時候,InnoDB先判斷數據是否在Buffer Pool中,如果是,則直接讀取數據進行操作,不用再次從磁盤加載;如果不是,則從磁盤加載到Buffer Pool中,然后讀取數據進行操作。

修改數據的時候,也是將數據先寫到Buffer Pool緩沖頁中,而不是每次更新操作都直接寫入磁盤。當緩沖頁中的數據和磁盤文件不一致的時候,緩沖頁被稱為臟頁。

那么臟頁是什么時候被同步到磁盤呢?

InnoDB中有專門的后臺線程每隔一段時間會把臟頁的多個修改刷新到磁盤上,這個動作叫做「刷臟」。

3. redo日志

3.1 為什么需要redo日志

不定時刷臟又帶來一個問題。如果臟頁的數據還沒有刷新到磁盤上,此時數據庫突然宕機或重啟,這些數據就會丟失。

首先想到的最簡單粗暴的解決方案就是在事務提交之前,把該事務修改的所有頁面都刷新到磁盤。但是上文說過,頁是內存和磁盤交互的最小單位,如果只修改了1個字節,卻要刷新16KB的數據到磁盤上,不得不說太浪費了,此路不通!

所以,必須要有一個持久化的措施。

為了解決這個問題,InnoDB把對所有頁的更新操作(再強調一遍,包含INSERT、UPDATE、DELETE)專門寫入一個日志文件。

當有未同步到磁盤中的數據時,數據庫在啟動的時候,會根據這個日志文件進行數據恢復。我們常說的關系型數據庫的ACID特性中的D(持久性),就是通過這個日志來實現的。

這個日志文件就是大名鼎鼎的 redo日志 。

「re」在英文中的詞根含義是“重新”,redo就是「重新做」的意思,顧名思義就是MySQL根據這個日志文件重新進行操作

圖片

這就出現了一個有意思的問題,刷新磁盤和寫redo日志都是進行磁盤操作,為什么不直接把數據刷新到磁盤中呢?

3.2 磁道尋址

我們需要稍微了解一下磁道尋址的過程。磁盤的構造如下圖所示。

圖片

每個硬盤都有若干個盤片,上圖的硬盤有4個盤片。

每個盤片的盤面上有一圈圈的同心圓,叫做「磁道」。

從圓心向外畫直線,可以將磁道劃分為若干個弧段,每個磁道上一個弧段被稱之為一個「扇區」(右上圖白色部分)。數據是保存在扇區當中的,扇區是硬盤讀寫的最小單元,如果要讀寫數據,必須找到對應的扇區,這個過程叫做「尋址」。

3.2.1 隨機I/O

如果我們需要的數據是隨機分散在磁盤上不同盤片的不同扇區中,那么找到相應的數據需要等到磁臂旋轉到指定的盤片然后繼續尋找對應的扇區,才能找到我們所需要的一塊數據,持續進行此過程直到找完所有數據,這個就是隨機I/O,讀取數據速度非常慢。

3.2.2 順序I/O

假設我們已經找到了第一塊數據,并且其他所需的數據就在這一塊數據之后,那么就不需要重新尋址,可以依次拿到我們所需的數據,這個就叫順序 I/O。

現在回答之前的問題。因為刷臟是隨機I/O,而記錄日志是順序I/O(連續寫的),順序I/O效率更高,本質上是數據集中存儲和分散存儲的區別。因此先把修改寫入日志文件,在保證了內存數據的安全性的情況下,可以延遲刷盤時機,進而提升系統吞吐。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 存儲
    +關注

    關注

    13

    文章

    4355

    瀏覽量

    86177
  • buffer
    +關注

    關注

    2

    文章

    120

    瀏覽量

    30130
  • MySQL
    +關注

    關注

    1

    文章

    829

    瀏覽量

    26743
收藏 人收藏

    評論

    相關推薦

    STM8L執行一條語句大概需要幾個時鐘周期?

    STM8L執行一條語句大概需要幾個時鐘周期
    發表于 05-06 06:16

    DSP執行一條語句的時間

    CPU配置成150M。高頻時鐘75M。 那么執行一條語句的時間是多少呢
    發表于 10-15 11:28

    為什么要動態sql語句?

    為什么要動態sql語句?因為動態sql語句能夠提供些比較友好的機制1、可以使得
    發表于 12-20 06:00

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

    首先肯定是我們的系統通過個數據庫連接發送到了MySQL上,然后肯定會經過SQL接口、解析器、優化器、執行器幾個環節,解析SQL語句,生成
    的頭像 發表于 10-21 10:40 ?2092次閱讀
    MySQL存儲引擎完成<b class='flag-5'>更新語句</b><b class='flag-5'>執行</b>的方法

    select語句和update語句分別是怎么執行

    樣,但是具體的實現還是有區別的。 當然深入了解select和update的具體區別并不是只為了面試,當希望Mysql能夠高效的執行的時候,最好的辦法就是清楚的了解Mysql是如何執行查詢的,只有更加全面的了解
    的頭像 發表于 11-03 09:41 ?3620次閱讀
    select<b class='flag-5'>語句</b>和update<b class='flag-5'>語句</b>分別是怎么<b class='flag-5'>執行</b>的

    一條SQL語句是怎么被執行

    直是想知道一條SQL語句是怎么被執行的,它執行的順序是怎樣的,然后查看總結各方資料,就有了下面
    的頭像 發表于 09-12 09:44 ?1546次閱讀
    <b class='flag-5'>一條</b><b class='flag-5'>SQL</b><b class='flag-5'>語句</b>是怎么被<b class='flag-5'>執行</b>的

    簡述SQL更新語句執行流程1

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

    簡述SQL更新語句執行流程2

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

    一條SQL查詢語句是怎么去執行的?(上)

    MySQL是典型的`C/S架構`(客戶端/服務器架構),客戶端進程向服務端進程發送段文本(MySQL指令),服務器進程進行語句處理然后返回執行結果。
    的頭像 發表于 03-03 09:58 ?431次閱讀
    <b class='flag-5'>一條</b><b class='flag-5'>SQL</b>查詢<b class='flag-5'>語句</b>是怎么去<b class='flag-5'>執行</b>的?(上)

    一條SQL查詢語句是怎么去執行的?(中)

    MySQL是典型的`C/S架構`(客戶端/服務器架構),客戶端進程向服務端進程發送段文本(MySQL指令),服務器進程進行語句處理然后返回執行結果。
    的頭像 發表于 03-03 09:58 ?503次閱讀
    <b class='flag-5'>一條</b><b class='flag-5'>SQL</b>查詢<b class='flag-5'>語句</b>是怎么去<b class='flag-5'>執行</b>的?(中)

    一條SQL查詢語句是怎么去執行的?(下)

    MySQL是典型的`C/S架構`(客戶端/服務器架構),客戶端進程向服務端進程發送段文本(MySQL指令),服務器進程進行語句處理然后返回執行結果。
    的頭像 發表于 03-03 09:58 ?435次閱讀
    <b class='flag-5'>一條</b><b class='flag-5'>SQL</b>查詢<b class='flag-5'>語句</b>是怎么去<b class='flag-5'>執行</b>的?(下)

    一條SQL更新語句執行流程2

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

    sql where條件的執行順序

    。 在深入討論WHERE條件的執行順序之前,先回顧一下一SQL語句執行順序。一條
    的頭像 發表于 11-23 11:31 ?2299次閱讀

    oracle執行sql查詢語句的步驟是什么

    Oracle數據庫是種常用的關系型數據庫管理系統,具有強大的SQL查詢功能。Oracle執行SQL查詢語句的步驟包括編寫
    的頭像 發表于 12-06 10:49 ?1040次閱讀

    單片機中for語句的運用

    語句,它的基本結構如下: for (初始化語句; 條件表達式; 更新語句) {循環體;} for語句執行
    的頭像 發表于 01-05 14:02 ?2618次閱讀
    网上百家乐官网有哪些玩法| 澳门百家乐走势图| 百家乐官网的出牌技巧| 百家乐官网说明| 百家乐官网群b28博你| 百家乐官网的分析| 蓝盾百家乐官网赌城| 百家乐官网博赌场娱乐网规则 | 八宿县| 真人百家乐官网开户须知| 百家乐官网轮盘桌| 百家乐官网怎么押钱| 免费百家乐官网的玩法技巧和规则| 女神百家乐官网的玩法技巧和规则| 24山灶位吉凶歌| 赌场百家乐试玩| 百家乐倍投软件| 属虎与属鼠做生意好吗| 百家乐美食坊| 威尼斯人娱乐场骗人| 足球赌球网| 百家乐官网娱乐求指点呀| 破解百家乐官网视频游戏密码| 利来国际注册| 百家乐官网开户优惠多的平台是哪家 | 威尼斯人娱乐备用网址| 百家乐送錢平臺| 求购百家乐程序| 百家乐官网单注打| 怎么玩百家乐官网的玩法技巧和规则 | 云鼎娱乐场网址| 富田太阳城二期| 日土县| 澳门百家乐官网小游戏| 百家乐官网网址讯博网| 优惠搏百家乐官网的玩法技巧和规则 | 百家乐官网在线投注系统| 百家乐官网大光明影院| 百家乐正式版| 百家乐的胜算法| 百家乐平注常赢玩法技巧|