У нас есть мультитенантное приложение SaaS, использующее стратегию «мультисхемы», то есть у каждого клиента есть выделенная схема в одном экземпляре базы данных. Мы используем MS SQL Server в качестве базы данных, которая переключается между схемами посредством настройки «схемы по умолчанию» для «пользователей» SQL Server. Например, клиенты A, B и C настроены в SQL Server следующим образом:
- Клиент A:
user_A
со схемой по умолчаниюschema_A
- Клиент Б:
user_B
со схемой по умолчаниюschema_B
- Клиент C:
user_C
со схемой по умолчаниюschema_C
... и так далее.
В нашем приложении мы переключаем соединение с источником данных так, чтобы оно указывало на правильную схему для каждого клиента, устанавливая «пользователя» SQL Server в соединении, выполняя следующий SQL перед каждым запросом:
EXECUTE AS USER = 'user_A';
Это создает некоторые проблемы для нас при попытке использовать Flyway для управления состоянием версий схемы - глобальным образом. Поскольку поддержка схемы flyway принимает только список имен схем, это не работает для MS SQL Server. Flyway выполняет миграции по схеме по умолчанию пользователя, предоставленной с конфигурацией DataSource; что в случае с SQL Server «пользователь» должен варьироваться в зависимости от клиента / схемы.
В идеале у нас должен быть обратный вызов типа FlywayCallback.beforeEachSchemaMigrate(Connection)
, который позволит нам установить желаемый пользовательский контекст для каждой схемы, выполняя оператор «Выполнить как пользователь» перед каждой миграцией для каждой схемы. Не знаете, почему этого крючка нет?
Еще один недостаток пролетного пути - это соглашение об использовании первой схемы в списке схем в качестве той, которая содержит таблицу schema_version
. Это нежелательно в многопользовательской среде на базе SQL Server. Поскольку мы не можем предположить, что схема, содержащая schema_version
таблицу, также является реальной схемой клиента. Имейте в виду, что в приложении SaaS, таком как наше, схемы для каждого арендатора / клиента создаются / уничтожаются на лету. Когда пользователь регистрируется, часть процесса подготовки создает новую схему на основе некоторых соглашений. Итак, список схем динамичен для нас.
В идеале мы можем указать Flyway использовать данную схему для создания таблицы schema_version
, не пытаясь выполнить миграции по этой схеме. Обычно это схема dbo
(которая является схемой по умолчанию в SQL Server). Мы используем схему dbo для хранения таблиц, которые являются глобальными по своей природе для всех клиентов, schema_version будет считаться глобальной таблицей.
В итоге после успешной миграции наша база данных должна выглядеть следующим образом:
- dbo.schema_version
- schema_A.my_tables
- schema_B.my_tables
- schema_C.my_tables
Все вышеперечисленные схемы находятся в одном «состоянии», продиктованы и контролируются dbo.schema_version
таблицей.
Возможно ли это сейчас?