由于中LGWR和DBWR工作的不一致,Oracle引入了检查点的概念,用于同步,保证数据库的一致性。在Oracle里面,检查点分为两种:完全检查点和增量检查点。下面我们分别介绍这两种检查点的作用: 1、完全检查点. X3 J9 \. P5 L
在Oracle8i之前,数据库的发生的检查点都是完全检查点,完全检查点会将数据缓冲区里面所有的脏数据块写入相应的数据文件中,并且同步数据文件头和控制文件,保证数据库的一致。完全检查点在8i之后只有在下列两种情况下才会发生:# e+ n% {& _$ `, u6 y7 ^: d
(1)DBA手工执行alter system checkpoint的命令;
* o( x; E; P; q+ M6 q (2)数据库正常shutdown(immediate,transcational,normal)。& G* F0 x- ]3 k; e2 o
由于完全检查点会将所有的脏数据库块写入,巨大的IO往往会影响到数据库的性能。因此Oracle从8i开始引入了增量检查点的概念。
- R6 |4 t+ m1 y7 j 2、增量检查点5 a9 w4 G% ? o' @ {" \0 x" _( N
Oracle 从8i开始引入了检查点队列这么一种概念,用于记录数据库里面当前所有的脏数据块的信息,DBWR 根据这个队列而将脏数据块写入到数据文件中。检查点队列按时间先后记录着数据库里面脏数据块的信息,里面的条目包含RBA(Redo Block Address,重做日志里面用于标识检查点期间数据块在重做日志里面第一次发生更改的编号)和数据块的数据文件号和块号。在检查点期间不论数据块更改几次,它在检查点队列里面的位置始终保持不变,检查点队列也只会记录它最早的RBA,从而保证最早更改的数据块能够尽快写入。当DBWR将检查点队列里面的脏数据块写入到数据文件后,检查点的位置也要相应地往后移,CKPT每三秒会在控制文件中记录检查点的位置,以表示Instance Recovery时开始恢复的日志条目,这个概念称为检查点的“心跳”(heartbeat)。检查点位置发生变更后,Oracle里面通过4个参数用于控制检查点位置和最后的重做日志条目之间的距离。在这里面需要指出的是,多数人会将这4个参数看作控制增量检查点发生的时间。事实上这是错误的,这4个参数是用于控制检查点队列里面的条目数量,而不是控制检查点的发生。% X3 u7 P2 O* d) L$ _4 e( B' c0 j
(1)fast_start_io_target0 B/ s/ l$ z" p. ~* R$ R( \
该参数用于表示数据库发生Instance Recovery的时候需要产生的IO总数,它通过v$filestat的AVGIOTIM来估算的。比如我们一个数据库在发生Instance Crash后需要在10分钟内恢复完毕,假定OS的IO每秒为500个,那么这个数据库发生Instance Recovery的时候大概将产生500*10*60=30,000次IO,也就是我们将可以把fast_start_io_target设置为 30000.4 P8 A- V. d" P% d
(2)fast_start_mttr_target5 Q4 z5 `8 U$ h0 L, D/ b
我们从上面可以看到fast_start_io_target 来估算检查点位置比较麻烦。Oracle为了简化这个概念,从9i开始引入了 fast_start_mttr_target这么一个参数,用于表示数据库发生Instance Recovery的时间,以秒为单位。这个参数我们从字面上也比较好理解,其中的mttr是mean time to recovery的简写,如上例中的情况我们可以将fast_start_mttr_target设置为600.当设置了 fast_start_mttr_target后,fast_start_io_target这个参数将不再生效,从9i后 fast_start_io_target这个参数被Oracle废除了。
/ Y: ^- @+ J7 V a4 d- s' I K (3)log_checkpoint_timeout
% Y1 t1 S* I( a, M 该参数用于表示检查点位置和重做日志文件末尾之间的时间间隔,以秒为单位,默认情况下是1800秒。
0 T2 m$ u, A( n( } (4)log_checkpoint_interval+ z6 `9 Z& _2 }: n% p* T6 e t
该参数是表示检查点位置和重做日志末尾的重做日志块的数量,以OS块表示。
! p8 F& M8 Z' Z$ D$ y (5)90% OF SMALLEST REDO LOG
' S4 |( J* w5 f 除了以上4个初始化参数外,Oracle内部事实上还将重做日志文件末尾前面90%的位置设为检查点位置。在每个重做日志中,这么几个参数指定的位置可能不尽相同,Oracle将离日志文件末尾最近的那个位置确认为检查点位置。
) q4 x! {3 O+ Q; e' C0 p oracle 9i instance recovery* ^ G& `7 n% z1 |9 P+ K6 V
1、增量检查点
4 H* S% Q# J/ ] U3 z8 Z, Z 在checkpoint queue的基础上实现了增量检查点,每3秒发生一次checkpoint heartbeat,记录dbwr上次写成功的最大RBA(redo block address)。这样的话做instance recovery的时候就从这个rba开始,而不是从上次checkpoint scn开始,大大节省了恢复时间。
8 B$ {$ t' h& u7 ~8 K/ t 2、twice scan of redo log
; U5 D' W7 x; s: D 在应用redo之前,redo将会被操作两次,第一次去扫描哪些redo record需要被应用,因为9i在redo里添加了dbwr写数据块的信息,所以dbwr发生前的日志将不会被应用。第二步就是选出需要被应用的日志然后开始rollforward.
: X! B! E% T; K7 }2 X 3、rollforward" N% N/ R: V& u' N! u- k, z
在做instance recovery时必须先定位到redo log 然后应用所有日志到datafile,这时候包括了committed和uncommitted的数据。当做完rollward,数据库就可以open了。 s- H! a7 u# H0 j% v( ^! P
4、rollback. y: A P4 g: ^1 p# m1 S
因 为rollforward产生了uncommitted数据,所以必须回滚这些数据。这将由smon和on-demand rollback来实现。smon将会扫描undo segment header去标志所有活动事务为dead,然后会逐渐去回滚这些事务。另外on-demand rollback提供了前台进程进行rollback,当前台进程企图获得被dead事务占用row lock,这时候前台进程将会去undo segment取得before image去回滚这个块,至于其他被这个dead事务lock的块就等待smon去回滚。
5 @1 ]: p0 W- t: T5 I+ B* ~( k. n5 U4 q% A, G% b( _$ y/ X4 r
另外,如果 在数据库打开的过程中process crash导致transaction dead,resource不能被释放的情况,这时候如果另一个进程需要这些resource,那么这个进程将会等待直到pmon清理dead process释放出resource. |