当前位置: 首页 > news >正文

django-4事务

Django 事务(Transaction)是保证数据库操作原子性的关键机制,用于确保一组数据库操作要么全部成功提交,要么在发生错误时全部回滚,从而维持数据的一致性。

事务的 ACID 特性

Django 事务遵循数据库事务的四大特性:

  • 原子性(Atomicity):事务中的所有操作要么全部完成,要么全部不执行。
  • 一致性(Consistency):事务执行前后,数据库从一个有效状态转换到另一个有效状态(如约束、关联关系不变)。
  • 隔离性(Isolation):多个事务并发执行时,彼此不会相互干扰(隔离级别决定干扰程度)。
  • 持久性(Durability):事务提交后,修改会永久保存到数据库,即使系统崩溃也不会丢失。

事务的使用方式

装饰器 @transaction.atomic(最常用)

将整个函数包装在事务中,函数内所有数据库操作作为一个原子单元。

from django.db import transaction
from myapp.models import Book, Order@transaction.atomic
def create_order(book_id, user_id, quantity):"""创建订单并扣减库存(原子操作)"""# 1. 查询书籍(加行锁防止并发问题)book = Book.objects.select_for_update().get(id=book_id)# 2. 检查库存if book.stock < quantity:raise ValueError("库存不足")  # 触发回滚# 3. 创建订单order = Order.objects.create(user_id=user_id,book=book,quantity=quantity,total_price=book.price * quantity)# 4. 扣减库存book.stock -= quantitybook.save()return order
  • 若函数正常执行,事务自动提交。
  • 若抛出未捕获的异常(如 ValueError),事务自动回滚。

上下文管理器 with transaction.atomic()

在代码块级别使用事务,更灵活地控制事务范围。

  • 适合仅需对部分代码进行事务控制的场景。
  • 代码块执行完毕自动提交,异常时自动回滚。
def update_inventory(book_id, new_stock):try:# 事务代码块with transaction.atomic():book = Book.objects.get(id=book_id)book.stock = new_stockbook.save()# 其他操作...print("操作成功,已提交")except Exception as e:print(f"操作失败,已回滚: {e}")

手动控制事务(低级 API)

通过 transaction.begin()transaction.commit()transaction.rollback() 手动管理事务(不推荐,容易出错)。

def manual_transaction():# 开始事务transaction.set_autocommit(False)  # 关闭自动提交try:book = Book.objects.get(id=1)book.stock -= 1book.save()# 手动提交transaction.commit()except:# 出错时回滚transaction.rollback()finally:# 恢复自动提交模式transaction.set_autocommit(True)

事务隔离级别

数据库事务的隔离级别决定了并发事务之间的可见性,Django 支持通过设置隔离级别控制这一行为。
可选隔离级别(因数据库而异)

  • READ UNCOMMITTED:最低隔离级别,允许读取未提交的数据(脏读)。
  • READ COMMITTED:默认级别(多数数据库),只能读取已提交的数据(避免脏读)。
  • REPEATABLE READ:确保同一事务中多次读取的数据一致(避免不可重复读)。
  • SERIALIZABLE:最高隔离级别,事务串行执行(避免幻读,性能最低)。

在 Django 中设置隔离级别

全局设置 settings.py)

DATABASES = {'default': {'ENGINE': 'django.db.backends.postgresql','NAME': 'mydb','OPTIONS': {'isolation_level': 'read committed',  # 或其他级别},}
}

局部设置(针对特定事务):

from django.db import transaction@transaction.atomic(isolation_level='serializable')
def critical_operation():# 高隔离级别的关键操作pass

事务保存点(Savepoint)

在复杂事务中,可设置保存点,允许回滚到事务中的特定位置,而不是整个事务。

  • transaction.savepoint():创建保存点,返回标识。
  • transaction.savepoint_rollback(savepoint):回滚到指定保存点。
  • transaction.savepoint_commit(savepoint):提交保存点(使其成为事务的一部分)。
@transaction.atomic
def complex_operation():# 操作1:创建用户user = User.objects.create(username="test")# 设置保存点savepoint = transaction.savepoint()try:# 操作2:创建订单(可能失败)order = Order.objects.create(user=user, total=100)except Exception as e:# 回滚到保存点(仅撤销操作2,保留操作1)transaction.savepoint_rollback(savepoint)print(f"订单创建失败,已回滚到保存点: {e}")else:# 提交保存点(操作2生效)transaction.savepoint_commit(savepoint)# 操作3:无论操作2是否成功,都会执行user.is_active = Trueuser.save()

并发控制与锁

事务中常需处理并发问题,Django 提供了两种锁机制:

行级锁 select_for_update()

查询时对记录加行锁,阻止其他事务修改该记录,直到当前事务完成。

  • 适用于并发修改同一记录的场景(如秒杀、库存扣减)。
  • 仅在事务中有效(需配合 atomic)。
@transaction.atomic
def decrease_stock(book_id, quantity):# 加行锁查询(其他事务需等待锁释放)book = Book.objects.select_for_update().get(id=book_id)if book.stock >= quantity:book.stock -= quantitybook.save()else:raise ValueError("库存不足")

表级锁(不推荐)

通过 select_for_update(of=…) 或原生 SQL 实现,会锁定整张表,性能较差,谨慎使用。

注意事项

事务范围不宜过大

避免在事务中包含耗时操作(如网络请求、大量计算),否则会长期占用数据库连接,降低并发性能。

@transaction.atomic
def bad_example():book = Book.objects.get(id=1)send_email()  # 耗时的网络操作,不应放在事务中book.stock -= 1book.save()

异常处理

事务仅对数据库操作生效,非数据库操作(如文件写入)不会随事务回滚,需手动处理。

@transaction.atomic
def handle_file_and_db():file_path = "data.txt"try:# 数据库操作book = Book.objects.get(id=1)book.stock += 1book.save()# 文件操作with open(file_path, "w") as f:f.write("data")except:# 手动删除已创建的文件if os.path.exists(file_path):os.remove(file_path)raise  # 触发数据库回滚

自动提交模式

Django 默认开启自动提交(autocommit=True),即每个数据库操作单独成事务。使用 atomic 时会临时关闭自动提交,结束后恢复。

http://www.dtcms.com/a/306205.html

相关文章:

  • 游戏盾是如何做到免疫攻击的
  • Android自定义游戏view积累
  • 从混乱走向高效:重塑企业IT服务管理的未来路径
  • 【网络运维】Linux:软件包管理
  • python案例分析:基于抖音评论的文本分析,使用svm算法进行情感分析以及LDA主题分析,准确率接近90%
  • Qt Quick 可视化组件应用
  • 应用药品 GMP 证书识别技术,实现证书信息的自动化、精准化提取与核验
  • OriGene:一种可自进化的虚拟疾病生物学家,实现治疗靶点发现自动化
  • RK3568下的进程间通信:基于UDP的mash网络节点通信
  • Java注解与反射:从自定义注解到框架设计原理
  • 双线串行的 “跨界对话”:I2C 与 MDIO 的异同解析
  • 详细聊下easyexcel导出
  • 实例教学FPN原理与PANet,Pytorch逐行精讲实现
  • 【源力觉醒 创作者计划 】文心大模型4.5系列与DeepSeek、通义千问Qwen 3.0深度对比分析
  • 人工智能与安全:智能安防的创新与伦理边界
  • pycharm中debug的一些小细节
  • 压敏电阻的选型与计算分析
  • YOLO-01目标检测基础
  • 电子对抗技术在特种车辆中的实战应用与发展解析
  • windows环境下MySQL 8.0 修改或重置密码
  • mysql创建一个管理员用户
  • 《校园生活平台从 0 到 1 的搭建》第五篇:商品后端
  • 《零基础入门AI:传统机器学习核心算法解析(KNN、模型调优与朴素贝叶斯)》
  • Java Stream核心:ReferencePipeline解析
  • 如何判断一个数据库是不是出问题了?
  • Python处理JSON和Excel文件的转换
  • 2025年6月电子学会青少年软件编程(C语言)等级考试试卷(一级)
  • Elasticsearch 8.19.0 和 9.1.0 中 LogsDB 和 TSDS 的性能与存储改进
  • 分布式搜索和分析引擎Elasticsearch实战指南
  • Expected one result (or null) to be returned by selectOne(), but found: 2