A middleware to automatically retry requests in the case of a deadlock.
Requires: Django >= 1.11, postgres as database connection, ATOMIC_REQUESTS enabled.
Deadlocks are a common problem with web applications. A deadlock occurs when multiple agents are waiting on locks held by the each other in a way that cannot be resolved. As an example:
T1 | T2
A --> B
B --> A
Transaction 1 locks A, transaction 2 locks B. When transaction 1 tries to lock B, it waits for transaction 2 which holds the lock. When transaction 2 tries to lock A, these transactions enter a deadlock where both transactions are both waiting on eachother. The deadlock detection in the database will kill one of the two transactions at this point.
The simple solution for the killed transaction is to simply retry. If transaction 2 is killed, the resulting order will be:
T1 | T2
A -->
B -->
--> B
--> A
Deadlocks are a classic problem in transactional databases, but they are not dangerous unless they are so frequent that you cannot run certain transactions at all. Normally, you must write your applications so that they are always prepared to re-issue a transaction if it gets rolled back because of a deadlock.
This middleware automatically retries requests that fail due to a deadlock.
To setup:
- Add
deadlock_middleware
toINSTALLED_APPS
. - Add
deadlock_middleware.DeadlockRetryMiddleware
toMIDDLEWARES
. - Add
DEADLOCK_RETRY_ATTEMPTS
(int) to djangosettings.py
. The default is 2 (1 retry).