Комментарии 7
Спасибо за статью. У меня есть один м-м-м глупый (для меня) вопрос. Почему запущенный select нельзя прервать? Что там за магия происходит, что мы не можем прервать чтение всех данных, если мы случайно ошиблись?
То, что по памяти упадёт процесс мне понятно, но почему чтение прервать нельзя?
Извините, что задал один и тот же вопрос три раза, просто меня это очень сильно поразило.
В Tarantool однопоточный асинхронный менеджер транзакций (запросов). Запросы выполняются в файберах (аналог корутин) — кооперативно. То есть в один момент времени выполняется только один запрос. Запрос select(nil) выполняется от начала и до конца — не выполняя прерываний и передачи управления другим запросам. Исторически это было сделано для того, чтобы в момент запроса к данным, не выполнялся другой запрос, который может эти данные перезаписать.
Я правильно понимаю, что «изолированность» в Tarantool обеспечена однопоточностью? Мне опять стало любопытно, а другим способом этого добиться можно?
да - смотрите механизмы других бд - версионность(постгрес), read_commited и другие... Просто тут это реализовали именно так, со всеми плюсами и минусами.
В Tarantool есть mvcc, подробнее можно здесь почитать: https://www.tarantool.io/ru/doc/latest/book/box/atomic/transaction_model/#isolation-level
Спасибо за статью.
Мало опыта с Tarantool, не понял ваш пример в главе "Неструктурированные данные".
В обоих случаях мы ищем по ключу key, в обоих случаях бегаем по данным и ищем по Name. Так а в чем отличие, почему второй вариант быстрее?
Смотрите, отличие в используемых структурах данных, в первом случае это Lua-table, которая создавалась для хранения любых типов данных и делает дополнительные проверки на типы, что получается более медленно, чем второй вариант:
for i = 1, 1000 do
local v = tuple.data[i] -- чтение поля таблицы
if v.name == 'name' then -- чтение поля таблицы
v.value = v.value + 1 -- чтение поля таблицы
end
tuple.data[i] = v -- запись поля таблицы
end
Во втором случае это обращение к полю структуры Tarantool tuple, который оптимизирован для получения данных с учетом формата + мы обходим данные по отдельному индексу:
for _, v in box.space.storage2:pairs({'key'}) do
if v.name == 'name' then -- чтения поля тапла
box.space.storage2:update({v.key, v.pos}, {{'+', 'value', 1}}) -- запись в тапл
end
end
Возможно, здесь еще сыграет роль объем данных (в первом случае мы должны перезаписать весь массив из 1000 элементов, во втором - только те элементы "массива", которые поменялись, но это не точно, можно побенчить.
Про Луа таблицы можно почитать здесь: https://habr.com/ru/company/vk/blog/493642/
Про индексы - здесь: https://habr.com/ru/company/vk/blog/505880/
Ну и вообще можно еще сюда посмотреть, тут пример того, как мы отказались от Lua-таблиц в пользу C structure: https://habr.com/ru/company/vk/blog/529456/
Топ-5 провальных решений при разработке на Tarantool