SQL Server的keepalive
一 TCP keepAlive
keepalivetime表示的是TCP连接处于畅通时候的探测频率,一旦探测包没有返回,就以keepaliveinterval的频率发送,经过若干次的重试,如果探测包都没有返回,那么就得出结论:TCP连接已经断开。
SQL server的keepalive 和Windows的TCP协议里面的keepalive 是一样,但不相互干扰。
SQL server 对每个TCP连接缺省指定keep alive 为30秒,keepaliveinterval为1秒。Windows TCP配置的TcpMaxDataRetransmissions缺省是5次。就是说,如果TCP连接idle了30秒,那么TCP会发送第一个keepalive检查。如果失败,那么TCP会每隔1秒重发keepalive 包,直到重发5次。如果第五次检测依然失败,则该连接就被close。所以,一个TCP连接如果出现异常问题,大概在35秒的时候就会被close。
SQL server2005使用configuration manager可以修改keep alive值,但是不能修改keepalive interval。 Keepaliveinterval是hardcoded的1秒。
注意SQL server的Native client也有类似配置,不要和server side 的TCP配置搞混。
服务器端的TCP连接和客户端的TCP连接各自发送自己的keepalive包
SQL server 不会关闭一个正常的TCP连接。除非底层TCP报告错误。或者连接或接收数据出错。查询 sys.dm_exec_connections比较输出里面的last_read/last_write和现在时间可以大概知道一个连接的idle时间。
SQL native client 和 SQLclient。其中SQLclient是.NET里面使用的托管provider。目前SQL Server configuration manager里面提供的keepalive设置是针对SQL native client 的:
SQL server management studio (ssms.exe)是使用.NET managed的SQLclient,所以针对native client的设置对SQLclient无效。SQL server management studio 使用了 hard-coded的30秒值,无法修改。
二服务器端如果网线被拔掉,这对于那些已经存在的TCP连接会有什么影响?SQL server会马上关闭连接么?如果拔掉网线然后马上又插回去呢?
[答]这样问题复杂一些。当网线拔掉的时候,网卡首先获知该事件。Windows 2003以及后面的操作系统都实现了media sense 媒体感知功能。操作系统收到网卡发来的media sense 的断线(disconnect)事件后,如果在DisconnectDampInterval(一般是5-10秒)的时间内,网线连接还没有恢复,那么就会发送信息给侦听该网卡IP的连接。那么所有监听该IP的上层应用程序如SQL server 就会得到disconnect的事件,然后就会进行相应的动作如kill connection, rollback事务等。
具体点来说,SQL server 的网络IO是通过IOCP (IOCompletionPort)实现的。 SQL server在后台有几个专门的线程侦听该端口。这些线程调用GetQueuedCompletionStatus()函数得到网络数据状态,然后调用相应的callback函数(如ReadHandler函数)来做具体的数据处理。当网线断的时候,操作系统过了DisconnectDampInterval时间后,GetQueuedCompletionStatus函数就会得到disconnect信息,而callback函数readhandler就被调用来读取数据但实际上是读到disconnect的网络断事件。SQL server 得知该disconnect事件后,就生成一个task,该task就是做kill session的任务,把事务会滚,把连接(connection)关掉。
所以说,如果你在很快的时间内(几秒),拔掉网线马上插回来,那么SQL server的TCP连接(connection)会保持不会被关闭。