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

SQLite异步批量插入返回重复ID,部分文件未写入数据库求助

问题分析与解决方案

这不是SQLite的固有问题,你的问题大概率出在并发场景下的数据库连接管理不当、SQL参数化不彻底,或者事务使用错误上,以下是具体分析和解决办法:

可能的原因

  1. 连接复用导致的竞态问题
    如果多个上传请求共用同一个SQLite连接,异步执行插入操作时,可能出现请求间的竞态:前一个请求的RETURNING Id结果被后一个请求错误获取,导致返回重复ID,而实际未插入成功的请求是因为SQLite的单写机制阻塞或覆盖了并发写入。

  2. SQL拼接的风险与时序问题
    你的SQL语句中,uploaderId、extension.Id、fileSize、Created都是直接字符串拼接,只有FileName用了参数。这种写法不仅存在SQL注入风险,还可能在高并发下因为字符串拼接的时序问题,导致生成的SQL语句不符合预期,进而影响插入结果和ID返回。

  3. 事务使用错误
    你提到用事务时出现语法错误,大概率是事务的执行逻辑不对:SQLite的事务必须在同一个数据库连接内完成BEGIN、INSERT、COMMIT/ROLLBACK的完整流程,跨连接的事务操作必然报错。

解决步骤

1. 彻底修复参数化查询

把所有变量都改为参数化传递,杜绝字符串拼接:

const insertSql = `INSERT INTO ${this.TableName} (
    UploaderId,
    ExtensionId,
    Size,
    FileName,
    IsStaging,
    Created
) VALUES (?, ?, ?, ?, 1, ?) RETURNING Id;`;

const insertResult = await Db.GetAsync(insertSql, 
    uploaderId, 
    extension.Id, 
    fileSize, 
    nameDetails.NameSanExtension, 
    SysTrick.NowToUtcString()
);

参数化查询不仅能避免SQL注入,还能确保每个请求的SQL语句独立,不会被并发操作干扰。

2. 确保每个请求使用独立的数据库连接

SQLite本质是单写数据库,高并发场景下必须保证每个请求使用独立的连接(或通过连接池管理连接),避免多个异步请求共用同一连接导致的竞态:

  • 如果使用sqlite(Promise版)或sqlite3,建议用连接池分配连接;
  • 如果用better-sqlite3,注意它是单线程同步库,需要用异步包装(如worker_threads)处理并发请求,避免阻塞。

3. 正确使用事务包裹插入操作

如果需要保证插入的原子性,事务必须在同一个连接内执行,示例代码如下:

// 假设DbPool是你的数据库连接池实例
const dbConn = await DbPool.acquire();
try {
    await dbConn.run('BEGIN TRANSACTION');
    const insertResult = await dbConn.get(insertSql, [
        uploaderId, 
        extension.Id, 
        fileSize, 
        nameDetails.NameSanExtension, 
        SysTrick.NowToUtcString()
    ]);
    await dbConn.run('COMMIT');
    result.Id = SysTrick.SafeInteger(insertResult.Id);
} catch (err) {
    await dbConn.run('ROLLBACK');
    throw err; // 抛出错误让上层处理
} finally {
    DbPool.release(dbConn); // 释放连接回池
}

4. 检查自增ID的定义

确保你的ID字段是INTEGER PRIMARY KEY AUTOINCREMENT,而不是单纯的INTEGER PRIMARY KEY。后者是SQLite rowid的别名,删除记录后可能会复用ID;前者会严格递增,确保数据库内ID绝对唯一(这一步是补充,不是直接解决返回重复ID的问题,但能强化数据完整性)。

总结

你的问题是并发场景下的代码实现问题,和SQLite本身的特性无关。按照上面的步骤修复后,多文件上传时的ID返回重复、记录丢失问题应该能解决。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 17:17:34