python - 数据库异常后 SQLAlchemy 回滚中的错误?

标签 python mysql sqlalchemy flask-sqlalchemy rollback

我的 SQLAlchemy 应用程序(在 MariaDB 上运行)包括两个模型 MyModelAMyModelB,其中后者是前者的子记录:

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)

这些是我创建的 MyModelAMyModelB 的实例:

>>> 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

删除应该会失败,数据库会抛出异常导致回滚。然而,即使在回滚之后,表中的行数表明该行 - 应该没有被删除 - 实际上已经消失了!!!

为什么会这样?我怎样才能解决这个问题?这似乎是 SQLAlchemy 中的错误。

最佳答案

长话短说 您的问题可能与缺少明确的关系声明有关。

例如,here有一个对象关系的样本。除了使用 ForeignKey 字段外,该类还明确使用 relationship 指令来定义该连接。在session API documentation ,出现以下文本:

object references should be constructed at the object level, not at the foreign key level

这可能暗示了 SQLAlchemy 管理关系的方式。我对底层机制不是很熟悉,但这可能就是发生的事情。您的 session 仅包含 MyModelA 对象。由于您没有在 MyModelB 的定义中使用 relationship() 指令,因此 MyModelA 类型的对象不知道其他一些对象可能通过 ForeignKey 引用它们。因此,当 session 即将提交时,它不知道删除该对象会影响其他一些 MyModelB 对象这一事实,并且它的事务机制没有考虑到这一点。 我建议明确添加关系可能会阻止这种行为。

关于python - 数据库异常后 SQLAlchemy 回滚中的错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40681371/

相关文章:

mysql - 如何在带有过滤器的sqlalchemy中使用dateadd?

python - 使用 SQLalchemy 和 Marshmallow 加载一对多关联属性

java - 以编程方式从java调用Linux终端中的python脚本

python - 在函数内编写循环会改变输出

mysql - 在 mysql 中使用简单的内部连接时遇到问题

java - 如何从 MySQL DATETIME 转换为 java.time.Instant 并以系统默认时区显示给用户?

php - Codeigniter 在数据透视表上连接 2 个表

python - 从 sqlalchemy Session 获取一个 mysql 线程 id

python - 加载大的 .npy 文件导致 python 停止工作

Python程序绘制一系列化学 react ,其唯一节点仅出现一次