查看: 82|回复: 0

.NET SqlSugar多线程下SqlSugarClient 的线程安全陷阱

[复制链接]

0

主题

0

回帖

0

积分

积极分子

金币
0
阅读权限
220
精华
0
威望
0
贡献
0
在线时间
0 小时
注册时间
2008-5-11
发表于 2026-3-5 17:40:00 | 显示全部楼层 |阅读模式

使用SqlSugar读取Sqlite数据库,项目运行过程中间歇性抛出以下异常:

SqlSugar.SqlSugarException:“中文提示 : 连接数据库过程中发生错误,检查服务器是否正常连接字符串是否正确,错误信息:Connection was closed, statement was terminatedDbType="Sqlite";ConfigId="".
English Message : Connection open error . Connection was closed, statement was terminatedDbType="Sqlite";ConfigId="" ”

经定位,异常抛出位置在一个很普通的查询操作上:

public List<SqliteDiskEntity> GetDisksByPDiskId(string env, string project, int pDiskId)
{
    return _db.Queryable<SqliteDiskEntity>().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};Version=3;Journal Mode=Wal;BusyTimeout=5000;",
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)。

整个调用链路如下:

image

这个错误的迷惑性在于:

  • 连接字符串完全正确
  • IsAutoCloseConnection = true 看似已经处理了连接释放
  • 异常只在多任务并发时偶发出现
  • 异常信息指向"连接错误",容易误导排查方向

将SqlSugarClient(非线程安全)改为SqlSugarScope(线程安全),即可

SqlSugarClient vs SqlSugarScope的区别,列个对比

image

 

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

相关侵权、举报、投诉及建议等,请发 E-mail:qiongdian@foxmail.com

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部