【发布时间】: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