it-swarm.it

Timeout transazione SQL Server

Esiste un modo in SQL Server 2008 R2 per causare un timeout per una modifica del database che coinvolge una transazione? Abbiamo uno scenario in cui il nostro codice dell'applicazione si blocca o genera un'eccezione e non riesce a eseguire un rollback o un commit. Ciò causa quindi l'attesa di altre sessioni in attesa del completamento della transazione.

9

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:

20
gbn

Sto rispondendo con esitazione perché non ci sono abbastanza informazioni nella descrizione del problema per essere sicuri al 100% che questo sia il miglior consiglio. "Hangs o genera un'eccezione" suggerisce che l'origine del problema non è stata compresa correttamente, quindi procedi con cautela.

La soluzione più semplice a questo è probabilmente SET XACT_ABORT ON.

XACT_ABORT determina se SQL Server eseguirà il rollback di una transazione in caso di errore di runtime. Il predefinito SET XACT_ABORT OFF eseguirà il rollback solo dell'istruzione che ha causato un errore, lasciando aperta qualsiasi transazione principale.

L'effetto collaterale "gotcha" dell'impostazione predefinita è che un timeout può causare esattamente lo stesso problema, una transazione aperta che è la responsabilità dei clienti di gestire e ripristinare. Se il cliente non prova/cattura/rollback, la transazione rimarrà aperta fino a quando non verrà seguita (e cito @gbn) l'ultra violenza di KILL <spid>.

Spesso citati articoli di Erland Sommarskog su gestione degli errori in SQL Server contengono tutto lo sfondo e la strategia necessari per gestire questi scenari e altro.

Modifica (seguente commento): per identificare le transazioni aperte, sp_whoisactive è probabilmente la funzione più completa.

11