我有一个基于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 connect('alcatelRSA; host = 10.125.1.21; port = 3306','tools',...)失败:C上的连接太多:/Perl/site/lib/DBIx/Connector.pm第30行
我想过每次使用DBIx :: Connectors“disconnect”调用来关闭与数据库的连接,但是根据需要,打开/关闭连接的性能影响似乎很大。
您对此问题有任何其他建议吗?
答案 0 :(得分: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进程数。每个单独的进程或线程必须有自己的数据库连接,但可能有多个 - 所以您可能还需要确保上面的代码只运行(即构建数据库管理对象)一次< / em>每个进程,并且每次构建此类对象的后续尝试都只返回现有对象的副本。一个简单的方法是使用MooseX::Singleton,但这会引入其他设计问题。