Fill(DataTable)成功进行测试,挂起在Production中

时间:2016-12-22 17:33:31

标签: c# sql-server sqldataadapter

我有一个控制台批处理应用程序,其中包含一个使用SqlDataAdapter.Fill(DataTable)在表上执行简单SELECT的过程。

private DataTable getMyTable(string conStr)
    {
        DataTable tb = new DataTable();
        StringBuilder bSql = new StringBuilder();
        bSql.AppendLine("SELECT * FROM MyDB.dbo.MyTable");
        bSql.AppendLine("WHERE LEN(IdString) > 0");                 
        try
        {
            string connStr = ConfigurationManager.ConnectionStrings[conStr].ConnectionString;
            using (SqlConnection conn = new SqlConnection(connStr))
            {
                conn.Open();
                using (SqlDataAdapter adpt = new SqlDataAdapter(bSql.ToString(), conn))
                {
                    adpt.Fill(tb);
                }

            }
            return tb;
        }          
        catch (SqlException sx)
        {
            throw sx;
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

此方法是同步执行的,并且在几个月的测试环境中成功运行 - 无论是从命令行启动还是在AutoSys作业的控制下启动。

然而,当进入生产阶段时,这个过程就会挂起 - 就像我们所知道的那样,在Fill方法中。更糟糕的是,它显然开始产生新的请求线程,而不是超时,几个小时之后,在应用服务器上消耗了超过5 GB的内存。这影响了其他活跃的应用程序,让我非常不受欢迎。没有例外。

连接字符串就像它们来的那样普通。

"data source=SERVER\INSTANCE;initial catalog=MyDB;integrated security=True;"

如果我对SQL DBA下面报告的内容使用了错误的术语,请注意道歉,但是当我们在SQL Server上放置跟踪时,它显示应用程序ID(运行AutoSys作业)被接受为有效登录。然后服务器似乎处理SELECT查询。但是,它从未回复过。相反,它进入了等待命令"状态。请求线程似乎保持打开几分钟,然后消失。

DBA表示没有死锁迹象,但他需要实时监控以确定是否存在阻塞。

这仅发生在生产环境中;在测试环境中,SQL Server总是在一秒钟内响应。

AutoSys应用程序ID不是新的 - 它已与其他SQL Server一起使用了几年,没有任何问题。 DBA甚至在以该ID登录的生产SQL服务器上手动运行SELECT查询,并且它正常响应。

我们无法在任何非生产环境中重现此问题,并且在生产中无需服务器管理员等待杀死该流程时犹豫不决。我们的安全要求限制了我对查看服务器日志和进程的访问权限,而且我通常需要聘请其他专家为我查看。

我们迟早要解决这个问题。我们正在查看的数据量目前只有几行,但会在接下来的几个月内增加。从发生的事情来看,我最好的猜测是它涉及应用服务器和SQL服务器之间的通信和/或安全性。

欢迎任何其他想要调查的想法或项目。谢谢大家。

2 个答案:

答案 0 :(得分:1)

这可能与权限有关。 SQL Server做了一些奇怪的事情,而不是有时给出正确的错误消息。

我的建议,无论如何,这可能会提高性能,就是在服务器端编写执行select的存储过程,并调用存储过程。这样,DBA可以确保您可以正确访问存储过程而不允许直接访问该表,如果由于某种原因被阻止,您应该看到轻微的性能提升。

答案 1 :(得分:0)

虽然它可能是由@user1895086提到的一些奇怪的权限/ ADO.NET问题引起的,但我还是建议再次重新检查一些事情:

  1. 确保DBA手动运行并在您的应用程序中执行的查询是相同的 - 硬编码或至少在运行之前记录。安全比抱歉更好。
  2. 尝试只选择几行 - 如果可以避免,最好不要选择整个表,在我们的情况下SELECT TOP 1(或100)查询可能不会出现此类问题。也许只有比您想象的更多的数据,ADO.Net只是尽职尽责地尝试加载所有这些行。或许不是。
  3. 尝试SqlDataReader以确保SqlDataAdapter不会导致任何问题 - 是的,它使用相同的DataAdapter internally,但我们至少会从嫌疑人列表中排除这些额外的操作。
  4. 尝试用5 GB的内存来获取转储 - analyzing memory dumps并不是一项微不足道的任务,但是它很难理解吃掉那些大量内存的东西。因为我不知何故怀疑ADO.NET会毫无理由地产生很多其他对象。