2

以下のコードでファイルを開くときにエラーが発生する理由について誰かにアドバイスできますか?エラーは、25スレッドの9回目の反復の約半分から始まり、「開いているファイルが多すぎます」エラーです。このエラーは、スレッドで実行している場合、およびDBI接続/切断が使用されている場合にのみ発生します。これは、開いているファイルの数にまったく影響しないはずですか?私はPerlにかなり慣れていないので、何か変なことをしたかどうかはわかりません。これはPerl5.8.8にあります。Solaris10の場合。

use threads ();
use DBI;
use DBD::Oracle;

my $thrds=25;
my $iter=10;
my @threads;

for (my $j=0; $j<$iter; $j++) {
    &start($j);
}

sub start {
    my $k=$_[0];
    for (my $i=0; $i<$thrds; $i++) {
        $threads[$i] = threads->new(\&RunThread,$k, $i);
    }
    for (my $i=0; $i<$thrds; $i++) { $threads[$i]->join; }
}

sub RunThread {
    my $dbh = DBI->connect("dbi:Oracle:lnrmsd9.world", "rms_reader", "rms_reader") or die "failed connect";
    my ($x, $y)=@_;
    open (my $fh, ">/tmp/da") or die "failed $! at iter $x thread $y";
    close ($fh);
    $dbh->disconnect;
}
4

2 に答える 2

5

以下を使用する必要があります。

use warnings;
use strict;

これらは、サブルーチンでグローバル変数 $i と $j を使用していることを示しています。変数にアクセスする複数のスレッドがあるため、すべての地獄が解き放たれます。また、それらはすべて 1 つの FILE も共有しています。これが別の問題の原因です。そして、スカラー '$threads' と配列 '@threads' の両方があることに気付きましたか?

スレッドでは、グローバル変数は...まあ、敵ではないにしても、非常に問題があります。

open;の FILE ハンドル形式は避けてください。myもっと自由に使ってください。

「use DBD::Oracle;」と言う必要はありません。これまで。バリアントを使用する必要がある場合があります。

use DBD::Oracle qw( :ora_types );

Oracle 固有のデータ型にアクセスできます。


テストされていないリビジョン:

use strict;
use warnings;
use threads ();
use DBI;
use DBD::Oracle;

my $threads=25;
my $iter=10;

for ($j = 0; $j < $iter; $j++) {
    &start($j);
}

sub start {
    my($j) = @_;
    my(@threads);
    for (my $i = 0; $i < $threads; $i++) {
        $threads[$i] = threads->new(\&RunThread,$j, $i);
    }
    for ($i=0; $i < $threads; $i++) { $threads[$i]->join; }
}

sub RunThread {
    my $dbh = DBI->connect("dbi:Oracle:ora", "user", "pass") or die "failed connect";
    my($j, $i) = @_;
    open(my $fh, ">/tmp/da") or die "failed $! at iter $j thread $i";
    close $fh;
    $dbh->disconnect;
}

理解できなかったことが 1 つありますuse DBD::Oracle;

「perldoc DBD::Oracle」を見ると、概要が表示されます。

use DBI;

$dbh = DBI->connect("dbi:Oracle:$dbname", $user, $passwd);

したがって、DBD::Oracle モジュールの主要なドキュメントは、直接使用しないことを示しています。

使用しても害はありません。使用する必要はありません。DBI モジュールは、 への呼び出しで接続文字列によって暗示されたドライバを自動的にロードしますDBI->connect()。と書くことuse DBD::Oracle;で、DBI が実際にローディングを行う必要がなくなります (ローディングはすでに行われています)。useまた、Perl に、モジュールを節でロードできることを確認してもらうこともあると思います。

于 2010-06-22T14:59:38.187 に答える
1

試す

my $FILE;
open ($FILE, ">/tmp/da") or die "failed $! at iter $j thread $i";
close ($FILE);

これはベストプラクティスです。

于 2010-06-22T15:06:46.123 に答える