commit_on_success 如何处理嵌套?
我对在特定情况下应该如何处理交易感到有点困惑。
我有一些代码可以归结为:
from django.db import transaction
@transaction.commit_on_success
def process_post():
#do stuff with database
for reply in post_replies:
process_post_reply(reply)
@transaction.commit_on_success
def process_post_reply(reply):
#do stuff with database
我想知道如果 process_post_reply()
失败会发生什么。
commit_on_success 如何处理嵌套?它是否会理解提交每个 process_post_reply()
或者如果失败则整个 process_post_reply()
会回滚?
I'm a bit confused about how I should handle transactions in a particular situation.
I've got some code that boils down to this:
from django.db import transaction
@transaction.commit_on_success
def process_post():
#do stuff with database
for reply in post_replies:
process_post_reply(reply)
@transaction.commit_on_success
def process_post_reply(reply):
#do stuff with database
I want to know what happens if a process_post_reply()
fails.
How does commit_on_success handle being nested? Will it understand to commit each process_post_reply()
or if one fails the whole process_post()
rolls back?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是它的源代码: https:// github.com/django/django/blob/1.2.4/django/db/transaction.py#L286
和 enter_transaction_management 就像将新的事务处理模式放在线程堆栈上一样简单。
因此,在您的情况下,如果 process_post_reply() 失败(即发生异常),则事务将全部回滚,然后异常从 process_post() 向上传播> 也一样,但没有什么可以回滚的。
不,如果一个
process_post_reply()
失败,则整个process_post()
不会回滚 - 那里没有魔法,只有数据库级别的 COMMIT 和 ROLLBACK ,这意味着回滚的只是最后一次提交process_post_reply()
之后写入数据库的内容。总结一下,我认为您需要的只是围绕
process_post
的一个commit_on_success()
,可能由事务保存点 - 不幸的是,仅在 PostgreSQL 后端可用,尽管 MySQL 5.x 支持它们以及。编辑 2012 年 4 月 10 日:对 MySQL 的 Savepoint 支持现已在 Django 1.4 中可用
编辑 2014 年 7 月 2 日:事务管理已在 Django 1.6 中完全重写 - https://docs.djangoproject.com/en/1.6/topics/db/transactions/ 和
commit_on_success
已被弃用。Here's the source code of it: https://github.com/django/django/blob/1.2.4/django/db/transaction.py#L286
And enter_transaction_management is as simple as putting new transaction handling mode on the thread stack.
So, in your case, if
process_post_reply()
fails (i.e. exception occurs), then the transaction is rolled back in its entirety, and then the exception propagates upwards fromprocess_post()
as well but there is nothing to roll back.And no, if one
process_post_reply()
fails then the wholeprocess_post()
is not being rolled back - there's no magic there, only COMMIT and ROLLBACK on the database level, which means that what gets rolled back is only what has been written to the DB after the last commitedprocess_post_reply()
.Summarizing, I think that what you need is just a single
commit_on_success()
aroundprocess_post
, possibly supported by transaction savepoints - which unfortunately are available only in PostgreSQL backend, even though MySQL 5.x supports them as well.EDIT 10 Apr 2012: Savepoint support for MySQL is now available in Django 1.4
EDIT 2 Jul 2014: Transaction management has been completely rewritten in Django 1.6 - https://docs.djangoproject.com/en/1.6/topics/db/transactions/ and
commit_on_success
has been deprecated.为了更好地控制事务管理,最好使用transaction.commit_manually():
在这里您可以根据情况决定是否提交事务。
To gain more control on the transaction management, it's good to use
transaction.commit_manually()
:Here you can decide depending on circumstances, commit transaction or not.