Skip to content

[12.x] Rollback lingering PDO transaction before retrying on commit deadlock#58906

Merged
taylorotwell merged 1 commit intolaravel:12.xfrom
dxnter:fix/rollback-pdo-transaction-on-commit-deadlock
Feb 19, 2026
Merged

[12.x] Rollback lingering PDO transaction before retrying on commit deadlock#58906
taylorotwell merged 1 commit intolaravel:12.xfrom
dxnter:fix/rollback-pdo-transaction-on-commit-deadlock

Conversation

@dxnter
Copy link
Contributor

@dxnter dxnter commented Feb 18, 2026

Fixes #58894

When DB::transaction() retries after a deadlock during commit, the PDO connection may still have an active (implicit) transaction because MySQL keeps autocommit disabled for the session. The next beginTransaction() call then throws PDOException: "There is already an active transaction".

This adds a simple $pdo->rollBack() in handleCommitTransactionException before returning for retry, matching how handleTransactionException already cleans up PDO state through performRollback() when deadlocks occur during the callback.

$mock = $this->getMockConnection([], $pdo);
$pdo->expects($this->exactly(3))->method('commit')->will($this->throwException(new DatabaseConnectionTestMockPDOException('Serialization failure', '40001')));
$pdo->expects($this->exactly(3))->method('beginTransaction');
$pdo->expects($this->never())->method('rollBack');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels a bit spooky to me we used to explicitly test that rollBack was specifically not called. I wonder why? Did we not roll back for a reason?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://github.com/laravel/framework/pull/29067/changes relevant PR where it says the transaction is rolled back automatically and we shouldn't roll back again

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#29067 (changes) relevant PR where it says the transaction is rolled back automatically and we shouldn't roll back again

That is correct for the database-level transaction, MySQL does roll it back on deadlock.

The problem is that PDO::beginTransaction() also disables autocommit for the session. After MySQL rolls back the deadlocked transaction, autocommit remains off, so MySQL implicitly starts a new transaction. PDO then sees an active transaction on the next beginTransaction() call and throws the exception

@taylorotwell taylorotwell merged commit f344339 into laravel:12.x Feb 19, 2026
72 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

"There is already an active transaction" when using DB::transaction

2 participants

Comments