在 SELECT 查询后使 SQLAlchemy COMMIT 而不是 ROLLBACK

发布于 2024-12-06 08:27:05 字数 1035 浏览 1 评论 0原文

我正在与合作伙伴一起开发一个应用程序。我在 PostgreSQL 中完成数据库部分,我的合作伙伴使用 SQLAlchemy 在 Web 服务器上使用 Python 实现该应用程序。我们大量使用服务器端功能。对其中之一的 SELECT 查询在数据库日志中看起来像这样:

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

SELECT col_a, col_b FROM some_func(E'myvalue');

ROLLBACK;

在函数中,我将某些输入写入日志表。应用程序通过 SELECT 进行查询,SQLAlchemy 只看到 SELECT 语句并坚持使用 ROLLBACK。记录失败。我需要它来COMMIT。我的合作伙伴声称没有简单的方法,我们必须完全删除 SQLAlchemy。我认为他一定是错的,但缺乏知识来提出相反的观点。

有没有一种简单的方法可以让 SQLAlchemy COMMIT 而不是 ROLLBACK
是什么让我无法执行 trans.commit()?我需要为此设置 autoflush=False 吗?

我已经扫描了 常见问题解答,但没有找到答案。
搜索SO发现了一些相关问题,例如此处这里,但我不太清楚。
也许这个食谱会起作用吗?

I am developing an app together with a partner. I do the database part in PostgreSQL, my partner implements the app on the web-server with Python using SQLAlchemy. We make heavy use of server-side functions. A SELECT query on one of those looks like this in the DB log:

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

SELECT col_a, col_b FROM some_func(E'myvalue');

ROLLBACK;

In the functions I write certain input to a log table. The app queries by SELECT, SQLAlchemy only sees a SELECT statement and insists on a ROLLBACK. Logging fails. I need it to COMMIT instead. My partner claims there is no easy way, we would have to remove SQLAlchemy altogether. I think he must be wrong but lack the knowledge to claim otherwise.

Is there an easy way to make SQLAlchemy COMMIT instead of ROLLBACK?
What keeps me from just executing trans.commit()? Do I need to set autoflush=False for that?

I have scanned the FAQ, but did not find an answer there.
Searching SO revealed some related questions like here and here, but I am not in the clear.
Maybe this recipe would work?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

夏有森光若流苏 2024-12-13 08:27:05

如果您使用 SQLAlchemy 的连接池,那么您看到的可能是连接在使用后关闭时发生的自动回滚。显然有必要保证连接下次从池中拉出时是“干净的”。有关详细信息,请参阅此页面;在顶部附近搜索“池机制”。

据我所知(自从我上次使用此方法以来已经有几年了),将隔离级别更改为自动提交并不能解决问题,因为它不会将 SELECT 语句视为需要提交。

您实际上只想将该语句包装在事务中。我不知道你的代码是如何构造的,但你应该能够使用 SQLAlchemy 的connection.begin 和connection.commit。您甚至可以将 BEGIN 和 COMMIT 作为任意 SQL 执行。

If you're using SQLAlchemy's connection pooling, then what you're seeing is probably the automatic rollback that happens when a connection is closed after use. It's apparently necessary to guarantee that the connection is 'clean' for the next time it's pulled out of the pool. See this page for more info; search for 'pooling mechanism' near the top.

From what I recall (it's been a couple years since I last worked with this) changing the isolation level to autocommit won't solve the problem, since it won't see the SELECT statement as requiring a commit.

You really just want to wrap that statement in a transaction. I don't know how your code is structured, but you should just be able to use SQLAlchemy's connection.begin and connection.commit. You could even just execute the BEGIN and COMMIT as arbitrary SQL.

千紇 2024-12-13 08:27:05

您可以在创建引擎时禁用ROLLBACK并设置AUTOCOMMIT

non_acid_engine = create_engine(
    "mysql://scott:tiger@host/db",
    pool_reset_on_return=None, --disabling the rollback
    isolation_level="AUTOCOMMIT",
)

注意:仅建议用于非事务连接

参考https://docs.sqlalchemy.org/en/20/core/pooling.html#pool-reset-on-return

You can disable the ROLLBACK and set AUTOCOMMIT while creating the engine.

non_acid_engine = create_engine(
    "mysql://scott:tiger@host/db",
    pool_reset_on_return=None, --disabling the rollback
    isolation_level="AUTOCOMMIT",
)

Note: This is only suggested for non-transactional connections

Reference: https://docs.sqlalchemy.org/en/20/core/pooling.html#pool-reset-on-return

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文