ORACLE|一次ORA-01578 NOLOGGING 坏块的处理

问题: 某系统的ORACLE数据库从Windows迁移到LINUX环境后,又搭建了DATAGUARD备机,以及设置了正常的RMAN备份策略。正常运行几天后,业务人员反馈程序使用时报错,截图中是ORA-01578错误,第一反应好可怕,但是想到有RMAN备份及DG备机,也不太担心。
ORACLE|一次ORA-01578 NOLOGGING 坏块的处理
文章图片

问题排查: 接入系统进行检查,对于坏块的检查,使用RMAN的会快一点,可以适当加并行,对于检查出的坏块,通过视图v d a t a b a s e b l o c k c o r r u p t i o n 以 及 R M A N 检 查 后 的 文 本 输 出 , 可 以 比 较 清 楚 的 知 道 坏 块 类 型 。 然 后 可 以 基 于 坏 块 的 类 型 , 来 决 定 采 用 什 么 方 法 进 行 坏 块 修 复 。 比 较 幸 运 的 是 本 次 遇 到 的 坏 块 类 型 是 N O L O G G I N G ( v database_block_corruption以及RMAN检查后的文本输出,可以比较清楚的知道坏块类型。然后可以基于坏块的类型,来决定采用什么方法进行坏块修复。比较幸运的是本次遇到的坏块类型是NOLOGGING(v databaseb?lockc?orruption以及RMAN检查后的文本输出,可以比较清楚的知道坏块类型。然后可以基于坏块的类型,来决定采用什么方法进行坏块修复。比较幸运的是本次遇到的坏块类型是NOLOGGING(vdatabase_block_corruption视图的CORRUPTION_TYPE列),基本分布在索引列及空块上,不涉及表的数据块,推测是当时进行创建索引时使用了NOLOGGING参数;不幸的是检查发现有多个数据文件好几百个数据块都被标记为此类坏块,后续在处理时也确实耗费了比较多的时间来处理。
处理方法: 本次的坏块分布在索引段及空块上,总体上使用重建索引(创建在其它表空间)以及创建测试表填充测试数据来重用空块(重用时会进行数据块格式化)两种办法,经过一翻折腾,全部坏块处理完毕。
参考资料:
针对普通坏块问题(非SYSTEM/UNDO等会导致数据库无法OPEN的),可以参考如下MOS文档:
如何格式化不属于任何段的损坏块 (文档 ID 1526163.1)
ORA-1578 / ORA-26040 - NOLOGGING 操作引起的坏块 - 错误解释和解决方案 (文档 ID 1623284.1)
ORA-1578 ORA-26040 in a LOB segment - Script to solve the errors (文档 ID 293515.1)
处理 Oracle7/8/8i/9i/10g/11g 中的 Oracle 块损坏 (文档 ID 1526911.1)

关于NOLOGGING导致的坏块,文档(文档 ID 1623284.1)上的说明比较清楚,一并放出,如下:
描述:
如果数据段定义为 NOLOGGING 属性,当 NOLOGGING/UNRECOVERABLE 操作修改该数据段时,联机重做日志只记录很少的日志信息,如果之后执行 RECOVERY 操作的话,会导致这些块无效。如果这些联机重做日志/归档日志被用来恢复数据文件,那么 Oracle 会将对应的数据块标志为无效,而且下一次访问这些数据块时,会报 ORA-1578 和 ORA-26040错误。NOLOGGING 导致的坏块不会导致 RMAN 备份失败,一般来说 soft corrupt block 不会导致 RMAN 备份失败,因此不需要设置 MAXCORRUPT。在这样的情况下,数据库备份中就会含有 soft corrupt block,如果使用这些备份恢复数据,那么恢复的数据也含有 soft corrupt block。除 ORA-26040 错误之外,当还有一些其他通用信息出现时,block dump 可 能会被产生,如果数据块的 block dump 内有 byte 0xff 信息或者属于某个段,那么尝试执行 SQL语句查询该数据块/段时,这个问题应该会重现。
解决方法
NOLOGGING 操作引起的坏块是不能修复的,比如"Media Recovery" 或 "RMAN blockrecover"都无法修复这种坏块。可行的方法是在 NOLOGGING 操作之后立刻备份对应的数据文件。对于除了索引以外的其他类型的段,为了修复这个问题,可以通过导出文件(exp/expdp)或者其他数据源来进行恢复。如果没有备份,可以采用下面的方法重建对象:参考 Note 819533.1 和 Note 472231.1找到坏块所在的对象:
如果NOLOGGING数据块位于空闲数据块(dba_free_space视图可以查询到),DBVerify检查会发现这个问题,报错DBV-00201
或者在v$database_block_corruption视图中显示.对于这种情况,我们可以等待到这个数据块被重用时,会自动格式化,或者
手动强制格式化,参考Doc ID 336133.1
如果是索引,重新创建(drop/create)索引。
如果是表,使用 procedure DBMS_REPAIR.SKIP_CORRUPT_BLOCKS 跳过坏块,请参考 Note 556733.1 获取包 DBMS_REPAIR 的使用示例。然后考虑是否重建表:
移动table: alter table &table_name move;
或者
保存数据 (export, Create Table as Select, etc) 然后truncate 或 drop/create.
如果是表中的 LOB 列对应的 LOB 段,移动LOB或请参考 Note 293515.1。
alter table &table_owner.&table_with_lob move LOB (&&lob_column) store as (tablespace &tablespace_name);
如果错误出现在物理 STANDBY 数据库, 从主库恢复被影响的数据文件 (只有当主库没有这个问题的情况下)。避免这种问题产生的方法是在主库运行。
alter database force logging;
如果问题是执行RMAN DUPLICATE 或 RESTORE之后 ,那么在源库打开FORCE LOGGING,然后再重新运行RMAN DUPLICATE 或 RESTORE
【ORACLE|一次ORA-01578 NOLOGGING 坏块的处理】处理过程用到的语句及相关LOG如下:
在这里插入代码片 1.检查坏块命令: backup validate check logical database; backup validate check logical datafile 43; select blocks from v$database_block_corruption; RMAN> backup validate check logical datafile 17; Starting backup at 20-NOV-19 using channel ORA_DISK_1 ………… channel ORA_DISK_1: backup set complete, elapsed time: 00:00:55 List of Datafiles ================= File Status Marked Corrupt Empty Blocks Blocks Examined High SCN ---- ------ -------------- ------------ --------------- ---------- 17OK227321941933122898612069 File Name: /oradata/orcl/ZHINDEX.DBF Block Type Blocks Failing Blocks Processed ---------- -------------- ---------------- Data021050 Index04138310 Other030733Finished backup at 20-NOV-19 SQL> select * from v$database_block_corruption; FILE#BLOCK#BLOCKS CORRUPTION_CHANGE# CORRUPTIO ---------- ---------- ---------- ------------------ --------- 393613957352881274711 NOLOGGING 39361399372881274784 NOLOGGING ……………………………… 491073873152881275182 NOLOGGING 491073889312881275189 NOLOGGING36 rows selected.######## 2.检查坏块位于哪个OBJECT上,没有OBJECT则是空块 SQL> select object_name,owner,object_id,to_char(CREATED,'yyyymmdd hh24:mi:ss') from dba_objects where object_name in(select segment_name from dba_extents where file_id = 39 and 3614041 between block_id and block_id + blocks -1); 2OBJECT_NAMEOWNEROBJECT_ID TO_CHAR(CREATED,' ------------------------------ ------------------------------ ---------- ----------------- ??????_IX_??IDZLCHS441947 20191105 16:29:01SQL> SQL> select object_name,owner,object_id,to_char(CREATED,'yyyymmdd hh24:mi:ss'),to_char(LAST_DDL_TIME,'yyyymmdd hh24:mi:ss') from dba_objects where object_name in(select segment_name from dba_extents where file_id = 39 and 3614041 between block_id and block_id + blocks -1); 2 OBJECT_NAMEOWNEROBJECT_ID TO_CHAR(CREATED,' TO_CHAR(LAST_DDL_ ------------------------------ ------------------------------ ---------- ----------------- ----------------- ??????_IX_??IDZLCHS441947 20191105 16:29:01 20191105 16:29:01######## 3.创建测试表来重用空块 SQL> create table s(n number,c varchar2(4000)) tablespace ZHINDEX; Table created.SQL> select segment_name,tablespace_name from user_segments where segment_name='S' ; 2 SEGMENT_NAMETABLESPACE_NAME --------------------------------------------------------------------------------- -------------------- SZHINDEXSQL> BEGIN 2for i in 1..1000 loop 3EXECUTE IMMEDIATE 'alter table s allocate extent (DATAFILE '||'''/oradata/orcl/ZHINDEX04.DBF''' ||'SIZE 64K) '; end loop; end ; / 456 PL/SQL procedure successfully completed.######## 4.重建索引 可以删除后重建。使用REDUILD时注意不要使用“ALTER INDEX ..REBUILD”命令重建损坏的非分区索引,这一点非常重要,因为此操作通常会尝试从包含坏块的现有索引段中构建新索引。 "ALTER INDEX ... REBUILD ONLINE" and "ALTER INDEX ... REBUILD PARTITION ..." 不会从旧索引段中构建新索引,因此可以使用。######## 5.相关alert日志: Tue Nov 12 16:59:08 2019 LNS: Standby redo logfile selected for thread 1 sequence 1395 for destination LOG_ARCHIVE_DEST_2 Tue Nov 12 17:05:21 2019 Errors in file /u01/app/oracle/diag/rdbms/orclpri/orcl/trace/orcl_ora_82018.trc(incident=120441): ORA-01578: ORACLE 脢媒戮脻驴茅脣冒禄碌 (脦脛录镁潞脜 39, 驴茅潞脜 3614023) ORA-01110: 脢媒戮脻脦脛录镁 39: '/oradata/orcl/ZHINDEX03.DBF' ORA-26040: 脢媒戮脻驴茅脢脟脢鹿脫脙 NOLOGGING 脩隆脧卯录脫脭脴碌脛 Incident details in: /u01/app/oracle/diag/rdbms/orclpri/orcl/incident/incdir_120441/orcl_ora_82018_i120441.trc Tue Nov 12 17:05:22 2019 Dumping diagnostic data in directory=[cdmp_20191112170522], requested by (instance=1, osid=82018), summary=[incident=120441]. Tue Nov 12 17:05:24 2019 Sweep [inc][120441]: completed Sweep [inc2][120441]: completed Tue Nov 12 17:05:30 2019 Starting background process ABMR Tue Nov 12 17:05:30 2019 ABMR started with pid=40, OS id=82411 Automatic block media recovery service is active. Automatic block media recovery requested for (file# 39, block# 3614023)

    推荐阅读