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

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

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

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

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

假設有一條如下這樣的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í)行器調用InnoDB存儲引擎的接口去執(zhí)行生成的執(zhí)行計劃。

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

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

重要的內存結構—Buffer Pool緩沖池

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

如果還沒提交事務時MySQL宕機了怎么辦

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

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

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

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

提交事務時將redo日志寫入磁盤中

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

(1)當innodb_flush_log_at_trx_commit = 0時

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

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

(2)當innodb_flush_log_at_trx_commit = 1時

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

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

(3)當innodb_flush_log_at_trx_commit = 2時

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

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

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

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

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

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

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

所以一般設置redo日志刷盤策略為1,保證事務提交后數(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ù)庫層面的日志文件。

提交事務時同時也會寫入binlog

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

下圖加入了執(zhí)行器這個組件,它會負責和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語句在磁盤與內存層面的全部數(shù)據(jù)更新操作。

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

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

binlog日志的刷盤策略分析

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

(1)當sync_binlog設置為0時

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

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

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

(2)當sync_binlog設置為1時

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

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

基于binlog的redo log完成事務的提交

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

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

在redo日志中寫入commit標記的意義

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

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

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

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

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

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

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

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

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

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

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

InnoDB存儲引擎的架構原理總結

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

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

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

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

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

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

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

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

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

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

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

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

(4)redo日志和binlog日志的數(shù)據(jù)結構是怎樣的

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日志恢復的數(shù)據(jù)庫和通過binlog日志恢復出來的臨時庫不一致。

總結

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

相關文章

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

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

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

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

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

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

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

    PHP mysqli擴展庫 預處理技術的使用分析

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

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

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

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

    這篇文章主要介紹了查看mysql當前連接數(shù)的方法詳解,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-06-06
  • MySQL的索引失效的原因實例及解決方案

    MySQL的索引失效的原因實例及解決方案

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

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

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

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

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

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

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

最新評論