mod_perl2 moose 应用程序的数据库连接过多

发布于 2024-09-05 17:00:51 字数 1658 浏览 7 评论 0原文

我有一个基于 mod_perl2 的 Web 应用程序,需要连接到 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;

然后,我在需要使用语句连接到数据库的所有驼鹿类中使用该角色

 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 行连接过多

DBI connect('alcatelRSA;host=10.125.1.21;port=3306','tools',...) 失败:C:/Perl/site/lib/DBIx/Connector.pm第 每次使用 DBIx::Connectors“disconnect”调用来关闭与数据库的连接,但根据需要打开/关闭连接对性能的影响似乎很严重。

您对这个问题有什么替代建议吗?

I have a mod_perl2 based web app that requires a connection to a mysql database. I have implemented the SQL connection specifics in a moose role.

Simplified, the role looks as follows:

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;

I then use this role in all moose classes that require a connection to the DB with a

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

statement.

While this works well when a few objects are created, i soon run into troubles when to many objects are created. In the httpd log for instance, i get the error:

DBI connect('alcatelRSA;host=10.125.1.21;port=3306','tools',...) failed: Too many connections at C:/Perl/site/lib/DBIx/Connector.pm line 30

I thought about using DBIx::Connectors "disconnect" call to close the connection to the database each time, but the performance impact seem to severe to open / close connections as required.

Do you have any alternative suggestions on this problem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

林空鹿饮溪 2024-09-12 17:00:51

您是否复制 dbh 并在 DBIx::Connector 对象超出范围?该文档明确指出不要这样做。相反,保存 DBIx::Connector 对象本身,并使用属性中的 handles 选项将 dbh 方法调用委托给它。

这就是我所做的(实际上我昨天刚刚发布了这段代码来回答另一个问题;有趣的是数据库问题是如何打包的):

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 进程。每个单独的进程或线程都必须有自己的数据库连接,但可能不止一个 - 因此您可能还需要确保上面的代码仅运行(即构建数据库管理对象)一次 /em> 每个进程,并且每次后续尝试构建此类对象仅返回现有对象的副本。一种简单的方法是使用 MooseX::Singleton,但这引入了其他设计本身的问题。

Are you copying the dbh and using it in places when the out of the DBIx::Connector object goes out of scope? The the documentation specifically says not to do that. Instead, save the DBIx::Connector object itself, and delegate the dbh method call to it with a handles option in the attribute.

This is what I do (I actually just posted this code yesterday in response to another question; funny how DB questions come in packs):

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) });
}

You may also want to look at how many mod_perl processes you are allowing. Each separate process or thread necessarily must have its own DB connection, but there may be more than one -- so you probably also need to ensure that the code above only runs (i.e a db management object is built) only once per process, and each subsequent attempt to build such an object simply returns a copy of the existing one. One easy way to do this is with MooseX::Singleton, but this introduces other design issues of its own.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文