[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. 总结: --//仅仅通过一些简单的例子基本演示整个过程,也许许多情况下更加复杂. --//不过已经足以说明这整个过程.
[20190102]块内重整2.txt
来源:这里教程网
时间:2026-03-03 12:49:49
作者:
编辑推荐:
下一篇:
相关推荐
-
雷神推出 MIX PRO II 迷你主机:基于 Ultra 200H,玻璃上盖 + ARGB 灯效
2 月 9 日消息,雷神 (THUNDEROBOT) 现已宣布推出基于英
-
制造商 Musnap 推出彩色墨水屏电纸书 Ocean C:支持手写笔、第三方安卓应用
2 月 10 日消息,制造商 Musnap 现已在海外推出一款 Oce
热文推荐
- 通过v$wait_chains视图诊断数据库hang和Contention
- RAC中的并行查询 DOP(Degree of Parallelism)
RAC中的并行查询 DOP(Degree of Parallelism)
26-03-03 - (重要)关于性能的几个主要动态视图
(重要)关于性能的几个主要动态视图
26-03-03 - Oracle date 和 timestamp 区别
Oracle date 和 timestamp 区别
26-03-03 - 深入理解Oracle调试事件:10046事件详解
深入理解Oracle调试事件:10046事件详解
26-03-03 - clusterware启动顺序——OHASD
clusterware启动顺序——OHASD
26-03-03 - Oracle自治数据仓库荣获2018年度创新产品奖
Oracle自治数据仓库荣获2018年度创新产品奖
26-03-03 - Word制作商务邀请函时怎么批量加入客户信息
Word制作商务邀请函时怎么批量加入客户信息
26-03-03 - ORACLE RAC clusterware
ORACLE RAC clusterware
26-03-03 - 沃趣微讲堂 | Oracle集群技术(五):集群中的三种心跳机制
沃趣微讲堂 | Oracle集群技术(五):集群中的三种心跳机制
26-03-03
