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