Sequelize异步查询并发执行是否会读取到未更新旧值问题咨询
结论
会出现读取到旧值的情况,Sequelize本身不存在查询等待另一个更新操作完成的默认机制。
原因说明
- Sequelize作为ORM层,仅负责将业务侧的查询、更新操作转换为SQL语句发送到数据库,本身没有全局的单行操作调度、排队逻辑。两个异步函数并发执行时,操作会独立发往数据库,很容易触发竞态条件:
函数A先查询拿到旧值 → 函数B在A的更新操作执行完成前也查询拿到相同旧值 → A先完成更新 → B基于旧值计算后执行更新,最终覆盖A的更新结果,导致数据异常。
- 这类并发读写问题本质是数据库层面的事务隔离级别问题,Sequelize默认不会替业务做额外的并发控制。
常见解决方案
1. 悲观锁(适合冲突频率高的场景)
查询时主动加行锁,持有锁的事务完成前,其他同数据行的查询会等待锁释放,避免读到未提交的旧值,需要包裹在事务中使用,示例代码:
const t = await sequelize.transaction(); try { // lock: true 表示对查询到的行加排他锁 const targetRow = await YourModel.findOne({ where: { id: 目标行ID }, lock: true, transaction: t }); // 执行业务计算逻辑 targetRow.目标列 = 计算后的新值; await targetRow.save({ transaction: t }); await t.commit(); } catch (err) { await t.rollback(); throw err; }
2. 乐观锁(适合冲突频率低的场景)
给对应数据表加version字段,Sequelize定义模型时开启version: true配置,更新操作会自动校验版本号,若版本号不匹配(说明其他事务已经更新过当前行)会抛出错误,业务侧捕获错误后重试即可。
内容的提问来源于stack exchange,提问作者Viriato
相关产品推荐
相关产品推荐

