針對查詢逾時錯誤進行疑難排解
徵狀
假設應用程式會查詢 SQL Server 資料庫中的資料。 如果查詢未在設定的逾時值內傳回任何資料 (通常為 30 秒),應用程式就會取消查詢並產生下列其中一個錯誤訊息:
-
逾時已過期。 在作業完成之前超過逾時等待的時間,或是伺服器未回應。 陳述式已終止。
-
System.Data.SqlClient.SqlException: 已超過連接逾時的設定。 在作業完成之前超過逾時等待的時間,或是伺服器未回應。
說明
這些錯誤會在應用程式端發生。 應用程式會設定逾時值,如果達到逾時,則會取消查詢。 在 SQL Server 端,從用戶端取消查詢會造成 Attention 事件,錯誤 3617 (MSSQLSERVER_3617)。 如果應用程式端的逾時值設定為 0 (沒有時間限制) ,Database Engine 會執行查詢,直到完成為止。
- 在 .NET Framework System.Data.SqlClient 中,於 CommandTimeout 屬性上設定逾時值。
- 在 ODBC API 中,透過 SQLSetStmtAttr 函式中的
SQL_ATTR_QUERY_TIMEOUT
屬性進行設定。 - 在 JAVA 資料庫連線 (JDBC) API 中,透過 setQueryTimeout 方法進行設定。
- 在 OLEDB 中,透過
DBPROP_COMMANDTIMEOUT
結構上的DBPROP
屬性進行設定。 - 在 VBA (Excel) 中,透過 ADODB.Command.CommandTimeout 屬性進行設定。
查詢逾時與連接逾時屬性不同。 後者會控制等待連接成功的時間長度,而且不涉及查詢執行。 如需詳細資訊,請參閱查詢逾時與連接逾時不同。
疑難排解步驟
到目前為止,查詢逾時的最常見原因是查詢效能不佳。 這表示查詢的執行時間超過預先定義的查詢逾時值。 讓查詢執行更快速是疑難排解建議的第一個目標。 查詢的檢查方式如下:
使用擴充事件或 SQL 追蹤來識別造成逾時錯誤的查詢。 您可以將 Attention 事件與
sql_batch_completed
和rpc_completed
擴充事件一起追蹤,並在相同的session_id
上相互關聯。 如果您觀察到已完成的事件緊接著注意事件,且已完成事件的持續時間大約對應至逾時設定,則您已識別出查詢。 以下為範例:注意事項
在此範例中,
SELECT
查詢幾乎剛好執行 30 秒後停止。 具有相同工作階段識別碼的 Attention 事件指出已由應用程式取消查詢。名稱 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/9/30 09:50:55.0000 注意 54 選取 … from Customers WHERE cid = 192937 40000 2021/9/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
設定是否小於預期的查詢持續時間。 如果使用者的設定正確且仍然發生逾時,這是由於查詢效能問題所造成。 以下是 ADO.NET 程式碼範例,其逾時值設定為 10 秒: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); } } } } }
查詢逾時與連線逾時不同
查詢逾時與連線逾時或登入逾時不同。當資料庫伺服器的初始連線達到預先定義的逾時期間時,就會發生連線或登入逾時。 在此階段中,尚未將任何查詢提交至伺服器。 這些訊息是連線或登入逾時錯誤的範例:
-
連線逾時已過期。 嘗試取用預先登入交握通知時所經過的逾時期間。 這可能是因為登入前交握失敗,或伺服器無法及時回應。 嘗試連線到此伺服器時所花費的持續時間為 [預先登入] initialization=23;handshake=14979;
-
逾時已過期。 在作業完成之前超過逾時等待的時間,或是伺服器未回應。 System.ComponentModel.Win32Exception (0x80004005) :等候作業逾時。
連線逾時值是用戶端設定,通常設定為 15 秒。 如需如何針對連線逾時進行疑難排解的詳細資訊,請參閱 針對連線逾時進行疑難排解。 如需查詢逾時疑難排解,請觀看這段 影片。