国产三级农村妇女在线,国产精品毛片a∨一区二区三区,国产乱子伦视频大全,国产精品色拉拉,国产欧美日韩一区二区三区,

首頁 > 技術(shù) > 數(shù)據(jù)庫

MySQL 數(shù)據(jù)庫InnoDB 存儲引擎的底層邏輯架構(gòu)

數(shù)據(jù)庫 2022-12-07 20:14:46

MySQL 數(shù)據(jù)庫有很多個存儲引擎,其中另我們印象深刻的應(yīng)該是 InnoDB 存儲引擎,它從 MySQL 5.5 之后就是默認的存儲引擎,它有支持事務(wù)、行級鎖、MVCC 以及外鍵等優(yōu)點。

那么你知道InnoDB存儲引擎的底層邏輯架構(gòu)嗎?下面我們就來聊一下InnoDB存儲引擎。

InnoDB存儲引擎主要由兩個部分組成,分別是內(nèi)存架構(gòu)磁盤架構(gòu),這兩個部分都有自己不可或缺的功能。下面我們就通過一張圖來詳細了解一下這兩個部分。


內(nèi)存架構(gòu)

內(nèi)存架構(gòu)(英文名稱:In-Memory Structures),在InnoDB存儲引擎中主要包括四個部分,分別是自適應(yīng)哈希索引、Buffer poolChange bufferLog Buffer四個部分。

1. 自適應(yīng)哈希索引

首先我們來聊聊自適應(yīng)哈希索引,自適應(yīng)哈希索引的英文名稱:Adaptive Hash Index。它的設(shè)計目的是想讓 MySQL 數(shù)據(jù)庫像內(nèi)存數(shù)據(jù)庫一樣高效,同時不會丟掉事務(wù)、行鎖以及外鍵等特性。

它并不是我們?nèi)藶槿?chuàng)建的,而是InnoDB存儲引擎通過索引監(jiān)控機制去自動創(chuàng)建的,也就是說如果InnoDB存儲引擎監(jiān)控到自適應(yīng)哈希索引可以提高查詢速度,隨即InnoDB存儲引擎會自動為本次查詢創(chuàng)建自適應(yīng)哈希索引。命中了自適應(yīng)哈希索引的查詢就不會觸發(fā)全表掃描,而是直接通過索引拿需要的數(shù)據(jù),這樣就可以提高數(shù)據(jù)庫的查詢速度。

但是自適應(yīng)哈希索引并不是任何情況下都可以使用,例如:link '%xxx',這是因為 link 前置百分號查詢本身就需要全表掃描,所以用與不用索引的結(jié)果都是一樣的,用索引反而會多此一舉,因此這種情況下不需要創(chuàng)建自適應(yīng)哈希索引。

2. Buffer pool

Buffer pool(中文名稱:緩沖池),是 MySQL 數(shù)據(jù)庫中最重要的一個部分。在數(shù)據(jù)庫啟動之時,首先會初始化這塊內(nèi)存區(qū)域,它占用了 MySQL 數(shù)據(jù)庫總內(nèi)存空間的80%以上。詳細情況可以通過show engine innodb statusG來查看:

mysql> show engine innodb statusG
----------------------
BUFFER POOL AND MEMORY
----------------------
Total large memory allocated 137428992
Dictionary memory allocated 301572
Buffer pool size   8191
Free buffers       6916
Database pages     1252
Old database pages 442
Modified db pages  0
Pending reads      0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 258, not young 1
0.00 youngs/s, 0.00 non-youngs/s
Pages read 320, created 938, written 3279
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
No buffer pool page gets since the last printout
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 1252, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]復(fù)制代碼

它的主要作用是提高數(shù)據(jù)庫查詢的效率,其中主要使用了LRU算法,下面我們一起來詳細了解一下LRU算法。


MySQL數(shù)據(jù)庫中,LRU算法的底層主要是一個鏈表。不過該鏈表被分為了兩個區(qū)域,分別是新子鏈表和舊子鏈表,而且新子鏈表占用總空間的5/8,舊子鏈表占用總空間的3/8。其主要實現(xiàn)的步驟如下:


  • 第一步:假設(shè)我們讀取數(shù)據(jù)2,這個時候恰好數(shù)據(jù)2在新子鏈表中,這個時候,會將數(shù)據(jù)2調(diào)換至新子鏈表的開頭。
  • 第二步:如果查詢一條buffer pool中沒有的數(shù)據(jù)時,MySQL數(shù)據(jù)庫將在磁盤中讀取出該條數(shù)據(jù)數(shù)據(jù)X,并且插入新子鏈表后面,同時會淘汰舊子鏈表中的數(shù)據(jù)N。

說到這里,可能就會有朋友問了,既然新數(shù)據(jù)移到鏈表的最前方,排列在最后面的數(shù)據(jù)直接淘汰,那么為什么還需要一個新子鏈表和舊子鏈表呢?

這個時候我們設(shè)想一下,假設(shè)我們查詢一個比較大的數(shù)據(jù),可能會占滿所有的Buffer pool內(nèi)存空間,按照我們理解的淘汰策略,這個時候會一下子將所有的數(shù)據(jù)全部淘汰。而這個時候正在高速運轉(zhuǎn)的數(shù)據(jù)庫會將所有的查詢?nèi)孔饔糜诖疟P,那將會導(dǎo)致系統(tǒng)磁盤 IO 急劇升高且數(shù)據(jù)庫反應(yīng)緩慢,最終會導(dǎo)致用戶體驗下降。

這個時候我們再看,如果把所有新查詢的數(shù)據(jù)全部存放于新子鏈表中,查詢的數(shù)據(jù)最多把新子鏈表中的空間全部占滿而舊子鏈表中仍然保留著之前的數(shù)據(jù),對于高速運轉(zhuǎn)的數(shù)據(jù)庫來講,就不會導(dǎo)致系統(tǒng)磁盤 IO 急劇升高和數(shù)據(jù)庫反應(yīng)緩慢了。這也正是新舊子鏈表設(shè)計的初衷。

Buffer Pool存儲塊中還保留有一個小內(nèi)存塊,即Change buffer。下面我們就來聊聊這塊內(nèi)存是用來做什么的。

3. Change buffer

Change Buffer的另一個名字叫“寫緩存”。見名知意,Change Buffer主要的功能是記錄數(shù)據(jù)庫的數(shù)據(jù)修改操作的結(jié)果的。主要目的是提高數(shù)據(jù)庫的寫性能

下面我們就來詳細分析一下,數(shù)據(jù)修改操作的步驟。

  • 第一步:修改一條數(shù)據(jù)時,首先判斷該條數(shù)據(jù)是否存在于Buffer Pool之中。
    • 如果在,直接修改Buffer Pool中的相關(guān)數(shù)據(jù)。
    • 如果不在,首先在磁盤中讀取該條數(shù)據(jù)到Change Buffer之中,而后在Change Buffer中修改該數(shù)據(jù),同時寫入Redo Log之中(為了防止數(shù)據(jù)丟失),等下一次查詢該條數(shù)據(jù)時,合并至Buffer Pool中。
  • 第二步:Change Buffer中數(shù)據(jù)修改之后,什么時候合并數(shù)據(jù)呢?
    • 第一種方式:當(dāng)修改的這條數(shù)據(jù)被查詢的時候,合并到Buffer Pool
    • 第二種方式:MySQL 數(shù)據(jù)庫中的Master Thread合并(周期默認:10s)。
    • 第三種方式:當(dāng) MySQL 數(shù)據(jù)庫關(guān)閉時,通過Redo Log合并到磁盤中。

Change Buffer之所以這樣設(shè)計,是因為對于高速運轉(zhuǎn)的 MySQL 數(shù)據(jù)庫來講,如果每一次修改都修改磁盤同時又修改Buffer Pool中的內(nèi)容的話,對于 MySQL 數(shù)據(jù)庫來講代價太大了,磁盤的 IO 也會非常高,最終會導(dǎo)致 MySQL 數(shù)據(jù)庫運行緩慢。那么,修改數(shù)據(jù)時使用Change Buffer相當(dāng)于在內(nèi)存中修改數(shù)據(jù),并且保存在內(nèi)存中,當(dāng)數(shù)據(jù)庫空閑時才會寫入磁盤,這樣既能夠達到修改數(shù)據(jù)的目的,又能夠降低數(shù)據(jù)庫對于系統(tǒng)的性能要求,進而提高數(shù)據(jù)庫的性能。

上面我們提到,Change Buffer修改完成之后,會修改redo log中的數(shù)據(jù),那么接下來我們就來了解一下Log Buffer

4. Log Buffer

我們設(shè)想一下,如果在Change Buffer修改完數(shù)據(jù)之后,僅僅保存在內(nèi)存中,那么如果這個時候數(shù)據(jù)庫宕機,也就意味著我們剛剛修改的數(shù)據(jù)也隨即丟失,而這一點是不能被允許的。

怎么解決這個問題呢?MySQL 給我們提供了一種寫日志的方案,也就是說,修改完的數(shù)據(jù)會保存到一個叫Redo Log(具體請參考下方的Redo Log部分)的日志中。它是一個物理日志,當(dāng)數(shù)據(jù)宕機時,它會將數(shù)據(jù)直接保存在磁盤之上;當(dāng)數(shù)據(jù)庫開啟時,自動寫入到數(shù)據(jù)庫的磁盤中,以至于數(shù)據(jù)不會丟失。

上方我們提到了,Redo Log是一個物理日志,如果把大量的數(shù)據(jù)直接寫進磁盤,還是會導(dǎo)致數(shù)據(jù)庫性能低下,我們用一個Log Buffer來保存需要寫入Redo log的數(shù)據(jù),這樣有利于提高數(shù)據(jù)庫的性能。

這個時候你可能會問:那Change Buffer為什么不直接寫入磁盤呢?

具體情況是這樣的,MySQL 數(shù)據(jù)庫在系統(tǒng)磁盤上保存的數(shù)據(jù)是有序的(典型就是按照主鍵 ID),如果每一次修改數(shù)據(jù)直接操作磁盤的話,會導(dǎo)致很多數(shù)據(jù)的位置發(fā)生更改(也就是我們常說的:隨機 IO),但是Redo log中保存的數(shù)據(jù)是無序的,隨意不會產(chǎn)生隨機 IO,所以使用Redo log暫時保存數(shù)據(jù)是確保數(shù)據(jù)不丟失時的最好辦法。

聊完InnoDB存儲引擎的內(nèi)存架構(gòu)之后,接下來我們再來了解一下InnoDB存儲引擎的磁盤架構(gòu)。

磁盤架構(gòu)

對于InnoDB存儲引擎來說,磁盤架構(gòu)最重要的就是表空間了。InnoDB存儲引擎的表空間主要分為:系統(tǒng)表空間、獨立表空間、普通表空間、Undo表空間以及臨時表空間。

下面我們一起來詳細聊聊InnoDB存儲引擎的磁盤架構(gòu)中的各個表空間。

1. 系統(tǒng)表空間

系統(tǒng)表空間是InnoDB存儲引擎中最重要的表空間之一,它的主要作用是存儲InnoDB數(shù)據(jù)字典、雙寫緩沖、更改緩存以及撤銷日志。

系統(tǒng)表空間一般存放于 MySQL 數(shù)據(jù)庫目錄中,名稱為:ibdata1。系統(tǒng)表空間一般不一定只有一個,也可能有多個,系統(tǒng)表空間的大小和數(shù)量由innodb_data_file_path控制。具體如下:

mysql> SHOW VARIABLES LIKE 'innodb_data_file_path';+-----------------------+------------------------+| Variable_name         | Value                  |+-----------------------+------------------------+| innodb_data_file_path | ibdata1:12M:autoextend |+-----------------------+------------------------+1 row in set (0.00 sec)復(fù)制代碼

在這里特別需要說明的是,InnoDB 數(shù)據(jù)字典在 MySQL 8.0 版本以后合并至 MySQL 數(shù)據(jù)字典中了,不再存儲在系統(tǒng)表空間中了。

這個時候你可能會問,MySQL 數(shù)據(jù)表中的數(shù)據(jù)存放于哪里呢?下面我們就來聊一聊這個問題。

2. 獨立表空間

對于innodb存儲引擎來說,我們通常創(chuàng)建數(shù)據(jù)表的時候,會在 MySQL 數(shù)據(jù)目錄中創(chuàng)建兩個文件,分別是.ibd.frm兩個文件。.ibd文件主要用來存儲表數(shù)據(jù),而.frm文件主要用來存儲索引。

這種做法可以將所有的數(shù)據(jù)表分開管理,也能夠?qū)崿F(xiàn)快速數(shù)據(jù)遷移,當(dāng)數(shù)據(jù)出現(xiàn)故障之時也可以提高數(shù)據(jù)恢復(fù)的成功率。不過這樣的做法又會增加磁盤的碎片,對系統(tǒng)處理表文件的性能有一定的影響。

3. 普通表空間

普通表空間的本質(zhì)其實就是一個共享的表空間。其具體文件在 MySQL 數(shù)據(jù)庫的數(shù)據(jù)目錄中是以.ibd結(jié)尾的文件。跟系統(tǒng)表空間類似,它支持所有 MySQL 數(shù)據(jù)庫中的數(shù)據(jù)表的結(jié)構(gòu),它是將數(shù)據(jù)庫的一些元數(shù)據(jù)保存在內(nèi)存之中,進而能夠減少獨立表空間對于內(nèi)存的消耗。

4. Undo 表空間

Undo 表空間主要是用來保存撤銷日志(即:Undo Log)的空間。它默認情況下存儲在 MySQL 數(shù)據(jù)庫的根目錄。我們可以通過以下方式來查看:

mysql> SHOW VARIABLES LIKE 'innodb_undo_directory';+--------------------------+-------+| Variable_name            | Value |+--------------------------+-------+| innodb_undo_directory    | ./    |+--------------------------+-------+4 rows in set (0.00 sec)復(fù)制代碼

MySQL 8.0版本之后,undo 表空間會在 MySQL 數(shù)據(jù)庫的數(shù)據(jù)根目錄生成 undo_001 和 undo002 共兩個文件。

5. 臨時表空間

臨時表空間主要是用來保存數(shù)據(jù)庫會話中的臨時數(shù)據(jù)的。在 MySQL 數(shù)據(jù)庫的數(shù)據(jù)根目錄中保存以ibtmp1命名的文件。最主要的是我們在使用 join 連表查詢的時候,會在臨時表空間內(nèi)創(chuàng)建臨時數(shù)據(jù)表用來輔助查詢。我們可以通過以下方式來查看臨時表空間的配置:

mysql> SELECT @@innodb_temp_data_file_path;+------------------------------+| @@innodb_temp_data_file_path |+------------------------------+| ibtmp1:12M:autoextend        |+------------------------------+1 row in set (0.00 sec)復(fù)制代碼

總結(jié)

InnoDB存儲引擎是 MySQL 數(shù)據(jù)庫中最重要的一個存儲引擎之一。今天我們一起通過它的內(nèi)存架構(gòu)和磁盤架構(gòu)深入地了解了它的底層架構(gòu)。

在內(nèi)存架構(gòu)中,自適應(yīng)哈希索引有利于提高查詢速度;Buffer pool主要提供了一個內(nèi)存池,將經(jīng)常查詢的數(shù)據(jù)存放于內(nèi)存中,這樣做有利于提高數(shù)據(jù)庫的查詢性能和降低系統(tǒng)的磁盤 IO;Change buffer主要是將修改好的數(shù)據(jù)存放于內(nèi)存之中,下一次查詢的時候合并到Buffer pool之中,這樣做的好處是可以降低修改數(shù)據(jù)時的磁盤 IO,進而提高數(shù)據(jù)庫的性能;Log Buffer是將所有修改的數(shù)據(jù)存放在其中,之后寫入到Redo Log之中,防止數(shù)據(jù)丟失。

在磁盤架構(gòu)中,系統(tǒng)表空間是用來修改和撤銷日志的地方,之前的數(shù)據(jù)庫版本中還存放InnoDB數(shù)據(jù)字典以及雙寫緩沖;獨立表空間主要是用來存儲表數(shù)據(jù)和索引的地方;普通表空間是一個共享的表空間,能夠減少獨立表空間對于內(nèi)存的消耗;Undo 表空間主要作用于事務(wù)回滾的,在使用未提交之前,用來保存原來的數(shù)據(jù),一旦事務(wù)回滾則用 Undo 表空間中的內(nèi)容替換修改過后的數(shù)據(jù),進而達到回滾的目的;臨時表空間主要是一個過渡的表空間,通常的一些操作需要有這種過渡來輔助操作,例如連表查詢。

從內(nèi)存架構(gòu)到磁盤架構(gòu),InnoDB存儲引擎為我們提供了一個高性能、高安全的數(shù)據(jù)庫存儲引擎。通常在實際應(yīng)用過程中,InnoDB存儲引擎是我們的首選存儲引擎,但是在使用過程中一定要把Buffer pool的空間設(shè)置得足夠大,這樣有利于提高數(shù)據(jù)的查詢性能。

作者:NPy

來源:稀土掘金

TAg

加載中~

本網(wǎng)站LOGO受版權(quán)及商標(biāo)保護,版權(quán)登記號:國作登字-2022-F-10126915,未經(jīng)湖南木星科技官方許可,嚴(yán)禁使用。
Copyright ? 2012-2022 湖南木星科技有限公司(木星網(wǎng))版權(quán)所有
轉(zhuǎn)載內(nèi)容版權(quán)歸作者及來源網(wǎng)站所有,本站原創(chuàng)內(nèi)容轉(zhuǎn)載請注明來源,商業(yè)媒體及紙媒請先聯(lián)系:aishangyiwan@126.com

工信部備案號:湘ICP備19012813號-5