Pyodbc Транзакции в Django View фиксируют изменения, несмотря на попытки отката

Я работаю над Django-приложением, в котором использую pyodbc для подключения к базе данных AWS RDS SQL Server. Мне нужно запустить серию необработанных SQL-запросов (включая INSERT, UPDATE, DELETE, DISABLE или ENABLE триггера и т. д.) в виде транзакции, гарантируя, что никакие изменения не будут зафиксированы, если во время выполнения возникнет какая-либо ошибка. Однако я столкнулся с проблемой, когда изменения фиксируются в базе данных даже при возникновении ошибки, и я вызываю rollback().

Вот что я пробовал до сих пор:

Установите autocommit = False в соединении pyodbc, чтобы предотвратить автоматические фиксации. Использовали несколько курсоров для разных SQL-запросов, все под одним и тем же соединением с autocommit = False. Обернул представление Django с @transaction.non_atomic_requests, чтобы отключить стандартную обработку транзакций в Django. Также попробовал обернуть код с transaction.atomic(), чтобы посмотреть, поможет ли управление транзакциями в Django. Несмотря на все эти усилия, изменения все равно фиксируются в базе данных после возникновения ошибки в представлении Django, но когда я запускаю точно такой же код в автономном скрипте на Python (вне Django), откат работает отлично, и никакие изменения не фиксируются.

Вот упрощенная версия кода, который я использую:

import pyodbc
from django.conf import settings
from django.db import transaction

@transaction.non_atomic_requests  # Tried this to disable Django transaction wrapping
def my_view(request):
    connection = pyodbc.connect(settings.DATABASE_CONNECTION_STRING, autocommit=False)
    try:
        # Start transaction
        cursor1 = connection.cursor()
        cursor1.execute("UPDATE my_table SET column1 = 'value1' WHERE id = 1")

        cursor2 = connection.cursor()
        cursor2.execute("INSERT INTO my_table (column1) VALUES ('value2')")

        # This line will cause an error
        cursor3 = connection.cursor()
        cursor3.execute("INVALID SQL STATEMENT")  # This should trigger a rollback

        # Commit if all queries succeed
        connection.commit()

    except Exception as e:
        print("Error occurred, rolling back transaction:", e)
        connection.rollback()  # This should prevent any changes from being committed

    finally:
        cursor1.close()
        cursor2.close()
        cursor3.close()
        connection.close()

Краткое описание проблемы:

Когда я запускаю этот код как отдельный скрипт вне Django, он работает, как и ожидалось, без фиксации изменений при возникновении ошибки. Когда я запускаю тот же код внутри представления Django, изменения фиксируются даже при возникновении ошибки.

Дополнительные примечания:

Я знаю, что Django по умолчанию оборачивает представления в транзакции, поэтому я попробовал @transaction.non_atomic_requests, чтобы предотвратить обработку транзакций Django. Я подтвердил, что autocommit установлен в False для pyodbc-соединения.

Вопросы:

1) Есть ли что-то в жизненном цикле запроса Django или промежуточном ПО, что может мешать моей ручной обработке транзакций?

2) Есть ли способ убедиться, что функция rollback() работает правильно в этой установке?

3) Есть ли в Django какие-либо специфические настройки или подходы, которые могут предотвратить фиксацию этих изменений?

Буду признателен за любое руководство по этому вопросу. Спасибо!

Вернуться на верх