暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle中怎么导出索引数据块?

719

Oracle唯一索引和NULL空值之间的关系》文章写到了dump索引数据块,当我们需要看一些数据表、索引在块上的存储形式时,dump数据块是一种很直接的操作。

1. 创建测试表,含1000条数据,创建唯一索引,

    SQL> create table tt1 as select owner, object_id, object_name from dba_objects where rownum < 1001;
    Table created.

    SQL> create unique index idx_tt1_01 on tt1(owner, object_id, object_name);
    Index created.

    SQL> select count(*from tt1;
    COUNT(*)
    ----------
          1000

    可知他现在有5个叶子节点块,索引层高为2,

      SQL> select table_name,index_name,blevel,leaf_blocks,num_rows,last_analyzed,degree,status from user_indexes where table_name='TT1';
      TABLE_NAME INDEX_NAME BLEVEL LEAF_BLOCKS NUM_ROWS LAST_ANALYZED DEGREE STATUS
      ------------------------- ------------------------- ---------- ----------- ---------- ------------------ ---------------------------------------- --------
      TT1                       IDX_TT1_01                         1           5       1000 26-APR-22          1                                        VALID

      2. 查询索引的object_id,

        SQL> select object_id from user_objects where object_name='IDX_TT1_01';
        OBJECT_ID
        ----------
             73011

        3. 查询索引的treedump,此处的参数,就是索引的object_id,

          SQL> alter session set events 'immediate trace name treedump level 73011';
          Session altered.

          4. 到Oracle的trace路径下,可以直接cd,或者通过oradebug setmypid -> oradebug tracefile_name得到trace文件名,文件片段如下,可以看到有5个leaf,这和上面查询到的索引包含5个节点叶子块是一致的,

            ----- begin tree dump
            *** 2022-04-25T19:08:55.943552+08:00 (BISALPDB1(3))
            branch: 0x3002bbb 50342843 (0: nrow: 5, level: 1)
            leaf: 0x3002bbc 50342844 (-1: row:270.270 avs:837)
            leaf: 0x3002bbd 50342845 (0: row:225.225 avs:816)
            leaf: 0x3002bbe 50342846 (1: row:224.224 avs:840)
            leaf: 0x3002bbf 50342847 (2: row:234.234 avs:826)
            leaf: 0x3002bc0 50342850 (3: row:50.50 avs:6158)
            ----- end tree dump

            5. 我们可以dump其中一个索引叶子节点的数据块,例如第五个leaf,根据值50342850,通过dbms_utility包的data_block_address_file和data_block_address_block就可以得到这个索引叶子节点对应的数据文件号、数据块号,此处是12号文件的第11200个数据块,

              SQL> select dbms_utility.data_block_address_file(50342850from dual;
              DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(50342850)
              ----------------------------------------------
              12

              SQL> select dbms_utility.data_block_address_block(50342850from dual;
              DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(50342850)
              -----------------------------------------------
              11200

              6. dump索引数据块,

                SQL> alter system dump datafile 12 block 11200;
                System altered.

                从trace路径,就可以找到dump出来的文件,从以下位置开始,就是索引数据块的信息了,可以看到typ:2-INDEX表示他是个索引的数据块,

                  Block header dump:  0x03003b70
                   Object id on Block? Y
                  seg/obj: 0x11d33 csc: 0x0000000000f8b3d6 itc: 2 flg: E typ: 2 - INDEX
                  brn: 1 bdba: 0x3003b68 ver: 0x01 opc: 0
                  inc: 0 exflg: 0

                  Itl Xid Uba Flag Lck Scn/Fsc
                  0x01 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000
                  0x02 0x0008.00d.000007f7 0x024000f6.02bf.17 --U- 1 fsc 0x0000.00f8b3f1
                  Leaf block dump
                  ===============
                  header address 1981317220=0x76188064
                  kdxcolev 0
                  KDXCOLEV Flags = - - -
                  kdxcolok 0
                  kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
                  kdxconco 3
                  kdxcosdc 0
                  kdxconro 127
                  kdxcofbo 290=0x122
                  kdxcofeo 3435=0xd6b
                  kdxcoavs 3145
                  kdxlespl 0
                  kdxlende 0
                  kdxlenxt 0=0x0
                  kdxleprv 50346863=0x3003b6f
                  kdxledsz 6
                  kdxlebksz 8032
                  row#0[7990] flag: -------, lock: 0, len=42, data:(6): 03 00 2b d6 00 60
                  col 0; len 3; (3): 53 59 53
                  col 1; len 3; (3): c2 09 4d
                  col 2; len 25; (25):
                  53 59 53 5f 4c 4f 42 30 30 30 30 30 30 30 38 37 35 43 30 30 30 34 38 24 24
                  row#1[7949] flag: -------, lock: 0, len=41, data:(6): 03 00 2b d6 00 5f
                  col 0; len 3; (3): 53 59 53
                  col 1; len 3; (3): c2 09 4e
                  col 2; len 24; (24):
                  53 59 53 5f 49 4c 30 30 30 30 30 30 30 38 37 35 43 30 30 30 34 38 24 24
                  row#2[7907] flag: -------, lock: 0, len=42, data:(6): 03 00 2b d6 00 5e
                  col 0; len 3; (3): 53 59 53
                  col 1; len 3; (3): c2 09 4f
                  col 2; len 25; (25):
                  53 59 53 5f 4c 4f 42 30 30 30 30 30 30 30 38 37 35 43 30 30 30 34 39 24 24

                  ...

                  row#125[3449] flag: -------, lock: 0, len=32, data:(6): 03 00 2b d6 00 da
                  col 0; len 3; (3): 53 59 53
                  col 1; len 3; (3): c2 0b 02
                  col 2; len 15; (15): 41 50 50 4c 59 24 5f 43 44 52 5f 49 4e 46 4f
                  row#126[3435] flag: -------, lock: 2, len=14, data:(6): 03 00 2b d7 00 00
                  col 0; len 1; (1): 61
                  col 1; len 2; (2): c1 02
                  col 2; NULL
                  ----- end of leaf block Logical dump -----
                  ----- end of leaf block dump -----

                  以第126行为例,

                  第1行的data(6)是rowid,

                  第2-4行是第1-3列索引值,

                    row#125[3449] flag: -------, lock: 0, len=32, data:(6):  03 00 2b d6 00 da
                    col 0; len 3; (3): 53 59 53
                    col 1; len 3; (3): c2 0b 02
                    col 2; len 15; (15): 41 50 50 4c 59 24 5f 43 44 52 5f 49 4e 46 4f

                    1. rowid

                    "data:(6): 03 00 2b d6 00 da"是16进制的rowid,先转成二进制,

                      00000011 00000000 00101011 11010110 00000000 11011010

                      按照rowid组成规则,

                      (1) 对应文件编号,表明该行所在文件的编号,表空间的每一个文件标号都是唯一的,文件编号所占用的位置是10位,如下所示,

                        00000011 00,10进制的文件号:12

                        (2) 块编号,表明改行所在文件的块的位置块编号需要22位,如下所示,

                          000000 00101011 11010110,10进制的块号:11222

                          (3) 行编号,表明该行在行目录中的具体位置行编号需要16位,如下所示,

                            00000000 11011010,10进制的行号:218

                            即第126行的数据是在第10个数据文件中第11222个数据块的第218行。

                            2. 索引实际值

                              col 0; len 3; (3):  53 59 53
                              col 1; len 3; (3): c2 0b 02
                              col 2; len 15; (15): 41 50 50 4c 59 24 5f 43 44 52 5f 49 4e 46 4f

                              dump文件中的索引值,可以转成实际的索引列的值,此时可以借助travel大神的函数f_get_from_dump,原始下载地址,应该被墙了,常规操作不让访问了,

                              http://www.traveldba.com/wp-content/uploads/scripts/f_get_from_dump.sql

                              除了翻墙,可以从我的github下载,

                              https://github.com/bisal-liu/oracle/blob/master/f_get_from_dump

                              他支持数值类型、字符串类型、ROWID类型等的转换,以第126行为例,

                              (1) 第一列是VARCHAR2类型的,

                                col 0; len 3; (3):  53 59 53

                                调用函数f_get_from_dump,得到值SYS,

                                  SQL> select f_get_from_dump('53,59,53','VARCHAR2'from dual;
                                  F_GET_FROM_DUMP('53,59,53','VARCHAR2')
                                  --------------------------------------------------------------------------------
                                  SYS

                                  (2) 第二列是NUMBER类型的,

                                    col 1; len 3; (3):  c2 0b 02

                                    调用函数f_get_from_dump,得到值1001,,

                                      SQL> select f_get_from_dump('c2,0b,02','NUMBER'from dual;
                                      F_GET_FROM_DUMP('C2,0B,02','NUMBER')
                                      --------------------------------------------------------------------------------
                                      1001

                                      (3) 第三列是VARCHAR2类型的,

                                        col 2; len 15; (15):  41 50 50 4c 59 24 5f 43 44 52 5f 49 4e 46 4f

                                        调用函数f_get_from_dump,得到值APPLY$_CDR_INFO,

                                          SQL> select f_get_from_dump('41,50,50,4c,59,24,5f,43,44,52,5f,49,4e,46,4f','VARCHAR2'from dual;
                                          F_GET_FROM_DUMP('41,50,50,4C,59,24,5F,43,44,52,5F,49,4E,46,4F','VARCHAR2')
                                          --------------------------------------------------------------------------------
                                          APPLY$_CDR_INFO

                                          从这些数据块的文件中,我们就可以了解表的数据、索引的数据是怎么物理存储的,对于理解一些原理层的知识,非常有用,当然要做到融会贯通,从现象到本质,还得加以时日的训练,还在学习中。

                                          近期更新的文章:

                                          MySQL唯一索引和NULL空值之间的关系

                                          MySQL的MDL锁解惑

                                          Oracle唯一索引和NULL空值之间的关系

                                          NFT,只可远观不可亵玩焉

                                          MySQL数据库设计开发规范


                                          文章分类和索引:

                                          公众号900篇文章分类和索引

                                          文章转载自bisal的个人杂货铺,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                                          评论