← Назад к вопросам

Приведи пример использования транзакции

1.8 Middle🔥 171 комментариев
#Базы данных (SQL)

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Транзакции в Python: примеры и лучшие практики

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

1. Базовая транзакция с psycopg2 (PostgreSQL)

import psycopg2

conn = psycopg2.connect("dbname=test user=postgres")
cur = conn.cursor()

try:
    cur.execute("INSERT INTO accounts (name, balance) VALUES (%s, %s)", 
                ("Alice", 1000))
    cur.execute("INSERT INTO accounts (name, balance) VALUES (%s, %s)", 
                ("Bob", 500))
    conn.commit()
    print("✓ Транзакция выполнена")
except Exception as e:
    conn.rollback()
    print(f"✗ Ошибка: {e}")
finally:
    cur.close()
    conn.close()

2. Контекстный менеджер (рекомендуется)

import psycopg2
from contextlib import contextmanager

@contextmanager
def get_db_connection():
    conn = psycopg2.connect("dbname=test user=postgres")
    try:
        yield conn
        conn.commit()
    except Exception:
        conn.rollback()
        raise
    finally:
        conn.close()

with get_db_connection() as conn:
    cur = conn.cursor()
    cur.execute("INSERT INTO orders (user_id, amount) VALUES (%s, %s)", (1, 99.99))
    cur.execute("UPDATE accounts SET balance = balance - %s WHERE id = %s", (99.99, 1))

3. SQLAlchemy

from sqlalchemy import create_engine
from sqlalchemy.orm import Session
from models import Account

engine = create_engine('postgresql://user:password@localhost/db')

def transfer_money(from_id: int, to_id: int, amount: float):
    with Session(engine) as session:
        try:
            from_account = session.query(Account).filter_by(id=from_id).with_for_update().one()
            to_account = session.query(Account).filter_by(id=to_id).with_for_update().one()
            
            if from_account.balance < amount:
                raise ValueError("Недостаточно средств")
            
            from_account.balance -= amount
            to_account.balance += amount
            
            session.commit()
            return True
        except Exception as e:
            session.rollback()
            print(f"Ошибка перевода: {e}")
            return False

4. Async с asyncpg

import asyncpg

async def create_order_async(user_id: int, items: list):
    conn = await asyncpg.connect('postgresql://user:password@localhost/db')
    
    async with conn.transaction():
        try:
            order_id = await conn.fetchval(
                'INSERT INTO orders (user_id, created_at) VALUES ($1, NOW()) RETURNING id',
                user_id
            )
            
            for item in items:
                await conn.execute(
                    'INSERT INTO order_items (order_id, product_id, qty) VALUES ($1, $2, $3)',
                    order_id, item['product_id'], item['quantity']
                )
            
            return order_id
        except Exception as e:
            print(f"Ошибка: {e}")
            raise
        finally:
            await conn.close()

Ключевые моменты:

  • ACID гарантии: Atomicity, Consistency, Isolation, Durability
  • Всегда используй try/except/finally или контекстные менеджеры
  • SELECT FOR UPDATE для race conditions
  • Уровни изоляции: READ UNCOMMITTED → SERIALIZABLE
  • Deadlocks: избегай циклических блокировок, заказывай ресурсы в одном порядке

Транзакции критичны для целостности данных в многопользовательских системах.