无法连接到SQL Server会话数据库

时间:2009-01-12 14:32:21

标签: c# asp.net sql-server session-state

我的asp.net应用程序每天都运行良好。 直到上个月,我的网站开始在Sqlsession状态服务器上遇到2-3次问题 遵循:

  

块引用   System.Web.HttpException抛出了类型'System.Web.HttpException'的异常。在System.Web.HttpAsyncResult.End()处于System.Web.HttpApplication.AsyncEventExecutionStep.OnAsyncEventCompletion(IAsyncResult ar)的System.Web.SessionState.SessionStateModule.EndAcquireState(IAsyncResult ar)中============ ======================================异常:System.Web.HttpException无法连接到SQL服务器会话数据库在System.Web.SessionState.SqlSessionState中的System.Web.SessionState.SqlSessionStateStore.ThrowSqlConnectionException(SqlConnection conn,Exception e)中的System.Web.SessionState.SqlSessionStateStore.SqlStateConnection..ctor(SqlPartitionInfo sqlPartitionInfo)处于System.Web.SessionState.SqlSessionStateStore.GetConnection(String id,Boolean& System.Web.SessionState.SqlSessionStateStore.GetItemExclusive(HttpContext)中的System.Web.SessionState.SqlSessionStateStore.DoGet(HttpContext context,String id,Boolean getExclusive,Boolean& locked,TimeSpan& lockAge,Object& lockId,SessionStateActions& actionFlags)中的usePooling) System.Web.SessionState.SessionStateModule.PollLockedSessionCallback(Object state)中System.Web.SessionState.SessionStateModule.GetSessionStateItem()的context,String id,Boolean& locked,TimeSpan& lockAge,Object& lockId,SessionStateActions& actionFlags)=== ===============================================异常:系统.InvalidOperationException超时已过期。从池中获取连接之前经过的超时时间。这可能是因为所有池连接都在使用中并且达到了最大池大小。位于System.Web.SessionState的System.Data.SqlClient.SqlConnection.Open()的System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection,DbConnectionFactory connectionFactory)上的System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)。 SqlSessionStateStore.SqlStateConnection..ctor(SqlPartitionInfo sqlPartitionInfo)

然后我开始查看我的会话数据库服务器,并在我的sql客户端中执行了“exec sp_who”,结果发现了大量的AspState操作记录。

我不知道是什么导致了这种问题,因为我们确实没有改变任何严肃的事情 在应用程序中,只修复了一些错误。

以下是我的Web应用程序环境的详细信息:

asp.net 3.5(从1.1转换)...工作得非常好 2个服务器场,具有会话状态的sqlmode。

有没有人知道这个问题或者有任何想法进行调查? 感谢

6 个答案:

答案 0 :(得分:3)

这听起来像是在耗尽池中所有可用连接的情况。浏览您的代码并确保像这样设置数据库连接:

using (SqlConnection cn = new SqlConnection(connectionString))
{
    using (SqlCommand cm = new SqlCommand(commandString, cn))
    {
        cn.Open();
        cm.ExecuteNonQuery(); // or fill a dataset, etc.
    }
}

一旦退出此“使用”语句,连接将自动关闭。

执行此操作将清除应用程序中的所有其他数据库连接,并且State Server连接将能够在需要时进行连接。

答案 1 :(得分:2)

我已经看到当开发人员使用大量SqldataReaders来获取数据来构建某种仪表板时,会发生这种确切的错误,但即使他将命令行为设置为CloseConnection,他也从未关闭过他的数据读取器。一旦他做了(通过封闭使用块)这些就消失了。同样,这可能不是您问题的实际原因,但连接池耗尽通常指向未正确关闭的连接。

答案 2 :(得分:2)

不确定是否还有人在看这个帖子,但我发现了一篇关于大会话状态和大量并发会话的有趣文章,这些文章在删除数据时(当会话不再有效时)导致问题。虽然这里的信息有点过时,但值得深入研究。这是链接:http://msmvps.com/blogs/greglow/archive/2007/02/04/improving-asp-net-session-state-database-performance-by-reducing-blocking.aspx

答案 3 :(得分:2)

自从这篇文章首次提出以来已经有一段时间了,但我最近在生产环境中遇到了这个问题,并认为它可能对将来的其他人有用。

我们在.NET 4.5.2上运行的ASP.NET MVC Web应用程序在两个节点之间进行负载平衡。该应用程序配置为在SQL Server 2012(版本11.0.5058.0)上的ASPState数据库中存储会话。我们正在遭受间歇性超时:

  

异常信息:       异常类型:HttpException       异常消息:无法连接到SQL Server会话数据库。   超时已过期。从池中获取连接之前经过的超时时间。这可能是因为所有池连接都在使用中并且达到了最大池大小。

这里的一些答案与确保代码库中没有其他连接泄漏相关,我认为是错误的。为每个不同的连接字符串创建连接池,因此对其他数据库的连接的任何修复都不会对会话状态数据库产生有益影响。

我们通过两处更改解决了这个问题:

  1. 通过覆盖web.config文件中连接字符串中的默认值100来提高最大池大小:

      sqlConnectionString="data source=SERVERNAME;Initial Catalog=AspState;user id=AspStateUser;password=xxxxx;App=xxxx; Max Pool Size=200;" 
    
  2. 很明显,AspState数据库是使用.NET 2.0命令行创建的,而且重要的是,dbo.DeleteExpiredSessions SP已经知道阻塞问题。为了进一步解决问题,该作业已配置为每分钟执行此过程。使用.NET 4.0命令行重新创建AspState数据库,如下所示:

  3.   

    C:\ Windows \ Microsoft.NET \ Framework \ v4.0.30319> aspnet_regsql.exe -ssadd    - sstype c -S OURSERVERNAME -d" AspState" -E

    重要的是,后一版本包含一个性能改进版本的DeleteExpiredSessions过程,该过程包含一个一次删除过期会话的游标。我们还将相关作业的时间表更改为每小时而不是每分钟执行一次。

答案 4 :(得分:2)

如果此处的答案都不起作用,请查看<configuration><sessionState>中的connectionString。在我的情况下,我更新了<configuration>中的连接字符串,但未更新会话状态以指向不同的SQL服务器。

只需在<sessionState>中指定正确的连接字符串即可解决此错误。

答案 5 :(得分:1)

您的负荷是否增加了?您可能有很多连接,因为您有更多用户使用该系统。

您可以做的一件事是优化会话使用率。您可以指定页面是使用会话状态还是仅执行读取。如果您的页面不使用或不修改会话,这可以节省大量成本。