所以我们刚刚开始使用存储在SQL服务器中的ASP.NET会话 - 它们非常整洁。但是,由于会话现在遍及应用程序池循环,如果我们部署新代码,这可能会给我们带来问题。是否有一种方法(在重新启动SQL服务器之外)强制所有会话(或至少应用程序池的所有会话)在此模型中被放弃?
答案 0 :(得分:8)
将其添加为ASPState数据库中的存储过程:
CREATE PROCEDURE [dbo].[DeleteExpiredSessions]
AS
DECLARE @now datetime
SET @now = GETUTCDATE()
DELETE [ASPState].dbo.ASPStateTempSessions
WHERE Expires < @now
RETURN 0
然后将作业添加到定期运行的SQL Server代理程序(我的午夜运行),该作业在该数据库上执行以下步骤:
dbo.DeleteExpiredSessions
这确保了当会话到期时,即使创建它们的进程不在,它们也会消失。如果你想在重启过程时摆脱它们,只需执行:
DELETE [ASPState].dbo.ASPStatsTempSessions
这将删除数据库中的所有会话。
答案 1 :(得分:6)
正如@RobertBeaubien所写,DeleteExpiredSessions程序应该处理这个问题。创建会话存储数据库时,aspnet_regsql工具应该已经在数据库中为您创建了该过程。应该有一个SQL代理作业每60秒调用一次,可能是意外禁用了。
该过程的ASP.NET 4.0版本如下所示:
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
GO
See here解释程序。
this MSDN article中解释了所涉及的存储过程以及SQL Server会话状态提供程序背后的机制。
答案 2 :(得分:1)
我的建议是,如果可以,请远离游标,出于性能原因。
我改为使用merge重写了DeleteExpiredSessions
存储过程:
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 dbo.ASPStateTempSessions WITH (NOLOCK)
WHERE Expires < @now
MERGE dbo.ASPStateTempSessions AS [target]
USING #tblExpiredSessions AS [source]
ON ([target].[SessionID] = [source].[SessionID] AND Expires < @now)
WHEN MATCHED
THEN DELETE;
DROP TABLE #tblExpiredSessions
RETURN 0
GO