Perl Parallel::ForkManager с обработчиками базы данных DBI

я заинтересован в параллельном выполнении нескольких действий с базой данных. Я играл с Perl Parallel::ForkManager, но еще не использовал его ни с какими базами данных. Я читал, что подключение к базе данных не очень хорошо поддерживается. У кого-нибудь есть опыт в этом?

В качестве примера я, вероятно, порождал бы системный вызов (который работает с DBI) НЕ необработанный код, т.е.

#!/opt/local/bin/perl -w

use strict;
use Parallel::ForkManager;

$| = 1;

my $max_procs = 10;

my $pm =  new Parallel::ForkManager($max_procs);

for (my $var = 0; $var <= 10; $var++) {
  my $pid = $pm->start('proc'.$var) and next;
  sleep ( 2 );
  system( "./DBworker.pl $var" );
  $pm->finish(0); 
}

print "Waiting for child procs\n";
$pm->wait_all_children;
print "complete!\n";

person nick fox    schedule 27.06.2010    source источник


Ответы (1)


Если работа выполняется другими программами, опасности для forking нет. Опасность возникает, когда вы открываете соединение с базой данных, а затем делаете ответвление. Ребенок не может повторно использовать родительское соединение; однако взгляните на DBIx::Connector, он обрабатывает то, что вам нужно сделать после forking для вас и запуска нескольких программ, как правило, не является правильным ответом.

#!/usr/bin/perl

use strict;
use warnings;

use DBIx::Connector;
use Parallel::ForkManager;

my $dsn  = "dbi:SQLite:dbname=foo.db";
my $user = "";
my $pass = "";
my $conn = DBIx::Connector->new($dsn, $user, $pass, 
    {
        AutoCommit       => 0,
        PrintError       => 0,
        RaiseError       => 1,
        ChopBlanks       => 1,
        FetchHashKeyName => 'NAME_lc',
    }
);
END { unlink "foo.db" }

#setup table
$conn->run(fixup => sub {
    my $dbh = $_;
    $dbh->do("create table foo ( id integer, name char(35) )");
    my $sth = $dbh->prepare("insert into foo (id, name) values (?, ?)");
    while (<DATA>) {
        chomp;
        $sth->execute(split /,/);
    }
});

my $pm = Parallel::ForkManager->new(3);

my $sth = $conn->dbh->prepare("select * from foo where id = ?");
for my $id (1 .. 3) {
    next if $pm->start;
    $sth->execute($id);
    while (my $row = $sth->fetchrow_hashref) {
        print "$id saw $row->{id} => $row->{name}\n";
    }
    $pm->finish;
}

$pm->wait_all_children;

print "done\n";

__DATA__
1,foo
2,bar
3,baz
person Chas. Owens    schedule 27.06.2010
comment
Этот скрипт должен работать и в Windows? - person MeirG; 06.12.2016
comment
@MeirG, поскольку Windows изначально не поддерживает fork (он эмулируется с некоторыми отличиями), я не могу сказать наверняка. У меня нет компьютера с Windows для тестирования, но если у вас возникнут какие-либо проблемы, просто опубликуйте, что происходит не так, как новый вопрос. - person Chas. Owens; 06.12.2016