偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

通過一條語句的執(zhí)行,深入理解InnoDB的底層架構

開發(fā) 架構
MySQL最常用的存儲引擎是innodb,我們今天就借助一條更新語句的執(zhí)行,了解下innodb具體是如何處理的,深入理解下它的架構。

 MySQL最常用的存儲引擎是innodb,我們今天就借助一條更新語句的執(zhí)行,了解下innodb具體是如何處理的,深入理解下它的架構。

假設更新語句是這樣的:

  1. update user set name ='xxx' where id = 1

這條SQL語句發(fā)送到MySQL上后,會經(jīng)過SQL接口、解析器、優(yōu)化器、執(zhí)行器幾個階段,解析SQL、生成執(zhí)行計劃,再由執(zhí)行器調(diào)用存儲引擎執(zhí)行這個執(zhí)行計劃。

如下圖所示:

圖1 MySQL底層架構

下面我們就跟隨一條update語句,分析下innodb存儲引擎的架構設計。

1、innodb最重要的組件:緩沖池(BufferPool)

innodb存儲引擎中有一個非常重要的組件,就是緩沖池(BufferPool),這里面會緩沖很多數(shù)據(jù),以便于以后操作數(shù)據(jù)的時候,可以直接操作內(nèi)存,就不用訪問磁盤了。

圖2 innoDB重要組件緩沖池

innoDB執(zhí)行上面那條更新語句的時候,會先看id = 1的這條語句是否在緩沖池中,如果不再就需要從磁盤加載到緩沖池來,而且還會對這條記錄加獨占鎖。

鎖相關的知識點,后面會有講解,這里不是重點,就不展開了。

2、undo日志文件

接下來,準備更新id = 1的這條數(shù)據(jù)時,會先把id = 1和name原來的值寫入到undo日志文件中去。

這么做的目的是什么?當然是方便回滾了。

MySQL增刪改數(shù)據(jù)都是放在事務里執(zhí)行的,如果事務提交失敗了,就可以根據(jù)undo日志進行回滾。

圖3 undo日志文件

把id = 1的那條要更新的數(shù)據(jù)加載到緩沖池,把要更新數(shù)據(jù)的舊值寫入undo日志文件后,就可以開始更新這條記錄了。

更新的時候,先更新緩沖池的數(shù)據(jù)。更新完后,緩沖池里的數(shù)據(jù)就變成:name = 'xxx'了,而此時磁盤上的數(shù)據(jù)還是name='zhangsan'。此時innoDB數(shù)據(jù)狀態(tài)就變成這樣了:

圖4 更新緩沖池數(shù)據(jù)

3、redo日志文件

此時緩沖池和磁盤上的數(shù)據(jù)是不一致的,如果MySQL宕機了,怎么辦?

此時MySQL宕機了,緩沖池里的數(shù)據(jù)肯定就丟失了。

這時候,就要引入一個新的組件:redo日志。

redo日志也是一個內(nèi)存緩沖區(qū),用來存放redo日志的,就是用來記錄你對數(shù)據(jù)做了那些修改。

比如,id = 1這條記錄,修改了name,redo日志可能就這樣:id = 1, name = 'xxx'。

圖5 redo日志

有了redo log,MySQL宕機后重啟,就可以恢復更新后的數(shù)據(jù)。

但是,如果此時MySQL數(shù)據(jù)庫宕機了,會怎樣?

必然是緩沖池中修改過的數(shù)據(jù),redo log buffer日志都會丟失。

但是,這也不要緊,因為你更新數(shù)據(jù)的事務沒有提交,此時MySQL宕機了,事務就執(zhí)行失敗了,客戶端會收到一個數(shù)據(jù)庫異常,MySQL重啟后磁盤上的數(shù)據(jù)還是原樣子。

所以數(shù)據(jù)還是一致的。

另外,redo日志是innoDB特有的一個組件。

4、提交事務

上面的步驟完成之后,就要提交事務了,此時會把redo日志刷到磁盤上去。

刷盤策略可以通過innodb_flush_log_at_trx_commit來配置。

這個配置有幾個選項:

0,提交事務的時候,不會把redo日志刷入磁盤;

1,默認值,提交事務的時候,會把redo刷入磁盤,只要事務提交成功,redo日志就比如進入磁盤了。

2,提交事務的時候,會把redo刷入os cache。操作系統(tǒng)會不定期把os cache里的數(shù)據(jù)刷到磁盤里去。

所以innodb_flush_log_at_trx_commit等于0或2的時候,redo日志都有事務提交成功,沒寫進磁盤的可能,緩沖池里更新后的數(shù)據(jù)也丟失了。此時MySQL重啟,就無法根據(jù)redo恢復更新后的數(shù)據(jù),就會出現(xiàn)數(shù)據(jù)不一致情況。

所以一般情況下,我們都會把innodb_flush_log_at_trx_commit配置為1。

圖6 redo日志

5、binlog日志

其實MySQL中提交事務的時候,還會記錄binlog。binlog是MySQL server自己的日志文件。

redo日志屬于一種偏向于物理性質(zhì)的重做日志,它里面記錄的相當于是“對某某數(shù)據(jù)頁的某某記錄,做了某某修改”。

binlog叫做歸檔日志,它里面記錄的是偏向于邏輯性的日志,類似于redis的aof日志。

我們提交事物的時候,除了把redo log日志寫到磁盤,還會同時把對應的binlog日志寫到磁盤文件中。

圖7 binlog日志

與redo log日志一樣,binlog日志有兩種刷盤策略,相應的配置項為:sync_binlog。

0,默認值,提交事務的時候,會把binlog刷入os cache。

1,提交事務的時候,會把binlog寫入磁盤。

所以,當sync_binlog設置為0的時候,如果機器宕機,binlog會有丟失的風險。設置為1的時候,即使機器宕機,binlog日志也不會丟失。

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

到此為止,一個事務提交才是完成了。

圖8 binlog刷到磁盤

最后再補充一點,在redo日志中寫入commit標識,其目的是保持redo log日志與binlog日志一致的。

也就是說,innoDB根據(jù)commit標識判定一個事務是否執(zhí)行成功。如果在圖8的5、6、7步,必須是三個步驟都執(zhí)行成功了,才算提交了事務。假如執(zhí)行其中某個步驟的時候,機器宕機了,會怎樣?

這時候,因為redo日志里沒有commit標識,所以會判定此次事務執(zhí)行不成功,就不會出現(xiàn)數(shù)據(jù)不一致的情況。

6、后臺線程把內(nèi)存數(shù)據(jù)刷到磁盤

此時事務提交了,已經(jīng)把緩沖池(BufferPool)中的數(shù)據(jù)更新了,磁盤里也有了redo日志和binlog日志,但這時候,磁盤上的數(shù)據(jù)還是舊的啊。

所以MySQL會有一個后臺IO線程,會在某個時間,隨機把緩沖池(BufferPool)中的數(shù)據(jù)刷到磁盤上去。

圖9  innoDB執(zhí)行更新語句時的完整流程

后臺IO線程把緩沖池的數(shù)據(jù)刷到磁盤前,即使MySQL宕機,也沒關系,因為機器重啟后,會根據(jù)redo日志回復之前提交事務所作的修改。

7、總結(jié)

通過一次更新數(shù)據(jù)的流程,了解了innoDB存儲引擎做了哪些工作。更新前記錄undo日志,更新緩沖池(BufferPool)里的數(shù)據(jù),記錄redo log日志,binlog日志,每一步都有其專門的作用,innoDB通過這套復雜的架構設計,保證了數(shù)據(jù)更新的高性能和一致性。 

 

責任編輯:龐桂玉 來源: Hollis
相關推薦

2020-08-10 18:03:54

Cache存儲器CPU

2024-07-18 10:12:04

2022-11-04 09:43:05

Java線程

2020-03-17 08:36:22

數(shù)據(jù)庫存儲Mysql

2018-04-16 11:04:23

HBaseRegion Serv數(shù)據(jù)庫

2022-01-14 12:28:18

架構OpenFeign遠程

2020-03-26 16:40:07

MySQL索引數(shù)據(jù)庫

2017-08-15 13:05:58

Serverless架構開發(fā)運維

2022-02-11 14:43:53

SQL語句C/S架構

2022-11-11 10:48:55

AQS源碼架構

2021-04-20 23:25:16

執(zhí)行函數(shù)變量

2024-07-08 09:29:07

2021-09-03 09:55:43

架構Yarn內(nèi)部

2023-06-07 15:34:21

架構層次結(jié)構

2024-12-17 06:20:00

MySQLSQL語句數(shù)據(jù)庫

2019-06-12 09:50:23

selectMySQLSQL

2021-09-26 09:59:14

MYSQL開發(fā)數(shù)據(jù)庫

2019-03-14 08:00:00

JavaScript執(zhí)行棧前端

2022-06-01 21:23:12

ELKLogstash底層

2012-11-22 10:11:16

LispLisp教程
點贊
收藏

51CTO技術棧公眾號