Как определить, что Oracle прервал / остановил соединение? - PullRequest
4 голосов
/ 16 сентября 2009

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

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

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

Ответы [ 6 ]

3 голосов
/ 13 сентября 2010

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

1 голос
/ 15 октября 2009

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

0 голосов
/ 17 декабря 2009

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

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

0 голосов
/ 16 декабря 2009

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

0 голосов
/ 08 октября 2009

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

Идея

If (current_time - lastPingTime > configuredPingTime)
{
     //Dummy query
     select 1 from dual;
}
0 голосов
/ 16 сентября 2009

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...