分类: Oracle
2011-06-22 10:32:04
《涂抹Oracle——三思笔记之一步一步学Oracle》作为一本创作之初就定位于技术应用的实践参考书,虽然前前后后串联了Oracle数据库中十余 个常用特性或工具,但在章节的设计上完全遵循这一理念。第16章讲述体系结构之数据库结构。本节说的是联机重做日志文件(Online Redolog Files)。
16.1.4 日志文件(Redolog Files)
在Oracle数据库环境下流传着这样一句话:要想知道数据库曾经都做过什么,问问重做日志文件就知道!人们是这样说,重做日志文件也是这样做的。 重做日志文件为什么能做到这一点,又是如何数十年如一日,始终保持重做日志组成员先进性的呢?这一切,要从重做日志文件的名字说起……
重做有一个好听的英文名字叫Redo,特指一项操作。在Oracle数据库中,执行数据修改操作后,并不是马上写入数据文件,而是首先生成重做信 息,并写入SGA中的一块叫LOG_BUFFER(关于这部分内容将在介绍实例的体系结构时详细阐述)的固定区域,LOG_BUFFER的空间并不是无限 大,事实上它非常小,一般设置在3~5MB左右。LOG_BUFFER有一定的触发条件,当满足触发条件后,会有相应进程将LOG_BUFFER中的内容 写入一个特定类型的文件,就是传说中的联机重做日志文件。
16.1.4.1 联机重做日志文件(Online Redolog Files)
在Oracle数据库环境中,如果开展"评选劳动模范"之类的活动,联机重做日志绝对是当之无愧的劳模代表(没有之一)。在某些比较极端的环境,甚 至自联机重做日志文件降临到Oracle数据库环境的那刻起,它就要从早忙到晚,从这头忙到那一头,再从那头忙回到这一头,艰苦朴素、吃苦耐劳,时刻履行 着作为一名重做日志组成员的光荣使命,数十年如一日,毫无怨言并且无条件地服从组织安排,全心全意完成组织交待的各项任务,忠实做好各项操作的记录工作。 这一切,都是每一名重做日志组成员的真实写照。
一个好汉三个帮,重做日志文件也有多个帮手,每个数据库至少要有两个重做日志文件组(一般应该为3~5组)。
联机重做日志文件是循环使用,如图16-1所示,创建了3个重做日志文件组,Oracle以循环方式使用这些重做日志文件组。如当前在写LOG日志 组1,那么LOG日志组1即为CURRENT状态,当该重做日志文件组中的日志文件被写满数据后,后台进程LGWR就开始写下一个,即LOG日志组2(此 时LOG日志组1状态被切换为ACTIVE状态,LOG日志组2的状态则变为CURRENT)。以此类推,当所有的日志文件都被写满后,后台进程LGWR 再次重新写入LOG日志组1……
因为联机重做日志文件非常重要,Oracle建议每组联机重做日志文件至少要有一份冗余。Oracle管这种方式叫复合 (Multiplexed),即为每个重做日志文件保持多份镜像,这样一旦因为磁盘损坏,或误操作导致丢失了某个重做日志文件,只要该组至少还有一个重做 日志文件状态正常,就能够保证数据不会丢失。
1.管理联机重做日志
创建联机重做日志文件时都是以组为单位,也就是说,想为数据库添加一个联机重做日志文件,就必须先为数据库创建一个联机重做日志文件组(如果使用DBCA建库,默认会创建三个联机重做日志文件组)。创建联机重做日志文件组的语法如图16-2所示。
在创建重做日志文件组时,可以为联机重做日志文件指定复合,并设置联机重做日志文件的大小,例如:
- JSSBOOK> ALTER DATABASE ADD LOGFILE GROUP 4
- 2 ('f:\oracle\oradata\jssbook\redod01.log',
- 3 'f:\oracle\oradata\jssbook\redod02.log') size 50m;
- Database altered.
删除连接联机重做日志文件组的语法就更简单了,例如,删除刚创建的GROUP 4:
- JSSBOOK> ALTER DATABASE DROP LOGFILE GROUP 4;
- Database altered.
注 意
使用ALTER DATABASE DROP LOGFILE命令删除联机重做日志文件组时,不能删除当前系统正在使用(CURRENT)或活动(ACTIVE)状态的联机重做日志文件组(一般来说, 刚刚创建的联机重做日志文件组的状态应该为UNUSED,表示还从未被写入过数据)。另外,ALTER DATABASE DROP LOGFILE命令只删除该联机重做日志文件组在数据字典中的定义,不会级联删除操作系统中对应的物理文件,如果需要删除对应的物理文件,DBA必须手动 通过操作系统命令进行删除。
你也可以为当前的联机重做日志组添加联机重做日志文件,语法如图16-3所示。
例如,为第3组联机重做日志添加日志文件:
- JSSBOOK> ALTER DATABASE ADD LOGFILE MEMBER 'f:\oracle
- \oradata\jssbook\redoa02.log' TO GROUP 1;
- Database altered.
注 意
添加联机重做日志文件不能指定大小,因为每个联机重做日志文件组中的文件都是相互冗余,因此文件大小必须一致。实际上在Oracle数据库中,每一 个联机重做日志文件组都可以拥有不同于其他联机重做日志文件组的大小,不过Oracle建议数据库中每组联机重做日志文件都拥有相同的大小。
删除联机重做日志文件组中的某个日志文件也很简单,如删除GROUP1中刚刚添加的日志文件,执行命令如下:
- JSSBOOK> ALTER DATABASE DROP LOGFILE MEMBER '
- f:\oracle\oradata\jssbook\redoa02.log';
- Database altered.
注 意
删除联机重做日志文件组成员前,必须确保删除后该联机重做日志文件组中至少还拥有一个组员,不然删除操作可能会触发ORA-00361错误。
2.查看联机重做日志
有两个视图可以用来查询当前系统中的联机重做日志文件的相关信息,其中用V$LOG视图查询当前的联机重做日志文件组信息,例如:
- JSSBOOK> SELECT * FROM V$LOG;
- GROUP# THREAD#SEQUENCE# BYTES MEMBERS ARCSTATUS FIRST_CHANGE#FIRST_TIM
- ---------------------------------------------- ---------------------
- 1 1 13 524288002YESINACTIVE 865158536029-JUN-09
- 2 1 14 52428800 1NO CURRENT 865162651401-JUL-09
- 3 1 12 524288001YESINACTIVE 8651585358 29-JUN-09
注意该视图中的STATUS列,表示对应的联机重做日志文件组状态,可能有下列几个值:
UNUSED:表示该联机重做日志文件组对应的文件还从未被写入过数据,通常刚刚创建的联机重做日志文件组会显示成这一状态。
CURRENT:当前Oracle数据库正在使用的联机重做日志文件组。
ACTIVE:如果处于这一状态,表示虽然当前并未使用,不过该文件中内容尚未归档,或者文件中的数据没有全部写入数据文件,一旦需要实例恢复,必须借助该文件中保存的内容。
CLEARING:表示该组重做日志文件正被重建(重建后该状态会变成UNUSED)。
CLEARING_CURRENT:表示该组重做日志重建时出现错误。
INACTIVE:表示对应的联机重做日志文件中的内容已被妥善处理,该组联机重做日志当前处于空闲状态。
V$LOGFILE则可以查询当前的联机重做日志文件明细,例如:
- JSSBOOK> SELECT * FROM V$LOGFILE;
- GROUP#STATUS TYPE MEMBER
- IS_
- ------------------------ -----------------------------------------------------
- 1 ONLINE F:\ORACLE\ORADATA\JSSBOOK\REDO01.LOG
- NO
- 2 ONLINE F:\ORACLE\ORADATA\JSSBOOK\REDO02.LOG
- NO
- 3 ONLINE F:\ORACLE\ORADATA\JSSBOOK\REDO03.LOG
- NO
- 1INVALID ONLINE F:\ORACLE\ORADATA\JSSBOOK\REDOA02.LOG
- NO
该视图中GROUP#列关联V$LOG.GROUP#,而MEMBER列则显示日志文件存储的实际路径。另一个需要注意的是TYPE列,该列只有两 个值:STANDBY表示该日志文件为Standby数据库专用,即Standby Redologs,ONLINE则表示该日志文件为普通联机重做日志文件。
3.设置联机重做日志文件大小
很多朋友可能会有疑问,究竟为联机重做日志文件分配多大的空间合适呢?这确实是一个很值得讨论的话题,不过这一问题并没有准确或者说固定的答案,每 个Oracle数据库设置的值可能都不相同。如果愿意深入研究的话,那么我认为在创建联机重做日志文件时,至少有下面几个因素需要考虑到:
数据修改频繁度。联机重做日志文件不能设置得太小。如数据修改比较频繁,"可能"会产生大量的重做信息(并不是所有操作都会产生重做日志,后面将会 专门谈到这一点,因此这里用可能两个字),这样重做日志文件就必然会被频繁地读写,一组写满了换另一组,另一组也写满再接着切换下一组。
如果数据的修改量非常大,而联机重做日志文件又设置得较小,那么从数据库状态来看,就会表现成日志文件在频繁地执行切换操作,不过,一旦日志文件切 换时发现下一组重做日志文件尚未完成写入,那么数据库就不得不停顿,等待该组重做日志文件完成归档或数据写入,此时Oracle实例将不得不暂时停止,相 当于进入了假死状态,直到出现可用的重做日志文件组为止。因此如果数据库的修改比较频繁,那么联机重做日志文件就不能设置得太小。
平均恢复时间。联机重做日志文件不能设置得太大。数据在被修改时并非直接写入数据文件,而是写入重做日志文件,当触发检查点(CKPT)操作时会从 重做日志中读取已提交的数据并写入数据文件,而触发重做日志文件中数据写向数据文件的条件之一,就是日志文件切换。在没有其他条件触发检查点的情况下,只 有等重做日志文件切换时,才会将修改的数据真正保存到数据文件中。如果联机重做日志文件设置得较大,那么这一过程也会被相应延长,在一般情况下当然无所 谓,不过如果考虑到万一遇到数据库崩溃,需要进行实例恢复的话,Oracle在执行实例恢复时也必须花费相应长的时间来处理这个巨大的日志文件(实际上没 有这么糟糕,自8i后Oracle引入了增量检查点的特性,数据也是在持续不断地写入数据文件的)。因此考虑到Oracle实例快速从崩溃中恢复的因素, 重做日志文件不宜设置过大。
高峰时的负载。每一个数据库系统都会根据具体应用的业务,而表现出不同的负载状态,某些系统可能早晨8:00~10:00点最为繁忙,有些系统则是 凌晨1:00~3:00点比较繁忙,其他时段则相对比较空闲;不管是什么类型的数据库系统,在设置联机重做日志文件大小时,都应该以最繁忙时段时产生的重 做日志量为准。如某个数据库系统每天产生50GB的日志,但是其中40GB是在13:00~15:00之间产生,那么在设置重做日志文件大小时,就应该调 整到足够放得下这期间生成的日志的大小,而不能按照平均每小时2GB左右的日志来确定。按照一般Oracle数据库系统以10~15分钟左右的时间切换一 次的频率(建议频率,并非必选频率),此处可以设置单个重做日志文件为3GB左右大小。
4.重做日志的生成
并不是所有的操作都会被记录重做日志。在执行某些操作时,DBA可能会希望尽可能少的记录重做日志,以加快执行速度,如执行某些DDL语句时附加 NOLOGGING子句或执行DML时指定HINT APPEND的方式操作数据,这种操作方式不会产生重做记录(或者是只生成了极少一部分),另外像SQL*Loader这类的工具采用直接路径方式时由于 跳过了SQL引擎,也不会生成重做记录。
不过如果你想,可以让所有操作均记录重做日志,Oracle数据库有一个Force Logging的属性,一旦将数据库改为Force Logging,则Nologging和Append Hint方式自动失效(甚至连SQLLDR命令的直接路径导入也会自动转换为常规路径),在这种方式下可以确保数据库中所做的操作均会记录重做信息。
查询当前数据库是否启用了Force Logging,可以查询V$DATABASE视图的Force_Logging列,例如:
- JSSBOOK> SELECT FORCE_LOGGING FROM V$DATABASE;
- FOR
- ---
- NO
在默认情况下数据库处于Noforce Logging状态,要将数据库置于Force Logging模式,执行下列语句即可:
- JSSBOOK> ALTER DATABASE FORCE LOGGING;
- Database altered.
该设置即时修改即时生效。不过需要注意的是,如果执行该操作时,数据库正在执行一些类似Nologging的操作,那么Force Logging必须等待这些操作完成后,才能对数据库属性进行修改。
取消Force Logging模式也很简单,执行下列语句即可:
- JSSBOOK> ALTER DATABASE NO FORCE LOGGING;
- Database altered.
该设置同样是修改后即时生效的。