2010-06-22 2 views
2

Может кто-нибудь посоветует, почему я получаю ошибки, открывая файл в коде ниже. Ошибки начинаются примерно наполовину через 9-ю итерацию из 25 потоков и являются ошибками «Слишком много открытых файлов». Ошибка возникает только при работе в потоках и только при использовании соединения DBI. Это не должно влиять на количество открытых файлов вообще? Я довольно новичок в Perl, поэтому не уверен, что я сделал что-то странное. Это на Perl 5.8.8. на Solaris 10.Perl - слишком много ошибок файлов при использовании DBD Oracle

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

+0

Я использовал это, и по какой-то причине это не сработало. В любом случае, ОК, спасибо –

ответ

5

Вы должны использовать:

use warnings; 
use strict; 

Они скажут вам, что вы используете глобальные переменные $ I- и $ J в подпрограмме. Поскольку у вас есть несколько потоков, обращающихся к переменным, все ад разрывается. Кроме того, все они совместно используют один ФАЙЛ - еще один источник проблем. И вы поняли, что у вас есть как скалярные «потоки», так и массив «@threads»?

С потоками глобальные переменные ... ну, если не совсем враги, крайне проблематичны.

Избегайте обработки ручки FILE open; используйте 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 :: Oracle», вы увидите Синопсис:

use DBI; 

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

Таким образом, первичная документация для модуля DBD :: Oracle показывает, что вы не используете это прямо.

Нет вреда при его использовании; нет необходимости использовать его. Модуль DBI автоматически загружает драйвер, подразумеваемый строкой соединения, в вызове DBI->connect(). Написав use DBD::Oracle;, вы сохраняете DBI от фактической загрузки (это уже сделано). Я полагаю, вы также получаете Perl для проверки того, что модуль доступен для загрузки с предложением use.

+0

+1. Perl - один из самых простых языков, с помощью которого можно стрелять себе в ногу: существует так много способов стрелять в ногу, когда вы отправляете запрос на comp.lang.perl.misc для определения оптимального подхода.После просеивания ответов на 500 ответов (которые вы выполняете с помощью короткого сценария Perl) вы ставите задачу просто и элегантно снимать себя в ногу, пока не обнаружите, что, хотя в большинстве случаев она отлично работает, Windows, VMS и различные вкусы Linux все позволяют вам стрелять в ногу раньше, чем ваш скрипт Perl. ;-) – DCookie

+0

Perl также дает отличную диагностику для фиксации стоп-стрельб - если программист решит их использовать. – Ether

+0

Никакой аргумент здесь! – DCookie

1

Попробуйте

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

Это в лучшем практике.

+0

Спасибо, пробовал, но без изменений –

Смежные вопросы