Как правильно закрыть H2? - PullRequest
       49

Как правильно закрыть H2?

23 голосов
/ 02 апреля 2012

Это связано с этим сообщением .
Я думаю, что у меня проблема с H2, означающим, что он не закрывается должным образом.
Я подозреваю это, так как вижу myDB.lock.db, когдаЯ отключаю tomcat, и процесс не останавливается.
Я использую пул соединений Tomcat, а URL к базе данных:
url="jdbc:h2:file:/opt/myOrg/tomcat/webapps/MyApplication/db/myDatabase;SCHEMA=myschema"

Из документа закройте H2 :

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

Я не могу понять, что я делаю что-то не так.
Должен ли я принуждатьбазу данных закрыть с помощью команды?В этом ли смысл крюка отключения?
Что я здесь не так делаю?

Примечание:
Я не могу найти в Google пример того, как правильно закрыть H2 (кроме заявления о том, что оно закрывается автоматически при последнем отключении соединения).Должен ли я позвонить SHUTDOWN сам?Это правильный подход?
Я уже вижу голоса, чтобы закрыть вопрос, но не было причины или ссылки на пример того, что я расследую

ОБНОВЛЕНИЕ:
После того, как Джунас Пулакка ответит на некоторую дополнительную информацию:

Из javacore я получил с помощью kill -3 Я вижу нити:

"H2 Log Writer MYAPPLICATION" J9VMThread: 0x08DC6F00, j9thread_t: 0x08C9B790, java / lang / Thread: 0xE7206CC8, состояние: CW, prio = 5 3XMTHREADINFO1 (идентификатор собственного потока: 0xA32, собственный приоритет: 0x5, собственная политика: UNKNOWN) 3XMTHREADINFO2
: собственный диапазон адресов стека от 0 000EE от 0 000E5E, до: 0xE5E67000, размер: 0x41000) 3XMTHREADINFO3 Java callstack:
4XESTACKTRACE в java / lang / Object.wait (собственный метод)
4XESTACKTRACE в java / lang / Object.wait (Object.java:196 (скомпилированный код)) 4XESTACKTRACE в org / h2 / store / WriterThread.run (WriterThread.java:102)
4XESTACKTRACE в java / lang / Thread.run (Thread.java:736)

3XMTHREADINFO "pool-8-thread-1 "J9VMThread: 0x087C0200, j9thread_t: 0x0840566C, java / lang / Thread: 0xE79BFC80, состояние: P, prio = 5
3XMTHREADINFO1 (идентификатор собственного потока: 0xE1A, собственный приоритет: 0x5, собственная политика: UNKNOWN) 3XMTHREADINFO2
(диапазон адресов собственных стеков:: 0xE5F69000, до: 0xE5FAA000, размер: 0x41000) 3XMTHREADINFO3 Java callstack:
4XESTACKTRACE в sun / misc / Unsafe.park (собственный метод)
4XESTACKTRACE в java / util / concurrent / locks / LockSupport (LockSupport).java: 184 (скомпилированный код)) 4XESTACKTRACE в java / util / concurrent / locks / AbstractQueuedSynchronizer $ ConditionObject.await (AbstractQueuedSynchronizer.java:1998 (скомпилированный код)) 4XESTACKTRACE в java / util / concurrent / LinkedBlockingQueBQ:413 (скомпилированный код)) 4XESTACKTRACE в java / util / concurrent / ThreadPoolExecutor.getTask (ThreadPoolExecutor.java:958 (скомпилированный код)) 4XESTACKTRACE в java / util / concurrent / ThreadPoolExecutor $ Worker.run (ThreadPoolExecACE )X: 4Блокировка файла java / lang / Thread.run (Thread.java:736)

3XMTHREADINFO "H2Функция наблюдения opt / myOrg / tomcat / webapps / MyApplication / db / myDatabase.lock.db "J9VMThread: 0x08DC6900, j9thread_t: 0x08C9BA24, ja
va / lang / Thread: 0xE71E9018, состояние: CW, 3X1 * RE5(собственный идентификатор потока: 0xA30, собственный приоритет: 0x9, собственная политика: НЕИЗВЕСТНО)
3XMTHREADINFO2 (диапазон адресов собственного стека от: 0xE5DBA000, до: 0xE5DFB000, размер: 0x41000) 3XMTHREADINFO3 Вызов стека вызовов Java: 4XESTACKTRACE в потоке java /.sleep (собственный метод) 4XESTACKTRACE
в java / lang / Thread.sleep (Thread.java:851 (скомпилированный код))
4XESTACKTRACE в org / h2 / store / FileLock.run (FileLock.java:490) 4XESTACKTRACE
в java / lang / Thread.run (Thread.java:736)

3XMTHREADINFO "FileWatchdog" J9VMThread: 0x087C, j9thread_t: 0x08C9B4FC, java / lang / Thread: 0xE715D878, состояние: CW, prio = 5
3XMTHREADINFO1 (идентификатор собственного потока: 0xA2C, собственный приоритет: 0x5, собственная политика: НЕИЗВЕСТНО) 3XMTHREADINFO2 диапазон адресов
от: 0xE5E67000, до: 0xE5EA8000, размер: 0x41000) 3XMTHREADINFO3 Вызов стека Java:
4XESTACKTRACE в java / lang / Thread.sleep (собственный метод) 4XESTACKTRACE в java / lang / Thread.sleep (Thread.java:851 (скомпилированный код)) 4XESTACKTRACE в org / apache / log4j / helpers / FileWatchdog.run (FileWatchdog.java:104)

Ответы [ 5 ]

9 голосов
/ 02 апреля 2012

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

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

При работе с большими базами данных закрытие может занять некоторое время.Посмотрите с помощью отладчика (например, VisualVM), какие потоки остаются активными после того, как вы вызвали (Tomcat) завершение работы.

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

4 голосов
/ 23 ноября 2016

Посмотрев на код DbStarter.contextDestroyed() (спасибо Allan5 ' answer ), вот код, который будет работать:

connection.createStatement().execute("SHUTDOWN");

Итак Аарон Дигулла ответ был верным (даже если не полностью «копировать / вставить»).

Более того, если вы запустили TCP-сервер H2, используя server = Server.createTcpServer("-tcpAllowOthers"), вы можете остановить его, просто набрав server.stop().

4 голосов
/ 19 октября 2016

Вы можете выполнить оператор SHUTDOWN, а затем закрыть соединение.

Команда SHUTDOWN сделает H2 немедленно освободить все ресурсы, связанные с соединением.Это, например, позволит вам избавиться от встроенной базы данных H2 при повторном развертывании веб-приложения.

1 голос
/ 27 апреля 2012

Не уверен, относится ли это к вашей ситуации, но вы пытались добавить прослушиватель DBStarter?

http://www.h2database.com/html/tutorial.html, см. Раздел «Использование прослушивателя сервлетов для запуска и остановки базы данных».

Ссылка предлагает добавить следующее в web.xml:

<listener>
    <listener-class>org.h2.server.web.DbStarter</listener-class>
</listener>

Пожалуйста, смотрите обсуждение здесь (по общему признанию, начиная с 2008 года, поэтому оно может быть устаревшим) - очевидно, исправление относится как к встроенным, так и к не встроенным экземплярам: http://groups.google.com/group/h2-database/browse_thread/thread/eb609d58c96f4317

В качестве альтернативы, как вы используете соединения? Вы уверены, что правильно очищаете соединения?

У меня были проблемы раньше, в моем случае я использовал соединение с JPA EntityManager, и я забыл закрыть экземпляр EntityManager после использования, что привело к некоторым проблемам:

@PersistenceUnit(unitName="myEm")
private EntityManagerFactory emf;

public void doStuff() {
    EntityManager em = emf.createEntityManager();
    ...
    em.close(); // forgot this line
}
1 голос
/ 02 апреля 2012

Нет, ловушка завершения работы - это просто поток, который запускается после завершения JVM, независимо от того, возвращается ли он из main (), вызывает ли System.exit (int) или выдает исключение. Только сбой JVM мог бы избежать этого. См. Runtime.addShutdownHook (Тема).

...