Python 在SQLAlchemy中以原子方式插入/更新多个表中的行

Python 在SQLAlchemy中以原子方式插入/更新多个表中的行,python,sqlalchemy,Python,Sqlalchemy,我的用例要求表A、B和C需要以原子方式插入/更新行。换句话说,如果A被更新了,B被更新了,并且在C被更新之前发生了灾难性的故障,我的应用程序就会崩溃 因此,要么所有三个表都应该立即更新,要么根本不更新 在SQLAlchemy中,我目前正在使用以下函数来执行插入 self.db_conn.execute(table.insert(), dicts) 但根据我的理解,这个“执行”也提交了事务。因此,如果我在三个不同的函数调用中执行对A、B和C的行插入,原子性就不能得到保证 谢谢你的帮助 假设sel

我的用例要求表A、B和C需要以原子方式插入/更新行。换句话说,如果A被更新了,B被更新了,并且在C被更新之前发生了灾难性的故障,我的应用程序就会崩溃

因此,要么所有三个表都应该立即更新,要么根本不更新

在SQLAlchemy中,我目前正在使用以下函数来执行插入

self.db_conn.execute(table.insert(), dicts)
但根据我的理解,这个“执行”也提交了事务。因此,如果我在三个不同的函数调用中执行
A
B
C
的行插入,原子性就不能得到保证


谢谢你的帮助

假设
self.dbconn
是由
engine.connect()
生成的连接,您可以将其用作上下文管理器,在退出时提交:

names=['Alice','Bob','Carol']
使用engine.connect()作为连接:
使用conn.begin():
对于名称中的名称:
conn.execute(users.insert(),name=name)
代码段生成此输出,显示每个插入在单个事务中发生:

2020-12-06 17:16:36683信息sqlalchemy.engine.engine开始(隐式)
2020-12-06 17:16:36683信息sqlalchemy.engine.engine插入用户(名称)值(?)
2020-12-06 17:16:36684信息sqlalchemy.engine.engine[在0.00019秒内生成]('Alice',)
2020-12-06 17:16:36684信息sqlalchemy.engine.engine插入用户(名称)值(?)
2020-12-06 17:16:36684信息sqlalchemy.engine.engine[自0.0006672s前缓存]('Bob',)
2020-12-06 17:16:36684信息sqlalchemy.engine.engine插入用户(名称)值(?)
2020-12-06 17:16:36684信息sqlalchemy.engine.engine[自0.0009919s前缓存]('Carol',)
2020-12-06 17:16:36684信息sqlalchemy.engine.engine提交
见文件

如果我们将列表中的最后一个元素更改为无法保存的内容(例如内置的
int
函数),则整个事务将回滚

2020-12-06 17:21:50760信息sqlalchemy.engine.engine开始(隐式)
2020-12-06 17:21:50761信息sqlalchemy.engine.engine插入用户(名称)值(?)
2020-12-06 17:21:50761信息sqlalchemy.engine.engine[在0.00019秒内生成]('Alice',)
2020-12-06 17:21:50761信息sqlalchemy.engine.engine插入用户(名称)值(?)
2020-12-06 17:21:50761信息sqlalchemy.engine.engine[从0.0006409年前开始缓存]('Bob',)
2020-12-06 17:21:50761信息sqlalchemy.engine.engine插入用户(名称)值(?)
2020-12-06 17:21:50761信息sqlalchemy.engine.engine[自0.0009716s前缓存](,)
2020-12-06 17:21:50762信息sqlalchemy.engine.engine回滚

假设
self.dbconn
是由
engine.connect()
生成的连接,您可以将其用作上下文管理器,它在退出时提交:

names=['Alice','Bob','Carol']
使用engine.connect()作为连接:
使用conn.begin():
对于名称中的名称:
conn.execute(users.insert(),name=name)
代码段生成此输出,显示每个插入在单个事务中发生:

2020-12-06 17:16:36683信息sqlalchemy.engine.engine开始(隐式)
2020-12-06 17:16:36683信息sqlalchemy.engine.engine插入用户(名称)值(?)
2020-12-06 17:16:36684信息sqlalchemy.engine.engine[在0.00019秒内生成]('Alice',)
2020-12-06 17:16:36684信息sqlalchemy.engine.engine插入用户(名称)值(?)
2020-12-06 17:16:36684信息sqlalchemy.engine.engine[自0.0006672s前缓存]('Bob',)
2020-12-06 17:16:36684信息sqlalchemy.engine.engine插入用户(名称)值(?)
2020-12-06 17:16:36684信息sqlalchemy.engine.engine[自0.0009919s前缓存]('Carol',)
2020-12-06 17:16:36684信息sqlalchemy.engine.engine提交
见文件

如果我们将列表中的最后一个元素更改为无法保存的内容(例如内置的
int
函数),则整个事务将回滚

2020-12-06 17:21:50760信息sqlalchemy.engine.engine开始(隐式)
2020-12-06 17:21:50761信息sqlalchemy.engine.engine插入用户(名称)值(?)
2020-12-06 17:21:50761信息sqlalchemy.engine.engine[在0.00019秒内生成]('Alice',)
2020-12-06 17:21:50761信息sqlalchemy.engine.engine插入用户(名称)值(?)
2020-12-06 17:21:50761信息sqlalchemy.engine.engine[从0.0006409年前开始缓存]('Bob',)
2020-12-06 17:21:50761信息sqlalchemy.engine.engine插入用户(名称)值(?)
2020-12-06 17:21:50761信息sqlalchemy.engine.engine[自0.0009716s前缓存](,)
2020-12-06 17:21:50762信息sqlalchemy.engine.engine回滚

谢谢!因此,我的应用程序有查询A、B、C和D,其中(A、B、C)必须以原子方式提交,但不一定是D。我希望对所有4个查询使用相同的DB连接,而不是打开两个不同的查询。可能吗?是的。只需使用self.db_conn.begin()执行另一个
-
begin
上下文管理器的范围就是事务;它不会关闭连接(鉴于
self.db_conn
是一个实例属性,您必须手动关闭它,而不是像我在回答中那样将其用作上下文管理器)。谢谢!因此,我的应用程序有查询A、B、C和D,其中(A、B、C)必须