Немедленная остановка базы данных Oracle (БД) с принудительным завершением всех сессий обычно выполняется достаточно быстро (настолько быстро, сколько времени требуется остановить все процессы в БД). Но бывают случаи, когда уже начатая остановка никак не может завершиться и уходит в бесконечно долгое ожидание. Можно надеяться на лучшее и терпеливо ждать когда же все завершится, но нет никакой уверенности, что это произойдет в ближайшее время и произойдет ли вообще. Поэтому лучше взять удачу в свои руки и завершить вручную зависшие процессы.
А что произошло?
По всей вероятности, команде остановки БД никак не удается завершить какую-то открытую сессию пользователя. Почему это происходит? Данный вопрос требует отдельного обсуждения. В одном из моих конкретных случаев, когда пришлось бороться с зависанием, один из пользователей запустил запрос к плохо индексированной таблице с большим объемом данных. Запрос ушел в долгое вычисление. Попытки отмены запроса, попытки принудительного завершения сессии ни к чему не приводили. Команда полной остановки БД также уперлась в этот процесс и никак не могла с ним справиться.
Как с этим бороться? Можно позвать на помощь команду SHUTDOWN ABORT
, но делать это крайне не рекомендуется. Есть риск получить повреждения в БД. Поэтому в данной ситуации лучше использовать более безопасный метод – найти зависшие процессы на уровне операционной системы (ОС) и завершить их вручную.
Как найти зависшие процессы БД в ОС
Находим все имеющиеся процессы, в имени которых присутствует название экземпляра БД в формате oracle$ORACLE_SID. Дополнительно проверяем наличие пометки LOCAL равно YES или NO. Когда БД уже находится в состоянии остановки, найденные таким образом процессы являются кандидатами на удаление.
[oracle@serv ~]$ ps -ef | grep LOCAL | grep oracle$ORACLE_SID oracle 13708 1 1 14:58 ? 00:01:06 oraclefrmtst (LOCAL=NO)
В нашем случае, вот он. Единственный активный процесс с зависшей сессией.
Список идентификаторов зависших процессов
Чтобы принудительно завершить найденные процессы в ОС надо получить список их идентификаторов.
[oracle@serv ~]$ ps -ef | grep LOCAL | grep oracle$ORACLE_SID | awk '{print $2}' 13708
Завершение процессов командой kill
Перенаправлением полученного списка идентификаторов процессов команде kill можно завершить все найденные процессы одним вызовом.
[oracle@serv ~]$ kill -9 $(ps -ef | grep LOCAL | grep oracle$ORACLE_SID | awk '{print $2}') [oracle@serv ~]$ echo $? 0
Источник: Ed Chen Logic