Модель транзакций
Модель транзакций Tarantool соответствует свойствам ACID (атомарность, согласованность, изолированность, долговечность).
В Tarantool предусмотрено два режима поведения транзакций:
- По умолчанию — подходит для быстрых монопольных атомарных транзакций
- MVCC — предназначен для длительных параллельных транзакций Каждая транзакция в Tarantool выполняется в одном файбере на одном потоке, видит согласованное состояние базы данных и фиксирует все изменения атомарно.
Все изменения транзакции записываются в WAL (Write Ahead Log) одной пакетной записью в определенном порядке во время фиксации изменений (коммита). При необходимости изменения транзакции можно откатить: полностью или до указанной точки сохранения (savepoint).
Таким образом, каждая транзакция в Tarantool имеет наивысший уровень изоляции транзакций — serializable.
По умолчанию уровень изоляции Tarantool — serializable.
Исключение составляет сбой при записи в WAL, который может возникнуть, например, при нехватке дискового пространства.
В этом случае уровень изоляции параллельной транзакции чтения будет read-committed.
В режиме MVСС доступно несколько параметров для настройки поведения видимости во время выполнения транзакции.
Уровень изоляции read-committed делает видимыми все транзакции, для
которых началась фиксация (был вызван box.commit()).
-
Транзакции записи с чтением
Ручное использование
read-committedдля транзакций записи с чтением полностью безопасно, так как такая транзакция в конечном итоге будет зафиксирована. Если предыдущая транзакция завершится с ошибкой, текущая транзакция также неизбежно завершится с ошибкой из-за уровня изоляции serializable. -
Транзакции чтения
Ручное использование
read-committedдля транзакций чтения может быть небезопасным, так как это может привести к фантомному чтению.
Уровень изоляции read-confirmed делает видимыми все транзакции, для
которых фиксация завершена (box.commit() вернул
управление). Это означает, что новые данные уже находятся на диске или
даже на других репликах.
-
Транзакции чтения
Использование
read-confirmedбезопасно для транзакций чтения при условии, что данные находятся на диске (для асинхронной репликации) или даже на других репликах (для синхронной репликации). -
Транзакции записи
Для достижения уровня
serializableлюбая транзакция записи должна читать все уже зафиксированные данные. В противном случае при фиксации может возникнуть конфликт.
Линеаризуемость операций чтения означает, что если ответ на запрос
записи был получен раньше, чем был отправлен запрос чтения, то этот
запрос чтения должен вернуть результаты запроса записи. При вызове с
параметром linearizable функция box.begin() передает
управление, пока экземпляр не получит достаточно данных от удаленных
узлов для уверенности в линеаризуемости транзакции.
Линеаризуемые транзакции могут выполнять запросы только к следующим типам memtx-спейсов:
- синхронные
- локальные (созданные с параметром
is_local = true) - временные (созданные с параметром
temporary = true)
Линеаризуемая транзакция может завершиться с ошибкой в следующих случаях:
- Если узлу не удается связаться с достаточным количеством удаленных узлов для определения того, какие данные зафиксированы.
- Если данные не получены в течение
timeout, заданного вbox.begin().
Для минимизации вероятности конфликтов в MVCC используется так
называемая видимость best-effort:
- для транзакций записи MVCC выбирает read-committed
- для транзакций чтения MVCC выбирает read-confirmed
Это неизбежно приводит к уровню изоляции serializable. Поскольку у MVCC нет возможности
проанализировать всю транзакцию целиком для принятия решения, выбор делается на первой операции.