繁体   English   中英

使用ADO.Net的查询的连接超时异常

[英]Connection Timeout exception for a query using ADO.Net

更新 :看起来查询不会抛出任何超时。 连接超时。

这是用于执行查询的示例代码。 有时,在执行耗时的查询时,会抛出超时异常。

不能使用以下任何技术:1)增加超时。 2)使用回调异步运行它。 这需要以同步方式运行。

请建议任何其他技术,以便在执行耗时的查询时保持连接活动?

private static void CreateCommand(string queryString,
    string connectionString)
{
    using (SqlConnection connection = new SqlConnection(
               connectionString))
    {
        SqlCommand command = new SqlCommand(queryString, connection);
        command.Connection.Open();
        command.ExecuteNonQuery();
    }
}

由于您使用的ExecuteNonQuery不返回任何行,因此您可以尝试这种基于轮询的方法。 它以asyc方式执行查询(没有回调),但应用程序将等待(在while循环内),直到查询完成。 来自MSDN 这应该解决超时问题。 请试一试。

但是,我同意其他人的意见,你应该多考虑优化查询,以便在30秒内执行。

        IAsyncResult result = command.BeginExecuteNonQuery();

        int count = 0;
        while (!result.IsCompleted)
        {
            Console.WriteLine("Waiting ({0})", count++);
            System.Threading.Thread.Sleep(1000);
        }
        Console.WriteLine("Command complete. Affected {0} rows.",
        command.EndExecuteNonQuery(result));

您应首先检查您的查询,看它是否已经过优化,并且不会以某种方式运行缺失的索引。 大多数查询分配30秒 ,即使在大型数据库上进行了适当调整也是如此。 如果您有使用查询计划的可靠证据,查询无法以更快的速度执行,那么您应该增加超时,没有其他方法来保持连接,这是超时终止连接的目的,如果查询未在该时间范围内完成。

我不得不同意Terrapin。

您可以选择如何减少时间。 首先,如果您的公司雇用DBA,我建议您向他们寻求建议。

如果这不是一个选项,或者如果你想先尝试一些其他的东西,这里有三个主要选择:

  1. 将查询分解为在超时下运行的组件。 这可能是最简单的。
  2. 更改查询以优化通过数据库的访问路径(通常:尽可能密切地命中索引)
  3. 更改或添加索引以影响查询的访问路径。

如果您不能使用更改超时值的默认过程,那么您很可能需要做更多的工作。 我想到了以下选项

  1. 使用您的DBA和其他代码审核进行验证,您已尽可能优化了查询
  2. 处理底层数据库结构,看看是否可以在数据库端获得任何增益,创建/修改idex。
  3. 将它分成多个部分,即使这意味着运行具有多个返回参数的过程,这些参数只是调用另一个参数。 (这个选项并不优雅,老实说如果你的代码真的需要花费很多时间我会去管理并重新讨论30秒超时)

我们最近在SQL Server 2000数据库上遇到了类似的问题。

在查询期间,在数据库服务器上的master数据库上运行此查询,并查看是否存在应该进行故障排除的任何锁定:

select 
  spid,
  db_name(sp.dbid) as DBname,
  blocked as BlockedBy,
  waittime as WaitInMs,
  lastwaittype,
  waitresource,
  cpu,
  physical_io,
  memusage,
  loginame,
  login_time,
  last_batch,
  hostname,
  sql_handle
from sysprocesses sp
where (waittype > 0 and spid > 49) or spid in (select blocked from sysprocesses where blocked > 0)

SQL Server Management Studio 2008还包含一个非常酷的活动监视器,可让您在查询期间查看数据库的运行状况。

在我们的例子中,它是一个网络锁,它使数据库保持忙碌状态。 这是一些遗留的VB代码,它没有足够快地断开其结果集。

如果禁止使用数据访问API的功能来允许查询持续超过30秒,那么我们需要查看SQL。

与优化SQL的优势相比,优化ADO.NET的使用所带来的性能提升很小。

而且您已经在使用最有效的SQL执行方法。 其他技术会慢慢变慢(尽管如果你快速检索你的行并且使用DataSet的一些非常慢的客户端处理,你可能能够将初始检索缩短到不到30秒,但我对此表示怀疑。 )

如果我们知道你是否在做插入,那么也许你应该使用批量插入。 但是我们不知道你的sql的内容。

这是一个UGLY黑客,但可能有助于暂时解决您的问题,直到您可以解决实际问题

    private static void CreateCommand(string queryString,string connectionString)
    {
        int maxRetries = 3;
        int retries = 0;
        while(true)
        {
            try
            {
                using (SqlConnection connection = new SqlConnection(connectionString))
                {
                    SqlCommand command = new SqlCommand(queryString, connection);
                    command.Connection.Open();
                    command.ExecuteNonQuery();
                }
                break;
            }
            catch (SqlException se)
            {
                if (se.Message.IndexOf("Timeout", StringComparison.InvariantCultureIgnoreCase) == -1)
                    throw; //not a timeout

                if (retries >= maxRetries)
                    throw new Exception( String.Format("Timedout {0} Times", retries),se);

                //or break to throw no error

                retries++;
            }
        }
    }
command.CommandTimeout *= 2;

这将使默认超时时间加倍,即30秒。

或者,将CommandTimeout的值放在配置文件中,这样您就可以根据需要进行调整而无需重新编译。

如果绝对无法增加超时,则唯一的选择是减少查询在默认的30秒超时内执行的时间。

您应该将查询分解为多个块,每个块在超时期限内执行。

我倾向于不喜欢增加连接/命令超时,因为在我看来,这将是一个照顾症状的问题,而不是问题

可能值得尝试分页结果。

只需将sqlcommand的CommandTimeout属性设置为0,这将导致命令等待查询完成...例如:

SqlCommand cmd = new SqlCommand(spName,conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandTimeout = 0;

你有没有想过将查询分成几个较小的块?

另外,您是否针对数据库引擎优化顾问运行了查询:

Management Studio>工具>数据库引擎优化顾问

最后,我们可以看看查询本身吗?

干杯

您是否尝试将sql包装在存储过程中,它们似乎具有更好的内存管理。 在使用经典ADO进行内部查询的plan sql语句之前,已经看到过这样的超时。 即select * from(select ....)t inner join somthingTable。 内部查询返回大量结果的位置。

其他提示1.使用with(nolock)执行提示执行读取,它很脏,我不推荐它,但它会更快。 2.还要查看您尝试运行的sql的执行计划,并减少行扫描,即连接表的顺序。 3.查看为表添加一些索引以便更快地读取。 4.我还发现删除行非常昂贵,您可以尝试限制每次调用的行数。 5.使用#temporary表交换@table变量在过去对我也有用。 6.您可能还保存了糟糕的执行计划(听到,从未见过)。

希望这可以帮助

更新:看起来查询不会抛出任何超时。 连接超时。

嘿,即使你不执行查询,连接也会超时? 因为有两个超时:连接和查询。 每个人似乎都专注于查询,但是如果你得到连接超时,那就是网络问题并且与查询无关:显然,必须首先建立连接,然后才能运行查询。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM