16.1. Поведение

Хотя автономные транзакции всегда выполняются внутри другой транзакции, в один момент времени может быть активна только одна транзакция; остальные должны ждать завершения активной транзакции. Когда автономная транзакция запускается, её родительская транзакция приостанавливается и помещается в стек автономных транзакций. Когда автономная транзакция фиксируется или отменяется, родительская транзакция извлекается из стека и продолжается. Завершить родительскую транзакцию можно только после завершения всех вложенных в неё автономных транзакций.

В рамках отдельной родительской транзакции можно выполнить несколько автономных, как последовательных, так и вложенных. По умолчанию Postgres Pro позволяет выполнить одновременно до 100 автономных транзакций во всех сеансах. Это ограничение можно увеличить, изменив параметр конфигурации max_autonomous_transactions. Максимальный уровень вложенности ограничен значением 128 и не может быть изменён.

Автономные транзакции не поддерживают следующие сценарии (при нарушениях выдаются ошибки):

  • Блокировка FOR UPDATE не поддерживается, так что нельзя заблокировать строку в родительской транзакции и пропустить её в автономной.

  • Если имеются временные таблицы, созданные с предложением ON COMMIT DROP, во вложенных автономных транзакциях не допускается использование одноимённых таблиц.

  • Уровень изоляции автономных транзакций внутри блоков PL/pgSQL или PL/Python переопределить нельзя.

  • Автономные транзакции не поддерживаются со следующими расширениями:

    • in_memory

    • online_analyze

    • pg_variables

Рассмотрите следующие примеры. В них непрерывная линия обозначает активную транзакцию, а пунктирная — транзакцию, которая была приостановлена и помещена в стек автономных транзакций. Течение времени направлено вниз.

BEGIN; -- начинается обычная транзакция T0
|
INSERT INTO t VALUES (1);
:\
: BEGIN AUTONOMOUS TRANSACTION; -- начинается автономная транзакция
: |                             -- T1, транзакция T0 помещается в стек
: |
: INSERT INTO t VALUES (2);
: |
: COMMIT AUTONOMOUS TRANSACTION / ROLLBACK AUTONOMOUS TRANSACTION; 
: |                             -- завершается автономная транзакция
: |                             -- T1, транзакция T0 извлекается из стека
:/
COMMIT / ROLLBACK;              -- завершается транзакция T0

В зависимости от выбора из COMMIT и ROLLBACK в двух местах, следующий запрос может вернуть четыре различных результата:

SELECT sum(x) FROM t;

В одной родительской транзакции может быть несколько автономных транзакций, вложенных одна в другую или следующих друг за другом.

BEGIN;                            -- начинается обычная транзакция T0
|
INSERT INTO t VALUES (1);
:\
: BEGIN AUTONOMOUS TRANSACTION;   -- начинается автономная транзакция
: |                               -- T1, транзакция T0 помещается в стек
: |
: INSERT INTO t VALUES (2);
: |
: COMMIT AUTONOMOUS TRANSACTION / ROLLBACK AUTONOMOUS TRANSACTION;
: |                               -- завершается автономная транзакция
: |                               -- T1, транзакция T0 извлекается из стека
:/
|
:\
: BEGIN AUTONOMOUS TRANSACTION;   -- начинается автономная транзакция
: |                               -- T2, транзакция T0 помещается в стек
: |
: INSERT INTO t VALUES (4);
: :\
: : BEGIN AUTONOMOUS TRANSACTION; -- начинается автономная транзакция
: : |                             -- T3, транзакция T2 помещается в стек
: : |
: : INSERT INTO t VALUES (6);
: : |
: : COMMIT AUTONOMOUS TRANSACTION / ROLLBACK AUTONOMOUS TRANSACTION;
: : |                             -- завершается автономная транзакция
: : |                             -- T3, транзакция T2 извлекается из стека
: :/
: |
: COMMIT AUTONOMOUS TRANSACTION / ROLLBACK AUTONOMOUS TRANSACTION;
: |                               -- завершается автономная транзакция
: |                               -- T2, транзакция T0 извлекается из стека
:/
COMMIT / ROLLBACK;                -- завершается транзакция T0