Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.11.27;
Скачать: CL | DM;

Вниз

Проблема с Update blob-поля   Найти похожие ветки 

 
iamkate ©   (2005-10-12 14:10) [0]

У меня большая проблема.
Есть таблица, с которой одновременно работают много пользователей. В ней есть blob-поле.
И если я пытаюсь сделать update в то время, когда другие пользователи что-то вставляют в таблицу или тоже
делают update, он зависает на строке Execute. Если же никто не делает insert или update, то все проходит нормально, хоть и долго.
До того, как в таблицу добавили blob-поле все шло хорошо и быстро.
Помогите, пожалуйста, решить проблему. (Blob-поле содержит bmp-картинки).
Спасибо.
Привожу пример своей процедуры:
Procedure
Var
 lobTmp : TLOBLocator;
 buff : ansistring;
 fs:TMemoryStream;
begin

with OracleQuery do
    begin
       Clear;
       DeleteVariables;
       DeclareVariable("NAME", otString);
       DeclareVariable("FAM", otString);
       SQL.Clear;
       SQL.Add("BEGIN UPDATE_PERSON (:NAME, :FAM); END; ");
       SetVariable("NAME", edit1.Text);
       SetVariable("FAM", edit2.Text);
       Execute;      
    end;

with MyOracleQuery do
 begin
    fs:= TMemoryStream.Create;
    image.Picture.Bitmap.SaveToStream(fs);
    fs.Seek(0, soFromBeginning);
    SetLength(buff, fs.Size);
    fs.Read(buff[1], fs.Size);
    fs.Free;
    lobTmp := TLOBLocator.Create(qryBlob.Session, otblob);
    SetVariable("ZAL_SUB", FKeyFieldValue);
    try
               SetComplexVariable("Photo", lobTmp);
               try
                 Execute;
                 lobTmp.AsString := Buff;
               except
                 on E:Exception do
                   MessageDlg(E.Message, mtError, [mbYes], 0);
               end;
             finally
               lobTmp.Free;
             end;
             OracleSession.Commit;
 end;
end.


 
Sergey13 ©   (2005-10-12 14:22) [1]

Перед редактированием
select * from myTable for update of (myBLOBField) NOWAIT
where id=:id


 
Johnmen ©   (2005-10-12 14:25) [2]

Так это нормально. Или что ты хочешь ?
А вот это место ОЧЕНЬ странное :)
      Clear; // Наверное Close ???
      DeleteVariables;
      DeclareVariable("NAME", otString);
      DeclareVariable("FAM", otString);
      SQL.Clear;
      SQL.Add("BEGIN UPDATE_PERSON (:NAME, :FAM); END; ");
      SetVariable("NAME", edit1.Text);
      SetVariable("FAM", edit2.Text);
      Execute;      

сначала чистим параметры.
а зачем, если текст запроса далее чиститься (что приводит неявно к уничтожению всех параметров) ?


 
Val ©   (2005-10-12 14:27) [3]

еще непонятка с явным подтверждением транзакции, которая явно не стартовала


 
Seg   (2005-10-12 14:35) [4]

"BEGIN UPDATE_PERSON (:NAME, :FAM); END;

рекомендую вставить commit

"BEGIN UPDATE_PERSON (:NAME, :FAM); COMMIT; END;

Это завершит предыдующие транзакции и может очень ускорить процесс.


 
Val ©   (2005-10-12 14:38) [5]

>[4] Seg   (12.10.05 14:35)
подозреваю, что автору все нужно выполнять как раз в одной транзакции, а не в разных. заполнять и фио и фото.


 
ANB ©   (2005-10-12 14:41) [6]


> Johnmen ©   (12.10.05 14:25) [2]
- в DOA нужно все чистить явно.


 
ANB ©   (2005-10-12 14:44) [7]


> И если я пытаюсь сделать update в то время, когда другие
> пользователи что-то вставляют в таблицу или тоже
> делают update,

Другие пользователи должны делать свои инсерты и апдейты максимально быстро. Иначе придется перепроверить логику программы.

> Seg   (12.10.05 14:35) [4]
- скорее всего не ускорит.


 
Sergey13 ©   (2005-10-12 14:45) [8]

Странные параметры для UPDATE_PERSON. (:NAME, :FAM). Ивановых Иванов мало ли? И почему картинку сюда же не передать?

2[6] ANB ©   (12.10.05 14:41)
Это не чистка параметров, а их пересоздание.


 
Seg   (2005-10-12 14:47) [9]

Ускорит, Ораклу не надо будет держать в памяти все незавершенные транзакции по этой таблице.
Кстати инсерты и апдейты остальных пользователей надо сразу же коммитить.
Других вариантов я не вижу.


 
Sergey13 ©   (2005-10-12 14:49) [10]

2[9] Seg   (12.10.05 14:47)
>Ускорит, Ораклу не надо будет держать в памяти все незавершенные транзакции по этой таблице.
а у него их много? Транзакций то?


 
Johnmen ©   (2005-10-12 14:54) [11]

>ANB ©   (12.10.05 14:41) [6]
>- в DOA нужно все чистить явно.

А создавать ?


 
ANB ©   (2005-10-12 15:12) [12]


> Johnmen ©   (12.10.05 14:54) [11]

И создавать тоже. Одна из причин, почему я одаком пользуюсь, хотя доа и надежнее.


 
ANB ©   (2005-10-12 15:13) [13]


> Seg   (12.10.05 14:47) [9]
- он их и так держать не будет, так как наверняка автокоммит включен.


 
ANB ©   (2005-10-12 15:15) [14]

Автору : Кстати, обрати внимание на Sergey13 ©   (12.10.05 14:45) [8]. Обновлять по ФИО - это нонсенс. Срочно заводите айдишники.


 
Sergey13 ©   (2005-10-12 15:22) [15]

2iamkate ©   (12.10.05 14:10)
>До того, как в таблицу добавили blob-поле все шло хорошо и быстро.
А запросы не переделывали? Может там так и осталось
select * from table


 
Sergey13 ©   (2005-10-12 15:45) [16]

2[12] ANB ©   (12.10.05 15:12)
> Одна из причин, почему я одаком пользуюсь, хотя доа и надежнее.
А че с Клиппера ушел? Там и переменные не надо декларировать. 8-)


 
iamkate ©   (2005-10-12 16:23) [17]

У меня во всех селектах делается коммит.
Я вытаскиваю данные из таблички, используя хранимую процедурку.
Например(оракловая процедурка):
create or replace procedure Read_Person
(
cursor in out package_person.person_cur
)
is
begin
open cur for
select id,name,photo
from person;
commit;
end;

Получаются какие-то данные
потом я вытаскиваю это в дельфовый грид, например в dxDbGrid

Потом я используя оракловый query, в примере MyOracleQuery (типа TOracleQuery), и используя TLobLocator хочу обновить эти данные
update-ом, после обновления я снова считываю данные той же процедуркой в тот же грид.

У меня нет никаких ошибок.
Но скорость update-a почему-то нестабильна, а иногда вообще зависает.
В чем может быть причина?


 
Seg   (2005-10-12 16:27) [18]

Зачем Коммит при селекте?
Коммит надо делать сразу после апдейта.


 
ANB ©   (2005-10-12 16:30) [19]


> Sergey13 ©   (12.10.05 15:45) [16]
- когда пишу скоростные надежные вещи, не требующие работы с интерфейсом - перехожу на DOA.


 
iamkate ©   (2005-10-12 16:31) [20]

>Зачем Коммит при селекте?
>Коммит надо делать сразу после апдейта.

Это чтобы транзакция не осталась в памяти
Память очищаю


 
Sergey13 ©   (2005-10-12 16:36) [21]

2 [20] iamkate ©   (12.10.05 16:31)
>Это чтобы транзакция не осталась в памяти
Память очищаю
С ИБ раньше работал?


 
ANB ©   (2005-10-12 16:37) [22]


> iamkate ©   (12.10.05 16:23) [17]

Уфф. Изгалятель. Блобик загружается без апдейта. Достаешь блобовое поле, вешаешь на него локатор, в локатор записываешь стрим и все закрываешь. По коду - как то странно.


 
iamkate ©   (2005-10-12 16:39) [23]

Да нет не приходилось
Я от db сразу в Oracle


 
Seg   (2005-10-12 16:39) [24]

В процедуре UPDATE_PERSON  коммит есть?


 
Sergey13 ©   (2005-10-12 16:41) [25]

2[17] iamkate ©   (12.10.05 16:23)
>select id,name,photo
from person;

У вас не убивают за такое? 8-)


 
iamkate ©   (2005-10-12 16:42) [26]

>>>>>>- как то странно
а что странного?
вообще то мне почему-то кажется с этим вопросом лучше на оракловый сайт зайти


 
iamkate ©   (2005-10-12 16:44) [27]

>>>В процедуре UPDATE_PERSON  коммит есть?

Нет, там нет
Коммит делается в Делфях

например, OracleSession.Commit;


 
iamkate ©   (2005-10-12 16:46) [28]

>>>У вас не убивают за такое?
не убивают,
а по сути можешь что-нибудь посоветовать? :-)


 
Seg   (2005-10-12 16:49) [29]

Поставь коммит во всех хранимых процедурах, сразу после инсерта или апдейта.
После селекта коммит надо убрать.
И не делать OracleSession.Commit в Дельфи для транзакции, которая не запущена из Дельфи.


 
atruhin ©   (2005-10-12 16:51) [30]

>>select id,name,photo
Он же на клиента всю таблицу тянет вместе с фотографиями. Как тут тормозов не будет?


 
Sergey13 ©   (2005-10-12 16:57) [31]

2[28] iamkate ©   (12.10.05 16:46)
>>>У вас не убивают за такое?
>не убивают,
Зря. 8-)

>а по сути можешь что-нибудь посоветовать? :-)
Выкинь фото из запроса. Доставай его отдельным запросом по требованию юзера как я написал в [1].

2[29] Seg   (12.10.05 16:49)
>И не делать OracleSession.Commit в Дельфи для транзакции, которая не запущена из Дельфи.

В Оракле транзакция запускается вместе с сессией (грубо конечно) и просто подтверждается или откатывается. После этого как бы начинается новая транзакция. Откуда она "запущена" - фиолетово. Именно поэтому коммиты ставить в процедуры нерекомендуется, ибо процедура может быть частью "другой", более сложной транзакции.


 
iamkate ©   (2005-10-12 16:58) [32]

>>>для транзакции, которая не запущена из Дельфи.

Но коммит после селекта мне не мешает
У меня процедурок 30 с коммитом работали и работают в одной базе
и не было никаких проблем с этим.
А commit после  update не надо - это принцип работы с TLobLocator


 
Seg   (2005-10-12 17:02) [33]

после обновления я снова считываю данные той же процедуркой в тот же грид.


А нельзя ли после обновления не вытаскивать обратно на клиент всю таблицу, а обойтись только обновленной записью?


 
Seg   (2005-10-12 17:04) [34]

У меня процедурок 30 с коммитом работали и работают в одной базе
и не было никаких проблем с этим.


И не будет, потому, что транзакции не было.
Это просто лишний оператор, Оракл его пропускает и все.


 
atruhin ©   (2005-10-12 17:04) [35]

Причем здесь транзакции? Тебе же сказали!!!!
Выкинь фото из запроса. Доставай его отдельным запросом по требованию юзера как я написал в [1].


 
Val ©   (2005-10-12 17:09) [36]

>[29] Seg   (12.10.05 16:49)
Поставь коммит во всех хранимых процедурах, сразу после инсерта или апдейта.
Не советуйте глупостей, пожалуйста. Если у вас несколько изменений/удалений/вставок в процедуре - после каждой поставите?


 
iamkate ©   (2005-10-12 17:11) [37]

>>Выкинь фото из запроса. Доставай его отдельным запросом по требованию >>юзера

попробую так сделать
завтра утром расскажу
пока


 
Seg   (2005-10-12 17:15) [38]

Если у вас несколько изменений/удалений/вставок в процедуре - после каждой поставите?

после удаления ставлю всегда.
После добаления/редактирования по мере необходимости, но по окончании процедуры обязательно.

В данном примере согласен, что дело не в редактировании, а в выборке всей таблицы с фотографиями.

Оптимально сделать следующим образом - список сотрудников вывести на экран без фотографий, а при открытии формы редактирования вытазкивать из базы фото редактируемого сотрудника.


 
ANB ©   (2005-10-12 17:24) [39]


> Seg   (12.10.05 17:15) [38]

Некошерно комиты в процедуры пихать. Могут быть большие грабли при составных транзакциях.


 
Val ©   (2005-10-12 17:27) [40]

>Seg   (12.10.05 17:15)
представим, есть табличка
accountid amount
1 100
2 200
3 300

задача - запомнить остаток, ликвидировать счет 1 (здесь - простое удаление), остаток перенести на счет 3 (именно в такой последовательности, неважно почему - просто пример).
вопрос: скажите, что произойдет с сотней, если после удаления , подтвержденного коммитом произойдет эксепшн?


 
Seg   (2005-10-12 17:53) [41]

Почему не сделать в правильной последовательности?

1.Запомнить остаток
2.Перенести остаток на счет 3
3.Удалить счет 1
4.COMMIT


 
Val ©   (2005-10-12 17:55) [42]

не увиливайте, ответьте пожалуйста


 
ANB ©   (2005-10-12 17:57) [43]


> Seg   (12.10.05 17:53) [41]

Хе, коммит то все равно в конце. А есть случаи и более сложные. Например : по количественной проводке по таблице настроек генерим кучу суммовых. На последней выяснем, что из-за, например, недостатка денег на счету, не можем выполнить операцию. Конечно, можно гулять 2 раза - сначала проверки, потом запросы. Но это не снимает проблему ошибки сервера. Да и код длиннее и менее логичен.


 
Seg   (2005-10-13 10:48) [44]

не увиливайте, ответьте пожалуйста

Это не увиливание от ответа, это выпрямление кривых процедур.


 
Sergey13 ©   (2005-10-13 10:53) [45]

2[44] Seg   (13.10.05 10:48)
Вопрос был про коммиты в процедурах. Если в [41] Seg   (12.10.05 17:53) 1,2,3 - это такие отдельные процедуры с коммитами, что будет если глюк?


 
Seg   (2005-10-13 10:53) [46]

Да и код длиннее и менее логичен

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


 
Seg   (2005-10-13 10:56) [47]

1,2,3 - это такие отдельные процедуры с коммитами

Это одна процедура.
Кстати, при желании пункты 1 и 2 можно выполнить одним запросом и если глюк, то сделать RollBack, если нет, то выполнить остальные пункты.


 
ANB ©   (2005-10-13 10:58) [48]


> Seg   (13.10.05 10:53) [46]
- прежде чем что то советовать, нужно что написать самому. Например бухгалтерию, успешно конкурирующую с 1С. А пока слушать советы не раз наступавших на грабли.
Не от хорошей жизни не рекомендуется :
- использовать коммит и обычный роллбэк в процедурах
- использовать DML в функциях


 
Sergey13 ©   (2005-10-13 11:01) [49]

2[47] Seg   (13.10.05 10:56)
Вилять продолжаем. 8-)
Ну а если такую процедуру надо больше 1 раза запустить? И при этом или все или ничего?


 
Seg   (2005-10-13 11:13) [50]

Ну а если такую процедуру надо больше 1 раза запустить? И при этом или все или ничего?

А может перестанете кривляться и опишете всю задачу сразу?


 
Seg   (2005-10-13 11:14) [51]

бухгалтерию, успешно конкурирующую с 1С

Ну в Вам, то это удалось?


 
Sergey13 ©   (2005-10-13 11:21) [52]

2[50] Seg   (13.10.05 11:13)
>А может перестанете кривляться
Какой ты грубый.

>и опишете всю задачу сразу?
Обеспечить целостность данных при множественном вызове модифицирующих процедур.


 
Seg   (2005-10-13 11:37) [53]

Это не задача, а общее требование к системе, причем к любой системе.


 
Sergey13 ©   (2005-10-13 11:43) [54]

2[53] Seg   (13.10.05 11:37)
И это требование к системе должно обеспечиваться каждый раз в любой задаче. А если писать коммиты в каждой процедуре, то обеспечить это требование с использованием этих процедур невозможно в ряде случаев.


 
Seg   (2005-10-13 11:54) [55]

невозможно в ряде случаев.

А вот эти случаи надо максимально избегать на этапе проектирования.

Если этого избежать невозможно, то можно и не писать коммиты в процедурах. Но мне такие процадуры разрабатывать не приходилось.


 
ANB ©   (2005-10-13 12:37) [56]


> Seg   (13.10.05 11:14) [51]
- удалось. Только она на клиппере еще писана была. На оракл надо переписывать.


> Seg   (13.10.05 11:54) [55]
- сначала на этапе проектирования решается, что можно так делать. Года через 2 приходит новый программер и удивляется, почему, если он выполняет в одной транзакции 2 процедуры, то они выполняются в разных. Причем он может и не удивиться, так как заметит скорее всего только пользователь, когда у него данные в базе поедут.


 
Seg   (2005-10-13 13:21) [57]

Года через 2 приходит новый программер

Документировать систему не пытались?


 
Sergey13 ©   (2005-10-13 13:23) [58]

2[56] ANB ©   (13.10.05 12:37)
Да брось ты. Он видимо непрошибаемый. Пусть коммитит. Жалко что ли. 8-)


 
ANB ©   (2005-10-13 14:14) [59]


> Sergey13 ©   (13.10.05 13:23) [58]

Не работает он в жесткой конторе. Огреб бы пару раз штрафов по 30 баксов, быстро бы грамотно писать научился.


 
iamkate ©   (2005-10-13 14:52) [60]

>Выкинь фото из запроса. Доставай его отдельным запросом по требованию >юзера как я написал в [1].

Большое спасибо. Это помогло. Теперь ничего не виснет и скорость увеличилась до 20 сек (раньше update шел не меньше 1,5 мин.)
Извиняюсь, что поздно сообщаю.



Страницы: 1 2 вся ветка

Текущий архив: 2005.11.27;
Скачать: CL | DM;

Наверх




Память: 0.63 MB
Время: 0.027 c
2-1131443009
pathfinder
2005-11-08 12:43
2005.11.27
Удаление записей в StrinList.


14-1131102516
Megabyte
2005-11-04 14:08
2005.11.27
Обращение к Юре Федорову


14-1130395075
Layner
2005-10-27 10:37
2005.11.27
Сервис, таймер в нем отказывается работать...


14-1131004493
syte_ser78
2005-11-03 10:54
2005.11.27
GeForse 3 TI 200 DDR 64 Mb manly


2-1131345089
John Doe
2005-11-07 09:31
2005.11.27
Область видимости и время жизни при рекурсии.