sql >> Database >  >> RDS >> Sqlserver

Is een enkele SQL Server-instructie atomair en consistent?

Ik heb gewerkt in de veronderstelling dat een enkele instructie in SQL Server consistent is

Die veronderstelling is fout. De volgende twee transacties hebben identieke vergrendelingssemantiek:

STATEMENT

BEGIN TRAN; STATEMENT; COMMIT

Helemaal geen verschil. Enkele verklaringen en automatische toewijzingen veranderen niets.

Dus het samenvoegen van alle logica in één verklaring helpt niet (als dat zo is, was het per ongeluk omdat het plan is gewijzigd).

Laten we het probleem bij de hand oplossen. SERIALIZABLE lost de inconsistentie op die u ziet, omdat het garandeert dat uw transacties zich gedragen alsof ze single-threaded zijn uitgevoerd. Evenzo gedragen ze zich alsof ze onmiddellijk worden uitgevoerd.

Je krijgt impasses. Als je akkoord gaat met een nieuwe poging, ben je nu klaar.

Als u meer tijd wilt investeren, past u vergrendelingstips toe om exclusieve toegang tot de relevante gegevens te forceren:

UPDATE Gifts  -- U-locked anyway
SET GivenAway = 1
WHERE GiftID = (
   SELECT TOP 1 GiftID
   FROM Gifts WITH (UPDLOCK, HOLDLOCK) --this normally just S-locks.
   WHERE g2.GivenAway = 0
    AND (SELECT COUNT(*) FROM Gifts g2 WITH (UPDLOCK, HOLDLOCK) WHERE g2.GivenAway = 1) < 5
   ORDER BY g2.GiftValue DESC
)

U ziet nu verminderde gelijktijdigheid. Dat kan helemaal goed zijn, afhankelijk van je belasting.

De aard van uw probleem maakt het moeilijk om gelijktijdigheid te bereiken. Als je daar een oplossing voor nodig hebt, moeten we meer invasieve technieken toepassen.

U kunt de UPDATE een beetje vereenvoudigen:

WITH g AS (
   SELECT TOP 1 Gifts.*
   FROM Gifts
   WHERE g2.GivenAway = 0
    AND (SELECT COUNT(*) FROM Gifts g2 WITH (UPDLOCK, HOLDLOCK) WHERE g2.GivenAway = 1) < 5
   ORDER BY g2.GiftValue DESC
)
UPDATE g  -- U-locked anyway
SET GivenAway = 1

Dit verwijdert één onnodige join.



  1. Wat is databasetesten en hoe voer je het uit?

  2. Converteer 'datetime' naar 'datetimeoffset' in SQL Server (T-SQL-voorbeelden)

  3. Hoe de maximale verbindingen in postgre te verhogen?

  4. Hoe een externe MySQL-verbinding in te stellen