作者:dbtan |【转载时请以超链接形式标明文章出处作者信息】


Redo 的内容:

大家知道,Oracle通过Redo来实现快速提交,一方面是因为Redo Log File可以连续、顺序地快速写出,另一个方面也和Redo记录的精简内容有关。

为了了解Redo的内容,需要了解两个概念。
·改变向量(Change Vector)改变向量表示对数据库内某一个数据块所做的一次变更。改变向量(Change Vector)中包含了变更的数据块的版本号、事务操作代码、变更从属数据块的地址(DBA)以及更新后的数据。例如,一个Update事务包含一系列的改变向量,对于数据块的修改是一个向量,对于回滚段的修改又是一个向量。
·重做记录(Redo Record)重做记录通常由一组改变向量组成,是一个改变向量的集合,代表一个数据库的变更(INSERT、UPDATE、DELETE等操作),构成数据库变更的最小恢复单位。例如,一个Update的重做记录包括相应的回滚段的改变向量和相应的数据块的改变向量等。

下面以一个更新(Update)操作为例介绍一下这个过程。
假定发出了一个更新语句:

update emp set sal=4000 where empno=7788;

看一下这个语句是怎样执行的(为了简化描述,尽量简化了情况)。

⑴ 检查empno=7788记录在Buffer Cache中是否存在,如果不存在则读取到Buffer Cache中。
⑵ 在回滚表空间的相应回滚段事务表上分配事务槽,这个操作需要记录Redo信息。
⑶ 从回滚段读入或者在Buffer Cache中创建sal=3000的前镜像,这需要产生Redo信息并记入Redo Log Buffer。
⑷ 修改sal=4000,这是update的数据变更,需要记入Redo Log Buffer。
⑸ 当用户提交时,会在Redo Log Buffer记录提交信息,并在回滚段标记该事务为非激活(INACTIVE)。

下面通过一个具体的试验来再现这个过程。
⑴ 首先通过switch logfile切换日志,使用sys用户进行日志切换,使得接下来的更新可以使用新的日志。

sys@NEI> alter system switch logfile;
System altered.
sys@NEI> select * from v$log;
    GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARC STATUS           FIRST_CHANGE# FIRST_TIME
---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- -------------------
         1          1       2235  104857600          1 NO  CURRENT               59589280 2009-12-14 10:02:52
         2          1       2233  104857600          1 YES INACTIVE              59565344 2009-12-14 01:01:19
         3          1       2234  104857600          1 YES ACTIVE                59565355 2009-12-14 01:01:23

⑵ 更新并提交事务。

scott@NEI> select * from emp where empno=7788;
     EMPNO ENAME      JOB              MGR HIREDATE               SAL       COMM     DEPTNO
---------- ---------- --------- ---------- --------------- ---------- ---------- ----------
      7788 SCOTT      ANALYST         7566 19-APR-87             3000                    20
scott@NEI> update emp set sal=4000 where empno=7788;
1 row updated.
scott@NEI> commit;
Commit complete.

⑶ 确认Session信息。

sys@NEI> select sid,serial#,username from v$session where username='SCOTT';
       SID    SERIAL# USERNAME
---------- ---------- ------------------------------
       145       3692 SCOTT

⑷ 使用sys用户在另外Session转储日志文件。

sys@NEI> alter system dump logfile '/home/oracle/oradata/ccdb/redo01.log';
System altered.
sys@NEI> @gettrcname.sql      
TRACE_FILE
------------------------------------------------------------
/home/oracle/admin/ccdb/udump/ccdb_ora_30976.trc

⑸ 获取Trace文件。
从日志文件的转储信息中,可以很容易地找到这个事务的信息,为了方便说明,我将这段日志分开讲解。
·改变向量1。这是对于回滚段头的修改,分配事务表,从绝对文件号为2(AFN:2)卡可以知道这是UNDO表空间,通过UBA机DBA的换算能够找到相应的Block。

CHANGE #1 TYP:0 CLS:23 AFN:2 DBA:0x00800039 OBJ:4294967295 SCN:0x0000.038d4baa SEQ:  2 OP:5.2
ktudh redo: slt: 0x0024 sqn: 0x0000815f flg: 0x0012 siz: 132 fbi: 0
            uba: 0x008007fd.314b.0a    pxid:  0x0000.000.00000000

·改变向量2。这里记录的是前镜像信息,注意到col  5: [ 2]  c2 1f记录的就是对于COL 5的修改,修改前的数值是3000(c2 1f,数值及存储转换方式,请参考下篇日志)。

CHANGE #2 TYP:0 CLS:36 AFN:2 DBA:0x00800678 OBJ:4294967295 SCN:0x0000.038d4bdb SEQ:  2 OP:5.1
ktudb redo: siz: 152 spc: 6504 flg: 0x0012 seq: 0x3117 rec: 0x0e
            xid:  0x000a.010.00008231 
ktubl redo: slt: 16 rci: 0 opc: 11.1 objn: 86274 objd: 86274 tsn: 4
Undo type:  Regular undo        Begin trans    Last buffer split:  No
Temp Object:  No
Tablespace Undo:  No
             0x00000000  prev ctl uba: 0x00800678.3117.0c
prev ctl max cmt scn:  0x0000.038d438d  prev tx cmt scn:  0x0000.038d43af
txn start scn:  0x0000.00000000  logon user: 54  prev brb: 8390260  prev bcl: 0 KDO undo record:
KTB Redo
op: 0x04  ver: 0x01 
op: L  itl: xid:  0x0006.012.00007490 uba: 0x00800058.2e9d.02
                      flg: C---    lkc:  0     scn: 0x0000.038d42f6
KDO Op code: URP row dependencies Disabled
  xtype: XAxtype KDO_KDOM2 flags: 0x00000080  bdba: 0x0100001c  hdba: 0x0100001b
itli: 2  ispac: 0  maxfr: 4858
tabn: 0 slot: 7(0x7) flag: 0x2c lock: 0 ckix: 191
ncol: 8 nnew: 1 size: 0
Vector content:
col  5: [ 2]  c2 1f

·改变向量3。这里记录的是对于数据块的修改,col  5: [ 2]  c2 29记录的是对于COL 5的修改,修改后的值为4000(c2 29)。

CHANGE #3 TYP:2 CLS: 1 AFN:4 DBA:0x0100001c OBJ:86274 SCN:0x0000.038d4a9f SEQ:  2 OP:11.5
KTB Redo
op: 0x11  ver: 0x01 
op: F  xid:  0x000a.010.00008231    uba: 0x00800678.3117.0e
Block cleanout record, scn:  0x0000.038d4bf3 ver: 0x01 opt: 0x02, entries follow...
  itli: 1  flg: 2  scn: 0x0000.038d4a9f
KDO Op code: URP row dependencies Disabled
  xtype: XAxtype KDO_KDOM2 flags: 0x00000080  bdba: 0x0100001c  hdba: 0x0100001b
itli: 2  ispac: 0  maxfr: 4858
tabn: 0 slot: 7(0x7) flag: 0x2c lock: 2 ckix: 191
ncol: 8 nnew: 1 size: 0
Vector content:
col  5: [ 2]  c2 29

·改变向量4。当事务提交之后,记录的SCN信息,注意这里标记为“MEDIA RECOVERY MARKER SCN”,也就是说,这是一个可以恢复的时间点,事务的恢复,必须以Redo Record为最小单位。

CHANGE #4 MEDIA RECOVERY MARKER SCN:0x0000.00000000 SEQ:  0 OP:23.1

·Session信息。最后部分记录的是产生这些Redo的Session信息。

session number   = 145
serial  number   = 3692
transaction name =

从以上的分析可以看到,对于数据块的修改,如果执行写出,那么通常需要写出8KB的Block,而对于Redo日志来说,重做信息却相当精简,Oracle只需要记录那些重构事务必须的信息(事务号、文件号、块号、行号、字段等)即可,这个数据量大大减少。

- The End -