跳到主要内容

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 事务最适合解决内容系统里那些“不够频繁、但一出问题就很恶心”的数据一致性问题。博客业务不复杂,反而更适合早点把这些底层习惯养起来。