【问题标题】:Is there a bug or limitation in LINQ to SQL which would cause stored procedures to timeout?LINQ to SQL 中是否存在会导致存储过程超时的错误或限制?
【发布时间】:2011-09-05 15:50:21
【问题描述】:

我在 Windows Server 2008 R2 上使用 .NET Framework 4.0、C# 和 SQL Server 2008 R2。我的 LINQ to SQL 数据上下文位于单独的库中,相关代码在 Windows 服务中运行。

我有一个经过良好测试的关键任务存储过程,它接受大约 19 个参数(我知道我知道),执行一些简单的“if”逻辑并构建一些变量,并将数据插入 3 个表中。它不使用游标或临时表。我已经描述了 SP 的作用,因为我不能随意发布 sql 代码。

由于命令超时,我在 Internet 上看到很多关于 SqlException 的帖子,而响应很少超出“增加命令超时”的范围。 Example

我遇到了上述异常,因此尝试将创建数据上下文时的命令超时时间增加到 10 分钟。在它坐在那里等待那 10 分钟后,我仍然得到异常。然后,我添加了一些调试日志记录以捕获 LINQ to SQL 的输出,并在 SQL Server Management Studio 中使用相同的参数值运行 SP。它在几分之一秒内成功完成。

这是 LINQ to SQL 日志输出(默认超时)与其他一些日志输出混合在一起,我在这篇文章中混淆了 SP 名称:

16:01:37 15269 Irrelevant log line, deleted for StackOverflow
EXEC @RETURN_VALUE = [dbo].[NAMEHIDDENONSTACKOVERFLOW] @Eastings = @p0, @Northings = @p1, @Speed = @p2, @UpdateDate = @p3, @UserId = @p4, @Postion = @p5, @Direction = @p6, @VehicleId = @p7, @Status = @p8, @Confidence = @p9, @Latitude = @p10, @Longitude = @p11, @PosLatitude = @p12, @PosLongitude = @p13, @WatchBoxId = @p14, @LastWatchBoxId = @p15, @WatchBoxIdAlert = @p16, @ImbolizationState = @p17, @TowAwayAlertState = @p18
-- @p0: Input Int (Size = -1; Prec = 0; Scale = 0) [560120]
-- @p1: Input Int (Size = -1; Prec = 0; Scale = 0) [5754714]
-- @p2: Input Int (Size = -1; Prec = 0; Scale = 0) [0]
-- @p3: Input DateTime (Size = -1; Prec = 0; Scale = 0) [02/08/2011 20:45:08]
-- @p4: Input Int (Size = -1; Prec = 0; Scale = 0) [11]
-- @p5: Input NVarChar (Size = 4000; Prec = 0; Scale = 0) [Swindon United Kingdom]
-- @p6: Input NVarChar (Size = 4000; Prec = 0; Scale = 0) [5]
-- @p7: Input Int (Size = -1; Prec = 0; Scale = 0) [15269]
-- @p8: Input Int (Size = -1; Prec = 0; Scale = 0) [901]
-- @p9: Input Int (Size = -1; Prec = 0; Scale = 0) [0]
-- @p10: Input Float (Size = -1; Prec = 0; Scale = 0) [51.939899]
-- @p11: Input Float (Size = -1; Prec = 0; Scale = 0) [-2.125414]
-- @p12: Input Float (Size = -1; Prec = 0; Scale = 0) [51.9333333]
-- @p13: Input Float (Size = -1; Prec = 0; Scale = 0) [-2.1]
-- @p14: Input Int (Size = -1; Prec = 0; Scale = 0) [-1]
-- @p15: Input Int (Size = -1; Prec = 0; Scale = 0) [-1]
-- @p16: Input Int (Size = -1; Prec = 0; Scale = 0) [0]
-- @p17: Input Int (Size = -1; Prec = 0; Scale = 0) [0]
-- @p18: Input Int (Size = -1; Prec = 0; Scale = 0) [0]
-- @RETURN_VALUE: Output Int (Size = -1; Prec = 0; Scale = 0) [Null]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.1

16:02:23 0 Error in DoPoll 1 Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.

我从搜索 Stack Overflow 中得到的唯一线索是,可能存在一种称为“参数嗅探”的问题,但我仍在阅读它以找出它的含义。

这是非常关键的东西,如果它在生产中失败,我会遇到很多麻烦,所以我很想回滚 LINQ 并返回原版 ADO。我的问题是:我的方法有什么问题吗(换句话说:我是个白痴吗?)或者 LINQ to SQL 中是否存在可能导致此问题的问题或错误?我可以做些什么来解决这个问题,还是恢复到香草 ADO 会更好?

【问题讨论】:

标签: c# linq-to-sql stored-procedures


【解决方案1】:

我会假设您已尝试增加 Linq 数据上下文的超时时间,正如您提到的,您发现的大多数帖子都暗示了这一点。

不过……

在这种情况下,让很多人感到不安的是 Web 服务器,尤其是如果您在 IIS7 上运行它。

过去我曾遇到过这样的情况,我花了无数小时追查事情以找出某些事情超时的地方,只是通过更改 IIS7 管理中服务器应用程序的超时值在 5 秒内修复它面板。

我并不是说这绝对是您的问题,但如果您只将 Web 服务器设置为 30 秒(这是默认设置),您可以整天坐下来更改数据上下文中的超时,并且您永远到不了任何地方。

如果您想尝试一下,请登录到运行 Web 服务器的机器,展开左侧窗格中的服务器/网站以深入了解运行存储过程的应用程序。

此时您有几个地方可以查看。如果您返回网站级别 EG:“默认网站”并单击它,然后单击最右侧的高级设置并展开连接限制,您可以在那里设置整个网站的秒数。

如果您从经典 ASP 文件调用您的 SP,则单击您的 web 应用程序,然后双击中心窗格中的 ASP 图标,展开“限制属性”并更改脚本超时值以适合。

最后,如果您使用某种 CGI 操作执行此操作,请单击您的 Web 应用程序,然后双击 CGI,然后在其中更改超时时间。

最后但并非最不重要的一点是,如果上述方法都没有帮助,您可以尝试将以下 XML sn-p 添加到您的应用程序 web.config 文件中的适当位置,以控制 .NET 脚本执行超时:

    <system.web>
      <httpRuntime executionTimeout="180"/>
    <\system.web>

如果您没有在 IIS7 上运行,那么您需要查看您的服务器用于类似设置的控制面板。

【讨论】:

  • 感谢您提供详细的答案,但不幸的是 IIS 不是这个等式的一部分。这是一项 Windows 服务。
【解决方案2】:

LINQ-to-SQL 在后台使用 vanilla ADO.NET。至少就 ADO.NET 和 SQL Server 而言,您并没有接近最大化它们可以处理的参数数量。 LINQ-to-SQL 对存储过程非常友好,只要存储过程不做任何可怕的事情,例如在过程中创建动态 SQL 或从临时表返回结果。

您如何为存储过程创建 Linq-to-SQL 映射? Visual Studio 的 SDK 中有一个名为“SQLMETAL”的行命令工具,它可以创建 .dbml 和 .cs,如果由命令行开关指定,它还将映射存储过程。它对存储过程进行了足够的分析,以验证 LINQ to SQL 是否可以处理它们,并且会为您提供不符合其标准的存储过程的错误消息。尝试运行 SQLMETAL,看看你会得到什么样的消息。

【讨论】:

  • 感谢赛隆。我知道原版 ADO 在幕后使用(实际上我看到的异常是 ADO 异常),但不知道 SqlMetal 提供了有用的输出,所以我会尝试一下。为了回答您的问题,我通过将存储过程从服务器资源管理器拖放到 Visual Studio 2010 中的数据上下文图来生成 dbml。
  • 我一直发现 SqlMetal 比拖放可视化工具(我认为它是演示软件,而不是生产质量)更好。 Linq-to-SQL 对存储过程确实有一定的限制,我知道 SqlMetal 会检查它们。
  • 试过了,只有一个来自不相关数据库对象的警告。
【解决方案3】:

我恢复到 vanila ADO 并且遇到了同样的异常,所以答案必须是“不,这不是 LINQ to SQL 错误”。我还根据参数嗅探文章重构了 SP,但没有帮助。随着代码再次开始工作,我只能想象这是一个临时的系统问题或数据库故障。为了其他有类似问题并稍后通过搜索找到此问题的人的利益,如果我发现更多内容,我会进一步更新,因为一位同事很快会在另一个系统上测试代码。

编辑:这是系统问题;具体来说,我的 VMWare 磁盘需要进行碎片整理。

(根据关于元的建议,我应该发布自己的答案而不是更新问题)。

【讨论】:

  • SQL SP 中是否有任何“IF”子句?我注意到有时 SQL 报告 1 个结果集,有时更多。我会尝试找到我用来确定这一点的代码。
  • 尝试运行exec sys.sp_procedure_params_rowset 'yoursp' 几次,看看输出是否保持不变。
  • 是的,有一些 IF 子句。
  • 它几乎是一段原子代码,它接收原始数据,然后确定要插入的内容和位置。如前所述,它不使用游标或临时表,只是选择、插入、声明和布尔逻辑。感谢您提供有关系统程序的提示。目前正在等待同事反馈。
  • 我现在倾向于认为这是硬盘问题!我已获准在周日进行部署,如果我了解更多可以帮助其他有类似问题的人,我会回帖。感谢所有试图提供帮助的人。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-14
  • 1970-01-01
  • 1970-01-01
  • 2023-03-20
  • 2010-10-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多