![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Утечка памяти при работе с TIbDataSet [D6, FireBird 2.1]
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