Sequelize 事务与并发安全
· 阅读需 2 分钟
很多人提到事务,第一反应都是订单、库存、支付。但内容系统也会遇到并发问题,只是它通常没那么刺眼,等线上数据变脏了才会意识到早该补。
博客后台最典型的两个场景:
- 一篇文章发布时,需要同时更新文章状态、发布时间和标签关系
- 批量调整分类或标签时,不能写到一半失败一半成功
Sequelize 在这类场景里,最稳的用法还是显式事务。
async function publishPost(postId, payload) {
return sequelize.transaction(async (transaction) => {
const post = await Post.findByPk(postId, { transaction });
if (!post) {
throw new Error('文章不存在');
}
await post.update({
title: payload.title,
summary: payload.summary,
content: payload.content,
status: 'published',
publishedAt: new Date(),
}, { transaction });
if (Array.isArray(payload.tagIds)) {
await post.setTags(payload.tagIds, { transaction });
}
return post;
});
}
为什么博客系统也值得上事务
如果不包事务,最常见的问题是:
- 文章已经变成已发布,但标签关系没更新成功
- 分类调整成功了,但归档时间没写进去
- 批量操作执行到一半报错,后台看到的是“部分成功”的脏状态
这种问题不一定会立刻炸,但会让内容列表越来越难维护。
事务别用得太重
我不建议把所有写操作都包进超长事务里。博客系统的事务更适合用在“一个业务动作需要保证多次写操作一致”的地方,而不是每个接口都上。
比较适合事务的动作有:
- 发布文章
- 撤回文章
- 批量迁移分类
- 标签关系重建
不太需要事务的动作:
- 单纯更新阅读量
- 单独修改标题
- 纯查询接口
并发安全不只靠事务
很多后台的内容覆盖问题,其实是“最后一次保存覆盖前一次编辑”。如果多人协作明显增加,除了事务,还可以考虑:
- 给文章加
updatedAt版本校验 - 保存前比对最近更新时间
- 后台界面提示“内容已被他人修改”
小结
Sequelize 事务最适合解决内容系统里那些“不够频繁、但一出问题就很恶心”的数据一致性问题。博客业务不复杂,反而更适合早点把这些底层习惯养起来。
