我有一个控制台批处理应用程序,其中包含一个使用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服务器之间的通信和/或安全性。
欢迎任何其他想要调查的想法或项目。谢谢大家。
答案 0 :(得分:1)
这可能与权限有关。 SQL Server做了一些奇怪的事情,而不是有时给出正确的错误消息。
我的建议,无论如何,这可能会提高性能,就是在服务器端编写执行select的存储过程,并调用存储过程。这样,DBA可以确保您可以正确访问存储过程而不允许直接访问该表,如果由于某种原因被阻止,您应该看到轻微的性能提升。
答案 1 :(得分:0)
虽然它可能是由@user1895086提到的一些奇怪的权限/ ADO.NET问题引起的,但我还是建议再次重新检查一些事情:
SELECT TOP 1
(或100)查询可能不会出现此类问题。也许只有比您想象的更多的数据,ADO.Net只是尽职尽责地尝试加载所有这些行。或许不是。