oracle学习篇:重做(Redo)
Posted myheart-new
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了oracle学习篇:重做(Redo)相关的知识,希望对你有一定的参考价值。
重做(Redo)和撤销(Undo)是oracle的重要特性,用以保证事务的可恢复性和可撤销性。
6.1 Redo的作用
在数据库中,Redo的功能主要通过3个组件来实现:Redo Log Buffer、LGWR后台进程和Redo Log File(在归档模式下,Redo Log File最终会写出为归档日志文件)。
6.2 Redo的内容
改变向量:表示对数据库内某一个数据块所做的一次变更。
重做记录:通常由一组改变向量组成,是一个改变向量的集合,代表一个数据库的变更,构成数据库变更的最小恢复单位。
假定发出一个update语句:update emp set sal-4000 where empno=7788;
(1)检查empno=7788记录在buffer cache中是否存在,如果不存在则读取到buffer cache中;
(2)在回滚段空间的相应回滚段事务表上分配事务槽,这个操作需要记录redo信息;
(3)从回滚段读入或者在buffer cache中创建sal=3000的前镜像,这需要产生redo信息并记入redo log buffer;
(4)修改sal=4000,这是update的数据更新,需要记入redo log buffer;
(5)当用户提交时,会在redo log buffer 记录提交信息,并在回滚段标记该事务为非激活(inactive)。
6.3 产生多少redo
(1)在sql*plus中使用autotrace功能时
776 redo size
(2)通过v$mystat查询
记录当前session的统计信息
col name for a30
select a.name,ab.value from v$statname a,v$mystat b where a.statistic#=b.statistic# and a.name=‘redo size‘;
(3)通过v$sysstat查询
对于数据库全局redo的生成量,可以通过v$sysstat视图查询
col value for 9999999
select name,value from v$sysstat where name =‘redo size‘;
从该视图中得到的是自数据库实例启动以来的累计日志生成量,可以根据实例启动时间估算每天日志生成量。
select startup_time form v$instance;
归档日志数据量,v$archived_log,也可以反过来估计每日的数据库活动性及周期性,并决定空间分配等问题。
6.4 Redo写的触发条件
6.4.1 每3秒钟超时(Timeout)
LGWR执行写出操作,log file parallel write等待事件将会出现。
启用10046事件,从LGWR跟踪日志中可以清楚地观察到这些事件。
6.4.2 阈值达到
redo log buffer1/3 满
redo log buffer具有1MB脏数据
也就是LGWR将在min(1M,1/3 log buffer size)时触发,此时的log buffer size是以log block来衡量的。
log buffer设置为3MB?
6.4.3 用户提交
在事务返回成功标志前,必须等待LGWR写完成,进程通知LGWR写,并且以log file sync事件开始休眠,超时时间为1秒。
注意:在递归调用(recursive call)中的提交不需要同步redo知道需要返回相应给用户,因此递归调用仅需要同步返回给用户调用之前的最后一次commit操作的RBA。
存在一个SGA变量用以记录redo线程需要同步的log block number。如果多个提交在唤醒LGWR之前发生,此变量记录最高的log block number,在此之前的所有redo 都将被写入磁盘。这有时候被称为组提交(Group Commit)。
6.4.4 在DBWn写之前
6.5 Redo Log Buffer的大小设置
一般来说3MB是一个较为合理的调整开端,当log buffer space等待时间出现并且较为显著时,可以考虑增大log buffer以缩减竞争。
6.6 Commit做了什么
提交完成,意味着oracle已经将此时间点之前的redo写入了重做日志文件中。
6.7 日志的状态
select * from v$log;
最常见的状态有:current,active,inactive,unused
(1)current
当前、活动、正在被使用,是崩溃恢复必须的
(2)active
非当前、可能完成归档也可能没完成归档,在crash恢复时会被用到。
active状态意味着,检查点尚未完成,如果日志文件循环使用再次到达该文件,数据库将处于等待的停顿状态,此时在alert文件中,可以看到如下记录:
Thread 1 cannot allocate new log,sequence 7239
Checkpoint not complete
Current log# 5 seq# 7238 mem#0:/opt/oracle/oradata/hsmk/redo05.log
当这种问题出现时,可以从数据库内部通过v$session_wait来观察,该视图会显示数据库当前哪些session正处于这种等待。
Checkpoint not complete在数据库中体现为等待时间log file switch (checkpoint incomplete);
引起checkpoint imcomplete可能有以下多种原因:
①日志文件过小,切换过于频繁;
②日志组太少,不能满足正常事务量的需要;
③日志文件所在磁盘I/O存在瓶颈,导致写出缓慢;
④由于数据文件磁盘I/O瓶颈,DBWR写出过于缓慢;
⑤由于事务量巨大,DBWR负荷过高,不堪重负。
针对不同的原因,可以从不同角度着手解决问题:
①适当增加日志文件大小;
②适当增加日志组数;
③使用更快速磁盘存储日志文件(如采用更高转速磁盘:使用RAID10而不是RAID5等方式);
④改善磁盘I/O性能;
⑤使用多个DBWR进程或使用异步I/O等。
这是一类严重的等待,它意味着数据库不能再产生日志,所有数据库修改操作将全部挂起。
(3)inactive
inactive的日志是非活动日志,该日志在实例恢复时不再需要,但是在介质恢复时可能会用到。inactive状态的日志也可能没有归档。如果数据库启动在归档模式,在未完成归档之前,日志文件也不允许被覆盖,这时候活动进程会处于log file switch(archived needed)等待之中。
日志是否完成归档,可以根据v$log的archived字段进行判断。
这种情况通常是由数据库异常引起的,可能是因为I/O缓慢,也可能是因为事务量过大,在特殊情况下,有可能是因为日志损坏。可以通过检查警报日志文件发现问题所在。
(4)unused
unused是指该日志从未被写入,这类日志可能是刚被添加到数据库或者在resetlogs之后被重置。被使用后,该状态会被修改。
6.8 日志的块大小
512bytes
6.9 日志文件大小
一般来说,在实际生成环境中,把log switch的时间控制在半小时左右即可;
对于通常的操作系统来说,日志文件的最大大小为2GB,在非常繁忙的业务系统中,由于受限于日志大小,能将日志控制在10分钟左右就已经算不错了。
6.10 为什么热备期间产生的redo要比正常的多
这是因为在热备份期间,oracle为了解决split block的问题,需要在日志文件中记录修改的行所在的数据块的前镜像,而不仅仅是修改信息。
在热备状态下,对于变更的数据,oracle需要在日志中记录整个变化的数据块的前镜像。
select * from redo_size;
6.11 能否不生成redo
6.11.1 nologging对数据库的影响
nologging可以使得日志生成大幅降低,但是必要日志(比如对字典表的修改)仍会被记录。
可以使用nologging的环境非常有限,在一些操作中,可以增加nologging字句:
①创建索引或重建索引时;
②通过/*+append*/提示,使用直接路径批量insert操作或sql*loader直接路径加载数据;
③CTAS方式创建数据表时;
④大对象LOB的操作;
⑤一些alter table操作,如move、split等
创建视图便于查询redo日志
create or replace view redo_size
as
select value from v$mystat,v$statname where v$mystat.statistic#=v$statname.statistic# and v$statname.name=‘redo size‘;
6.11.2 disable_logging对于数据库的影响
除了以上常规操作之外,oracle还存在一个内部参数,可以使数据库关闭日志记录,从而实现某些特殊需要或测试目的,这个参数可以动态设置alter system set "_disable_logging"=true;
6.11.3 force logging模式
当使用dataguard作为数据库的备份或容灾高可用性手段时,通常日志就变得不可缺少,可以将数据库至于强制日志模式。在该模式下,所有操作都将记录日志。
6.12 redo故障的恢复
6.12.1 丢失非活动日志组的故障恢复
通过clear重建该日志组即可恢复
! rm /op/oracle/oradata/redo02.log
alter system switch logfile;
startup
atartup mount;
select * from v$log;
select * from v$logfile;
注意到,由于日志组2已经损失,在日志切换过程中,数据库crash,所以日志组3的状态变为invalidated,日志文件redo03.log的状态变为stale(stale通常出现在上一次操作失败后,在下一次成功操作后状态会恢复正常)
清除该日志组后即可启动数据库:
alter database clear logfile group 2;
如果数据库处于归档模式,并且该日志组未完成归档则需要强制清除:
alter database clear unarchived logfile group 2;
6.12.2 丢失活动或当前日志文件的恢复
oracle通过日志文件保证提交成功的数据不丢失,可是在故障中,用户可能损失了当前的日志文件。这又分为两种情况,数据库正常关闭还是异常关闭。
(1)在损失当前日志时,数据库正常关闭
在关闭数据库前,oracle会执行全面检查点,当前日志在实例恢复中可以不再需要。
(2)在损失当前日志时,数据库异常关闭
对于这种情况,通常需要从备份中恢复数据文件,通过应用归档日志文件向前推演,直到最后一个完好的日志文件,然后可以通过resetlogs启动数据库完成恢复,丢失的数据就是损坏的日志文件中的数据。
当数据库没有备份时,oracle提供了一种内部手段用于强制性数据库打开,忽略一致性等问题。在打开数据库之后,oralce建议导出exp数据, 然后重新建库,再导入imp数据,完成灾难恢复。
使用隐含参数强制启动数据库:
alter system set "_allow_resetlogs_corruption"= true spfile;
shutdown immediate;
startup mount;
recover database using backup controlfile until cancel;
alter database open resetlogs;
shutdown immediate;
startup
6.13 诊断案例一:通过clear日志恢复数据库
从日志看,数据库不能归档,归档路径错误
select * from v$archive_dest;
show parameter log_archive_dest;
由于多次归档不成功,导致数据库将归档日志标记未error,使得后续正常的日志同样无法归档。
select * from v$log;
可以看到在其他人进行的多次重启切换过程中,日志组2和日志组3的sequence#都已经增进,只有日志组1的sequence#仍然是202,由于日志组1并非current日志组,所以可以通过clear方式消除该日志内容,从而使该日志恢复正常状态。
alter database clear unarchived logfile group 1;
注意,由于该日志未归档,所以之前的热备份用于恢复时将不能跨越这个缺口,oracle建议重新全库备份,从警告日志中也可以看到提示。
后续工作是需要对数据库进行备份。
6.14 诊断案例二:日志组过度激活的诊断
问题描述:相应缓慢,应用请求已经无法返回
这时登陆数据库检查,发现redo日志组除current外都处于active状态
如果日志都处于active状态,那么显然dbwr的写已经无法跟上log switch触发的检查点。接下来检查以西dbwr的繁忙程度。
ps -ef|grep ora_
dbwr的进程号是2266,使用top命令观察一下:
top
可以看到2266号进程消耗的cpu不多,显然并不繁忙,那么瓶颈就很可能在IO上,使用iostat‘工具加检查io状况。”
iostat -xn 3
可以看到写速度(kw/s)只有500KB左右,而该磁盘通常写速度为为10MB/s,推测为磁盘发生了损坏。更换磁盘后,系统逐渐恢复正常。
第六章完
以上是关于oracle学习篇:重做(Redo)的主要内容,如果未能解决你的问题,请参考以下文章
oracle联机重做日志文件(online redo log file)
Oracle重做日志管理与深入解析_超越OCP精通Oracle视频课程培训14