`

转:ORACLE中REDO的解析

阅读更多

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

两个概念:

改变向量(Change Vector

改变向量表示对数据库内某一个数据块所做的一次变更。改变向量中包含了变更的数据块的版本号、事务操作代码、变更从属数据块的地址(DBA)以及更新后的数据。例如:一个update事务包含一系列的改变向量,对于数据块的修改是一个向量,对于回滚段的修改又是一个向量。

重做记录(Redo Record

重做记录通常由一组改变向量组成,是一个改变向量的集合,代表一个数据库的变更(INSERTUPDATEDELETE等操作),构成数据库变更的最小恢复单位。例如:一个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记录提交信息,并在回滚段标记该事务为非激活。

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

 

产生多少Redo

SQL*Plus中使用autotrace功能

当在SQL*Plus中启用autotrace跟踪后,在执行了特定的DML语句时,Oracle会显示该语句的统计信息,其中,Redo size一栏表示的就是该操作产生的Redo的数量:

SQL> set autotrace trace stat

SQL> insert into test

 2 select empno,ename from scott.emp;

已创建12行。

Statistics

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

       189 recursive calls

         2 db block gets

        37 consistent gets

         4 physical reads

       564 redo size

       778 bytes sent via SQL*Net to client

       823 bytes received via SQL*Net from client

         4 SQL*Net roundtrips to/from client

         1 sorts (memory)

         0 sorts (disk)

        12 rows processed

 

通过v$mystat查询:

Oracle通过v$mystat视图记录当前session的统计信息,也可以从该视图中查询得到sessionRedo生成情况:

SQL> col name for a30

SQL> select a.name,b.value

 2 from v$statname a,v$mystat b

 3 where a.statistic#=b.statistic# and a.name='redo size';

 

NAME                               VALUE

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

redo size                              5000

 

SQL> insert into test

 2 select empno,ename from scott.emp;

已创建12行。

 

SQL> select a.name,b.value

 2 from v$statname a,v$mystat b

 3 where a.statistic#=b.statistic# and a.name='redo size';

 

NAME                               VALUE

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

redo size                              5564

 

SQL> select 5564-5000 from dual;

 

 5564-5000

----------

      564

 

通过v$sysstat查询:

对于数据库全局redo的生成量,可以通过v$sysstat视图来查询得到:

SQL> col value for 999999999999

SQL> select name,value from v$sysstat

 2 where name='redo size';

 

NAME                                  VALUE

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

redo size                          11471552

 

v$sysstat视图中得到的是自数据库实例启动以来累计日志生成量,可以根据实例启动时间来大致估算每天数据库的日志生成量:

SQL> select

 2 (select value/1024/1024/1024 from v$sysstat where name='redo size')/

 3 (select sysdate-(select startup_time from v$instance) from dual)

 4 redo_gb_per_day from dual;

 

REDO_GB_PER_DAY

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

    .073238253

 

 

Redo写的触发条件:

3秒钟超时(Timeout

LGWR处于空闲状态时,它依赖于rdbms ipc message等待,处于休眠状态,直到3秒超时时间到,如果LGWR发现有Redo需要写出,那么LGWR将执行写出操作,log file parallel write等待时间将会出现。

启用10046事件,从LGWR跟踪文件中可以观察到这些事件。

 

域值达到:

两个触发日志写的条件:

  • Redo Log Buffer 1/3满;
  • Redo Log Buffer具有1MB脏数据。

这两者都是限制条件,在触发时是协同生效的。

只要有进程在Log Buffer中分配和使用空间,已经使用的Log Buffer的数量将被计算。如果使用的块的数量大于或等于一个隐含参数_log_io_size的设置,那么将会触发LGWR写操作。如果此时LGWR未处于活动状态,那么LGWR将被通知去执行后台写操作。

缺省的_log_io_size等于1/3log buffer大小,上限值为1MB,此参数在X$KSPPSV中显示的0值意为缺省值。

也就是LGWR将在Min(1M,1/3 log buffer size)时触发,注意此处的log buffer size是以Log Block来衡量的。

经常有人推荐Log Buffer设置为3MB大小,就是因为当Redo Log Buffer3MB时,以上两个条件可能同时达到。

 

用户提交

当一个事务提交时,在Redo Stream中将记录一个提交标志。在这些Redo被写到磁盘上之前,这个事务是不可恢复的。所以在事务返回成功标志给用户前,必须等待LGWR写完成。进程通知LGWR写,并且以Log File Sync事件开始休眠,超时时间为1秒。

Oracle的隐含参数_wait_for_sync参数可以设置为false来避免Redo File Sync的等待,但是将无法保证事务的恢复性。

存在一个SGA变量用以记录Redo线程序要同步的Log Block Number。如果多个提交在唤醒LGWR之前发生,此变量记录最高的Log Block Number,在此之前的所有Redo都将被写入磁盘,这有时被称为组提交

 

DBWn写之前

如果DBWR将要写出的数据的高RBA超过LGWR的on-disk rba,则DBWR将通知LGWR去执行写出。

在ORACLE 8I以前,此时DBWR将等待Log File Sync事件。从ORACLE 8I开始,DBWR把这些BLOCK放入一个DEFER队列,同时通知LGWR执行REDO写出,DBWR可以继续执行无需等待的数据写出。

 

Redo Log Buffer的大小设置

Redo Log Buffer的大小由初始化参数LOG_BUFFER定义,该参数的缺省值为:

MAX(512KB,128KB*CPU_COUNT)

通常这个缺省值是足够的,由于Redo Log Buffer的写出操作相当频繁,所以过大的Log Buffer设置通常是没有必要的。如果缺省值不能满足要求,一般来说3MB是一个较合理的调整开端。

log_buffer参数的设置是否需要调整,可以从数据库的等待事件来判断:

SQL> select event#,name from v$event_name where name='log buffer space';

   EVENT# NAME

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

      178 log buffer space

Log Buffer Space等待事件出现并且较为显著时,可以考虑增大Log Buffer以缩减竞争。

 

Commit做了什么

当完成事务操作,发出Commit命令之后,随后会收到一个反馈“Commit complete”。

提交完成,意味着Oracle已经将此时间点之前的Redo写入重做日志文件中,这个日志写完成之后,Oracle可以释放用户去执行其他任务。如果此后发生数据库崩溃,那么Oracle可以从重做日志文件中恢复这些提交过的数据,从而保证提交之后的数据不会丢失。

 

日志的状态

CURRENT:指的是当前的日志文件,该日志文件是活动的,当前正在被使用的,在进行崩溃恢复时,Current的日志文件时必须的。

ACTIVE:活动的非当前日志,该日志可能已经完成归档也可能没有归档,活动的日志文件在Crash恢复时会被用到。

ACITVE状态意味着检查点尚未完成,如果日志文件循环使用再次到达该文件,数据库将处于等待的停顿状态,此时在alert文件中,可以看到类似如下记录:Checkpoint not complete

当这种问题出现时,可以从数据库内部通过v$session_wait来观察,该视图会显示数据库当前哪些session正处于这种等待。

Checkpoint not complete在数据库中体现为等待事件log file switch(checkpoint incomplete)

SQL> select sid,event,state from v$session_wait;

 

在此同时,可能DBWR进程正在进行db file parallel write,日志文件必须等待DBWR完成检查点触发的写操作之后才能被覆盖。如果设置了参数log_checkpoints_to_alertTRUE的话,还可以在alert文件中清晰地看到检查点的增进和完成情况。

引起Checkpoint Incomplete可能有以下多种原因

日志文件过小,切换过于频繁;

日志组太少,不能满足正常业务量的需要;

日志文件所在磁盘I/O存在瓶颈,导致写出缓慢,阻塞数据库正常运行;

由于数据文件磁盘I/O瓶颈,DBWR写出过于缓慢;

由于事务量巨大,DBWR负载过高,不堪重负。

解决方法

适当增加日志文件大小;

适当增加日志组数;

使用更快的磁盘存储日志文件(如采用更高转速磁盘;使用RAID10而不是RAID5等方式);

改善磁盘I/O的性能;

使用多个DBWR进程或使用异步I/O等。

 

注意:Checkpoint Incomplete是一类严重的等待,它意味着数据库不能再产生日志,所有数据库修改操作将全部挂起。

 

INACTIVE:非活动日志,该日志在实例恢复时不再需要,但是在介质恢复时可能会用到。INACTIVE状态的日志也可能没有被归档。如果数据库启动在归档模式,在未完成归档之前,日志文件也不允许被覆盖,这时候活动进程会处于log file switch(archiving needed)等待之中。

日志是否完成归档,可以根据v$log视图的archived字段进行判断。

 

UNUSED:是指该日志从未被写入,这类日志可能是刚被添加到数据库或者在RESETLOGS之后被重置。被使用之后,该状态会被改变。

 

日志块的大小:

初始化参数LOG_BUFFER决定了Redo Log Buffer的大小,这个参数的缺省值为

MAX(512KB,128KB*CPU_COUNT)

虽然LOG_BUFFER中的Redo Entries的大小是以bytes为单位,但是LGWR仍然以block为单位把redo写入磁盘,Redo Block SizeOracle源代码中固定的,通常的操作系统都是以512bytes为单位。

可以从v$sysstat中的统计信息中通过计算粗略得到,主要有以下几个统计信息:

  1. Redo SizeRedo信息的大小;
  2. Redo Wastage:浪费的Redo的大小;
  3. Redo Block WrittenLGWR写出的Redo Block的数量;
  4. 额外的信息:每个Redo Block Header需要占用16bytes

SQL> select name,value from v$sysstat

 2 where name in('redo size','redo wastage','redo blocks written');

 

NAME                                                                 VALUE

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

redo size                                                          6298004

redo wastage                                                       1458232

redo blocks written                                                  15641

 

SQL> select ceil(16+(6298004+1458232)/15641) rbsize from dual;

   RBSIZE

----------

      512

  

日志文件的大小:

当日志文件发生切换时,会触发一个检查点,那么日志文件的大小就和检查点的触发频率相关。频繁的检查点操作可以缩短数据库的恢复时间,但是过于频繁的检查点却会带来性能负担。所以如何合理的设置日志文件的大小也是数据库优化的一个重要内容。

一般来说,在实际生产环境中,把log switch的时间控制在半小时左右即可。

 

为什么热备份期间产生的Redo要比正常的多

在数据库处于热备份状态时,会产生比平常更多的日志。这是因为在热备份期间,Oracle为了解决SPLIT Block的问题,需要在日志文件中记录修改的行所在的数据块前镜像,而不仅仅是修改信息。

简单了解一下SPLIT Block的概念:

Oracle的数据块是由多个操作系统块组成。通常UNIX文件系统使用512bytes的数据块,而Oracle使用8KBdb_block_size。当热备份数据文件时,要使用文件系统的命令工具(cp)拷贝文件,并且使用文件系统的blocksize读取数据文件。

这种情况下,可能出现如下状况:当拷贝数据文件的同时,数据库正好向数据文件写数据。这就使得拷贝的文件中包含这样的database block,它的一部分OS Block来自于数据库向数据文件(这个DB Block)写操作之前,另一部分来自于写操作之后。对于数据库来说,这样的Block本身并不一致,而是一个分裂块(SPLIT Block)。这样的分裂块在恢复时并不可用(会提示Corrupted Block)。

所以在热备份状态下,对于变更的数据,Oracle需要在日志中记录整个变化的数据块的前镜像。这样如果在恢复的过程中,数据文件中出现分裂块,Oracle就可以通过日志文件中的数据块的前镜像覆盖备份,以完成恢复。

 

分裂块产生的根本原因在于备份过程中引入了操作系统工具(如cp工具等),操作系统工具无法保证Oracle数据库的一致性。如果使用RMAN备份,由于RMAN可以通过反复对区获得一致的Block,从而可以避免Split Block的生成,所以不会生成额外的Redo。因此建议在备份时(特别是繁忙的数据库),应该尽量采用RMAN备份。

 

能否不生成Redo

NOLOGGING对于数据库的影响

正常的数据库必须生成Redo,这是数据库的机制,否则数据库在遇到故障或Crash时则无法恢复。但是Oracle为了增强某些特殊操作的性能,对于一些SQL语句,Oracle允许使用NOLOGGING子句,NOLOGGING可以使得日志生成大幅降低,但是必要日志(比如对于字典表的修改)仍然会被记录。

可以使用NOLOGGING的环境非常有限,在以下操作中,可以增加NOLOGGING子句:

  • 创建索引或重建索引时;
  • 通过/*+append */提示,使用直接路径批量INSERT操作或SQL*Loader直接路径加载数据;
  • CTAS方式创建数据表时;
  • 大对象(LOB)的操作;
  • 一些Alter table操作,如movesplit等。

 

 

关于NOLOGGING的作用,在ITPUB上曾经有过深入的探讨,总结起来就是,NOLOGGING与表模式(NOLOGGING/LOGGING)、插入模式(APPEND/NO APPEND)及数据库的运行模式(归档/非归档)都有关系。具体可以归结为下面的表:

 

数据库模式         表模式          插入模式         REDO生成

ARCHIVELOG         LOGGING         APPEND           有REDO

                                   NO APPEND        有REDO

                   NOLOGGING       APPEND           无REDO

                                   NO APPEND        有REDO

NOARCHIVE LOG      LOGGING         APPEND           无REDO

 

                                   NO APPEND        有REDO

                   NOLOGGING       APPEND           无REDO

                                   NO APPEND        有REDO

 

 

需要注意的是,由于NOLOGGING操作会导致对于数据的操作不记录日志,如果数据库崩溃,这部分数据是无法恢复的,所以通常的建议是,在进行了NOLOGGING操作之后,需要对数据库进行备份,以避免数据因数据库实效而丢失。

 

disable_logging对于数据库的影响

Oracle存在一个内部参数,可以使数据库关闭日志记录,从而实现某些特殊需要或测试目的,这个参数是_disable_logging,可以动态设置这个参数。

由于不记录日志,在进行数据库恢复时,这些数据是无法恢复的。

如果数据库运行在归档模式下,设置该参数会导致日志文件损坏。因为在设置该参数之后,归档进程无法识别该日志文件格式,会将该日志文件标记为损坏。

设置了_disable_logging参数,可以禁用日志的生成,从而提高某些测试的性能。

 

Force logging(强制日志)模式

当使用Dataguard作为数据库的备份或容灾高可用性手段时,通常日志就变得不可缺少。在Oracle 9iR2中,可以将数据库置于强制日志模式(Force Logging Mode)。在强制日志模式下,所有操作都将记录日志。

 

Redo故障的恢复

丢失非活动日志组的故障恢复

如果数据库丢失的是非活动(INACTIVE)日志组,由于非活动日志组已经完成检查点,数据库不会发生数据损失,此时只需要通过clear重建该日志组即可。

清除日志组的命令:

alter database clear logfile group 2;

如果数据库处于归档模式下,并且该日志组未完成归档则需要使用如下命令强制清除:

Alter database clear unarchived logfile group 2;

 

丢失活动或当前日志文件的恢复

在损失当前日志时,数据库是正常关闭的

由于关闭数据库前,Oracle会执行全面检查点,当前日志在实例恢复中可以不再需要。直接clear即可。

Oracle 9i中,可能无法对当前日志进行clear,需要通过until cancel恢复后,resetlogs打开。

 

在损失当前日志时,数据库是异常关闭的

如果在损失当前日志时,数据库是异常关闭的,那么Oracle在进行实例恢复时必须要求当前日志,否则Oracle将无法保证提交成功的数据不丢失(也就意味着Oracle会丢失数据),在这种情况下,Oracle数据库将无法启动。

对于这种情况,通常需要从备份中恢复数据文件,通过应用归档日志文件向前推演,直到最后一个完好的日志文件,然后通过resetlogs启动数据库完成恢复。丢失的数据就是损坏的日志文件中的数据。

分享到:
评论

相关推荐

    oracle IO问题解析

    Redo Log 的写入是指 Oracle 数据库中对 Redo Log 文件的写入,包括事务中的写操作和 Log Buffer 中的记录。LGWR 进程负责将 Log Buffer 中的记录写入 Redo Log 文件中去。 Archive Log 的写入是指 Oracle 数据库中...

    Oracle SCN机制解析

    Oracle SCN(System Change Number)机制是Oracle数据库中用于追踪和管理数据变化的关键组件。SCN是一个不断递增的数字,确保了数据库能够准确地识别和处理事务中的数据修改,尤其是在故障恢复、Data Guard、Streams...

    oracle scn概念解析

    ### Oracle SCN 概念解析 #### 一、SCN 的定义与作用 **SCN (System Change Number)** 是 Oracle 数据库中的一个重要概念,用于记录数据库的状态变化。它本质上是一个递增的逻辑计数器,每当数据库发生变化时就会...

    Oracle redo 异常暴增 日志挖掘 logminer

    Oracle Redo日志是数据库系统中的重要组成部分,用于记录事务对数据块的修改,确保数据在系统崩溃或异常情况下的可恢复性。当Redo日志异常暴增时,这通常意味着数据库活动增加,或者存在某些问题导致了不必要的日志...

    深入解析ORACLE初始化

    "深入解析Oracle初始化"意味着我们将探讨Oracle数据库在启动时如何配置和准备其环境,以确保高效、稳定和安全的运行。Oracle的初始化参数文件,通常称为init.ora或spfile,包含了控制数据库行为和设置的各种参数,这...

    Oracle IO问题解析

    ### Oracle IO问题解析 #### 一、Oracle中的IO产生 在深入探讨Oracle数据库中的输入输出(IO)问题之前,我们首先要了解Oracle数据库的基本物理结构及其如何处理数据的读写操作。Oracle数据库的IO问题通常涉及读取...

    oracle日志查看程序

    用java写的一个oracle日志查看器源代码,调用oracle数据库的logminer过程。包含一个不错的日历选择面板

    oracle的原文书籍

    1. **Oracle体系结构**:Oracle数据库的架构包括多个组件,如SGA(System Global Area)、PGA(Program Global Area)、Redo Logs、Datafiles、Control Files等。理解这些组件的职责和交互方式是深入学习Oracle的...

    hex格式redo log解析

    在Oracle数据库中,redo log是持久化数据的重要部分,它确保了即使在系统崩溃或硬件故障后,数据库也能恢复到一致的状态。本篇将深入解析hex格式的redo log,包括文件头、日志头、块头以及一个insert语句的详细内容...

    涂抹Oracle 高清版

    首先,"涂抹Oracle"这个标题可能寓意着作者以一种新颖、直观的方式解析Oracle的复杂性,如同在Oracle的复杂表象上涂抹清晰的色彩,使读者能看透其内在机制。这种比喻性的手法在教学中常见,能够激发读者的兴趣,使...

    Oracle数据库体系结构( 中文详细版)

    本文将详细解析Oracle数据库的体系结构,帮助读者深入理解其内部工作原理。 Oracle数据库的核心架构可以分为以下几个主要部分: 1. **数据文件**(Data Files):数据文件是Oracle数据库存储实际数据的地方,包含...

    oracle代码

    标签 "源码 工具" 提示我们可能涉及Oracle数据库的源代码解析或使用工具进行操作。 在Oracle数据库中,SQL(结构化查询语言)是用于管理关系型数据库的主要工具。`study.sql` 文件很可能包含了用于学习、测试或演示...

    REDO文件block损坏的解决方法

    在Oracle数据库管理中,遇到REDO文件block损坏的情况是一种较为复杂且紧急的问题,尤其是在Oracle 8版本中。本文将详细解析此类问题的成因、影响以及解决方案,旨在为数据库管理员提供一套行之有效的应对策略。 ###...

    oracle实训教材

    10. **故障排除**:学习如何阅读和解析Oracle的日志文件,如alert.log、trace文件和DBA视图,可以帮助你在遇到问题时快速定位和解决问题。 通过这份"Oracle实训教材"的学习,你将不仅获得理论知识,还能通过实际...

    oracle内存管理,深入浅出oracle内存管理,盖国强oracleppt

    在这个过程中,软解析(soft parse)是指如果在Library Cache中找到已解析的SQL,而硬解析(hard parse)则表示需要重新解析SQL。 7. **CBO与RBO**:Cost-Based Optimizer(CBO)和Rule-Based Optimizer(RBO)是...

    深入分析oracle日志文件

    LogMiner 可以重构等价的 SQL 语句和 UNDO 语句,记录在 V$LOGMNR_CONTENTS 视图的 SQL_REDO 和 SQL_UNDO 中。LogMiner 还可以将日志中记录的信息转换为原始 SQL 语句,包括数据库的更改历史、更改类型、更改对应的 ...

    oracle

    3. **SQL处理**:Oracle支持标准SQL语言,提供强大的查询优化器来处理SQL语句,通过解析、优化和执行三个阶段完成对数据的操作。 4. **事务处理**:Oracle支持ACID(原子性、一致性、隔离性和持久性)特性,保证了...

    ORACLE的工作机制.rar

    以下是对Oracle工作机制的详细解析: 1. **数据存储**:Oracle采用表空间(Tablespaces)的概念来管理数据,表空间由一个或多个数据文件(Datafiles)组成。数据在数据文件中以块(Blocks)的形式存储,块是Oracle...

Global site tag (gtag.js) - Google Analytics