Django `transaction.atomic()` 完整使用指南
目录
- #概述
- #基本用法
- #事务一致性保障机制
- #破坏一致性的常见场景
- #高级用法
- #最佳实践
- #诊断与调试
- #附录
概述
transaction.atomic()
是 Django 提供的数据库事务管理工具,用于确保一系列数据库操作要么全部成功提交,要么全部回滚,维护数据的一致性。
基本用法
1. 作为上下文管理器
from django.db import transactiondef view_func(request):with transaction.atomic():# 事务内的操作obj1.save()obj2.save()
2. 作为装饰器
@transaction.atomic
def view_func(request):# 整个函数都在事务中执行obj1.save()obj2.save()
事务一致性保障机制
- 进入块时:创建保存点或开始新事务
- 成功退出:提交所有更改
- 异常退出:自动回滚所有更改
- 嵌套处理:内层块作为保存点处理
破坏一致性的常见场景
1. 异常处理不当
with transaction.atomic():try:risky_operation()except Exception:logger.error("Error occurred") # 不重新抛出异常 → 破坏一致性
修复方案:
with transaction.atomic():try:risky_operation()except Exception as e:logger.error("Error occurred")raise # 重新抛出异常
2. 长时间运行事务
with transaction.atomic():process_data() # 耗时操作update_database() # 可能因锁超时失败
3. 混合非数据库操作
with transaction.atomic():save_to_db()call_external_api() # 网络操作save_to_db_again() # 外部API失败可能导致不一致
4. 多数据库操作
with transaction.atomic(): # 只针对default数据库ModelA.objects.create(...) # defaultModelB.objects.using('other_db').create(...) # 不受保护
5. 隔离级别冲突
# 事务1
with transaction.atomic():item = Item.objects.select_for_update().get(pk=1)time.sleep(10)# 事务2 (并发执行)
with transaction.atomic():item = Item.objects.get(pk=1) # 可能被阻塞或读取过期数据
高级用法
1. 手动保存点控制
with transaction.atomic():a.save()sid = transaction.savepoint() # 创建保存点try:b.save()except Exception:transaction.savepoint_rollback(sid) # 回滚到保存点# 可继续其他操作transaction.savepoint_commit(sid) # 释放保存点
2. 指定数据库
with transaction.atomic(using='replica_db'):ReplicaModel.objects.create(...)
3. 嵌套事务控制
with transaction.atomic(): # 外层事务a.save()try:with transaction.atomic(): # 内层保存点b.save()raise ValueErrorexcept ValueError:pass # 仅回滚内层c.save() # 仍会提交
最佳实践
- 保持事务简短:只包含必要的数据库操作
- 明确异常处理:
- 要么完全处理并确保一致性
- 要么重新抛出异常
- 避免混合操作:
- 不在事务中执行网络/文件IO
- 不在事务中执行耗时计算
- 多数据库处理:
with transaction.atomic(using='default'):with transaction.atomic(using='other_db'):# 跨数据库操作
- 测试隔离级别:了解数据库的默认隔离级别
- 监控长事务:设置数据库长事务警报
诊断与调试
1. 检查事务状态
from django.db import connectionprint(f"In atomic block: {connection.in_atomic_block}")
print(f"Needs rollback: {connection.needs_rollback}")
2. 检查隔离级别(PostgreSQL)
with connection.cursor() as cursor:cursor.execute("SHOW transaction_isolation")print(cursor.fetchone())
3. 日志记录
LOGGING = {'loggers': {'django.db.backends': {'level': 'DEBUG','handlers': ['console'],}}
}
附录
支持的数据库后端
数据库 | 支持级别 | 注意事项 |
---|---|---|
PostgreSQL | 完全支持 | 建议使用 |
MySQL/MariaDB | 支持 | 需使用InnoDB |
SQLite | 支持 | 实际是文件锁 |
Oracle | 完全支持 | - |
SQL Server | 支持 | 需验证隔离级别 |
事务隔离级别参考
级别 | 脏读 | 不可重复读 | 幻读 | 说明 |
---|---|---|---|---|
读未提交 | 可能 | 可能 | 可能 | 最低隔离 |
读已提交 | 不可能 | 可能 | 可能 | 多数数据库默认 |
可重复读 | 不可能 | 不可能 | 可能 | MySQL默认 |
串行化 | 不可能 | 不可能 | 不可能 | 最高隔离 |