重做记录

一、数据库的变更与事物

          数据库的任何变更都会产生一条重做记录,是定义哪些操作必须在一起,并且按顺序执行。包含了一系列操作。

          一个变更对应一条重做记录,一个重做记录包含一个或多个CHANGE VECTORchange vector记录了对一个数据块的原子操作。所以Change Vector保证了数据块在修改前后的一致性,而其容器——重做记录则保证了数据库修改前后的一致性。

 

理解SCN、数据库版本号(SCN+SEQ)和RBA(重做字节地址)

         SCN   4Base字节  2Wrap字节组成   Base随时间流失和变更操作的执行而递增,用尽之后开始循环,此时Wrap递增(进位)。

        任何数据库的变更的操作都会产生新的SCN,如果没有发生任何事,每3SCN也要增加1

          v$database大部分信息来自控制文件,调用v$database.CURRENT_SCN相当于调用序列的NEXTVAL,ORACLE将访问控制文件也视为一种变更,因此,两次查询肯定会返回两个不同的SCNDbms_flashback.get_system_change_number会得到当前的SCN 

         每个能够对数据库状态修改的操作,都会产生一个新的SCN写入到重做记录中,这样重做记录之间就可以分清在时间顺序上对应的操作的先后顺序。

        如果在两个重做记录中的SCN是相同的,这是由于ORACLE的某些内部操作导致的,所以又有了SUBSCN,用以标记同一个SCN下的多次变更。

转储文件中的SCNSUBSCN  SCN:0xffff.ffffffff  subscn:n

       修改操作完成后,SCNSUBSCN都会保存到数据块头部,占用7字节,SCN不变,但是SUBSCN改为SEQ,加起来就是数据块版本号。

这样修改操作的SCN就出现在了两个地方:重做日志和数据文件中。

        RBA:重做记录地址,重做记录中记录了SCNSUBSCN来说明变更操作的时间,而记录RBA说明变更操作的地址(在哪个重做日志的哪个字节处能找到其自身)。

转储文件中的RBA:THREAD:n RBA:0xffffff.ffffffff.ffff

        比如:Thread1RBA:0x000013.00000004.0010,标志在1号线程的19号序列号的重做日志文件的第4个块的第16字节处。

关于rowid关于oracle rowid的一些内容

 

看一下一个简单的update产生的重做记录:


 

SQL>alter system switch logfile;

 

Systemaltered.

 

SQL>select * from v$log;

 

    GROUP#   THREAD#  SEQUENCE#      BYTES   MEMBERS ARC STATUS            FIRST_CHANGE# FIRST_TIM

-------------------- ---------- ---------- ---------- --- ---------------- ----------------------

 1           1           53101  52428800             1 NO ACTIVE               1.1633E+11 19-JUL-13

 2           1           53102  52428800             1 NO CURRENT               1.1633E+11 19-JUL-13

 3           1           53100  52428800             1 NO ACTIVE               1.1633E+11 19-JUL-13

 4           1           53097 524288000             1 NO INACTIVE               1.1618E+11 16-JUL-13

 5           1           53098 524288000             1 NO INACTIVE               1.1632E+11 19-JUL-13

 6           1           53099 524288000             1 NO ACTIVE               1.1633E+11 19-JUL-13

 

6rows selected.

 

 

SQL>conn dptwm/dptwm

Connected.

 

SQL>select * from emp;

 

SQL>/

 

     EMPNO ENAME     JOB               MGRHIREDATE            SAL      COMM     DEPTNO

-------------------- --------- ---------- --------- ---------- ---------- ----------

      7369 SMITH     CLERK              790217-DEC-80            800                   20

      7499 ALLEN     SALESMAN              769820-FEB-81           1600       300           30

      7521 WARD      SALESMAN              769822-FEB-81           1250       500           30

      7566 JONES     MANAGER              783902-APR-81           2975                   20

      7654 MARTIN    SALESMAN              769828-SEP-81           1250      1400           30

      7698 BLAKE     MANAGER              783901-MAY-81           2850                   30

      7782 CLARK     MANAGER              783909-JUN-81           2450                   10

      7788 SCOTT     ANALYST              756609-DEC-82           4320                   20

      7844 TURNER    SALESMAN              769808-SEP-81           1500        0           30

      7876 ADAMS     CLERK              778812-JAN-83           1100                   20

      7900 JAMES     CLERK              769803-DEC-81            950                   30

 

     EMPNO ENAME     JOB               MGRHIREDATE            SAL      COMM     DEPTNO

-------------------- --------- ---------- --------- ---------- ---------- ----------

      7902 FORD      ANALYST              756603-DEC-81           3000                   20

      7934 MILLER    CLERK              778223-JAN-82           1300                   10

 

13rows selected.

 

 

SQL>update emp set sal=sal*1.2 where empno=7788;

 

1row updated.

 

SQL>commit;

 

Commitcomplete.

 

SQL>alter system dump logfile '/u01/oracle/oradata/dipdb/redo02.log';

 

Systemaltered.

 

 

-->以上操作为update一行

 

[oracle@OAudump]$ cat dipdb_ora_10521.trc |less

/u01/oracle/admin/dipdb/udump/dipdb_ora_10521.trc

OracleDatabase 10g Enterprise Edition Release 10.2.0.1.0 - 64bit Production

Withthe Partitioning, OLAP and Data Mining options

ORACLE_HOME= /u01/oracle/product/10.2.0/db_1

Systemname:    Linux

Nodename:      OA

Release:        2.6.18-128.el5

Version:        #1 SMP Wed Dec 17 11:41:38 EST 2008

Machine:        x86_64

Instancename: dipdb

Redothread mounted by this instance: 1

Oracleprocess number: 42

Unixprocess pid: 10521, image: oracle@OA (TNS V1-V3)

 

 

REDORECORD - Thread:1 RBA: 0x00cf6e.0000000e.0010 LEN: 0x0220 VLD: 0x0d

SCN:0x001b.16034844 SUBSCN:  2 07/19/201314:25:49

CHANGE #1 TYP:2 CLS: 1 AFN:4 DBA:0x01005956 OBJ:224326SCN:0x001b.15fb1f87 SEQ:  1 OP:11.5

KTBRedo

op:0x11  ver: 0x01 

op:F  xid: 0x0005.017.0001733b    uba:0x00800097.eef8.1a

Blockcleanout record, scn:  0x001b.16034843ver: 0x01 opt: 0x02, entries follow...

  itli: 2 flg: 2  scn: 0x001b.15fb1f87

KDOOp code: URP row dependencies Disabled

  xtype: XA flags: 0x00000000  bdba: 0x01005956  hdba: 0x01005953

itli:1  ispac: 0  maxfr: 4858

tabn:0slot: 7(0x7) flag: 0x2c lock: 1 ckix: 0

ncol:8 nnew: 1 size: 1

col  5: [3] c2 2c 15

 

-->AFN :绝对文件编号,表示数据库写入到哪个文件中

 -->DBA:相对数据库地址,包含相对文件标号和数据块编号,可以通过以前语句查到。

例上面DBA为:0x01005956转换为10进制为:16800086

SQL>select dbms_utility.data_block_address_file(16800086) asrfile,dbms_utility.data_block_address_block(16800086) as block from dual;

 

    RFILE        BLOCK

--------------------

 4        22870

 

该变量表示的是我们要做的操作是修改文件4(AFN)中的22870DBA)这个数据块的第8行(slot)的第5个字段(col),修改为c2 2c 15

 

CHANGE #2 TYP:0 CLS:25 AFN:2 DBA:0x00800049OBJ:4294967295SCN:0x001b.16034832 SEQ:  2 OP:5.2

ktudhredo: slt: 0x0017 sqn: 0x0001733b flg: 0x0012 siz: 156 fbi: 0

            uba: 0x00800097.eef8.1a    pxid: 0x0000.000.00000000

 

-->第二个矢量向量是分配的左右是负责创建事务表 PS:按道理应该是先分配一个undo段,在undo段中创建一个事务表,才开始事务,不知道这里为什么是先写了数据库的修改(矢量变量1),再分配了undo段。

 

CHANGE #3 TYP:0 CLS:25 AFN:2 DBA:0x00800049OBJ:4294967295SCN:0x001b.16034844 SEQ:  1 OP:5.4

ktucmredo: slt: 0x0017 sqn: 0x0001733b srt: 0 sta: 9 flg: 0x2

ktucfredo: uba: 0x00800097.eef8.1a ext: 3 spc: 4550 fbi: 0

 

-->第三个矢量和第二个写的是同一个undo块,分配了两个表,可能是因为改表有外键关系

 

CHANGE #4 TYP:0 CLS:26 AFN:2 DBA:0x00800097OBJ:4294967295SCN:0x001b.16034832 SEQ:  1 OP:5.1

ktudbredo: siz: 156 spc: 4708 flg: 0x0012 seq: 0xeef8 rec: 0x1a

            xid:  0x0005.017.0001733b 

ktublredo: slt: 23 rci: 0 opc: 11.1 objn: 224326 objd: 224326 tsn: 4

Undotype:  Regular undo        Begin trans    Last buffer split:  No

TempObject:  No

TablespaceUndo:  No

             0x00000000  prev ctl uba: 0x00800097.eef8.19

prevctl max cmt scn:  0x001b.16010657  prev tx cmt scn:  0x001b.1601065b

txnstart scn:  0x0000.00000000  logon user: 92  prev brb: 8388756  prev bcl: 0 KDO undo record:

KTBRedo

op:0x04  ver: 0x01 

op:L  itl: xid:  0x0005.00a.000172f9 uba: 0x008001ac.eef7.1d

                      flg: C---    lkc: 0     scn: 0x001b.15fb0f18

KDOOp code: URP row dependencies Disabled

  xtype: XA flags: 0x00000000  bdba: 0x01005956  hdba: 0x01005953

itli:1  ispac: 0  maxfr: 4858

tabn:0 slot: 7(0x7) flag: 0x2c lock: 0 ckix: 0

ncol:8 nnew: 1 size: -1

col  5: [ 2] c2 25

 

-->这个矢量是表示在2号文件的8388759号数据块中保存撤销数据,以保证事务可被回滚。

 

转换进制可以使用一下语句来验证:

例:

SQL>Select dump(3600,16) from dual;

 

DUMP(3600,16)

------------------

Typ=2Len=2: c2,25

 

反向计算的话为

指数位换算:

正数:指数=符号/指数位 - 193 (最高位为1是代表正数

负数:指数=62 -第一字节

 

                                 16进制转化为10进制         c2=194    25=37

         194-193=1 指数位为1表示正数 

 

每个<数字位>乘以100^(指数-N) (N是有效位数的顺序位,第一个有效位的N=0)

           37-1=36*100^(1-0)=3600

 

具体算法可以参考: How Oracle Store Number internal?

 

以上就是一条重做记录的组成。

 

 

重要的事:

一个重做记录中记录的操作,需要在记录到log buffer之后,才会按照重做记录去执行。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值