3

mysql データベースへの接続を必要とする mod_perl2 ベースの Web アプリがあります。moose ロールに 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;

次に、DB への接続を必要とするすべての moose クラスでこのロールを使用します。

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

声明。

これは少数のオブジェクトが作成される場合にはうまく機能しますが、多くのオブジェクトが作成されるとすぐに問題が発生します。たとえば、httpd ログでは、次のエラーが表示されます。

DBI connect('alcatelRSA;host=10.125.1.21;port=3306','tools',...) 失敗: C:/Perl/site/lib/DBIx/Connector.pm 行 30 での接続が多すぎます

DBIx::Connectors の "disconnect" 呼び出しを使用して毎回データベースへの接続を閉じることを考えましたが、必要に応じて接続を開いたり閉じたりすると、パフォーマンスへの影響が深刻なようです。

この問題に関する別の提案はありますか?

4

1 に答える 1

6

DBIx::Connectorオブジェクトが範囲外になったときに、dbh をコピーして使用していますか? ドキュメントには、そうしないように具体的に書かれています。代わりに、DBIx::Connector オブジェクト自体を保存し、属性のオプションをdbh使用してメソッド呼び出しを委任します。handles

これが私がしていることです(実際に昨日、別の質問に答えてこのコードを投稿しました。DBの質問がパックになっているのは面白いです):

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 プロセスの数を確認することもできます。それぞれの個別のプロセスまたはスレッドには必ず独自の DB 接続が必要ですが、複数ある場合もあります。そのため、上記のコードがプロセスごとに 1だけ実行される (つまり、db 管理オブジェクトが構築される) ことを確認する必要があります。その後、そのようなオブジェクトを作成しようとすると、既存のオブジェクトのコピーが返されます。これを行う簡単な方法の 1 つはMooseX::Singletonを使用することですが、これには別の設計上の問題があります。

于 2010-06-15T14:57:08.610 に答える