当前位置: 代码网 > it编程>数据库>Mysql > Django MySQL 事务机制与回滚行为的使用说明

Django MySQL 事务机制与回滚行为的使用说明

2025年12月24日 Mysql 我要评论
django 中 transaction.atomic() 的事务行为进行系统性总结,重点说明:哪些异常会触发自动回滚、哪些情况不会、为何产生差异,以及如何正确编写可控的事务逻辑。1. transac

django 中 transaction.atomic() 的事务行为进行系统性总结,重点说明:哪些异常会触发自动回滚、哪些情况不会、为何产生差异,以及如何正确编写可控的事务逻辑。

1. transaction.atomic() 的基本行为

transaction.atomic() 会在进入时创建一个 数据库保存点(savepoint)
代码块退出时根据执行结果决定回滚或提交:

  • 若出现 未捕获的异常:自动回滚到保存点,并继续抛出该异常。
  • 若代码执行正常结束:提交保存点。

核心原则:是否回滚取决于是否有异常向外抛出。

2. 会触发自动回滚的情况

2.1 未捕获的 python 异常

只要异常没有在 atomic 块内被捕获,都会触发回滚,包括:

  • zerodivisionerror
  • valueerror
  • typeerror
  • keyerror
  • indexerror
  • assertionerror
  • 自定义异常
  • raise exception("...")

示例:

with transaction.atomic():
    obj = model.objects.create(...)
    raise exception("abort transaction")  # 未捕获 → 自动回滚

2.2 未捕获的 django orm / 数据库异常

数据库相关异常未被捕获时,也会触发自动回滚,包括:

  • integrityerror(唯一约束、外键约束)
  • dataerror(无效数据)
  • operationalerror(死锁、锁超时)
  • programmingerror(sql 错误)
  • databaseerror
  • interfaceerror

示例:

with transaction.atomic():
    model.objects.create(id=1)
    model.objects.create(id=1)  # integrityerror → 自动回滚

2.3 drf 验证错误(raise_exception=true)

serializer.is_valid(raise_exception=true)

该语句抛出的 validationerror 未被捕获 → 自动回滚。

3. 不会自动回滚的情况

3.1 异常被捕获并吞掉

只要异常被捕获,没有继续向外抛出,django 会视为“执行成功”,不会回滚。

with transaction.atomic():
    try:
        raise exception("error")
    except exception:
        pass  # 异常被吞掉 → 不回滚

若需要强制回滚,必须手动调用:

transaction.set_rollback(true)

3.2 没有异常但提前 return

业务判断不属于错误,不会自动回滚。

with transaction.atomic():
    if invalid:
        return response({"error": ...})  # 不回滚

3.3 drf 验证错误未 raise

serializer.is_valid(raise_exception=false)
if serializer.errors:
    return response(serializer.errors)  # 不回滚

只有抛出异常才会回滚。

3.4 数据库层无异常但逻辑错误

例如外键检查关闭、不符合约束但 mysql 未抛错,此类不会产生自动回滚。

3.5 使用 atomic(savepoint=false) 并在内部捕获异常

with transaction.atomic(savepoint=false):
    try:
        raise exception()
    except:
        pass

内部异常被捕获 → 无异常向上抛出 → 不会回滚。

4. raise exception(‘xxx’) 是否回滚?

答案:会回滚,只要未被捕获。

raise exception('xxx') 会触发 python 异常,atomic 在退出时检测到异常 → 自动回滚保存点。

示例:

with transaction.atomic():
    raise exception("abort")  # 自动回滚

若被捕获,则不会回滚:

with transaction.atomic():
    try:
        raise exception("abort")
    except exception:
        pass  # 无异常向上抛出 → 不回滚

5. 总结:事务回滚的唯一决定因素

django 中事务是否回滚,唯一决定因素:

是否有异常从 atomic 块中冒出。

可以总结为:

  • 未捕获异常 → 自动回滚
  • 捕获异常 → 不自动回滚
  • 没有异常 → 正常提交
  • drf raise_exception=true → 会回滚
  • return 并非错误 → 不回滚

6. 推荐的事务编写模式(最佳实践)

from django.db import transaction

def perform_action():
    try:
        with transaction.atomic():
            # 业务逻辑
            do_something()

    except exception as e:
        # atomic 已自动回滚
        handle_error(e)
        raise

如果希望在捕获异常后仍然回滚:

with transaction.atomic():
    try:
        do_something()
    except exception:
        transaction.set_rollback(true)  # 手动回滚
        raise

到此这篇关于django mysql 事务机制与回滚行为的使用说明的文章就介绍到这了,更多相关django mysql 事务机制与回滚行为内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com