事务作用域不要跨服务无限扩散
· 阅读需 2 分钟
Sequelize 开事务并不难,难的是控制事务作用域。很多项目一开始只是局部写入,后来为了复用逻辑,把 transaction 对象一层层往下传,结果一个简单发布动作能串起好几个服务函数,谁都可能在事务里顺手写点东西。
我更倾向把事务边界收在“用例层”或“服务入口层”。也就是说,事务由最外层业务流程负责开启和提交,内部子函数只接受明确的仓储操作,不继续把事务语义向外扩散。这样做能让人很清楚地知道:一次事务到底保护了哪些写入,失败时该回滚到哪里。
如果事务对象在系统里漫游太久,通常会带来两个问题:
- 调用方越来越难判断自己是否处于事务上下文。
- 本来可以拆开的逻辑被迫绑成同步链路。
事务的价值在于保护一致性,不是在代码里制造隐形耦合。边界越清楚,后面越好维护。
为什么这类问题总会在线上阶段突然变贵
围绕「事务作用域不要跨服务无限扩散」这类判断,最容易被低估的地方,是大家前期总把它当成 ORM 写法偏好,而不是数据契约和查询边界。数据量小、调用方少的时候,字段命名、关联深度、分页方式、迁移顺序都像只是风格问题;一旦接口被更多页面复用,筛选、排序、统计和审计需求一起叠上来,之前没收住的边界就会同时在性能、排障和协作成本上爆出来。
落地时我会先卡住的检查项
- 先把输入 DTO、模型字段和最终 SQL 这三层对应关系看清,避免“接口语义已经变了,ORM 代码却还在偷偷兜底”。
- 把统计、明细、写操作和回滚路径拆开看,别让一个方便的查询顺手背上太多职责。
- 一旦这篇文章讨论的点已经影响到索引、事务或迁移顺序,就说明它不是微调,而是该补正式约束了。
