当针对Oracle 11.2.0.3实例执行包含OracleTimeStamp
的ADO.NET命令时,我注意到非托管内存一直在增长,直到使用了OracleConnection
。到目前为止,我只使用OracleTimeStamp
设法重现此行为,当使用其他类型(Varchar2,...)时,一切都按预期工作。
这是一个示例控制台应用程序,它导致非托管内存增长,直到连接被释放:
internal class MemoryTestOracle
{
private const string SpTestOracleTimeStamp = "SP_MEM_TEST_TIMESTAMP";
private const string SpTestOracleTimeStampParam = "P_CONTENT_DATETIMEOFFSET";
private const int StatementsPerLoop = 1000;
private const string ConnectionString =
"Data Source=YOURSERVER;Persist Security Info=True;User ID=YOURUSER;Password=YOURPASSWORD;Pooling=false";
private static void Main(string[] args)
{
using (OracleConnection connection = new OracleConnection(ConnectionString))
{
Console.WriteLine("Start connect with {0}", typeof(OracleConnection).Assembly.ToString());
connection.Open();
for (int currentLoop = 0; true; currentLoop++)
{
OracleTimeStamp[] valuesDateTimeOffset = new OracleTimeStamp[StatementsPerLoop];
Parallel.For(0, StatementsPerLoop,
current => { valuesDateTimeOffset[current] = new OracleTimeStamp(DateTime.Now); });
Stopwatch stopExecution = Stopwatch.StartNew();
using (OracleTransaction transaction = connection.BeginTransaction())
{
using (OracleCommand command = new OracleCommand(SpTestOracleTimeStamp, connection))
{
command.Transaction = transaction;
command.CommandType = CommandType.StoredProcedure;
using (OracleParameter timeStampParameter = new OracleParameter())
{
timeStampParameter.OracleDbType = OracleDbType.TimeStamp;
timeStampParameter.Value = valuesDateTimeOffset;
timeStampParameter.Direction = ParameterDirection.Input;
timeStampParameter.ParameterName = SpTestOracleTimeStampParam;
command.Parameters.Add(timeStampParameter);
command.ArrayBindCount = valuesDateTimeOffset.Length;
command.ExecuteNonQuery();
}
}
transaction.Commit();
}
stopExecution.Stop();
Console.WriteLine("Loop # {0} took {1} ms", currentLoop, stopExecution.ElapsedMilliseconds);
}
}
}
}
测试时我使用了以下storedProcedure:
CREATE OR REPLACE PROCEDURE SP_MEM_TEST_TIMESTAMP (
P_CONTENT_DATETIMEOFFSET TIMESTAMP
)
IS
BEGIN
NULL;
END;
/
这是Oracle.DataAccess(4.112.3.0)中的错误,已安装的Oracle驱动程序还是我在这里做错了(最有可能,但我无法弄明白)?
非常感谢任何意见!
更新:添加使用/ disposing到OracleParameter本身。使用OracleParameter我认为我处理所有一次性物品。问题仍然存在。
更新2:在大约15.000次循环(15.000.000 db执行)之后,非托管内存大小约为150MB;即使DateTimeOffset值是在循环外创建的(所以基本上所有循环都在相同的数据上运行)内存不断增长(尽管速度较慢)
更新3:到目前为止,我已经使用Oracle的托管提供商测试了上述代码 - 没有内存问题。 我也用Devart的ADO提供商进行测试。在他们的一个版本(7. *)中,问题完全相同,在最近的版本中它似乎已修复。
答案 0 :(得分:0)
尝试显式关闭和处理您正在使用的所有Oracle对象,包括OracleCommand,OracleTransaction和OracleParameter。
对于托管垃圾收集器,这些对象似乎并不重量级,但实际上它们可能在非托管端。因此,最好的做法是在完成任务后始终关闭并处理所有内容。