成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

一篇學會 InnoDB 表空間

網絡 通信技術
我們存在 MySQL 中的數據,到底在磁盤上長啥樣。你可能會說,數據不都存儲在聚簇索引中嗎?但很遺憾,你并沒有回答我的問題。我會再問你,那聚簇索引在磁盤上又長啥樣?

[[408831]]

本文轉載自微信公眾號「SH的全棧筆記」,作者SH的全棧筆記。轉載本文請聯系SH的全棧筆記公眾號。

想了很久的標題,算了,就這樣吧。

這應該是 MySQL 原理中最底層的部分了,我們存在 MySQL 中的數據,到底在磁盤上長啥樣。你可能會說,數據不都存儲在聚簇索引中嗎?但很遺憾,你并沒有回答我的問題。我會再問你,那聚簇索引在磁盤上又長啥樣?

就像 Redis 的 RDB 文件,最終落在磁盤上就是一個真真切切的 dump.rdb 文件,而 MySQL 就顯得有點迷,我們只知道通過 SQL 去拿數據,并不知道數據最終是以什么方式進行存儲的。當然,了解其底層的存儲邏輯,并不僅僅是為了滿足好奇心這么簡單。

其底層的存儲方式,會影響到聚簇索引中數據的存儲,進而影響到 MySQL 的 DML(Data Manipulation Language) 性能,所以對底層存儲邏輯有個清晰的認知,就能夠在某些對性能有著極致追求的場景下,幫助我們對 MySQL 進行優化。

表在磁盤上到底長啥樣

首先我們先不扯像表空間這類的專業詞匯,讓我們先來建一張表,從磁盤的結構上來看一下。首先你得找到 MySQL 的數據目錄,如果你是用 Docker 啟動的話,這個目錄大概長下面這樣:

  1. /data00/docker/volumes/ef876f70d5f5c95325c2a79689db79cc4d1cecb7d96e98901256bd49ca359287/_data 

然后我們新建一個叫 test 的 DB,然后在 _data 的這個目錄下就會多一個 test 的目錄。然后在 test 數據庫下新建了一張 student 的表,在 test 目錄下就會多出兩個文件,分別是 student.frm 和 student.ibd。

可以發現,最終數據在磁盤上的宏觀表現其實很簡單,就這么些個文件,什么索引啊、頁啊都先忽略不管。

對于后綴為 .frm 文件,里面都有啥?里面包含了每張表的元數據,包括了表的結構定義。而 .ibd 文件里則存放了該表的數據和索引。

我看到有人在博客里把 .ibd 寫成了 .idb...雖然 db 看著更順,但很遺憾并不正確,你把 ibd 的全稱 innodb data 記住,就不會把縮寫記錯了。

上面說的這個以表名命名的 ibd 文件,其實還有一個專業術語叫表空間。

顧名思義可以理解為我這個表專屬的空間。

認識表空間

如果我上來就直接告訴你,InnoDB 中有個概念叫表空間,你大概率是很難理解的。

像上文描述的這種每張表都有自己單獨的數據存儲文件的,叫獨占表空間;相對應的,InnoDB 還有自己的系統表空間,在系統表空間下,所有表的數據都存儲在同一個文件中。

那數據什么時候存儲在系統表空間,又什么時候存儲在獨占表空間呢?

這個可以通過 MySQL 的配置項 innodb_file_per_table 來決定。當該配置項開啟時,每張表都會有自己單獨的表空間;相反,當該配置項關閉時,表數據將會存儲在系統的表空間內。

該配置項是默認開啟的,你可以在 MySQL 中通過命令 SHOW VARIABLES LIKE 'innodb_file_per_table' 來查看該變量的狀態。

其實從 MySQL 將獨占表空間作為默認的設置來看,你就應該知道獨占表空間的性能肯定是要比系統表空間好的。

因為對于系統表空間來說,通常只有一個文件,所有的表數據都在這一個文件中,如果我們對某張表進行 TRUNCATE 操作,需要將分散在文件中各個地方的數據刪除。首先這樣做性能就不好,其次 TRUNCATE 操作會在該文件中產生很多空閑的碎片空間,并且并不會減少共享表空間文件 ibdata1 的大小。

不能理解的話,可以想象 Java 里的標記-清理垃圾回收算法,該算法會在清理的時候造成大量的內存碎片,不利于提高后期的內存利用率。

而對于獨占表空間來說,從始至終一整張表的數據都只存儲在一個文件,比起共享表空間誰更容易清理并且還能釋放磁盤空間,簡直是一目了然。所以,對于獨占表空間來說,TRUNCATE 的性能會更好。

除此之外,獨占表空間能夠提升單張表的最大容量限制,這塊可能不是很好理解,為什么獨占表空間還有這個功效?在這里你只需要記住這個結論就好了,后文講到頁相關的東西時,我們會具體的論證。

了解了表空間的概念之后,我們就可以繼續深入了解數據在表空間內到底是怎么存儲的了。

深入表空間文件內部

其實在很早之前我講 InnoDB的內存架構 時我就講過,在 InnoDB 中,頁是其數據管理的最小單位。所以講道理我們應該從其最小的部分開始,但是之前已經專門寫過一篇文章來討論頁了,所以在這里就不贅述了。

表空間由一堆的**頁(Pages)**組成,并且每張頁的大小是相等的,頁大小默認為 16K,當然這個大小可以調整。

頁大小可以通過配置項 innodb_page_size 根據業務的實際情況進行調整,可以選擇的大小分別為 4K、8K、16K、32K和64K。

一堆頁組合在一起,就變成了區(Extents)。

每個區的大小是固定的。當我們設置了不同的 innodb_page_size 時,每個區(Extents)內所包含的頁的數量、和對應的固定區大小都不同,具體的情況如下圖所示。

當 innodb_page_size 為 4K、8K或者16K時,其對應的區(Extents)大小為1M;當其頁大小為32K時,區大小為2M;當頁大小為64K時,區大小為4M。

MySQL 5.6的時候其實只支持 4K、8K和16K,至于上面說到的32K和64K,是在 MySQL 5.7.6 之后添加的。

隨著頁和區大小的變動,每個區內所能容納的 頁數量 也會隨之改變。舉個例子,當 innodb_page_size 的值為 16K 時,每個區就包含 64 頁;當其為 8K 時,每個區包含 128 頁;當其為 4K 時,每個區就會包含 256 頁。

上面聊過,一頁一頁的數據組成了區,而一個一個區則組成了段(Segments)。

在邏輯上,InnoDB 的表空間就是由一個一個這樣的段(Segment)組成的。隨著數據量的持續增長需要申請新的空間時,InnoDB 會先請求32個頁,之后便會直接分配一整個區(Extents) 。甚至在某個很大的 Segment 內,還會一次性分配 4 個區。

默認情況下,InnoDB 會給每個索引分配兩個段(Segment)。一個用于存儲索引中的非葉子結點,另一個用于存儲葉子結點。

表空間的分類

上面大概介紹了兩種表空間類別,分別是系統表空間、獨占表空間。接下來就需要詳細的了解一下各個表空間分類的細節了。

系統表空間

當我們開啟了innodb_file_per_table 這個配置項(默認就是開啟的)之后,系統表空間內就只用于存儲 Change Buffer 相關的數據。而當我們將其關閉之后,系統表空間內就會存儲表和索引相關的數據。當然,在 MySQL 8.0之前,獨占表空間內還包含了 Double Write Buffer(兩次寫緩沖),但在 MySQL 8.0.20 之后被移了出去,存放在了一個單獨的文件中。

默認情況下,系統表空間只會有一個叫 ibdata1 的數據文件,當然,它是允許有多個文件存在的。這所有的屬性包括文件名稱、文件大小都是通過配置項目 innodb_data_file_path 來制定的,舉個例子:

  1. innodb_data_file_path=ibdata1:10M:autoextend 

這里指明了系統表空間的文件名為ibdata1 ,初始化大小為10M 。你可發現了,這個 autoextend 是個什么鬼?

剛剛說到,初始大小是 10M ,那么隨著 MySQL 的運行,其數據量會慢慢的增長,數據文件必須要申請更多的空間來存儲數據。而定義了 autoextend InnoDB 就會幫我們自動對數據文件進行擴容,每次擴容申請 8M 的空間。當然,這個 8M 也是可以配置的,我們可以通過配置項 innodb_autoextend_increment 來配置。

獨占表空間

這塊其實上面在引入的時候已經介紹的差不多了,這里簡單的總結一下就好。當配置項 innodb_file_per_table 開啟時(現在是默認開啟的),每張表的數據都會存儲自己單獨的數據文件中。

常規表空間

這個暫時不用了解,知道常規表空間跟系統表空間類似,也是一個共享的存儲空間就好。

Undo 表空間

這里主要存儲 Undo Logs,有了 Undo Logs 我們就可以在事務出錯之后快速的將更改回滾。InnoDB 會默認給 Undo 表空間創建兩個數據文件,如果沒有特別指定,其文件名默認為 undo_001 和 undo_002 。

至于這兩個數據文件的具體存放路徑,可以通過配置項 innodb_undo_directory 來指定。當然,如果沒有指定,Undo 表空間的數據文件就會放在 InnoDB 的默認數據目錄下,通常來說是 /usr/local/mysql 。

而這兩個 Undo 表空間數據文件的初始大小,在 MySQL 8.0.23 之前是由 InnoDB 的頁大小來決定的,具體的情況如下圖:

而在 MySQL 8.0.23 之后,Undo 表空間的初始化大小都是 16M 了。至于 Undo 表空間的擴容,不同的版本也有不通的處理方式。

在 MySQL 8.0.23 之前,每次擴容是申請 4 個區(Extends),按照之前的討論,如果頁大小為 16 K,那么對應到區就是 1M,換句話說,每次擴容申請 4M 的空間,當然這個具體的大小會根據頁大小的變化而變化,這個在上文提到過在此就不再贅述。

而在 MySQL 8.0.23 之后,每次最少都要擴容 16 M的空間。而且,為了防止數據量爆發式的增長,InnoDB 對擴容的容量會做一個動態的調整。

如果本次擴容和上次擴容時間差小于 0.1 秒,則擴容的空間會加倍,也就是變成 32 M。如果多次擴容的時間差都小于 0.1 秒,這個 加倍 的操作會 累加,直到達到上限 256M;那你可能會說,那如果某段時間剛好請求量比較大,使得擴容的容量達到了最大的 256 M,那后續請求量下去了呢?難道還是申請 256 M嗎?這顯的不太合理。所以 InnoDB 判斷如果兩次擴容間隔大于 0.1 秒,就會將擴容的容量減半,直到減少到最小限制 16 M。

臨時表空間

臨時表空間內的數據,顧名思義都是臨時的。

你在說屁話...

它分為兩個部分,分別是:

  • Session 臨時表空間
  • 全局臨時表空間

對于 Session 臨時表空間,里面會存儲由用戶或者優化器創建的臨時表。對于每個 Session 來說,InnoDB 最多會分配兩個數據文件(表空間),分別用于存儲用戶創建的臨時表和優化器創建的內部臨時表。當 Session 失效之后,這些已分配的數據文件會被 Truncate 然后放到一個 數據文件池 中。

這個操作其實跟其他的池化技術沒有區別,值得注意的是,這些文件被 Truncate 了之后大小并不會發生變化。而這個數據文件池會在 MySQL 服務器啟動的時候創建,里面會默認扔進去 10 個文件,每個文件的默認大小為 5 頁。

而對于全局臨時表空間,里面會存對臨時表做了改動的回滾段(Rollback Segment),其初始化的大小大約是 12 M,同樣會在 MySQL 服務器啟動的時候創建。

 

責任編輯:武曉燕 來源: SH的全棧筆記
相關推薦

2021-09-07 17:54:04

OpenGauss分區表索引

2022-06-22 07:32:53

Sharding分庫數據源

2022-01-02 08:43:46

Python

2022-08-29 08:00:11

哈希表數組存儲桶

2022-02-07 11:01:23

ZooKeeper

2021-05-11 08:54:59

建造者模式設計

2021-07-06 08:59:18

抽象工廠模式

2023-01-03 08:31:54

Spring讀取器配置

2022-08-26 09:29:01

Kubernetes策略Master

2021-07-05 22:11:38

MySQL體系架構

2023-11-28 08:29:31

Rust內存布局

2022-08-23 08:00:59

磁盤性能網絡

2021-07-02 08:51:29

源碼參數Thread

2021-09-28 08:59:30

復原IP地址

2021-10-14 10:22:19

逃逸JVM性能

2022-04-12 08:30:52

回調函數代碼調試

2021-07-16 22:43:10

Go并發Golang

2023-03-13 21:38:08

TCP數據IP地址

2021-10-27 09:59:35

存儲

2022-10-20 07:39:26

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 激情五月婷婷 | 欧美一级片在线观看 | 人人叉| 性网站免费| 人人看人人草 | 亚洲精品一区在线观看 | 91视频在线观看免费 | 国产91在线精品 | 日日日干干干 | 97超碰在线免费 | 免费观看一级视频 | 国产精品久久欧美久久一区 | 视频在线一区 | 91高清在线观看 | 成人三级网址 | 中文字幕第一页在线 | 精品一区二区三区四区 | 成人a视频 | 男人天堂视频在线观看 | 欧美大片一区 | 成人在线视频观看 | 精品一区二区三区四区五区 | 一级片在线视频 | 亚洲精品成人在线 | 啪一啪在线视频 | 手机看片1 | 免费午夜视频在线观看 | 午夜伊人 | 亚洲午夜久久久 | 九七午夜剧场福利写真 | 国产精品福利一区二区三区 | 国产精品片aa在线观看 | k8久久久一区二区三区 | 天天看天天干 | 一区二区三区福利视频 | 97国产精品视频 | 欧美日韩国产高清 | 国产在线网站 | 成人福利视频网站 | 成人深夜福利 | 国产剧情一区 |