考虑到SQL Azure Federations不支持IDENTITY属性或序列,在插入记录时生成序列号的有效方法是什么?
例如,给定一个包含以下列的表:
CREATE TABLE [dbo].[Orders] (
[TenantId] [uniqueidentifier] NOT NULL,
[OrderId] [uniqueidentifier] NOT NULL,
[OrderNumber] [int] NOT NULL
CONSTRAINT [PK_Orders] PRIMARY KEY CLUSTERED (
[TenantId] ASC,
[OrderId] ASC
)
) FEDERATED ON ([FederationKey] = [TenantId])对于为给定租户插入的每个订单,OrderId都应递增。例如,对于tentant,A OrderId将是1,2,3...对于租户B,OrderId也是1,2,3...以一个独立的序列。理想情况下,应该没有空隙。
TenantId和OrderId是主键的组件。它们的值是由应用程序设置的,它们与生成序列的问题无关;只有OrderId具有具有业务意义的序列号。此外,TenantId是联盟的分发密钥。
This MSDN Blog article在选项1中描述了一种方法,该方法具有保存序列的表,并在隔离事务中使用存储过程来递增序列。每个租户在这个表上都有一条记录,记录了序列的最后一次使用值。
考虑到可伸缩性、争用、资源锁定,这是最好的方法吗?考虑到SQL Azure Federations的局限性,还有其他有用的技巧吗?
发布于 2012-03-12 10:42:38
这里有两个额外的想法。
一种方法是让一个单独的流程更新该字段,使其成为异步的,如果这对于您的业务场景是可能的话。对于这种方法,您需要让OrderNumber字段接受空值。为了知道哪个顺序最先出现,以便它获得正确的OrderNumber,我还添加了一个InsertedDate字段。如果您有多个工作者角色执行此冗余职责,则异步处理将变得更加复杂,在这种情况下,您将需要让每个进程为自己分配它正在处理的记录(因此您还需要一个OwnedBy字段),在更新期间添加一个并发测试以确保每个进程在其自己的记录上执行,并在进程崩溃时使记录的分配过期(因此您还需要一个AssignedOn字段),以便它不会留下孤立的记录。并不是那么微不足道。
然后你有穷人的方法..。当恒星排列得足够好时,这可能就是你所需要的。如果您愿意使用乐观并发方法,请尝试在插入过程中使用下一个数字(首先为给定的TenantId和OrderId选择最大OrderNumber ),然后执行插入。如果插入失败(因为您在TenantId上添加了唯一索引,为此在OrderNumber上添加了唯一索引),那么只需在OrderNumber中添加1即可。这里真正的问题是重试的频率和这种方法失败的可能性。如果您有一个相对精简的业务流程,这实际上可能永远不会失败;但是,如果您有从多个途径不断添加的订单,这可能是一个不可接受的方法。
https://stackoverflow.com/questions/9642916
复制相似问题