如何回收存储在SQL Server中的ASP.NET会话?

时间:2012-01-10 15:50:47

标签: asp.net

所以我们刚刚开始使用存储在SQL服务器中的ASP.NET会话 - 它们非常整洁。但是,由于会话现在遍及应用程序池循环,如果我们部署新代码,这可能会给我们带来问题。是否有一种方法(在重新启动SQL服务器之外)强制所有会话(或至少应用程序池的所有会话)在此模型中被放弃?

3 个答案:

答案 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