SQL UPDATE语句执行无更新 SELECT查询返回更新前数据如何排查
问题原因分析
- 最核心的原因是你使用的Node.js SQLite接口(通常为
sqlite3库)的所有数据库操作都是异步非阻塞的:调用db.run时仅会把更新任务提交到事件队列,代码不会等待更新执行完成就会继续向下执行后续的db.all查询,因此查询操作实际在更新操作落地到数据库之前就已经完成,自然返回的是旧数据。 - 次要排查点:若确认执行顺序没有问题,可检查
WHERE var = '5678'的匹配条件,确认表中确实存在var字段值为5678的行,没有匹配行的情况下更新不会产生任何修改,也会返回旧数据。
解决方案
- 方案1:把查询逻辑放到UPDATE的回调函数中,保证更新执行完成后再触发查询
if (req.headers['user-agent'].includes('HeadlessChrome') && (end - start <= 500)) { db.run("UPDATE tab SET var = '1234' WHERE var = '5678'", (err) => { if(err) { return console.log(err.message); } // 更新完成后再执行查询 const query = "SELECT * FROM tab" db.all(query, (error, rows) => { // 此处获取的就是更新后的最新数据 ... }) }) }
- 方案2:改用Promise+async/await写法,避免回调嵌套,逻辑更清晰。可以直接用
sqlite封装库,也可以自行对sqlite3的接口做Promise化封装
// 先封装db.run和db.all为Promise形式 const dbRun = (sql, params = []) => new Promise((resolve, reject) => { db.run(sql, params, function(err) { if (err) reject(err) else resolve(this) }) }) const dbAll = (sql, params = []) => new Promise((resolve, reject) => { db.all(sql, params, (err, rows) => { if (err) reject(err) else resolve(rows) }) }) // 业务逻辑用async函数包裹 async function handleRequest() { if (req.headers['user-agent'].includes('HeadlessChrome') && (end - start <= 500)) { await dbRun("UPDATE tab SET var = '1234' WHERE var = '5678'") } const rows = await dbAll("SELECT * FROM tab") // 此处获取的就是更新后的最新数据 ... }
- 方案3:特殊场景需要强制同步执行的话,可以使用
sqlite3的exec同步接口,但不推荐在请求处理逻辑中使用,会阻塞事件循环影响服务性能。
内容的提问来源于stack exchange,提问作者seriouslyg0e
相关产品推荐
相关产品推荐

