Oracle: как определить завершение клиентского процесса, как это работает для sqlplus?

У меня есть следующая проблема в моем приложении, которое подключается к базе данных Oracle 10g:

Когда мой клиент дает сбой, или процесс завершается через диспетчер задач, или клиент теряет связь на некоторое время, соответствующая запись в представлении v$session остается.

Теперь, когда я подключаюсь к базе данных с помощью sqlplus и уничтожаю sqlplus.exe через диспетчер задач, запись сеанса удаляется почти мгновенно.

Последнее поведение было бы предпочтительным для моего приложения по разным причинам.

Что делает sqlplus по-другому, и могу ли я сделать то же самое в своих собственных приложениях?


person Tim Meyer    schedule 09.03.2012    source источник
comment
Я столкнулся с такой разницей в поведении при использовании драйвера тонкого клиента оракула, а не драйвера OCI.   -  person Juergen Hartelt    schedule 09.03.2012


Ответы (3)


SQL*Plus использует OCI — интерфейс вызовов Oracle. Это обширный API (более четырехсот вызовов функций. OCI предоставляет множество методов для обработки соединений и сеансов. Я не знаю наверняка, но предполагаю, что SQL*Plus использует OCILogon2() для регистрации выделенного сеанса для пользователя, и помещает что-то в дескриптор сеанса, что позволяет ему определять, когда сеанс ABEND.

Итак, возможно, ваше приложение не использует OCI для подключения к базе данных. Если вы хотите узнать больше об OCI, вы можете прочитать документацию. Имейте в виду, что это довольно низкоуровневый материал! Подробнее...

person APC    schedule 09.03.2012
comment
Я использую Qt, который предлагает плагин QSQLOCI, который является оболочкой Qt для OCI. Думаю, я собираюсь взглянуть на слой QSQLOCI. - person Tim Meyer; 09.03.2012
comment
Этот слой использует OCIServerAttach и OCISessionBegin; Я не смог найти ни одного вхождения OCILogon или OCILogon2. Знаете ли вы, является ли ServerAttach/SessionBegin альтернативой OCILogon или они не связаны? - person Tim Meyer; 09.03.2012

Вы можете установить sqlnet.expire_time=minutes_to_check в $ORACLE_HOME/network/admin/sqlnet.ora; это не будет мгновенно, как oci, но очистит мертвые соединения.

person Adam Musch    schedule 09.03.2012
comment
Это очищает только мертвые соединения? Или это также повлияет на соединения, которые простаивали дольше minutes_to_check? - person Tim Meyer; 12.03.2012
comment
И то, и другое на самом деле. Наши системы настроены таким образом, так как тогда не имеет значения емкость клиентского приложения, и большинство наших Java-приложений используют пулы соединений, чтобы они могли перезапустить мертвое соединение в своем пуле. - person Adam Musch; 12.03.2012
comment
Есть ли способ установить что-то подобное только для текущего сеанса? Проблема в том, что целевой сервер используется для нескольких приложений (не только наших), и мы должны гарантировать, что другие приложения не перестанут работать, когда мы захотим что-то изменить на сервере. - person Tim Meyer; 13.03.2012
comment
Не то, чтобы я знал об этом - вам придется использовать уровень OCI, как рекомендуется APC. - person Adam Musch; 14.03.2012

Дальнейшее исследование показало, что хотя sqlplus ведет себя по-разному при завершении процесса, на самом деле он ведет себя так же, когда сетевой кабель отключается на секунду => оборванный сеанс останется на сервере.

Теперь я создал профиль пользователя с ограниченным idle_time, который назначается нужным мне пользователям. Фоновый поток отправляет «поддерживающие» запросы, чтобы соединение не было SNIPED из-за PMON.

См. мой другой вопрос Oracle: idle_time игнорируется, если вы интересно, что я сделал, и увидеть ответ о том, что вы должны сделать, чтобы заставить idle_time работать.

person Tim Meyer    schedule 15.03.2012