2015-04-15 4 views
1

Учитывая следующий libpq код:Postgres libpq как сказать, если соединение было прервано

PGconn * internalConnection = PQconnectdb("my connection string"); 
if (PQstatus(internalConnection) != CONNECTION_OK) 
{ 
    // return error on failure 
} 

// Kill all connections 
if(0 == PQsendQuery(internalConnection, "SELECT pid, (SELECT pg_terminate_backend(pid)) as killed from pg_stat_activity")) 
{ 
    // return error on failure 
} 

Что делает следующее:

  1. Делает подключение к серверу.
  2. Выполняет запрос, убивая все соединения (включая это соединение).

Как сообщить клиентской стороне, что соединение было убито? Если я запустить снова следующее:

PQstatus(internalConnection) 

Я до сих пор получает CONNECTION_OK как мой результат.

Используя API MySQL, я могу проверить mysql_ping на соединение, чтобы узнать, все ли открыто соединение, но в Postgres похоже, что подобный вызов метода (который я мог найти) не похож.

Любые предложения относительно того, как я могу определить с клиентской стороны, если соединение было убито?

ответ

2

Чтобы увидеть, если соединение, кажется, жив через libpq вы можете отправить пустую строку запроса:

res = PQexec(conn, ""); 

и проверить результат.

На уровне протокола PostgreSQL это может быть сделано более эффективно с простым Sync сообщением, но libpq в настоящее время не подвергать способ послать только Sync.


Вам не обязательно это делать. Когда соединение закрывается сервером, он отправляет TCP RST клиенту. Это должно сообщить клиенту, что его сокет закрыт. Хотя я его не тестировал, я подозреваю, что для обработки любых оставшихся данных о соединении будет достаточно позвонить PQconsumeInput и заметить, что сокет был закрыт. Обратите внимание, однако, что если нет ввода для потребления, эта функция блокирует ожидание сообщения с сервера.


Кстати, в то время как в данном случае это разумно (МОГ), чтобы проверить соединение, в общем, это очень плохой дизайн. Вы никогда не должны делать это:

  • Тестовое соединение
  • Выполнить запрос
  • Пусть успех

как есть гонка между тестирование соединения и фактического выполнения запроса или запросов. Не говоря уже о том, что запросы могут потерпеть неудачу по другим причинам.

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

PostgreSQL's libpq может сделать это намного проще, чем в настоящее время для пользователей. Он должен выставить некоторые функции для проверки SQLState, чтобы увидеть, возможно ли это, например, переходный процесс, поэтому приложения могут использовать один вызов для повторной попытки по отключению блокировки, сбоям сериализации и т. Д. Пока вы должны сделать это сами.

+0

«PQconsumeInput» работает для меня в Ruby ('conn.consume_input') в цикле while-sleep. Чтобы правильно обрабатывать вещи, я должен поймать исключение «PG :: ConnectionBad». Я мог бы «вручную» проверить сокет FD, но это кажется немного чище. Большое спасибо за ответ на этот вопрос (хотя я и не спрашивал) – Otheus

Смежные вопросы