hibernate c3p0 сломанная труба

Я использую hibernate 3 с c3p0 для программы, которая постоянно извлекает данные из какого-то источника и записывает их в базу данных. Теперь проблема в том, что база данных может стать недоступной по каким-то причинам (в простейшем случае: я просто отключил ее).

Если что-то должно быть записано в базу данных, не должно быть никаких исключений — запрос должен ждать целую вечность, пока база данных снова не станет доступной. Если я не ошибаюсь, это одна из вещей, которые может сделать для меня пул соединений: если есть проблема с базой данных, просто повторите попытку подключения - в худшем случае до бесконечности.

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

Даже если я поймаю исключение, как я могу снова чисто повторно инициализировать спящий режим? (Пока что без c3p0 я просто снова построил фабрику сеансов, но я не удивлюсь, если это может привести к утечке соединений (или это нормально?)).

База данных представляет собой версию Virtuoso с открытым исходным кодом.

Моя конфигурация hibernate.xml.cfg c3p0:

<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>  
<property name="hibernate.c3p0.breakAfterAcquireFailure">false</property>
<property name="hibernate.c3p0.acquireRetryAttempts">-1</property>
<property name="hibernate.c3p0.acquireRetryDelay">30000</property>
<property name="hibernate.c3p0.automaticTestTable">my_test_table</property>

<property name="hibernate.c3p0.initialPoolSize">3</property>
<property name="hibernate.c3p0.minPoolSize">3</property>
<property name="hibernate.c3p0.maxPoolSize">10</property>

кстати: создается тестовая таблица, и я получаю массу отладочной информации, так что кажется, что она действительно читает конфигурацию.


person raven_arkadon    schedule 30.10.2009    source источник


Ответы (4)


Что ж, кажется, BoneCP действительно реализовал это. Его можно настроить на запись транзакции и ее воспроизведение при сбое сети или базы данных:

http://jolbox.com/bonecp/downloads/site/apidocs/com/jolbox/bonecp/BoneCPConfig.html#setTransactionRecoveryEnabled(boolean)

person Nella    schedule 12.06.2010

Если я не ошибаюсь, это одна из вещей, которые может сделать для меня пул соединений: если есть проблема с базой данных, просто повторите попытку подключения - в худшем случае до бесконечности.

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

Тем не менее, эти соединения могут устареть (например, если вы перезапустите базу данных). К счастью, большинство пулов соединений можно настроить так, чтобы они проверяли, действительны ли соединения, и обновляли их перед их распространением. c3p0 поддерживает эту функцию, как описано в разделе Настройка тестирования подключения, и вы на самом деле уже используя один из различных вариантов. Поэтому ваши соединения должны быть обновлены, когда база данных вернется.

Но не ожидайте, что ваше приложение будет волшебным образом приостановлено, когда база данных выйдет из строя, пул этого не сделает.

person Pascal Thivent    schedule 30.10.2009

Спасибо за ответ. Кажется, я просто не совсем понял последний абзац раздела http://www.mchange.com/projects/c3p0/index.html#configuring_recovery

Потому что на первый взгляд кажется, что c3p0 может это сделать (обнаружить устаревшие соединения и повторить попытку установить соединения на всю вечность, никогда не вызывая исключения в коде приложения (если, конечно, это не ошибка, связанная с оператором sql, а не с соединением), но в последнем абзаце, который написан довольно запутанно, кажется, что c3p0 не может гарантировать это на 100%.

Итак, мое решение состояло в том, чтобы сделать небольшую оболочку для методов, которые мне нужны, из интерфейса подключения jdbc, которые пытаются переподключиться, если запрос не работает из-за ошибки подключения. Конечно, это немного хакерски, потому что я бы предпочел, чтобы мои компоненты использовали стандартный интерфейс Connection вместо моего собственного интерфейса, но, по крайней мере, теперь он работает чисто.

person raven_arkadon    schedule 02.11.2009

Вы забываете:

  • А как насчет ваших транзакций, которые были начаты?
  • Как насчет любых подготовленных операторов, которые уже были отправлены в БД?
  • и т.д

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

В случае BoneCP (http://jolbox.com) пул обнаруживает сбой, перехватывая исключение сначала выбрасывается драйвером JDBC и обрабатывается либо путем пометки этого соединения как ошибочного, либо путем воссоздания всего пула соединений.

Изменить: это обрабатывается сейчас.

person wwadge    schedule 11.11.2009
comment
Да, теперь я вижу, что такая бухгалтерия может быть реализована поверх, например. пул соединений, но он выходит за рамки такого пула. - person raven_arkadon; 13.11.2009