上文 最後的innodb體系結構中我們重點指明了表空間,本篇就來看看tablespace表空間。
表空間只是邏輯概念,學習它的重點在於將邏輯理清楚。
前面的文章中提到過檔案
這個虛擬概念,我們程式開發時對檔案進行操作,但是根本不用關心檔案在磁碟上是如何儲存的。也即檔案遮蔽了底層儲存的細節,這當然是作業系統的功勞。
而前文也提到過,每個表的索引和資料都存放在.ibd
檔案中,既然是檔案,則同樣會被作業系統管理。而這個ibd
檔案在innodb看來,就可以叫做是表空間,因為在innodb應用程式的內部來看,是沒有檔案
這個概念的,我的地盤我做主嘛,所以當這個檔案
載入到innodb程序中時,就被看做是開啟(進入)了乙個表空間
。
那麼,innodb是如何找到這個表空間的入口,通過月光寶盒嗎?當然是通過mysql.cnf
配置檔案中配置的 data資料庫目錄位址找到的。姑且不論他是什麼時機開啟或者其他***,反正現在表空間這個潘多拉魔盒已經開啟了,那麼我們就進一步地去探索。
因為眾所周知的原因,作業系統中檔案是由乙個個磁碟上的頁組成,當然這裡的檔案和頁都是虛擬概念,只有磁碟是物理存在的。換句話說,ibd
檔案被作業系統切割成了乙個個的頁,儲存在磁碟上。(innodb心都在滴血,表空間都被切割爛了。這樣看,作業系統就是空間系的聖魔導師,哈哈哈)。
現在有個矛盾必須解決,矛盾的雙發就是mysql 和 作業系統,矛盾的物件就是這個檔案(表空間),矛盾如下:
矛盾是真的不小,可是擁有上帝視角的開發大牛多麼聰明啊。既然不能直接改變你作業系統的管理方式,那我就在你的基礎上再造乙個就好了唄。造乙個什麼呢?對,就造乙個針對這些被作業系統切碎的頁面的空間管理系統。
這個空間管理系統當然分成兩塊:表空間(僅僅是乙個物件)和圍繞表空間的一系列執行方法。這樣,就可以實現乙個建立在作業系統裡的檔案系統之上的檔案系統
。
現在,對於表空間來說,我們已經十分清楚它的目的了,即:
管理表空間對應的無數頁面那麼,第一步,自然要
去作業系統化
,將作業系統中的頁替換掉,變成表空間中的頁。也就是檔案在作業系統上是頁1、頁2,到了表空間這邊就變成了頁a、頁b
。雖然都稱之為頁,但是此頁非彼頁。下面所說的頁
都是表空間的這個頁。
當然了,這兩個不同概念的頁怎麼對映的,我們就不多管閒事了。
這樣子,整個表空間的基石,就完完全全是自主研發可控的了。所以我們可以隨便修改 innodb 的頁大小,而不用管作業系統。
可是,成千上萬的頁全部在乙個表空間中,我們該怎麼管理呢?(表空間中的頁就是前文我們講到的資料頁之類的)
萬事萬物都是有聯絡的,你可以考慮下,假如是你,你會提出什麼建議呢?
隨便舉幾個例子,比如軍隊中,難道就乙個司令去管理幾百萬的士兵嗎?
再比如,學校裡,為啥分班啊,直接全部一起就好了唄?
再比如,商場裡,這麼多商品隨便放著就好了唄,為啥還要什麼生鮮區、日用品區呢?
還有很多很多例子。發現了嗎,解決的辦法是什麼?
區,也就是分割槽,分層次。自然,innodb的表空間中同樣引入了
區 extent
概念。每個區包含64個頁面,每256個區為劃分為一組。這樣,當頁大小為16k時,每個區就為1m。每組中的第乙個區中的前幾頁,自然就負責記錄該組中關於各個區的一些關鍵資訊。
這樣,對於頁面的管理就具有了層次,不會混亂。但是這樣就好了嗎?那肯定不是的,上文說innodb 要極致的提公升效能,光這樣規定下層次有什麼用呢。
所以innodb又做了如下幾個處理:
每個區中頁面在磁碟上都是連續的。連續意味著一定場景下減少磁碟的隨機i/o。
但是連續性如何保證?這就依靠作業系統的管理。innodb可以一次申請這麼多頁面大小的空間,那自然就是連續的。
由於每棵 b+ 樹只有葉子節點頁面中儲存著資料,而非葉子節點的目的就是為了找到對應的葉子節點。如果這兩種型別的頁面放在一起,比如是aaaabbaabbaaaa的頁面排列形式,則同樣不利於查詢。
針對這點,innodb又引出了乙個段
的概念。每建立乙個索引(即一棵b+樹),都會在表空間中生成兩個段:索引段和資料段。並且規定,段是以區為單位進行分配,即乙個段可以包括好幾個區。所以段
的出現主要是解決這個效能的。
衡量乙個演算法的效能是從兩個方面:時間和空間。對應innodb同樣是,因為他也可以看做是乙個大的演算法。所以對於空間上的優化,innodb還引入了一種區
,就是碎片區
。有什麼好處呢?
在第2點中講到了段,每個段下面的區,這些區裡面的頁面都是這個段對應索引的葉子節點或者非葉子節點。不會和其他索引的段下區混在一起。但是碎片區就允許,不論是哪個段的頁面,都可以存放在碎片區中。
這樣,乙個大致的流程就是:建立好錶空間,此時出現了兩個段(主鍵索引),插入一條資料。那麼資料會儲存到資料頁中,而此資料頁就是從碎片區拿過來的。繼續插入資料,這個段已經在碎片區中佔了32個頁後,就會申請完整的區繼續儲存。
如果沒有碎片區的話,那麼初始插入一條資料就會直接申請乙個區的空間(每個段乙個),則直接占用2m空間,有些表根本用不了這麼多空間。
實際上,乙個區既在某個組內,同時又可能在某個段中。
這種層次一劃分,很好地提公升了效能。但是還引出了其他的效能問題,那就是這些區如何快速尋找?
比如乙個表空間大小10g,則區就有1萬個。這些區中有的區已經滿了,有的區還有空間。則新插入資料時,如何找到合適的區插入,難道乙個個遍歷過去嗎?
當然不是,看頁結構時,裡面就有各種鍊錶。實際上表空間中也是由各種鍊錶將區維護起來,比如碎片區鍊錶或者滿空間區鍊錶等。
針對每個區而言,都處於四種狀態之一:
表空間中的鍊錶有兩個角度,乙個是站在整個表空間層面看,有三條鍊錶串聯起來所有的區,即:
可以明顯地看到,三條鍊錶中的區沒有第四種狀態,所以另乙個角度是站在某乙個段的層面去看,也有三條鍊錶,即:
所以,乙個區會在不同層面被分到不同的鍊錶中。
對應的,每個區的屬性結構(結構體、物件描述)又叫做:xdes entry
,每個段的屬性結構叫做inode entry
。而上面的6條鍊錶,其節點都是 xdes entry。
上面提到的鍊錶,必須有能夠找到煉表頭節點的節點,所以在 inode entry 中儲存了它的三條鍊錶的 base節點。
對於整個表空間來說,表空間獨有的資訊當然是儲存在第乙個區中的,也就是 extent0 區中。同時,extent0 區也是表空間第乙個組的第乙個區,所以也要記錄組獨有的資訊。其他組中的第乙個區,就不需要記錄表空間的獨有資訊了。
對於上面站在表空間層面的三條鍊錶,他們的base節點就儲存在extent0中。當然具體是儲存在extent0中的某個頁面上了(第乙個頁)。
xdes entry
有專門的頁來儲存,頁型別即為xdes
,我們前面已經看過頁型別為資料頁
的。不同型別的頁結構當然是類似的。所以同樣會有頁之間的鍊錶存在。
inode entry
的頁型別為inode
,同樣inode
頁之間會有鍊錶存在。
那麼對於系統表空間 system tablespace 來說呢?是不是還和普通表空間一樣呢?
當然是,結構當然是一樣的。只不過系統表空間的一些區被用來做更特殊的用途,同時儲存全域性的(所有表空間共享的)一些資訊。
其中一些資訊關鍵字,我們已經在innodb的基本結構中見過了,即:資料字典、雙寫緩衝、change buffer、undo logs等。
關於表空間就到這裡,我們不再像頁結構那樣,去看比如 xdes entry 中有哪些屬性等等。因為表空間整體下來,各種屬性太多了,沒必要看也沒必要記。只要把邏輯理順,知道表空間中的各種重要元素就行了。後續學習其他鎖、事務的時候,還是會遇到一些屬性的,到時候說到表空間只要有巨集觀映像就行了。
最後,本篇沒有畫圖,兩個原因:主要講邏輯,圖沒多大用;屬性太多,畫圖和**表示也不行,意義不大。想看圖的網上隨便搜都有的,還能順便加深印象。
mysql引擎之MyISAM與InnoDB
在mysql中,支援幾種引擎,其中包括myisam與innodb,兩者皆採用b tree的資料結構,樹 鍊錶 myisam 索引和資料是分開的,也叫非聚集索引,不管是以自增id作為索引還是以其他作為索引,最下層的葉子節點存放的是乙個實體地址,通過這個實體地址找到需要的資料 索引和資料是分開的,也叫聚...
MYSQL資料庫引擎,ISAM和INNODB
其餘都屬於第二類,稱為 非事務安全型 non transaction safe 1 isam isam是乙個定義明確且歷經時間考驗的資料 管理方法,它在設計之時就考慮到資料庫被查詢的次數要遠大於更新的次數。因此,isam執行讀取操作的速度很快,而且不占用大量的記憶體和儲存資源。isam的兩個主要不足...
mysql修改資料庫的儲存引擎 InnoDB
檢視當前的儲存引擎 基本的差別 myisam型別不支援事務處理等高階處理,而innodb型別支援。myisam型別的表強調的是效能,其執行數度比innodb型別更快,但是不提供事務支援,而innodb提供事務支援以及外部鍵等高階資料庫功能。然後,一般我們的專案中設計的資料表是有外來鍵的.修改儲存引擎...