[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.

总结:
--//仅仅通过一些简单的例子演示这个过程,也许许多情况下更加复杂.

[20190101]块内重整.txt的更多相关文章

  1. 【Python文件处理】递归批处理文件夹子目录内所有txt数据

    因为有个需求,需要处理文件夹内所有txt文件,将txt里面的数据筛选,重新存储. 虽然手工可以做,但想到了python一直主张的是自动化测试,就想试着写一个自动化处理数据的程序. 一.分析数据格式 需 ...

  2. Firefox 对条件判断语句块内的函数声明的处理与其他浏览器有差异

    标准参考 函数声明和函数表达式 定义一个函数有两种途径:函数声明和函数表达式. 函数声明: function Identifier ( FormalParameterList opt ) { Func ...

  3. C语言块内变量回收问题

    之前有一个错误认识,错误的认为局部变量的回收是发生在函数返回时.其实在块结束时块内使用的内容就会被回收了. 以下的实例说明了问题 ]; ; i < ; ++i) { int item = i; ...

  4. HTML div块内剧中

    在HTML中有一个块内元素剧中的方法   那就是margin:0 auto; 剧中前 剧中后

  5. 【css对齐】块内或者行内图片与文字居中对齐最靠谱的方式!

    块内或者行内图片与文字居中对齐最靠谱的方式! 做图片与文字在一行的按钮时候最常用到,总结了一个靠谱的方法,终于可以完美的对齐下面给个代码 首先是html: <p class="btnU ...

  6. pins-模块内的代码及资源隔离方案

    随着项目的不断迭代,复杂的业务模块及项目自身的基础技术组件迅速扩张,以往基于单个模块的项目往往显得过于臃肿.代码目录结构,包名混乱,代码模块职责不清晰,耦合度高,不便维护.基础公共组件没有抽取并剥离干 ...

  7. 将多个文件夹内的txt合并

    import os import re def text_create(name): """ 创建txt文件夹 """ desktop_pa ...

  8. python实现将文件夹内所有txt文件合并成一个文件

    新建一个文件夹命名为yuliao,把所有txt文件放进去就ok啦!注意路径中‘/’,windows下路径不是这样. #coding=utf-8  import os #获取目标文件夹的路径 filed ...

  9. 利用MFC在控件内将txt中的数据画图

    1:采集txt文件中的数据测试程序如下: #include "stdafx.h" #include <fstream> #include "iostream& ...

随机推荐

  1. 五分钟轻松了解Hbase面向列的存储

    说明:从严格的列式存储的定义来看,Hbase并不属于列式存储,有人称它为面向列的存储,请各位看官注意这一点. 行式存储 传统的数据库是关系型的,且是按行来存储的.如下图: 其中只有张三把一行数据填满了 ...

  2. python使用多进程

    python多线程适合IO密集型场景,而在CPU密集型场景,并不能充分利用多核CPU,而协程本质基于线程,同样不能充分发挥多核的优势. 针对计算密集型场景需要使用多进程,python的multipro ...

  3. 阿里云IoT

    阿里云IoT: https://iot.aliyun.com/

  4. PHP开发中bcscale timezone charset的设定

    关于php的开发,有几个细节设定,需要知悉下:在项目的init.php 或 index.php 或 api.php 1. bcscale(18); 表示bc函数,默认小数点位数. 没有设定的话,默认为 ...

  5. entity framework codefirst 用户代码未处理DataException,InnerException基础提供程序在open上失败,数据库生成失败

    警告:这是一个入门级日志,如果你很了解CodeFirst,那请绕道 背景:这篇日志记录我使用Entity FrameWork CodeFirst时出现的错误和解决问题的过程,虽然有点曲折……勿喷 备注 ...

  6. vs 中引用自己创建程序集出现小叹号

    出现的问题: 原因是.net frame work版本不一致 解决方法: 项目单击右键-->属性: 改为与你要引用的项目的程序集的版本一致即可

  7. SQL去除数据库表中tab、空格、回车符等特殊字符的解决方法

    按照ASCII码, SELECT char(64) 例如64 对应 @,则 ), 'kk'); 则结果为 abckkqq.com 依此类推, 去掉其他特殊符号,参考ASCII码对照表, 去掉tab符号 ...

  8. c# 接口的协变和逆变

    如果派生类只是用于输出值,那么这种结构化的委托有效性之间的常数关系叫做协变 就是创建一个派生类委托对象 让派生类赋值给基类对象 协变关键字out 对期望传入基类时允许传入派生对象的特性叫逆变  逆变关 ...

  9. 【Java每日一题】20170307

    20170306问题解析请点击今日问题下方的“[Java每日一题]20170307”查看(问题解析在公众号首发,公众号ID:weknow619) package Mar2017; public cla ...

  10. C#设计模式之二十职责链模式(Chain of Responsibility Pattern)【行为型】

    一.引言 今天我们开始讲“行为型”设计模式的第八个模式,该模式是[职责链模式],英文名称是:Chain of Responsibility Pattern.让我们看看现实生活中的例子吧,理解起来可能更 ...