【问题标题】:sporadic ASP.NET data error: "Cannot find table 0"零星的 ASP.NET 数据错误:“找不到表 0”
【发布时间】:2011-01-17 14:49:42
【问题描述】:

在生产环境中部署了新版本的 ASP.NET 站点后,我每秒记录数十个数据错误,几乎总是出现“找不到表 0”错误。我们使用数据集并经常引用Table[0],虽然我了解在访问Table[0] 之前检查数据集以查找表的防御性编码实践,但在过去这从来都不是问题。某个页面将在一秒钟内正常加载,然后下一秒钟就会丢失其中一个数据驱动组件。只是看看这是否会为任何人敲响警钟。

更多细节:这次我使用了不同的构建服务器,虽然我认为两者的编译器设置相同,但我很难想到有一个开关可以使 50%我的数据库调用返回时没有表。我还将项目切换到 VS 2008,但当我切换回 VS 2005 时,我又恢复了所有这些更改。我注意到构建的程序集有一个新的 MyLibrary.XmlSerializers.dll,它不习惯的地方,但我也无法想象这是造成所有麻烦的原因。 (它也不会因调用 MyLibrary 而失败,或者至少不会超过任何其他时间。)

更新添加:我发现麻烦的构建是“发布”构建,工作构建被编译为“调试”。这可以解释吗?

在这些更改修复之前回滚到构建。 (重新启动 SQL Server,我们之前尝试过的步骤没有。)

问题似乎也是基于负载的 - 这在我们的集成和 QA 环境中运行没有问题,甚至我们的冒烟测试环境 - 指向生产数据的环境 - 在轻负载下也很好。

这是否具有您过去可能见过的任何东西的显着特征?

【问题讨论】:

  • 看看我下面的答案...这是一个迟到的答案,所以你可能忽略了它,但我之前已经解决了这个错误消息,并以“硬杀”结束了我描述的情况。

标签: asp.net sql-server dataset


【解决方案1】:

我之前已经准确地解决了这个错误消息。关键是底层数据方法吞下了超时异常。

你可能正在做这样的事情:

var table = GetEmployeeDataSet().Tables[0];

GetEmployeeDataSet 正在吞噬一个异常,可能是一个超时异常,这就是它只是偶尔发生的原因——它在负载下发生。您需要执行以下操作来修复它:

  1. 修改底层代码不要吞下异常,而是让它冒泡到下一个级别,以便您可以正确识别它。
  2. 确定导致问题的查询,然后重写、重新索引、非规范化或将硬件用于问题。有关更多信息,请参见:System.Data.SqlClient.SqlException: Timeout expired

【讨论】:

  • 谢谢;在我的例子中,代码有几个,所以这给了我一个很好的地方开始寻找和挂钩(异常块)。
【解决方案2】:

提出这个老问题是因为我们遇到了同样的问题,也许我们的解决方案可以更深入地了解导致此问题的原因。

本质上,此问题发生在生产环境中,该生产环境在使用多个线程同时处理多个作业的 Windows 服务中承受着非常重的负载(100 个用户通过 ASP.NET Web 应用程序使用同一个数据库,并且大约有 60 个事务/在使用 SQL Server 2000 的旧硬件上排名第二)。

不共享任何变量,即重新打开连接、启动事务、执行操作、提交事务和关闭连接。

在重负载下有时会出现以下异常之一:

NullReferenceException: Object reference not set to an instance of an
object.
at System.Data.SqlClient.SqlInternalConnectionTds.get_IsLockedForBulkCopy()

System.Data.SqlClient.SqlException:
The server failed to resume the transaction. Desc:3400000178  

New request is not allowed to start because it should come with valid  transaction descriptor  

This SqlTransaction has completed; it is no longer usable

似乎池中的连接以某种方式损坏并与以前使用的事务保持关联。此外,如果从池中检索到此类连接,则 sqlAdapter.Fill(dataset) 会导致空数据集,从而导致“找不到表 0”。因为我们的服务会在失败时重试操作(读取作业列表),并且它总是会从池中获得相同的损坏连接,所以它会失败并出现此错误,直到重新启动。

我们通过对异常使用 SqlConnection.ClearPool(connection) 来消除此问题,以确保从池中丢弃此连接并重组应用程序,以便更少的线程同时访问相同的资源。

我不知道究竟是谁造成了这个问题,所以我不确定我们是否真的解决了这个问题,也许只是让它变得如此罕见以至于还没有再次发生。

【讨论】:

    【解决方案3】:

    我见过类似的东西。我相信我们的问题与重复使用失败的会话有关(一旦会话对象失败,它就会进入不良状态并且无法恢复。)我们通过增加会话池的内存和增加网络的频率来修复它应用程序回收。

    它也是由一个新版本“引起”的,乍一看似乎没有任何变化来引起这种影响。然而,最终很明显,程序的逻辑是打开和关闭比以前更多的连接(可能多 20%)。这个小改动突破了我们之前配置的限制。

    【讨论】:

    • 这很有趣——我不认为这是我的“答案”,但我可以想象连接池是问题的一部分,因为它很神秘。我再看一下代码,看看有没有什么可疑之处。
    【解决方案4】:

    我在以非线程安全的方式使用 nHibernate Sessions 做某事时看到过类似的情况。这可以解释为什么你只能在负载下看到它。需要查看您的代码来猜测什么不是线程安全的。

    【讨论】:

      【解决方案5】:

      哪些数据库调用在版本之间发生了变化?

      这个错误显然是告诉你你的一个数据库调用有时没有返回任何数据;我想不出任何会导致代码/程序集问题的情况。

      【讨论】:

      • 添加了一个夜间报告,并更新了一个很少使用的 SP。没有更改核心功能,并且错误似乎弹出每个可能的地方可以调用数据库,这就是为什么它对我来说很可疑。
      【解决方案6】:

      您可以检查 SQL Server 日志中的错误。或者,Web 服务器事件日志。听起来您的连接池可能没有打开的连接,或者您的数据库可能已关闭。

      【讨论】:

      • SQL Server 错误日志是干净的。你能想到任何改变连接池选项的编译项目/程序集选项吗?我不能。
      猜你喜欢
      • 2014-06-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多