Существует два способа вложения транзакций в SQLAlchemy. Один из них - виртуальные транзакции, где SQLAlchemy отслеживает, сколько начальных значений вы создали, и выдает коммит только тогда, когда совершает самая внешняя транзакция. Откат однако выдается сразу. Поскольку транзакция является виртуальной - то есть база данных ничего не знает о вложенности, вы не сможете ничего сделать с этим сеансом после отката, пока не откатите все внешние транзакции. Чтобы разрешить использование виртуальных транзакций, добавьте аргумент subtransactions=True
к вызову begin()
. Эта функция существует, чтобы позволить вам использовать управление транзакциями внутри функций, которые могут вызывать друг друга, не отслеживая, находитесь ли вы внутри транзакции или нет. Чтобы это имело смысл, сконфигурируйте сеанс с autocommit=True
и всегда выдавайте session.begin(subtransactions=True)
в транзакционной функции.
Другой способ вложения транзакций - использование реальных вложенных транзакций. Они реализованы с использованием точек сохранения. Если вы откатываете вложенную транзакцию, все изменения, сделанные в этой транзакции, откатываются, но внешняя транзакция остается пригодной для использования, и любые изменения, сделанные внешней транзакцией, все еще остаются. Для использования вложенной транзакции выведите session.begin(nested=True)
или просто session.begin_nested()
. Вложенные транзакции поддерживаются не для всех баз данных. Функция конфигурации библиотеки набора тестов SQLAlchemy sqlalchemy.test.requires.savepoints
говорит о поддержке:
emits_warning_on('mssql', 'Savepoint support in mssql is experimental and may lead to data loss.'),
no_support('access', 'not supported by database'),
no_support('sqlite', 'not supported by database'),
no_support('sybase', 'FIXME: guessing, needs confirmation'),
exclude('mysql', '<', (5, 0, 3), 'not supported by database')
В PostgreSQL вложенные транзакции SQLAlchemy работают просто отлично.