Проверьте соединение с базой данных, прежде чем открывать новое - PullRequest
0 голосов
/ 22 октября 2018

У меня мохолитичное приложение, структурированное так:

 /root_dir/lib/Mojo_App/Controller/Main.pm  
 /root_dir/lib/Mojo_App/Database/Db.pm  
 /root_dir/ ...

В базе данных :: Db у меня есть подпрограмма, которая создает соединение с SQL SERVER.Эта подпрограмма экспортируется и используется в Main.pm
Пример:
База данных :: 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; 
}   

Достигнет ли эта реализация того, чего я хочу?Когда соединение с базой данных активно для использования и не воссоздано.Если да, безопасно ли использовать DBIx как Dbi?Я имею в виду здесь:

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

Спасибо

Ответы [ 2 ]

0 голосов
/ 23 октября 2018

Безопасно использовать метод dbh из объекта DBIx :: Connector, а затем использовать его в качестве обычного дескриптора 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(...);
0 голосов
/ 22 октября 2018

Это проблема, которую 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 похожа на "connect", за исключением того, что дескриптор базы данныхВозвращенный также хранится в хэше, связанном с данными параметрами.Если будет сделан другой вызов connect_cached с теми же значениями параметров, то соответствующий кэшированный $dbh будет возвращен, если он все еще действителен.Дескриптор кэшированной базы данных заменяется новым соединением, если оно было отключено или если метод ping не работает.

См. Документы для важных заявлений об отказе.

...