问题
I have an odd problem. On my dev computer I am getting errors. However on the live system the errors do not happen. If I fix the issues on dev the fixes cause problems in production.
It has to do with when I am closing prepared statements. On production I have to call finish after every fetch. If I do this on my dev system then the next execute of the statement will return undef, and there is nothing $dbh->errstr or in $DBI::errstr.
Any Idea where to even start with this one?
Here is a simple test:
#!/usr/bin/perl
use strict;
use warnings;
use DBI;
use DateTime;
use DateTime::Format::Strptime;
use Data::Dumper;
# Debug flag.
my $debug = 1;
#helper
sub getLoggingTime {
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
my $nice_timestamp = sprintf ( "%04d/%02d/%02d %02d:%02d:%02d",
$year+1900,$mon+1,$mday,$hour,$min,$sec);
return $nice_timestamp;
}
# Debug function.
sub dbg { if (! $debug) { return }; my $str = getLoggingTime() . " " . shift ; print STDERR $str }
# These are *the* date and time formats we use.
my $dateFormat = new DateTime::Format::Strptime('pattern' => '%F', 'locale' => 'en_NZ', 'time_zone' => 'Pacific/Auckland');
my $timeFormat = new DateTime::Format::Strptime('pattern' => '%T', 'locale' => 'en_NZ', 'time_zone' => 'Pacific/Auckland');
# Connect to the database.
my $dbconnect = *****removed**** || die 'No dbi_connection configured.';
my $dbusername = *****removed**** || die 'No dbi_username configured.';
my $dbpassword = *****removed**** || die 'No dbi_password configured.';
my $dbh = DBI->connect ($dbconnect, $dbusername, $dbpassword, { RaiseError => 1, PrintError => 1, AutoCommit => 1 }) ||
die 'Cannot connect to database. ' . DBI::errstr;
my $test_sth = $dbh->prepare('
SELECT
? as teststring,
GETDATE() as testdate
') || die 'Cannot prepare franchise name statement: ' . ($dbh->errstr ||$DBI::errstr || "") . "\n";
##Attempt One
$test_sth->execute("Test string") || die "Could not execute test statement: " . ($dbh->errstr ||$DBI::errstr || "") . "\n";
my $result = $test_sth->fetchrow_hashref()
|| die "Cannot get result: " . ($dbh->errstr ||$DBI::errstr || "") . "\n";
$test_sth->finish();
my $testString = $result->{'teststring'};
my $testDate = $result->{'testdate'};
dbg("testString = $testString, testDate = $testDate\n");
##Attempt Two
$test_sth->execute("Test string") || die "Could not execute test statement: " . ($dbh->errstr ||$DBI::errstr || "") . "\n";
$result = $test_sth->fetchrow_hashref()
|| die "Cannot get result: " . ($dbh->errstr ||$DBI::errstr || "") . "\n";
$test_sth->finish();
$testString = $result->{'teststring'};
$testDate = $result->{'testdate'};
dbg("testString = $testString, testDate = $testDate\n");
$dbh->disconnect();
1;
On dev I get :
perl dbiTest.pl 2014/03/13 11:15:51 testString = Test string, testDate = Mar 13 2014 11:15AM Could not execute test statement:
on Prod I get:
dbiTest.pl 2014/03/13 11:17:20 testString = Test string, testDate = Mar 13 2014 11:17AM 2014/03/13 11:17:20 testString = Test string, testDate = Mar 13 2014 11:17AM
If I comment the first $test_sth->finish(); On dev I get:
perl dbiTest.pl 2014/03/13 11:24:44 testString = Test string, testDate = Mar 13 2014 11:24AM 2014/03/13 11:24:44 testString = Test string, testDate = Mar 13 2014 11:24AM on Prod I get: perl dbiTest.pl 2014/03/13 11:18:06 testString = Test string, testDate = Mar 13 2014 11:18AM DBD::Sybase::st execute failed: OpenClient message: LAYER = (0) ORIGIN = (0) SEVERITY = (78) NUMBER = (51) Message String: Attempt to initiate a new Adaptive Server operation with results pending DBD::Sybase::st execute failed: OpenClient message: LAYER = (0) ORIGIN = (0) SEVERITY = (78) NUMBER = (51) Message String: Attempt to initiate a new Adaptive Server operation with results pending
UPDATE:
Setting $dbh->{syb_flush_finish} = 1;
allows the dev system to run finish and not break.
This does fix my problem, but does not explain what is happening.
回答1:
Your version of DBD::Sysbase is way out of date. According to the changelog, a fix was added in v1.01 (released all the way back in September, 2003!) to
Automatically
finish()
statement handles if they are re-executed before all the rows have been fetched.
There was another fix in v1.06 (August, 2005) because finish
sometimes failed to clean up the associated database handle. There have been many, many changes since v1.00, so upgrade to the latest version and drop the calls to finish
.
来源:https://stackoverflow.com/questions/22364932/perl-dbi-when-to-close-prepared-statements