SQL Server数据库中,若是应用程序正在执行一个事务的时候忽然遭遇了网络异常,例如网络掉包,网络中断等,那么这个事务会怎么样? SQL Server数据库是经过什么机制来判断处理呢? 估计不少人跟我同样都有很多疑问, 咱们下面构造一个测试实验来测试验证一下。以下所示:html
步骤1:在客户端连使用SSMS工具链接到测试数据库,执行下面脚本,显性事务既不提交也不回滚。模拟事务正在执行当中。sql
USE AdventureWorks2012;数据库
GO服务器
SELECT@@SPID;网络
BEGINTRANtcp
DELETEFROM [dbo].[Products] WHERE ProductID=1;函数
--ROLLBACK;工具
输出的会话ID为59测试
步骤2:在测试服务器上开启Profiler跟踪一下具体信息。具体步骤略过。编码
步骤3:经过VMware vSphere Client的控制台链接到测试服务器,禁用网卡,而后启用网卡,模拟网络异常。(注意:玩过Vmware的应该都知道,这里不详细介绍!)
以下截图所示,在跟踪过程当中,咱们能够看到当我构造网络异常时,会话ID=59的事务当即回滚了。
固然你也能够使用下面函数查看日志里面的相关记录信息。以下所示:
SELECT*
FROMfn_dblog(NULL,NULL)
WHERE Operation ='LOP_ABORT_XACT';
你能够看到 LOP_BEGIN_XACT (事务开始)-> LOP_DELETE_ROWS (删除记录) -> LOP_INSERT_ROWS (插入记录) ->LOP_ABORT_XACT (事务回滚)
经过上面实验测试,咱们知道当应用程序遭遇网络异常时,数据库会回滚未提交的事务。那么接下来的问题有下面几个:
1: SQL Server须要多长时间才能检测到会话的网络异常?
如上所示,我断开的是服务器的网络,会话当即就回滚了。可是若是我断开的是客户端(执行SSMS客户端的网络),那么会话回滚的时间是30秒。以下截图所示
事务开始时间为: 2017-07-27 13:48:01:820
事务回滚时间为: 2017-07-27 13:48:32.043
这个是服务器上Keep Alive参数控制的,具体位置 “SQL Server Configuration Manager”-> “SQL Server Network Configuration” -> "Protocol for MSSQLSERVER" -> "TCP/IP " 右键单击属性,以下截图所示:
30000 的单位是毫秒, 等价于30秒, 若是你将这个设置为60000 ,那么测试结果就会是60秒或超过60秒。
固然这个时间差是你断开网络的时间和事务结束的时间差,而不是事务开始时间与结束时间差,以下测试所示,截图1,因为需找到禁用网络的位置,而后又切换窗口,致使延误了几秒,这个事务开始、结束时间差为70秒。 固然这个值不可能彻底等于Keep Alive的值,由于还涉及参数Keep Alive Interval的值,因此这个值玩玩是大于等于Keep Alive的值。具体后面会讲述!
2: SQL Server经过什么机制来判断当前会话遭遇了网络异常?
在这篇“ORACLE的Dead Connection Detection浅析”文章里面, 我介绍了Linux系统下TCP KeepAlive概念,顾名思义,TCP keepalive它是用来保持TCP链接的,注意它只适用于TCP链接。系统会替你维护一个timer,时间到了,就会向remote peer发送一个probe package,固然里面是没有数据的,对方就会返回一个应答,这时你就知道这个通道保持正常。与TCP keepalive有关的三个参数tcp_keepalive_time、tcp_keepalive_intvl、tcp_keepalive_probes
/proc/sys/net/ipv4/tcp_keepalive_time 当keepalive起用的时候,TCP发送keepalive消息的频度。默认是2小时。
/proc/sys/net/ipv4/tcp_keepalive_intvl 当探测没有确认时,keepalive探测包的发送间隔。缺省是75秒。
/proc/sys/net/ipv4/tcp_keepalive_probes 若是对方不予应答,keepalive探测包的发送次数。缺省值是9。
其实在Windows系统中也有相似的参数,分别是KeepAliveTime、KeepAliveInterval、TcpMaxDataRetransmissions
KeepAliveTime 默认是7,200,000 milliseconds = 2 hours
KeepAliveInterval 默认是1,000 milliseconds = 1 second
TcpMaxDataRetransmissions 默认值是5次
https://technet.microsoft.com/en-us/library/cc957549.aspx
https://technet.microsoft.com/en-us/library/cc957548.aspx
https://technet.microsoft.com/en-us/library/cc938210.aspx
根据上面文档描述,几个值能够在HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters里设置,可是我检查过Windows 2000/2003/2008/2012 默认状况下,在注册表里面都没有这个值,可是能够在注册表里添加该选项。固然好像在有些操做系统下,有些参数是硬编码值,有些还不能修改.“Important note: If OS is Windows Vista/2008, the number of TCP Keepalive attempts are hardcoded to 10 and could not be adjusted via the registry.” 。 具体参考下面连接,固然这些值我的没有测试过。
那么SQL Server是否也是经过OS的这三个参数来判断会话是否orphaned, 很显然不是。它是经过SQL Server的Keep Alive、Keep Alive Interval来判断会话是否遭遇网络异常。那么操做系统的KeepAliveTime跟SQL Server的Keep Alive是否是一回事? 又有什么区别呢? 其实这个能够参考https://blogs.msdn.microsoft.com/apgcdsd/2011/05/02/sql-server-connection-keepalive-faq/。摘抄部分原文以下:
1、什么是SQL Server TCP链接的Keep Alive?
简单说,Keep Alive 是SQL Server在创建每个TCP 链接的时候,指定了TCP 协议的Keepaliveinterval 和 Keepalivetime参数。这样对每一个TCP链接,若是该链接空闲时间(没有任何数据交互)超过Keepalivetime,TCP协议会自动发出Keepalive 包检测链接存活与否。若是Keepalive检测次数超过注册表TcpMaxDataRetransmissions定义的值而对方仍是没有回应,那么TCP就认为该链接有问题而关闭它。经过这样的机制SQL Server可以检测出Orphaned Connection等问题。
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 Server可以检测出Orphaned Connection等问题。
3、SQL Server的Keepalive 和Windows的TCP协议里面的Keepalive 是同样的吗?
原理同样,但不相互干扰。Windows 的TCP协议也有keep alive 配置,位置以下:
HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
OS的TCP协议的Keep Alive 和SQL Server 的Keep Alive 工做原理同样的,就是在创建TCP链接的时候指定TCP链接的Keepalive属性(参见后面描述)。可是SQL Server读取本身注册表的Keep Alive来设置TCP链接属性,不理会Windows OS的注册表里面的Keepalivetime和Keepaliveinterval的值。若是一个应用程序没有显式调用函数设置TCP链接的Keepalive属性,那么他的TCP链接默认使用OS 的TCP配置。OSkeep Alive配置默认是关闭的。
参考资料:
https://blogs.technet.microsoft.com/nettracer/2010/06/03/things-that-you-may-want-to-know-about-tcp-keepalives/
https://blogs.msdn.microsoft.com/apgcdsd/2011/05/02/sql-server-connection-keepalive-faq/
https://blogs.msdn.microsoft.com/apgcdsd/2012/06/07/sql-server-connection-keep-alive-faq3/