Perl - 使用 DBD Oracle 时出现文件过多错误
有人可以告诉我为什么在下面的代码中打开文件时出错。这些错误大约在 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;
}
Can someone advise on why I get errors opening the file in the code below. The errors start about half way through the 9th iteration of 25 threads, and are "Too many open files" errors. The error only happens when running in threads, and only when the DBI connect/disconnect are used. This shouldn't affect the open file count at all should it?
I'm fairly new to Perl so not sure if I've done something weird. This is on Perl 5.8.8. on 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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您需要使用:
这些会告诉您正在子例程中使用全局变量 $i 和 $j 。由于您有多个线程访问变量,所以一切都变得混乱了。此外,它们也都共享一个文件——这是另一个麻烦来源。您是否意识到您同时拥有标量“$threads”和数组“@threads”?
对于线程来说,全局变量……好吧,即使不完全是敌人,也是非常有问题的。
避免使用
open
的 FILE 句柄形式;更自由地使用my
。而且您不需要说“使用 DBD::Oracle;”曾经。有时您可能需要使用变体:
来访问 Oracle 特定的数据类型。
未经测试的修订版:
如果您查看“perldoc DBD::Oracle”,您将看到概要:
因此,DBD::Oracle 模块的主要文档表明您不直接使用它。
使用它并没有什么坏处;没有必要使用它。 DBI 模块自动加载 DBI->connect() 调用中的连接字符串所隐含的驱动程序。通过编写
use DBD::Oracle;
,您可以使 DBI 不必实际执行加载(它已经完成)。我想您还让 Perl 来验证该模块是否可以使用use
子句加载。You need to use:
These would tell you that you're using global variables $i and $j in the subroutine. Since you've got multiple threads accessing the variables, all hell breaks loose. Also, they're all sharing a single FILE, too - another source of trouble. And did you realize you had both a scalar '$threads' and an array '@threads'?
With threads, global variables are ... well, if not exactly the enemy, extremely problematic.
Avoid the FILE handle form of
open
; usemy
much more liberally.And you don't need to say 'use DBD::Oracle;' ever. You might sometimes need to use the variant:
to gain access to Oracle-specific data types.
Untested revision:
If you look at the 'perldoc DBD::Oracle', you will see the Synopsis:
So, the primary documentation for the DBD::Oracle module shows that you do not use it directly.
There is no harm done in using it; there is no need to use it. The DBI module automatically loads the driver implied by the connection string in the call to
DBI->connect()
. By writinguse DBD::Oracle;
, you save the DBI from having to actually do the loading (it is already done). I suppose you also get Perl to verify that the module is available to be loaded with theuse
clause.尝试
这是最佳实践。
Try
This is in the best practice.