Как выявить коррупцию и попытаться исправить?

dbstalker, 20 февраля

Для этого есть несколько возможностей. О них уже было написано в блоге.Здесь вы найдете еще немного информации об этом.

DBVerify – об этом методе достаточно подробно было написано здесь.

ANALYZE … VALIDATE STRUCTURE об этой команде найдете информацию, например, здесь.Команда ANALYZE используется для проверки блоков данных в анализируемом объекте. Если обнаружено повреждение, информация о нем помещается в таблицу INVALID_ROWS.

DB_BLOCK_CHECKING – об этом параметре инициализации немного написано здесь. Когда этот параметр установлен в значение TRUE, Оракл проверяет корректность содержимого блока. Но не все так просто с этим параметром. Проверка эта потребляет достаточно много ресурсов, поэтому установка этого параметра в значение TRUE должно быть хорошо продумана.

RMAN VALIDATE - Варианты использования изложены в нескольких постах: здесь, здесь, здесь. Для Oracle 11g с помощью RMAN можно проверить datafiles, tablespaces или всю базу данных следующим образом:

VALIDATE DATAFILE 1;
VALIDATE DATAFILE 'c:\oracle\oradata\my_db\system01.dbf';
VALIDATE TABLESPACE users;
VALIDATE DATABASE;

Все поврежденные блоки можно увидеть в представлении V$DATABASE_BLOCK_CORRUPTION.

DBMS_REPAIR - этот пакет позволяет обнаружить и устранить коррупцию. Упоминание об этом пакете есть здесь, здесь и здесь.

Назначение основных процедур в пакете DBMS_REPAIR:

  1. CHECK_OBJECT – проверка и сбор информации о поврежденных блоках в таблице или индексе
  2. FIX_CORRUPT_BLOCKS - помечает выявленные с помощью CHECK_OBJECT блоки, как логически поврежденные
  3. DUMP_ORPHAN_KEYS – выгружает индексные ключи, указывающие на поврежденные блоки.
  4. REBUILD_FREELISTS - перестраивает списки свободных блоков
  5. SKIP_CORRUPT_BLOCKS - позволяет пропускать блоки, отмеченные как поврежденные, во время сканирования таблицы или индекса. Если не использовать, то можно получить ошибку ORA-01578.

Сначала нужно создать две таблицы, в которые будет помещаться информация о поврежденных блоках и индексных ключах, указывающих на эти блоки. Таблицы создаются следующим образом:

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;
/

Проверка таблицы проводится вот так:

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

После чего получаем перечень битых блоков:

select object_name, block_id, corrupt_type, marked_corrupt,    corrupt_description, repair_description from repair_table;

Если коррупция была обнаружена, то колонки CORRUPTION_DESCRIPTION и REPAIR_DESCRIPTION в таблице REPAIR_TABLE содержат полную информацию о поврежденных блоках.

Выявленные блоки теперь нужно пометить как испорченные, чтобы команды DML их пропускали и корректно отрабатывали. Это делается с помощью процедуры FIX_CORRUPT_BLOCKS

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

Если в таблице были обнаружены поврежденные блоки, то можно попытаться спасти информацию, которая содержится в индексах, ссылающихся на битые блоки.


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

А теперь можно просмотреть висячие ключи:


SELECT SCHEMA_NAME, INDEX_NAME, INDEX_ID, TABLE_NAME, KEYROWID, KEY,               DUMP_TIME FROM ORPHAN_ADMIN;

Если были обнаружены висячие ключи, то индекс обязательно нужно перестроить.

Для перестройки списка свободных блоков используется процедура DBMS_REPAIR.rebuild_freelists. Эта процедура просканирует таблицу и свободные блоки поместит в freelists. Все блоки, помеченные как битые, при сканировании будут пропущены.

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

Чтобы DML команды игнорировали блоки, помеченные как битые, используется процедура DBMS_REPAIR.skip_corrupt_blocks

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

По колонке SKIP_CORRUPT в представлении DBA_TABLES можно судить насколько успешным было выполнение этой процедуры.

После манипуляций, изложенных выше, таблица стала доступной, с ней можно работать. Но не забывайте, что нужно устранить потерю данных, попавших в коррумпированные блоки.

Для этого существуют следующие методы:

  1. Полное восстановление базы данных
  2. Восстановление конкретного датафайла
  3. Восстановление блока с помощью RMAN
  4. Использование команды CREATE TABLE .. AS SELECT, где в конструкции WHERE ограничить доступ к данным в битом блоке.
  5. Удалить таблицу и восстановить ее из предыдущего экспортного файла.

 

Новый комментарий

Я не спамер: введите суму 8+3



 

От авторов блога

О Блоге - прочитай перед началом.

Задать вопрос и получить ответ - уже решено 94 вопросов

Глоссарий - список терминов и сокращений


 
 

Бизнес форум

Последние темы:

Нужен поставщик Дропшиппинг
10 декабря, 1 ответа
КИНО КАФЕ!!!!!!!!!!!!!!!!
10 декабря, 1 ответа