2016-06-27 5 views
0

Ich habe die folgende SQL:Ist dieses SQL-Update garantiert atomar?

UPDATE Customer SET Count=1 WHERE ID=1 AND Count=0 
SELECT @@ROWCOUNT 

Ich muss wissen, ob dies gewährleistet ist atomar zu sein.

Wenn 2 Benutzer gleichzeitig versuchen, wird nur einer erfolgreich sein und einen Rückgabewert von 1 erhalten? Muss ich eine Transaktion oder etwas anderes verwenden, um dies zu garantieren?

Ziel ist es, einen eindeutigen "Count" für den Kunden zu erhalten. Kollisionen in diesem System werden so gut wie nie vorkommen, daher mache ich mir keine Gedanken über die Performance, wenn ein Benutzer erneut (und wieder) abfragen muss, um eine eindeutige Zählung zu erhalten.

EDIT:

Das Ziel ist nicht, eine Transaktion zu verwenden, wenn es nicht benötigt wird. Auch diese Logik wird sehr selten ausgeführt (bis zu 100 pro Tag), also wollte ich es so einfach wie möglich halten.

+1

Ich denke, Sie haben diese SQL zu sehr vereinfacht, um mit Ihrem letzten Absatz zu entsprechen. Was ist der Zweck, einen einzigartigen "Count" zu haben? Soll es nur einen Wert von 0 oder 1 haben? –

+0

Es erhält eine eindeutige Nummer für jede Bestellung vom Kunden. Dies ist die Referenznummer des Benutzers für die Bestellung, also beginnt jeder Kunde bei 0 für die erste Bestellung und 1 für die zweite Bestellung, dann 2 usw. – David

+0

Mögliches Duplikat von [Vermeidung von Nebenläufigkeitsproblemen mit MAX + 1 Ganzzahl in SQL Server 2008 ... eigenen IDENTITY-Wert machen] (http://stackoverflow.com/questions/8956044/avoiding-concurrency-problems-with-max1-integer-in-sql-server-2008-making-ow) –

Antwort

0

Mit SQL Server (v 11.0.6020), dass dies in der Tat eine atomare Operation ist, so gut ich kann feststellen.

Ich schrieb einige Test gespeicherte Prozeduren, diese Logik zu versuchen, zu testen:

-- Attempt to update a Customer row with a new Count, returns 
-- The current count (used as customer order number) and a bit 
-- which determines success or failure. If @Success is 0, re-run 
-- the query and try again. 
CREATE PROCEDURE [dbo].[sp_TestUpdate] 
(
    @Count INT OUTPUT, 
    @Success BIT OUTPUT 
) 
AS 
BEGIN 
    DECLARE @NextCount INT 

    SELECT @Count=Count FROM Customer WHERE ID=1 
    SET @NextCount = @Count + 1 
    UPDATE Customer SET [email protected] WHERE ID=1 AND [email protected] 
    SET @[email protected]@ROWCOUNT 
END 

Und:

-- Loop (many times) trying to get a number and insert in into another 
-- table. Execute this loop concurrently in several different windows 
-- using SMSS. 
CREATE PROCEDURE [dbo].[sp_TestLoop] 
AS 
BEGIN 
    DECLARE @Iterations INT 
    DECLARE @Counter INT 
    DECLARE @Count INT 
    DECLARE @Success BIT 
    SET @Iterations = 40000 
    SET @Counter = 0 
    WHILE (@Counter < @Iterations) 
    BEGIN 
     SET @Counter = @Counter + 1 
     EXEC sp_TestUpdate @Count = @Count OUTPUT , @Success = @Success OUTPUT 
     IF (@Success=1) 
     BEGIN 
      INSERT INTO TestImage (ImageNumber) VALUES (@Count) 
     END 
    END 
END 

Dieser Code lief, wodurch einzigartige sequentielle ImageNumber Werte in der Tabelle Testimage. Dies beweist, dass der obige SQL-Update-Aufruf tatsächlich atomar ist. Keine Funktion garantiert, dass die Updates durchgeführt wurden, aber sie haben garantiert, dass keine Duplikate erstellt wurden, und keine Nummern wurden übersprungen.

0

Es kann von dem SQL-Server abhängen, den Sie verwenden. Für die meisten ist die Antwort jedoch Ja. Ich nehme an, Sie implementieren eine Sperre.