Что такое транзакции в базах данных и зачем они нужны

Ответ

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

Простой пример из жизни — банковский перевод. Операция состоит из двух действий: списание денег с одного счета и зачисление на другой. Если после списания произойдет сбой, а зачисления не будет, данные станут несогласованными. Транзакция гарантирует, что оба действия будут выполнены успешно, либо отменены вместе.

Свойства ACID

Надежность транзакций описывается акронимом ACID:

  • Atomicity (Атомарность): Гарантирует, что транзакция выполняется по принципу "все или ничего".
  • Consistency (Согласованность): Каждая успешная транзакция переводит базу данных из одного согласованного состояния в другое.
  • Isolation (Изолированность): Параллельно выполняющиеся транзакции не должны влиять друг на друга. Результат их одновременной работы должен быть таким же, как если бы они выполнялись последовательно.
  • Durability (Долговечность): Если транзакция успешно завершена, сделанные ею изменения сохранятся даже в случае сбоев системы (например, отключения питания).

Пример на Python и SQLite

import sqlite3

# Используем 'with' для автоматического закрытия соединения
with sqlite3.connect('bank.db') as conn:
    cursor = conn.cursor()
    sender_id = 1
    receiver_id = 2
    amount = 100

    try:
        # Явно начинаем транзакцию
        conn.execute('BEGIN TRANSACTION')

        # 1. Списание со счета отправителя
        cursor.execute(
            'UPDATE accounts SET balance = balance - ? WHERE id = ?',
            (amount, sender_id)
        )

        # 2. Зачисление на счет получателя
        cursor.execute(
            'UPDATE accounts SET balance = balance + ? WHERE id = ?',
            (amount, receiver_id)
        )

        # Если все операции успешны, подтверждаем изменения
        conn.commit()
        print("Перевод успешно выполнен!")

    except sqlite3.Error as e:
        # В случае любой ошибки откатываем все изменения
        conn.rollback()
        print(f"Ошибка! Транзакция отменена: {e}")

Если между двумя UPDATE произойдет ошибка, conn.rollback() отменит списание, и баланс первого счета останется неизменным, сохраняя целостность данных.