【问题标题】:How can I recycle ASP.NET sessions stored in SQL Server?如何回收存储在 SQL Server 中的 ASP.NET 会话?
【发布时间】:2012-01-10 15:50:46
【问题描述】:

所以我们刚刚开始使用存储在 SQL Server 中的 ASP.NET 会话 - 它们非常简洁。但是,由于会话现在通过应用程序池回收持续存在,如果我们部署新代码,这可能会给我们带来问题。有没有办法(除了重新启动 SQL 服务器)强制在此模型中放弃所有会话(或至少应用程序池的所有会话)?

【问题讨论】:

    标签: asp.net


    【解决方案1】:

    将此作为存储过程添加到 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
    

    这将删除数据库中的所有会话。

    【讨论】:

    【解决方案2】:

    正如@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 程序说明。

    所涉及的存储过程和 SQL Server 会话状态提供程序背后的机制在 this MSDN article 中进行了说明。

    【讨论】:

      【解决方案3】:

      出于性能原因,我的建议是尽可能远离光标。 我改用合并重写了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
      

      【讨论】:

      猜你喜欢
      • 2012-08-09
      • 1970-01-01
      • 1970-01-01
      • 2011-12-23
      • 1970-01-01
      • 1970-01-01
      • 2012-12-22
      • 2014-09-17
      • 1970-01-01
      相关资源
      最近更新 更多