我们有一个文件,每晚运行,已经工作了几个月没有问题。突然间,它正在抛出查询超时错误。快速跟踪显示每次在任何辅助查询(更新)上都失败。
代码执行的非常通用的摘要:
strSQL = "EXEC usp_GET_listofRecords"
rsRun(recSet, strSQL)
Do While Not recSet.EOF
If recSet("condition") = 0 Then
strSQL2 = "UPDATE t_table SET status=0 WHERE id=" & recSet("id")
rsRun2(recSet2, strSQL2)
rsClose(recSet2)
ElseIf recSet("condition") = 1 Then
strSQL2 = "UPDATE t_table SET status=1 WHERE id=" & recSet("id")
rsRun2(recSet2, strSQL2)
rsClose(recSet2)
ElseIf recSet("condition") = 3 Then
strSQL2 = "UPDATE t_table SET status=3 WHERE id=" & recSet("id")
rsRun2(recSet2, strSQL2)
rsClose(recSet2)
End if
recSet.MoveNext
Loop
rsClose(recSet)
这已经好几个月和几个月一直正常工作,现在每次碰到任何更新都会失败。
编辑:我知道更新命令是有效的,因为执行以下工作没有问题:
strSQL = "EXEC usp_GET_listofRecords"
rsRun(recSet, strSQL)
Do While Not recSet.EOF
If recSet("condition") = 0 Then
strSQL2 = strSQL2 & "UPDATE t_table SET status=0 WHERE id=" & recSet("id") & "; "
ElseIf recSet("condition") = 1 Then
strSQL2 = strSQL2 & = "UPDATE t_table SET status=1 WHERE id=" & recSet("id") & "; "
ElseIf recSet("condition") = 3 Then
strSQL2 = strSQL2 & = "UPDATE t_table SET status=3 WHERE id=" & recSet("id") & "; "
End if
recSet.MoveNext
Loop
rsClose(recSet)
rsRun recSet, strSQL2
rsClose(recSet)
编辑2:包括所谓的函数:
Function rsRun(recSet, strSQL)
Call OpenDB()
Set recSet = Server.CreateObject("ADODB.Recordset")
recSet.Open strSQL, dbConn
End Function
Function rsRun2(recSet2, strSQL2)
Call OpenDB()
Set recSet2 = Server.CreateObject("ADODB.Recordset")
recSet2.Open strSQL2, dbConn
End Function
Function OpenDB()
Set dbConn = Server.CreateObject("ADODB.Connection")
dbConn.ConnectionTimeout = 30
dbConn.CommandTimeout = 120
dbConn.Open strConnectionString, strUserName, strPassword
End Function
这里似乎有一些问题,但我会首先了解超时的主要原因。当我看到一个名为rsRun2
的函数的调用时,我就怀疑了。
请注意,在您对rsRun
和rsRun2
的定义中,您可以调用OpenDB
并每次打开一个新连接。调用OpenDB
替换旧的dbConn
与新连接,而不关闭旧连接,如果已经打开。这意味着,对于循环中的每次迭代,您都要打开新的数据库连接,因此随着数据大小的增加,您实际上会泄漏*越来越多的连接,直到这些连接请求开始超时,因为数据库服务器赢了“不再接受了。
您的重写版本工作的事实进一步证明了这一点,因为您实际上是通过批量处理所有要在两个连接上的单个调用中运行的命令来解决问题。
请注意,在同一连接上执行多个命令是完全可以的,因此如果您只使用一个数据库,请使用一个连接,不要再打开。除了一开始,从代码中的任何地方删除对OpenDB
的调用,这样您就可以完全控制自己正在做的事情。
现在提供一些额外的建议。正如Ansgar Wiechers所说,您的SQL可能容易受到SQL注入攻击,特别是如果这是您在其他地方编写数据库代码的方式。您应该研究一下如何使用ADO和参数化查询,以提高代码的安全性。
*理论上,这些旧对象最终会被VBScript垃圾收集,但不能保证这很快就会发生,或者相应的连接被正确关闭。