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><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>
不同的记录类型会包含不同的信息。连接环缓冲区显示的三种记录类型为:ConnectionClose, Error, 与LoginTimers。该连接类型为ConnectionClose,因为它不是登陆时的连接关闭,也不是由超时或一些其他的登陆错误场景:
<RecordType>ConnectionClose</RecordType>
我们可以看见这是SPID 55的连接被关闭:
<Spid>55</Spid>
我们可以看到连接为本地的(因为XML编码的标签文字显示“<local machine>”,说明这个是本地的,共享内存连接):
<RemoteHost><local machine></RemoteHost>
如果是使用TCP协议连接到SQL Server的话可以获得更多有用的相关信息 - 包括本地IP和端口,远程IP和端口,允许您鉴别出记录对应的客户机以及应用程序。
另外,环缓冲区包含了时间戳和客户端进程的SPID(如果可能的话)以关联无缝化(因为SPID可能随着时间被不同的连接重复利用)。
我们也能看到客户端在TDS包内发送了多少比特数据,及TDS中是否包含错误信息:
<TdsInputBufferError>0</TdsInputBufferError>
<TdsOutputBufferError>0</TdsOutputBufferError>
<TdsInputBufferBytes>60</TdsInputBufferBytes>
对于ConnectionClose记录最相关最容易分析的部分信息是在TdsDisconnectFlags内,包含了大量说明了关闭的连接状态的值。在这个例子中我们可以看到没有出现错误,但这也不是一个正常的断开连接或普通的会话登出。我们看到的是一个说明会话是被杀掉的标记:
<SessionIsKilled>1</SessionIsKilled>