zoukankan      html  css  js  c++  java
  • oracle 日志学习(转载)

    一,重做日志概念

    重做日志文件(redo log file)对于Oracle数据库至关重要。它们是数据库的事务日志。通常只用于恢复,不过也可以用于以下工作:

    q 系统崩溃后的实例恢复

    q 通过备份恢复数据文件之后恢复介质

    q 备用(standby)数据库处理

    q 输入到流中,这是一个重做日志挖掘过程,用于实现信息共享(这也是一种奇特的复制)

    重做日志文件的主要目的是,万一实例或介质失败,重做日志文件就能派上用场,或者可以作为一种维护备用数据库(standby database)的方法来完成故障恢复。如果数据库所在主机掉电,导致实例失败,Oracle会使用在线重做日志将系统恢复到掉电前的那个时刻。如果包 含数据文件的磁盘驱动器出现了永久性故障,Oracle会使用归档重做日志以及在线重做日志,将磁盘驱动器的备份恢复到适当的时间点。另外,如果你“无意 地”删除了一个表,或者删掉了一些重要的信息,而且提交了操作,则可以恢复一个备份,并让Oracle使用这些在线和归档重做日志文件将其恢复到意外发生 前的那个时刻。

    你在Oracle中完成的每个操作几乎都会生成一定的redo信息,并写入在线重做日志文件。向表中插入一行时,插入的最终结果会写入重做日志。删 除一行时,则会在重做日志中写入你删除了这一行这一事实。删除一个表时,删除的效果会写入重做日志。从表中删除的数据不会写入;不过,Oracle删除表 时执行的递归SQL确实会生成redo。例如,Oracle从SYS.OBJ$表(和其他内部字典对象)中删除一行时,这就会生成redo,另外如果支持 不同模式的补充日志(supplemental logging ),还会把具体的DROP TABLE语句写入重做日志流。

    有些操作可能会以尽量少生成redo的模式完成。例如,可以使用NOLOGGING属性创建一个索引。这说明,最初创建索引数据的操作不会记入日 志,但是Oracle完成的所有递归SQL会写入日志。例如,创建索引后,将向SYS.OBJ$表中插入一行表示索引存在,这个插入会记入日志,以后使用 SQL插入、更新和删除等操作完成的修改也会记入日志。但是,最初向磁盘写索引结构的操作不会记入日志。

    前面我提到了两种类型的重做日志文件:在线(online)和归档(archived)。下面几节将详细介绍这两类重做日志文件。在第9章中,我们还会结合回滚段来讨论redo,看看它们对开发人员有什么影响。现在,我们只关注这些重做日志文件是什么,它们有什么用途。

    3.7.1 在线重做日志

    每个Oracle数据库都至少有两个在线重做日志文件组。每个重做日志组都包含一个或多个重做日志成员(redo按成员组来管理)。这些组的单个重 做日志文件成员之间实际上形成彼此真正的镜像。这些在线重做日志文件的大小是固定的,并以循环方式使用。Oracle先写日志文件组1,当到达这组文件的 最后时,会切换至日志文件组2,从头到尾重写这些文件的内容。日志文件组2填满时,再切换回到日志文件组1(假设只有两个重做日志文件组;如果有3个重做 日志文件组,当然会继续写第3个组)。如图3-4所示。4 日志文件组


    从一个日志文件组切换到另一个日志文件组的动作称为日志切换(log switch)。重要的是注意到,如果数据库配置得不好,日志切换可能会导致临时性“暂停”。由于重做日志的目的是在失败时恢复事务,所以我们自己必须保 证一点:在重用重做日志之前,失败时应该不需要重做日志文件的内容。如果Oracle不能肯定这一点,也就是说,它不清楚是否真的不需要日志文件的内容, 就会暂时挂起数据库中的操作,确保将缓存中的数据(即redo“保护”的数据)安全地写入磁盘本身(建立检查点)。一旦Oracle能肯定这一点,再恢复 处理,并重用重做文件。

    我们刚刚提到一个重要的数据库概念:检查点(checkpointing)。要理解在线重做日志如何使用,就需要了解检查点,知道数据库缓冲区缓存如何工作,还要知道一个称为数据块写入器(data block writer,DBWn)的进程会做什么。数据库缓冲区缓存和DBWn将在后面详细讨论,但是我们先提前说两句,不过点到为止。

    数据库缓冲区缓存(database buffer cache)就是临时存储数据库块的地方。这是Oracle SGA中的一个结构。读取块时,会存储在这个缓存中,这样以后就不必再物理地重新读取它们。缓冲区缓存首先是一个性能调优设备,其目的只是让非常慢的物理 I/O过程看上去快一些。修改块(更新块上的一行)时,这些修改会在内存中完成,写至缓冲区缓存中的块。另外,会把重做这些修改所需的足够信息保存在重做 日志缓冲区(redo log buffer)中,这是另一个SGA数据结构。提交(COMMIT)修改时,会使这些修改成为永久的。Oracle并不是访问SGA中修改的所有块,并把 它们写到磁盘上。相反,它只是把重做日志缓冲区的内容写到在线重做日志中。只要修改的块还在缓冲区缓存中,而不在磁盘上,数据库失败时我们就会需要该在线 重做日志的内容。如果提交过后,突然掉电,数据库缓冲区缓存就会彻底清空。

    如果发生这种情况,则只有重做日志文件中有修改记录。重启数据库时,Oracle实际上会重放我们的事务,再用同样的方式修改块,并提交。所以,只要修改的块被缓存而未写入磁盘,就不能重用重做日志文件。

    在这里DBWn就能起作用了。这是Oracle的一个后台进程,负责在缓冲区缓存填满时请求空间,更重要的是,它会建立检查点。建立检查点就是把脏 块(已修改的块)从缓冲区缓存写至磁盘。Oracle会在后台为我们做这个工作。有很多情况都会导致建立检查点,最常见的事件就是重做日志切换。

    在填满日志文件1并切换到日志文件2时,Oracle就会启动一个检查点。此时,DBWn开始将日志文件组1所保护的所有脏块写至磁盘。在DBWn 把该日志文件保护的所有块刷新输出之前,Oracle不能重用这个日志文件。如果DBWn在完成其检查点之前就想使用日志文件,就会在数据库的ALERT 日志中得到以下消息:

    所以,出现这个消息时,数据库中的处理会挂起,因为DBWn正忙于完成它的检查点。此时,Oracle会尽可能地把所有处理能力都交给DBWn,希望它能更快地完成。

    如果数据库实例得到了妥善地调优,是不会看到这个消息的。如果你确实看到了这个消息,就应该知道肯定让最终用户陷入了不必要的等待,而这是可以避免 的。我们的目标是分配足够的在线重做日志文件(这是对DBA而言,对开发人员则不一定),这样就不会在检查点完成之前试图重用日志。如果经常看到这个消 息,这说明DBA未能为应用分配足够多的在线重做日志文件,或者要对DBWn进行调优才能更高效地工作。

    不同的应用会生成不同数量的重做日志。很自然地,决策支持系统(Decision Support System,DSS,仅查询)或数据仓库(DW)系统生成的在线重做日志总是比OLTP(事务处理)系统生成的在线重做日志少得多。如果一个系统在数据 库中对二进制大对象(Binary Large Object,BLOB)完成了大量图像处理,相对于简单的订单输入系统来说,则会生成更多的redo。有100位用户的订单输入系统与有1 000位用户的系统相比,生成的redo可能只是后者的十分之一。至于重做日志多大才合适,这没有“正确”的答案,不过你肯定希望重做日志足够大,能适应 你的工作负载。

    在设置在线重做日志的大小和数目时,还有一些问题需要考虑。其中很多问题都超出了这本书的范围,不过在此把它们都列出来,以便你有一个大致的认识:

    q 高峰负载(peak workload):你可能希望系统不必等待对未完成的消息建立检查点,不要在高峰处理期间遭遇瓶颈。你不能针对“平均”的小时吞吐量来确定重做日志的大 小,而要针对高峰处理来确定。如果每天生成24 GB的日志,但是其中10 GB的日志都是在9:00 am到11:00 am这一时段生成的,就要把重做日志的大小调整到足以放下那两小时高峰期间生成的日志。如果只是针对每小时1 GB来确定日志大小可能是不够的。

    q 大量用户修改相同的块:如果大量用户都要修改相同的块,你可能希望重做日志文件很大。因为每个人都在修改同样的块,最好尽可能多地更新之后才将其写出到磁盘。每个日志切换都会导致一个检查点,所以你可能不希望频繁地切换日志。不过,这样一来又会影响恢复时间。

    q 平均恢复时间:如果必须确保恢复尽可能快地完成,即便是大量用户要修改相同的块,也可能倾向于使用较小的重做日志文件。如果只是处理一两个小的重做日志文 件,而不是一个巨大的日志文件,则所需的恢复时间会比较短。由于重做日志文件小,往往会过多地建立检查点,时间长了,整个系统会越来越慢(本不该如此), 但是恢复所花的时间确实会更短。要减少恢复时间,除了使用小的重做日志文件外,还可以使用其他的数据库参数。

    3.7.2 归档重做日志

    Oracle数据库可以采用两种模式运行:ARCHIVELOG模式和NOARCHIVELOG模式。这两种模式的区别只有一点,即Oracle重 用重做日志文件时会发生什么情况。“会保留redo的一个副本吗?还是Oracle会将其重写,而永远失去原来的日志?”这是一个很重要的问题,下面就来 回答。除非你保留了这个文件,否则无法从备份将数据恢复到当前的时间点。

    假设你每周的星期六做一次备份。现在是星期五下午,已经生成了这一周的数百个重做日志,突然你的磁盘出问题了。如果没有以ARCHIVELOG模式运行,那么现在的选择只有:

    q 删除与失败磁盘相关的表空间。只要一个表空间有该磁盘上的文件,就要删除这个表空间(包括表空间的内容)。如果影响到SYSTEM表空间(Oracle的数据字典),就不能用这个办法。

    q 恢复上周六的数据,这一周的工作就白做了。

    不论是哪种选择都不太好。这两种做法都意味着你会丢失数据。不过另一方面,如果之前以ARCHIVELOG模式运行,那么只需再找一个磁盘就行了。 你要根据上周六的备份将受影响的文件恢复到这个磁盘上。最后,再对这些文件应用归档重做日志和(最终的)在线重做日志,实际上是以一种快进的方式重放整个 星期的事务。这样一来,什么也不会丢失。数据会恢复到发生失败的那个时间点。

    人们经常告诉我,他们的生产系统不需要ARCHIVELOG模式。在我的印象里,这样说的人没有一个说对的。我认为,如果系统不以 ARCHIVELOG模式运行,那它根本就不能算是生产系统。未以ARCHIVELOG模式运行的数据库总有一天会丢失数据。这是在所难免的;如果你的数 据库不以ARCHIVELOG模式运行,你肯定会丢失数据。

    “我们在使用RAID-5,所以可以得到完全的保护”,这是一种很常见的托辞。我曾见过,由于制造方面的错误,RAID中的所有磁盘都“冻结”了, 而且几乎是同时发生的。我也见过,有时硬件控制器会对数据文件带来破坏,所以他们只是在用RAID设备安全地保护已经被破坏的数据。另外,对于避免操作员 错误(这也是丢失数据的一个最常见的原因),RAID也无能为力。

    “在出现硬件或操作员错误之前,而且归档尚未受到影响,如果此时建立了备份,就能很好地恢复”。关键是,既然系统上的数据是有价值的,有什么理由不 采用ARCHIVELOG模式呢?性能不能作为理由;适当配置的归档只会增加极少的开销甚至根本不增加开销。由于这一点,再加上另外一条:如果一个系统会 “丢失数据”,那它再快也是没有用的,所以退一万步说,即使归档会增加100%的开销,我们也不得不做。如果可以把一个特性删除而没有任何重大损失,这个 特性就叫做开销(overhead);开销就像是蛋糕上的糖霜,可以不要而不会影响蛋糕的美味。但归档不同,利用归档可以保住你的数据,确保数据不会丢 失,这不是开销,而且正是DBA的主要任务!

    只有测试或开发系统才应当采用NOARCHIVELOG模式执行。不要受人蛊惑在非ARCHIVELOG模式下运行。你花了很长时间开发你的应用,肯定希望人们相信你。如果把他们的数据丢失了,也会让他们对你的系统失去信心。

    注意    有些情况下,大型的DW(数据仓库)以NOARCHIVELOG模式运行也是合适的,因为它可能适当地使用了READ ONLY(只读)表空间,而且会通过重新加载数据来完全重建受失败影响的所有READ WRITE(读写)表空间。





    二、重做日志组的补充

    Oracle使用多个重做日志组来管理重做日志,这些重做日志组循环使用;即日志组1,2,3,写满以后写2,然后写3,然后循环写1。

    每个日志组至少包含一个日志成员,保险起见,建议每个日志组包含两个以上成员,每个日志成员位于不同的磁盘上,写入日志时Oracle会将相同的内容同时写入同一个日志组的多个成员;
    日志文件与日志成员是一回事。

    (1)、ORACLE引入重做日志目的:记录数据的改变,提供数据库的恢复。

               1、日志文件需要分组,同一个重做日志组的每个成员所存的信息完全相同。

               2、每个组中的重做日志文件均被称为成员

               3、每组最好有2、3个成员,分别放置不同的物理磁盘,这样安全性较高。

               4、最少需要两个重做日志组


    (2)、重做日志的运行流程:

           重做日志按照有序循环的方式被使用,即当一组日志文件被填满后,循环覆盖下一组日志文件,不断循环。此时称为日志切换。检查点操作也在此时发生,检查点操作是用来实现同步的,它会写数据文件的头信息、控制文件。在归档模式下,当一组日志文件被填满后,ARCH(归档写进程)将这组复制到归档日志文件中。 (在ARCH正在写的重做日志文件LGWR是不可以写的)

              1、重做日志文件的定稿是依靠LGWR后台进程

              2、LGWR正在写的重做日志组称为:当前重做日志组。

              3、重做日志文件------联机日志文件;归档日志文件------脱机日志文件

    (3)、查询重做日志组:

              1、日志组:

           select group#, sequence#, members, bytes, status, archived from v$log;

           Status列中各值的意义:

             Current:当前组。

             Inactive:实例恢复已不需要这组日志了

             Activie:这组日志是活动的,但非当前组。例如正在归档。

             Unused:此组从未被写过。是日志刚被添加到DB中的状态。

                  Thread :线程(通过后台进程lgwr 启动),在单实例的环境下,thread# 永远是1

         Sequence :日志序列号。在日志切换时会递增。(在归档日志中会有该序列号)


                  FIRST_CHANGE# :在当前日志中记录的首个数据块的scn。(当事务完成的时候会在数据块上写入一个scn,代表数据块的变化)。


                  ARC:是否归档模式

         2、日志文件:

           Select * from v$logfile;

           Status列中各值的含义:

             空白:此文件正在使用。

              Stale:该文件内容是不完全的。当数据库怀疑日志文件没完成或者不正确时,日志文件为不新鲜状态,当该日志组变为active group 时,stale日志文件会变为valid状  态

                  Invalid:该文件不可以被访问。例如刚建立

                  Deleted:该文件已不再有用。

                  Valid  :有效状态

    (4)、创建与删除重做日志文件组:

            1、添加删除重做日志文件组:

            Alter database add logfile (‘d:**.log’ , ‘e:**.log’ ) size15m;

            (这样创建的2个重做日志文件都会是同一组)

              Alter database drop logfile group 4;

             删除指定组号的重做日志组(删除后实际文件并未删除,需手动删除)

             删除过程中出现的各种限制条件如下:

             current log group当前日志组不可删除,要删除当前日志组需要先对当前日志组进行切换,使用命令为alter system switch logfile;

             active log group活动的日志组不可删除

             no archived log group没有归档的日志组不可删除(前提是已运行在归档模式下)

         2、添加/删除重做日志文件:

              Alter database add logfile member‘d: ed004.log’ to group 1,‘d: ed005.log’ to group2;

              Alter database drop logfile member ‘d: ed004.log’;
              删除时遇到的限制条件:

             不能删除当前组的成员,如要删除则:强制性切换重做日志的命令:alter system switch logfile;

              active log group活动的日志成员不可删除

              no archived log group没有归档的日志成员不可删除(前提是已运行在归档模式下)

              at least one member per group当日志成员中只有一个成员

             特例:

              有的时候在删除重做日志文件redo log file时,会出现如下错误

              ERROR位于第1行:

              ORA-00362:要求输入成员以组成组4中的有效日志文件

              ORA-01517:日志成员: 'C:ORACLEORADATAGXCNCREDO041.LOG'

            (之 所以不能drop logfile member from group 2,是因为group 2的其他redo log file的状态不对。这种情况,应该作几次alter system switch logfile ,使group 2  

              其       他redo log file的状态变为 正常 就可以了。)

         3、查看日志生成量

                     通过联合查询视图 v$statname ,v$mystat可以查看日志生成量

          select a.name,b.value from v$statname a,v$mystat b  
          where b.statistic#=a.statistic# and a.name like '%redo size%';

  • 相关阅读:
    access生成sql脚本,通过VBA调用ADOX
    virtualbox 使用USB引导启动安装系统
    atom 调用g++编译cpp文件
    VPython 三维显示 —— hello word
    sql高级篇(一)
    sql基础篇
    struts2中的<s:select>默认选项
    关于SVN更新注意
    mysql中的substr()函数
    mysql中exists的用法介绍
  • 原文地址:https://www.cnblogs.com/zmlctt/p/3696676.html
Copyright © 2011-2022 走看看