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

.NET Core IQueryable Lambda查询内存泄漏问题排查求助

EF Core查询引发内存泄漏问题排查与解决

问题背景

在带有唯一索引的列上执行Lambda查询时,每个请求会产生8-12KB的内存泄漏。当前每秒约有7-8次请求(100个客户端每4.5秒调用一次),IIS内存在1-2小时内会升至2GB。已尝试AsNoTracking、ToList()、Count()等方法,均无法解决内存泄漏问题。怀疑是数据库连接未完成导致Dispose失效,同时怀疑Controller过载引发内存累积,计划测试1000 RPS场景,寻求排查与解决方法。

相关代码

查询方法代码

bool KontrolKullanildi(string QrCode)
{
    using (EmlesCore.Models.Database db = new EmlesCore.Models.Database())
    {                
        using (var o = db.mobilQrTempler.AsNoTracking().Where(f => f.CryptoKod == QrCode && f.Kullanildi).AsNoTracking().FirstOrDefault())
        {
            if (o != null)
            {
                return true;
            }
        }

        return false;
    }
}

DbContext代码

public class Database:DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(Utils.DbConnectionString());
        
    }

    public DbSet<mobileQrTemp> mobilQrTempler { get; set; }
}

Controller代码

public class QrGirisCikisQrKontrol : Controller{
    public async Task<JsonResult> GetQrCode(string parameters)
    {
        if (KontrolKullanildi(QrFiltre))
        {
            return Json(QrCodeOlusturDondur(Parameters));
        }

        return Json(Ok());
    }
}

Ajax调用示例

$.ajax({
    type: "GET",
    url: "@Url.Action("GetQrCode","QrGirisCikisQrKontrol")",
    data: params,
    success: function (result) ..............
})

排查与解决步骤

1. 修正查询代码中的错误用法

查询代码存在明显问题:FirstOrDefault()返回的实体对象默认不实现IDisposable接口,不能用using包裹,这种错误用法可能引发对象生命周期异常,间接导致内存问题。同时重复调用AsNoTracking无意义,且FirstOrDefault()会加载整个实体,内存开销更大。

修正后的查询代码:

bool KontrolKullanildi(string QrCode)
{
    using (EmlesCore.Models.Database db = new EmlesCore.Models.Database())
    {                
        // 使用Any()生成高效的EXISTS SQL,无需加载实体
        return db.mobilQrTempler.AsNoTracking()
                                .Any(f => f.CryptoKod == QrCode && f.Kullanildi);
    }
}

2. 检查DbContext与数据库连接配置

  • 确认连接池设置:确保Utils.DbConnectionString()返回的连接字符串包含合理的连接池参数,避免频繁创建/销毁连接导致的内存波动,示例:
    Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;Max Pool Size=100;Min Pool Size=5;
    
  • 验证DbContext释放逻辑:默认EF Core的DbContext会在Dispose时将连接归还到连接池,无需重写Dispose方法,若自定义了该方法需检查是否破坏了原有逻辑。

3. 定位内存泄漏具体来源

  • 使用内存分析工具:用Visual Studio内存诊断工具或dotMemory捕获高并发下的内存快照,对比多次请求后的对象变化,重点排查:
    • EF Core内部缓存对象是否持续增长
    • 未被回收的数据库连接相关对象
    • Controller或业务方法中的静态变量/全局集合
  • 检查业务逻辑中的大对象:若QrCodeOlusturDondur方法生成大型QR码对象,需确认是否存在未释放的引用,或改用带过期策略的分布式缓存替代内存缓存。

4. 优化Controller请求处理

  • 改为异步查询:当前Controller方法标记为async但查询是同步的,高并发下会阻塞线程池资源,引发内存堆积。修正为异步实现:

async Task KontrolKullanildiAsync(string QrCode)
{
using (EmlesCore.Models.Database db = new EmlesCore.Models.Database())
{
return await db.mobilQrTempler.AsNoTracking()
.AnyAsync(f => f.CryptoKod == QrCode && f.Kullanildi);
}
}

// Controller中调用
public async Task GetQrCode(string parameters)
{
if (await KontrolKullanildiAsync(QrFiltre))
{
return Json(QrCodeOlusturDondur(Parameters));
}

return Json(Ok());

}

### 5. 高并发测试验证
用JMeter、k6等工具模拟1000 RPS场景,同时监控内存变化:
- 观察内存是否稳定,无持续飙升情况
- 对比优化前后的SQL执行效率,确认`Any()`生成的查询更高效

内容的提问来源于stack exchange,提问作者ahomag
相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 19:20:41