随笔 - 55  文章 - 0 评论 - 6 trackbacks - 0

Q:对于复杂的连接问题,我如何获得更多的信息以用于纠错?

A:
SQL Server 2008包含了一个用于帮助特别困难的连接问题纠错的新特性 - 连接环缓冲区(Connectivity Ring Buffer)。它可以捕捉每一个服务器发起的连接关闭,包括关闭会话或登陆失败事件。为了使纠错更加方便有效,环缓冲区试图提供与客户端失败与服务器端关闭行为的相关信息。只要服务器在线,环缓冲区内最多可以存储1000条记录。连接环缓冲区的记录。当超过1000条记录,缓冲区会被循环利用,最早的记录会被替代。连接环缓冲区的记录可以通过DMV以如下语句查询:

SELECT CAST(record AS XML) FROM sys.dm_os_ring_buffers
WHERE ring_buffer_type = 'RING_BUFFER_CONNECTIVITY'

这会把所有的记录以XML形式查询出来。在SQL Server Managerment Studio中,您可以点击记录以更易读的方式阅读记录。如果您想要使用SQL查询以更加精准地定位特定的问题,您可以使用SQL Server的XML支持把结果放入一个临时表中,对记录进行查询。

一个简单的范例:基本的环缓冲区条目:杀掉SPID
最简单的导致服务器发起的连接问题,是打开两个对SQL Server的连接,找到其中一个的SPID,然后使用另外一个连接来杀掉该SPID:

SELECT @@spid
go
--如果结果SPID为51
kill 51
go

如果您进行该尝试,查询环缓冲区,您会得到类似如下结果:

<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&gt;</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>

不同的记录类型会包含不同的信息。连接环缓冲区显示的三种记录类型为:ConnectionClose, Error, 与LoginTimers。该连接类型为ConnectionClose,因为它不是登陆时的连接关闭,也不是由超时或一些其他的登陆错误场景:

    <RecordType>ConnectionClose</RecordType>

我们可以看见这是SPID 55的连接被关闭:
    <Spid>55</Spid>
我们可以看到连接为本地的(因为XML编码的标签文字显示“<local machine>”,说明这个是本地的,共享内存连接):
    <RemoteHost>&lt;local machine&gt;</RemoteHost>
如果是使用TCP协议连接到SQL Server的话可以获得更多有用的相关信息 - 包括本地IP和端口,远程IP和端口,允许您鉴别出记录对应的客户机以及应用程序。
另外,环缓冲区包含了时间戳和客户端进程的SPID(如果可能的话)以关联无缝化(因为SPID可能随着时间被不同的连接重复利用)。

我们也能看到客户端在TDS包内发送了多少比特数据,及TDS中是否包含错误信息:
      <TdsInputBufferError>0</TdsInputBufferError>
      <TdsOutputBufferError>0</TdsOutputBufferError>
      <TdsInputBufferBytes>60</TdsInputBufferBytes>
对于ConnectionClose记录最相关最容易分析的部分信息是在TdsDisconnectFlags内,包含了大量说明了关闭的连接状态的值。在这个例子中我们可以看到没有出现错误,但这也不是一个正常的断开连接或普通的会话登出。我们看到的是一个说明会话是被杀掉的标记:
      <SessionIsKilled>1</SessionIsKilled>

更多例子请参见:http://blogs.msdn.com/sql_protocols/archive/2008/05/20/connectivity-troubleshooting-in-sql-server-2008-with-the-connectivity-ring-buffer.aspx

posted on 2009-03-25 15:33 Dem 阅读(...) 评论(...) 编辑 收藏