INNODB 頁節點資料的儲存方式、資料鏈、刪除鏈的學習和實驗總結
前文:
關於MYSQL INNODB index page header學習和實驗總結
http://blog.itpub.net/7728585/viewspace-2063921/
關於INNODB SYSTEM RECORD infimum和supremum的學習和實驗研究
http://blog.itpub.net/7728585/viewspace-2065464/
所用到的工具是自己寫的mysqlblock和bcview,
我放到了百度雲盤
供大家下載和使用
本文只討論COMPACT行模式
資料:
mysql> select * from km1;
+------+---------+
| id | name |
+------+---------+
| 2 | gaopeng |
| 4 | gaopeng |
| 5 | gaopeng |
| 6 | gaopeng |
| 7 | gaopeng |
| 8 | gaopeng |
+------+---------+
6 rows in set (0.04 sec)
上一篇文章已經從infimum找到了第一行資料的偏移量
為99+65=164
同時取出了第一行資料:
bcview km1.ibd 16 164 30|more
current block:00000003--Offset:00164--cnt bytes:30--data is:000001cc64260000002d0272d300000d1201108000000267616f70656e67
分解一下資料
000001cc6426 ROWID
0000002d0272 transaction id
d300000d120110 roll pointer
80000002 資料2,這裡8出現在第15位,可能為符號位
67616f70656e67 資料'gaopeng'的ascII值
那麼我們解析來介紹關於CLUSTER KEY-LEAF BLOCK的相關的部分
很顯然我這裡的表只有一個塊,因為資料很少。所以先介紹這個
,因為所謂的infimum的offset是指向的資料的開頭,而行頭資訊
記錄在offset-N的位置,N不確定看了如下就知道了
variable field lengths (1-2 bytes* var )
nullable field bitmap (1 bit * null field)
info flags (4 bits)
number of records owned (4 bits)
order (13 bits)
record type (3 bits)
next record offset (2 bytes)
offset ----cluster key fields (N bytes)
transaction id (6 bytes)
roll pointer (7 bytes)
non-key fields (M bytes)
1、variable field lengths
每個可變長度的變數型別儲存一個長度如varchar,對於固定長度的比如INT不記錄。
如果不存在可變長度的變數型別,至少佔用一個位元組為00。
2、nullable field bitmap
每個NULL值佔用一個一位(bit),如果不滿一個位元組按一個位元組算,如果不存在NULL值
至少佔用一個位元組為00。
3、info flags
這4位(4bits)標示是一個行標識,其中binary 0001表示非葉節點最小的行
其中binary 0010表示是刪除的行,而infimum和supremum行在我測試資料庫中為binary 0000
4、number of records owned
這4位(4bits)表示在本page directory(槽)中的記錄數,關於槽的概念後面詳細探討
5、order
這13位(13bits)表示記錄插入到塊中順序,INFIMUM恆等於0而SPREMUM恆等於1,而資料行的ORDER從2開始,這裡的order
我實驗得出的結論為實際物理空間的順序
6、record type
這3位(3bits)表示記錄的型別,supermum恆等於3及binary 011,infimum恆等於2及binary010,節點指標為1及001,資料行為000
7、next record offset
這2個位元組是按照CLUSTER KEY值排序的,也就是說他的順序和order沒有任何聯絡,order是插入的順序
在INFIMUM中表示的是第一個行的偏移量這個偏移量是當前記錄的位置+offset,這個offset直接指向了資料而相關的行頭在offset-n開始n為行頭的開銷。
當然supermum為的偏移量就是NULL空指標了。
8、cluster key fields
這N個位元組代表主鍵位元組數,沒有就是ROWID佔用6位元組
9、transaction id
這6個位元組為最後一次修改本行的事物ID
10、roll pointer
這7個位元組是用於支援MVCC多版本的回退指標,
1bit 標識
7bit 回退段ID
4bytes 回滾段頁號
2bytes 回滾段頁的偏移量
這幾位在討論MVCC的時候詳細研究
11、non-key fields
也就是M個位元組的非主鍵欄位的資料了。
那我們可以完整的取出第一行
我們計算一下我這裡包含一個變數 varchar 1個位元組,沒有NULL值
那行頭的位元組就是1BYTES+1bytes+4BIT+4BIT+13BIT+3BIT+2BYTES=7BYTES
而偏移量為
99+65=164-行頭7bytes=157byes
bcview km1.ibd 16 157 37|more
這裡的37=行頭7BYTES+
CLUSTER KEY(我是ROWID 6BYTES)+
transaction id(6BYTES)+
roll pointer(7BYTES)+
non-key fields(INT 4BYTES+VARCHAR(7BYTES))
current block:00000003--Offset:00157--cnt bytes:37--data is:0700000018004a000001cc64260000002d0272d300000d1201108000000267616f70656e67
分解一下資料
0X07 varchar 實際資料'gaopeng'的長度
0X00 null型別標示位元組我這裡沒有NULL
0X0 我這裡是0他既不是刪除行也不是非頁節點的最小行,可以理解在也節點中刪除的行在這4位上才有0010的值,隨後測試
0X0 記錄在槽0上
0X0018 轉換為二進位制0000 0000 0001 1000 前13位為0000 0000 0001 1=十進位制的3 為什麼是3呢?不是
說從2開始嗎?因為我這裡本來的第一行插入的資料被我DELETE掉了,而空間得到從用,OFFSET排序是按照CLUSTER KEY排序的。
000為record type,很明顯我這裡是資料行,當然也就是000
0X004a 下一個資料的偏移量十進位制74
0X000001cc6426 ROWID
0X0000002d0272d3 事物ID
0X00000d120110 回滾指標
0X80000002 帶符號的int型別的2
0X67616f70656e67 資料'gaopeng'
那我們接下來尋找第二條資料
164+74,由於資料格式一樣,
直接
164+74-行頭7bytes=231
取37位元組
bcview km1.ibd 16 231 37|more
current block:00000003--Offset:00231--cnt bytes:37--data is:0700000028ffdb000001cc64280000002d0278d700000d0601108000000467616f70656e67
分解資料
07 同上
00 同上
0 同上
0 同上
0028 0000 0000 0010 1000
0000 0000 0010 1=十進位制的5
000 表示是普通資料
ffdb 這裡注意了負數儲存方式是以補碼的方式,負數說明我們的偏移量回退了,也就是使用了DELETE的空間
ffdb 也就是-37大家可以自行計算
000001cc6428 同上
0000002d0278d7 同上
00000d060110 同上
80000004 實際資料4
67616f70656e67 實際資料'gaopeng'
那我們接下來尋找第三條資料
164+74+(-37)-7=194
bcview km1.ibd 16 194 37|more
current block:00000003--Offset:00194--cnt bytes:37--data is:0700000020ffb6000001cc65000000002d062bab00000d0c01108000000567616f70656e67
同樣分解資料
07
00
0
0
0020 這裡分解同上 0000 0000 0010 0=十進位制4 這是order 表示這個資料在上條資料插入之前,但是OFFSET是按照ROWID排序的。
ffb6 任然是補碼的方式 實際就是-74
000001cc6500
0000002d062bab
00000d0c0110
80000005 實際資料5
67616f70656e67 實際資料'gaopeng'
再來第四條資料
164+74+(-37)+(-74)-7=120 這裡來到了物理的第一行資料
bcview km1.ibd 16 120 37|more
current block:00000003--Offset:00120--cnt bytes:37--data is:07000000100094000001cc66000000002d0a2cab00000d0c01108000000667616f70656e67
分解資料
07
00
0
0
0010 0000 0000 0000 1000
0000 0000 0000 1=十進位制2
0094 偏移量
000001cc6600
0000002d0a2cab
00000d0c0110
80000006 實際資料6
67616f70656e67 實際資料'gaopeng'
接下來的尋找剩下的2條資料我就自己完成了
ID=7 實際位置 164+74+(-37)+(-74)+148-7=268 bcview km1.ibd 16 268 37|more
ID=8 實際位置 164+74+(-37)+(-74)+148+37-7=305 bcview km1.ibd 16 305 37|more
實際上我們大概得出了一個連結串列
infimum order 0 offset 65
-->實際資料 id=2 rowid 000001cc6426 order 3 offset 74
-->實際資料 id=4 rowid 000001cc6428 order 5 offset -37
-->實際資料 id=5 rowid 000001cc6500 order 4 offset -37
-->實際資料 id=6 rowid 000001cc6600 order 2 offset 148
-->實際資料 id=7 rowid 000001cc6700 order 6 offset 37
-->實際資料 id=8 rowid 000001cc6800 order 7 offset -200
-->supermum order 1 offset null
注意最後一條資料的-200,實際為起始位置為164+74+(-37)+(-74)+148+37-200=112
那麼我們看到了他的順序確實為ROWID的排序,而ORDER 實際才是物理順序。
同時注意這裡是按照ROWID進行排序的因為沒有主鍵因為並沒有主鍵,這裡並不是按照ID進行
排序的,這裡只是湊巧而已
如果插入一條
mysql> insert into km1 values(1,'gaopeng12');
Query OK, 1 row affected (0.06 sec)
ID=1的資料
bcview km1.ibd 16 342 40|more分解資料得到
-->實際資料 id=8 rowid 000001cc6800 order 7 offset 37
-->實際資料 id=1 rowid 000001cc6900 order 8 offset -237
-->supermum order 1 offset null
此外還需要做一個實驗就是刪除的行是否在這個連結串列出,同時測試刪除行的info flags
刪除剛才插入的資料
mysql> delete from km1 where id=1;
Query OK, 1 row affected (0.11 sec)
及
-->實際資料 id=8 rowid 000001cc6800 order 7 offset 37
-->實際資料 id=1 rowid 000001cc6900 order 8 offset -237 刪除
-->supermum order 1 offset null
再次檢視
bcview km1.ibd 16 305 37|more
current block:00000003--Offset:00305--cnt bytes:37--data is:0700000038ff38000001cc68000000002d0e2bab00000d0c01108000000867616f70656e67
分解一下
07
0
0
00
0038
ff38 這裡的offset從37變為了-200 顯然刪除的行從連結串列中刪除了,因為這一行直接指向了supermum
000001cc6800
0000002d0e2bab
00000d0c0110
80000008
67616f70656e67
我們再次檢視
bcview km1.ibd 16 342 39|more
current block:00000003--Offset:00342--cnt bytes:40--data is:09002000400000000001cc69000000002d10323200000d17022d8000000167616f70656e673132
09
0
0
20 binary 0010 0000可以看到這個位元組的前4位變為了0010 確實binary 0010表示是刪除的行
0040 order 也沒有變為8
0000 這裡指標從先前的-237 變為了0 及空指標
000001cc6900
0000002d103232
00000d17022d
80000001
67616f70656e673132
那麼剛才的連結串列
infimum order 0 offset 65
-->實際資料 id=2 rowid 000001cc6426 order 3 offset 74
-->實際資料 id=4 rowid 000001cc6428 order 5 offset -37
-->實際資料 id=5 rowid 000001cc6500 order 4 offset -37
-->實際資料 id=6 rowid 000001cc6600 order 2 offset 148
-->實際資料 id=7 rowid 000001cc6700 order 6 offset 37
-->實際資料 id=8 rowid 000001cc6800 order 7 offset 37
-->實際資料 id=1 rowid 000001cc6900 order 8 offset -237 刪除
-->supermum order 1 offset null
變為了
infimum order 0 offset 65
-->實際資料 id=2 rowid 000001cc6426 order 3 offset 74
-->實際資料 id=4 rowid 000001cc6428 order 5 offset -37
-->實際資料 id=5 rowid 000001cc6500 order 4 offset -37
-->實際資料 id=6 rowid 000001cc6600 order 2 offset 148
-->實際資料 id=7 rowid 000001cc6700 order 6 offset 37
-->實際資料 id=8 rowid 000001cc6800 order 7 offset -200
-->supermum order 1 offset null
並且刪除的資料
-->實際資料 id=1 rowid 000001cc6900 order 8 offset 0 刪除
如此我們驗證了2個事實
1、刪除的行從offset連結串列中刪除
2、確實binary 0010表示是刪除的行
也許還記得在index page header中包含了兩個資訊
first garbage record offset 2bytes 第一行刪除記錄的偏移量
garbage space 2bytes 刪除的空間大小單位bytes
如果標示了第一個刪除的行是不是,刪除行也有一個連結串列呢?
我們先來看看這2個位元組當前值
first garbage record offset
bcview km1.ibd 16 44 2|more (first garbage record offset)
current block:00000003--Offset:00044--cnt bytes:02--data is:015d
當前這個值為0X15d及349 指向了剛才刪除行的OFFSET,我們猜測試著刪除連結串列的開頭
garbage space
bcview km1.ibd 16 46 2|more (garbage space)
current block:00000003--Offset:00046--cnt bytes:02--data is:0027
當前這個值為0X27及39 這個值剛好是刪除記錄的佔用空間
及7+6+7+6+4+9位元組
infimum order 0 offset 65
-->實際資料 id=2 rowid 000001cc6426 order 3 offset 74
-->實際資料 id=4 rowid 000001cc6428 order 5 offset -37
-->實際資料 id=5 rowid 000001cc6500 order 4 offset -37
-->實際資料 id=6 rowid 000001cc6600 order 2 offset 148
-->實際資料 id=7 rowid 000001cc6700 order 6 offset 37
-->實際資料 id=8 rowid 000001cc6800 order 7 offset -200
-->supermum order 1 offset null
並且刪除的資料
first garbage record offset
-->實際資料 id=1 rowid 000001cc6900 order 8 offset 0 刪除
我們來刪除
mysql> delete from km1 where id=2;
Query OK, 1 row affected (0.00 sec)
-->實際資料 id=2 rowid 000001cc6426 order 3 offset 74
刪除後
檢視infimum的偏移量
bcview km1.ibd 16 97 2
current block:00000003--Offset:00097--cnt bytes:02--data is:008b
為0X8b為139
那麼第一條資料的位置為
99+139-7=231
我們檢視一下
bcview km1.ibd 16 231 37|more
current block:00000003--Offset:00231--cnt bytes:37--data is:0700000028ffdb000001cc64280000002d0278d700000d0601108000000467616f70656e67
分解
0700000028
ffdb 偏移量還是-37(補碼方式)
000001cc64280000002d0278d700000d060110
80000004 可以看到這個資料ID=4了
67616f70656e67
那麼也就證明刪除的行從資料連結串列中摘除了。
那麼我們的資料連結串列變為
infimum order 0 offset 139
-->實際資料 id=4 rowid 000001cc6428 order 5 offset -37
-->實際資料 id=5 rowid 000001cc6500 order 4 offset -37
-->實際資料 id=6 rowid 000001cc6600 order 2 offset 148
-->實際資料 id=7 rowid 000001cc6700 order 6 offset 37
-->實際資料 id=8 rowid 000001cc6800 order 7 offset -200
-->supermum order 1 offset null
再次檢視
first garbage record offset
bcview km1.ibd 16 44 2|more
current block:00000003--Offset:00044--cnt bytes:02--data is:00a4
當前這個值為0XA4及164,剛才為0X15d及349
那麼我們看看 164-7就是行的開頭
bcview km1.ibd 16 157 37|more
current block:00000003--Offset:00157--cnt bytes:37--data is:070020001800b9000001cc64260000002d1038350000014527b68000000267616f70656e67
07
0
0
20 --刪除的行
0018 --order為3
00b9 --下一個刪除行的偏移量
000001cc6426 rowid
0000002d103835
0000014527b6
80000002 資料ID=2
67616f70656e67
最後按照這個偏移量來找到ID=1 rowid 000001cc6900的資料
164+185(0Xb9)-7=342
bcview km1.ibd 16 342 39|more
current block:00000003--Offset:00342--cnt bytes:39--data is:09002000400000000001cc69000000002d10323200000d17022d8000000167616f70656e673132
看看這裡的和剛才的
09002000400000000001cc69000000002d10323200000d17022d8000000167616f70656e673132
沒有任何變化
garbage space
bcview km1.ibd 16 46 2|more
current block:00000003--Offset:00046--cnt bytes:02--data is:004c
當前這個值為0X4C及76 這個值剛好是刪除2條記錄佔用的空間
那麼這個刪除連結串列變成了
first garbage record offset 164
-->實際資料 id=2 rowid 000001cc6426 order 3 offset 185
-->實際資料 id=1 rowid 000001cc6900 order 8 offset 00
隨後我又進行了一次測試,發現在刪除連結串列中first garbage record offset總是指向最近被刪除的一條的記錄的偏移量,而空間從用總是
先使用first garbage record offset指向的空間,使用完成後加入資料連結串列,而first garbage record offset指向下一個節點的位置。
那麼我們可以描述刪除連結串列實際準守一個後入先出的原則,這個有點像棧空間的使用,這個也可以理解,因為在資料連結串列中為了保證
資料的有序讀取必須是按CLUSTER KEY排序的,而在刪除連結串列中沒有這樣需求,簡單實用這種類似棧的連結串列更加簡單。
整個計算過程比較繁瑣,
最後總結一下:
1、一個BLOCK中有2個連結串列一個是資料連結串列,一個是刪除資料的連結串列
資料連結串列的開頭和結尾是infimum和supermum,
刪除連結串列的開頭是first garbage record offset,結尾就是最後一個刪除的塊。
next offset為0000空指標
2、 在資料連結串列中next record offset 是按照CLUSTER KEY 大小進行排序的或者是ROWID
而在刪除連結串列中first garbage record offset總是指向最近被刪除的一條的記錄的偏移量,next record offset 的順序就是刪除的順序,
刪除連結串列的空間從用類似棧空間的使用遵循後入先出的原則。
3、order 是物理位置的排序,他展示了資料在block中的物理位置,infimum和supermum
分別為0和1,因為他們總是在開始的。
4、info flags在頁節點中除非刪除了行才標記為 binary 0010
5、刪除的行從資料連結串列中摘除,然後掛載到了刪除連結串列中
6、刪除的行的資料會被重用,在從用之前,delete的資料理論上是可以恢復的,因為他們都在刪除連結串列中
7、關於負的偏移量,也就是刪除後從用的空間,是以補碼的方式給出的
關於MYSQL INNODB index page header學習和實驗總結
http://blog.itpub.net/7728585/viewspace-2063921/
關於INNODB SYSTEM RECORD infimum和supremum的學習和實驗研究
http://blog.itpub.net/7728585/viewspace-2065464/
我放到了百度雲盤
供大家下載和使用
本文只討論COMPACT行模式
資料:
mysql> select * from km1;
+------+---------+
| id | name |
+------+---------+
| 2 | gaopeng |
| 4 | gaopeng |
| 5 | gaopeng |
| 6 | gaopeng |
| 7 | gaopeng |
| 8 | gaopeng |
+------+---------+
6 rows in set (0.04 sec)
上一篇文章已經從infimum找到了第一行資料的偏移量
為99+65=164
同時取出了第一行資料:
bcview km1.ibd 16 164 30|more
current block:00000003--Offset:00164--cnt bytes:30--data is:000001cc64260000002d0272d300000d1201108000000267616f70656e67
分解一下資料
000001cc6426 ROWID
0000002d0272 transaction id
d300000d120110 roll pointer
80000002 資料2,這裡8出現在第15位,可能為符號位
67616f70656e67 資料'gaopeng'的ascII值
那麼我們解析來介紹關於CLUSTER KEY-LEAF BLOCK的相關的部分
很顯然我這裡的表只有一個塊,因為資料很少。所以先介紹這個
,因為所謂的infimum的offset是指向的資料的開頭,而行頭資訊
記錄在offset-N的位置,N不確定看了如下就知道了
variable field lengths (1-2 bytes* var )
nullable field bitmap (1 bit * null field)
info flags (4 bits)
number of records owned (4 bits)
order (13 bits)
record type (3 bits)
next record offset (2 bytes)
offset ----cluster key fields (N bytes)
transaction id (6 bytes)
roll pointer (7 bytes)
non-key fields (M bytes)
1、variable field lengths
每個可變長度的變數型別儲存一個長度如varchar,對於固定長度的比如INT不記錄。
如果不存在可變長度的變數型別,至少佔用一個位元組為00。
2、nullable field bitmap
每個NULL值佔用一個一位(bit),如果不滿一個位元組按一個位元組算,如果不存在NULL值
至少佔用一個位元組為00。
3、info flags
這4位(4bits)標示是一個行標識,其中binary 0001表示非葉節點最小的行
其中binary 0010表示是刪除的行,而infimum和supremum行在我測試資料庫中為binary 0000
4、number of records owned
這4位(4bits)表示在本page directory(槽)中的記錄數,關於槽的概念後面詳細探討
5、order
這13位(13bits)表示記錄插入到塊中順序,INFIMUM恆等於0而SPREMUM恆等於1,而資料行的ORDER從2開始,這裡的order
我實驗得出的結論為實際物理空間的順序
6、record type
這3位(3bits)表示記錄的型別,supermum恆等於3及binary 011,infimum恆等於2及binary010,節點指標為1及001,資料行為000
7、next record offset
這2個位元組是按照CLUSTER KEY值排序的,也就是說他的順序和order沒有任何聯絡,order是插入的順序
在INFIMUM中表示的是第一個行的偏移量這個偏移量是當前記錄的位置+offset,這個offset直接指向了資料而相關的行頭在offset-n開始n為行頭的開銷。
當然supermum為的偏移量就是NULL空指標了。
8、cluster key fields
這N個位元組代表主鍵位元組數,沒有就是ROWID佔用6位元組
9、transaction id
這6個位元組為最後一次修改本行的事物ID
10、roll pointer
這7個位元組是用於支援MVCC多版本的回退指標,
1bit 標識
7bit 回退段ID
4bytes 回滾段頁號
2bytes 回滾段頁的偏移量
這幾位在討論MVCC的時候詳細研究
11、non-key fields
也就是M個位元組的非主鍵欄位的資料了。
那我們可以完整的取出第一行
我們計算一下我這裡包含一個變數 varchar 1個位元組,沒有NULL值
那行頭的位元組就是1BYTES+1bytes+4BIT+4BIT+13BIT+3BIT+2BYTES=7BYTES
而偏移量為
99+65=164-行頭7bytes=157byes
bcview km1.ibd 16 157 37|more
這裡的37=行頭7BYTES+
CLUSTER KEY(我是ROWID 6BYTES)+
transaction id(6BYTES)+
roll pointer(7BYTES)+
non-key fields(INT 4BYTES+VARCHAR(7BYTES))
current block:00000003--Offset:00157--cnt bytes:37--data is:0700000018004a000001cc64260000002d0272d300000d1201108000000267616f70656e67
分解一下資料
0X07 varchar 實際資料'gaopeng'的長度
0X00 null型別標示位元組我這裡沒有NULL
0X0 我這裡是0他既不是刪除行也不是非頁節點的最小行,可以理解在也節點中刪除的行在這4位上才有0010的值,隨後測試
0X0 記錄在槽0上
0X0018 轉換為二進位制0000 0000 0001 1000 前13位為0000 0000 0001 1=十進位制的3 為什麼是3呢?不是
說從2開始嗎?因為我這裡本來的第一行插入的資料被我DELETE掉了,而空間得到從用,OFFSET排序是按照CLUSTER KEY排序的。
000為record type,很明顯我這裡是資料行,當然也就是000
0X004a 下一個資料的偏移量十進位制74
0X000001cc6426 ROWID
0X0000002d0272d3 事物ID
0X00000d120110 回滾指標
0X80000002 帶符號的int型別的2
0X67616f70656e67 資料'gaopeng'
那我們接下來尋找第二條資料
164+74,由於資料格式一樣,
直接
164+74-行頭7bytes=231
取37位元組
bcview km1.ibd 16 231 37|more
current block:00000003--Offset:00231--cnt bytes:37--data is:0700000028ffdb000001cc64280000002d0278d700000d0601108000000467616f70656e67
分解資料
07 同上
00 同上
0 同上
0 同上
0028 0000 0000 0010 1000
0000 0000 0010 1=十進位制的5
000 表示是普通資料
ffdb 這裡注意了負數儲存方式是以補碼的方式,負數說明我們的偏移量回退了,也就是使用了DELETE的空間
ffdb 也就是-37大家可以自行計算
000001cc6428 同上
0000002d0278d7 同上
00000d060110 同上
80000004 實際資料4
67616f70656e67 實際資料'gaopeng'
那我們接下來尋找第三條資料
164+74+(-37)-7=194
bcview km1.ibd 16 194 37|more
current block:00000003--Offset:00194--cnt bytes:37--data is:0700000020ffb6000001cc65000000002d062bab00000d0c01108000000567616f70656e67
同樣分解資料
07
00
0
0
0020 這裡分解同上 0000 0000 0010 0=十進位制4 這是order 表示這個資料在上條資料插入之前,但是OFFSET是按照ROWID排序的。
ffb6 任然是補碼的方式 實際就是-74
000001cc6500
0000002d062bab
00000d0c0110
80000005 實際資料5
67616f70656e67 實際資料'gaopeng'
再來第四條資料
164+74+(-37)+(-74)-7=120 這裡來到了物理的第一行資料
bcview km1.ibd 16 120 37|more
current block:00000003--Offset:00120--cnt bytes:37--data is:07000000100094000001cc66000000002d0a2cab00000d0c01108000000667616f70656e67
分解資料
07
00
0
0
0010 0000 0000 0000 1000
0000 0000 0000 1=十進位制2
0094 偏移量
000001cc6600
0000002d0a2cab
00000d0c0110
80000006 實際資料6
67616f70656e67 實際資料'gaopeng'
接下來的尋找剩下的2條資料我就自己完成了
ID=7 實際位置 164+74+(-37)+(-74)+148-7=268 bcview km1.ibd 16 268 37|more
ID=8 實際位置 164+74+(-37)+(-74)+148+37-7=305 bcview km1.ibd 16 305 37|more
實際上我們大概得出了一個連結串列
infimum order 0 offset 65
-->實際資料 id=2 rowid 000001cc6426 order 3 offset 74
-->實際資料 id=4 rowid 000001cc6428 order 5 offset -37
-->實際資料 id=5 rowid 000001cc6500 order 4 offset -37
-->實際資料 id=6 rowid 000001cc6600 order 2 offset 148
-->實際資料 id=7 rowid 000001cc6700 order 6 offset 37
-->實際資料 id=8 rowid 000001cc6800 order 7 offset -200
-->supermum order 1 offset null
注意最後一條資料的-200,實際為起始位置為164+74+(-37)+(-74)+148+37-200=112
那麼我們看到了他的順序確實為ROWID的排序,而ORDER 實際才是物理順序。
同時注意這裡是按照ROWID進行排序的因為沒有主鍵因為並沒有主鍵,這裡並不是按照ID進行
排序的,這裡只是湊巧而已
如果插入一條
mysql> insert into km1 values(1,'gaopeng12');
Query OK, 1 row affected (0.06 sec)
ID=1的資料
bcview km1.ibd 16 342 40|more分解資料得到
-->實際資料 id=8 rowid 000001cc6800 order 7 offset 37
-->實際資料 id=1 rowid 000001cc6900 order 8 offset -237
-->supermum order 1 offset null
此外還需要做一個實驗就是刪除的行是否在這個連結串列出,同時測試刪除行的info flags
刪除剛才插入的資料
mysql> delete from km1 where id=1;
Query OK, 1 row affected (0.11 sec)
及
-->實際資料 id=8 rowid 000001cc6800 order 7 offset 37
-->實際資料 id=1 rowid 000001cc6900 order 8 offset -237 刪除
-->supermum order 1 offset null
再次檢視
bcview km1.ibd 16 305 37|more
current block:00000003--Offset:00305--cnt bytes:37--data is:0700000038ff38000001cc68000000002d0e2bab00000d0c01108000000867616f70656e67
分解一下
07
0
0
00
0038
ff38 這裡的offset從37變為了-200 顯然刪除的行從連結串列中刪除了,因為這一行直接指向了supermum
000001cc6800
0000002d0e2bab
00000d0c0110
80000008
67616f70656e67
我們再次檢視
bcview km1.ibd 16 342 39|more
current block:00000003--Offset:00342--cnt bytes:40--data is:09002000400000000001cc69000000002d10323200000d17022d8000000167616f70656e673132
09
0
0
20 binary 0010 0000可以看到這個位元組的前4位變為了0010 確實binary 0010表示是刪除的行
0040 order 也沒有變為8
0000 這裡指標從先前的-237 變為了0 及空指標
000001cc6900
0000002d103232
00000d17022d
80000001
67616f70656e673132
那麼剛才的連結串列
infimum order 0 offset 65
-->實際資料 id=2 rowid 000001cc6426 order 3 offset 74
-->實際資料 id=4 rowid 000001cc6428 order 5 offset -37
-->實際資料 id=5 rowid 000001cc6500 order 4 offset -37
-->實際資料 id=6 rowid 000001cc6600 order 2 offset 148
-->實際資料 id=7 rowid 000001cc6700 order 6 offset 37
-->實際資料 id=8 rowid 000001cc6800 order 7 offset 37
-->實際資料 id=1 rowid 000001cc6900 order 8 offset -237 刪除
-->supermum order 1 offset null
變為了
infimum order 0 offset 65
-->實際資料 id=2 rowid 000001cc6426 order 3 offset 74
-->實際資料 id=4 rowid 000001cc6428 order 5 offset -37
-->實際資料 id=5 rowid 000001cc6500 order 4 offset -37
-->實際資料 id=6 rowid 000001cc6600 order 2 offset 148
-->實際資料 id=7 rowid 000001cc6700 order 6 offset 37
-->實際資料 id=8 rowid 000001cc6800 order 7 offset -200
-->supermum order 1 offset null
並且刪除的資料
-->實際資料 id=1 rowid 000001cc6900 order 8 offset 0 刪除
如此我們驗證了2個事實
1、刪除的行從offset連結串列中刪除
2、確實binary 0010表示是刪除的行
也許還記得在index page header中包含了兩個資訊
first garbage record offset 2bytes 第一行刪除記錄的偏移量
garbage space 2bytes 刪除的空間大小單位bytes
如果標示了第一個刪除的行是不是,刪除行也有一個連結串列呢?
我們先來看看這2個位元組當前值
first garbage record offset
bcview km1.ibd 16 44 2|more (first garbage record offset)
current block:00000003--Offset:00044--cnt bytes:02--data is:015d
當前這個值為0X15d及349 指向了剛才刪除行的OFFSET,我們猜測試著刪除連結串列的開頭
garbage space
bcview km1.ibd 16 46 2|more (garbage space)
current block:00000003--Offset:00046--cnt bytes:02--data is:0027
當前這個值為0X27及39 這個值剛好是刪除記錄的佔用空間
及7+6+7+6+4+9位元組
infimum order 0 offset 65
-->實際資料 id=2 rowid 000001cc6426 order 3 offset 74
-->實際資料 id=4 rowid 000001cc6428 order 5 offset -37
-->實際資料 id=5 rowid 000001cc6500 order 4 offset -37
-->實際資料 id=6 rowid 000001cc6600 order 2 offset 148
-->實際資料 id=7 rowid 000001cc6700 order 6 offset 37
-->實際資料 id=8 rowid 000001cc6800 order 7 offset -200
-->supermum order 1 offset null
並且刪除的資料
first garbage record offset
-->實際資料 id=1 rowid 000001cc6900 order 8 offset 0 刪除
我們來刪除
mysql> delete from km1 where id=2;
Query OK, 1 row affected (0.00 sec)
-->實際資料 id=2 rowid 000001cc6426 order 3 offset 74
刪除後
檢視infimum的偏移量
bcview km1.ibd 16 97 2
current block:00000003--Offset:00097--cnt bytes:02--data is:008b
為0X8b為139
那麼第一條資料的位置為
99+139-7=231
我們檢視一下
bcview km1.ibd 16 231 37|more
current block:00000003--Offset:00231--cnt bytes:37--data is:0700000028ffdb000001cc64280000002d0278d700000d0601108000000467616f70656e67
分解
0700000028
ffdb 偏移量還是-37(補碼方式)
000001cc64280000002d0278d700000d060110
80000004 可以看到這個資料ID=4了
67616f70656e67
那麼也就證明刪除的行從資料連結串列中摘除了。
那麼我們的資料連結串列變為
infimum order 0 offset 139
-->實際資料 id=4 rowid 000001cc6428 order 5 offset -37
-->實際資料 id=5 rowid 000001cc6500 order 4 offset -37
-->實際資料 id=6 rowid 000001cc6600 order 2 offset 148
-->實際資料 id=7 rowid 000001cc6700 order 6 offset 37
-->實際資料 id=8 rowid 000001cc6800 order 7 offset -200
-->supermum order 1 offset null
再次檢視
first garbage record offset
bcview km1.ibd 16 44 2|more
current block:00000003--Offset:00044--cnt bytes:02--data is:00a4
當前這個值為0XA4及164,剛才為0X15d及349
那麼我們看看 164-7就是行的開頭
bcview km1.ibd 16 157 37|more
current block:00000003--Offset:00157--cnt bytes:37--data is:070020001800b9000001cc64260000002d1038350000014527b68000000267616f70656e67
07
0
0
20 --刪除的行
0018 --order為3
00b9 --下一個刪除行的偏移量
000001cc6426 rowid
0000002d103835
0000014527b6
80000002 資料ID=2
67616f70656e67
最後按照這個偏移量來找到ID=1 rowid 000001cc6900的資料
164+185(0Xb9)-7=342
bcview km1.ibd 16 342 39|more
current block:00000003--Offset:00342--cnt bytes:39--data is:09002000400000000001cc69000000002d10323200000d17022d8000000167616f70656e673132
看看這裡的和剛才的
09002000400000000001cc69000000002d10323200000d17022d8000000167616f70656e673132
沒有任何變化
garbage space
bcview km1.ibd 16 46 2|more
current block:00000003--Offset:00046--cnt bytes:02--data is:004c
當前這個值為0X4C及76 這個值剛好是刪除2條記錄佔用的空間
那麼這個刪除連結串列變成了
first garbage record offset 164
-->實際資料 id=2 rowid 000001cc6426 order 3 offset 185
-->實際資料 id=1 rowid 000001cc6900 order 8 offset 00
隨後我又進行了一次測試,發現在刪除連結串列中first garbage record offset總是指向最近被刪除的一條的記錄的偏移量,而空間從用總是
先使用first garbage record offset指向的空間,使用完成後加入資料連結串列,而first garbage record offset指向下一個節點的位置。
那麼我們可以描述刪除連結串列實際準守一個後入先出的原則,這個有點像棧空間的使用,這個也可以理解,因為在資料連結串列中為了保證
資料的有序讀取必須是按CLUSTER KEY排序的,而在刪除連結串列中沒有這樣需求,簡單實用這種類似棧的連結串列更加簡單。
整個計算過程比較繁瑣,
最後總結一下:
1、一個BLOCK中有2個連結串列一個是資料連結串列,一個是刪除資料的連結串列
資料連結串列的開頭和結尾是infimum和supermum,
刪除連結串列的開頭是first garbage record offset,結尾就是最後一個刪除的塊。
next offset為0000空指標
2、 在資料連結串列中next record offset 是按照CLUSTER KEY 大小進行排序的或者是ROWID
而在刪除連結串列中first garbage record offset總是指向最近被刪除的一條的記錄的偏移量,next record offset 的順序就是刪除的順序,
刪除連結串列的空間從用類似棧空間的使用遵循後入先出的原則。
3、order 是物理位置的排序,他展示了資料在block中的物理位置,infimum和supermum
分別為0和1,因為他們總是在開始的。
4、info flags在頁節點中除非刪除了行才標記為 binary 0010
5、刪除的行從資料連結串列中摘除,然後掛載到了刪除連結串列中
6、刪除的行的資料會被重用,在從用之前,delete的資料理論上是可以恢復的,因為他們都在刪除連結串列中
7、關於負的偏移量,也就是刪除後從用的空間,是以補碼的方式給出的
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7728585/viewspace-2071787/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 儲存系統實現-資料刪除之索引的刪除索引
- innodb 頁儲存管理的實驗
- 關於InnoDB表資料和索引資料的儲存索引
- 儲存系統實現-如何刪除資料
- 資料獲取,解析,儲存等知識的學習總結
- 區塊鏈資料總結區塊鏈
- 【儲存資料恢復】HP EVA儲存誤刪除VDISK的資料恢復案例資料恢復
- 【儲存資料恢復】NetApp儲存誤刪除的資料恢復案例資料恢復APP
- 【RAC】刪除RAC資料庫節點(一)——刪除資料庫例項資料庫
- 資料庫儲存選型經驗總結資料庫
- 誤刪除儲存SqlServer資料庫資料恢復SQLServer資料庫資料恢復
- 七牛雲端儲存資料,刪除無用資料
- MySQL-07.InnoDB資料儲存結構MySql
- 【資料結構】二叉樹(順序儲存、鏈式儲存)的JAVA程式碼實現資料結構二叉樹Java
- 從一條資料說起——InnoDB儲存資料結構資料結構
- 【RAC】刪除RAC資料庫節點(二)——刪除ASM資料庫ASM
- 【RAC】刪除RAC資料庫節點(五)——刪除ONS資料庫
- 資料結構實驗5、鏈佇列的基本操作資料結構佇列
- 區塊鏈學習資料區塊鏈
- InnoDB資料頁結構
- PUBLIC資料庫鏈無法刪除的問題(二)資料庫
- PUBLIC資料庫鏈無法刪除的問題(一)資料庫
- 資料結構(線性錶鏈式儲存)的幾個基本操作資料結構
- 從零開始學資料結構和演算法(二)線性表的鏈式儲存結構資料結構演算法
- 【RAC】刪除RAC資料庫節點(三)——刪除監聽資料庫
- MYSQL innodb buffer 狀態資料的儲存和載入MySql
- 資料儲存的三種方式
- 《MySQL 基礎篇》十二:InnoDB 儲存引擎的資料結構MySql儲存引擎資料結構
- 單細胞資料 儲存方式彙總
- MySQL InnoDB的儲存結構總結MySql
- java 資料儲存方式Java
- 層次結構資料的資料庫儲存和使用資料庫
- 【劉文彬】區塊鏈 + 大資料:EOS儲存區塊鏈大資料
- 傳統資料庫也能實現區塊鏈儲存資料庫區塊鏈
- 資料結構 (計算機儲存、組織資料方式)資料結構計算機
- iOS儲存資料的4種方式iOS
- 【RAC】刪除RAC資料庫節點(四)——刪除資料庫軟體及ASM軟體資料庫ASM
- iOS開發資料儲存篇—iOS中的幾種資料儲存方式iOS