SQLAlchemy为何会回滚

3 投票
2 回答
6950 浏览
提问于 2025-04-17 20:39

我正在使用sqlalchemy把数据存储到postgresql数据库里。对于sqlalchemy在执行时回滚而没有抛出异常这件事,我有点困惑。我在文档中找到了一篇文章,并尝试通过设置 pool_reset_on_return='commit' 来防止回滚。

结果,这实际上导致sqlalchemy什么都不做。因此,我插入了一行代码,明确调用 trans.commit(),这导致了以下输出:

2014-03-03 18:03:33,390,p:32764 Thread-3, sqlalchemy.engine.base.Engine(_execute_context) [INFO]: INSERT INTO _fd (**)
2014-03-03 18:03:33,391,p:32764 Thread-3, sqlalchemy.engine.base.Engine(_execute_context) [INFO]: {****}
2014-03-03 18:03:33,392,p:32764 Thread-3, sqlalchemy.engine.base.Engine(__init__) [DEBUG]: Col ('fid',)
2014-03-03 18:03:33,393,p:32764 Thread-3, sqlalchemy.engine.base.Engine(process_rows) [DEBUG]: Row (*,)
2014-03-03 18:03:33,393,p:32764 Thread-3, sqlalchemy.engine.base.Engine(_rollback_impl) [INFO]: ROLLBACK

到目前为止,代码非常简单:

1837     with conn.begin() as trans:                                                                                                                                                                                                           
1838         statement = meta.tables[_table_name].insert().values(
...
1847         )
1848         res = conn.execute(statement)
1849         trans.commit()

有没有人知道,回滚的原因可能是什么?

2 个回答

3

我不太确定具体原因,但从源代码来看,当你在with....结构中使用trans.commit()时,它会把事务设置为不活跃。然后,当事务的Context Managerwith语句结束时尝试运行__exit__()方法时,由于is_active标志被设置为False,它会触发rollback()。我不知道在提交事务后再回滚会发生什么。

总之,这个“问题”是with结构会自动处理提交和回滚的部分。根据文档,你只需要做

with conn.begin() as trans:      
    statement = meta.tables[_table_name].insert().values(
    ...
    )
    res = conn.execute(statement)
0

好的,我不知道为什么会有这个习惯,但在语句的最后加上 conn.execute("commit") 就能解决这个问题。

撰写回答