Прерывает ли ошибка транзакцию в постгрес?

Прерывает ли ошибка транзакцию в постгрес? Я использую libpq, открываю транзакцию, пытаюсь вставить запись, если запись уже существуе, делаю селект, но на селекте вылетает следующая ошабка

ОШИБКА: текущая транзакция прервана, команды до конца блока транзакции игнорируются in_failed_sql_transaction(25P02)

Значит ли это, что ошибка прерывает транзакцию, и есть ли способ обойти это не прибегая к проверке существования записи до вставки?


Ответы (1 шт):

Автор решения: Roman Konoval

Да, в постгрес после возникновения ошибки новые операторы в транзакции выполнять нельзя.

Проверку перед вставкой непросто реализовать правильно. Простой select запрос проблему не решит, так как после проверки другая транзакция может вставить запись до того, как это успеет. Правильный способ так сделать, то есть делать проверку во время вставки - описан ниже.

Можно только сделать откат всей транзакции или до заранее созданной точки сохранения (англ. Savepoint). С помощью них можно отменять часть операций сделанных в транзакции до комита.

Так что последовательность действий такая:

  1. перед операцией, которая потенциально может пройти неуспешно, создаете точку сохранения командой SAVEPOINT имя-точки-сохранения
  2. выполняете операцию
  3. если операция завершилась успешно, отпускаете точку сохранения (если нет необходимости к ней возвращаться) командой RELEASE SAVEPOINT имя-точки-сохранения
  4. если операция завершилась неуспешно, используете команду ROLLBACK TO SAVEPOINT имя-точки-сохранения.

Как правильно отметил Мелкий savepoint-ы небесплатны по производительности и в этом случае имеет смысл рассмотреть использование insert .. on conflict do nothing и анализировать количество измененных строк.

→ Ссылка