гибернация c3p0 сломанная труба - PullRequest
1 голос
/ 31 октября 2009

Я использую 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>

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

Ответы [ 4 ]

3 голосов
/ 31 октября 2009

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

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

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

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

1 голос
/ 12 июня 2010

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

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

0 голосов
/ 11 ноября 2009

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

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

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

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

Редактировать: Сейчас он обрабатывается.

0 голосов
/ 02 ноября 2009

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

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

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

...