InnoDB 存儲結(jié)構(gòu)

MySQL 5.5 版本開始默認(rèn)使用 InnoDB 作為引擎做葵,它擅長處理事務(wù)酗洒,具有自動崩潰恢復(fù)的特性窗骑,在日常開發(fā)中使用非常廣泛。下面是官方的 InnoDB 引擎架構(gòu)圖耳鸯,主要分為內(nèi)存結(jié)構(gòu)和磁盤結(jié)構(gòu)兩大部分湿蛔。

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

內(nèi)存結(jié)構(gòu)主要包括 Bu?er Pool膀曾、Change Bu?erAdaptive Hash IndexLog Bu?er 四大組件阳啥。

SHOW ENGINE INNODB STATUS;


Database pages + Free buffers <= Buffer pool size(其它空間有可能分配給自適應(yīng)索引和 changeBuffer

1.1 Buffer Pool

緩沖池添谊,簡稱 BPBPPage 頁為單位苫纤,默認(rèn)大小 16K碉钠,BP 的底層采用鏈表數(shù)據(jù)結(jié)構(gòu)管理 Page。在 InnoDB 訪問表記錄和索引時會在 Page 頁中緩存卷拘,以后使用可以減少磁盤 IO 操作喊废,提升效率。

1.1.1 Page 管理機(jī)制

Page 根據(jù)狀態(tài)可以分為三種類型:

  • free page : 空閑 page栗弟,未被使用
  • clean page:被使用 page污筷,數(shù)據(jù)沒有被修改過
  • dirty page:臟頁,被使用 page乍赫,數(shù)據(jù)被修改過瓣蛀,頁中數(shù)據(jù)和磁盤的數(shù)據(jù)產(chǎn)生了不一致

針對上述三種 page 類型,InnoDB 通過三種鏈表結(jié)構(gòu)來維護(hù)和管理

  • free list :表示空閑緩沖區(qū)雷厂,管理 free page
  • ?ush list:表示需要刷新到磁盤的緩沖區(qū)惋增,管理 dirty page,內(nèi)部 page 按修改時間排序改鲫。臟頁既存在于 ?ush鏈表诈皿,也在 LRU鏈表 中,但是兩種互不影響像棘,LRU鏈表 負(fù)責(zé)管理 page 的可用性和釋放稽亏,而 ?ush鏈表 負(fù)責(zé)管理臟頁的刷盤操作。
  • lru list:表示正在使用的緩沖區(qū)缕题,管理 clean pagedirty page截歉,緩沖區(qū)以 midpoint 為基點,前面鏈表稱為 new 列表區(qū)烟零,存放經(jīng)常訪問的數(shù)據(jù)瘪松,占 63%;后 面的鏈表稱為 old列表區(qū)瓶摆,存放使用較少數(shù)據(jù)凉逛,占37%
1.1.2 改進(jìn)型 LRU 算法維護(hù)
  • 普通 LRU:末尾淘汰法群井,新數(shù)據(jù)從鏈表頭部加入,釋放空間時從末尾淘汰
  • 改進(jìn) LRU:鏈表分為 newold 兩個部分毫胜,加入元素時并不是從表頭插入书斜,而是從中間 midpoint 位置插入诬辈,如果數(shù)據(jù)很快被訪問,那么 page 就會向 new 列表頭部移動荐吉,如果數(shù)據(jù)沒有被訪問焙糟,會逐步向 old 尾部移動,等待淘汰样屠。

每當(dāng)有新的 page 數(shù)據(jù)讀取到 buffer pool 時穿撮,InnoDB 引擎會判斷是否有空閑頁,是否足夠痪欲,如果有就將 free pagefree list列表刪除悦穿,放入到 LRU 列表中。沒有空閑頁业踢,就會根據(jù) LRU 算法淘汰 LRU鏈表默認(rèn)的頁栗柒,將內(nèi)存空間釋放分配給新的頁。

1.1.3 Buffer Pool 配置參數(shù)
-- 查看page頁大小
show variables like '%innodb_page_size%';
-- 查看 lru list 中 old 列表參數(shù)
show variables like '%innodb_old%';
-- 查看 bu?er pool 參數(shù)
show variables like '%innodb_buffer%';  

建議:innodb_buffer_pool_size 設(shè)置為總內(nèi)存大小的 60%-80%知举, innodb_buffer_pool_instances 可以設(shè)置為多個瞬沦,這樣可以避免緩存爭奪。

1.2 Change Buffer

寫緩沖區(qū)雇锡,簡稱 CB 逛钻。在進(jìn)行 DML 操作時,如果 BP 沒有其相應(yīng)的 Page 數(shù)據(jù)锰提, 并不會立刻將磁盤頁加載到緩沖池曙痘,而是在 CB 記錄緩沖變更,等未來數(shù)據(jù)被讀取時欲账,再將數(shù)據(jù)合并恢復(fù)到 BP 中屡江。

ChangeBuffer 占用 BufferPool 空間,默認(rèn)占25%赛不,大允許占50%惩嘉,可以根據(jù)讀寫業(yè)務(wù)量來 進(jìn)行調(diào)整。參數(shù) innodb_change_buffer_max_size;

show variables like '%innodb_change_buffer_max_size%';

當(dāng)更新一條記錄時踢故,該記錄在 BufferPool 存在文黎,直接在 BufferPool 修改,一次內(nèi)存操作殿较。如果該記錄在 BufferPool 不存在(沒有命中)耸峭,會直接在 ChangeBuffer 進(jìn)行一次內(nèi)存操作,不用再去磁盤查詢數(shù)據(jù)淋纲,避免一次磁盤IO劳闹。當(dāng)下次查詢記錄時,會先進(jìn)性磁盤讀取,然后再從 ChangeBuffer中讀取信息合并本涕,最終載入BufferPool 中业汰。

寫緩沖區(qū),僅適用于非唯一普通索引頁菩颖,為什么样漆?
如果在索引設(shè)置唯一性,在進(jìn)行修改時晦闰,InnoDB 必須要做唯一性校驗放祟,因此必須查詢磁盤, 做一次 IO 操作呻右。會直接將記錄查詢到 BufferPool中跪妥,然后在緩沖池修改,不會在ChangeBuffer 操作窿冯。

1.3 Adaptive Hash Index

自適應(yīng)哈希索引骗奖,用于優(yōu)化對 BP 數(shù)據(jù)的查詢。InnoDB 存儲引擎會監(jiān) 控對表索引的查找醒串,如果觀察到建立哈希索引可以帶來速度的提升执桌,則建立哈希索引,所以稱之為自適應(yīng)芜赌。InnoDB 存儲引擎會自動根據(jù)訪問的頻率和模式來為某些頁建立哈希索引仰挣。

1.4 Log Bu?er

日志緩沖區(qū),用來保存要寫入磁盤上 log文件(Redo/Undo)的數(shù)據(jù)缠沈,日志緩沖區(qū)的內(nèi)容定期刷新到磁盤 log 文件中膘壶。日志緩沖區(qū)滿時會自動將其刷新到磁盤,當(dāng)遇到 BLOB 或多行更新的大事務(wù)操作時洲愤,增加日志緩沖區(qū)可以節(jié)省磁盤 I/O颓芭。

LogBuffer 主要是用于記錄 InnoDB 引擎日志,在 DML 操作時會產(chǎn)生 RedoUndo日志柬赐。LogBuffer 空間滿了亡问,會自動寫入磁盤「厮危可以通過將 innodb_log_buffer_size 參數(shù)調(diào)大州藕,減少磁盤IO頻率

show variables like '%innodb_log_buffer_size%';
show variables like '%innodb_log%';
SHOW VARIABLES LIKE '%innodb_flush_log_at_trx_commit%'

innodb_flush_log_at_trx_commit參數(shù)控制日志刷新行為,默認(rèn)為1

  • 0 : 每隔 1 秒寫日志文件和刷盤操作(寫日志文件 LogBu?er -> OS cache酝陈,刷盤 OS cache -> 磁盤文件)床玻,最多丟失 1 秒數(shù)據(jù)
  • 1:事務(wù)提交,立刻寫日志文件和刷盤沉帮,數(shù)據(jù)不丟失锈死,但是會頻繁IO操作
  • 2:事務(wù)提交贫堰,立刻寫日志文件,每隔 1 秒鐘進(jìn)行刷盤操作

2. 磁盤結(jié)構(gòu)

InnoDB 磁盤主要包含Tablespaces馅精,InnoDB Data Dictionary严嗜,Doublewrite Buffer粱檀、Redo LogUndo Logs洲敢。

2.1 表空間(Tablespaces)

用于存儲表結(jié)構(gòu)和數(shù)據(jù)。表空間又分為系統(tǒng)表空間茄蚯、獨立表空間压彭、 通用表空間、臨時表空間渗常、Undo 表空間等多種類型壮不;

2.1.1 系統(tǒng)表空間(The System Tablespace)

包含 InnoDB 數(shù)據(jù)字典,Doublewrite Buffer皱碘,Change Bu?er询一,Undo Logs 的存儲區(qū)域。系統(tǒng)表空間也默認(rèn)包含任何用戶在系統(tǒng)表空間創(chuàng)建的表數(shù)據(jù)和索引數(shù)據(jù)癌椿。系統(tǒng)表空間是一個共享的表空間因為它是被多個表共享的健蕊。該空間的數(shù)據(jù)文件通過參數(shù) innodb_data_?le_path 控制,默認(rèn)值是 ibdata1:12M:autoextend(文件名為ibdata1踢俄、 12MB缩功、自動擴(kuò)展)。

SHOW VARIABLES LIKE '%innodb_data_file_path%'
2.1.2 獨立表空間(File-Per-Table Tablespaces)

默認(rèn)開啟都办,獨立表空間是一個單表表空間嫡锌,該表創(chuàng)建于自己的數(shù)據(jù)文件中,而非創(chuàng)建于系統(tǒng)表空間中琳钉。當(dāng) innodb_?le_per_table 選項開啟時势木,表將被創(chuàng)建于表空間中。否則歌懒, innodb 將被創(chuàng)建于系統(tǒng)表空間中啦桌。每個表文件表空間由一個 .ibd 數(shù)據(jù)文件代表,該文件默認(rèn)被創(chuàng)建于數(shù)據(jù)庫目錄中歼培。表空間的表文件支持動態(tài)(dynamic)和壓縮 (commpressed)行格式震蒋。

SHOW VARIABLES LIKE '%innodb_file_per_table%'
2.1.3 通用表空間(General Tablespaces)

通用表空間為通過 create tablespace 語法創(chuàng)建的共享表空間。通用表空間可以創(chuàng)建于 mysql數(shù)據(jù)目錄外的其他表空間躲庄,其可以容納多張表查剖,且其支持所有的行格式。

 -- 創(chuàng)建表空 間ts1 
CREATE TABLESPACE ts1 ADD DATAFILE ts1.ibd Engine=InnoDB;
 -- 將表添加到 ts1 表空間
CREATE TABLE t1 (c1 INT PRIMARY KEY) TABLESPACE ts1;
2.1.4 撤銷表空間(Undo Tablespaces)

撤銷表空間由一個或多個包含 Undo 日志文件組成噪窘。在 MySQL 5.7 版本之前Undo占用的 是System Tablespace共享區(qū)笋庄,從5.7開始將UndoSystem Tablespace分離了出來。 InnoDB 使用的 undo表空間由 innodb_undo_tablespaces 配置選項控制,默認(rèn)為0直砂。參 數(shù)值為0表示使用系統(tǒng)表空間ibdata1菌仁;大于0表示使用undo表空間undo_001、 undo_002等静暂。

SHOW VARIABLES LIKE '%innodb_undo_tablespaces%'
2.1.5 臨時表空間(Temporary Tablespaces)

分為 session temporary tablespacesglobal temporary tablespace 兩種济丘。session temporary tablespaces 存儲的是用戶創(chuàng)建的臨時表和磁盤內(nèi)部的臨時表庆揪。global temporary tablespace 儲存用戶臨時表的回滾段(rollback segments )煞抬。mysql服務(wù)器正常關(guān)閉或異常終止時夏跷,臨時表空間將被移除鹤耍,每次啟動時會被重新創(chuàng)建恨溜。

2.2 數(shù)據(jù)字典(InnoDB Data Dictionary)

InnoDB 數(shù)據(jù)字典由內(nèi)部系統(tǒng)表組成昭齐,這些表包含用于查找表瞎惫、索引和表字段等對象的元數(shù) 據(jù)盐股。元數(shù)據(jù)物理上位于InnoDB系統(tǒng)表空間中驮审。由于歷史原因鲫寄,數(shù)據(jù)字典元數(shù)據(jù)在一定程度上 與InnoDB表元數(shù)據(jù)文件(.frm文件)中存儲的信息重疊。

2.3 雙寫緩沖區(qū)(Doublewrite Buffer)

位于系統(tǒng)表空間疯淫,是一個存儲區(qū)域地来。在 BufferPagepage 頁刷新到磁盤真正的位置前,會先將數(shù)據(jù)存在Doublewrite 緩沖區(qū)峡竣。如果在 page頁寫入過程中出現(xiàn)操作系統(tǒng)靠抑、存儲子系統(tǒng)或 mysqld進(jìn)程崩潰,InnoDB可以在崩潰恢復(fù)期間從Doublewrite 緩沖區(qū)中找到頁的一個備份适掰。在大多數(shù)情況下颂碧,默認(rèn)情況下啟用雙寫緩沖區(qū);要禁用 Doublewrite 緩沖區(qū)类浪,可以將 innodb_doublewrite 設(shè)置為0载城。使用Doublewrite 緩沖區(qū)時建議將 innodb_?ush_method 設(shè)置為 O_DIRECT

SHOW VARIABLES LIKE '%innodb_doublewrite%'
SHOW VARIABLES LIKE '%innodb_flush_method%'

MySQL 的 innodb_?ush_method 這個參數(shù)控制著 innodb 數(shù)據(jù)文件及 redo log 的打開费就、 刷寫模式诉瓦。有三個值:fdatasync(默認(rèn)),O_DSYNC力细,O_DIRECT睬澡。

設(shè)置 O_DIRECT 表示數(shù)據(jù)文件寫入操作會通知操作系統(tǒng)不要緩存數(shù)據(jù),也不要用預(yù)讀眠蚂,直接從Innodb Buffer 寫到磁盤文件煞聪。

默認(rèn)的 fdatasync 意思是先寫入操作系統(tǒng)緩存,然后再調(diào)用 fsync() 函數(shù)去異步刷數(shù)據(jù)文件與redo log 的緩存信息逝慧。

2.4 重做日志(Redo Log)

重做日志是一種基于磁盤的數(shù)據(jù)結(jié)構(gòu)昔脯,用于在崩潰恢復(fù)期間更正不完整事務(wù)寫入的數(shù)據(jù)啄糙。 MySQL 以循環(huán)方式寫入重做日志文件,記錄 InnoDB 中所有對 Buffer Pool 修改的日志云稚。當(dāng)出現(xiàn)實例故障(像斷電)隧饼,導(dǎo)致數(shù)據(jù)未能更新到數(shù)據(jù)文件,則數(shù)據(jù)庫重啟時須 redo静陈,重新把數(shù)據(jù)更新到數(shù)據(jù)文件燕雁。讀寫事務(wù)在執(zhí)行的過程中,都會不斷的產(chǎn)生 redo log窿给。默認(rèn)情況下贵白,重做日志在磁盤上由兩個名為 ib_log?le0ib_log?le1 的文件物理表示。

2.5 撤銷日志(Undo Logs)

撤消日志是在事務(wù)開始之前保存的被修改數(shù)據(jù)的備份崩泡,用于例外情況時回滾事務(wù)。撤消日志屬于邏輯日志猬膨,根據(jù)每行記錄進(jìn)行記錄角撞。撤消日志存在于系統(tǒng)表空間、撤消表空間和臨時表空間中勃痴。

3. 新版本結(jié)構(gòu)演變

3.1 MySQL 5.7 版本

  • Undo 日志表空間從共享表空間 ibdata 文件中分離出來谒所,可以在安裝 MySQL 時由用戶自行指定文件大小和數(shù)量。
  • 增加了 temporary 臨時表空間沛申,里面存儲著臨時表或臨時查詢結(jié)果集的數(shù)據(jù)劣领。
  • Buffer Pool 大小可以動態(tài)修改,無需重啟數(shù)據(jù)庫實例铁材。

3.2 MySQL 8.0 版本

  • InnoDB 表的數(shù)據(jù)字典和 Undo 都從共享表空間 ibdata中徹底分離出來了尖淘,以前需要 ibdata 中數(shù)據(jù)字典與獨立表空間 ibd 文件中數(shù)據(jù)字典一致才行,8.0 版本就不需要了著觉。
  • temporary 臨時表空間也可以配置多個物理文件村生,而且均為 InnoDB 存儲引擎并能創(chuàng)建索引,這樣加快了處理的速度饼丘。
  • 用戶可以像 Oracle 數(shù)據(jù)庫那樣設(shè)置一些表空間趁桃,每個表空間對應(yīng)多個物理文件,每個表空間可以給多個表使用肄鸽,但一個表只能存儲在一個表空間中卫病。
  • Doublewrite Buffer 從共享表空間 ibdata 中也分離出來了。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末典徘,一起剝皮案震驚了整個濱河市蟀苛,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌烂斋,老刑警劉巖屹逛,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件础废,死亡現(xiàn)場離奇詭異,居然都是意外死亡罕模,警方通過查閱死者的電腦和手機(jī)评腺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來淑掌,“玉大人蒿讥,你說我怎么就攤上這事∨淄螅” “怎么了芋绸?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長担敌。 經(jīng)常有香客問我摔敛,道長,這世上最難降的妖魔是什么全封? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任马昙,我火速辦了婚禮,結(jié)果婚禮上刹悴,老公的妹妹穿的比我還像新娘行楞。我一直安慰自己,他們只是感情好土匀,可當(dāng)我...
    茶點故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布子房。 她就那樣靜靜地躺著,像睡著了一般就轧。 火紅的嫁衣襯著肌膚如雪证杭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天钓丰,我揣著相機(jī)與錄音躯砰,去河邊找鬼。 笑死携丁,一個胖子當(dāng)著我的面吹牛琢歇,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播梦鉴,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼李茫,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了肥橙?” 一聲冷哼從身側(cè)響起魄宏,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎存筏,沒想到半個月后宠互,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體味榛,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年予跌,在試婚紗的時候發(fā)現(xiàn)自己被綠了搏色。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡券册,死狀恐怖频轿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情烁焙,我是刑警寧澤航邢,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站骄蝇,受9級特大地震影響膳殷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜乞榨,卻給世界環(huán)境...
    茶點故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一秽之、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧吃既,春花似錦、人聲如沸跨细。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽冀惭。三九已至震叙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間散休,已是汗流浹背媒楼。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留戚丸,地道東北人划址。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像限府,于是被迫代替她去往敵國和親夺颤。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,685評論 2 360

推薦閱讀更多精彩內(nèi)容

  • 一起走進(jìn)MySQL引擎是如何工作的 MySQL服務(wù)器服務(wù)器負(fù)責(zé)對數(shù)據(jù)進(jìn)行讀取與存人的部分工作是存儲引擎胁勺,服務(wù)器支持...
    蝸牛也瘋狂_6104閱讀 406評論 0 0
  • InnoDB存儲結(jié)構(gòu) Innodb邏輯存儲單元為為表空間,段,區(qū),頁 InnoDB表空間 InnoDB存儲引擎表中...
    逆光花輪閱讀 936評論 0 1
  • 持續(xù)更新 邏輯存儲結(jié)構(gòu) InnoDB存儲引擎的邏輯存儲結(jié)構(gòu)和Oracle幾乎一樣世澜,從大到小分別為:表空間、段署穗、區(qū)寥裂、...
    xiewen閱讀 1,256評論 0 1
  • InnoDB體系架構(gòu) 上圖簡單顯示了InnoDB存儲引擎的體系架構(gòu)圖中可見嵌洼,InnoDB存儲引擎有多個內(nèi)存塊,可以...
    Rick617閱讀 4,038評論 0 6
  • 今天感恩節(jié)哎封恰,感謝一直在我身邊的親朋好友麻养。感恩相遇!感恩不離不棄俭驮。 中午開了第一次的黨會回溺,身份的轉(zhuǎn)變要...
    迷月閃星情閱讀 10,572評論 0 11