SQL: Kolejność wykonywania transakcji

11-Mar-2018

Tym razem zajmę się kolejnością wykonywania transakcji. Przeanalizujmy taką sytuację:

  • Transakcja A czyta rekord, ale po przeczytaniu rekordu pozostawia na nim lock (czyli np. transakcja pracuje w poziomie izolacji REPEATABLE READ)
  • Transkacja B startuje po transakcji A, i zamierza zmodyfikować ten sam rekord
  • Transakcja C startuje po transakcji B i zamierza przeczytać ten rekord

Pytanie – w jakiej kolejności wykonają się te transakcje?

  • A – B – C, bo w takiej kolejności te transakcje startowały, czy
  • A – C – B, bo transakcja C tylko czyta rekord, tak samo jak transakcja A, czyli nie jest w konflikcie z A. B jako transakcja modyfikująca dane i tak musi czekać, więc nie ma problemu, aby „przepuściła” transakcję „C”

Zacznijmy od potwierdzenia, że jeśli mamy tylko A i C, to bez problemu można uruchomić obie transakcje:

A:

USE AdventureWorks
GO

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ

BEGIN TRAN

SELECT * FROM Production.Product WHERE ProductID = 400

C:

use AdventureWorks

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ

BEGIN TRAN

SELECT * FROM Production.Product where ProductID = 400
SELECT SYSDATETIME()

ROLLBACK

Transakcja A przeczyta w tym przypadku rekord, ale ponieważ transaction isolation level został zmieniony na REPEATABLE READ, to shared lock na rekordzie nadal występuje! Transakcja C, też musi jedynie założyć lock shared. Oba locki są kompatybilne i transakcja C się wykona bez przeszkód.

Ale co się stanie jeśli po uruchomieniu A, przed uruchomieniem C, uruchomiona zostanie następująca transakcja B:

B:

use AdventureWorks
go

BEGIN TRAN
 UPDATE Production.Product SET color ='xxx' WHERE ProductID = 400
 SELECT SYSDATETIME()
 --ROLLBACK

Nie jest tutaj ważne czy transakcja B skończy się przez COMMIT czy ROLLBACK. Właściwie polecenie ROLLBACK jest zakomentowane tylko po to aby łatwiej było obserwować co się dzieje.  Ucruchamiając kolejno A, B, C mamy:

  • transakcja A oczywiście ciągle trwa i posiada lock shared
  • transakcja B jest zablokowana, bo chce założyć lock exclusive
  • transakcja C… no właśnie – czeka. Chociaż nie wymaga locka exclusive i teoretycznie mogłaby być wykonana, to czeka! Ruszy dopiero gdy po pierwsze zakończy sie A a po drugie zakończy się B (przez COMMIT lub ROLLBACK)

Czyli kolejka jest całkiem… jak u lekarza. Przyszła baba do lekarza – co pani jest pyta lekarz. Ja jestem transakcja A i chciałam tylko zapytać….

Tymczasem do kolejki wpada transakcja B, z większym problemem – powiedzmy, że ma widelec w oku, ale musi czekać, bo gabinet jest zajęty.

Chwilę później przychodzi transakcja C – patrzy kolejka do lekarza, więc mówi, „mogę wejść bez kolejki? Ja się tylko chcę o coś zapytać….”. Czy transakcja B się zgodzi i ją przepuści? Nie. gdyby przepuściła, to ryzykuje, że ciagle będą przychodziły transakcje pytające i transakcja B nigdy nie wejdzie do gabinetu.

Odpowiedź na zagadkę to więc A – B – C

Dodaj komentarz:

Autor: Rafał Kraik