#34523: Model.objects.update_or_create method sometimes raises
TransactionManagementError
-------------------------------------+-------------------------------------
Reporter: gatello-s | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: 4.2
(models, ORM) |
Severity: Normal | Resolution:
Keywords: update_or_create | Triage Stage:
TransactionManagementError | Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Simon Charette):
The changes in 331a460f8f2e4f447b68fba491464b68c9b21fd1 are semantically
correct but they had the side effect of making
`BaseDatabaseWrapper._savepoint_allowed` return `False` and thus
`savepoint()` creation always return `None`.
Since `update_or_create` uses nested `atomic` to handle possible integrity
errors it was previously taking the savepoints created by MySQL as way to
mark back the connection as usable. Now that savepoints are not returned
anymore it assumes the outer atomic block is tainted as well and raise
`TransactionManagementError`.
I'm not sure why `Atomic.__enter__` and `__exit__` are not simply noops
when transactions are determined to not be supported instead of trying to
handle all kind of nesting and savepoint combinations.
{{{#!diff
diff --git a/django/db/transaction.py b/django/db/transaction.py
index 4150cbcbbe..28229f8f3a 100644
--- a/django/db/transaction.py
+++ b/django/db/transaction.py
@@ -181,6 +181,8 @@ def __init__(self, using, savepoint, durable):
def __enter__(self):
connection = get_connection(self.using)
+ if not connection.features.supports_transactions:
+ return
if (
self.durable
@@ -223,6 +225,8 @@ def __enter__(self):
def __exit__(self, exc_type, exc_value, traceback):
connection = get_connection(self.using)
+ if not connection.features.supports_transactions:
+ return
if connection.in_atomic_block:
connection.atomic_blocks.pop()
}}}
As for the heuristics to determine if a backend supports transaction the
situation is definitely weird on MySQL as supports is on a per-table basis
and `default_storage_engine` is really just a guess at that.
--
Ticket URL: <https://code.djangoproject.com/ticket/34523#comment:13>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/01070187cb6d4824-f2855de3-694f-49f1-a603-4302f736fc96-000000%40eu-central-1.amazonses.com.