从SQL 2000迁移到SQL 2008后,VB6 ADODB后续SELECT查询超时

时间:2012-04-23 08:42:08

标签: sql-server vb6 timeout migration adodb

在将数据库移动到另一台服务器后执行多个SELECT时,我遇到了超时问题,在文件(VB6应用程序)中,我的任务是修补。在古老的环境中,事情完美无瑕,新的包含旧桌子的副本。

注意! 数据库是从头开始构建 (也就是说,DBA运行了许多CREATE TABLE + INSERT脚本来创建碳副本表然后用旧数据填充它们。

这是错误来源:

// "conn" is being initialized outside the function
Public Function PerformOperation(ByRef conn as ADODB.Connection, query as string) as Boolean
  Dim rs as ADODB.Recordset
  //This below is the timeout source
  rs.Open conn, query, adOpenStatic, adLockReadOnly

  If Not (rs.EOF or rs.BOF) Then
    rs.MoveFirst
    //assign data to many variables
  End If

ExitPoint:
  If Not (rs Is Nothing) Then
    If (rs.State = adStateOpen) Then rs.Close
    Set rs = Nothing
  End If   

  Exit Function

Error:
  MsgBox "Blah blah"
  Resume ExitPoint
  Resume 0

End Function

像这样调用函数

conn = New ADODB.Connection
conn.ConnectionString = "..."
conn.Open

For i = 1 To RowCount //reading data from a grid component (data is correct!)
  //very long select here... kept short
  query = "SELECT something FROM somewhere WHERE <manyFields> = <manyValues>" 
  If PerformOperation(conn, query) = True Then
    //UPDATE another table based on the SELECT data
    // NOTE: this occurs on a DIFFERENT, INDEPENDENT ADODB.Connection object
  End If
Next i

第一次调用PerformOperation时,无论我设置CommandTimeout多长时间,它都会很快完成,第二次会超时。如果循环“循环”一次,它也可以正常工作。

这里的大问题是,我必须尝试的是生产环境,所以我需要格外小心。我也没有非常深入的DBA知识......只是一个非常古老的软件,最终将被移植到.NET,但需要同时处理......

如何检查和/或解决此问题? 必须适用于For周期的任何长度

非常感谢任何建议(一如既往,如果我错过任何必要的细节指出它,我会提供它,如果我可以)。

编辑#1 我扩展了第一个和第二个代码块,以提供有关正在发生的事情的更深入细节。注释已更改,以尝试修复突出显示(单引号搞乱着色)。

编辑#2 在连接字符串中启用多个活动结果集(MARS)也无济于事。

2 个答案:

答案 0 :(得分:1)

我有点惊讶它迄今为止运作良好。

您必须关闭打开的记录集,否则您将为每个运行的查询使用一个数据库连接。数据库将在一段时间后回收未使用的连接,但是如果过多地使用过多的连接,则会达到每个用户的连接数限制,并且数据库将拒绝任何更多的连接。

它与旧数据库一起工作的原因可能是因为它根据需要创建了新连接。这在以后的版本中已经更改,您必须更改设置以允许更老,更浪费资源的行为。但是,更改该设置不是解决问题的好方法。

关闭记录集并在不再需要时删除引用。这将释放连接,以便您可以将其用于另一个查询:

Public Function PerformOperation(ByRef conn as ADODB.Connection, query as string) as Boolean
  Dim rs as ADODB.Recordset
  'This below is the timeout source
  rs.Open conn, query, adOpenStatic, adLockReadOnly

  rs.Close()
  Set rs = Nothing

  ' [cut]: PerformOperation returns true if SELECT returns something
End Function

编辑:

还有其他开放状态而不是adStateOpen,您应该检查关闭状态:

If (rs.State <> adStateClosed) Then rs.Close

答案 1 :(得分:0)

问题已解决,编辑此行:

If PerformOperation(conn, query) = True Then
像这样

If PerformOperation(connOther, query) = True Then

基本上,方法调用已移动到自己的连接,声明与另一个完全相同。现在它可以工作,虽然我不知道为什么:这是一些疯狂编辑的结果,试图修补。