Транзакции, когда должны быть отменены и откат
-
10-07-2019 - |
Вопрос
Я пытаюсь отладить приложение (в PostgreSQL) и обнаружил следующую ошибку: " текущая транзакция прервана, команды проигнорированы ".
Насколько я понимаю, "транзакция" это просто понятие, связанное с подключением к базе данных.
Если в соединении есть автоматическая фиксация " false " ;, вы можете выполнять запросы через один и тот же оператор, если он не дает сбоя. В этом случае вы должны выполнить откат.
Если автоматическая фиксация имеет значение " true " тогда это не имеет значения, если все ваши запросы считаются атомарными.
Используя auto commit false, я получаю вышеупомянутую ошибку в PostgreSQL, даже если простое
select * from foo
терпит неудачу, что заставляет меня спросить, при каких условиях SQLException является «транзакцией» считается недействительным и должен быть откатан или не использован для другого запроса?
с использованием MacOS 10.5, Java 1.5.0_16, PostgreSQL 8.3 с драйвером JDBC 8.1-407.jdbc3
Решение
Эта ошибка означает, что один из запросов, отправленных в транзакции, потерпел неудачу, поэтому остальные запросы игнорируются до конца текущей транзакции (что автоматически приведет к откату). Для PostgreSQL транзакция не удалась, и в любом случае она будет откатана после ошибки с одним исключением. Вы должны принять соответствующие меры, один из
<Ол>Включите ведение журнала запросов , чтобы увидеть, какой запрос является ошибочным и почему.
В любом случае точный ответ на ваш вопрос заключается в том, что любое исключение SQLException должно означать, что откат произошел при отправке команды завершения транзакции, то есть при выполнении команды COMMIT или ROLLBACK (или END). Вот как это работает: если вы используете точки сохранения, вы все равно будете придерживаться тех же правил, вы просто сможете вернуться туда, где вы сохранили, и попробовать что-то еще.
Другие советы
Кажется, что это характерное поведение PostgreSQL, которое не используется большинством других СУБД. В целом (за пределами PostgreSQL) вы можете потерпеть неудачу в одной операции из-за ошибки, а затем в той же транзакции можете попробовать альтернативные действия, которые будут успешными, компенсируя ошибку. Один пример: рассмотрим операцию объединения (вставки / обновления). Если вы попытаетесь ВСТАВИТЬ новую запись, но обнаружите, что она уже существует, вы можете переключиться на операцию ОБНОВЛЕНИЕ, которая вместо этого изменяет существующую запись. Это прекрасно работает во всех основных СУБД. Я не уверен, что он не работает в PostgreSQL, но описания, которые я видел в других местах, а также в этом вопросе, предполагают, что когда попытка INSERT означает, что любая дальнейшая активность в транзакции обречена на провал. Что в лучшем случае драконовское, а в худшем «непригодное».