Home > other >  Transaction commit failed because the transaction has been marked for rollback only
Transaction commit failed because the transaction has been marked for rollback only

Time:02-10

#PHP, #Doctrine, #Symfony

I had a problem with the transaction and would be happy if I found a solution how it makes it run properly.

I had a transaction which send data to API and if an exception was thrown It rollback created data from DB and flushed exception message after rollback to DB. If everything was OK I did commit.

It was called in 2 locations

  1. in cron module (it was always ran first)
  2. in controller (if error was thrown, admin could resend it)

In the cron module everything worked fine but if I wanted to rerun the transaction because it failed in the cron I got error with

"Transaction commit failed because the transaction has been marked for rollback only."

I debug it and found that after rollback

I had $this->transactionNestingLevel set to 1 but $this->isRollbackOnly was set on TRUE

so that's why that exception was thrown. Is something it needs to be added above?


$this->em->beginTransaction();

$this->em->commit();

$this->em->rollback();

access to $this->isRollbackOnly is private. Need to be false I guess but don't know how I could make it :(

/**
     * Cancels any database changes done during the current transaction.
     *
     * @return bool
     *
     * @throws ConnectionException If the rollback operation failed.
     */
    public function rollBack()
    {
        if ($this->transactionNestingLevel === 0) {
            throw ConnectionException::noActiveTransaction();
        }

        $connection = $this->getWrappedConnection();

        $logger = $this->_config->getSQLLogger();

        if ($this->transactionNestingLevel === 1) {
            if ($logger) {
                $logger->startQuery('"ROLLBACK"');
            }

            $this->transactionNestingLevel = 0;
            $connection->rollBack();
            $this->isRollbackOnly = false;
            if ($logger) {
                $logger->stopQuery();
            }

            if ($this->autoCommit === false) {
                $this->beginTransaction();
            }
        } elseif ($this->nestTransactionsWithSavepoints) {
            if ($logger) {
                $logger->startQuery('"ROLLBACK TO SAVEPOINT"');
            }

            $this->rollbackSavepoint($this->_getNestedTransactionSavePointName());
            --$this->transactionNestingLevel;
            if ($logger) {
                $logger->stopQuery();
            }
        } else {
            $this->isRollbackOnly = true;
            --$this->transactionNestingLevel;
        }

        return true;
    }

doctrine rollback code

CodePudding user response:

  •  Tags:  
  • Related