最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MySQL存儲引擎InnoDB架構(gòu)原理和執(zhí)行流程

 更新時間:2025年04月19日 11:35:23   作者:東陽馬生架構(gòu)  
InnoDB是MySQL的當(dāng)前默認(rèn)存儲引擎,支持外鍵、行級鎖定和ACID事務(wù),通過BufferPool緩沖池緩存數(shù)據(jù),RedoLogBuffer和undo日志文件保證數(shù)據(jù)的持久性和回滾能力,MySQL宕機(jī)重啟時,InnoDB會根據(jù)LSN值決定是否需要從redo日志恢復(fù)數(shù)據(jù)

InnoDB 是 MySQL 的當(dāng)前默認(rèn)存儲引擎。該引擎支持外鍵、行級鎖定和 ACID 事務(wù)。這些功能使 InnoDB 成為現(xiàn)代應(yīng)用程序的可靠且合適的選擇。它的崩潰恢復(fù)機(jī)制、數(shù)據(jù)完整性和高性能是 InnoDB 目前成為默認(rèn) MySQL 引擎的一些原因。

更新語句在MySQL中是如何執(zhí)行的

假設(shè)有一條如下這樣的SQL語句,那么這條語句是如何執(zhí)行的呢?

update users set name = 'xxx' where id = 1;

首先Java系統(tǒng)會通過一個數(shù)據(jù)庫連接將該SQL語句發(fā)送到MySQL上,然后經(jīng)過SQL接口、查詢解析器、查詢優(yōu)化器、執(zhí)行器環(huán)節(jié),在解析出了SQL語句、生成了執(zhí)行計劃后,再由執(zhí)行器調(diào)用InnoDB存儲引擎的接口去執(zhí)行生成的執(zhí)行計劃。

MySQL原理簡介—2.InnoDB架構(gòu)原理和執(zhí)行流程_提交事務(wù)

下面介紹InnoDB存儲引擎里的架構(gòu)設(shè)計,以及如何基于InnoDB存儲引擎完成一條更新語句的執(zhí)行。

重要的內(nèi)存結(jié)構(gòu)—Buffer Pool緩沖池

InnoDB有一個非常重要、放在內(nèi)存里的組件,就是緩沖池(Buffer Pool)。緩沖池會緩存很多磁盤文件數(shù)據(jù),以便在查詢時不用去查磁盤。如下圖示:

MySQL原理簡介—2.InnoDB架構(gòu)原理和執(zhí)行流程_MySQL_02

所以當(dāng)InnoDB存儲引擎要執(zhí)行更新語句時:比如對"id=1"這一行數(shù)據(jù),會先判斷"id=1"這一行數(shù)據(jù)是否在緩沖池里。如果不在,則直接從磁盤里加載到緩沖池里,且對這行記錄加獨占鎖。

undo日志文件如何讓更新的數(shù)據(jù)可以回滾

假設(shè)"id=1"這行數(shù)據(jù)的name原來是"zhangsan",現(xiàn)在要更新為"xxx"。那么InnoDB得先把原值"zhangsan"和"id=1"寫入到undo日志文件中。

Java系統(tǒng)在執(zhí)行一條SQL更新語句時,要是它在一個事務(wù)里,那么事務(wù)提交前是可以對數(shù)據(jù)進(jìn)行回滾的。所以考慮到可能要回滾數(shù)據(jù),InnoDB會把更新前的值寫入undo日志文件。如下圖示:

MySQL原理簡介—2.InnoDB架構(gòu)原理和執(zhí)行流程_MySQL_03

更新Buffer Pool緩沖池中的緩存數(shù)據(jù)

當(dāng)InnoDB把要更新的那行記錄從磁盤文件加載到了緩沖池,同時對它加完鎖,而且還把更新前的舊值寫入undo日志文件后,InnoDB就可以正式開始更新這行記錄了。

更新的時候,會先更新緩沖池中的記錄,此時這個數(shù)據(jù)就是臟數(shù)據(jù)了。所謂的更新內(nèi)存緩沖池里的數(shù)據(jù),意思就是把內(nèi)存里的"id=1"這行數(shù)據(jù)的name字段修改為"xxx"。

為什么說此時這行數(shù)據(jù)是臟數(shù)據(jù)呢?因為這時磁盤上"id=1"這行數(shù)據(jù)的name字段還是"zhangsan",但內(nèi)存里這行數(shù)據(jù)已經(jīng)被修改了,所以它是臟數(shù)據(jù)。

MySQL原理簡介—2.InnoDB架構(gòu)原理和執(zhí)行流程_MySQL_04

Redo Log Buffer如何避免宕機(jī)時數(shù)據(jù)丟失

現(xiàn)在已經(jīng)把內(nèi)存里的數(shù)據(jù)進(jìn)行了修改,但是磁盤上的數(shù)據(jù)還沒修改。此時萬一MySQL所在機(jī)器宕機(jī),必然會導(dǎo)致內(nèi)存里已修改的數(shù)據(jù)丟失。這該如何處理?

為此必須把對內(nèi)存所做的修改寫入一個Redo Log Buffer里,Redo Log Buffer也是內(nèi)存里的一個緩沖區(qū),是用來存放redo日志的。

所謂redo日志,就是記錄InnoDB要對數(shù)據(jù)做什么修改。比如對"id=1"這行記錄修改name字段的值為"xxx",就是一條redo日志。

MySQL原理簡介—2.InnoDB架構(gòu)原理和執(zhí)行流程_提交事務(wù)_05

如果還沒提交事務(wù)時MySQL宕機(jī)了怎么辦

在數(shù)據(jù)庫中,哪怕執(zhí)行一條SQL語句,其實也可以是一個獨立的事務(wù)。只有當(dāng)事務(wù)提交后,SQL語句才算執(zhí)行結(jié)束。

所以如果還沒提交事務(wù)MySQL宕機(jī)了,那么必然導(dǎo)致內(nèi)存里Buffer Pool中修改過的數(shù)據(jù)都丟失,同時寫入Redo Log Buffer中的日志也會丟失。

MySQL原理簡介—2.InnoDB架構(gòu)原理和執(zhí)行流程_MySQL_06

此時數(shù)據(jù)丟失其實是不要緊的。因為一條更新語句只要沒提交事務(wù),那么就代表還沒執(zhí)行成功。此時MySQL宕機(jī)雖然導(dǎo)致內(nèi)存里的數(shù)據(jù)丟失,但還沒影響磁盤上的數(shù)據(jù)。

提交事務(wù)時將redo日志寫入磁盤中

如果InnoDB想要提交一個事務(wù),就會根據(jù)一定的策略把redo日志從Redo Log Buffer中刷入到磁盤文件里,這個策略是通過如下這個參數(shù)來配置的:innodb_flush_log_at_trx_commit。

(1)當(dāng)innodb_flush_log_at_trx_commit = 0時

那么進(jìn)行事務(wù)提交時,不會把Redo Log Buffer的數(shù)據(jù)刷入到磁盤文件里。這時即便提交了事務(wù),但如果MySQL宕機(jī)了,內(nèi)存里的數(shù)據(jù)也會全部丟失而且redo日志里沒有數(shù)據(jù)。

MySQL原理簡介—2.InnoDB架構(gòu)原理和執(zhí)行流程_數(shù)據(jù)_07

(2)當(dāng)innodb_flush_log_at_trx_commit = 1時

那么進(jìn)行事務(wù)提交時,會把內(nèi)存中的redo log刷入到磁盤文件里。只要事務(wù)提交成功,那么redo log就必然在磁盤里。哪怕此時Buffer Pool中更新過的數(shù)據(jù)還沒刷新到磁盤,系統(tǒng)崩潰重啟后,也可以根據(jù)磁盤中的redo log恢復(fù)。

MySQL原理簡介—2.InnoDB架構(gòu)原理和執(zhí)行流程_數(shù)據(jù)_08

(3)當(dāng)innodb_flush_log_at_trx_commit = 2時

那么進(jìn)行事務(wù)提交時,會把內(nèi)存中的redo log寫入到OS Cache緩存里。OS Cache緩存里的數(shù)據(jù)可能在1秒后才會被寫入到磁盤文件中。

在這種模式下,當(dāng)InnoDB存儲引擎提交事務(wù)后,redo log可能還停留在OS Cache緩存里,還沒實際進(jìn)入到磁盤文件。而此時MySQL所在機(jī)器宕機(jī)了,那么OS Cache里的redo log也會丟失。從而出現(xiàn)即便提交了事務(wù),但是數(shù)據(jù)還是丟失了的情況。

MySQL原理簡介—2.InnoDB架構(gòu)原理和執(zhí)行流程_提交事務(wù)_09

redo日志刷盤策略的選擇和建議

通常建議設(shè)置innodb_flush_log_at_trx_commit的值為1。也就是提交事務(wù)時,redo日志必須同時刷入磁盤文件里。這樣可以嚴(yán)格保證提交事務(wù)后數(shù)據(jù)絕對不會丟失。

如果innodb_flush_log_at_trx_commit = 0,那么提交事務(wù)后如果MySQL宕機(jī)而此時redo日志還沒有刷盤,則會導(dǎo)致內(nèi)存里的redo日志丟失,內(nèi)存更新好的數(shù)據(jù)也丟失。

如果innodb_flush_log_at_trx_commit = 2,那么提交事務(wù)后雖然redo日志進(jìn)入了OS Cache,但OS Cache的數(shù)據(jù)此時還沒進(jìn)入磁盤文件而MySQL機(jī)器宕機(jī)了,則也會導(dǎo)致OS Cache的redo日志丟失。

所以一般設(shè)置redo日志刷盤策略為1,保證事務(wù)提交后數(shù)據(jù)不會丟失。

MySQL的redo log和binlog對比

MySQL的redo log,是一種偏向物理性的重做日志。因為其記錄的是:對哪個數(shù)據(jù)頁中的哪條記錄做了什么修改。而且redo log是屬于InnoDB存儲引擎特有的日志文件。

MySQL的binlog,是一種偏向于邏輯性的日志,也叫歸檔日志。類似"對users表中id=1的一行記錄做了更新操作,更新后的值是什么"。binlog不是InnoDB存儲引擎特有的日志文件,binlog是屬于MySQL數(shù)據(jù)庫層面的日志文件。

提交事務(wù)時同時也會寫入binlog

提交事務(wù)時,除了會把redo日志寫入到磁盤文件中,還會把這次SQL更新對應(yīng)的binlog日志寫入到磁盤文件中。

下圖加入了執(zhí)行器這個組件,它會負(fù)責(zé)和InnoDB存儲引擎進(jìn)行交互:

步驟1:從磁盤加載數(shù)據(jù)到Buffer Pool緩存

步驟2:寫入undo日志

步驟3:更新Buffer Pool里的數(shù)據(jù)

步驟4:寫入redo日志到Redo Log Buffer

步驟5:redo日志刷入磁盤

步驟6:寫入binlog日志

實際上,執(zhí)行器是非常核心的一個組件。執(zhí)行器會與存儲引擎完成SQL語句在磁盤與內(nèi)存層面的全部數(shù)據(jù)更新操作。

下圖把一次更新語句的執(zhí)行,拆分為兩個階段。其中步驟1、2、3、4是執(zhí)行更新語句的階段,而步驟5和6是屬于提交事務(wù)的階段。

MySQL原理簡介—2.InnoDB架構(gòu)原理和執(zhí)行流程_MySQL_10

binlog日志的刷盤策略分析

binlog日志也有不同的刷盤策略,通過sync_binlog參數(shù)可以控制binlog的刷盤策略,默認(rèn)值是0。

(1)當(dāng)sync_binlog設(shè)置為0時

表示執(zhí)行器沒有直接將binlog寫入磁盤文件,而是先將binlog寫入OS Cache緩存,與redo log的innodb_flush_log_at_trx_commit的值為2一樣。

如果OS Cache里的數(shù)據(jù)還沒寫入磁盤文件時,MySQL所在機(jī)器宕機(jī),那么binlog日志也會丟失。

MySQL原理簡介—2.InnoDB架構(gòu)原理和執(zhí)行流程_提交事務(wù)_11

(2)當(dāng)sync_binlog設(shè)置為1時

表示在提交事務(wù)時,執(zhí)行器會把binlog直接寫入到磁盤文件中。這樣在提交事務(wù)后即便宕機(jī),binlog也不會丟失。

MySQL原理簡介—2.InnoDB架構(gòu)原理和執(zhí)行流程_提交事務(wù)_12

基于binlog的redo log完成事務(wù)的提交

當(dāng)MySQL把binlog寫入磁盤后,接著就會完成最終的事務(wù)提交。此時會把本次更新對應(yīng)的binlog文件名稱和位置,都寫入到redo日志里,同時在redo日志文件里寫入一個commit標(biāo)記。在完成這個事情后,才算是最終完成事務(wù)的提交。

MySQL原理簡介—2.InnoDB架構(gòu)原理和執(zhí)行流程_數(shù)據(jù)_13

在redo日志中寫入commit標(biāo)記的意義

寫入commit標(biāo)記是用來保持redo日志與binlog日志一致。也就是說,在提交事務(wù)的時候,上圖的步驟5、6、7必須都執(zhí)行完畢,才算是提交了事務(wù)。

(1)如果剛完成步驟5時,redo日志剛刷入到磁盤文件,MySQL宕機(jī)了

這時因為在redo日志沒有最終的事務(wù)commit標(biāo)記,所以此次事務(wù)不成功。因為不允許出現(xiàn)這樣的情況:redo日志文件里有更新日志,但是binlog日志文件里沒有對應(yīng)的更新日志。否則就會導(dǎo)致數(shù)據(jù)不一致。

(2)如果在完成步驟6時,binlog日志已寫入磁盤,MySQL宕機(jī)了

這時因為在redo日志沒有最終的事務(wù)commit標(biāo)記,所以此次事務(wù)也失敗。所以必須要在redo日志寫入最終的事務(wù)commit標(biāo)記,才算事務(wù)提交成功。這樣redo日志有本次更新的日志,binlog日志也有本次更新的日志,從而實現(xiàn)redo日志和binlog日志完全一致。

后臺IO線程隨機(jī)將內(nèi)存更新后的臟數(shù)據(jù)刷盤

當(dāng)完成事務(wù)提交后,MySQL已把內(nèi)存中的Buffer Pool緩存數(shù)據(jù)更新了,同時磁盤里也有redo日志和binlog日志,但磁盤上的數(shù)據(jù)文件還是舊值。

這時MySQL會有一個后臺IO線程,在事務(wù)提交后的某個時間,隨機(jī)把內(nèi)存Buffer Pool中修改后的臟數(shù)據(jù)刷回到磁盤上的數(shù)據(jù)文件里。

MySQL原理簡介—2.InnoDB架構(gòu)原理和執(zhí)行流程_MySQL_14

當(dāng)IO線程把Buffer Pool里修改后的臟數(shù)據(jù)刷回磁盤后,磁盤上的數(shù)據(jù)才會跟內(nèi)存里的數(shù)據(jù)一樣,都是修改后的值。

當(dāng)IO線程把臟數(shù)據(jù)刷回磁盤之前,即便MySQL宕機(jī)也沒關(guān)系。因為重啟后會根據(jù)redo日志恢復(fù)提交事務(wù)時所做的修改到內(nèi)存里。之后IO線程還是會把修改后的數(shù)據(jù)刷到磁盤的數(shù)據(jù)文件里。

InnoDB存儲引擎的架構(gòu)原理總結(jié)

InnoDB存儲引擎會使用Buffer Pool、Redo Log Buffer來緩存數(shù)據(jù)。InnoDB存儲引擎有屬于自己的undo日志文件、redo日志文件,MySQL也有屬于自己的binlog日志文件。

執(zhí)行更新時:會修改Buffer Pool里的數(shù)據(jù)、寫undo日志、寫Redo Log Buffer。

提交事務(wù)時:會把binlog刷入磁盤、在redo日志中寫入事務(wù)標(biāo)記,把redo日志刷入磁盤。最后InnoDB后臺的IO線程會隨機(jī)把Buffer Pool的臟數(shù)據(jù)刷入到磁盤文件。

(1)MySQL宕機(jī)重啟如何確定是否需要從redo日志恢復(fù)數(shù)據(jù)

MySQL宕機(jī)重啟,如何確定臟數(shù)據(jù)在宕機(jī)前是否已全部刷寫回磁盤文件。

MySQL宕機(jī)重啟,InnoDB會首先去查看數(shù)據(jù)頁中LSN的數(shù)值。LSN就是InnoDB使用的一個版本標(biāo)記的計數(shù)。如果數(shù)據(jù)頁中的LSN異于redo日志的commit標(biāo)記,那么就去查看redo日志的LSN大小。如果數(shù)據(jù)頁的LSN值大,則說明數(shù)據(jù)頁領(lǐng)先redo日志,不需要恢復(fù),反之則需要從redo日志中恢復(fù)。

(2)從redo日志恢復(fù)數(shù)據(jù)時是全量恢復(fù)還是指定位置后恢復(fù)

redo日志是劃歸于一個redo日志組的。默認(rèn)一個redo日志組有兩個redo日志文件。寫redo日志時是循環(huán)寫入,寫滿一個redo日志文件再寫另外一個。

在寫滿切換redo日志文件時,會觸發(fā)數(shù)據(jù)庫的檢查點checkpoint。checkpoint所做的事就是把臟頁刷新回磁盤。

當(dāng)DB重啟恢復(fù)時只需要恢復(fù)checkpoint之后的數(shù)據(jù)即可。所以redo日志文件大小不宜過大,不然導(dǎo)致恢復(fù)時需要更長的時間。redo日志文件大小也不宜過小,不然導(dǎo)致頻繁切換觸發(fā)檢測點降低性能。

(3)既然有redo日志來保證崩潰恢復(fù),為什么還要有binlog日志

binlog日志其實就是歸檔日志,主要用來做數(shù)據(jù)恢復(fù)的。MySQL最開始設(shè)計時只有MyISAM引擎只有binlog,不支持InnoDB。此外數(shù)據(jù)庫備份以及hadoop系統(tǒng)數(shù)據(jù)分析都是binlog來實現(xiàn)的,所以還需要binlog。

(4)redo日志和binlog日志的數(shù)據(jù)結(jié)構(gòu)是怎樣的

redo日志是循環(huán)寫,會把redo日志分為0,1,2,3四個區(qū)間,有兩個指針。writepos指針是一邊寫一邊向后移動,checkpoint指針是一邊擦除一邊向后移動。所以redo日志是不能保存很多記錄的,必須持久化到磁盤中。binlog日志是追加寫,不會覆蓋之前的日志。

(5)binlog日志和redo日志是怎么保持一致性的

binlog日志和redo日志是通過兩階段提交來保持一致性的。否則如果數(shù)據(jù)庫系統(tǒng)發(fā)生crash,則通過redo日志恢復(fù)的數(shù)據(jù)庫和通過binlog日志恢復(fù)出來的臨時庫不一致。

總結(jié)

到此這篇關(guān)于MySQL存儲引擎InnoDB架構(gòu)原理和執(zhí)行流程的文章就介紹到這了,更多相關(guān)MySQL中InnoDB架構(gòu)原理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • MySQL獲取版本號的N種方法(全網(wǎng)最全以及避坑大全)

    MySQL獲取版本號的N種方法(全網(wǎng)最全以及避坑大全)

    相信大家在工作學(xué)習(xí)中經(jīng)常有需要查詢 MySQL 數(shù)據(jù)庫版本的情況,這里給大家介紹幾種在 MySQL 中查詢數(shù)據(jù)庫版本的方法以及每種方法適用的場景,相信總有一種可以幫到你,需要的朋友可以參考下
    2024-10-10
  • MySQL主機(jī)因多次連接數(shù)據(jù)庫錯誤而被阻塞的解決方案

    MySQL主機(jī)因多次連接數(shù)據(jù)庫錯誤而被阻塞的解決方案

    文章講述了MySQL數(shù)據(jù)庫連接失敗導(dǎo)致主機(jī)被阻塞的問題,分析了原因,并提供了兩種解決方法:調(diào)整max_connect_errors參數(shù)和執(zhí)行FLUSH HOSTS命令
    2025-12-12
  • 如何合理使用數(shù)據(jù)庫冗余字段的方法

    如何合理使用數(shù)據(jù)庫冗余字段的方法

    今天小編就為大家分享一篇關(guān)于如何合理使用數(shù)據(jù)庫冗余字段的方法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • MySQL數(shù)據(jù)庫重命名的快速且安全方法(3種)

    MySQL數(shù)據(jù)庫重命名的快速且安全方法(3種)

    這篇文章主要介紹了MySQL數(shù)據(jù)庫重命名的快速且安全方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • MySQL之索引結(jié)構(gòu)解讀

    MySQL之索引結(jié)構(gòu)解讀

    這篇文章主要介紹了MySQL之索引結(jié)構(gòu)解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • MySQL錯誤Forcing close of thread的兩種解決方法

    MySQL錯誤Forcing close of thread的兩種解決方法

    這篇文章主要介紹了MySQL錯誤Forcing close of thread的兩種解決方法,需要的朋友可以參考下
    2014-11-11
  • Apache Drill 連接 MySQL 或 PostgreSQL 數(shù)據(jù)庫的詳細(xì)步驟

    Apache Drill 連接 MySQL 或 PostgreSQL&

    Drill 連接 MySQL或PostgreSQL 數(shù)據(jù)庫需要通過配置JDBC存儲插件實現(xiàn),核心是通過JDBC 驅(qū)動連接外部數(shù)據(jù)庫,下面給大家介紹Apache Drill 連接 MySQL 或 PostgreSQL 數(shù)據(jù)庫的詳細(xì)步驟,感興趣的朋友跟隨小編一起看看吧
    2025-11-11
  • mysql中的服務(wù)器架構(gòu)詳解

    mysql中的服務(wù)器架構(gòu)詳解

    這篇文章主要介紹了mysql中的服務(wù)器架構(gòu),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-06-06
  • 使用MySQL Workbench構(gòu)建ER圖的詳細(xì)教程

    使用MySQL Workbench構(gòu)建ER圖的詳細(xì)教程

    ER圖又稱實體-聯(lián)系圖(Entity Relationship Diagram),提供了表示實體類型、屬性和聯(lián)系的方法,用來描述現(xiàn)實世界的概念模型,MySQL?Workbench是一個強(qiáng)大的數(shù)據(jù)庫設(shè)計工具,提供了便捷的數(shù)據(jù)導(dǎo)入導(dǎo)出功能,本文介紹了使用MySQL Workbench構(gòu)建ER圖的詳細(xì)教程
    2024-06-06
  • sql自增長設(shè)置與刪除的深入分析

    sql自增長設(shè)置與刪除的深入分析

    本篇文章是對sql自增長設(shè)置與刪除進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-06-06

最新評論

香港 | 乐都县| 始兴县| 张家口市| 山东省| 栾川县| 西乌珠穆沁旗| 上犹县| 胶南市| 咸阳市| 张家港市| 钟祥市| 杭锦后旗| 驻马店市| 阜平县| 长泰县| 牟定县| 卢氏县| 四子王旗| 昌乐县| 北碚区| 庆云县| 固原市| 涞水县| 方正县| 德江县| 兰州市| 永靖县| 应用必备| 民县| 日喀则市| 和田市| 屏东县| 南木林县| 台湾省| 乌兰浩特市| 玛曲县| 璧山县| 开阳县| 信阳市| 梅河口市|