如何解决间歇性 SQL 超时错误
Posted
技术标签:
【中文标题】如何解决间歇性 SQL 超时错误【英文标题】:How to Troubleshoot Intermittent SQL Timeout Errors 【发布时间】:2011-12-06 07:43:25 【问题描述】:我们每天都会遇到一些实例,其中我们从多个应用程序中收到大量 SQL 超时错误(System.Data.SqlClient.SqlException:超时已过期。在操作或服务器完成之前超时时间已过没有响应。)我们的网络上有 100 多个不同的应用程序,包括 Web 和桌面应用程序。从 VB6 和 Classic ASP 到 .NET 4 的所有内容。我可以找到各种显示副作用的数据,但无法查明导致这种情况的原因。我们的 DBA 说 SQL 服务器没有问题,IT 说 Web 服务器或网络没有问题,所以我当然要在中间尝试解决这个问题。
我真的只是在寻找有关我可以做哪些其他故障排除的建议来尝试追踪这个问题。
我们在集群中运行 SQL Server 2008 R2。有一些不同的服务器连接到它,从 Windows server 2003 到不同品种的 2008。
这是我到目前为止所做的:
运行长时间运行的查询和死锁的 SQL 跟踪。 这表明在出现问题时没有死锁,长时间运行的查询都与我们的超时错误一致,但看起来是副作用,而不是原因。非常基本的查询通常会立即返回,有时最终需要 30、60 或 120 秒才能运行。这种情况会持续几分钟,然后一切都会恢复并正常工作。 使用性能监视器来跟踪连接池连接。这有时会显示连接数在超时时间附近出现一些峰值,但仍然没有达到默认的 100 个连接限制的一半。同样,这里似乎没有任何迹象表明原因。 将 Web 应用程序分离到不同的应用程序池中。我们试图缩小我们认为可能是主要问题的应用程序(最烦人等)并将它们放在单独的应用程序池中,但这似乎没有影响或帮助我们缩小范围。 监控 SQL Server 上的磁盘使用情况。我们已经在 SQL Server 上进行了一些监控,并且在发生这些超时时没有看到任何峰值或任何问题迹象。 已验证的 TempDB 不是问题的原因。如果我想到我们尝试过的其他方法,我会回来添加更多内容。请告诉我一些关于接下来要解决什么问题的想法。
【问题讨论】:
您查看过有关锁定 sql server 的性能计数器吗? 几年前我也遇到过类似的问题 - 结果发现清洁器每天大约在同一时间出现,并拔下路由器为真空吸尘器提供电源插座......没有帮助,我知道。 @Nevillek:起初我以为你的意思是“更清洁”是一些 SQL 进程,但后来,哇! 不久前遇到了同样的问题。对我们来说,解决方案不是摆弄 SQL Server。是我们的代码库没有清理在所有情况下都正确关闭连接的阅读器。自从我们经历了这一切以来,还没有遇到过这个问题。 我最初认为这也是连接的问题,但是在监控这些时,我们通常不会在任何给定时间获得超过 20-30 个连接,所以这似乎不是问题. 【参考方案1】:对长时间运行的查询和死锁运行 SQL 跟踪。这表明没有 出现问题时的死锁和长时间运行的查询 与我们的超时错误一致,但看起来是副作用,并且 不是原因。通常返回的非常基本的查询 有时会立即运行 30、60 或 120 秒。这 发生了几分钟,然后一切恢复正常 之后。
看起来有些查询/事务在完成之前会锁定您的数据库。您必须找出哪些查询正在阻塞并在其他时间重写/运行它们以避免阻塞其他进程。此时等待的查询刚刚超时。
还有一点需要研究的是事务日志和数据库的自动增量大小。将它们设置为固定大小而不是当前文件的百分比。如果文件越来越高,分配足够空间所需的时间最终会随着事务超时而变长。然后你的数据库就停止了。
【讨论】:
哦,自动增量是个好主意——没想到。还要检查自动收缩! 谢谢 Peer,我应该补充一点,我们确实确保不是事务日志或数据库大小调整导致了问题。我会做更多的挖掘,看看是否能找到任何阻塞查询。 您可以使用活动监视器查看Head Blocker(右键单击ssms中的sql实例) 更新 - 我们仍然看到一些超时,但我认为这很可能是同一问题的更多案例......我们只是缩小范围并修复我们可以解决的问题,希望我们会抓住一切。 不要使用自动收缩,它会从你的数据库中分裂出来。 sqlskills.com/blogs/paul/post/…【参考方案2】:性能问题归结为 CPU、IO 或锁争用。听起来你已经排除了 IO。我猜 CPU 不是问题,因为这是一个数据库,而不是数字处理器。所以,这就留下了锁争用。
如果您可以在查询超时时执行 sp_who2,您可以使用 BlkBy 列来追溯其他人正在等待的持有锁。由于这种情况每天只发生几次,如果您手动运行,您可能无法捕获足够的数据,因此我建议您安装一个自动化系统来定期转储此输出,或者可能由应用程序超时异常。您还可以按照同行的建议,使用活动监视器实时观察查询响应能力的下降情况。
一旦您找到了长时间运行的查询和执行它的应用程序,您就可以立即通过将单个应用程序的超时时间减少到所有其他应用程序以下来解决超时的多米诺骨牌(现在,它必须更长)。然后,您应该检查代码以确定更好的解决方案。您可以通过在存储过程中更快地提交事务来减少锁定的持有时间,或者通过 NOLOCK 或 UPDLOCK 等提示减少读取查询所需的锁定。
这里有更多关于 sp_who2 的阅读:http://sqlserverplanet.com/dba/using-sp_who2/
以及查询提示: http://msdn.microsoft.com/en-us/library/ms181714.aspx http://msdn.microsoft.com/en-us/library/ms187373.aspx
【讨论】:
sp_who2 +1,我发现 sp_who3 也很有用,因为它包含实际查询 使用 sp_who2 并在 BlkBy 列中找到 SPID 后,您可以使用DBCC INPUTBUFFER([SPID from sp_who2 in BLKBY column])
查找线程正在执行的查询。 sqlserverplanet.com/dba/using-dbcc-inputbuffer
这是sp_who4
的URL,其中包括@Dunc 所说的实际查询:saji-sqlsolutions.blogspot.com/2013/04/spwho4.html【参考方案3】:
有点远见,但在不久前的实验室中,我们遇到过 SQL Server 似乎没有响应的情况,这不是因为我们使用了 CPU 或我们可以在 SQL Server 中跟踪的任何东西,它似乎对所有测试都有效但在某些负载下连接失败。
这个问题原来是由于针对服务器的流量过大,这意味着我们在 Windows 中触发了内置的 Windows Syn Attack Flood Protection。令人讨厌的是,当您点击此按钮时,Windows 服务器或 SQL 中没有记录消息 - 您只会看到连接失败的症状 - 这是因为 Windows 在接受消息时减慢了速度,让我们建立一个队列。从连接的角度来看,服务器似乎没有响应(它甚至不确认消息到达)
http://msdn.microsoft.com/en-us/library/ee377084(v=bts.10).aspx
向下滚动到 SynAttackProtect,您将看到 Windows Server 2003 sp1 及更高版本中的默认设置是默认启用此功能。它实际上是一种 DDOS 保护机制,并且它触发的日志记录的缺失使得很难检测到您的服务器何时执行此操作。
MS 实验室花了 3 天时间才弄明白。
您提到了 100 个连接,我们有一个应用程序不断连接、运行查询然后断开连接,它没有保持连接打开。这意味着我们在每台机器连接上都有多个线程g 这样做,10 台机器,每台机器有多个线程,并且认为持续建立/丢弃的不同连接足以触发防御。
你是否处于那个水平(因为它不是 MS 明确定义的阈值)很难说。
【讨论】:
伙计,我认为这实际上可能是它,似乎它符合正在发生的事情......不幸的是,我们的 SQL 服务器正在 Windows 2008 Server 上运行,并且不再这样设置 :( 感谢不过建议! 这是一个远射 - 但如果防守被关闭,那就不可能了。【参考方案4】:就像其他发帖人所建议的那样,听起来您遇到了锁争用问题。几周前我们遇到了类似的问题;但是,我们的问题更加断断续续,并且经常在我们让 DBA 进入服务器运行 sp_who2 以追查问题之前清理干净。
我们最终做的是在锁超过某个阈值时实现电子邮件通知。一旦我们把它放在适当的位置,我们就能够识别正在锁定的进程,并在适当的地方将隔离级别更改为读取未提交以解决问题。
Here's an article that provides an overview of how to configure this type of notification.
如果锁定是问题所在,并且您还没有这样做,我建议您查看configuring row versioning-based isolation levels。
【讨论】:
【参考方案5】:您在跟踪和分析方面走在了正确的轨道上。您需要做的是寻找超时的查询的共同点——它们很可能都会命中一小部分表或索引。我怀疑某些应用程序有一个长时间运行的更新/插入,这会影响对使用受更新/插入影响的索引的表的查询。
您必须稍微向后工作 - 考虑到您看到超时的表子集,请查看这些表上的索引。查找在 smae 时间运行的、触及这些表/索引的其他查询。我打赌你会发现一小部分更新/插入这样做。
然后你需要做出一些决定。一种选择是更改超时查询的锁定提示。但这通常是不好的做法,因为它会在一段时间内掩盖真正的问题。虽然您可能会看到超时消失一段时间,但根据您选择的提示,您最终可能会遇到脏读,然后从这些查询中返回虚假数据。结果可能比超时更糟糕 - 很难说。
最好的办法是弄清楚您的哪些应用程序正在提交您找到的更新/插入,并深入了解它们为什么要花这么长时间。
【讨论】:
【参考方案6】:我建议你深入了解一下超酷的 SQL Server 的Dynamic Management Views 功能:
动态管理视图和函数返回服务器状态信息 可用于监控服务器实例的健康状况、诊断 问题,并调整性能。
本文是 DMV 的一个良好开端,尽管它是为 SQL 2005 编写的(DMV 功能首次出现):Troubleshooting Performance Problems in SQL Server 2005,尤其是“阻塞”章节。
【讨论】:
【参考方案7】:我对这些问题的经验(虽然不是在 SQL Server 上)是过度的多任务处理通常是问题的原因。如果许多连接(几乎)同时查询相似/连接的数据/表,则 DBMS 可能难以保持所有隔离检查。与使某些连接等待其他连接完成的事情相比,这并不是磁盘使用的问题。同步在 CPU 使用方面非常昂贵。
在我看来,100 个连接太多了。 (再次根据我的经验)即使要求一台机器完成 20 个连接也可能过于乐观。
【讨论】:
在一台服务器上(没有集群!)我们平均有 5oo-6oo 个并发用户和高峰时段每秒大约 250 个事务。没问题;-) 这对我来说非常令人惊讶,也相当令人印象深刻。需要考虑一下这些事情。但是我仍然认为尝试使用较小的连接池更有效,因为让连接等待它们的时间到达 DB 处理时间,而不是让它们在 DB 层同时工作。这是我最好的猜测,祝你好运。 讽刺地感谢那些对我在一个模糊而复杂的问题上的经历投反对票的人。如此多的尝试帮助解决利基问题,而不是扮演谁首先回答一个普遍的问题,并且在 SO 上对问题进行了高度投票。 @Brimstedt 我夸大了一点,抱歉 :)【参考方案8】:听起来您可能已经有了答案,但如果您需要更多的地方查看,您可能需要检查临时数据库的大小和活动。我们曾经在一个客户站点遇到过这样的问题,一天几次,他们的性能会严重下降并且偶尔会超时。问题原来是一个单独的应用程序,它严重破坏了临时数据库,影响了整体服务器性能。
祝您好运,继续进行故障排除!
【讨论】:
谢谢,这是我们的 DBA 检查的一件事,我们的 TempDB 没问题。我会将其添加到我们检查的事项列表中。 我不是 dba,所以您是否有机会在检查 tempdb 时扩展此处查找的内容?【参考方案9】:如果在 SQL 服务器上安装了防病毒软件,我已经看到类似的问题。 AV 的自动更新功能正在为服务器计时,并且没有为 SQL Server 提供足够的 CPU。
另外,您是否在 SQL 服务器本身上放置了一个小型应用程序来验证可以建立连接或运行非常基本的 SQL,例如“SELECT GETDATE();”?这将消除网络的可能性。
【讨论】:
【参考方案10】:由于我每天都在工作中进行故障排除,因此我想做以下事情:
由于它是 SQL Server 2008 R2,您可以运行作为产品一部分提供的 SQLDiag。您可以在线参考书籍以获取更多详细信息。简而言之,捕获服务器端跟踪和阻止脚本。
捕获跟踪后,查找“注意”事件。那将是收到错误的 spid。如果您按 SPID 过滤,您会在“注意”之前看到 RPC:Completed 事件。看看那边的时间。那个时间是30秒吗?如果是,则客户端等待 30 秒以从 SQL 获得响应并“超时”[这是客户端设置,因为 SQL 永远不会停止和连接]
现在,检查正在运行的查询是否真的需要 30 秒?
如果是,则调整查询或增加客户端的超时设置。
如果不是,则此查询必须等待某些资源(阻塞)
此时返回 Blocker Script 并检查“注意”到来的时间范围
以上假设问题与 SQL Server 无关!
【讨论】:
如果您有一些关于如何在 2016 或更新版本的 Sql Srver 上执行此操作的更新说明。【参考方案11】:当在 C# 应用程序中通过 SqlCommand 对象运行查询时,我们在 SQL Server 2012 / SP3 中遇到过这种情况。命令是对具有一个表参数的存储过程的简单调用;我们传递了一个大约 300 个整数的列表。该过程依次调用三个用户定义的函数,并将表作为参数传递给每个函数。 CommandTimeout 设置为 90 秒。
在 SQL Server Management Studio 中使用相同参数运行完全相同的存储过程时,查询运行时间为 15 秒。但是当使用上述设置从我们的应用程序运行它时,SqlCommand 超时。相同的 SqlCommand(具有不同但可比较的数据)已经成功运行了数周,但现在它失败了,因为任何表参数包含超过 20 个左右的整数。我们进行了跟踪,发现当从 SqlCommand 对象运行时,数据库花费了整个 90 秒来获取锁,并且仅在大约超时时刻才会调用该过程。我们更改了 CommandTimeout 时间,无论我们选择什么,存储过程都只会在该时间段结束时被调用。因此我们推测 SQL Server 无限期地一遍又一遍地获取相同的锁,并且只有 Command 对象的超时导致 SQL Server 停止其无限循环并开始执行查询,此时已经太晚了,无法成功。在类似的服务器上使用类似的数据模拟同样的过程没有显示出这样的问题。我们的解决方案是重启整个数据库服务器,之后问题就消失了。
因此,SQL Server 中似乎存在一些问题,其中一些资源被累积消耗并且从未释放。最终,当通过 SqlConnection 连接并运行涉及表参数的 SqlCommand 时,SQL Server 进入获取锁的无限循环。循环由 SqlCommand 对象的超时终止。解决方案是重新启动,显然恢复(临时?)SQL Server 的健全性。
【讨论】:
请大家...这与 SqlConnection 超时时间或查询运行所需的时间无关。回答前请详细阅读我的陈述。 您找到更好的解决方案了吗? 我们有一个类似的问题,为了解决这个问题,我们曾经重新启动 SqlServer 服务或重新启动服务器,这需要一段时间才能使数据库再次可用,因此我们了解到,如果您修改MAX MEMORY
属性通过 SQL Server Management Studio 资源被释放,数据库恢复正常,直到它再次发生,但我们在我们的应用程序中检测到 Timeout expired
后调用 T-SQL 脚本(存储过程)来修改最大内存在try catch
块上。【参考方案12】:
问题是由于查询错误导致执行查询的时间超过 60 秒或锁定在表上
这个问题看起来像是发生了死锁;我们有查询阻止查询及时完成。查询的默认超时时间为 60 秒,超过此时间我们将遇到超时 SQLException。
请检查 SQL Server 日志中是否存在死锁。另一种解决问题的方法是增加命令对象的超时时间(临时解决方案)。
【讨论】:
【参考方案13】:这些服务器是虚拟化的吗?在另一篇文章中,我读到了由于内存不足而导致有时运行非常缓慢的 SQL 服务器。这反过来又是由所谓的内存气球引起的,虚拟程序用来限制该虚拟服务器使用的内存量。很难找到,因为物理内存的压力与 SQL 服务器本身无关。
临时性能下降的另一个常见原因可能是病毒扫描程序。安装新的病毒定义后,所有其他进程都会受到影响并且运行速度非常慢。检查任何其他自动更新过程,这也可能会非常意外地占用大量资源。祝你好运!
【讨论】:
【参考方案14】:Windows 团队通过关闭 TLS-DHE* 密码解决了我们的问题。
我们遇到的问题:我们有从一台服务器(sql server 2012 和 windows 2012 R2)运行并连接到另一台服务器(SQL server 2016 SP2 和 windows 2019)的 SSIS 包,我们过去有时会超时的 SSIS 包,它随机失败。在 windows 团队关闭 TLS-DHE 密码后,问题得到解决。
https://support.microsoft.com/en-us/topic/transport-layer-security-tls-connections-might-fail-or-timeout-when-connecting-or-attempting-a-resumption-326bd5b1-52a1-b367-8179-b154e5c01e90
【讨论】:
您能否确认您正在尝试为本页顶部问题中描述的问题提供解决方案?我之所以这么问,是因为我的印象是“我们遇到了一个不同但相似的问题,而这已经被……解决了”。【参考方案15】:我遇到了类似的问题,发现是由于默认的 .Net 框架设置
Sqlcommand.Timeout
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.commandtimeout(v=VS.100).aspx
微软在上述网址中表示默认为 30 秒,请尝试将其设置为更高的秒数或 -1,然后再打开连接以查看这是否能解决问题。
它可能是您的 web.config 或 app.config 文件或您的应用程序/网络服务器配置文件中的设置。
【讨论】:
谢谢,但问题不在于它花费的时间超过 30 秒,这些查询通常需要 1 秒才能运行,但被其他东西挂断了。【参考方案16】:我遇到了同样的问题。我在几个我可以识别的经常长时间运行的功能中构建了一些日志记录。当我经常说的时候,我的意思是大约 2% 的时间。所以部分日志插入了过程或查询的开始时间和结束时间。然后我生成了一个简单的报告,按总执行时间递减排序几天的日志。这是我发现的。
长时间运行的实例总是在 HH:00 和 HH:02 或 HH:30 和 HH:32 之间启动,并且在这些时间之间没有任何短期运行的查询运行。有趣....
现在看来,我所经历的混乱实际上有了更多的秩序。我使用的恢复目标为 0,这在我的数据库中实现了“间接检查点”,因此我的恢复时间可以达到近 1 分钟。导致这些检查点每 30 分钟创建一次。
哇,真是巧合!
在微软关于更改数据库恢复时间的在线文档中带有这个小警告......
“为间接检查点配置的数据库上的在线事务工作负载可能会遇到性能下降。”
哇,图……
所以我修改了我的恢复时间并且没有更多问题了。
【讨论】:
以上是关于如何解决间歇性 SQL 超时错误的主要内容,如果未能解决你的问题,请参考以下文章
解决Azure Web App 500内部服务器错误超时问题并对其进行故障排除
如何解决 NSInvalidArgumentException 错误?