有关SQL server connection Keep Alive 的FAQ(3)
這個是SQL Server Keep Alive FAQ文章的最后一篇。
?
問題1:為什么我在客戶端設置了KeepAlive值,但是我使用SQL server management studio 測試的時候,該值總是不起作用??
?
[答]目前市場上主流的數據庫訪問技術有ODBC,OLEDB,SQL native client 和 SQLclient。其中SQLclient是.NET里面使用的托管provider。目前SQL Server configuration manager里面提供的keepalive設置是針對SQL native client 的:?
?
也就是說, 該值只對使用SQL Native Client 來訪問數據庫的程序有效。SQLcmd.exe是使用SQL native client來訪問SQL server的一個命令行工具,所以您可以使用SQLCmd來測試上面的keepalive值。注意修改keepalive值后,你需要退出SQLcmd重新運行它才能使用新值。我在幾組機器測試了幾組不同的keepalive值,SQLcmd程序的TCP連接都很好按照設置的值發出keepalive網絡包。注意你需要使用TCP連接服務器來測試。 我使用下面的連接串以保證使用TCP 連接:
?
SQLcmd -E -STCP:mycomputer\SQL2012,55890
(機器名:mycomputer,實例名:SQL2012,端口號 55890)
?
我使用network monitor 3.4捕獲keepalive包如下圖:?
?
?上圖中深藍高亮的是我挑出的由服務器TCP連接發給SQLcmd的keepalive包,每個包間隔30秒(時間間隔可以看time offset前后相減即可)。而上圖間隔7秒的是SQLcmd的TCP連接發出的keepalive包。我測試中使用SQL server configuration manager設置了native client 的keepalive為7秒。從上面圖也印證了服務器端的TCP連接和客戶端的TCP連接各自發送自己的keepalive包,相互不影響。
?
注意, SQL Server native client的keepalive值存放在下面注冊表里面:
?
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\Client\SNIx.0\tcp\Property2
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\Client\SNIx.0\tcp\Property3
?
那么SQL server management studio (ssms.exe)是使用.NET managed的SQLclient,所以上面針對native client的設置對SQLclient無效。SQL server management studio? 使用了 hard-coded的30秒值,無法修改。
?
?
問題2. ODBC,SQL OLEDB,SQL native client和SQLClient的TCP keepalive缺省時間都是多少?在哪里可以設置?
?
[答]缺省值都是30秒。
?
可以修改如下注冊表值來設置ODBC 和SQL OLEDB的keepalive值:
?
HKLM\SOFTWARE\Microsoft\MSSQLServer\Client\SuperSocketNetLib\Tcp ==> KeepAliveTime : DWORD : <dwValue>
HKLM\SOFTWARE\Microsoft\MSSQLServer\Client\SuperSocketNetLib\Tcp ==> KeepAliveInterval : DWORD : <dwValue>
?
注意如果是x64的機器,在上面運行32位的ODBC/SQL OLEDB程序,則需要修改如下注冊表:
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\MSSQLServer\Client\SuperSocketNetLib\TCP
?
對于SQLserver native client 和SQL server 的keep alive設置,可以在SQL server configuration manager 修改,具體請參考請參考FAQ (1)和FAQ (2)或問題1。
?
對于SQL client,需要在使用sqlclient的應用程序里面使用代碼設置。
?
問題3:服務器端如果網線被拔掉,這對于那些已經存在的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)會保持不會被關閉。
?
你或許會問,media sense功能如何disable呢?具體可以參考如下命令:
?
netsh interface ipv4 set global dhcpmediasense=disabled
netsh interface ipv6 set global dhcpmediasense=disabled
?
如何察看這些設置的命令如下:
netsh interface ipv4 show global
netsh interface ipv6 show global
?
回到keepalive。 如果SQL Server服務器的TCP的keepalive設置時間很短,小于DisconnectDampInterval -5時間值,那么SQL server會先于操作系統得知連接斷線的狀態而采取相應的動作。實際中不建議過短的keepalive值。
?
問題4:DisconnectDampInterval在哪里可以修改?有沒有media sense的更多的信息?
[答]可以參考如下WinCE的文檔:在
http://msdn.microsoft.com/en-US/library/ee486075(v=WinEmbedded.60).aspx
?
ConnectDampingInterval specifies the amount of time, in seconds, by which TCP/IP will delay any action in response to a Media Sense connect event.
DisconnectDampInterval specifies the amount of time, in seconds, by which TCP/IP will delay any action in response to a Media Sense disconnect event.
?
在非CE平臺上該定義依然有效,不過,缺省值是5~10秒。可以修改如下注冊表修改該值:
?
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Tcpip\Parameters
DisconnectDampInterval
ConnectDampInterval
?
這兩個參數有最大最小值限制, Min = 5 seconds,Max = 10 seconds。
?
問題5:如下圖SQL server的網絡協議TCP的屬性頁為何沒有keep alive interval選項?
?
[答]SQL server的網絡協議TCP的keep alive interval是不能修改的,注冊表也無法修改. SQL server源代碼里面寫定了1秒的時間間隔.
?
問題6:我的應用程序如何才能捕獲keepalive機制偵測到的網絡問題?
[答] 對于用戶程序,你需要調用ExecuteSQL或類似的方法才能獲知connection的真實狀態. 如下面例子所示:
?
using (SqlConnection connection = new SqlConnection())
{
connection.ConnectionString ="Data Source=TCP:cn-simon-w7\\sql2012,55890;Initial Catalog=test;Integrated Security=true;pooling=false";
?
??SqlCommand cmd = new SqlCommand();
??cmd.CommandText = "select * from t";
??cmd.Connection = connection;
??cmd.CommandTimeout = 0;
?
?try
?{
??connection.Open();
?? cmd.ExecuteNonQuery();
? }
?
?catch (Exception ex)
?? {
????? //do your work here for this exception
?????? MessageBox.Show(ex.Message);
??? };
????????????????????????????????
}
?
我做了小測試步驟如下:
?
1)?? 想辦法阻塞 “select * from t”使得它不返回結果而處于等待狀態。
2)?? 然后拔掉服務器網絡線。
3)?? 然后過一會,我的catch語句捕獲了錯誤?
?
你其實可以對ex對象做更多的處理,請參看有關編程文檔,此處不多描述。?
總結
以上是生活随笔為你收集整理的有关SQL server connection Keep Alive 的FAQ(3)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 推荐些在线小制作小工具
- 下一篇: 快速深入一门语言的几个问题 - Shel