SQL Server事務遭遇網絡異常時的處理機制淺析

SQL Server數據庫中,若是應用程序正在執行一個事務的時候忽然遭遇了網絡異常,例如網絡掉包,網絡中斷等,那麼這個事務會怎麼樣? SQL Server數據庫是經過什麼機制來判斷處理呢? 估計不少人跟我同樣都有很多疑問, 咱們下面構造一個測試實驗來測試驗證一下。以下所示:html

 

 

步驟1:在客戶端連使用SSMS工具鏈接到測試數據庫,執行下面腳本,顯性事務既不提交也不回滾。模擬事務正在執行當中。sql

 

USE AdventureWorks2012;數據庫

GO服務器

SELECT@@SPID;網絡

 

 

BEGINTRANtcp

 

    DELETEFROM [dbo].[Products] WHERE ProductID=1;函數

 

    --ROLLBACK;工具

 

 

輸出的會話ID59測試

 

 

 

步驟2:在測試服務器上開啓Profiler跟蹤一下具體信息。具體步驟略過。編碼

 

 

 

步驟3:經過VMware vSphere Client的控制檯鏈接到測試服務器,禁用網卡,而後啓用網卡,模擬網絡異常。(注意:玩過Vmware的應該都知道,這裏不詳細介紹!)

 

 

以下截圖所示,在跟蹤過程當中,咱們能夠看到當我構造網絡異常時,會話ID=59的事務當即回滾了。

 

 

clip_image001[4]

 

 

固然你也能夠使用下面函數查看日誌裏面的相關記錄信息。以下所示:

 

 

SELECT*

FROMfn_dblog(NULL,NULL)

WHERE Operation ='LOP_ABORT_XACT';

 

clip_image002[4]

 

你能夠看到 LOP_BEGIN_XACT (事務開始)->   LOP_DELETE_ROWS (刪除記錄) ->  LOP_INSERT_ROWS (插入記錄)  ->LOP_ABORT_XACT (事務回滾)

 

clip_image003[4]

 

 

經過上面實驗測試,咱們知道當應用程序遭遇網絡異常時,數據庫會回滾未提交的事務。那麼接下來的問題有下面幾個:

 

 

 

1 SQL Server須要多長時間才能檢測到會話的網絡異常?

 

如上所示,我斷開的是服務器的網絡,會話當即就回滾了。可是若是我斷開的是客戶端(執行SSMS客戶端的網絡),那麼會話回滾的時間是30。以下截圖所示

 

事務開始時間爲: 2017-07-27 13:48:01:820

事務回滾時間爲: 2017-07-27 13:48:32.043

 

clip_image004[4]

 

clip_image005[4]

 

 

這個是服務器上Keep Alive參數控制的,具體位置 SQL Server Configuration Manager->  SQL Server Network Configuration ->  "Protocol for MSSQLSERVER" ->  "TCP/IP " 右鍵單擊屬性,以下截圖所示:

 

 

30000 的單位是毫秒, 等價於30秒, 若是你將這個設置爲60000 ,那麼測試結果就會是60秒或超過60秒。

 

clip_image006[4]

 

 

固然這個時間差是你斷開網絡的時間和事務結束的時間差,而不是事務開始時間與結束時間差,以下測試所示,截圖1,因爲需找到禁用網絡的位置,而後又切換窗口,致使延誤了幾秒,這個事務開始、結束時間差爲70秒。 固然這個值不可能徹底等於Keep Alive的值,由於還涉及參數Keep Alive Interval的值,因此這個值玩玩是大於等於Keep Alive的值。具體後面會講述!

 

clip_image007[4]

 

clip_image008[4]

 

clip_image009[4]

 

 

2 SQL Server經過什麼機制來判斷當前會話遭遇了網絡異常?

 

在這篇ORACLE的Dead Connection Detection淺析文章裏面, 我介紹了Linux系統下TCP KeepAlive概念,顧名思義,TCP keepalive它是用來保持TCP鏈接的,注意它只適用於TCP鏈接。系統會替你維護一個timer,時間到了,就會向remote peer發送一個probe package,固然裏面是沒有數據的,對方就會返回一個應答,這時你就知道這個通道保持正常。與TCP keepalive有關的三個參數tcp_keepalive_timetcp_keepalive_intvltcp_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系統中也有相似的參數,分別是KeepAliveTimeKeepAliveIntervalTcpMaxDataRetransmissions

 

 

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.」 。 具體參考下面連接,固然這些值我的沒有測試過。

 

  https://blogs.technet.microsoft.com/nettracer/2010/06/03/things-that-you-may-want-to-know-about-tcp-keepalives/

 

 

 

那麼SQL Server是否也是經過OS的這三個參數來判斷會話是否orphaned, 很顯然不是。它是經過SQL ServerKeep AliveKeep Alive Interval來判斷會話是否遭遇網絡異常。那麼操做系統的KeepAliveTimeSQL ServerKeep 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鏈接,若是該鏈接空閒時間(沒有任何數據交互)超過KeepalivetimeTCP協議會自動發出Keepalive 包檢測鏈接存活與否。若是Keepalive檢測次數超過註冊表TcpMaxDataRetransmissions定義的值而對方仍是沒有迴應,那麼TCP就認爲該鏈接有問題而關閉它。經過這樣的機制SQL Server可以檢測出Orphaned Connection等問題。

 

SQL  Server 對每一個TCP鏈接缺省指定Keep Alive 30秒,Keepaliveinterval1秒。Windows TCP配置的TcpMaxDataRetransmissions缺省是5次。就是說,若是TCP鏈接idle30秒,那麼TCP會發送第一個keepalive檢查。若是失敗,那麼TCP會每隔1秒重發Keepalive 包,直到重發5次。若是第五次檢測依然失敗,則該鏈接就被Close。因此,一個TCP鏈接若是出現異常問題,大概在35秒的時候就會被Close。的機制SQL Server可以檢測出Orphaned Connection等問題。

 

3SQL Server的Keepalive WindowsTCP協議裏面的Keepalive 是同樣的嗎?

 

原理同樣,但不相互干擾。Windows TCP協議也有keep alive 配置,位置以下:

 

HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters

 

OSTCP協議的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.msdn.microsoft.com/sql_protocols/2006/03/08/understand-special-tcpip-property-keep-alive-in-sql-server-2005/

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/

相關文章
相關標籤/搜索