在Do While Not.EOF超时内更新查询

时间:2017-12-20 12:58:54

标签: sql vbscript asp-classic

我们有一个每晚运行的文件,该文件已经运行数月而没有问题。突然间,它正在抛出查询超时错误。快速跟踪显示每次在任何辅助查询(更新)上都失败。

代码执行的非常通用的摘要:

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

1 个答案:

答案 0 :(得分:0)

这里似乎有一些问题,但我会首先了解超时的主要原因。当我看到一个名为rsRun2的函数的调用时,我就怀疑了。

请注意,在rsRunrsRun2的定义中,您拨打OpenDB并每次都打开一个新连接 。调用OpenDB 将旧dbConn替换为新连接,而不关闭旧连接(如果已经打开)。这意味着,对于循环中的每次迭代,您都要打开新的数据库连接,因此随着数据大小的增加,您实际上会泄漏*越来越多的连接,直到这些连接请求开始超时,因为数据库服务器赢了“接受了。

您的重写版本的工作原理进一步证明了这一点,因为您实际上是通过批量处理所有要在两个连接上的单个调用中运行的命令来解决问题。

请注意,在同一连接上执行多个命令是完全可以的,因此如果您只使用一个数据库,请使用一个连接,不要再打开。除了一开始就从代码中的任何地方删除对OpenDB的调用,这样您就可以完全控制自己正在做的事情。

现在提供一些额外的建议。正如Ansgar Wiechers所说,您的SQL可能容易受到SQL注入攻击,特别是如果这是您在其他地方编写数据库代码的方式。您应该研究一下如何使用ADO和参数化查询,以提高代码的安全性。

*理论上,这些旧对象最终会被VBScript垃圾收集,但不能保证这很快就会发生,或者相应的连接被正确关闭。