You need to enable JavaScript to run this app. ASP.NET Core下Oracle.ManagedDataAccess.Core大查询后内存不释放求助
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core下Oracle.ManagedDataAccess.Core大查询后内存不释放求助

Oracle.ManagedDataAccess.Core 大结果集查询后内存不释放问题排查

问题核心现象

  • 团队封装的统一Oracle查询类Clases.Oracle()在常规业务场景下运行稳定,仅执行某类返回大结果集的查询时出现内存异常累积问题:单次查询最坏场景返回26万行结果,内存临时攀升至1GB本身属于可接受范围,但查询执行完成后内存始终无法主动回落
  • 重复执行该类大结果集查询时,内存会随执行次数持续叠加,单线程重复执行的内存攀升上限为2GB;模拟8个并发请求场景时,内存最高可攀升至3GB
  • 内存诊断工具观测显示,查询执行完成、业务结果返回很久后,Oracle驱动内部对象OracleInternal.Common.ZoneValue仍占用大量内存
  • 存在特殊的内存回落触发条件:只要执行1次返回少于100行的小结果集查询,之前累积的高内存就会快速回落至1GB以下

已开展的排查与尝试

  • 已对代码中涉及的数据库连接、命令、读取器等资源型对象全部使用using语句做隐式释放,执行完成后也在finally块中手动调用了Close()、Dispose()方法,确认无未释放的持久化资源
  • 最初尝试主动调用基础版本的GC.Collect()、GC.WaitForPendingFinalizers()做强制垃圾回收,未获得明显回收效果
  • 调整强制GC的实现逻辑,使用带分代参数的双次回收策略,仅获得小幅回收改善,对应代码如下:
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
GC.WaitForPendingFinalizers();
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
  • 关于封装类的设计判断:Clases.Oracle()类本身仅持有连接字符串、数据库所有者名称两个字符串字段,类内使用的所有资源型对象都已做独立释放处理,因此团队认为该类本身不需要实现IDisposable接口

现有业务实现代码

封装类内的核心命令执行方法

private DataTable ExecuteReader(string package, ref OracleParameter[] parametros, string owner)
{
    var dt = new DataTable();
    using (var cn = new OracleConnection(_connection_string))
    {
        using var cmd = cn.CreateCommand();
        try
        {
            cn.Open();
            cmd.CommandText = $"{owner}.{package}";
            cmd.CommandType = CommandType.StoredProcedure;
            foreach (var par in parametros)
            {
                cmd.Parameters.Add(par);
            }
            using var rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
            dt.Load(rdr);
        }
        catch (Exception ex)
        {
            throw new Exceptions.OracleException(ex.Message);
        }
        finally
        {
            cn?.Close();
            cmd?.Dispose();
            cn?.Dispose();
        }
    }
    return dt;
}

业务侧的大结果集查询调用方法

public List<AuditoriaUsuarios> ObtieneAuditoriaUsuarios(long incluyeCargoRol = 0)
{
    var ora = new Clases.Oracle();
    var param = new OracleParameter[]
    {
        ora.AddInParameter("PIN_INCLUYECARGOROL",OracleDbType.Decimal, incluyeCargoRol),
        ora.AddOutCursor("CUR_OUT"),
        ora.AddOutParameter("PON_CODE", OracleDbType.Decimal),
        ora.AddOutParameter("POV_ERROR", OracleDbType.Varchar2)
    };
    var result = ora.ExecuteReader<AuditoriaUsuarios>($"{_PCK}.p_AUDIT_USUARIOS", ref param);
    if (ora.HayError(param))
    {
        throw new Exceptions.OracleException(ora.CodigoError, ora.MensajeError);
    }
    return result;
}

运行环境说明

  • 项目类型:x64架构ASP.NET Core WebAPI
  • 技术栈:.NET Core 3.1、C#
  • 开发工具:Visual Studio 2019 企业版
  • 问题触发的业务场景:该大结果集数据提取操作每周仅执行数次,不属于日常高频业务,因此对强制GC带来的短暂CPU开销敏感度较低

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.04 05:15:11