ITPub博客

首页 > Linux操作系统 > Linux操作系统 > [zt]Oracle检查点ckpt (checkpoint)

[zt]Oracle检查点ckpt (checkpoint)

原创 Linux操作系统 作者:tolywang 时间:2008-12-31 14:10:30 0 删除 编辑


由于Oracle中LGWR和DBWR工作的不一致,Oracle引入了检查点的概念,用于同步数据库,保证数据库的一致性。在Oracle里面,检查点分为两种:完全检查点和增量检查点。下面我们分别介绍这两种检查点的作用:


1、 完全检查点

在Oracle8i之前,数据库的发生的检查点都是完全检查点,完全检查点会将数据缓冲区里面所有的脏数据块写入相应的数据文件中,并且同步数据文件头和控制文件,保证数据库的一致。完全检查点在8i之后只有在下列两种情况下才会发生:

(1、)DBA手工执行alter system checkpoint的命令;

(2、)数据库正常shutdown(immediate,transcational,normal)。

由于完全检查点会将所有的脏数据库块写入,巨大的IO往往会影响到数据库的性能。因此Oracle从8i开始引入了增量检查点的概念。


2、 增量检查点
Oracle从8i开始引入了检查点队列这么一种概念,用于记录数据库里面当前所有的脏数据块的信息,DBWR 根据这个队列而将脏数据块写入到数据文件中。检查点队列按时间先后记录着数据库里面脏数据块的信息,里面的条目包含RBA(Redo Block Address,重做日志里面用于标识检查点期间数据块在重做日志里面第一次发生更改的编号)和数据块的数据文件号和块号。在检查点期间不论数据块更改几次,它在检查点队列里面的位置始终保持不变,检查点队列也只会记录它最早的RBA,从而保证最早更改的数据块能够尽快写入。当DBWR将检查点队列里面的脏数据块写入到数据文件后,检查点的位置也要相应地往后移,CKPT每三秒会在控制文件中记录检查点的位置,以表示Instance Recovery时开始恢复的日志条目,这个概念称为检查点的“心跳”(heartbeat)。检查点位置发生变更后,Oracle里面通过4个参数用于控制检查点位置和最后的重做日志条目之间的距离。在这里面需要指出的是,多数人会将这4个参数看作控制增量检查点发生的时间。事实上这是错误的,这4个参数是用于控制检查点队列里面的条目数量,而不是控制检查点的发生。

(1、)fast_start_io_target
该参数用于表示数据库发生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。

(2、)fast_start_mttr_target
我们从上面可以看到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废除了。

(3、)log_checkpoint_timeout
该参数用于表示检查点位置和重做日志文件末尾之间的时间间隔,以秒为单位,默认情况下是1800秒。

(4、)log_checkpoint_interval
该参数是表示检查点位置和重做日志末尾的重做日志块的数量,以OS块表示。

(5、)90% OF SMALLEST REDO LOG
除了以上4个初始化参数外,Oracle内部事实上还将重做日志文件末尾前面90%的位置设为检查点位置。在每个重做日志中,这么几个参数指定的位置可能不尽相同,Oracle将离日志文件末尾最近的那个位置确认为检查点位置。

oracle 9i instance recovery
1. 增量检查点
在checkpoint queue的基础上实现了增量检查点,每3秒发生一次checkpoint heartbeat,记录dbwr上次写成功的最大RBA(redo block address)。这样的话做instance recovery的时候就从这个rba开始,而不是从上次checkpoint scn开始,大大节省了恢复时间。
 
2. twice scan of redo log
在应用redo之前,redo将会被操作两次,第一次去扫描哪些redo record需要被应用,因为9i在redo里添加了dbwr写数据块的信息,所以dbwr发生前的日志将不会被应用。第二步就是选出需要被应用的日志然后开始rollforward。
 
3. rollforward
在做instance recovery时必须先定位到redo log 然后应用所有日志到datafile,这时候包括了committed和uncommitted的数据。当做完rollward,数据库就可以open了。
 
4. rollback
因 为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去回滚。
 
另外,如果 在数据库打开的过程中process crash导致transaction dead,resource不能被释放的情况,这时候如果另一个进程需要这些resource,那么这个进程将会等待直到pmon清理dead process释放出resource。

如果数据库Crash,重新启动,很久远以前的未提交事务并不在Redo的恢复序列中。
但是未提交事务一定在回滚段事务表上存在,并且State=10,为活动事务。这就够了。

数据库启动之后,这些事务会被SMON逐个标记为Dead(不可能再活过来了),然后由SMON慢慢去回滚这些事务;也存在另外一种情况,后来的进程会去读这些未提交数据,发现Dead事务未提交,则主动进行回滚。

1. 一个数据块发生更新,必然写回滚
2. 回滚段的block变化也记录在redo中

一份未提交的数据必定在回滚中有相应的前镜像,任何正常的恢复都一定会把这些变化重新构建出来。


想像一下

1. update事务1更新了block 1
2. 回滚段1记录了block1的前镜像
3. checkpoint
4. update事务2更新了block2
5. 回滚段2记录了block2的前镜像
6. instance crash

现在重启数据库

1. 根据redo重新构建block2
2. 根据redo重新构建回滚段2
3. database open
4. SMON用回滚段2的数据回滚block2,SMON用回滚段1的数据回滚block1

最后一步也可能是
在另外一个select检索到block1或者block2的时候,发现这两个block的数据都是未提交的,此时再回滚block1和block2。

所以,只要有相应的回滚数据存在,无论什么时候oracle都可以找到一致的数据,oracle只需要知道这个事务是提交了的还是没提交了的,而这点在block header ITL中有记录。

 http://spaces.msn.com/roujiaweize/blog/cns!9745F14B4AEB3B72!328.entry

對SCN和CKPT的一點理解

scn (system change number,系統改變號),它提供 oracle 的內部時鐘機制,定義數據庫在某個確切時刻提交的版本,其作用是維護數據庫的數據的一致性。


ckpt (checkpoint,檢查點),它是一個數據庫事件,它將已修改的數據從高速緩存刷新寫入磁盤,並更新控制文件和數據文件。在一個檢查點之後,重做日誌文件中的重做記錄對於崩潰/實例恢復不再有用。


控制文件為每個數據文件保存有一個:checkpoint scn, stop scn,只有數據文件中有 stop scn
select name,checkpoint_change#,last_change# from v$datafile;


系統檢查點 scn (這個看別人寫的,不懂)
select checkpoint_change# from v$database;
當一個檢查點動作完成後,oracle 就把系統檢查點的 scn 存儲到控制文件中。


數據文件頭:數據庫 checkpoint scn
select name,checkpoint_change# from v$datafile_header;(這個是數據庫正常打開時從控制文件中查的,因為數據庫正常打開時這兩個相等,數據文件頭真正的 scn,oracle 自己讀文件頭)


控制文件為每個 redo 線程保存有一個:checkpoint scn
select thread#,checkpoint_change# from v$thread;


當一個檢查點動作完成後,oracle 更新控制文件中的這些 checkpoint scn (控制文件中一個,所有數據文件頭在控制文件中的存儲,redo 在控制文件中的信息),以及數據文件頭中的 checkpoint scn。所以可以理解,上面這些值都是從控制文件中取出來的。


當數據庫用 normal 或者 immediate 選項關閉時,執行檢查點,更新控制文件中數據文件的 stop scn,等於數據文件頭中的 checkpoint scn。


下次啟動數據庫時,oracle 要進行兩次檢查。第一次看數據文件頭中的 checkpoint scn 與控制文件中數據文件的 checkpoint scn。如果相等,進行第二次檢查,檢查數據文件頭中的 checkpoint scn 與控制文件中數據文件的 stop scn。如果相等,不需要對這個文件恢復。每個數據文件都做這樣的檢查,然後打開數據庫,將每個 stop scn 重新置為無窮大。


如果用 abort 關閉數據庫,則不執行檢查點處理,控制文件中數據文件的 stop scn 仍為無窮大。


下次啟動時做兩次檢查。如第一次相等,再比較第二個。這時,數據文件頭中的 checkpoint scn 一定是小於控制文件中數據文件的 stop scn 的,需要進行崩潰/實例恢復,進行前滾和回滾。


如果用備份代替了數據文件再啟動數據庫,這時做第一次檢查時,數據文件頭中的 checkpoint scn 一定小於控制文件中數據文件的 checkpoint scn;或者用備份的控制文件代替了控制文件再啟動數據庫,這時數據文件頭中的 checkpoint scn 一定大於控制文件中數據文件的 checkpoint scn。只要這兩個不相等,就需要介質恢復。


還有一種情況,如果控制文件和數據文件都是備份的,而這兩個 checkpoint scn 正好相等,第一次比較通過,那麼再看第二次比較了。其實這個時候在第一次比較之前,會先比較控制文件中 redo 線程的 checkpoint scn 的和 online log 的 scn,如果相等,繼續,如果不相等(小於),提示控制文件是舊的需要介質恢復。

 

本文檔來自于(http://blog.itpub.net/post/94/63495)

 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/35489/viewspace-524784/,如需转载,请注明出处,否则将追究法律责任。

下一篇: SQL Server专题 [zt]
请登录后发表评论 登录
全部评论
Oracle , MySQL, SAP IQ, SAP HANA, PostgreSQL, Tableau 技术讨论,希望在这里一起分享知识,讨论技术,畅谈人生 。

注册时间:2007-12-10

  • 博文量
    5595
  • 访问量
    13342128