sql-server - 管理 SQL Server 中的并发

标签 sql-server concurrency isolation-level sqltransaction

我的 SQL Server 数据库中有一个表,其中包含一些有关书籍的数据,如下面给定的屏幕截图:

+----+-------+-------+--------+
| Id | Title | Price | Status |
+----+-------+-------+--------+
|  1 | C#6   | 40.00 |      0 |
+----+-------+-------+--------+

状态列指示图书是否可以借阅(0 = 可用,1 = 已借)。

假设有 2 个或更多用户在我的 Web 应用程序中看到了这本书,并且这些用户同时尝试借阅这本书,如果不管理并发性,我们将得到除用户 #1 之外的其他用户的异常。

我知道我们可以使用 SQL 事务以及像 Serialized 这样的隔离级别来确保没有更多用户同时使用同一条数据,但是在这里,我有几个问题:

  1. 这是这种情况下的最佳做法吗?如果没有,请分享您的建议。
  2. 如果是这样,其他用户怎么办?用户 #1 获得借阅书后他们应该得到什么?另外,在最终确认之后或之前处理最终级别的并发是否好?

最佳答案

这种情况下的最佳实践是乐观并发。向表中添加 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-server - 管理 SQL Server 中的并发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46246536/

相关文章:

java - 我可以使用 ForkJoinPool 的工作窃取行为来避免线程饥饿死锁吗?

javascript - 如何在 JavaScript 中实现原子操作(并发模型)?

database - oracle 中的隔离级别

sql-server - 事务隔离级别范围

sql - 如何创建用增量填充字段的 SQL 函数

c# - 在 C#/.NET 中执行批量更新的最快方法

Java多线程文件系统树遍历

C# - 安全地连接到远程 SQL Server?

sql - 根据另一列的不同值聚合一列

MySQL。应使用什么隔离级别?