Как обнаружить разорванное / остановленное соединение Oracle?

StackOverflow https://stackoverflow.com/questions/1431560

Вопрос

В нашей настройке сервера / клиента мы сталкиваемся с каким-то странным поведением.Клиент представляет собой приложение на C / C ++, которое использует OCI для подключения к серверу Oracle (используя ОТЛ библиотека).

Время от времени сервер БД каким-то образом умирает (да, это основная проблема, но со стороны приложения мы не можем ее решить, но в любом случае с этим приходится иметь дело), так что машина больше не отвечает на новые запросы / подключения, но существующие, такие как Oracle-connections, не прерываются и время ожидания не истекает.Запросы, отправленные в базу данных, просто больше никогда не возвращаются успешно.

Какие возможности (если таковые имеются) предоставляются Oracle для обнаружения этих остановленных подключений со стороны клиентского приложения и восстановления более или менее безопасным способом?

Это было полезно?

Решение

Это ошибка в Oracle (или назовите ее функцией) до 11.1.0.6, и они сказали, что патч для Oracle 11g, выпуск 1 (патч 11.1.0.7), в котором есть исправление. Нужно видеть это. Если это произойдет, вам придется отменить (убить) поток, выполняющий это действие. Не очень хороший подход, хотя

Другие советы

Во всей моей схеме базы данных у меня есть таблица с одной постоянной записью.Просто периодически опрашивайте такую таблицу простым SQL-запросом.Все остальные методы ненадежны.

В OTL есть API set_timeout , который может быть полезен для этого.

Редактировать. На самом деле игнорируйте это. set_timeout не работает с OCI. Посмотрите описание set_timeout в здесь , где оно описывает Техника, которая может быть использована с OCI

Похоже, вам нужно запустить запрос к базе данных (например, SELECT * FROM dual; ), а затем, если база данных не ответила в течение указанного времени, предположим, что сервер имеет умер и отреагировал соответственно. Боюсь, я не знаю C / C ++, но можете ли вы использовать многопоточность для запуска оператора, а затем ждать ответа, не вешая приложение?

Это работает - я сделал именно то, что вы ищете. Пусть родительский процесс (A) создаст дочерний процесс (B). Дочерний процесс (B) подключается к базе данных, выполняет запрос (что-то вроде «выберите 1 из a_table» - вы получите более высокую производительность, если не будете использовать для этого «двойной» и создадите свою собственную таблицу). Если (B) успешно, то он пишет, что он был успешным и выходит. (A) ждет указанное количество времени. Я использовал 15 секунд. Если (A) обнаруживает, что (B) все еще работает - тогда он может предположить, что база данных зависла - он убивает (B) и предпринимает необходимые действия (например, звонит мне по телефону с помощью SMS).

Если вы сконфигурируете SQL * NET для использования тайм-аута, вы, вероятно, заметите, что из-за этого большие запросы не будут выполнены. Конфигурация OCI set_timeout также будет вызывать это.

Существует ручной способ избежать этого.Вы можете открыть брандмауэр и выполнять что-то вроде пинга базы данных через каждый указанный промежуток времени.Таким образом, соединение с базой данных не будет потеряно.

идея

If (current_time - lastPingTime > configuredPingTime)
{
     //Dummy query
     select 1 from dual;
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top