【问题标题】:Best approach for multi-tenant primary keys多租户主键的最佳方法
【发布时间】:2012-12-19 06:05:46
【问题描述】:

我有几个客户使用的数据库。我真的不希望代理增量键值在客户端之间流血。我希望编号从 1 开始并针对特定客户。

我将使用 tenant_id 的两部分组合键以及增量 ID。

为每个租户创建增量密钥的最佳方法是什么?

我正在使用 SQL Server Azure。我担心锁定表、重复键等。我通常会将主键设置为 IDENTITY 并继续。

谢谢

【问题讨论】:

  • “我真的不希望代理增量键值在客户端之间流失......”我很好奇,你为什么不希望这种情况发生?
  • 主要是因为它会让人们知道我正在处理多少行,在我的乌托邦世界中,它们应该完全相互隔离
  • 事实上,您可以同时拥有 - 参考完整性的代理主键(对客户隐藏)和两列唯一索引,例如:(Cust_id, Order_Number)
  • 非常正确。我会再考虑一下。不确定它是否感觉完全正确,但绝对是一个想法。谢谢
  • 您也可以使用GUID/UUID,并且键后面没有任何隐含含义。

标签: sql primary-key multi-tenant


【解决方案1】:

您是否计划在未来使用 SQL Azure 联合?如果是这样,当前版本的 SQL Azure 联合不支持将 IDENTITY 用作聚集索引的一部分。有关详细信息,请参阅此What alternatives exist to using guid as clustered index on tables in SQL Azure (Federations)

如果您还没有看过联邦,您可能想看看它,因为它提供了一种有趣的方式来分片数据库和数据库内的租户隔离。

根据您的最终目标,使用联合,您可以使用 GUID 作为表上的主聚集索引,还可以使用表上的增量 INT IDENTITY 字段。这个 INT IDENTITY 字段可以显示给最终用户。如果您在 TenantID 上进行联合,则每个“租户表”实际上都变成了一个筒仓(至少据我所知),因此在该表中的字段上使用 IDENTITY 将有效地成为一个不断增加的自动生成值,该值在给定租户内递增.

当 \ 如果数据被合并在一起(合并来自多个租户的数据),你最终会在这个 INT IDENTITY 字段上发生冲突(因此为什么不支持 IDENTITY 作为联邦中的主键)但只要你是' t 使用此字段作为整个系统中的唯一标识符,您应该没问题。

【讨论】:

    【解决方案2】:

    如果您希望复制在插入时自动分配唯一 INT 键的便利性,您可以添加一个 INSTEAD OF INSERT 触发器,该触发器使用现有列 +1 的 MAX 来确定下一个值。

    如果具有标识值的列是索引中的第一个键,则MAX查询将是一个简单的索引查找,非常高效。

    事务将确保分配唯一值,但这种方法将具有与标准标识列不同的锁定语义。 IIRC,SQL Server 可以为并行请求它的每个事务分配不同的标识值,如果事务回滚,分配给它的值将被丢弃。 MAX 方法一次只允许一个事务向表中插入行。

    一种相关的方法可能是拥有一个由表名、租户 ID 和当前身份值作为键的专用键值表。它将需要相同的INSTEAD OF INSERT 触发器和更多样板来查询并保持该键表的更新。但它不会改善并行操作;锁将只是在不同表的记录上。

    解决锁定瓶颈的一种可能性是将当前 SPID 包含在密钥的值中(现在标识密钥是顺序 int 和发生分配它的任何 SPID 的组合,而不是简单的顺序),使用专用标识值根据需要在每个 SPID 表和插入记录;身份表 PK 将是(表名、租户、SPID)并且有一个具有当前顺序值的非键列。这样,每个 SPID 将拥有自己的动态分配的身份池,并且只会锁定自己的 SPID 特定记录。

    另一个缺点是维护触发器,每当您更改任何特殊标识表中的列时,这些触发器都必须更新。

    【讨论】:

      猜你喜欢
      • 2017-01-07
      • 2018-04-06
      • 2011-04-16
      • 2019-05-16
      • 1970-01-01
      • 2014-05-31
      • 2012-05-26
      • 2015-08-21
      • 1970-01-01
      相关资源
      最近更新 更多