【问题标题】:Max connection pool reached已达到最大连接池
【发布时间】:2018-04-10 17:06:40
【问题描述】:

我有一个简单的 SQL 语句,我想在短时间内调用很多次(在

System.InvalidOperationException: '超时已过期。在从池中获取连接之前超时时间已过。这可能是因为所有池连接都在使用中并且已达到最大池大小。'

我已经阅读了很多关于这个错误的帖子。他们都建议要么用using 块包装你的代码,要么在最后调用SQL 连接的.Close() 方法。这两个我都实现了,还是不行。我没有正确实施吗? (该方法工作正常,当不重复调用时)。

我的代码如下所示:

public static ObjectModel GetObject(int objGroupId, DateTime date)
{
    ObjectModel obj = new ObjectModel () { EffectiveFrom = date };

    // Get connection string from the App.Config file
    string connectionString = ConfigurationManager.AppSettings["ConnectionString"];

    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        connection.Open();

        using (SqlCommand command = new SqlCommand("[dbo].[GetObjectData]", connection))
        {
            // Request the data which were in force on the specified date
            command.CommandType = CommandType.StoredProcedure;
            command.Parameters.Add("@Date", SqlDbType.DateTime).Value = obj.EffectiveFrom;
            command.Parameters.Add("@ObjecGrouptId", SqlDbType.Int).Value = objGroupId;

            using (SqlDataReader reader = command.ExecuteReader())
            {
                while (reader.Read())
                {
                    int objId = reader.GetInt32NullIsZero("Id");
                    decimal value = reader.GetDecimalNullIsZero("value");
                    SetObjData(obj, objId, value);
                }
            }
        }

        connection.Close();
    }                

    return obj;
}

【问题讨论】:

  • 这是打开连接的唯一代码吗?
  • 这些调用是否重叠?默认的最大池大小为 100。如果您尝试在 parallel 中触发超过 100 个查询,则会收到此错误。你可以碰一下MaxPoolSize,或者想办法序列化调用。
  • 我也建议检查你的存储过程,如果你能优化它的执行时间。
  • @C.Evenhuis 这是每次抛出错误的地方,没有例外。我怀疑它也会从其他方法抛出异常,如果它发生在那里。它被称为其他地方,但应始终包裹在 using 块中。
  • @TheGeneral GC 在这里不是一个因素; using 释放到池的 底层 连接;收集SqlConnection 对象需要多长时间是无关紧要的

标签: c# .net sql-server


【解决方案1】:

你展示的代码看起来干净;所有正确的using 等都在那里。这让我怀疑此代码外部的某些东西正在保持连接并占用池。我所知道的唯一事情是:环境事务,即TransactionScope

作为一个调试工具只是为了检验这个假设,我建议尝试抑制 TransactionScope(如果有的话),你可以通过:

using (var tran = new TransactionScope(TransactionScopeOption.Suppress))
{
    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        connection.Open();

        //... the rest of your code

        connection.Close();
    }                

    tran.Complete();
}

请注意,connection 的创建和Open 必须发生在内部被抑制的区域内才能计数。

如果这使问题消失,那么:环境事务导致所有连接都被纳入更广泛的事务 - 可能是 DTC 事务(因为 LTM 事务可以重用连接,IIRC)。

所以:如果这解决了它,那么坦率地说,我的建议是更改方法以允许您有选择地将连接作为输入传递,从而允许您为 400 重用单个连接操作而不是依靠连接池。


重要提示:禁止交易通常不是一个好主意;那笔交易是有原因的。此处的代码只是用于调查这是否是问题的诊断辅助工具。

【讨论】:

    【解决方案2】:

    问题解决了。事实证明,有一个(完全不同的方法)是async。我将其更改为Task(而不是void)并添加了await。所以@JeroenMostert 是在正确的轨道上。我仍然不明白为什么异常总是发生在与async 部分无关的方法中。

    【讨论】:

    • 如果你没有await async,你最终可能会同时运行 - 非常 如果它在一个循环中 - 所以如果@ 987654328@ 代码就是在循环中调用这个方法的东西,然后是的:那会很快吃掉池。
    猜你喜欢
    • 1970-01-01
    • 2016-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-23
    • 1970-01-01
    • 2020-01-02
    • 1970-01-01
    相关资源
    最近更新 更多