AXForum  
Вернуться   AXForum > Microsoft Dynamics NAV > NAV: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 22.03.2005, 17:17   #1  
Cheb is offline
Cheb
Участник
Лучший по профессии 2017
 
138 / 13 (1) ++
Регистрация: 22.09.2002
Адрес: Ростов-на-Дону -> Москва
Здравствуйте.

Подскажите, имеет ли значение, в каком порядке указывать SETRANGE и LOCKTABLE? Можно ли вообще говоря, заблокировать не всю таблицу, а только некоторый диапазон записей? А то просто беда с учетом заказов, при учете большого заказа остальные пользователи, работающие с другими заказами, просто напросто висят.
В качестве сервера используем MS SQL 2000.
Старый 22.03.2005, 17:21   #2  
Dzemon is offline
Dzemon
Moderator
 
1,247 / 12 (3) ++
Регистрация: 09.09.2004
С SQL все гораздо хуже. На самом деле, код Навижина не оптимизирован для работы с SQL сервером. Если вы почитаете Performance Troubleshooting Guide или Tuning Navision for better performance то поймете, что все не так просто.
Старый 22.03.2005, 17:33   #3  
Kirvisniemi is offline
Kirvisniemi
Moderator
 
342 / 13 (1) ++
Регистрация: 21.12.2004
LOCKTABLE в SQL Server таблицу не лочит вообще. Да и не нужно это.
Старый 23.03.2005, 10:42   #4  
Cheb is offline
Cheb
Участник
Лучший по профессии 2017
 
138 / 13 (1) ++
Регистрация: 22.09.2002
Адрес: Ростов-на-Дону -> Москва
Так все таки, почему при учете заказов блокируются ВСЕ заказы, а не только учитываемый? Если в кодеюните 80 после строки SalesLine.LOCKTABLE написать
SalesLine.SETRANGE("Document Type","Document Type");
SalesLine.SETRANGE("Document No.","No.");
IF SalesLine.FIND('+') THEN;

Это приведет только к блокировке только данного заказа?
Старый 23.03.2005, 10:58   #5  
Dzemon is offline
Dzemon
Moderator
 
1,247 / 12 (3) ++
Регистрация: 09.09.2004
Дело в том, что на SQL версии, оператор FIND БЛОКИРУЕТ ТАБЛИЦУ, а GET и LOCKTABLE - нет.
Старый 23.03.2005, 11:17   #6  
Kirvisniemi is offline
Kirvisniemi
Moderator
 
342 / 13 (1) ++
Регистрация: 21.12.2004
В 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
Старый 23.03.2005, 11:21   #7  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от tyrex
В SQL-версии таблицы никогда не блокируются, блокируются только записи.
Да, согласен.
Только хотелось бы уточнить, что блокировки эскалируются.
И если FIND заблокирует достаточно много записей, то СКЛ автоматически поднимет уровень блокировки до страничной и до таблицы.
__________________
полезное на axForum, github, vk, coub.
Старый 23.03.2005, 11:29   #8  
Kirvisniemi is offline
Kirvisniemi
Moderator
 
342 / 13 (1) ++
Регистрация: 21.12.2004
Согласен. Правда эскалацию можно отключать.
Старый 23.03.2005, 11:37   #9  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
ой. не надо бы такие советы давать

это как правка реестра - если не знаешь, то лучше не соваться. если знаешь, то можно делать чудеса.

но это отдельная тема.
__________________
полезное на axForum, github, vk, coub.
За это сообщение автора поблагодарили: mira (1).
Старый 23.03.2005, 11:39   #10  
Yoil is offline
Yoil
NavAx
NavAx Club
Лучший по профессии 2017
Лучший по профессии 2009
 
1,574 / 70 (6) ++++
Регистрация: 20.11.2002
Адрес: Msk
Цитата:
Сообщение от mazzy
И если FIND заблокирует достаточно много записей, то СКЛ автоматически поднимет уровень блокировки до страничной и до таблицы.
Господа, так FIND блокирует таки рекордсет из трех записей или чо ваще?
__________________
"Моей лошадке ядрышком полмордочки снесло..."
А.В.Суворов, письма к дочери
Старый 23.03.2005, 11:46   #11  
Dzemon is offline
Dzemon
Moderator
 
1,247 / 12 (3) ++
Регистрация: 09.09.2004
Цитата:
Сообщение от 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 код Навижина, результаты неплохие, но объем изменений ужасает.
Старый 23.03.2005, 11:52   #12  
Cheb is offline
Cheb
Участник
Лучший по профессии 2017
 
138 / 13 (1) ++
Регистрация: 22.09.2002
Адрес: Ростов-на-Дону -> Москва
Значит, исходя из всего вышесказанного, решить проблему с учетом заказов нельзя?
Старый 23.03.2005, 12:10   #13  
Kirvisniemi is offline
Kirvisniemi
Moderator
 
342 / 13 (1) ++
Регистрация: 21.12.2004
Решить можно, но не через механизм блокировок, потому что блокировки и так работают как надо (лочат только диапазон рабочих значений).

Есть идея поставить в цикле побольше COMMIT'ов - тогда после каждого коммита блокировка будет сниматься. Недостаток этого способа - если какая итерация вызовет ошибку, заказ не откатится, а все равно учтется, правда не полностью
Старый 23.03.2005, 13:39   #14  
Cheb is offline
Cheb
Участник
Лучший по профессии 2017
 
138 / 13 (1) ++
Регистрация: 22.09.2002
Адрес: Ростов-на-Дону -> Москва
Спасибо за ответ. Но COMMIT однозначно не подходит в этой ситуации, надежность все-таки важнее.
Старый 04.04.2005, 18:13   #15  
ablievn_imported is offline
ablievn_imported
Участник
 
18 / 10 (1) +
Регистрация: 07.02.2005
Вот интересная ссылка про sql-локи, может кому интересно будет:
http://www.mbsonline.org/forum/topic.asp?TOPIC_ID=5531
Старый 19.09.2007, 04:55   #16  
smoyk is offline
smoyk
Участник
 
188 / 13 (1) ++
Регистрация: 20.04.2007
Интересно, все согласны, что таблицы в 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.
Кто нибудь может прокомментировать? Версия Navision 3.70.A.
Старый 19.09.2007, 11:31   #17  
Fordewind is offline
Fordewind
Участник
 
1,134 / 10 (3) +
Регистрация: 01.12.2005
Цитата:
Сообщение от smoyk Посмотреть сообщение
LOCKTABLE (Record)
Use this function to lock a C/SIDE table to protect it from write transactions that conflict with each other..
Это справедливо для Native сервера
Старый 19.09.2007, 12:07   #18  
smoyk is offline
smoyk
Участник
 
188 / 13 (1) ++
Регистрация: 20.04.2007
Цитата:
Сообщение от Fordewind Посмотреть сообщение
Это справедливо для Native сервера
С чего Вы взяли? В справке не написано, что это верно только для одного Native сервера. Вы думаете справка писалась только под него?
Старый 25.09.2007, 10:31   #19  
Raul is offline
Raul
Участник
 
35 / 10 (1) +
Регистрация: 15.03.2006
Не согласен с тем утверждением что locktable работает только в нативной базе. В SQL варианте он тоже работает и блокирует таблицу, если для таблицы вызван locktable, то из другой транзакции можно только читать записи в таблице, любое их изменение упирается в блокировку. Таким образом Locktable для выбранной таблицы поднимает уровень изоляции транзакций до повторяемого четния. То что код учетных CU наполнен операторами locktable только для того чтобы найти последнюю операцию в таблице и на протяжении всего учета таблица будет блокирована, делает реальную многопользовательскую работу невозможной. Именно поэтому висят учеты документов, а иногда nav откровенно пишет ваше действие заблокировано другим пользователем .
Старый 27.09.2007, 14:11   #20  
Голышев Михаил is offline
Голышев Михаил
Участник
 
106 / 10 (1) +
Регистрация: 03.07.2006
Цитата:
Сообщение от Dzemon Посмотреть сообщение
Дело в том, что на SQL версии, оператор FIND БЛОКИРУЕТ ТАБЛИЦУ, а GET и LOCKTABLE - нет.
Не верно.

FIND не блокирует таблицу, если текущий уровень изоляции транзакции READUNCOMMITTED.
Или в нотации Navision TRANSACTIONTYPE::Browse
Аналогично работает и GET.

Этот тип изоляции с которым запускается по умолчанию любой код (до первых изменений в базе данных, после этого уровень изоляции увеличивается.) Также с этим уровнем изоляции отображаются некоторые формы, например
Фин Журнал и Товарный Журнал. Можно также указать уровень изоляции в свойствах Report'ов (св-во TransactionType).

Как правильно заметил Raul, уровень изоляции можно принудительно повысить, применив LOCKTABLE.
При этом следующий вызов FIND или GET будет не с хинтом READUNCOMMITTED, а с хинтом UPDLOCK (что заблокирует набор возвращаемых записей).

------
В качестве ускорения учета, мы в компании предприняли много мер, вот некоторые из них, которые приходят на ум:
  • 1
    Учет надо разделить на несколько этапов:
    а) Предучетные заполнения (обновления полей, расчет цен и т.п. Всё что можно сохранить до учета)
    б) COMMIT
    в) Предучетные проверки (Все проверки, TESTFIELDы, ERRORы и прочее, что может "обломить" учет). Выносим это непосредственно перед учетом, чтобы код выполнялся в режиме READUNCOMMITTED (TRANSACTIONTYPE::Browse).
    Некоторые проверки продублированы как в предучетной фазе так и в основной. Это немного увеличивает нагрузку, зато не возникает блокирование\освобождение ресурсов и откатов транзакции.
    г) основной учет
  • 2
    Борьба с эскалацией блокировок.
    Как было сказано выше, sql всегда осуществляет блокировку на уровне строк таблицы (по ключам).
    Однако, есть таблицы, для которых это излишне. Некоторые можно блокировать на уровне страниц, некоторые стразу на уровне таблиц.
    Вот наши хинты. Будьте осторожны, не выполняйте эти скрипты "в тупую".

    Код:
    ALTER INDEX ALL ON [dbo].[КРОК$G_L_Entry]		SET (ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = OFF);
    ALTER INDEX ALL ON [dbo].[КРОК$17$0]			SET (ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = OFF);
    ALTER INDEX ALL ON [dbo].[КРОК$G_L_Correspondence_Entry]	SET (ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = OFF);
    ALTER INDEX ALL ON [dbo].[КРОК$12401$0]			SET (ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = OFF);
    ALTER INDEX ALL ON [dbo].[КРОК$12401$1]			SET (ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = OFF);
    ALTER INDEX ALL ON [dbo].[КРОК$Ledger_Entry_Dimension]		SET (ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = ON);
    ALTER INDEX ALL ON [dbo].[КРОК$Posted_Document_Dimension]	SET (ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = ON);
    ALTER INDEX ALL ON [dbo].[КРОК$Analysis_View_Entry]			SET (ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = ON);
    ALTER INDEX ALL ON [dbo].[КРОК$Cust__Ledger_Entry]			SET (ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = OFF);
    ALTER INDEX ALL ON [dbo].[КРОК$21$0]			SET (ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = OFF);
    ALTER INDEX ALL ON [dbo].[КРОК$Detailed_Cust__Ledg__Entry]	SET (ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = OFF);
    ALTER INDEX ALL ON [dbo].[КРОК$379$0]			SET (ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = OFF);
    ALTER INDEX ALL ON [dbo].[КРОК$Vendor_Ledger_Entry]			SET (ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = OFF);
    ALTER INDEX ALL ON [dbo].[КРОК$25$0]			SET (ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = OFF);
    ALTER INDEX ALL ON [dbo].[КРОК$Detailed_Vendor_Ledg__Entry]	SET (ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = OFF);
    ALTER INDEX ALL ON [dbo].[КРОК$380$0]			SET (ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = OFF);
    ALTER INDEX ALL ON [dbo].[КРОК$Item_Ledger_Entry]			SET (ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = OFF);
    ALTER INDEX ALL ON [dbo].[КРОК$Item_Application_Entry]		SET (ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = OFF);
    ALTER INDEX ALL ON [dbo].[КРОК$32$0]			SET (ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = OFF);
    ALTER INDEX ALL ON [dbo].[КРОК$Item_Entry_Relation]			SET (ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = OFF);
    ALTER INDEX ALL ON [dbo].[КРОК$VAT_Entry]		SET (ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = OFF);
    ALTER INDEX ALL ON [dbo].[КРОК$Bank_Account_Ledger_Entry]	SET (ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = OFF);
    ALTER INDEX ALL ON [dbo].[КРОК$271$0]			SET (ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = OFF);
    ALTER INDEX ALL ON [dbo].[КРОК$Reservation_Entry]			SET (ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = ON);
    ALTER INDEX ALL ON [dbo].[КРОК$Item_Application_Entry]		SET (ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = OFF);
    ALTER INDEX ALL ON [dbo].[КРОК$Value_Entry]		SET (ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = OFF);
    ALTER INDEX ALL ON [dbo].[КРОК$5802$0]			SET (ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = OFF);
    ALTER INDEX ALL ON [dbo].[КРОК$Value_Entry_Relation]		SET (ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = OFF);
    ALTER INDEX ALL ON [dbo].[КРОК$FA_Ledger_Entry]	SET (ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = OFF);
    ALTER INDEX ALL ON [dbo].[КРОК$Sales_Line]		SET (ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = ON);
  • 3
    Отложенный учет (постановка в очередь, для учета ночью роботом. Перед постановкой - предучетные проверки в режиме READUNCOMMITTED)
  • 4
    Изничтожить SETCURRENTKEY везде где возможно (мало того, что изза него SQL строит кривые планы запросов, так еще и блокировки идут не по ключу).
  • 5
    Своевременно (ежедневно) обновлять статистику по индексам. (Правильные планы запросов=>правильный ключ=>меньше заблокированных строк)
  • 6
    Plan Guides. (Хинты для запросов, позволяют сделать тюнинг особо частых запросов на построение оптимального плана) в BOL написано достаточно подробно.
  • 7
    Поменьше FIND('+'),FIND('-'). Побольше ISEMPTY, FINDFIRST, FINDLAST, FINDSET. (Для примера, проверка наличия записей с помощью ISEMPTY быстрее FIND('-') более чем в 10000 раз).
  • 8
    Поменьше длинных индексов. (Об этом много рассказано на форуме. Делайте индексы по принципу: "Первое поле индекса бьет, второе - добивает").
  • 9
    Поменьше SIFTов (Об этом также неоднократно говорилось)
Возможно чтото было еще, сразу не вспомнишь
 


Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 11:03.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.