代码之家  ›  专栏  ›  技术社区  ›  GeneQ

为什么Apache抱怨我的mod_perl程序“disconnect使1个活动语句句柄失效”?

  •  8
  • GeneQ  · 技术社区  · 16 年前

    断开使1失效激活 语句句柄(或破坏) 语句句柄或调用完成于 断开之前)

    以下从MySQL中获取数据的代码成功执行,但会导致Apache在其错误日志中生成上述消息:

    my $driver   = "mysql";
    my $server   = "localhost:3306";
    my $database = "test";
    my $url      = "DBI:$driver:$database:$server";
    my $user     = "apache";
    my $password = "";
    
    #Connect to database
    my $db_handle = DBI->connect( $url, $user, $password ) 
        or die $DBI::errstr;
    
    #SQL query to execute
    my $sql = "SELECT * FROM tests WHERE id=?";
    
    #Prepare SQL query
    my $statement = $db_handle->prepare($sql)
            or die "Couldn't prepare query '$sql': $DBI::errstr\n";
    
    #Execute SQL Query
    $statement->execute($idFromSomewhere)
        or die "Couldn't execute query '$sql': $DBI::errstr\n";
    
    #Get query results as hash
    my $results = $statement->fetchall_hashref('id');
    
    $db_handle->disconnect();
    
    • 会有什么可怕的后果吗 忽略上述错误/警告? 代码已经运行了一周了 没有任何不良影响。

    • 密码有什么问题吗 或者这只是一个无害的警告?

    编辑

    代码通过mod_perl执行。

    3 回复  |  直到 16 年前
        1
  •  12
  •   Paul Tomblin    11 年前

    你应该打电话 $statement->finish(); 之前 $db_handle->disconnnect(); .

    通常你不需要打电话 finish 除非你没有得到所有的行。如果在循环中使用 fetchrow_array ,除非中止循环,否则不会在结束时调用finish。

    我不知道为什么mysql驱动程序在 fetchall_hashref . 手册建议您的查询可能由于以下错误而中止:

    如果发生错误,则返回fetchall_hashref 返回到目前为止获取的数据, 可能没有。你应该查一下 $sth->之后出错(或使用 raiseError属性)发现 数据已完成或被截断 因为一个错误。

        2
  •  3
  •   wds    16 年前

    这是由于句柄仍处于活动状态。通常情况下,它应该自动关闭,但您似乎没有从中获取所有数据。从 perldoc 关于DBI:

    当所有的数据都被提取 从select语句中,驱动程序 应自动调用finish for 你。所以你通常不需要 明确地调用它,除非 知道你没有把所有的 语句句柄中的数据。最多的 常见的例子是当你只想 获取一行,但在这种情况下, selectrow方法通常更好 不管怎样。在之后添加要完成的调用 每个获取循环都是一个常见的错误, 别这么做,它能掩饰真实 未捕获获取错误等问题。

        3
  •  0
  •   veeTrain M A Hossain Tonu    12 年前

    虽然可能不是你得到这个的原因 警告 (这就是 manual 声称是的),我在稍微不同的情况下经历了同样的警告,我想在这里提出建议,而不是打开我自己的问题。

    如果您执行一个查询来获取一些行,那么您可能会发现自己处于这个场景中——但目的只是为了知道是否有匹配的行。在我的情况下,如果找到匹配项,我们将更新行,否则将插入。

    因为没有对找到的行进行任何处理,所以我认为这构成了一个场景,在这个场景中遵循警告的引导是适当的。因此,我打电话给 finish() 在断开连接之前,在我的选择处理程序上。

    免责声明 :作为DBI的新手,有一种更好的方法。我会用的 ->do() 除了 the documentation 指出它应该 重复执行时使用——也不鼓励 SELECT 出于某种原因的声明!

    下面是一些Perl伪代码,显示了我登录的内容:

    $selectHandler = $dbh->prepare($queryString) or die "Cannot prepare: ".$dbh->errstr;
    #Loop through a list of keys to check existence {
        $selectHandler.execute($uniqueID);
        $found = 0;
        $found = $selectHandler->fetch();
        if (!$found) {
            # Do an insert of $uniqueID
        } else {
            # Do an update of $uniqueID
        }
    #}
    # Having not done anything with the selectHandler's result (when rows were 
    # found) close it now that the loop is complete
    $selectHandler->finish(); # we don't need you any more select handler!
    $dbh->disconnect or warn "Disconnection error: $DBI::errstr\n";
    

    希望这能帮助其他人,如果我误导了任何人,请随时纠正我的方法。