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


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

 

 

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

 

USE AdventureWorks2012;

GO

SELECT@@SPID;

 

 

BEGINTRAN

 

    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/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM