Przepraszam, jeśli jest to duplikat. Najbliższe, jakie mogłem znaleźć, to Random timeout running a stored proc - drop recreate fixes, ale nie jestem pewien, czy odpowiedzi na to pytanie dotyczą rekompilacji procedury przechowywanej.Uszkodzona procedura składowana SQL Azure SQL może zostać naprawiona tylko przez odtworzenie ponownie:
Mam bazę danych Azure SQL, najnowszą wersję, która ma duży ruch z interfejsu aplikacji internetowej Azure. Mam nocne zlecenie zdalne, które uruchamia partię, aby odbudować indeksy w bazie danych Azure SQL, ponieważ wydaje się, że bardzo pomaga to w kontrolowaniu wielkości i wydajności bazy danych.
Zazwyczaj odbudowywanie indeksów trwa około 20 minut. Ostatniej nocy upłynął limit czasu po 2 godzinach. Procedura obsługi błędów w tej grupie nie zarejestrowała żadnych błędów.
Wkrótce po rozpoczęciu przebudowy indeksów, jedna procedura składowana zaczyna limit czasu dla każdego klienta wywołującego ją. Inne procedury przechowywane przy użyciu tych samych tabel nie miały żadnych problemów. Kiedy odkryłem problem, mogłem złagodzić wszystkie limity czasu i zawiesić procesy, zmieniając procedurę przechowywaną, aby natychmiast powrócić. Kiedy ponownie zmieniłem procedurę przechowywaną, aby zachowywać się normalnie, problemy pojawiały się natychmiast. Rozumiem, że zmiana procedury przechowywanej zmusiła ją do rekompilacji, ale to nie naprawiło.
Ostatecznie całkowicie upuściłem i ponownie utworzyłem procedurę z oryginalnym kodem, a problem został rozwiązany.
Ta procedura i stosowany przez nią schemat były całkowicie stabilne przez wiele miesięcy. Sama procedura jest dość prosta:
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
Choć procedura zawiśnie i czas się z czymś takim:
exec dbo.uspActivityGet 'AF3EA01B-DB22-4A39-9E1C-D096D2DF1215'
Running identyczny wybierz w oknie zapytań wróci szybko i skutecznie:
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
Jakieś pomysły, jak mogę temu zapobiec w przyszłości? Dziękuję Ci.
Edycja - Dodawanie wykonania planu ekranu
Edycja - Dodawanie zapytanie użyte do wyświetlenia uruchomionych procesów. Było wiele, zgadując około 150, w stanie zawieszenia i wszyscy byli za tą samą procedurą przechowywaną - uspActivityGet. Procent danych IO został również przekroczony przez cały czas, gdy normalnie wynosi 20-40% w godzinach szczytowego zapotrzebowania. Nie pamiętam, jaki był typ oczekiwania. Oto zapytanie użyte do wyświetlenia tego.
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
Edytuj - To się powtórzyło dziś wieczorem. Oto plan wykonania tej samej procedury podczas emisji. Po upuszczeniu i ponownym utworzeniu procedury plan wykonania powrócił do normy i problem został rozwiązany.
Podczas wydania, sp_executesql z identycznym zapytaniem zajęło około 5 minut i wierzę, że jest reprezentatywne dla tego, co się dzieje. Wystąpiło około 50 przypadków uspActivityGet zawieszonych z typem oczekiwania SLEEP_TASK lub IO_QUEUE_LIMIT.
Być może następnym pytaniem jest, dlaczego odbudowy indeksu lub inne nocne konserwacja robi to do planu wykonania?
inne procedury, które nie mają problemów, korzystają z tych samych połączeń? może różne procedury wykorzystują różne indeksy? czy 'd.DatabaseId' jest indeksowany? czy wskazówki "NOLOCK" są wymagane? może indeksowanie problemów jest ukryte przez tę podpowiedź? co się stanie, jeśli uruchomisz zapytanie SSMS, gdy procedura się nie powiedzie? – Paolo
@Paolo z uruchomieniem identycznej instrukcji SELECT w oknie zapytania powróci szybko i pomyślnie. – RJBreneman
Czy jesteś w stanie stwierdzić, czy proc jest zablokowany lub robi coś przez bardzo długi czas lub coś innego? Gdy podasz identyfikator GUID jako stałą w zapytaniu, zmienia on sposób, w jaki SQL Server kosztuje zapytanie, aby test nie uruchamiał obu zapytań w ten sam sposób. Spróbuj przetestować za pomocą sp_executesql N '- twoje zapytanie', N '@ databaseid uniqueidentifier', '--your param' i sprawdź, czy nadal działa szybko lub grzęźnie. Podziel się także swoimi planami wykonawczymi, abyśmy mogli zobaczyć, co SQL Server myślał – SQLmojoe