データベース接続に 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;
これをある間隔 (例えば 200ms) のタイマーで実行すると、消費されるメモリはさまざまな速度 (1 時間あたり 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 のバグだと思いますか?回避策はありますか?
更新: この問題は、オブジェクトが静的であっても実際に発生します。たとえば、フォームに配置された接続コンポーネントとクエリ コンポーネントで、接続は開いたままです。クエリ SQL テキストのみが変更され、実行されます。
PGfoundry.org から別のプロバイダーをインストールしようとしましたが、結果がおかしいです。
メモリ リークは、異なる OS 上の両方の Postgres プロバイダで発生しますが、MySQL では発生しません。私はそれが何を意味するのか分かりません。それが VCL の問題である場合、それは常に存在するべきではありませんか? そうでない場合、同じDBサーバーの異なるプロバイダーで発生することを考慮して、どのレイヤーが原因ですか?