找回密码
 立即注册
首页 业界区 业界 Django事务

Django事务

丘娅楠 2025-9-28 18:42:31
1. 事务基础概念

1.1 什么是事务?

事务是具有以下特性(ACID)的数据库操作单元:

  • 原子性 (Atomicity):事务是一个不可分割的工作单位,事务中的操作要么全部发生,要么全部不发生。
  • 一致性 (Consistency):事务必须使数据库从一个一致性状态变换到另一个一致性状态。例如,转账前后两个账户的总金额应保持不变。
  • 隔离性 (Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务。数据库提供了不同的隔离级别(如读未提交、读已提交、可重复读、串行化)来平衡一致性和性能。
  • 持久性 (Durability):一旦事务提交,它对数据库中数据的改变就是永久性的。
1.2 Django 中的事务支持

Django 默认使用自动提交模式,每个查询都会立即提交到数据库。但你可以手动控制事务。
2. 事务管理方式

2.1 使用装饰器管理事务

2.1.1 函数视图
  1. from django.db import transaction
  2. from django.http import JsonResponse
  3. from .models import Account
  4. @transaction.atomic # 使用装饰器确保此视图中的数据库操作在一个事务中执行
  5. def test_view(request, from_id, to_id, amount):
  6.     try:
  7.         amount = float(amount)
  8.         # 获取账户对象,select_for_update 用于在事务中锁定行,防止并发修改
  9.         from_account = Account.objects.select_for_update().get(pk=from_id)
  10.         to_account = Account.objects.select_for_update().get(pk=to_id)
  11.         # 检查转出账户余额是否充足
  12.         if from_account.balance < amount:
  13.             return JsonResponse({"status": "error", "message": "余额不足"})
  14.         # 执行转账操作
  15.         from_account.balance -= amount
  16.         to_account.balance += amount
  17.         # 保存到数据库
  18.         from_account.save()
  19.         to_account.save()
  20.         return JsonResponse({"status":"success"})
  21.     except Exception as e:
  22.         # 如果发生任何异常,Django 会自动回滚事务
  23.         return JsonResponse({"status": "error"})
复制代码
2.1.2 类视图
  1. class TestView(View):
  2.     @method_decorator(transaction.atomic)
  3.     def post(self, request):
  4.         try:
  5.             return JsonResponse({'success': True})
  6.         except Exception as e:
  7.             return JsonResponse({'success': False})
复制代码
2.2 使用上下文管理器管理事务
  1. def transfer_funds(sender_id, receiver_id, amount):
  2.     try:
  3.         # 使用上下文管理器明确事务边界
  4.         with transaction.atomic():
  5.             ...
  6.             
  7.     except ValueError as e:
  8.         # 处理业务逻辑错误
  9.         print(f"Transfer failed: {e}")
  10.     except Exception as e:
  11.         # 处理其他异常,事务会自动回滚
  12.         print(f"Unexpected error: {e}")
复制代码
3、保存点(Savepoints)

对于复杂的事务,可以使用保存点来实现部分回滚:
  1. from django.db import transaction
  2. def complex_operation():
  3.     with transaction.atomic(): # 开启外部事务
  4.         obj1 = ModelA.objects.create(field='value') # 操作1
  5.         sid = transaction.savepoint() # 设置保存点
  6.         try:
  7.             obj2 = ModelB.objects.create(field=obj1.pk) # 操作2
  8.         except Exception:
  9.             transaction.savepoint_rollback(sid) # 回滚到保存点,操作2被撤销,操作1仍有效
  10.             raise # 继续抛出异常,让外部事务决定是否回滚
  11.         transaction.savepoint_commit(sid) # 提交保存点
  12. # 外部事务结束,所有操作(包括操作1和2)最终提交
复制代码
4、其他

4.1 隔离级别

Django 本身不直接提供隔离级别的配置,但可以通过数据库后端或原始SQL来设置。
4.1.1 数据库后端配置
  1. DATABASES = {
  2.     'default': {
  3.         'ENGINE': 'django.db.backends.postgresql',
  4.         'NAME': 'mydatabase',
  5.         'USER': 'mydatabaseuser',
  6.         'PASSWORD': 'mypassword',
  7.         'HOST': '127.0.0.1',
  8.         'PORT': '5432',
  9.         'OPTIONS': {
  10.             # PostgreSQL 隔离级别设置, 'read uncommitted', 'read committed'(默认), 'repeatable read', 'serializable'
  11.             'isolation_level': 'read committed',
  12.             # MySQL 隔离级别设置,'READ UNCOMMITTED', 'READ COMMITTED', 'REPEATABLE READ'(默认), 'SERIALIZABLE'
  13.             # 'isolation_level': 'READ-COMMITTED',
  14.         },
  15.     }
  16. }
复制代码
4.2 在代码中设置隔离级别
  1. # 使用原始SQL
  2. from django.db import connection, transaction
  3. def set_isolation_level():
  4.     with transaction.atomic():
  5.         # 设置事务隔离级别
  6.         with connection.cursor() as cursor:
  7.             # PostgreSQL
  8.             cursor.execute("SET TRANSACTION ISOLATION LEVEL SERIALIZABLE")
  9.             
  10.             # MySQL
  11.             # cursor.execute("SET TRANSACTION ISOLATION LEVEL SERIALIZABLE")
  12.             
  13.             # SQLite (默认就是SERIALIZABLE)
  14.             # cursor.execute("PRAGMA read_uncommitted = 0")
  15.         
  16.         # 执行事务操作
  17.         # ...
  18. # 使用上下文管理器
  19. from contextlib import contextmanager
  20. from django.db import connection
  21. @contextmanager
  22. def serializable_transaction():
  23.     with transaction.atomic():
  24.         with connection.cursor() as cursor:
  25.             cursor.execute("SET TRANSACTION ISOLATION LEVEL SERIALIZABLE")
  26.         yield
复制代码
4.2 transaction.non_atomic_requests

在 Django 的设置文件 (settings.py) 中,你可以通过配置 ATOMIC_REQUESTS = True为指定的数据库开启​​全局事务模式。这意味着:

  • 每个 HTTP 请求都会被自动包裹在一个数据库事务中。
  • 如果视图函数成功返回响应,Django 会自动提交事务。
  • 如果视图函数抛出异常,Django 会自动回滚事务。
而 @transaction.non_atomic_requests装饰器的作用就是​​让被装饰的视图函数不受上述全局事务规则的限制​​,恢复为 Django 默认的自动提交模式
4.2.1 基本用法
  1. from django.db import transaction
  2. @transaction.non_atomic_requests
  3. def my_view(request):
  4.     # 这个视图函数中的数据库操作将在自动提交模式下运行,
  5.     # 不会受到全局事务设置的影响。
  6.     do_stuff()
复制代码
4.2.2 指定数据库
  1. from django.db import transaction
  2. @transaction.non_atomic_requests(using='other')
  3. def my_other_view(request):
  4.     # 此视图仅对别名为 'other' 的数据库禁用全局事务。
  5.     do_stuff_on_the_other_database()
复制代码
5、总结

在Django中使用事务,关键在于识别出哪些数据库操作需要作为一个不可分割的单元。通过 @transaction.atomic装饰器或 with transaction.atomic()上下文管理器,你可以清晰地界定事务的范围。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册