Django - 像盗梦空间一样的事务处理

3 投票
1 回答
904 浏览
提问于 2025-04-16 14:17

我不是数据库方面的专家,所以请原谅我用词不当:

当你使用Django的transaction.commit_on_success(func)时,如果在这个函数中发生了错误,控制权会返回到commit_on_success,这时会撤销之前的操作,这在你需要确保某个方法要么全部成功,要么全部失败时非常有用。这使得Django在处理需要做很多事情的视图时,事务管理变得非常好用。

有时候我会把模型方法或者一些普通的辅助函数放在commit_on_success里面,以实现同样的全部成功或全部失败的效果。

但是问题来了,当你有嵌套的Django事务时。举个例子:一个受保护的事务视图调用了一个被commit_on_success包裹的模型方法,然后又做了一些其他操作,结果引发了异常。哎呀,当控制权从模型方法返回到commit_on_success时,事务已经被提交了,这样视图就出现了错误,变成了部分成功而不是全部成功。这种情况不仅限于视图。我可能有多个嵌套的操作,而这些操作都使用了lots_o_foo_or_nothing(),并且调用了all_or_nothing_1()all_or_nothing_2(),这两个方法也都被commit_on_success包裹。如果lots_o_foo_or_nothing()出错了,子函数的调用会已经把它们的事务提交到数据库,这样就会逻辑上破坏我的数据。

有没有什么办法可以解决这个问题?如果我理解错了,请多包涵,但看起来这是我观察到的行为,找到解决办法会非常方便。

1 个回答

2

这不是最终的解决方案,而是一个基于这个代码片段的想法(这个想法本身就不错)。

结合保存点,可以创造出一个很好的解决方案:一个装饰器,它会知道当前的事务是否在另一个事务里面(如果是的话,就使用保存点而不是事务)。

撰写回答