MySQL - 存儲引擎 邏輯存儲結構 架構 事務原理 MVCC(多版本併發控制)

邏輯存儲結構

  • 表空間: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:僅在事務中第一次執行快照讀時生成,後邊複用
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章