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.