Метод begin_nested класса Session
Метод begin_nested класса Session
создает вложенную транзакцию, которая работает
внутри уже открытой внешней транзакции.
Вложенная транзакция реализуется через механизм
SAVEPOINT, поддерживаемый большинством
СУБД. Метод не принимает обязательных параметров
и возвращает объект SessionTransaction,
который можно использовать как контекстный
менеджер. Если внутри вложенной транзакции
произойдет откат, изменения откатятся только
до точки сохранения, а внешняя транзакция
останется активной.
Синтаксис
Session.begin_nested()
Пример
Давайте создадим сессию и откроем вложенную транзакцию внутри основной, а затем выполним откат вложенной транзакции:
from sqlalchemy import create_engine, String, select
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session
class Base(DeclarativeBase):
pass
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str] = mapped_column(String(50))
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
with session.begin():
session.add(Article(title='article 1'))
with session.begin_nested():
session.add(Article(title='article 2'))
session.rollback()
session.add(Article(title='article 3'))
res = session.scalars(select(Article)).all()
print([a.title for a in res])
Результат выполнения кода:
['article 1', 'article 3']
Как видно из результата, запись article 2 была
откачена, потому что она находилась внутри
вложенной транзакции, а записи article 1
и article 3 сохранились.
Пример
Давайте посмотрим, какой SQL-запрос генерирует вложенная транзакция при откате:
from sqlalchemy import create_engine, String
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session
class Base(DeclarativeBase):
pass
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str] = mapped_column(String(50))
engine = create_engine('sqlite:///:memory:', echo=True)
Base.metadata.create_all(engine)
with Session(engine) as session:
with session.begin():
session.add(Article(title='article'))
with session.begin_nested():
session.add(Article(title='article 2'))
session.rollback()
Итоговый SQL запрос:
SAVEPOINT sa_savepoint_1
ROLLBACK TO SAVEPOINT sa_savepoint_1
Пример
Давайте получим объект вложенной транзакции
через метод get_nested_transaction и
проверим ее состояние:
Результат выполнения кода:
True
True
Смотрите также
-
класс
Session,
который управляет сессией работы с базой -
метод
begin,
который открывает внешнюю транзакцию -
метод
rollback,
который откатывает текущую транзакцию -
метод
get_nested_transaction,
который возвращает текущую вложенную транзакцию