Felsöka tidsgränsfel för frågor
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 ett av följande felmeddelanden:
-
Tidsgränsen har överskridits. Tidsgränsöverskridning uppstod innan åtgärden slutfördes eller servern svarar inte. Instruktionen har avslutats.
-
System.Data.SqlClient.SqlException: Tidsgränsen har överskridits. Tidsgränsöverskridning uppstod innan åtgärden slutfördes eller servern svarar inte.
Förklaring
Dessa fel uppstår på programsidan. Programmet anger ett timeout-värde och om tidsgränsen nås avbryts frågan. På SQL Server-sidan orsakar en frågeavbokning från klientsidan en Attention-händelse, fel 3617 (MSSQLSERVER_3617). Om tidsgränsvä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 Java Database Connectivity (JDBC) API anges det via metoden setQueryTimeout.
- I OLEDB anges den via
DBPROP_COMMANDTIMEOUT
egenskapen iDBPROP
strukturen. - I VBA (Excel) anges det via egenskapen ADODB.Command.CommandTimeout.
Tidsgränsen för frågor skiljer sig från en timeout-egenskap för anslutning. Det senare styr hur lång tid det tar att vänta på en lyckad anslutning och inte deltar i frågekörningen. Mer information finns i Tidsgränsen för frågor är inte samma som tidsgränsen för anslutningen.
Felsökningsanvisningar
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 timeout-felen. Du kan spåra uppmärksamhetshändelsen tillsammans med de
sql_batch_completed
utökade händelserna ochrpc_completed
korrelera dem på sammasession_id
. Om du observerar 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:Kommentar
I exemplet kördes
SELECT
frågan i nästan exakt 30 sekunder och stoppades. Uppmärksamhetshändelsen med samma sessions-ID anger att frågan avbröts av programmet.Name Session_id Sql_text Varaktighet (mikrosekunder) Tidsstämpel sql_batch_started 54 Markera … från Kunder WHERE cid = 192937 NULL 2021-09-30 09:50:25.0000 sql_batch_completed 54 Markera … från Kunder WHERE cid = 192937 29999981 2021-09-30 09:50:55.0000 Observera! 54 Markera … från Kunder WHERE 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 långsamma frågor i SQL Server
Kommentar
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 spårning av utökade händelser (logga in och ansluta händelser med
collect_options_text
) och kontrolleraoptions_text
kolumnen. 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ågeprestandaskillnad 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 timeout-vä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 densamma 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 för anslutning eller inloggning:
-
Tidsgränsen för anslutning överskreds. Tidsgränsen passerades när handskakningen före inloggningen skulle genomföras. Detta kan bero på att handskakningen misslyckades eller på att servern inte kunde svara i tid. Tidsåtgången för att försöka ansluta till servern var: [före inloggning] initiering=23; handskakning=14979;
-
Tidsgränsen har överskridits. Tidsgränsöverskridning uppstod innan åtgärden slutfördes eller servern svarar inte. System.ComponentModel.Win32Exception (0x80004005): Tidsgränsen för vänteåtgärden överskreds.
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änsen för anslutningen. Om du vill felsöka tidsgränser för frågor kan du titta på den här videon.