在 SQL 服务器中管理并发
Manage concurrency in SQL Server
我的 SQL 服务器数据库中有一个 table,其中包含一些关于书籍的数据,如下面给定的屏幕截图:
+----+-------+-------+--------+
| Id | Title | Price | Status |
+----+-------+-------+--------+
| 1 | C#6 | 40.00 | 0 |
+----+-------+-------+--------+
Status
栏表示图书可借(0=可用,1=已借)。
假设有 2 个或更多用户在我的 Web 应用程序中看到了这本书,并且这些用户同时试图借这本书,如果不管理并发性,我们将为除用户之外的其他用户获得异常# 1.
我知道我们可以使用 SQL 事务和像 Serializable
这样的隔离级别来确保没有更多的用户同时使用同一条数据,但是在这里,我有几个问题:
- 这是这种情况的最佳做法吗?如果没有,请分享您的建议。
- 如果是这样,其他用户怎么办?在用户#1 借到书后他们应该得到什么?还有,在最终确认之后还是在最终确认之前在最终级别处理并发好吗?
这种情况下的最佳做法是乐观并发。在 table 中添加一个 rowversion 列,并在更新时检查该值是否与原始值发生变化:
CREATE TABLE dbo.Book(
Id int NOT NULL CONSTRAINT PK_book PRIMARY KEY
, Title varchar(30) NOT NULL
, Price decimal(9,2) NOT NULL
, Status bit NOT NULL
, row_version rowversion NOT NULL
);
INSERT INTO dbo.Book (Id, Title, Price, [Status])
VALUES(1, 'C# 6', 40.0, 0);
GO
CREATE PROC dbo.UpdateBookAvailability
@Id int
, @Rowversion rowversion
, @Status bit
AS
UPDATE dbo.Book
SET Status = @Status
WHERE
Id = @Id
AND row_version = @RowVersion;
IF @@ROWCOUNT < 1
BEGIN
RAISERROR('book not avaiable', 16, 1);
END;
GO
我的 SQL 服务器数据库中有一个 table,其中包含一些关于书籍的数据,如下面给定的屏幕截图:
+----+-------+-------+--------+
| Id | Title | Price | Status |
+----+-------+-------+--------+
| 1 | C#6 | 40.00 | 0 |
+----+-------+-------+--------+
Status
栏表示图书可借(0=可用,1=已借)。
假设有 2 个或更多用户在我的 Web 应用程序中看到了这本书,并且这些用户同时试图借这本书,如果不管理并发性,我们将为除用户之外的其他用户获得异常# 1.
我知道我们可以使用 SQL 事务和像 Serializable
这样的隔离级别来确保没有更多的用户同时使用同一条数据,但是在这里,我有几个问题:
- 这是这种情况的最佳做法吗?如果没有,请分享您的建议。
- 如果是这样,其他用户怎么办?在用户#1 借到书后他们应该得到什么?还有,在最终确认之后还是在最终确认之前在最终级别处理并发好吗?
这种情况下的最佳做法是乐观并发。在 table 中添加一个 rowversion 列,并在更新时检查该值是否与原始值发生变化:
CREATE TABLE dbo.Book(
Id int NOT NULL CONSTRAINT PK_book PRIMARY KEY
, Title varchar(30) NOT NULL
, Price decimal(9,2) NOT NULL
, Status bit NOT NULL
, row_version rowversion NOT NULL
);
INSERT INTO dbo.Book (Id, Title, Price, [Status])
VALUES(1, 'C# 6', 40.0, 0);
GO
CREATE PROC dbo.UpdateBookAvailability
@Id int
, @Rowversion rowversion
, @Status bit
AS
UPDATE dbo.Book
SET Status = @Status
WHERE
Id = @Id
AND row_version = @RowVersion;
IF @@ROWCOUNT < 1
BEGIN
RAISERROR('book not avaiable', 16, 1);
END;
GO