Состояние активного сеанса Oracle при аварийном завершении работы клиента

1

Хорошее время.

Несколько дней назад наша команда БД обнаружила, что есть сеансы с статусом "АКТИВ" для неактивных клиентов. Исследование показало, что для таких вопросов есть два основных источника:

  1. удаленные соединения SQL Developer (на самом деле, этот случай не очень интересен),
  2. аномальный tomcat (где выполнялось наше приложение) завершение работы (например, "kill -9")

Для меня странно, что все эти сеансы находятся в статусе "ACTIVE". Может кто-нибудь, пожалуйста, уточнить, как это может быть (может быть, есть что-то с лежащими в основе процессами, которые ждут соответствующих сокетов или... Насколько все хорошо при правильном завершении tomcat, кажется, что первопричина связана с транзакциями...)?

Помогло бы это, если бы мы установили 'IDLE_TIME' (для всех подключений) и 'EXPIRE_TIME' (для всех наших экземпляров RAC)?

Правильно ли, что должны иметь место следующие сценарии (с указанными выше параметрами):

  1. Когда клиент подключается, сеанс помечен как "ACTIVE"
  2. Без уважения к статусу "ACTIVE" существует процесс "ping", инициированный параметром "EXPIRE_TIME", который связывает клиента.
  3. Если процесс Ping завершился с ошибкой в течение периода времени EXPIRE_TIME, хотя сеанс "ACTIVE", сеанс убивается оракулом.
  4. Если клиент отвечает на пинги, но не выполняет никакой обработки, после периода времени IDLE_TIME сеанс становится "НЕАКТИВНО" и (если параметр "IDLE_TIME" установлен) через некоторое время - "SNIPED". После этого процесс SMON запускает домашнюю работу для этой сессии (и другие с статусом "SNIPED").

ОБНОВЛЕНИЕ:

Кажется, что единственный способ работать с такой ситуацией - настроить экземпляры Oracle. Есть результаты моего расследования:

  • https://community.oracle.com/thread/873226?start=0&tstart=0

    Для Dead Connection Detection используется серверный параметр файла sqlnet.ora сервера SQLNET.EXPIRE_TIME = <число минут>

    Другой вариант - реализовать idle_time в настройках профиля. И затем, когда какая-то работа завершит сеансы SNIPED (когда idle_time будет достигнуто, сеанс станет от INACTIVE до SNIPED).


    Если я открою соединение и уйду на обед, ограничение IDLE_TIME приведет к прекращению моего сеанса после 15 минут бездействия. EXPIRE_TIME из 15 минут будет просто отправить Oracle пакет в мое клиентское приложение, чтобы убедиться, что клиент не сработал. Если клиент встал, он ответит на пинг, и мой сеанс останется неопределенным. EXPIRE_TIME только заставляет сеансы убивать, если клиентское приложение не отвечает на пинг, что означает, что процесс клиента завершился неудачно или что клиентская система потерпела неудачу. IDLE_TIME будет убивать сеансы, которые не имеют активности в течение определенного периода времени, но, как правило, это плохо работает с приложениями, поддерживающими пул соединений, поскольку предполагается, что пул соединений будет иметь достаточное количество соединений, которые бездействуют для периодов дня, и поскольку приложения, использующие пулы соединений, плохо реагируют на соединения в пуле, убиваемом.

  • https://asktom.oracle.com/pls/asktom/f?p=100:11:0::P11_QUESTION_ID:2233109200346833212

    TCP/IP не прерывает работу по умолчанию, по дизайну. Когда соединение уходит, клиент и/или сервер не получают немедленного уведомления. Таким образом, если ваш клиент подключается к базе данных и ничего не делает, и вы отключите свой клиент (синий экран, убейте его, вытащите сетевой кабель, выбейте компьютер, как бы то ни было), шансы на то, что сеанс останется в базе данных. Сервер не будет знать, что он никогда не получит от вас сообщения. У нас есть мертвое обнаружение клиента, если это становится проблемой:

    http://download.oracle.com/docs/cd/B12037_01/network.101/b10776/sqlnet.htm#sthref476

    Что касается активного сеанса, это очень просто. Вы открываете соединение, вы отправляете запрос по этому соединению, например, "lock table T". Таблица t заблокирована вашей транзакцией в вашем сеансе. Затем вы отправляете блок кода, например:

    begin loop dbms_lock.sleep(5); конец цикла; конец; /

    ваш сеанс будет активным до тех пор, пока этот код будет запущен - клиентский процесс блокируется в сокете, ожидающем, пока сервер вернет результат - ответ (который, конечно, никогда не придет). Сервер не трогает сеть прямо сейчас - он активен с вашим кодом. Итак, если ваш клиент "умирает" прямо сейчас - блок кода будет продолжать работать, запускаться и запускаться - и поскольку он никогда не совершает - он будет просто висеть там и запускаться, и, конечно, любые блокировки, которые у вас есть, будут оставаться на месте.

  • http://www.databaseskill.com/4267817/

  • http://www.dba-oracle.com/t_connect_time_idle_expire_timeout.htm

    Параметр sqlnet.expire_time используется для установки временного интервала в минутах, чтобы определить, как часто следует отправлять пробник, проверяя, что соединения клиент/сервер активны. Если вам необходимо убедиться, что соединения не остаются открытыми неограниченно (или до времени, заданного параметрами операционной системы), вы должны установить значение, большее 0. Это защищает систему от подключений, открытых открытыми из-за ненормального завершение клиента.

  • https://asktom.oracle.com/pls/apex/f?p=100:11:0::NO::P11_QUESTION_ID:453256655431

    Если сеанс ожидает блокировки ресурсов или защелок, и если это время ожидания превышает значение idle_time в профиле, выполняется ли сеанс sniped, даже если сеанс находится в середине транзакции и ожидает блокировки и т.д.

    Если да, будут ли какие-либо записи в журнале предупреждений.

    Следовать за

    если вы ожидаете блокировки, вы активны - не праздны.


    Эта страница привлекла мое внимание, за шесть месяцев до того, как у меня появилась поддержка Oracle для защиты данных, поэтому один из ребят из Oracle заметил, что я использую Idle_Time, и он сказал мне, что этот параметр не работает очень хорошо, потому что Oracle не выпускает ресурс сеансов, которые были отмечены как отловленные, до следующего попытки пользователя использовать его (ожидание, чтобы сообщить, что ваша сессия была убита, чтобы очистить ресурсы сеанса)

    Следовать за

    ... после расследования... существует "сессия", которая не исчезнет, пока клиент не подтвердит это, но "транзакция" исчезла.


    Том, я изменил профиль, чтобы иметь IDLE_TIME = 240 (4 часа) и удостоверился, что для параметра resource_limit установлено значение TRUE. Когда я запрашиваю сеанс v $, я вижу некоторые "отрезанные" сеансы, но также и "неактивные", которые простаивают более одного дня. У всех этих пользователей этот профиль назначен им. Если сеанс пользователя был подключен до того, как был установлен idle_time, повлияют ли эти сеансы на эти сеансы или нет? Некоторое время назад я внес изменения. Есть ли что-нибудь еще, что я должен был сделать?

    Следовать за

    Если сеанс пользователя был подключен до того, как был установлен idle_time, они будут "grandfathered" in - они не будут sniped. это влияет только на новые сеансы.

  • http://agstamy.blogspot.ru/2011/03/profile-and-resource-limit.html

  • дополнительный материал и рекомендации: https://rebby.com/blog.php?detail=32
  • 0
    Привет, какой тип связи вы используете? Выделенный или общий (или объединенный)? Существует некоторая ошибка с общим сервером. Мы попали в эту ошибку. Oracle не видит отключения активного клиента и продолжает запрос. Они просто присылают нам патч, чтобы исправить это
  • 1
    Привет, Элиату. Мы используем пулы соединений, но очень интересно узнать все вышеперечисленное в деталях. Не могли бы вы поделиться знаниями по этому вопросу как можно более подробно, и, если это возможно, поделиться патчем.
Показать ещё 2 комментария
Теги:
jdbc
session-timeout

1 ответ

0
Лучший ответ

Мы проверили параметры, перечисленные в приведенном выше исследовании, и все работает правильно!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню