2016-11-18 8 views
8

Мои SQLAlchemy приложение (работает поверх MariaDB) включает в себя две модели MyModelA и MyModelB, где последний является ребенком-запись бывший:Ошибка в SQLAlchemy Откат после исключения БД?

class MyModelA(db.Model): 
    a_id = db.Column(db.Integer, nullable=False, primary_key=True) 
    my_field1 = db.Column(db.String(1024), nullable=True) 

class MyModelB(db.Model): 
    b_id = db.Column(db.Integer, nullable=False, primary_key=True) 
    a_id = db.Column(db.Integer, db.ForeignKey(MyModelA.a_id), nullable=False) 
    my_field2 = db.Column(db.String(1024), nullable=True) 

Эти случаи MyModelA и MyModelB что я создаю:

>>> my_a = MyModelA(my_field1="A1") 
>>> my_a.aid 
1 
>>> MyModelB(a_id=my_a.aid, my_field2="B1") 

у меня есть следующий код, который удаляет экземпляр MyModelA где a_id==1:

db.session.commit() 
try: 
    my_a = MyModelA.query.get(a_id=1) 
    assert my_a is not None 
    print "#1) Number of MyModelAs: %s\n" % MyModelA.query.count() 
    db.session.delete(my_a) 
    db.session.commit() 
except IntegrityError: 
    print "#2) Cannot delete instance of MyModelA because it has child record(s)!" 
    db.session.rollback() 
    print "#3) Number of MyModelAs: %s\n" % MyModelA.query.count() 

Когда я запускаю этот код взглянуть на неожиданные результаты, которые я получаю:

#1) Number of MyModelAs: 1 
#2) Cannot delete instance of MyModelA because it has child record(s)! 
#3) Number of MyModelAs: 0 

удалить якобы не удается, и DB генерирует исключение, которое вызывает откат. Однако даже после откат количество строк в таблице указывает на то, что строка, которая предположительно не была удалена, на самом деле ушла !!!

Почему это происходит? Как я могу это исправить? Это похоже на ошибку в SQLAlchemy.

+0

Вы проверили, отключена ли автоматическая защита? –

+0

та же идея: вы говорите, что используете MariaDB. Какой двигатель в MariaDB? MyISAM не поддерживает транзакции, поэтому он всегда находится в режиме «autocommit» –

+0

Каковы запросы, генерируемые sqlalchemy? У 'SELECTs' есть' FOR UPDATE'? –

ответ

0

TL; DR Ваша проблема может быть связана с отсутствием явной декларации отношений.

Например, here есть образец отношений объектов. В дополнение к использованию поля ForeignKey класс явно использует директиву relationship для определения этого соединения. В session API documentation, появится следующий текст:

ссылки на объекты должны быть построены на уровне объекта, а не на внешнем ключевом уровне

Что может означать на путь SQLAlchemy для управления отношений. Я не очень хорошо разбираюсь в основных механизмах, но возможно, что так происходит. Ваша сессия включает только объект MyModelA. Поскольку вы не использовали директиву relationship() в определении MyModelB, объекты типа MyModelA не знают, что какой-либо другой объект может ссылаться на них через ForeignKey. Следовательно, когда сеанс собирается совершить, он не осознает тот факт, что удаление объекта влияет на какой-то другой объект MyModelB, и его механизм транзакций не учитывает это. Я предлагаю, чтобы явное добавление отношений могло помешать этому поведению.

 Смежные вопросы

  • Нет связанных вопросов^_^