Steve Cookson - gmail
2015-05-26 10:07:03 UTC
Hi Guys,
You may have seen part of this post on PerlMonks. If so apologies for
the duplication. This started off as a general search for leaks in my
code, and resulted in a few hits, one of which was attached to every
database access.
A simple "select ATT_RECORD_NAME_TXT from TBL_TEST; " results in the
leak of one scalar value. It seems to be attached to the ->prepare
statement.
At first I assumed it was down to my Firebird driver, which is
relatively new, so I switched the driver to ODBC::Firebird, with the
same result. Finally I changed to mysql and again got a memory leak.
The only thing I can assume is that either my code is generically wrong
(and I hope this is the case), or there is a leak in dbi, which I would
be surprised by.
I would appreciate some advice.
Test code follows. Please install Devel::Leak to pick up leaked scalars
and update the dsn to the dsn of your choice.
Thanks for your help.
Regards,
Steve.
#! /usr/bin/perl
package main;
use strict;
use warnings;
use DBI;
#use DBD::Firebird;
use DBD::ODBC;
use Devel::Leak;
my $handle;
my $count_start;
my $count_stop;
my $gl_dbh;
# Just do this 5 times to make sure there is no contribution to
$handle count from Devel::Leak
for (1..10){
print "Handle init: ", Devel::Leak::NoteSV($Launch::handle),"\n";
}
#my $loc_dsn = <<DSN;
#dbi:ODBC:Driver=Firebird;Dbname=/home/image/Documents/Endoscopia/DB/newEndo.fdb;
#ib_dialect=3;
#DSN
my $loc_dsn = <<DSN;
DBI:mysql:database=new_schema_test;
host=localhost;
port=3306";
DSN
$Launch::gl_dbh=DBI->connect($loc_dsn,"root","password", {
PrintError => 1, # Report errors via warn
RaiseError => 1 # Report errors via Die
}
) or die;
my @loc_sql_string =();
$loc_sql_string[0]="CREATE TABLE TBL_TEST_LEAK ( ATTR_RECORD_ID_TXT
VARCHAR(10) NOT NULL, ATT_RECORD_NAME_TXT VARCHAR(255), CONSTRAINT
PK_TBL_TEST_LEAK PRIMARY KEY (ATTR_RECORD_ID_TXT) ); ";
$loc_sql_string[1]="GRANT DELETE, INSERT, REFERENCES, SELECT,
UPDATE ON TBL_TEST_LEAK TO SYSDBA WITH GRANT OPTION";
$loc_sql_string[2]="INSERT INTO TBL_TEST_LEAK (ATTR_RECORD_ID_TXT,
ATT_RECORD_NAME_TXT) VALUES ('206', 'Delay Test 1' )";
$loc_sql_string[3]="select ATT_RECORD_NAME_TXT from TBL_TEST_LEAK; ";
$loc_sql_string[4]= $loc_sql_string[3];
$loc_sql_string[5]= $loc_sql_string[3];
$loc_sql_string[6]= $loc_sql_string[3];
$loc_sql_string[7]= $loc_sql_string[3];
$loc_sql_string[8]= $loc_sql_string[3];
$loc_sql_string[9]="drop table TBL_TEST_LEAK; ";
for (my $i=1;$i<=9;$i++){
$count_start=Devel::Leak::NoteSV($Launch::handle);
print "DBD start: ", $count_start,"\n";
print $loc_sql_string[$i], "\n";
dbd_select($loc_sql_string[$i]);
# You can use
#$count_stop=Devel::Leak::CheckSV($Launch::handle);
$count_stop=Devel::Leak::NoteSV($Launch::handle);
print "Handle stop: ", $count_stop,"\n";
print "Count difference: ", $count_stop-$count_start,"\n";
}
$Launch::gl_dbh->disconnect;
sub dbd_select{
my $loc_sql_string=shift;
my $loc_sth=$Launch::gl_dbh->prepare($loc_sql_string) or die;
#$loc_sth->execute() or die;
#$loc_sth->finish();
return;
}
1;
You may have seen part of this post on PerlMonks. If so apologies for
the duplication. This started off as a general search for leaks in my
code, and resulted in a few hits, one of which was attached to every
database access.
A simple "select ATT_RECORD_NAME_TXT from TBL_TEST; " results in the
leak of one scalar value. It seems to be attached to the ->prepare
statement.
At first I assumed it was down to my Firebird driver, which is
relatively new, so I switched the driver to ODBC::Firebird, with the
same result. Finally I changed to mysql and again got a memory leak.
The only thing I can assume is that either my code is generically wrong
(and I hope this is the case), or there is a leak in dbi, which I would
be surprised by.
I would appreciate some advice.
Test code follows. Please install Devel::Leak to pick up leaked scalars
and update the dsn to the dsn of your choice.
Thanks for your help.
Regards,
Steve.
#! /usr/bin/perl
package main;
use strict;
use warnings;
use DBI;
#use DBD::Firebird;
use DBD::ODBC;
use Devel::Leak;
my $handle;
my $count_start;
my $count_stop;
my $gl_dbh;
# Just do this 5 times to make sure there is no contribution to
$handle count from Devel::Leak
for (1..10){
print "Handle init: ", Devel::Leak::NoteSV($Launch::handle),"\n";
}
#my $loc_dsn = <<DSN;
#dbi:ODBC:Driver=Firebird;Dbname=/home/image/Documents/Endoscopia/DB/newEndo.fdb;
#ib_dialect=3;
#DSN
my $loc_dsn = <<DSN;
DBI:mysql:database=new_schema_test;
host=localhost;
port=3306";
DSN
$Launch::gl_dbh=DBI->connect($loc_dsn,"root","password", {
PrintError => 1, # Report errors via warn
RaiseError => 1 # Report errors via Die
}
) or die;
my @loc_sql_string =();
$loc_sql_string[0]="CREATE TABLE TBL_TEST_LEAK ( ATTR_RECORD_ID_TXT
VARCHAR(10) NOT NULL, ATT_RECORD_NAME_TXT VARCHAR(255), CONSTRAINT
PK_TBL_TEST_LEAK PRIMARY KEY (ATTR_RECORD_ID_TXT) ); ";
$loc_sql_string[1]="GRANT DELETE, INSERT, REFERENCES, SELECT,
UPDATE ON TBL_TEST_LEAK TO SYSDBA WITH GRANT OPTION";
$loc_sql_string[2]="INSERT INTO TBL_TEST_LEAK (ATTR_RECORD_ID_TXT,
ATT_RECORD_NAME_TXT) VALUES ('206', 'Delay Test 1' )";
$loc_sql_string[3]="select ATT_RECORD_NAME_TXT from TBL_TEST_LEAK; ";
$loc_sql_string[4]= $loc_sql_string[3];
$loc_sql_string[5]= $loc_sql_string[3];
$loc_sql_string[6]= $loc_sql_string[3];
$loc_sql_string[7]= $loc_sql_string[3];
$loc_sql_string[8]= $loc_sql_string[3];
$loc_sql_string[9]="drop table TBL_TEST_LEAK; ";
for (my $i=1;$i<=9;$i++){
$count_start=Devel::Leak::NoteSV($Launch::handle);
print "DBD start: ", $count_start,"\n";
print $loc_sql_string[$i], "\n";
dbd_select($loc_sql_string[$i]);
# You can use
#$count_stop=Devel::Leak::CheckSV($Launch::handle);
$count_stop=Devel::Leak::NoteSV($Launch::handle);
print "Handle stop: ", $count_stop,"\n";
print "Count difference: ", $count_stop-$count_start,"\n";
}
$Launch::gl_dbh->disconnect;
sub dbd_select{
my $loc_sql_string=shift;
my $loc_sth=$Launch::gl_dbh->prepare($loc_sql_string) or die;
#$loc_sth->execute() or die;
#$loc_sth->finish();
return;
}
1;