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/