日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > 数据库 >内容正文

数据库

【转】2.2【MySQL】运行原理(二):InnoDB 内存结构、磁盘结构及update sql执行过程分析

發(fā)布時(shí)間:2023/12/10 数据库 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【转】2.2【MySQL】运行原理(二):InnoDB 内存结构、磁盘结构及update sql执行过程分析 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前一篇講完了查詢流程,我們是不是再講講更新流程、插入流程和刪除流程?在數(shù)據(jù)庫(kù)里面,我們說(shuō)的update操作其實(shí)包括了更新、插入和刪除。如果大家有看過(guò)MyBatis的源碼,應(yīng)該知道Executor里面也只有doQuery()和doUpdate()的方法,沒(méi)有doDelete()和doInsert()。

更新流程和查詢流程有什么不同呢?基本流程也是一致的,也就是說(shuō),它也要經(jīng)過(guò)解析器、優(yōu)化器的處理,最后交給執(zhí)行器。區(qū)別就在于拿到符合條件的數(shù)據(jù)之后的操作。

緩沖池 Buffer Pool

首先,InnnoDB的數(shù)據(jù)都是放在磁盤上的,InnoDB操作數(shù)據(jù)有一個(gè)最小的邏輯單位,叫做頁(yè)(索引頁(yè)和數(shù)據(jù)頁(yè))。我們對(duì)于數(shù)據(jù)的操作,不是每次都直接操作磁盤,因?yàn)榇疟P的速度太慢了。 InnoDB使用了一種緩沖池的技術(shù),也就是把磁盤讀到的頁(yè)放到一塊內(nèi)存區(qū)域里面。這個(gè)內(nèi)存區(qū)域就叫Buffer Pool。

下一次讀取相同的頁(yè),先判斷是不是在緩沖池里面,如果是,就直接讀取,不用再次訪問(wèn)磁盤。

修改數(shù)據(jù)的時(shí)候,先修改緩沖池里面的頁(yè)。內(nèi)存的數(shù)據(jù)頁(yè)和磁盤數(shù)據(jù)不一致的時(shí)候,我們把它叫做臟頁(yè)。InnoDB里面有專門的后臺(tái)線程把Buffer Pool的數(shù)據(jù)寫入到磁盤,每隔一段時(shí)間就一次性地把多個(gè)修改寫入磁盤,這個(gè)動(dòng)作就叫做刷臟。


BufferPool是InnoDB里面非常重要的一個(gè)結(jié)構(gòu),它的內(nèi)部又分成幾塊區(qū)域。這里我們趁機(jī)到官網(wǎng)來(lái)認(rèn)識(shí)一下InnoDB的內(nèi)存結(jié)構(gòu)和磁盤結(jié)構(gòu)。

1.Innodb 內(nèi)存結(jié)構(gòu)

Innodb的內(nèi)存結(jié)構(gòu)主要分為 3 個(gè)部分: Buffer Pool、Change Buffer、Adaptive HashIndex,另外還有一個(gè)(redo)log buffer。

1.1 Buffer Pool

Buffer Pool緩存的是頁(yè)面信息,包括數(shù)據(jù)頁(yè)、索引頁(yè)。

SHOW STATUS LIKE '%innodb_buffer_pool%'; -- 查看服務(wù)器狀態(tài)中 Buffer Pool 相關(guān)信息 SHOW VARIABLES like '%innodb_buffer_pool%'; -- 查看參數(shù)(系統(tǒng)變量)

這些狀態(tài)都可以在官網(wǎng)查到詳細(xì)的含義,用搜索功能。 Buffer Pool默認(rèn)大小是128M(134217728字節(jié)),可以調(diào)整。

內(nèi)存的緩沖池寫滿了怎么辦?(Redis 設(shè)置的內(nèi)存滿了怎么辦?)InnoDB 用 LRU算法來(lái)管理緩沖池(鏈表實(shí)現(xiàn),不是傳統(tǒng)的LRU,分成了young和old),經(jīng)過(guò)淘汰的數(shù)據(jù)就是熱點(diǎn)數(shù)據(jù)。

內(nèi)存緩沖區(qū)對(duì)于提升讀寫性能有很大的作用。思考一個(gè)問(wèn)題:當(dāng)需要更新一個(gè)數(shù)據(jù)頁(yè)時(shí),如果數(shù)據(jù)頁(yè)在BufferPool中存在,那么就直接更新好了。否則的話就需要從磁盤加載到內(nèi)存,再對(duì)內(nèi)存的數(shù)據(jù)頁(yè)進(jìn)行操作。也就是說(shuō),如果沒(méi)有命中緩沖池,至少要產(chǎn)生一次磁盤IO,有沒(méi)有優(yōu)化的方式呢?

1.2 Change Buffer(寫緩沖)

如果這個(gè)數(shù)據(jù)頁(yè)不是唯一索引(注:唯一索引就是在同一字段下不能有相同值),也就不需要從磁盤加載索引頁(yè)判斷數(shù)據(jù)是不是重復(fù)(唯一性檢查)。這種情況下可以先把修改記錄在內(nèi)存的緩沖池中,從而提升更新語(yǔ)句(Insert、Delete、Update)的執(zhí)行速度。這一塊區(qū)域就是 Change Buffer。5.5 之前叫Insert Buffer 插入緩沖,現(xiàn)在也能支持delete和update。最后把 Change Buffer 記錄到數(shù)據(jù)頁(yè)的操作叫做 merge。

什么時(shí)候發(fā)生 merge?有幾種情況:在訪問(wèn)這個(gè)數(shù)據(jù)頁(yè)的時(shí)候,或者通過(guò)后臺(tái)線程、或者數(shù)據(jù)庫(kù)shut down、redo log寫滿時(shí)觸發(fā)。

如果數(shù)據(jù)庫(kù)大部分索引都是非唯一索引,并且業(yè)務(wù)是寫多讀少,不會(huì)在寫數(shù)據(jù)后立刻讀取,就可以使用Change Buffer(寫緩沖)。寫多讀少的業(yè)務(wù),調(diào)大這個(gè)值:

SHOW VARIABLES LIKE 'innodb_change_buffer_max_size';

max_size 代表Change Buffer占Buffer Pool的比例,默認(rèn)25%。

1.3 Adaptive Hash Index

索引應(yīng)該是放在磁盤的,為什么要專門把一種哈希的索引放到內(nèi)存?這里就不說(shuō)了,把問(wèn)題的答案放在詳談索引存儲(chǔ)結(jié)構(gòu)推演過(guò)程…

1.4 Log Buffer(Redo log)

MySQL 在更新數(shù)據(jù)時(shí),為了減少磁盤的隨機(jī) IO,因此并不會(huì)直接更新磁盤上的數(shù)據(jù),而是先更新 Buffer Pool 中緩存頁(yè)的數(shù)據(jù),等到合適的時(shí)間點(diǎn),再將這個(gè)緩存頁(yè)持久化到磁盤。而 Buffer Pool 中所有緩存頁(yè)都是處于內(nèi)存當(dāng)中的,當(dāng) MySQL 宕機(jī)或者機(jī)器斷電,內(nèi)存中的數(shù)據(jù)就會(huì)丟失,因此 MySQL 為了防止緩存頁(yè)中的數(shù)據(jù)在更新后出現(xiàn)數(shù)據(jù)丟失的現(xiàn)象,引入了 redo log 機(jī)制。

當(dāng)進(jìn)行增刪改操作時(shí),MySQL 會(huì)在更新 Buffer Pool 中的緩存頁(yè)數(shù)據(jù)時(shí),會(huì)記錄一條對(duì)應(yīng)操作的 redo log 日志,這樣如果出現(xiàn) MySQL 宕機(jī)或者斷電時(shí),如果有緩存頁(yè)的數(shù)據(jù)還沒(méi)來(lái)得及刷入磁盤,那么當(dāng) MySQL 重新啟動(dòng)時(shí),可以根據(jù) redo log 日志文件,進(jìn)行數(shù)據(jù)重做,將數(shù)據(jù)恢復(fù)到宕機(jī)或者斷電前的狀態(tài),保證了更新的數(shù)據(jù)不丟失,因此 redo log 又叫做重做日志。它的本質(zhì)是保證事務(wù)提交后,更新的數(shù)據(jù)不丟失。——用它來(lái)實(shí)現(xiàn)事務(wù)的持久性。


這種日志和磁盤配合的整個(gè)過(guò)程,其實(shí)就是 MySQL 里的 WAL 技術(shù)(Write-Ahead Logging),它的關(guān)鍵點(diǎn)就是先寫日志,再寫磁盤。

同樣是寫磁盤,為什么不直接寫db file,而是先寫日志?

我們先來(lái)了解一下隨機(jī)I/O和順序I/O的概念。磁盤的最小組成單元是扇區(qū),通常是512個(gè)字節(jié)。操作系統(tǒng)和內(nèi)存打交道,最小的單位是頁(yè)P(yáng)age。操作系統(tǒng)和磁盤打交道,讀寫磁盤,最小的單位是塊Block。

如果我們所需要的數(shù)據(jù)是隨機(jī)分散在不同頁(yè)的不同扇區(qū)中,那么找到相應(yīng)的數(shù)據(jù)需要等到磁臂旋轉(zhuǎn)到指定的頁(yè),然后盤片尋找到對(duì)應(yīng)的扇區(qū),才能找到我們所需要的一塊數(shù)據(jù),一次進(jìn)行此過(guò)程直到找完所有數(shù)據(jù),這個(gè)就是隨機(jī)IO,讀取數(shù)據(jù)速度較慢。

假設(shè)我們已經(jīng)找到了第一塊數(shù)據(jù),并且其他所需的數(shù)據(jù)就在這一塊數(shù)據(jù)后邊,那么就不需要重新尋址,可以依次拿到我們所需的數(shù)據(jù),這個(gè)就叫順序IO。

刷盤是隨機(jī)I/O,而記錄日志是順序I/O,順序I/O效率更高。所以,先不斷把內(nèi)存中bufferpool的數(shù)據(jù)修改寫入日志,保證不會(huì)丟失,然后等到一個(gè)適當(dāng)?shù)臅r(shí)機(jī)(系統(tǒng)比較空閑)將操作記錄更新到磁盤里面。達(dá)到延遲刷盤時(shí)機(jī)的目的,進(jìn)而提升系統(tǒng)吞吐。redo log存在的意義主要就是降低對(duì)數(shù)據(jù)頁(yè)刷盤的要求。

redo log(重做日志)有什么特點(diǎn)?

  • redo log是InnoDB存儲(chǔ)引擎實(shí)現(xiàn)的,并不是所有存儲(chǔ)引擎都有。

  • 不是記錄數(shù)據(jù)頁(yè)更新之后的狀態(tài)(某一行或某幾行修改成怎樣怎樣),而是記錄當(dāng)前頁(yè)做了什么改動(dòng),屬于物理日志。它用來(lái)恢復(fù)提交后的物理數(shù)據(jù)頁(yè)(恢復(fù)數(shù)據(jù)頁(yè),且只能恢復(fù)到最后一次提交的位置)

    日志分為物理日志和邏輯日志。

    • 物理日志就是直接記錄數(shù)據(jù),記錄被修改的page的偏移量,優(yōu)點(diǎn)就是不依賴原page的內(nèi)容,用日志的內(nèi)容可以直接覆蓋到磁盤上面,而缺點(diǎn)就是占用的空間太多,比如新增一個(gè)btree索引或者一個(gè)update操作。
    • 邏輯日志只是記錄關(guān)系表上面的元操作,比如update一行數(shù)據(jù),delete一行數(shù)據(jù)等,優(yōu)點(diǎn)就是比較簡(jiǎn)潔而且占用的空間要小,缺點(diǎn)就是需要依賴原page內(nèi)容,而且會(huì)有部分執(zhí)行和操作一致性的問(wèn)題。
  • redo log 分成內(nèi)存和磁盤兩部分:

    • 內(nèi)存部分:Log Buffer,存在刷盤操作。
    • 磁盤部分:對(duì)應(yīng)于 /var/lib/mysql/目錄下的ib_logfile0和ib_logfile1,每個(gè)48M。
  • 因?yàn)閞edo log 實(shí)際上記錄數(shù)據(jù)頁(yè)的變更,而這種變更記錄是沒(méi)必要全部保存,所以 redo log 的大小是固定的,前面的內(nèi)容會(huì)被覆蓋。如下圖所示:

  • 再?gòu)?qiáng)調(diào)一次,redo log的內(nèi)容主要是用于崩潰恢復(fù)。磁盤的數(shù)據(jù)文件,數(shù)據(jù)來(lái)自 buffer pool。redo log 寫入磁盤,不是寫入數(shù)據(jù)文件。

    redo log 的內(nèi)存部分:Log Buffer

    當(dāng)然redo log也不是每一次都直接寫入磁盤,在Buffer Pool里面有一塊內(nèi)存區(qū)域(Log Buffer)專門用來(lái)保存即將要寫入日志文件的數(shù)據(jù),Innodb_log_buffer默認(rèn)大小為8M,它一樣可以節(jié)省磁盤IO。

    SHOW VARIABLES LIKE 'innodb_log_buffer_size';


    那么,Log Buffer什么時(shí)候?qū)懭雔og file,或者說(shuō)什么日志什么時(shí)候刷盤?

    在我們寫入數(shù)據(jù)到磁盤的時(shí)候,操作系統(tǒng)本身是有緩存的。flush就是把操作系統(tǒng)緩沖區(qū)寫入到磁盤。log buffer寫入磁盤的時(shí)機(jī),由一個(gè)參數(shù)控制,默認(rèn)是1。

    值含義
    0(延遲寫)logbuffer 將每秒一次地寫入 logfile 中,并且 logfile 的 flush 操作同時(shí)進(jìn)行。 該模式下,在事務(wù)提交的時(shí)候,不會(huì)主動(dòng)觸發(fā)寫入磁盤的操作。
    1(默認(rèn),實(shí)時(shí)寫,實(shí)時(shí)刷)每次事務(wù)提交時(shí) MySQL 都會(huì)把 logbuffer 的數(shù)據(jù)寫入 logfile,并且刷到磁盤中去。
    2(實(shí)時(shí)寫,延遲刷)每次事務(wù)提交時(shí) MySQL 都會(huì)把 logbuffer 的數(shù)據(jù)寫入 logfile。但是 flush 操作并不會(huì)同時(shí)進(jìn)行。該模式下,MySQL 會(huì)每秒執(zhí)行一次 flush 操作。

    SHOW VARIABLES LIKE 'innodb_flush_log_at_trx_commit';

    以上就是MySQL的內(nèi)存結(jié)構(gòu)。總結(jié)一下,分為:Buffer pool、change buffer、Adaptive Hash Index、 log buffer。

    2.Innodb 磁盤結(jié)構(gòu)(表空間)

    磁盤結(jié)構(gòu)里面主要是各種各樣的表空間,叫做Table space。表空間可以看做是 InnoDB 存儲(chǔ)引擎邏輯結(jié)構(gòu)的最高層,所有的數(shù)據(jù)都存放在表空間中。InnoDB的表空間分為5大類。

    2.1 system tablespace(系統(tǒng)表空間)

    在默認(rèn)情況下 InnoDB 存儲(chǔ)引擎有一個(gè)共享表空間(對(duì)應(yīng)文件/var/lib/mysql/ibdata1),也叫系統(tǒng)表空間。


    InnoDB系統(tǒng)表空間包含InnoDB數(shù)據(jù)字典和雙寫緩沖區(qū),ChangeBuffer和UndoLogs),如果沒(méi)有指定file-per-table,也包含用戶創(chuàng)建的表和索引數(shù)據(jù)。

    • undo在后面介紹,因?yàn)橛歇?dú)立的表空間。
    • 數(shù)據(jù)字典:由內(nèi)部系統(tǒng)表組成,存儲(chǔ)表和索引的元數(shù)據(jù)(定義信息)。
    • 雙寫緩沖(InnoDB的一大特性):InnoDB的頁(yè)和操作系統(tǒng)的頁(yè)大小不一致,InnoDB頁(yè)大小一般為16K,操作系統(tǒng)頁(yè)大小為4K,InnoDB的頁(yè)寫入到磁盤時(shí),一個(gè)頁(yè)需要分4次寫。

    如果存儲(chǔ)引擎正在寫入頁(yè)的數(shù)據(jù)到磁盤時(shí)發(fā)生了宕機(jī),可能出現(xiàn)頁(yè)只寫了一部分的情況,比如只寫了4K,就宕機(jī)了,這種情況叫做部分寫失效(partial page write),可能會(huì)導(dǎo)致數(shù)據(jù)丟失。

    show variables like 'innodb_doublewrite';

    我們不是有 redo log 嗎?但是有個(gè)問(wèn)題,如果這個(gè)頁(yè)本身已經(jīng)損壞了,用它來(lái)做崩潰恢復(fù)是沒(méi)有意義的。所以在對(duì)于應(yīng)用redo log之前,需要一個(gè)頁(yè)的副本。如果出現(xiàn)了寫入失效,就用頁(yè)的副本來(lái)還原這個(gè)頁(yè),然后再應(yīng)用redo log。這個(gè)頁(yè)的副本就是?double write,InnoDB的雙寫技術(shù)。通過(guò)它實(shí)現(xiàn)了數(shù)據(jù)頁(yè)的可靠性。

    跟 redo log 一樣,double write 由兩部分組成,一部分是內(nèi)存的double write,一個(gè)部分是磁盤上的double write。因?yàn)閐ouble write是順序?qū)懭氲?#xff0c;不會(huì)帶來(lái)很大的開(kāi)銷。在默認(rèn)情況下,所有的表共享一個(gè)系統(tǒng)表空間,這個(gè)文件會(huì)越來(lái)越大,而且它的空間不會(huì)收縮。

    2.2 file-per-table tablespaces(獨(dú)占表空間)

    我們可以讓每張表獨(dú)占一個(gè)表空間。這個(gè)開(kāi)關(guān)通過(guò)innodb_file_per_table設(shè)置,默認(rèn)開(kāi)啟。

    SHOW VARIABLES LIKE 'innodb_file_per_table';

    開(kāi)啟后,則每張表會(huì)開(kāi)辟一個(gè)表空間,這個(gè)文件就是數(shù)據(jù)目錄下的 ibd文件(例如
    /var/lib/mysql/forum/user_innodb.ibd),存放表的索引和數(shù)據(jù)。

    但是其他類的數(shù)據(jù),如回滾(undo)信息,插入緩沖索引頁(yè)、系統(tǒng)事務(wù)信息,二次寫緩沖(Double write buffer)等還是存放在原來(lái)的共享表空間內(nèi)。

    2.3 general tablespaces(通用表空間)

    通用表空間也是一種共享的表空間,跟ibdata1類似。可以創(chuàng)建一個(gè)通用的表空間,用來(lái)存儲(chǔ)不同數(shù)據(jù)庫(kù)的表,數(shù)據(jù)路徑和文件可以自定義。語(yǔ)法:

    create table space ts2673 add datafile '/var/lib/mysql/ts2673.ibd' file_block_size=16K engine=innodb;

    在創(chuàng)建表的時(shí)候可以指定表空間,用ALTER修改表空間可以轉(zhuǎn)移表空間。

    create table t2673(idinteger) tablespace ts2673;

    不同表空間的數(shù)據(jù)是可以移動(dòng)的。刪除表空間需要先刪除里面的所有表:

    drop table t2673; drop tablespace ts2673;

    2.4 temporary tablespaces(臨時(shí)表空間)

    存儲(chǔ)臨時(shí)表的數(shù)據(jù),包括用戶創(chuàng)建的臨時(shí)表,和磁盤的內(nèi)部臨時(shí)表。對(duì)應(yīng)數(shù)據(jù)目錄下的ibtmp1文件。當(dāng)數(shù)據(jù)服務(wù)器正常關(guān)閉時(shí),該表空間被刪除,下次重新產(chǎn)生。

    2.5 undo log tablespace

    undo log(撤銷日志或回滾日志)記錄了事務(wù)發(fā)生之前的數(shù)據(jù)狀態(tài)(不包括select) 。用來(lái)保證在必要時(shí)實(shí)現(xiàn)回滾,如果另一個(gè)事務(wù)需要在一致性讀操作中查看原始數(shù)據(jù),則從undo日志記錄中檢索未修改的數(shù)據(jù),也就是說(shuō)MVCC機(jī)制也依賴于undo log來(lái)實(shí)現(xiàn)。在執(zhí)行 undo 的時(shí)候,僅僅是將數(shù)據(jù)從邏輯上恢復(fù)至事務(wù)之前的狀態(tài),而不是從物理頁(yè)面上操作實(shí)現(xiàn)的,屬于邏輯格式的日志。

    redo Log 和 undo Log 與事務(wù)密切相關(guān),統(tǒng)稱為事務(wù)日志。但與redo log不同的是:

    • redo log 是存儲(chǔ)的是物理日志,undo log存儲(chǔ)的是邏輯日志
    • redo log 是重做日志,提供?前滾?操作;undo log 是回退日志,提供?回滾?操作。

    undo 是在事務(wù)開(kāi)始之前保存的被修改數(shù)據(jù)的一個(gè)版本,產(chǎn)生undo日志的時(shí)候,同樣會(huì)伴隨類似于保護(hù)事務(wù)持久化機(jī)制的 redo log 的產(chǎn)生。

    • Redo 記錄某?數(shù)據(jù)塊?被修改??的值,可以用來(lái)恢復(fù)未寫入 data file 的已成功事務(wù)更新的數(shù)據(jù)。-- 保證事務(wù)持久性
    • Undo 記錄某?數(shù)據(jù)?被修改??的值,可以用來(lái)在事務(wù)失敗時(shí)進(jìn)行 rollback;-- 保證事務(wù)原子性


    比如某一時(shí)刻數(shù)據(jù)庫(kù) DOWN 機(jī)了,有兩個(gè)事務(wù),一個(gè)事務(wù)已經(jīng)提交,另一個(gè)事務(wù)正在處理。數(shù)據(jù)庫(kù)重啟的時(shí)候就要根據(jù)日志進(jìn)行前滾及回滾,把已提交事務(wù)的更改寫到數(shù)據(jù)文件,未提交事務(wù)的更改恢復(fù)到事務(wù)開(kāi)始前的狀態(tài)。

    • 當(dāng)數(shù)據(jù) crash-recovery 時(shí),通過(guò) redo log 將所有已經(jīng)在存儲(chǔ)引擎內(nèi)部提交的事務(wù)應(yīng)用 redo log 恢復(fù)
    • 所有已經(jīng) prepared 但是沒(méi)有 commit 的 transactions 將會(huì)應(yīng)用 undo log 做 roll back

    undo Log 的數(shù)據(jù)默認(rèn)在系統(tǒng)表空間ibdata1 文件中,因?yàn)楣蚕肀砜臻g不會(huì)自動(dòng)收縮,也可以單獨(dú)創(chuàng)建一個(gè)undo表空間。

    ==>update過(guò)程分析

    有了這些日志之后,我們來(lái)總結(jié)一下一個(gè)更新操作的流程,這是一個(gè)簡(jiǎn)化的過(guò)程(name原值是zhangsan)。

    update user set name='penyuyan' where id=1; 1. 事務(wù)開(kāi)始,從內(nèi)存或磁盤取到這條數(shù)據(jù),返回給Server 的執(zhí)行器; 2. 執(zhí)行器修改這一行數(shù)據(jù)的值為penyuyan; 3. 記錄 name=zhangsan 到 undo log; 4. 記錄 name=penyuyan 到 redo log; 5. 調(diào)用存儲(chǔ)引擎接口,在內(nèi)存(Buffer Pool)中修改 name=zhangsan; 6. 事務(wù)提交

    另外,內(nèi)存和磁盤之間,工作著很多后臺(tái)線程。后臺(tái)線程的主要作用是負(fù)責(zé)刷新內(nèi)存池中的數(shù)據(jù)和把修改的數(shù)據(jù)頁(yè)刷新到磁盤。后臺(tái)線程分為:master thread,IO thread,purge thread,page cleaner thread。

    • master thread:負(fù)責(zé)刷新緩存數(shù)據(jù)到磁盤并協(xié)調(diào)調(diào)度其它后臺(tái)進(jìn)程
    • IO thread:分為 insert buffer、 log、 read、 write進(jìn)程。分別用來(lái)處理 insert buffer、重做日志、讀寫請(qǐng)求的IO回調(diào)
    • purge thread:用來(lái)回收undo 頁(yè)
    • page cleaner thread:用來(lái)刷新臟頁(yè)

    除了 InnoDB 架構(gòu)中的日志文件,MySQL 的 Server 層也有一個(gè)日志文件,叫做binlog,它可以被所有的存儲(chǔ)引擎使用。

    binlog 以事件的形式記錄了所有的DDL和DML語(yǔ)句(因?yàn)樗?strong>記錄的是操作而不是數(shù)據(jù)值,屬于邏輯日志),可以用來(lái)做主從復(fù)制和數(shù)據(jù)恢復(fù)。跟redo log不一樣,它的文件內(nèi)容是可以追加的,沒(méi)有固定大小限制。

    在開(kāi)啟了binlog功能的情況下,我們可以把binlog導(dǎo)出成SQL語(yǔ)句,把所有的操作重放一遍,來(lái)實(shí)現(xiàn)數(shù)據(jù)的恢復(fù)。binlog的另一個(gè)功能就是用來(lái)實(shí)現(xiàn)主從復(fù)制,它的原理就是從服務(wù)器讀取主服務(wù)器的binlog,然后執(zhí)行一遍。

    參考鏈接:對(duì)比總結(jié)三大日志:重做日志(redo log),回滾日志(undo log),二進(jìn)制日志(binlog)

    有了這兩個(gè)日志之后,我們來(lái)看一下一條更新語(yǔ)句是怎么執(zhí)行的:

    update teacher set name='盆魚(yú)宴' where id=1

    1. 先查詢到這條數(shù)據(jù),如果有緩存,也會(huì)用到緩存。 2. 把name改成盆魚(yú)宴,然后調(diào)用引擎的API接口,寫入這一行數(shù)據(jù)到內(nèi)存,同時(shí)記錄redo log。這時(shí) redo log 進(jìn)入prepare 狀態(tài),然后告訴執(zhí)行器,執(zhí)行完成了,可以隨時(shí)提交。 3. 執(zhí)行器收到通知后記錄binlog,然后調(diào)用存儲(chǔ)引擎接口, 設(shè)置redolog為commit狀態(tài)。 4. 更新完成。

    需要特別注意的幾點(diǎn):

  • 先記錄到內(nèi)存,再寫日志文件。
  • 記錄redo log分為兩個(gè)階段。
  • 存儲(chǔ)引擎和Server記錄不同的日志,先記錄redo,再記錄binlog

  • 總結(jié)腦圖

    總結(jié)

    以上是生活随笔為你收集整理的【转】2.2【MySQL】运行原理(二):InnoDB 内存结构、磁盘结构及update sql执行过程分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。