久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

InnoDB中怎么插入數(shù)據(jù)

共計(jì) 10141 個(gè)字符,預(yù)計(jì)需要花費(fèi) 26 分鐘才能閱讀完成。

自動(dòng)寫(xiě)代碼機(jī)器人,免費(fèi)開(kāi)通

本篇文章給大家分享的是有關(guān) InnoDB 中怎么插入數(shù)據(jù),丸趣 TV 小編覺(jué)得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說(shuō),跟著丸趣 TV 小編一起來(lái)看看吧。

表空間 /Tablespace

假如,我想成為一名文學(xué)家,立志寫(xiě)一部長(zhǎng)篇巨著,那么就需要把文字記錄在紙張上。第一步就是從造紙廠購(gòu)買(mǎi)兩大卷未做裁切的白紙。相應(yīng)的,在計(jì)算機(jī)中,所有數(shù)據(jù)也需要記錄在磁盤(pán)、磁帶、光盤(pán)等存儲(chǔ)介質(zhì)上進(jìn)行長(zhǎng)期保存。

這些介質(zhì)被劃分成文件,它們是存儲(chǔ)數(shù)據(jù)的物理空間。

由于我買(mǎi)了兩卷紙,而任何一卷都可以存儲(chǔ)文字,因此每當(dāng)我開(kāi)始下筆時(shí),都費(fèi)勁心思難以抉擇:到底應(yīng)該記錄到哪一卷中? 這對(duì)于有選擇困難癥的我來(lái)說(shuō)苦不堪言。

于是,我計(jì)劃請(qǐng)一個(gè)秘書(shū),把要寫(xiě)的內(nèi)容口述給他,通過(guò)他幫我文字謄寫(xiě)到具體的紙卷上,至于到底寫(xiě)在哪一卷上,我無(wú)所謂。

同理,用程序操作文件時(shí),首先也需要指定文件路徑。可是在數(shù)據(jù)庫(kù)中,表是面向開(kāi)發(fā),而存儲(chǔ)設(shè)備是面向運(yùn)維。開(kāi)發(fā)創(chuàng)建表時(shí),很難確定一張表對(duì)應(yīng)哪個(gè)文件。而運(yùn)維也會(huì)根據(jù)實(shí)際情況動(dòng)態(tài)為數(shù)據(jù)庫(kù)添加文件。

表與文件的緊耦合嚴(yán)重制約了數(shù)據(jù)庫(kù)使用的便利性,于是在文件與表之間增加一層表空間便順理成章,它向上對(duì)接表,向下對(duì)接文件; 開(kāi)發(fā)者只需在表空間中操作表,而具體存儲(chǔ)由 Innodb 存儲(chǔ)引擎根據(jù)表空間自動(dòng)維護(hù)。

InnoDB 中怎么插入數(shù)據(jù)

表空間是 InnoDB 存儲(chǔ)引擎中邏輯結(jié)構(gòu)的最高層,所有數(shù)據(jù)邏輯上都存儲(chǔ)在表空間中。

表空間主要包括以下幾種類(lèi)型:

系統(tǒng)表空間 存儲(chǔ) change buffer, doublewrite  buffer 以及與 innodb 相關(guān)的所有對(duì)象的元數(shù)據(jù)。如:表空間和數(shù)據(jù)庫(kù)信息,表結(jié)構(gòu)與字段信息等等。mysql8.0 中移除了原先用于存儲(chǔ)表結(jié)構(gòu)信息的.frm 文件,所有元數(shù)據(jù)都存儲(chǔ)在此系統(tǒng)表空間中。系統(tǒng)表空間 information_schema 庫(kù)中相關(guān)的核心視圖如下:

InnoDB 中怎么插入數(shù)據(jù)

假如數(shù)據(jù)庫(kù) world 中有一張對(duì)應(yīng)表 user 表,測(cè)試如下:查詢表所屬表空間信息:select * from  information_schema.innodb_tablespace where name= world/user  (space: 表空間 id,name:表空間名)

InnoDB 中怎么插入數(shù)據(jù)

查詢表空間對(duì)應(yīng)的數(shù)據(jù)文件信息:select * from information_schema.files where  tablespace_name= world/user (file_name:數(shù)據(jù)文件相對(duì)路徑)

InnoDB 中怎么插入數(shù)據(jù)

查詢表對(duì)應(yīng)的 id: select * from information_schema.innodb_tables where  name= world/user

InnoDB 中怎么插入數(shù)據(jù)

查詢主鍵索引對(duì)應(yīng)的根節(jié)點(diǎn)所在的頁(yè)號(hào)(root page no) select * from  information_schema.innodb_indexes where table_id=1269 and name= primary  (page_no:B+ 樹(shù) root page no;name= primary 表示主鍵索引)

InnoDB 中怎么插入數(shù)據(jù)

系統(tǒng)表空間也有對(duì)應(yīng)的數(shù)據(jù)文件,這個(gè)文件默認(rèn)為(windows 下)xxx\MySQL Server  8.0\Data\ibdata1。只有系統(tǒng)表空間可以指定多個(gè)文件,其它類(lèi)型的表空間都只能指定一個(gè)數(shù)據(jù)文件。

獨(dú)立表空間   每張表對(duì)應(yīng)一個(gè)獨(dú)立的表空間。通過(guò)配置 my.ini 中的參數(shù):innodb_file_per_table= 1 啟動(dòng)獨(dú)立表空間,否則,默認(rèn)為系統(tǒng)表空間。5.6.6 之后此配置默認(rèn)開(kāi)啟,因此默認(rèn)為獨(dú)立表空間。

InnoDB 中怎么插入數(shù)據(jù)

當(dāng)創(chuàng)建表時(shí),會(huì)自動(dòng)為表創(chuàng)建一個(gè)對(duì)應(yīng)表名的表空間,并在數(shù)據(jù)庫(kù)目錄下生成一個(gè)“表名.ibd”的表空間文件。如:在數(shù)據(jù)庫(kù) world 中創(chuàng)建 user 表結(jié)果如下

InnoDB 中怎么插入數(shù)據(jù)

普通表空間 即通過(guò)“create tablespace 表空間名”手動(dòng)創(chuàng)建的表空間。

臨時(shí)表空間 存儲(chǔ)臨時(shí)表以及臨時(shí)表變化對(duì)應(yīng)的回滾段。默認(rèn)的臨時(shí)文件為(windows 下)xxx\MySQL Server  8.0\Data\ibtmp1

區(qū) / 簇 /Extent

由于一卷原始的紙?zhí)^(guò)于龐大,展開(kāi)后可能會(huì)鋪滿我豪宅地板十幾層,甚至幾十層,非常不方便使用,畢竟我 9 平米的豪宅還需要留出空間會(huì)客。最好的辦法就是把這些紙張切割成一張張 A4 大小的數(shù)據(jù)頁(yè)。

同理,一個(gè)磁盤(pán)或文件的容量也是非常可觀,極其不便管理,因此 innodb 把文件劃分成一個(gè)個(gè)大小相等的存儲(chǔ)塊,這些塊也被稱為頁(yè);

InnoDB 中怎么插入數(shù)據(jù)

對(duì)于一部文學(xué)故事而言,只要通過(guò)頁(yè)碼就可以依次找到下一頁(yè),從而完整的讀完這個(gè)故事。通常我們讀完第一頁(yè)時(shí),會(huì)馬上接著讀第二頁(yè),但此時(shí)對(duì)應(yīng)的書(shū)頁(yè)如果零散的分布在臥室、廁所、客廳,將使閱讀體驗(yàn)大大折扣。如果能把這些分散的書(shū)頁(yè)合訂成本,就可以極大地提高閱讀的便利性。

根據(jù)局部性原理,cpu 在使用的數(shù)據(jù)時(shí),下一步也會(huì)大概率使用邏輯上相鄰的數(shù)據(jù)。因此為了提高數(shù)據(jù)讀操作的性能,innodb 把邏輯上相臨的數(shù)據(jù)盡可能在物理上也存儲(chǔ)在相鄰的頁(yè)中; 為了實(shí)現(xiàn)這一目標(biāo),Innodb 引入了區(qū) / 簇的概念;

InnoDB 中怎么插入數(shù)據(jù)

一個(gè)區(qū) / 簇是物理上連續(xù)分配的一段空間,extent 又被劃分成連續(xù)的頁(yè),以存儲(chǔ)同一邏輯單元的數(shù)據(jù) (如下面的索引段、數(shù)據(jù)段)。一個(gè)區(qū) / 簇,默認(rèn)由 64 個(gè)連續(xù)的頁(yè)(Page) 組成,每個(gè)頁(yè)默認(rèn)大小為 16K。

實(shí)際上,innodb 是先把文件劃分成連續(xù)的區(qū) / 簇,然后在區(qū) / 簇內(nèi)再劃分出連續(xù)的頁(yè),從總體上看:一個(gè)文件即是微觀上一系列連續(xù)的頁(yè)組成,也是宏觀上一系列連續(xù)的區(qū) / 簇組成。知道一個(gè)頁(yè)的頁(yè)號(hào)和頁(yè)大小就可以計(jì)算出此頁(yè)在磁盤(pán)上的具體位置,同理知道一個(gè)頁(yè)號(hào)就可以計(jì)算出一個(gè)區(qū) / 簇的大小以及頁(yè)所在的區(qū) / 簇是第幾個(gè)區(qū) / 簇(它本身沒(méi)有編號(hào),但假設(shè)第一個(gè)區(qū) / 簇為 0 號(hào),可以知道它邏輯上是第幾個(gè))。

如果把頁(yè)看作現(xiàn)實(shí)書(shū)本中的頁(yè),那么 extent 可以看作現(xiàn)實(shí)中的書(shū)本。

區(qū)的目的是為邏輯單元分配連續(xù)的空間,同時(shí)也用于管理區(qū)內(nèi)的存儲(chǔ)空間狀態(tài)(如:區(qū)內(nèi)哪些頁(yè)已滿,哪些還未使用,哪些包含碎片)。具體通過(guò)不同的區(qū) / 簇鏈表來(lái)指明區(qū)本身的空間狀態(tài),以及通過(guò) XDES  Entry 中的 XDES_BITMAP 指明區(qū)內(nèi)頁(yè)的空間狀態(tài))。

### 段 /Segment

當(dāng)年大劉寫(xiě)完三體第一本后,遲遲沒(méi)有更新,但由于內(nèi)容過(guò)于精彩,導(dǎo)致奧巴馬又是寫(xiě)郵件,又是通過(guò)外交手段催更。為了避免中美關(guān)系受損,大劉如法炮制,又連續(xù)寫(xiě)了兩本。

在邏輯上故事情連貫的這三本書(shū)總體上都叫三體,于是我們稱這種具有相關(guān)性的多本書(shū)為一套。同理,innodb 把邏輯上有關(guān)聯(lián)的區(qū) / 簇歸屬為一個(gè)段。

InnoDB 中怎么插入數(shù)據(jù)

為了使同一邏輯單元可以在物理上具有連續(xù)的存儲(chǔ)空間,Innodb 提出的區(qū)的概念,但是 io 的最小操作單元為頁(yè),一次 io 并不能寫(xiě)滿一個(gè)區(qū),同時(shí)數(shù)據(jù)是可以擦除 (刪除) 重寫(xiě),因此必須記錄區(qū)自身以及區(qū)內(nèi)的空間狀態(tài):哪些區(qū)已寫(xiě)滿,哪些區(qū)還未使用,哪些區(qū)還有碎片空間。

innodb 中把這些記錄具有相關(guān)性區(qū)的存儲(chǔ)空間狀態(tài)的管理信息稱為段實(shí)體,段實(shí)體所管理的區(qū)的總和稱為段。段的目的是管理區(qū)的使用情況以及為數(shù)據(jù)分配空間時(shí),提供空間存儲(chǔ)狀態(tài)。

段可以類(lèi)似的看做現(xiàn)實(shí)中一套書(shū)中的套。

innodb 中數(shù)據(jù)是以 B + 樹(shù)的方式組織,葉子節(jié)點(diǎn)存儲(chǔ)關(guān)鍵字與行數(shù)據(jù),非葉子節(jié)點(diǎn)存儲(chǔ)關(guān)鍵字 (索引數(shù)據(jù)) 與頁(yè)號(hào)。索引數(shù)據(jù)與業(yè)務(wù)行數(shù)據(jù)分別具有不同的數(shù)據(jù)結(jié)構(gòu),因此它們被分開(kāi)存儲(chǔ),非葉子節(jié)點(diǎn)的索引數(shù)據(jù)存儲(chǔ)在一個(gè)段中,葉子節(jié)點(diǎn)的業(yè)務(wù)數(shù)據(jù)存儲(chǔ)在另一個(gè)段,對(duì)應(yīng)的它們也分別存儲(chǔ)在不同結(jié)構(gòu)的區(qū)和頁(yè)中。

數(shù)據(jù)邏輯結(jié)構(gòu)如下:

InnoDB 中怎么插入數(shù)據(jù)

物理存儲(chǔ)結(jié)構(gòu)如下:

InnoDB 中怎么插入數(shù)據(jù)

段是表空間的邏輯組成部分,用來(lái)存儲(chǔ)具有相同意義的數(shù)據(jù),如:B+ 對(duì)中的非葉子節(jié)點(diǎn)或 B + 樹(shù)中的葉子節(jié)點(diǎn)。常見(jiàn)的段有數(shù)據(jù)段、索引段、回滾段等。

每創(chuàng)建一個(gè)索引就會(huì)創(chuàng)建兩個(gè)段: 一個(gè)是數(shù)據(jù)段 (B+ 樹(shù)對(duì)應(yīng)的葉子節(jié)點(diǎn)),一個(gè)是索引段(非葉子節(jié)點(diǎn))。對(duì)于聚集索引(一般是主鍵索引) 數(shù)據(jù)段存儲(chǔ)的是索引關(guān)鍵字和業(yè)務(wù)行(所有字段); 對(duì)于非聚集索引,數(shù)據(jù)段存儲(chǔ)的是索引關(guān)鍵字和主鍵; 如果通過(guò)非聚集索引查詢,需要先通過(guò) B + 樹(shù)查出主鍵,再通過(guò)主鍵從聚集索引中二次查詢具體的行, 這稱為回表。下圖:左邊為二級(jí)索引(非聚集索引),右邊為主鍵索引(聚集索引)

InnoDB 中怎么插入數(shù)據(jù)

表數(shù)據(jù)是通過(guò)聚集索引組織存儲(chǔ),也即按主鍵索引創(chuàng)建的 B + 樹(shù)存儲(chǔ)數(shù)據(jù),因此創(chuàng)建表時(shí)應(yīng)該同時(shí)指定一個(gè)主鍵。如果沒(méi)有指定主鍵,也沒(méi)有創(chuàng)建唯一索引,表會(huì)默認(rèn)創(chuàng)建一個(gè)自增的隱藏字段:row_id 做為聚集索引 B + 樹(shù)的關(guān)鍵字段。因?yàn)槭请[藏字段,所以這個(gè)字段只能回表查詢時(shí)使用。

頁(yè) /Page

正如上面所說(shuō),頁(yè)就像現(xiàn)實(shí)中一本書(shū)的書(shū)頁(yè)一樣,是 innodb 中 io 操作的最小單位。innodb 中的頁(yè)類(lèi)似于現(xiàn)實(shí)中書(shū)本的頁(yè)。

頁(yè)的大小默認(rèn)是 16KB; 可以通過(guò) innodb_page_size 參數(shù)指定,可選項(xiàng)為:4KB、8KB、16KB、32KB、64KB; 當(dāng) page  size 為 4、8、16KB 時(shí),對(duì)應(yīng)一個(gè) extent 的 page 數(shù)量同步變化,以保證 extent(區(qū) / 簇)大小保持 1M 不變。當(dāng) page  size 為 32KB 或 64KB 時(shí),extent 內(nèi)的 page 數(shù)量保證不變,extent 同步變?yōu)?2M 和 4M;

InnoDB 中怎么插入數(shù)據(jù)

每個(gè)頁(yè)都有一個(gè)對(duì)應(yīng)的從 0 開(kāi)始的編號(hào),這個(gè)編號(hào)叫做頁(yè)號(hào)。因?yàn)楸砜臻g的數(shù)據(jù)文件會(huì)被劃分成大小相等的頁(yè),所以知道頁(yè)號(hào),再根據(jù)文件的初始位置,就可以計(jì)算出頁(yè)在磁盤(pán)中的準(zhǔn)確地址。

同理,一張表對(duì)應(yīng)一個(gè)聚集索引,而聚集索引元數(shù)據(jù)中指定了 root page 的頁(yè)號(hào),因此 Innodb 引擎可以根據(jù)頁(yè)號(hào)和頁(yè)大小計(jì)算出索引 B + 樹(shù) root  page 的準(zhǔn)確地址,從而對(duì)整個(gè)表數(shù)據(jù)進(jìn)行操作。

page 主要用來(lái)存儲(chǔ)業(yè)務(wù)相關(guān)的數(shù)據(jù),但是為了管理內(nèi)存分配而存在的 extent 和 segment 信息也需要 page 存儲(chǔ)。innodb 根據(jù) page 存儲(chǔ)內(nèi)容不同分以下幾類(lèi):

FSP HDR   頁(yè):一個(gè)表空間可能對(duì)應(yīng)多個(gè)數(shù)據(jù)文件,每個(gè)文件都有自己的編號(hào)。表空間是數(shù)據(jù)庫(kù)中最頂層的結(jié)構(gòu),通過(guò)系統(tǒng)表空間中的元數(shù)據(jù)可以查詢對(duì)應(yīng)的表空間文件等元信息,卻無(wú)法查詢當(dāng)前表空間對(duì)應(yīng)的段、區(qū)等信息,因此也無(wú)法獲取表空間中頁(yè)的存儲(chǔ)狀態(tài)。

為了使表空間的物理存儲(chǔ)有一個(gè)對(duì)外訪問(wèn)的入口,規(guī)定表空間中的 0 號(hào)文件的 0 號(hào) page 頁(yè)中存儲(chǔ)表空間信息以及當(dāng)前表空間所擁有的段鏈表的指針。

任何一個(gè)頁(yè)都由頁(yè)頭、頁(yè)身和頁(yè)尾組成。

一個(gè) page 默認(rèn) 16KB,而段和區(qū)對(duì)應(yīng)的指針數(shù)據(jù)量并不大,因此只需要部分頭信息就可以維護(hù)。而剩下的大部分空間,則用來(lái)存儲(chǔ)當(dāng)前表空間擁有的部分發(fā)區(qū)實(shí)體信息。

InnoDB 中怎么插入數(shù)據(jù)

頁(yè)頭:指明當(dāng)前頁(yè)號(hào)、類(lèi)型和所屬表空間。頁(yè)尾:主要用于數(shù)據(jù)的校驗(yàn)。頁(yè)身:這是頁(yè)中用來(lái)存儲(chǔ)數(shù)據(jù)的主要部分。

頁(yè)身又分為表空間首頁(yè)頭信息區(qū)和業(yè)務(wù)數(shù)據(jù)區(qū)。FSP HEADER:(1):表空間信息:對(duì)應(yīng)空間 id、表空間總頁(yè)數(shù)等  (2):段信息:已寫(xiě)滿數(shù)據(jù)的段實(shí)體所在頁(yè)的鏈表指針、未寫(xiě)滿數(shù)據(jù)的段實(shí)體所在頁(yè)的鏈表指針 (指向的不是段實(shí)體而是段實(shí)體所在的頁(yè),一頁(yè)存儲(chǔ) 85 個(gè)段實(shí)體)。(3):碎片區(qū) / 簇信息:空閑的碎片區(qū) / 簇(XDES 實(shí)體本身,不是 XEDS 實(shí)體所在的頁(yè)) 鏈表指針、未寫(xiě)滿的碎片區(qū)鏈表指針、已寫(xiě)滿的碎片區(qū)鏈表。這些區(qū) / 簇信息不屬于任何段,而屬于表空間,用于給段下次申請(qǐng)空間時(shí)分配。

理論上一個(gè)區(qū) / 簇會(huì)完整的分配給一個(gè)段,但一些區(qū) / 簇創(chuàng)建后直接歸屬表空間,用做碎片區(qū)。為了減少浪費(fèi),只會(huì)把這些區(qū)中的部分頁(yè)分配給一個(gè)指定的段。

例如:當(dāng)你豪言萬(wàn)丈的宣布要寫(xiě)一部曠世巨著,并要求秘書(shū)給你五百頁(yè)紙時(shí),秘書(shū)很可能已經(jīng)看透了一切,一面是是是的回應(yīng)你,一面只會(huì)給你取 3 頁(yè)紙,因?yàn)樗J(rèn)為你很可能 7 天憋不出 6 個(gè)字。同理,innodb 給某一個(gè)新創(chuàng)建的段分配空間時(shí),并不是一開(kāi)始就分配一個(gè)區(qū) / 簇,而是從碎片區(qū)中先分配 32 頁(yè),只有這 32 頁(yè)使用完,innodb 才認(rèn)為這個(gè)段是一個(gè)大數(shù)據(jù)段,從而正式開(kāi)始為其分配一個(gè)完整的區(qū) / 簇。

數(shù)據(jù)部分:

FSP HEADER 中指向了段鏈表和碎片區(qū)鏈表,但這些只是鏈表指針,真正的區(qū)信息節(jié)點(diǎn)則存放在當(dāng)前頁(yè)的數(shù)據(jù)區(qū)。一個(gè)區(qū) / 簇信息實(shí)體稱為一個(gè) XDES  Entry(eXtent DEScript); 一頁(yè)存儲(chǔ) 256 個(gè) XDES Entry。

XDES  Entry 如上面圖示,包含了段 id(如果分配給一個(gè)段)、碎片區(qū)鏈表中的下一個(gè)節(jié)點(diǎn)指針等。它不包含頁(yè)信息,因?yàn)閰^(qū) / 簇有對(duì)應(yīng)的物理空間,它空間內(nèi)的頁(yè)就是擁有的頁(yè),因此無(wú)需在 entry 中指明。

細(xì)心的朋友會(huì)發(fā)現(xiàn),XDES Entry 雖然是描述區(qū) / 簇,但卻沒(méi)有指定區(qū) / 簇的編號(hào)或地址,那么它到底對(duì)應(yīng)物理空間中哪塊區(qū) / 簇呢?

區(qū) / 簇本身沒(méi)有編號(hào),但區(qū) / 簇像頁(yè)一樣,也是從文件第一個(gè)字節(jié)開(kāi)始連續(xù)分配的。同時(shí),每隔 256 個(gè)區(qū) / 簇的第一個(gè)區(qū)的第一頁(yè)就是這 256 個(gè)區(qū) / 簇的索引頁(yè),即 XDES  page。

而 XDES page 有 page No,因此就可以計(jì)算出此 XDES  page 的地址,也即此 page 所有的區(qū) / 簇的地址。緊接著的 255 個(gè)區(qū) / 簇都有一個(gè)對(duì)應(yīng)的 XDES Entry 存儲(chǔ)在 XDES page 中,這些 XDES  Entry 在此 page 中位置的偏移量,即為后面 255 個(gè)區(qū) / 簇的偏移量,從當(dāng)前 XDES page 所有區(qū) / 簇位置以及對(duì)應(yīng)的偏移量就可以計(jì)算出一個(gè) XDES  Entry 對(duì)應(yīng)的區(qū) / 簇的物理位置。

FSP HDR 頁(yè)就像一個(gè)表空間的封面頁(yè),是整個(gè)表空間的入口頁(yè)。

XDES 頁(yè):XDES 頁(yè)即 eXtent DEScript 區(qū) / 簇描述頁(yè)的縮寫(xiě),用來(lái)存儲(chǔ)區(qū) / 簇信息實(shí)體的頁(yè),即存儲(chǔ) XDES  Entry 的頁(yè)。它除了與 FSP 頁(yè)中 FSP  HEADER 不同外,其它內(nèi)容一模一樣。本質(zhì)上首頁(yè)也是一個(gè) XDES 頁(yè),只是首頁(yè)是整個(gè)表空間的第一頁(yè),因此它又兼職記錄了表空間信息。

XDES Entry:存儲(chǔ)了區(qū)自身信息的邏輯塊。

因?yàn)橐豁?yè) XDES 只能存儲(chǔ) 256 個(gè) entry,對(duì)應(yīng) 256 個(gè)區(qū),因此邏輯上每隔 256 個(gè)區(qū),就需要一個(gè) xdex 頁(yè)來(lái)存儲(chǔ)下一系列 256 個(gè)區(qū)的信息。

INODE 頁(yè):同區(qū) / 簇對(duì)應(yīng)的 Entry 信息一樣,表空間只是指向了各種狀態(tài)的段頁(yè) (非段實(shí)體) 鏈表,而未存儲(chǔ)段信息本身。inode 頁(yè)就是用來(lái)存儲(chǔ)描述段信息  inode entry 的頁(yè)。

InnoDB 中怎么插入數(shù)據(jù)

一個(gè) inode 頁(yè)默認(rèn)存儲(chǔ) 85 條段實(shí)體,每個(gè)實(shí)體又指向了本段對(duì)應(yīng)的不同狀態(tài)的區(qū) / 簇鏈表:未使用的區(qū) / 簇鏈表、已寫(xiě)滿的區(qū) / 簇鏈表、未寫(xiě)滿的區(qū) / 簇鏈表。

Index 頁(yè)   以上的頁(yè)均是存儲(chǔ)物理空間使用狀態(tài),并用于管理區(qū) / 簇和段本身的頁(yè)。index 頁(yè)則是用于最終存儲(chǔ)業(yè)務(wù)數(shù)據(jù)。innodb 中表數(shù)據(jù)是通過(guò)聚集索引組織存儲(chǔ)的,而葉子節(jié)點(diǎn)存儲(chǔ)在一個(gè)段中,非葉子節(jié)點(diǎn)存儲(chǔ)在另一個(gè)段中,但最終都會(huì)存儲(chǔ)在 Index 類(lèi)型的頁(yè)中。

index 頁(yè)詳細(xì)項(xiàng)如下圖:

InnoDB 中怎么插入數(shù)據(jù)

index 頁(yè)頁(yè)內(nèi)存儲(chǔ)結(jié)構(gòu)如下圖:

InnoDB 中怎么插入數(shù)據(jù)

頁(yè)內(nèi)的業(yè)務(wù)數(shù)據(jù)是一個(gè)邏輯上按順序排列的單向鏈表。頁(yè)內(nèi)有兩條虛擬行,會(huì)別代表整個(gè)頁(yè)中索引值最小的行和最大的行,即鏈表中第一行和最后一行,用來(lái)界定鏈表的范圍。

另外,對(duì)于索引段,一頁(yè)大概有 16250B 用來(lái)存儲(chǔ)用戶數(shù)據(jù)。一行包含一個(gè) 4 字節(jié)的 int 類(lèi)型 key,一個(gè)指向葉子節(jié)點(diǎn)占 6 字節(jié)的頁(yè)號(hào),大概 6 字節(jié)的 row  header,總共大概 16 字節(jié)。那么一頁(yè)粗略的計(jì)算可以存儲(chǔ) 16250/16 約為 1000 條。為了優(yōu)化查詢,每隔 4 - 8 行數(shù)據(jù)把這幾行數(shù)據(jù)的第一行地址在存放在一個(gè)稱為 slot 的 2 字節(jié)空間中,這些 slot 一起組成一個(gè)稱為 Page  directory 的數(shù)組中。

如圖:數(shù)組最后一個(gè) slot 存儲(chǔ)第一行 infimum,倒數(shù)據(jù)第二個(gè) slot 存儲(chǔ) row4,正序第一個(gè) slot 存儲(chǔ)最后一行數(shù)據(jù) supremum。這樣 page  directory 數(shù)組就是一個(gè)有序的數(shù)組,可以通過(guò)一次二分查找算法快速定位數(shù)據(jù)塊,然后在這個(gè)塊中遍歷找到最終符合要求的數(shù)據(jù)。

注意:由于用戶行與頁(yè)尾之間有空閑空間,而 slot 個(gè)數(shù)受頁(yè)內(nèi)行數(shù)影響而不固定,即 page  dirctory 數(shù)組長(zhǎng)度不固定,因此通過(guò)逆序向前追加的方式分配 slot。

整體結(jié)構(gòu)

以上是表空間中不同對(duì)象各自的結(jié)構(gòu)和數(shù)據(jù)信息,下面從整體的角度看一看各個(gè)組件是如何關(guān)聯(lián)的。

InnoDB 中怎么插入數(shù)據(jù)

微觀上,表空間文件從物理上分隔為大小相等且連續(xù)的頁(yè)。

宏觀上,表空間文件從物理上分隔為大水相乘且連續(xù)的區(qū) / 簇。

0 號(hào)文件的 0 號(hào)頁(yè)稱為 FSP 頁(yè),即首頁(yè),可以假定為表空間的封面頁(yè)。它存儲(chǔ)了整個(gè)表空間其它組件的鏈表指針,是整個(gè)表空間的入口頁(yè)。

從邏輯上,F(xiàn)SP 頁(yè)通過(guò)兩條線指向不同組件。(1):通過(guò) FSP_SEG_INODES_FULL(已寫(xiě)滿的段頁(yè)鏈表)和 FSP_SEG_INODES_FREE(未寫(xiě)滿的段頁(yè)鏈表),指向段信息。段實(shí)體又通過(guò) FSEG_FREE(空閑的區(qū) / 簇鏈表)、FSEG_FULL(寫(xiě)滿的區(qū) / 簇)、FSEG_NOT_FULL(未寫(xiě)滿的區(qū) / 簇),指向?qū)儆诒径蔚膮^(qū) / 簇。(2):通過(guò) FSP_FREE(空閑的區(qū) / 簇鏈表)、FSP_FREE_FRAG(未寫(xiě)滿的碎片區(qū) / 簇)、FSP_FULL_FRAG(已寫(xiě)滿的碎片區(qū) / 簇),指向不屬于任何段的區(qū) / 簇。

每 256 個(gè)區(qū) / 簇的第一個(gè)區(qū) / 簇的第一頁(yè)存儲(chǔ)這 256 個(gè)區(qū) / 簇的管理信息。0 號(hào)頁(yè)因?yàn)樘厥饨凶?FSP 頁(yè),其它叫做 XDES 頁(yè)。通過(guò)這個(gè)頁(yè)號(hào)以及存儲(chǔ)在其中的 Entry 位置偏移量,可以很容易的計(jì)算出這 256 個(gè)區(qū)在磁盤(pán)上的位置。因此即使 XDES  Entry 中沒(méi)有記錄區(qū) / 簇的編號(hào)或地址,也可以知道每個(gè) Entry 管理的是哪個(gè)區(qū) / 簇。

當(dāng) index 頁(yè)中插入一條數(shù)據(jù)時(shí),如果本頁(yè)已滿,則需要向此頁(yè)所在的區(qū) / 簇申請(qǐng)空間,如果此區(qū) / 簇也滿了,則向所在的段申請(qǐng),如果段也滿了,則會(huì)向表空間申請(qǐng),表空間會(huì)通過(guò)操作系統(tǒng)向磁盤(pán)申請(qǐng) 3 個(gè)區(qū) / 簇,并加入到 FSP 中的 FSP_FREE 鏈表中。然后再一級(jí)級(jí)分配,存儲(chǔ)到其對(duì)應(yīng)的鏈表中。

行 /Row

以上介紹的所有對(duì)象都是為了給業(yè)務(wù)數(shù)據(jù)分配一塊用來(lái)存儲(chǔ)的物理空間,到此終于可以在指定的頁(yè)中記錄業(yè)務(wù)數(shù)據(jù)。而 innodb 是基于行進(jìn)行存儲(chǔ),下面簡(jiǎn)單的看一看行 Compact 格式的存儲(chǔ)結(jié)構(gòu)。

InnoDB 中怎么插入數(shù)據(jù)

每條記錄都包含一系列頭信息,描述當(dāng)前記錄的存儲(chǔ)狀態(tài)如圖。但是除了頭信息外,則根據(jù)記錄所在節(jié)點(diǎn)不同存儲(chǔ)的數(shù)據(jù)也有所不同。

聚集索葉子節(jié)點(diǎn),記錄存儲(chǔ)的是表中的業(yè)務(wù)行,除行數(shù)據(jù)本身外,還包含了事務(wù) id,回滾段指針,以及在沒(méi)有指定主鍵和唯一索引時(shí)還包含一個(gè)隱藏的 row_id。

非葉子節(jié)點(diǎn)針對(duì)的是 B + 樹(shù)搜索,因此記錄的是子節(jié)點(diǎn)的最小記錄值以及子節(jié)點(diǎn)的頁(yè)號(hào)。

B+ 樹(shù)節(jié)點(diǎn)與 page 的關(guān)系

Innodb  page 只是物理上的存儲(chǔ)空間,相當(dāng)于一本書(shū)的一頁(yè),僅僅是數(shù)據(jù)的載體。B+ 樹(shù)節(jié)點(diǎn)是數(shù)據(jù)的邏輯結(jié)構(gòu),理論上它們沒(méi)有必然的關(guān)系。可以在一個(gè) page 頁(yè)內(nèi)存儲(chǔ)一棵完整的 B + 樹(shù),也可以多個(gè) page 頁(yè)一起存儲(chǔ)一棵完整的 B + 樹(shù),甚至可以把 page 頁(yè)與 B + 樹(shù)中的節(jié)點(diǎn)一一對(duì)應(yīng)。

實(shí)際上 Innodb 中為了實(shí)現(xiàn)簡(jiǎn)單,B+ 樹(shù)節(jié)點(diǎn)與 page 頁(yè)是一一對(duì)應(yīng),以下是其簡(jiǎn)單的擴(kuò)展過(guò)程。

假設(shè)有一個(gè)聚集索引 B + 樹(shù)開(kāi)始的樣子如下:

InnoDB 中怎么插入數(shù)據(jù)

向 B + 樹(shù)中插入 16、17、18 三行數(shù)據(jù)如下(綠色部分):

InnoDB 中怎么插入數(shù)據(jù)

向 B + 樹(shù)繼續(xù)插入 19 一行數(shù)據(jù),原先的空間已滿擴(kuò)展如下(藍(lán)色部分):

InnoDB 中怎么插入數(shù)據(jù)

如果聚集索引使用的是自增的主鍵,那么數(shù)據(jù)是以追加的方式存儲(chǔ)在每一頁(yè)中,如果頁(yè)已經(jīng)存滿,只需要重新分配一頁(yè)空間繼續(xù)追加即可。

如果聚集索引使用的是無(wú)順序的列如 uuid,由于 B + 是一個(gè)邏輯上有序的集合,那么向 B + 樹(shù)中插入數(shù)據(jù)就很可能插入到原先已經(jīng)滿了的 page 頁(yè)中,就會(huì)導(dǎo)致原來(lái)的頁(yè)進(jìn)行分裂。會(huì)像向數(shù)組中插入數(shù)據(jù)一樣先進(jìn)行移動(dòng),為新數(shù)據(jù)騰出空間。因此建議使用有序的列做聚集索引。

InnoDB 中怎么插入數(shù)據(jù)

如何一步步存儲(chǔ)一條數(shù)據(jù)

經(jīng)歷了千辛萬(wàn)苦,終于可以從頭到尾插入一條數(shù)據(jù),一探 innodb 如何一步步把數(shù)據(jù)存儲(chǔ)到文件中。妹妹們估計(jì)已經(jīng)聽(tīng)的如癡如醉,想想都開(kāi)心,我可真是個(gè)小機(jī)靈鬼。

伸伸懶腰,甜甜的望向妹妹們。

哎,人呢? 我是穿越到平等空間了嗎?

算了,善始善終,我就講給自己聽(tīng),迷倒不了別人,我還不信迷倒不了自己。

在數(shù)據(jù)庫(kù) world 中創(chuàng)建表 user

CREATE TABLE user ( id int(11) NOT NULL AUTO_INCREMENT, name varchar(10) DEFAULT NULL, age int(11) DEFAULT NULL, gender smallint(6) DEFAULT NULL, create_time date DEFAULT NULL, PRIMARY KEY (id) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4

innodb 向系統(tǒng)表空間的 information_schema 庫(kù)的 tables 和 columns 中存入表結(jié)構(gòu)信息

InnoDB 中怎么插入數(shù)據(jù)

InnoDB 中怎么插入數(shù)據(jù)

創(chuàng)建表空間   同時(shí)創(chuàng)建獨(dú)立表空間 world/user 以及對(duì)應(yīng)的數(shù)據(jù)文件 world/user.ibd,并更新到 information_schema.innodb_tablespaces 中

InnoDB 中怎么插入數(shù)據(jù)

同步更新表空間所對(duì)應(yīng)的文件信息到 information_schema.files 中

InnoDB 中怎么插入數(shù)據(jù)

規(guī)定表空間 0 號(hào)文件即 world/user.ibd 文件的 0 號(hào)頁(yè)為表空間的封面頁(yè)。

創(chuàng)建聚集索引   如果指定的主鍵或唯一索引,則使用指定的列創(chuàng)建聚集索引,否則使用隱藏列 row_id 創(chuàng)建聚集索引,并存儲(chǔ)到 information_schema.innodb_indexes 中

InnoDB 中怎么插入數(shù)據(jù)

為索引創(chuàng)建兩個(gè)段:索引段 (非葉子節(jié)點(diǎn)) 和數(shù)據(jù)段(葉子節(jié)點(diǎn)),并把段信息存儲(chǔ)到表空間封面頁(yè)的段鏈表中。

為索引創(chuàng)建第一頁(yè)即 Root Page,把段信息記錄在 Root Page 的段鏈表中,從而管理本 B + 樹(shù)的段信息。同時(shí)把 Root  PageNo 記錄到 information_schema.innodb_indexes 中,如上圖。從頁(yè)使邏輯表與物理存儲(chǔ)關(guān)聯(lián)起來(lái),這個(gè) Root  Page 相當(dāng)于索引的封面。

插入數(shù)據(jù) 向表中插入一條數(shù)據(jù)如下

insert into world.user(name,age,gender,create_time) values(木葉瀟瀟 ,18,1,now())

從 sql 中提取數(shù)據(jù)庫(kù)名和表名,從 information_schema.innodb_tables 中查出表 id

InnoDB 中怎么插入數(shù)據(jù)

根據(jù)表 id,從 information_schema.innodb_indexes 中查出表對(duì)應(yīng)的聚集索引的 Root Page No 為 4。

InnoDB 中怎么插入數(shù)據(jù)

通過(guò) Root Page No 4 計(jì)算出 Root Page 的物理地址。根據(jù) Root Page 中指定的段信息,向 Root  Page 中插入索引數(shù)據(jù),向數(shù)據(jù)段對(duì)應(yīng)的頁(yè)中插入數(shù)據(jù)行,并關(guān)聯(lián)兩種類(lèi)型的頁(yè)。

如果一頁(yè)空間不足,會(huì)計(jì)算出當(dāng)前頁(yè)所在的區(qū) / 簇并向其申請(qǐng)空間,區(qū) / 簇則會(huì)根據(jù) XDES  Entry 中的 bitmap 查詢空閑的頁(yè)并進(jìn)行分配。如果區(qū) / 簇也沒(méi)有空閑空間,則會(huì)一級(jí)一級(jí)向上面的段、表空間、操作系統(tǒng)申請(qǐng)所需空間。

申請(qǐng)到的表空間會(huì)存儲(chǔ)在各自對(duì)應(yīng)的鏈表中(如:表空間申請(qǐng)到的空間會(huì)存儲(chǔ)在對(duì)應(yīng)的 FSP_FREE 鏈表中)。

在頁(yè)分配或擴(kuò)展時(shí),為了保證通過(guò) innodb_indexes 中的 Root Page No 能找到它,Root Page 物理空間與 B + 樹(shù)對(duì)應(yīng)的 Root   節(jié)點(diǎn)保持不變, 即頁(yè)號(hào)不變,永遠(yuǎn)是頁(yè)號(hào)為 4 的那塊空間。

當(dāng) B + 對(duì)應(yīng)的物理頁(yè)不斷變化時(shí),為了保證樹(shù)的平衡,會(huì)產(chǎn)生新的 Root 節(jié)點(diǎn),為了保持 Root 頁(yè)不變,innodb 是通過(guò)交換的方式,把新的 Root 節(jié)點(diǎn)數(shù)據(jù)復(fù)制交換到原來(lái)的 Root  Page 頁(yè),這樣就可以保證 Root Page 永遠(yuǎn)不變,即保證表與物理空間的關(guān)聯(lián)永遠(yuǎn)不會(huì)斷開(kāi)。

總結(jié)

表空間是數(shù)據(jù)庫(kù)中的邏輯結(jié)構(gòu),它解耦了表、索引等與文件的關(guān)聯(lián)。

段也是一個(gè)邏輯結(jié)構(gòu),它讓具有具體相同邏輯含義和相同存儲(chǔ)結(jié)構(gòu)的數(shù)據(jù)歸為一組,方便管理。

區(qū)是物理存儲(chǔ)結(jié)構(gòu),對(duì)應(yīng)大磁盤(pán)中真實(shí)的物理空間。它從文件第一個(gè)字節(jié)開(kāi)始按相同大小劃分,并通過(guò) XDES Entry 在邏輯上把區(qū)串聯(lián)起來(lái)。通過(guò) XDES  Entry 所在頁(yè)以及頁(yè)內(nèi)偏量可以計(jì)算出 XDES Entry 與它管理的物理空間區(qū)的關(guān)系。

頁(yè)是物理存儲(chǔ) IO 操作的最小單元。它也是從文件第一個(gè)字節(jié)開(kāi)始按相同大小劃分。表是通過(guò)索引的方式組織數(shù)據(jù),聚集索引元數(shù)據(jù)中存儲(chǔ)了此表對(duì)就的 Root page  No。頁(yè)是有編號(hào)的,通過(guò)編號(hào)就可與物理空間建立關(guān)聯(lián)。

段、區(qū)都是為了管理空間的存儲(chǔ)狀態(tài),為頁(yè)分配空間服務(wù),真正的查詢只需要通過(guò) Page  No 和 B + 樹(shù)中各級(jí)節(jié)點(diǎn)的關(guān)聯(lián)關(guān)系就可以操作整個(gè)表物理空間上的數(shù)據(jù)。

行是最終存儲(chǔ)業(yè)務(wù)數(shù)據(jù)的物理單元。默認(rèn)一頁(yè) 16K,可以存儲(chǔ)大概 1000 多行索引數(shù)據(jù)(非葉子節(jié)點(diǎn)),或者 20 行甚至更多的業(yè)務(wù)數(shù)據(jù)(葉子節(jié)點(diǎn))。頁(yè)之間通過(guò) B + 樹(shù)的“二分找查(假設(shè)為多分)”算法快速定位數(shù)據(jù),頁(yè)內(nèi)則通過(guò)  Page Directory,把多行分一組,一組對(duì)應(yīng) Page Directory 有序數(shù)組中的一個(gè) slot,這樣可以在頁(yè)內(nèi)進(jìn)行一次“二分查找”優(yōu)化。

為了記錄行本身的狀態(tài),一條記錄 innodb 會(huì)增加額外的記錄頭信息。如果是葉子節(jié)點(diǎn),還會(huì)增加:row_id(隱藏的主鍵)、trx_id(事務(wù) id)、回滾指針等附加字段。

以上就是 InnoDB 中怎么插入數(shù)據(jù),丸趣 TV 小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見(jiàn)到或用到的。希望你能通過(guò)這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注丸趣 TV 行業(yè)資訊頻道。

向 AI 問(wèn)一下細(xì)節(jié)

正文完
 
丸趣
版權(quán)聲明:本站原創(chuàng)文章,由 丸趣 2023-12-04發(fā)表,共計(jì)10141字。
轉(zhuǎn)載說(shuō)明:除特殊說(shuō)明外本站除技術(shù)相關(guān)以外文章皆由網(wǎng)絡(luò)搜集發(fā)布,轉(zhuǎn)載請(qǐng)注明出處。
評(píng)論(沒(méi)有評(píng)論)
主站蜘蛛池模板: 高淳县| 三门县| 乳山市| 宜兰县| 淳安县| 沈丘县| 安阳县| 云梦县| 兴文县| 广德县| 崇义县| 舒兰市| 香格里拉县| 宁海县| 襄垣县| 万载县| 定结县| 定边县| 杭锦后旗| 云南省| 平顺县| 永修县| 巴东县| 布拖县| 阿瓦提县| 阿城市| 富锦市| 全州县| 通山县| 资阳市| 瓮安县| 弥勒县| 广水市| 太和县| 赤峰市| 肥乡县| 贞丰县| 莱阳市| 镇巴县| 安化县| 莎车县|