Как обнаружить разорванное / остановленное соединение Oracle?
-
07-07-2019 - |
Вопрос
В нашей настройке сервера / клиента мы сталкиваемся с каким-то странным поведением.Клиент представляет собой приложение на 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;
}