SPID inattivo che blocca altre transazioni


16

Ho davvero problemi a rintracciare alcuni blocchi che stiamo vivendo.

Lo stato di SPID che blocca la radice è "sleep", il cmd è "AWAITING COMMAND" e lo sqltextè SET TRANSACTION ISOLATION LEVEL READ COMMITTED.

Quando visualizzo il rapporto Transazioni principali per conteggio transazioni bloccate, l'istruzione SQL di blocco è "-".

Ho eseguito una traccia sull'SQL e quando il blocco si verifica tracciando lo SPID di blocco radice, ma non mi ha portato da nessuna parte. L'ultima istruzione trace è uguale alla sqltextprecedente SET TRANSACTION ISOLATION LEVEL READ COMMITTED.

Ho verificato tutte le relative procedure memorizzate che riesco a trovare per assicurarmi che abbiano TRY / CATCH INIZIA TRAN / COMMIT TRAN / ROLLBACK TRAN (utilizziamo le procedure memorizzate per tutto, quindi non ci sono istruzioni standalone in esecuzione). Questo problema è appena iniziato nelle ultime 24 ore e nessuno afferma di aver apportato modifiche al sistema.

Soluzione: una delle nostre procedure memorizzate utilizzate di rado ha avuto un errore con un inserimento (il numero di colonne non corrisponde), ma siamo ancora confusi su ciò che stava accadendo esattamente.

Quando si guardavano tutte le informazioni di traccia, l'istruzione EXEC per questa procedura memorizzata veniva elencata a volte, ma MAI poco prima che il BLOCCO si verificasse sullo SPID di blocco. Sembrava che quando ha iniziato a bloccare, la traccia non ha registrato l'esecuzione di esso (o nessuna delle dichiarazioni al suo interno). Tuttavia, ci sono altre volte in cui la traccia ha registrato la sua esecuzione e non si è verificato alcun blocco.

Il rapporto sugli errori della procedura memorizzata proveniva da un utente e sono stato in grado di trovare più istruzioni EXEC nelle tracce ed eseguirle in SSMS. Nessun momento in cui li ho eseguiti abbiamo avuto qualche blocco o si sono bloccati. Hanno funzionato come previsto (il blocco catch è stato attivato e ripristinato la transazione dopo l'errore). Dopo aver risolto la correzione della procedura memorizzata, non abbiamo più riscontrato il problema.


Suppongo che il nome host dello SPID di blocco non sia stato di alcun aiuto?
Jon Seigel,

No, è solo l'IP di uno dei nostri server web ... Abbiamo un'altra idea di cambiare ogni accesso SQL per ogni chiamata SPROC durante il processo di accesso / registrazione (che riteniamo sia il luogo in cui si sta verificando l'errore) in un nome utente separato che potrebbe aiutaci a isolare quale SPROC potrebbe causare il blocco.
Brad,

1
TRY / CATCH non rileverà errori di compilazione e un inserto di colonna non corrispondente sarebbe un tale errore di compilazione. Ciò non scatenerebbe mai molti degli eventi XX: Completed profiler.
Remus Rusanu,

1
In realtà non è un errore di compilazione in questo caso perché lo sviluppatore geniale ha usato INSERT INTO [table] SELECT * da [othertable] e non è stato catturato dal peer. Ho eseguito lo SPROC sullo sviluppo 1000 volte da ColdFusion in 3 sessioni simultanee e non ha mai lasciato aperta una transazione come era in produzione.
Brad,

Risposte:


10

Dai commenti, suppongo che tu abbia avuto un timeout del comando sul lato client che ha interrotto la query SQL. Ciò non ripristina la transazione perché la connessione rimane aperta su SQL Server a causa del pool di connessioni.

Pertanto, è necessario utilizzare SET XACT_ABORT ON o aggiungere un codice di rollback del client

Vedere Timeout transazione SQL Server per tutti i dettagli gory


Tutti i nostri SPROC contengono blocchi TRY / CATCH e le istruzioni BEGIN TRAN / COMMIT TRAN / ROLLBACK TRAN, ROLLBACK in CATCH. XACT_ABORT avrebbe ancora effetto?
Brad,

@Brad: si. Vedi il mio link Il blocco catch non viene colpito su CommandTimeout
gbn

gbn: grazie. Sono ancora confuso. Le nostre connessioni sono impostate su mai timeout (0). Quindi stai dicendo che se riutilizziamo le connessioni e una connessione esegue uno SPROC con un errore (che ha blocchi TRY / CATCH e TRAN), in qualche modo non può mai eseguire il ROLLBACK nel blocco CATCH bloccando così le tabelle e mantenendo una transazione Aperto? Questo non ha senso per me.
Brad,

@Brad: uno SPROC con un errore colpirà il blocco CATCH. Non ho detto diversamente o diversamente. Ma il mio link indica cosa succede se hai un CommandTimeout, che è diverso da un ConnectionTimeout. Il client dice "abort" e SQL Server interrompe l'elaborazione. Ergo, il blocco o il rollback o il commit di CATCH non viene mai raggiunto
gbn

Non credo che abbiamo specificato CommandTimeout. Tutte le nostre procedure memorizzate stanno testando utilizzando sqlstress e devono eseguire meno di 1000 ms a 10 utenti 10 iterazioni (almeno). Sono ancora molto confuso su ciò che è successo, ma sto aggiornando la domanda con ciò che abbiamo riscontrato è stato il problema.
Brad,

9

Utilizzare most_recent_sql_handle in sys.dm_exec_connections per vedere l'ultima istruzione eseguita.

SELECT  t.text,
        QUOTENAME(OBJECT_SCHEMA_NAME(t.objectid, t.dbid)) + '.'
        + QUOTENAME(OBJECT_NAME(t.objectid, t.dbid)) proc_name,
        c.connect_time,
        s.last_request_start_time,
        s.last_request_end_time,
        s.status
FROM    sys.dm_exec_connections c
JOIN    sys.dm_exec_sessions s
        ON c.session_id = s.session_id
CROSS APPLY sys.dm_exec_sql_text(c.most_recent_sql_handle) t
WHERE   c.session_id = 72;--your blocking spid

Controlla anche se ci sono transazioni aperte per quello spid

SELECT  st.transaction_id,
        at.name,
        at.transaction_begin_time,
        at.transaction_state,
        at.transaction_status
FROM    sys.dm_tran_session_transactions st
JOIN    sys.dm_tran_active_transactions at
        ON st.transaction_id = at.transaction_id
WHERE   st.session_id = 72;--your blocking spid

Puoi anche usare DBCC INPUTBUFFER(spid)per vedere l'ultimo SQL eseguito.
Mike Fal

Ho usato tutti questi e l'ultimo comando è sempre quello che ho messo nel mio post originale: SET TRANSACTION ISOLATION LEVEL LEGGI IMPEGNATO. Ho anche eseguito DBCC OPENTRAN e posso vedere che esiste una transazione aperta per il PID di blocco.
Brad,

La mia prima selezione ti dà anche il nome della procedura, se l'istruzione fa effettivamente parte di una procedura.
Sebastian Meine

Ti assicuro che non utilizziamo query ad hoc dai nostri server Web e quando eseguo quella prima query, anche senza la clausola WHERE ottengo solo lo SPROC denominato su una manciata di sessioni SQL, il resto della colonna è NULL.
Brad,

Noto che ho tonnellate di sessioni che dicono "IMPOSTA IL LIVELLO DI ISOLAMENTO PER LE TRANSAZIONI LEGGI IMPEGNATO" e tutte provengono da ColdFusion (lo script principale utilizzato sui nostri server Web). Forse ColdFusion quando inattivo emette quell'istruzione per mantenere aperta una connessione (poiché è impostata per mantenere aperte le connessioni).
Brad,

4

Hai provato a utilizzare sp_whoisactive di Adam Machanic ? C'è un'opzione per ottenere il comando esterno per vedere se è davvero all'interno di un proc. È possibile che l'applicazione stia tenendo aperta una transazione invece di eseguirla. Prova anche a guardare DBCC OPENTRAN .


Grazie per DBCC OPENTRAN. Mi dice che il PID di blocco ha una transazione aperta, ma non sono disponibili ulteriori dettagli. sp_whoisactive restituisce le stesse informazioni sul processo bloccato che sono stato in grado di ottenere da solo. Non ci sono ancora dettagli su ciò che sta succedendo oltre a "IMPOSTARE IL LIVELLO DI ISOLAMENTO DELLE TRANSAZIONI LEGGI IMPEGNATO"
Brad,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.