Perdonami se questo è un duplicato. Il più vicino che ho trovato è stato Random timeout running a stored proc - drop recreate fixes ma non sono sicuro che le risposte relative alla ricompilazione della stored procedure siano valide.La stored procedure SQL di Azure danneggiata potrebbe essere risolta solo con la funzione di creazione di punti di ripristino
Ho un database SQL di Azure, l'ultima versione, che ha molto traffico da un front-end dell'app Web di Azure. Ho un lavoro remoto notturno che esegue un batch per ricostruire gli indici nel database SQL di Azure in quanto sembra essere di grande aiuto per il controllo delle dimensioni e delle prestazioni del database.
Normalmente, la ricostruzione degli indici richiede circa 20 minuti. La scorsa notte è scaduto dopo 2 ore. Il gestore degli errori in quel batch non ha registrato errori.
Subito dopo l'avvio degli indici di ricostruzione, una particolare procedura memorizzata inizia a scadere per ogni client che la chiama. Altre stored procedure che utilizzavano le stesse tabelle non presentavano alcun problema. Quando ho scoperto il problema, ho potuto alleviare tutti i timeout e i processi sospesi modificando la stored procedure per tornare immediatamente. Quando ho modificato di nuovo la stored procedure per comportarmi normalmente, i problemi sono riapparsi immediatamente. La mia comprensione è che l'alterazione della stored procedure lo ha costretto a ricompilare, ma ciò non ha risolto il problema.
In definitiva, ho completamente abbandonato e ricreato la procedura con il codice originale e il problema è stato risolto.
Questa procedura e lo schema utilizzato sono stati completamente stabili per molti mesi. La stessa procedura è abbastanza semplice:
CREATE Procedure [dbo].[uspActivityGet] (@databaseid uniqueidentifier) AS
begin
SET NOCOUNT ON;
--There may be writing activities to the table asynchronously, do not use nolock on tblActivity - the ActivityBlob might be null in a dirty read.
select top 100 a.Id, h.HandsetNumber, a.ActivityBlob, a.ActivityReceived
from dbo.tblDatabases d with(nolock) join dbo.tblHandsets h with(nolock) on d.DatabaseId = h.DatabaseId join dbo.tblActivity a on h.Id = a.HandsetId
where d.DatabaseId = @databaseid and a.ActivitySent is null
order by a.ActivityReceived
end
Mentre la procedura si bloccano e il tempo fuori con qualcosa di simile:
exec dbo.uspActivityGet 'AF3EA01B-DB22-4A39-9E1C-D096D2DF1215'
L'esecuzione del select identico in una finestra di query sarebbe tornato prontamente e con successo:
declare @databaseid uniqueidentifier; set @databaseid = 'AF3EA01B-DB22-4A39-9E1C-D096D2DF1215'
select top 100 a.Id, h.HandsetNumber, a.ActivityBlob, a.ActivityReceived
from dbo.tblDatabases d with(nolock) join dbo.tblHandsets h with(nolock) on d.DatabaseId = h.DatabaseId join dbo.tblActivity a on h.Id = a.HandsetId
where d.DatabaseId = @databaseid and a.ActivitySent is null
order by a.ActivityReceived
Qualche idea su come impedire che ciò accada in futuro? Grazie.
Modifica - Aggiunta esecuzione piano Schermate
Modifica - Aggiunta query utilizzata per visualizzare i processi in esecuzione. Ce n'erano molti, indovinando approssimativamente 150, nello stato sospeso e erano tutti per la stessa procedura memorizzata: uspActivityGet. Inoltre, la percentuale di I/O dati è stata esaurita per tutto il tempo in cui normalmente viene eseguita tra il 20 e il 40% nei momenti di picco della domanda. Non ricordo quale fosse il tipo di attesa. Ecco la query utilizzata per vederlo.
select * from sys.dm_Exec_requests r with(nolock) CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) order by r.total_elapsed_time desc
Modifica - È successo di nuovo stasera. Ecco il piano di esecuzione della stessa procedura durante il problema. Dopo aver rilasciato e creato nuovamente la procedura, il piano di esecuzione è tornato alla normalità e il problema è stato risolto.
Durante il problema, sp_executesql con la query identica impiegava circa 5 minuti per essere eseguito e credo che sia rappresentativo di ciò che stava accadendo. C'erano circa 50 istanze di uspActivityGet sospese con tipo di attesa SLEEP_TASK o IO_QUEUE_LIMIT.
Forse la prossima domanda è perché la ricostruzione dell'indice o altra manutenzione notturna lo fa al piano di esecuzione?
altre procedure che non presentano problemi utilizzano gli stessi join? forse diverse procedure sfruttano diversi indici? fa 'd.DatabaseId' è indicizzato? sono richiesti i suggerimenti 'NOLOCK'? forse i problemi di indicizzazione sono nascosti da quel suggerimento? cosa succede se si esegue la query da SSMS quando la procedura non riesce? – Paolo
@Paolo che esegue l'istruzione select identica in una finestra di query restituirebbe prontamente e con successo. – RJBreneman
Sei in grado di dire se il proc è bloccato o fare qualcosa per un tempo molto lungo o qualcos'altro? Quando si fornisce il GUID come costante nella query, viene modificato il modo in cui SQL Server costa la query, pertanto il test non esegue realmente entrambe le query nello stesso modo. Prova a testare con sp_executesql N '- la tua query', N '@ databaseid uniqueidentifier', '- your param' e vedere se funziona ancora velocemente o si impantana. Inoltre, condividi i tuoi piani di esecuzione in modo da poter vedere che cosa stava pensando SQL Server – SQLmojoe