|
|
|
блокировка таблицы при insert
|
|||
|---|---|---|---|
|
#18+
pb 9.01, msSqlServer 2000 требутся, чтобы при запуске dw.update() новые строки добавлялись с "хинтом" (с блокировкой), то есть так: Код: plaintext возможно ли это где-то настроить? или придётся логику добаления в таблицу переносить на сервер БД? (всякие там view + триггер instead insert)? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.06.2005, 14:34 |
|
||
|
блокировка таблицы при insert
|
|||
|---|---|---|---|
|
#18+
savosin_sergeyвозможно ли это где-то настроить? или придётся логику добаления в таблицу переносить на сервер БД? (всякие там view + триггер instead insert)? Обрабатывайте событие DataWindow sqlpreview. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.06.2005, 14:39 |
|
||
|
блокировка таблицы при insert
|
|||
|---|---|---|---|
|
#18+
Локшин Марк savosin_sergeyвозможно ли это где-то настроить? или придётся логику добаления в таблицу переносить на сервер БД? (всякие там view + триггер instead insert)? Обрабатывайте событие DataWindow sqlpreview. А по моему легче написать ХП и обновлять через них, чем возиться с SQLPreview. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.06.2005, 14:43 |
|
||
|
блокировка таблицы при insert
|
|||
|---|---|---|---|
|
#18+
спасибо! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.06.2005, 14:44 |
|
||
|
блокировка таблицы при insert
|
|||
|---|---|---|---|
|
#18+
2 ASCRUS: то есть, dw.update() вообще не использовать? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.06.2005, 14:45 |
|
||
|
блокировка таблицы при insert
|
|||
|---|---|---|---|
|
#18+
savosin_sergey2 ASCRUS: то есть, dw.update() вообще не использовать? Т.е. использовать Stored Procedure Update, а не Update Properties (в окне Specify Update Properties сбросить флажок Allow Updates) --- С уважением, IKAR ikarhomecenter@narod.ru IkarHomeCenter ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.06.2005, 14:48 |
|
||
|
блокировка таблицы при insert
|
|||
|---|---|---|---|
|
#18+
savosin_sergey2 ASCRUS: то есть, dw.update() вообще не использовать? Это почему не использовать ??? Отключаете в DW UpdateProperties, включаете StoredProcedureUpdates. PB будет не сам скрипты генерить на обновление, а вызывать указанные ХП соотвествующе на добавление, обновление и удаление, в которых Вы и напишите свой Insert c блокировкой таблицы. P.S. Я только никак не понимаю, зачем при вставке записи блокировать всю таблицу :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.06.2005, 14:49 |
|
||
|
блокировка таблицы при insert
|
|||
|---|---|---|---|
|
#18+
2 ASCRUS: вот, http://www.sql.ru/forum/actualthread.aspx?tid=189052#1590905 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.06.2005, 15:26 |
|
||
|
блокировка таблицы при insert
|
|||
|---|---|---|---|
|
#18+
ASCRUS А по моему легче написать ХП и обновлять через них, чем возиться с SQLPreview. Но если есть готовый проект, то гораздо быстрее будет подправить на SQLPreview, чем писать кучу хранимых процедур и править кучу DataWindow... Хотя зачем блокировать - действительно не понятно... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.06.2005, 15:59 |
|
||
|
блокировка таблицы при insert
|
|||
|---|---|---|---|
|
#18+
savosin_sergey2 ASCRUS: вот, http://www.sql.ru/forum/actualthread.aspx?tid=189052#1590905 Так не легче ли в триггере на получение максимального номера документа в SELECT через хинт ставить уровень SERIALIZABLE, чем блокировать всю таблицу ? Это "притормозит" до окончания Вашей транзакции все остальные DML операторы на таблицу. Вы же вообще режите любые операции над таблицей - то есть при таком хинте Ваша транзакция во первых будет ждать, пока все транзакции на таблице закончаться, во вторых во время выполнения будет не только "резать" вставляющих записи, но и вообще всех, даже читателей. Какой в этом глубокий спрашивается смысл ? IMHO - не нужно кривизну проектирования БД решать посредством хинтов. Я не знаю логики Вашего приложения, но в случаях, если у Вас могут допускаться разрывы в номерах документов, то вообще легче поставить хинт в триггере на грязное чтения и никого не блокировать лишний раз. Так же можно увести логику с триггера в ХП, ответственной за добавление записей, в MSSQL лучше осторожничать с триггерами, это не ASA :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.06.2005, 16:01 |
|
||
|
блокировка таблицы при insert
|
|||
|---|---|---|---|
|
#18+
авторНо если есть готовый проект, то гораздо быстрее будет подправить на SQLPreview, чем писать кучу хранимых процедур и править кучу DataWindow... Хотя зачем блокировать - действительно не понятно... Почитал по ссылке, оказывается не везде нужно делать... ну все равно я бы не так делал... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.06.2005, 16:24 |
|
||
|
блокировка таблицы при insert
|
|||
|---|---|---|---|
|
#18+
ASCRUS Так не легче ли в триггере на получение максимального номера документа в SELECT через хинт ставить уровень SERIALIZABLE, чем блокировать всю таблицу ? да, я тоже так думаю. --------- 2 ASCRUS, Локшин Марк меня волнует такая задача: таблица "документ" с тремя полями: id int primary key debit varchar(3) dnum int Код: plaintext Для некоторых дебетов (капитальные вложения = "106") надо в поле dnum ("номер позиции") присваивать последовательные номера (в разрезе всей таблицы). Для других значений поля debit такого тербования нет. Там может быть даже NULL . -------------------- Как реализовать генерацию номера dnum ? да с учётом многопользовательского доступа к таблице "документ"? Я виду пока два способа. 1-й способ в insert-триггере на таблице tdocument находить максимальный номер для дебетов "106" и заменять его в добавленных строках, соответственно увеличив. Проблема: возможны взаимные блокировки (deadlock) при добавлении строк в нескольких процессах. Для решения этого на соседнем форуме было предложено при insert блокировать таблицу ( insert into <table> with(TABLOCKX) ). Довольно мрачно, но deadlock'и пропали. 2-й способ в insert-триггере на таблице tdocument обращаться к вспомогательной таблице-счёткику, у которой, в строке (например, с некоторым ключём) хранится последнее использованное значение счётчика. В триггере этот счётчик надо увеличить и присвоить добавленным строкам (у которых нужный дебет "106") новые значения. Проблема: при откате транзакции могут в таблице счётчиков оказаться "дыры" (если два пользователя взялись править таблицу счётчиков, у первого произошёл откат транзакции, но второй после этого всё-таки сохранил своё новое значение счётчика). Возможное решение: наложение блокировки на таблицу счётчиков! чтобы с ней мог работать одновременно только один триггер.. есть ли ещё способы, работающие реализации такого "выборочного" инкремента номера документа? поделитесь! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.06.2005, 16:30 |
|
||
|
блокировка таблицы при insert
|
|||
|---|---|---|---|
|
#18+
Я бы лично модифицировал второй способ. Не делал там инкрементное поле, а сделал таблицу только с одной записью и одним полем, в котором бы хранил последнее актуальное значение номера. Тогда бы схема работы выглядела так в ХП на добавление записи в tdocument: 1. Получаем новое значение счетчика, одновременно его увеличивая (UPDATE tdocument_num SET @Number = Number = Number + 1), таким образом вешаем экслюзивную блокировку на эту запись в таблице и сразу его получаем новое значение в переменную @Number. 2. Вставляем запись (INSERT INTO tdocument) уже сразу с присвоенным номером (в ней же можно для уверенности организовать UNIQUE, конечно если нет NULL полей, определяющих уникальность). Клиент PB на добавление записи через Stored Proc Update вызывает эту ХП, передает значения полей в параметры, она отрабатывает. Далее как обычно COMMIT или ROLLBACK, в зависимости от того, что вернула DW.UPDATE(). Что теперь будет с другими сессиями ? Ничего страшного. Все будут работать как обычно, никаких deallock, кто одновременно пытается добавить записи будут ждать, пока update по commit освободит запись. Таким образом не будет разрывов, триггеров на MSSQL и никто не будет занимать лишнее места (зачем спрашивается с инкриментом или генераторами связываться, когда они изначально был сделан именно для того, чтобы не реагировать на транзакции). P.S. Давно я на MSSQL ничего не делал, но наверное так бы и сделал, причем и на ASA тоже - мне кажется для блокировочников неплохое должно быть решение. Кстати если в таблицу еще ввести поле Имя, то таким образом можно в одной табличке хранить множество ведения собственных именованных счетчиков для разных нужд. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.06.2005, 17:31 |
|
||
|
блокировка таблицы при insert
|
|||
|---|---|---|---|
|
#18+
спасибо! ASCRUS2. Вставляем запись (INSERT INTO tdocument) уже сразу с присвоенным номером (в ней же можно для уверенности организовать UNIQUE, конечно если нет NULL полей, определяющих уникальность). NULL'ы могут быть! да и поля с дебетом, отличным от "106" могут быть неуникальны.. Я тоже согласен, что подход со вспомогательной таблицей более работоспособен. Разве вместо вызода хранимой процедуры можно повесить триггер на update таблицы документа. И осталось разобраться с блокировкой таблицы со счётчиками, так как при откате транзакции возможны "дыры" в нумерации строк документа, см. .. Я имею ввиду, что (может быть) блокировать update, в котором изменяется значение счётчика мало, надо гарантировать работу триггера в одиночестве . То есть, пока он не завершится или не произойдёт откат транзакции, другой триггер не должен обращаться к таблице счётчиков (или к строке, соответствующей счётчику этого документа для дебета "106"). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.06.2005, 17:46 |
|
||
|
блокировка таблицы при insert
|
|||
|---|---|---|---|
|
#18+
savosin_sergeyРазве вместо вызода хранимой процедуры можно повесить триггер на update таблицы документа. Я лично не рекомендую - Вы опять можете нарваться на deadlock-и и другие неприятные ситуации. Смысл в том, что в моем варианте Вы получаете и блокируете номер ДО начала операции вставки документа, а в AFTER триггере MSSQL номер будет получаться и блокироваться ПОСЛЕ вставки документа в таблицу. savosin_sergeyИ осталось разобраться с блокировкой таблицы со счётчиками, так как при откате транзакции возможны "дыры" в нумерации строк документа, см. .. Я имею ввиду, что (может быть) блокировать update, в котором изменяется значение счётчика мало, надо гарантировать работу триггера в одиночестве . То есть, пока он не завершится или не произойдёт откат транзакции, другой триггер не должен обращаться к таблице счётчиков (или к строке, соответствующей счётчику этого документа для дебета "106"). Дыр не будет. В таблице tdocument_number нет инкремент полей - поле Number обычное int поле и обновляем мы его через UPDATE вручную, прибавляя для каждого нового документа единичку. Соотвествующе номер участвует в транзакции и если например она выполнится не успешно, то там так же будет откачен назад номер полученного документа, остальные же, кто пытается вставить запись, в это время по любому в "зависшем" состоянии ждут, пока с таблицы снимется блокировка. Соотвествующе если документ прошел по COMMIT, они получат новый номер, если не прошел по ROLLBACK, они получат тот же номер, который не смогла задействовать откатившая транзакцию сессия. Так что мои 3 совета: 1. Откажитесь от триггера 2. Сделайте как я написал - создайте табличку с полем Number, добавьте в нее запись, напишите ХП и прицепите ее к PB 3. Почитайте поподробнее о транзакциях, блокировках и инкрементах в MSSQL, чтобы иметь более внятное представление обо всем этом. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.06.2005, 17:57 |
|
||
|
блокировка таблицы при insert
|
|||
|---|---|---|---|
|
#18+
А если вопрос поставить по другому- как штатными средствами ПБ заблокировать строку(без тригеров, без ХП, без хинтов) - чтобы работало для ПОЧТИ всех баз. Потом ее и разблокировать. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.06.2005, 16:27 |
|
||
|
блокировка таблицы при insert
|
|||
|---|---|---|---|
|
#18+
Во всех DBMS, где есть транзакции, любой DML блокирует задействованные строки по записи до окончания транзакции, в которой он выполнен. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.06.2005, 17:01 |
|
||
|
блокировка таблицы при insert
|
|||
|---|---|---|---|
|
#18+
Кину свои 5 копеек. Если смотреть на Insert-ы, то "дырок" можно избежать, используя тот или иной механизм назначения номеров документов. Однако, если взглянуть в сторону Delete, а они неизбежны в реальных системах, то "дырки" появятся. Поэтому лучше честно сказать пользователю, что "дырки" будут и, исходя из этого предположения, выбирать механизм. И не стремиться к идеальному варианту без "дырок". Такой подход снимает много проблем. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.06.2005, 20:13 |
|
||
|
блокировка таблицы при insert
|
|||
|---|---|---|---|
|
#18+
2 Anatoly Moskovsky Я понимаю что транзакции блокируют, поэтому и хочу заблокировать строку РАНЬШЕ транзакции и делать с ней то, ЧТО НУЖНО МНЕ, а не соревноваться в скорости-кто изменит строку раньше. В некоторых случаях-в частности - при поддержке псевдо Identity нужно заблокировать запись с идентити ДО выполнения операции. Потом ее разблокировать. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.06.2005, 13:35 |
|
||
|
блокировка таблицы при insert
|
|||
|---|---|---|---|
|
#18+
при поддержке псевдо Identity нужно заблокировать запись с идентити ДО выполнения операции. Потом ее разблокировать Совершенно нет необходимости заранее что-либо блокировать: В момент сохранения: - получаем следующий ID (здесь блокируется генератор ID) - вставляем в таблицу запись с ним - commit (здесь все разблокируется) До момента сохранения нет никаких транзакций. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.06.2005, 17:41 |
|
||
|
блокировка таблицы при insert
|
|||
|---|---|---|---|
|
#18+
как выяснилось, если в в одной транзакции к одной таблице выполняется сначала select, затем update, то велика вероятность взаимоблокировок (кроме msSqlserver'а я ничего нигде больше не проверял), вот ссылка , в ней пример номер 2.. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.06.2005, 18:31 |
|
||
|
блокировка таблицы при insert
|
|||
|---|---|---|---|
|
#18+
savosin_sergeyкак выяснилось, если в в одной транзакции к одной таблице выполняется сначала select, затем update, то велика вероятность взаимоблокировок (кроме msSqlserver'а я ничего нигде больше не проверял), вот ссылка , в ней пример номер 2.. А зачем делать сначала Select? - update idgen set curr_id = curr_id + 1 where tab_name = 'doc'; - select curr_id into :id from idgen where tab_name = 'doc'; - insert into doc (id, ...) values (:id, ...); - commit Первая из конкурирующих транзакций заблокирует запись с id до commit, остальные будут ожидать. После commit возникает снова конкуренция за блокировку среди оставшихся транзакций и все повторяется. Это работает в любой DBMS. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.06.2005, 19:00 |
|
||
|
блокировка таблицы при insert
|
|||
|---|---|---|---|
|
#18+
В этом случае правда возможен deadlock, если происходит вставка в 2 и более таблицы, и порядок получения ID таблиц в разных транзакциях отличается. Например: - (Транзакция1) update idgen set curr_id = curr_id + 1 where tab_name = 'doc'; - (Транзакция2) update idgen set curr_id = curr_id + 1 where tab_name = 'detail'; - (Транзакция1) update idgen set curr_id = curr_id + 1 where tab_name = 'detail'; здесь deadlock - (Транзакция2) update idgen set curr_id = curr_id + 1 where tab_name = 'doc'; Поэтому все клиенты должны соблюдать единый порядок - (Транзакция1) update idgen set curr_id = curr_id + 1 where tab_name = 'doc'; - (Транзакция2) update idgen set curr_id = curr_id + 1 where tab_name = 'doc'; здесь Транзакция2 ожидает commit 1 - (Транзакция1) update idgen set curr_id = curr_id + 1 where tab_name = 'detail'; - (Транзакция2) update idgen set curr_id = curr_id + 1 where tab_name = 'detail'; ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.06.2005, 19:11 |
|
||
|
блокировка таблицы при insert
|
|||
|---|---|---|---|
|
#18+
Идеи конечно правильные - никто не возражает. Но кроме OLTP есть просто информационные системы, в которых блокировка документа является способом указать что с ним уже работают и другие изменения не приветствуются. Вопрос о конкурирующих транзакциях вообще не стоит. Можно поставить TimeStamp, но можно просто блокировать. DeadLock не будет потому работа идет с одной таблицей. Поэтому вопрос и был, что все таки в PowerBuilder позволяет делать явные операции блокировок-получается ничего. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.06.2005, 10:01 |
|
||
|
блокировка таблицы при insert
|
|||
|---|---|---|---|
|
#18+
эти блокировки много от чего зависят, вряд ли можно обойтись какими-то настройками, вроде autocommit=yes/no.. в msSqlServer2k, например, на них влияет настройка isolation level транзакции, "хинты" в операторах insert, update, select, delete ну и, конечно же, от выбора СУБД тоже многое зависит! так что либо использовать хранимые процедуры, либо писать нормальные триггеры, т.е. управлять транзакциями на СУБД, а не из powerBuilder'а.. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.06.2005, 13:10 |
|
||
|
|

start [/forum/topic.php?fid=15&msg=33101523&tid=1338308]: |
0ms |
get settings: |
4ms |
get forum list: |
9ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
53ms |
get topic data: |
6ms |
get forum data: |
1ms |
get page messages: |
36ms |
get tp. blocked users: |
1ms |
| others: | 197ms |
| total: | 311ms |

| 0 / 0 |
