0

在将数据库移动到不同的服务器后执行多个 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)也没有帮助。

4

2 回答 2

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
于 2012-04-23T08:57:52.507 回答
0

问题已解决编辑此行:

If PerformOperation(conn, query) = True Then

像这样

If PerformOperation(connOther, query) = True Then

基本上,方法调用已移至其自己的连接,声明与另一个完全一样。现在它起作用了,虽然我真的不知道为什么:这是一些疯狂编辑试图修补的结果。

于 2012-06-06T12:34:48.297 回答