天天看點

日志檢測發現Checkpoint not complete

1.檢查告警日志發現Checkpoint not complete

報錯如下:

Sat May 21 07:36:43 2016

Thread 1 cannot allocate new log, sequence 6672

Checkpoint not complete

  Current log# 2 seq# 6671 mem# 0: /home/oracle/app/oracle/oradata/qianlong/redo02.log

Sat May 21 07:36:58 2016

Private strand flush not complete

Thread 1 advanced to log sequence 6672 (LGWR switch)

  Current log# 3 seq# 6672 mem# 0: /home/oracle/app/oracle/oradata/qianlong/redo03.log

         看見報錯,并且日志切換特别頻繁,第一反映就是應該增加redo日志大小。網上找了相關報錯解決方法也都是建議增加redo日志大小。

----檢視日志切換時間:

SQL> select sequence#,first_time,nexttime,round(((first_time-nexttime)*24)*60,2) diff from (select sequence#,first_time,lag(first_time) over(order by sequence#) nexttime from v$log_history where thread#=1 and to_char(first_time,'yyyy-mm-dd')='2016-05-23')  order by sequence# desc;

----每天日志切換數量

select to_char(first_time,'yyyy-mm-dd') day1,count(*)

    from v$log_history

      where first_time>=to_date('2016-05-03','yyyy-mm-dd')

      group by to_char(first_time,'yyyy-mm-dd') order by day1;

2.問題分析

--------------來自DAVE的分析 

         CKPT這個背景程序就是做checkpoint這件事,checkpoint被觸發的條件之一是就發生redo log switch,Checkpoint的具體工作包括: 

         觸發DBWr向磁盤寫入dirty data。 把checkpoint資訊更新到datafile header和control file裡。 

         Checkpoint做的事情之一是觸發DBWr把buffer cache中的dirty cache寫入磁盤。另外就是把最近的系統的SCN更新到datafile header和control file(每一個事務都有一個SCN),做第一件事的目的是為了減少由于系統突然當機而需要的恢複時間,做第二件事實為了保證資料庫的一緻性。 

  而redo log switch就是觸發checkpoint的主要的事件(event) ,當第一組redo log被用完之後,Oracle就要停止使用目前的redo log,轉而使用另一組redo log,這就叫做log switch。而log switch觸發checkpoint。 

2.1出現checkpoint not complete原因:

         假設我們隻有兩個redo log group:group 1和group 2,并且buffer cache中總是有大量的dirty block需要寫入datafile,當redo log從group 1 switch to group 2的時候,會觸發checkpoint, checkpoint要求DBWr把buffer cache中的dirty block寫入datafile。然而,當我們再次用完group 2裡面的空間,需要再次switch to group 1并重用group 1的時候,如果我們發現redo log group 1所保護的那些dirty block還沒有完全寫入到datafile,整個資料庫必須等待DBWr把所有的dirty block寫入到datafile之後才能做其他的事情,這就是我們遇到的"checkpoint not complete"問題。

         解決辦法包括增加redo日志組合增大online redo log檔案大小,為DBRr争取充裕的時間。

2.2出現cannot allocate new log原因:

         Checkpoint will flush dirty block to datafile, 進而觸發DBWn書寫dirty buffer,等到redo log覆寫的dirty block全部被寫入datafile後才能使用redo log(循環使用),如果DBWn寫入過慢,LGWR必須等待DBWn完成,則這時會出現“checkpoint not completed!”。 是以當出現checkpoint not competed的時候,還會伴随cannot allocate new log的錯誤。

         在出現這個錯誤的時候,資料庫是短暫hang住的,等待checkpoint的完成。 在hang住的時候,沒有日志産生。

2.3 Tom大師對這個問題的解釋如下:

the infamous "checkpoint not complete, cannot allocate new log" message.

this occurrs when Oracle attempts to reuse a log file but the checkpoint that would flush

the blocks that may have redo in this log file has not yet completed -- we must wait

until that checkpoint completes before we can reuse that file -- thats when this message is printed. during this time (when we cannot allocate a new log) processing is suspended in the database while the checkpoint is made to complete ASAP.

---- 我們必須等待checkpoint 的完成, 在這個過程中, 資料庫是短暫的hang住的。

The major way to relieve this is to have sufficient log to carry you through peak times. that way, we can complete the checkpoint while you are not busy. also make sure your checkpoints happen as fast as they can (eg: enable ASYNC IO or configure >1 DBWR if ansyc IO cannot be used, make sure disks are not contending with other apps and so on)

Another way is to make the log files smaller, hence increasing the frequency with which we checkpoint (log checkpoint interval and other init.ora parameters achieve the same effect btw).

----這個主題使DBA能對checkpoint和checkpoint優化的參數有一個較好的了解:

- FAST_START_MTTR_TARGET

- LOG_CHECKPOINT_INTERVAL

- LOG_CHECKPOINT_TIMEOUT

- LOG_CHECKPOINTS_TO_ALERT

它也解釋了怎樣解釋和處理出現在ALERT.LOG file中的checkpoint的錯誤"'Checkpoint not Complete' and 'Cannot Allocate New Log"。

3.什麼是checkpoint

3.1 checkpoint原理分析

Checkpoint是為了記憶體中已經被修改的資料塊與磁盤資料檔案同步的一種資料庫事件。它提供了一種保持事務送出以後資料一緻的手段。往Oracle磁盤寫髒資料的機制與事務送出不是同步的。

checkpoint有兩個目的:

1、確定資料一緻性。

2、使資料庫能快速地恢複。

怎樣快速恢複

因為資料庫會把所有的改變都在資料檔案上設定checkpoint并一直增加,它不需要請求checkpoint之前的重做日志,Checkpoint能保證所有在緩存區的資料寫到相應的資料檔案,防止因為意外的執行個體失敗導緻的資料丢失。

Oracle寫這個髒資料的條件下:

1、DBWR 逾時,大約3秒時間

2、系統中沒有多的空緩沖區來存放資料

3、CKPT程序(産生新的checkpoint) 觸發DBWR

4、表級别的truncate或drop也會觸發資料寫

5、修改表空間為read only

6、做表空間的offline

7、熱備份begin backup指令

一個checkpoint有5種事件類型:

1、每次重做日志的切換;

2、LOG_CHECKPOINT_TIMEOUT 這個延遲參數的到達

3、相應位元組(LOG_CHECKPOINT_INTERVAL* size of IO OS blocks)被寫到目前的重做日志

4、ALTER SYSTEM SWITCH LOGFILE 這個指令會直接導緻checkpoint發生

5、ALTER SYSTEM CHECKPOINT

Checkpoint期間會有下面程序發生:

1、DBWR寫所有髒資料到資料檔案;

2、LGWR更新控制檔案和資料檔案的SCN。

3.2 Checkpoints和優化:

Checkpoints是一個資料庫優化的難點。頻繁的Checkpoints可以實作快速的恢複,但也會使性能下降。怎樣處理這個問題呢?

依賴于資料庫資料檔案的數量,一個Checkpoint可能是高速的運作。因為所有的資料檔案在Checkpoint期間都會被當機。更頻繁的Checkpoints可以快速恢複資料庫。這也客戶對不按規定系統當機的容忍的原因。然而,在一些特殊情況下,頻繁的Checkpoints也不能保證可以快速恢複。我們假設資料庫在95%的時間内是正常運作,5%由于執行個體失敗導緻不可用,要求恢複。對大多數客戶而言,他們更希望調整95%的性能而不是5%的當機時間。這個假設表明,性能是擺在第一位的,是以我門的目标就是在優化期間減少Checkpoints的頻繁度。

優化Checkpoints包括4個關鍵的初始化參數:

FAST_START_MTTR_TARGET

LOG_CHECKPOINT_INTERVAL

LOG_CHECKPOINT_TIMEOUT

LOG_CHECKPOINTS_TO_ALERT

詳細介紹每個參數:

1、FAST_START_MTTR_TARGET:

Oracle9i以來FAST_START_MTTR_TARGET 參數是調整checkpoint的首選的方法。FAST_START_MTTR_TARGET 可以指定單執行個體恢複需要的秒數。基于内部的統計,增長的checkpoint會自動調整的checkpint的目标以滿足FAST_START_MTTR_TARGET 的需求。

V$INSTANCE_RECOVERY中ESTIMATED_MTTR 顯示目前估計需要恢複的秒數。這個值會被顯示即使FAST_START_MTTR_TARGET 沒有被指定。

sys@ORCL>select estimated_mttr from v$instance_recovery;

ESTIMATED_MTTR

--------------

            11

V$INSTANCE_RECOVERY中TARGET_MTTR 表明在短時間内MTTR的目标。

V$MTTR_TARGET_ADVICE 顯示這個目前MTTR設定的工作量産生的I/O數量和其他I/O。這個視圖幫助使用者評定這個在優化和恢複之前的平衡。

2、LOG_CHECKPOINT_INTERVAL:

LOG_CHECKPOINT_INTERVAL 參數指定這個最大的重做塊的間隔數目。如果FAST_START_MTTR_TARGET被指定,LOG_CHECKPOINT_INTERVAL不能被設定為0。

在大多數Unix系統的OS塊大小是512位元組。設定LOG_CHECKPOINT_INTERVAL=10000意味着這個增長的checkpoint不能追加到目前日志,因為多于5M。如果你的重做日志是20M,你将發出4個checkpoint對每個重做日志。

LOG_CHECKPOINT_INTERVAL 會發生影響當一個checkpoint發生時,小心設定這個參數,保持它随着重做日志檔案大小變化而變化。checkpoint頻繁是這個影響資料庫恢複的原因之一。短的checkpoint間隔意味資料庫将快速恢複,也增加了資源的利用。這個參數也影響資料庫向前復原的時間。實際的恢複時間是基于這個時間,當然還有失敗的類型和需要歸檔日志的數量。

3、LOG_CHECKPOINT_TIMEOUT:

這個參數指定checkpoint發出的時間間隔。換句話說,它指定一次髒資料多少時間寫出一次。checkpoint頻率會影響這個資料庫恢複的時間。長時間的間隔會要求資料庫恢複要求更久。Oracle建議用LOG_CHECKPOINT_interval去控制checkpoint而不用LOG_CHECKPOINT_TIMEOUT,LOG_CHECKPOINT_TIMEOUT每n秒發一次checkpoint,不顧事務送出的頻率。這可能會導緻一些沒有必要的checkpoint在事務已經變化的情況下。不必要的checkpoint必須被避免。還有一個容易誤解的地方:LOG_CHECKPOINT_TIMEOUT 會間隔性地發出log switch。而Log switch會觸發一個checkpoint,但checkpoint不會導緻一個log switch。唯一手工方式alter system switch logfile或者重新設定redo logs大小可以導緻頻繁switch。

SQL> alter system set log_checkpoint_timeout=300;[機關是秒]

log_checkpoint_to_alert:

設定為真,可以在告警日志中觀察到增量檢查點的觸發。

SQL> alter system set log_checkpoints_to_alert=true;

對于優化和恢複, 線上重做日志的大小是關鍵的。

修改Redo log 大小的操作方法:

檢視目前日志組狀态:

SQL> select group#,sequence#,bytes,members,status from v$log;

GROUP# SEQUENCE# BYTES MEMBERS STATUS

---------- ---------- ---------- ---------- ----------------

1 14230 52428800 1 ACTIVE

2 14231 52428800 1 CURRENT

3 14229 52428800 1 INACTIVE

CURRENT: 表示是目前的日志。

INACTIVE:髒資料已經寫入資料塊。該狀态可以drop。

ACTIVE: 髒資料還沒有寫入資料塊。

檢視目前日志組成員:

SQL> select member from v$logfile;

MEMBER

--------------------------------------------------------------------------------

/u03/oradata/newccs/redo03.log

/u03/oradata/newccs/redo02.log

/u03/oradata/newccs/redo01.log

添加online redo log組:

SQL> alter database add logfile group 4 ('/u03/oradata/newccs/redo04.log') size 100m reuse;

SQL> alter database add logfile group 5 ('/u03/oradata/newccs/redo05.log') size 100m reuse;

SQL> alter database add logfile group 6 ('/u03/oradata/newccs/redo06.log') size 100m reuse;

切換歸檔日志:

SQL> alter system switch logfile;

檢視歸檔檔案的狀态,因為隻有Inactive的我們才可以drop,它的資料塊已經寫入了資料塊。如果是Active狀态,表示這裡的髒資料還沒有寫入寫入資料庫,手工加個全局檢查點,督促CKPT馬上喚醒DBWR寫入髒資料

SQL>alter system checkpoint;

2 14231 52428800 1 ACTIVE

4 14229 52428800 1 CURRENT

5 14229 52428800 1 UNUSED

6 14229 52428800 1 UNUSED

因為5,6 我們還沒有用,是以顯示為UNUSED

删除redo log組:

SQL> alter database drop logfile group 1;

Database altered.

或者:

SQL> alter database drop logfile '/u03/oradata/newccs/redo01.log';

在添加redo log group 1.

SQL> alter database add logfile group 1 ('/u03/oradata/newccs/redo01.log') size 100m reuse;

通過删除在添加,達到對redo log group 的resize.

注意兩點

1、單純加redo log group單個檔案的大小沒有作用,同一個group裡,檔案大小都是一緻的。

2、如果是歸檔模式的話,確定已經自動歸檔,如果手動歸檔的話,需要在alter system switch logfile鎖死的時候,用alter system log current 來手動歸檔。或者通過alter system archive log start打開自動歸檔。否則的話,當redo log group切換完整個groups的時候,會一直等待狀态(******)。

3、《Oracle DBA必備技能詳解》(Robert G.Freeman),上面建議redo log 最好是15分鐘切換一次。