Слишком много соединений с БД с приложением mod_perl2 Moose - PullRequest
3 голосов
/ 15 июня 2010

У меня есть веб-приложение на основе mod_perl2, которое требует подключения к базе данных MySQL.Я реализовал специфику SQL-соединения в роли лося.

Упрощенно, роль выглядит следующим образом:

package Project::Role::SQLConnection;

use Moose::Role;
use DBIx::Connector;

has 'connection' => (is => 'rw', lazy_build => 1);
has 'dbh' => (is => 'rw', lazy_build => 1);
has 'db'    => ( is => 'rw', default => 'alcatelRSA');
has 'port'  => ( is => 'rw', default => 3306);
has 'host'  => ( is => 'rw', default => '10.125.1.21');
has 'user'  => ( is => 'rw', default => 'tools');
has 'pwd'   => ( is => 'rw', default => 'alcatel');


#make sure connection is still alive...
before dbh => sub {
    my $self = shift;
    $self->connection->run(fixup => sub { $_->do('show tables') });
};

sub _build_dbh {
    my $self = shift;
    return $self->connection->dbh;
}

sub _build_connection {
    my $self = shift;
    my $dsn = 'DBI:mysql:'.$self->db.';host='.$self->host.';port='.$self->port;
    my $conn = DBIx::Connector->new($dsn, $self->user, $self->pwd);
    return $conn;
}

no Moose::Role;
1;

Затем я использую эту роль во всех классах Moose, которые требуют подключения к БД с

 with qw(Project::Role::SQLConnection);

заявление.

Хотя это работает хорошо, когда создается несколько объектов, я скоро столкнусь с проблемами, когда создается много объектов.Например, в журнале httpd я получаю сообщение об ошибке:

DBI-соединение ('alcatelRSA; хост = 10.125.1.21; порт = 3306', 'tools', ...) не выполнено: слишком многосоединения в C: /Perl/site/lib/DBIx/Connector.pm строка 30

Я думал об использовании DBIx :: Connectors вызова "отключить", чтобы каждый раз закрывать соединение с базой данных, новлияние на производительность, по-видимому, слишком велико для открытия / закрытия соединений.

Есть ли у вас какие-либо альтернативные предложения по этой проблеме?

1 Ответ

6 голосов
/ 15 июня 2010

Вы копируете dbh и используете его местами, когда объект DBIx :: Connector выходит из области видимости?В документации конкретно сказано не делать этого.Вместо этого сохраните сам объект DBIx :: Connector и делегируйте ему вызов метода dbh с параметром handles в атрибуте.

Это то, что я делаю (на самом деле я только что опубликовал этот код вчерав ответ на другой вопрос (забавно, как вопросы о БД входят в пакеты):

has dbixc => (
    is => 'ro', isa => 'DBIx::Connector',
    lazy_build => 1,
    # DO NOT save a copy of the dbh. Use this accessor every time, as
    # sometimes it will change unexpectedly!
    handles => [ qw(dbh) ],
);

sub _build_dbixc
{
    my $this = shift;
    DBIx::Connector->new(
        $this->dsn,
        $this->username,
        $this->password,
        $this->connect_options,
    );
}

sub call_dbh
{
    my $this = shift;
    my $method = shift;
    my @args = @_;

    # the normal behaviour -- pings on every dbh access
    #return $this->dbh->$method(@args);

    # the smart behaviour -- presume the DB connection still works
    $this->dbixc->run(fixup => sub { $_->$method(@args) });
}

Вы также можете посмотреть, сколько процессов mod_perl вы разрешаете.Каждый отдельный процесс или поток обязательно должен иметь свое собственное соединение с БД, но их может быть несколько, поэтому вам, вероятно, также необходимо убедиться, что приведенный выше код выполняется только (т. Е. Создается объект управления БД) только один раз за процесс, и каждая последующая попытка построить такой объект просто возвращает копию существующего.Один простой способ сделать это с помощью MooseX :: Singleton , но это ставит другие собственные проблемы проектирования.

...