首先我們在存儲真實數據的時候,按照字段里的數據值去存儲。
比如有一行數據是“jack NULL m NULL xx_school”,那么他真實存儲大致如下所示:
0x09 0x04 00000101 0000000000000000000010000000000000011001 jack m xx_school
剛開始先是他的變長字段的長度,用十六進制來存儲,然后是NULL值列表,指出了誰是NULL,接着是40個bit位的數據頭,然后是真實的數據值,就放在后面。
在讀取這個數據的時候,他會根據變長字段的長度,先讀取出來jack這個值,因為他的長度是4,就讀取4個長度的數據,jack就出來了;
然后發現第二個字段是NULL,就不用讀取了;
第三個字段是定長字段,直接讀取1個字符就可以了,就是m這個值;
第四個字段是NULL,不用讀取了;
第五個字段是變長字段長度是9,讀取出來xx_school就可以了。
但是,大家覺得真正在磁盤上存儲的時候,我們那些字符串就是直接這么存儲在磁盤上嗎?
顯然不是的! 實際上字符串這些東西都是根據數據庫指定的字符集編碼,進行編碼之后再存儲的,所以大致看起來一行數據是如下所示的:
0x09 0x04 00000101 0000000000000000000010000000000000011001 616161 636320 6262626262
我們的字符串和其他類型的數值最終都會根據字符集編碼,搞成一些數字和符號存儲在磁盤上 。
所以其實一行數據是如何存儲的,我相信大家就都已經了解的很清晰了,給大家簡單提一下,在實際存儲一行數據的時候,會在他的真實數據部分,加入一些隱藏字段,這個隱藏字段跟后續的一些內容是有關聯的。 首先有一個DB_ROW_ID字段,這就是一個行的唯一標識,是他數據庫內部給你搞的一個標識,不是你的主鍵ID字段。如果我們沒有指定主鍵和unique key唯一索引的時候,他就內部自動加一個ROW_ID作為主鍵。
接着是一個DB_TRX_ID字段,這是跟事務相關的,他是說這是哪個事務更新的數據,這是事務ID,這個后續我們講解到事務的時候會跟大家說的。
最后是DB_ROLL_PTR字段,這是回滾指針,是用來進行事務回滾的,也是我們后續在講解事務的時候再詳細說。 所以如果你加上這幾個隱藏字段之后,實際一行數據可能看起來如下所示:
0x09 0x04 00000101 0000000000000000000010000000000000011001 00000000094C(DB_ROW_ID)
00000000032D(DB_TRX_ID) EA000010078E(DB_ROL_PTR) 616161 636320 6262626262
我給上面幾個隱藏字段都加了括號說明了,上面那基本就是最終在磁盤上一行數據是長成什么樣的了。
我們再看看下面的圖,當你執行crud的時候,
先會把磁盤上的數據加載到Buffer Pool里緩存,
然后更新的時候也是更新Buffer Pool的緩存,同時維護一堆鏈表。
然后定時或者不定時的,根據flush鏈表和lru鏈表,Buffer Pool里的更新過的臟數據就會刷新到磁盤上去。
現在我們思考一下,在磁盤上的數據,每一行數據是不是就是類似“0x09 0x04 000001010000000000000000000010000000000000011001 00000000094C(DB_ROW_ID)00000000032D(DB_TRX_ID)
EA000010078E(DB_ROL_PTR) 616161 636320 6262626262”
這樣的東西?
現在我們初步的把磁盤上的數據和內存里的數據給關聯起來了,他每一行數據的真實存儲結構就了解了,屢清楚這個他們之間的關系,其實這些都是有機一體的 。