我们有一个WCF web服务,它使用实体框架作为数据访问的ORM。我们使用的oracle数据库是oracle database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production。实体框架使用Oracle.DataAccess.dll连接数据库。Oracle。DataAccess版本为2.112.3.0。当调用Oracle数据库时,我们会得到内存泄漏。在调查,挂起转储显示,4.35%到8.33%的线程在OraOCIEI11!slgtd()调用时被阻塞。2.20%的线程由于临界区泄漏而阻塞(拥有临界区的线程是处理OraOps11w!ssmem_free()调用的线程)。正在等待的呼叫有:Oracle.DataAccess.Client.OpsDac.Dispose ()Oracle.DataAccess.Client.OpsDac.Read ()我们想知道是否期望调用等待OraOCIEI11函数?
我们还有另一个临界区处于锁定状态,拥有线程处理oracle调用OraOCIEI11!slgtd()。我们看到Oracle.DataAccess.Client.OracleDataReader.Read()方法在从数据库中检索Clob数据时花费了一些时间。
,Oracle.DataAccess.Client.OracleDataReader.Dispose调用未返回的OraOps11w!ssmem_free()该方法在使用EF的CompiledQuery特性后由实体框架在内部调用。
这个问题与我们正在使用的dll版本有关吗?有没有什么方法可以避免临界区泄漏和内存泄漏?如有任何建议,不胜感激。
问候,Manish
如果涉及clob,则它们是一次性对象。根据您获取数据的方式,您可能需要负责手动处理结果。他们针对。net的所有示例实际上都显示了一旦数据被处理出对象就调用。close和。dispose。Dispose()应该同时处理这两种情况,但它们的文档明确显示了这两种情况。单独处理clob修复了内存不足异常和内存泄漏。这是Orcale ODP。Net文档和CLOB示例:https://docs.oracle.com/cd/E20434_01/doc/win.112/e23174/OracleClobClass.htm
我们的原始代码IDataRecord记录;//初始化自。read ()
obj o = record[columnName];
这段代码确实返回CLOB值,但是泄漏了与它相关的内存。
所取代o = ((OracleDataReader)record).GetOracleValue(record.GetOrdinal(columnName));
if (o is OracleString)
{
if (((OracleString)o).IsNull)
{
return defaultValue
}
return o.ToString();
}
else if (o is OracleClob)
{
OracleClob clob = (OracleClob)o;
try
{
if (clob.IsNull)
{
return defaultValue;
}
return clob.Value;
}
finally
{
clob.Close();
clob.Dispose();
}
}
代码格式将根据语言(这里是c#)和接口而变化。