Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Дали един израз на SQL Server е атомичен и последователен?

Работих при предположението, че един израз в SQL Server е последователен

Това предположение е погрешно. Следните две транзакции имат идентична семантика на заключване:

STATEMENT

BEGIN TRAN; STATEMENT; COMMIT

Никаква разлика. Единичните оператори и автоматичните комити не променят нищо.

Така че обединяването на цялата логика в едно изявление не помага (ако е така, това е било случайно, защото планът се промени).

Нека поправим проблема. SERIALIZABLE ще коригира несъответствието, което виждате, защото гарантира, че вашите транзакции се държат така, сякаш се изпълняват еднонишково. По същия начин, те се държат така, сякаш са изпълнили незабавно.

Ще получите безизходица. Ако сте наред с цикъла за повторен опит, на този етап сте готови.

Ако искате да инвестирате повече време, приложете заключващи съвети, за да наложите изключителен достъп до съответните данни:

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
)

Сега ще видите намален едновременност. Това може да е напълно добре в зависимост от натоварването ви.

Самото естество на вашия проблем прави постигането на паралелност трудно. Ако имате нужда от решение за това, ще трябва да приложим по-инвазивни техники.

Можете да опростите АКТУАЛИЗИРАНЕТО малко:

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

Това премахва едно ненужно присъединяване.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да посочите номер на порт в низа за връзка на SQL Server?

  2. Представяме ви нова функция:Група за винаги наличност

  3. Как да коригирате „Изразът EXECUTE не бе успешен, защото неговата клауза WITH RESULT SETS посочи 2 колона(и) за набор от резултати...“ Msg 11537 в SQL Server

  4. Как да заявя стойности от xml възли?

  5. Как да създадете ограничение за проверка на една колона в SQL Server - SQL Server / TSQL урок, част 83