Estensione della risposta di Mark ...
Quando si verifica un evento di timeout del client (ad esempio .net CommandTimeout), il client invia un "ABORT" a SQL Server. SQL Server quindi abbandona semplicemente l'elaborazione della query. Non viene eseguito il rollback di alcuna transazione, non vengono rilasciati blocchi.
Ora, la connessione viene restituita al pool di connessioni, quindi non è chiusa su SQL Server. Se ciò dovesse accadere (tramite KILL o riavvio del client, ecc.) Le transazioni + i blocchi verranno cancellati. Nota che sp_reset_connection non li cancella o non li cancella, anche se è pubblicizzato per farlo
Questo detrito dall'interruzione bloccherà altri processi.
Il modo per rendere trasparenti le transazioni + i blocchi di SQL Server sul timeout del client (rigorosamente, eventi ABORT) è utilizzare SET XACT_ABORT ON.
È possibile verificare che questo apra 2 finestre di query in SSMS:
Finestra 1:
Nel menu Query..Query Options imposta un timeout di 5 secondi quindi esegui questo
BEGIN TRAN
UPDATE sometable WITH (TABLOCKX) SET foo = foo WHERE 1 = 0;
WAITFOR DELAY '00:00:10' -- just has to be longer then timeout
Finestra 2, questo attenderà per sempre (o raggiungerà il timeout)
SELECT * FROM sometable
SET XACT_ABORT ON ha anche effetti collaterali interessanti:
- @@ TRANCOUNT è impostato su zero sul rollback implicito ma l'errore 266 viene eliminato (ciò accade se @@ TRANCOUNT è diverso all'entrata e all'uscita da un proc memorizzato)
- XACT_STATE sarà -1 (è "condannato")
La combinazione di questo significa che non è possibile utilizzare SAVEPOINTS (anche se non ricordo il comportamento esatto) per commit / rollback parziali. Che mi va bene
Collegamenti SO su SET XACT_ABORT:
Su proc memorizzati nidificati:
Su sp_reset_connection: