【问题标题】:Delphi ADO Memory ConsumptionDelphi ADO 内存消耗
【发布时间】:2012-06-12 11:09:34
【问题描述】:

我正在调试一个使用 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”消耗内存,只是速度较慢。带有“删除...”语句的 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 问题,不应该一直存在吗?如果不是,考虑到同一数据库服务器的不同提供商会发生这种情况,是哪一层导致它?

【问题讨论】:

  • 您是否将系统的 MDAC 更新到最新版本?你试过直接访问 OleDB 层吗?你可以试试our Open Source units
  • QC cmets 建议尝试使用服务器端游标而不是客户端。你测试了吗?
  • 不幸的是,我更新了 MDAC 并在 Server 2008 和 2003 上进行了测试,结果相同。游标对内存消耗也没有影响。至于直接访问,我还没有尝试过,因为我想避免重写太多的代码部分,代码很大,不是我写的。如果没有其他选择,我也会尝试。
  • 一种选择是更改驱动程序,例如devart.com
  • 由于它显然与 SQL 查询本身相关联,因此请尝试在调用和不调用 extract(year from now()-Field1) 中的函数的情况下进行测试,即将 now() 替换为常量 ,然后是 extract(...)。然后尝试一次更改查询的 1 部分,看看它是否有所作为...分而治之;-)

标签: delphi postgresql memory-leaks oledb ado


【解决方案1】:

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

有两个原因:

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

  2. MS 对Critical Section implementation 的更改(“按设计”行为)不会释放调试信息。

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

【讨论】:

  • 感谢您的建议。不幸的是,持久安全信息不会改变行为。我更新了上面的问题以反映最新的测试。问题似乎出在查询本身,因为它不受保持连接的影响。
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 2016-03-15
    • 1970-01-01
    • 2010-10-12
    • 1970-01-01
    • 2011-10-03
    • 2012-11-24
    • 2013-10-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多