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;

これをある間隔 (例えば 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サーバーの異なるプロバイダーで発生することを考慮して、どのレイヤーが原因ですか?

4

2 に答える 2

1

これがあなたのケースに当てはまるかどうかはわかりませんが、過去に SQL Server に接続する Windows Server 2008 (Win7 でも該当) で同様のメモリの問題が発生しました。

2つの原因がありました:

  1. ConnectionString に含まれていない場合にリークを引き起こす MDAC スタックの MS バグPersist Security Info=true

  2. デバッグ情報を解放しない MS によるクリティカル セクション実装の変更 (「設計どおりの」動作) 。

考えられる回避策は、常に接続を閉じてから再度開くのではなく、できる限り開いたままにすることです。

于 2012-06-12T23:32:05.910 に答える
0

DB2 に接続しているときに同じ問題が発生するため、問題は MS/SQL に限定されません。Embarcadero フォーラムにスレッドがありましたが、やめました。これらの人々に、それが私のコード以外のものであることを納得させる方法はありませんでした。一番上を取り除いても、問題とはまったく関係のない推奨事項が返されました。私のプロセスは 7/24/365 のマルチスレッド プログラムであるため、最終的にはスケジューラの下で実行し、毎日シャットダウンすることに我慢しました。これは醜い修正ですが、クライアントに請求できるようにする必要があります!!

また、C# で小さなテスト アプリを作成して、同じ問題を作成できるかどうかを確認しました。メモリフットプリントがそこで成長するのを見ませんでした。これは Delphi の問題です。

于 2014-01-08T22:22:04.593 に答える