2010-06-22 97 views
2

有人可以告诉我为什么在下面的代码中打开文件时出错。错误从25个线程的第9次迭代中途开始,并且是“太多打开的文件”错误。错误只发生在线程中运行时,并且仅在使用DBI连接/断开连接时才会发生。这应该不会影响打开文件的数量吗? 我对Perl相当陌生,所以不确定自己做了些什么奇怪的事情。这是在Perl 5.8.8上。在Solaris 10上Perl - 使用DBD时出现太多文件错误

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)[email protected]_; 
    open (my $fh, ">/tmp/da") or die "failed $! at iter $x thread $y"; 
    close ($fh); 
    $dbh->disconnect; 
} 
+1

编辑器中的小二进制图标用于粘贴代码。 (请参阅标记帮助指南。) – Ether 2010-06-22 14:54:16

+0

我曾使用过它,但由于某种原因它不起作用。无论如何,现在好了,谢谢 – 2010-06-23 08:34:08

回答

5

您需要使用:

use warnings; 
use strict; 

,你在子程序中使用全局变量$ i和$ J中使用这些会告诉你。既然你有多个线程访问这些变量,所有的地狱崩溃了。此外,他们也都共享一个文件 - 另一个麻烦来源。你有没有意识到你有一个标量'线程'和一个数组'@线程'?

对于线程,全局变量是......好吧,如果不是完全的敌人,那么问题就很大。

避免使用open的FILE句柄形式;更加宽松地使用my

而且您不需要说'使用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; 
} 

有一件事我不明白 - 为什么我不能用use DBD::Oracle;

如果你看“的perldoc DBD ::甲骨文”,你会看到剧情简介:

use DBI; 

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

所以,对于DBD ::甲骨文模块的主要文档表明您不使用它直接。

使用它没有任何伤害;没有必要使用它。 DBI模块会自动加载DBI->connect()调用中连接字符串隐含的驱动程序。通过编写use DBD::Oracle;,您可以将DBI从实际上进行加载(已经完成)。我想你也可以通过Perl来验证模块是否可用于加载use子句。

+0

+1。 Perl是在脚下拍摄自己的最简单的语言之一:有很多方法可以在脚中拍摄自己,然后将查询发布到comp.lang.perl.misc以确定最佳方法。在筛选了500个回复之后(你用一个简短的Perl脚本完成的)之后,你就可以简单而优雅地在脚下自我射击,直到你发现,尽管在大多数情况下,Windows,VMS和各种工具都能正常工作Linux的各种风格都可以让你在比Perl脚本更快的速度下拍摄你的脚。 ;-) – DCookie 2010-06-22 15:06:25

+0

Perl也为固定脚射击提供了很好的诊断 - 如果程序员选择使用它们。 – Ether 2010-06-22 16:16:08

+0

这里没有参数! – DCookie 2010-06-22 17:12:14

1

尝试

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

这是最好的做法。

+0

谢谢,试过了,但没有改变 – 2010-06-23 08:38:47