1

我正在调试一个使用 ADO 进行数据库连接的应用程序,主要是 TAdoConnection 和 TAdoQuery 经过一些测试后发现 TAdoQuery 一直在消耗内存而不是释放内存。使用以下代码可以很容易地重现该问题:

procedure TForm1.RunQueries;
var
  Q: TADOQuery;
  Conn: TADOConnection;
begin
  Conn := TADOConnection.Create(nil);
  Conn.ConnectionString := 'Provider=PGNP.1;Password=*****;User ID=*****;Data Source=*****;Initial Catalog=*****;Extended Properties="PORT=5432"';
  Conn.LoginPrompt:=False;
  Conn.Connected := true;

  Q := TADOQuery.Create(nil);
  Q.Connection := Conn;
  Q.SQL.Text := 'select * from sometable where extract(year from now()-Field1)::int/60>=15 or Field2>=50 limit 5';

  q.Open;
  q.Close;
  FreeAndNil(Q);
  FreeAndNil(Conn);
end;

如果以某个时间间隔(例如 200 毫秒)使用计时器运行,则消耗的内存会以各种速度(每小时 20-50MB)不断增加。SQL 文本本身并不真正相关。它还使用“select * from Table1”消耗内存,只是速度较慢。带有 'delete ...' 语句的 ExecSQL 似乎不会引起问题。

我用 GetProcessMemoryInfo 做了一些测试,似乎在调用 Open 方法后内存被消耗而不是释放。不过,并非所有执行都会导致相同的内存增加。

这发生在使用 PostgreSQL 和不同 ADO 提供程序的开发服务器上,但我无法使用 MySQL 重现它。其他使用来自http://www.pgoledb.com的 ADO 提供程序的应用程序似乎工作正常,所以问题不仅在于我尝试过 AQTime 和 FastMM4 的提供程序,而且都报告没有泄漏。使用 D6 和 XE2 构建的代码工作方式相同。

我发现这个问题Delphi: TAdoQuery Memory Leak? ,但是那里的问题是由代码中的错误引起的。

我的问题类似于此错误报告http://qc.embarcadero.com/wc/qcmain.aspx?d=7018

您认为这是 Delphi 中的一个错误,是否有解决方法?

更新: 即使对象是静态的,也会出现此问题。例如,放置在表单上的 Connection 和 Query 组件,并且连接保持打开状态。只有查询 SQL 文本被更改和执行。

我尝试从 PGfoundry.org 安装不同的提供程序,但结果对我来说很奇怪。

内存泄漏出现在不同操作系统上的两个 Postgres 提供程序中,但没有出现在 MySQL 中。我不确定这意味着什么。如果是 VCL 问题,不应该一直存在吗?如果不是,考虑到同一数据库服务器的不同提供商会发生这种情况,是什么层导致它?

4

2 回答 2

1

我不知道这是否适用于您的情况,但过去我们在 Windows Server 2008(也适用于 Win7)连接到 SQL Server 时遇到了类似的内存问题。

有2个原因:

  1. MDAC 堆栈中的一个 MS 错误,当 ConnectionString 不包含时导致泄漏Persist Security Info=true

  2. MS 在关键部分实现中的更改(“按设计”行为)不会释放调试信息。

一种可能的解决方法是尽可能多地保持连接打开,而不是一直关闭并重新打开它们。

于 2012-06-12T23:32:05.910 回答
0

我在连接到 DB2 时遇到了同样的问题,因此您的问题不仅限于 MS/SQL。我在 Embarcadero 论坛上有一个帖子,但退出了。我无法让这些人相信这不是我的代码。即使我把它从最上面剥下来,我还是得到了与这个问题完全无关的建议。由于我的进程是一个 7/24/365 多线程程序,所以我最终让自己在调度程序下运行它并让它每天自行关闭。这是一个丑陋的修复,但我必须能够向我的客户开具发票!

我还用 C# 编写了一个小测试应用程序,看看是否可以创建相同的问题。我没有看到内存足迹在那里增长。这是一个德尔福问题。

于 2014-01-08T22:22:04.593 回答