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:
- CHECK_OBJECT – проверка и сбор информации о поврежденных блоках в таблице или индексе
- FIX_CORRUPT_BLOCKS - помечает выявленные с помощью CHECK_OBJECT блоки, как логически поврежденные
- DUMP_ORPHAN_KEYS – выгружает индексные ключи, указывающие на поврежденные блоки.
- REBUILD_FREELISTS - перестраивает списки свободных блоков
- 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 можно судить насколько успешным было выполнение этой процедуры.
После манипуляций, изложенных выше, таблица стала доступной, с ней можно работать. Но не забывайте, что нужно устранить потерю данных, попавших в коррумпированные блоки.
Для этого существуют следующие методы:
- Полное восстановление базы данных
- Восстановление конкретного датафайла
- Восстановление блока с помощью RMAN
- Использование команды CREATE TABLE .. AS SELECT, где в конструкции WHERE ограничить доступ к данным в битом блоке.
- Удалить таблицу и восстановить ее из предыдущего экспортного файла.