• Oracle core02_数据块


    数据更改

    oracle core完成了oracle的核心功能,recovery,读一致性等。 深入的了解oracle的机制,就从一个最简单的更新开始。
    对于oracle来说,最大的一个特性就是写了两次数据:

    1. 写数据到数据文件中
    2. 写数据的变更日志到日志文件中

    对于最常见的数据更新来说,oracle主要做了一下动作:

    1. 创建数据块变更的日志记录即 redo change vector
    2. 创建数据块的映像即undo record
    3. 创建undo数据块变更的日志记录
    4. 更新数据块

    下面就以update为例:记录变更的过程。
    实验环境:Oracle Database 10g Enterprise Edition Release 10.2.0.1.0

    oracle对于update,会依次做以下变更:

    1. 创建插入undo record的undo变更redo change vector
    2. 创建数据块变更的redo change vector
    3. 组合redo change vector为record写入log buffer
    4. undo record插入到undo块中
    5. 更新数据块

    这里可以看到,对于oracle来说,所有的数据块的变更都是日志先行。

      1. 准备数据:

        

    SYS/SYS@ORCL>create table test(id number, name varchar2(100));
    Table created.
    SYS/SYS@ORCL>insert into test values(1,'xpchild_1');
    1 row created.
    SYS/SYS@ORCL>insert into test values(2,'xpchild_2');
    1 row created.
    SYS/SYS@ORCL>insert into test values(3,'xpchild_3');
    1 row created.
    SYS/SYS@ORCL>commit;
    Commit complete.

      2.dump 当前数据块

    SYS/SYS@ORCL>select owner, segment_name, tablespace_name, HEADER_FILE, HEADER_BLOCK , blocks 
    from dba_segments where segment_name='TEST' AND OWNER='XPCHILD';
    
    OWNER                SEGMENT_NAME         TABLESPACE_NAME      HEADER_FILE HEADER_BLOCK     BLOCKS
    -------------------- -------------------- -------------------- ----------- ------------ ----------
    XPCHILD              TEST                 USERS                          4          475          8
    
    SYS/SYS@ORCL>select owner, segment_name, tablespace_name, file_id, block_id,blocks 
    from dba_extents where owner='XPCHILD' and segment_name='TEST';
    
    OWNER                SEGMENT_NAME         TABLESPACE_NAME         FILE_ID   BLOCK_ID     BLOCKS
    -------------------- -------------------- -------------------- ---------- ---------- ----------
    XPCHILD              TEST                 USERS                         4        473          8

    上面的两个数据字典的查询,可以得出,test表在users表空间中,file_id为4。一共分配了一个extents,包括8个block。

      

    SYS/SYS@ORCL>alter system dump datafile 4 block 473,474,475,476;
    
    System altered.

    block 473,474分别是first level bitmap block,second level bitmap block。主要记录块的空闲情况。
    如:

    --------------------------------------------------------
      DBA Ranges :
    --------------------------------------------------------
       0x010001d9  Length: 8      Offset: 0      
      
       0:Metadata   1:Metadata   2:Metadata   3:75-100% free
       4:75-100% free   5:75-100% free   6:75-100% free   7:75-100% free

    block 475为pagetable segment header。

    block 480为存放真正数据的块,这也是堆管理的方式所决定,如下dump信息所示:

     Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
    0x01   0x0001.01e.000000f4  0x008000aa.00f0.14  --U-    3  fsc 0x0000.000d61e9
    0x02   0x0000.000.00000000  0x00000000.0000.00  ----    0  fsc 0x0000.00000000
    0xe:pti[0]      nrow=3  offs=0
    0x12:pri[0]     offs=0x1f88
    0x14:pri[1]     offs=0x1f78
    0x16:pri[2]     offs=0x1f68
    block_row_dump:
    tab 0, row 0, @0x1f88
    tl: 16 fb: --H-FL-- lb: 0x1  cc: 2
    col  0: [ 2]  c1 02
    col  1: [ 9]  78 70 63 68 69 6c 64 5f 31
    tab 0, row 1, @0x1f78
    tl: 16 fb: --H-FL-- lb: 0x1  cc: 2
    col  0: [ 2]  c1 03
    col  1: [ 9]  78 70 63 68 69 6c 64 5f 32
    tab 0, row 2, @0x1f68
    tl: 16 fb: --H-FL-- lb: 0x1  cc: 2
    col  0: [ 2]  c1 04
    col  1: [ 9]  78 70 63 68 69 6c 64 5f 33

    2, 更新数据

      

    SYS/SYS@ORCL>SYS/SYS@ORCL>update test set name='it is  beyond the current length' where id=2;
    Session altered.
    SYS/SYS@ORCL>alter system dump datafile 4 block 480;
    System altered.
    -------------------------------------------------------
     Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
    0x01   0x0001.01e.000000f4  0x008000aa.00f0.14  C---    0  scn 0x0000.000d61e9
    0x02   0x0001.018.000000f4  0x008000aa.00f0.26  --U-    1  fsc 0x0000.000d6475
    0xe:pti[0]      nrow=3  offs=0
    0x12:pri[0]     offs=0x1f88
    0x14:pri[1]     offs=0x1f41
    0x16:pri[2]     offs=0x1f68
    block_row_dump:
    tab 0, row 0, @0x1f88
    tl: 16 fb: --H-FL-- lb: 0x0  cc: 2
    col  0: [ 2]  c1 02
    col  1: [ 9]  78 70 63 68 69 6c 64 5f 31
    tab 0, row 1, @0x1f41
    tl: 39 fb: --H-FL-- lb: 0x2  cc: 2
    col  0: [ 2]  c1 03
    col  1: [32]
     69 74 20 69 73 20 20 62 65 79 6f 6e 64 20 74 68 65 20 63 75 72 72 65 6e 74
     20 6c 65 6e 67 74 68
    tab 0, row 2, @0x1f68
    tl: 16 fb: --H-FL-- lb: 0x0  cc: 2
    col  0: [ 2]  c1 04
    col  1: [ 9]  78 70 63 68 69 6c 64 5f 33

    这里主要说明两点:

    1. @0x1f78变为@0x1f41,这里是代表的这一行的真正的行内偏移地址,因为update更新一个比当前大的值,需要一个更大的连续空间,所以在块内部行进行了迁移,即偏移量发生了变化,rowid指向的是slot的地址,所以update仅仅是更新了slot中存放的块内偏移量,rowid保持不变。
    2. 开始事务时,lock byte lb:变为了0x2。关联的事务标示为itl(interested transaction list)。

    redo change vector

      

    接下来看下redo change vector的内容:

      

    SYS/SYS@ORCL>alter system switch logfile;
    System altered.
    SYS/SYS@ORCL>update test set name='ssssssss' where id=2;
    1 row updated.
    SYS/SYS@ORCL>commit;
    Commit complete.
    SYS/SYS@ORCL>alter system switch logfile;
    System altered.
    
    SYS/SYS@ORCL>select * from v$Log;
    
        GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARCHIV STATUS                           FIRST_CHANGE# FIRST_TIME
    ---------- ---------- ---------- ---------- ---------- ------ -------------------------------- ------------- -------------------
             1          1          5   52428800          1 NO     CURRENT                                 879223 2012-01-11 17:11:00
             2          1          4   52428800          1 YES    ACTIVE                                  879196 2012-01-11 17:09:52
             3          1          3   52428800          1 YES    ACTIVE                                  879176 2012-01-11 17:08:57
    SYS/SYS@ORCL>select SEQUENCE# , name from v$archived_log;
    SEQUENCE# NAME
    ---------- -----------------------------------------------------------------------------------
             1 /opt/oracle/flash_recovery_area/ORCL/archivelog/2012_01_11/o1_mf_1_1_7jvkvdfo_.arc
             2 /opt/oracle/flash_recovery_area/ORCL/archivelog/2012_01_11/o1_mf_1_2_7jw23sfk_.arc
             3 /opt/oracle/flash_recovery_area/ORCL/archivelog/2012_01_11/o1_mf_1_3_7jw25j8o_.arc
             4 /opt/oracle/flash_recovery_area/ORCL/archivelog/2012_01_11/o1_mf_1_4_7jw27nhp_.arc
    
    23 rows selected.
    
    
    SYS/SYS@ORCL>alter system dump logfile 
    '/opt/oracle/flash_recovery_area/ORCL/archivelog/2012_01_11/o1_mf_1_4_7jw27nhp_.arc';
    
    System altered.
    
    KTB Redo 
    op: 0x11  ver: 0x01  
    op: F  xid:  0x0004.013.000000fb    uba: 0x00800054.0110.05
    Block cleanout record, scn:  0x0000.000d6a6c ver: 0x01 opt: 0x02, entries follow...
      itli: 1  flg: 2  scn: 0x0000.000d6a12
    KDO Op code: URP row dependencies Disabled
      xtype: XA flags: 0x00000000  bdba: 0x010001e0  hdba: 0x010001db
    itli: 2  ispac: 0  maxfr: 4858
    tabn: 0 slot: 1(0x1) flag: 0x2c lock: 2 ckix: 10
    ncol: 2 nnew: 1 size: 1
    col  1: [ 8]  73 73 73 73 73 73 73 73

    这一部分代表的是更新数据库的redo。bdba代表更新的块,hdba代表segment header。

    SYS/SYS@ORCL>select ubafil,ubablk,start_ubablk,used_ublk from v$transaction;
    
        UBAFIL     UBABLK START_UBABLK  USED_UBLK
    ---------- ---------- ------------ ----------
             2        155          155          1
    
    1 row selected.
    SYS/SYS@ORCL>alter system dump datafile 2 block 155;
    System altered.  

    对于更新的事务,根据v$transaction可以查询到这个事务使用的undo块的信息,然后dump这个块的情况:

      

    *-----------------------------
    * Rec #0x5  slt: 0x0f  objn: 52634(0x0000cd9a)  objd: 52634  tblspc: 4(0x00000004)
    *       Layer:  11 (Row)   opc: 1   rci 0x00   
    Undo type:  Regular undo    Begin trans    Last buffer split:  No 
    Temp Object:  No 
    Tablespace Undo:  No 
    rdba: 0x00000000
    *-----------------------------
    uba: 0x0080009b.00f2.03 ctl max scn: 0x0000.000d56ca prv tx scn: 0x0000.000d56e5
    txn start scn: scn: 0x0000.000d6dec logon user: 0
     prev brb: 8389342 prev bcl: 0
    KDO undo record:
    KTB Redo 
    op: 0x04  ver: 0x01  
    op: L  itl: xid:  0x0004.013.000000fb uba: 0x00800054.0110.05
                          flg: C---    lkc:  0     scn: 0x0000.000d6a70
    KDO Op code: URP row dependencies Disabled
      xtype: XA flags: 0x00000000  bdba: 0x010001e0  hdba: 0x010001db
    itli: 2  ispac: 0  maxfr: 4858
    tabn: 0 slot: 1(0x1) flag: 0x2c lock: 0 ckix: 12
    ncol: 2 nnew: 1 size: -1
    col  1: [ 7]  78 70 63 68 69 6c 64

    这便是undo块的dump信息,这里也可以看到,undo的信息也仅仅只保留了被改变的那一部分信息,而不是整个块的原始镜像。

    txn start scn:  0x0000.000d6a12  logon user: 0  prev brb: 8388689  prev bcl: 0 KDO undo record:
    KTB Redo
    op: 0x04  ver: 0x01
    op: L  itl: xid:  0x0001.018.000000f4 uba: 0x008000aa.00f0.26
                          flg: C---    lkc:  0     scn: 0x0000.000d6475
    KDO Op code: URP row dependencies Disabled
      xtype: XA flags: 0x00000000  bdba: 0x010001e0  hdba: 0x010001db
    itli: 2  ispac: 0  maxfr: 4858
    tabn: 0 slot: 1(0x1) flag: 0x2c lock: 0 ckix: 10
    ncol: 2 nnew: 1 size: -1
    col  1: [ 7]  78 70 63 68 69 6c 64

      

    这一部分代表undo的redo日志,因为oracle对所有对数据块的变更都写两份,一份是数据变更,一份是日志,这一部分就是

    对undo 块变更的重做日志。

  • 相关阅读:
    【HDU
    写个shell脚本依次运行每个程序半小时
    Windows10 + Visual Studio 2017环境为C++工程安装使用ZMQ
    【UVALive
    【Gym
    【最短路算法】Dijkstra+heap和SPFA的区别
    【Gym 100812C】Story of Princess (走完图所有边)
    【C++】VS2015/VS2017连接Mysql数据库教程
    博客园设置Google-code-prettify渲染代码高亮
    【QML与C++混合编程】用QVariantList传递数组类型成员
  • 原文地址:https://www.cnblogs.com/xpchild/p/3695131.html
Copyright © 2020-2023  润新知