Felsöka tidsgräns-fel för fråga
Symptom
Anta att ett program frågar efter data från en SQL Server-databas. Om frågan inte returnerar några data inom det konfigurerade tidsgränsvärdet (vanligtvis 30 sekunder) avbryter programmet frågan och genererar något av följande felmeddelanden:
-
Tidsgränsen har upphört att gälla. Tidsgränsen nåddes innan åtgärden slutfördes, eller så svarar inte servern. Instruktionen har avslutats.
-
System.Data.SqlClient.SqlException: Tidsgränsen har upphört att gälla. Tidsgränsen nåddes innan åtgärden slutfördes, eller så svarar inte servern.
Förklaring
Dessa fel uppstår på programsidan. Programmet anger ett tidsgränsvärde och om tidsgränsen nås avbryts frågan. På SQL Server-sidan orsakar en frågeavbokning från klientsidan en uppmärksamhetshändelse, fel 3617 (MSSQLSERVER_3617). Om timeout-värdet på programsidan är inställt på 0 (ingen tidsgräns) kör databasmotorn frågan tills den har slutförts.
- I .NET Framework System.Data.SqlClient anges tidsgränsvärdet för egenskapen CommandTimeout.
- I ODBC API anges det via
SQL_ATTR_QUERY_TIMEOUT
attributet i funktionen SQLSetStmtAttr. - I JDBC-API:et (Java Database Connectivity) anges det via metoden setQueryTimeout.
- I OLEDB anges den via egenskapen
DBPROP_COMMANDTIMEOUT
på strukturenDBPROP
. - I VBA (Excel) anges det via egenskapen ADODB.Command.CommandTimeout.
Tidsgränsen för frågor skiljer sig från en tidsgräns-egenskap för anslutning. Det senare styr hur lång tid det tar att vänta på en lyckad anslutning och ingår inte i frågekörningen. Mer information finns i Tidsgränsen för frågor är inte samma som tidsgränsen för anslutning.
Felsökningssteg
Den överlägset vanligaste orsaken till tidsgränser för frågor är underpresterande frågor. Det innebär att frågan körs längre än det fördefinierade tidsgränsvärdet för frågan. Att köra frågan snabbare är det rekommenderade första målet för felsökningen. Så här kontrollerar du frågor:
Använd Extended Events eller SQL Trace för att identifiera de frågor som orsakar tidsgräns-felen. Du kan spåra uppmärksamhetshändelsen tillsammans med
sql_batch_completed
ochrpc_completed
utökade händelser och korrelera dem på sammasession_id
. Om du ser att en slutförd händelse omedelbart följs av en uppmärksamhetshändelse, och varaktigheten för den slutförda händelsen motsvarar ungefär tidsgränsinställningen, har du identifierat frågan. Här är ett exempel:Obs!
I exemplet kördes frågan
SELECT
i nästan exakt 30 sekunder och stoppades. Uppmärksamhetshändelsen med samma sessions-ID anger att frågan avbröts av programmet.Namn Session_id Sql_text Varaktighet (mikrosekunder) Tidsstämpel sql_batch_started 54 Välj … från kunder där cid = 192937 NULL 2021-09-30 09:50:25.0000 Sql_batch_completed 54 Välj … från kunder där cid = 192937 29999981 2021-09-30 09:50:55.0000 Obs! 54 Välj … från kunder där cid = 192937 40000 2021-09-30 09:50:55.0400 Kör och testa frågorna i SQLCMD eller i SQL Server Management Studio (SSMS).
Om frågorna också är långsamma i SQLCMD och SSMS kan du felsöka och förbättra frågornas prestanda. Detaljerad information finns i Felsöka frågor som körs långsamt i SQL Server
Obs!
I SQLCMD och SSMS anges tidsgränsvärdet till 0 (ingen tidsgräns) och frågorna kan testas och undersökas.
Om frågorna är snabba i SQLCMD och SSMS, men är långsamma på programsidan, ändrar du frågorna så att de använder samma SET-alternativ som används i SQLCMD och SSMS. Jämför SET-alternativen genom att samla in en Extended Events-spårning (logga in och ansluta händelser med
collect_options_text
) och kontrollera kolumnenoptions_text
. Här är ett exempel:ALTER EVENT SESSION [setOptions] ON SERVER ADD EVENT sqlserver.existing_connection(SET collect_options_text=(1) ACTION(package0.event_sequence,package0.last_error,sqlos.system_thread_id,sqlserver.context_info,sqlserver.session_id,sqlserver.sql_text)), ADD EVENT sqlserver.login(SET collect_options_text=(1) ACTION(sqlos.system_thread_id,sqlserver.context_info,sqlserver.sql_text))
Mer information finns i Felsöka frågeprestandaskillnader mellan databasprogram och SSMS.
Kontrollera om inställningen
CommandTimeout
är mindre än den förväntade frågevaraktigheten. Om användarens inställning är korrekt och tidsgränser fortfarande inträffar beror det på ett problem med frågeprestanda. Här är ett ADO.NET-kodexempel med ett tidsgränsvärde inställt på 10 sekunder:using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Data.SqlClient; using System.Data; namespace ConsoleApplication6 { class Program { static void Main() { string ConnectionString = "Data Source=.\sql2019;Integrated Security=SSPI;Initial Catalog=tempdb;"; string queryString = "exec test"; using (SqlConnection connection = new SqlConnection(ConnectionString)) { connection.Open(); SqlCommand command = new SqlCommand(queryString, connection); // Setting command timeout to 10 seconds command.CommandTimeout = 10; //command.ExecuteNonQuery(); try { command.ExecuteNonQuery(); } catch (SqlException e) { Console.WriteLine("Got expected SqlException due to command timeout "); Console.WriteLine(e); } } } } }
Tidsgränsen för frågan är inte samma som tidsgränsen för anslutningen
Tidsgränsen för en fråga skiljer sig från tidsgränsen för anslutningen eller tidsgränsen för inloggning. Tidsgränsen för anslutning eller inloggning inträffar när den första anslutningen till databasservern når en fördefinierad tidsgräns. I det här skedet har ingen fråga skickats till servern. Dessa meddelanden är exempel på timeout-fel vid anslutning eller inloggning:
-
Tidsgränsen för inloggning har upphört att gälla. Tidsgränsen uppnåddes vid försök att använda handskakningsbekräftelse före inloggning. Det kan bero på att handskakningen före inloggningen misslyckades eller att servern inte kunde svara bakåt i tiden. Varaktigheten för att försöka ansluta till den här servern var [Pre-Login] initiering=23. Handskakning=14979.
-
Tidsgränsen har upphört att gälla. Tidsgränsen nåddes innan åtgärden slutfördes, eller så svarar inte servern. System.ComponentModel.Win32Exception (0x80004005): vänteåtgärden nådde sin tidsgräns.
Tidsgränsvärdet för anslutningen är en inställning på klientsidan och är vanligtvis inställd på 15 sekunder. Mer information om hur du felsöker tidsgränsen för anslutning finns i Felsöka tidsgräns för anslutning. Titta på den här videon för felsökning av tidsgränser för frågor.