Myisam-儲存引擎-動態格式-DELETED ROWS

Steven1981發表於2009-03-19
在上一節中,我們簡單地談到了:
如果行被刪除,那麼其標誌位為被置為"00".而且行的部分資料會被重新賦值.
在這一章節中,我們將詳細討論:
在動態格式的表中,如果行資料被刪除了,這一行的資料將如何發生變化,以及其資料所包含的具體含義.
[@more@]1.測試環境
OS : LINUX 2.6.9-42.ELsmp
DB : MYSQL 5.0.51a
ENGINE : MYISAM DEFAULT CHARSET=latin1

2. 動態格式表中被刪除的記錄儲存
2.1 模擬資料
drop table if exists heyf ;
create table heyf (id int , name varchar(50)) type myisam DEFAULT CHARSET=latin1;
insert into heyf values
(1,'aaaaa'),(2,'bbbbb') ,(45,'ssssss') ,
(65,'dddddddd'),(23,'hhhhhhhhhhhh'),(5,'jjjjjjj');
system hexdump /opt/mysql/data/test/heyf.MYD;
------------------------------------------------
0000000 0003 040c fc00 0001 0000 6105 6161 6161
0000010 0000 0000 0003 040c fc00 0002 0000 6205
0000020 6262 6262 0000 0000 0003 030d fc00 002d
0000030 0000 7306 7373 7373 0073 0000 0003 010f
0000040 fc00 0041 0000 6408 6464 6464 6464 0064
0000050 0003 0113 fc00 0017 0000 680c 6868 6868
0000060 6868 6868 6868 0068 0003 020e fc00 0005
0000070 0000 6a07 6a6a 6a6a 6a6a 0000
------------------------------------------------
我們根據定義讀出每行的資料:
===========================================================
ROW1: 03 00 0c 04 00 fc 01 00 00 00 05 61 61 61 61 61 00 00 00 00
ROW2: 03 00 0c 04 00 fc 02 00 00 00 05 62 62 62 62 62 00 00 00 00
ROW3: 03 00 0d 03 00 fc 2d 00 00 00 06 73 73 73 73 73 73 00 00 00
ROW4: 03 00 0f 01 00 fc 41 00 00 00 08 64 64 64 64 64 64 64 64 00
ROW5: 03 00 13 01 00 fc 17 00 00 00 0c 68 68 68 68 68 68 68 68 68 68 68 68 00
ROW6: 03 00 0e 02 00 fc 05 00 00 00 07 6a 6a 6a 6a 6a 6a 6a 00 00
===========================================================
根據題意,我們先刪除第1,3,5行資料:
delete from heyf where id in (1,45,23) ;
system hexdump /opt/mysql/data/test/heyf.MYD;
------------------------------------------------
0000000 0000 1400 ffff ffff ffff ffff 0000 0000
0000010 0000 2800 0003 040c fc00 0002 0000 6205
0000020 6262 6262 0000 0000 0000 1400 0000 0000
0000030 0000 0000 0000 0000 0000 5000 0003 010f
0000040 fc00 0041 0000 6408 6464 6464 6464 0064
0000050 0000 1800 0000 0000 0000 2800 ffff ffff
0000060 ffff ffff 6868 0068 0003 020e fc00 0005
0000070 0000 6a07 6a6a 6a6a 6a6a 0000
------------------------------------------------

再次讀出各行資料:
===========================================================
ROW1: 00 00 00 14 ff ff ff ff ff ff ff ff 00 00 00 00 00 00 00 28
ROW2: 03 00 0c 04 00 fc 02 00 00 00 05 62 62 62 62 62 00 00 00 00
ROW3: 00 00 00 14 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 50
ROW4: 03 00 0f 01 00 fc 41 00 00 00 08 64 64 64 64 64 64 64 64 00
ROW5: 00 00 00 18 00 00 00 00 00 00 00 28 ff ff ff ff ff ff ff ff 68 68 68 00
ROW6: 03 00 0e 02 00 fc 05 00 00 00 07 6a 6a 6a 6a 6a 6a 6a 00 00
===========================================================
2.2 開始分析資料
下來我們來解釋一下:
當一行被刪除. 那麼該行資料的前20個位元組將被置為含有特殊意義的數字,該行20個位元組以後的內容不變.
前20位的具體含義如下: (第1行)
---------------------------------------------------------
00 : 1B, FLAG, 0X00 -> Deleted
00 00 14 : 3B, Block_len ,0X14 -> 20B
ff ff ff ff ff ff ff ff : 8B,Prev deleted row's address .
00 00 00 00 00 00 00 28 : 8B,Next deleted row's address .
---------------------------------------------------------
上面的意思是說,下一個已經被刪除的行的地址是0X0000028,
核對一下,這個地址確實剛好是被刪除的第三行ADDR.
我們把第3行資料也拿出來分析一下:
前20位的具體含義如下: (第3行)
---------------------------------------------------------
00 : 1B, FLAG, 0X00 -> Deleted
00 00 14 : 3B, Block_len ,0X14 -> 20B
00 00 00 00 00 00 00 00 : 8B, Prev deleted row's address .
00 00 00 00 00 00 00 50 : 8B, Next deleted row's address .
---------------------------------------------------------
這裡意思是:
上一個被刪除的行的地址是: 0x0000000, 就是我們的第1行ADDR
下一個被刪除的行的地址是: 0x0000050, 就是我們的第5行ADDR.
我們來看第5行資料.
前20位的具體含義如下: (第5行)
---------------------------------------------------------
00 : 1B, FLAG, 0X00 -> Deleted
00 00 18 : 3B, Block_len ,0X18 -> 24B
00 00 00 00 00 00 00 28 : 8B,Prev deleted row's address .
ff ff ff ff ff ff ff ff : 8B,Next deleted row's address .
---------------------------------------------------------
這裡說:
上一個被刪除的行的地址是: 0x0000028, 就是我們的第3行ADDR
下一個被刪除的行的地址是: 0xfffffff, 就是說檔案結尾.

2.3 在刪除過程中,MYISAM是如何處理碎片的
如果相鄰的行被刪除,MYSQL如何處理
2.3.0 首先來製造一些資料
drop table if exists heyf ;
create table heyf (id int , name varchar(50)) type myisam ;
insert into heyf values (1,'aaaaa'),(2,'bbbbb') ,(45,'ssssss') ,(65,'dddddddd'),(23,'hhhhhhhhhhhh'),(5,'jjjjjjj');
system hexdump /opt/mysql/data/test/heyf.MYD;
delete from heyf where id in (45) ;
system hexdump /opt/mysql/data/test/heyf.MYD;
------------------------------------------------
0000000 0003 040c fc00 0001 0000 6105 6161 6161
0000010 0000 0000 0003 040c fc00 0002 0000 6205
0000020 6262 6262 0000 0000 0000 1400 ffff ffff
0000030 ffff ffff ffff ffff ffff ffff 0003 010f
0000040 fc00 0041 0000 6408 6464 6464 6464 0064
0000050 0003 0113 fc00 0017 0000 680c 6868 6868
0000060 6868 6868 6868 0068 0003 020e fc00 0005
0000070 0000 6a07 6a6a 6a6a 6a6a 0000
------------------------------------------------
在這裡我們刪除了第3行資料:
-----------------------------------------------------
ROW3: 0000 1400 ffff ffff ffff ffff ffff ffff ffff ffff
-----------------------------------------------------
FLAG+LEN PREV_DEL_ADDRESS NEXT_DEL_ADDRESS
DELETED ROWS LIST 指標的方向:
START END

2.3.1 新刪除的行在空行(已經刪除的行)的後面
繼續上面的測試:
delete from heyf where id in (65) ;
system hexdump /opt/mysql/data/test/heyf.MYD;
------------------------------------------------
0000000 0003 040c fc00 0001 0000 6105 6161 6161
0000010 0000 0000 0003 040c fc00 0002 0000 6205
0000020 6262 6262 0000 0000 0000 1400 ffff ffff
0000030 ffff ffff 0000 0000 0000 3c00 0000 1400
0000040 0000 0000 0000 2800 ffff ffff ffff ffff
0000050 0003 0113 fc00 0017 0000 680c 6868 6868
0000060 6868 6868 6868 0068 0003 020e fc00 0005
0000070 0000 6a07 6a6a 6a6a 6a6a 0000
------------------------------------------------
我們刪除了第4行資料(在第3行後面),
現在被刪除的行有: ROW3,ROW4,我們來看一下:
-----------------------------------------------------
ROW3: 0000 1400 ffff ffff ffff ffff 0000 0000 0000 3c00
ROW4: 0000 1400 0000 0000 0000 2800 ffff ffff ffff ffff
-----------------------------------------------------
FLAG+LEN PREV_DEL_ADDRESS NEXT_DEL_ADDRESS
首先ROW3的資料首先了變化,他的NEXT_DEL_ADDRESS 指向了ROW4的地址.
而ROW4的資料: 他的PREV_DEL_ADDRESS指向了ROW3的地址.NEXT_DEL_ADDRESS指向FF.
DELETED ROWS LIST 指標的方向:
START ROW4 -> END
這個我們可以把它理解成為一個雙向鏈條.
(不相鄰的行也一樣處理,有興趣的同學可以自已測一下)

2.3.2 新刪除的行在空行(已經刪除的行)的前面
繼續上面的測試:
delete from heyf where id in (2) ;
system hexdump /opt/mysql/data/test/heyf.MYD;
------------------------------------------------
0000000 0003 040c fc00 0001 0000 6105 6161 6161
0000010 0000 0000 0000 2800 0000 0000 0000 3c00
0000020 ffff ffff ffff ffff 0000 1400 ffff ffff
0000030 ffff ffff 0000 0000 0000 3c00 0000 1400
0000040 ffff ffff ffff ffff 0000 0000 0000 1400
0000050 0003 0113 fc00 0017 0000 680c 6868 6868
0000060 6868 6868 6868 0068 0003 020e fc00 0005
0000070 0000 6a07 6a6a 6a6a 6a6a 0000
------------------------------------------------

我們又刪除了第2行資料(在第3行前面),
現在被刪除的行有(根據先後順序): ROW3,ROW4,ROW2 ,我們來看一下:
-----------------------------------------------------
ROW2: 0000 2800 0000 0000 0000 3c00 ffff ffff ffff ffff
ROW3: 0000 1400 ffff ffff ffff ffff 0000 0000 0000 3c00
ROW4: 0000 1400 ffff ffff ffff ffff 0000 0000 0000 1400
-----------------------------------------------------
FLAG+LEN PREV_DEL_ADDRESS NEXT_DEL_ADDRESS
我們發現,MYISAM把ROW2的BLOCK_LEN設成了0X28 -> 40B ,也就是他認為ROW2,ROW3這兩行是一個連續的可用空間.
而ROW4的PREV_DEL_ADDRESS和 NEXT_DEL_ADDRESS都發生了變化.
DELETED ROWS LIST 指標鏈變成了:
START "ROW2,ROW3" -> END
^ | |
|-----
這也就是說,MYISAM在DELETE的同時,會對連續的可用空間進行整理.(條件是新刪除行的物理位置必須在空行的前面)
再接著刪除第1行, 按上面的推測,1,2,3應該是連續的塊了.
delete from heyf where id in (1) ;
system hexdump /opt/mysql/data/test/heyf.MYD;
------------------------------------------------
0000000 0000 3c00 0000 0000 0000 3c00 ffff ffff
0000010 ffff ffff 0000 2800 0000 0000 0000 3c00
0000020 0000 0000 0000 0000 0000 1400 ffff ffff
0000030 ffff ffff 0000 0000 0000 3c00 0000 1400
0000040 ffff ffff ffff ffff 0000 0000 0000 0000
0000050 0003 0113 fc00 0017 0000 680c 6868 6868
0000060 6868 6868 6868 0068 0003 020e fc00 0005
0000070 0000 6a07 6a6a 6a6a 6a6a 0000
------------------------------------------------
讀出各行資料:
-----------------------------------------------------
ROW1: 0000 3c00 0000 0000 0000 3c00 ffff ffff ffff ffff
ROW2: 0000 2800 0000 0000 0000 3c00 0000 0000 0000 0000
ROW3: 0000 1400 ffff ffff ffff ffff 0000 0000 0000 3c00
ROW4: 0000 1400 ffff ffff ffff ffff 0000 0000 0000 0000
-----------------------------------------------------
我們發現ROW1的BLOCK_LEN設成了0X3C -> 60B ,也就是他認為ROW1,ROW2,ROW3這3行是一個連續的可用空間.
而ROW4的NEXT_DEL_ADDRESS也發生了變化,指向ROW1.
DELETED ROWS LIST 指標鏈變成了:
START "ROW1,ROW2,ROW3" -> END
* ^ * | |
* |-----****>>>****
3. 小結
3.1.行被刪除後,在其原物理位置還佔20B,用來標識該行被刪除以及刪除鏈的PREV_DEL_ADDRESS和NEXT_DEL_ADDRESS.
具體標識和含義如下:
FLAG:00 (1B) + BLOCK_LEN (3B) + PREV_DEL_ADDRESS(8B) + NEXT_DEL_ADDRESS(8B)
3.2.如果新刪除行的物理位置後面剛好有空行(以前刪除的). 那麼這兩個空間會被合併成一個連續的塊.

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/703656/viewspace-1019041/,如需轉載,請註明出處,否則將追究法律責任。

相關文章