Я работаю над программой, которая позволяет нескольким пользователям получить доступ к db (MySQL), и в разное время я получаю SQLException: Lock wait timeout exceeded
.Когда вы отключаете `SELECT ... FOR UPDATE`?
соединение создается с помощью:
conn = DriverManager.getConnection(connString, username, password);
conn.setAutoCommit(false);
и звонки все пройти через этот бит кода:
try {
saveRecordInternal(record);
conn.commit();
} catch (Exception ex) {
conn.rollback();
throw ex;
}
Где saveRecordInternal
имеет некоторую внутреннюю логику, сохраняя данную запись. Где-то по пути является метод, который я подозреваю, что проблема:
private long getNextIndex() throws Exception {
String query = "SELECT max(IDX) FROM MyTable FOR UPDATE";
PreparedStatement stmt = conn.prepareStatement(query);
ResultSet rs = stmt.executeQuery();
if (rs.next()) {
return (rs.getLong("IDX") + 1);
} else {
return 1;
}
}
Этот метод вызывается saveRecordInternal
где-то это операция, в случае необходимости. По причинам, которые в настоящее время находятся вне моего контроля, я не могу использовать индекс автоматического инкремента, и в любом случае индекс, который нужно встать, необходим для некоторой внутренней логики.
Я бы предположил, что либо conn.commit()
, либо conn.rollback()
назвали достаточно, чтобы освободить замок, но, видимо, это не так. Поэтому мой вопрос: должен ли я использовать stmt.close()
или rs.close()
внутри getNextIndex
? Отпустит ли блокировку до того, как транзакция будет совершена или откатна, или просто обеспечит освобождение блокировки при вызове conn.commit()
или conn.rollback()
?
Есть ли что-нибудь еще, что мне не хватает/делает совершенно неправильно?
Редактировать: В момент блокировки все подключенные клиенты кажутся отзывчивыми, без запросов в настоящее время, но закрытие всех подключенных клиентов устраняет проблему. Это заставляет меня думать, что замок каким-то образом сохраняется, даже если сделка (предположительно?) Заканчивается, совершая или откатываясь назад.
Да, я подумал, что где-то есть замок, вопрос в том, как он останавливается? Кажется, что все клиенты выполняют свои задачи, но блокировка остается (я объясню свой вопрос, чтобы объяснить это). – Itai
Итак, что может случиться здесь: клиент выполнил некоторый запрос в базе данных, а клиент выпустил соединение. но запрос запущен в базе данных. Таким образом, даже несмотря на то, что клиент выпустил соединение, запрос все еще запущен. – Jaydatt
Это не имеет смысла, потому что при закрытии клиента проблема решена, поэтому она не может быть сиротским соединением/запросом. – Itai