Потоки
Функциональность
потоков и интерактивных транзакций,
добавленная в Tarantool версии 2.10.0, обеспечивает две возможности:
последовательную обработку и чередование.
Последовательная обработка: При использовании потоков гарантируется, что серверный экземпляр не начнет обрабатывать следующий запрос в потоке, пока не завершит обработку предыдущего.
Чередование: Например, серия запросов может включать "begin для потока №1", "begin для потока №2", "insert для потока №1", "insert для потока №2", "delete для потока №1", "commit для потока №1", "rollback для потока №2".
Для работы с потоковыми транзакциями через iproto требуется следующее:
-
Движок должен быть vinyl или memtx с mvcc.
-
Клиент отвечает за то, чтобы идентификатор потока – беззнаковое целое число IPROTO_STREAM_ID – присутствовал в заголовке запроса. IPROTO_STREAM_ID может быть любым положительным 64-битным числом и должен быть уникальным для соединения. Если IPROTO_STREAM_ID равен нулю, серверный экземпляр игнорирует его.
Имя | Код | Описание |
|---|---|---|
0x0e | Начать транзакцию в указанном потоке | |
0x0f | Зафиксировать транзакцию в указанном потоке | |
0x10 | Откатить транзакцию в указанном потоке |
Код: 0x0e.
Начинает транзакцию в указанном потоке. См. stream:begin(). Тело запроса необязательно и может содержать два элемента:
IPROTO_TIMEOUT – необязательное время ожидания (в секундах). По истечении времени ожидания транзакция автоматически откатывается.
Код: 0x0f.
Фиксирует транзакцию в указанном потоке. См. stream:commit().
Код: 0x10.
Откатывает транзакцию в указанном потоке. См. stream:rollback().
Предположим, что клиент создал поток с помощью модуля net.box
net_box = require('net.box')conn = net_box.connect('localhost:3302')stream = conn:new_stream()
На этом этапе объект потока выглядит как копия объекта conn с одним
дополнительным полем: stream_id. Теперь, используя stream вместо conn,
клиент отправляет два запроса:
stream.space.T:insert{1}stream.space.T:insert{2}
Заголовок и тело этих запросов будут такими же, как в обычных (непотоковых) запросах IPROTO_INSERT, за исключением того, что заголовок будет содержать дополнительный элемент: IPROTO_STREAM_ID=0x0a со значением MP_UINT=0x01. В данном примере значение равно 1, поскольку каждый вызов conn:new_stream() назначает новый номер, начиная с 1.
Клиент выполняет потоковые транзакции, отправляя по порядку:
-
IPROTO_BEGIN с необязательным временем ожидания транзакции в поле IPROTO_TIMEOUT тела запроса.
-
Запросы на изменение данных и запросы на выборку в рамках транзакции.
-
IPROTO_COMMIT или IPROTO_ROLLBACK.
Все эти запросы должны содержать одинаковое значение IPROTO_STREAM_ID.
Откат выполняется автоматически при разрыве соединения или истечении времени ожидания транзакции до выполнения фиксации.
Таким образом, теперь доступно несколько способов работы с транзакциями:
с помощью net_box – stream:begin() и stream:commit() или
stream:rollback(), которые инициируют IPROTO_BEGIN и IPROTO_COMMIT или
IPROTO_ROLLBACK с текущим значением stream.stream_id; с помощью
box.begin() и box.commit() или
box.rollback(); с помощью SQL –
START TRANSACTION и COMMIT или
ROLLBACK. Приложение может использовать любой или все
эти способы.