|
![]() |
#1 |
Участник
|
Здравствуйте.
Подскажите, имеет ли значение, в каком порядке указывать SETRANGE и LOCKTABLE? Можно ли вообще говоря, заблокировать не всю таблицу, а только некоторый диапазон записей? А то просто беда с учетом заказов, при учете большого заказа остальные пользователи, работающие с другими заказами, просто напросто висят. В качестве сервера используем MS SQL 2000. |
|
![]() |
#2 |
Moderator
|
С SQL все гораздо хуже. На самом деле, код Навижина не оптимизирован для работы с SQL сервером. Если вы почитаете Performance Troubleshooting Guide или Tuning Navision for better performance то поймете, что все не так просто.
|
|
![]() |
#3 |
Moderator
|
LOCKTABLE в SQL Server таблицу не лочит вообще. Да и не нужно это.
|
|
![]() |
#4 |
Участник
|
Так все таки, почему при учете заказов блокируются ВСЕ заказы, а не только учитываемый? Если в кодеюните 80 после строки SalesLine.LOCKTABLE написать
SalesLine.SETRANGE("Document Type","Document Type"); SalesLine.SETRANGE("Document No.","No."); IF SalesLine.FIND('+') THEN; Это приведет только к блокировке только данного заказа? |
|
![]() |
#5 |
Moderator
|
Дело в том, что на SQL версии, оператор FIND БЛОКИРУЕТ ТАБЛИЦУ, а GET и LOCKTABLE - нет.
|
|
![]() |
#6 |
Участник
|
Цитата:
FIND не блокирует таблицу, если текущий уровень изоляции транзакции READUNCOMMITTED. Или в нотации Navision TRANSACTIONTYPE::Browse Аналогично работает и GET. Этот тип изоляции с которым запускается по умолчанию любой код (до первых изменений в базе данных, после этого уровень изоляции увеличивается.) Также с этим уровнем изоляции отображаются некоторые формы, например Фин Журнал и Товарный Журнал. Можно также указать уровень изоляции в свойствах Report'ов (св-во TransactionType). Как правильно заметил Raul, уровень изоляции можно принудительно повысить, применив LOCKTABLE. При этом следующий вызов FIND или GET будет не с хинтом READUNCOMMITTED, а с хинтом UPDLOCK (что заблокирует набор возвращаемых записей). ------ В качестве ускорения учета, мы в компании предприняли много мер, вот некоторые из них, которые приходят на ум:
![]() |
|
![]() |
#7 |
Moderator
|
В SQL-версии таблицы никогда не блокируются, блокируются только записи.
Приведенный код SalesLine.LOCKTABLE; SalesLine.SETRANGE("Document Type","Document Type"); SalesLine.SETRANGE("Document No.","No."); IF SalesLine.FIND('+') THEN; заблокирует recordset, состоящий из двух записей - текущей (последней) и предпоследней (обычно блокируется запись сверху и запись снизу). Цитата:
оператор FIND БЛОКИРУЕТ ТАБЛИЦУ, а GET и LOCKTABLE - нет
Rec.LOCKTABLE; Rec.FIND(...) блокирует recordset из трех записей. Код Rec.LOCKTABLE; Rec.GET(...) блокирует текущую запись таблицы Rec |
|
![]() |
#8 |
Участник
|
Цитата:
Сообщение от tyrex
В SQL-версии таблицы никогда не блокируются, блокируются только записи.
Только хотелось бы уточнить, что блокировки эскалируются. И если FIND заблокирует достаточно много записей, то СКЛ автоматически поднимет уровень блокировки до страничной и до таблицы. |
|
![]() |
#9 |
Moderator
|
Согласен. Правда эскалацию можно отключать.
|
|
![]() |
#10 |
Участник
|
ой. не надо бы такие советы давать
![]() это как правка реестра - если не знаешь, то лучше не соваться. если знаешь, то можно делать чудеса. но это отдельная тема. |
|
|
За это сообщение автора поблагодарили: mira (1). |
![]() |
#11 |
NavAx
|
Цитата:
Сообщение от mazzy
И если FIND заблокирует достаточно много записей, то СКЛ автоматически поднимет уровень блокировки до страничной и до таблицы.
__________________
"Моей лошадке ядрышком полмордочки снесло..." А.В.Суворов, письма к дочери |
|
![]() |
#12 |
Moderator
|
Цитата:
Сообщение от tyrex
В SQL-версии таблицы никогда не блокируются, блокируются только записи.
Приведенный код SalesLine.LOCKTABLE; SalesLine.SETRANGE("Document Type","Document Type"); SalesLine.SETRANGE("Document No.","No."); IF SalesLine.FIND('+') THEN; заблокирует recordset, состоящий из двух записей - текущей (последней) и предпоследней (обычно блокируется запись сверху и запись снизу). Цитата:
оператор FIND БЛОКИРУЕТ ТАБЛИЦУ, а GET и LOCKTABLE - нет
Rec.LOCKTABLE; Rec.FIND(...) блокирует recordset из трех записей. Код Rec.LOCKTABLE; Rec.GET(...) блокирует текущую запись таблицы Rec Важно то, что с базой SQL и родной, Навижин работает по разным принципам, соответственно и написание кода требует ухищрений для корректной работы в обеих вариантах, чего к сожалению не делается. Сейчас одни знакомые энтузиасты работы под SQL активно оптимизируют C/AL код Навижина, результаты неплохие, но объем изменений ужасает. |
|
![]() |
#13 |
Участник
|
Значит, исходя из всего вышесказанного, решить проблему с учетом заказов нельзя?
|
|
![]() |
#14 |
Moderator
|
Решить можно, но не через механизм блокировок, потому что блокировки и так работают как надо (лочат только диапазон рабочих значений).
Есть идея поставить в цикле побольше COMMIT'ов - тогда после каждого коммита блокировка будет сниматься. Недостаток этого способа - если какая итерация вызовет ошибку, заказ не откатится, а все равно учтется, правда не полностью |
|
![]() |
#15 |
Участник
|
Спасибо за ответ. Но COMMIT однозначно не подходит в этой ситуации, надежность все-таки важнее
![]() |
|
![]() |
#16 |
Участник
|
Вот интересная ссылка про sql-локи, может кому интересно будет:
http://www.mbsonline.org/forum/topic.asp?TOPIC_ID=5531 |
|
![]() |
#17 |
Участник
|
Интересно, все согласны, что таблицы в SQL Server не блокируются и LOCKTABLE толи не используется, толи непонятно что делает... Между тем C/SIDE Reference Guide утверждает, что :
Цитата:
LOCKTABLE (Record)
Use this function to lock a C/SIDE table to protect it from write transactions that conflict with each other. |
|
![]() |
#18 |
Участник
|
|
|
![]() |
#19 |
Участник
|
|
|
![]() |
#20 |
Участник
|
Не согласен с тем утверждением что locktable работает только в нативной базе. В SQL варианте он тоже работает и блокирует таблицу, если для таблицы вызван locktable, то из другой транзакции можно только читать записи в таблице, любое их изменение упирается в блокировку. Таким образом Locktable для выбранной таблицы поднимает уровень изоляции транзакций до повторяемого четния. То что код учетных CU наполнен операторами locktable только для того чтобы найти последнюю операцию в таблице и на протяжении всего учета таблица будет блокирована, делает реальную многопользовательскую работу невозможной. Именно поэтому висят учеты документов, а иногда nav откровенно пишет ваше действие заблокировано другим пользователем .
|
|