我需要创建一种创建唯一订单号的方法。每个订单号必须始终大于最后一个,但它们不应总是连续的。该解决方案必须在Web场环境中工作。
目前有一个存储过程,负责获取新的订单号,必须对其进行播种,以使订单号不连续。应用程序现在从单个服务器转移到Web场,因此通过使用C#中的锁来控制对存储过程的访问不再可行作为控制访问的方法。我已经更新了存储过程,但是我担心在发生并发调用时我会引入blocks \ locks \ deadlocks。
表和索引结构如下
MyAppSetting Table
CREATE TABLE [dbo].[MyAppSetting](
[SettingName] [nvarchar](255) NOT NULL,
[SettingValue] [nvarchar](max) NOT NULL,
CONSTRAINT [PK_MyAppSetting] PRIMARY KEY CLUSTERED
(
[SettingName] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
我的订单表
CREATE TABLE [dbo].[MyOrder](
[id] [int] IDENTITY(1,1) NOT NULL,
[OrderNumber] [nvarchar](50) NOT NULL CONSTRAINT [DF_MyOrder_OrderNumber] DEFAULT (N''),
... rest of the table
CONSTRAINT [PK_MyOrder] PRIMARY KEY NONCLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
Sql Transaction
Set Transaction Isolation Level Serializable;
Begin Transaction
--Gen random number
SELECT @Random = ROUND(((@HighSeed - @LowSeed -1) * RAND() + @LowSeed), 0)
--Get Seed
select @Seed = [SettingValue] FROM [MyAppSetting] where [SettingName] = 'OrderNumberSeed'
--Removed concurrency and not required as order numbe should not exceed the seed number
--select @MaxOrderNUmber = Max(OrderNumber) FROM MyOrder
--if @MaxOrderNumber >= @Seed Begin
-- Set @Seed = @MaxOrderNumber
--end
-- New Seed
Set @OrderNumber = @Seed + @Random
Update [MyAppSetting] Set [SettingValue] = @OrderNumber where [SettingName] = 'OrderNumberSeed'
select @OrderNumber
Commit
答案 0 :(得分:0)
使用修订后的SQL,您只需选择并更新一个表。您可以在单个查询中执行此操作,以避免死锁的风险,并避免显式事务的需要。
设定:
CREATE TABLE OrderNumber ( NextOrderNumber int)
INSERT OrderNumber(NextOrderNumber) values (123)
获取下一个订单号
DECLARE @MinIncrement int = 5
DECLARE @MaxIncrement int = 50
DECLARE @Random int = ROUND(((@MaxIncrement - @MinIncrement -1) * RAND() + @MinIncrement), 0)
DECLARE @OrderNumber int
UPDATE OrderNumber
SET @OrderNumber=NextOrderNumber, NextOrderNumber = NextOrderNumber + @Random
SELECT @OrderNumber
我将LowSeed和HighSeed更改为MinIncrement和MaxIncrement,因为我发现这里的Seed一词令人困惑。我会使用专用于跟踪订单号的表来避免锁定MyAppSetting表上的任何其他内容。
我还要挑战订单总是增加但不是顺序的要求 - 如果没有这个GUID会更容易。 要考虑的替代方案是从某个时候获得从时间得到的订单号 - 用最后一个数字来识别不同的服务器。