SQL Server 连接问题案例解析(1)

   Microsoft Network Monitor(Netmon)是由微软发布的一款网络协议数据分析工具,利用Netmon可以捕获网络数据并进行查看和分析。
在处理SQL Server 的连接问题时,Netmon常常会起到关键的作用。在本篇博文中,我将为大家分享一个通过使用 Netmon 解决的经典案例。
      在这个案例中,客户发现在客户端的 SQL Server Management Studio 中执行某一个Query时就会发生错误,
错误信息是“connection forcibly close by the remote server ”。
 
为了调查连接被关闭的原因,我们在客户端和服务端抓取了Netmon。在正式分析这个案例前,我们先来介绍一些有关Netmon的知识和使用技巧。
 
                                                     Netmon界面

1. 在Netmon界面中的Frame Summary 部分,我们首先可以看到Frame Number,不管我们在浏览时是否有设置filter,Frame Number的值是不会发生改变的,

它相当于Frame的一个行号。
 
2. 在左侧Network Conversation 中,我们会看到进程的name和ID,在示例中即为Ssms.exe和3352。继续展开后看到IPv4,
那么我们可以知道这个conversation是从哪里来的。再次展开可以看到这个conversation的端口,本示例中,端口为143349428
 
在这里需要额外讲解一下,当客户端程序创建连接到SQL Server时会使用哪些端口呢?
客户端会向操作系统申请并使用一个动态端口并向SQL Server发送连接请求。如果在连接时使用的是machine name,provider默认会去连接1433端口,
这是一个provider的行为,改变这个行为需要修改注册表:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\Client\<Provider>\tcp\DefaultPort
3. 当客户端尝试创建一个连接到SQL Server,有了source port和destination port后,在这两个port中就会形成一组physical tcp连接。
形成连接之后每发一个包,包的sequence值就会发生变化。请注意,只有在同一个物理连接中,sequence的变化是连续的
如果客户端和SQL Server建立了两个不同的物理连接,这两个连接中的sequence没有任何关系。
4. Netmon中数据量很大,如果查看呢?
比如在浏览一个比较大的Netmon时,我们发现了一个Reset  Flag:
21  3:46:20 PM 9/5/2014          21.8000442   Ssms.exe       172.22.204.237      172.16.221.38           TCP    
TCP: [Bad CheckSum]Flags=...A.R.., SrcPort=49428, DstPort=1433, PayloadLen=0,

Seq=3636257929, Ack=707503184, Win=0     {TCP:2,IPv4:1}
就可以从这个Frame的详细信息入手。从详细信息中可以找到它的source port是49428。
(1)此时我们可以就通过添加 filterTcp.port==49428 来过滤出这个Reset的conversation。
(2)另外一种过滤方法是直接在右键单击Frame后弹出的菜单中选择Find Conversation, 但这种方法有可能会造成丢包,因此还是推荐使用第一种方法。
找到了port就几乎相当于找到了出问题的连接。当然,对于不同时间点,同样的port有可能会是两个不同的连接,
因为上一个连接关掉后,下一个连接有可能重用这个port。按照port过滤后,从reset 开始顺序往前看。
5. 在Netmon中我们还可以看到一些protocol是TDS的Frame。TDS的好处是在查看Frame Details时,可以看到更多的信息。
例如我们查看一个TDS:SQLBatch的TDS Frame Detail,可以看到SQL的statement:

对于当SQL Server使用的端口不是默认的1433时,如何显示TDS frames,
6. 除了在4中介绍的通过port进行过滤,最常用的filter还有
ipv4.address==<xxx.xx.xx.xx>
除直接在filter中写入之外还有一种添加filter的方法,以过滤出所有flag是reset的frames为例来说明:那么我可以在某个reset frame的details中找到这个flag,
在右键单击弹出的菜单中选择Add Selected
Value to Display filter:
 
7. 一个SQL Server的包会在网络传输过程中会经过以下几层:
NIC(网卡物理设备)—》NDIS(网卡驱动)—》TCPIP (操作系统)—》afd(操作系统后台线程,每一个tcp port上都会有一个afd)—》
SQL Server—》for authentication(调用 sspi—lssas—DC)
Netmon所抓取的数据是在网卡驱动上面和TCPIP 下面的
 
所以Netmon所抓到的包是不能作为网卡真正发出去的包的,需要比较发出去的包和客户端收到的包来判断网卡或路由等是否进行了切包。
8. 在chimney开启时,抓到的包的信息有可能是不全的,如果在查看时发现包的行为很奇怪,怀疑丢包,
那么一定要请客户关闭chimney(以管理员运行CMD并且执行命令:netsh interface tcp set global chimney=disabled)后重新收集Netmon。

接下来,我们就来讨论一下今天的案例。当具备了以上Netmon的知识和技巧后,在处理这个案例中所收到的Netmon数据就非常有针对性了。

将客户端的Netmon数据按照端口号filter后,可以很清楚的看到,客户端一直面对着重传的问题。16是12的重传,17也是12的重传,甚至18,19,20:

那么我们来看一下12的详细信息:

可以看到这个包的长度是4096。那么16呢?查看16的详细信息时我们发现,16的长度变成了1460:

      在重传时包的长度变小说明,由于之前大包无法传递,传递的包的大小被自动调小了。继续查看17,18,19和20会发现这几个包的长度都是1460。
很明显,这是一个大包发不过去导致重传的问题。
      那么现在问题来了,为什么第一次大包发不过去,之后以小包重传也不成功呢?
      查看server端Netmon后会发现,这是由于传输4096的包被切成1460+1460+1172后,server端只收到了最后一个包。
接下来,由于sequence断了,server端会认为这是一个不合法的包,因为中间的信息缺失了。
之后这个连接就在server端直接被block了(所以我们收到的错误信息是“connection forcibly close by the remote server
”),因此后续re-transmit的1460的包server再也没有接收过(后续重传全都失败了)。
      最终问题的解决办法是关闭网卡上的两个选项:Jumbo Packet和Large Send Offload(LSO)。

开启Jumbo Packet表示支持大包,关闭则表示从NIC发出的包采用标准大小1500。

如果LSO是开启的,切包会由网卡驱动(NDIS)完成。如果LSO关闭,切包会由操作系统(TCP Stack)完成,切成多大由Jombo Packet的设置来决定。

我们通常不建议由网卡来切包,因为网卡切包与网络环境有关,可能会导致包的大小不固定,建议还是由操作系统来进行切包。
将这两个选项关闭后,传输包的大小均为标准大小1500,就解决了这个大包被切,重传失败的问题。
      这就是今天的分享,更多SQL Server案例学习请持续关注本博客的更新。

server端Netmon和client端netmon

 
Jumbo Packet:巨型包
 

SQL Server 连接问题案例解析(1)的更多相关文章

  1. SQL Server 连接超时案例一则

    上周六,一工厂系统管理员反馈一数据库连接不上,SSMS连接数据库报"连接超时时间已到.在尝试使用预登录握手确认时超过了此超时时间.......", 如下截图所示: 另外远程连接也连 ...

  2. SQL Server并行死锁案例解析

    并行执行作为提升查询响应时间,提高用户体验的一种有效手段被大家所熟知,感兴趣的朋友可以看我以前的博客SQL Server优化技巧之SQL Server中的"MapReduce", ...

  3. SQL Server 连接问题-TCP/IP

    原文:SQL Server 连接问题-TCP/IP 出自:http://blogs.msdn.com/b/apgcdsd/archive/2012/02/24/ms-sql-server-tcp-ip ...

  4. 通过sql server 连接mysql

    图文:通过sql server 连接mysql   1.在SQL SERVER服务器上安装MYSQL ODBC驱动; 驱动下载地址:http://dev.mysql.com/downloads/con ...

  5. ASP.NET连接数据库时,提示“用户 'sa' 登录失败原因: 未与信任 SQL Server 连接相关联

    用ASP.NET连接数据库时,提示"用户 'sa' 登录失败.原因: 未与信任 SQL Server 连接相关联.".解决方法:首先检查是不是web.config文件内的用户名密码 ...

  6. SQL Server 2000:提示“未与信任SQL SERVER连接相关连”错误

    在使用“用户模式”登陆SQL Server 2000时提示“未与信任SQL SERVER连接相关连”错误,因为在安装SQL Server时选择“仅Windows”模式,所以所有用户都不可以登陆. 解决 ...

  7. SQL Server 连接问题圣经-命名管道

    SQL Server 连接问题圣经-命名管道 (1) APGC DSD Team 12 Jan 2011 1:24 AM 3 一.前言 在使用SQL Server 的过程中,用户遇到的最多的莫过于连接 ...

  8. 【J2EE】Java连接SQL Server 2000问题:“com.microsoft.sqlserver.jdbc.SQLServerException:用户'sa'登录失败。该用户与可信SQL Server连接无关联”

    1.问题现象 E:\JSP\HibernateDemo\HibernateDemoProject\src\sine>java ConnectSQLServerConnect failed!com ...

  9. [ASP.NET]SQL Server 连接字符串和身份验证

    SQL Server .NET Data Provider 连接字符串包含一个由一些属性名/值对组成的集合.每一个属性/值对都由分号隔开. PropertyName1=Value1; Property ...

随机推荐

  1. 创建Hello World程序(part-1)

    写在前面: 2006年,刚上大学,班上有几个计算机文盲,1分钟打二十几个字都困难,很不幸,我就是其中的一个.强烈的自尊心驱使我不停恶补,翻遍了图书馆的计算机文化基础,知耻而后勇...后来,C语言居然考 ...

  2. Delphi中ExtractFilePath、ParamStr以及更多文件/目录操作涉及的函数。附加对应的例子

    先介绍ExtractFilePath和ParamStr ParamStr 该函数的原型是:function paramstr(i: Integer): String; 对于任何的application ...

  3. Codeigniter的Redis使用

    1. ./config/redis.php: <?php $config['redis_host'] = '127.0.0.1'; $config['redis_port'] = '6379'; ...

  4. Azure Site to Site VPN 配置手册

    目录 1    Azure Site to Site VPN配置前的准备    1 1.1    设备兼容    1 1.2    网络要求和注意事项    1 2    配置Azure site t ...

  5. ABP中单元测试的技巧:Mock和数据驱动

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:虽然ABP为大家提供了测试的脚手架了,不过有些小技巧还是需要自己探索的. ASP.NE ...

  6. Python-类的属性

    类的属性,可以称为成员变量 类的方法,可以称为成员函数   对象的创建 - 创建对象的过程称之为实例化:当一个对象被创建后,包含三个方面的特性:对象句柄.属性和方法. - 句柄用于区分不同的对象(实例 ...

  7. mysql 连接池超时

    var mysql = require('mysql'); var pool = mysql.createPool({ host: 'localhost', user: 'nodejs', passw ...

  8. 个人总结深入.NET平台和C#编程

    前言:学习C#编程应该有几个月了,作为一个菜鸟,没有资格来评论什么.只有对自己所学进行一个总结,可能有不严谨的地方,万望谅解.          一·深入.NET框架 .NET框架(.NET Fram ...

  9. Nginx+FastCGI运行原理

    Nginx不支持对外部程序的直接调用或者解析,所有的外部程序(包括PHP)必须通过FastCGI接口来调用.FastCGI接口在Linux下是socket(这个socket可以是文件socket,也可 ...

  10. 整理几种在axure里使页面居中的方法

    1. 用动态面板固定浏览器功能. 很简单方便. 但缺点是 当浏览器窗口大小小于页面时, 由于会强制居中,导致页面2边是在显示范围外并且是无法通过滚动条滚动的(滚动条是没有的). 2. 使用页面属性里的 ...