当前位置:文档之家› Oracle日志(redo)机制探讨

Oracle日志(redo)机制探讨

Oracle日志(redo)机制探讨
【摘要】oracle数据库的redo机制是保障数据安全和故障恢复的至关重要的手段,也是对数据库性能影响非常巨大的关键因素。

通过对oracle日志机制的探讨可以帮助数据库管理员更好的理解、维护oracle数据库。

【关键词】redo checkpoint 事务恢复
一、redo原理
计算机系统中最容易出现瓶颈的就是磁盘的I/O操作。

Oracle通过批量方式将buffer cache(数据缓冲区)中发生变更的“脏”数据块写入数据文件。

这样减少了低效率的离散写磁盘操作,大大减轻了磁盘I/O的压力。

通过将buffer cache中的变更后的数据延迟写入数据文件,提升了数据库的性能,但也带来了数据丢失的风险。

为了保证buffer cache中的“脏”数据块在系统发生故障时不丢失,oracle要将这些数据块的变更记录下来,并及时写入日志。

即使系统发生故障,oracle通过日志中记录的redo信息可以将数据块发生的变化过程重演,这样就可以将数据库恢复到故障前的最后时刻。

二、日志文件
为了保证redo信息及时写入日志文件,oracle的lgwr(写
日志进程)非常活跃。

为了避免磁盘缓冲带来的滞后风险Lgwr采用了直接写磁盘(direct IO)的方式将redo信息直接写入文件。

触发lgwr的条件很多:每3秒钟;事务提交(commit);redo log buffer(日志缓存区)1/3满或有1MB 数据;dbwr(写数据文件进程)启动时发现“脏”数据库对应的redo信息未写入日志。

Oracle的日志文件是循环使用的,所以至少要两个日志组。

为保障日志文件安全,每组日志可以有多个镜像(多镜像会增加lgwr的负担)。

当一个日志文件写满后,会切换到另一个日志文件(log switch)。

切换日志会触发检查点(checkpoint)事件,通知dbwr进程将写满的日志文件中保护的数据块写入数据文件。

在checkpoint完成之前,该日志文件是不能被覆盖重用的。

因此,日志文件通常会有current (当前)、active(checkpoint未完成)、inactive(checkpoint 已完成)三种状态。

如果是新添加的日志文件或者数据库resetlogs(重置),日志文件的状态为unused(未使用)。

当日志文件切换频繁时,就会发生因日志文件处于active状态而无法切换的问题,此时数据库处于“挂起”状态,等待checkpoint完成,Alert文件中会记录:checkpoint not complete。

发生这种问题对系统性能影响非常大,严重的甚至会导致业务中断。

通常数据库管理员会采取增加日志文件大小、增加日志组数这两种方法来应对。

日志文件对数据库的影响是非常巨大的,尤其是current 日志文件如果发生损坏,丢失数据就无法避免。

日志文件越大,就意味着越多的数据有丢失的风险。

因此,从保障数据安全、减少发生故障时的数据损失的角度来看,只要不发生checkpoint not complete,日志文件应越小越好。

所以,采用小日志文件、多日志组的方式可以较好的解决数据库系统的安全和性能的冲突。

但是日志文件的切换、归档也会消耗系统资源,小日志文件在业务高峰期会发生频繁切换,对系统性能的影响不可小觑。

因此,很多情况下数据库管理员会依据业务高峰时段的日志产生量来决定日志文件的大小。

但业务高峰期和空闲期的数据变更量差别非常大,满足业务高峰期的日志文件大小对业务空闲时段来说就显得太大了,会出现日志文件很长时间都不切换的现象。

而不切换、归档的日志就存在着损坏的风险,时间越长风险就越大。

针对此问题,笔者采用了通过设置archive_lag_target参数的手段来强制数据库进行日志切换。

archive_lag_target参数设定的是日志切换时间(单位为秒),默认值为0(不启用)。

启用该参数后,即使日志文件未写满,只要达到时间限制就强制切换日志。

通常建议archive_lag_target参数设定不小于20分钟,但过长也失去了保护数据的意义(笔者建议不超过90分钟)。

三、减少redo
Redo机制保障了oracle数据库的故障恢复能力,提高了
系统的稳定性。

所以,在正常情况下数据库发生变更都会产生redo。

但在某些特殊情况下,减少redo的产生可以极大的提高数据库的性能,对提升应用系统的工作效率具有重要意义。

笔者在这里对一些常用的减少redo产生的操作方式给予简单介绍。

(一)直接路径(direct path)批量insert数据
在SQL语句中增加/*+append*/提示,在非归档模式下运行的oracle数据库会不产生数据块变更的redo。

注意:这种方式对在归档模式下运行的数据库需要将插入数据的表的
模式改为nologging才有效。

举例insert /*+append*/ into test select * from t1
直接路径批量插入数据只是不产生insert的redo,但如果表上加有索引,insert数据的过程中系统会及时更新索引,这个操作会产生redo。

对此可以先将索引删除(drop),insert 数据完成后再创建索引。

如果采用nologging方式创建索引,则可以将创建索引的redo减少。

(二)nologging创建表和索引
创建表的同时采用直接路径append数据。

例如create table test nologging as select * from t1
创建索引的语句后面加上nologging即可。

(三)补充
不产生redo的操作方式如果对数据字典发生了修改仍
然会产生日志,这是Oracle为了保障数据库的安全和一致性采取的必要手段。

这也是在采用上述方式操作后,oracle有时仍然会产生少量日志的原因。

为保障数据安全,建议对nologging操作之后立即对数据库进行数据备份(不是日志备份)。

四、结束语
Oracle数据库的redo机制是一个非常有特色的技术亮点,对数据库的性能也影响非常大。

掌握这个机制并根据系统的实际情况加以利用对数据库管理员来说非常具有实用价值。

相关主题