防止
      
      
        ADO
      
      
        连接
      
      
        SQL Server
      
      
        时的隐式连接
      
      
                
         
      
    
    | 
             Report Date : 2002/9  | 
          
             
              
                
                  Prepared by
                
              
              
                
                  :
                
              
              
                
                  
                         
                  
                
              
              
                郑
              
              
                
                              
                
              
              
                昀
              
              
                  | 
        
| 
             Article last modified on 2002-9  | 
        |
| 
             
              
                The information in this article applies to: 
         
                 
              
                ü
                
                           
                
              
              
                Microsoft SQL Server 2000,7.0 
         
                 
              
                ü
                
                           
                
              
              
                Microsoft ADO 2.5
              
              
                
                    | 
        |
      
        问题陈述
      
      
        
          : 
      
          
           
        
      
    
    
      
        
          数据库服务器:
        
        
          Microsoft SQL Server 2000
        
        
          以及
        
        
          7.0
        
        
          ;
        
        
          
      
        
          数据库服务器补丁:
        
        
          Microsoft SQL Server 2000 ServicePack1
        
        
          ;
        
        
          
      
        
          ADO
        
        
          名称:
        
        
          Microsoft Data Access - ActiveX Data Objects 2.5 Type Library 
      
          
      
        
          ADO
        
        
          版本:
        
        
          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: LPC 
         
                 
              
                set quoted_identifier on 
         
                 
              
                set implicit_transactions off 
         
                 
              
                set cursor_close_on_commit off 
         
                 
              
                set ansi_warnings on 
         
                 
              
                set ansi_padding on 
         
                 
              
                set ansi_nulls on 
         
                 
              
                set concat_null_yields_null on 
         
                 
              
                set language 
              
              
                简体中文
              
              
                 
              
                set dateformat ymd 
         
                 
              
                set datefirst 7 
         
                  | 
        
| 
             
              
                SQL:Stm tStarting 
         
                  | 
          
             
              
                Select * from users 
         
                  | 
        
| 
             
              
                Audit Login 
         
                 
              
                (
              
              
                第
              
              
                2
              
              
                次连接
              
              
                ) 
         
                  | 
          
             
              
                -- network protocol: LPC 
         
                 
              
                set quoted_identifier on 
         
                 
              
                set implicit_transactions off…
              
              
                略
              
              
                  | 
        
| 
             
              
                SQL:Stm tStarting 
         
                  | 
          
             
              
                Select * from users 
         
                  | 
        
| 
             
              
                Audit Login 
         
                 
              
                (
              
              
                第
              
              
                3
              
              
                次连接
              
              
                ) 
         
                  | 
          
             
              
                -- network protocol: LPC 
         
                 
              
                set quoted_identifier on 
         
                 
              
                set 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 = adOpenStatic
      
        rs.ActiveConnection = cn
        
        rs.Open "select * from orders"
      
    
      
        
          
            rs.CursorType = adOpenStatic
          
        
      
      
        
      
      
        rs2.ActiveConnection = cn
        
        rs2.Open "select * from orders"
      
    
看来,确实如微软所说的,只有接收默认的记录集时才会发生隐式连接。如果设置 ADO.Recordset 为其它类型,如静态集,就不会发生这个问题。
      
        当然,默认的记录集的属性
      
      
        forward-only
      
      
        、
      
      
        read-only
      
      
        情况执行速度最快。
      
      
        
      
        
            
      
          
      
        
          Writen by 
        
        
          
            
              zhengyun@tomosoft.com
            
          
        
        
      
        
            
      
          
      
        
          本文档所包含的信息代表了在发布之日,
        
        
          ZhengYun 
        
        
          对所讨论问题的当前看法,
        
        
          Zhengyun 
        
        
          不保证所给信息在发布之日以后的准确性。
        
        
          
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=12694

