2012-06-12 6 views
1

Я отлаживаю приложение, использующее ADO для подключения к базе данных, в основном TAdoConnection и TAdoQuery . После некоторого тестирования выяснилось, что TAdoQuery продолжает потреблять и не выпускать память. Проблема может быть воспроизведена довольно легко с этим кодом:Потребление памяти Delphi ADO

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-50 МБ в час). Сам текст SQL не имеет особого значения. Он также потребляет память с помощью «select * from Table1», только медленнее. ExecSQL с выражением «delete ...», похоже, не вызывает проблемы.

Я провел несколько тестов с помощью GetProcessMemoryInfo, и кажется, что память потребляется и не освобождается после вызова метода Open. Однако не все исполнения привели к тому же увеличению памяти.

Это происходит на сервере разработки с PostgreSQL и различными поставщиками ADO, но я не смог воспроизвести его с помощью MySQL. Другие приложения, использующие провайдера ADO от http://www.pgoledb.com, похоже, работают исправно, поэтому проблема не только в провайдере Я пробовал AQTime и FastMM4, но оба не сообщают об утечках. Код, построенный с D6 и XE2, работает одинаково.

Я нашел этот вопрос Delphi: TAdoQuery Memory Leak?, но проблема была вызвана ошибками в коде.

Моя проблема похожа на этот отчет об ошибке http://qc.embarcadero.com/wc/qcmain.aspx?d=7018.

Как вы думаете, это ошибка в Delphi, и есть ли обходной путь?

Обновление: Эта проблема возникает, даже если объекты являются статическими. Например, компоненты Connection и Query, которые помещаются в форму, и соединение остается открытым. Изменяется и выполняется только текст запроса Query.

Я попытался установить другого провайдера из PGfoundry.org, но результаты для меня странные.

Утечки памяти появляются вместе с поставщиками Postgres на разных ОС, но не с MySQL. Я не уверен, что это значит. Если это проблема VCL, разве она не всегда присутствует? Если нет, то какой слой вызывает его, учитывая, что это происходит с разными провайдерами для одного и того же сервера БД?

+0

Вы обновили MDAC системы до последней версии? Вы пытались получить доступ непосредственно к слою OleDB - вы можете попробовать [наши модули с открытым исходным кодом] (http://blog.synopse.info/post/2011/06/27/SynOleDB%3A-OpenSource-Unit-for-direct- доступ к любой из баз-через-OleDB). –

+0

В комментариях к QC предлагается попытаться использовать серверные курсоры вместо клиентской стороны. Вы проверили это? – whosrdaddy

+0

Я обновил MDAC и протестировал на обоих серверах 2008 и 2003 с такими же результатами, к сожалению. Курсоры также не влияли на потребление памяти. Что касается прямого доступа, я еще не пробовал, так как хочу избежать перезаписи слишком большого количества кода, который довольно большой и не написан мной. Я попробую это также, если нет других вариантов. – VGeorgiev

ответ

1

Я не знаю, применимо ли это к вашему делу, но у нас были аналогичные проблемы с памятью в прошлом с Windows Server 2008 (также применимым в Win7), подключающимся к SQL Server.

Были 2 причины:

  1. МС ошибки в стеке MDAC, который вызвал утечку, когда ConnectionString не включает в себя Persist Security Info=true

  2. изменения («как разработанные» поведения) в Critical Section implementation от MS, которая не освобождает отладочную информацию.

Возможное обходное решение заключается в том, чтобы поддерживать связь как можно практичнее, а не закрывать и снова открывать их.

+0

Благодарим вас за предложения. Информация Persist Security, к сожалению, не изменяет поведение. Я обновил свои вопросы выше, чтобы отразить последние тесты. Проблемы, похоже, связаны с самим запросом, так как на него не влияет соединение или нет. – VGeorgiev

0

Я страдаю от этого при подключении к DB2, поэтому ваша проблема не ограничивается MS/SQL. У меня был поток, идущий на форумах Embarcadero, но ушел. Я не мог убедить этих людей, что это нечто иное, чем мой код. Даже когда я убрал его сверху вниз, я получил рекомендации, которые не имели абсолютно никакого отношения к проблеме. Поскольку мой процесс представляет собой многопоточную программу 7/24/365, я, наконец, смирился с тем, что запускаю его под планировщиком и каждый день закрываю его. Это уродливое решение, но я должен иметь возможность выставлять счета моему клиенту!

Я также написал небольшое тестовое приложение на C#, чтобы увидеть, могу ли я создать такую ​​же проблему. Я не видел, как там растет память. Это проблема Delphi.

Смежные вопросы