无法连接到 SQL 服务器会话数据库异常 - 所有池连接都在使用中
Unable to connect to SQL Server session database exception - All pooled connections were in use
我在生产时突然在我的日志文件中收到此错误:
System.Web.HttpException (0x80004005): Exception of type 'System.Web.HttpException' was thrown.
System.Web.HttpException (0x80004005): Unable to connect to SQL Server session database.
System.InvalidOperationException: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.
我看了很多其他答案,比如 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="data source=servername;initial catalog=DBname;user id=userName;password=password;multipleactiveresultsets=True;App=EntityFramework""
providerName="System.Data.EntityClient" />
更新
一个使用没有连接泄漏的数据库的例子:
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。
通常这种连接池问题伴随着连接泄漏。数据库操作可能会发生一些异常,连接可能无法正常关闭。
请添加一个 try{} catch{} finally{} 块并在 finally 块中关闭连接。
如果您使用 using
,则 try catch finally 是隐式的,运行时本身将关闭连接。所以你不需要明确关闭连接。如果使用 using
块,请从您的代码中删除 connection.Close()
。
Using
语句实际上是 try{} catch{} finally{} 的语法糖,其中连接由运行时关闭并在 finally 中处理。
try
{
connection.Open();
// DB Operations
}
finally
{
connection.Close();
}
错误消息表明会话状态数据库出现问题,但您提供的信息是针对应用程序连接的。由于不同的连接字符串,会话状态池不同。
会话状态问题的常见原因是 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
如果问题是由于实例规模过小造成的,并且扩展不可行,请考虑使用会话状态分区进行扩展。
我在生产时突然在我的日志文件中收到此错误:
System.Web.HttpException (0x80004005): Exception of type 'System.Web.HttpException' was thrown.
System.Web.HttpException (0x80004005): Unable to connect to SQL Server session database.
System.InvalidOperationException: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.
我看了很多其他答案,比如 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="data source=servername;initial catalog=DBname;user id=userName;password=password;multipleactiveresultsets=True;App=EntityFramework""
providerName="System.Data.EntityClient" />
更新
一个使用没有连接泄漏的数据库的例子:
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。
通常这种连接池问题伴随着连接泄漏。数据库操作可能会发生一些异常,连接可能无法正常关闭。 请添加一个 try{} catch{} finally{} 块并在 finally 块中关闭连接。
如果您使用 using
,则 try catch finally 是隐式的,运行时本身将关闭连接。所以你不需要明确关闭连接。如果使用 using
块,请从您的代码中删除 connection.Close()
。
Using
语句实际上是 try{} catch{} finally{} 的语法糖,其中连接由运行时关闭并在 finally 中处理。
try
{
connection.Open();
// DB Operations
}
finally
{
connection.Close();
}
错误消息表明会话状态数据库出现问题,但您提供的信息是针对应用程序连接的。由于不同的连接字符串,会话状态池不同。
会话状态问题的常见原因是 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
如果问题是由于实例规模过小造成的,并且扩展不可行,请考虑使用会话状态分区进行扩展。