ADODB nested recordset TCP 1433 TIME_WAIT flood issue

今天在 troubleshooting 客戶主機上問題的時候,不經意從 Tcpview 發現某個系統在使用者使用的時候會對 SQL Server 產生大量 TIME_WAIT session,這對於自我要求的系統開發者來說,是個不能視而不見的瑕疵,於是開始進行 debug...

經過兩個小時分析後,發現了一個狀況(先看以下程式碼):

'// 預設 Conn 已經建立

'// 第一個 adCmdStoreProc
Dim rs1 : Set rs1 = Server.CreateObject("ADODB.Recordset")
Dim cmd1 : Set cmd1 = Server.CreateObject("ADODB.Command")

cmd1.ActiveConnection = Conn
cmd1.CommandText = "usp_SPNAME1"
cmd1.CommandType = adCmdStoredProc
cmd1.Parameters.Refresh

cmd1.Parameters("@Param1").Value = 1

Set rs1 = cmd1.Execute

'// 第二個 adCmdStoreProc
Dim rs2 : Set rs2 = Server.CreateObject("ADODB.Recordset")
Dim cmd2 : Set cmd2 = Server.CreateObject("ADODB.Command")

cmd2.ActiveConnection = Conn
cmd2.CommandText = "usp_SPNAME2"
cmd2.CommandType = adCmdStoredProc
cmd2.Parameters.Refresh

cmd2.Parameters("@Param2").Value = 2

Do While NOT rs1.EOF

	cmd2.Execute

	rs1.MoveNext
Loop

這是一個 loop 但是為巢狀查詢,依據 rs1 取得的 recordset 執行 cmd2 的查詢,以上程式碼看起來沒有問題,執行起來也不會發生錯誤,但是會產生等同於 recordset count 數量的 TCP TIME_WAIT session,關鍵在於 Conn (Connection) 被拿來用了兩次 (cmd1.ActiveConnection & cmd2.ActiveConnection),即便在第二次設定給 cmd2前 Set cmd1 = Nothing 也沒用,一樣會造成 cmd2 在作動時產生 TIME_WAIT  。 (CommandType = adCmdStoredProc 時在設定Parameters 值的時候就會產生 TIME_WAIT,CommandType = adCmdText 時在 Execute 時會產生 TIME_WAIT)

而這個 issue 的解決辦法是:

每個 ActiveConnection 都給他一個獨立的 Connection object

延伸閱讀:

Nested RecordSet and the port/socket in TIME_WAIT problem by example.

分類: Web technology,標籤: 。這篇內容的永久連結