重做日志文件(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(读写)表空间。
—
重做日志文件是Oracle数据库中一种非常重要的日志文件,也是其一个很有特色的功能。重做日志文件会纪录对于数据库的任何操作,如利用DML语句或者DDL语句对数据进行更改,或者数据库管理员对数据库结构进行更改,都会在重做日志中进行记录。
可见,当数据被意外的删除或者修改,我们可以利用重新日志文件进行恢复; 当出现例程失败或者介质失败的情况下,也可以利用日志文件实现例程恢复或者介质恢复。所以说,我们若能够管理好重做日志文件的话,对于保障数据库数据的安全是非常重要的。
下面笔者谈谈管理好Oracle 数据库日志文件的几点经验技巧,或许,能够给大家在重做日志文件的管理中带来一些启示。
一、 合理确定重做日志文件的存放位置。
我们知道,当数据库内部数据丢失或者被意外更改的情况下,数据库管理员可以利用重做日志文件实现数据库数据的恢复工作。当数据库出现意外事故,如硬盘物理损坏、数据丢失时怎么办?
我们第一个就会想到利用数据库重做日志对数据进行恢复。可是当数据库重做日志跟数据库数据文件放在同一个硬盘的话,很明显,当硬盘损坏的时候,数据文件将跟日志文件共赴黄泉。此时,连天皇老子都救不了我们。
所以,此时,我们就有必要把重做日志文件跟数据库数据文件放在两个不同的硬盘上面。此时,任何一个硬盘若发生损坏,我们都可以凭借另外一块硬盘的数据,来挽回损失。如存放数据文件的硬盘损坏时,我们就可以利用存放在另外一块硬盘上的数据重做日志文件进行修复,挽回损失。
鸡蛋不能放在同一个篮子里,故重做日志文件与数据文件也不要放在同一块硬盘上。那时非常危险一个动作。
其实,这个重做日志文件就跟数据库的备份文件类似。我们在对数据库进行备份的时候,都知道需要进行异地备份。可惜的是,很多数据库管理员,在进行 Oracle 数据库管理的时候,没有注意到这一点,结果当出现问题的时候,就来不及了。故,对于数据重做日志文件,保存时,要跟数据库备份文件一样,进行异地保存。
二、 合理设置数据库的归档模式。
因为数据重做日志会纪录数据库所有的修改动作,所以,当数据库频繁修改时,如那些ERP系统需要频繁对数据库进行修改操作,此时,数据库的重做日志文件就会很庞大。为了便于日志文件的管理,Oracle 数据库默认情况下,在
安装
的时候,会有三个重做日志文件。当第一个重做日志文件达到一定容量时,就会停止写入,而会转向第二个日志文件; 第二个也满时,就会转向第三个。当第三个满时,就会往第一个日志文件中写入。在往这原来的纪录中写入重做日志文件的时候,是否需要对原有的纪录进行备份呢?根据用户需求的不同,就存在这两种处理模式。一种是不需要数据库进行自动备份,这种模式就叫做非归档模式; 而当重做日志改写原有的重做日志文件以前,数据库会自动对原有的日志文件进行备份的话,这种操作模式就叫做归档模式。
现在摆在数据库管理员面前有两个选择。选择归档模式或者非归档模式呢?
这要根据
企业
对于数据完整性的要求不同而采取不同的操作模式。笔者的建议是,采用归档模式。因为现在硬盘非常的便宜,故我们可以花比较少的代价,换取比较齐全的数据库重做日志文件,个人认为这对于企业来说,是很值得的。、
笔者现在的做法是,重做日志文件至少保存一年。也就是说,当一年过后,就可以重写原来的日志文件。这主要是跟企业所处的行业以及对于数据的
安全性
程度不同而有所区别。如银行就不同,他们可能要求重新日志保留十年甚至更长的时间。要知道,对于他们来说,任何一条记录可能都涉及到很大的资金。
三、 合理选择日志切换的方法。
日志切换是指停止向某个重做日志文件组写入而向另一个联机的重做日志文件组写入的那一刹那,我们称为日志切换。一般来说,这个日志切换主要有三种处理方式。通常情况下,使到重做日志文件组容量满的时候,会发生日志切换动作。另外,我们还可以以时间的方式指定日志切换的方式,如我们可以以一个星期或者一个月作为切换的单位。第三,有时候我们可能出于数据库维护的需要,如当发现存放数据重做日志的硬盘容量快用光时,我们需要换一块硬盘,此时,就需要在当前时刻,进行日志的切换动作,这我们一般称之为强行日志切换。
归档就是在重做日志文件被覆盖时,将重做日志文件通过复制操作系统文件的方式,保存到其他指定的位置。一般情况下,只有在处于归档日志模式下的数据库中,才会对重做日志文件进行归档动作。
日志切换的模式选择,一般对于数据的安全性没有很大关系,但是,对于我们进行数据重做日志的管理,却会产生很大影响。合理部署重做日志文件的切换方法,对于我们数据库管理员来说,具有非常的现实意义。我们设置的好,可以大大节省我们数据库的管理工作,提高数据库的自动化管理效率。
如笔者现在对于数据重做日志是如此管理的。
根据笔者对于数据库变动的观察,笔者在新建立数据库的时候,设置了六个数据库重做日志文件。然后笔者采用基于时间的方是进行数据日志的切换动作。每两个月进行切换一次。为什么要选择这个时间呢?一方面是出于这个重做日志文件大小的考虑,另一方面,也是出于日后查询与管理的需要。如此的话,一年六个数据重做日志文件,就非常的清楚。
但是,基于时间的策略来对重做日志文件进行切换的话,有一个不好的地方,就是对于重做日志文件的大小很难控制。如可能在应用系统前期部署阶段,如ERP系统前期数据倒入阶段,因为涉及到很多的数据更改动作,所以,这个数据重做日志文件就会非常的大。而到后来项目上线,业务趋于正常的时候,数据重做日志文件大小又会迅速的回落。这就会导致数据重做日志文件大小差异太大,而数据重做日志的多路复用或者归档带来一定的麻烦。笔者的做法是,当ERP系统前期数据更新完毕,项目上线时,先对数据库进行强制数据重做日志切换。对于这个重做日志进行独立的管理。如此的话,后续的重做日志容量大小就会差不多,易于我们管理。