资讯专栏INFORMATION COLUMN

Oracle undo探索

IT那活儿 / 3553人阅读
Oracle undo探索

点击上方“IT那活儿”,关注后了解更多内容,不管IT什么活儿,干就完了!!!




概  述

1


undo段又叫rollback段,undo的前身就是rollback,查询undo段。

大家都知道的,修改数据后,没有提交的数据写到硬盘上,修改前的数据放在undo segment上。虽然未提交的数据已经写入硬盘,但另外的会话查询时是从undo segment上读取数据,在事务没有结束前,undo里的数据不会清除。
若事务太大导致undo空间不够,此时这个事务就会失败。



实验前准备

2


查出表内容:


</>复制代码

  1. SQL> select * from t2;
    ID NA
    ---------- --
    1 A
    2 a
    3 b
    4 c
修改一行记录:

</>复制代码

  1. SQL> update t2 set NAME=ab where id=4;
    1 row updated.





从逻辑层面获取块数据

3


该表的行数据所在的逻辑文件编号和块编号:


</>复制代码

  1. SQL> select dbms_rowid.rowid_relative_fno(rowid) fno,dbms_rowid.rowid_block_number(rowid) bn1 from t2;
    FNO BN1
    ---------- ----------
    41    1519940
    41    1519940
    41    1519940
    41    1519940
sys用户操作,查询dump文件路径,是用户进程,所以看user_dump_dest:

</>复制代码

  1. SQL> show parameter dump
    NAME TYPE VALUE
    ------------------------------------ ----------- ------------------------------
    background_core_dump string      partial
    background_dump_dest string      /u01/app/oracle/diag/rdbms/ocs
    tstdb/ocststdb/trace
    core_dump_dest string      /u01/app/oracle/diag/rdbms/ocs
    tstdb/ocststdb/cdump
    max_dump_file_size string      unlimited
    shadow_core_dump string      partial
    user_dump_dest string      /u01/app/oracle/diag/rdbms/ocs
    tstdb/ocststdb/trace
生成逻辑编号是41,块编号是1519940的dump文件:

</>复制代码

  1. SQL> alter system dump datafile 41 block 1519940;
    System altered.
查询该session产生的dump文件,或者在没有其他session的前提下,直接看最新的dump文件:

</>复制代码

  1. SQL> select distinct sid from v$mystat;
    SID
    ----------
    581
    SQL> select paddr from v$session where sid=581;
    PADDR
    ----------------
    0000000253FCC010
    SQL> select spid from v$process where addr=0000000253FCC010;
    SPID
    ------------------------
    8212
找到dump文件,下载到本地:

</>复制代码

  1. [oracle@ocsdbtest trace]$ pwd
    /u01/app/oracle/diag/rdbms/ocststdb/ocststdb/trace
    [oracle@ocsdbtest trace]$ ls *8212.trc
    ocststdb_ora_8212.trc
用UE打开,主要最后面的:

</>复制代码

  1. .................
    Start dump data blocks tsn: 42 file#:41 minblk 1519940 maxblk 1519940
    .................
    Itl Xid Uba Flag Lck Scn/Fsc
    0x01 0x0003.017.002c083b 0x00c004f8.e3f0.06  C--- 0  scn 0x0e73.5c418bf9
    0x02 0x0009.010.002c7c61 0x00c0032e.e670.23  ---- 1  fsc 0x0000.00000000
    bdba: 0x0a573144
    data_block_dump,data header at 0x7f0ea1953a64
    ===============
    tsiz: 0x1f98
    hsiz: 0x1a
    pbl: 0x7f0ea1953a64
    76543210
    flag=--------
    ntab=1
    nrow=4
    frre=-1
    fsbo=0x1a
    fseo=0x1f6f
    avsp=0x1f5a
    tosp=0x1f5a
    0xe:pti[0] nrow=4  offs=0
    0x12:pri[0] offs=0x1f90
    0x14:pri[1] offs=0x1f88
    0x16:pri[2] offs=0x1f80
    0x18:pri[3] offs=0x1f6f
    block_row_dump:
    tab 0, row 0, @0x1f90
    tl: 8 fb: --H-FL-- lb: 0x0 cc: 2
    col  0: [ 2] c1 02
    col  1: [ 1] 41
    tab 0, row 1, @0x1f88
    tl: 8 fb: --H-FL-- lb: 0x0 cc: 2
    col  0: [ 2] c1 03
    col  1: [ 1] 61
    tab 0, row 2, @0x1f80
    tl: 8 fb: --H-FL-- lb: 0x0 cc: 2
    col  0: [ 2] c1 04
    col  1: [ 1] 62
    tab 0, row 3, @0x1f6f
    tl: 9 fb: --H-FL-- lb: 0x2 cc: 2
    col  0: [ 2] c1 05
    col  1: [ 2] 61 62
    end_of_block_dump
    End dump data blocks tsn: 42 file#: 41 minblk 1519940 maxblk 1519940





从物理磁盘层面获取块数据

4


再次dump绝对文件的内容:


</>复制代码

  1. SQL> alter system dump datafile /oradata/ocststdb/TSSXCPMIS01.dbf block 1519940;
    System altered.
由于在同一个session下dump的,trc文件也是一样的,再次下载,UE打开:

</>复制代码

  1. ...............
    Start dump data block from file /oradata/ocststdb/TSSXCPMIS01.dbf minblk 1519940 maxblk 1519940
    .............
    Itl Xid Uba Flag Lck Scn/Fsc
    0x01   0x0003.017.002c083b 0x00c00b68.6795.07  C--- 0 scn 0x0e73.5c418bf9
    0x02   0x0009.010.002c7c61 0x00c00b68.6795.0b ---- 1 fsc 0x0000.00000000
    bdba: 0x0a573144
    data_block_dump,data header at 0x7f0ea1953a64
    ===============
    tsiz: 0x1f98
    hsiz: 0x1a
    pbl: 0x7f0ea1953a64
    76543210
    flag=--------
    ntab=1
    nrow=4
    frre=-1
    fsbo=0x1a
    fseo=0x1f6f
    avsp=0x1f5a
    tosp=0x1f5a
    0xe:pti[0] nrow=4  offs=0
    0x12:pri[0] offs=0x1f90
    0x14:pri[1] offs=0x1f88
    0x16:pri[2] offs=0x1f80
    0x18:pri[3] offs=0x1f6f
    block_row_dump:
    tab 0, row 0, @0x1f90
    tl: 8 fb: --H-FL-- lb: 0x0 cc: 2
    col  0: [ 2] c1 02
    col  1: [ 1] 41
    tab 0, row 1, @0x1f88
    tl: 8 fb: --H-FL-- lb: 0x0 cc: 2
    col  0: [ 2] c1 03
    col  1: [ 1] 61
    tab 0, row 2, @0x1f80
    tl: 8 fb: --H-FL-- lb: 0x0 cc: 2
    col  0: [ 2] c1 04
    col  1: [ 1] 62
    tab 0, row 3, @0x1f6f
    tl: 9 fb: --H-FL-- lb: 0x2 cc: 2
    col  0: [ 2] c1 05
    col  1: [ 2] 61 62
    end_of_block_dump
    End dump data block from file /oradata/ocststdb/TSSXCPMIS01.dbf minblk 1519940 maxblk 1519940
这一行意思开始dump文件“/oradata/ocststdb/TSSXCPMIS01.dbf”,块“1519940”:

</>复制代码

  1. Start dump data block from file /oradata/ocststdb/TSSXCPMIS01.dbf minblk 1519940 maxblk 1519940
有4行数据:

</>复制代码

  1. nrow=4
改行数据有锁,0x2,没锁的是0x0:

</>复制代码

  1. tl: 9 fb: --H-FL-- lb: 0x2 cc: 2
最后一行内容是2列:

</>复制代码

  1. col  0: [ 2] c1 05
    col  1: [ 2] 61 62





从undo段获取块数据

5


截取地址(Uba:0x00c00b68.6795.07),0x和第一个“.”之间内容,00c00b68,这是个16进制的地址,通过这个地址获取文件编号和块编号。

先转换成10进制数:

</>复制代码

  1. SQL> select to_number(00c00b68,xxxxxxxxxx) from dual;
    TO_NUMBER(00C00B68,XXXXXXXXXX)
    ----------------------------------
    12585832
获取文件编号:

</>复制代码

  1. SQL> select dbms_utility.data_block_address_file(12585832) from dual;
    DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(12585832)
    ----------------------------------------------
    3
获取块编号:

</>复制代码

  1. SQL> select dbms_utility.data_block_address_block(12585832) from dual;
    DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(12585832)
    -----------------------------------------------
    2920
查看当前undo使用的那个表空间:

</>复制代码

  1. SQL> show parameter undo_tablespace
    NAME TYPE VALUE
    ------------------------------------ ----------- ------------------------------
    undo_tablespace string UNDOTBS1
查询UNDOTBS的文件编号:

</>复制代码

  1. SQL> select file_id from dba_data_files where tablespace_name=UNDOTBS1;
    FILE_ID
    ----------
    3
由此确认通过Uba获取的文件编号的正确。
将这个文件dump出来:

</>复制代码

  1. SQL> alter system dump datafile 3 block 2920;
    System altered.
地址(Uba:0x00c00b68.6795.07)最后一位是07地址,打开dump文件找到地址为07的,看到它的值是63,即“c”,也就是原数据存放到undo表空间去了:

</>复制代码

  1. *-----------------------------
    * Rec #0x7 slt: 0x1a objn: 176942(0x0002b32e) objd: 176942  tblspc: 42(0x0000002a)
    * Layer: 11 (Row) opc: 1   rci 0x00
    Undo type: Regular undo    Begin trans Last buffer split:  No
    Temp Object:  No
    Tablespace Undo: No
    rdba: 0x00000000Ext idx: 0
    flg2: 0
    *-----------------------------
    uba: 0x00c00b68.6795.06 ctl max scn: 0x0e73.5c4ac77d prv tx scn: 0x0e73.5c4ac783
    txn start scn: scn: 0x0e73.5c4a9dce logon user: 130
    prev brb: 12585831 prev bcl: 0
    KDO undo record:
    KTB Redo
    op: 0x03 ver: 0x01
    compat bit: 4 (post-11) padding: 1
    op: Z
    KDO Op code: URP row dependencies Disabled
    xtype: XA flags: 0x00000000 bdba: 0x0a573144 hdba: 0x0a573142
    itli: 2  ispac: 0  maxfr: 4858
    tabn: 0 slot: 3(0x3) flag: 0x2c lock: 0 ckix: 0
    ncol: 2 nnew: 1 size: -1
    col  1: [ 1] 63
查出“a”和“b”的ASSIC值:

</>复制代码

  1. SQL> select ascii(a) from dual;
    ASCII(A)
    ----------
    97
    SQL> select ascii(b) from dual;
    ASCII(B)
    ----------
    98
将97和98转换成16进制,则是61和62,正式最后一行的内容:

</>复制代码

  1. SQL> select to_char(97,XX) from dual;
    TO_
    ---
    61
    SQL> select to_char(98,XX) from dual;
    TO_
    ---
    62





各层面获取的数据对比

6


可以看到第一个dump文件,逻辑文件编号出来的文件,和第二个dump文件,绝对文件编号出来的文件,在最后一行的内容都是一致的:


</>复制代码

  1. col  1: [ 2] 61 62
即从内存中读取出来的内容和从硬盘读取出来的内容是一样的,未commit就已经写到磁盘上了。
没提交的数据是有标记的,是有锁的,其他session是查不到的。其他session查询该数据,读到这个块时发现有锁,“tl: 9 fb: --H-FL-- lb: 0x2  cc: 2”,可以看到Lck是“1”,表示有1条数据锁定。




总  结

7


通过dump数据得到验证,表的逻辑数据和磁盘数据都保存的是新数据,undo段里则保存原始数据。



本文作者:胡 伟

本文来源:IT那活儿(上海新炬王翦团队)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/129604.html

相关文章

发表评论

0条评论

IT那活儿

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<