数据库服务开发:分层、Session 与事务回滚|课后复习

课堂课件 · 课前原始判断 · 本周导学

今天学会了什么

能解释 with 如何进入、退出并传播异常,验证成功、业务失败和提交失败后的资源清理;能在真实 MySQL 验证整笔订单回滚。

原子下单与唯一提交点

在图上找出订单头、全部明细与库存共用的提交点,再沿异常路径指出哪些变化必须一起撤销。

今天讲了什么(对照复习)

下面逐项对应课堂正文。先盖住右边那一栏,凭记忆回答;卡住了再翻回左边同名的小节。光说得出名字不算会,还要能讲清它会做什么、什么时候会失效。

课堂对应章节必须能解释的机制与边界
四层职责和依赖方向;从文件错误迁移到数据库业务错误Model 管对象规则,Service 管用例和跨对象规则,持久化层管理读写,CLI/后续 Router 适配输入输出。数据库阶段沿用 CommerceError 下的 ResourceNotFound 等实际异常;旧文件 StorageCorruptedError 不替代数据库业务错误。
SQLAlchemy:先认识表映射与连接工厂ORM 映射表与对象,不自动决定事务。Engine 可共享连接池,sessionmaker 是工厂,Session 是一次工作状态;Mapped/mapped_column 描述映射,不等于运行时业务校验。
先演示一个坏结果;事务是什么;原子下单只有一个提交点;autocommit 的陷阱相关写入放进一个事务,全部成功才 commit,否则 rollback。循环逐项提交会留下半张订单;不能仅凭代码没写 commit 就忽略驱动和数据库的自动提交模式。
Session 是什么;flush、commit、rollbackSession 取连接、追踪变更、发 SQL,结束后关闭并归还资源。flush 发出待写 SQL但未最终提交;commit 会先 flush 再提交;失败后 rollback 恢复事务边界,不能继续使用失败状态的 Session。
Service 与 Unit of Work:一次用例一次事务UoW 汇合一次用例的数据访问与事务;Protocol 声明需要的方法,省略号不代表已实现。with 调用 enter/exit,具体实现负责未提交回滚和 close。查询订单关联明细时,joinedload 与 unique 分别处理关联读取和重复行。
用失败注入证明 rollback;rollback 通过要看到什么第二条明细失败时,用独立查询比较前后:新订单头与明细不存在,两件商品库存均回到操作前。捕获异常或打印失败不证明回滚;稳定业务错误与数据库故障需区分。
先建立同步数据库服务,再讨论异步今天直接用 Python/CLI 调用同步 Service,每个用例独立 Session。Fake 可验证规则,不证明 InnoDB 锁与约束;真实数据库集成另记,HTTP 翻译在下次课接入。

出了问题:怎么发现、怎么修、怎么验证

只在你自己那份课程副本或专用实验数据上复验,把改之前和改之后的真实结果都留下来。

风险/现象提前预防怎样发现怎样处理怎样复验
循环提交留下半张订单Service 统一事务,全部完成才提交第二项失败后查询订单头、明细及两项库存移除数据访问内部提交,统一 UoW全部前后事实符合回滚要求
全局 Session 或失败后不清理每用例创建会话,退出必清理观察异常后的下一次请求及连接占用rollback 后关闭;工厂共享、实例独立失败后新用例正常,资源及时归还
flush 被当成持久提交标清 flush 与 commit 位置flush 后注入异常,再用新会话查询保持单一最终提交点未提交变化撤销,成功事务可查
业务异常名混用或连接故障冒充不存在对照当前异常类型与职责分别触发未知订单与连接不可用上层按业务类型处理,保留底层诊断两种错误可区分,错误细节不泄密
Fake 通过冒充真实回滚结果注明替身或真实库核对连接环境和操作前后 SQL 结果在课程 MySQL 重新执行失败注入真实结果单独留证,未跑则待验证

本日新增 Python 知识怎样进入商城

enter/exit、异常传播、try/finally、contextmanager 单次 yield、closing;复用 Session/UoW/flush/commit/rollback。它们共同支持“整笔订单失败回滚与连接释放”。我应能打开 session_scope.py 指出每个机制的位置,并重跑 正常 commit→close;业务失败 rollback→close;提交失败仍关闭;真实第二项失败后核对三类表和库存。

风险提前预防怎样发现怎样处理怎样复验
异常被上下文压住退出返回 False/None,捕获后重新抛出失败实验却走到成功提示恢复异常传播调用者收到错误且 close 已发生
提交或业务失败资源未释放close 放 finally,事务策略统一替身事件缺 close,实库连接未归还修复退出边界,不在循环提交正常/业务失败/提交失败分别回归

闭卷自测

先自己答一遍,再去运行或翻回课堂核对;不确定的地方标出来,别用 AI 的答案顶掉你自己的第一次判断。

  1. 说出一次创建订单各层负责什么;为什么 Router 或 CLI 不应自己提交数据库事务?

  2. Engine、sessionmaker、Session 能否全部全局共享?flush 与 commit 有什么差别?

  3. Protocol 的方法写了省略号是否可以执行业务?with 如何触发 UoW 的进入与退出?

  4. 第二个商品失败后,列出必须核对的订单、明细和库存事实。异常被捕获为什么不够?

  5. Fake 测试、真实 MySQL 事务测试各能证明什么?如何避免把连接失败返回成资源不存在?

  6. exit 返回 True 会怎样影响业务异常?生成器上下文管理器为何只 yield 一次?commit 失败时怎样验证 rollback 与 close?

再看一眼真实业务

有赞公开说明能确认订单与库存的业务关联;它没有证明后台是否使用单库事务。用自己的两明细失败记录解释课程实现怎样保护这个关联。

今天留下什么,下节课怎么接着用

同时保留本人 session_scope.py 及成功、业务失败、提交失败的生命周期记录,后续 API 继续使用同一资源边界。

保留数据库版 Service、UoW/Session 生命周期图、正常提交与第二项失败回滚证据,以及真实库/替身分栏结果。W02-D03 复用这些服务接 HTTP,不在路由里重写规则。

隔离级别、真实连接竞争和死锁在 W03-D01 深化;今天不以串行成功证明并发正确。

补充交接:D03 直接复用数据库服务,通过 HTTP 接入并补异步多源查询。本人 commerce_ops 每天增量合并,不用后一天骨架覆盖前一天实现。