1. transaction.on_commit()
是什么?
这是在Django中,当想在数据库事务成功提交后执行某个操作时使用的回调注册方法.
from django.db import transaction
transaction.on_commit(my_function)
执行该代码后,只有在当前事务成功结束后,my_function()
才会执行.
2. 在什么情况下使用?
情况 | 使用情况 |
---|---|
想在DB存储确认完成后执行某个操作时 | ✅ 适用 |
希望在事务之后执行Celery任务时 | ✅ 适用 |
外部API调用、缓存更新等 | ✅ 适用 |
在事务外调用时顺序不重要 | ❌ 不适用 |
3. 核心概念
on_commit()
的含义只有在“当前正在执行的事务存在时”.- 如果没有事务,回调会立即执行!
4. 错误示例
def my_view(request):
def notify():
print("已执行!")
transaction.on_commit(notify) # 由于没有事务立即执行!
5. 正确使用示例
from django.db import transaction
def my_view(request):
with transaction.atomic():
post = Post.objects.create(...)
post.categories.add(...)
def translate():
translate_post.delay(post.id)
transaction.on_commit(translate)
在该示例中,post
创建和分类添加全部完成后,translate()
才会执行.
6. 为什么重要?
许多开发者会混淆以下几点:
- ORM的
create()
、add()
并不是实际提交的 - 在提交之前都处于“逻辑存储”状态
- Celery任务是在单独的进程中执行的,
- 如果在提交前执行,将会引用不完整的数据
7. 与Celery一起使用的理想示例
@shared_task
def post_finalize_task(post_id, categories, tags):
post = Post.objects.get(id=post_id)
with transaction.atomic():
for name in categories:
cat, _ = Category.objects.get_or_create(name=name)
post.categories.add(cat)
for name in tags:
tag, _ = Tag.objects.get_or_create(name=name)
post.tags.add(tag)
def schedule_translation():
translate_post.delay(post.id)
transaction.on_commit(schedule_translation)
该结构保证在类别/标签存储确认之后,translate_post
任务才能执行.
8. 摘要整理
概念 | 描述 |
---|---|
何时执行? | 事务成功提交后 |
失败时? | 一旦rollback绝对不执行 |
没有事务时? | 立即执行 (注意!) |
使用位置 | with transaction.atomic() 块内部 |
应用示例 | 执行Celery任务、发送通知、更新缓存等 |
9. Jesse的评论
transaction.on_commit()
并不仅仅是简单的延迟执行.
这是开发者清晰表达意图的方式,只有在事务成功时才执行,
在使用ORM与异步处理时,维护数据完整性的重要工具.
댓글이 없습니다.