Knex.js事务生成有效SQL无报错,但PostgreSQL未更新数据
问题原因
你这段代码的核心问题在于forEach不支持异步等待,循环内的await不会阻塞整个循环流程。事务回调函数会在所有更新操作实际完成前就执行完毕,而Knex的事务机制会在这种情况下自动回滚事务,最终导致数据库没有任何变更。
虽然Knex调试器显示每个更新语句都正常生成,但因为事务被自动回滚了,这些变更根本没被提交到数据库。而直接执行原生SQL时没有事务上下文,所以变更能正常生效。
修复方案
方案一:使用for...of循环(串行更新)
把forEach替换成支持异步等待的for...of,确保所有更新操作完成后事务才会提交:
const updatedLocations = await knex.transaction(async (trx) => { for (const location of locations) { location.entry_id = entry.id; await trx("locations").update(location).where("id", location.id); } });
方案二:使用Promise.all并行更新
如果你的更新操作之间没有依赖关系,可以用Promise.all并行执行所有更新,提升效率:
const updatedLocations = await knex.transaction(async (trx) => { await Promise.all(locations.map(async (location) => { location.entry_id = entry.id; return trx("locations").update(location).where("id", location.id); })); });
额外注意点
- 别忘了在
knex.transaction前加上await,这样可以正确捕获事务中的异常,也能确保后续代码在事务完成后再执行。 - 如果你需要更精细的控制,可以显式调用
trx.commit()或trx.rollback(),但只要回调函数返回的Promise被正确resolve,Knex会自动提交事务。
内容的提问来源于stack exchange,提问作者NYCaver
相关产品推荐
相关产品推荐

