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

 

ANALYZE … VALIDATE STRUCTURE

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

DB_BLOCK_CHECKING

 Когда этот параметр установлен в значение TRUE, Oracle проверяет корректность содержимого блока. Но не все так просто с этим параметром. Проверка эта потребляет довольно много ресурсов, следовательно установка этого параметра в значение 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. Удалить таблицу и восстановить ее из предыдущего экспортного файла.

Вас заинтересует / Intresting for you:

Видеокурс по администрированию...
Видеокурс по администрированию... 10719 просмотров Илья Дергунов Mon, 14 May 2018, 05:08:47
Oracle и непроцедурный доступ ...
Oracle и непроцедурный доступ ... 8511 просмотров Antoni Tue, 21 Nov 2017, 13:32:50
Обновление до Oracle Database ...
Обновление до Oracle Database ... 7829 просмотров Илья Дергунов Tue, 21 Nov 2017, 13:18:05
Работа с запросами Approximate...
Работа с запросами Approximate... 2271 просмотров Андрей Васенин Mon, 29 Oct 2018, 06:40:46
Войдите чтобы комментировать

OraCool аватар
OraCool ответил в теме #8395 6 года 11 мес. назад
Спасибо за очень подробную статью. Удалось исправить коррупцию в таблице Oracle при помощи пакета DBMS_REPAIR. Алилуййя!