Форум: "Базы";
Текущий архив: 2005.03.13;
Скачать: [xml.tar.bz2];
ВнизБлокировка таблицы транзакцией в MSSQL Найти похожие ветки
← →
lats © (2005-02-07 08:25) [0]Начинаю транзакцию. При этом блокируется таблица или даже вся база. Испльзую ADO.
← →
Danilka © (2005-02-07 09:31) [1]И что? Пущщай блокируется. :)
Транзакцию следует начинать и заканчивать в одной процедуре - процедуре записи, и те доли секунды, что она будет отрабатывать, блокировка нескольких записей (а не вся таблица) никому не помешает.
← →
Serggg (2005-02-07 11:09) [2]Аналогичная проблема. У меня при начале работы таблицы включается транзакция (чтобы можно было откатить изменения), при этом напрочь блокируется чтение к таблице (хотя свойство в ADO-компоненте - Optimistic). Как получить-таки доступ на чтение таблички для других юзверей?
← →
lats © (2005-02-07 11:18) [3]Дело в том, что транзакция начинается перед созданием записи в первой таблице, потом создаются записи во второй и третьей таблице, которые ссылаются на ключевое поле первой. Причем на любом этапе добавление записи(ей) можно отменить. Конечно при отмене можно удалять запись в первой таблице, но для этого много переделывать. Может есть какой другой способ?
← →
Sergey13 © (2005-02-07 11:27) [4]2lats © (07.02.05 08:25)
Я с этим сервером не работал, но что то слабо верится. ИМХО, если бы это было так, то с ним ввобще бы никто не работал. 8-)
← →
Danilka © (2005-02-07 11:49) [5][2] Serggg (07.02.05 11:09)
Не надо при начале стартовать транзакцию. Смотри справку по UpdateBatch.
[3] lats © (07.02.05 11:18)
Вообще, так я не делал еще с МС-Скулем, все как-то сначала сохраняешь мастер-запись, а потом уже детальные таблицы заполняешь. Но, думаю, опять-же все можно провернуть через клиентские курсоры и UpdateBatch, только нет здесь МС-Скуля проверить, сам смотри и пробуй.
← →
Serggg (2005-02-07 16:17) [6]danilka, так у меня мастер-детальные таблички (главная и подчиненная), и если главная табличка будет кэшироваться, тов ней первичный ключ (до UpdateBatch) будет пустой, а значит я не смогу добавить строки в детальную табличку. А транзакция начинается при начале изменениий (на BeforeEdit, например). Т.е. мне надо, чтобы юзер вносил изменения в главную и подчиненную таблицы, но мог это все дело отменить. Типа "Сохранить изменения? Да/нет"
← →
Desdechado © (2005-02-07 16:24) [7]транзакцию начинай после нажатия на сохранить:
1. создаешь мастер-записи
2. получаешь их коды
3. создаешь деталь-записи
4. подтверждаешь/откатываешь транзакцию
ручной работы больше, чем при автомате, зато транзакция коротко-живущая и более гибкая
← →
aus (2005-02-07 19:57) [8]Набор данных скорее всего не блокируется, а переходит в Zombie State, о чем выдается сообщение (по кр. мере у меня так было).
Вот это мне помогло:
with (DataSet as TCustomADODataSet).Properties do begin
Item["Preserve on Commit"].Value := true;
Item["Preserve on Abort"].Value := true;
end;
← →
Nikolay M. © (2005-02-08 11:27) [9]
> мне надо, чтобы юзер вносил изменения в главную и подчиненную
> таблицы, но мог это все дело отменить. Типа "Сохранить изменения?
> Да/нет"
Из этого не следует, что нужно делать так:
> транзакция начинается при начале изменениий (на BeforeEdit,
> например).
Если бы все так делали, то
> с ним ввобще бы никто не работал.
Транзакция всегда должна быть как можно более короткой по времени. Кстати, почитай еще про SET TRANSACTION ISOLATION LEVEL. READ UNCOMMITTED может тебе помочь, но можешь нарваться на грабли.
← →
Nikolay M. © (2005-02-08 11:27) [10]
> мне надо, чтобы юзер вносил изменения в главную и подчиненную
> таблицы, но мог это все дело отменить. Типа "Сохранить изменения?
> Да/нет"
Из этого не следует, что нужно делать так:
> транзакция начинается при начале изменениий (на BeforeEdit,
> например).
Если бы все так делали, то
> с ним ввобще бы никто не работал.
Транзакция всегда должна быть как можно более короткой по времени. Кстати, почитай еще про SET TRANSACTION ISOLATION LEVEL. READ UNCOMMITTED может тебе помочь, но можешь нарваться на грабли.
← →
Ega23 © (2005-02-08 13:18) [11]Я всегда Isolation level для транзакции выставлял...
← →
roottim © (2005-02-08 13:53) [12]> зато транзакция коротко-живущая и более гибкая
собственно смысла тразакции, в короткоживущих ее реализациях, - никакого.
Это "проблема" блокировочных систем аля мсскл, в которых
чем быстрее протекает транзакция тем быстрее снимается блокировка,
отчего и разработку нужно вести в этом ключе.
Для версионников (oracle, FB, postgres) приемущество транзакций остаются в силе на довольно продолжительное время. Вот тут действительно целостность и гибкость, правда можно нарваться на snapshot too old (для оракла), но это уже другая песня.
Помоему, по слухам, мсскл тоже планирует переходить на версионную архитектуру ?
← →
Nikolay M. © (2005-02-08 14:04) [13]
> по слухам, мсскл тоже планирует переходить на версионную
> архитектуру ?
В Yukon-е. Кажется, третья бета уже вышла.
← →
Serggg (2005-02-08 15:05) [14]Да вот не помогает TRANSACTION ISOLATION LEVEL. READ UNCOMMITTED :(
← →
Desdechado © (2005-02-08 15:10) [15]2 roottim
Пишущие транзакции все равно должны быть короткоживущими. Даже в ИБ, хоть он и версионник. Потому как если ты открыл данные для изменения, то остальные-то не смогут их тоже открыть для изменения. И это не зависит от структуры сервера.
Кстати, оракл ты зря к версионникам отнес. Имхо, типичный блокировочник.
← →
Serggg (2005-02-08 15:17) [16]Так блин сервак даже на чтение не открывает данные :(
← →
Serggg (2005-02-08 15:23) [17]И потом, как мне тогда организовать откат изменений? Если я отменяю все изменения начиная с какого-то опред. момента? ИМХО, кроме как транзакцией не получится. :(
← →
lats © (2005-02-08 15:42) [18]Я сделал так. Удаляю свою родительскую таблицу, а дочерние сами удаляются, т.к. связанные мо ключевому полю и выполнено каскадное удаление. Т.е. все изменения также отменяются. Может тебе тоже поможет.
← →
Serggg (2005-02-08 16:02) [19]а если это не добавление, а изменение? Неее, так конечно тоже можно, но должны же быть нормальные способы... тем более если несколько записей добавлялось в главную? У меня ж сохранение идет в конце сеанса работы (т.е. при сохранении или выходе из окна)
← →
Danilka © (2005-02-08 16:42) [20][19] Serggg (08.02.05 16:02)
> но должны же быть нормальные способы...
Самый нормальный способ тебе уже сказали: все что делает клиент у себя на компе нифига на сервер заносить не надо, пока он не нажмет кнопку ОК. Вот когда нажал ее, тогда открывай транзакцию и пиши на сервак что надо, а если он отмену нажал - тогда ничего не пиши. Чего в этом сложного-то?
← →
lats © (2005-02-08 16:48) [21]Т.е. хранить все данные в переменных, а потом их скопом записывать и раскидывать по таблицам? Мне это уже предлагали, но в этом случае ручками писать много нужно. Автоматизации никакой.
← →
Desdechado © (2005-02-08 17:31) [22]Не в переменных, а в кэшированных датасетах.
А когда придет время (юзер жмет ок), то сбрасываешь кэш в базу в одной короткой транзакции. Для этого есть даже специальные компоненты UpdateSQL для БДЕ или метод beforeupdaterecord в dataprovider.
И, естественно, ApplyUpdates.
см. в справке и примерах в demos
← →
Danilka © (2005-02-08 20:54) [23][21] lats © (08.02.05 16:48)
> Мне это уже предлагали, но в этом случае ручками писать
> много нужно. Автоматизации никакой.
Во-первых, их есть уже, и говорил я про них в самом начале ветки, UpdateBatch для всех наследников TCustomADODataSet, помнишь? Так и не почитал справку?
А во-вторых, даже если чего-то ручками придется делать, и что,
лениво очень? Ну, тогда остается только посидеть, погрустить. :)
← →
lats © (2005-02-09 14:28) [24]UpdateBatch не подойдет, т.к. добавление записей в дочерние таблицы производится с помощью процедур на сервере.
А во вторых, не лениво. Можно и на асемблере написать, но для того и создан Делфи чтобы ручками как можно меньше делать. Этот вопрос уже много раз обсуждался.
← →
lats © (2005-02-09 14:33) [25]UpdateBatch не подойдет, т.к. добавление записей в дочерние таблицы производится с помощью процедур на сервере.
А во вторых, не лениво. Можно и на асемблере написать, но для того и создан Делфи чтобы ручками как можно меньше делать. Этот вопрос уже много раз обсуждался.
← →
lats © (2005-02-09 14:33) [26]UpdateBatch не подойдет, т.к. добавление записей в дочерние таблицы производится с помощью процедур на сервере.
А во вторых, не лениво. Можно и на асемблере написать, но для того и создан Делфи чтобы ручками как можно меньше делать. Этот вопрос уже много раз обсуждался.
← →
Serggg (2005-02-09 15:21) [27]Не, может не очень понятно ситуацию обрисовал, но... Мастер-детальные таблички! Если главная табличка у меня в BatchOptimistic, то первичного ключа до момента UpdateBatch я не имею (т.е. значение полю pk не присваиваивается), соответственно, при вставке записей в дочернюю таблицу я не могу прописать ссылку на первичный ключ строки главной таблицы, к которой относятся детальные строки. Кроме того, выполняются ряд операций по удалению/добавлению блоков данных с использованием ADOCommand... хм... как жить?
← →
lats © (2005-02-09 16:46) [28]Вот и я про то-же. Предложили выход - хранить все изменения и дополнения во временных (переменных, таблицах), а потом махом все изменения записывать. Сказали, что примерно так работает фокспра. Много ручной работы. Может есть какой другой выход?
← →
Desdechado © (2005-02-09 18:36) [29]посмотри еще раз Desdechado © (08.02.05 17:31) [22]
там не временные таблицы и тем более не переменные, а нормальный набор данных, изменения в котором до нажатия кнопки хранятся в кэше (его кэше, а не в твоем ручном)
← →
Danilka © (2005-02-10 00:20) [30][29] Desdechado © (09.02.05 18:36)
У него не БДЕ, а АДО, в АДО ApplyUpdates называецца как UpdateBatch.
:))
[25] lats © (09.02.05 14:33)
> но для того и создан Делфи чтобы ручками как можно меньше
> делать
Ну, тогда сиди и жди доброго дядю. который тебе красиво сделает. :)
27] Serggg (09.02.05 15:21)
Тока-шо сделал, пришлось повозиться, но работает. :)
Сделал таким образом:
1. Мастер-таблица просто оптимистическая, детальная уже BatchOptimistic.
2. Связаны мастер/деталь не по-обычному, а ручками, в AfterScroll мастера деталь закрывается, меняется параметр на новый айдишник и снова открывается.
3. На DataSource мастера, на событие OnStateChange вешаем обрабочик, в котором смотрим - если поменялся на dsInsert, то пишем в параметр детали: -1 и переоткрываем ее.
4. У мастера режимах dsInsert и dsEdit запрещаем скроллить.
5. По кнопке "Ок" делаем следующее:
старт транзакции
пост записи-мастеру, если он до этого был в состоянии dsInsert, то забираем сгенеренный айдишник, примерно так:
id := ADOConnection1.Execute("select @@IDENTITY").Fields[0].Value;
далее, пробегаемся по записям детайла и пишем ему айдишник мастера.
UpdateBatch детайлу
коммит.
все работет, без проблем.
← →
Danilka © (2005-02-10 07:37) [31]Да, забыл добавить, в деталь на БефореИнсерт пишется id мастера из параметра, по которому фильтруется (в случае с добавлением новой записи вв мастер, туда пишется -1, соответственно).
И еще, в п.3, п.4 слежует учесть, что сначала меняется состояние на dsInsert, и только потом скроллится на новую запись, соответственно вызывается AfterScroll.
Вобщем, все решаемо, и это не единственный способ, возможно и не самый красивый, незнаю чего вы тему несколько дней мусолите.
← →
Serggg (2005-02-10 10:36) [32]Данилка, примерно так же и я пытался сделать, но есть одно жирное НО... В этом случае дважды добавить в мастер-таблицу данные в рамках одной транзакции не получится, так ведь? (иначе заблокируется табличка на МССКЛ). Т.е. отменить ВСЕХ изменений скопом не получится, тока в детальной. :( А еще у меня используется ADOCommand, действия которого в этом случае тоже не откатить :( Хнык.
← →
Danilka © (2005-02-10 11:17) [33][32] Serggg (10.02.05 10:36)
Хм, а это действительно необходимо? Редактирование/добавление нескольких записей и в мастер и в деталь для них в рамках одного изменения?
Тут гемороя будет больше, с учетом того, что айдишники у мастера автоинкрементные..
Проще перестроить логику работы, чтоб юзерам нормально было когда за раз только одна мастер-запись крячится. :)
← →
lats © (2005-02-10 11:33) [34]
> Ну, тогда сиди и жди доброго дядю. который тебе красиво
> сделает. :)
Да никого я не жду уже давно все сделал.
По нажатию "отмена" в мастере удаляется запись которую добавлял, а в детальных все сами удаляются т.к. связанные. Вот и всё. Без транзакций. А как сделать множественную отмену в масере так и не ясно. Хотя можно запоминать какие добавляем и опять же скопом их все удалять. Или даже пошаговое удаление можно реализовать. Мне это правда не нужно.
← →
Ega23 © (2005-02-10 11:51) [35]через жопу ты сделал. Поверь.
← →
Danilka © (2005-02-10 11:55) [36][34] lats © (10.02.05 11:33)
> Да никого я не жду уже давно все сделал.
маладец. :)
только, некрасиво как-то, все-таки, писать в базу, а по отмене удалять оттуда..
а на счет множественного изменения мастера и его детальных, тут можно попытаться свой кэш сделать на основе датасетов в памяти, например MemTableEh, входящий в дистрибутив EhLib. Но там гемороя будет больше. Однако, я все-таки не понимаю необходимости обязательного множественного изменения мастера.
← →
Serggg (2005-02-10 13:01) [37]ну как же. Типа, открыл файл, внес изменения, закрыл файл с сохр. или без. Аналогично и с базюкой. Каждую запись подтверждать менее красиво
← →
Ega23 © (2005-02-10 13:12) [38]запись подтверждать менее красиво
Зато более актуально при количестве клиентов > 1.
Страницы: 1 вся ветка
Форум: "Базы";
Текущий архив: 2005.03.13;
Скачать: [xml.tar.bz2];
Память: 0.55 MB
Время: 0.035 c