База данных H2 с Apache DBCP2 неожиданно закрывается
Я запускаю многопоточное приложение и использую DBCP2 для управления соединениями между потоками. В моем приложении нет абсолютно никакого кода, который закрывает соединение JDBC с базой данных. Приложение работает в фоновом режиме 24/7 и никогда не предназначено для закрытия.
Однако иногда соединение H2 закрывается, и любые последующие операции с базой данных генерируют следующую трассировку стека исключений:
org.h2.jdbc.JdbcSQLException: The database has been closed [90098-196]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:345)
at org.h2.message.DbException.get(DbException.java:179)
at org.h2.message.DbException.get(DbException.java:155)
at org.h2.message.DbException.get(DbException.java:144)
at org.h2.engine.Session.getTransaction(Session.java:1636)
at org.h2.engine.Session.getStatementSavepoint(Session.java:1646)
at org.h2.engine.Session.setSavepoint(Session.java:825)
at org.h2.command.Command.executeUpdate(Command.java:254)
at org.h2.jdbc.JdbcPreparedStatement.executeUpdateInternal(JdbcPreparedStatement.java:164)
at org.h2.jdbc.JdbcPreparedStatement.executeUpdate(JdbcPreparedStatement.java:150)
at org.apache.commons.dbcp2.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:98)
at org.apache.commons.dbcp2.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:98)
at sotec.automation.inverters.huawei.HuaweiDao.newSample(HuaweiDao.java:854) <= Just a regular DB operation which has succeeded on sevral occaissions before this exception is thrown.
База данных H2 является встроенной базой данных (простой файл в корне пути к классу):
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.196</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.1</version>
</dependency>
Настройка DBCP следующая:
final BasicDataSource bds = new BasicDataSource();
bds.setDriver(new org.h2.Driver());
bds.setUrl("jdbc:h2:./db3");
bds.setDefaultAutoCommit(false);
Все соединения с базой данных получены с использованием блока try-with-resources. Функция, которая вызвала вышеупомянутое исключение, включена для полноты, но я почти уверен, что это не источник проблемы:
public int newSample(Collection<Inverter> inverters, Instant from, Instant until) throws SQLException {
try (final Connection conn = bds.getConnection()) {
try (final PreparedStatement statement = conn.prepareStatement("INSERT INTO ... SELECT ... FROM ... JOIN ... JOIN ... JOIN ... ")) { // A very long and very ugly SQL statement
statement.setTimestamp(1, Timestamp.from(until), db.getCalendar());
// ... parameters
statement.setTimestamp(7, Timestamp.from(until), db.getCalendar());
final int count = statement.executeUpdate();
conn.commit();
log.debug("Sampled {} huawei inverter samples between {} and {} serached inverters: {}", count, from, until, invNos);
return count;
}
}
}
Мои вопросы связаны со следующим:
- Почему моя БД закрывается?
- Почему DBCP не просто заново открывает соединение?
- Что я могу сделать, чтобы БД была доступна 24/7 на вечность и дальше?