DBI begin_work doesn't work with stored proced

2019-02-27 09:12发布

问题:

I am trying to make a call to a stored procedure from with in a transaction in its simplified form:

my $dbh= DBI->connect(............  );  

my $sth = $dbh->prepare("call sp_get_workitems (1,1)");
$dbh->begin_work  or die $dbh->errstr;
$sth->execute();
my ($result)= $sth->fetchrow_array();

$dbh->commit;

this gives the following error :

DBD driver has not implemented the AutoCommit attribute

If I replace the begin_work statement with $dbh->{'AutoCommit'} = 0; (before or after the prepare), I get this error:

DBD::mysql::db commit failed: Commands out of sync; you can't run this command now

If I replace the stored procedure call with a simple select statement it all works fine.

The stored procedure includes a number of updates and finishes with a select statement. Of course it would be easier if I could handle the transaction within the procedure put I need to action some perl code if rollback occurs.

I'm using ActivePerl on windows 7 and an amazon cloud instance running Centos with DBI 1.616 installed, this occurs on both.

Should this work or is there a way around it?

Thanks

回答1:

Make sure you explicitly finish() every executed prepared procedure CALL before you explicitly commit() the transaction. E.g.,

$sth->finish;
$sth->commit();

This appears to be a bug to me, given the typical semantics of finish(). Multiple result sets, calling more_results, etc. did not matter.

DBD 1.616, DBD::mysql 4.020 and MySQL 5.5.19.



回答2:

If you are using AutoCommit => 0, then you don't need begin_work(). Everything is in a transaction until you commit() or rollback(). Then a new transaction begins.

Actually, you should connect with RaiseError => 1, because you should get an error on begin_work() when AutoCommit is 0. From the fine docs:

If AutoCommit is already off when begin_work is called then it does nothing except return an error. If the driver does not support transactions then when begin_work attempts to set AutoCommit off the driver will trigger a fatal error.

Also, what version of DBD::mysql are you using? I think the latest version does implement AutoCommit.