原文地址: http://blog.csdn.net/lsz_qh/article/details/7297741 写得非常不错!
主要介绍DBWN,CKPT,LGWR之间
回顾
DBWn n指的是0-9 a-j 20个写进程的区分标记 将脏块写盘
11G 0-9 a-z
SQL> show parameter db_writer_processes
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_writer_processes integer 1
最好的性能:cpu核-1
SQL>
触发写的条件
1.产生检查点
2.脏数据缓冲区达到阀值 默认10%
3.扫描整个data buffer没有空闲 data buffer中包含脏的和未脏的 优先写脏数据列表 再写未改的
4.timeout超时 如果DBWR没事做 会被每三秒唤醒一次去巡检 写不写不一定
5.集群环境的ping请求触发多实例的数据写请求
6.表级别的truncate或drop也会触发数据写
7.修改表空间的read only
8.做表空间的off line(离线)
9.热备份 begin backup命令
LGWR 只有一个进程 不会向数据写进程那么多 因为写要求有顺序 将redo log buffer里的条目 写到redo文件
触发写的条件
1.commit
2.redo log buffer 1/3满
3.redo log buffer 日志缓冲区达到1M
4.写日志优先
当DBWR要写脏数据时,要检查脏数据对应的日志是否写盘,如果日志还没写,会优先写日志
5.3秒写一次
CKPT 把新的检查点写入指定位置
1.调度数据写dbwN
2.将新检查点写数据文件头
3.将新检查点写控制文件中 和 写入数据文件头中
实例恢复 数据库自动根据这套机制(SMON)去恢复,不需要DBA参与
介质恢复(物理文件损坏后的恢复):DBA自行恢复
数据库运行过程中崩溃:
恢复(redo应用)的起点和终点
起点:
终点:redo文件中的最后一条记录
检查点:
检查点发生的SCN之前的所有脏块全写盘了,也就不需要恢复
检查点发生的SCN之后的所有做的改动,全都未写盘,需要恢复
SCN点以前的所有脏数据全写+数据文件头+控制文件中的SCN
30分钟触发一次检查点,运行到29分崩溃,恢复时间很长,宕机时间长,业务中断时间长
30分钟内DBWR空闲,刚好到30分钟的时候,突发性大工作量
1分钟触发一次检查点,崩溃后恢复时间很短,宕机时间短,业务中断时间短
写盘太频繁
完全检查点:
所有脏数据全写+数据文件头+控制文件中的SCN
2中机制会触发:
1、alter system checkpoint;
2、非shutdown abort的一致性关机命令
增量检查点:
全局检查点 RAC
局部检查点
单机
完全:所有内存中的脏块+所有的数据文件+所有的控制文件
增量:只更新控制文件中的LRBA的位置
延迟:日志切换,不立即做
上一组日志内涉及的脏块和数据文件头控制文件头
内存数据块写入数据文件,在写的过程中,一旦发生实例崩溃,就需要实例恢复
要有一套完整的机制能够保证用户已经提交的数据不会丢失
而且这套机制要充分考虑IO效率问题
Oracle引入了CKPT和LGWR这两个后台进程,这两个进程与DBWn进程互相合作,
提供了既安全又高效的写脏数据块的解决方案。
用户进程每次修改内存数据块时,都会在日志缓冲区(log buffer)中构造一个相应的重做条目(redo entry),
该重做条目描述了被修改的数据块在修改之前和修改之后的值。
而LGWR进程则负责将这些重做条目写入联机日志文件。
只要重做条目进入了联机日志文件,那么数据的安全就有保障了,否则这些数据都是有安全隐患的。
用户提交(commit)时,Oracle是不一定会把提交的数据块写入数据文件的。
那么实例崩溃时,必然会有一些已经提交但是还没有被写入数据文件的内存数据块随内存断电消失,就需要恢复
当实例再次启动时,Oracle需要利用日志文件中记录的重做条目在buffer cache中重新构造出被丢失的数据块,
从而完成先前滚和后回滚的工作,并将丢失的数据块找回来。
在恢复的过程中必然要有恢复的起点和终点
终点很好解决.最后commit的点
起点就比较难定位 起点就意味着这之前的数据都已经从内存同步到数据文件中了.其后的就是脏数据
起点定位时间太长,说明下次恢复周期长,周期长安全隐患大
起点定位时间太短,说明DBWN进程频繁的写,IO就比较紧张
为了确定最佳起点位置oracle采用CKPT进程实现完全检查点和增量检查点来分别定位起点
可以说检查点的引入就是为了加速实例恢复.
oracle为检查点进程提供了检查点队列,该队列串起来的都是脏数据块所对应的buffer header.
DBWn就是按着这个队列的记录将脏数据写入数据文件的.写完的数据也就从这个队列中脱离了.
检查点队列上的buffer header是按照数据块第一次被修改的时间的先后顺序来排列的。
越早修改的数据块的buffer header排在越前面,
同时如果一个数据块被修改了多次的话,在该链表上也只出现一次。
检查点队列里记录着这次的修改产生的redo条目在REDO文件中的位置 简称为(RBA)
检查点队列上的buffer header还记录了脏数据块在第一次被修改时,
所对应的重做条目在重做日志文件中的地址,也就是LRBA(Low Redo Block Address)
数据块最后一次修改的地址叫做HRBA
当数据块第一次被修改时 LRBA与HRBA是同一个地址,当同一个数据块第二次修改时则更新HRBA值
在检查点队列里最后一个记录的RBA被称为ON DISK RBA.
oracle8I版本前只有完全检查点,完全检查点就意味着buffer cache中所有脏数据都完全写入到了数据文件中.
那个版本,日志切换就会触发完全检查点
到了8I版本后,完全检查点只有在两种情况下才触发:
1. alter system checkpoint;
2.除了shutdown abort以外的正常关库命令
手动执行alter system checkpoint完全检查点会将所有脏块写盘(包括未提交的)
关闭数据库时会将为完成的事物回滚.再将脏块写盘
同时,完全检查点会更新控制文件和数据文件头.
8I中引入了增量检查点(incremental checkpoint),的概念.
增量检查点每隔3秒
检查点队列随着时间增长,由CKPT通知DBWR去写,每次告诉DBWR写到队列的什么地方 与主机的IO效率有关
也就是CKPT是监工,向DBWR提交任务,DBWR即为劳力
CKPT除了通知DBWR去写以外,还会每三秒检查一次DBWR的工作进度,并将DBWR当前进度记录到控制文件
如果3秒触发,CKPT只做一件事,就是找出检查点队列里第一个buffer header
并将该buffer header中所记录的LRBA(Low Redo Block Address Low表示第一次修改时对应的RBA)
将LRBA记录到控制文件中去。
如上事件即称为增量检查点.目的是实例崩溃后,定位恢复的redo起点. 使起点和终点尽可能短,恢复时间就少.
延缓检查点
如果是日志切换,也换做检查点,这个检查点并不立即去做,当日志循环切一圈时,第一次切换的日志要被覆盖前必须写盘时会去做
除了记录LRBA到控制文件,还需要记录到每个数据文件头。
概括下来其实就是DBWn负责写检查点队列上的脏数据块,
而CKPT负责记录当前检查点队列的第一个数据块所对应的的重做条目在日志文件中的地址,将其写到控制文件中去.
比如数据库运行期间 发生事务修改数据
日志情况:
事务号 文件号 block号 行号 列 值 RBA
T1 4 33 5 1 a 11
T1 5 62 13 2 b 22
T3 6 40 66 3 c 33
T4 7 58 121 7 d 44
T5 5 62 19 3 e 55
Commit SCN# timestamp 66
T199 8 345 235 8 f 77
事务T1改了两个块 接着T3T4T5也做了修改,T1和T5在同一个62号块上 这个块在队列里就只记录一次
对应检查点队列情况:
11 22 33 44 77
4/33 5/62 6/40 7/58 8/345
最早---------------------->当前
日志文件中所记录的提交标记也不会体现在检查点队列上,因为提交本身只是一个标记而已,不会涉及修改数据块
比如此时3秒超时,发生增量检查点,就将第一个队列的脏数据库块对应的LRBA记录到控制文件中去.就是RBA11.
等到DBWn启动时写这个队列中的记录脏块,写完就从队列里摘除.
这几个块写的过程中又发生新的事务,新的事务再次更改数据,队列继续增长
11 22 33 44 77 88 99 100
4/33 5/62 6/40 7/58 8/345 7/11 4/66 2/66
最早-------------------------------------->当前
黄色代表被写完 就从队列里摘除了 后面的是新增加的
刚好写到33,此时断电,就从11对应的redo中开始恢复
如果不断电,DBWn写完了44.
再次到了3秒超时,又一次触发了增量检查点
11 22 33 44 77 88 99 100
4/33 5/62 6/40 7/58 8/345 7/11 4/66 2/66
最早-------------------------------------->当前
这时就把第一个队列的脏数据库块对应的LRBA记录到控制文件中去.就是77
再断电恢复的起点就是77对应REDO中的位置.
增量检查点引入的原因 就是加速实例恢复和减缓DBWR一次突发大任务量
oracle提供给DBA控制检查点队列长度的参数
1,fast_start_io_target
用于表示数据库崩溃后 实例恢复时需要产生的IO总数,他
通过v$filestat的AVGIOTIM来估算的.
已经在9I中废弃
2,fast_start_mttr_target
oracle为了简化DBA操作,9I中引入fast_start_mttr_target这个参数,
用于表示数据库崩溃后 实例恢复需要的时间.以秒为单位,
其中的mttr是mean time to recovery的简写,
比如你控制实例恢复时间在5分钟,则设置为300秒,oracle会自己去根据当前系统IO效率去平衡.
3.log_checkpoint_timeout
用于表示检查点位置和重做日志尾之间的时间间隔,以秒为单位,默认情况下是1800秒.
这个参数实际上表示了脏块保持脏状态的最长时间.
4,log_checkpoint_interval
表示检查点位置和重做日志末尾的块的数量
5.log_checkpoints_to_alert
用于在告警日志中记录检查点信息.给DBA做检查点频度的分析使用
在9I后,对检查点频率,建议只设置fast_start_mttr_target.
也可以通过设置log_checkpoint_timeout,设置一个脏块保持脏状态的最大时间,
两个都设置会取最小时间做为有效时间
而其他两个参数fast_start_io_target,log_checkpoint_interval建议不再使用