Транзакции, когда должны быть отменены и откат
Я пытаюсь отладить приложение (в 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
2 ответа
Эта ошибка означает, что один из запросов, отправленных в транзакции, потерпел неудачу, поэтому остальные запросы игнорируются до конца текущей транзакции (которая автоматически будет откатом). Для PostgreSQL транзакция не удалась, и в любом случае она будет откатана после ошибки с одним исключением. Вы должны принять соответствующие меры, один из
- откажитесь от утверждения и начните заново.
- используйте SAVEPOINT s в транзакции, чтобы иметь возможность вернуться к этому моменту времени и попробовать другой путь. (Это исключение)
Включите ведение журнала запросов, чтобы увидеть, какой запрос является ошибочным и почему.
В любом случае точный ответ на ваш вопрос заключается в том, что любое исключение SQLException должно означать, что откат произошел при отправке команды завершения транзакции, то есть при выполнении команды COMMIT или ROLLBACK (или END). Вот как это работает: если вы используете точки сохранения, вы все равно будете придерживаться тех же правил, вы просто сможете вернуться туда, где вы сохранили, и попробовать что-то еще.
Кажется, это характерное поведение PostgreSQL, которое не используется большинством других СУБД. В целом (за пределами PostgreSQL) вы можете потерпеть неудачу в одной операции из-за ошибки, а затем в той же транзакции можете попробовать выполнить альтернативные действия, которые завершатся успешно, компенсируя ошибку. Один пример: рассмотрим операцию объединения (вставки / обновления). Если вы попытаетесь ВСТАВИТЬ новую запись, но обнаружите, что она уже существует, вы можете переключиться на операцию ОБНОВЛЕНИЕ, которая вместо этого изменяет существующую запись. Это прекрасно работает во всех основных СУБД. Я не уверен, что он не работает в PostgreSQL, но описания, которые я видел в других местах, а также в этом вопросе, показывают, что когда попытка INSERT означает, что любая дальнейшая активность в транзакции обречена на провал. Что в лучшем случае драконовское, а в худшем "непригодное".