Win32异常(0x80004005):等待操作超时。

69

我正在运行一个ASP.NET Web Pages页面,在初始加载时从SQL服务器中提取项目列表。这个查询大约需要1秒钟左右的时间,可以在2秒钟内加载页面。返回大约有1000个记录,多少有所不同。我正在从Service Manager SQL数据库中提取主机名以及其他一些信息。

在这个页面中,我内置了一个搜索功能,它基本上运行相同的查询,但是使用基于主机名的LIKE运行查询。这将使用所有包含在搜索查询中的部分主机名加载相同的页面。该查询通常在SQL Management Studio中运行时间不到1秒钟,但是加载页面需要更长时间,并且有时会超时。

我的问题是,为什么基于参数的搜索需要更长时间,有时会因没有明显原因而超时?是否有任何措施可以采取以缓解这种超时情况?以下是完整的错误信息。

'/'应用程序中的服务器错误。


The wait operation timed out 

描述:当前网页请求的执行过程中出现未处理异常。请检查堆栈跟踪以获取有关错误信息及其在代码中的起源位置的更多信息。

异常详情:

System.ComponentModel.Win32Exception: The wait operation timed out
Source Error: 

Line 13:     }
Line 14:     
Line 15:     var selectedData = db.Query(selectCommand, searchTerm);
Line 16: 
Line 17:

Source File:  c:\Users\u0149920\Documents\My Web Sites\AppSupport\servers\default.cshtml    Line:  15

堆栈跟踪:

[Win32Exception (0x80004005): The wait operation timed out]
[SqlException (0x80131904): Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.]
   System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) +1753346
   System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) +5295154
   System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) +242
   System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) +1682
   System.Data.SqlClient.SqlDataReader.TryConsumeMetaData() +59
   System.Data.SqlClient.SqlDataReader.get_MetaData() +90
   System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) +365
   System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite) +1325
   System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite) +175
   System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) +53
   System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) +134
   System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) +41
   System.Data.Common.DbCommand.ExecuteReader() +12
   WebMatrix.Data.<QueryInternal>d__0.MoveNext() +152
   System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) +381
   System.Linq.Enumerable.ToList(IEnumerable`1 source) +58
   WebMatrix.Data.Database.Query(String commandText, Object[] parameters) +103
   ASP._Page_servers_default_cshtml.Execute() in c:\Users\u0149920\Documents\My Web Sites\AppSupport\servers\default.cshtml:15
   System.Web.WebPages.WebPageBase.ExecutePageHierarchy() +197
   System.Web.WebPages.WebPage.ExecutePageHierarchy(IEnumerable`1 executors) +69
   System.Web.WebPages.WebPage.ExecutePageHierarchy() +151
   System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage) +76
   System.Web.WebPages.WebPageHttpHandler.ProcessRequestInternal(HttpContextBase httpContext) +114

版本信息:Microsoft .NET Framework 版本:4.0.30319;ASP.NET 版本:4.0.30319.17929


11个回答

45

你遇到的问题是查询命令执行时间太长。我认为查询执行的默认超时时间是15秒。您需要设置CommandTimeout(以秒为单位),以便它足够长以完成其执行。 "CommandTimeout"与连接字符串中的"连接超时"不同,必须为每个命令设置。

在您的SQL选择事件中,请使用以下命令:

e.Command.CommandTimeout = 60

例如:

Protected Sub SqlDataSource1_Selecting(sender As Object, e As System.Web.UI.WebControls.SqlDataSourceSelectingEventArgs)
    e.Command.CommandTimeout = 60
End Sub

2
我刚刚解决了一个 Web 应用程序中的问题,查询确实花费了太长时间 - 因为没有人在数据库上为被查询的字段创建索引!这应该是第一步 :) - James McCormack

28

对于那些比我更了解的人,建议多读一遍,而不是标记为无用或误导。我曾经遇到过虚拟机(VM)因为所有资源都被锁定线程占用而变得无响应的问题,所以杀死线程是我唯一的选择。我并不建议任何正在运行长查询的人这样做,但对于那些卡在无响应的 VM 中的人可能会有所帮助。决策权在个人手中。是的,它将终止您的查询,但它保护了我的 VM 机器不被毁坏。

Serverstack已经回答了类似的问题。它解决了我在 VM 机器上运行 SQL 的问题。请查看此处

您需要运行以下命令来修复索引的问题。

exec sp_updatestats

20
这并非通用答案,即使索引统计信息最近已更新,查询仍可能运行时间超过任何给定的超时时间。 - Kenny Evitt
1
在运行之前,请务必阅读并理解执行 exec sp_updatestats 的后果。 - brianc
是的,我在虚拟机中遇到了这个问题。 - Jeeva J
这不是个坏建议,但太过浩大且需要上下文。如果由于查询缓慢而遇到CommandTimeout问题,这可能会解决它,因为它有助于SQL服务器找到更好的执行计划。但是,这个命令会更新所有统计数据,但问题很可能是一个表接收了足够的更新以扭曲计划(即计划假定1行具有匹配值,但实际上是100行)。你最好使用分析器找到缓慢的查询,获取其执行计划,并查找实际和估计行数之间的巨大差异,以找到需要统计数据更新的那个表。 - b_levitt
@b_levitt,请理解这种情况,我当时试图保存我的虚拟机。虚拟机没有响应,因此保存已完成的工作比考虑查询性能更为重要。一旦我恢复了虚拟机,我尽可能地调整了数据库。 - Sanjay Zalke
是的,我完全理解,并没有给你投反对票。我只是想说,在紧急情况下使用大锤时,你只需要指出它确实是一把大锤 :)。 - b_levitt

21

如果您正在使用Entity Framework,您可以通过执行以下操作来扩展默认超时时间(以便长时间运行的查询有更多时间完成):

如果你正在使用Entity Framework,你可以通过执行以下操作来扩展默认超时时间(以便长时间运行的查询有更多时间完成):

myDbContext.Database.CommandTimeout = 300;

其中myDbContext是您的 DbContext 实例,300是超时值(以秒为单位)。

(该语法适用于 Entity Framework 6。)


谢谢,这很有帮助。这是否意味着我的查询结构不好,太重或其他原因?我在SQL Server Profiler中检查了生成的SQL事务,没有发现任何奇怪的东西。 - Sam Alekseev

7

我曾遇到同样的问题。有时候运行exec sp_updatestats可以解决问题,但并非总是有效。我决定在查询中使用NOLOCK语句来加速查询。

只需在FROM子句后添加NOLOCK即可,例如:

SELECT clicks.entryURL, clicks.entryTime, sessions.userID
FROM sessions, clicks WITH (NOLOCK)
WHERE sessions.sessionID = clicks.sessionID AND clicks.entryTime > DATEADD(day, -1, GETDATE())

阅读完整文章,请点击这里


NOLOCK是一个很好的解决方案,当你的服务器正在进行大量的多用户工作或大量长时间运行的报告时! - Kristen Waite
6
NOLOCK通常是解决大多数问题的不良解决方案。 (http://blogs.sqlsentry.com/aaronbertrand/bad-habits-nolock-everywhere/): 1)“脏读” 2)缺失行 3)重复读取行 4)读取同一行的多个版本 5)索引损坏 6)读取错误等问题。 只需谷歌搜索“NOLOCK不好”,就会有更多信息。(提示:在某些情况下,快照隔离可能对您有帮助) - HansLindgren
3
我不同意使用NOLOCK通常都是“大多数问题的糟糕解决方案”。这实际上取决于具体问题以及你是否理解NOLOCK的作用。有些情况下,数据的整体完美并不是很重要。还有一些情况下非常重要,在这种情况下,你应该尽量减少查询时间/锁表所花费的时间。 - Panh
不使用NOLOCK? - Kiquenet

5

执行以下代码以重新索引数据库中的所有表: exec sp_MSforeachtable 'DBCC DBREINDEX(''?'','' '',90)' - François Breton

5

我尝试了此处的其他答案以及其他一些方法。我甚至停止并重新启动了SQL服务,但仍然无法解决问题。

不过,重启我的计算机确实解决了问题。


1
这个方法可以暂时解决问题,但问题会再次出现,需要重新启动,有没有真正的永久解决方法? - BlackICE

2
我们在将 SQL Server 从 2008 升级到 2014 后遇到了这个错误,之前我们本地开发的一些连接字符串中有一个类似 Data Source=./ 的参数。
        <add name="MyLocalDatabase" connectionString="Data Source=./;Initial Catalog=SomeCatalog;Integrated Security=SSPI;Application Name=MyApplication;"/>

将“./”更改为“(本地)”或“localhost”可以解决问题。
<add name="MyLocalDatabase" connectionString="Data Source=(local);Initial Catalog=SomeCatalog;Integrated Security=SSPI;Application Name=MyApplication;"/>

我在从SQL Server 2012升级到2014后遇到了同样的问题。虽然SQL Server和Web服务器位于不同的机器上,但将数据源从“SERVER”更改为“SERVER.domain.local”似乎已经解决了这个问题。 - Darren

2

我曾经遇到过同样的问题,通过运行 "exec sp_updatestats" 命令,问题得到解决并且现在可以正常工作。


1

我的数据表没有主键,所以我遇到了超时错误。设置主键后问题得到解决。


0
在我们的情况下,我们能够将原因缩小到一些视图上,这些视图上有WITH SCHEMABINDING。虽然这应该提高性能,但它导致了一个糟糕的查询计划(对被这些视图引用的表进行单个记录更新需要近2秒的经过时间)。移除WITH SCHEMABINDING意味着一切都恢复正常了,"等待操作超时"错误也消失了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接