深入解析事件基础与原子操作原理

打印 上一主题 下一主题

主题 1417|帖子 1417|积分 4251

title: 深入解析事件基础与原子操作原理
date: 2025/04/23 12:07:08
updated: 2025/04/23 12:07:08
author: cmdragon
excerpt:
事件是数据库操作的核心,需满足ACID特性:原子性、一致性、隔离性和持久性。事件隔离级别包括读未提交、读已提交、可重复读和串行化,实用于不同场景。嵌套事件通过上下文管理实现,支持回滚点以部分回滚。实战案例展示了订单体系中的事件处理,包括余额查抄和付出失败回滚。常见错误如TransactionManagementError和死锁,需通过精确使用事件装饰器和重试机制办理。课后Quiz探究了事件隔离和嵌套事件回滚的处理方法。运行情况设置包括依赖安装和FastAPI启动设置。
categories:

  • 后端开辟
  • FastAPI
tags:

  • 事件处理
  • ACID特性
  • 嵌套事件
  • 回滚点
  • 订单体系
  • 事件隔离级别
  • 数据库操作
扫描二维码关注或者微信搜一搜:编程智域 前端至全栈交流与成长
探索数千个预构建的 AI 应用,开启你的下一个伟大创意
1. 事件基础与原子操作原理

1.1 事件的ACID特性

在数据库操作中,事件必要满足ACID特性:

  • 原子性(Atomicity):操作要么全部乐成,要么全部失败
  • 一致性(Consistency):保持数据库的完整性束缚
  • 隔离性(Isolation):并发事件相互隔离
  • 持久性(Durability):提交后永世保存
  1. # 示例:银行转账的原子操作
  2. from fastapi import APIRouter, Depends
  3. from tortoise.transactions import atomic
  4. router = APIRouter()
  5. @router.post("/transfer")
  6. @atomic()  # 使用装饰器包裹事务范围
  7. async def transfer_money(
  8.         from_account: str,
  9.         to_account: str,
  10.         amount: float
  11. ):
  12.     # 扣减转出账户
  13.     from_acc = await Account.get(number=from_account)
  14.     from_acc.balance -= amount
  15.     await from_acc.save()
  16.     # 增加转入账户
  17.     to_acc = await Account.get(number=to_account)
  18.     to_acc.balance += amount
  19.     await to_acc.save()
  20.     return {"message": "转账成功"}
复制代码
1.2 事件隔离级别对比

级别脏读不可重复读幻读实用场景读未提交大概大概大概低并发场景读已提交禁止大概大概默认级别可重复读禁止禁止大概金融体系串行化禁止禁止禁止高精度要求2. 嵌套事件实现与回滚点

2.1 嵌套事件上下文管理
  1. from tortoise.transactions import in_transaction
  2. async def complex_operation():
  3.     async with in_transaction() as conn1:  # 外层事务
  4.         await Model1.create(...)
  5.         try:
  6.             async with in_transaction(connection=conn1) as conn2:  # 内层事务
  7.                 await Model2.create(...)
  8.                 await conn2.rollback()  # 仅回滚内层操作
  9.         except Exception:
  10.             pass
  11.         await Model3.create(...)  # 外层事务继续执行
复制代码
2.2 回滚点(Savepoint)使用
  1. async def savepoint_demo():
  2.     async with in_transaction() as conn:
  3.         savepoint = await conn.savepoint()  # 创建回滚点
  4.         try:
  5.             await Model.create(...)
  6.             if error_condition:
  7.                 await savepoint.rollback()  # 回滚到保存点
  8.         except Exception:
  9.             await savepoint.rollback()
复制代码
3. 完整实战案例:订单体系
  1. from fastapi import Depends
  2. from tortoise.contrib.fastapi import register_tortoise
  3. from tortoise.models import Model
  4. from tortoise import fields
  5. # 数据模型定义
  6. class User(Model):
  7.     id = fields.IntField(pk=True)
  8.     balance = fields.DecimalField(max_digits=10, decimal_places=2)
  9. class Order(Model):
  10.     id = fields.UUIDField(pk=True)
  11.     user = fields.ForeignKeyField('models.User')
  12.     amount = fields.DecimalField(max_digits=10, decimal_places=2)
  13.     status = fields.CharField(max_length=20)
  14. # 事务处理服务
  15. class OrderService:
  16.     @staticmethod
  17.     @atomic()
  18.     async def create_order(user_id: int, amount: float):
  19.         user = await User.get(id=user_id)
  20.         # 检查余额
  21.         if user.balance < amount:
  22.             raise ValueError("余额不足")
  23.         # 扣减余额
  24.         user.balance -= amount
  25.         await user.save()
  26.         # 创建订单记录
  27.         order = await Order.create(
  28.             user=user,
  29.             amount=amount,
  30.             status="PENDING"
  31.         )
  32.         # 模拟第三方支付调用
  33.         if not await call_payment_gateway():
  34.             await OrderService.rollback_order(order.id)
  35.             raise Exception("支付失败")
  36.         return order
  37.     @staticmethod
  38.     @atomic()
  39.     async def rollback_order(order_id: str):
  40.         order = await Order.get(id=order_id)
  41.         user = await order.user
  42.         # 恢复用户余额
  43.         user.balance += order.amount
  44.         await user.save()
  45.         # 更新订单状态
  46.         order.status = "CANCELED"
  47.         await order.save()
复制代码
4. 常见报错办理方案

4.1 TransactionManagementError

错误征象
TransactionManagementError: Transaction not found for current context
办理方法

  • 查抄事件装饰器的使用范围
  • 确保异步函数精确使用async/await
  • 验证数据库连接设置是否精确
4.2 死锁检测

错误日志
Deadlock found when trying to get lock
处理方案
  1. from tortoise.exceptions import OperationalError
  2. from fastapi import HTTPException
  3. async def safe_transaction():
  4.     try:
  5.         async with in_transaction():
  6.     # 数据库操作
  7.     except OperationalError as e:
  8.         if "Deadlock" in str(e):
  9.             await asyncio.sleep(0.1)  # 随机延迟后重试
  10.             return await safe_transaction()
  11.         else:
  12.             raise HTTPException(status_code=500, detail="数据库错误")
复制代码
5. 课后Quiz

5.1 事件隔离问题

问题:在可重复读隔离级别下,如何处理余额校验时的并发修改?
答案解析
使用SELECT FOR UPDATE锁定记录:
  1. async def update_balance(user_id: int):
  2.     async with in_transaction():
  3.         user = await User.select_for_update().get(id=user_id)
  4.         # 后续操作
复制代码
5.2 嵌套事件回滚

问题:当外层事件捕获内层事件的非常时,如何保证部分提交?
精确答案
使用保存点机制:
  1. async def nested_transaction():
  2.     async with in_transaction() as conn:
  3.         savepoint = await conn.savepoint()
  4.         try:
  5.         # 内层操作
  6.         except Exception:
  7.             await savepoint.rollback()
  8.         # 外层继续执行
复制代码
6. 运行情况设置

安装依赖:
  1. pip install fastapi tortoise-orm uvicorn pydantic
复制代码
启动设置:
  1. # main.py
  2. from fastapi import FastAPI
  3. app = FastAPI()
  4. register_tortoise(
  5.     app,
  6.     db_url='sqlite://db.sqlite3',
  7.     modules={'models': ['models']},
  8.     generate_schemas=True,
  9.     add_exception_handlers=True
  10. )
复制代码
启动命令:
  1. uvicorn main:app --reload
复制代码
余下文章内容请点击跳转至 个人博客页面 或者 扫码关注或者微信搜一搜:编程智域 前端至全栈交流与成长,阅读完整的文章:深入解析事件基础与原子操作原理 | cmdragon's Blog
往期文章归档:


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

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

本版积分规则

星球的眼睛

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表