Perl - 使用DBD Oracle时出现太多文件错误

时间:2010-06-22 14:33:03

标签: perl oracle dbd

有人可以告诉我为什么在下面的代码中打开文件时出错。错误从25个线程的第9次迭代的大约一半开始,并且是“太多打开文件”错误。该错误仅在线程中运行时发生,并且仅在使用DBI连接/断开连接时发生。这应该不应该影响打开文件数应该是什么呢? 我对Perl很新,所以不确定我是否做了一些奇怪的事情。这是在Perl 5.8.8上。在Solaris 10上。

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

2 个答案:

答案 0 :(得分:5)

您需要使用:

use warnings;
use strict;

这些会告诉您在子例程中使用全局变量$ i和$ j。由于你有多个线程访问变量,所以所有的地狱都破裂了。此外,他们也共享一个文件 - 另一个麻烦来源。你是否意识到你有一个标量'$ threads'和一个数组'@threads'?

对于线程,全局变量......好吧,如果不是完全是敌人,那就非常有问题了。

避免使用open的FILE句柄形式;

你不需要说'使用DBD :: Oracle;'永远。您有时可能需要使用变体:

my

获取对特定于Oracle的数据类型的访问权。


未经测试的修订:

use DBD::Oracle qw( :ora_types );

  

我不明白的一件事 - 为什么我不应该使用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; }

如果你看一下'perldoc DBD :: Oracle',你会看到概要:

use DBD::Oracle;

因此,DBD :: Oracle模块的主要文档显示您不直接使用它。

使用它没有任何危害;没有必要使用它。 DBI模块在use DBI; $dbh = DBI->connect("dbi:Oracle:$dbname", $user, $passwd); 的调用中自动加载连接字符串隐含的驱动程序。通过编写DBI->connect(),您可以保存DBI不必实际进行加载(已经完成)。我想你也可以通过Perl验证模块是否可以加载use DBD::Oracle;子句。

答案 1 :(得分:1)

尝试

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

这是最好的做法。