Top.Mail.Ru
Стримы и интерактивные транзакции | Tarantool
Tarantool
Узнайте содержание релиза 2.8
Стримы и интерактивные транзакции

Стримы и интерактивные транзакции

Начиная с версии v. 2.10.0-beta1, в iproto реализованы стримы и интерактивные транзакции.

Стрим
Стрим поддерживает мультиплексирование нескольких транзакций в рамках одного соединения. Все запросы в стриме выполняются строго последовательно, что позволяет проводить интерактивные транзакции.

Стрим передает данные по протоколу между клиентом и сервером. Это понятие не связано с потоками выполнения, реализующими многозадачность внутри программ.

Интерактивная транзакция
Интерактивной называется транзакция, которую не обязательно отправлять целиком в рамках одного запроса. begin, commit и другие TX-инструкции могут быть отправлены и выполнены в разных запросах.

Основное предназначение стрима — выполнение транзакций внутри потока iproto. У каждого стрима есть идентификатор, уникальный в рамках соединения. Все запросы с одинаковым ненулевым идентификатором стрима относятся к одному стриму. Запросы в стриме выполняются синхронно. Следующий запрос не начинает выполняться, пока не завершится предыдущий. Если идентификатор стрима запроса равен 0, то этот запрос не привязан к какому-либо стриму и обрабатывается обычным способом.

В net.box стрим представляет собой объект над соединением, который имеет те же методы, но позволяет выполнять запросы последовательно. Идентификатор генерируется автоматически на стороне клиента. Пользователь может также создать собственный коннектор с поддержкой стримов. Используя стримы с пользовательским коннектором, необходимо передавать stream_id через протокол iproto.

Поскольку каждый стрим может запустить транзакцию, одно соединение способно мультиплексировать несколько транзакций. Начать транзакцию, сделать ее коммит и отменить ее можно, используя с синтаксисом SQL-транзакций методы стрима: call, eval, execute. Пользователь может комбинировать эти методы. Например, можно начать транзакцию с помощью stream:begin(), а коммит провести, используя stream:call('box.commit') или stream:execute('COMMIT'). Все запросы между stream:begin() и stream:commit() выполняются в рамках одной транзакции. Если один запрос во время транзакции завершится ошибкой, на остальные запросы это не повлияет. Если во время активной транзакции в стриме произойдет сбой подключения, эта транзакция будет отменена, если она не прошла коммит до сбоя.

Пример:

local conn = net_box.connect(remote_server_addr)
local conn_space = conn.space.test
local stream = conn:new_stream()
local stream_space = stream.space.test

-- Начать транзакцию через поток iproto:
stream:begin()
space:replace({1})

-- Пустой select, коммит транзакции не выполнен.
-- Ее нельзя увидеть из запросов, не относящихся
-- к транзакции.

-- Метод select возвращает ранее вставленный кортеж,
-- так как этот кортеж относится к транзакции:
conn_space:select{}
stream_space:select({})

-- Коммит транзакции:
stream:commit()

-- Теперь и этот select возвращает кортеж, так как транзакция прошла коммит:
conn_space:select{}