Skip to content

Redo and Undo - 2. page

2.解析REDO:Records

前面一节讲到,一个redo logfile中包含了2部分内容,分别为Redo file header,Redo record。这里将对这2部分进行解析。
1.2.1 Redo logfile header
重做日志文件头的大小为512byte,在一个logfile的dump中可以在file header中找到 BLKSIZ=512.日志文件头主要记录的内容为当前日志的seq,rba,scn,logsize,log number,DBID,low rba,highrba等信息。(如下图)

Opcodes *.*
RBAs: 0x000000.00000000.0000 thru 0xffffffff.ffffffff.ffff
SCNs: scn: 0x0000.00000000 thru scn: 0xffff.ffffffff
Times: creation thru eternity
FILE HEADER:
Compatibility Vsn = 185597952=0xb100000
Db ID=3093517514=0xb86354ca, Db Name='11GOCMDB'
Activation ID=3093532362=0xb8638eca
Control Seq=1033=0x409, File size=102400=0x19000
File Number=2, Blksiz=512, File Type=2 LOG
descrip:"Thread 0001, Seq# 0000000014, SCN 0x0000000c76be-0xffffffffffff"
thread: 1 nab: 0xffffffff seq: 0x0000000e hws: 0x2 eot: 1 dis: 0
resetlogs count: 0x2f85bc4c scn: 0x0000.00081bca (531402)
prev resetlogs count: 0x27a409d9 scn: 0x0000.00000001 (1)
Low scn: 0x0000.000c76be (816830) 11/20/2013 23:37:48
Next scn: 0xffff.ffffffff 01/01/1988 00:00:00
Enabled scn: 0x0000.00081bca (531402) 10/21/2012 22:27:24
Thread closed scn: 0x0000.000c76be (816830) 11/20/2013 23:37:48
Disk cksum: 0xd4a3 Calc cksum: 0xd4a3
Terminal recovery stop scn: 0x0000.00000000
Terminal recovery 01/01/1988 00:00:00
Most recent redo scn: 0x0000.00000000
Largest LWN: 0 blocks
End-of-redo stream : No
Unprotected mode
Miscellaneous flags: 0x800000
Thread internal enable indicator: thr: 0, seq: 0 scn: 0x0000.00000000

1.2.2 Redo record header
Redo record主要由2部分组成,分别为redo record header和change vectors,在这里把change vectors我单独出来一章分析,因为在这一部分oracle在10g的前后做了比较大的变化(IMU),原理不同(1.1.5中有描述),这部分只讲解redo record header.

Redo record header 的内容大致如下:

REDO RECORD - Thread:1 RBA: 0x00000e.00000003.0010 LEN: 0x02a4 VLD: 0x05
SCN: 0x0000.000c76c2 SUBSCN: 1 11/20/2013 23:37:49

可以看到redo record header的内容主要包含信息为RBA,LEN,SCN,SUBSCN,THREAD等信息。因为这RBA和SCN个内容和redo标识中最重要的组成部分,下来对上面的RBA和SCN号做详细的解析

1. RBA(redo byte address)
在redo logfile中,没一个redo record都对应有一个RBA,记录这个record所处在的位置,RBA为10个字节大小,由三个部分组成,
分别为:
日志文件序列号(4字节)
日志文件块编号(4字节)
重做日志记录在日志块中的起始偏移字节数(2字节)

RBA: 0x00000e.00000003.0010

日志文件序列号:0x00000e
日志文件块编号:00000003
偏移字节数:0010
通常使用RBA的形式有:
LRBA (LOW RBA)

Redo log file中的LRBA (Low Redo Block Address) 表示脏数据块在buffer cache中第
一次被修改时候所对应的重做条目在重做日志文件中的地址 (Low表示第一次修改)
[LRBA0][LRBA1][LRBA2][LRBA3][LRBA4][LRBA5][LRBA6]

HRBA (HIGH RBA)

数据缓存(buffer cache)中一个脏块最近一次被更新的时候产生的重做日志记录在
重做日志文件中所对应的位置就称为HRBA。

checkpoint RBA

当一个checkpoint事件发生的时候,checkpoint进程会记录下当时所写的重做日志
记录的地址即RBA,此时记录的RBA被称为checkpoint RBA。从上一个checkpoint RBA
到当前的checkpoint RBA之间的日志所保护的buffer cache中的脏块接下来将会被写
入到数据文件当中去。

2. SCN(system change number)
也称作system commit number,一共有6字节长,格式为如下:

SCN: 0x0000.000c76c2

由2部分组成,

WRAP:0x0000(2bytes)
BASE:000c76c2(4bytes)

Base部分记录着当前数据库最新的scn,一般保存在record header中,rac中记录的为全局scn,分布式事务记录的为high scn。

关于scn更详细的内容可以参考
http://czmmiao.iteye.com/blog/1010267

1.谈谈对redo的理解

作为这一系列文章的开头,我想说一些问题,它们是我在学习oracle到这一步入门时候所积累的一些经验。
任何的技术学习都有一个目的,学习oracle也一样。在学习到redo的时候你又是怎么样的目的?这里不妨我提出几个问题,作为思考的方向。

1.redo 日志是什么?
2.redo 有何作用?
3.redo 直接有关的进程有哪些?
4.redo 和内存中的哪块区域有关?
5.redo 相关的字典或者视图有哪些,redo记录了哪类信息?
6.redolog的结构是怎么样的?
7.在数据库中怎么统计一个事务的相关redo量?

关于redo重做日志的概念可以参考《concepts》里1.1.3.3部分的介绍.我这里将对redo作主要特征以及运行原理的理解阐述。

一:redo的介绍

redo日志它记录了对database的所有变更操作的记录,这些在数据库中的变更操作记录叫做重做日志条目(redo entry).redo日志主要应用在Recover(实例恢复以及介质恢复),dataguard,goldengate,stream等恢复以及数据同步的环境中。

二:redo entry有3个主要特性:

2.1.在实例中,一个变更操作在数据库加载在buffercache之前或者实际的block操作之前就已经在log buffer中生成相关的redo entry(重做日志条目)
2.2.在将变更的块写入datafile之前,相关事务的redo entry必须先由lgwr进程写入到redo logfile中
2.3.当一个事务提交的时候,logbuffer中的redo entry写入到redo log file

(这里原理涉及到了checkpoint以及增量checkpoint的机制,在这个系列的checkpoint中将会结合oracle在redo设计上为了保护crash方面作详细解说.)
三:redo entry的生成:
3.1:10g中的写redo log buffer的步骤(10g的新特性,即IMU,in memory undo)

1. 通过获得在private memory中的配对的内存结构,开始事务。配对的内存结构一个是从x$ktifp(即in memory undo pool,负责undo变化矢量),一个是从x$kcrfstrand(即private redo,负责forward变化矢量)。
2.标记每个受影响的block为“has private redo”(但是不改变block)
3.将每个undo变化矢量写入被选中的in memory undo pool
4.将每个redo变化矢量写入被选中的private redo thread
5.通过将上述的2个内存结构串联到一个redo change记录中,事务完成(shared pool)。
6.将redo change记录拷贝到redo中,并且将change apply到block上。

1

3.2:10g之前版本的redo record 生成步骤
  datablock在block header分配ITL。
  生成undo的change vector(PGA)
  生成data的change vector(pga)
  将undo的redo vector和data的redo vector合并成一条change record。
  获得redo copy的latch
  获得redo allocation的latch
  将change record写入到log buffer中
  应用undo的change vector
  应用data的change vector
2

四 Redo log的存储相关
1. redo logfile是存储在系统中的,它使用的redo 块大小取决于操作系统的块大小。通常是512bytes,存储格式取决于操作系统和数据库版本。
2. 每一个redo logfile包含了日志文件头,重做日志条目
3. redo logfile的重做日志条目是顺序写的方式
一个redo logfile的基础结构如下图:
3

12.实例恢复,介质恢复,崩溃恢复的原理理解

OCP教材 042 – 02章

1、media recovery是需要利用以前的备份来进行恢复的,而INSTANCE RECOVERY是不需要的。

2、media recovery通常发生在数据库的数据文件之类发生损坏,需要利用以前的备份来进行的恢复,需要人工处理;

而INSTANCE恢复则是发生在实例不正常关闭情况下的恢复,是INSTANCE自己来的,不需要人工干预的。

Media Recovery 概念:

如果发生数据文件丢失或破坏,就需要用备份和归档日志来进行恢复,这种恢复操作就叫作介质恢复(Media Recovery),这种恢复操作需要有备份、归档日志、联机日志一起才能完成,并分成完全恢复和不完全恢复两种情况。

Instance Recovery概念:

如果实例被SHUTDOWN ABORT方法强行关闭,或者因为断电等事故发生故障。数据文件、控制文件、联机日志都没有丢失,这时数据库再次启动时,要利用联机日志的内容进行恢复,这种恢复就是实例恢复(Instance Recovery)。

Instance Recovery主要包括3个阶段:

1)根据联机日志内容进行ROLLOVER;

2)打开数据库,提供服务;

3)SMON或用户进程进行ROLLBACK。

Crash Recovery:

到了RAC环境下,同样也有Media Recovery和Instance Recovery,并且RAC还有Crash Recovery。

简单地说,Instance Recovery是指所有的实例都发生Crash后进行的Recovery,从发生地点来看,这种Recovery发生在故障实例上,是故障实例重新启动时执行的Recovery。

而Crash Recovery是指某个实例发生了Crash后在其他实例上进行的Recovery。这里最重要的区别是发生地点不是在故障节点,而是在某个健康节点。这种Recovery有一个特殊要求:在健康节点执行Crash Recovery时,必须要保证故障节点不能再对共享数据进行操作,也就是要对故障节点进行IO隔离(IO Fencing),这是由CSS服务来保证的。

在单实例环境下,Crash Recovery和Instance Recovery没有区别。只有在RAC这种多实例环境下,这两个名词的区别才能体现出来。

说明:对于Crash Recovery最重要的是,必须保证在执行Crash Recovery时,故障节点被IO Fencing。

Crash/Instance Recovery与Media Recovery的本质区别在于:

Crash/Instance Recovery针对需要恢复的实例从增量检查点(incremental checkpoint)开始apply redo应用重做日志。由于日志覆盖的先提条件是完成相关日志的logfile switch checkpoint,且从定义上说归档日志总是落后于实例的检查点,所以对于crash/instance recovery崩溃或实例恢复总是只需要访问读取在线的重做日志(online redo logfile)。

介质恢复Media Recovery从旧数据文件的检查点开始apply redo引用重做日志,这些旧的数据文件可能来源于备份。 介质恢复情况下需要用到归档重做日志,因此RMAN或DBA(用户管理的备份)也需要将备份相关的归档日志还原出来。

Crash/Instance Recovery总是保证仅当所有的持久重做数据被应用之后才算恢复完成。 在Oracle保证所有已提交的事务都已经被包含恢复的情况下,才认为崩溃实例完成了恢复工作。

相反,介质恢复有不完全恢复(incomplete recovery)和部分恢复(partial recovery)的提法,以实现恢复数据库(db)到某个时间点的一致性。

Crash/Instance Recovery与Media Recovery的相同点在于:

Crash/Instance Recovery与Media Recovery都是传统的前滚恢复方式(rolling forward),原理上都是对持久redo log数据的重演。 不管是Crash/Instance Recovery还是Media Recovery的前滚,都需要继之以事务回滚以便回滚未提交的事务,虽然前滚完成后数据库即可以打开而不用等回滚完成,但是仅在回滚完成的时候我们认为数据库是真正一致的。

浅谈Oracle的恢复机制以及各种恢复手段(更新中)

一直都要把redo,undo在recovery中是怎么协调作用的东西写下来,一直都往后推拖,到了现在稍微有了点时间,也就顺便把这一系列的东西做了一个整理.
我这些文章中对log的dump操作请参考文章
How to Dump Redo Log File Information

大概会有3个大系列,分为如下部分:

1.谈谈redo

1.1.谈谈redo以及Imu的理解
1.2.什么是redo Records
1.3.理解redo log file header,redo block header and redo record header
1.4.什么是change vectors
1.5.理解Row and Index Operations
1.6.理解Direct Loads以及Nologging 在redo中的展现
1.7.理解审计与Redo之间的关系
1.8.理解附加日志内幕
(www.ludatou.com)

2:谈谈undo机制

2.1.理解undo的作用
2.2.理解事务与undo的关系
2.3.理解XID
2.4.理解UBA
2.5.理解UNDO CHAIN实现机制
2.6.理解延迟块清除
2.7.关于ora-01555的处理
(www.ludatou.com)

 

3.谈谈检查点机制

3.1.

4.谈谈控制文件

4.1理解控制文件的作用
4.2理解bootstrap

5.谈谈恢复原理以及特殊恢复技术

5.1.概念:实例恢复,介质恢复,崩溃恢复的概念
13.深入理解recovery的实现机制:Page Fix、写日志优先、Checkpoint
(www.ludatou.com)
5.1.1无法启动故障根本原因的定位案例
5.2.ora 00600 [2662]处理
5.3.ora 00600 [4097]一例
5.4.ora 00600 [4193]处理
—-BBED处理
5.5.数据文件头损坏恢复
5.6.控制文件损坏恢复
5.7.系统表空间损坏恢复

 

 

redo 日志产生量的监控以及测试

用实验说明
一、在非归档模式下:
view plaincopy
SQL> archive log list
数据库日志模式 非存档模式
自动存档 禁用
存档终点 USE_DB_RECOVERY_FILE_DEST
最早的联机日志序列 2491
当前日志序列 2493

用sys用户创建查询redo size的视图(方便查询)
view plaincopy
SQL> create or replace view redo_size
2 as
3 select value
4 from v$mystat, v$statname
5 where v$mystat.statistic# = v$statname.statistic#
6 and v$statname.name = ‘redo size’;

视图已创建。
用sys用户创建同义词
view plaincopy
SQL> create public synonym redo_size for redo_size;

同义词已创建。

以下用scott操作
创建测试表
view plaincopy
SQL> create table test_redos as select * from dba_objects where 1=2;

表已创建。

查看当前redo量
view plaincopy
SQL> select * from redo_size;

VALUE
———-
736

插入数据,看结果
view plaincopy
SQL> insert into test_redos select * from dba_objects;

已创建73104行。

SQL> select * from redo_size;

VALUE
———-
8473536

SQL> insert /*+ append */ into test_redos select * from dba_objects;

已创建73100行。

SQL> select * from redo_size;

VALUE
———-
8504856

SQL> select (8473536-736)普通插入,(8504856-8473536) append插入 from dual;

普通插入 APPEND插入
———- ———-
8472800 31320

以上结果说明在非归档模式下,append插入数据产生的redo要少得多。

二、在归档模式下(在数据库和表空间级别为设置force logging的情况下,默认非force logging):
view plaincopy
SQL> archive log list;
Database log mode Archive Mode
Automatic archival Enabled
Archive destination /archive1
Oldest online log sequence 114
Next log sequence to archive 116
Current log sequence 116

同上(非归档里面)建立测试表
①:在表为logging的情况下
view plaincopy
SQL> create table test_redos as select * from dba_objects where 1=2;

Table created.

SQL> select * from redo_size;

VALUE
———-
26812

SQL> insert into test_redos select * from dba_objects;

71971 rows created.

SQL> select * from redo_size;

VALUE
———-
8490044

SQL> insert /*+ append */ into test_redos select * from dba_objects;

71971 rows created.

SQL> select * from redo_size;

VALUE
———-
17001396

SQL> select (8490044-26812)普通插入,(17001396-8490044) append插入 from dual;

普通插入 APPEND插入
———- ———-
8463232 8511352

可以看出在归档模式表logging(默认)的情况下,append插入产生的redo量并不会减少。
②:在表nologging的情况下
将表设置为nologging模式
view plaincopy
SQL> alter table test_redos nologging;

Table altered.
继续测试
view plaincopy
SQL> select * from redo_size;

VALUE
———-
8397184

SQL> insert into test_redos select * from dba_objects;

71971 rows created.

SQL> select * from redo_size;

VALUE
———-
16801072

SQL> insert /*+ append */ into test_redos select * from dba_objects;

71971 rows created.

SQL> select * from redo_size;

VALUE
———-
16836516

SQL> select (16801072-8397184)普通插入,(16836516-16801072) append插入 from dual;

普通插入 APPEND插入
———- ———-
8403888 35444

可以看出在表nologging的模式下,append可以减少大量减少redo量的产生。
三、在归档force logging模式下:
改变SCOTT用户的默认表空间为force logging模式
view plaincopy
SQL> select username,default_tablespace from dba_users where username=’SCOTT’;

USERNAME DEFAULT_TABLESPACE
—————————— ——————————
SCOTT USERS
–在数据级别置为force logging模式语句为 alter database force logging;
SQL> alter tablespace users force logging;

Tablespace altered.
继续测试
view plaincopy
SQL> select * from redo_size;

VALUE
———-
25488368

SQL> insert into test_redos select * from dba_objects;

72010 rows created.

SQL> select * from redo_size;

VALUE
———-
33973556

SQL> insert /*+ append */ into test_redos select * from dba_objects;

72010 rows created.

SQL> select * from redo_size;

VALUE
———-
42492396

SQL> select (33973556-25488368)普通插入,(42492396-33973556) append插入 from dual;

普通插入 APPEND插入
———- ———-
8485188 8518840

可以看出在表空间在force logging模式下append不能减少redo量