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 какие-либо специфические настройки или подходы, которые могут предотвратить фиксацию этих изменений?
Буду признателен за любое руководство по этому вопросу. Спасибо!