I am using Doctrine together with Symfony (Doctrine 2.5.4, Docrine Symfony
Bundle 1.6.2 and Symfony 3.0.7). I have a project that I have not touched
for about a year. I now upgraded Symfony and Doctrine to the aforementioned
versions and now I suffer from some kind of "regression" bug.
I rely on the implicit transaction handling provided by the Doctrine ORM
EntityManager. I know for sure that it worked before the upgrade but now I
get a PDO exception "There is no active transaction".
Assume the case I have an entity that is supposed to be deleted from
database but there are still foreign keys that prohibited the particular
row from being deleted. Before the upgrade Doctrine
1. started a transaction,
2. tried to delete the row from the database,
3. committed the transaction
4. did a rollback and then
5. threw an exception that the row could not be deleted to due foreign
key constraints
Now, after the upgrade Doctrine
1. starts a transaction,
2. tries to delete the row from the database,
3. commits the transaction
4. tries a rollback and then
5. throws an exception that there is no active transaction
What?! I say "tries a rollback" in step 4 because the ROLLBACK command
never reaches my SQL server.
This is my PHP code
/**
* @Route("/RentalUnit/{id}", name="hekdb_delete_rental_unit",
requirements={"id": "\d+"})
* @Method({"DELETE"})
*/
public function deleteRentalUnit( Request $request, $id ) {
$id = intval( $id );
try {
$em = $this->getDoctrine()->getManager();
$rep = $em->getRepository( 'HEKdbBundle:RentalUnit' );
$unit = $rep->find( $id );
$em->remove( $unit );
$em->flush();
} catch( ORMException $e ) {
throw new InternalServerErrorHttpException( null, $e->getMessage(),
$e );
}
}
Nothing, special about it. This code relies on implicit transaction
handling by $em->flush() and has worked before.
The stacktrace is
1. at PDO->rollBack() in
vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php at line 1278
2. at Connection->rollBack() in
vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php at line 413
3. at UnitOfWork->commit(null) in
vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php at line 356
4. at EntityManager->flush() in
src/HEK/HEKdbBundle/Controller/RentalUnitController.php at line 289
5. at RentalUnitController->deleteRentalUnit( object(Request), '175' )
In "vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php" I see
public function commit($entity = null) {
// ... lines left out
// HERE a transaction is started
$conn->beginTransaction();
try {
// ... lines left out
if ($this->entityDeletions) {
for ($count = count($commitOrder), $i = $count - 1; $i >= 0 &&
$this->entityDeletions; --$i) {
$this->executeDeletions($commitOrder[$i]);
}
}
// Throws the expected execption due to violated foreign key
constraints
$conn->commit();
} catch (Exception $e) {
$this->em->close();
// The following line throws another exception inside the exception
// handler. WHY?! :-(
$conn->rollback();
$this->afterTransactionRolledBack();
throw $e;
}
}
Hence, a transaction should be started. According to the Symfony Debug
Toolbar the following SQL statements are
executed:
1. SELECT t0.id AS id_1, t0.rev AS rev_2, t0.display_name AS
display_name_3, t0.period AS period_4, t0.capacity AS capacity_5,
t0.comment AS comment_6 FROM rental_unit t0 WHERE t0.id = ?
Parameters: [175]
2. "START TRANSACTION"
Parameters: { }
3. DELETE FROM rental_unit WHERE id = ?
Parameters: [175]
4. "COMMIT"
Parameters: { }
5. "ROLLBACK"
Parameters: { }
This looks totally fine and actually there is a transaction and even a
rollback. However, I think the rollback has never really happened, because
the exception occurred first. My server logs are
2016-06-28 19:21:39 CEST LOG: 00000: connection received: host=[local]
2016-06-28 19:21:39 CEST LOCATION: BackendInitialize, postmaster.c:4134
2016-06-28 19:21:39 CEST LOG: 00000: connection authorized: user=hekdbui
database=matthias.nagel_hekdb
2016-06-28 19:21:39 CEST LOCATION: PerformAuthentication, postinit.c:258
2016-06-28 19:21:39 CEST LOG: 00000: execute <unnamed>: SET NAMES 'UTF8'
2016-06-28 19:21:39 CEST LOCATION: exec_execute_message, postgres.c:1932
2016-06-28 19:21:39 CEST LOG: 00000: execute <unnamed>: SELECT t0.id AS
id_1, t0.rev AS rev_2, t0.display_name AS display_name_3, t0.period AS
period_4, t0.capacity AS capacity_5, t0.comment AS comment_6 FROM
rental_unit t0 WHERE t0.id = $1
2016-06-28 19:21:39 CEST DETAIL: parameters: $1 = '175'
2016-06-28 19:21:39 CEST LOCATION: exec_execute_message, postgres.c:1932
2016-06-28 19:21:39 CEST LOG: 00000: statement: BEGIN
2016-06-28 19:21:39 CEST LOCATION: exec_simple_query, postgres.c:914
2016-06-28 19:21:39 CEST LOG: 00000: execute <unnamed>: DELETE FROM
rental_unit WHERE id = $1
2016-06-28 19:21:39 CEST DETAIL: parameters: $1 = '175'
2016-06-28 19:21:39 CEST LOCATION: exec_execute_message, postgres.c:1932
2016-06-28 19:21:39 CEST LOG: 00000: statement: COMMIT
2016-06-28 19:21:39 CEST LOCATION: exec_simple_query, postgres.c:914
2016-06-28 19:21:39 CEST ERROR: 23503: update or delete on table
"rental_unit" violates foreign key constraint
"rental_unit_allocation_rental_unit_id_fkey" on table
"rental_unit_allocation"
2016-06-28 19:21:39 CEST DETAIL: Key (id, period)=(175,
[2016-06-26,infinity)) is still referenced from table
"rental_unit_allocation".
2016-06-28 19:21:39 CEST LOCATION: ri_ReportViolation, ri_triggers.c:3316
2016-06-28 19:21:39 CEST STATEMENT: COMMIT
2016-06-28 19:25:04 CEST LOG: 00000: checkpoint starting: time
2016-06-28 19:25:04 CEST LOCATION: LogCheckpointStart, xlog.c:7957
2016-06-28 19:25:05 CEST LOG: 00000: checkpoint complete: wrote 3 buffers
(0.0%); 0 transaction log file(s) added, 0 removed, 0 recycled; write=0.201
s, sync=0.001 s, total=0.206 s; sync files=3, longest=0.001 s,
average=0.000 s
2016-06-28 19:25:05 CEST LOCATION: LogCheckpointEnd, xlog.c:8052
This also looks very sane except that I do not see the "ROLLBACK" message.
So, what is causing this error? Thank, you.
--
You received this message because you are subscribed to the Google Groups
"doctrine-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/doctrine-user.
For more options, visit https://groups.google.com/d/optout.