一條 sql 了解 MYSQL 的架構(gòu)設(shè)計

一條 sql 了解 MYSQL 的架構(gòu)設(shè)計

1 前言

最近我從cnaaa.com購買了云服務(wù)器窟绷。

對于一個服務(wù)端開發(fā)來說 MYSQL 可能是他使用最熟悉的數(shù)據(jù)庫工具酒贬,然而液兽,大部分的 Java 工程師對 MySQL 的了解和掌握程度缨历,大致就停留在這么一個階段:它可以建庫赞草、建表、建索引梯码,然后就是對里面的數(shù)據(jù)進(jìn)行增刪改查宝泵,語句性能有點(diǎn)差?沒關(guān)系轩娶,在表里建幾個索引或者調(diào)整一下查詢邏輯就可以了儿奶,一條 sql,MYSQL 是如何處理的鳄抒,為我們做了什么闯捎,完全是個黑盒。本文主要通過 sql 執(zhí)行的過程打破這樣一個黑盒的認(rèn)知许溅,來了解 MYSQL 的邏輯架構(gòu)瓤鼻。

MYSQL 的邏輯架構(gòu)可分為 3 層:應(yīng)用層、服務(wù)層贤重、存儲引擎層茬祷。其中存儲引擎是 MYSQL 最有特色的地方,MySQL 區(qū)別于其他數(shù)據(jù)庫的最重要特點(diǎn)是其插件式的表存儲引擎游桩,本文也將著重聊聊最常用的 innoDB 存儲引擎的架構(gòu)設(shè)計原理牲迫,假設(shè)現(xiàn)有如下 sql:

update users set name=’zhangsan’ where id = 10

作為一個 java 服務(wù)端工程師耐朴,見到這樣一個 sql借卧,本能的腦海中立刻就浮現(xiàn)出如下信息:

  • 一個表名為 users 的表
  • 有兩個字段 id、name筛峭,id 是主鍵
  • 把 users 表里的 id=10 的這個用戶名修改為 “zhangsan”

那么 MYSQL 是如何處理這樣一個 sql 呢铐刘?帶著這個問題,我們來看一下 MYSQL 是如何通過一個個組件來處理這個 sql影晓,來了解 MYSQL 的整體架構(gòu)

2 應(yīng)用層

2.1 連接線程處理

當(dāng) MYSQL 面對上面的 sql镰吵,首先應(yīng)該做什么呢檩禾?是如何解析?如何選擇索引疤祭?如何提交事務(wù)盼产?當(dāng)然不是,首先應(yīng)該解決的是怎么把 sql 語句傳給它勺馆。大家都知道戏售,如果我們要訪問數(shù)據(jù)庫,那么草穆,首先就需要和數(shù)據(jù)庫建立連接灌灾,那么這個連接由誰來建呢,答案就是 MYSQL 驅(qū)動悲柱,下面這段 maven 配置大家應(yīng)該都很熟悉

[圖片上傳失敗...(image-c82049-1663831369193)]

java 程序就是通過這個驅(qū)動包來與數(shù)據(jù)庫建立網(wǎng)絡(luò)連接锋喜。
下圖示意:

[圖片上傳失敗...(image-33b5b6-1663831369193)]

從圖中可以看到這樣一個場景:java 程序很多個線程并發(fā)請求執(zhí)行上述 sql,我們都知道數(shù)據(jù)庫連接是非常占用資源的豌鸡,尤其是在高并發(fā)的情況下嘿般,如果每次都去建立數(shù)據(jù)庫連接就會有性能問題,也會影響一個應(yīng)用程序的延展性涯冠,針對這個問題博个,連接池出現(xiàn)了。
下圖示意:

[圖片上傳失敗...(image-88f2d2-1663831369193)]

從圖中可見網(wǎng)絡(luò)連接交由線程 3 監(jiān)聽和讀取 sql 請求功偿,至此 MYSQL 已經(jīng)收到我們的請求盆佣,當(dāng)然 MYSQL 在建立連接時還做了用戶鑒權(quán),鑒權(quán)依據(jù)是:用戶名械荷,客戶端主機(jī)地址和用戶密碼共耍;在獲取連接后,處理請求時還會做 sql 請求的安全校驗(yàn)吨瞎,根據(jù)用戶的權(quán)限判斷用戶是否可以執(zhí)行這條 sql痹兜。

3 服務(wù)層

3.1 SQL 接口

從上圖中我們知道線程 3 負(fù)責(zé)監(jiān)聽并讀取 sql,拿到這個 sql 之后颤诀,如何執(zhí)行是一項極其復(fù)雜的任務(wù)字旭,所以 MYSQL 提供了 SQL 接口這么一個組件,線程 3 會將 sql 轉(zhuǎn)交給 SQL 接口來執(zhí)行如下圖:

[圖片上傳失敗...(image-66987f-1663831369193)]

SQL 接口具體處理功能有:DDL崖叫、DML遗淳、存儲過程、視圖心傀、觸發(fā)器等屈暗。

3.2 SQL 解析器

接著問題來了,SQL 接口如何執(zhí)行本文 sql 呢?养叛,數(shù)據(jù)庫怎么理解本文這個 sql 呢种呐?相信懂 sql 語法的人立馬就能知道什么意思,但是 MYSQL 是個系統(tǒng)不是人弃甥,它無法直接理解 sql 的意思爽室,這個時候關(guān)鍵的組件出場了,SQL 解析器的作用主要就是是解析 sql 語句淆攻,最終生成語法樹肮之,比如本文 sql 就可以拆解成如下幾個部分:

  1. 需要從 users 表里更新數(shù)據(jù)
  2. 需要更新 id 字段是 10 的那行數(shù)據(jù)
  3. 需要把這行數(shù)據(jù)的 name 字段的值改為 “zhangsan”

[圖片上傳失敗...(image-1e611f-1663831369193)]

3.3 SQL 優(yōu)化器

當(dāng)通過 SQL 解析器理解了 sql 語句要干什么之后,該如何實(shí)現(xiàn)呢卜录,以本文的更新語句為例戈擒,我們可以有以下兩種實(shí)現(xiàn)方式:

  1. 直接定位到 users 表中 id 字段等于 10 的一行數(shù)據(jù),然后查出這行數(shù)據(jù)數(shù)據(jù)艰毒,然后設(shè)置 name 字段為 “zhangsan”筐高;
  2. 也可以通過更新 name 字段索引的方式在 name 索引上遍歷 id 等于 10 的索引值,然后設(shè)置 name 字段為 “zhangsan”丑瞧。

上面兩種途徑都能實(shí)現(xiàn)最終結(jié)果柑土,顯然第一種路徑更好一些,所以绊汹,SQL 優(yōu)化器就是從眾多實(shí)現(xiàn)路徑中選則一條最優(yōu)的路徑出來稽屏,也就是我們常說的執(zhí)行計劃。

[圖片上傳失敗...(image-4e56f4-1663831369193)]

3.4 執(zhí)行器

通過 SQL 優(yōu)化器我們得到一套執(zhí)行計劃西乖,那么狐榔,這個計劃怎么執(zhí)行呢?這個時候就不得不提 MYSQL 存儲引擎获雕,我們都知道 MySQL 和其他關(guān)系型數(shù)據(jù)庫不一樣的地方在于它的彈性以及可以通過插件形式提供不同種類的存儲引擎薄腻,類似 java 接口的多實(shí)現(xiàn),MYSQL 肯定會有一套標(biāo)準(zhǔn)的存儲引擎接口届案,而執(zhí)行器就是按照執(zhí)行計劃一步一步的調(diào)用存儲引擎接口完成 sql 執(zhí)行而已庵楷,如下圖:

[圖片上傳失敗...(image-9dde91-1663831369193)]

上圖專門將 binlog 標(biāo)出來是為了和下文 innodb 存儲引擎的 undo log、redo log 做區(qū)分楣颠,強(qiáng)調(diào) binlog 是 server 層的日志尽纽,后續(xù) binlog 和 redo log 的兩階段方式完成事務(wù)的提交會再次提到。

3.5 查詢緩存

MYSQL 服務(wù)層為追求高效也引入了 QUERY BUFFER 這個組件童漩,但是這個組件比較雞肋弄贿,緩存不僅需要 sql 全字匹配命中,而且對基礎(chǔ)表的任何修改都會導(dǎo)致這些表的所有緩存失效睁冬,既不符合現(xiàn)在用戶變量的開發(fā)模式挎春,大部分時候也不高效看疙。MYSQL 從 5.7 開始不推薦使用默認(rèn)關(guān)閉豆拨,8.0 中不再支持直奋,詳細(xì)原因如下圖:

[圖片上傳失敗...(image-56d761-1663831369193)]

截圖來源 MYSQL 開發(fā)者專區(qū)文檔:https://dev.mysql.com/blog-archive/mysql-8-0-retiring-support-for-the-query-cache/

4 存儲引擎層

4.1 概述

上文執(zhí)行器拿到執(zhí)行計劃后,調(diào)用存儲引擎的接口來完成 sql 的執(zhí)行施禾,那么存儲引擎如何幫助我們?nèi)ピL問脚线、操作內(nèi)存以及磁盤上的數(shù)據(jù)呢?我們都知道 MYSQL 的存儲引擎有很多弥搞,實(shí)現(xiàn)方式各一邮绿,下面讓我們繼續(xù)通過上文的 sql 來初步了解我們常用的 Innodb 存儲引擎的核心原理和架構(gòu)設(shè)計

[圖片上傳失敗...(image-d91946-1663831369193)]

重溫一下本文 sql:

update users set name=’zhangsan’ where id = 10 —- 歷史 name = ‘lisi’

4.2 緩沖池(buffer pool)

InnoDB 存儲引擎中有一個非常重要的放在內(nèi)存里的組件,就是緩沖池(Buffer Pool)攀例,這里面會緩存很多的數(shù)據(jù)船逮,以便于以后在查詢的時候,萬一你要是內(nèi)存緩沖池里有數(shù)據(jù)粤铭,就可以不用去查磁盤了挖胃,如下圖:

[圖片上傳失敗...(image-72ea89-1663831369193)]

緩沖池(buffer pool)在 Innodb 中的地位類似于我們現(xiàn)在系統(tǒng)設(shè)計中 redis 的地位,在 Innodb 中引入這一組件的就是為了高效的存取梆惯,我們都知道 MYSQL 查詢數(shù)據(jù)很快酱鸭,究其原因不止是索引查詢,深層次的原因就是所有的增刪改查都是在 buffer pool 這塊內(nèi)存上操作的垛吗,相比于操作磁盤凹髓,效率不言自明。

4.2.1 數(shù)據(jù)頁怯屉、緩存頁和臟頁

還是拿我們的 sql 舉例蔚舀,更新 id=10 的這條記錄,難道從磁盤里只拉取 id=10 數(shù)據(jù)進(jìn)入內(nèi)存中嗎锨络?很明顯不是蝗敢,畢竟加入內(nèi)存的記錄不止這一張表,而且單表每行記錄也不一樣足删,內(nèi)存管理會非常困難的寿谴,所以,MYSQL 對數(shù)據(jù)抽象出來的一個叫數(shù)據(jù)頁的邏輯概念失受,每頁固定大小默認(rèn) 16KB讶泰,可以存多條數(shù)據(jù),并且 buffer pool 里的存儲結(jié)構(gòu)和數(shù)據(jù)頁一致拂到,這樣內(nèi)存管理就會簡單的多痪署,數(shù)據(jù)頁注冊元數(shù)據(jù)后加載進(jìn)內(nèi)存后就是緩存頁。

[圖片上傳失敗...(image-5ae8bf-1663831369193)]

從圖中可以看到在緩存頁在 sql 更新完還未刷回硬盤時數(shù)據(jù)和磁盤中的數(shù)據(jù)頁是不一致的兄旬,這個時候我們稱這種緩存頁為臟頁狼犯。至于后續(xù)臟頁如何落盤暫時不提余寥。

4.2.2 元數(shù)據(jù)

從上圖我們看到 buffer pool 中除了緩存頁,還多了一個元數(shù)據(jù)內(nèi)存結(jié)構(gòu)悯森,這個可以簡單的理解為登記宋舷,比如因?yàn)橐咔橥獾厝嘶丶疫^年會被當(dāng)?shù)卣M(jìn)行登記,記錄從哪來瓢姻、到哪去等信息祝蝠,便于管理,buffer pool 也是這樣做的幻碱;但是元數(shù)據(jù)可不止記錄緩存頁的磁盤地址和內(nèi)存地址這么簡單绎狭,buffer pool 核心原理都是通過元數(shù)據(jù)來實(shí)現(xiàn)的

4.2.3 free 鏈表

buffer pool 在 MYSQL 初始化的時候,就根據(jù)配置在內(nèi)存中申請了一塊連續(xù)的空間褥傍,申請過后就按數(shù)據(jù)頁的大小和元數(shù)據(jù)的大小進(jìn)行合理的劃分出很多個連續(xù)的儡嘶、空的緩存頁,當(dāng)需要查詢數(shù)據(jù)的時候就會從磁盤讀入數(shù)據(jù)頁放入到緩存頁當(dāng)中恍风,但是由于臟頁的存在蹦狂,數(shù)據(jù)還未刷盤不能使用偏塞,那么數(shù)據(jù)頁加載進(jìn)哪個緩存頁就是個問題月弛。為了解決哪些緩存頁是空閑的,MYSQL 團(tuán)隊為 Buffer pool 設(shè)計了一個 free 鏈表招狸,它是一個雙向鏈表的數(shù)據(jù)結(jié)構(gòu)兄世,這個 free 鏈表里每個節(jié)點(diǎn)就是一個空閑的緩存頁的元數(shù)據(jù)塊地址啼辣,也就是說只要一個緩存頁是空閑的,那么他的元數(shù)據(jù)塊就會放入這個 free 鏈表中御滩,這樣加載數(shù)據(jù)頁是只需要從 free 鏈表中找空閑的緩存頁即可鸥拧。

[圖片上傳失敗...(image-4519ba-1663831369193)]

從圖中即可看出鏈表的大致結(jié)構(gòu),那么現(xiàn)在我們要更新 users 表中 id=10 的記錄削解,首先要知道 id=10 這條記錄的數(shù)據(jù)頁有沒有在緩存頁當(dāng)中富弦,然后在決定是否是加載數(shù)據(jù)頁還是直接使用緩存頁,所以氛驮,buffer pool 里還有左下角這種 hash 表腕柜,用表空間 + 數(shù)據(jù)頁號作為 key,緩存頁地址為 value矫废,可以快速判斷數(shù)據(jù)頁是否被緩存盏缤。

4.2.4 flush 鏈表

本文 sql 執(zhí)行更新后,這樣就導(dǎo)致內(nèi)存中的數(shù)據(jù)和磁盤上的數(shù)據(jù)不一致蓖扑,這就表明這個緩存頁是臟頁唉铜,臟頁是需要刷新到磁盤文件的。但是不可能所有緩存頁都刷回磁盤律杠,比如有的緩存頁可能只是查詢的時候用到了潭流,沒有別更新過竞惋,所以數(shù)據(jù)庫就引入 flush 鏈表,flush 鏈表和 free 鏈表的實(shí)現(xiàn)方式一樣灰嫉,都是在元數(shù)據(jù)中增加兩個指針做成雙向鏈表拆宛,用來標(biāo)記鏈表上的都是臟頁,需要刷回磁盤熬甫,后續(xù) IO 線程異步刷盤就是將 flush 鏈表的數(shù)據(jù)刷盤胰挑,然后把緩存頁移除 flush 鏈表蔓罚,加入 free 鏈表當(dāng)中椿肩。

4.2.5 LRU 鏈表

隨著不停的把磁盤上的數(shù)據(jù)頁加載到空閑的緩存頁里去,free 鏈表中空閑的緩存頁越來越少豺谈,如果 free 鏈表空了郑象,這時候就無法從磁盤加載數(shù)據(jù)頁了,這時候就需要淘汰掉一些緩存頁茬末,首先想到的就是把修改過的緩存頁刷新回磁盤上厂榛,然后清空這個緩存頁

具體選擇哪個緩存頁進(jìn)行清空呢,數(shù)據(jù)庫引入 LRU 鏈表丽惭,結(jié)構(gòu)和 free 鏈表基本一致击奶,最近訪問的緩存頁都會被移動到 LRU 鏈表的頭部,這樣尾部的就是少訪問的數(shù)據(jù)责掏,但是這樣的 LRU 有個問題柜砾,就是 MYSQL 的預(yù)讀機(jī)制,會把不常訪問或者不訪問的數(shù)據(jù)連帶著加載到內(nèi)存换衬,這樣就把這一部分也放在了 LRU 頭結(jié)點(diǎn)上痰驱,很明顯不合理,同理瞳浦,全表掃描也有這個問題担映。

[圖片上傳失敗...(image-6499f4-1663831369193)]

從上面可以看出,如果此時需要淘汰緩存頁叫潦,就可能把熱點(diǎn)數(shù)據(jù)提前淘汰掉蝇完。對于這種不合理的 LRU 算法 MYSQL 基于冷熱數(shù)據(jù)分離的方法對 LRU 算法進(jìn)行如下優(yōu)化:LRU 鏈表被拆分為兩個部分,一部分熱數(shù)據(jù)矗蕊,一部分冷數(shù)據(jù)短蜕,數(shù)據(jù)頁第一次加載到緩存的時候是放在冷數(shù)據(jù)表頭,在 1s 后再次訪問這個緩存頁拔妥,就很有可能是熱數(shù)據(jù)忿危,就會把它挪到熱數(shù)據(jù)表頭區(qū)域,這樣設(shè)計防止了剛加載就訪問造成的假熱現(xiàn)象没龙。

[圖片上傳失敗...(image-d09bfb-1663831369193)]

冷熱區(qū)域緩存頁移動規(guī)則如下:

  • 冷數(shù)據(jù) -> 熱數(shù)據(jù)
    冷數(shù)據(jù)區(qū)的緩存頁是在 1s 后再被訪問到就移動到熱數(shù)據(jù)區(qū)的鏈表頭部
  • 熱數(shù)據(jù) -> 冷數(shù)據(jù)
    能留在熱數(shù)據(jù)區(qū)域的緩存頁铺厨,證明都是緩存命中率比較高的缎玫,會經(jīng)常被訪問到。如果每個緩存頁被訪問都移動到鏈表頭部解滓,那這個操作將會非常的頻繁赃磨。所以 InnoDB 存儲引擎做了一個優(yōu)化,只有在熱數(shù)據(jù)區(qū)域的后 3/4 的緩存頁被訪問了洼裤,才會移動到鏈表頭部邻辉;如果是熱數(shù)據(jù)區(qū)域的前 1/4 的緩存頁被訪問到,它是不會被移動到鏈表頭部去的腮鞍。這樣盡可能的減少鏈表中節(jié)點(diǎn)的移動了

4.2.6 小結(jié)

現(xiàn)在我們了解了更新數(shù)據(jù)會先把數(shù)據(jù)加載進(jìn) buffer pool 在進(jìn)行值骇,了解 buffer pool 是如何通過冷熱數(shù)據(jù)分離的機(jī)制優(yōu)化 LRU 鏈表,為系統(tǒng)設(shè)計中緩存過期淘汰策略提供的新的解決思路移国。既然吱瘩,數(shù)據(jù)更新是把數(shù)據(jù)載入 buffer pool 中修改,那么更新完緩存頁之后數(shù)據(jù)庫是如何保證事務(wù)提交迹缀、如何保證數(shù)據(jù)頁和緩存頁數(shù)據(jù)一致的呢

4.3 undo log

說到事務(wù)就不得不提事務(wù)是如何回滾的使碾,innodb 是引入了 undo log 的日志組件來實(shí)現(xiàn)事務(wù)回滾的,以本文 sql 為例祝懂,在數(shù)據(jù)加載進(jìn)緩存頁后票摇,修改之前,會將執(zhí)行的 sql 取反保存在 undo log 中砚蓬,邏輯類似 sql:

update users set name=’lisi’ where id = 10

當(dāng)然如果是 insert 語句與之對應(yīng)的就是 delete 語句矢门,delete 語句也就對應(yīng)的 insert 語句,這也就明白為什么 delete 的數(shù)據(jù)是可以回滾怜械,而 truncate 數(shù)據(jù)之后無法回滾的根本原因颅和,在于 truncate 無法生成 undo log。

[圖片上傳失敗...(image-3feaf9-1663831369193)]

上圖是本問 sql 執(zhí)行的大致步驟缕允,至于加入 buffer pool 這塊上文已經(jīng)詳細(xì)了解過了峡扩,就不在贅述。從圖中可以看出因?yàn)?log 直接刷盤比較損耗性能障本,所以引入 log buffer 進(jìn)行緩存教届,然后在通過異步的方式把數(shù)據(jù)刷入磁盤既然數(shù)據(jù)更新之前的數(shù)據(jù)記錄下來并成功刷入磁盤,則事務(wù)的回滾就不難實(shí)現(xiàn)了驾霜。

當(dāng)然 undo log 除了提供回滾功能案训,還為多版本并發(fā)控制(MVCC)提供了實(shí)現(xiàn)基礎(chǔ),實(shí)現(xiàn)了 MYSQL 的非阻塞讀寫粪糙,提高了系統(tǒng)的并發(fā)性强霎。本文也不再深入

4.4 redo log

下面來了解一下 innodb 是如何保證 buffer pool 緩存的數(shù)據(jù)一致性問題,數(shù)據(jù)更新值內(nèi)存后并不會立即刷新至磁盤數(shù)據(jù)頁蓉冈,而是一致以臟頁的形式保存在 buffer pool 當(dāng)中城舞,這樣做有兩個原因會導(dǎo)致效率很差轩触,一個是內(nèi)存向磁盤寫數(shù)據(jù)本身效率就慢,另一個就是隨機(jī) IO 會寫磁盤的時間上附加上很多磁頭尋址的時間家夺,所以立即刷數(shù)據(jù)頁效率很低脱柱。

Innodb 是如何規(guī)避上述問題的呢,正常情況下拉馋,異步刷盤就已經(jīng)可以解決了刷磁盤慢的問題榨为,但是,假如 MYSQL 系統(tǒng)崩潰煌茴、宕機(jī)随闺,這時候臟頁還未及時刷盤,那么緩存頁期間所有改動數(shù)據(jù)豈不是丟了景馁,所以板壮,Innodb 引入了另一個組件 redo log逗鸣,專門記錄數(shù)據(jù)被緩存期間做過的修改記錄合住,然后立即寫入 redo log 磁盤文件,相比于緩存頁刷盤撒璧,redo log 刷盤的數(shù)據(jù)了小多了透葛,并且寫 redo log 是順序 IO,而緩存頁刷盤是隨機(jī) IO卿樱。下圖示意:

[圖片上傳失敗...(image-1b6f73-1663831369193)]

這樣當(dāng)數(shù)據(jù)庫異常宕機(jī)時僚害,即使緩存頁丟失數(shù)據(jù)也不會丟失,因?yàn)?redo log 已經(jīng)落盤繁调,數(shù)據(jù)庫重啟的時候會更近 redo log 把磁盤上歷史的數(shù)據(jù)頁重新載入內(nèi)存萨蚕,重新按 redo log 的修改記錄操作一遍就能將緩存頁中的數(shù)據(jù)恢復(fù)至宕機(jī)前的狀態(tài)。

如果系統(tǒng)宕機(jī)時蹄胰,redo log 還沒落盤數(shù)據(jù)豈不是丟了岳遥,對,這種情況下數(shù)據(jù)會丟裕寨,這種 redo log 丟數(shù)據(jù)分兩中情況:

第一種情況浩蓉,MYSQL 有三種刷盤策略,通過 innodb_flush_log_at_trx_commit 參數(shù)進(jìn)行配置

  1. 配置為 0:事務(wù)提交的時候不會把 redolog buffer 里的數(shù)據(jù)立即刷入磁盤宾袜,此時如果宕機(jī)則會導(dǎo)致已提交的數(shù)據(jù)修改丟失捻艳;
  2. 配置為 1:則是事務(wù)提交的時候必須把 redolog buffer 里的數(shù)據(jù)刷入磁盤,以保證事務(wù)提交后操作數(shù)據(jù)日志不丟庆猫;
  3. 配置為 2:則表示只是把數(shù)據(jù)交給操作系統(tǒng)進(jìn)行刷盤认轨,操作系統(tǒng)刷沒刷成功則不管,理論上操作系統(tǒng)刷盤是先要經(jīng)過 os cache 內(nèi)存緩存的月培,就是說數(shù)據(jù)會先在 os chache 里沒有真正的落盤嘁字,這種模式下也可能導(dǎo)致數(shù)據(jù)丟失

[圖片上傳失敗...(image-76f172-1663831369193)]

這第一種情況如果產(chǎn)生丟數(shù)據(jù)昨稼,是真的丟失,所以拳锚,如果對數(shù)據(jù)庫丟失數(shù)據(jù)零容忍假栓,建議配置策略為 1

第二種情況,就是未寫 commit 標(biāo)記日志的情況霍掺,即下圖第 9 步丟失的情況匾荆,但是這種情況系統(tǒng)認(rèn)為事務(wù)提交失敗,所以丟失了并不影響數(shù)據(jù)一致性杆烁。

[圖片上傳失敗...(image-1c6452-1663831369193)]

圖中 7牙丽、8、9 三個步驟是事務(wù)提交 commit 的時候才做的(本文只用一個 sql 來講解兔魂,默認(rèn)事務(wù)自動提交)烤芦,redo log 記錄更新記錄之后,執(zhí)行器會把修改記錄寫在 server 層的 binlog 當(dāng)中析校,很明顯這是兩個文件构罗,如果出現(xiàn)上述宕機(jī)等異常情況,這兩個文件的數(shù)據(jù)一致性是不能保證的智玻,所以遂唧,為了保證兩個文件的數(shù)據(jù)一致性,innodb 會在 binlog 寫完之后在 redo log 中補(bǔ)上一個 commit 標(biāo)記告訴 redo log 事務(wù)成功吊奢。事務(wù)執(zhí)行成功后操作 redo log 刷入磁盤盖彭,至此本文 sql 執(zhí)行成功。

5 總結(jié)

通過一條 update 的 sql 的更新流程页滚,清晰的看到 MYSQL 的整體架構(gòu)設(shè)計召边,對 Innodb 存儲引擎的幾大核心組件如何相互協(xié)作、配合以實(shí)現(xiàn)高效的數(shù)據(jù)庫系統(tǒng)有了更清晰的認(rèn)識裹驰;核心組件 buffer pool 的冷熱數(shù)據(jù)分離的緩存淘汰機(jī)制也為以后系統(tǒng)的架構(gòu)設(shè)計提供了新的解決思路隧熙。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市邦马,隨后出現(xiàn)的幾起案子贱鼻,更是在濱河造成了極大的恐慌,老刑警劉巖滋将,帶你破解...
    沈念sama閱讀 219,589評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件邻悬,死亡現(xiàn)場離奇詭異,居然都是意外死亡随闽,警方通過查閱死者的電腦和手機(jī)父丰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評論 3 396
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蛾扇,你說我怎么就攤上這事攘烛。” “怎么了镀首?”我有些...
    開封第一講書人閱讀 165,933評論 0 356
  • 文/不壞的土叔 我叫張陵坟漱,是天一觀的道長。 經(jīng)常有香客問我更哄,道長芋齿,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,976評論 1 295
  • 正文 為了忘掉前任成翩,我火速辦了婚禮觅捆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘麻敌。我一直安慰自己栅炒,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,999評論 6 393
  • 文/花漫 我一把揭開白布术羔。 她就那樣靜靜地躺著赢赊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪聂示。 梳的紋絲不亂的頭發(fā)上域携,一...
    開封第一講書人閱讀 51,775評論 1 307
  • 那天,我揣著相機(jī)與錄音鱼喉,去河邊找鬼。 笑死趋观,一個胖子當(dāng)著我的面吹牛扛禽,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播皱坛,決...
    沈念sama閱讀 40,474評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼编曼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了剩辟?” 一聲冷哼從身側(cè)響起掐场,我...
    開封第一講書人閱讀 39,359評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎贩猎,沒想到半個月后熊户,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,854評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡吭服,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,007評論 3 338
  • 正文 我和宋清朗相戀三年嚷堡,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片艇棕。...
    茶點(diǎn)故事閱讀 40,146評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡蝌戒,死狀恐怖串塑,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情北苟,我是刑警寧澤桩匪,帶...
    沈念sama閱讀 35,826評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站友鼻,受9級特大地震影響吸祟,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜桃移,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,484評論 3 331
  • 文/蒙蒙 一屋匕、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧借杰,春花似錦过吻、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至绞惦,卻和暖如春逼纸,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背济蝉。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評論 1 272
  • 我被黑心中介騙來泰國打工杰刽, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人王滤。 一個月前我還...
    沈念sama閱讀 48,420評論 3 373
  • 正文 我出身青樓贺嫂,卻偏偏與公主長得像,于是被迫代替她去往敵國和親雁乡。 傳聞我的和親對象是個殘疾皇子第喳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,107評論 2 356

推薦閱讀更多精彩內(nèi)容