3

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

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

任何人都可以对这个错误提供任何解释吗?当 Perl 在关闭之前进行清理时,在没有参数(self?)的情况下调用 DESTROY 时,它似乎从 Pg.sx 中抛出。(我通过 google 在较旧的源代码中看到该消息,但在我们的版本中没有。)我们的环境:

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

2 回答 2

4

这是在黑暗中拍摄的。

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

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

发生这种情况时,对象将作为“全局销毁”的一部分被销毁,这基本上只是取消定义所有内容并DESTROY实际上调用随机顺序。这可能是导致您的虚假错误的原因。

首先,您可以尝试在脚本的开头和结尾枚举您的数据库句柄,看看最后是否仍在使用。请参阅此代码段

sub show_child_handles {
    my ($h, $level) = @_;
    printf "%sh %s %s\n", $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,每次创建或销毁句柄时都会记录下来。

于 2013-02-22T22:12:52.130 回答
3

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

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

更新:此解决方法仅修复了我的某些脚本中的错误。在其他情况下,当显式破坏数据库句柄时,错误也会持续存在。

于 2015-03-11T08:26:53.343 回答