MYSQL-->InnoDB引擎底層原理

来源:https://www.cnblogs.com/wdadwa/archive/2022/10/13/MYSQL_Learning_13.html
-Advertisement-
Play Games

邏輯存儲結構 邏輯存儲結構圖 表空間 表空間文件在Linux下存放在 /var/lib/mysql文件中的 xxx.ibd 文件就是表空間文件 表空間文件用來存儲,記錄,索引等數據。 段 段分為,數據段(Leaf node segment) ,索引段(Non-leaf node segment),回 ...


邏輯存儲結構

邏輯存儲結構圖

image

  1. 表空間

    表空間文件在Linux下存放在 /var/lib/mysql文件中的 xxx.ibd 文件就是表空間文件

    表空間文件用來存儲,記錄,索引等數據。

  2. 段分為,數據段(Leaf node segment)索引段(Non-leaf node segment)回滾段(Rollback segment),InnoDB是索引組織表,數據段就是B+樹的葉子節點,索引段就是非葉子節點,段用來管理Extend(區)。

    一個段相當於一張表

  3. 區是表空間的單元結構,每個區大小為1M,預設情況下InnoDB存儲引擎頁大小為16k,一個區一共16個連續的頁。

  4. 頁,是InnoDB存儲引擎磁碟管理的最小單元。

    每個區預設16KB,為了保證頁的連續性,InnoDB存儲引擎每次從磁碟申請4到5個區。

  5. 行指的是InnoDB存儲的數據

    表結構中倆個隱藏欄位

    Trx_id:最後一次操作事務的id

    Roll pointer:指針,指向增刪改之前的數據,可以拿這個找到修改之前的數據。

架構

MySQL5.5版本後,預設使用InoDB存儲引擎。

它擅長事務處理,具有崩潰恢復性特性!

下圖為InnoDB架構圖,左邊為記憶體結構,右邊為磁碟結構。

image

記憶體結構

image

Buffer Pool(緩衝池)

緩衝池是主記憶體的一個區域,裡面可以緩存磁碟上經常操作的真實數據。

在執行增刪改查操作的時候,先操作緩存池中的數據(如果沒有,從磁碟載入並且緩存)

然後以一定頻率刷新到磁碟,從而減少磁碟IO,加快處理速度

在緩存池中有一塊一塊的,這個是頁。

緩存池以頁為單位,底層採用鏈表數據結構管理Page。

根據狀態將Page分為三類:

  1. free page :空閑頁,未被使用的頁。
  2. clean page :被使用的頁,數據沒有被修改過。
  3. dirty page :臟頁,被使用的頁,頁中數據和磁碟中數據不一致。

Change Buffer(更改緩存區)

介紹

更改緩存區,主要針對非唯一的二級索引。

在執行DML語句時,如果這些數據頁不在Buffer Poor中,不會直接操作磁碟,而是將數據變更在更改緩存區Change Buffer中

在未來數據被讀取的時候,再將數據合併恢復到Buffer Pool中,再將合併後的數據刷新到磁碟中。

意義

和聚集索引不同,二級索引是非唯一的!

並且二級索引以相對隨機的順序插入。

同樣的刪除和更新可能會影響索引樹中不相鄰的二級索引頁,如果每一次都操作磁碟,會造成大量磁碟IO。

有了ChangeBuffer後,我們可以在緩衝池中進行合併處理減少磁碟IO

Log Buffer(日誌緩存區)

日誌緩存區,用來保存要寫入磁碟中的log日誌數據(redo log 、undo log)。

預設大小16MB,日誌緩存區的日誌會定期刷新到磁碟中。如果需要更新、插入、或刪除多行的事務,增加日誌緩存區大小可以節約磁碟IO

在系統變數中設置即可

關鍵字:

innodb_log_buffer_size 緩存區大小

innodb_flush_log_at_trx_commit 日誌刷新到磁碟的時機

1代表的是日誌在每次事務提交時寫入並刷新到磁碟

0代表每秒將日誌寫入並刷新到磁碟一次

2代表日誌在每次事務提交後寫入,並且每秒刷新到磁碟一次

Adaaptive Hash index(自適應哈希索引)

自適應哈希索引,用於優化Buffer Pool數據的查詢。

InnoDB存儲引擎會監控表上各索引頁的查詢,如果觀察到hash索引可以提高速度,就會建立hash索引。

這個叫自適應哈希索引

可以在系統變數中查詢是否開啟自適應哈希索引

關鍵字是 adaptive_hash_index

磁碟結構

image

System Tablespace(系統表空間)

系統表空間是change Buffer的存放區域。

關鍵字:innodb_data_file_path

系統表空間存放路徑

File-Per-Table Tablespaces

存放每個表的獨立表空間

預設是開啟的-->開啟後代表每一張表都會生成對應的表空間文件。

xxx.ibd結尾的文件都是表的表空間文件

查看變數 innodb_file_per_table看是開的還是關的

裡面存放了表結構,表數據,索引

General Tablespaces(通用表空間)

通用表空間,需要手動通過

create tablespace 表空間名 add datafile '表空間對應的磁碟文件.ibd' engine=innodb; 

創建通用表空間。

在創建表的時候可以指定該表空間

create table 表名(
	欄位....
)engine=存儲引擎 tablespace 表空間名;

Undo Tablespaces(撤銷表空間)

撤銷表空間,MYSQL實例在初始化的時候會自動創建倆個預設的undo表空間(初始大小16M)用來存放undo log日誌

預設叫 undo_001和undo_002

Temporary Tablespaces(臨時表空間)

用來存儲用戶創建的臨時表。

Doublewrite Buffer Files(雙寫緩衝區)

雙寫緩衝區,innoDB存儲引擎會將數據頁沖Buffer Pool刷新到磁碟前,先將數據頁寫入雙寫緩衝區文件中,便於系統異常時恢複數據。

雙寫緩衝區文件:xxx.dblwr

Redo Log(重做日誌)

用來實現事務的持久性。

該日誌文件由倆個部分組成:重做日誌緩衝區(redo log buffer)重做日誌文件(redo log)

重做日誌緩衝區:是在記憶體中

重做日誌文件:是在磁碟在

事務提交後會把所有修改的信息存放在該日誌中,用於刷新臟頁到磁碟,發生錯誤時,進行數據恢復使用

以迴圈的方式寫入重做文件,涉及到倆個文件:ib_logfile0和ib_logfile1

後臺線程

作用:將Innodb緩衝池的數據在合適的時機刷新到磁碟文件中。

分為四類:

  1. Master Thread

    核心後臺線程,負責調度其他線程。還負責將緩衝池中的數據非同步刷新到磁碟中,保持數據的一致性。

    還包括,臟頁的刷新合併插入緩衝undo頁的回收

  2. IO Thread

    在InoDB存儲引擎中大量使用了AIO來處理IO請求,這樣可以極大提高資料庫性能,IO Thread主要負責以下IO請求的回調

    線程類型 預設個數 責任
    Read thread 4 負責讀操作
    write thread 4 負責寫操作
    Log thread 1 負責將日誌緩衝區刷新到磁碟
    Insert buffer thread 1 負責將寫緩衝區內容刷新到磁碟

    關於AIO(非同步IO)和IO(同步IO)

    同步就是在發出一個功能調用時,在沒有得到結果之前,該調用就不返回。也就是必須一件一件事做,等前一件事做完了才能做下一件事。

    非同步的概念和同步相對。當一個非同步過程調用發出後,調用者不能立刻得到結果(在此期間,調用者可以去乾一些別的事情)。實際處理這個調用的部件在完成後,通過狀態、通知和回調。

  3. Purge Thread

    主要用於回收事務已經提交的undo log,在事務提交之後,undo log可能不需要了,就用這個來回收。

  4. Page Cleaner Thread

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

整個流程

在增刪改查的時候,會操作記憶體結構區域,如果裡面沒有數據就從。磁碟結構中載入,然後進行操作。

最後在特定時間會自動從記憶體結構中刷新到磁碟中。在磁碟中進行持久化保存下來

事務原理

事務

事務是一組操作的集合,它是一個不可分割的工作單位,事務會把所有操作作為一個整體一起向系統提交撤銷操作請求。

這些操作要麼同時成功要麼同時失敗。

事務的四大性質

  1. 原子性

    事務是不可分割的最小操作單元,要麼全部成功,要麼全部失敗。

  2. 一致性

    事務完成時,必須使所有的數據保持一致性。

  3. 隔離性

    資料庫系統提高隔離機制,保證事務在不受外部併發操作影響的獨立環境運行。

  4. 持久性

    事務一旦提交或回滾,他對資料庫的數據改變就是永久的。

事務的原理

事務的原子性,一致性,持久性都是由redo log和undo log實現的

事務的隔離性是由 鎖機制和MVCC實現的。

redo log

重做日誌,記錄的是事務提交時數據頁的物理修改用來實現事務的持久性

該日誌文件由倆部分組成:

  1. 重做日誌緩衝(redo log buffer)

    在記憶體中

  2. 重做日誌文件(redo log file)

    在磁碟中

當事務提交後會把所有修改信息都存放到該日誌文件中,用於在刷新臟頁到磁碟中,發生錯誤時,進行數據的恢復。

大概流程:

  1. 客戶端A對innoDB存儲引擎的表進行增刪改事務操作

  2. 先訪問記憶體結構中的緩衝池,如果增刪改數據在其中不存在,

    就會從磁碟中讀取數據再刷新到緩衝池(這個數據必須是唯一索引,否則會先進入到更改緩衝區)

  3. 在緩衝池中變成臟頁,並記錄在redolog buffer中,後直接刷新到磁碟中

  4. 如果臟頁在一段時間後刷新到磁碟中報錯了,可以通過redo log進行恢復。

image

使用redo log直接刷新到磁碟結構的好處

事務一般是一組多條的增刪改查操作,故事務提交的時候會隨機的操作多條的記錄。

這些記錄會操作多條數據頁,這樣會產生大量的隨機磁碟IO

而直接將redo log文件非同步刷新到磁碟io中,由於它是日誌文件,日誌文件都是追加的,此時是順序磁碟IO,這樣會節約大量的磁碟IO

這種機制叫WAL(Write-Ahead Logging)(先寫日誌)

然後過一段時間臟頁日誌才會刷新到磁碟中。

故倆份日誌是迴圈清理的

事務的redo log日誌是為瞭解決臟頁刷新到磁碟出錯時進行數據的恢復使用的,用來保證數據的持久性

undo log

undo log日誌是用來保證事務的原子性的。

undo log也叫回滾日誌,用於記錄數據被修改前的信息,作用為:提供回滾和MVCC

redo log記錄的是物理日誌!

undo log記錄的是邏輯日誌,可以認為當執行delete 一條記錄時,undo log中會記錄一條對應的insert記錄,反之同理。

當執行rollback時,就可以從undo log中的邏輯記錄讀取到對應內容,從而進行回滾。

Undo log銷毀

undo log在事務執行時產生,事務提交時,並不會馬上刪除undo log,因為這些日誌可能還用於MVCC

Undo log存儲

undo log採用,的方式進行管理和記錄,存放在前面介紹的rollback segment回滾中,內部包含了1024個undo log segment

這個段是邏輯存儲結構的段哦~

MVCC(多版本併發控制)(高頻面試題)

MVCC的幾個基本概念

當前讀

我們讀取的是記錄的最新版本,讀取時還要保證其他併發事務不能修改當前記錄,會對讀取的記錄進行加鎖,

對於我們日常的操作,如:select...lock in share mode(共用鎖),select...for update,update,insert,delete(排他鎖)

都是一種當前讀。

案例:

在RR的隔離級別下

  1. 事務A進行查詢操作,事務B進行更新操作並提交事務
  2. 事務A使用當前讀select...此時讀取的是事務B更新之前的數據(原因是隔離級別)
  3. 事務A使用select...lock in share mode(當前讀)此時讀取的是事務B更新之後的數據。

快照讀

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

  1. Read Committed隔離級別:每次select都生成一個快照讀
  2. Repeatable Read隔離級別:開啟事務後第一個select語句才是快照讀的地方(後續查的就是這個快照數據)
  3. Serializable隔離級別:快照讀會退化為當前讀

MVCC介紹

全稱Multi-Version Concurrency Control 多版本併發控制。

指的是維護一個數據的多個版本,使得讀寫操作沒有衝突

快照讀為MYSQL實現MVCC提供了一個非阻塞讀功能,MVCC的具體實現,還需要依賴,資料庫的三個隱藏欄位

undo log日誌readView

MVCC-實現原理

記錄中的隱藏欄位

當我們創建了表除了自己本身創建的欄位,innoDB引擎會自動給我們創建三個欄位

分別是:

  1. DB_TRX_ID
  2. DB_ROLL_PTR
  3. DB_ROW_ID
隱藏欄位 含義
DB_TRX_ID 最近修改事務ID,記錄插入這條記錄或者最後一次修改該記錄的ID(事務id)
DB_ROLL_PTR 回滾指針,指向這條記錄的上一個版本,用於配合undo log指向上一個版本
DB_ROW_ID 隱藏主鍵,如果表結構沒有指定主鍵,就會生成該隱藏欄位

可以查看表空間文件內容來查看隱藏欄位信息

事務id是自增的!

在MYSQL中提供了一個命令來查看表空間文件的記錄信息

ibd2sdi xxx.ibd

undo log版本鏈

回滾日誌,在insert、update、delete的時候產生的便於數據回滾的日誌

當insert的時候,產生的undo log日誌只在回滾時需要,在事務提交後,可被立即刪除。

當update、delete的時候,產生的undo log日誌不只是回滾時需要,在快照讀時也需要,不會被立即刪除。

Undo log版本鏈

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

image

執行順序:

從上到下代表執行順序。在同一行代表同一時間執行。

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

版本鏈數據訪問規則

trx_id 代表的是當前事務的id

用這個id和ReadView的四個核心欄位進行比對

  1. trx_id == creator_trx_id 可以訪問該版本 這個條件成立代表數據是當前這個事務更改的

  2. trx_id < min_trx_id 可以訪問該版本 這個條件成立,說明數據已提交

  3. trx_id > max_trx_id 不可以訪問該版本 這個條件成立,說明事務是在ReadView生成之後才開啟的

  4. min_trx_id <= trx_id <= max_trx_id 如果trx_id不在m_ids中,就可以訪問該版本

    這個條件成立,說明數據已經提交。

根據隔離級別的不同ReadView生成時機不同

  1. 在Read Committed隔離級別下

    在事務第一次執行快照讀時都生成一個Read view

  2. 在Repeatable read隔離級別下

    在事務第一次執行快照讀時生成,後續復用這個Read view

在RC隔離級別下,版本鏈訪問原理分析

在事務第一次執行快照讀時都生成一個Read view

第一個快照讀,讀取情況

image

這個快照讀,根據規則,讀取的是0x00002這個地址的數據,對應著事務2修改後的數據內容。

第二個快照讀,讀取情況

image

這個快照讀,根據規則讀取到的是,0x00003地址的數據內容,就是事務3修改後的數據。

在RR隔離級別下,版本鏈訪問原理分析

在RR隔離級別下,只有事務在第一次執行快照讀的時候生成ReadView,後續復用這個ReadView

image

具體的和RC規則一致,不重覆講解。

總結

隱藏欄位+Undo log版本鏈+ReadView組成MVCC

MVCC+鎖構成事務的隔離機制

事務的一致性由Redo log和undo log共同保證


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 支持.NET/.NET Framework/.NET Core RabbitMQ作為一款主流的消息隊列工具早已廣受歡迎。相比於其它的MQ工具,RabbitMQ支持的語言更多、功能更完善。 本文提供一種市面上最/極簡單的使用RabbitMQ的方式,只需要會調用以下三個方法,你就幾乎可以掌握整個Rabb ...
  • 一:背景 1.講故事 前段時間有位朋友微信找到我,說他的程式出現了 CPU 爆高,幫忙看下程式到底出了什麼情況?圖就不上了,我們直接進入主題。 二:WinDbg 分析 1. CPU 真的爆高嗎? 要確認是否真的爆高,可以使用 !tp 觀察。 0:000> !tp CPU utilization: 9 ...
  • 最近在學著使用blackwidow這個工具,在ubuntu20.02系統的安裝過程當中遇到了selenium使用的一些問題。 selenium是個什麼工具? Selenium是一個用於Web應用程式測試的工具。Selenium測試直接運行在瀏覽器中,就像真正的用戶在操作一樣。支持的瀏覽器包括IE(7 ...
  • Ubuntu官網會給各種公有雲平臺提供cloud鏡像, 例如AWS, MS Azure, Google Cloud, 以及本地虛機環境例如 QEMU, VMware, Vagrant等, 這些鏡像在 https://cloud-images.ubuntu.com 上可以下載. 這裡說明如何在 KVM... ...
  • 最近在配置Linux系統的ntp校時,涉及到開機啟動問題,總結一下 兩個環境: CentOS release 6.5 (Final) CentOS Linux release 7.9.2009 (Core) centos6.5 設置開機啟動使用chkconfig方式 chkconfig 是設置服務在 ...
  • nginx訪問控制,用戶認證,配置https,zabbix監控nginx狀態頁面 nginx訪問控制 用於location段 allow:設定允許哪台或哪些主機訪問,多個參數間用空格隔開 deny: 設定禁止哪台或哪些主機訪問,多個參數間用空格隔開 //測試 [root@nginx ~]# cd / ...
  • 1、進程結構特征: >>進程式控制制塊的作用: 動態性 進程最基本的特征是動態性 進程的生命周期 進程由創建而產生,由調度而執行,由撤銷而消亡的過程 併發性 獨立性 非同步性 2、進程的三種基本狀態 就緒狀態 執行狀態 阻塞狀態 ...
  • 一、CentOS 7.9 安裝 elasticsearch-7.8.1 地址 https://www.elastic.co https://www.elastic.co/cn/downloads/past-releases https://github.com/elastic https://git ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...