Создание новых дескрипторов базы данных с помощью mod_perl
При стресс-тестировании mod_perl я столкнулся с проблемой, что соединения с базой данных исчезают. Я подозреваю, что процессы совместно используют соединения с базой данных, вызывая проблему.
Но я следовал всем инструкциям для Apache::DBI и не могу понять это.
Я делаю соединения в дочернем процессе, а не в startup.pl. Но когда я проверяю $dbh, возвращаемый каждым дочерним элементом из DBI->connnect, адрес одинаков для каждого процесса httpd. Во-первых, если это работает правильно и переподключается для каждого процесса, должен ли адрес, возвращаемый DBI->connect, отличаться для каждого дочернего процесса? Я предположил, но, насколько я могу судить, основной C-код в DBI (dbih_setup_handle) управляет этим и возвращает тот же адрес. Поэтому, возможно, я не понимаю, что значит воссоединиться с ребенком.
Правильно ли я подключаюсь, если идентификаторы $dbh одинаковые?
1 ответ
Похоже, вы устанавливаете соединение с базой данных в <perl>...</perl>
в разделе конфигурации запуска или в модуле, загруженном при запуске, и храните его до тех пор, пока разветвленные процессы не попытаются его использовать.
К сожалению, вам не сойти с рук. Вам нужно как-то убедиться, что новые процессы получают новые соединения.
Мое решение этой проблемы было центральной функцией для получения dbh, который отслеживал, что $$
(текущий идентификатор процесса) был, когда было установлено соединение. Если при передаче соединения функция обнаружила, что $$
изменился, он удалит все существующие соединения, не закрывая их, и создаст новое:
my $_dbh;
my $pid;
sub dbh {
if($pid != $$) {
$_dbh = DBI->connect(...);
$pid = $$;
}
return $_dbh;
}
Любой код, который хотел использовать базу данных, сначала вызвал бы dbh()
чтобы получить дескриптор базы данных, и позволить ему создать новый, если необходимо, или передать ранее установленное соединение, если оно может быть использовано.