ASP.NET SessionState 和SQL Server blocking

 

ASP.NET 提供了Session State 用来保存IIS会话状态信息。 Session State可以存放在三个不同的地方:

 

l The in-process state store 将Session存到进程内(这是Default值。)

l The out-of-process state service 将Session存到独立的状态服务中(Asp.net State Service).

l SQL Server

 

如果Session State存放在SQL server,你可以获得很不错的扩展性,特别对web服务器群来说。但是因为要和SQL server 交互以及数据的序列化,可能比进程内的方法较慢一些。和SessionState 相关的表主要有两个 [ASPStateTempApplications]和 [ASPStateTempSessions]。其中ASPStateTempSessions的更新非常频繁。在一个繁忙的Web服务器中,下面的存储过程频繁被调用更新ASPStateTempSessions表:

 

TempGetStateItemExclusive3

TempResetTimeout

 

 

一个不常碰到的问题就是,你有可能碰到因为SessionState访问导致的blocking (阻塞)问题。 如果这样,你可以试图使用下面的方法解决。

 

大部分阻塞问题是因为TempGetStateItemExclusive3 或TempResetTimeout

里面的UPDATE语句:

 

UPDATE [ASPState].dbo.ASPStateTempSessions

            SET Expires = DATEADD(n, Timeout, @now),

                LockDate = CASE Locked

                    WHEN 0 THEN @now

                    ELSE LockDate

                    END,

                LockDateLocal = CASE Locked

                    WHEN 0 THEN @nowLocal

                    ELSE LockDateLocal

                    END,

             ......

                    END

            WHERE SessionId = @id

           

 

阻塞在LCK_M_U锁上面:

 

你可以注意到,blocking head正在等待WRITELOG, 这表示UPDATE事务正在写transaction log,但是被延迟了。很可能存放log的磁盘特别慢导致。 那么当然应该把transaction log放到更快的磁盘,阻塞问题应该能够缓解一点。

 

还有一个方法就是,修改SessionStateLockedItemPollInterval的值, 使得sessionstate在block的时候,查询的频度少一点。 具体可以参考如下文档:

 

https://support.microsoft.com/kb/939866/zh-cn

 

你甚至可以修改TempGetStateItemExclusive3,使得它不会频繁修改热表ASPStateTempSessions。 我的一个客户就这样做了,效果也很不错。

 

更多best Practice:

https://msdn.microsoft.com/zh-cn/library/ff649152.aspx

https://www.microsoft.com/en-us/download/details.aspx?displaylang=en&id=11711

 

l Prefer basic types to reduce serialization costs .

l Disable session state if you do not use it.

l Avoid storing STA COM objects in session state .

l Use the ReadOnly attribute when you can.