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

C#使用SQLite事务批量插入数据时报database is locked错误如何解决

错误说明

你遇到的是SQLite常见的写锁冲突错误:

Unhandled exception. code = Busy (5), message = System.Data.SQLite.SQLiteException (0x800007AF): database is locked
database is locked

核心原因
  • 参数重复添加导致执行异常:你在foreach循环中反复调用AddWithValue给同一个命令对象追加参数,而非覆盖原有参数值,导致命令逻辑异常,事务持有写锁的时间被大幅拉长,甚至出现执行异常导致锁未正常释放。
  • 默认锁等待时间过短:SQLite默认的锁超时时间很短,只要短时间内获取不到写锁就会直接抛出Busy错误。
  • 大事务持有锁时间过长:如果records数据量很大,单事务执行时间过长,会导致其他请求等待超时触发锁错误。
修复方案
  1. 修正参数添加逻辑,避免循环内重复追加参数
    提前在循环外定义好命令参数,循环内仅修改参数值即可,优化后的代码如下:
public void InsertRecords(List<string> records, Device device)
{
    using (var conn = new SQLiteConnection(connStr))
    {
        conn.Open();
        // 设置30秒锁超时,大幅降低锁冲突报错概率
        conn.BusyTimeout = 30000;
        using (var transaction = conn.BeginTransaction())
        {
            // 初始化插入records的命令,提前绑定参数
            var insRecStmt = new SQLiteCommand(
                "INSERT INTO records(content) VALUES(@content);", 
                conn, 
                transaction
            );
            insRecStmt.Parameters.Add("@content", System.Data.DbType.String);

            // 初始化插入foo的命令,提前绑定参数
            var fooStmt = new SQLiteCommand(
                "INSERT INTO foo(rec_id, bar) VALUES (@rec_id, @bar);", 
                conn, 
                transaction
            );
            fooStmt.Parameters.Add("@bar", System.Data.DbType.Int32).Value = device.Id;
            fooStmt.Parameters.Add("@rec_id", System.Data.DbType.Int64);

            foreach (var record in records)
            {
                // 仅修改参数值,不要重复Add
                insRecStmt.Parameters["@content"].Value = record;
                insRecStmt.ExecuteNonQuery();
                var rowID = conn.LastInsertRowId;
                fooStmt.Parameters["@rec_id"].Value = rowID;
                fooStmt.ExecuteNonQuery();
            }

            transaction.Commit();
        }
    }
}
  1. 调整连接字符串配置
    可以在连接字符串中开启共享缓存,降低同进程多连接的锁冲突概率,参考配置:
    Data Source=你的数据库文件路径;Version=3;Cache=Shared;
  2. 大数量场景拆分事务
    如果单次插入的records数量超过1万条,建议拆分事务,每1000~5000条提交一次,避免单事务持有锁时间过长。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 21:36:03