SAVEPOINT

Тема дорожной карты · PostgreSQL

SAVEPOINT в PostgreSQL создаёт именованную точку отката внутри открытой транзакции, позволяя выполнять частичные откаты, отменяющие работу, выполненную после точки сохранения, без отмены всей транзакции. Синтаксис SAVEPOINT name отмечает точку, ROLLBACK TO SAVEPOINT name отменяет все изменения, сделанные после данной точки сохранения, оставляя транзакцию открытой, а RELEASE SAVEPOINT name удаляет маркер точки сохранения без выполнения отката. Точки сохранения особенно полезны в скриптах администрирования баз данных и в коде приложения, обрабатывающем пакеты операций, где сбой отдельного элемента не должен прерывать весь пакет — например, при итерации по строкам с перехватом нарушений ограничений для каждой строки. PostgreSQL поддерживает вложенные точки сохранения: несколько SAVEPOINT могут сосуществовать в рамках одной транзакции, обеспечивая детальные паттерны восстановления при ошибках в процедурах PL/pgSQL и сложных транзакционных рабочих процессах. Понимание точек сохранения — важная часть освоения транзакций PostgreSQL и создания надёжных, отказоустойчивых приложений баз данных.

Как это работает

SAVEPOINT оборачивают несколько операторов как одну атомарную единицу: BEGIN; ... ; COMMIT; (или ROLLBACK). ACID-гарантии: atomicity (всё или ничего), consistency (constraints выполнены), isolation (конкурентные txn выглядят последовательно на выбранном уровне), durability (committed = записано). Уровни изоляции: Read Committed (дефолт), Repeatable Read, Serializable (сильнейший, может требовать retry). Postgres использует MVCC: читатели не блокируют писателей и наоборот.

Когда применять

Оборачивайте multi-row бизнес-операции в транзакции — частичное состояние после крэша хуже, чем сбой. Serializable — для денежной логики, где два конкурентных update могут двойной счёт; иначе Read Committed достаточен и быстрее. SELECT ... FOR UPDATE — для явных row-локов. Savepoint (SAVEPOINT ...; ROLLBACK TO ...;) — для nested partial rollback внутри длинной транзакции.

Типичные ошибки

Ловушки SAVEPOINT: долгие транзакции блокируют VACUUM (autovacuum не освобождает, пока snapshot жив — bloat растёт); idle-in-transaction соединения (баговый ORM не делает commit/rollback); Serializable повсюду без retry-обработки (получите криптичные 40001); медленный внешний IO (HTTP-вызовы) внутри транзакции (lock держится слишком долго). Ставьте idle_in_transaction_session_timeout.

Связанные понятия

Полезные ресурсы