MySQL高階10-InnoDB引擎儲存架構

Se7eN_HOU發表於2023-09-19

一、邏輯儲存結構

  MySQL高階10-InnoDB引擎儲存架構

  表空間(Tablespace):一個mysql例項,及一個資料庫例項,可以對應多個表空間(ibd檔案),用於儲存記錄,索引等資料。

  

  段(Segment):分為資料段(Leaf node segment)、索引段(Non-leaf node segment)、回滾段(Rollback segment),InnoDB是索引組織表,資料段就是B+樹的葉子節點(Leaf node segment),索引段即為B+樹的非葉子節點(Non-leaf node segment)。段用來管理多個Extent(區)。

  

 

  區(Extent):表空間的單元結構,每個區的大小為1M, 預設情況下,InnoDB儲存引擎頁大小為16k,即一個區中一共有64個連續的頁

  頁(Page):頁是InnoDB儲存引擎磁碟管理的最小單元,每個頁大小預設為16K,為了保證頁的連續,InnoDB儲存引擎每次從磁碟申請4-5個區

  行(Row):InnoDB儲存引擎資料是按行進行存放的,Trx_id:每次對某條記錄進行改動時,都會把對應的事務id賦值給這個trx_id隱藏列。Roll_pointer:每次對某條記錄進行改動時,都會把舊的版本寫入到undo日誌中,然後這個隱藏列就相當於一個指標,透過它可以找到該記錄修改前的資訊

 

二、整體架構

  MySQL5.5 版本開始,預設使用 InnoDB 儲存引擎,它擅長事務處理,具有崩潰恢復特性,在日常開發中使用非常廣泛,下面是 InnoDB 架構圖,左側為記憶體架構,右側為磁碟架構。 

  

 

 

三、記憶體結構

   

  記憶體架構中主要分為:Buffer Poll(記憶體緩衝池)、Change Buffer()、LogBuffer()、Adaptive Hash Index()四個區。

  3.1 Buffer Pool

    緩衝池是主記憶體中的一個區域,裡面可以快取磁碟上經常操作的真實資料,在執行增刪改查操作時,先操作緩衝池中的資料,若緩衝池沒有資料,則從磁碟載入並快取,然後再以一定頻率重新整理到磁碟,從而減少磁碟IO,加快出來速度。緩衝池以Page頁為單位,底層採用連結串列資料結構管理Page,根據狀態可以將Page分為三種型別。

    • free page:空閒Page,未被使用。
    • clean page:被使用page,資料沒有被修改過。
    • dirty page:髒頁,被使用page,資料被修改過,其中資料與磁碟上的資料產生了不一致。

  3.2 Change Buffer

    更改緩衝區,針對與非唯一二級索引頁,在執行DML語句時,如果這些資料Page沒有在Buffer Pool中,不會直接操作磁碟,而是將資料變更存在更改緩衝區Change Buffer中,在未來資料被讀取時,再將資料合併恢復到Buffer Pool中,再講合併後的資料重新整理到磁碟中。

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

  MySQL高階10-InnoDB引擎儲存架構

  3.3 Adaptive Hash index

    自適應hash索引,InnoDB預設是不支援hash索引的,預設支援的是B+樹的索引。因為hash索引不支援範圍查詢,僅可以用來做值匹配查詢。但是自適應hash索引,用於最佳化對Buffer Pool資料的查詢。InnoDB儲存引擎會監控對錶上各項索引頁的查詢,如果觀察到hash索引可以提升速度,則建立hash索引,稱之為自適應hash索引。

    自適應雜湊索引,無需人工干預,是系統根據情況自動完成。透過 innodb_adaptive_hash_index 引數可以配置自適應hash索引的開啟和關閉。 

mysql> show variables like "%innodb_adaptive_hash_index%";
+----------------------------------+-------+
| Variable_name                    | Value |
+----------------------------------+-------+
| innodb_adaptive_hash_index       | ON    |
| innodb_adaptive_hash_index_parts | 8     |
+----------------------------------+-------+
2 rows in set (0.00 sec)

  3.4 Log Buffer

    日誌緩衝區,用來儲存要寫入到磁碟中的log日誌(redolog,undolog),預設大小為16M, 日誌緩衝區的日誌會定期重新整理到磁碟中,如果需要更新、插入或者刪除許多行的事務,增加日誌緩衝區的大小可以節省磁碟i/o

    透過 innodb_log_buffer_size 引數可以檢視緩衝區大小

    透過 innodb_flush_log_at_trx_commit 引數可以檢視重新整理到磁碟時機。這裡有0,1,2三個值:

      • 0:每秒將日誌寫入並重新整理到磁碟一次。
      • 1:日誌在每次事務提交時寫入並重新整理到磁碟。
      • 2:日誌在每次事務提交後寫入,並每秒重新整理到磁碟一次。
mysql> show variables like "innodb_log_buffer_size";
+------------------------+----------+
| Variable_name          | Value    |
+------------------------+----------+
| innodb_log_buffer_size | 16777216 |
+------------------------+----------+
1 row in set (0.00 sec)

mysql>   show variables like "%flush_log%";
+--------------------------------+-------+
| Variable_name                  | Value |
+--------------------------------+-------+
| innodb_flush_log_at_timeout    | 1     |
| innodb_flush_log_at_trx_commit | 1     |
+--------------------------------+-------+
2 rows in set (0.00 sec)

 

四、磁碟架構  

   

  4.1 System Tablespace  

    在MySQL中,System Tablespace(系統表空間)是一個用於儲存系統表和一些特殊表的預設表空間。系統表空間包含了以下幾個重要的系統表:

    • mysql.user:儲存了MySQL中的使用者和許可權資訊。
    • mysql.db:儲存了所有資料庫的資訊。
    • mysql.host:儲存了允許連線到MySQL伺服器的主機資訊。
    • mysql.tables_priv:儲存了表級別的許可權資訊。
    • mysql.columns_priv:儲存了列級別的許可權資訊。

    系統表空間還包含其他系統表,用於儲存MySQL伺服器的配置和後設資料資訊。
    系統表空間預設儲存在名為`ibdata1`的共享檔案中。這個檔案通常位於MySQL的資料目錄下。

    MySQL高階10-InnoDB引擎儲存架構

    要注意的是,在InnoDB儲存引擎中,除了系統表空間(System Tablespace),還存在一個叫做表空間檔案(Tablespaces)的概念。表空間檔案用於儲存使用者建立的表和索引。每個InnoDB表都會有一個對應的表空間檔案。
    需要注意的是,有時候系統表空間的大小會超過預期,導致空間不足或效能問題。在這種情況下,可以考慮調整系統表空間的大小或進行其他最佳化措施以解決問題。
    總結:系統表空間是MySQL中用於儲存系統表和特殊表的預設表空間,包含了一些重要的系統表,通常儲存在名為`ibdata1`的共享檔案中。

  4.2 File-Per-Table Tablespace

    MySQL高階10-InnoDB引擎儲存架構

    File-Per-Table Tablespace(每個表一個表空間)是MySQL中的一個儲存配置選項,它允許每個InnoDB表使用單獨的表空間檔案來儲存資料和索引。這與預設情況下的系統表空間不同。

    在預設情況下,所有的InnoDB表共享一個系統表空間,即儲存在ibdata1檔案中。而使用File-Per-Table Tablespace選項,每個InnoDB表都會有一個獨立的表空間檔案,位於資料目錄下。

    File-Per-Table Tablespace的優點包括:

    • 管理:每個表有自己的表空間檔案,方便管理和維護。可以更方便地備份、恢復或遷移單個表。
    • 效能:每個表具有獨立的表空間檔案,可以在磁碟上更好地分佈和組織資料,提高效能和併發訪問的能力。
    • 儲存空間:使用File-Per-Table Tablespace可以更有效地使用儲存空間。當有大量小表或經常進行刪除和重建表時,每個表的表空間檔案可以更好地管理空間,避免系統表空間的不斷增長。

    File-Per-Table Tablespace的缺點和注意事項包括:

    • 管理複雜性:每個表都會有一個獨立的表空間檔案,這可能增加了管理的複雜性,包括備份和維護的管理操作。
    • 儲存和檔案系統:使用File-Per-Table Tablespace可能涉及更多的磁碟IO操作,並可能增加檔案系統的碎片化問題。

    使用File-Per-Table Tablespace可以在建立表時進行配置或在現有表上進行更改。要在建立新表時啟用File-Per-Table Tablespace,可以在建立表的DDL語句中加上ENGINE=InnoDB選項。要在已有表上啟用File-Per-Table Tablespace,可以使用MySQL的ALTER TABLE語句並設定innodb_file_per_table引數為ON。

    總結:File-Per-Table Tablespace是MySQL InnoDB儲存引擎的一個選項,允許每個表使用單獨的表空間檔案儲存資料和索引。它提供了更靈活的管理、更好的效能和更高效的儲存空間利用率

  4.3 General Tablespaces

    General Tablespaces(通用表空間)是MySQL 5.7版本引入的一個功能,在InnoDB儲存引擎中提供了更靈活和更高階的表空間管理選項。 

    通用表空間允許將多個InnoDB表儲存在一個或多個共享表空間檔案中,而不是每個表都有自己的獨立表空間檔案(如File-Per-Table Tablespace中)。這些共享表空間檔案可以在執行時動態新增或刪除新的表。

    通用表空間的優點包括:

    • 簡化管理:使用通用表空間可以更方便地管理和維護多個表。可以將相關的表組織在同一個共享表空間中,便於備份、恢復和遷移。
    • 空間效率:通用表空間可以更有效地使用儲存空間。多個表可以共享一個表空間檔案,避免了為每個表都建立單獨的表空間檔案的開銷。
    • 高效能:由於多個表共享表空間檔案,可以提高磁碟IO操作的效率。此外,共享表空間可以利用預讀機制(預讀相鄰頁)來提高查詢效能。

     使用通用表空間時,可以在建立表時指定TABLESPACE子句來為表分配到指定的共享表空間,也可以使用ALTER TABLE語句將現有表移動到共享表空間中。

     建立通用表空間示例:

mysql> create tablespace my_test add datafile "my_test.ibd" engine=InnoDB;
Query OK, 0 rows affected (0.01 sec)

    MySQL高階10-InnoDB引擎儲存架構

     建立使用通用表空間的表示例:

mysql> create table tablespace_test(id int) tablespace my_test;
Query OK, 0 rows affected (0.03 sec)

    說明1:此時MySQL就不會再給tablespace_test表建立單獨的表空間了,而是使用通用表空間my_test.ibd空間

    將現有表移動到通用表空間語法示例:

ALTER TABLE table_name TABLESPACE tablespace_name;

    說明2:`table_name`是要移動的表的名稱,`tablespace_name`是要移動到的表空間的名稱。    

    刪除通用表空間語法示例

ALTER TABLESPACE tablespace_name DROP DATAFILE '<path>/tablespace_file.ibd';

    說明3:`tablespace_name`是要刪除的表空間的名稱,`<path>/tablespace_file.ibd`是要刪除的表空間檔案的路徑和檔名。

  4.4 undo Tablespace

    在MySQL中,"undo tablespace"(撤銷表空間)是用於儲存撤銷日誌資料的一種特殊型別的表空間。

    撤銷日誌是 MySQL 中的一項重要功能,用於回滾或撤銷事務中所做的更改。當事務執行 UPDATE、DELETE 或 INSERT 操作時,撤銷日誌記錄了被修改或刪除的非聚集索引的舊值,以及 INSERT 操作插入的新記錄。這些撤銷日誌記錄儲存在名為 "undo log" 的資料結構中。

    為了高效地管理和儲存撤銷日誌資料,MySQL引入了 "undo tablespace" 的概念。撤銷表空間是一個獨立於資料表空間的區域,用於儲存撤銷日誌資料。它可以包含一個或多個檔案,這些檔案具有固定大小(通常是小於等於1GB)和特定的命名約定,預設的是undo_001和undo_002

    MySQL高階10-InnoDB引擎儲存架構

    撤銷表空間的主要作用有以下幾個方面:

    • 提供事務的回滾能力:如果一個事務需要回滾,MySQL可以使用撤銷表空間中的撤銷日誌來還原事務執行前的資料狀態。
    • 支援併發事務:撤銷表空間使得多個事務可以同時進行,並提供了事務隔離級別的支援。
    • 回收空間:當事務完成時,撤銷表空間中的撤銷日誌可以被清除,空間可以被重複使用。

     撤銷表空間在MySQL的配置檔案(my.cnf或my.ini)中透過innodb_undo_directoryinnodb_undo_tablespaces配置項進行設定。innodb_undo_directory定義了撤銷表空間檔案的儲存目錄,而innodb_undo_tablespaces指定了要使用的撤銷表空間檔案的數量。

    總結:撤銷表空間是MySQL中用於儲存撤銷日誌資料的表空間,支援事務的回滾、併發事務和空間回收。

  4.5 Temporary Tablespace

    在MySQL中,臨時表空間(Temporary Tablespace)是用於儲存臨時表資料和臨時結果集的一種特殊型別的表空間。臨時表空間的作用是儲存臨時表的資料,這些臨時表通常是在查詢過程中建立的。這些臨時表可能包括臨時表名、中間結果集或者用於排序和聚合的臨時資料。

    預設情況下,MySQL使用系統表空間(system tablespace)來儲存臨時表資料。但是,在高併發環境下,使用單個系統表空間可能會導致效能瓶頸。為了提高效能並最佳化系統資源的使用,MySQL引入了臨時表空間的概念。透過為臨時表資料分配獨立的臨時表空間,MySQL可以更好地管理和最佳化臨時表的建立和使用。臨時表空間可以在獨立的表空間檔案中儲存臨時表資料,這些檔案可以位於不同的儲存裝置上,從而分散了IO負載。

    可以透過以下配置項來設定臨時表空間:既可以寫在MySQL配置檔案中也可以在MySQL互動介面上使用set 指令設定

    -`tmp_table_size`:用於設定每個臨時表的記憶體大小。如果臨時表大小超過此值,則會將其儲存到臨時表空間中。

    -`max_heap_table_size`:用於設定只在記憶體中儲存的臨時表的最大大小。

    -`tmpdir`:用於設定臨時表空間的目錄。

    使用臨時表空間可以提升查詢效能,減少對系統表空間的負載,並提供更好的系統擴充套件性和可維護性。

    總結:臨時表空間是MySQL中用於儲存臨時表資料和臨時結果集的表空間。它可以提高查詢效能,並分散IO負載,提供更好的系統資源利用和擴充套件性。

  4.6 Doublewrite Buffer Files

    在MySQL中,Doublewrite Buffer Files(雙寫緩衝區檔案)是一種用於提高資料保護和恢復機制的技術。Doublewrite Buffer Files使用了一種雙寫技術,先將資料寫入到雙寫緩衝區檔案,然後再寫入到實際的資料檔案。這可以減少資料損壞和頁級別的IO不一致性的風險。雙寫緩衝區檔案的主要作用是用於在MySQL崩潰或意外斷電的情況下,保護InnoDB儲存引擎使用的資料頁的完整性。
    當InnoDB儲存引擎進行寫操作時,會先將資料寫入到雙寫緩衝區檔案,然後透過後臺執行緒將資料寫入到磁碟上的實際資料檔案。這樣,在發生崩潰或斷電時,雙寫緩衝區中的資料可以用來恢復資料檔案的一致性。雙寫緩衝區檔案在重啟MySQL時會自動應用並刪除。
    雙寫緩衝區檔案的大小由配置引數`innodb_doublewrite_buffer_size` 控制,預設值為`1MB`。可以透過在MySQL配置檔案中設定該引數來修改雙寫緩衝區檔案的大小。
    使用雙寫緩衝區檔案的一個潛在問題是會增加寫操作的IO負載,因為每個寫操作都需要寫入兩次。為了減少雙寫帶來的效能影響,可以考慮將雙寫緩衝區檔案放置在快速的儲存介質上,如SSD。
    總結:Doublewrite Buffer Files是一種用於提高資料保護和恢復機制的技術,透過在寫入實際資料檔案之前將資料先寫入到雙寫緩衝區檔案,來減少資料損壞和頁級別的IO不一致性的風險。雙寫緩衝區檔案的大小由配置引數控制,需要在MySQL配置檔案中進行配置。

    MySQL高階10-InnoDB引擎儲存架構

  4.7 Redo Log

    在MySQL中,Redo Log(重做日誌)是用於實現事務的永續性和恢復能力的關鍵元件之一。它記錄了發生在資料庫中的資料更改操作,以確保在系統崩潰或斷電時,能夠將未完成的事務重新應用到資料庫中,以保持資料的一致性。

    Redo Log是迴圈寫入的,意味著當日志檔案寫滿後,會重新從開頭開始覆蓋之前的日誌。所有的修改操作都會先寫入到Redo Log,然後非同步地重新整理到磁碟上的資料檔案。這樣即使在寫操作還未重新整理到磁碟上的資料檔案時發生崩潰,透過Redo Log的回放可以重新執行未完成的事務,確保資料的永續性。

    Redo Log是以邏輯方式記錄的,而不是物理方式。它記錄了事務引起的資料修改,而不是實際的資料變化。透過記錄這些邏輯操作,MySQL可以在恢復時重新執行所需的操作。

    在MySQL中,Redo Log由兩個檔案組成,通常為`ib_logfile0`和`ib_logfile1`。這些檔案的大小由配置引數`innodb_log_file_size`控制,預設情況下為`48MB`。可以在MySQL配置檔案中進行修改。

    使用Redo Log的一個重要注意事項是,寫入Redo Log會引起磁碟IO操作,因此對於事務密集型負載,合理調整Redo Log的大小和I/O效能是很重要的。過小的Redo Log可能導致頻繁的重新整理和IO延遲,而過大的Redo Log可能對記憶體和磁碟空間帶來負擔。

    總結:Redo Log是MySQL中用於實現事務的永續性和恢復的關鍵元件,它記錄了資料的修改操作,保證在系統崩潰或斷電後,能夠重新應用未完成的事務。Redo Log由兩個檔案組成,透過迴圈寫入的方式記錄資料修改。合理調整Redo Log的大小和I/O效能對於資料庫效能和永續性是重要的。

    MySQL高階10-InnoDB引擎儲存架構

 

 

相關文章