Транзакции в распределённых системах

Материал из Викиконспекты
Версия от 20:25, 3 июня 2019; Yeputons (обсуждение | вклад) (Новая страница: «== Зачем == Пусть у нас есть несколько узлов (процессов), которых хранят какие-то ''непересе…»)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

Зачем

Пусть у нас есть несколько узлов (процессов), которых хранят какие-то непересекающиеся данные. Например, на одном узле хранятся банковские счета пользователей на "А", на другом — на "Б", и так далее.

Тогда мы можем хотеть транзакционно изменять данные на разных узлах (см. BEGIN TRANSACTION и COMMIT TRANSACTION в SQL).

Определение:
Транзакция — это единица работы над множеством элементов из базы данных, которую можно в процессе работы целиком отменить (либо сама база данных, либо пользователь, см. ROLLBACK TRANSACTION), либо подтвердить (база данных может иногда не справиться, тогда транзакция отменяется).

У транзакции обычно выделяют свойства по аббревиатуре ACID:

  1. Atomicity (атомарность) — транзакция либо полностью применила все свои изменения, либо полностью откатилась (отменилась)
  2. Consitency (согласованность) — в конце транзакции система находится в согласованном состоянии
  3. Isolation (изолированность) — параллельные транзакции не должны влиять друг на друга (например, при помощи phantom reads), а должны выполняться как будто последовательно
  4. Durability (надёжность) — завершённые (commited) транзакции сохраняются даже в случае сбоев и перезапуска системы

Атомарность и надёжность

Предположим, что нам нужны только атомарность и надёжность. Самое сложное — откатывать транзакцию, если что-то пошло не так. Есть два основных способа этого добиться.

Undo log

Каждый узел сначала записывает предыдущие значения в надёжный журнал (лог, обычно append-only и сохраняется на диск), а только потом изменяет состояние в памяти. Когда транзакция подтверждается, надо записать произведённые изменения в надёжное место и можно стереть кусок журнала. Если транзакцию надо откатить (например, после перезапуска системы в журнале нет записи "транзакция успешна"), то мы идём с конца журнала и восстанавливаем старые значения.

Redo log

Мы вообще не делаем изменения в данных до подтверждения транзакции, а просто пишем в журнал все операции, которые надо произвести с данными. Когда транзакция успешно завершается, у нас две опции:

  • Изменить данные прямо на диске.
  • Записать об этом в журнал на диск (append-only), а состояние просто каждый раз восстанавливать из этого журнала. Иногда делать checkpoint'ы для сохранения состояния. Это сейчас на практике популярнее.

Согласованность и изоляция