.NET SqlSugar多线程下SqlSugarClient 的线程安全陷阱
was terminatedDbTypeSqlite;ConfigId.English Message : Connection open error . Connection was closed, statement was terminatedDbTypeSqlite;ConfigId ”经定位异常抛出位置在一个很普通的查询操作上public ListSqliteDiskEntity GetDisksByPDiskId(string env, string project, int pDiskId) { return _db.QueryableSqliteDiskEntity().Where(x x.PDiskId pDiskId).ToList(); }连接字符串没有问题数据库文件也正常存在且异常并非每次必现而是偶发性的。排查过程1. 排除连接字符串问题连接配置如下看起来没有明显问题1 private static SqlSugarClient CreateClient(string dbPath) 2 { 3 return new SqlSugarClient(new ConnectionConfig 4 { 5 ConnectionString $Data Source{dbPath};Version3;Journal ModeWal;BusyTimeout5000;, 6 DbType SqlSugar.DbType.Sqlite, 7 IsAutoCloseConnection true, 8 }); 9 }已开启 WAL 模式、设置了 BusyTimeout、配置了 IsAutoCloseConnection true表面上不应该出问题。2. 调试器线程分析 —— 发现并发访问在 Visual Studio 中暂停调试查看线程窗口时发现了关键线索线程 ID 当前位置34996 DiskSubscribeTimer_Triggered(object, SubscribeTaskArgs)30716 ExecuteSubscribeTask(SubscribeTaskArgs) → RunSubscribeTaskAsync()38276 DiskSubscribeTimer_Triggered(object, SubscribeTaskArgs)虽然代码中用 ConcurrentDictionary 防止了同一个磁盘的并发执行但不同的订阅任务仍然会并行运行共享同一个 _db 实例。问题根因及解决_db是SqlSugarClient实例所以此实例不是线程安全的。 当多个线程同时通过同一个 SqlSugarClient 实例操作数据库时内部的连接/命令对象会发生竞争导致 SQLite 底层返回 SQLITE_MISUSE即 bad parameter or other API misuse。整个调用链路如下这个错误的迷惑性在于连接字符串完全正确IsAutoCloseConnection true 看似已经处理了连接释放异常只在多任务并发时偶发出现异常信息指向连接错误容易误导排查方向将SqlSugarClient非线程安全改为SqlSugarScope线程安全即可SqlSugarClient vs SqlSugarScope的区别列个对比