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()
решил это.
Обновление: этот обходной путь исправил ошибки только в некоторых моих скриптах. В других случаях ошибка сохраняется и при явном уничтожении дескриптора базы данных.