【发布时间】:2017-01-23 19:40:04
【问题描述】:
在我的 CherryPy + Peewee 应用程序中,我经常使用以下模式:启动事务、执行操作列表并返回显示结果的页面。如果在任何操作过程中出现问题,我会在日志表中添加一行,然后重定向到显示该行的页面。
问题是 CherryPy 中的重定向是通过引发异常来执行的,异常会导致一些事务回滚。回滚是失败的操作(以及所有先前的操作,即使它们成功)所需要的,但这不是我想要的日志记录。
例如,如果用户转到a_page?a=1&b=2&c=3,则使用以下代码:
-
do_this会找到x != y而不会执行show_message -
do_this将更新Table1上的一条记录 -
do_that会找到x == y并执行show_message -
show_message将在Message日志表中添加一行 -
show_message将引发异常以重定向到将显示刚刚记录的消息的页面
由于在事务中引发了异常,因此在do_this 中对Table1 进行的更新和在show_message 中记录的消息都将被回滚。
如何提交记录表中的行并回滚所有其他更改?
@cherrypy.expose
def a_page(self, a, b, c):
with db.transaction():
self.do_this(a, b)
self.do_that(b, c)
return render('it_worked.html')
def do_this(self, x, y):
if x == y:
self.show_message('Wrong this')
Table1.update(f2=x).where(f1 == y).execute()
def do_that(self, x, y):
if x != y:
self.show_message('Wrong that')
Table1.update(f3=x).where(f1 == z).execute()
def show_message(self, message)
msg = Message.create(msg=message)
raise cherrypy.HTTPRedirect('show_message?id={}'.format(msg.id))
【问题讨论】:
-
可能是嵌套事务,即保存点。
-
@CL。据我所知,嵌套事务不允许您保存内部操作。我需要相反:我不想保存直到现在执行的事务,但我想保存最后一个。
-
我找到了一个我不喜欢的解决方案,因为 (1) 它需要将事务传递给函数,并且 (2) 如果存在嵌套事务,它将无法工作。在我下面的回答中。请让我知道这是否是一个好的解决方案,或者我可以做得更好
-
您必须在回滚到保存点后写入日志。
-
@CL。这就是我在下面的示例中所做的。
Log.show_log()需要知道最外层的事务才能回滚,我不知道我是否喜欢。
标签: sqlite transactions cherrypy peewee