今天生產環境遇到了異常: Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding. The statement has been terminated。
超時已過期。操作完成前的超時時間或服務器未響應。聲明已被終止
按照以往的經驗出現這種情況一般是兩種原因
- 數據庫發生死鎖,導致執行時間超時
- 數據量太大,導致在連接時間內,沒有完成sql處理,sql需要優化
針對這個異常,首先在測試環境沒有復現出來
然后在該操作執行期間查看活動監視器,分析了進程,資源等待和大量資源消耗的情況,然后在數據庫分析了鎖及阻塞情況,發現這次和以往不一樣,並沒有死鎖或者大量資源消耗及表阻塞的情況。
--是否堵塞
SELECT spid,blocked,waittime,waittype,waitresource,p.dbid,cpu,physical_io,memusage,open_tran
,status,login_time,last_batch,hostname,program_name,hostprocess,loginame,cmd,text
FROM master.dbo.sysprocesses p CROSS APPLY sys.dm_exec_sql_text(p.sql_handle) s
WHERE blocked > 0 OR spid IN(SELECT blocked FROM master.dbo.sysprocesses WHERE blocked > 0)
go
----查看被鎖表:
SELECT
request_session_id spid,
OBJECT_NAME(
resource_associated_entity_id
) tableName
FROM
sys.dm_tran_locks
WHERE
resource_type = 'OBJECT'
ORDER BY request_session_id ASC
--spid 鎖表進程
--tableName 被鎖表名
--死鎖
select
er.session_id,
CAST(csql.text AS varchar(max)) AS CallingSQL
from master.sys.dm_exec_requests er WITH (NOLOCK) CROSS APPLY fn_get_sql (er.sql_handle) csql
where er.session_id in (select request_session_id from sys.dm_tran_locks where resource_type = 'OBJECT');
然后嘗試調大了連接超時時間,依然是這個異常,基本已經可以排除上述的兩種情況。
以往的經驗行不通了,說明這次情況和以前不一樣,在stackoverflow上找到這么一篇文章
發現除了上述兩種情況外 數據庫的統計信息和/或查詢計划緩存不正確也可能會導致這個錯誤
https://stackoverflow.com/questions/8602395/timeout-expired-the-timeout-period-elapsed-prior-to-completion-of-the-operation
解決方案:
-- 更新表或索引視圖的查詢優化統計信息
exec sp_updatestats
在官網上找個存儲過程
更新表或索引視圖的查詢優化統計信息。 默認情況下,查詢優化器已根據需要更新統計信息以改進查詢計划;但在某些情況下,可以通過使用 UPDATE STATISTICS 或存儲過程 sp_updatestats 來比默認更新更頻繁地更新統計信息,提高查詢性能。
更新統計信息可確保查詢使用最新的統計信息進行編譯。 不過,更新統計信息會導致查詢重新編譯。 我們建議不要太頻繁地更新統計信息,因為需要在改進查詢計划和重新編譯查詢所用時間之間權衡性能。 具體的折衷方案取決於你的應用程序。 UPDATE STATISTICS 可以使用 tempdb 對行樣本進行排序以生成統計信息。
執行過后發現並沒有解決問題:
於是看一了第二條
-- 刪除內存中緩存的所有執行計划
dbcc freeproccache
刪除計划高速緩存中的所有元素,通過指定計划句柄或 SQL 句柄從計划高速緩存中刪除特定計划,或者刪除與指定資源池相關聯的所有高速緩存條目。
備注
DBCC FREEPROCCACHE 不清除本機編譯的存儲過程的執行統計信息。 過程高速緩存不包含有關本機編譯的存儲過程的信息。 從過程執行中收集的任何執行統計信息都將顯示在執行統計信息 DMV 中:sys.dm_exec_procedure_stats (Transact-SQL) 和 sys.dm_exec_query_plan (Transact-SQL)。
執行完之后,可以正常操作,基本可以確定本次是因為內存中緩存的執行計划有誤或者不是最優導致的,但是什么情況會導致這個問題目前還不清楚,需要進一步排查。