Ok I found it. Seems I was allocating a little (year right) too much memory to the array. I set it up to do a max of 4k.

Tested this for 1,000,000 plus inserts and the memory did grow but you would expect that as you are generating a new array from the returned values

This is checked into trunk n SVN

I will be putting out a new version of DBD::Oracle next week so I would wait until then as there is no real fix for this right now.

You could get the Trunk version of DBD.Oracle. and use it. you can find it here

http://svn.perl.org/modules/dbd-oracle/trunk

cheers

John Scoles


John Scoles wrote:
Very odd indeed I will have a look at that.

Ricky Egeland wrote:
Hi,

Today I installed DBD::Oracle 1.21 and DBI 1.605 to run with oracle instant client 10.2.0.3 on 32-bit linux. (Scientific Linux 4 - basically RHEL4).

I wanted to try out bind_param_inout_array() in order to optimize writing. Unfortunately, my test program resulted in an "Out of Memory" error. Below
is my program, which used the code in the DBD::Oracle perldoc as
inspiration. For @in_values of 10 items it works, but for 100 it fails with
"Out of Memory".  I ran with DBI_TRACE=15=dbitrace.out and found the
following interesting lines:


OCIBindByName(9a79ee4,9a7c974,9a028f8,":p2",placeh_len=3,value_p=9975460,value_sz=160572495,dty=1,indp=9a7c98c,a
lenp=0,rcodep=9a7c984,maxarr_len=0,curelep=0 (*=0),mode=2)=SUCCESS

OCIBindDynamic(9a78fa8,9a028f8,9a7c950,3f6db0,9a7c950,3f6ff0)=SUCCESS
        OCIAttrGet(9a78fa8,OCI_HTYPE_BIND,9a7c960,0,31,9a028f8)=SUCCESS
dbd_rebind_ph(): bind :p2 <== ARRAY(0x99c39b4) (inout, not-utf8, csid
39->0->39, ftype 1, csform 0->0, maxlen 160572495,
 maxdata_size 0)
        OCIAttrSet(9a78fa8,OCI_HTYPE_BIND,bffe65da,0,31,9a028f8)=SUCCESS
    <- bind_param_inout_array= 1 at TestInOut.pl line 43 via  at
TestInOut.pl line 33
>> execute_array DISPATCH (DBI::st=HASH(0x9a7c110) rc1/1 @2 g0 ima5041
pid#27874) at TestInOut.pl line 44 via  at Te
stInOut.pl line 33
    -> execute_array in DBD::_::st for DBD::Oracle::st
(DBI::st=HASH(0x9a7c110)~0x9979d8c HASH(0x9979d68)) thr#979e008
    >> FETCH       DISPATCH (DBI::st=HASH(0x9979d8c) rc1/2 @2 g0 ima404
pid#27874) at /data/phedex/Testbed/sw/slc4_ia32_
gcc345/external/p5-dbi/1.605/lib/site_perl/5.8.5/i386-linux-thread-multi/DBI.pm
line 1851 via  at TestInOut.pl line 44
1   -> FETCH for DBD::Oracle::st (DBI::st=HASH(0x9979d8c)~INNER
'NUM_OF_PARAMS') thr#979e008
    .. FETCH DBI::st=HASH(0x9979d8c) 'NUM_OF_PARAMS' = 2 (cached)
1   <- FETCH= 2 at
/data/phedex/Testbed/sw/slc4_ia32_gcc345/external/p5-dbi/1.605/lib/site_perl/5.8.5/i386-linux-thread-
multi/DBI.pm line 1851 via  at TestInOut.pl line 44
    >> execute_for_fetch DISPATCH (DBI::st=HASH(0x9979d8c) rc1/2 @3 g0
ima5041 pid#27874) at /data/phedex/Testbed/sw/slc
4_ia32_gcc345/external/p5-dbi/1.605/lib/site_perl/5.8.5/i386-linux-thread-multi/DBI.pm
line 1924 via  at TestInOut.pl li
ne 44
1 -> execute_for_fetch for DBD::Oracle::st (DBI::st=HASH(0x9979d8c)~INNER
CODE(0x9a7c20c) ARRAY(0x9979d50)) thr#979e00
8
ora_st_execute_array INSERT count=100 (ARRAY(0x99694f4) ARRAY(0x9a7c3a4)
undef)...

OCIBindByName(9a79ee4,9a7b434,9a028f8,":p1",placeh_len=3,value_p=0,value_sz=3,dty=1,indp=0,alenp=0,rcodep=0,maxa
rr_len=0,curelep=0 (*=0),mode=2)=SUCCESS

OCIBindDynamic(9a790e0,9a028f8,9a7b410,3f6db0,9a7b410,3f6ff0)=SUCCESS

OCIBindByName(9a79ee4,9a7c974,9a028f8,":p2",placeh_len=3,value_p=0,value_sz=160572495,dty=1,indp=0,alenp=0,rcode
p=0,maxarr_len=0,curelep=0 (*=0),mode=2)=SUCCESS

OCIBindDynamic(9a78fa8,9a028f8,9a7c950,3f6db0,9a7c950,3f6ff0)=SUCCESS
...
out ':p2' [0,0]: alen 160572496, piece 0
out ':p2' [1,0]: alen 160572496, piece 0
out ':p2' [2,0]: alen 160572496, piece 0
...

I looked up the meaning of 'alen' in OCI documentation and found that it is related to the maximum size of the parameters to be bound. Could it be that DBD::Oracle is allocating 160572496 bytes of memory for each entry in the
array?  That would explain the "Out of Memory" error ;-)

If this is a known problem with a workaround, I would be most grateful.

Cheers,
Ricky



=== BEGIN CODE ===
#!/usr/bin/perl

use warnings;
use strict;

use DBI;
use DBD::Oracle;
use Data::Dumper;

my $data_source = 'dbi:Oracle:XXX';
my $username = XXX
my $auth = XXX
my %attr = ( RaiseError => 1,
             AutoCommit => 0 );

print "Connecting...";
my $dbh = DBI->connect($data_source, $username, $auth, \%attr);
print "Done.\n";

eval {
    print "Dropping test objects...";
    $dbh->do( qq{ drop table foo } );
    $dbh->do( qq{ drop sequence foo_id_seq } );
    print "Done\n";
};
warn $@ if $@;

print "Creating test objects...";
$dbh->do( qq{ create table foo (id number, bar number) } );
$dbh->do( qq{ create sequence foo_id_seq } );
print "Done.\n";

eval {
    my @in_values=(1..100);
    my @out_values;
    my @status;
    my $sth = $dbh->prepare(qq{
        INSERT INTO foo (id, bar)
            VALUES (foo_id_seq.nextval, ?)
            RETURNING id INTO ?

});
$sth->bind_param_array(1,[EMAIL PROTECTED]);
    $sth->bind_param_inout_array(2,[EMAIL PROTECTED], 0);   #,{ora_type =>
ORA_VARCHAR2});
$sth->execute_array({ArrayTupleStatus=>[]}) or die "error inserting";
    foreach my $id
(@out_values){
print 'returned id='.$id."\n";

}
};
warn $@ if
$@;

print "Dropping test
objects...";
$dbh->do( qq{ drop table foo } );
$dbh->do( qq{ drop sequence foo_id_seq }
);
print "Done\n";

$dbh->disconnect();

exit;
=== END CODE ===

Reply via email to