Perl-使用DBD Oracle时文件过多错误

Perl-使用DBD Oracle时文件过多错误,perl,oracle,dbd,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 @th

有人能告诉我为什么在下面的代码中打开文件时出错吗。这些错误大约在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;
}
使用线程();
使用DBI;
使用DBD::Oracle;
我的$thrds=25;
我的$iter=10;
我的@threads;
对于(my$j=0;$jconnect(“dbi:Oracle:lnrmsd9.world”、“rms\u reader”、“rms\u reader”)或die“连接失败”;
我的($x,$y)=@;
打开(my$fh,“>/tmp/da”)或死亡“失败$!在iter$x线程$y”;
收盘价($fh);
$dbh->断开连接;
}
您需要使用:

use warnings;
use strict;
这会告诉你,你在子例程中使用了全局变量$i和$j。因为有多个线程访问这些变量,所有这些变量都会崩溃。而且,它们也都共享一个文件——这是另一个麻烦。你意识到你有标量“$threads”和数组“@threads”吗

对于线程来说,全局变量是……嗯,如果不是敌人的话,也是非常有问题的

避免使用
open
的文件句柄形式;更自由地使用
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;
}
因此,DBD::Oracle模块的主要文档表明您不直接使用它

使用它不会造成任何伤害;不需要使用它。DBI模块会自动加载调用
DBI->connect()
中连接字符串隐含的驱动程序。通过编写
use DBD::Oracle;
,您可以避免DBI实际进行加载(已经完成了)。我想您还可以让Perl验证模块是否可以使用
use
子句加载。

试试看

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

这是最佳做法。

编辑器中的小二进制图标用于粘贴代码。(请参阅标记帮助指南。)我使用了它,但出于某种原因它不起作用。无论如何,好吧,现在,谢谢+1。Perl是最简单的自责语言之一:自责的方法有很多,你可以在comp.lang.Perl.misc上发布一个查询来确定最佳方法。在筛选了500个回复之后(这是通过一个简短的Perl脚本来完成的),您开始简单而优雅地攻击自己的脚,直到您发现,虽然在大多数情况下工作正常,但Windows、VM和各种风格的Linux都可以让您比Perl脚本更快地攻击自己的脚。;-)Perl还提供了很好的诊断方法,可以修复脚射——如果程序员选择使用它们的话。好的,谢谢,这有点混乱!我的借口是,在更大的脚本中重新创建问题既快又脏。无论如何,我整理了(并在原始帖子中更改了代码),但不幸的是,我仍然得到了正确的答案“打开的文件太多"9次迭代后出现错误。所以问题还没有解决。有一件事我不明白-为什么我不应该使用DBD::Oracle;?@Joe Watkins:请参阅“为什么不使用DBD::Oracle”问题答案的结尾。关于泄漏的文件描述符:开始看起来有问题。省略一项检查:关闭成功吗?如果没有,那就是泄漏的地方。O因此,在我看来,泄漏一定是在DBI和DBD::Oracle中,
$dbh->disconnect
似乎没有释放文件描述符。另一项需要检查的是使用线程安全OCI库编译的DBD::Oracle,并且知道将要使用线程。如果存在描述符泄漏,请向支持人员报告故障列表
dbi-users@perl.org
@Joe Watkins:另请参见。报告问题时,您需要报告DBI和DBD::Oracle版本,以及Oracle版本(客户端软件-OCI)。如果您使用的是陈旧代码,则第一个响应应该是“升级到当前版本”。
my $FILE;
open ($FILE, ">/tmp/da") or die "failed $! at iter $j thread $i";
close ($FILE);