使用存储过程 select 创建订单号并在事务中更新

Create Order Number using a Stored procedure select and update within a transaction

我需要创建一种创建唯一订单号的方法。每个订单号必须始终大于最后一个,但它们不应始终连续。该解决方案必须在网络场环境中运行。

目前有一个存储过程负责获取新的订单号,必须对订单号进行播种,以使订单号不连续。该应用程序现在正从单个服务器移动到网络场,因此通过使用 C# 中的锁来控制对存储过程的访问不再是一种可行的控制访问方法。我已经更新了存储过程如下但是我担心我将在并发调用发生时引入 blocks\locks\deadlocks。

table和索引结构如下

MyAppSettingTable

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]

我的订单table

    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 交易

    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

修改后的 SQL 您只提供了 select 并更新了一个 table。您可以在单个查询中执行此操作,这应该避免死锁的风险,并避免需要显式事务。

设置:

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 令人困惑。我会使用 table 专用于跟踪订单号,以避免在 MyAppSetting table.

上锁定任何其他内容

我还会质疑订单总是增加但不是顺序增加的要求 - 没有这个 GUID 会更容易。 要考虑的替代方案是以某种方式从时间派生的订单号 - 用最后一位数字来标识不同的服务器。