01окт Убить мёртвую сессию. В копилку администратору

Часто бывает так, что утрачено соединение сервера с клиентом. В этом случае, если сессия пребывала в статусе «ACTIVE», настанет момент, когда серверному процессу нужно будет обратиться к клиенту. И если связи с ним не будет, то серверный процесс завершается, а фоновый процесс PMON очистит занимаемые ресурсы. А если сессия была в состоянии 'INACTIVE'? Или сеанс «завис» по какой-то причине и блокировки, которые он удерживает, мешают работать прочим клиентам? Или тайм-ауты firewall/router/switch мешают жить соединению клиента с сервером?

В этом случае первое, что можно пробовать выполнять:

ALTER SYSTEM KILL SESSION 'sid,serial#';

ALTER SYSTEM DISCONNECT SESSION 'sid,serial#' IMMEDIATE;

Где значения sid и serial# можно почерпнуть из представления v$session.

Но, увы! Часто бывает так, что сессия приобретает после этого статус 'KILLED' (process='PSEUDO') и избавиться от этой сессии удается лишь после перезагрузки. А если это не возможно?

Тогда пробуйте следующий вариант:

  • Определимся с нашим мертвым процессом с помощью следующего запроса:SELECT p.spid FROM v$session s, v$process p WHERE s.paddr=p.addr;
  • Если удалось найти наш мертвый процесс, то удаляем его средствами операционной системы. Для LINUX это реализуется командой KILL -9 spid.

Но и в этом случае есть подводные камни, например, не во всех операционных системах удается очистить память после таких манипуляций.

Есть еще вариант: Попробуйте в sqlnet.ora на сервере установить параметр SQLNET.EXPIRE_TIME (значение в минутах).

Очень часто это тоже не помогает. И вот почему (излагаю своё представление, поэтому прошу быть снисходительными и исправить, если Вы нашли несуразность):

Сетевая модель OSI (можно почитать здесь) состоит из 7 уровней.

  • Сетевой протокол ORACLE (Oracle Net/NET8/SQL*Net) находится на 6-7 уровне. Здесь работает тайм-аут SQLNET.EXPIRE_TIME . Когда проблемы возникают здесь, тогда срабатывает SQLNET.EXPIRE_TIME и мертвый сеанс будет закрыт, PMON очистит ресурсы.
  • Протокол TCP/IP (его использует оракловский сетевой протокол) находится на 4-5 уровне. Здесь работает тайм-аут TCP_KEEP_ALIVE TIME (значение по умолчанию для каждой ОС разное: Linux - 45 минут ,Solaris - 72 часа…). И если проблемы возникли на этих уровнях (разорвался сетевой кабель …), то все время тайм-аута KEEP_ALIVE TIME протокол TCP пробует восстановить связь сервера с клиентом только на своих уровнях, на верхние уровни (где находится Oracle Net) об этом не сообщает, поэтому уровень оракловского протокола о проблеме даже не подозревает. Вот по этой причине SQLNET.EXPIRE_TIME не срабатывает.

Выход: KeepAliveTime устанавливать значительно меньшим, чем по умолчанию (например, 1-3 минуты). Очевидно, что для каждой ОС устанавливается KeepAliveTime по разному (LINUX : /proc/sys/net/ipv4/tcp_keepalive_time,WIN: HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/Tcpip/Parameters…). Консультируйтесь со своим сетевым администратором, ибо с этим параметром не все так просто. Не забудьте на клиентах в TNSNAMES.ORA установить конструкцию (ENABLE=BROKEN) для Вашего алиаса . На пример:

My_db.my_domain = (DESCRIPTION=(ENABLE=BROKEN)(ADDRESS= ....)... )

Здесь источник информации.

Комментарии (2)

[315] Комментарий от гость   01.10.2008(15:55:31)
в статье опечатка: запрос SELECT p.spid FROM v$session s, v$process p WHERE s.paddr=p.addr вернет ВСЕ процессы ОС, необходимо добавить условие: "AND s.sid=<sid>"
[316] Комментарий от dbstalker   01.10.2008(17:27:32)
Конечно,Вы правы. Только по представлению v$session нужно найти sid нашей мертвой сессии.Спасибо!



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

Имя
Электронная почта
 
Ваш сайт
Защита от спама: укажите сумму 8 + 6
   
 

Поиск по блогам



Подпишись на RSS:

RSS - Подписаться на блог



Читателям


Рекомендую к прочтению





Разделы блога



Последние публикации



Последние коментарии