Найти - Пользователи
Полная версия: Проблема с транзакциями
Начало » Pyramid / Pylons / TurboGears » Проблема с транзакциями
1 2
dorian
Пытаемся сделать множественный insert в базу. Если данные не корректны - проблема с индексами, типами и тд., то такие строки нам не нужны.
Получился код представления:
@view_config(route_name="loader",
                 request_method="POST",
                 renderer="json")
    def _loader(self):
        # ........
        for i, el in enumerate(els):
            try:
                # .......
                ask = page.xpath(el.ask_xpath)
                bid = page.xpath(el.bid_xpath)
                r = DBSession.query(Rate).filter(Rate.date==datetime.date.today()).first()
                if r: DBSession.delete(r)
                r = Rate(ask = ask, bid = bid)
                DBSession.add(rate)
            except Exception, e:
                pass
            finally:
                self.request.session.flash(i, queue='loader');
        return dict(parse_progress=self.request.session.pop_flash('loader'))

Выполнение кода приводит к ошибке
InvalidRequestError: This Session's transaction has been rolled back due to a previous exception during flush. To begin a new transaction with this Session, first issue Session.rollback().

Если ставим DBSession.rollback() в блок исключений, то получаем
ResourceClosedError: The transaction is closed

Похожий вопрос задавался здесь, но предложенные решения не рабочие
sank
Такое ощущение, что в каждой итерации начинается новая транзакция, т.к. ошибка “ To begin a new transaction with this Session, first issue Session.rollback()” появляется тогда, когда есть незакрытая транзакция и какая-то новая транзакция пытается что-то делать в базе.
Может как-то явно попробовать начать транзакцию и в ней все изменения делать?
Lexander
После DBSession.rollback() в обработке исключения нужно создать новый объект DBSession.
Но это больше похоже на устранение последствий, а не причин.

После изменения модели нужно делать DBSession.flush(), чтобы обновить состояние модели.
Проверьте состояние DBSession.autoflush. Должно быть True.
И только после обработки всех данных закоммитить транзакцию во внешнем блоке try…except (сейчас у вас в коде его нет).
dorian
Lexander
После DBSession.rollback() в обработке исключения нужно создать новый объект DBSession.Но это больше похоже на устранение последствий, а не причин.После изменения модели нужно делать DBSession.flush(), чтобы обновить состояние модели.Проверьте состояние DBSession.autoflush. Должно быть True.И только после обработки всех данных закоммитить транзакцию во внешнем блоке try…except (сейчас у вас в коде его нет).

Перед тем как создавалась тема, были испробованы:
DBSession.flush()+DBSession.rollback() - ResourceClosedError: The transaction is closed
transaction.commit()+transaction.abort() - на первой итерации закрывается транзакция
автокомит и автофлуш включены

sank
Такое ощущение, что в каждой итерации начинается новая транзакция, т.к. ошибка “ To begin a new transaction with this Session, first issue Session.rollback()” появляется тогда, когда есть незакрытая транзакция и какая-то новая транзакция пытается что-то делать в базе.Может как-то явно попробовать начать транзакцию и в ней все изменения делать?
Вся печаль в том, что закомитить можно через transaction.commit(), но как и писал выше, это автоматом прекращает выполнение кода.
sank
Дык вы явно транзакцию запускать пробовали?
connection = engine.connect()
trans = connection.begin()
try:
    r1 = connection.execute(table1.select())
    connection.execute(table1.insert(), col1=7, col2='this is some data')
    trans.commit()
except:
    trans.rollback()
    raise
стырено отсюда: http://docs.sqlalchemy.org/en/rel_0_7/core/connections.html#using-transactions
Я сам по причине лени не пробовал, но думается мне надо туда копать …
Если не поможет, то, думаю, нужно явный execute делать, вместо использования объектов.
Либо курить доку и разбираться чо там ORM делает в случае появления SQL-ных эксепшенов.

… у вас ситуация немного не штатная. Вы хотите на эксепшене ничего не делать, продолжая транзакцию, поэтому тут ORM может вам палки в колёса ставить.
Lexander
sank
Дык вы явно транзакцию запускать пробовали?
При условии включенного автокоммита, если явная транзакция сработает, значит либо баг в Алхимии, либо ошибка в алгоритме.

Что выдает монитор операций СУБД?
Возможно, какие-то команды лишние идут.

Lexander
Плюс я бы проверил connection.info перед каждой операцией.
bismigalis
не оно? http://stackoverflow.com/a/575711/1449350
dorian
bismigalis
не оно? http://stackoverflow.com/a/575711/1449350
нет
в общем пришлось проверять каждое значение, иного выхода не нашлось. Проблема судя по всему в pyramid_tm ибо этот код вне пирамиды и без pyramid_tm работает как нужно.
bismigalis
dorian
в общем пришлось проверять каждое значение

А можно поподробнее, а то хочется понять в чем там собака была
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB