有连接池保持打开状态的问题(显式关闭连接)

本文关键字:连接 问题 状态 | 更新日期: 2023-09-27 18:12:03

我的应用程序出现了一个错误,认为已达到最大池大小:

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

我们有一个内部函数,它返回一个DataReader。在这个函数内部,我们使用ExecuteReader方法,它被赋值为CommandBehavior.CloseConnection。在读取了我们需要的数据之后,我们在该函数返回的DataReader上调用.Close.Dispose

在旁注上,我还尝试实现一种不同的方法,其中我在连接上做了using标签,并且仍然将其视为数据库中的"睡眠"。

我运行下面的查询来获取仍处于睡眠状态的连接。在任何时候,我们都能看到大约40个左右的人被列为"睡觉"。我抓住这里使用的SQL脚本,将其追溯到它们在应用程序中使用的地方,并三重检查DataReader正在关闭。

SELECT sp.spid, sp.hostname, sp.program_name, sp.loginame, sp。login_time, sp.status, CAST(text AS VARCHAR(1000)) AS SQLScript从系统。sysprocesses sp CROSS APPLY sys.dm_exec_sql_text(sp.sql_handle) where program_name='。. Net SqlClient数据提供程序'和loginname ='[LoginNameForSql]' order by SQLScript

我还需要做些什么来确保这些连接被关闭吗?我们的团队非常困惑,因为我们所有人都在使用后再三检查我们的阅读器是否关闭并处理。

获取数据阅读器的函数:

        SqlConnection conn = OpenConnection();
        SqlDataReader rdr = null;
        //    try
        //    {
        SQL = strSQL;
        CommandBehavior intBehavior = CommandBehavior.CloseConnection;
        using (var cmd = conn.CreateCommand())
        {
            cmd.CommandText = strSQL;
            cmd.CommandTimeout = Timeout;
            rdr = cmd.ExecuteReader(intBehavior);
            cmd.Parameters.Clear();
        }
      return rdr;

使用上述函数:

       var rdr = FunctionReturningDataReader();
        if (rdr != null)
        {
            if (rdr.HasRows)
            {
                while (rdr.Read())
                {
                }
            }
         }
            rdr.Close();
            rdr.Dispose();

编辑:我将最大池大小增加到200,并且自3天前以来没有在我们的应用程序中看到此错误。

有连接池保持打开状态的问题(显式关闭连接)

我担心的是,您正在关闭连接,但它没有超出范围并被处理(快速?)。

我没有看到FunctionReturningDataReader()增加了那么多的值。
不要浪费时间——尽可能晚地打开连接,尽可能早地关闭和处理连接。
我会在行中这样做,并将SQLconnection放在using中。
SqlDataReader

private static void ReadOrderData(string connectionString)
{
    string queryString =
        "SELECT OrderID, CustomerID FROM dbo.Orders;";
    using (SqlConnection connection =
               new SqlConnection(connectionString))
    {
        SqlCommand command =
            new SqlCommand(queryString, connection);
        connection.Open();
        SqlDataReader reader = command.ExecuteReader();
        // Call Read before accessing data. 
        while (reader.Read())
        {
            ReadSingleRow((IDataRecord)reader);
        }
        // Call Close when done reading.
        reader.Close();
    }
}

我的答案被投票否决了,因为没有把reader放在using
这是来自文档的,我发现reader.Close()已经足够了
如果你觉得有必要把reader放到using

确保您还关闭了Database Connection对象,而不仅仅是DataReader。打开数据库连接将填满连接池