[翻译]-Detect And Repair Corruption in an Oracle Database

本文是对这篇文章Detect And Repair Corruption in an Oracle Database[1]的翻译,翻译如有不当的地方,敬请谅解,请尊重原创和翻译劳动成果,转载的时候请注明出处。谢谢!

Oracle数据库提供了多种方法检测和修复数据文件中的坏块。主要有下面一些方法:

  • RMAN (BACKUP VALIDATE, RESTORE VALIDATE, VALIDATE)
  • Multitenant : RMAN VALIDATE
  • DBVerify
  • ANALYZE .. VALIDATE STRUCTURE
  • DB_BLOCK_CHECKING
  • Block Media Recovery (BMR)
  • DBMS_REPAIR
  • Other Repair Methods

RMAN (BACKUP VALIDATE, RESTORE VALIDATE, VALIDATE)

Oracle Recovery Manager (RMAN) 可以使用 BACKUP VALIDATE命令检测验证数据库

RMAN> BACKUP VALIDATE DATABASE ARCHIVELOG ALL;

该过程输出的信息与备份期间看到的信息相同,但是不会创建备份。任何块损坏都会在V$DATABASE_BLOCK_CORRUPTION 视图以及 RMAN 输出信息中见到。

默认情况下,该命令仅检查物理损坏/坏块。添加CHECK LOGICAL选项可以包含对逻辑损坏的检查。

RMAN> BACKUP VALIDATE CHECK LOGICAL DATABASE ARCHIVELOG ALL;

RMAN可以使用RESTORE VALIDATE命令验证备份文件内容。

RMAN> RESTORE DATABASE VALIDATE;
RMAN> RESTORE ARCHIVELOG ALL VALIDATE;

与命令BACKUP VALIDATE类似,命令RESTORE VALIDATE模拟恢复过程,但实际上并不执行恢复。

在Oracle 11g之前,VALIDATE命令只能直接用于验证备份相关文件。在 Oracle 11g及更高版本中,该VALIDATE命令还可以验证数据文件、表空间或整个数据库,因此您可以使用它来代替BACKUP VALIDATE命令。

RMAN> VALIDATE DATAFILE 1;
RMAN> VALIDATE DATAFILE '/u01/app/oracle/oradata/ORCL/system01.dbf';

RMAN> VALIDATE CHECK LOGICAL DATAFILE 1;
RMAN> VALIDATE CHECK LOGICAL DATAFILE '/u01/app/oracle/oradata/ORCL/system01.dbf';

RMAN> VALIDATE TABLESPACE users;
RMAN> VALIDATE CHECK LOGICAL TABLESPACE users;

RMAN> VALIDATE DATABASE;
RMAN> VALIDATE CHECK LOGICAL DATABASE;

任何损坏的块都可以从V$DATABASE_BLOCK_CORRUPTION视图中找到。您可以使用类似这样的查询来识别包含损坏块的对象。

COLUMN owner FORMAT A20
COLUMN segment_name FORMAT A30

SELECT DISTINCT owner, segment_name
FROM   v$database_block_corruption dbc
       JOIN dba_extents e ON dbc.file# = e.file_id AND dbc.block# BETWEEN e.block_id and e.block_id+e.blocks-1
ORDER BY 1,2;

更多的语法例子可以从这个链接[2]查看

Multitenant : RMAN VALIDATE

主实例(main instance)的许多RMAN命令也可以用于可插拔数据库(PDB) 或根容器。例如,当连接到根容器时,您可以执行以下操作。

rman target=/

# Everything.
VALIDATE DATABASE;
VALIDATE CHECK LOGICAL DATABASE;

# Just the root container.
VALIDATE DATABASE ROOT;
VALIDATE CHECK LOGICAL DATABASE ROOT;

# Just the specified PDB, or comma-separated list.
VALIDATE PLUGGABLE DATABASE pdb1;
VALIDATE CHECK LOGICAL PLUGGABLE DATABASE pdb1;

如果您直接连接到 PDB,则可以使用下面命令。

rman target=sys/SysPassword1@pdb1

# Just the specified PDB.
VALIDATE DATABASE;
VALIDATE CHECK LOGICAL DATABASE;

DBVerify

DBVerify是一个外部应用程序,可用于验证离线和在线数据文件。除了离线数据文件外,它还可用于检查备份数据文件的有效性。

C:\>dbv file=C:\Oracle\oradata\TSH1\system01.dbf feedback=10000 blocksize=8192

这个工具通常不用于验证控制文件或重做日志,但在MOS Doc ID 1949795.1中有一个将其与控制文件一起使用的示例。

ANALYZE .. VALIDATE STRUCTURE

ANALYZE命令可用于验证所分析对象中的每个数据块。如果检测到任何损坏,则会将行添加到INVALID_ROWS表中。


-- Create the INVALID_ROWS table
SQL> @C:\Oracle\901\rdbms\admin\UTLVALID.SQL

-- Validate the table structure.
SQL> ANALYZE TABLE scott.emp VALIDATE STRUCTURE;

-- Validate the table structure along with all it's indexes.
SQL> ANALYZE TABLE scott.emp VALIDATE STRUCTURE CASCADE;

-- Validate the index structure.
SQL> ANALYZE INDEX scott.pk_emp VALIDATE STRUCTURE;

DB_BLOCK_CHECKING

当DB_BLOCK_CHECKING参数设置为[TRUE|HIGH]时,Oracle会遍历块中的数据以检查其是否自洽(self-consistent.)。不幸的是,块检查会给服务器增加1%到10%的开销。如果开销可以接受,Oracle 建议将此参数设置为[TRUE|HIGH]。

允许的值包括 [OFF|FALSE]、LOW、MEDIUM、[HIGH|TRUE]。请在此处阅读定义。

Block Media Recovery (BMR)

块介质恢复 (BMR) 允许在不影响整个数据文件的情况下恢复指定块。它仅用于已知且有限数量的块受到影响的情况。这可以缩短平均恢复时间 (MTTR) 并提高可用性,因为在操作期间只有受影响的块处于脱机状态。BMR只能通过 RMAN 使用命令执行BLOCKRECOVER。

块介质恢复是企业版的一项功能。

可以使用以下方法识别损坏的块:

  • 错误消息
  • alert日志
  • 跟踪文件
  • ANALYZE [TABLE | INDEX]命令
  • dbverify工具
  • VCOPY_CORRUPTION视图列出了备份中的损坏块,而不是数据库本身。
  • V$DATABASE_BLOCK_CORRUPTION列出了在各种 RMAN 操作期间检测到的数据库中损坏的块。恢复的块仍将列出,直到执行下一次备份为止。

一旦检测到损坏的块,可以单独恢复。或者可以使用CORRUPTION LIST选项恢复视图V$DATABASE_BLOCK_CORRUPTION中列出的所有块。可以使用 UNTIL 选项限制此列表

BLOCKRECOVER DATAFILE 3 BLOCK 121;
BLOCKRECOVER CORRUPTION LIST RESTORE UNTIL TIME 'SYSDATE - 7';

DBMS_REPAIR

与前面讨论的方法不同,DBMS_REPAIR 包允许您检测和修复损坏。该过程需要两个管理表来保存损坏块的列表以及指向这些块的索引键。这些创建如下。

BEGIN
  DBMS_REPAIR.admin_tables (
    table_name => 'REPAIR_TABLE',
    table_type => DBMS_REPAIR.repair_table,
    action     => DBMS_REPAIR.create_action,
    tablespace => 'USERS');

  DBMS_REPAIR.admin_tables (
    table_name => 'ORPHAN_KEY_TABLE',
    table_type => DBMS_REPAIR.orphan_table,
    action     => DBMS_REPAIR.create_action,
    tablespace => 'USERS');
END;
/

建立管理表后,我们能够使用 CHECK_OBJECT 过程检查感兴趣的表。

SET SERVEROUTPUT ON
DECLARE
  v_num_corrupt INT;
BEGIN
  v_num_corrupt := 0;
  DBMS_REPAIR.check_object (
    schema_name       => 'SCOTT',
    object_name       => 'DEPT',
    repair_table_name => 'REPAIR_TABLE',
    corrupt_count     =>  v_num_corrupt);
  DBMS_OUTPUT.put_line('number corrupt: ' || TO_CHAR (v_num_corrupt));
END;
/

假设损坏块的数量大于 0,则可以使用 REPAIR_TABLE 的 CORRUPTION_DESCRIPTION 和 REPAIR_DESCRIPTION 列获取更多有关损坏的信息。

此时,损坏块已被检测到,但尚未标记为损坏。可以使用 FIX_CORRUPT_BLOCKS存粹过程将块标记为损坏,一旦表处于正确模式,DML 就可以跳过它们。

SET SERVEROUTPUT ON
DECLARE
  v_num_fix INT;
BEGIN
  v_num_fix := 0;
  DBMS_REPAIR.fix_corrupt_blocks (
    schema_name       => 'SCOTT',
    object_name       => 'DEPT',
    object_type       => Dbms_Repair.table_object,
    repair_table_name => 'REPAIR_TABLE',
    fix_count         => v_num_fix);
  DBMS_OUTPUT.put_line('num fix: ' || TO_CHAR(v_num_fix));
END;
/

一旦找到并标记了表中损坏的块,就必须检查所有索引,查看其中是否有任何键条目指向损坏的块。这是使用 DUMP_ORPHAN_KEYS 过程完成的。

SET SERVEROUTPUT ON
DECLARE
  v_num_orphans INT;
BEGIN
  v_num_orphans := 0;
  DBMS_REPAIR.dump_orphan_keys (
    schema_name       => 'SCOTT',
    object_name       => 'PK_DEPT',
    object_type       => DBMS_REPAIR.index_object,
    repair_table_name => 'REPAIR_TABLE',
    orphan_table_name => 'ORPHAN_KEY_TABLE',
    key_count         => v_num_orphans);
  DBMS_OUTPUT.put_line('orphan key count: ' || TO_CHAR(v_num_orphans));
END;
/

如果孤立键(orphan key)数量大于 0,则应重建索引。

将表块标记为损坏的过程会自动将其从空闲列表中删除。这可以防止空闲列表访问损坏块之后的所有块。要纠正此问题,必须使用 REBUILD_FREELISTS 过程重建空闲列表。

BEGIN
  DBMS_REPAIR.rebuild_freelists (
    schema_name => 'SCOTT',
    object_name => 'DEPT',
    object_type => DBMS_REPAIR.table_object);
END;
/

该过程的最后一步是确保所有 DML 语句忽略标记为损坏的数据块。这是用 SKIP_CORRUPT_BLOCKS 过程完成的。

BEGIN
  DBMS_REPAIR.skip_corrupt_blocks (
    schema_name => 'SCOTT',
    object_name => 'DEPT',
    object_type => DBMS_REPAIR.table_object,
    flags       => DBMS_REPAIR.skip_flag);
END;
/

视图DBA_TABLES中的SKIP_CORRUPT列表示此操作是否成功。

此时表可以再次使用,但您必须采取措施纠正与丢失块相关的任何数据丢失。

Other Repair Methods

修复坏块的其他方法包括:

  • 完整数据库恢复(Full database recovery)。
  • 单个数据文件恢复。
  • 使用命令CREATE TABLE .. AS SELECT 重新创建表,注意通过限制查询的 where 子句来避免损坏的块。
  • 删除表并从之前的导出的dump文件中恢复。这可能需要一些手动操作来替换丢失的数据。

更多信息请参阅:

  • DBVERIFY: Offline Database Verification Utility[3]
  • DBMS_REPAIR[4]
  • Handling Oracle Block Corruptions in Oracle7/8/8i/9i/10g/11g[5]
  • Master Note for Handling Oracle Database Corruption Issues [ID 1088018.1][6]
参考资料
[1]

原文地址: https://oracle-base.com/articles/misc/detect-and-correct-corruption

[2]

2: https://oracle-base.com/articles/11g/data-recovery-advisor-11gr1#validate

[3]

3: http://docs.oracle.com/cd/E11882_01/server.112/e22490/dbverify.htm

[4]

4: http://docs.oracle.com/cd/E11882_01/appdev.112/e40758/d_repair.htm

[5]

5: https://support.oracle.com/epmos/faces/DocContentDisplay?id=28814.1

[6]

6: https://support.oracle.com/epmos/faces/DocContentDisplay?id=1088018.1

扫描上面二维码关注我
如果你真心觉得文章写得不错,而且对你有所帮助,那就不妨帮忙“推荐"一下,您的“推荐”和”打赏“将是我最大的写作动力!
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接.