处理 Oracle 块损坏 (文档 ID 1526911.1) |
|
适用于: Oracle Database - Enterprise Edition - 版本 7.0.16.0 到 11.2.0.2.0 [发行版 7.0 到 11.2] 处理 Oracle7/8/8i/9i/10g/11g/12c 中的 Oracle 块损坏 由于 NOLOGGING 或 UNRECOVERABLE 操作导致的坏块 Options for various Segment Types: CACHE CLUSTER INDEX PARTITION INDEX LOBINDEX LOBSEGMENT ROLLBACK TABLE PARTITION TABLE TEMPORARY IOT(索引组织表) TYPE2 UNDO 其他一些段类型 No Segment 块级恢复 , 数据文件恢复 , 数据库恢复 , 本文章讨论如何处理 Oracle 数据文件中的一个或多个坏块,并介绍了处理这些坏块的主要方法。在采取任何措施之前,请先阅读完整篇文章。 注意: 如果在启动时出现 ORA-1578 问题,请与当地支持中心联系,以获得参考建议。 本文章介绍了许多类型的错误,很多其他地方也可能引用到本文章。重要的是,您需要知道关于每个坏块的以下信息: · 包含坏块的文件的绝对文件编号 (FILE NUMBER)。 · 包含坏块的文件的名称。 SELECT name FROM v$datafile WHERE file#=&AFN; 如果文件号未显示在 Oracle8i 的 V$DATAFILE 中,且 &AFN 大于 DB_FILES 参数值,则该文件可能是临时文件。在这种情况下,可以使用以下查询找到文件名: SELECT name FROM v$tempfile WHERE file#=(&AFN - &DB_FILES_value); · 文件中坏块的块编号。 · 包含受影响块的表空间编号和名称。 SELECT ts# "TSN" FROM v$datafile WHERE file#=&AFN; · 表空间中的坏块大小。 SELECT block_size FROM dba_tablespaces 对于 Oracle 7、8.0 和 8.1,数据库中所有表空间使用相同的块大小。 例如:对于 ORA-1578 错误: ORA-01578: ORACLE data block corrupted (file # 7, block # 12698) &AFN 为 "22" (从错误 ORA-1110 部分获得) 对于其他错误(ORA-600、ORA-1498 等),上述值应由 Oracle Support 提供给您,或从涵盖相关错误的文章中获取。 有多种原因可能导致坏块,包括: o
产生 Oracle 错误的时间点可能要比最初发生任何块损坏的时间点晚得多。 在遇到坏块时,我们通常无从了解根本原因,并且在大多数情况下,当下最迫切的需求是重新启动数据库并使其运行起来,正因如此,本文将介绍用于解决坏块问题的步骤,如下所列: 1. 确定坏块问题的范围,并确定这些问题是持久性问题还是暂时性问题。 如果问题涉及范围很大,或错误不稳定,则关键在于先识别原因(检查硬件等)。这点很重要,因为如果是底层硬件出现错误,恢复系统便毫无意义。
2. 更换或拆下任何有问题的或可疑的硬件。 3. 确定哪些数据库对象受到影响。 4. 选择最合适的数据库恢复/数据抢救选项。 对于上述所有步骤,最好应收集证据并详细记录所采取的措施。本文中的“证据>>”标签列出了应收集的信息,以帮助您识别问题的根本原因。 由于 NOLOGGING 或 UNRECOVERABLE 操作导致的坏块 如果对某个对象执行了 NOLOGGING(或 UNRECOVERABLE)操作,随后又恢复了包含该对象的数据文件,则受到 NOLOGGING 操作影响的数据块将被标记为“坏块”,当您访问该数据块时将显示 ORA-1578 错误。
请参考Note 836658.1查找坏块的范围。使用 RMAN或者DBVERIFY 扫描受影响的文件(以及一切重要的文件)也是不错的办法,这样可以检查是否有其他坏块,从而确定问题的范围。有关使用 DBVERIFY 的详细信息,请参阅 Note:35512.1 每次发生坏块错误时,都应记下完整的错误消息,并查看该实例的告警日志和跟踪文件,以了解任何相关的错误。首先进行这些步骤非常重要,这可以评估该损坏是单个块,还是由于 UNRECOVERABLE 操作产生的错误,抑或是更严重的问题。 一旦确定了损坏的文件/块组合列表,即可使用以下步骤来帮助确定应采取何种措施。 证据: · 完整记录初始错误,以及发生错误的应用程序的详细信息。 · 及时地保存从告警日志中首次 (FIRST) 记录到问题前数小时到当前时间点所提取的内容。 · 保存告警日志中提到的任何跟踪文件。 · 记录最近遇到的任何 OS 问题。 · 记录是否正在使用任何特殊功能,例如:ASYNC IO、快速写入磁盘选项等。 · 记录当前的备份位置(日期、类型等) · 记录数据库是否处于 ARCHIVELOG 模式, 大多数坏块问题是由故障硬件导致的。 您可以使用以下步骤移动数据文件: ·
重要信息: 如果存在多个错误(不是由于 NOLOGGING操作导致的) 如果使用了任何特殊 IO 选项,例如 direct IO、async IO 或类似的选项,最好将其禁用,以消除这些选项成为潜在问题原因的可能性。 在决定如何恢复之前,最好先确定哪些对象受到了影响,因为坏块可能发生在那些容易被重新创建的对象中。 对于每个坏块,请收集下表中的信息。
下列说明将有助于您针对每个坏块填写此表。
SELECT tablespace_name, file_id "AFN", relative_fno "RFN" FROM dba_data_files;[Insert code here. Use 'Paste from Word' to retain layout.] 在 Oracle8i/9i/10g 中: SELECT tablespace_name, file_id+value "AFN", relative_fno "RFN" FROM dba_temp_files, v$parameter WHERE name='db_files'; 在 Oracle7 中: “绝对文件号”和“相关文件号”使用相同的文件号
SELECT * FROM dba_extents
SELECT owner, segment_name, segment_type, partition_name 相关对象和能够使用的恢复选项取决于 SEGMENT_TYPE。对于各种最常见的段类型,其他查询和可能的恢复选项如下所列。 IOT 如果段类型为 CACHE,请再次检查您是否输入了正确的 SQL语句和参数。 如果段类型为 CLUSTER,则应确定它包含哪些表。 例如: SELECT owner, table_name fROM dba_tables WHERE owner='&OWNER' AND cluster_name='&SEGMENT_NAME'; 解决方法:
如果段类型为 INDEX PARTITION,请记录名称和所有者,然后确定哪些分区受到影响: SELECT partition_name 解决方法: 或者 {Continue} {Back to Segment List} 确定索引位于哪个表中: SELECT table_owner, table_name CONSTRAINT_TYPE 的可能值包括: SELECT owner, constraint_name, constraint_type, table_name 解决方法: 如果段类型为 ROLLBACK,请联系 Oracle Support,因为 ROLLBACK 段坏块需要特殊处理。 解决方法: {Continue} {Back to Segment List} TYPE2 UNDO 是系统管理的 undo 段,它是 rollback 段的一种特殊形式。这些段的坏块需要特殊处理。 解决方法: 如果段类型为 TABLE PARTITION,请记录名称和所有者,然后确定哪些分区受到影响: SELECT partition_name 然后按照处理 TABLE 段的步骤继续下面的操作。 解决方法: 或者 {Continue} {Back to Segment List} 如果所有者为“SYS”,则联系 Oracle Support 并上传所有详细信息。 对于非字典 TABLE 或 TABLE PARTITION,确定表中存在哪些索引: 例如: SELECT owner, index_name, index_type 并确定表中是否存在任何主键: 例如:SELECT owner, constraint_name, constraint_type, table_name 如果存在主键,则确认它是否被任何外键约束引用: 例如: 解决方法: 或者 如果所有者为“SYS”,则联系 Oracle Support 并上传所有详细信息。 IOT 表中的坏块应按照表或分区表中的处理方式来处理。 或者 如果所有者为“SYS”,则联系 Oracle Support 并上传所有详细信息。 {Continue} {Back to Segment List} 确定 LOB 属于哪个表: SELECT table_name, column_name 不可以重建 LOB 索引,因此您必须将该问题作为受影响的表中 LOB 列上的坏块来处理。 或者 移动LOG 段 alter table &table_owner.&table_with_lob move LOB (&&lob_column) store as (tablespace &tablespace_name); 如果所有者为“SYS”,则联系 Oracle Support 并上传所有详细信息。 确定 LOB 属于哪个表: 例如: 对于非字典表 ... 使用 ”TABLE“ 部分中的 SQL 语句获取包含坏块的 LOB 数据的表的索引和约束信息,然后返回此处查找具体受影响的行的详细信息。 要查找引用损坏的 LOB 块的具体行可能比较困难,因为报告的错误中不会显示表中的哪一行数据包含损坏的 LOB 数据。 Typically one can refer to application logs or any SQL_TRACE or 10046 trace of a session hitting the error (if available) or see if having event "1578 trace name errorstack level 3" set in the session helps identify the current SQL/binds/row. 例如: 然后等待应用程序触发该错误,并查找跟踪文件。 如果没有任何线索,您可以构建 PLSQL 块,逐行扫描问题表以提取 LOB 列数据,扫描将一直循环进行,直至发生错误。此方法可能需要一段时间,但它应该可以找到引用了损坏的 LOB 块的数据行的主键或 ROWID。 例如: another script more generic: set serverout on 解决方法: 对于非字典表,可能的选项包括: 恢复 或者用empty_clob/empty_blob更新lob列,避免在出现ORA-1578;这样可以清理表里面的lob列: SQL> set concat off 将损坏的lob设置为empty lob后,之前的数据块还会放回这个lob的freelist。这些空间以后可能会被重用, alter table &table_owner.&table_with_lob move LOB (&&lob_column) store as (tablespace &tablespace_name); 或 抢救表(及其 LOB 列)中的数据
{Continue} {Back to Segment List} 如果段类型为 TEMPORARY,则坏块不会影响永久对象。检查发生问题的表空间是否正在被用作 TEMPORARY 表空间: SELECT count(*) FROM dba_users WHERE temporary_tablespace='&TABLESPACE_NAME'; 解决方法: 通常情况下,不需要进行任何还原,但如果磁盘可能有问题,且表空间包含有用数据,则最好对数据库中受影响的文件进行恢复。
{Continue} {Back to Segment List} 如果返回的段类型未包含在上述类型中,则请联系 Oracle Support 并提供迄今为止收集的所有信息,以获得相关建议。
{Continue} {Back to Segment List} 如果没有包含坏块的 extent,则首先再次检查查询中使用的参数。如果您确定文件号和块编号是正确的,且不属于 DBA_EXTENTS 中的某个对象,则执行以下操作:
选项: 未使用的 Oracle 块上的错误可以忽略,因为如果需要使用该块,Oracle 会创建新的块映像(格式化),因此,该块上的任何问题将永不会被读取。 如果您怀疑该块可能是空间管理块,则可以使用 DBMS_SPACE_ADMIN 包来帮助您进行检查: exec DBMS_SPACE_ADMIN.TABLESPACE_VERIFY('&TABLESPACE_NAME'); 以上命令会将不一致写入跟踪文件,但如果遇到致命的坏块,它将报告如下错误: ORA-03216: Tablespace/Segment Verification cannot proceed
{Continue} {Back to Segment List} 对于每个坏块,如果需要尝试并确定实际坏块原因,则收集如下物理证据也是一个比较好的方法:
dd if=&FILENAME bs=&TS_BLOCK_SIZE skip=&BL-1 count=3 of=BL.dd dd if=ts11.dbf bs=4k skip=1223 count=3 of=1223_1225.dd DUMP/BLOCKS=(start:XXXX,end:YYYY)/out=dump.out &FILENAME
ALTER SYSTEM DUMP DATAFILE '&FILENAME' BLOCK &BL; (DUMP将生成到 USER_DUMP_DEST 下的跟踪文件)。
{Continue} {Back to Segment List} 现在,最佳的恢复选项取决于受影响的对象。前面第 (3) 部分中的说明应该已经重点介绍了针对每个受影响对象的主要可用选项。选择的实际恢复方法可能包含以下一种或多种混合方法: 是否需要进行任何恢复操作? 表空间中,或位于不再属于任何数据库对象的块中,则无需进行任何操作,尽管将问题表空间重定位到其他存储设备中可能较为明智。 请参阅警告 可以使用完全恢复吗? 要选用完全恢复,必须满足如下条件:
(“ARCHIVE LOG LIST”命令显示 Archivelog 模式)
如果满足上述条件,完全恢复通常是首选方法 *但请注意*
如果执行数据库恢复后坏块仍然存在,则表示所有备份都包含坏块,底层错误仍存在,或问题通过 redo 重现。在这些情况下,需要选择其他一些恢复选项。 请参阅 "(4A) 完全恢复" ,以了解完全恢复步骤。 如果不需要从对象本身提取任何数据,能否删除或重新创建该对象? 您可以删除对象或从脚本/最近导出的副本重新创建对象。一旦删除一个对象后,该对象中的块将被标记为“空闲”,并且该块在被分配到新对象时将被重新格式化。明智的做法是,对表进行重命名,而不是删除,除非您完全确定不再需要其中的数据。 对于表分区,只需要删除受影响的分区。 例如: ALTER TABLE ... DROP PARTITION ... 如果坏块影响到分区段头,或者包含分区头的文件处于离线状态,则 DROP PARTITION 可能会失败。在这种情况下,首先将其更换为具有相同定义的表,之后仍然可以删除该分区。 例如: ALTER TABLE .. EXCHANGE PARTITION .. WITH TABLE ..; 最常见的可重建对象为索引。始终在处理表中的索引问题之前处理表坏块。 对于任何段,如果您拥有坏块的绝对文件号和块号,则可使用以下快速提取对象 DDL 的方法: set long 64000 是否需要在重新创建对象之前抢救数据? 如果问题位于定期更新的关键应用表上,则可能需要尽可能多地抢救表中数据,然后重新创建该表。 有关详细信息,请参阅"(5C) 抢救表中数据" 。 当前忽略坏块是否可取? 在某些情况下,最直接的选项可能就是忽略坏块,并阻止应用程序对它进行访问。 有关详细信息,请参阅 "(5D) 忽略坏块"。 最后的选项 下列选项是否可行? 将数据库或表空间恢复到较早的时间点(通过时间点恢复) 或还原出现坏块前的冷备份 或使用现有导出文件 有关详细信息,请参阅"(5E) 最后的选项"。 如果数据库处于 ARCHIVELOG 模式下,且您拥有受影响文件的完好备份,则恢复通常为首选方法。 如果使用的是 Oracle9i(或更高版本),则可以使用 RMAN BLOCKRECOVER 命令执行块级恢复。 如果使用的是 Oracle 11g(或更高版本),则可以使用“Data Recovery Advisor(数据恢复指导)”. 自 Oracle9i 版本起,RMAN 允许恢复单个块,同时数据库的其他部分(包括数据文件中的其他块)仍可以进行正常访问。请注意,块级恢复只能将块完全恢复到当前时间点。 例如: 实际情况是,文件 6 的块 30 上发生 ORA-1578 错误,可能是由于介质问题导致的坏块,且您拥有该文件的完好冷备份映像,并已还原到“.../RESTORE/filename.dbf”。 rman nocatalog 此操作将使用注册的数据文件备份映像和任何需要的归档日志来执行块恢复,仅将有问题的块恢复到当前时间点。 有关 RMAN BLOCKRECOVER 命令和限制的所有详细信息,请参阅文档 Note 144911.1。 数据文件恢复包括下列步骤。如果有多个文件,则针对每个文件重复执行这些步骤,或参阅下面的“数据库恢复”。当数据库处于 OPEN 或 MOUNTED 状态时,均可使用这些步骤。 使受影响的数据文件离线 例如: ALTER DATABASE DATAFILE 'name_of_file' OFFLINE; 将文件复制到安全位置(以防备份损坏) 将文件的最新备份还原到完好的磁盘上 使用 DBVERIFY 检查还原的文件是否有坏块 假设还原的文件完好,则将数据文件重命名并保存到新位置(如果不是原来的位置) 例如: ALTER DATABASE RENAME FILE 'old_name' TO 'new_name'; 恢复数据文件 例如: RECOVER DATAFILE 'name_of_file'; 使数据文件上线 例如: ALTER DATABASE DATAFILE 'name_of_file' ONLINE; 数据库恢复通常包含以下步骤: 关闭数据库(使用选项 immediate 或 abort) 将待恢复的所有文件的当前副本复制到安全位置 将备份文件还原到完好的磁盘上 使用 DBVERIFY 检查还原的文件。有关使用 DBVERIFY 的详细信息,请参阅 Note:35512.1 启动数据库到MOUNT状态(startup mount) 对任何需要重新定位的数据文件进行重命名 例如: ALTER DATABASE RENAME FILE 'old_name' TO 'new_name'; 确保所有必需的文件在线 例如: ALTER DATABASE DATAFILE 'name_of_file' ONLINE; 恢复数据库 例如: RECOVER DATABASE 打开数据库 例如: ALTER DATABASE OPEN; 一旦执行了完全恢复,最好在允许使用之前先检查数据库: 针对每个问题对象运行: "ANALYZE VALIDATE STRUCTURE CASCADE" 检查表/索引是否存在不匹配。 如果有任何 undo 操作曾被放弃,此命令可能会显示不匹配,此时需要重建索引。 在应用程序级别检查表中数据的逻辑完整性。 损坏对象为用户索引时,如果底层表没有损坏,则可以删除并重建该索引。 如果收集的信息表示索引有从属外键约束,则需要执行以下操作:
ALTER TABLEDISABLE CONSTRAINT ;
ALTER TABLE DISABLE CONSTRAINT ;DROP INDEX ; CREATE INDEX .. with appropriate storage clause ALTER TABLE ENABLE CONSTRAINT ;
ALTER TABLE ENABLE CONSTRAINT ; 对于索引分区,可以执行以下命令: ALTER INDEX ... REBUILD PARTITION ...; 注意:
"ALTER INDEX ... REBUILD ONLINE" and "ALTER INDEX ... REBUILD PARTITION ..."
如果损坏的对象为 TABLE 或 CLUSTER 或 LOBSEGMENT,则您必须明白,坏块内的数据已经丢失。 重要信息: 从包含坏块的表中提取数据有多种方法。选择最恰当的方法,详细信息如下所述。这些方法的目的是从可访问的表块中提取尽可能多的数据。通常,将损坏的表重命名是一个比较好的方法,这样就可以使用正确的名称创建新对象。 例如: RENAME TO ;
- 使用 DBMS_REPAIR.ADMIN_TABLES 创建管理表
在 LOB 段上不可以使用 DBMS_REPAIR。 如果坏块 LOB 块未被表中的任何行引用,则应该可以使用 CREATE TABLE as SELECT (CTAS) 来按选择创建表,或按原样导出/删除/导入该表。 如果坏块 LOB 块被某个行引用,则应该可以使用不包括问题行的 WHERE 谓词进行选择或导出。 警告: 由于坏块本身已经“损坏”,则从该块中提取的任何数据都应被视为可疑数据。从坏块本身获取数据行的主要方法包括:
出错时可以忽略坏块并接受报告的错误,或在应用程序级别阻止对出问题的块行进行访问。 例如:如果问题块/行位于子表中,则可以在应用程序级别阻止对父表中对应行的访问,从而子行就永不会被访问。(但要注意级联类约束) 这样做可能不利于批量访问数据的报告和其他任务,因此,为了阻止块在被访问时报错,前面 4C 中所述的 DBMS_REPAIR 选项也不失为一个可取的方法。使用这种方法标记并跳过坏块提供了一种短期的解决方案,从而在计划停机时可以尝试进行完全数据抢救和/或恢复,或留出更多时 间在第二个(克隆)数据库上尝试其他恢复选项。但请注意,使用 DBMS_REPAIR.FIX_CORRUPT_BLOCKS 标记块坏块将导致标记的块在恢复后还是“坏块”。 忽略坏块对于快速老化且即将被清除的数据而言是比较好的选择(例如,在按日期分区的表中,较老的分区将在某时间点被删除)。 在应用程序级别,可以忽略损坏的 LOB 列,直到可以重新构建该表。 确保不出现上述“警告”中的情形的一种方法是,确保应用程序只能通过表上的包含WHERE 谓词的视图来访分表中的数据。 ALTER TABLE MYTAB ADD ( BAD VARCHAR2(1) ); 对任何问题行设置 BAD='Y' 如果只通过 MYVIEW 访问 MYTAB,该行将永不可见,因此也无法更新,从而实现了坏块条目隔离,直到问题解决。 很明显,此示例更多的是一个设计时解决方案,但某些应用程序可能已有类似机制,且可能只通过某个视图(或通过 RLS 策略)访问数据,从而提供某些选项来隐藏问题行。 虽然可以忽略坏块,但需要注意的是,坏块在运行 DBVERIFY、RMAN 备份时仍然会以警告/错误等形式出现。 请务必仔细记录您将在这些工具中看到的任何坏块,尤其是您期望在使用 RMAN 时跳过的任何块(例如,设置了 MAX_CORRUPT),并确保在清除坏块后移除任何对错误的“接受”选项。 例如:假设坏块已处理为忽略坏块,并在应用程序级别跳过问题行。 此外,还有重要的一点需要注意,忽略 table 段中的坏块可能导致查询返回不一致的结果。 请注意,如果忽略坏块但使用 DBMS_REPAIR.FIX_CORRUPT_BLOCKS 标记,系统会向坏块中写入 redo 信息,这可能会限制后续的恢复选项。 如果你有 standby 环境(物理或逻辑),请首先对其进行检查。 DBVERIFY 通常可用于检查还原的文件是否存在坏块。
本部分列出了一些可用于进行恢复操作的最终选项。
最后的机会: 请注意,如果您丢失了数据文件的所有副本,但仍具有自文件创建以来的全部归档日志,则仍有可能恢复该文件。 例如: 如果您遇到这种情况,请在继续下面的操作之前先尝试使用这些步骤来恢复数据文件。 如果您到达这一步,就说明没有其他办法可以将文件恢复到当前时间点。此时最好关闭实例,并对当前数据库进行备份,以便在选用的措施失败后仍然能够回退到当前时间点。(例如:如果发现备份坏块)。 可用的一些选项概述如下: 恢复到早期的冷备份 从冷备份建立克隆数据库,并提取(导出)问题表,或传输问题表空间。 使用基于时间点的恢复将数据库恢复到一致的时间点
表空间基于时间点的恢复 从逻辑导出/副本重新创建数据库 如果已具有完好备份,使用 DB_BLOCK_CHECKING=TRUE 进行前滚将有助于找到首次出错的时间点。在调查恢复选项时,通常不需要关闭问题数据库。 例如:可以只将系统表空间和问题表空间数据文件还原到完全不同的位置和/或机器,作为不同的实例,以便于调查可以前滚到多久以前的时间点等。
---转自 MOS ID 1526911.1 |
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/29785807/viewspace-2122964/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/29785807/viewspace-2122964/