Perl 死于: "Usage: DBD::Pg::db::DESTROY(dbh) during global destruction"



一个稳定的、基于web的、单线程/进程的、在生产中运行的perl应用程序开始间歇性地抛出这个错误,并且只有在系统负载很重的情况下才会出现。我们无法确定根本原因。

Usage: DBD::Pg::db::DESTROY(dbh) during global destruction

有人能解释一下这个错误吗?当Perl在关闭前进行清理时,在没有参数(self?(的情况下调用DESTROY时,它似乎是从Pg.sx抛出的。(我通过谷歌在旧的源代码中看到了这条消息,但在我们的版本中没有。(我们的环境:

  • 操作系统:FreeBSD 8.3-STABLE
  • Perl v5.14.2
  • DBD::Pg v2.19.3
  • PostgreSQL:v9.2.3

这是一张黑暗中的照片。

DBI数据库句柄通常像任何其他对象一样被销毁——当没有任何对象引用它们时。然而,事物可以防止句柄被自然破坏:

  • 句柄是一个包全局
  • 句柄是Perl无法自动释放的循环引用的一部分

当这种情况发生时,对象作为"全局销毁"的一部分被销毁,基本上只是对所有内容进行解锁,并以随机顺序调用DESTROY。这可能是导致您出现虚假错误的原因。

首先,您可以尝试在脚本开始和结束时枚举DB句柄,并查看到结束时是否有任何句柄仍在使用中。请参阅以下代码片段:

sub show_child_handles {
    my ($h, $level) = @_;
    printf "%sh %s %sn", $h->{Type}, "t" x $level, $h;
    show_child_handles($_, $level + 1)
        for (grep { defined } @{$h->{ChildHandles}});
}
my %drivers = DBI->installed_drivers();
show_child_handles($_, 0) for (values %drivers);

如果您不确定对象仍在使用的原因,可以使用Devel::Cycle对一些大数据结构进行查找。

您可能还发现DBI的跟踪功能非常有用。在运行脚本之前导出DBI_TRACE=2,它会在每次创建或销毁句柄时进行日志记录。

在我的案例中,它是在升级服务器后开始发生的,因此它似乎是PostgreSql/Perl/DBD版本特定的错误。

这个错误突然开始出现在我没有明确销毁数据库句柄的所有脚本中。添加$dbx->disconnect()解决了这个问题。

更新:这个解决方法只修复了我的一些脚本中的错误。在其他情况下,当显式销毁数据库句柄时,错误也会持续存在。

相关内容

  • 没有找到相关文章

最新更新