我有几个客户使用的数据库。我真的不希望代理增量键值在客户端之间流血。我希望编号从 1 开始并且是特定于客户的。
我将使用由两部分组成的复合键tenant_id
以及增量 id。
为每个租户创建增量密钥的最佳方法是什么?
我正在使用 SQL Server Azure。我担心锁定表、重复键等。我通常会将主键设置为 IDENTITY 并继续前进。
谢谢
我有几个客户使用的数据库。我真的不希望代理增量键值在客户端之间流血。我希望编号从 1 开始并且是特定于客户的。
我将使用由两部分组成的复合键tenant_id
以及增量 id。
为每个租户创建增量密钥的最佳方法是什么?
我正在使用 SQL Server Azure。我担心锁定表、重复键等。我通常会将主键设置为 IDENTITY 并继续前进。
谢谢
您是否计划在未来使用 SQL Azure 联合?如果是这样,当前版本的 SQL Azure 联合不支持将 IDENTITY 用作聚集索引的一部分。有关更多详细信息,请参阅在 SQL Azure(联合)中将 guid 用作表上的聚集索引有哪些替代方法。
如果您还没有看过联邦,您可能想看看它,因为它提供了一种有趣的方式来分片数据库和数据库内的租户隔离。
根据您的最终目标,使用联合,您可能能够使用 GUID 作为表上的主聚集索引,还可以使用表上的增量 INT IDENTITY 字段。这个 INT IDENTITY 字段可以显示给最终用户。如果您在 TenantID 上进行联合,则每个“租户表”实际上都变成了一个筒仓(至少据我所知),因此在该表中的字段上使用 IDENTITY 将有效地成为一个不断增加的自动生成值,该值在给定租户内递增.
当 \ 如果数据合并在一起(合并来自多个租户的数据)时,您最终会在此 INT IDENTITY 字段上发生冲突(因此为什么不支持 IDENTITY 作为联邦中的主键)但只要您不使用它字段作为整个系统中的唯一标识符,您应该没问题。
如果您希望复制在插入时自动分配唯一 INT 键的便利性,您可以添加一个INSTEAD OF INSERT
触发器,该触发器使用现有列 +1 的 MAX 来确定下一个值。
如果具有标识值的列是索引中的第一个键,则 MAX 查询将是一个简单的索引查找,非常高效。
事务将确保分配唯一值,但这种方法将具有与标准标识列不同的锁定语义。IIRC,SQL Server 可以为并行请求它的每个事务分配不同的标识值,如果事务回滚,分配给它的值将被丢弃。MAX 方法一次只允许一个事务向表中插入行。
一种相关的方法可能是拥有一个由表名、租户 ID 和当前身份值作为键的专用键值表。它需要相同的INSTEAD OF INSERT
触发器和更多的样板来查询并保持该键表的更新。但它不会改善并行操作;锁将只是在不同表的记录上。
解决锁定瓶颈的一种可能性是将当前 SPID 包含在密钥的值中(现在标识密钥是顺序 int 和发生分配它的任何 SPID 的组合,而不是简单的顺序),使用专用标识值表并插入必要时按 SPID 记录;身份表 PK 将是(表名、租户、SPID),并且有一个具有当前顺序值的非键列。这样,每个 SPID 将拥有自己的动态分配的身份池,并且只会锁定自己的 SPID 特定记录。
另一个缺点是维护触发器,每当您更改任何特殊身份表中的列时,这些触发器都必须更新。