利用Ring Buffer在SQL Server 2008中进行连接故障排除
SQL Server 2008 中包含一个新功能,旨在帮助解决特别棘手的连接问题。这个新功能是 Connectivity Ring Buffer ,它可以捕捉每一个由服务器发起的连接关闭记录 (server-initiated connection closure) ,包括每一个 session 或登录失败事件。为了进行有效的故障排除, Ring Buffer 会尝试提供客户端的故障和服务器的关闭动作之间的关系信息。只要服务器在线 , 最高 1K 的 Ring Buffer 就会被保存, 1000 条记录后, Buffer 开始循环覆盖,即从最老的记录开始覆盖。 Connectivity Ring Buffer 的记录是能够使用 DMV 查询的: SELECT CAST ( record AS XML ) FROM sys . dm_os_ring_buffers WHERE ring_buffer_type = ‘RING_BUFFER_CONNECTIVITY’ 上述指令会选择所有记录为 XML 类型 ; 在 Management Studio 中 , 你可以单击记录 , 从而获得更具可读性的版本。如果你想使用 SQL 查询 XML 记录从而找到相应的问题 , 你可以使用 SQL server 的 XML 支持 , 将之变为一个临时的表 , 从而查询记录。 一个基本的Buffer entry:Killed SPID 一个导致服务器发起的连接关闭的简单方法是打开两个 SQL 服务器的连接,找到一个连接的 SPID ,然后从另一个连接中将该 SPID 杀死。 C:>osql -E 1> SELECT @@ spid 2> go —— 51 (1 row affected) C:>osql -E 1> kill 51 2> go 1> 如果你做了上述工作,然后查询 Ring Buffer ,你会得到和如下类似的结果: < Record id = ” 2 ” type = ” RING_BUFFER_CONNECTIVITY ” time = ” 110448275 ” > < ConnectivityTraceRecord > < RecordType > ConnectionClose </ RecordType > < RecordSource > Tds </ RecordSource > < Spid > 55 </ Spid > < SniConnectionId > B7882F3C-3BA9-45A7-8D23-3C5C05F9BDF9 </ SniConnectionId > < SniProvider > 4 </ SniProvider > < RemoteHost > & lt ; local machine > ; </ RemoteHost > < RemotePort > 0 </ RemotePort > < LocalHost /> < LocalPort > 0 </ LocalPort > < RecordTime > 5/6/2008 22:47:35.880 </ RecordTime > < TdsBuffersInformation > < TdsInputBufferError > 0 </ TdsInputBufferError > < TdsOutputBufferError > 0 </ TdsOutputBufferError > < TdsInputBufferBytes > 60 </ TdsInputBufferBytes > </ TdsBuffersInformation > < TdsDisconnectFlags > < PhysicalConnectionIsKilled > 0 </ PhysicalConnectionIsKilled > < DisconnectDueToReadError > 0 </ DisconnectDueToReadError > < NetworkErrorFoundInInputStream > 0 </ NetworkErrorFoundInInputStream > < ErrorFoundBeforeLogin > 0 </ ErrorFoundBeforeLogin > < SessionIsKilled > 1 </ SessionIsKilled > < NormalDisconnect > 0 </ NormalDisconnect > < NormalLogout > 0 </ NormalLogout > </ TdsDisconnectFlags > </ ConnectivityTraceRecord > < Stack > < frame id = ” 0 ” > 0X01CA0B00 </ frame > < frame id = ” 1 ” > 0X01CA0DB1 </ frame > < frame id = ” 2 ” > 0X01DF6162 </ frame > < frame id = ” 3 ” > 0X02E53C98 </ frame > < frame id = ” 4 ” > 0X02E54845 </ frame > < frame id = ” 5 ” > 0X02E57BE9 </ frame > < frame id = ” 6 ” > 0X02E38F57 </ frame > < frame id = ” 7 ” > 0X02E3B2C0 </ frame > < frame id = ” 8 ” > 0X02E3C832 </ frame > < frame id = ” 9 ” > 0X02E3D55E </ frame > < frame id = ” 10 ” > 0X781329BB </ frame > < frame id = ” 11 ” > 0X78132A47 </ frame > </ Stack > </ Record > 不同的记录类型包括不同的信息。 Connectivity Ring Buffer 记录的三种记录类型分别是: ConnectionClose , Error ,和 LoginTimers 。上面的结果是一个 ConnectionClose ,因为这不是一个登陆时超时,或者其它的登陆失败的场景: < RecordType > ConnectionClose </ RecordType > 我们可以看出, SPID 55 的连接关闭了: <![endif]> < Spid > 55 </ Spid > 我们可以看到连接是本地的( <local machine> 表明其是一个本地的, shared memory 类型的连接)。 <![endif]> < RemoteHost > & lt ; local machine > ; </ RemoteHost > 当使用 TCP 协议进行连接时,可以获得更多的相关信息 – 例如,本地 IP 地址,端口,以及远程 IP 地址和端口,从而允许你唯一的确定客户机及其应用。另外, Ring Buffer 包括了一个时间戳以及与之相对应的 SPID (如果有的话),这样才能形成一个完整的对应关系。(因为随着时间的推移 SPID 会被不同的连接所重用)。 我们同样可以看到客户发的 TDS 包中有多少 bytes ,并且可以知道是否在 TDS 中有任何的错误: < TdsInputBufferError > 0 </ TdsInputBufferError > < TdsOutputBufferError > 0 </ TdsOutputBufferError > < TdsInputBufferBytes > 60 </ TdsInputBufferBytes > 最相关的,最易于分析的信息记录在 TdsDisconnectFlags 中,有一系列的值,记录了关闭连接的状态。这里,我们看到没有发现错误,但是这里记录了这也不是一个正常的断开或者一个正常的登出。从如下的 flag 中,这个 session 是被杀死的: < SessionIsKilled > 1 </ SessionIsKilled > 一个更有意思的例子:DC 连接性问题 跟踪被杀死的 SPID 看起来很 cool 。但是 Connectivity Ring Buffer 更重要的最用 是帮助我们可以在不使用 network monitor 的情况下来解决棘手的问题。以下是一个 Connectivity Ring Buffer 中 Login Time 记录的例子,如果没有代价高昂的问题重现过程并且分析网络抓获的包,这个问题很难查明: < Record id = ” 3 ” type = ” RING_BUFFER_CONNECTIVITY ” time = ” 112254962 ” > < ConnectivityTraceRecord > < RecordType > LoginTimers </ RecordType > < Spid > 0 </ Spid > < SniConnectionId > B401B045-3C82-4AAC-A459-DB0520925431 </ SniConnectionId > < SniConsumerError > 17830 </ SniConsumerError > < SniProvider > 4 </ SniProvider > < State > 102 </ State > < RemoteHost > & lt ; local machine > ; </ RemoteHost > < RemotePort > 0 </ RemotePort > < LocalHost /> < LocalPort > 0 </ LocalPort > < RecordTime > 5/6/2008 23:17:42.556 </ RecordTime > < TdsBuffersInformation > < TdsInputBufferError > 0 </ TdsInputBufferError > < TdsOutputBufferError > 232 </ TdsOutputBufferError > < TdsInputBufferBytes > 198 </ TdsInputBufferBytes > </ TdsBuffersInformation > < LoginTimers > < TotalLoginTimeInMilliseconds > 21837 </ TotalLoginTimeInMilliseconds > < LoginTaskEnqueuedInMilliseconds > 0 </ LoginTaskEnqueuedInMilliseconds > < NetworkWritesInMilliseconds > 2 </ NetworkWritesInMilliseconds > < NetworkReadsInMilliseconds > 77 </ NetworkReadsInMilliseconds > < SslProcessingInMilliseconds > 3 </ SslProcessingInMilliseconds > < SspiProcessingInMilliseconds > 21756 </ SspiProcessingInMilliseconds > < LoginTriggerAndResourceGovernorProcessingInMilliseconds > 0 </ LoginTriggerAndResourceGovernorProcessingInMilliseconds > </ LoginTimers > </ ConnectivityTraceRecord > < Stack > < frame id = ” 0 ” > 0X01CA0B00 </ frame > … < frame id = ” 15 ” > 0X02E3C832 </ frame > </ Stack > </ Record > 在这个情况下,在客户端,我们可以看到: [SQL Server Native Client 10.0]Shared Memory Provider: Timeout error [258]
Read the original:
利用Ring Buffer在SQL Server 2008中进行连接故障排除


