500秒命令超时-太长

本文关键字:太长 超时 命令 500秒 | 更新日期: 2023-09-27 18:26:27

我们在生产中遇到了一个重要应用程序的问题。作为短期修复,我们在整个代码的许多地方增加了命令超时:

var cmd = new SqlCommand(szSQL, conn) {CommandTimeout = _cmdTimeout};

开发人员使用的初始默认值为500秒(8+分钟)。在我们找到长期解决方案之前,这是我们的解决方案。我关心的是使用的秒数。8分钟以上的时间似乎很长(太长了),我想知道用这么长的时间还会带来什么其他问题。尽量保持在3-4分钟以内会更好吗?还是8就好?

500秒命令超时-太长

我认为在必要时使用8分钟作为超时没有问题。AFAIK,SSMS在运行查询时有无限超时!

然而,我建议基于这个提取的代码使用一种稍微不同的方法:

private static bool IsRetryAfterException(SqlException aSqlExc)
{
  if (aSqlExc != null)
  {
    // If anybody finds a better way than this, please update!
    return aSqlExc.Message.Contains("The timeout period elapsed prior to completion of the operation or the server is not responding");
  }
  else
    throw new ArgumentNullException("The parameter 'aSqlExc' cannot be null.");
}
private int CallExecuteNonQuery(SqlCommand aCmd)
{
  for (int iRetry = 1; iRetry <= m_MaxTimeoutRetry; iRetry++)
    try
    {
      return aCmd.ExecuteNonQuery();
    }
    catch (SqlException wSqlE)
    {
      if (iRetry == m_MaxTimeoutRetry || !IsRetryAfterException(wSqlE))
        throw;
      // otherwise, we double the timeout and retry
      aCmd.CommandTimeout = 2 * aCmd.CommandTimeout;
      // let SQL breathe a bit!
      System.Threading.Thread.Sleep(aCmd.CommandTimeout * 10);
    }
    // This code cannot be reached but the compiler thinks otherwise 
    // this is because it cannot know that m_MaxTimeoutRetry is always >= 1 for the for-loop
    throw new DataAccessException();
}

在我们的代码中,所有查询都是通过CallExecuteNonQuery方法调用的。这对你来说可能很难更改你的代码,但你可以使用Lambda表达式来实现这一点,并轻松地修改你现有的代码,使其通过这种独特的方法,只需很少的更改。。。

所以问题是为什么要使用循环并重试?这是因为SQL死锁。我的经验是,最好让一个命令快速超时,比如30秒,如果超时,通过加倍超时并让SQL呼吸来重试,而不是默认情况下让所有查询都有一个大的超时。

我希望这会有所帮助,并且有意义。