Perl умирает с: "Использование: DBD::Pg::db::DESTROY(dbh) во время глобального уничтожения"

Стабильное веб-приложение, однопоточное / процессное Perl-приложение, работающее в рабочей среде, начало периодически выдавать эту ошибку и только при большой нагрузке на систему. Мы не можем определить причину.

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

Кто-нибудь может предложить какое-либо объяснение этой ошибки? Похоже, что он выбрасывается из Pg.sx, когда DESTROY вызывается без аргумента (self?), Когда Perl очищается перед выключением. (Я вижу это сообщение в более старом исходном коде через Google, но не в нашей версии.) Наша среда:

  • ОС: FreeBSD 8.3-STABLE
  • Perl v5.14.2
  • DBD:: Pg v2.19.3
  • PostgreSQL: v9.2.3

2 ответа

Вот выстрел в темноте.

Дескрипторы базы данных DBI обычно уничтожаются, как и любой другой объект - когда ничто не ссылается на них. Однако, вещи могут препятствовать естественному разрушению ручки:

  • Ручка представляет собой глобальный пакет
  • Дескриптор является частью циклической ссылки, которую 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 перед запуском вашего скрипта, и он будет регистрировать каждый раз, когда дескриптор создается или уничтожается.

В моем случае это начало происходить после обновления сервера, поэтому, похоже, это ошибка, связанная с версией PostgreSql/Perl/DBD.

Эта ошибка внезапно начала появляться во всех сценариях, где я не уничтожаю дескриптор базы данных. Добавление $dbx->disconnect() решил это.

Обновление: этот обходной путь исправил ошибки только в некоторых моих скриптах. В других случаях ошибка сохраняется и при явном уничтожении дескриптора базы данных.

Другие вопросы по тегам