[20190101]块内重整.txt

来源:这里教程网 时间:2026-03-03 12:50:00 作者:

[20190101]块内重整.txt --//我不知道用什么术语表达这样的情况,我仅仅一次开会对方这么讲,我现在也照用这个术语. --//当dml插入数据到数据块时,预留一定的空间(pctfree的百分比)不再插入.保留一些空间主要目的为了ITL的增加,以及update时空间增长. --//避免大量的行迁移情况出现. --//当到达顶部时,会出现一次块内重整(也有叫块内重组).通过演示了解这个过程. 1.环境: SCOTT@test01p> @ ver1 PORT_STRING          VERSION    BANNER                                                                       CON_ID -------------------- ---------- ---------------------------------------------------------------------------- ------ IBMPC/WIN_NT64-9.1.0 12.2.0.1.0 Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production      0 SCOTT@test01p> create table t as select rownum id,to_char(rownum)||lpad('x',800,'x') name from dual connect by level<=8; Table created. SCOTT@test01p> @desc t Name Null?    Type ---- -------- ------------- ID            NUMBER NAME          VARCHAR2(840) --//name 定义VARCHAR2(840). SCOTT@test01p> select rowid ,id from t; ROWID              ID ------------------ -- AAAF61AALAAAACrAAA  1 AAAF61AALAAAACrAAB  2 AAAF61AALAAAACrAAC  3 AAAF61AALAAAACrAAD  4 AAAF61AALAAAACrAAE  5 AAAF61AALAAAACrAAF  6 AAAF61AALAAAACrAAG  7 AAAF61AALAAAACrAAH  8 8 rows selected. --//有8条记录在一个块中. SCOTT@test01p> @rowid AAAF61AALAAAACrAAA     OBJECT       FILE      BLOCK        ROW ROWID_DBA            DBA                  TEXT ---------- ---------- ---------- ---------- -------------------- -------------------- ----------------------------------------      24245         11        171          0  0x2C000AB           11,171               alter system dump datafile 11 block 171 SCOTT@test01p> alter system checkpoint ; System altered. 2.通过bbed观察: BBED> set dba 11,172         DBA             0x02c000ac (46137516 11,172) --//windows版本block+1. BBED> map  File: D:\APP\ORACLE\ORADATA\TEST\TEST01P\USERS01.DBF (11)  Block: 172                                   Dba:0x02c000ac ------------------------------------------------------------  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 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. 3.继续测试,删除部分数据: --//先删除一部分数据,仅仅打上标识标识删除. SCOTT@test01p> delete from t where id in (1,3,6,7); 4 rows deleted. SCOTT@test01p> commit ; Commit complete. SCOTT@test01p> alter system checkpoint ; System altered. --//通过bbed观察: BBED> map  File: D:\APP\ORACLE\ORADATA\TEST\TEST01P\USERS01.DBF (11)  Block: 172                                   Dba:0x02c000ac ------------------------------------------------------------  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 --//仅仅flag从2c变成3c,加入了KDRHFD标识. 4.然后修改一部分数据看看: SCOTT@test01p> update t set name=lpad('a',811,'a') where id=2; 1 row updated. SCOTT@test01p> commit ; Commit complete. SCOTT@test01p> alter system checkpoint ; System altered. --//我修改的长度与原来不等,这样增加长度增加10个字节.这样还剩下1550-820 = 730字节. --//验证看看: BBED> map  File: D:\APP\ORACLE\ORADATA\TEST\TEST01P\USERS01.DBF (11)  Block: 172                                   Dba:0x02c000ac ------------------------------------------------------------  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 --//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> 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: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa... trunc.. --//如果继续修改记录,长度消耗大于730并且长度与原来不一样,这样就会出现块内重整的情况: SCOTT@test01p> update t set name=lpad('b',811,'b') where id=4; 1 row updated. SCOTT@test01p> commit ; Commit complete. SCOTT@test01p> alter system checkpoint ; System altered. BBED> map  File: D:\APP\ORACLE\ORADATA\TEST\TEST01P\USERS01.DBF (11)  Block: 172                                   Dba:0x02c000ac ------------------------------------------------------------  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 --//可以发现行目录发生变化对比前面的情况,做了整理,整体下移.我前面删除的记录是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: D:\APP\ORACLE\ORADATA\TEST\TEST01P\USERS01.DBF (11)  Block: 172                               Offsets: 6550 to 6569                            Dba:0x02c000ac -----------------------------------------------------------------------------------------------------------  3c023c02 2c000202 c106fe21 03357878 78787878                            l <.<.,...??.5xxxxxx <32 bytes per line> --//仅仅保留2个字节. 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: D:\APP\ORACLE\ORADATA\TEST\TEST01P\USERS01.DBF (11)  Block: 172                               Offsets: 8186 to 8191                            Dba:0x02c000ac -----------------------------------------------------------------------------------------------------------  3c020106 ff18                                                           l <.....  <32 bytes per line> --//这个时候按照以前使用bbed修复删除记录的方法是无用的.因为对应的记录信息已经被覆盖了. 5.继续插入记录看看. SCOTT@test01p> insert into  t values(9,to_char(9)||lpad('y',800,'y')); 1 row created. SCOTT@test01p> commit ; Commit complete. SCOTT@test01p> alter system checkpoint ; System altered. --//当前块已经空出许多空间,可以继续插入数据,看看这时的情况: BBED> map  File: D:\APP\ORACLE\ORADATA\TEST\TEST01P\USERS01.DBF (11)  Block: 172                                   Dba:0x02c000ac ------------------------------------------------------------  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=3950. 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> 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: 9yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy..trunc.. --//注意看前面的kdbr[0],kdbr[2],kdbr[5],kdbr[6]对应的偏移量(2,5,6,-1),通过偏移量链接起来. --//也就是这个这时的偏移量指向的地址根本不是rowdate区域. --//我不知道是否可以得出这样结论:如果kdbr指向的值如果小于当前的行目录数量(9),这些行对应的记录应该是删除的. --//理论讲这时对应记录很难恢复,已经覆盖了. 6.测试重用的情况: --//是否会重用呢?理论讲应该会重用.打开新的会话看看: SCOTT@test01p> insert into  t values(10,to_char(10)||lpad('x',800,'x')); 1 row created. SCOTT@test01p> commit ; Commit complete. SCOTT@test01p> alter system checkpoint; System altered. BBED> map  File: D:\APP\ORACLE\ORADATA\TEST\TEST01P\USERS01.DBF (11)  Block: 172                                   Dba:0x02c000ac ------------------------------------------------------------  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. 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 --//理论讲不同的会话不会插入相同的块,因为我建表比较特殊,使用ctas建立的. --//可以发现插入占用了kdbr[0]. BBED> x /rnc *kdbr[0] rowdata[0]                                  @3299 ---------- flag@3299: 0x2c (KDRHFL, KDRHFF, KDRHFH) lock@3300: 0x03 cols@3301:    2 col    0[2] @3302: 10 col  1[802] @3305: 10xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...trunc.. SCOTT@test01p> select rowid,id from t; ROWID                      ID ------------------ ---------- AAAF61AALAAAACrAAA         10 AAAF61AALAAAACrAAB          2 AAAF61AALAAAACrAAD          4 AAAF61AALAAAACrAAE          5 AAAF61AALAAAACrAAH          8 AAAF61AALAAAACrAAI          9 6 rows selected. --//oracle在插入时能快速定位到kdbr[0],估计在块内有相关记录. BBED> p  kdbh struct kdbh, 14 bytes                       @124    ub1 kdbhflag                             @124      0x00 (NONE)    b1 kdbhntab                              @125      1    b2 kdbhnrow                              @126      9    sb2 kdbhfrre                             @128      2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~       sb2 kdbhfsbo                             @130      36    sb2 kdbhfseo                             @132      3175    b2 kdbhavsp                              @134      3147    b2 kdbhtosp                              @136      3147 --//猜测记录在kdbh.kdbhfrre中,当前是2.如果继续插入,变成5就可以验证我的判断。 --//注意在新的会话插入(session 2): SCOTT@test01p> insert into  t values(11,to_char(11)||lpad('w',800,'w')); 1 row created. SCOTT@test01p> commit ; Commit complete. SCOTT@test01p> alter system checkpoint; System altered. BBED> map  File: D:\APP\ORACLE\ORADATA\TEST\TEST01P\USERS01.DBF (11)  Block: 172                                   Dba:0x02c000ac ------------------------------------------------------------  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继续减少。 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 struct kdbh, 14 bytes                       @124    ub1 kdbhflag                             @124      0x00 (NONE)    b1 kdbhntab                              @125      1    b2 kdbhnrow                              @126      9    sb2 kdbhfrre                             @128      5 --//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~变成5,验证的判断。    sb2 kdbhfsbo                             @130      36    sb2 kdbhfseo                             @132      2364    b2 kdbhavsp                              @134      2336    b2 kdbhtosp                              @136      2336 --//这样通过kdbr[5],里面记录的是6,继续插入可以很容易行目录,最后记录-1,表示已经没有了。 SCOTT@test01p> select rowid,id from t; ROWID                      ID ------------------ ---------- AAAF61AALAAAACrAAA         10 AAAF61AALAAAACrAAB          2 AAAF61AALAAAACrAAC         11 AAAF61AALAAAACrAAD          4 AAAF61AALAAAACrAAE          5 AAAF61AALAAAACrAAH          8 AAAF61AALAAAACrAAI          9 7 rows selected. 总结: --//仅仅通过一些简单的例子演示这个过程,也许许多情况下更加复杂.

相关推荐