Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2005.11.27;
Скачать: [xml.tar.bz2];

Вниз

Проблема с 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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.61 MB
Время: 0.016 c
14-1130950980
Pazitron_Brain
2005-11-02 20:03
2005.11.27
Нужен крэк для СП2.


1-1130791479
Aragon
2005-10-31 23:44
2005.11.27
Передача по ссылке параметра в Dll-процедуру


11-1112330908
DeimosX7
2005-04-01 08:48
2005.11.27
PaintBox


14-1131418978
TModem
2005-11-08 06:02
2005.11.27
У кого нибудь есть модем Zyxel UNO ?


5-1113173273
Бывший студент
2005-04-11 02:47
2005.11.27
Колонки TStringGrid





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский