問題陳述:資料庫伺服器:Microsoft SQL Server 2000以及7.0;資料庫伺服器補丁:Microsoft SQL Server 2000 ServicePack1;ADO名稱:Microsoft Data Access - ActiveX Data Objects 2.5 Type LibraryADO版本:2.61.7326.0 執行下面的VB代碼時,我們的開發人員產生了疑問: cnn.Open "Provider=SQLOLEDB.1;Persist Security Info=False;User ID=sa;Initial Catalog=freemail;Data Source=svr;ConnectionTimeout=10", "", "", -1
sql = "select * from users" Set rs = cnn.Execute(sql)
Set rs2 = cnn.Execute(sql)
Set rs3 = cnn.Execute(sql)
執行這段代碼時,在SQL Server Profiler中看到,每個sql語句執行之前都會有一個Audit Login事件。而Audit Login事件的解釋是:“收集自跟蹤啟動後發生的所有新的串連事件,例如用戶端請求串連到運行 Microsoft SQL Server 執行個體的伺服器”。也就是說,用Connection對象串連SQL Server之後,每次執行sql語句時仍然會重建立立一次串連,即使用的是同一個Connection?!建立串連的事件探查記錄(按時間順序)為:
EventClass |
Text Data |
TraceStart |
|
Audit Login(第一次串連) |
-- network protocol: LPCset quoted_identifier onset implicit_transactions offset cursor_close_on_commit offset ansi_warnings onset ansi_padding onset ansi_nulls onset concat_null_yields_null onset language 簡體中文set dateformat ymdset datefirst 7 |
SQL:Stm tStarting |
Select * from users |
Audit Login(第2次串連) |
-- network protocol: LPCset quoted_identifier onset implicit_transactions off…略 |
SQL:Stm tStarting |
Select * from users |
Audit Login(第3次串連) |
-- network protocol: LPCset quoted_identifier onset implicit_transactions off…略 |
SQL:Stm tStarting |
Select * from users |
Audit Logout |
|
Audit Logout |
|
Audit Logout |
|
TraceStop |
|
而如果每句cnn.Execute後面加上rs.close(),則每個execute之前不會有Audit Login事件,而是連續的3個SQL:StmtStarting事件。這樣頻繁建立物理串連,是否會影響效能?照例說應該重用同一個串連才對呀?Cause:這種情況叫做隱式登入。當set一個ADO.Recordset對象接收ADO.Connection.Execute返回的記錄集時,就會出現隱式登入,再次和資料庫伺服器建立一次物理串連,而且這個串連還沒有辦法重用,也不能池化。這個的原因是:Because the SQL Server OLE DB provider doesn't permit more than one set of results to be pending on a connection where the results are being returned by means of a forward-only, read-only (default-resultset) cursor, the provider needs to create an additional SQL Server connection to execute a second command on the connection. The provider will only do this implicitly if the Data Source property DBPROP_MULTIPLECONNECTIONS is set to VARIANT_TRUE. 可以參考微軟的KB文檔:http://support.microsoft.com/default.aspx?scid=kb;EN-GB;q271128&GSSNB=1《PRB: Implicit Connections Created by the SQL Server OLE DB Provider (SQLOLEDB) Are Not Pooled》
【不會重複建立資料庫連接的代碼片斷】:
通過改變ADO.Recordset的屬性避免隱式登入 Dim cn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim rs2 As New ADODB.Recordset
cn.open ..........
rs.CursorType = adOpenStaticrs.ActiveConnection = cn
rs.Open "select * from orders"
rs.CursorType = adOpenStatic
rs2.ActiveConnection = cn
rs2.Open "select * from orders"看來,確實如微軟所說的,只有接收預設的記錄集時才會發生隱式串連。如果設定ADO.Recordset為其它類型,如靜態集,就不會發生這個問題。當然,預設的記錄集的屬性forward-only、read-only情況執行速度最快。