MySQL - 存储引擎初探
文章目錄
- 生猛干貨
- 存儲引擎概述
- 實例層
- 物理層
- 內存和物理結構
- Buffer Pool
- Redo log
- 5.7新版本特性
- 8.0 新版本特性
- InnoDB VS MyISAM
- 功能對比
- 事務支持
- 其他
- 性能對比
- InnoDB 存儲引擎
- 核心特性
- ARIES 三原則
- 小結
- 搞定MySQL
生猛干貨
帶你搞定MySQL實戰,輕松對應海量業務處理及高并發需求,從容應對大場面試
存儲引擎概述
存儲引擎是 MySQL 中具體與文件打交道的子系統,它是根據 MySQL AB 公司提供的文件訪問層抽象接口定制的一種文件訪問機制,這種機制就叫作存儲引擎 。
常用的存儲引擎:
有古老的 MyISAM、支持事務的 InnoDB、內存類型的 Memory、歸檔類型的 Archive、列式存儲的 Infobright,以及一些新興的存儲引擎,以 RocksDB 為底層基礎的 MyRocks 和 RocksDB,和以分形樹索引組織存儲的 TokuDB, 以及國產的分布式存儲引擎 ArkDB。
在 MySQL 5.6 版本之前,默認的存儲引擎都是 MyISAM,但 5.6 版本以后默認的存儲引擎就是 InnoDB 了。
InnoDB 存儲引擎的具體架構如下圖所示。上半部分是實例層(計算層),位于內存中,下半部分是物理層,位于文件系統中。
實例層
實例層分為線程和內存。InnoDB 重要的線程有 Master Thread,Master Thread 是 InnoDB 的主線程,負責調度其他各線程。
Master Thread 的優先級最高, 其內部包含幾個循環:主循環(loop)、后臺循環(background loop)、刷新循環(flush loop)、暫停循環(suspend loop)。Master Thread 會根據其內部運行的相關狀態在各循環間進行切換。
大部分操作在主循環(loop)中完成,其包含 1s 和 10s 兩種操作。
【1s 操作主要包括如下】
-
日志緩沖刷新到磁盤(這個操作總是被執行,即使事務還沒有提交)。
-
最多可能刷 100 個新臟頁到磁盤。
-
執行并改變緩沖的操作。
-
若當前沒有用戶活動,可能切換到后臺循環(background loop)等。
【10s 操作主要包括如下】
-
最多可能刷新 100 個臟頁到磁盤。
-
合并至多 5 個被改變的緩沖(總是)。
-
日志緩沖刷新到磁盤(總是)。
-
刪除無用的 Undo 頁(總是)。
-
刷新 100 個或者 10 個臟頁到磁盤(總是)產生一個檢查點(總是)等。
-
buf_dump_thread 負責將 buffer pool 中的內容 dump 到物理文件中,以便再次啟動 MySQL 時,可以快速加熱數據。
-
page_cleaner_thread 負責將 buffer pool 中的臟頁刷新到磁盤,在 5.6 版本之前沒有這個線程,刷新操作都是由主線程完成的,所以在刷新臟頁時會非常影響 MySQL 的處理能力,在5.7 版本之后可以通過參數設置開啟多個 page_cleaner_thread。
-
purge_thread 負責將不再使用的 Undo 日志進行回收。
-
read_thread 處理用戶的讀請求,并負責將數據頁從磁盤上讀取出來,可以通過參數設置線程數量。
-
write_thread 負責將數據頁從緩沖區寫入磁盤,也可以通過參數設置線程數量, page_cleaner 線程發起刷臟頁操作后 write_thread 就開始工作了。
-
redo_log_thread 負責把日志緩沖中的內容刷新到 Redo log 文件中。
-
insert_buffer_thread 負責把 Insert Buffer 中的內容刷新到磁盤。實例層的內存部分主要包含 InnoDB Buffer Pool,這里包含 InnoDB 最重要的緩存內容。數據和索引頁、undo 頁、insert buffer 頁、自適應 Hash 索引頁、數據字典頁和鎖信息等。additional memory pool 后續已不再使用。Redo buffer 里存儲數據修改所產生的 Redo log。double write buffer 是 double write 所需的 buffer,主要解決由于宕機引起的物理寫入操作中斷,數據頁不完整的問題。
物理層
物理層在邏輯上分為系統表空間、用戶表空間和 Redo日志
系統表空間里有 ibdata 文件和一些 Undo,ibdata 文件里有 insert buffer 段、double write段、回滾段、索引段、數據字典段和 Undo 信息段。
用戶表空間是指以 .ibd 為后綴的文件,文件中包含 insert buffer 的 bitmap 頁、葉子頁(這里存儲真正的用戶數據)、非葉子頁。InnoDB 表是索引組織表,采用 B+ 樹組織存儲,數據都存儲在葉子節點中,分支節點(即非葉子頁)存儲索引分支查找的數據值。
Redo 日志中包括多個 Redo 文件,這些文件循環使用,當達到一定存儲閾值時會觸發checkpoint 刷臟頁操作,同時也會在 MySQL 實例異常宕機后重啟,InnoDB 表數據自動還原恢復過程中使用。
內存和物理結構
上面介紹了 MySQL InnoDB 存儲引擎的具體架構,下面重點講解內存和物理結構。
Buffer Pool
用戶讀取或者寫入的最新數據都存儲在 Buffer Pool 中,如果 Buffer Pool 中沒有找到則會讀取物理文件進行查找,之后存儲到 Buffer Pool 中并返回給 MySQL Server。Buffer Pool 采用LRU 機制。
Buffer Pool 決定了一個 SQL 執行的速度快慢,如果查詢結果頁都在內存中則返回結果速度很快,否則會產生物理讀(磁盤讀),返回結果時間變長,性能遠不如存儲在內存中。
但我們又不能將所有數據頁都存儲到 Buffer Pool 中,比如物理 ibd 文件有 500GB,我們的機器不可能配置能容得下 500GB 數據頁的內存,因為這樣做成本很高而且也沒必要。
在單機單實例情況下,我們可以配置 Buffer Pool 為物理內存的 60%~80%,剩余內存用于 session 產生的 sort 和 join 等,以及運維管理使用。
如果是單機多實例,所有實例的buffer pool總量也不要超過物理內存的80%。開始時我們可以根據經驗設置一個 Buffer Pool 的經驗值,比如 16GB,之后業務在 MySQL 運行一段時間后可以根據 show global status like '%buffer_pool_wait%' 的值來看是否需要調整 Buffer Pool 的大小。
Redo log
Redo log 是一個循環復用的文件集,負責記錄 InnoDB 中所有對 Buffer Pool的物理修改日志 。
當 Redo log文件空間中,檢查點位置的 LSN 和最新寫入的 LSN 差值(checkpoint_age)達到 Redo log 文件總空間的 75% 后,InnoDB 會進行異步刷新操作,直到降至 75% 以下,并釋放 Redo log 的空間;
當 checkpoint_age 達到文件總量大小的 90% 后,會觸發同步刷新,此時 InnoDB 處于掛起狀態無法操作。
這樣我們就看到 Redo log 的大小直接影響了數據庫的處理能力,如果設置太小會導致強行 checkpoint 操作頻繁刷新臟頁,那我們就需要將 Redo log 設置的大一些,5.6 版本之前 Redo log 總大小不能超過 3.8GB,5.7 版本之后放開了這個限制。那既然太小影響性能,當然了也不是越大也好,需要權衡考慮。
事務提交時 log buffer 會刷新到 Redo log 文件中,具體刷新機制由參數控制 。
若參數 innodb_file_per_table=ON,則表示用戶建表時采用用戶獨立表空間,即一個表對應一組物理文件,.frm 表定義文件和 .ibd 表數據文件。
當然若這個參數設置為 OFF,則表示用戶建表存儲在 ibdata 文件中,不建議采用共享表空間,這樣會導致 ibdata 文件過大,而且當表刪除后空間無法回收。獨立表空間可以在用戶刪除大量數據后回收物理空間,執行一個 DDL 就可以將表空間的高水位降下來了。
5.7新版本特性
-
將 Undo 從共享表空間 ibdata 文件中分離出來,可以在安裝 MySQL 時由用戶自行指定文件大小和數量。
-
增加了 temporary 臨時表空間,里面存儲著臨時表或臨時查詢結果集的數據。
-
Buffer Pool 大小可以動態修改,無需重啟數據庫實例。
8.0 新版本特性
-
將 InnoDB 表的數據字典和 Undo 都從共享表空間 ibdata 中徹底分離出來了,以前需要ibdata 文件中數據字典與獨立表空間 ibd 文件中數據字典一致才行,8.0 版本就不需要了。
-
temporary 臨時表空間也可以配置多個物理文件,而且均為 InnoDB 存儲引擎并能創建索引,這樣加快了處理的速度。
-
用戶可以像 Oracle 數據庫那樣設置一些表空間,每個表空間對應多個物理文件,每個表空間可以給多個表使用,但一個表只能存儲在一個表空間中。
InnoDB VS MyISAM
功能對比
事務支持
-
InnoDB 支持 ACID 的事務 4 個特性,而 MyISAM 不支持
-
InnoDB 支持 4 種事務隔離級別,默認是可重復讀 Repeatable Read 的,MyISAM 不支持
-
InnoDB 支持 crash 安全恢復,MyISAM 不支持
-
InnoDB 支持外鍵,MyISAM 不支持
-
InnoDB 支持行級別的鎖粒度,MyISAM 不支持,只支持表級別的鎖粒度
-
InnoDB 支持 MVCC,MyISAM 不支持
其他
InnoDB 表最大還可以支持 64TB,支持聚簇索引、支持壓縮數據存儲,支持數據加密,支持查詢/索引/數據高速緩存,支持自適應hash索引、空間索引,支持熱備份和恢復等。
性能對比
在性能對比上,InnoDB 也完勝 MyISAM,如下圖所示。
-
讀寫混合模式下,隨著 CPU 核數的增加,InnoDB 的讀寫能力呈線性增長,
-
在測試用例里,最高可達近 9000 的 TPS,但 MyISAM 因為讀寫不能并發,它的處理能力跟核數沒關系,呈一條水平線,TPS 低于 500。
-
只讀模式下,隨著 CPU 核數的增加,InnoDB 的讀寫能力呈線性增長,最高可達近 14000 的 TPS,但 MyISAM 的處理能力不到 3000 TPS
以上測試僅為說明 InnoDB 比 MyISAM 的處理能力強大,具體 TPS 測試數據跟硬件和測試條件不同而有很大差異。
InnoDB 存儲引擎
核心特性
InnoDB 存儲引擎的核心特性包括:MVCC、鎖、鎖算法和分類、事務、表空間和數據頁、內存線程以及狀態查詢。
ARIES 三原則
ARIES 三原則,是指 Write Ahead Logging(WAL)
先寫日志后寫磁盤,日志成功寫入后事務就不會丟失,后續由 checkpoint 機制來保證磁盤物理文件與 Redo 日志達到一致性;
利用 Redo 記錄變更后的數據,即 Redo 記錄事務數據變更后的值;
利用 Undo 記錄變更前的數據,即 Undo 記錄事務數據變更前的值,用于回滾和其他事務多版本讀。
show engine innodb status\G 的結果里面有詳細的 InnoDB 運行態信息,分段記錄的,包括內存、線程、信號、鎖、事務等,日常工作中可以多多使用,出現問題時從中能分析出具體原因和解決方案。
小結
主要梳理了 MySQL數據庫的體系結構,SQL 的執行流程,存儲引擎和分類,重點講解了 InnoDB 存儲引擎的體系結構、特性,對比了 InnoDB 和 MyISAM存儲引擎的功能和性能,在各方面 InnoDB 都完勝 MyISAM,InnoDB 也是 MySQL 今后重點發力的地方,很多地方都默認采用 InnoDB 進行存儲,還有 InnoDB 引擎內部的組成和各版本對比。
搞定MySQL
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的MySQL - 存储引擎初探的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MySQL - 体系结构初探
- 下一篇: MySQL - 多版本控制 MVCC 机