Redo的内容
Oracle通过Redo来实现快速提交,一方面是因为Redo Log File可以连续、顺序地快速写出,另外一个方面也和Redo记录的精简内容有关。
为了了解Redo的内容,首先需要了解两个概念:改变向量和重做记录。
¡ 改变向量(Change Vector)
改变向量表示对数据库内某一个数据块所做的一次变更。改变向量(Change Vector)中包含了变更的数据块的版本号、事务操作代码、变更从属数据块的地址(DBA)以及更新后的数据。例如,一个Update事务包含一系列的改变向量,对于数据块的修改是一个向量,对于回滚段的修改又是一个向量。
¡ 重做记录(Redo Record)
重做记录通常由一组改变向量组成,是一个改变向量的集合,代表一个数据库的变更(INSERT、UPDATE、DELETE等操作),构成数据库变更的最小恢复单位。例如,一个Update的重做记录包括相应的回滚段的改变向量和相应的数据块的改变向量等。
下面以一个更新(Update)操作为例介绍一下这个过程,如图6-2所示。
图6-2 更新(Update)操作引起的重做
假定发出了一个更新语句:
UPDATE emp SET sal = 4000 Where empno= 7788;
看一下这个语句是怎样执行的(为了简化描述,这里尽量简化了情况):
(1)检查empno=7788记录在Buffer Cache中是否存在,如果不存在则读取到Buffer Cache中。
(2)在回滚表空间的相应回滚段事务表上分配事务槽,这个操作需要记录Redo信息。
(3)从回滚段读入或者在Buffer Cache中创建sal=3000的前镜像,这需要产生Redo信息并记入Redo Log Buffer。
(4)修改Sal=4000,这是UPDATE的数据变更,需要记入Redo Log Buffer。
(5)当用户提交时,会在Redo Log Buffer记录提交信息,并在回滚段标记该事务为非激活(Inactive)。
下面通过一个具体的试验来再现这个过程。
(1)首先通过switch logfile切换日志。使用SYS用户进行日志切换,使得接下来的更新可以使用新的日志。
SQL> alter system switch logfile;
System altered.
SQL> select * from v$log;
GROUP# THREAD# SEQUENCE# BYTES MEMBERS ARC STATUS FIRST_CHANGE# FIRST_TIM
---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- ---------
1 1 310 10485760 1 NO ACTIVE 8.9035E+12 26-MAR-06
2 1 309 10485760 1 NO INACTIVE 8.9035E+12 19-MAR-06
3 1 311 10485760 1 NO CURRENT 8.9035E+12 26-MAR-06
4 1 308 1048576 1 NO INACTIVE 8.9035E+12 19-MAR-06
(2)更新并提交事务。
SQL> select * from emp where empno=7788;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- --------- ---------- ---------- ----------
7788 SCOTT ANALYST 7566 19-APR-87 3000 20
SQL> update emp set sal=4000
2 where empno=7788;
1 row updated.
SQL> commit;
Commit complete.
(3)确认session信息。
SQL> select sid,serial#,username from v$session
2 where username='SCOTT';
SID SERIAL# USERNAME
---------- ---------- ------------------------------
13 405 SCOTT
(4)使用SYS用户在另外session转储日志文件:
SQL> ALTER SYSTEM DUMP LOGFILE '/opt/oracle/oradata/conner/redo03.log';
System altered.
SQL> @gettrcname
TRACE_FILE_NAME
------------------------------------------------------------------------------------------------------------------------
/opt/oracle/admin/conner/udump/conner_ora_31885.trc
此脚本在本书中多次使用,现收录于下:
SELECT d.VALUE
|| '/'
|| LOWER (RTRIM (i.INSTANCE, CHR (0)))
|| '_ora_'
|| p.spid
|| '.trc' trace_file_name
FROM (SELECT p.spid
FROM SYS.v$mystat m, SYS.v$session s, SYS.v$process p
WHERE m.statistic# = 1 AND s.SID = m.SID AND p.addr = s.paddr) p,
(SELECT t.INSTANCE
FROM SYS.v$thread t, SYS.v$parameter v
WHERE v.NAME = 'thread'
AND (v.VALUE = 0 OR t.thread# = TO_NUMBER (v.VALUE))) i,
(SELECT VALUE
FROM SYS.v$parameter
WHERE NAME = 'user_dump_dest') d
/
(5)获取Trace文件。
从日志文件的转储信息中,可以很容易地找到这个事务(sid= 15,serial#=43870)的信息,为了方便说明,将这段日志分开讲解。
¡ 改变向量1
这是对于回滚段头的修改,分配事务表,从绝对文件号为2(AFN:2)可以知道这是UNDO表空间,通过UBA机DBA的换算能够找到相应的Block,限于篇幅,本文不再做过多的介绍。
REDO RECORD - Thread:1 RBA: 0x000137.00000005.0010 LEN: 0x0198 VLD: 0x01
SCN: 0x0819.0036f14d SUBSCN: 1 03/26/2006 12:01:44
CHANGE #1 TYP:0 CLS:19 AFN:2 DBA:0x00800009 SCN:0x0819.0036f03c SEQ: 1 OP:5.2
ktudh redo: slt: 0x001d sqn: 0x000038ea flg: 0x0012 siz: 108 fbi: 0
uba: 0x008000c3.04b1.0c pxid: 0x0000.000.00000000
¡ 改变向量2
这里记录的是前镜像信息,注意到“col 5: [ 2] c2 1f”记录的就是对于COL 5的修改,修改前的数值是3000(c2 1f)。
CHANGE #2 TYP:0 CLS:20 AFN:2 DBA:0x008000c3 SCN:0x0819.0036f03b SEQ: 1 OP:5.1
ktudb redo: siz: 108 spc: 6740 flg: 0x0012 seq: 0x04b1 rec: 0x0c
xid: 0x0002.01d.000038ea
ktubl redo: slt: 29 rci: 0 opc: 11.1 objn: 7961 objd: 7961 tsn: 0
Undo type: Regular undo Begin trans Last buffer split: No
Temp Object: No
Tablespace Undo: No
0x00000000 prev ctl uba: 0x008000c3.04b1.0b
prev ctl max cmt scn: 0x0819.00364c81 prev tx cmt scn: 0x0819.00365073
KDO undo record:
KTB Redo
op: 0x03 ver: 0x01
op: Z
KDO Op code: URP row dependencies Disabled
xtype: XA bdba: 0x00405c5a hdba: 0x00405c59
itli: 2 ispac: 0 maxfr: 4863
tabn: 0 slot: 7(0x7) flag: 0x2c lock: 0 ckix: 0
ncol: 8 nnew: 1 size: 0
col 5: [ 2] c2 1f
¡ 改变向量3
这里记录的是对于数据块的修改,“col 5: [ 2] c2 29”记录的是对于COL 5的修改,修改后的值为4000(c2 29)。
CHANGE #3 TYP:2 CLS: 1 AFN:1 DBA:0x00405c5a SCN:0x0819.0036efb1 SEQ: 1 OP:11.5
KTB Redo
op: 0x11 ver: 0x01
op: F xid: 0x0002.01d.000038ea uba: 0x008000c3.04b1.0c
Block cleanout record, scn: 0x0819.0036f14d ver: 0x01 opt: 0x02, entries follow...
itli: 1 flg: 2 scn: 0x0819.0036efb1
KDO Op code: URP row dependencies Disabled
xtype: XA bdba: 0x00405c5a hdba: 0x00405c59
itli: 2 ispac: 0 maxfr: 4863
tabn: 0 slot: 7(0x7) flag: 0x2c lock: 2 ckix: 0
ncol: 8 nnew: 1 size: 0
col 5: [ 2] c2 29
¡ 改变向量4
当事务提交之后,记录的SCN信息,注意这里标记为“MEDIA RECOVERY MARKER SCN”,也就是说,这是一个可以恢复的时间点,事务的恢复必须以Redo Record为最小单位。
CHANGE #4 MEDIA RECOVERY MARKER SCN:0x0000.00000000 SEQ: 0 OP:5.20
¡ session信息
最后部分记录的是产生这些Redo的session信息。
session number = 13
serial number = 405
transaction name =
从以上分析中可以看到,对于数据块的修改,如果执行写出,那么通常需要写出8KB的Block,而对于Redo日志来说,重做信息却相当精简,Oracle只需要记录那些重构事务必须的信息(如事务号、文件号、块号、行号、字段等)即可,这个数据量大大减少。
Oracle通过Redo来实现快速提交,一方面是因为Redo Log File可以连续、顺序地快速写出,另外一个方面也和Redo记录的精简内容有关。
为了了解Redo的内容,首先需要了解两个概念:改变向量和重做记录。
¡ 改变向量(Change Vector)
改变向量表示对数据库内某一个数据块所做的一次变更。改变向量(Change Vector)中包含了变更的数据块的版本号、事务操作代码、变更从属数据块的地址(DBA)以及更新后的数据。例如,一个Update事务包含一系列的改变向量,对于数据块的修改是一个向量,对于回滚段的修改又是一个向量。
¡ 重做记录(Redo Record)
重做记录通常由一组改变向量组成,是一个改变向量的集合,代表一个数据库的变更(INSERT、UPDATE、DELETE等操作),构成数据库变更的最小恢复单位。例如,一个Update的重做记录包括相应的回滚段的改变向量和相应的数据块的改变向量等。
下面以一个更新(Update)操作为例介绍一下这个过程,如图6-2所示。
图6-2 更新(Update)操作引起的重做
假定发出了一个更新语句:
UPDATE emp SET sal = 4000 Where empno= 7788;
看一下这个语句是怎样执行的(为了简化描述,这里尽量简化了情况):
(1)检查empno=7788记录在Buffer Cache中是否存在,如果不存在则读取到Buffer Cache中。
(2)在回滚表空间的相应回滚段事务表上分配事务槽,这个操作需要记录Redo信息。
(3)从回滚段读入或者在Buffer Cache中创建sal=3000的前镜像,这需要产生Redo信息并记入Redo Log Buffer。
(4)修改Sal=4000,这是UPDATE的数据变更,需要记入Redo Log Buffer。
(5)当用户提交时,会在Redo Log Buffer记录提交信息,并在回滚段标记该事务为非激活(Inactive)。
下面通过一个具体的试验来再现这个过程。
(1)首先通过switch logfile切换日志。使用SYS用户进行日志切换,使得接下来的更新可以使用新的日志。
SQL> alter system switch logfile;
System altered.
SQL> select * from v$log;
GROUP# THREAD# SEQUENCE# BYTES MEMBERS ARC STATUS FIRST_CHANGE# FIRST_TIM
---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- ---------
1 1 310 10485760 1 NO ACTIVE 8.9035E+12 26-MAR-06
2 1 309 10485760 1 NO INACTIVE 8.9035E+12 19-MAR-06
3 1 311 10485760 1 NO CURRENT 8.9035E+12 26-MAR-06
4 1 308 1048576 1 NO INACTIVE 8.9035E+12 19-MAR-06
(2)更新并提交事务。
SQL> select * from emp where empno=7788;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- --------- ---------- ---------- ----------
7788 SCOTT ANALYST 7566 19-APR-87 3000 20
SQL> update emp set sal=4000
2 where empno=7788;
1 row updated.
SQL> commit;
Commit complete.
(3)确认session信息。
SQL> select sid,serial#,username from v$session
2 where username='SCOTT';
SID SERIAL# USERNAME
---------- ---------- ------------------------------
13 405 SCOTT
(4)使用SYS用户在另外session转储日志文件:
SQL> ALTER SYSTEM DUMP LOGFILE '/opt/oracle/oradata/conner/redo03.log';
System altered.
SQL> @gettrcname
TRACE_FILE_NAME
------------------------------------------------------------------------------------------------------------------------
/opt/oracle/admin/conner/udump/conner_ora_31885.trc
此脚本在本书中多次使用,现收录于下:
SELECT d.VALUE
|| '/'
|| LOWER (RTRIM (i.INSTANCE, CHR (0)))
|| '_ora_'
|| p.spid
|| '.trc' trace_file_name
FROM (SELECT p.spid
FROM SYS.v$mystat m, SYS.v$session s, SYS.v$process p
WHERE m.statistic# = 1 AND s.SID = m.SID AND p.addr = s.paddr) p,
(SELECT t.INSTANCE
FROM SYS.v$thread t, SYS.v$parameter v
WHERE v.NAME = 'thread'
AND (v.VALUE = 0 OR t.thread# = TO_NUMBER (v.VALUE))) i,
(SELECT VALUE
FROM SYS.v$parameter
WHERE NAME = 'user_dump_dest') d
/
(5)获取Trace文件。
从日志文件的转储信息中,可以很容易地找到这个事务(sid= 15,serial#=43870)的信息,为了方便说明,将这段日志分开讲解。
¡ 改变向量1
这是对于回滚段头的修改,分配事务表,从绝对文件号为2(AFN:2)可以知道这是UNDO表空间,通过UBA机DBA的换算能够找到相应的Block,限于篇幅,本文不再做过多的介绍。
REDO RECORD - Thread:1 RBA: 0x000137.00000005.0010 LEN: 0x0198 VLD: 0x01
SCN: 0x0819.0036f14d SUBSCN: 1 03/26/2006 12:01:44
CHANGE #1 TYP:0 CLS:19 AFN:2 DBA:0x00800009 SCN:0x0819.0036f03c SEQ: 1 OP:5.2
ktudh redo: slt: 0x001d sqn: 0x000038ea flg: 0x0012 siz: 108 fbi: 0
uba: 0x008000c3.04b1.0c pxid: 0x0000.000.00000000
¡ 改变向量2
这里记录的是前镜像信息,注意到“col 5: [ 2] c2 1f”记录的就是对于COL 5的修改,修改前的数值是3000(c2 1f)。
CHANGE #2 TYP:0 CLS:20 AFN:2 DBA:0x008000c3 SCN:0x0819.0036f03b SEQ: 1 OP:5.1
ktudb redo: siz: 108 spc: 6740 flg: 0x0012 seq: 0x04b1 rec: 0x0c
xid: 0x0002.01d.000038ea
ktubl redo: slt: 29 rci: 0 opc: 11.1 objn: 7961 objd: 7961 tsn: 0
Undo type: Regular undo Begin trans Last buffer split: No
Temp Object: No
Tablespace Undo: No
0x00000000 prev ctl uba: 0x008000c3.04b1.0b
prev ctl max cmt scn: 0x0819.00364c81 prev tx cmt scn: 0x0819.00365073
KDO undo record:
KTB Redo
op: 0x03 ver: 0x01
op: Z
KDO Op code: URP row dependencies Disabled
xtype: XA bdba: 0x00405c5a hdba: 0x00405c59
itli: 2 ispac: 0 maxfr: 4863
tabn: 0 slot: 7(0x7) flag: 0x2c lock: 0 ckix: 0
ncol: 8 nnew: 1 size: 0
col 5: [ 2] c2 1f
¡ 改变向量3
这里记录的是对于数据块的修改,“col 5: [ 2] c2 29”记录的是对于COL 5的修改,修改后的值为4000(c2 29)。
CHANGE #3 TYP:2 CLS: 1 AFN:1 DBA:0x00405c5a SCN:0x0819.0036efb1 SEQ: 1 OP:11.5
KTB Redo
op: 0x11 ver: 0x01
op: F xid: 0x0002.01d.000038ea uba: 0x008000c3.04b1.0c
Block cleanout record, scn: 0x0819.0036f14d ver: 0x01 opt: 0x02, entries follow...
itli: 1 flg: 2 scn: 0x0819.0036efb1
KDO Op code: URP row dependencies Disabled
xtype: XA bdba: 0x00405c5a hdba: 0x00405c59
itli: 2 ispac: 0 maxfr: 4863
tabn: 0 slot: 7(0x7) flag: 0x2c lock: 2 ckix: 0
ncol: 8 nnew: 1 size: 0
col 5: [ 2] c2 29
¡ 改变向量4
当事务提交之后,记录的SCN信息,注意这里标记为“MEDIA RECOVERY MARKER SCN”,也就是说,这是一个可以恢复的时间点,事务的恢复必须以Redo Record为最小单位。
CHANGE #4 MEDIA RECOVERY MARKER SCN:0x0000.00000000 SEQ: 0 OP:5.20
¡ session信息
最后部分记录的是产生这些Redo的session信息。
session number = 13
serial number = 405
transaction name =
从以上分析中可以看到,对于数据块的修改,如果执行写出,那么通常需要写出8KB的Block,而对于Redo日志来说,重做信息却相当精简,Oracle只需要记录那些重构事务必须的信息(如事务号、文件号、块号、行号、字段等)即可,这个数据量大大减少。