1

我们有一个基于 ASP.NET/MSSQL 的 Web 应用程序,它生成具有顺序订单号的订单。

当用户保存表单时,会创建一个新订单,如下所示:

  1. SELECT MAX(order_number) FROM order_table,调用这个max_order_number
  2. 设置 new_order_number = max_order_number + 1
  3. 使用这个 new_order_number 插入一个新的订单记录(它只是订单记录中的一个字段,而不是数据库键)

如果我在单笔交易中附上以上3个步骤,如果两个客户同时保存一个新订单,是否会避免创建重复的订单号?(假设系统最终位于具有多个 IIS 服务器和一个 MSSQL 服务器的网络场上)。

我想避免两个客户由于系统某处的并发而选择相同的 MAX(order_number)。

应该使用什么隔离级别?谢谢你。

4

4 回答 4

5

为什么不直接使用身份作为订单号?

编辑:
据我所知,您可以将当前 order_number 列设为身份(您可能需要重置种子,我已经有一段时间没有这样做了)。你可能想做一些测试。
这是一个很好的阅读,了解当您将列更改为 SSMS 中的身份时实际发生的情况。作者提到如果表已经有数百万行,这可能需要一段时间。

于 2012-07-25T17:29:42.043 回答
1

风险是两个进程在其中一个插入新订单之前选择了 MAX(order_number)。一种更安全的方法是一步完成:

INSERT INTO order_table
(order_number, /* other fields */)
VALUES
( (SELECT MAX(order_number)+1 FROM order_table ) order_number,
  /* other values */
)
于 2012-07-25T17:43:02.253 回答
1

我同意 G_M;使用身份字段。添加记录时,只需

INSERT INTO order_table (/* other fields */)
VALUES (/* other fields */) ; SELECT SCOPE_IDENTITY()

Scope Identity的返回值将是您的订单号。

于 2012-07-25T17:47:20.317 回答
1

使用身份是迄今为止最好的主意。我像这样创建所有表:

CREATE TABLE mytable (
    mytable_id int identity(1, 1) not null primary key,
    name varchar(50)
)

“身份”标志的意思是“让 SQL Server 为我分配这个号码”。(1, 1) 表示身份编号应从 1 开始,每次有人将记录插入表中时递增 1。Not Null 意味着不允许任何人在该列中插入空值,而“主键”意味着我们应该在该列上创建聚集索引。使用这种表格,您可以像这样插入记录:

-- We don't need to insert into mytable_id column; SQL Server does it for us!
INSERT INTO mytable (name) VALUES ('Bob Roberts')

但是要回答您的字面问题,我可以上一堂有关交易如何运作的课程。这样做当然是可能的,尽管不是最佳的:

-- Begin a transaction - this means everything within this region will be 
-- executed atomically, meaning that nothing else can interfere.
BEGIN TRANSACTION
    DECLARE @id bigint

    -- Retrieves the maximum order number from the table
    SELECT @id = MAX(order_number) FROM order_table

    -- While you are in this transaction, no other queries can change the order table,
    -- so this insert statement is guaranteed to succeed
    INSERT INTO order_table (order_number) VALUES (@id + 1)

-- Committing the transaction releases your lock and allows other programs 
-- to work on the order table
COMMIT TRANSACTION

请记住,使用标识主键列声明您的表会自动为您完成这一切。

于 2012-07-25T17:47:45.847 回答