【DB筆試面試434】ORA-01578和ORA-26040塊錯誤的原因有哪些?
- 2019 年 10 月 11 日
- 筆記
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 <file number>, bno <block number>)"
"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版本變化:
RDBMS版本 |
變化 |
---|---|
10.2.0.4+ |
DBverify報告NOLOGGING block錯誤資訊 "DBV-00201: Block, DBA <rdba>, marked corrupt for invalid redo application" |
10.2.0.5, 10.2.0.1+ |
RMAN validate命令檢查NOLOGGING block,在v$database_block_coruption視圖中記錄corruption_type='NOLOGGING' |
11g+ |
引入db_unrecoverable_scn_tracking參數 |
11.1.0.6 or 11.1.0.7 or 11.2.0.1 |
NOARCHIVELOG模式資料庫,對NOLOGGING對象執行了DIRECT PATH操作,並且以後手動恢復資料庫,即使打開了FORCE LOGGING,也會報ORA-1578 和 ORA-26040。這個約束在11.2.0.2以上版本取消,這個問題在10g不會發生。 |
12c |
RMAN validate的結果不在視圖v$database_block_corruption中,而是在視圖v$nonlogged_block |
12.2 |
以下RMAN命令被引入:RMAN> validate [database / datafile] nonlogged block;RMAN> recover [database / datafile] nonlogged block; -> 對於 Standby 資料庫 |
(六)解決方法
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。
About Me:小麥苗
● 本文作者:小麥苗,只專註於資料庫的技術,更注重技術的運用
● 作者部落格地址:http://blog.itpub.net/26736162/abstract/1/
● 本系列題目來源於作者的學習筆記,部分整理自網路,若有侵權或不當之處還請諒解
● 版權所有,歡迎分享本文,轉載請保留出處
● 題目解答若有不當之處,還望各位朋友批評指正,共同進步