Skip to content

Redo - 2. page

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

浅谈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量

_disable_logging对数据库产生的影响

测试下_disable_logging将对数据库产生的影响,由于是隐含参数,所以通过如下方法获取对这个参数的描述:

SQL> select ksppinm,ksppdesc from x$ksppi where ksppinm like '%logging';

KSPPINM              KSPPDESC
------------------------------------
_disable_logging     Disable logging
 

将其改为ture,也就是启用了不记录日志的方式:

SQL> alter system set "_disable_logging"=true scope=both;
System altered.
 

创建一个,并模拟事务运行,生成大量的redo,

SQL> create table mm tablespace marvener as select * from dba_objects;
Table created.

SQL> insert into mm  select * from dba_objects;
45167 rows created.

SQL> /
 45167 rows created.

此时模拟掉电,shutdown abort关闭数据库:

SQL> shutdown abort
ORACLE instance shut down.
SQL> startup
ORACLE instance started.

Total System Global Area 1610612736 bytes
Fixed Size                  2084296 bytes
Variable Size             385876536 bytes
Database Buffers         1207959552 bytes
Redo Buffers               14692352 bytes
Database mounted.
ORA-00354: corrupt redo log block header
ORA-00353: log corruption near block 81435 change 856029 time 01/30/2012
15:50:39
ORA-00312: online log 1 thread 1: '/u01/app/oracle/oradata/marven/redo01.log'
 

如上。可以发现数据库无法正常打开,并提示重做日志块头损坏,在告警中可见大量的告警,
即使通过Resetlogs方式打开数据库:

alter system set "_allow_resetlogs_corruption"=true scope=spfile;
shutdown abort
startup
 

数据库仍然会显然如下告警,并强制关闭实例:

SMON: enabling cache recovery
Mon Jan 30 16:15:41 2012
Errors in file /u01/app/oracle/admin/marven/udump/marven_ora_2900.trc:
ORA-00600: internal error code, arguments: [2662], [0], [855728], [0], [855937], [8388649], [], []
Mon Jan 30 16:15:42 2012
Errors in file /u01/app/oracle/admin/marven/udump/marven_ora_2900.trc:
ORA-00600: internal error code, arguments: [2662], [0], [855728], [0], [855937], [8388649], [], []
Mon Jan 30 16:15:42 2012
Error 600 happened during db open, shutting down database
USER: terminating instance due to error 600
Instance terminated by USER, pid = 2900
ORA-1092 signalled during: alter database open resetlogs...
Mon Jan 30 16:16:34 2012
  

然而可以通过推进Oracle的SCN来解决此类问题:

增进SCN有几种常用方法,这里介绍其中2种:
1.通过immediate trace name方式(在数据库Open状态下)
alter session set events ‘IMMEDIATE trace name ADJUST_SCN level x’;
2.通过10015事件(在数据库无法打开,mount状态下)
alter session set events ‘10015 trace name adjust_scn level x’;
注:10015的推进级别有个计算算法,具体可以参考adjust的官方说明。

alter session set events '10015 trace name adjust_scn level 10';

SQL> alter database open;

Database altered.