# Экспорт снимка между сессиями _MVCC и видимость · PostgreSQL Knowledge Base_ **TL;DR:** pg_export_snapshot() возвращает идентификатор снимка, а другая сессия через SET TRANSACTION SNAPSHOT берёт ровно тот же снимок и видит данные в том же срезе времени. Так работает параллельный pg_dump: все рабочие процессы выгружают согласованную копию. Экспортирующая транзакция должна оставаться открытой. Снимок (см. [snapshot](/courses/postgres/kb/snapshot.md)) - это компактный набор чисел. Раз так, его можно не только взять, но и **передать** другой сессии, чтобы две транзакции видели базу в одинаковом срезе времени. ## Как передать снимок В первой сессии экспортируем снимок изнутри открытой транзакции: ```sql BEGIN; SELECT pg_export_snapshot(); -- 00000006-00000002-1 -- транзакцию НЕ коммитим: пока она открыта, снимок «живёт» ``` Во второй сессии берём этот же снимок первым же действием транзакции: ```sql BEGIN; SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; SET TRANSACTION SNAPSHOT '00000006-00000002-1'; -- теперь эта транзакция видит данные точно так же, как первая ``` С этого момента обе сессии видят один и тот же набор версий: чужие коммиты, случившиеся после экспорта, скрыты от обеих. ## Жёсткие условия Механизм требовательный, и не зря: - принимающая транзакция должна быть на уровне Repeatable Read или Serializable (см. [isolation-levels](/courses/postgres/kb/isolation-levels.md)) - на Read Committed снимок берётся на каждый оператор, делить нечего; - `SET TRANSACTION SNAPSHOT` должен идти **до** любого запроса в транзакции, пока у неё ещё нет собственного снимка; - экспортирующая транзакция обязана оставаться открытой, пока все принимающие не подхватили снимок. Закроется раньше - идентификатор станет недействительным. ## Зачем это нужно: параллельный бэкап Главный потребитель - `pg_dump -j` (параллельная выгрузка). Чтобы дамп был согласованным, все рабочие процессы должны видеть базу в один и тот же момент. Ведущий процесс экспортирует снимок, остальные подхватывают его через `SET TRANSACTION SNAPSHOT` - и выгружают разные таблицы, но из одного среза времени. Без этого параллельный дамп мог бы поймать половину таблиц до чужого коммита, половину после, и получить несогласованную копию. Экспорт снимка - это не способ «поделиться данными» между сессиями, а способ договориться о точке во времени, из которой обе на эти данные смотрят. ## Команды ```sql SELECT pg_export_snapshot(); ``` Выдать идентификатор текущего снимка (внутри открытой транзакции) ```sql SET TRANSACTION SNAPSHOT '00000006-00000002-1'; ``` Принять чужой снимок первым действием своей транзакции ```sql BEGIN ISOLATION LEVEL REPEATABLE READ; ``` Уровень, на котором приём снимка вообще имеет смысл ## См. также - [Снимок данных (snapshot)](/courses/postgres/kb/snapshot.md) - [Уровни изоляции в PostgreSQL](/courses/postgres/kb/isolation-levels.md) - [Виртуальные и реальные xid](/courses/postgres/kb/virtual-xid.md)