Sergei_Erjemin
@Sergei_Erjemin
Улыбайся, будь самураем...

Почему в django не срабатывают «with transaction.atomic()» при записи к несколько разных БД?

Перегоняю данные из одной (удалённой) базы данных в локальную. Удалённая -- "old_z". Примерно такой код:
q_ext_orders = TbExtOrder.objects.using("old_z").filter(bExported=False)
order_error = 0
for ext_order in q_ext_orders:
    try:
        with transaction.atomic():
            int_order_archive = TbOrderArchive(
                szOrderCheck=ext_order.szOrderCheck,
                iAccount=ext_order.iAccount,
                iPay=ext_order.iPay
                # и еще куча полей
            )
            int_order_archive.save()
            ext_order.bExported = True
            ext_order.save(using="old_z")
            print_log(msg="IMPORT ORDER %s" % (ext_order.szOrderCheck,), status="OK")
    except DatabaseError:
        ext_order.bExported = False
        order_error += 1
        print_log(msg="IMPORT ORDER %s" % (ext_order.szOrderCheck,), status="ERR1")
    except IntegrityError:
        ext_order.bExported = False
        order_error += 1
        print_log(msg="IMPORT ORDER %s" % (ext_order.szOrderCheck,), status="ERR2")

Все это обёрнуто в циклы, и ещё в циклы... и проверки стоят, что order_error != 0...

Но при принудительном завершении кода (перезагрузка процесса, например) может не происходить записи в локальную базу данных. Т.е. для удалённой БД, кусочек кода:
ext_order.bExported = True
ext_order.save(using="old_z")
выполняется. А в локальной БД кусочек кода:
int_order_archive = TbOrderArchive(
    szOrderCheck=ext_order.szOrderCheck,
    iAccount=ext_order.iAccount,
    iPay=ext_order.iPay
    # и еще куча полей
)
int_order_archive.save()
не выполняется... При этом, как видим, обе записи (ext_order.save(using="old_z") и int_order_archive.save()) внутри with transaction.atomic():!
Причём в именно в порядке: сначала записать в локальную базу, а после записать в удалённую!! Но мало того, что транзакция не работает и исключения не отрабатываются, так ещё и в удалённую базу пишет, а в локальную нет! Т.е. кусок кода написанный выше не срабатывает, а код под ним срабатывает!

Кто-нибудь с таким сталкивался?

P.S. Пробовал и в основном процессе Django исполнять, и в параллельном под django-backgrond-tasks -- результат один. Т.е. результат не предсказуем. Может после возобновления работы корректно записаться в обе базы, а может и нет.
  • Вопрос задан
  • 116 просмотров
Решения вопроса 1
sergey-gornostaev
@sergey-gornostaev Куратор тега Django
Седой и строгий
Странный вопрос. Очевидно, транзакции существуют в пределах одной БД. У вас транзакция локальной БД открывается в контекстном блоке и, естественно, при принудительном завершении кода откатывается, а операции с базой old_z выполняются без транзакции, поэтому и отката никакого нет.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы