Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2322701
  • 博文数量: 310
  • 博客积分: 6853
  • 博客等级: 准将
  • 技术积分: 2833
  • 用 户 组: 普通用户
  • 注册时间: 2005-08-04 16:41
文章分类

全部博文(310)

文章存档

2013年(17)

2012年(42)

2011年(76)

2010年(71)

2009年(99)

2007年(2)

2006年(1)

2005年(2)

分类: Oracle

2009-11-19 11:00:04

重做日志文件(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 日志文件组


图3-

从一个日志文件组切换到另一个日志文件组的动作称为日志切换(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(读写)表空间。

阅读(5818) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~