2017-09-15 7 views
2

J'ai une table dans ma base de données SQL Server qui contient des données sur les livres comme la capture d'écran ci-dessous:Gérer concurrency dans SQL Server

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

La colonne Status indique la disponibilité du livre d'emprunt (0 = Disponible, 1 = Emprunté). Supposons que 2 utilisateurs ou plus ont vu le livre dans mon application Web et que ces utilisateurs essaient d'emprunter le livre au même moment, sans gérer la concurrence, nous obtiendrons une exception pour les autres utilisateurs sauf l'utilisateur n ° 1 .

Je sais que nous pouvons utiliser des transactions SQL et aussi le niveau d'isolement comme Serializable pour vous assurer de pas plus d'utilisateurs utilisent le même morceau de données en même temps, mais ici, je quelques questions:

  1. Est-ce la meilleure pratique dans une telle situation? Si ce n'est pas le cas, veuillez partager votre recommandation.
  2. Si oui, qu'en est-il des autres utilisateurs et que devraient-ils obtenir après que l'utilisateur n ° 1 a obtenu le livre à emprunter? Et aussi, est-il bon de gérer la concurrence au niveau final après la confirmation finale ou avant?

Répondre

4

La meilleure pratique dans ce cas serait une concurrence optimiste. Ajoutez une colonne rowversion à la table et vérifiez si la valeur a changé par rapport à la valeur d'origine lors de la mise à jour:

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