尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
意外提交致数月重构!用AST和LLM规范数据库事务操作
深藏多层的意外提交耗时数月教你用AST和LLM规范数据库事务操作一个深藏多层的意外提交让我耗费了数月时间。本文将探讨为何数据库DB层必须掌控每一个提交和事务以及如何使用抽象语法树AST和代码检查工具linters来执行这些规则。2026年7月13日我为一个规范工作了好几个月最终所有相关方都批准了。我已将所有需要迁移的代码片段整理到了一个Notion数据库中。当处理第一个拉取请求PR时我看到了“db.commit()”这样的代码意识到这些“事务”在原子性的外衣下被提交了而我之前忘记考虑这些。这次问题并非出在对象关系映射ORM、参数化SQL语句或查询构建器上而是代码组织和抽象层面的严重失误导致事务内的代码失去了原子性。示例展示这些示例仅作说明之用代码已简化不包含任何框架或库的所有细微细节如会话创建等。隐藏的敌人class DBAccess:staticmethoddef create_records(records: List[DomainModel]):# 所有记录应作为一个事务处理with transaction():for r in records:DBAccess.create_main_records(r) # 调用辅助函数最终会调用 commit()# 另一个事务自动启动DBAccess.create_details_records(r)DBAccess.create_records(recs)这段代码在距离事务装饰器或上下文管理器两层以上的地方手动提交事务调用 create_main_records 时很难想到这个方法会进行提交操作。沉默的“假朋友”class DBAccess:staticmethoddef fetch_records(ids: List[int]) - List[DBModel]:db_models session.query(DBModel).filter(DBModel.id.in_(ids)).all()return cast(List[DBModel], db_models)with transaction():db_models DBAccess.fetch_records(ids)db_models[0].yo_mama_fat True # 这是一个无声的数据库写入操作# 上下文管理器退出时会帮你解决问题这段代码将数据库模型像普通领域模型一样传来传去设置属性看似只是赋值但实际上会触发数据库写入操作。一去不返class DBAccess:staticmethoddef fetch_records(ids: List[int]) - List[DBModel]:db_models session.query(DBModel).filter(DBModel.id.in_(ids)).all()return cast(List[DBModel], db_models)# 事务已被注释掉# with transaction():db_models DBAccess.fetch_records(ids)db_models[0].yo_mama_fat True# 请求结束数据消失得无影无踪# 就像程序员的爸爸出去买牛奶再也没回来这段代码既没有自动提交也没有事务处理会导致数据丢失。谁该负责不要责怪框架也不要责怪业务需求程序员是唯一的责任人。在很多情况下你可能不用为代码的现状负责但这次不行。任何做法都比随机提交要好。最后不管代码是不是你写的你都得负责解决这个烂摊子就像我这几个月一直在做的一样。我们能学到什么不要随意添加数据库会话或事务数据库抽象层应掌控事务和提交操作否则会像“撒盐哥”那样失败。不要在数据库层内外传递数据库模型。再次阅读第1点和第2点然后再读一遍把它们记在心里。不要在数据库层之外摆弄事务、提交、查询等操作连看都别看想都别想。不要手动提交尤其是在使用上下文管理器或装饰器的情况下你没那么厉害。不要把代码分散到辅助函数中原子性的多次写入操作应放在一个函数中代码重复能让原子性更明显也不会产生隐藏的问题。如何执行这些规则AST分析可以通过使用 [AST](https://docs.python.org/3/library/ast.html) 分析的自定义测试或者 [flake8](https://flake8.pycqa.org/en/latest/) 等代码检查工具来实现。无论选择哪种方式都应做到完全禁止手动调用提交操作。禁止在数据库访问层之外访问数据库会话。禁止在数据库访问层之外访问事务。禁止在数据库访问层之外导入数据库模型。使用AST进行禁止操作class TestDBBoundaries:def test_no_manual_commits():violations []for path, tree in parsed_source_files(): # 对源代码树进行 ast.parsefor node in ast.walk(tree):if not isinstance(node, ast.Call):continuefunc node.funcif ((isinstance(func, ast.Attribute) and func.attr commit) # session.commit()or (isinstance(func, ast.Name) and func.id commit)): # commit session.commit; commit()violations.append(f{path}:{node.lineno} manual commit())assert not violations, .join(violations)使用flake8进行禁止操作同样的遍历逻辑只是套上了flake8的“外衣”import astclass BanManualCommits:def __init__(self, tree):self.tree treedef run():for node in ast.walk(self.tree):if not isinstance(node, ast.Call):continuefunc node.funcif ((isinstance(func, ast.Attribute) and func.attr commit)or (isinstance(func, ast.Name) and func.id commit)):yield node.lineno, node.col_offset, DB001 manual commit(), type(self)注册方式如下[project.entry-points.flake8.extension]DB0 flake8_db_boundaries:BanManualCommits使用AST还是flake8在规则需要检查整个代码库或者不能修改共享的代码检查配置时使用AST测试。否则使用flake8或其他代码检查工具它们成为标准工具是有原因的。结合大语言模型LLM支持LLM可用于禁止数据库层返回任何数据库模型。AST和类型检查工具mypy都无法检测到这一点因为返回注释可能不准确cast() 函数会绕过类型检查且存在随机提交的代码库很难让人对类型系统有信心。因此这个检查可以在持续集成/持续部署CI/CD管道中通过LLM来完成。一个确定性的脚本会导出数据库访问层的公共函数/方法然后LLM回答一个简单的问题“是否有返回数据库模型而非领域模型的情况”结果如下是 - [人工审核](https://www.youtube.com/shorts/9arcEhyv_ZM)可能 - 人工审核否 - 通过领取工资总结数据库抽象层应掌控提交和事务其他做法都是因处理不当而采取的权宜之计。这样你就不用在发现一个随机提交后花费数月时间重构整个代码库来修复混乱的事务了。另外一定要读这本书[《领域驱动设计软件核心复杂性应对之道》](https://a.co/d/08hCw8SE)。想收听更多我的疯狂吐槽留下你的邮箱。订阅。如果你讨厌邮箱也可以使用 [RSS订阅源](/index.xml)。
RELATED

相关推荐

密码强度检查算法与安全实践详解

密码强度检查算法与安全实践详解

1. 项目背景与需求分析"SDUT-实验九-26 检查密码"这个实验题目看起来像是某高校软件工程或计算机相关专业的课程实验作业。作为一名带过多年实验课的助教,我深知这类密码检查实验的核心教学目的——让学生掌握字符串处理的基本方法,同时培养严…

📅 2026/9/22 4:44:49
claude code使用命令技巧(三)(后端需求开发流程)

claude code使用命令技巧(三)(后端需求开发流程)

问题一、后端标准需求开发完整流程(适配日常迭代、配合 Claude Code 协作)整体分为 需求阶段 → 方案设计 → 编码开发 → 自测联调 → 提测修复 → 上线收尾 6 大阶段,每个环节配套后端必做事项,同时附上适配你当前 Claude 开发模…

📅 2026/9/21 14:07:14
GIS本科生如何构建核心竞争力与提升就业价值

GIS本科生如何构建核心竞争力与提升就业价值

1. 本科GISer如何打造核心竞争力与附加价值作为一名在GIS行业摸爬滚打多年的从业者,我见过太多刚毕业的本科生在求职时面临的困境。他们往往掌握了ArcGIS等基础软件操作,却缺乏让用人单位眼前一亮的差异化竞争力。今天我就来聊聊,本科阶段的G…

📅 2026/8/24 12:52:11
MORE NEWS

更多资讯

📰

84888.com实战:从报错到精通,后端开发避坑指南

84888.com实战:从报错到精通,后端开发避坑指南 面对满屏的红色 StackTrace,你第一反应是复制粘贴去搜吗?别急,90%的新手都在这里栽了跟头。报错信息看不懂,代码逻辑理不清,这才是阻碍你从入门到精通的真正门槛。…

📰

英语交流实战项目避坑指南:搞定环境配置不卡壳

英语交流实战项目避坑指南:搞定环境配置不卡壳 刚接手一个跨境电商的后台系统,核心需求就是让客服团队能和海外客户进行 英语交流 。 配置环境就卡半天 ,这种痛谁懂? 我盯着终端报错信息看了二十分钟,最后发现是 Node.js…

📰

告别Pyplot报错:数据可视化选型最佳实践与避坑指南

告别Pyplot报错:数据可视化选型最佳实践与避坑指南 屏幕上一片红,满屏的 Traceback 堆叠,看着 ValueError 和 TypeError…

📰

南大团队推翻美室温超导研究,运维人如何入门到精通

南大团队推翻美室温超导研究,运维人如何入门到精通 官方文档太长抓不住重点,这是无数新人入行时的第一道坎。别慌,今天咱们不整虚的,直接拆解 南大团队推翻美室温超导研究 这一热点背后的技术逻辑,带你从入门到精通。…

📰

3分钟搞懂什么是5g:面试防挂速查手册

3分钟搞懂什么是5g:面试防挂速查手册 面试被问“什么是5G”,你张嘴就是“网速快”,考官脸都绿了。 别慌,手里没个 速查手册 ,这种基础概念题最容易翻车。 今天把原理、代码、坑点一次性讲透,让你下次面试稳拿分。 概念速懂:别只盯着网速…

📰

琅琊榜排名图解原理:3步搞定性能优化,告别配置卡顿

琅琊榜排名图解原理:3步搞定性能优化,告别配置卡顿 配置环境就卡半天?别急,先看看琅琊榜排名背后的图解原理。 很多开发者在跑高并发场景时,发现列表排序接口响应慢,CPU 飙升,内存泄漏。…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬