在打开新数据库之前检查数据库连接
Check database connection before open a new one
我的应用程序结构如下:
/root_dir/lib/Mojo_App/Controller/Main.pm
/root_dir/lib/Mojo_App/Database/Db.pm
/root_dir/ ...
在 Database::Db 中,我有一个创建到 SQL SERVER 的连接的子例程。该子例程被导出并在 Main.pm
中使用
示例:
Database::DB
my $config = {
db1 => {
host => 'dbi:Driver:server=ip01;database=db01',
user => 'user01',
pass => 'pass01'
},
db2 => {
host => 'dbi:Driver:server=ip02;database=db02',
user => 'user02',
pass => 'pass02'
},
db3 => {
host => 'dbi:Driver:server=ip03;database=db03',
user => 'user03',
pass => 'pass03'
}
};
sub connect_db {
use DBI;
my $self = shift;
return 0 unless $self;
my $dbh;
if (exists($config->{$self})) {
return $dbh = DBI->connect($config->{$self}->{host}, $config->{$self}->{user}, $config->{$self}->{pass}) || die( $DBI::errstr . "\n" ) ;
} else {
return "Connection not in config. \n" ;
}
return $dbh;
}
在 Main.pm 我是这样连接的:
my $dbh = connect_db('db1');
现在假设我需要连接到索引页上的数据库,所以我将在 Main.pm 中有一个像这样的子例程索引:
sub index {
my $self = shift;
my $dbh = connect_db('db1');
...
$self->render();
}
现在我不希望每次用户访问索引页时都建立一个新连接,我想检查连接是否存在,如果不存在则创建它。
我已经阅读了有关 ping 方法的信息,但我不知道如何在这里实现它。
我还阅读了 DBIx 并尝试了以下实现:
sub connect_db {
use DBIx::Connector;
my $self = shift;
return 0 unless $self;
my $dbh;
if (exists($config->{$self})) {
my $conn = DBIx::Connector->new($config->{$self}->{host}, $config->{$self}->{user}, $config->{$self}->{pass}, {
RaiseError => 1,
AutoCommit => 1,
});
return $dbh = $conn->dbh; ;
} else {
return "Connection not in config. \n" ;
}
return $dbh;
}
这个实现能实现我想要的吗?当数据库连接处于活动状态以供使用而不是重新创建时。如果是,像 Dbi 一样使用 DBIx 安全吗?我在这里指的是:
my $dbh = $conn->dbh;
$dbh->do('INSERT INTO foo (name) VALUES (?)', undef, 'Fred' );
and not
$conn->run(fixup => sub {
$_->do('INSERT INTO foo (name) VALUES (?)', undef, 'Fred' );
});
谢谢
这是DBI::connect_cached
要解决的问题:
$dbh = DBI->connect_cached($data_source, $username, $password)
or die $DBI::errstr;
$dbh = DBI->connect_cached($data_source, $username, $password, \%attr)
or die $DBI::errstr;
connect_cached
is like "connect
", except that the database handle returned is also stored in a hash associated with the given parameters. If another call is made to connect_cached
with the same parameter values, then the corresponding cached $dbh
will be returned if it is still valid. The cached database handle is replaced with a new connection if it has been disconnected or if the ping
method fails.
有关重要免责声明,请参阅文档。
从 DBIx::Connector 对象使用 dbh
方法然后将其用作普通 DBI 句柄是安全的,但是您会错过 DBIx::Connector 的大部分好处如果您不保留 DBIx::Connector 对象。创建一个新的 DBIx::Connector 对象将意味着需要一个新的连接,因为该对象是缓存连接的地方。此外,每当您调用 ->dbh
或 ->run
时,DBIx::Connector 会检查连接是否处于活动状态并且您没有分叉,并在需要时建立新连接。因此,最好存储和传递 DBIx::Connector 对象,然后让任何单独的代码段检索 dbh
或调用 run
。在 Mojolicious 应用程序中,通常会在应用程序中存储这样的内容 helper(但当然您可以将其放在任何方便的地方)。
# in application startup
my %dbs;
$app->helper(db => sub {
my ($c, $name) = @_;
return $dbs{$name} //= DBIx::Connector->new(...);
});
# elsewhere
my $dbh = $c->db('db1')->dbh;
# or
$c->db('db1')->run(...);
我的应用程序结构如下:
/root_dir/lib/Mojo_App/Controller/Main.pm
/root_dir/lib/Mojo_App/Database/Db.pm
/root_dir/ ...
在 Database::Db 中,我有一个创建到 SQL SERVER 的连接的子例程。该子例程被导出并在 Main.pm
中使用
示例:
Database::DB
my $config = {
db1 => {
host => 'dbi:Driver:server=ip01;database=db01',
user => 'user01',
pass => 'pass01'
},
db2 => {
host => 'dbi:Driver:server=ip02;database=db02',
user => 'user02',
pass => 'pass02'
},
db3 => {
host => 'dbi:Driver:server=ip03;database=db03',
user => 'user03',
pass => 'pass03'
}
};
sub connect_db {
use DBI;
my $self = shift;
return 0 unless $self;
my $dbh;
if (exists($config->{$self})) {
return $dbh = DBI->connect($config->{$self}->{host}, $config->{$self}->{user}, $config->{$self}->{pass}) || die( $DBI::errstr . "\n" ) ;
} else {
return "Connection not in config. \n" ;
}
return $dbh;
}
在 Main.pm 我是这样连接的:
my $dbh = connect_db('db1');
现在假设我需要连接到索引页上的数据库,所以我将在 Main.pm 中有一个像这样的子例程索引:
sub index {
my $self = shift;
my $dbh = connect_db('db1');
...
$self->render();
}
现在我不希望每次用户访问索引页时都建立一个新连接,我想检查连接是否存在,如果不存在则创建它。
我已经阅读了有关 ping 方法的信息,但我不知道如何在这里实现它。
我还阅读了 DBIx 并尝试了以下实现:
sub connect_db {
use DBIx::Connector;
my $self = shift;
return 0 unless $self;
my $dbh;
if (exists($config->{$self})) {
my $conn = DBIx::Connector->new($config->{$self}->{host}, $config->{$self}->{user}, $config->{$self}->{pass}, {
RaiseError => 1,
AutoCommit => 1,
});
return $dbh = $conn->dbh; ;
} else {
return "Connection not in config. \n" ;
}
return $dbh;
}
这个实现能实现我想要的吗?当数据库连接处于活动状态以供使用而不是重新创建时。如果是,像 Dbi 一样使用 DBIx 安全吗?我在这里指的是:
my $dbh = $conn->dbh;
$dbh->do('INSERT INTO foo (name) VALUES (?)', undef, 'Fred' );
and not
$conn->run(fixup => sub {
$_->do('INSERT INTO foo (name) VALUES (?)', undef, 'Fred' );
});
谢谢
这是DBI::connect_cached
要解决的问题:
$dbh = DBI->connect_cached($data_source, $username, $password) or die $DBI::errstr; $dbh = DBI->connect_cached($data_source, $username, $password, \%attr) or die $DBI::errstr;
connect_cached
is like "connect
", except that the database handle returned is also stored in a hash associated with the given parameters. If another call is made toconnect_cached
with the same parameter values, then the corresponding cached$dbh
will be returned if it is still valid. The cached database handle is replaced with a new connection if it has been disconnected or if theping
method fails.
有关重要免责声明,请参阅文档。
从 DBIx::Connector 对象使用 dbh
方法然后将其用作普通 DBI 句柄是安全的,但是您会错过 DBIx::Connector 的大部分好处如果您不保留 DBIx::Connector 对象。创建一个新的 DBIx::Connector 对象将意味着需要一个新的连接,因为该对象是缓存连接的地方。此外,每当您调用 ->dbh
或 ->run
时,DBIx::Connector 会检查连接是否处于活动状态并且您没有分叉,并在需要时建立新连接。因此,最好存储和传递 DBIx::Connector 对象,然后让任何单独的代码段检索 dbh
或调用 run
。在 Mojolicious 应用程序中,通常会在应用程序中存储这样的内容 helper(但当然您可以将其放在任何方便的地方)。
# in application startup
my %dbs;
$app->helper(db => sub {
my ($c, $name) = @_;
return $dbs{$name} //= DBIx::Connector->new(...);
});
# elsewhere
my $dbh = $c->db('db1')->dbh;
# or
$c->db('db1')->run(...);