MySQL 存儲引擎InnoDB 架構(gòu)與原理深度解析
索引結(jié)構(gòu)提供了高效的數(shù)據(jù)檢索方式,索引信息與數(shù)據(jù)記錄均存儲于文件系統(tǒng)中,具體而言是存儲在頁結(jié)構(gòu)中。索引的實(shí)現(xiàn)依賴于存儲引擎,MySQL 服務(wù)器通過存儲引擎完成對表數(shù)據(jù)的讀寫操作。不同存儲引擎的數(shù)據(jù)存儲格式各異,部分存儲引擎(如 MEMORY)甚至不使用磁盤存儲數(shù)據(jù),而是將數(shù)據(jù)保存在內(nèi)存中。
MySQL 支持的存儲引擎類型
通過以下命令可以查看 MySQL 支持的所有存儲引擎:
SHOW ENGINES;
查詢結(jié)果示例:
| 存儲引擎 | 支持狀態(tài) | 說明 | 事務(wù) | 分布式事務(wù) | 保存點(diǎn) |
|---|---|---|---|---|---|
| InnoDB | 默認(rèn) | 支持事務(wù)、行級鎖和外鍵 | 是 | 是 | 是 |
| MyISAM | 是 | 傳統(tǒng)存儲引擎,不支持事務(wù) | 否 | 否 | 否 |
| MEMORY | 是 | 基于哈希索引,數(shù)據(jù)存儲于內(nèi)存,適用于臨時表 | 否 | 否 | 否 |
| CSV | 是 | 以 CSV 格式存儲數(shù)據(jù) | 否 | 否 | 否 |
| ARCHIVE | 是 | 高壓縮比的歸檔存儲引擎 | 否 | 否 | 否 |
| BLACKHOLE | 是 | 黑洞存儲引擎,寫入的數(shù)據(jù)不會被保存 | 否 | 否 | 否 |
| FEDERATED | 否 | 聯(lián)邦存儲引擎,用于訪問遠(yuǎn)程表 | 空 | 空 | 空 |
| MRG_MYISAM | 是 | MyISAM 表的集合 | 否 | 否 | 否 |
| PERFORMANCE_SCHEMA | 是 | 性能監(jiān)控與診斷 | 否 | 否 | 否 |
默認(rèn)存儲引擎的查看與配置
版本差異
MySQL 在不同版本中采用不同的默認(rèn)存儲引擎:
- MySQL 5.5 及以后版本:默認(rèn)存儲引擎為 InnoDB
- MySQL 5.5 之前版本:默認(rèn)存儲引擎為 MyISAM
若在創(chuàng)建表時未顯式指定存儲引擎,MySQL 將自動使用默認(rèn)存儲引擎。
查看當(dāng)前 MySQL 版本
SELECT VERSION();
查看默認(rèn)存儲引擎
SHOW VARIABLES LIKE 'default_storage_engine';
查詢結(jié)果示例(MySQL 5.6.40):
| Variable_name | Value |
|---|---|
| default_storage_engine | InnoDB |
修改默認(rèn)存儲引擎
- 方式一:通過配置文件修改(永久生效)
- 定位 MySQL 配置文件
- Linux 系統(tǒng):
my.cnf - Windows 系統(tǒng):
my.ini
- Linux 系統(tǒng):
- 在配置文件中添加或修改
[mysqld]部分:
[mysqld] default-storage-engine = InnoDB
重啟 MySQL 服務(wù)使配置生效:
systemctl restart mysqld.service
方式二:通過 SQL 命令修改(會話級別)
SET default_storage_engine = MyISAM;
主要存儲引擎特性對比
各存儲引擎核心特性
- InnoDB:支持 ACID 事務(wù)、行級鎖定、崩潰恢復(fù)、外鍵約束,是 MySQL 的默認(rèn)存儲引擎
- MyISAM:不支持事務(wù)、行級鎖和外鍵約束,但針對數(shù)據(jù)統(tǒng)計操作進(jìn)行了優(yōu)化,
COUNT(*)查詢效率較高 - MEMORY:將表數(shù)據(jù)完全存儲于內(nèi)存中,讀寫速度極快,但數(shù)據(jù)不具備持久性
- ARCHIVE:采用高壓縮比存儲,適用于存儲大量歷史數(shù)據(jù),僅支持 INSERT 和 SELECT 操作
- NDB:分布式存儲引擎,支持高可用性和容錯性,適用于高并發(fā)寫入場景
核心區(qū)別:InnoDB 與 MyISAM 的三大關(guān)鍵差異在于事務(wù)支持、外鍵約束和行級鎖定。
功能特性對比表
| 功能 | MyISAM | MEMORY | InnoDB |
|---|---|---|---|
| 存儲限制 | 258 TB | RAM | 64 TB |
| 事務(wù)支持 | × | × | √ |
| 全文索引支持 | √ | × | √(5.6+) |
| B 樹索引支持 | √ | √ | √ |
| 哈希索引支持 | × | √ | √(自適應(yīng)) |
| 集群索引支持 | × | × | √ |
| 數(shù)據(jù)索引支持 | × | √ | √ |
| 數(shù)據(jù)壓縮支持 | √ | × | × |
| 空間使用率 | 低 | N/A | 高 |
| 外鍵支持 | × | × | √ |
InnoDB 與 MyISAM 存儲引擎對比分析
InnoDB 存儲引擎
InnoDB 提供了完善的事務(wù)管理、崩潰恢復(fù)能力和并發(fā)控制機(jī)制。其主要優(yōu)勢在于:
- 事務(wù)完整性:支持 ACID 特性,適用于對數(shù)據(jù)一致性要求較高的應(yīng)用場景,特別是涉及頻繁更新和刪除操作的業(yè)務(wù)系統(tǒng)
- 并發(fā)性能:支持行級鎖定,能夠有效處理高并發(fā)訪問場景,避免表級鎖帶來的性能瓶頸
- 數(shù)據(jù)安全性:提供崩潰恢復(fù)功能,服務(wù)器異常重啟后能夠自動恢復(fù)已提交的事務(wù)并回滾未提交的操作
主要劣勢:
- 讀寫效率相對較低
- 磁盤空間占用較大
MyISAM 存儲引擎
MyISAM 適用于以讀取和插入操作為主、更新和刪除操作較少且對事務(wù)要求不高的系統(tǒng)。其主要優(yōu)勢在于:
- 查詢性能:在數(shù)據(jù)量較小的情況下,讀寫效率優(yōu)于 InnoDB
- 存儲效率:磁盤空間占用相對較少
主要劣勢:
- 不支持事務(wù)和行級鎖,僅支持表級鎖
- 在高并發(fā)場景下容易出現(xiàn)鎖表問題,影響系統(tǒng)性能
選型建議
InnoDB 是處理大規(guī)模數(shù)據(jù)的首選存儲引擎。除非存在特殊的業(yè)務(wù)需求,否則應(yīng)優(yōu)先選擇 InnoDB 存儲引擎。
InnoDB 核心優(yōu)勢
- 崩潰恢復(fù):服務(wù)器崩潰后重啟時,InnoDB 自動執(zhí)行崩潰恢復(fù)流程,將已提交的事務(wù)固化到磁盤,回滾未提交的事務(wù),無需人工干預(yù)
- 緩沖池機(jī)制:InnoDB 在主內(nèi)存中維護(hù)緩沖池(Buffer Pool),將高頻訪問的數(shù)據(jù)緩存在內(nèi)存中直接處理,顯著提升數(shù)據(jù)訪問速度。該緩存機(jī)制適用于多種數(shù)據(jù)類型,有效加速數(shù)據(jù)處理過程
- 內(nèi)存配置:在專用數(shù)據(jù)庫服務(wù)器上,建議將物理內(nèi)存的 60%-80% 分配給 InnoDB 緩沖池
- 外鍵約束:支持外鍵約束以維護(hù)數(shù)據(jù)完整性。當(dāng)向子表插入數(shù)據(jù)時,若主表中不存在對應(yīng)的主鍵記錄,插入操作將被自動拒絕。更新或刪除主表數(shù)據(jù)時,相關(guān)聯(lián)的子表數(shù)據(jù)會自動更新或刪除
- 數(shù)據(jù)校驗(yàn):內(nèi)置校驗(yàn)和(Checksum)機(jī)制,在磁盤或內(nèi)存數(shù)據(jù)損壞時及時發(fā)出警告,防止使用損壞的數(shù)據(jù)
- 查詢優(yōu)化:當(dāng)表的主鍵設(shè)計合理時,涉及主鍵的操作會被自動優(yōu)化。插入、更新、刪除操作通過變更緩沖(Change Buffer)機(jī)制自動優(yōu)化
- 讀寫并行:InnoDB 不僅支持當(dāng)前讀寫操作,還會將變更數(shù)據(jù)緩存并異步刷新到磁盤
- 自適應(yīng)哈希索引:當(dāng)同一列被頻繁查詢時,自適應(yīng)哈希索引會自動創(chuàng)建,顯著提升查詢性能
- 表壓縮:支持表和索引的壓縮,在不影響性能和可用性的前提下節(jié)省存儲空間
- 在線 DDL:支持在不影響業(yè)務(wù)的情況下創(chuàng)建或刪除索引
- 大對象存儲:對于大型文本和 BLOB 數(shù)據(jù),采用動態(tài)行格式(Dynamic Row Format),提供更高效的存儲布局
- 監(jiān)控能力:通過查詢 INFORMATION_SCHEMA 數(shù)據(jù)庫中的系統(tǒng)表,可以實(shí)時監(jiān)控存儲引擎的內(nèi)部運(yùn)行狀態(tài)
- 混合使用:在同一 SQL 語句中,InnoDB 表可以與其他存儲引擎的表混合使用
- 大文件支持:即使操作系統(tǒng)限制單個文件大小為 2GB,InnoDB 仍然可以處理更大的數(shù)據(jù)量
- CPU 優(yōu)化:在處理大數(shù)據(jù)量時,InnoDB 能夠充分利用 CPU 資源以達(dá)到最優(yōu)性能
表級存儲引擎操作
| 操作描述 | SQL 語句 |
|---|---|
| 查看表的存儲引擎 | SHOW TABLE STATUS LIKE 表名稱; |
| 創(chuàng)建表時指定存儲引擎 | CREATE TABLE 表名稱 (…) ENGINE = 存儲引擎名稱; |
| 修改表的存儲引擎 | ALTER TABLE 表名稱 ENGINE = 存儲引擎名稱; |
| 查看數(shù)據(jù)庫所有表的存儲引擎 | SELECT TABLE_NAME, ENGINE FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = ‘數(shù)據(jù)庫名稱’; |
| 查看表的創(chuàng)建語句(包括存儲引擎) | SHOW CREATE TABLE 表名稱; |
InnoDB 存儲引擎架構(gòu)
頁:磁盤與內(nèi)存交互的基本單位
InnoDB 將數(shù)據(jù)劃分為若干個頁(Page),默認(rèn)頁大小為 16KB。頁是磁盤與內(nèi)存之間數(shù)據(jù)交換的基本單位,即每次至少從磁盤讀取 16KB 數(shù)據(jù)到內(nèi)存,或?qū)?nèi)存中的 16KB 數(shù)據(jù)刷新到磁盤。
設(shè)計原理:數(shù)據(jù)庫不以行為單位進(jìn)行讀取,否則每次磁盤 I/O 操作僅能處理一行數(shù)據(jù),效率極低。
在數(shù)據(jù)庫系統(tǒng)中,無論讀取一行還是多行數(shù)據(jù),都會將這些行所在的整個頁加載到內(nèi)存。因此,頁是數(shù)據(jù)庫管理存儲空間和執(zhí)行 I/O 操作的最小單位,一個頁可以存儲多行記錄。
不同數(shù)據(jù)庫系統(tǒng)的頁大小
- MySQL InnoDB:16KB(默認(rèn))
- SQL Server:8KB
- Oracle:2KB、4KB、8KB、16KB、32KB、64KB(稱為"塊")
查看 InnoDB 頁大?。?/p>
SHOW VARIABLES LIKE '%innodb_page_size%';
查詢結(jié)果默認(rèn)為 16384 字節(jié),即 16KB。
頁結(jié)構(gòu)組織方式
頁之間通過雙向鏈表關(guān)聯(lián),無需在物理結(jié)構(gòu)上連續(xù)存儲。每個數(shù)據(jù)頁內(nèi)部的記錄按主鍵值從小到大組成單向鏈表。為了提高查詢效率,每個數(shù)據(jù)頁會為其中的記錄生成頁目錄(Page Directory),通過主鍵查找記錄時,可以在頁目錄中使用二分查找法快速定位到對應(yīng)的槽(Slot),然后遍歷該槽對應(yīng)分組中的記錄即可快速找到目標(biāo)記錄。
InnoDB 存儲結(jié)構(gòu)層次
InnoDB 采用分層的存儲結(jié)構(gòu),從小到大依次為:行(Row)、頁(Page)、區(qū)(Extent)、段(Segment)、表空間(Tablespace)。


存儲結(jié)構(gòu)層次關(guān)系
- 行(Row):數(shù)據(jù)庫表中的一條記錄
- 頁(Page):InnoDB 的基本存儲單位,默認(rèn) 16KB,包含多行記錄
- 區(qū)(Extent):由 64 個連續(xù)的頁組成,大小為 1MB(64 × 16KB)
- 段(Segment):由一個或多個區(qū)組成,如數(shù)據(jù)段、索引段、回滾段等
- 表空間(Tablespace):最高層的邏輯容器,包含多個段
區(qū)(Extent)
區(qū)是比頁更高一級的存儲結(jié)構(gòu)。在 InnoDB 中,一個區(qū)包含 64 個連續(xù)的頁。由于頁的默認(rèn)大小為 16KB,因此一個區(qū)的大小為 64 × 16KB = 1024KB = 1MB。
段(Segment)
段由一個或多個區(qū)組成。區(qū)在文件系統(tǒng)中是連續(xù)分配的空間(在 InnoDB 中為連續(xù)的 64 個頁),但段中的區(qū)之間無需相鄰。段是數(shù)據(jù)庫的分配單位,不同類型的數(shù)據(jù)庫對象以不同的段形式存在。創(chuàng)建表時會創(chuàng)建表段,創(chuàng)建索引時會創(chuàng)建索引段。
根據(jù)存儲內(nèi)容和用途的不同,InnoDB 中的段主要分為以下三種類型:
1. 數(shù)據(jù)段(Data Segment / Leaf Node Segment)
數(shù)據(jù)段用于存儲表的實(shí)際數(shù)據(jù)行,對應(yīng) B+ 樹索引結(jié)構(gòu)的葉子節(jié)點(diǎn)。
- 存儲位置:B+ 樹的葉子節(jié)點(diǎn)層
- 存儲內(nèi)容:在 InnoDB 的聚簇索引(主鍵索引)中,葉子節(jié)點(diǎn)存儲完整的行數(shù)據(jù),包括所有列的值
- 數(shù)量關(guān)系:每個 InnoDB 表至少有一個數(shù)據(jù)段,對應(yīng)主鍵索引的葉子節(jié)點(diǎn)部分
- 訪問特點(diǎn):數(shù)據(jù)段是順序掃描和范圍查詢的主要訪問對象
2. 索引段(Index Segment / Non-Leaf Node Segment)
索引段用于存儲索引的非葉子節(jié)點(diǎn)數(shù)據(jù),對應(yīng) B+ 樹索引結(jié)構(gòu)的內(nèi)部節(jié)點(diǎn)。
- 存儲位置:B+ 樹的非葉子節(jié)點(diǎn)層(根節(jié)點(diǎn)和中間節(jié)點(diǎn))
- 存儲內(nèi)容:索引鍵值和指向下一層節(jié)點(diǎn)的指針,用于快速定位數(shù)據(jù)位置
- 適用范圍:
- 主鍵索引的非葉子節(jié)點(diǎn)屬于索引段
- 二級索引(輔助索引)的所有節(jié)點(diǎn)(包括葉子節(jié)點(diǎn)和非葉子節(jié)點(diǎn))都屬于索引段
- 作用:通過索引段的層次結(jié)構(gòu),實(shí)現(xiàn)高效的數(shù)據(jù)檢索
3. 回滾段(Rollback Segment / Undo Segment)
回滾段用于存儲事務(wù)的回滾信息(Undo Log),是 InnoDB 事務(wù)機(jī)制的核心組件。
- 存儲內(nèi)容:數(shù)據(jù)修改前的舊版本(Undo Log)
- 主要用途:
- 事務(wù)回滾:當(dāng)事務(wù)執(zhí)行失敗或主動回滾時,使用 Undo Log 將數(shù)據(jù)恢復(fù)到修改前的狀態(tài)
- MVCC 實(shí)現(xiàn):通過保存數(shù)據(jù)的歷史版本,支持多版本并發(fā)控制(Multi-Version Concurrency Control),使不同事務(wù)能夠讀取到數(shù)據(jù)的不同版本
- 崩潰恢復(fù):系統(tǒng)崩潰后,利用 Undo Log 回滾未提交的事務(wù)
- 事務(wù)保證:回滾段是實(shí)現(xiàn)事務(wù)原子性(Atomicity)和一致性(Consistency)的關(guān)鍵機(jī)制
三種段的協(xié)同工作


段類型對比表
| 特性 | 數(shù)據(jù)段 | 索引段 | 回滾段 |
|---|---|---|---|
| 存儲內(nèi)容 | 完整的行數(shù)據(jù) | 索引鍵值和指針 | 數(shù)據(jù)修改前的舊版本 |
| 對應(yīng)結(jié)構(gòu) | B+ 樹葉子節(jié)點(diǎn) | B+ 樹非葉子節(jié)點(diǎn) | Undo Log |
| 主要用途 | 存儲表數(shù)據(jù) | 加速數(shù)據(jù)檢索 | 事務(wù)回滾和 MVCC |
| 創(chuàng)建時機(jī) | 創(chuàng)建表時 | 創(chuàng)建索引時 | 事務(wù)修改數(shù)據(jù)時 |
| 生命周期 | 與表同生命周期 | 與索引同生命周期 | 事務(wù)提交后可清理 |
| 訪問頻率 | 高(數(shù)據(jù)查詢) | 高(索引查詢) | 中(事務(wù)回滾、MVCC) |
表空間(Tablespace)
表空間是邏輯容器,用于存儲段。一個表空間可以包含一個或多個段,但一個段只能屬于一個表空間。數(shù)據(jù)庫由一個或多個表空間組成,表空間從管理角度可劃分為系統(tǒng)表空間、用戶表空間、撤銷表空間、臨時表空間等。
到此這篇關(guān)于MySQL 存儲引擎InnoDB 架構(gòu)與原理深度解析的文章就介紹到這了,更多相關(guān)MySQL 存儲引擎InnoDB內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
在MySQL數(shù)據(jù)庫中使用C執(zhí)行SQL語句的方法
與PostgreSQL相似,可使用許多不同的語言來訪問MySQL,包括C、C++、Java和Perl。從Professional Linux Programming中第5章有關(guān)MySQL的下列章節(jié)中,Neil Matthew和Richard Stones使用詳盡的MySQL C接口向我們介紹了如何在MySQL數(shù)據(jù)庫中執(zhí)行SQL語句。2012-10-10
mysql 數(shù)據(jù)插入優(yōu)化方法之concurrent_insert
在MyISAM里讀寫操作是串行的,但當(dāng)對同一個表進(jìn)行查詢和插入操作時,為了降低鎖競爭的頻率,根據(jù)concurrent_insert的設(shè)置,MyISAM是可以并行處理查詢和插入的2021-07-07
查看MySQL中已經(jīng)創(chuàng)建的存儲過程及其定義
在MySQL中,查看已創(chuàng)建存儲過程的方法包括使用SHOW CREATE PROCEDURE命令查看存儲過程定義,查詢INFORMATION_SCHEMA.Routines表或mysql.proc表獲取存儲過程信息,使用source命令執(zhí)行存儲過程創(chuàng)建腳本,或查看存儲過程的文檔注釋,這些方法有助于了解和管理數(shù)據(jù)庫中的存儲過程2024-11-11
IDEA的database插件無法連接mysql的解決辦法(08001錯誤)
用navicat鏈接數(shù)據(jù)庫正常,mysql控制臺操作正常,但是用IDEA的數(shù)據(jù)庫插件鏈接一直報 08001 錯誤,本文就給大家介紹一下IDEA的database插件無法連接mysql報08001錯誤的解決辦法,需要的朋友可以參考下2024-07-07

