30.09.2005, 13:53 | #21 |
Участник
|
Попробуйте последовать совету Alterant.
У меня была похожая ситуация до тех пор пока не убрал все промежуточные COMMIT. (в моем случае пришлось убрать все LOCTABLE в своем коде) При этом совсем необязательно, чтобы после промежуточных COMMIT были LOCTABLE, dead... проявится и при модификации записей после COMMIT, поскольку происходит автоматический захват записи. И помоему использование LOCTABLE с SQL практически не эффетивно. |
|
30.09.2005, 14:39 | #22 |
Участник
|
Я могу еще посоветовать вот что. В самое начало функции вставить LOCK какой-нибудь не особо нужной таблицы. И кстати, надо учитывать, что когда система выходит из кодюнита все локи снимаются - какждая стандартная учетная процедура написана в одном кодюните.
|
|
30.09.2005, 16:11 | #23 |
Участник
|
Alterant подскажите пожалуйста,
снимаются LOCK установленные внутри codeunit или вообще все ? |
|
30.09.2005, 16:24 | #24 |
Участник
|
Цитата:
Сообщение от zub
Alterant подскажите пожалуйста,
снимаются LOCK установленные внутри codeunit или вообще все ? Этот пример я привел к тому, что дедлоки могут возникать, если после отработки стандартного кодюнита, пользовательская функция опять лочит таблицу, именно в этот промежуток другая сессия может поставить блокировку. По этому весь код, который ставит блокировки лучше помещать в один кодюнит. |
|
30.09.2005, 16:33 | #25 |
Участник
|
Alterant, эксперемент показал, что LOCK не снимается при выходе из codeunit, он снимется только после возврата в форму, из которой он был вызван, если ранее не будет вызван COMMIT
|
|
03.10.2005, 10:53 | #26 |
Участник
|
Выполняемая операция регистрации использует несколько кодеюнитов. Если я правильно Вас понял, то если я залочил таблицы в одном кодеюните, а потом вызвал код из другого кодеюнита, то залоченные таблицы будут разлочены?
COMMIT, используемый в вызывнном кодеюните завершит все транзакции только текущего кодеюнита или и транзакции вызвавшего кодеюнита? |
|
04.10.2005, 10:13 | #27 |
Участник
|
Выход из codeunit не преводит к снятию блокировки, а вот COMMIT снимет абсолютно все блокировки сделанные до него, независимо от вызовов codeunit
Поэтому желательно делать один СOMMIT в конце совершаемой операции |
|
04.10.2005, 11:40 | #28 |
Участник
|
Цитата:
Сообщение от zub
Выход из codeunit не преводит к снятию блокировки, а вот COMMIT снимет абсолютно все блокировки сделанные до него, независимо от вызовов codeunit
Поэтому желательно делать один СOMMIT в конце совершаемой операции Тестирование проводилось на SQL Server, следующим кодом: <div class='CALtop'>C/AL</div><div class='CAL'> OBJECT Codeunit 99000 TestCommit { OBJECT-PROPERTIES { Дата=04.10.05; Время=11:17:19; Изменен=Да; Список версий=; } PROPERTIES { OnRun=BEGIN PayTerms.LOCKTABLE; SLEEP(10000); END; } CODE { VAR PayTerms@1000000000 : Record 3; BEGIN END. } } OBJECT Codeunit 99001 LockRun { OBJECT-PROPERTIES { Дата=04.10.05; Время=11:19:42; Изменен=Да; Список версий=; } PROPERTIES { OnRun=BEGIN LockTest.RUN; SLEEP(5000); LockTest.RUN; MESSAGE('%1', TIME); END; } CODE { VAR LockTest@1000000000 : Codeunit 99000; BEGIN END. } } OBJECT Codeunit 99002 LockRun2 { OBJECT-PROPERTIES { Дата=04.10.05; Время=11:20:39; Изменен=Да; Список версий=; } PROPERTIES { OnRun=BEGIN LockTest.RUN; MESSAGE('%1', TIME); END; } CODE { VAR LockTest@1000000000 : Codeunit 99000; BEGIN END. } } </div> Первый пользователь запустил кодюнит 99001 LockRun, второй сразу после него 99002 LockRun2. По результатам теста, второй пользователь получил сообщение раньше, чем первый. Если бы система сохранила блокировки установленные при первом вызове кодюнита 99000 TestCommit первым пользователем (из кодюнита 99001 LockRun), то второй пользователь получил бы доступ к таблице только после первого, т.е. результаты теста были бы другими. Причем результаты теста не зависят от того, вызывался ли кодюнит с обработкой возвращаемого значения или без, т.е. и в случае <div class='CALtop'>C/AL</div><div class='CAL'> LockTest.RUN </div> и <div class='CALtop'>C/AL</div><div class='CAL'> IF LockTest.RUN THEN </div> блокировки установленные в LockTest снимаются! |
|
04.10.2005, 11:49 | #29 |
Участник
|
Alterant - думаю Ваш пример не совсем корректен, так как блокировки накладываются не на таблицу, а на запись. Чтобы проверить это предлагаю запустить QA, в нем процедуру sp_lock и добавить find('+') в Ваш код.
|
|
04.10.2005, 12:37 | #30 |
Участник
|
Цитата:
Сообщение от rmv
Alterant - думаю Ваш пример не совсем корректен, так как блокировки накладываются не на таблицу, а на запись. Чтобы проверить это предлагаю запустить QA, в нем процедуру sp_lock и добавить find('+') в Ваш код.
Но обнаружил другую особенность, при замене sleep на некий код, приближенный к реальному, блокировка действительно не снимается. Так что, возможно, это я ввожу людей в заблуждение, за что извиняюсь. |
|
04.10.2005, 13:34 | #31 |
Участник
|
Провел дополнительные исследования, похоже в моем примере интерпретатор "видит", что после locktable никаких действий с таблицой не производится и блокировку не ставит.
Так что Zub, Вы были правы, а я нет. |
|
04.10.2005, 14:14 | #32 |
Участник
|
ссссспади....
ну неужели доку лень почитать? не выход из юнита, а полное окончание процесса (возврат управления пользователю) завершает транзакцию неявно. COMMIT завершает транзакцию явно. Возможности запустить в одном процессе несколько транзакций нет. Все блокировки с завершением транзакции снимаются. |
|
04.10.2005, 16:40 | #33 |
Участник
|
Доку то читать не лень, но как говорил Козьма Прутков "Если на клетки льва видиш надпись осел - неверь глазам своим", особенно если имееш дело с мелкософтом. Иногда приходится и эсперементировать
|
|
11.10.2005, 12:05 | #34 |
Участник
|
Запускаю операцию регистрации складского контроля с одной машины на двух клиентах под разными логинами с запущенными мониторами клиентов и логгерами выполнения кода.
Если "повезет" оба клиента зависают и висят бесконечно долго. Один клиент заблокирован другим. А блокирующий висит, непонятно по какой причине. Принудительно отключаю блокирующего с помощью kill process через 26 минут зависа (12.48). Запускаю Form 150020 Client Monitor (из комплекта Performance troubleshooting) и в конце лога получается следующее: 12.22: SQL Error: [Microsoft][ODBC SQL Server Driver][DBNETLIB]ConnectionRead (recv()). 12.48: SQL Error: [Microsoft][ODBC SQL Server Driver]Ошибка связи 12.48: SQL Error: [Microsoft][ODBC SQL Server Driver]Ошибка связи В 12.22 блокирующий клиент выполнял код: IF WhseActivLine.FIND('+') THEN Что за ошибка возникла в 12.22? |
|
11.10.2005, 15:57 | #35 |
Участник
|
вот, я ж говорю что это не дедлок! один залочил и повис, другой его ждет.
что-то с железом или с сервером или с драйвером... на sql.ru не пробовали спросить? |
|
12.10.2005, 10:08 | #36 |
Участник
|
Вот, вспомнилось...
Однажды в подобной ситуации - тоже что-то про connect было, помогла переустановка ODBC драйвера дляMS SQL на клиентской машине. В другой раз был совсем глюк какой-то, одна из записей в книге (товарной, кажется) не читалась. Ну буквально, вот форму пролистываешь, дойдет до неё и зависает... Помогло удаление таблицы и заливка в неё данных из бакапа.. |
|
13.10.2005, 08:17 | #37 |
Участник
|
Спасибо, но ODBC драйверы переустановили на клиентских машинах - не помогло.
На sql.ru создал обсуждение, если интересно, то: http://www.sql.ru/forum/actualthread.aspx?tid=224869 |
|
13.10.2005, 09:39 | #38 |
Участник
|
DeSp - если можно имитируйте ситуацию еще раз и снимите результаты процедуры sp_lock в QA.
|
|
13.10.2005, 11:07 | #39 |
Участник
|
В 12.22 блокирующий клиент выполнял код: IF WhseActivLine.FIND('+') THEN
А на какой операции "споткнулся" блокируемый ? Установлен ли Locktable на WhseActivLine ? |
|
13.10.2005, 11:48 | #40 |
Участник
|
Блокируемый ждал в том же месте и на той же команде, судя по логу монитора клиентов.
Да, таблица Warehouse Activity Line была ранее заблокирована в другом кодеюните из которого вызвался текущий кодеюнит. |
|