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

Node.js中如何将现有SQL查询替换为SELECT FOR UPDATE?

使用SELECT FOR UPDATE优化你的Node.js MySQL查询

首先,SELECT FOR UPDATE的作用是锁定查询到的行,确保在当前事务完成(提交或回滚)之前,其他事务无法修改这些行,这在处理并发场景(比如用户余额更新、订单状态修改)时非常有用。不过要注意,必须配合事务使用,否则锁会在查询执行完成后立即释放,起不到预期效果。

下面是修改后的完整代码,我会标注关键改动点:

pool.connect((err, db) => { 
  if(err) { 
    console.log("Failed connection to mysql"); 
    errHandler(err); 
    return;
  } 

  // 1. 开启事务
  db.beginTransaction((err) => {
    if (err) {
      console.log("Failed to start transaction");
      errHandler(err);
      db.release(); // 释放连接
      return;
    }

    // 2. 修改SQL语句,添加FOR UPDATE
    let sql1 = 'select * from user where email = ? and role_number = ? FOR UPDATE'; 
    
    db.query(sql1, [email, role], (err, result) => { 
      if(err) { 
        console.log("Error in checking existing email");
        // 出错时回滚事务
        db.rollback(() => {
          errHandler(err);
          db.release(); // 释放连接
        });
        return;
      } 

      // 这里可以添加你需要执行的后续操作(比如更新用户信息、修改关联表数据等)
      // 示例:更新用户的last_login时间
      let updateSql = 'UPDATE user SET last_login = NOW() WHERE email = ?';
      db.query(updateSql, [email], (err, updateResult) => {
        if (err) {
          console.log("Error updating user");
          db.rollback(() => {
            errHandler(err);
            db.release();
          });
          return;
        }

        // 3. 所有操作完成后提交事务
        db.commit((err) => {
          if (err) {
            db.rollback(() => {
              console.log("Failed to commit transaction");
              errHandler(err);
              db.release();
            });
            return;
          }
          console.log("Transaction completed successfully");
          db.release(); // 最后一定要释放连接
        });
      });
    });
  });
});

关键注意事项:

  • 存储引擎要求:你的user表必须使用InnoDB存储引擎(MyISAM不支持事务和行级锁),否则SELECT FOR UPDATE不会生效。
  • 连接释放:无论操作成功还是失败,都要记得调用db.release()释放连接回连接池,避免连接泄漏。
  • 死锁预防:尽量减少事务的执行时间,避免长时间持有锁;同时确保多个事务的锁获取顺序一致,防止死锁。
  • 隔离级别:MySQL默认的隔离级别是REPEATABLE READ,这已经能满足大部分使用SELECT FOR UPDATE的场景,如果有特殊需求可以调整。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:18:25