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

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

Транзакции MSSQL - работа через BDE [D6, MSSQL]


Igor_ ©   (2006-02-03 10:46:00) 

Работаю с MSSQL через BDE.

Из программы рамках транзакции выполняются действия с update и insert в таблицы (T1, T2), которые занимают продолжительное время. В рамках этой же транзакции производится select из таблицы T3 (изменений данных в ней не производится).

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

Транзакции везде read commited, т.е. по идее приложение делающее select должно свободно получать данные из T3, а получается, что на время транзакции доступ к таблицам просто блокируется.

Подскажите, пожайлуста, как с этим бороться.


msguns   (2006-02-03 15:11:00) [1]

Вообще при клиент-серверном подходе надежнее отделять операции извлечения данных от их изменения. В этом случае механизм "Читаем" - "Даем пользователю изменить данные вне БД" - "Формируем запрос на целостное изменение объектовБД" - "Выполняем запрос" - "Обрабатываем ошибки" - "Обновляем отображаемые данные"


Val   (2006-02-03 15:07:00) [2]

в MS SQL нету аналога оракловского select for update? т.е. блокирования нужного набора именно на уровне строк.


Igor_   (2006-02-03 14:54:00) [3]

Прошу прощения. Не совсем верно был описана постановка вопроса. Как оказалось Т3 не блокировалась, просто в другом приложении

> Igor_ ©   (03.02.06 10:46)  
> Получается ситуация, что во время работы транзакции пользователи
> в сети, работающие с другими приложениями, которые делают
> select из T3 не получают данных, пока транзакция не завершится.

невзначай, сразу не заметил, еще был select из T1.

В результате всех мучений, пришел к выводу, что нужно будет переделать логику с использованием кешированных изменений. Т.е. сначала делаю select всего, что нужно, принимаю решение нужно ли мне делать update, а потом в короткой транзакции делаю, собственно, update.


msguns   (2006-02-03 13:14:00) [4]

>Val ©   (03.02.06 12:53) [11]

Принцип блокировок при обработке конкурирующих транзакций можно посмотреть на примере акцеса.


Val   (2006-02-03 12:53:00) [5]

>[10] ЮЮ ©   (03.02.06 12:45)
ну это понятно и разумно, спасибо.


ЮЮ   (2006-02-03 12:45:00) [6]

Именно из T3? Значит автор где-то задел её на Update (В 17-строке, наверное).

Сейчас проверил. Более того Блокируется SELECT с WHERE Code = <ключ измененной записи>, а если Code другой записи или вообще без Where - то селект не блокируется. (селекты делал из SQL Explorer, блокировку и update - EM)


Val   (2006-02-03 12:28:00) [7]

Знатоки MS SQL, поясните, если несложно, все-таки - почему в данном случае блокируется T3? Я, к сожалению, еще не знаком с данным сервером и информация по ссылке Николая не натолкнула меня на понимание ситуации :( Я вижу только блокирующее чтение - это так?


ЮЮ   (2006-02-03 12:13:00) [8]


> т.к. в процессе update БД выполняется не просто так  q.SQL.
> Text := "Update..",


1)  Text := "Update..", всё же лучще сменить на  
    qUpdate.Params[0].asXXX
    ...
    qUpdate.Params[nn].asXXX
a для qUpdate сделать Prepare

2) Может тогда лучше все сделать на клиенте в кэшированном НД, а потом уже скопом ApplayUpdates?


Igor_   (2006-02-03 12:05:00) [9]


> msguns ©   (03.02.06 11:50) [6]
Подобные "хитрые" многоступенчатые изменения в нескольких таблицах БД, которые должны проходить только полностью или не проходить вообще разумнее выполнять не только в контексте единой транзакции, но и на сервере (хп).

А перенос в хп поможет решить описанную проблему?

Хотя, перенести в хп вряд ли получится, т.к. в процессе update БД выполняется не просто так  q.SQL.Text := "Update..", а в приложении довольно сложная логика и создана куча классов, которые эту логику реализовывают. Если перенести все в хп, то будет очень трудно ее (логику) контролировать и вообще понять..


msguns   (2006-02-03 11:50:00) [10]

>Igor_ ©   (03.02.06 11:02) [3]

Подобные "хитрые" многоступенчатые изменения в нескольких таблицах БД, которые должны проходить только полностью или не проходить вообще разумнее выполнять не только в контексте единой транзакции, но и на сервере (хп).


Nikolay M.   (2006-02-03 11:09:00) [11]


> Транзакции везде read commited, т.е. по идее приложение
> делающее select должно свободно получать данные из T3, а
> получается, что на время транзакции доступ к таблицам просто
> блокируется.


Налицо недопонимание механизма блокировок и уровней изоляции.
Про бликировки можно почитать, например, тут:

http://www.sql.ru/articles/mssql/2004/04110303AdvancedLocking.shtml


Igor_   (2006-02-03 11:05:00) [12]


> Val ©   (03.02.06 10:59)
p.s.неужели MS SQL блокирует таблицу на время чтения? странно как-то...

Вот и я про то же..


Igor_   (2006-02-03 11:02:00) [13]

Не получается. Дело в том, что в рамках транзакции проворачивается много данных. И по ходу выполнения, чтобы знать, для чего мне нужно делать update T1 b T2 приходится выбирать select-ом дополнительные данные из T3.
Т.е. схематично все выглядит примерно так:


Begin Tran

for i := 0; .... do begin
      Select from T3
      Insert into T1
      Update T2
end; // for i := 0; ....

Commit Tran (или Rollback Tran)


Можно, конечно, сначала все выбрать и запомнить в переменных программы, а потом у же делать update..
Но здесь вопрос принципиальный. Транзакции read commited, т.е., насколько я понимаю не должны быть видны изменения, которые не подтвердились, но почему доступ вообще блокируется?


Val   (2006-02-03 10:59:00) [14]

>Ega23 ©   (03.02.06 10:50)
подозреваю, что выборка нужна именно для инсертов и апдейтов. только я разницы не пойму - ну и что что вы вынесете селект из рамок явной транзакции - что изменится-то?
p.s.неужели MS SQL блокирует таблицу на время чтения? странно как-то...


Ega23   (2006-02-03 10:50:00) [15]

А почему-бы не объявлять транзакцию только на Update и Insert? А Select уже вне рамок этой транзакции делать?
ТИпа

Begin Tran

 Insert into T1
 Update T2

Commit Tran (или Rollback Tran)

Select * from T3

?


Наверх

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