對查詢逾時錯誤進行疑難排解
徵兆
假設應用程式會從 SQL Server 資料庫查詢資料。 如果查詢未傳回設定逾時值內的任何資料(通常是 30 秒),應用程式會取消查詢並產生下列其中一個錯誤訊息:
-
已超過逾時的設定。 在作業完成前就已超過逾時期間,或是伺服器沒有回應。 陳述式已經結束。
-
System.Data.SqlClient.SqlException:逾時過期。 在作業完成前就已超過逾時期間,或是伺服器沒有回應。
說明
這些錯誤發生在應用程式端。 應用程式會設定逾時值,如果達到逾時值,則會取消查詢。 在 SQL Server 端,客戶端的查詢取消會導致注意事件,錯誤 3617 (MSSQLSERVER_3617)。 如果應用程式端的逾時值設定為 0(沒有時間限制),資料庫引擎 會執行查詢,直到查詢完成為止。
- 在 .NET Framework System.Data.SqlClient 中,逾時設定在 CommandTimeout 屬性上。
- 在 ODBC API 中,它會透過
SQL_ATTR_QUERY_TIMEOUT
SQLSetStmtAttr 函式中的 屬性進行設定。 - 在 JAVA 資料庫連線 (JDBC) API 時,其是透過 setQueryTimeout 方法來設定。
- 在OLEDB中,它會透過
DBPROP_COMMANDTIMEOUT
結構上的DBPROP
屬性來設定。 - 在 VBA (Excel) 中,其是透過 ADODB.Command.CommandTimeout 屬性來設定。
查詢逾時與聯機逾時屬性不同。 後者會控制等候成功連線的時間長度,且不涉及查詢執行。 如需詳細資訊,請參閱 查詢逾時與連線逾時不同。
疑難排解步驟
到目前為止,查詢逾時最常見的原因是查詢效能不佳。 這表示查詢的執行時間超過預先定義的查詢逾時值。 加快查詢執行速度是疑難解答的建議第一個目標。 以下是檢查查詢的方式:
使用 擴充事件 或 SQL 追蹤 來識別導致逾時錯誤的查詢。 您可以將注意力事件與
sql_batch_completed
和rpc_completed
擴充事件一起追蹤,並在相同的session_id
上相互關聯。 如果您發現已完成的事件緊接著注意事件,且已完成事件的持續時間大約會對應至逾時設定,則表示您已識別查詢。 以下是範例:注意
在此範例中
SELECT
,查詢執行了將近30秒並停止。 具有相同會話標識碼的注意事件表示應用程式已取消查詢。名稱 Session_id Sql_text 持續時間(微秒) 時間戳記 sql_batch_started 54 選取 … from Customers WHERE cid = 192937 NULL 2021-09-30 09:50:25.0000 sql_batch_completed 54 選取 … from Customers WHERE cid = 192937 29999981 2021-09-30 09:50:55.0000 注意 54 選取 … from Customers WHERE cid = 192937 40000 2021-09-30 09:50:55.0400 在 SQLCMD 或 SQL Server Management Studio (SSMS) 中執行及測試查詢。
如果 SQLCMD 和 SSMS 中的查詢速度也很慢,請針對查詢進行疑難解答並改善效能。 如需詳細資訊,請參閱 針對 SQL Server 中執行緩慢的查詢進行疑難解答
注意
在 SQLCMD 和 SSMS 中,逾時值會設定為 0 (沒有時間限制),而且可以測試及調查查詢。
如果查詢在 SQLCMD 和 SSMS 中快速,但在應用程式端的速度很慢,請將查詢變更為使用 SQLCMD 和 SSMS 中使用的相同 SET 選項 。 藉由收集擴充事件追蹤來比較 SET 選項(使用 登入和連接事件
collect_options_text
),並檢查數據options_text
行。 以下是範例: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))
如需詳細資訊,請參閱 針對資料庫應用程式和 SSMS 之間的查詢效能差異進行疑難解答。
檢查設定是否
CommandTimeout
小於預期的查詢持續時間。 如果使用者的設定正確且仍發生逾時,這是因為查詢效能問題。 以下是將逾時值設定為 10 秒的 ADO.NET 程式代碼範例: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); } } } } }
查詢逾時與聯機逾時不同
查詢逾時與聯機逾時或登入逾時不同。當資料庫伺服器的初始連接達到預先定義的逾時期間時,就會發生連線或登入逾時。 在這個階段中,尚未將任何查詢提交至伺服器。 這些訊息是連線或登入逾時錯誤的範例:
-
已超過連線逾時。 嘗試取用登入前的交握確認時超過逾時時間。 這可能是因為登入前交握失敗,或伺服器無法及時回應。 嘗試連線到這部伺服器所花費的時間為 [登入前] 初始化=23;交握=14979;
-
已超過逾時的設定。 在作業完成前就已超過逾時期間,或是伺服器沒有回應。 System.ComponentModel.Win32Exception (0x80004005):等候作業已逾時。
線上逾時值是客戶端設定,通常設定為 15 秒。 如需如何針對連線逾時進行疑難解答的詳細資訊,請參閱 針對連線逾時進行疑難解答。 如需查詢逾時疑難解答,請觀看這段 影片。