欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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宕機重啟時,InnoDB會根據(jù)LSN值決定是否需要從redo日志恢復(fù)數(shù)據(jù)

InnoDB 是 MySQL 的當(dāng)前默認(rèn)存儲引擎。該引擎支持外鍵、行級鎖定和 ACID 事務(wù)。這些功能使 InnoDB 成為現(xiàn)代應(yīng)用程序的可靠且合適的選擇。它的崩潰恢復(fù)機制、數(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ù)進行回滾的。所以考慮到可能要回滾數(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如何避免宕機時數(shù)據(jù)丟失

現(xiàn)在已經(jīng)把內(nèi)存里的數(shù)據(jù)進行了修改,但是磁盤上的數(shù)據(jù)還沒修改。此時萬一MySQL所在機器宕機,必然會導(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宕機了怎么辦

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

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

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

此時數(shù)據(jù)丟失其實是不要緊的。因為一條更新語句只要沒提交事務(wù),那么就代表還沒執(zhí)行成功。此時MySQL宕機雖然導(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時

那么進行事務(wù)提交時,不會把Redo Log Buffer的數(shù)據(jù)刷入到磁盤文件里。這時即便提交了事務(wù),但如果MySQL宕機了,內(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時

那么進行事務(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時

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

在這種模式下,當(dāng)InnoDB存儲引擎提交事務(wù)后,redo log可能還停留在OS Cache緩存里,還沒實際進入到磁盤文件。而此時MySQL所在機器宕機了,那么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宕機而此時redo日志還沒有刷盤,則會導(dǎo)致內(nèi)存里的redo日志丟失,內(nèi)存更新好的數(shù)據(jù)也丟失。

如果innodb_flush_log_at_trx_commit = 2,那么提交事務(wù)后雖然redo日志進入了OS Cache,但OS Cache的數(shù)據(jù)此時還沒進入磁盤文件而MySQL機器宕機了,則也會導(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存儲引擎進行交互:

步驟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所在機器宕機,那么binlog日志也會丟失。

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

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

表示在提交事務(wù)時,執(zhí)行器會把binlog直接寫入到磁盤文件中。這樣在提交事務(wù)后即便宕機,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宕機了

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

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

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

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

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

這時MySQL會有一個后臺IO線程,在事務(wù)提交后的某個時間,隨機把內(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宕機也沒關(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線程會隨機把Buffer Pool的臟數(shù)據(jù)刷入到磁盤文件。

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

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

MySQL宕機重啟,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)文章

  • SQL Server 數(shù)據(jù)庫的備份詳細(xì)介紹及注意事項

    SQL Server 數(shù)據(jù)庫的備份詳細(xì)介紹及注意事項

    這篇文章主要介紹了SQL Server 備份詳細(xì)介紹及注意事項的相關(guān)資料,需要的朋友可以參考下
    2016-12-12
  • 以Centos為例講解MySQL在Linux中的部署

    以Centos為例講解MySQL在Linux中的部署

    這篇文章主要介紹了以Centos為例講解MySQL在Linux中的部署,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-12-12
  • mysql中text,longtext,mediumtext區(qū)別小結(jié)

    mysql中text,longtext,mediumtext區(qū)別小結(jié)

    在 MySQL 中,text、mediumtext 和 longtext 都是用來存儲大量文本數(shù)據(jù)的數(shù)據(jù)類型,本文就來詳細(xì)的介紹一下這三種類型的區(qū)別,具有一定的參考價值,感興趣的可以了解一下
    2023-12-12
  • PHP mysqli擴展庫 預(yù)處理技術(shù)的使用分析

    PHP mysqli擴展庫 預(yù)處理技術(shù)的使用分析

    本篇文章,介紹了PHP mysqli擴展庫 預(yù)處理技術(shù)的使用分析。需要的朋友參考下
    2013-05-05
  • Mysql內(nèi)置函數(shù)的實現(xiàn)示例

    Mysql內(nèi)置函數(shù)的實現(xiàn)示例

    mysql內(nèi)置了很多的函數(shù),本文主要介紹了Mysql內(nèi)置函數(shù)的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-07-07
  • 查看mysql當(dāng)前連接數(shù)的方法詳解

    查看mysql當(dāng)前連接數(shù)的方法詳解

    這篇文章主要介紹了查看mysql當(dāng)前連接數(shù)的方法詳解,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-06-06
  • MySQL的索引失效的原因?qū)嵗敖鉀Q方案

    MySQL的索引失效的原因?qū)嵗敖鉀Q方案

    這篇文章主要討論了MySQL索引失效的常見原因及其解決方案,它涵蓋了數(shù)據(jù)類型不匹配、隱式轉(zhuǎn)換、函數(shù)或表達式、范圍查詢、LIKE查詢、OR條件、全表掃描、索引選擇性低、覆蓋索引不足和統(tǒng)計信息不準(zhǔn)確等問題,感興趣的朋友一起看看吧
    2024-12-12
  • 在WIN命令提示符下mysql 用戶新建、授權(quán)、刪除,密碼修改

    在WIN命令提示符下mysql 用戶新建、授權(quán)、刪除,密碼修改

    一般情況下,修改MySQL密碼,授權(quán),是需要有mysql里的root權(quán)限的,本操作是在WIN命令提示符下,感興趣的朋友可以參考下
    2013-11-11
  • MySql 5.6.14 Win32位免安裝解壓縮版配置教程

    MySql 5.6.14 Win32位免安裝解壓縮版配置教程

    本文給大家介紹mysql 5.6.14 win32 位免安裝解壓縮版配置方法,本文分步驟給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,對mysql5.6.14 免安裝解壓縮版配置方法感興趣的朋友一起看看吧
    2016-11-11
  • MySQL查詢表中某列字段相同的重復(fù)數(shù)據(jù)的方法

    MySQL查詢表中某列字段相同的重復(fù)數(shù)據(jù)的方法

    在數(shù)據(jù)庫查詢中,我們經(jīng)常需要查找表中某列中重復(fù)的數(shù)據(jù),本文將介紹如何使用 SQL 查詢語句來查找表中某列字段相同的重復(fù)數(shù)據(jù),幫助你快速定位重復(fù)數(shù)據(jù)問題并進行處理
    2023-08-08

最新評論