You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL如何实现类似Firestore的原子增减 解决并发更新数值错误问题

基于PostgreSQL实现原子增减的方案

核心原理

PostgreSQL的单条UPDATE语句本身具备原子性,执行时会自动对目标行加排他锁,并发请求会按顺序依次执行更新,每一次的字段计算都会基于上一次更新后的最新值,天然避免竞态条件,默认的READ COMMITTED事务隔离级别即可满足需求,无需额外配置。

原生SQL实现

假设你的业务表名为posts,需要增减的计数字段为like_count,帖子主键为id,实现+1的SQL语句如下:

-- +1操作
UPDATE posts SET like_count = like_count + 1 WHERE id = 目标帖子ID;
-- -1操作只需把+改成-即可
UPDATE posts SET like_count = like_count - 1 WHERE id = 目标帖子ID;

该写法下并发5个+1请求执行后,字段值会从10变为15,不会出现更新覆盖的问题。如果需要直接拿到更新后的最新值,可以在SQL末尾加RETURNING like_count,无需二次查询。

结合NodeJS + Express的代码实现

以最常用的pg(node-postgres)库为例,接口示例如下:

const { Pool } = require('pg');
const pool = new Pool({
  // 替换为你的PostgreSQL连接配置
  host: 'localhost',
  user: '数据库用户名',
  password: '数据库密码',
  database: '业务库名'
});

// 帖子点赞接口示例
app.post('/posts/:id/like', async (req, res) => {
  const postId = req.params.id;
  try {
    const result = await pool.query(
      `UPDATE posts SET like_count = like_count + 1 WHERE id = $1 RETURNING like_count;`,
      [postId]
    );
    if (result.rowCount === 0) {
      return res.status(404).json({ message: '帖子不存在' });
    }
    // 直接返回最新计数值给前端React渲染
    res.json({ likeCount: result.rows[0].like_count });
  } catch (err) {
    console.error('更新失败:', err);
    res.status(500).json({ message: '操作失败' });
  }
});

ORM场景示例(可选)

如果你的项目使用Sequelize等ORM框架,无需手写SQL也可以调用封装好的原子增减方法,本质也是生成上述原子UPDATE语句:

// Sequelize 示例
const [updatedRows, [updatedPost]] = await Post.increment('like_count', {
  by: 1, // 增减数值,减1传-1即可
  where: { id: postId },
  returning: true // 开启后返回更新后的行数据
});
console.log(updatedPost.like_count); // 最新的计数值

TypeORM等其他ORM都有对应的原生增减方法,直接调用即可。

常见避坑

  • 禁止使用「先SELECT查值 -> JS层做加减计算 -> 再UPDATE写回」的实现逻辑,该方案存在竞态条件,并发场景下必然出现更新覆盖的问题
  • 若需要动态指定增减数值,直接将动态值作为SQL参数传入即可,语法为UPDATE posts SET like_count = like_count + $2 WHERE id = $1,原子性不受影响
  • 仅当存在多字段关联更新、带复杂条件的更新等需求时,才需要配合事务+行锁实现,纯±1场景无需额外加锁,默认配置即可保证并发安全

内容的提问来源于stack exchange,提问作者SURYA B

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 17:51:01