Ответ
Транзакция — это последовательность операций с базой данных, которая выполняется как единое целое: либо все операции успешно завершаются, либо ни одна из них не применяется. Основная цель транзакций — обеспечение целостности и согласованности данных.
Простой пример из жизни — банковский перевод. Операция состоит из двух действий: списание денег с одного счета и зачисление на другой. Если после списания произойдет сбой, а зачисления не будет, данные станут несогласованными. Транзакция гарантирует, что оба действия будут выполнены успешно, либо отменены вместе.
Свойства 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()
отменит списание, и баланс первого счета останется неизменным, сохраняя целостность данных.