Миграции
Миграцией называется любое изменение схемы данных: добавление/удаление поля, добавление/удаление индекса, изменение формата поля и т. д.
В Tarantool есть только два вида миграции схемы, при которых не нужно мигрировать данные:
- добавление поля в конец спейса
- добавление индекса
Примечание
Check the Upgrading space schema section.
With the help of space:upgrade()
,
you can enable compression and migrate, including already created tuples.
Добавление поля происходит следующим образом:
local users = box.space.users
local fmt = users:format()
table.insert(fmt, { name = 'age', type = 'number', is_nullable = true })
users:format(fmt)
Обратите внимание: поле обязательно должно иметь параметр is_nullable
. Иначе произойдет ошибка.
После создания нового поля, вы, вероятно, захотите заполнить его данными. Для этой задачи удобно использовать модуль tarantool/moonwalker. В README есть описание того, как начать его использовать.
Про добавление индекса рассказывается в описании метода space_object:create_index().
Остальные виды миграций также возможны, однако поддерживать консистентность данных при этом сложнее.
Миграции можно выполнять в двух случаях:
- при старте Tarantool, пока ни один клиент еще не использует БД
- в процессе обработки запросов, когда у БД уже есть активные клиенты
Для первого случая достаточно кода миграции, который будет написан и оттестирован. Самая сложная задача — это провести миграцию данных при наличии активных клиентов. Это необходимо иметь в виду при начальном проектировании схемы данных.
Мы выделяем следующие проблемы при наличии активных клиентов:
- Связанные данные могут атомарно изменяться.
- Нужно уметь отдавать данные как по новой схеме, так и по старой.
- Когда данные перемещают в новый спейс, доступ к данным должен учитывать, что данные могут быть как в одном спейсе, так и в другом.
- Запросы на запись не должны мешать корректной миграции. Типичный подход: всегда писать по новой схеме.
Эти проблемы могут быть или не быть релевантными в зависимости от вашего приложения и требований к его доступности.
В Tarantool есть механизм транзакций. Он полезен при написании миграции, так как позволяет атомарно работать с данными. Но перед использованием механизма транзакций нужно знать об ограничениях.
Подробнее о них описано в разделе про транзакции.
Код миграций исполняется на запущенном инстансе Tarantool. Важно: ни один способ не гарантирует вам транзакционное применение миграций на всем кластере.
Способ 1: написать миграции в коде основного приложения
Это довольно просто: когда вы перезагружаете код, в нужный момент происходит миграция данных и схема базы данных обновляется. Однако такой способ может подойти не всем. У вас может не быть возможности перезапустить Tarantool или обновить код через механизм горячей перезагрузки (hot reload).
Способ 2: tarantool/migrations (только для кластера на Tarantool Cartridge)
Про этот способ подробнее написано в README самого модуля tarantool/migrations.
Примечание
Есть также два способа, которые мы не рекомендуем использовать, но вы можете найти их полезными по тем или иным причинам.
Method 3: the tt utility
Connect to the necessary instance using tt connect
.
$ tt connect admin:password@localhost:3301
Если ваша миграция написана в Lua файле, вы можете исполнить его с помощью функции
dofile()
. Вызовите ее и первым аргументом укажите путь до файла с миграцией. Выглядит это вот так:tarantool> dofile('0001-delete-space.lua') --- ...
(или) можно скопировать код скрипта миграции, вставить его в консоль и применить.
You can also connect to the instance and execute the migration script in a single call:
$ tt connect admin:password@localhost:3301 -f 0001-delete-space.lua
Способ 4: применение миграции с помощью Ansible
Если вы используете Ansible-роль для развёртывания кластера Tarantool, то вы можете применить eval
. Прочитать подробнее про eval
можно в документации по Ansible-роли.