Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Утечка памяти при работе с TIbDataSet [D6, FireBird 2.1]


Страницы:   1 2 3 4

DelphiN! ©   (2008-10-06 16:09:00) 

Доброго времени суток!
Написал следующее:

     for j := 0 to Res.Count-1 do
     begin
       ServerFT.SelectSQL.Text := 'INSERT INTO SERVERFT (FILENAME,FILESIZE,FILECRC,BASEDIR) VALUES('''+Res.FileName[j]+''','+
         IntToStr(Res.FileSize[j])+','+IntToStr(Res.FileCRC[j])+', '''+Res.BaseDir[j]+''')';
       ServerFT.ExecSQL;
       ServerFT.Transaction.Commit;
     end;


В массиве Res более 50 000 записей, при дохождении цикла до 5080ой записи программа вываливается с ошибкой о нехватке памяти. Куда девается память? Что я делаю неправильно?


Игорь Шевченко   (2008-10-07 10:53:00) [41]

Johnmen ©   (07.10.08 10:27) [21]


> Смысл - не накапливать версии записей, ускорение. Почитать,
>  как обычно, можно на ibase.ru


Тогда чем плохо коммитить по одной ? Вопрос был о том, зачем именно пакет организовывать


jack128_   (2008-10-07 10:50:00) [42]


> и фиг с ней, с целостностью ?

а ты уверен, что вставка 500 записей нарушит целостность?


Johnmen   (2008-10-07 10:27:00) [43]


> Игорь Шевченко ©   (06.10.08 22:19) [13]
> можно дураку объяснить - какой смысл в commit-е порциями
> (ну скажем, по 500-1000 штук) ?

Смысл - не накапливать версии записей, ускорение. Почитать, как обычно, можно на ibase.ru

> MsGuns ©   (07.10.08 00:50) [14]
> И мне заодно тоже

В чем сомнения?

> DelphiN!

Рекомендуется к прочтению http://www.ibase.ru/devinfo/ibx.htm


MsGuns   (2008-10-07 10:26:00) [44]

>jack128_   (07.10.08 10:12) [19
>быстрее вставка происходить будет.

и фиг с ней, с целостностью ?


jack128_   (2008-10-07 10:12:00) [45]


> можно дураку объяснить - какой смысл в commit-е порциями
> (ну скажем, по 500-1000 штук) ?

быстрее вставка происходить будет.


Виталий Панасенко   (2008-10-07 09:27:00) [46]


> DelphiN!   (07.10.08 06:28) [15]

Может, IBX надо проапдейтить?


MsGuns   (2008-10-07 09:14:00) [47]

Еще раз (настойчиво):

зачем всякий раз завершать транзакцию и затем вновь ее стартовать ?

И еще вопрос - сервер где запущен - на твоем компе ?


Сергей М.   (2008-10-07 08:31:00) [48]


> DelphiN!   (07.10.08 06:28) [15]


Укажи конкретную строчку кода из [15], при выполнении которой возбуждается исключение.
Приведи дословно текст сообщения об исключении.


DelphiN!   (2008-10-07 06:28:00) [49]

Попробовал выше описаный вариант

     with TIBSQL.Create(nil) do
     try
       Transaction := IBDatabase1.DefaultTransaction;

       if not Transaction.InTransaction then
         Transaction.StartTransaction;

       SQL.Text := 'INSERT INTO SERVERFT (FILENAME,FILESIZE,FILECRC,BASEDIR) '+
         'VALUES(:FILENAME,:FILESIZE,:FILECRC,:BASEDIR)';

       for j := 0 to Res.Count-1 do
       begin
         labState.Caption := 'Статус : Обновление файловой таблицы сервера [Импорт файлов('+IntToStr(j)+'/'+IntToStr(Res.Count)+')] ... ';
         Application.ProcessMessages;
         Params[0].AsString := Res.Filename[j];
         Params[1].AsInteger := Res.FileSize[j];
         Params[2].AsInteger := Res.FileCRC[j];
         Params[3].AsString := Res.BaseDir[j];
         ExecQuery;
         if j mod 5000 = 0 then
         begin
           Transaction.Commit;
           Transaction.StartTransaction;
         end;
       end;

       if Transaction.InTransaction then
         Transaction.Commit;
     finally
       Free;
     end;
   end;

Всеравно утечка, только уже на 35011 записи память кончается :)


MsGuns   (2008-10-07 00:50:00) [50]

>Johnmen ©   (06.10.08 21:28) [12]
>Не каждая, а каждые 5000. В соответствии с рекомендациями лучших >ИБ/ФБ'водов надо каждые ~500.

>Игорь Шевченко ©   (06.10.08 22:19) [13]
>можно дураку объяснить - какой смысл в commit-е порциями (ну скажем, >по 500-1000 штук) ?

И мне заодно тоже


Игорь Шевченко   (2008-10-06 22:19:00) [51]

можно дураку объяснить - какой смысл в commit-е порциями (ну скажем, по 500-1000 штук) ?


Johnmen   (2008-10-06 21:28:00) [52]


> MsGuns ©   (06.10.08 21:02) [10]
> Не вижу великого смысла в подтверждении КАЖДОЙ вставки.

Не каждая, а каждые 5000. В соответствии с рекомендациями лучших ИБ/ФБ'водов надо каждые ~500. Что и есть "пакет". Без неуместной вр.таблицы.
Остальные "результаты" а) б) в) как минимум странны...


MsGuns   (2008-10-06 21:10:00) [53]

И вообще.
В подобных случаях (большие объемы вставок-модификаций, фрмируемые на клиенте) лучше все-таки следовать "пакетной" технологии:

- Создается временная таблица на сервере
- Туда заносятся все записи пакета
- Запускается от 1 до 3 запросов на вставку, удаление, изменение.

Результат:
а) Сервер не "напрягается" на длительное время обслуживанием одного клиента и не "блокирует" таблицы (в смысле не держит длительное время версии кучи записей)
б) Удобно управлять транзакциями, не "карауля" каждый пук с клиента, а ловя сбой лишь в момент ошибки, если она возникает
в) Просто намного прозрачнее с т.зр.логики приложения

>kaif ©   (06.10.08 18:16) [8]

Настоящие пачаны на обработку ошибки не заморачиваются ?


MsGuns   (2008-10-06 21:02:00) [54]

Не вижу великого смысла в подтверждении КАЖДОЙ вставки.
Ну а кроме этого, зачем всякий раз завершать транзакцию и затем неявно вновь ее стартовать ?


sniknik   (2008-10-06 19:55:00) [55]

> хотя бы в таком виде:
предлагаю добавить/заменить
>     ExecQuery;
> end;

> Transaction.Commit;

на
...
      ExecQuery;
      if j mod 5000 = 0 then begin
        Transaction.Commit;
        Transaction.StartTransaction;
      end;
 end;

 if Transaction.InTransaction then
   Transaction.Commit;
...


kaif   (2008-10-06 18:16:00) [56]

А этот код работает?
Предлагаю для начала переписать его хотя бы в таком виде:

with TIBSQL.Create(nil) do
try
 Transaction := <компонент транзакции>;

 if not Transaction.InTransaction then
   Transaction.StartTransaction;

 SQL.Text := 'INSERT INTO SERVERFT (FILENAME,FILESIZE,FILECRC,BASEDIR)
   VALUES(:FILENAME,:FILESIZE,:FILECRC,:BASEDIR)';

 for j := 0 to Res.Count-1 do
 begin
      Params[0].AsString := Res.Filename[j];
      Params[1].AsInteger := Res.Res.FileSize[j];
      Params[2].AsInteger := Res.FileCRC[j];
      Params[3].AsString := Res.BaseDir[j];
      ExecQuery;
 end;

 Transaction.Commit;
finally
 Free;
end;


Правильный$Вася   (2008-10-06 18:02:00) [57]


> for j := 0 to Res.Count-1 do      begin ...
>    ServerFT.Transaction.Commit;

50 тыс коммитов? ну-ну


clickmaker   (2008-10-06 17:48:00) [58]

> А смысл?

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


Johnmen   (2008-10-06 17:47:00) [59]


> clickmaker ©   (06.10.08 17:31) [3]
> а не проще ли завести параметры, чем каждый раз строку записывать?

Более того - именно параметрические запросы и должныбыть у данного компонента!


Виталий Панасенко   (2008-10-06 17:43:00) [60]


> clickmaker ©   (06.10.08 17:31) [3]

А смысл?После заполнения ВСЕХ сиквелов, IBDataSet ведет себя как обычный DataSet: Insert/Post/Edit/Delete


Страницы:   1 2 3 4

Наверх

Титульная страница Поиск, карта сайта Написать письмо