有关SQL server connection Keep Alive 的FAQ(3)
這個(gè)是SQL Server Keep Alive FAQ文章的最后一篇。
?
問(wèn)題1:為什么我在客戶端設(shè)置了KeepAlive值,但是我使用SQL server management studio 測(cè)試的時(shí)候,該值總是不起作用??
?
[答]目前市場(chǎng)上主流的數(shù)據(jù)庫(kù)訪問(wèn)技術(shù)有ODBC,OLEDB,SQL native client 和 SQLclient。其中SQLclient是.NET里面使用的托管provider。目前SQL Server configuration manager里面提供的keepalive設(shè)置是針對(duì)SQL native client 的:?
?
也就是說(shuō), 該值只對(duì)使用SQL Native Client 來(lái)訪問(wèn)數(shù)據(jù)庫(kù)的程序有效。SQLcmd.exe是使用SQL native client來(lái)訪問(wèn)SQL server的一個(gè)命令行工具,所以您可以使用SQLCmd來(lái)測(cè)試上面的keepalive值。注意修改keepalive值后,你需要退出SQLcmd重新運(yùn)行它才能使用新值。我在幾組機(jī)器測(cè)試了幾組不同的keepalive值,SQLcmd程序的TCP連接都很好按照設(shè)置的值發(fā)出keepalive網(wǎng)絡(luò)包。注意你需要使用TCP連接服務(wù)器來(lái)測(cè)試。 我使用下面的連接串以保證使用TCP 連接:
?
SQLcmd -E -STCP:mycomputer\SQL2012,55890
(機(jī)器名:mycomputer,實(shí)例名:SQL2012,端口號(hào) 55890)
?
我使用network monitor 3.4捕獲keepalive包如下圖:?
?
?上圖中深藍(lán)高亮的是我挑出的由服務(wù)器TCP連接發(fā)給SQLcmd的keepalive包,每個(gè)包間隔30秒(時(shí)間間隔可以看time offset前后相減即可)。而上圖間隔7秒的是SQLcmd的TCP連接發(fā)出的keepalive包。我測(cè)試中使用SQL server configuration manager設(shè)置了native client 的keepalive為7秒。從上面圖也印證了服務(wù)器端的TCP連接和客戶端的TCP連接各自發(fā)送自己的keepalive包,相互不影響。
?
注意, SQL Server native client的keepalive值存放在下面注冊(cè)表里面:
?
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,所以上面針對(duì)native client的設(shè)置對(duì)SQLclient無(wú)效。SQL server management studio? 使用了 hard-coded的30秒值,無(wú)法修改。
?
?
問(wèn)題2. ODBC,SQL OLEDB,SQL native client和SQLClient的TCP keepalive缺省時(shí)間都是多少?在哪里可以設(shè)置?
?
[答]缺省值都是30秒。
?
可以修改如下注冊(cè)表值來(lái)設(shè)置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的機(jī)器,在上面運(yùn)行32位的ODBC/SQL OLEDB程序,則需要修改如下注冊(cè)表:
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\MSSQLServer\Client\SuperSocketNetLib\TCP
?
對(duì)于SQLserver native client 和SQL server 的keep alive設(shè)置,可以在SQL server configuration manager 修改,具體請(qǐng)參考請(qǐng)參考FAQ (1)和FAQ (2)或問(wèn)題1。
?
對(duì)于SQL client,需要在使用sqlclient的應(yīng)用程序里面使用代碼設(shè)置。
?
問(wèn)題3:服務(wù)器端如果網(wǎng)線被拔掉,這對(duì)于那些已經(jīng)存在的TCP連接會(huì)有什么影響?SQL server會(huì)馬上關(guān)閉連接么?如果拔掉網(wǎng)線然后馬上又插回去呢?
?
[答]這樣問(wèn)題復(fù)雜一些。當(dāng)網(wǎng)線拔掉的時(shí)候,網(wǎng)卡首先獲知該事件。Windows 2003以及后面的操作系統(tǒng)都實(shí)現(xiàn)了media sense 媒體感知功能。操作系統(tǒng)收到網(wǎng)卡發(fā)來(lái)的media sense 的斷線(disconnect)事件后,如果在DisconnectDampInterval(一般是5-10秒)的時(shí)間內(nèi),網(wǎng)線連接還沒(méi)有恢復(fù),那么就會(huì)發(fā)送信息給偵聽(tīng)該網(wǎng)卡IP的連接。那么所有監(jiān)聽(tīng)該IP的上層應(yīng)用程序如SQL server 就會(huì)得到disconnect的事件,然后就會(huì)進(jìn)行相應(yīng)的動(dòng)作如kill connection, rollback事務(wù)等。
?
具體點(diǎn)來(lái)說(shuō),SQL server 的網(wǎng)絡(luò)IO是通過(guò)IOCP (IOCompletionPort)實(shí)現(xiàn)的。 SQL server在后臺(tái)有幾個(gè)專門的線程偵聽(tīng)該端口。這些線程調(diào)用GetQueuedCompletionStatus()函數(shù)得到網(wǎng)絡(luò)數(shù)據(jù)狀態(tài),然后調(diào)用相應(yīng)的callback函數(shù)(如ReadHandler函數(shù))來(lái)做具體的數(shù)據(jù)處理。當(dāng)網(wǎng)線斷的時(shí)候,操作系統(tǒng)過(guò)了DisconnectDampInterval時(shí)間后,GetQueuedCompletionStatus函數(shù)就會(huì)得到disconnect信息,而callback函數(shù)readhandler就被調(diào)用來(lái)讀取數(shù)據(jù)但實(shí)際上是讀到disconnect的網(wǎng)絡(luò)斷事件。SQL server 得知該disconnect事件后,就生成一個(gè)task,該task就是做kill session的任務(wù),把事務(wù)會(huì)滾,把連接(connection)關(guān)掉。
?
所以說(shuō),如果你在很快的時(shí)間內(nèi)(幾秒),拔掉網(wǎng)線馬上插回來(lái),那么SQL server的TCP連接(connection)會(huì)保持不會(huì)被關(guān)閉。
?
你或許會(huì)問(wèn),media sense功能如何disable呢?具體可以參考如下命令:
?
netsh interface ipv4 set global dhcpmediasense=disabled
netsh interface ipv6 set global dhcpmediasense=disabled
?
如何察看這些設(shè)置的命令如下:
netsh interface ipv4 show global
netsh interface ipv6 show global
?
回到keepalive。 如果SQL Server服務(wù)器的TCP的keepalive設(shè)置時(shí)間很短,小于DisconnectDampInterval -5時(shí)間值,那么SQL server會(huì)先于操作系統(tǒng)得知連接斷線的狀態(tài)而采取相應(yīng)的動(dòng)作。實(shí)際中不建議過(guò)短的keepalive值。
?
問(wèn)題4:DisconnectDampInterval在哪里可以修改?有沒(méi)有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平臺(tái)上該定義依然有效,不過(guò),缺省值是5~10秒。可以修改如下注冊(cè)表修改該值:
?
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Tcpip\Parameters
DisconnectDampInterval
ConnectDampInterval
?
這兩個(gè)參數(shù)有最大最小值限制, Min = 5 seconds,Max = 10 seconds。
?
問(wèn)題5:如下圖SQL server的網(wǎng)絡(luò)協(xié)議TCP的屬性頁(yè)為何沒(méi)有keep alive interval選項(xiàng)?
?
[答]SQL server的網(wǎng)絡(luò)協(xié)議TCP的keep alive interval是不能修改的,注冊(cè)表也無(wú)法修改. SQL server源代碼里面寫定了1秒的時(shí)間間隔.
?
問(wèn)題6:我的應(yīng)用程序如何才能捕獲keepalive機(jī)制偵測(cè)到的網(wǎng)絡(luò)問(wèn)題?
[答] 對(duì)于用戶程序,你需要調(diào)用ExecuteSQL或類似的方法才能獲知connection的真實(shí)狀態(tài). 如下面例子所示:
?
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);
??? };
????????????????????????????????
}
?
我做了小測(cè)試步驟如下:
?
1)?? 想辦法阻塞 “select * from t”使得它不返回結(jié)果而處于等待狀態(tài)。
2)?? 然后拔掉服務(wù)器網(wǎng)絡(luò)線。
3)?? 然后過(guò)一會(huì),我的catch語(yǔ)句捕獲了錯(cuò)誤?
?
你其實(shí)可以對(duì)ex對(duì)象做更多的處理,請(qǐng)參看有關(guān)編程文檔,此處不多描述。?
總結(jié)
以上是生活随笔為你收集整理的有关SQL server connection Keep Alive 的FAQ(3)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 推荐些在线小制作小工具
- 下一篇: 快速深入一门语言的几个问题 - Shel