Chanler

Chanler

「黑馬 MySQL」二、InnoDB 引擎

邏輯儲存結構#

image.png|500

在 InnoDB 儲存引擎中,每行資料包含了表中所定義的所有欄位的值之外,還包括以下幾個重要的東西:

  1. 6 字節的事務 ID trx id
    在 InnoDB 中,每個事務都會被賦予一個唯一的事務 ID,並且每行資料都包含了這個事務 ID 的值,用於實現事務級別的多版本並發控制 MVCC
  2. 7 字節的回滾指針 roll pointer
    為了支持事務的回滾操作,在每個行資料中都會包含一個指向回滾日誌裡對應記錄的回滾指針,當事務需要回滾時,通過回滾指針可以快速定位到對應的回滾記錄並恢復資料。
  3. 非空列位圖
    非空列位圖是 InnoDB 儲存引擎中用於提高儲存效率的一種機制,由於在一個表中往往會有很多列都是 NULL 值,因此可以將這些列的信息使用位圖的方式來進行表示,從而在儲存資料時盡可能地壓縮儲存空間
  4. 記錄頭
    每個行資料都包含了一個記錄頭,其中包括了一些元數據信息,如資料是否被刪除、是否被鎖定等
  5. 版本號
    在 InnoDB 的 MVCC 實現中,每個行資料還會包含一個版本號,用來表示當前行的版本信息,當一個事務更新一行資料時,實際上是在原有行資料的基礎上新增了一條新記錄,並通過版本號來區分這兩條記錄

綜上所述,InnoDB 行 ROW 中除了表中所定義的欄位的值,還包含了很多其他的元數據信息,在 InnoDB 儲存引擎實現事務支持、MVCC、儲存效率和資料恢復等方面都發揮著重要的作用

架構#

下面是 InnoDB 架構圖,左側為內存結構,右側是磁碟結構

image.png|500

內存結構 - 緩衝池 Buffer Pool#

操作緩衝池的資料,再以一定頻率刷新到磁碟,減少磁碟 IO

image.png|500

緩衝池以頁 Page 為單位,底層採用鏈表管理,分為三種型別:

  1. free page:空閒 page,未被使用
  2. clean page:被使用過的 page,但沒有被修改過資料
  3. dirty page:髒頁,被使用過的 page,修改過資料,此時資料與磁碟的資料產生了不一致,需要刷新進磁碟

內存結構 - 更改緩衝區 Change Buffer#

將資料的變更緩存在更改緩衝區,當未來有資料被讀取時,將資料合併並恢復到緩衝池 Buffer Pool 中,然後合併的資料會被刷入磁碟

image.png|500

更改緩衝區 Change Buffer 存在意義:
二級索引通常非唯一的並且插入的比較隨機,刪除更改操作的設涉及範圍比較大,造成大量磁碟 IO,先在緩衝池 Buffer Pool 中合併資料可以減少磁碟 IO

內存結構 - 自適應哈希索引 Adaptive Hash Index#

優化對 Buffer Pool 的資料查詢

image.png|500

內存結構 - 日誌緩衝區 Log Buffer#

日誌緩衝區保存 redo log、undo log 這類日誌資料,默認 16MB,定期刷到磁碟,減少大量操作頻繁磁碟 IO

image.png|500

磁碟結構 - 系統表空間 System Tablespace#

image.png|500

磁碟結構 - 檔案表空間 File-Per-Table Tablespaces:#

image.png|500

磁碟結構 - 通用表空間 General Tablespaces#

image.png|500

磁碟結構 - 撤銷表空間 Undo Tablespaces 臨時表空間 Temporary Tablespaces#

image.png|500

磁碟結構 - 雙寫緩衝區 Doublewrite Buffer Files 重做日誌 Redo Log#

image.png|500

背景線程#

背景線程作用:內存刷到磁碟

image.png|500

事務原理#

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

ACID 特性

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

原子性 - undo log
持久性 - redo log
一致性 - undo log + redo log
隔離性 - 鎖 + MVCC

redo log - 持久性#

當髒頁刷入磁碟發生錯誤時,根據 redo log 進行資料的恢復

image.png|500

WAL write-ahead logging 先寫日誌,日誌是 append 寫入,順序磁碟 IO,而非刷入髒頁的隨機磁碟 IO

undo log - 原子性#

回滾日誌 undo log 用於記錄資料被修改前的信息,提供回滾 rollback 和 MVCC

undo log 主要適用於回滾,所以記錄是邏輯日誌,會記錄相反操作語句,這樣 rollback 就可以讀到相應內容並回滾

image.png|500

MVCC#

RU:直接讀最近資料,沒 MVCC,沒鎖,什麼都沒
RC:每次讀都生成一個快照讀,可以讀到最新的已提交資料
RR:事務開啟後的第一個 select 語句生成快照讀,此後延續使用這個 readview,保證可重複讀
SE:每次都是當前讀,會被阻塞,也會上鎖

當前讀:
讀取的是記錄的最新版本,讀取時還要保證其他並發事務不能修改當前記錄,會對讀取的記錄進行加鎖,如:
select..lock in share mode 共享鎖,select..for update、update、insert、delete 排他鎖都是一種當前讀

快照讀:
簡單的 select(不加鎖)就是快照讀,快照讀,讀取的是記錄資料的可見版本,有可能是歷史資料,不加鎖,是非阻塞讀

  • Read Committed:每次 select,都生成一個快照讀
  • Repeatable Read:開啟事務後第一個 select 語句才是快照讀的地方
  • Serializable:快照讀會退化為當前讀

MVCC:
全稱 Multi-Version Concurrency Control,多版本並發控制,指維護一個資料的多個版本,使得讀寫操作沒有衝突,快照讀為 MySQL 實現 MVCC 提供了一個非阻塞讀功能
MVCC 的具體實現,依賴於資料庫記錄中的三個隱式欄位、undo log 日誌、readView

實現原理 - 三個隱式欄位#

DB_TRX_ID、DB_ROLL_PTR、DB_ROW_ID

image.png|500

實現原理 - undo log 日誌#

回滾日誌 undo log,在 insert、update、delete 時產生,便於資料回滾的日誌
insert 產生的 undo log 日誌只在回滾時需要,在事務提交後,可被立即刪除
update、delete 產生的 undo log 日誌不僅在回滾時需要,在快照讀時也需要,不會立即被刪除

image.png|500

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

實現原理 - readView#

每個事物在進行讀取資料時生成的 readView 都不同

image.png|500

readView 版本鏈訪問規則

  1. 先看當前事務 trx_id 是否等於 creator_trx_id,是則訪問,不是則 2
  2. 檢查當前事務 trx_id 是否 between min_trx_id and max_trx_id(最大 trx_id + 1)並且已經不再活躍(已提交),是則訪問,不是則 3
  3. 找到最大的小於 min_trx_id 的版本(最早已提交版本)

image.png|500

Read Committed

事務 5 第一次快照讀,trx_id = 2 的版本符合條件 2 的要求,trx_id < min_trx_id = 3,實現讀事務 2 已提交

事務 5 第二次快照讀,trx_id = 3 的版本符合條件 2 的要求,trx_id < min_trx_id = 4,實現讀事務 3 已提交

image.png|500

Repeatable Read

RR 事務隔離級別僅在第一次執行快照讀時生成 readView,後續複用該 readView

image.png|500

此文由 Mix Space 同步更新至 xLog
原始鏈接為 https://blog.0xling.cyou/posts/mysql/mysql-2


載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。