Версия:

Управление экземплярами

Управление экземплярами

Общие сведения

Чтобы получить общую информацию и взглянуть на примеры использования, см. раздел Управление транзакциями.

Соблюдайте следующие правила в работе с транзакциями:

Правило #1

Запросы в транзакции должны отправляться на сервер в виде единого блока. Недостаточно просто размещать их между началом транзакции и коммитом или откатом. Чтобы убедиться, что они отправляются в виде единого блока: поместите их в функцию, поместите их на одну строку или используйте символы-разделители, чтобы многостроковые запросы обрабатывались совместно.

Правило #2

Все операции с базой данных в рамках транзакции должны работать с одним движком баз данных. Небезопасно в рамках одной транзакции получать доступ к наборам кортежей, которые определяются по {engine='vinyl'}, а также к наборам кортежей, которые определяются по {engine='memtx'}.

Правило #3

Нельзя использовать запросы, которые могут приводить к изменению определения данных – создание, изменение, удаление, очистка.

Индекс

Ниже приведен перечень всех функций для управления транзакциями.

Имя Использование
box.begin() Начало транзакции
box.commit() Окончание транзакции и сохранение всех изменений
box.rollback() Окончание транзакции и отмена всех изменений
box.savepoint() Получение дескриптора точки сохранения
box.rollback_to_savepoint() Запрещение окончания транзакции и отмена всех изменений, сделанных после точки сохранения
box.atomic() Выполнение функции как транзакции
box.on_commit() Define a trigger that will be activated by box.commit
box.on_rollback() Define a trigger that will be activated by box.rollback
is_in_txn() State whether a transaction is in progress
box.begin()

Начало транзакции. Отключение неявной передачи управления до окончания транзакции. Сигнал о записи в :ref :журнал упреждающей записи <internals-wal> будет задержан до окончания транзакции. Фактически файбер, который выполняет функцию box.begin(), начинает «активную транзакцию со множеством запросов» с блокировкой всех остальных файберов.

возвращается:error if this operation is not permitted because there is already an active transaction.
возвращается:error if for some reason memory cannot be allocated.
box.commit()

Окончание транзакции и применение результатов всех операций по изменению данных.

возвращается:error and abort the transaction in case of a conflict.
возвращается:error if the operation fails to write to disk.
возвращается:error if for some reason memory cannot be allocated.
box.rollback()

Окончание транзакции, но отмена результатов всех операций по изменению данных. Явный вызов функций не из модуля box.space, которые всегда передают управление, например fiber.sleep() или fiber.yield(), приведет к тому же результату.

box.savepoint()

Возврат дескриптора точки сохранения (тип = таблица), который может затем использоваться в box.rollback_to_savepoint(savepoint). Точки сохранения могут быть созданы, пока активна транзакция, и удаляются после окончания транзакции.

возвращается:savepoint table
тип возвращаемого значения:
 Lua-объект.
возвращается:error if the savepoint cannot be set in absence of active transaction.
возвращается:error if for some reason memory cannot be allocated.
box.rollback_to_savepoint(savepoint)

Запрещение окончания транзакции, но отмена всех изменений и операций box.savepoint(), сделанных после точки сохранения.

возвращается:error if the savepoint cannot be set in absence of active transaction.
возвращается:error if the savepoint does not exist.

Пример:

function f()
    box.begin()           -- start transaction
    box.space.t:insert{1} -- this will not be rolled back
    local s = box.savepoint()
    box.space.t:insert{2} -- this will be rolled back
    box.rollback_to_savepoint(s)
    box.commit()          -- end transaction
  end
box.atomic(function-name[, function-arguments])

Выполнение функции так, как будто функция начинается с явного вызова box.begin() и заканчивается неявным вызовом box.commit() после успешного выполнения или же заканчивается неявным вызовом box.rollback() в случае ошибки.

возвращается:the result of the function passed to atomic() as an argument.
возвращается:any error that box.begin() and box.commit() can return.
box.on_commit(trigger-function[, old-trigger-function])

Define a trigger for execution when a transaction ends due to an event such as box.commit.

The trigger function may take an iterator parameter, as described in an example for this section.

The trigger function should not access any database spaces.

If the trigger execution fails and raises an error, the effect is severe and should be avoided – use Lua’s pcall() mechanism around code that might fail.

box.on_commit() must be invoked within a transaction, and the trigger ceases to exist when the transaction ends.

Параметры:
  • trigger-function (function) – функция, в которой будет триггер
  • old-trigger-function (function) – существующая функция с триггером, которую заменит новая
возвращается:

nil или указатель функции

Если указаны параметры (nil, old-trigger-function), старый триггер будет удален.

Подробная информация о характеристиках триггера находится в разделе Триггеры.

Simple and useless example: this will display „commit happened“:

function f()
function f() print('commit happened') end
box.begin() box.on_commit(f) box.commit()

But of course there is more to it: the function parameter can be an ITERATOR.

The iterator goes through the effects of every request that changed a space during the transaction.

The iterator will have:

  • an ordinal request number,
  • the old value of the tuple before the request (this will be nil for an insert request),
  • the new value of the tuple after the request (this will be nil for a delete request),
  • and the id of the space.

Less simple more useful example: this will display the effects of two replace requests:

box.space.test:drop()
s = box.schema.space.create('test')
i = box.space.test:create_index('i')
function f(iterator)
  for request_number, old_tuple, new_tuple, space_id in iterator() do
    print('request_number ' .. tostring(request_number))
    print('  old_tuple ' .. tostring(old_tuple[1]) .. ' ' .. old_tuple[2])
    print('  new_tuple ' .. tostring(new_tuple[1]) .. ' ' .. new_tuple[2])
    print('  space_id ' .. tostring(space_id))
  end
end
s:insert{1,'-'}
box.begin() s:replace{1,'x'} s:replace{1,'y'} box.on_commit(f) box.commit()

The result will look like this:

tarantool> box.begin() s:replace{1,'x'} s:replace{1,'y'} box.on_commit(f) box.commit()
request_number 1
  old_tuple 1 -
  new_tuple 1 x
  space_id 517
request_number 2
  old_tuple 1 x
  new_tuple 1 y
  space_id 517
box.on_rollback(trigger-function[, old-trigger-function])

Define a trigger for execution when a transaction ends due to an event such as box.rollback.

The parameters and warnings are exactly the same as for box.on-commit.

box.is_in_txn()

If a transaction is in progress (for example the user has called box.begin and has not yet called either box.commit or box.rollback, return true. Otherwise return false.