當前位置:
首頁 > 最新 > 修復由於主庫NOLOGGING操作引起的備庫ORA-01578和ORA-26040錯誤

修復由於主庫NOLOGGING操作引起的備庫ORA-01578和ORA-26040錯誤

GIF

GIF

今天小麥苗給大家分享的是修復由於主庫NOLOGGING操作引起的備庫ORA-01578和ORA-26040錯誤。

修復由於主庫NOLOGGING操作引起的備庫ORA-01578和ORA-26040錯誤

(一)NOLOGGING操作引起的壞塊(ORA-01578和ORA-26040)簡介

如果只是錯誤ORA-01578,而沒有伴隨ORA-26040,那麼這個壞塊是由其它的原因引起的壞塊,可以嘗試使用RMAN的BMR(Block Media Recovery)修復。

如果數據段(表段、索引段)被定義為NOLOGGING屬性,那麼當NOLOGGING加APPEND、UNRECOVERABLE操作修改該數據段或者使用數據泵(DATAPUMP)impdp參數DISABLE_ARCHIVE_LOGGING:Y時,聯機重做日誌只會記錄很少的日誌信息。如果這些聯機重做日誌或歸檔日誌被用來恢複數據文件,那麼Oracle會將對應的數據塊標誌為無效(Soft Corrupt),而且下一次訪問這些數據塊時,會報ORA-01578和ORA-26040錯誤。

例如:

SQL> select * from test_nologging;

ORA-01578: ORACLE data block corrupted (file # 11, block # 84)

ORA-01110: data file 4: "/oradata/users.dbf"

ORA-26040: Data block was loaded using the NOLOGGING option

數據字典視圖DBA_TABLES、DBA_INDEXES、DBA_LOBS、DBA_TAB_PARTITIONS、DBA_LOB_PARTITIONS、DBA_TAB_SUBPARTITIONS中的LOGGING列記錄了NOLOGGING屬性。若LOGGING="NO"則表示NOLOGGING。

數據泵DATAPUMP的impdp參數DISABLE_ARCHIVE_LOGGING:Y在執行導入時會禁止LOGGING定義,而產生NOLOGGING操作。如果相應的datafile被restored和recovered,那麼接下來的涉及到目標表的查詢會報錯ORA-1578和ORA-26040。如果資料庫是FORCE LOGGING模式,那麼DISABLE_ARCHIVE_LOGGING選項不會關閉LOGGING。

impdp使用參數「DISABLE_ARCHIVE_LOGGING:Y」的一個例子:

impdp scott/tiger directory=DATA_PUMP_DIR dumpfile=dp transform=disable_archive_logging:y

NOLOGGING導致的壞塊不會導致RMAN備份失敗。一般來說soft corrupt block不會導致RMAN備份失敗,不需要設置MAXCORRUPT。資料庫備份中就會含有soft corrupt block,如果使用這些備份恢複數據,那麼恢復的數據也含有soft corrupt block。

除ORA-26040錯誤之外,當還有一些其他通用信息出現時,block dump可能會被產生。如果數據塊的block dump內有byte 0xff信息或者屬於某個段,ORA-1578和ORA-26040會因為介質恢復了NOLOGGING的部分導致了corruption而出現。

(二)利用RMAN、DBV檢測NOLOGGING導致的壞塊

DBV在檢測壞塊時,如果RDBMS版本小於10.2.0.4,那麼DBV列印錯誤DBV-200,如果RDBMS版本大於或等於10.2.0.4,那麼DBV列印錯誤DBV-201:

DBV-00200: Block, dba 46137428, already marked corrupted

DBV-00201: Block, DBA 46137428, marked corrupt for invalid redo application

RMAN的VALIDATE命令可以用來檢測NOLOGGING數據塊,檢查結果記錄在視圖V$DATABASE_BLOCK_CORRUPTION(小於12c的版本)和V$NONLOGGED_BLOCK(12c及其以上)。

下面的例子中檢查出DATAFILE 4有933壞塊,查詢V$DATABASE_BLOCK_CORRUPTION或者V$NONLOGGED_BLOCK。

RMAN> VALIDATE DATABASE;

...

.....

File Status Marked Corrupt Empty Blocks Blocks Examined High SCN

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

4 OK 933 1 6401 2275124

File Name: /oracle/dbs/users.dbf

RMAN在檢測壞塊時,如果RDBMS版本小於10.2.0.5和11.1.0.7,RMAN列印如下錯誤:

10.2.0.4 and lower, 11.1.0.6, 11.1.0.7:

RMAN validate reports it in v$database_block_corruption with CORRUPTION_TYPE=LOGICAL

如果RDBMS版本大於或等於10.2.0.5和11.2.0.1,RMAN報告,查看視圖v$database_block_corruption中CORRUPTION_TYPE=NOLOGGING的記錄。

10.2.0.5 and 11.2.0.1+:

RMAN validate reports it in v$database_block_corruption with CORRUPTION_TYPE=NOLOGGING

在12c及以後版本中,RMAN validate的結果不在視圖v$database_block_corruption中,而是在視圖v$nonlogged_block。從12.2版本開始,可以使用新的命令:「validate .. nonlogged block」去驗證nologging的block。

在以下的例子中,數據文件5和6有nologged的block:

RMAN> validate database nonlogged block;

Starting validate at ...

using target database control file instead of recovery catalog

allocated channel: ORA_DISK_1

channel ORA_DISK_1: SID=133 device type=DISK

channel ORA_DISK_1: starting validation of datafile

channel ORA_DISK_1: validation complete, elapsed time: 00:00:35

List of Datafiles

=================

File Status Nonlogged Blocks Blocks Examined Blocks Skipped

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

1 OK 0 106363 0

2 OK 0 78919 0

3 OK 0 96639 0

4 OK 0 4991 0

5 OK 400 2559 0

6 OK 569 2559 0

Details of nonlogged blocks can be queried from v$nonlogged_block view

在告警日誌中會更新以下信息:

Started Nonlogged Block Replacement recovery(validate) on file 5 (ospid 26351 rcvid 10616970560844821494)

Finished Nonlogged Block Replacement recovery(validate) on file 5. 400 blocks found

Started Nonlogged Block Replacement recovery(validate) on file 6 (ospid 26351 rcvid 10616970560844821494)

Finished Nonlogged Block Replacement recovery(validate) on file 6. 569 blocks found

(三)監控NOLOGGING操作

若執行了NOLOGGING操作,並且之後在沒有備份的情況下,RMAN命令「REPORT UNRECOVERABLE」可以查詢出被影響的datafile。

RMAN> report unrecoverable;

using target database control file instead of recovery catalog

Report of files that need backup due to unrecoverable operations

File Type of Backup Required Name

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

4 full or incremental /oracle/dbs/users.dbf

當初始化參數db_unrecoverable_scn_tracking設置為true(默認值,該參數在10g中是不可用的),那麼V$DATAFILE中以下列會被更新;

SYS@lhr121> select UNRECOVERABLE_CHANGE# ,

2 UNRECOVERABLE_TIME ,

3 FIRST_NONLOGGED_SCN ,

4 FIRST_NONLOGGED_TIME from v$datafile where file#=6;

UNRECOVERABLE_CHANGE# UNRECOVERABLE_TIME FIRST_NONLOGGED_SCN FIRST_NONLOGGED_TIM

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

2878238 2018-04-10 10:53:47 2878238 2018-04-10 10:53:47

在11.2.0.4或12.1.0.2+版本中,設置event 16490的情況下,物理備庫的MRP進程會檢查出NOLOGGING變化,並記錄在alert log。

ORA-16490 "logging invalidated blocks on standby due to invalidation redo"

"INVD_BLKS: Invalidating (file , bno )"

"fname: "Datafile name". rdba: ..."

(四)識別數據塊什麼時候被標誌為NOLOGGING

識別數據塊什麼時候被標誌為NOLOGGING,可以將trace文件中數據塊SCN或者v$database_block_coruption視圖中CORRUPTION_CHANGE#值轉換為時間:

 使用trace文件中數據塊SCN,例如:

Start dump data blocks tsn: 60 file#: 4 minblk 84 maxblk 84

buffer tsn: 3 rdba: 0x02c00054 (11/84)

scn: 0x0771.4fa24eb5 seq: 0xff flg: 0x04 tail: 0x4eb500ff

提取SCN值0x0771.4fa24eb5,刪除".",然後轉換0x07714fa24eb到十進位511453045995。

 使用v$database_block_coruption視圖中CORRUPTION_CHANGE#值

如果運行RMAN validate命令後,v$database_block_coruption視圖中corruption_type="NOLOGGING" (10.2.0.5和11.2.0.1+),那麼CORRUPTION_CHANGE#列的值就是十進位的SCN值。可以使用下面的方法獲得SCN Timestamp時間:

select scn_to_timestamp(&&decimal_scn) from dual;

如果運行RMAN validate:

select file#, block#, scn_to_timestamp(CORRUPTION_CHANGE#)

from v$database_block_corruption

where CORRUPTION_TYPE="NOLOGGING";

在12c中:

select file#, block#, scn_to_timestamp(NONLOGGED_START_CHANGE#) from v$nonlogged_block;

如果查詢gv$archived_log或gv$log_history遇到錯誤ORA-08181:

alter session set nls_date_format = "DD-MON-YY HH24:MI:SS";

select first_time, next_time

from gv$archived_log

where &decimal_scn between first_change# and next_change#;

select first_time

from gv$log_history

where &decimal_scn between first_change# and next_change#;

如果運行RMAN validate:

alter session set nls_date_format = "DD-MON-YY HH24:MI:SS";

select file#, block#, first_time, next_time

from v$archived_log, v$database_block_corruption

where CORRUPTION_CHANGE# between first_change# and next_change#

and CORRUPTION_TYPE="NOLOGGING";

select file#,block#,first_time

from v$log_history, v$database_block_corruption

where CORRUPTION_CHANGE# between first_change# and next_change#

and CORRUPTION_TYPE="NOLOGGING";

12c:

alter session set nls_date_format = "DD-MON-YY HH24:MI:SS";

select file#, block#, first_time, next_time

from v$nonlogged_block, v$archived_log

where NONLOGGED_START_CHANGE# between first_change# and next_change#;

select file#, block#, first_time

from v$nonlogged_block, v$log_history

where NONLOGGED_START_CHANGE# between first_change# and next_change#;

(五)SYSAUX表空間、AWR、EM等出現NOARCHIVELOG和NOLOGGING問題

如果資料庫版本是11.1.0.6或11.1.0.7或11.2.0.1,對NOLOGGING對象執行過DIRECT PATH操作,並且後續執行了RECOVER DATABASE命令,即使資料庫FORCE LOGGING是打開的情況下,會出現ORA-1578和ORA-26040錯誤。這種問題經常發生在SYSAUX表空間中的AWR或EM對象。請參考Note 1071869.1。注意資料庫當前版本可能已經大於11.1或者11.2.0.1但是問題可能是在升級之前產生的。這個約束在11.2.0.2以上版本中取消,這個問題在10g不會發生。

RDBMS版本變化:

(六)解決方法

NOLOGGING操作引起的壞塊是不能修復的,比如「Media Recovery」或「RMAN blockrecover」都無法修復這種壞塊。可行的方法是在NOLOGGING操作之後立刻備份對應的數據文件。

如果錯誤是執行RMAN DUPLICATE或RESTORE之後產生的,那麼在源庫打開FORCE LOGGING,然後再重新運行RMAN DUPLICATE或RESTORE。

alter database force logging;

如果錯誤出現在物理STANDBY資料庫,那麼可以從主庫恢復被影響的數據文件(只有當主庫沒有這個問題的情況下)。參考文檔Doc ID 958181.1。在Oracle 12c中可以使用RMAN選項RECOVER NONLOGGED BLOCK with DATAFILE、TABLESPACE、DATABASE。例如:

RMAN> RECOVER DATABASE NONLOGGED BLOCK;

為了避免這個問題發生,在主庫強制生產日誌:

alter database force logging;

如果同一個datafile的數據塊在主庫出現nologging壞塊,但是備庫沒有,可以通過手動跳過(dbms_repair)壞塊或者設置event 10231。主庫出現nologging壞塊可能是由於主庫執行過備份恢復或者之前是備庫,執行了switchover。

如果NOLOGGING數據塊位於空閑數據塊(dba_free_space視圖可以查詢到),那麼DBVerify檢查會發現這個問題,報錯DBV-00201或者在v$database_block_corruption視圖中顯示。對於這種情況,可以等待到這個數據塊被重用時會自動格式化或者手動強制格式化。

如果是索引,那麼可以重新創建(drop/create)索引。如果是表,那麼可以使用存儲過程DBMS_REPAIR.SKIP_CORRUPT_BLOCKS跳過壞塊,然後考慮是否重建表。

在刪除有壞塊的段之後,這個壞塊就處於空閑狀態,後續可以被分配給其他對象或段,當這個壞塊被分配給其它對象或段時,這個數據塊被重新格式化。如果v$database_block_corruption視圖中還是顯示為壞塊,那麼可以手動運行rman validate來清除視圖中的信息。

如果是LOB,那麼請參考Note 293515.1。

眾所周知,DG數據同步是基於日誌流的,這也是為什麼在配置DG階段需要將主庫設置為FORCE LOGGING的原因。但是,這也會帶來很多問題,SQL執行效率慢,例如:當我們使用數據泵進行遷移時我們希望最少停機時間完成,這時候我們就可能會考慮到以最小日誌導入的方式以加快導入速度,然後重新同步備庫。

在一些場景中,我們會去使用nologging操作去節省大量數據插入的時間,而這種操作所帶來的問題就是,如果該庫在有備庫的情況下,因為主庫的nologging插入操作不會生成redo,所以不會在備庫上傳輸和應用,這會導致備庫的數據出現問題。

在一個具有主備關係的主庫上將force_logging設置為nologging模式,隨後創建一張表,設置為nologging模式:

SQL> alter database no force logging;

SQL> create table DEMO tablespace users pctfree 99 as select rownum n from xmltable("1 to 100");

SQL> alter table DEMO nologging;

之後使用/* +append*/插入數據並提交

SQL> insert /*+ append */ into DEMO select rownum n from xmltable("1 to 1000");

SQL> commit

這時候在備庫對該表進行查詢會看到如下報錯信息

SQL>select count(1) from demo;

select count(1) from demo

*

ERROR at line 1:

ORA-01578: ORACLE data block corrupted (file # 4, block # 819)

ORA-01110: data file 4: "/data/data1/ORCL2/datafile/o1_mf_users_3ft1e9qb_.dbf"

ORA-26040: Data block was loaded using the NOLOGGING option


在Oracle 11g中,如果遇到這樣的問題,可以通過在備庫恢復有問題的數據文件來解決問題。而要修復這個問題,需要將包含缺少的數據的數據文件從主庫複製到物理備庫。

1、查詢主庫

SQL> SELECT NAME, UNRECOVERABLE_CHANGE# FROM V$DATAFILE;

NAME UNRECOVERABLE_CHANGE#

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

+DATADG/orcl/datafile/system.270.972381717 0

+DATADG/orcl/datafile/sysaux.265.972381717 0

+DATADG/orcl/datafile/undotbs1.261.972381717 0

+DATADG/orcl/datafile/users.259.972381717 6252054

+DATADG/orcl/datafile/example.264.972381807 0

+DATADG/orcl/datafile/undotbs2.258.972381927 0

+DATADG/orcl/datafile/example.266.972400297 0

+DATADG/orcl/datafile/ax.268.973612569 0

2、查詢備庫

sys@ORCL>SELECT NAME, UNRECOVERABLE_CHANGE# FROM V$DATAFILE;

NAME UNRECOVERABLE_CHANGE#

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

/data/data1/ORCL2/datafile/o1_mf_system_3dt1e9op_.dbf 0

/data/data1/ORCL2/datafile/o1_mf_sysaux_3ct1e9nb_.dbf 0

/data/data1/ORCL2/datafile/o1_mf_undotbs1_3gt1e9qq_.dbf 0

/data/data1/ORCL2/datafile/o1_mf_users_3ft1e9qb_.dbf 5383754

/data/data1/ORCL2/datafile/o1_mf_example_3et1e9ps_.dbf 0

/data/data1/ORCL2/datafile/o1_mf_undotbs2_3ht1e9r1_.dbf 0

/data/data1/ORCL2/datafile/o1_mf_example_3at1e9nb_.dbf 0

/data/data1/ORCL2/datafile/o1_mf_ax_3bt1e9nb_.dbf 0

3、比較主資料庫和備用資料庫的查詢結果

在兩個查詢結果中比較UNRECOVERABLE_CHANGE#列的值。如果主庫中UNRECOVERABLE_CHANGE#列的值大於備庫中的同一列,則需要將這些數據文件在備庫恢復。

將主庫對應的數據文件拷貝至備庫:

SQL> alter tablespace users begin backup;

SQL> exit

ASMCMD>cp +DATADG/orcl/datafile/users.259.972381717 /tmp

$ scp /tmp/users.259.972381717 10.10.60.123:/data/data1/ORCL2/datafile/

SQL> alter tablespace users end backup;

備庫將舊的數據文件RENAME至新的數據文件:

SQL>startup mount force

SQL> alter database recover managed standby database cancel;

SQL> alter system set standby_file_management=manual; #在備庫執行rename操作時,需要此參數為manual

SQL> alter database rename file "/data/data1/ORCL2/datafile/o1_mf_users_3ft1e9qb_.dbf" to "/data/data1/ORCL2/datafile/users.259.972381717";

SQL> alter system set standby_file_management=auto;

SQL> alter database recover managed standby database using current logfile disconnect from session;

之後就可以在備庫查詢到實例表DEMO

SQL> select count(1) from demo;

COUNT(1)

----------

1100


對於這種情況,在12.1版本中,RMAN提供了一種便捷的方式讓我們不需要在主庫上進行數據文件的備份傳輸而可以在備庫使用restore database (or datafile ) from service去從主庫進行恢復。

當然,Oracle的RMAN是足夠聰明的:如果數據文件是正常的狀態,RMAN可以根據它們的數據文件頭進行跳躍恢復。如果,由於nologging操作導致某些塊被標記為損壞的,那麼這部分數據文件就是需要恢復的,然後怎麼辦?在恢復命令中有FORCE選項。但我們可能並不需要它。因為有些時候數據文件是同步的,實時日誌應用進程還是在運行的。這個時候,為了恢復,我們需要停止應用。

一旦我們停止了應用,那麼就不需要執行RESOTORE DATABASE FORCE操作,因為現在數據文件的狀態是過舊的,就算你不加FORCE選項RMAN也是不會跳過這些數據文件的。

備庫關掉實時日誌應用,並開啟至mount狀態。

SQL> alter database recover managed standby database cancel;

SQL> shutdown immediate

Database closed.

Database dismounted.

ORACLE instance shut down.

SQL> startup mount

ORACLE instance started

備庫登陸RMAN,使用restore database (or datafile ) from service進行恢復

RMAN> restore database from service "primary_db"; #這裡的primary_db,為備庫至主庫的tns連接串的別名

Starting restore at 2018-05-03 17:00:35

using target database control file instead of recovery catalog

allocated channel: ORA_DISK_1

channel ORA_DISK_1: SID=29 device type=DISK

channel ORA_DISK_1: starting datafile backup set restore

channel ORA_DISK_1: using network backup set from service primary_db

channel ORA_DISK_1: specifying datafile(s) to restore from backup set

channel ORA_DISK_1: restoring datafile 00001 to /data/data1/ORCL2/datafile/o1_mf_system_02t1t9ck_.dbf

channel ORA_DISK_1: restore complete, elapsed time: 00:00:25

channel ORA_DISK_1: starting datafile backup set restore

channel ORA_DISK_1: using network backup set from service primary_db

channel ORA_DISK_1: specifying datafile(s) to restore from backup set

channel ORA_DISK_1: restoring datafile 00003 to /data/data1/ORCL2/datafile/o1_mf_sysaux_03t1t9d3_.dbf

channel ORA_DISK_1: restore complete, elapsed time: 00:00:15

channel ORA_DISK_1: starting datafile backup set restore

channel ORA_DISK_1: using network backup set from service primary_db

channel ORA_DISK_1: specifying datafile(s) to restore from backup set

channel ORA_DISK_1: restoring datafile 00004 to /data/data1/ORCL2/datafile/o1_mf_undotbs1_04t1t9di_.dbf

channel ORA_DISK_1: restore complete, elapsed time: 00:00:02

channel ORA_DISK_1: starting datafile backup set restore

channel ORA_DISK_1: using network backup set from service primary_db

channel ORA_DISK_1: specifying datafile(s) to restore from backup set

channel ORA_DISK_1: restoring datafile 00006 to /data/data1/ORCL2/datafile/o1_mf_users_05t1t9dm_.dbf

channel ORA_DISK_1: restore complete, elapsed time: 00:00:15

Finished restore at 2018-05-03 17:01:34

當然要記得去起庫並開啟實時日誌應用進程!


在12.2中,Oracle提供了一種更方便的方式去進行恢復主庫會將未記錄的塊的列表發送至備庫,並記錄在備庫控制文件中,我們可以從備庫的v$nonlogged_block這個視圖查看到相關信息。不需要發送主庫的整個數據文件,而是在RMAN執行一個簡單的命令來恢復它們:

RECOVER DATABASE NONLOGGED BLOCK

停止備庫實時日誌應用

SQL> alter database recover managed standby database cancel;

備庫登陸RMAN執行

RECOVER DATABASE NONLOGGED BLOCK

注意:執行此步驟前請確認主備庫的log_archive_config參數已經設置

RMAN> recover database nonlogged block;

Starting recover at 2018-05-03 14:54:22

using target database control file instead of recovery catalog

allocated channel: ORA_DISK_1

channel ORA_DISK_1: SID=56 device type=DISK

starting recovery of nonlogged blocks

List of Datafiles

=================

File Status Nonlogged Blocks Blocks Examined Blocks Skipped

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

1 OK 0 0 107519

3 OK 0 0 262399

4 OK 0 0 149759

5 OK 0 0 31999

6 OK 0 0 42239

7 OK 0 16707 21532

8 OK 0 0 12799

9 OK 0 0 76799

18 OK 0 0 33279

19 OK 0 0 57599

20 OK 0 0 24959

21 OK 0 0 33279

22 OK 0 0 51199

23 OK 0 0 12799

29 OK 0 0 1310719

30 OK 0 0 12799

31 OK 0 0 33279

32 OK 0 0 52479

33 OK 0 0 923519

34 OK 0 16822 8777

35 OK 0 0 12799

37 OK 0 0 24959

Details of nonlogged blocks can be queried from v$nonlogged_block view

recovery of nonlogged blocks complete, elapsed time: 00:00:08

Finished recover at 2018-05-03 14:54:32

最後別忘了開啟實時日誌應用進程。

綜上來看,12.2中這個特性在數據倉庫等一些場景是可以嘗試的。以往我們開啟force logging造成大量的redo日誌並且影響一部分dml語句的執行效率。在12.2我們可以嘗試使用nonlogging操作去節省大量數據插入的時間,然後在系統空閑時間進行備庫恢復操作。但是注意這種操作也存在弊端,這樣你的備庫的可用性就大大降低了。

注意:本文內容太多,公眾號有字數限制,全文可點擊文末的閱讀原文,謝謝大家的理解。Oracle培訓和認證記得找小麥苗喲。


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 小麥苗資料庫 的精彩文章:

如何在 oracle 集群環境下修改私網信息

TAG:小麥苗資料庫 |