﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
34523	Model.objects.update_or_create method sometimes raises TransactionManagementError	gatello-s	nobody	"When using with **myisam**-only database the method **update_or_create** can occur a TransactionManagementError exception if creating a record was unsuccessful (because of IntegrityError, for example the record with a same primary key was already created by another process).  

The problem has started after the upgrading from Django 3.2.16 to 4.1.7

The test below just simulates a parallel insertion of the record with the same PK^ 

Database backend: mariadb server (10.5.19) (default-storage-engine is **myisam**).

This test works fine with Django 3.2.16 and fails on Django 4.1.7+:
{{{
class TransactionManagementErrorTest(TestCase):

    class TestModel(models.Model):
        managed = False
        field = models.IntegerField(null=True)

        class Meta(object):
            db_table = 'test_model_update_or_create'

        class QuerySet(models.QuerySet):
            def create(self, **kwargs):
                super().create(**kwargs)  # simulate parallel insertion
                return super().create(**kwargs)
    
        class TestModelManager(models.Manager.from_queryset(QuerySet)):
            pass

        objects = TestModelManager()

    def exec_sql(self, sql):
        from django.db import connections, router
        db = router.db_for_write(self.TestModel)
        connection = connections[db]
        connection.cursor().execute(sql)

    def setUp(self):
        super().setUp()
        self.exec_sql(
            'CREATE TABLE IF NOT EXISTS `test_model_update_or_create` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `field` integer NULL);'
        )

    def tearDown(self):
        self.exec_sql(
            'DROP TABLE IF EXISTS `test_model_update_or_create`;'
        )
        super().tearDown()

    def test_update_or_create(self):
        self.TestModel.objects.update_or_create(id=1, defaults={'field': 2})
}}}

**Exception**: django.db.transaction.TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block.

**Failure stack:**
{{{
Traceback (most recent call last):
  File ""/home/alex/workspace/test_TransactionManagementError/mysite/polls/tests.py"", line 47, in test_update_or_create
    self.TestModel.objects.update_or_create(id=1, defaults={'field': 2})
  File ""/home/alex/workspace/test_TransactionManagementError/.venv/lib/python3.9/site-packages/django/db/models/manager.py"", line 87, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File ""/home/alex/workspace/test_TransactionManagementError/.venv/lib/python3.9/site-packages/django/db/models/query.py"", line 949, in update_or_create
    obj, created = self.select_for_update().get_or_create(defaults, **kwargs)
  File ""/home/alex/workspace/test_TransactionManagementError/.venv/lib/python3.9/site-packages/django/db/models/query.py"", line 926, in get_or_create
    return self.get(**kwargs), False
  File ""/home/alex/workspace/test_TransactionManagementError/.venv/lib/python3.9/site-packages/django/db/models/query.py"", line 633, in get
    num = len(clone)
  File ""/home/alex/workspace/test_TransactionManagementError/.venv/lib/python3.9/site-packages/django/db/models/query.py"", line 380, in __len__
    self._fetch_all()
  File ""/home/alex/workspace/test_TransactionManagementError/.venv/lib/python3.9/site-packages/django/db/models/query.py"", line 1881, in _fetch_all
    self._result_cache = list(self._iterable_class(self))
  File ""/home/alex/workspace/test_TransactionManagementError/.venv/lib/python3.9/site-packages/django/db/models/query.py"", line 91, in __iter__
    results = compiler.execute_sql(
  File ""/home/alex/workspace/test_TransactionManagementError/.venv/lib/python3.9/site-packages/django/db/models/sql/compiler.py"", line 1560, in execute_sql
    cursor.execute(sql, params)
  File ""/home/alex/workspace/test_TransactionManagementError/.venv/lib/python3.9/site-packages/django/db/backends/utils.py"", line 67, in execute
    return self._execute_with_wrappers(
  File ""/home/alex/workspace/test_TransactionManagementError/.venv/lib/python3.9/site-packages/django/db/backends/utils.py"", line 80, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File ""/home/alex/workspace/test_TransactionManagementError/.venv/lib/python3.9/site-packages/django/db/backends/utils.py"", line 83, in _execute
    self.db.validate_no_broken_transaction()
  File ""/home/alex/workspace/test_TransactionManagementError/.venv/lib/python3.9/site-packages/django/db/backends/base/base.py"", line 531, in validate_no_broken_transaction
    raise TransactionManagementError(
django.db.transaction.TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block.
}}}"	Bug	new	Database layer (models, ORM)	4.2	Normal		update_or_create TransactionManagementError	Anton Plotkin	Unreviewed	0	0	0	0	0	0
