[20190102]塊內重整2.txt

lfree發表於2019-01-02

[20190102]塊內重整2.txt


--//我不知道用什麼術語表達這樣的情況,我僅僅一次開會對方這麼講,我現在也照用這個術語.

--//當dml插入資料到資料塊時,預留一定的空間(pctfree的百分比)不再插入.保留一些空間主要目的為了ITL的增加,以及update時空間增長.

--//避免大量的行遷移情況出現.

--//當到達頂部時,會出現一次塊內重整(也有叫塊內重組).透過演示瞭解這個過程,同時瞭解資料塊內一些資訊的變化.

--//昨天的測試忘記跟蹤對應資料塊不同情況下的kdbh.kdbhfrre變化,重新測試看看.

--//而且當時在不同會話插入,應該在同一會話插入也應該能演示出來.


1.環境:

SCOTT@book> @ ver1

PORT_STRING                    VERSION        BANNER

------------------------------ -------------- --------------------------------------------------------------------------------

x86_64/Linux 2.4.xx            11.2.0.4.0     Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production


SCOTT@book> create table t as select rownum id,to_char(rownum)||lpad('x',800,'x') name from dual connect by level<=8;

Table created.



SCOTT@book> @desc t

           Name  Null?    Type

           ----- -------- -------------

    1      ID             NUMBER

    2      NAME           VARCHAR2(840)

--//name 定義VARCHAR2(840).


SCOTT@book> select rowid ,id from t;

ROWID                      ID

------------------ ----------

AAAWFjAAEAAAAIjAAA          1

AAAWFjAAEAAAAIjAAB          2

AAAWFjAAEAAAAIjAAC          3

AAAWFjAAEAAAAIjAAD          4

AAAWFjAAEAAAAIjAAE          5

AAAWFjAAEAAAAIjAAF          6

AAAWFjAAEAAAAIjAAG          7

AAAWFjAAEAAAAIjAAH          8

8 rows selected.

--//8k的資料塊.有8條記錄在一個塊中.


SCOTT@book> @rowid AAAWFjAAEAAAAIjAAA

    OBJECT       FILE      BLOCK        ROW ROWID_DBA            DBA                  TEXT

---------- ---------- ---------- ---------- -------------------- -------------------- ----------------------------------------

     90467          4        547          0  0x1000223           4,547                alter system dump datafile 4 block 547 ;


SCOTT@book> alter system checkpoint ;

System altered.


2.透過bbed觀察:

BBED> set dba 4,547

        DBA             0x01000223 (16777763 4,547)


BBED> map

 File: /mnt/ramdisk/book/users01.dbf (4)

 Block: 547                                   Dba:0x01000223

------------------------------------------------------------

 KTB Data Block (Table/Cluster)

 struct kcbh, 20 bytes                      @0

 struct ktbbh, 96 bytes                     @20

 struct kdbh, 14 bytes                      @124

 struct kdbt[1], 4 bytes                    @138

 sb2 kdbr[8]                                @142

 ub1 freespace[1550]                        @158

 ub1 rowdata[6480]                          @1708

 ub4 tailchk                                @8188

--//還有freespace=1550.


BBED> p kdbr

sb2 kdbr[0]                                 @142      7254

sb2 kdbr[1]                                 @144      6444

sb2 kdbr[2]                                 @146      5634

sb2 kdbr[3]                                 @148      4824

sb2 kdbr[4]                                 @150      4014

sb2 kdbr[5]                                 @152      3204

sb2 kdbr[6]                                 @154      2394

sb2 kdbr[7]                                 @156      1584


BBED> x /rnc *kdbr[0]

rowdata[5670]                               @7378

-------------

flag@7378: 0x2c (KDRHFL, KDRHFF, KDRHFH)

lock@7379: 0x00

cols@7380:    2


col    0[2] @7381: 1

col  1[801] @7384: 1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ..trunc.


--//注這裡的偏移是相對偏移 7254+124(kdbh地址) = 7378.

--//共佔用3+1+2+3+801 = 810,注前面有1個位元組保持長度指示器.另外注意字串長度大於250,需要使用3個位元組儲存長度指示器.

--//可以從資料的偏移量可以看出資料是從塊底開始插入的.當前剩餘空間是1550.


BBED> p kdbh.kdbhfrre

sb2 kdbhfrre                                @128     -1

--//kdbh.kdbhfrre=-1,也就是這個時候沒有刪除記錄的情況,或者沒有可重用的行目錄.


3.繼續測試,刪除部分資料:

--//先刪除一部分資料,僅僅打上標識標識刪除.

SCOTT@book> delete from t where id in (1,3,6,7);

4 rows deleted.


SCOTT@book> commit ;

Commit complete.


SCOTT@book> alter system checkpoint ;

System altered.


--//透過bbed觀察,執行前打入set dba 4,547,這樣才會從磁碟重新讀取資料塊.不然看到是當前快取資料塊的資訊,以下測試注意這個問

--//題.

BBED> set dba 4,547

        DBA             0x01000223 (16777763 4,547)


BBED> map

 File: /mnt/ramdisk/book/users01.dbf (4)

 Block: 547                                   Dba:0x01000223

------------------------------------------------------------

 KTB Data Block (Table/Cluster)

 struct kcbh, 20 bytes                      @0

 struct ktbbh, 96 bytes                     @20

 struct kdbh, 14 bytes                      @124

 struct kdbt[1], 4 bytes                    @138

 sb2 kdbr[8]                                @142

 ub1 freespace[1550]                        @158

 ub1 rowdata[6480]                          @1708

 ub4 tailchk                                @8188

--//刪除部分記錄,freespace空間保持不變.


BBED> p kdbr

sb2 kdbr[0]                                 @142      7254

sb2 kdbr[1]                                 @144      6444

sb2 kdbr[2]                                 @146      5634

sb2 kdbr[3]                                 @148      4824

sb2 kdbr[4]                                 @150      4014

sb2 kdbr[5]                                 @152      3204

sb2 kdbr[6]                                 @154      2394

sb2 kdbr[7]                                 @156      1584


BBED> x /rnc *kdbr[0]

rowdata[5670]                               @7378

-------------

flag@7378: 0x3c (KDRHFL, KDRHFF, KDRHFD, KDRHFH)

lock@7379: 0x02

cols@7380:    0

--//oracle僅僅修改flag從2c變成3c,加入了KDRHFD標識,表示刪除,這個時候可以透過bbed修復.


BBED> p kdbh.kdbhfrre

sb2 kdbhfrre                                @128     -1

--//kdbh.kdbhfrre=-1,沒有變化.


4.然後修改一部分資料看看:

SCOTT@book> update t set name=lpad('a',811,'a') where id=2;

1 row updated.


SCOTT@book> commit ;

Commit complete.


SCOTT@book> alter system checkpoint ;

System altered.


--//我修改的長度與原來不等,這樣增加長度增加10個位元組.這樣還剩下1550-820 = 730位元組.

--//驗證看看:

BBED> map

 File: /mnt/ramdisk/book/users01.dbf (4)

 Block: 547                                   Dba:0x01000223

------------------------------------------------------------

 KTB Data Block (Table/Cluster)

 struct kcbh, 20 bytes                      @0

 struct ktbbh, 96 bytes                     @20

 struct kdbh, 14 bytes                      @124

 struct kdbt[1], 4 bytes                    @138

 sb2 kdbr[8]                                @142

 ub1 freespace[730]                         @158

 ub1 rowdata[7300]                          @888

 ub4 tailchk                                @8188

--//freespace=730,ok正確!!


BBED> p kdbr

sb2 kdbr[0]                                 @142      7254

sb2 kdbr[1]                                 @144      764

sb2 kdbr[2]                                 @146      5634

sb2 kdbr[3]                                 @148      4824

sb2 kdbr[4]                                 @150      4014

sb2 kdbr[5]                                 @152      3204

sb2 kdbr[6]                                 @154      2394

sb2 kdbr[7]                                 @156      1584

--//kdbr[1] 指向新的位置.對應id=2的記錄.其它沒有變化.


BBED> p kdbh.kdbhfrre

sb2 kdbhfrre                                @128     -1

--//kdbh.kdbhfrre=-1,沒有變化.


BBED> x /rnc *kdbr[1]

rowdata[0]                                  @888

----------

flag@888:  0x2c (KDRHFL, KDRHFF, KDRHFH)

lock@889:  0x03

cols@890:     2


col    0[2] @891: 2

col  1[811] @894: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..trunc..

--//如果繼續修改記錄,長度消耗大於730並且長度與原來不一樣,這樣就會出現塊內重整的情況:


SCOTT@book> update t set name=lpad('b',811,'b') where id=4;

1 row updated.


SCOTT@book> commit ;

Commit complete.


SCOTT@book> alter system checkpoint ;

System altered.


BBED> set dba 4,547

        DBA             0x01000223 (16777763 4,547)


BBED> map

 File: /mnt/ramdisk/book/users01.dbf (4)

 Block: 547                                   Dba:0x01000223

------------------------------------------------------------

 KTB Data Block (Table/Cluster)

 struct kcbh, 20 bytes                      @0

 struct ktbbh, 96 bytes                     @20

 struct kdbh, 14 bytes                      @124

 struct kdbt[1], 4 bytes                    @138

 sb2 kdbr[8]                                @142

 ub1 freespace[4762]                        @158

 ub1 rowdata[3268]                          @4920

 ub4 tailchk                                @8188

-//freespace變成了4762,出現一次塊內重整,而且收回刪除記錄的空間.


BBED> p kdbr

sb2 kdbr[0]                                 @142      8062

sb2 kdbr[1]                                 @144      7242

sb2 kdbr[2]                                 @146      7240

sb2 kdbr[3]                                 @148      4796

sb2 kdbr[4]                                 @150      6430

sb2 kdbr[5]                                 @152      6428

sb2 kdbr[6]                                 @154      6426

sb2 kdbr[7]                                 @156      5616


BBED> p kdbh.kdbhfrre

sb2 kdbhfrre                                @128     -1

--//kdbh.kdbhfrre=-1,沒有變化.


--//可以發現行目錄發生變化對比前面的情況,做了整理,整體下移.我前面刪除的記錄是id in (1,3,6,7);

--//id=6,7的記錄應該對應kdbr[5],kdbr[6],可以發現記錄的偏移地址6428,6426,挨的很近.

--//可以大致猜測它的演算法,移動除kdbr[3](對應id=4)的記錄下移騰出空間,你可以發現kdbr[3]指向的偏移是當前最小的.


BBED> x /rnc *kdbr[5]

rowdata[1632]                               @6552

-------------

flag@6552: 0x3c (KDRHFL, KDRHFF, KDRHFD, KDRHFH)

lock@6553: 0x02

cols@6554:    0


BBED> x /rnc *kdbr[6]

rowdata[1630]                               @6550

-------------

flag@6550: 0x3c (KDRHFL, KDRHFF, KDRHFD, KDRHFH)

lock@6551: 0x02

cols@6552:    0


BBED> dump /v offset 6550 count 20

 File: /mnt/ramdisk/book/users01.dbf (4)

 Block: 547                               Offsets: 6550 to 6569                            Dba:0x01000223

-----------------------------------------------------------------------------------------------------------

 3c023c02 2c000202 c106fe21 03357878 78787878                            l <.<.,......!.5xxxxxx

 <32 bytes per line>

--//僅僅保留2個位元組.這也很容易理解打上刪除標識後,為什麼bbed不顯示後面的資料資訊(如果能顯示的話)


BBED> x /rnc *kdbr[0]

rowdata[3266]                               @8186

-------------

flag@8186: 0x3c (KDRHFL, KDRHFF, KDRHFD, KDRHFH)

lock@8187: 0x02

cols@8188:    0


BBED> dump /v count 20

 File: /mnt/ramdisk/book/users01.dbf (4)

 Block: 547                               Offsets: 8186 to 8191                            Dba:0x01000223

-----------------------------------------------------------------------------------------------------------

 3c020206 c4dc                                                           l <.....

     ~~~~~~~~~

 <32 bytes per line>


--//後面4個位元組是taichk的資訊.這個時候按照以前使用bbed修復刪除記錄的方法是無用的.因為對應的記錄資訊已經被覆蓋了.


5.繼續插入記錄看看.

SCOTT@book> insert into  t values(9,to_char(9)||lpad('y',800,'y'));

1 row created.


SCOTT@book> commit ;

Commit complete.


SCOTT@book> alter system checkpoint ;

System altered.

--//當前塊已經空出許多空間,可以繼續插入資料,看看這時的情況:

BBED> set dba 4,547

        DBA             0x01000223 (16777763 4,547)


BBED> map

 File: /mnt/ramdisk/book/users01.dbf (4)

 Block: 547                                   Dba:0x01000223

------------------------------------------------------------

 KTB Data Block (Table/Cluster)

 struct kcbh, 20 bytes                      @0

 struct ktbbh, 96 bytes                     @20

 struct kdbh, 14 bytes                      @124

 struct kdbt[1], 4 bytes                    @138

 sb2 kdbr[9]                                @142

 ub1 freespace[3950]                        @160

 ub1 rowdata[4078]                          @4110

 ub4 tailchk                                @8188

--//freespace在減少,前面4762,現在freespace=3950.

--//減少4762-3950 = 812,比前面多消耗2個位元組是因為行目錄增加1行.從7->8,這樣多消耗2個位元組.


BBED> p kdbr

sb2 kdbr[0]                                 @142      2

sb2 kdbr[1]                                 @144      7242

sb2 kdbr[2]                                 @146      5

sb2 kdbr[3]                                 @148      4796

sb2 kdbr[4]                                 @150      6430

sb2 kdbr[5]                                 @152      6

sb2 kdbr[6]                                 @154     -1

sb2 kdbr[7]                                 @156      5616

sb2 kdbr[8]                                 @158      3986

--//可以發現當前塊又插入1條.


BBED> p kdbh.kdbhfrre

sb2 kdbhfrre                                @128      0

--//kdbh.kdbhfrre=0.已經從-1變成0.


BBED> x /rnc *kdbr[8]

rowdata[0]                                  @4110

----------

flag@4110: 0x2c (KDRHFL, KDRHFF, KDRHFH)

lock@4111: 0x02

cols@4112:    2


col    0[2] @4113: 9

col  1[801] @4116: 9yyyyyyyyyyyyyyyyyyyyyy...trunc..


--//注意看前面的kdbr[0],kdbr[2],kdbr[5],kdbr[6]對應的偏移量已經發生變化,變成2,5,6,-1,透過偏移量連結起來.

--//也就是這個這時的偏移量指向的地址根本不是rowdate區域.

--//我不知道是否可以得出這樣結論:如果kdbr指向的值如果小於當前的行目錄數量(9),這些行對應的記錄應該是刪除的.

--//理論講這時對應記錄很難恢復,已經覆蓋了.

--//另外注意這時kdbh.kdbhfrre=0,也就是指向kdbr[0].


6.測試重用的情況:

--//是否會重用呢?繼續插入看看.

SCOTT@book> insert into  t values(10,to_char(10)||lpad('x',800,'x'));

1 row created.


SCOTT@book> commit ;

Commit complete.


SCOTT@book> alter system checkpoint ;

System altered.


BBED> set dba 4,547

        DBA             0x01000223 (16777763 4,547)


BBED> map

 File: /mnt/ramdisk/book/users01.dbf (4)

 Block: 547                                   Dba:0x01000223

------------------------------------------------------------

 KTB Data Block (Table/Cluster)

 struct kcbh, 20 bytes                      @0

 struct ktbbh, 96 bytes                     @20

 struct kdbh, 14 bytes                      @124

 struct kdbt[1], 4 bytes                    @138

 sb2 kdbr[9]                                @142

 ub1 freespace[3139]                        @160

 ub1 rowdata[4889]                          @3299

 ub4 tailchk                                @8188

--//freespace=3139.3950-3139 = 811,比前面多1個自己,是因為插入的name=to_char(10)||lpad('x',800,'x'),多了1個位元組.


BBED> p kdbr

sb2 kdbr[0]                                 @142      3175

sb2 kdbr[1]                                 @144      7242

sb2 kdbr[2]                                 @146      5

sb2 kdbr[3]                                 @148      4796

sb2 kdbr[4]                                 @150      6430

sb2 kdbr[5]                                 @152      6

sb2 kdbr[6]                                 @154     -1

sb2 kdbr[7]                                 @156      5616

sb2 kdbr[8]                                 @158      3986


BBED> p kdbh.kdbhfrre

sb2 kdbhfrre                                @128      2


--//oracle在插入時能快速定位到kdbr[0],因為當時的kdbh.kdbhfrre=0,能很快定位到行目錄kdbr[0]的位置,並且插入後修改

--//kdbh.kdbhfrre=2,指向下一個能插入的位置.


--//實際上到這裡可以刪除連結串列的頭記錄在kdbh.kdbhfrre中,當前是2.如果繼續插入,變成5就可以驗證我的判斷。

SCOTT@book> insert into  t values(11,to_char(11)||lpad('w',800,'w'));

1 row created.


SCOTT@book> commit ;

Commit complete.


SCOTT@book> alter system checkpoint ;

System altered.



BBED> map

 File: /mnt/ramdisk/book/users01.dbf (4)

 Block: 547                                   Dba:0x01000223

------------------------------------------------------------

 KTB Data Block (Table/Cluster)

 struct kcbh, 20 bytes                      @0

 struct ktbbh, 96 bytes                     @20

 struct kdbh, 14 bytes                      @124

 struct kdbt[1], 4 bytes                    @138

 sb2 kdbr[9]                                @142

 ub1 freespace[2328]                        @160

 ub1 rowdata[5700]                          @2488

 ub4 tailchk                                @8188

--//freespace繼續減少。3139-2328 = 811.


BBED> p kdbr

sb2 kdbr[0]                                 @142      3175

sb2 kdbr[1]                                 @144      7242

sb2 kdbr[2]                                 @146      2364

sb2 kdbr[3]                                 @148      4796

sb2 kdbr[4]                                 @150      6430

sb2 kdbr[5]                                 @152      6

sb2 kdbr[6]                                 @154     -1

sb2 kdbr[7]                                 @156      5616

sb2 kdbr[8]                                 @158      3986

--//插入記錄佔用了kdbr[2]。


BBED> p kdbh.kdbhfrre

sb2 kdbhfrre                                @128      5

--//變成kdbh.kdbhfrre=5,驗證自己的判斷。

--//這樣透過kdbr[5],裡面記錄的是6,繼續插入可以很容易定位行目錄,最後記錄-1,表示已經沒有了,回到初始的狀態.


SCOTT@book> select rowid,id,substr(name,1,10) c10  from t;

ROWID                      ID C10

------------------ ---------- ----------

AAAWFjAAEAAAAIjAAA         10 10xxxxxxxx

AAAWFjAAEAAAAIjAAB          2 aaaaaaaaaa

AAAWFjAAEAAAAIjAAC         11 11wwwwwwww

AAAWFjAAEAAAAIjAAD          4 bbbbbbbbbb

AAAWFjAAEAAAAIjAAE          5 5xxxxxxxxx

AAAWFjAAEAAAAIjAAH          8 8xxxxxxxxx

AAAWFjAAEAAAAIjAAI          9 9yyyyyyyyy

7 rows selected.


總結:

--//僅僅透過一些簡單的例子基本演示整個過程,也許許多情況下更加複雜.

--//不過已經足以說明這整個過程.


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

相關文章