在将数据库移动到另一台服务器后执行多个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)也无济于事。
答案 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
基本上,方法调用已移动到自己的连接,声明与另一个完全相同。现在它可以工作,虽然我不知道为什么:这是一些疯狂编辑的结果,试图修补。