Demonstrate deadlock involving transactions and prepared statements #802
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Gorm can deadlock in the following scenario:
SELECT 1
SELECT 1
In step (3), Caller C will try to prepare the statement
SELECT 1
, since no one else is currently preparing that statement. In order to do that, Caller C needs to acquire a database connection. But they are all currently in use, so Caller C waits on the pool.In step (4), the holders of all the connections in the pool will wait for the statement
SELECT 1
to be prepared.This creates a deadlock: Caller C is waiting on a connection, but all connections are waiting on Caller C.
This can happen in normal Gorm user code just by using
db.Transaction
when the underlying database uses a connection pool. No trickery is needed to reproduce this bug. When it occurs, the entire application ceases to make progress forever.I'm observing this in prod on Gorm v1.25.6, and can reproduce it in latest Gorm as demonstrated in this playground.
Here is an alternate single-file example, which can emit a Goroutine call stack to confirm that the situation is well and truly deadlocked:
https://gist.github.com/wchargin/9b48fd98d95299640a14fff2882d2b80