sql-server - 如何在 Multi-Tenancy 数据库中最好地生成唯一的用户编号而不会重复

标签 sql-server sql-server-2008

背景:

这是一个 Multi-Tenancy 应用程序,因此普通身份列将不起作用。所有表都有一个唯一的客户端标识符 Clients.id。所以每个客户可以有很多客户。为简单起见,下面不包括此列。

我们希望生成一个从 1000 开始的唯一客户编号。

我们将当前(最后)生成的数字存储在名为 Master 的表中。 .比方说 Master.CustomerNumber .所以数字会变成 1001、1002 等,最后一个存储在那里。

所以每次我们添加一个客户时,我们都会有一个查询来查找当前值,增加它,然后将它插入到 Customer.Number 中。 .

注意:我们使用的是 SQL Server 2008。我们在一个集群中有多个服务器。

确保如果同时添加两个客户,每个客户都获得唯一客户编号的最佳方法是什么?存储过程、锁定、CFLOCKING?

我如何确保这个进程是“单线程”的,并且不会发出两次相同的数字?

我确实在 Customer.Number+Clients.id 上有一个唯一索引.我对如何在生成时保证唯一性的实现感兴趣。

最佳答案

我没有审查现有的解决方案,因为它们很长而且很复杂。以下不就是你所需要的吗?

CREATE TABLE MasterDB.dbo.Sequences (ClientId INT NOT NULL PRIMARY KEY, LastGeneratedNumber INT NOT NULL)

DECLARE @nextId INT; //Holds the newly allocated ID

UPDATE MasterDB.dbo.Sequences
SET LastGeneratedNumber = LastGeneratedNumber + 1, @nextId = LastGeneratedNumber + 1
WHERE ClientId = 1234

这在任何隔离级别和任何索引结构下都是正确的。保存 ID 信息的行将被引擎锁定为 U 或 X。

如果从未生成过 ID,则此更新语句将不会执行任何操作。您可以使用 MERGE 来解决这个问题或通过使用控制流。我推荐 MERGE .

或者,每当您创建新客户端时插入一行。套装LastGeneratedNumber = 1000 - 1 .

无需使用存储过程,但您当然可以。从应用程序批量执行此 T-SQL 几乎没有性能差异。做对你来说更方便的事情。

如果您将此 T-SQL 作为主事务的一部分,则 ID 分配将是事务性的。它可能会回滚,并将序列化客户创建。如果您不喜欢那样,请使用单独的事务。但是,这样 ID 可能会丢失。这在任何解决方案中都是不可避免的。
UPDATE 的变体上面给出的是:
UPDATE MasterDB.dbo.Sequences
SET LastGeneratedNumber = LastGeneratedNumber + 1
OUTPUT INSERTED.LastGeneratedNumber
WHERE ClientId = 1234

您可以为每个客户端使用一个序列。这要求您的应用程序执行 DDL。这可能很尴尬。此外,您不能使 ID 生成具有事务性。控制较少。我不建议这样做,但这是可能的。

关于sql-server - 如何在 Multi-Tenancy 数据库中最好地生成唯一的用户编号而不会重复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37419447/

相关文章:

sql - 将 COUNT 与多个表一起使用

sql-server - 系统.Data.SqlClient.SqlException(0x80131904): Incorrect syntax near ')'

sql-server-2008 - SQL Server 2008 View 中允许的最大列数是多少?

sql - 向表添加新列的脚本

sql-server - 返回未阻止 sql server 的用户的行

sql-server - 如何将超过 8000 个字符的 XML 字段转换为字符串?

sql - 获取 SQL 结果到变量

sql - 是否有可能在同一触发器运行中混合更新和插入?

visual-studio-2008 - 如何使SSIS约束线保持整洁?

sql - SQL Server如何获取一个巨大字段的内容?