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

7
我的asp.net应用程序每天都能正常工作。但是从上个月开始,我的网站开始出现2-3次与Sqlsession状态服务器相关的问题,如下所示:
System.Web.HttpException 异常类型'System.Web.HttpException'被抛出。在System.Web.HttpAsyncResult.End() at System.Web.SessionState.SessionStateModule.EndAcquireState(IAsyncResult ar) at System.Web.HttpApplication.AsyncEventExecutionStep.OnAsyncEventCompletion(IAsyncResult ar)
异常: System.Web.HttpException 无法连接到SQL Server会话数据库。 在System.Web.SessionState.SqlSessionStateStore.ThrowSqlConnectionException(SqlConnection conn, Exception e) at System.Web.SessionState.SqlSessionStateStore.SqlStateConnection..ctor(SqlPartitionInfo sqlPartitionInfo) at System.Web.SessionState.SqlSessionStateStore.GetConnection(String id, Boolean& usePooling) at System.Web.SessionState.SqlSessionStateStore.DoGet(HttpContext context, String id, Boolean getExclusive, Boolean& locked, TimeSpan& lockAge, Object& lockId, SessionStateActions& actionFlags) at System.Web.SessionState.SqlSessionStateStore.GetItemExclusive(HttpContext context, String id, Boolean& locked, TimeSpan& lockAge, Object& lockId, SessionStateActions& actionFlags) at System.Web.SessionState.SessionStateModule.GetSessionStateItem() at System.Web.SessionState.SessionStateModule.PollLockedSessionCallback(Object state)
异常: System.InvalidOperationException 超时已过期。在从池中获取连接之前,超时时间已过。这可能是因为所有池化连接都在使用并且达到了最大池大小。在System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection) at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory) at System.Data.SqlClient.SqlConnection.Open() at System.Web.SessionState.SqlSessionStateStore.SqlStateConnection..ctor(SqlPartitionInfo sqlPartitionInfo)
然后我开始查看我的会话数据库服务器,并在我的SQL客户端中执行“exec sp_who”以查找AspState操作的许多记录。
我不知道是什么原因导致这种问题,因为我们在应用程序中没有进行任何重要的更改,只是修复了一些错误。
以下是我的Web应用程序环境的详细信息:
asp.net 3.5(从1.1转换)...在sqlmode session state的2个服务器群集中工作得非常好。
有人知道这个问题或者有任何调查想法吗?谢谢。
6个回答

6

这篇文章发布已经有一段时间了,但是我最近在生产环境中遇到了这个确切的问题,并认为这对未来的其他人可能会有所帮助。

我们有一个ASP.NET MVC Web应用程序,运行在.NET 4.5.2上,跨两个节点进行负载均衡。该应用程序被配置为将Session存储在SQL Server 2012(版本11.0.5058.0)上的ASPState数据库中。我们遭受了间歇性超时的折磨:

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

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

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

  1. Raising the Max Pool Size by overriding the default of 100 in the connection string in the web.config file:

      sqlConnectionString="data source=SERVERNAME;Initial Catalog=AspState;user id=AspStateUser;password=xxxxx;App=xxxx; Max Pool Size=200;" 
    
  2. It was apparent that the AspState database had been created with the .NET 2.0 command-line and importantly, the dbo.DeleteExpiredSessions SP has known issues with blocking. To further compound the problem, the job was configured to execute this procedure every minute. The AspState database was re-created using the .NET 4.0 command line as follows:

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

重要的是,较新版本包括性能改进的DeleteExpiredSessions过程的版本,其中包含一个游标,以逐个删除过期会话。我们还将相关作业的计划更改为每小时执行一次,而不是每分钟执行。


关于 optimize-aspstate https://sqlperformance.com/2013/01/t-sql-queries/optimize-aspstate 有什么想法? DeleteExpiredSessions SP NET 4.5 version 不要试图一次性删除所有行,也不要一个一个地删除。相反,以单独的事务方式每次删除n行 - 减少阻塞时间并最小化日志的影响。 - Kiquenet
dbo.TempResetTimeout 每次加载页面时(如果 Web 应用程序未正确创建,则可能在每个页面加载时多次调用),都会调用 SP dbo.TempResetTimeout,确保该特定会话的超时时间在其继续生成活动的同时得到延长。在繁忙的网站上,这可能会导致针对表 dbo.ASPStateTempSessions 的非常高的更新活动量。 查看:optimize-aspstate https://sqlperformance.com/2013/01/t-sql-queries/optimize-aspstate - Kiquenet
在我的情况下,我没有DB AspState。我使用给定的命令创建了DB,它起作用了。 - eswara amirthan s

3
如果这里的任何答案都不起作用,那么请检查<configuration><sessionState>中的connectionString。在我的情况下,我更新了<configuration>中的连接字符串,但没有在会话状态中指向不同的SQL服务器。
只需在<sessionState>中指定正确的连接字符串即可解决相同的错误。

就是这样了!感谢他的提示! - Casey Crookston

3

1
更详细的文章请参见Greg Low的http://aspalliance.com/1184_Avoiding_Blocking_Issues_in_ASPNET_Session_State_Databases。 - Michael Freidgeim

2

我曾经看到过开发人员使用大量的SqldataReaders来获取数据以构建某种仪表板时出现了这个精确的错误,但是他从未关闭自己的数据读取器,即使他已将命令行为设置为CloseConnection。一旦他通过using块进行封装,这些问题就消失了。再次强调,这可能不是您问题的实际原因,但连接池枯竭通常指出连接未正确关闭。


2

这似乎是您在池中使用了所有可用连接的情况。请检查您的代码,并确保设置数据库连接如下:

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

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

这样做将清理应用程序中的所有其他数据库连接,并且状态服务器连接将能够在需要时连接。


2
为每个唯一的连接字符串创建一个连接池,因此修复任何潜在的连接泄漏问题不会影响Asp Session State数据库,这是确定的吗? - abrown

1

你的负载增加了吗?可能是因为有更多的用户使用系统,导致连接数量增加。

你可以优化会话的使用。你可以指定一个页面是否使用会话状态或者只是进行读取操作。如果有一些页面不使用或者不修改会话状态,这将会节省很大的开销。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接