我们有一个使用“多模式”策略的多租户 SaaS 应用程序,即每个客户在同一个数据库实例中都有专用的模式。我们使用 MS SQL Server 作为数据库,它通过 SQL Server“用户”的“默认模式”设置在模式之间切换。例如客户 A、B 和 C 在 SQL Server 中配置如下:
- 客户 A:
user_A
使用默认架构schema_A
- 客户 B:
user_B
使用默认架构schema_B
- 客户 C:
user_C
使用默认模式schema_C
……等等。
在我们的应用程序中,我们通过在每次查询之前执行以下 SQL 在连接上设置 SQL Server“用户”,将 DataSource 连接切换为指向每个客户的正确模式:
EXECUTE AS USER = 'user_A';
在尝试使用 Flyway 以全局方式管理模式版本的状态时,这给我们带来了一些问题。由于 flyway 的架构支持仅接受架构名称列表,因此这不适用于 MS SQL Server。Flyway 在 DataSource 配置提供的用户的默认模式上执行迁移;在 SQL Server 的情况下,“用户”需要因客户/模式而异。
理想情况下,我们会有一个这样的回调FlywayCallback.beforeEachSchemaMigrate(Connection)
,让我们通过在每个模式的每次迁移之前执行“以用户身份执行”语句来设置每个模式所需的用户上下文。不知道为什么没有那个钩子?
flyway 的另一个缺点是在模式列表中使用第一个模式的约定,作为持有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
表指示和控制。
这目前可能吗?