Я использую PostgreSQL JDBC, и у меня есть соединение для некоторых запросов выбора и вставки.Некоторые запросы занимают некоторое время, поэтому я добавил время ожидания.Проблема заключается в том, что тайм-аут закрывает соединение, но запрос все еще выполняется на сервере БД, и он создает блокировки.
Упрощенный код для проблемы (Реальный код намного сложнее и больше, но это не так.не имеет значения):
PGPoolingDataSource source = new PGPoolingDataSource();
source.setUrl(url);
source.setUser(user);
source.setPassword(password);
source.setMaxConnections(10);
source.setSocketTimeout(5); // Timeout of 5 seconds
// Insert a row data, and make timeout
Connection con = source.getConnection();
con.setAutoCommit(false);
try {
Statement st2 = con.createStatement();
st2.execute("insert into data.person values (4, 'a')");
Statement st3 = con.createStatement();
st3.executeQuery("select pg_sleep(200)"); // A query which takes a lot of time and causes a timeout
con.commit();
con.close();
} catch (SQLException ex) {
if (!con.isClosed()) {
con.rollback();
con.close();
}
ex.printStackTrace();
}
Connection con2 = source.getConnection();
con2.setAutoCommit(false);
try {
Statement st2 = con2.createStatement();
// This insert query is locked because the query before is still executed, and the rollback didn't happen yet, and the row with the id of 4 is not released
st2.execute("insert into data.person values (4, 'b')");
con2.commit();
con2.close();
} catch (SQLException ex) {
if (!con2.isClosed()) {
con2.rollback();
con2.close();
}
ex.printStackTrace();
}
(data.person
- таблица с id
и name
.)
Тайм-аут закрывает соединение, и оно даже не получаетсяна линию con.rollback();
.Я читал, что когда возникает исключение в запросе, он выполняет откат в фоновом режиме, поэтому все в порядке.
Но запрос занимает много времени (несколько часов), и в результате откат будетпроисходит после того, как большой запрос на выбор завершен.Таким образом, я не могу добавить строку в data.person
в течение нескольких часов (Во второй раз, когда я пытаюсь вставить, я получаю исключение тайм-аута, потому что он ожидает снятия блокировки ...).
Я прочитал, что могу использовать функцию pg_terminate_backend
в PostgreSQL для завершения запроса, и поэтому я могу выполнить запрос вставки во второй раз.
Мои вопросы:
1) КакБезопасно ли это?
2) Насколько распространено это решение?
3) Есть ли более безопасное решение, которое предоставляют JDBC или PostgreSQL?