Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Как работают транзакции
Транзакция — это неделимая последовательность операций БД, которая либо полностью выполняется (COMMIT), либо полностью отменяется (ROLLBACK).
ACID свойства
Atomicity — либо все, либо ничего. Если во время выполнения происходит ошибка, все изменения откатываются.
Consistency — база переходит из одного консистентного состояния в другое. Все constraints соблюдены.
Isolation — транзакции выполняются независимо, не видят промежуточные изменения друг друга.
Durability — после коммита данные сохранены на диск и не теряются при сбое.
Пример на Python
import psycopg2
conn = psycopg2.connect("dbname=bank")
cursor = conn.cursor()
try:
cursor.execute("BEGIN")
cursor.execute("UPDATE accounts SET balance = balance - 100 WHERE id = 1")
cursor.execute("UPDATE accounts SET balance = balance + 100 WHERE id = 2")
conn.commit() # Обе операции фиксируются атомарно
except Exception as e:
conn.rollback() # Отменяем все
print(f"Ошибка: {e}")
finally:
cursor.close()
conn.close()
Уровни изоляции
- READ UNCOMMITTED — видим грязные чтения (незакомиченные данные)
- READ COMMITTED — видим только закомиченные данные (default PostgreSQL)
- REPEATABLE READ — стабильное чтение в пределах транзакции
- SERIALIZABLE — максимальная изоляция, как будто транзакции выполняются последовательно
cursor.execute("SET TRANSACTION ISOLATION LEVEL SERIALIZABLE")
Блокировки
Shared Lock (FOR SHARE) — несколько процессов читают одновременно
BEGIN;
SELECT * FROM accounts WHERE id = 1 FOR SHARE;
COMMIT;
Exclusive Lock (FOR UPDATE) — только один процесс работает
BEGIN;
SELECT * FROM accounts WHERE id = 1 FOR UPDATE;
UPDATE accounts SET balance = 1000 WHERE id = 1;
COMMIT;
Savepoints — частичный откат
cursor.execute("BEGIN")
cursor.execute("UPDATE accounts SET balance = 1000 WHERE id = 1")
cursor.execute("SAVEPOINT sp1")
cursor.execute("UPDATE accounts SET balance = -500 WHERE id = 2")
try:
conn.commit()
except:
cursor.execute("ROLLBACK TO sp1") # Откат только до savepoint
conn.commit()
Deadlock
Взаимная блокировка: процесс 1 ждет ресурс процесса 2, процесс 2 ждет ресурс процесса 1.
Решение: всегда берите блокировки в одинаковом порядке.
SQLAlchemy пример
from sqlalchemy.orm import Session
with Session(engine) as session:
try:
account1 = session.query(Account).get(1)
account1.balance -= 100
account2 = session.query(Account).get(2)
account2.balance += 100
session.commit() # Атомарный коммит
except:
session.rollback() # Откат всех изменений
raise
Транзакция обеспечивает целостность и надежность данных при параллельном доступе множества пользователей.