【问题标题】:Unable to connect to SQL Server session database exception - All pooled connections were in use无法连接到 SQL Server 会话数据库异常 - 所有池连接都在使用中
【发布时间】:2021-06-11 15:08:28
【问题描述】:

在生产过程中,我的日志文件中突然出现此错误:

System.Web.HttpException (0x80004005):引发了“System.Web.HttpException”类型的异常。

System.Web.HttpException (0x80004005):无法连接到 SQL Server 会话数据库。

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

我看了很多其他答案,比如here

但我没有连接泄漏,我不想只将最大池设置为 200左右因为我想了解为什么我突然得到这个异常......

这些是我的连接字符串:

<!--Nhibernate-->
<add name="name" 
     connectionString="Server= servername;Initial Catalog=DBname;UID=username;Password=password;MultipleActiveResultSets=true" 
     providerName="System.Data.SqlClient" /> 

<!--Entity Framework-->
<add name="name" 
     connectionString= "metadata=res://*/Models.Model1.csdl|res://*/Models.Model1.ssdl|res://*/Models.Model1.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=servername;initial catalog=DBname;user id=userName;password=password;multipleactiveresultsets=True;App=EntityFramework&quot;" 
     providerName="System.Data.EntityClient" /> 

更新

一个使用db没有连接泄漏的例子:

using (var db = new dbName())
{
    using (var connection = db.Database.Connection)
    {
       var command = connection.CreateCommand();

       ...

       connection.Open();

       using (var reader = command.ExecuteReader())
       {
          ...
          reader.NextResult();
          ...
          reader.NextResult();
          ...
          reader.NextResult();
          ...
       }

       connection.Close();
    }
}  

更新

事实证明,我在 Entity Framework 中确实有连接泄漏, 一个没有使用using的地方,连接也没有关闭!

例子:

private DbContext context = new DbContext();

...

List<dbObject> SeriesEvents = context.dbObject.Where(e => e.RecurrenceId == entity.RecurrenceId).ToList();

context 变量未关闭。

我更重要的是,这个查询做了很多数据库查询,超过了 100 个。

【问题讨论】:

  • 让我们看看应该是 don't have connections leak 我敢打赌你没有正确处理的代码
  • @Charlieface 你错了,我处理得当。我会更新一个例子
  • db.Database.Connection 属性的实现是什么样的?连接确实返回了正确的DbConnection,对吗?
  • 发生错误时您在 SQL Server 中有多少个连接?在任何给定时间,您在该 Sql Server 上是否有超过 32,000 个连接?
  • 该 sql server 是在同一个机器上运行还是在单独的服务器上运行?网络服务器/客户端运行的操作系统是什么? nHiberbate 上下文是否有可能泄漏连接而不是这个 EF 连接?它是否会在创建连接的多个位置或始终在代码中的相同方法处引发此异常?

标签: c# sql-server database connection-string connection-pooling


【解决方案1】:

这种连接池问题通常伴随着连接泄漏。数据库操作中可能会发生一些异常,连接可能无法正确关闭。 请添加一个 try{} catch{} finally{} 块并在 finally 块中关闭连接。

如果你使用using,那么try catch finally 是隐式的,运行时本身会关闭连接。因此,您无需显式关闭连接。如果使用 using 块,请从您的代码中删除 connection.Close()

Using 语句实际上是 try{} catch{} finally{} 的语法糖,其中连接被关闭并最终由运行时释放。

try
{
     connection.Open();
     // DB Operations
}
finally
{
     connection.Close();                
}

【讨论】:

  • 形成我检查的使用就足够了,不是吗?
  • 他们声称他们将连接包装在 using 中,并且编译器会生成一个 try/catch,在这种情况下保证会调用 dispose。如果他们的代码正确实现了 using 语句,则添加 try/catch 将无济于事。
  • 在这种情况下,请删除代码中的connection.close(),因为它是由使用自动管理的。
  • @Habeeb 你说得对,connection.close() 是多余的,我会删除它
  • 我接受这个答案,因为最终证明是连接泄漏问题
【解决方案2】:

错误消息表明会话状态数据库出现问题,但您提供的信息是针对应用程序连接的。由于连接字符串不同,会话状态池也不同。

会话状态问题的常见原因是 1) 托管会话状态数据库的实例对于工作负载来说过小,或者 2) 会话状态清理作业导致长期阻塞。

早期 .NET 版本中的清理作业会一次性删除所有过期会话,并且因在繁忙的站点上造成长期阻塞而臭名昭著,尤其是在会话状态被大量使用时:

CREATE PROCEDURE dbo.DeleteExpiredSessions
AS
    DECLARE @now datetime
    SET @now = GETUTCDATE()

    DELETE [ASPState].dbo.ASPStateTempSessions
    WHERE Expires < @now

    RETURN 0

后来的 .NET 版本使用游标进行删除以大大提高并发性。

CREATE PROCEDURE dbo.DeleteExpiredSessions
AS
    SET NOCOUNT ON
    SET DEADLOCK_PRIORITY LOW 

    DECLARE @now datetime
    SET @now = GETUTCDATE() 

    CREATE TABLE #tblExpiredSessions 
    ( 
        SessionId nvarchar(88) NOT NULL PRIMARY KEY
    )

    INSERT #tblExpiredSessions (SessionId)
        SELECT SessionId
        FROM [ASPState].dbo.ASPStateTempSessions WITH (READUNCOMMITTED)
        WHERE Expires < @now

    IF @@ROWCOUNT <> 0 
    BEGIN 
        DECLARE ExpiredSessionCursor CURSOR LOCAL FORWARD_ONLY READ_ONLY
        FOR SELECT SessionId FROM #tblExpiredSessions 

        DECLARE @SessionId nvarchar(88)

        OPEN ExpiredSessionCursor

        FETCH NEXT FROM ExpiredSessionCursor INTO @SessionId

        WHILE @@FETCH_STATUS = 0 
            BEGIN
                DELETE FROM [ASPState].dbo.ASPStateTempSessions WHERE SessionId = @SessionId AND Expires < @now
                FETCH NEXT FROM ExpiredSessionCursor INTO @SessionId
            END

        CLOSE ExpiredSessionCursor

        DEALLOCATE ExpiredSessionCursor

    END 

    DROP TABLE #tblExpiredSessions

RETURN 0

如果问题是由于实例过小而无法纵向扩展,请考虑使用会话状态分区进行横向扩展。

【讨论】:

    猜你喜欢
    • 2010-09-30
    • 2011-03-11
    • 2021-09-27
    • 1970-01-01
    • 2017-08-09
    相关资源
    最近更新 更多