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

Что такое свойства ACID в базах данных?

1.0 Junior🔥 11 комментариев
#Тестирование

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

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

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

Свойства ACID в базах данных

ACID — это набор из четырёх ключевых свойств, обеспечивающих надёжность транзакций в базах данных. ACID гарантирует, что даже при сбоях система останется в согласованном состоянии.

A — Atomicity (Атомарность)

Определение: Транзакция либо выполнится полностью, либо не выполнится вообще (all-or-nothing).

# Пример: перевод денег между счётами
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

Base = declarative_base()

class Account(Base):
    __tablename__ = 'accounts'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    balance = Column(Integer)

engine = create_engine('postgresql://...')
Session = sessionmaker(bind=engine)

def transfer_money(from_id, to_id, amount):
    session = Session()
    try:
        # Начало транзакции
        from_account = session.query(Account).filter_by(id=from_id).first()
        to_account = session.query(Account).filter_by(id=to_id).first()
        
        # Обе операции выполнятся вместе
        from_account.balance -= amount
        to_account.balance += amount
        
        session.commit()  # Успех: обе операции записаны
    except Exception as e:
        session.rollback()  # Ошибка: откатываем ВСЕ операции
        print(f"Transfer failed: {e}")
    finally:
        session.close()

# Если произойдёт ошибка (сбой питания), деньги не потеряются

Без атомарности: "снимаем 100₽ со счёта A" успешна, но "добавляем 100₽ на счёт B" падает → деньги исчезли.

C — Consistency (Согласованность)

Определение: БД переходит из одного согласованного состояния в другое. Все правила и ограничения сохраняются.

# Правило: баланс не может быть отрицательным
class Account(Base):
    __tablename__ = 'accounts'
    id = Column(Integer, primary_key=True)
    balance = Column(Integer, CheckConstraint('balance >= 0'))  # Правило БД

# Попытка снять больше, чем есть
try:
    account = session.query(Account).get(1)
    account.balance -= 1000  # На счёте только 500
    session.commit()  # БД отклонит это! CheckConstraint нарушен
except Exception:
    session.rollback()  # Состояние осталось согласованным

Консистентность гарантирует, что невозможны "неправильные" состояния БД.

I — Isolation (Изолированность)

Определение: Одновременные транзакции не влияют друг на друга. Результат выполнения n транзакций одновременно = результату их последовательного выполнения.

# Проблема без изоляции (грязное чтение)
# Транзакция 1: читает баланс = 100
# Транзакция 2: меняет баланс на 200
# Транзакция 1: читает баланс = 200 (противоречие!)

# Решение: уровни изолированности
# 1. READ UNCOMMITTED — видим незафиксированные изменения (грязное чтение)
# 2. READ COMMITTED — видим только зафиксированные данные
# 3. REPEATABLE READ — повторное чтение даст одинаковый результат
# 4. SERIALIZABLE — транзакции выполняются как последовательно

session = Session()
session.connection().execution_options(isolation_level="REPEATABLE READ")

# Теперь эта транзакция защищена
account = session.query(Account).filter_by(id=1).first()
balance_first = account.balance  # 100

# Другая транзакция изменяет баланс

balance_second = account.balance  # Всё ещё 100, не 200!

D — Durability (Долговечность)

Определение: Если транзакция зафиксирована (committed), данные сохраняются постоянно, даже при сбое системы.

# После commit() даже при отключении питания данные сохранятся
session.commit()  # Точка невозврата
# Система сбилась — но данные уже на диске

# Механизм: Write-Ahead Logging (WAL)
# 1. Записываем в лог (диск) ДО фиксации
# 2. Фиксируем транзакцию
# 3. При восстановлении восстанавливаем из логов

Примеры нарушений

# ✗ Нарушение A (Atomicity)
delete_user(user_id=5)  # Сбой
# Пользователь удалён, но его комментарии остались (orphaned records)

# ✗ Нарушение C (Consistency)
account.balance = -1000  # Отрицательный баланс! Неправильное состояние

# ✗ Нарушение I (Isolation)
# Транзакция 1 видит незафиксированные изменения транзакции 2

# ✗ Нарушение D (Durability)
insert_record()
commit()
# Сбой ОС → запись потеряна (если нет WAL)

ACID в Python приложении

from sqlalchemy import create_engine, event
from sqlalchemy.orm import sessionmaker

# Настройка для максимальной надёжности
engine = create_engine(
    'postgresql://...',
    isolation_level="SERIALIZABLE",  # Самый строгий уровень
    pool_pre_ping=True,  # Проверяем соединение перед использованием
)

Session = sessionmaker(bind=engine)

def safe_transaction(func):
    """Декоратор для безопасных транзакций"""
    def wrapper(*args, **kwargs):
        session = Session()
        try:
            result = func(session, *args, **kwargs)
            session.commit()  # Commit = фиксируем
            return result
        except Exception as e:
            session.rollback()  # Откатываем при любой ошибке
            raise e
        finally:
            session.close()
    return wrapper

@safe_transaction
def transfer_between_accounts(session, from_id, to_id, amount):
    from_account = session.query(Account).get(from_id)
    to_account = session.query(Account).get(to_id)
    
    from_account.balance -= amount
    to_account.balance += amount
    # session.commit() вызовется автоматически

Компромисс: BASE вместо ACID

Для высокой доступности некоторые системы используют BASE (Basically Available, Soft state, Eventually consistent):

# ACID: консистентно, но медленно
# BASE: быстро, но с временной несогласованностью
# NoSQL часто использует BASE (MongoDB, Cassandra)

Заключение

ACID — это гарантии, которые обеспечивают надёжность и корректность. Все реляционные БД (PostgreSQL, MySQL, SQLite) полностью поддерживают ACID. Это критично для систем, где важна целостность данных (банки, заказы, платежи).