Ответ
Транзакции в SQLAlchemy обеспечивают атомарность операций с базой данных (принцип ACID). Управлять ими можно несколькими способами, но предпочтительным является использование контекстных менеджеров.
1. Рекомендуемый способ: Контекстный менеджер Session.begin()
Это самый надежный и лаконичный подход. Он автоматически выполняет commit() при успешном выходе из блока или rollback() при возникновении исключения.
from sqlalchemy.orm import Session
# session создается ранее
with Session(engine) as session:
try:
with session.begin():
# Все операции внутри этого блока — часть одной транзакции
user = User(name='John Doe')
session.add(user)
# ... другие операции
# Здесь транзакция автоматически закоммитится
except Exception as e:
# Здесь транзакция автоматически откатится
print(f"Transaction failed: {e}")
2. Явное управление через Session
Классический подход, требующий ручного вызова commit() и rollback().
from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind=engine)
session = Session()
try:
user = User(name='Jane Doe')
session.add(user)
session.commit() # Явный коммит
except:
session.rollback() # Явный откат в случае ошибки
raise
finally:
session.close() # Важно закрывать сессию
3. Уровень Core: Контекстный менеджер Engine.begin()
Подходит для выполнения низкоуровневых SQL-запросов без использования ORM-сессий.
with engine.begin() as connection:
connection.execute(text("UPDATE users SET active=true WHERE id=1"))
# Автоматический commit или rollback
Ключевые принципы:
- Атомарность: Всегда используйте транзакции для операций, которые должны быть выполнены как единое целое (например, перевод денег со счета на счет).
- Безопасность: Контекстные менеджеры (
with ...) — лучший способ избежать незакрытых сессий или незавершенных транзакций. - Вложенные транзакции: Для более сложных сценариев можно использовать
session.begin_nested().
Ответ 18+ 🔞
А, ну вот, опять про эти ваши транзакции, блядь! Слушай, давай я тебе на пальцах, как для дебила, объясню, а то ты, сука, опять накосячишь и базу мне похеришь.
Представь, что ты в кабаке заказываешь пиво и чипсы. Транзакция — это когда ты либо и пиво, и чипсы получил, либо нихуя. Не может быть такого, чтобы ты пиво выпил, а чипсы тебе забыли принести. Это пиздец, а не заказ. Вот SQLAlchemy как раз за этим и следит, чтобы не было такого распиздяйства.
Способ первый, нормальный (через Session.begin())
Это как прийти в нормальный бар, где официант умный. Ты ему сказал, что хочешь, он всё принёс, ты расплатился — и все довольны. Если кухня сгорела и чипсов нет, он тебе и пиво не принесёт, деньги вернёт. Всё честно.
from sqlalchemy.orm import Session
# Допустим, у тебя уже есть engine, как бутылка водки в баре
with Session(engine) as session: # Зашёл в бар
try:
with session.begin(): # Сказал официанту "я хочу вот это"
# Всё, что тут делаешь — это один заказ
user = User(name='Вася Пупкин')
session.add(user) # "И пиво, и чипсы!"
# ... другие операции
# Тут официант сам тебе всё принёс и счёт отдал (автокоммит)
except Exception as e:
# А тут кухня взорвалась, и он говорит: "Извини, братан, нихуя не будет" (автороллбэк)
print(f"Всё пропало, шеф: {e}")
Способ второй, ручной (как в подвальном баре)
Тут ты сам себе официант, бармен и кассир. Забыл что-то сделать — сидишь трезвый и голодный. Надо всё руками: сказать, что хочешь, заплатить, а если что-то пошло не так — самому деньги из кассы забрать. Страшно и неудобно.
from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind=engine)
session = Session() # Зашёл в этот тёмный подвал
try:
user = User(name='Жанна Дарк')
session.add(user) # Крикнул бармену заказ
session.commit() # А теперь, сука, беги на кухню, готовь и приноси счёт! (явный коммит)
except:
session.rollback() # Ой, всё, бармен сдох. Быстро забирай свои деньги из кассы и беги! (явный откат)
raise
finally:
session.close() # И дверь за собой, мудак, закрой, сквозняк!
Способ третий, для гурманов (через Engine.begin())
Это когда ты вообще мимо бара прошёл, зашёл прямо на склад, взял ящик пива и паллету чипсов. Без официантов, без сессий, голыми руками. Для сложных, мужицких операций.
with engine.begin() as connection: # Пролез на склад через чёрный ход
connection.execute(text("UPDATE users SET active=true WHERE id=1")) # Взял что надо
# Ушёл — и автоматически сигнализация сработала (коммит) или охрана тебя поймала (роллбэк)
Запомни, балбес:
- Атомарность — это когда либо всё, либо нихуя. Как с тем пивом и чипсами.
- Контекстные менеджеры (
with ...) — это твои лучшие друзья. Они за тебя всё закроют, откатят и приберутся. Не будь идиотом, используй их. - Вложенные транзакции (
session.begin_nested()) — это когда ты внутри большого заказа делаешь ещё один маленький. Типа "я ещё и кальян хочу". Сложная хуйня, без надобности не лезь.
Вот и вся наука. Не усложняй, пиши код так, чтобы его не стыдно было показать, а то опять накосячишь, и мне за тебя краснеть.