понедельник, 2 ноября 2009 г.

ORA-600, UNDO tablespace and rollback segment corruption

Несмотря на некоторый опыт работы с RDBMS Oracle, бывают ситуации приводящие меня в состояние близкое к ступору. ORA-00600 -- это одна из таких ситуаций. Вообще говоря, до последнего времени я с подобными случаями и разбираться-то не хотел. Ну это же ора-600! Чего тут разбираться? Патчить до последнего patch-set, если не помогло искать строчку в коде, на которой 600 случается и придумывать воркэраунд.

Случилась тут падучая с одним нашим девелоперским инстансом (ESXi+RHEL5.2+10.2.0.4). Перед самоубийством бд говорила такое:

Wed Oct 28 13:17:47 2009
Errors in file /oracle/admin/frontend/bdump/frontend_smon_7076.trc:
ORA-01595: error freeing extent (3) of rollback segment (8))
ORA-00607: Internal error occurred while making a change to a data block
ORA-00600: internal error code, arguments: [4194], [21], [21], [], [], [], [], []
Ну и после нескольких таких заскоков, скоренько:
Errors in file /oracle/admin/frontend/bdump/frontend_pmon_7064.trc:
ORA-00600: internal error code, arguments: [4194], [21], [21], [], [], [], [], []
PMON: terminating instance due to error 472
Instance terminated by PMON, pid = 7064
Падением сопровождался любой коммит записывающий новые данные. Инстанс девелоперский (т.е. простой для него не критичен), бэкап разматывать с ленты было лениво (не говоря о том, что это пофиксило бы только симптом болезни, но не ее причину), поэтому я решил докопаться до правды.

Строчка "error freeing extent (3) of rollback segment (8))" ясно давала понять, что нехорошее случилось с файлами данных. Но вот ролбэк-сегменты, они же в восьмерке остались? Или нет? Почитав по теме, выяснил что таки нет не ушли они никуда, просто затаились в недрах Undo-tablespace. Похоже было, что анду физически повреждено, тут я ничего не смог придумать лучше чем просто пересоздать его. Для этого стартанул в рестрикт моде:
SQL>STARTUP RESTRICT MOUNT
Попытался дропнуть UNDOTBS1:
SQL>ALTER DATABASE DATAFILE '/oradata/frontend/undotbs01.dbf' OFFLINE DROP;
Получил такое:
ERROR at line 1: ORA-01548: active rollback segment ‘_SYSSMU1$’ found, terminate dropping tablespace
Посмотрел, сколько все-таки этих ролбэк-сегментов побито:
SQL>select segment_name,status,tablespace_name from dba_rollback_segs where status='NEEDS RECOVERY';
А вот сколько:
SEGMENT_NAME STATUS TABLESPACE_NAME —————————— —————- —————– _SYSSMU1$ NEEDS RECOVERY UNDOTBS1 _SYSSMU2$ NEEDS RECOVERY UNDOTBS1 _SYSSMU3$ NEEDS RECOVERY UNDOTBS1 _SYSSMU4$ NEEDS RECOVERY UNDOTBS1 _SYSSMU5$ NEEDS RECOVERY UNDOTBS1 _SYSSMU6$ NEEDS RECOVERY UNDOTBS1 _SYSSMU7$ NEEDS RECOVERY UNDOTBS1 _SYSSMU8$ NEEDS RECOVERY UNDOTBS1 _SYSSMU9$ NEEDS RECOVERY UNDOTBS1 _SYSSMU10$ NEEDS RECOVERY UNDOTBS1
Добавляем такое в pfile:
_corrupted_rollback_segments =(’_SYSSMU1$’,'_SYSSMU2$’,'_SYSSMU3$’,'_SYSSMU4$’,'_SYSSMU5$’, '_SYSSMU6$’,‘_SYSSMU7$’,'_SYSSMU8$’,'_SYSSMU9$’,'_SYSSMU10$’)
Рестартимся с этим пфайлом и делаем так со всеми битыми сегментами:
SQL>DROP rollback segment "_SYSSMU1$";
После, можно безнаказанно сделать так:
SQL>DROP TABLESPACE UNDOTBS1;
Создать новое табличное пространство отмены:
SQL>CREATE UNDO TABLESPACE UNDOTBS2 DATAFILE '/oradata/frontend/undotbs02.dbf'
SIZE 2000M reuse AUTOEXTEND ON;
Сделать его дефолтным:
SQL>ALTER SYSTEM SET undo_tablespace = UNDOTBS2;
В пфайле убрать _corrupted_rollback_segments и изменить undo_tablespace=UNDOTBS1 на undo_tablespace=UNDOTBS2 Все, у меня после этого на какое-то время проблема ушла. Способ топорный и сопряжен с тем, что в случае продакшена мы потеряем кучу данных в сегментах отмены. Причина же побитых файлов скорее всего была в рейд контроллере. Вернее в связке Adaptec->Firmware->VmWare ESXi4->RHEL5.2 Окончательно полечить проблему помогло обновление прошивки контроллера и накатка последних патчей на ESXi. Как-то так.

Комментариев нет:

Отправить комментарий