租户的带外键约束的SQL模式设计

租户的带外键约束的SQL模式设计,sql,database,postgresql,database-schema,multi-tenant,Sql,Database,Postgresql,Database Schema,Multi Tenant,我正在设计一个用于多租户场景的数据库。 我最近了解到,为了确保相互引用的表之间的租户id是一致的,我需要表的主键同时包含表id和租户id。然后外键必须同时引用表id和租户id 这似乎按预期工作,但如果我有不引用租户的表怎么办?在下面的示例中,我有一个播放列表项目,它不直接引用租户。我在这里看到的一个问题是,playlist_项可能引用的内容与它所属的播放列表不具有相同的租户 一个可能的解决方案是将租户id包括到数据库中存在的所有表中,以便能够始终引用租户,但这对我来说似乎有点麻烦,因为playl

我正在设计一个用于多租户场景的数据库。 我最近了解到,为了确保相互引用的表之间的租户id是一致的,我需要表的主键同时包含表id和租户id。然后外键必须同时引用表id和租户id

这似乎按预期工作,但如果我有不引用租户的表怎么办?在下面的示例中,我有一个播放列表项目,它不直接引用租户。我在这里看到的一个问题是,playlist_项可能引用的内容与它所属的播放列表不具有相同的租户

一个可能的解决方案是将租户id包括到数据库中存在的所有表中,以便能够始终引用租户,但这对我来说似乎有点麻烦,因为playlist_项(在本例中)已经通过其与playlist的所有者关系具有隐含的租户id

我希望能够深入了解在这种情况下什么是一个好的解决方案,以及是否有任何替代方法可以实现相同的目标,而不存在数据不一致的潜在风险

(这只是一个示例,不是实际的数据库)


这里有两个基本选项

第一种方法是添加额外的外键和唯一约束,其中包括
tenant\u id
,如果您这样做,您可以确保整个系统都引用相同的tenant。如果要使用行级安全策略,请执行此操作,因为它将解决检查安全性时的一系列性能问题

在这种情况下,playlist将在
(id,租户id)
上有第二个唯一索引,playlist\u项将在
(playlist\u id,租户id)
上有一个外键引用该外键


您的第二个选项是将
租户id
放到可传递引用的位置。在这种情况下,您始终可以通过联接进行查找,但当绑定到使用行级安全性时,这种方式的性能很差。

引用的列(在外键关系中)必须始终在引用的表中形成唯一的键(主键或PostgreSQL中的唯一约束)。因此,您实际上无法创建上面的示例,除非
id
playlist
content
中的主键。如果它是唯一的约束,那么它“只是”主键的一部分就没有意义(因为它本身是唯一的)。换句话说:您应该决定哪些实体可以有重叠的ID(跨租户)。您的
用户
表f.ex。可能有。你是对的,我还需要在表id上有一个唯一的索引。结果是:主键(id,租户id)和唯一(id)。对吗?这在技术上是可能的,但主键应该始终是唯一的最小列集。因此,可以使用
id
作为主键创建表,并将
tenant\u id
包含到其中一些表中(如果它们可以通过另一个外键连接到租户,则不需要),或者在任何地方使用
id
+
tenant\u id
主键。