自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

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

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

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

假設(shè)更新語(yǔ)句是這樣的:

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

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

如下圖所示:

圖1 MySQL底層架構(gòu)

下面我們就跟隨一條update語(yǔ)句,分析下innodb存儲(chǔ)引擎的架構(gòu)設(shè)計(jì)。

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

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

圖2 innoDB重要組件緩沖池

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

鎖相關(guān)的知識(shí)點(diǎn),后面會(huì)有講解,這里不是重點(diǎn),就不展開了。

2、undo日志文件

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

這么做的目的是什么?當(dāng)然是方便回滾了。

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

圖3 undo日志文件

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

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

圖4 更新緩沖池?cái)?shù)據(jù)

3、redo日志文件

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

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

這時(shí)候,就要引入一個(gè)新的組件:redo日志。

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

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

圖5 redo日志

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

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

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

但是,這也不要緊,因?yàn)槟愀聰?shù)據(jù)的事務(wù)沒有提交,此時(shí)MySQL宕機(jī)了,事務(wù)就執(zhí)行失敗了,客戶端會(huì)收到一個(gè)數(shù)據(jù)庫(kù)異常,MySQL重啟后磁盤上的數(shù)據(jù)還是原樣子。

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

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

4、提交事務(wù)

上面的步驟完成之后,就要提交事務(wù)了,此時(shí)會(huì)把redo日志刷到磁盤上去。

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

這個(gè)配置有幾個(gè)選項(xiàng):

0,提交事務(wù)的時(shí)候,不會(huì)把redo日志刷入磁盤;

1,默認(rèn)值,提交事務(wù)的時(shí)候,會(huì)把redo刷入磁盤,只要事務(wù)提交成功,redo日志就比如進(jìn)入磁盤了。

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

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

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

圖6 redo日志

5、binlog日志

其實(shí)MySQL中提交事務(wù)的時(shí)候,還會(huì)記錄binlog。binlog是MySQL server自己的日志文件。

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

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

我們提交事物的時(shí)候,除了把redo log日志寫到磁盤,還會(huì)同時(shí)把對(duì)應(yīng)的binlog日志寫到磁盤文件中。

圖7 binlog日志

與redo log日志一樣,binlog日志有兩種刷盤策略,相應(yīng)的配置項(xiàng)為:sync_binlog。

0,默認(rèn)值,提交事務(wù)的時(shí)候,會(huì)把binlog刷入os cache。

1,提交事務(wù)的時(shí)候,會(huì)把binlog寫入磁盤。

所以,當(dāng)sync_binlog設(shè)置為0的時(shí)候,如果機(jī)器宕機(jī),binlog會(huì)有丟失的風(fēng)險(xiǎn)。設(shè)置為1的時(shí)候,即使機(jī)器宕機(jī),binlog日志也不會(huì)丟失。

當(dāng)我們把binlog日志寫入磁盤后,接著就完成了最終的事務(wù)提交,最后會(huì)把本次更新對(duì)應(yīng)的binlog日志文件名和這次更新的binlog日志在文件里的位置,都寫入到redo log日志里去,同時(shí)在redo log日志文件里寫入一個(gè)commit標(biāo)記。

到此為止,一個(gè)事務(wù)提交才是完成了。

圖8 binlog刷到磁盤

最后再補(bǔ)充一點(diǎn),在redo日志中寫入commit標(biāo)識(shí),其目的是保持redo log日志與binlog日志一致的。

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

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

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

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

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

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

后臺(tái)IO線程把緩沖池的數(shù)據(jù)刷到磁盤前,即使MySQL宕機(jī),也沒關(guān)系,因?yàn)闄C(jī)器重啟后,會(huì)根據(jù)redo日志回復(fù)之前提交事務(wù)所作的修改。

7、總結(jié)

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

 

責(zé)任編輯:龐桂玉 來源: Hollis
相關(guān)推薦

2020-08-10 18:03:54

Cache存儲(chǔ)器CPU

2024-07-18 10:12:04

2022-11-04 09:43:05

Java線程

2020-03-17 08:36:22

數(shù)據(jù)庫(kù)存儲(chǔ)Mysql

2020-03-26 16:40:07

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

2018-04-16 11:04:23

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

2022-01-14 12:28:18

架構(gòu)OpenFeign遠(yuǎn)程

2017-08-15 13:05:58

Serverless架構(gòu)開發(fā)運(yùn)維

2022-02-11 14:43:53

SQL語(yǔ)句C/S架構(gòu)

2022-11-11 10:48:55

AQS源碼架構(gòu)

2021-04-20 23:25:16

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

2024-07-08 09:29:07

2021-09-03 09:55:43

架構(gòu)Yarn內(nèi)部

2024-12-17 06:20:00

MySQLSQL語(yǔ)句數(shù)據(jù)庫(kù)

2023-06-07 15:34:21

架構(gòu)層次結(jié)構(gòu)

2019-06-12 09:50:23

selectMySQLSQL

2021-09-26 09:59:14

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

2019-03-14 08:00:00

JavaScript執(zhí)行棧前端

2022-06-01 21:23:12

ELKLogstash底層

2022-05-31 13:58:09

MySQL查詢語(yǔ)句
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)