轉載:有關SQL server connection Keep Alive 的FAQ(3)

stswordman發表於2013-08-20

   

轉載:http://blogs.msdn.com/b/apgcdsd/archive/2012/06/07/sql-server-connection-keep-alive-faq-3.aspx

這個是SQL Server Keep Alive FAQ文章的最後一篇。

   

問題1:為什麼我在客戶端設定了KeepAlive,但是我使用SQL server management studio 測試的時候,該值總是不起作用?

   

[]目前市場上主流的資料庫訪問技術有ODBCOLEDBSQL 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連線發給SQLcmdkeepalive包,每個包間隔30秒(時間間隔可以看time offset前後相減即可)。而上圖間隔7秒的是SQLcmdTCP連線發出的keepalive包。我測試中使用SQL server configuration manager設定了native client keepalive7秒。從上面圖也印證了伺服器端的TCP連線和客戶端的TCP連線各自傳送自己的keepalive包,相互不影響。

   

注意, SQL Server native clientkeepalive值存放在下面登錄檔裡面:

   

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 managedSQLclient,所以上面針對native client的設定對SQLclient無效。SQL server management studio  使用了 hard-coded30秒值,無法修改。

   

   

問題2. ODBCSQL OLEDBSQL native clientSQLClientTCP keepalive預設時間都是多少?在哪裡可以設定?

   

[]預設值都是30秒。

   

可以修改如下注冊表值來設定ODBC SQL OLEDBkeepalive值:

   

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 serverTCP連線(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伺服器的TCPkeepalive設定時間很短,小於DisconnectDampInterval -5時間值,那麼SQL server會先於作業系統得知連線斷線的狀態而採取相應的動作。實際中不建議過短的keepalive值。

   

問題4DisconnectDampInterval在哪裡可以修改?有沒有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的網路協議TCPkeep 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物件做更多的處理,請參看有關程式設計文件,此處不多描述。

   

相關文章