MySQL - 存儲引擎

邏輯存儲結構

  • 表空間:ibd 文件,一個 MySQL 實例可以對應多個表空間,用于存儲記錄、索引等數據。
  • :分為數據段(Leaf node segment)、索引段(Non-leaf node segment)、回滾段(Rollback segment),InnoDB 是索引組織表,數據段就是 B+ 樹的葉子節點,索引就是 B+ 樹的非葉子節點。段用來管理多個區。
  • :表空間的單元結構,每個區的大小為1M。默認情況下,InnoDB 存儲引擎頁的大小為16K,即一個區中有64個連續的頁。
  • :InnoDB 存儲引擎磁盤管理的最小單元,每個頁的默認16K。為了保證頁的連續,InnoDB 每次從磁盤申請4-5個區。
  • :InnoDB 存儲引擎是按行存儲數據的。Trx id,每次對某條記錄改動時,都會把對應的事務id賦值為Trx id;Roll pointer,每次對某條記錄改動時,都會把舊的版本寫入到undo日志中,然后這個隱藏列就相當于一個指針,可以通過它找到該記錄修改前的信息。

架構

上邊是 InnoDB 的架構圖,左側為內存結構,右側為磁盤結構。

內存結構

Buffer Pool

緩沖池,是主內存中的一個區域,里邊可以緩存磁盤上經常操作的真實數據,在執行增刪改查操作時,先操作緩沖池的數據(如果緩沖池沒數據,則從磁盤加載數據),然后再以一定的頻率刷新到磁盤,從而減少磁盤IO,加快處理速度。

緩沖池以頁為單位,底層采用鏈表數據結構管理頁。根據狀態可以將頁分為三種類型:

  • free page:空閑的頁,未被使用。
  • clean page:被使用的頁,數據沒有被修改過。
  • dirty page:臟頁,被使用的頁,數據被修改過,頁中數據與磁盤中的數據不一致。
Change Buffer

更改緩沖區(針對于非唯一二級索引),在執行 DML 語句時,如果這些數據頁沒有在 Buffer Pool 中,不會直接操作磁盤,而是將數據變更在 Change Buffer 中,在未來數據被讀取時,再將數據合并恢復到 Buffer Pool 中,最后將數據刷新到磁盤中。

Change Buffer 的意義:與聚集索引不同,二級索引通常是非唯一的,并且以相對隨機的方式插入到二級索引。同樣,刪除和更新可能會影響索引樹中不相鄰的二級索引頁,如果每一次都操作磁盤,會造成大量的磁盤IO。有了 Change Buffer,可以在緩沖池進行合并處理,減少磁盤IO。

Adaptive Hash Index

自適應 hash 索引,用于優化對 Buffer Pool 數據的查詢。InnoDB 存儲引擎會監控對表上各索引頁的查詢,如果觀察到 hash 索引可以提升速度,則建立 hash 索引,稱之為自適應 hash 索引。

自適應 hash 索引,無需人工干預,是系統根據情況自動完成。

Log Buffer

日志緩沖區,用來保存要寫入到磁盤中的 log 日志數據(redo log、undo log),默認大小為16MB,日志緩沖區的日志會定期刷新到磁盤中。如果需要更新、插入或刪除許多行的事務,增加日志緩沖區的大小可以節省磁盤 IO。

涉及到如下變量:

  • innodb_log_buffer_size:緩沖區大小
  • innodb_flush_log_at_trx_commit:日志刷新到磁盤的時機,有以下三種時機,1:日志在每次事務提交時寫入并刷新到磁盤;0:每秒將日志寫入并刷新到磁盤一次;2:日志在每次事務提交后寫入,并每秒刷新到磁盤一次。

磁盤結構

System Tablespace

系統表空間,是更改緩沖區的存儲區域,如果表是在系統表空間而不是每個表文件或通用表空間中創建的,它也可能包含表和索引數據。參數:innodb_data_file_path

File-Per-Table Tablespace

每張表的文件表空間包含單個 InnoDB 表的數據和索引,并存儲在文件系統上的單個數據文件中。參數:innodb_file_per_table

General Tablespaces

通用表空間,需要通過create tablespace語法創建通用表空間,在創建表時,可以指定該表空間。

--- 創建表空間
create tablespace ts_sh add datafile 'sh.ibd' engine = innodb;
--- 建表時指定表空間
create table xxx... tablespace ts_sh;
Undo Tablespaces

撤銷表空間,MySQL 實例在初始化時會自動創建兩個默認的 undo 表空間(undo_001、undo_002)初始大小分別為16M,用于存儲 undo log 日志

Temporary Tablespaces

InnoDB 使用會話臨時表空間和全局臨時表空間,存儲用戶創建的臨時表等數據。

Doublewrite Buffer Files

雙寫緩沖區文件,InnoDB 將數據頁從 Buffer Pool 刷新到磁盤前,先將數據頁寫入雙寫緩沖區文件中(#ib_16384_0.dblwr、#ib_16384_1.dblwr),便于系統異常時恢復數據。

Redo Log

重做日志,用來實現事務的持久性。該日志文件由兩部分組成:重做日志緩沖區(redo log buffer)以及重做日志文件(redo log),前者是內存中,后者是磁盤中。當事務提交之后會把所有修改信息保存到該日志中,用于在刷新臟頁到磁盤時如果發生錯誤,進行數據恢復使用。以循環方式寫入重做日志文件(ib_logfile0、ib_logfile1)

后臺線程

將 InnoDB 存儲引擎緩沖池中的數據在合適的時機刷新到磁盤文件中。

  • Master Thread:核心后臺線程,負責調度其它線程,還負責將緩沖區的數據異步刷新到磁盤中,保持數據的一致性,還包括臟頁刷新、合并插入緩存、undo 頁的回收。

  • IO Thread
    在 InnoDB 存儲引擎中大量使用了 AIO (異步非阻塞IO)來處理 IO 請求,這樣可以極大提高數據庫性能,IO Thread 主要負責這些 IO 請求的回調。

線程類型 默認個數 職責
Read Thread 4 讀操作
Write Thread 4 寫操作
Log Thread 1 將日志緩沖區刷新到磁盤
Insert Buffer Thread 1 將寫緩沖區內容刷新到磁盤
  • Page Thread:主要用于回收事務已提交了的 undo log,在事務提交后,undo log 可能不用了,就用它來回收

  • Page Cleaner Thread
    協助 Master Thread 刷新臟頁到磁盤的線程,可以減輕 Master Thread 的工作壓力,減少阻塞。

事務原理

事務是一組操作的集合,它是一個不可分割的工作單位,事務會把所有操作作為一個整體一起向系統提交或撤銷的操作請求,這些操作請求要么同時成功要么同時還失敗。

事務四大特性(ACID):

  • 原子性(Atomicity):事務是不可分割的最小操作單元,要么全部成功,要么全部失敗
  • 一致性(Consistency):事務完成時,必須使所有的數據都保持一致狀態
  • 隔離性(Isolation):數據庫系統提供的隔離機制,保證事務在不受外部并發操作響應的獨立環境下運行
  • 持久性(Durability):事務一旦提交或回滾,它對數據庫中的數據的改變是永久的

事務的原理主要就是了解四大特性的實現原理。

redo log

重做日志,記錄的是事務提交時數據頁的物理修改,用來實現事務的持久性
該日志由兩部分組成:重做日志緩沖(redo log buffer)以及重做日志文件(redo log file),前者是在內存中,后者在磁盤中。當事務提交后會把所有修改信息都存到該日志文件中,用于在刷新臟頁到磁盤,發生錯誤時,進行數據恢復使用。

undo log

回滾日志,記錄數據被修改前的信息,有兩個作用:提供回滾和 MVCC(多版本并發控制),用來實現事務的原子性
undo log 和 redo log 記錄物理日志不一樣,它記錄的是邏輯日志。可以認為當 delete 一條記錄時,undo log 中會記錄一條對應的 insert 記錄,反之亦然;當 update 一條記錄時,它記錄一條對應相反的 update 記錄。當執行 rollback 時,就可以從 undo log 中的邏輯記錄中讀取響應內容進行回滾。

undo log 銷毀:uodo log 在事務執行時發生,事務提交時,并不會立即刪除 undo log,因為這些日志可能還用于 MVCC。
undo log 存儲:undo log 采用段的方式進行管理和記錄,存儲在前面介紹的 rollback segment 回滾段中,內不包含1024個 undo log segment。

MVCC(多版本并發控制)

基本概念

  • 當前讀:讀取的是記錄的最新版本,讀取時還要保證其它并發事務不能修改當前記錄,會對讀取的記錄加鎖。比如常見的操作:select...lock in share mode(共享鎖)select...for update、insert、delete(排它鎖)都是一種當前讀。
  • 快照讀:簡單的 select(不加鎖)就是快照讀,讀取的是記錄數據的可見版本,有可能是歷史數據,不加鎖,是非阻塞讀。根據不同的隔離級別,快照度的處理不同:
    1、read committed:每次 select,都生成一個快照讀
    2、repeatable read:開啟事務后第一個 select 語句才是快照讀的地方
    3、serializable:快照度會退化為當前讀
  • MVVC
    全程是 Multi-Version Concurrency Control,多版本并發控制。維護一個數據的多個版本,使得讀寫操作沒有沖突,快照讀為 MySQL 實現 MVCC 提供了一個非阻塞讀功能。MVCC的具體實現,還需要依賴于數據庫記錄中的三個隱式字段、undo log 日志、ReadView。

原理

記錄中的隱藏字段
隱藏字段 含義
DB_TRX_ID 記錄插入這條記錄或最后一次修改該記錄的事務ID
DB_ROL_PIT 回滾指針,用于配合 undo log,指向這條記錄的上一個版本
DB_ROW_ID 隱藏主鍵,如果表結構沒有指定主鍵,將會生成該隱藏字段

通過命令行查看隱藏字段:

ibd2sdi table_name.ibd
undo log

回滾日志,在 insert、update、delete 時產生的便于數據回滾的日志。
當 insert 時候,產生的 undo log 日志只在回滾時需要,在事務提交后,可以被立即刪除。
當 update、delete 時,產生的 undo log 日志不僅在回滾時需要,在快照讀時也需要,不會被立即刪除。

undo log 版本鏈:不同事務或相同事務對同一條記錄進行修改,會導致該記錄的 undo log 生成一條記錄版本的鏈表,鏈表的頭部是最新的記錄,尾部是最舊的記錄。

ReadView

ReadView(讀視圖),是快照讀 SQL 執行時 MVCC 提取數據的依據,記錄并維護系統當前活躍的事務(未提交的)id。ReadView 中包含四個核心字段:

字段 含義
m_ids 當前活躍的事務 ID 集合
min_trx_id 最小活躍事務 ID
max_trx_id 預分配事務 ID,當前最大事務 ID + 1(因為事務 ID 是自增的)
creator_trx_id ReadView 創建者的事務 ID

不同的隔離級別,生成 ReadView 的時機不同:

  • read committed:在事務中每一次執行快照讀時生成
  • repeatable read:僅在事務中第一次執行快照讀時生成,后邊復用
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,488評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,034評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,327評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,554評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,337評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,883評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,975評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,114評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,625評論 1 332
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,555評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,737評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,244評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,973評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,615評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,343評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,699評論 2 370

推薦閱讀更多精彩內容

  • 什么是存儲引擎? 數據庫存儲引擎是數據庫底層軟件組織,數據庫管理系統(DBMS)使用數據引擎進行創建、查詢、更新和...
    小波同學閱讀 627評論 0 11
  • 零、本文綱要 一、MySQL存儲引擎 二、InnoDB存儲引擎1、InnoDB邏輯存儲結構2、InnoDB架構3、...
    石頭耳東閱讀 444評論 0 9
  • 一:簡介 相當于Linux 文件系統,只不過比文件系統強大 二:功能了解: 數據讀寫, 數據安全(讀寫一致性), ...
    醉舞經閣半卷書A閱讀 214評論 0 0
  • locak tables city read; ??unlock table; (open)??select * f...
    我要笑閱讀 104評論 0 0
  • InnoDB存儲引擎核心特性說明 事務行鎖MVCC外鍵ACSR自動故障恢復熱備復制(多線程,GTID,MTS) 查...
    大仙兒沒溜兒閱讀 377評論 0 0