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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 28.10.2006, 16:01   #1  
Blog bot is offline
Blog bot
Участник
 
25,617 / 848 (80) +++++++
Регистрация: 28.10.2006
aEremenko: Ресурс заблокирован, ждите...
Источник: http://blogs.msdn.com/aeremenk/archi...15/666176.aspx
==============

Сразу оговорюсь, что нижеизложенное действительно для Microsoft Dynamics Ax работающего с Microsoft SQL Server, Oracle не рассматриваем.
Проблема блокирования ресурсов на чтение и запись далеко не нова и описана во многих источниках. Первое исследование, касающееся того, как Microsoft Dynamics Ax блокирует ресурсы, которое мне довелось видеть -документ “Решение проблемы взаимных блокировок” созданный много лет назад моим коллегой Андреем Васько. Очень рекомендую к чтению (был опубликован на http://club.msbs.ru, ресурс доступен для партнеров), актуально и по сей день...
Данные из этого документа, с любезного согласия автора, были использованы при создании книги “Разработка бизнес-приложений в Microsoft® Business Solutions — Axapta® версии 3.0” http://www.alpina.ru/book/189/.
В общем представлении, для обновления записи, Microsoft SQL Server блокирует объект. В зависимости от доступных ресурсов, объектом может быть строка, страница, либо вся таблица. Нужно понимать, что длительность блокирования (обновления) играет также существенную роль в общей производительности системы.
Microsoft Dynamics Ax использует READ COMMITED внутри транзакций. На изменяемые данные налагается блокировка, запрещающая не только модификацию, но и чтение данных другой транзакцией.
Итак, что можно предложить для улучшения ситуации с блокировками в версии 3.0? Не секрет, что код типа ‘select for update ’ в Microsoft Dynamics Ax преобразуется в 'select from (UPDLOCK)' в Microsoft SQL Server.
Например, возьмем следующий кусок кода (/Classes/InventUpd_Reservation/deleteReserveRefTransId) :
X++:
ttsbegin;
while select forupdate inventTrans
    index hint TransIdIdx
    where inventTrans.inventTransId == _movementissue.transId() &&
        inventTrans.transChildType == _movementIssue.transChildType() &&
        inventTrans.transChildRefId == _movementissue.transChildRefId() &&
        inventTrans.statusReceipt == StatusReceipt::None &&
        inventTrans.StatusIssue >= statusIssue::ReservPhysical &&
        inventTrans.InventRefTransId != ''
{
    inventTrans::DeleteMarking(inventTrans.InventRefTransId,inventTrans.InventTransId,inventTrans.Qty,true);
    inventTrans.InventRefTransId = '';
    inventTrans.StatusIssue = statusIssue::OnOrder;
    inventTrans.update();
    
}
ttscommit;
Принимаем к рассмотрению:
· “while select forupdate”, который можеn привести к блокировке таблицы
· “index hint”, заставляющий использовать индекс ‘TransIdIdx’, хотя лучший индекс мог бы быть выбран оптимизатором базы данных

Для уменьшения риска возможного нарушения целостности данных, повторяем выборку внутри цикла (с добавлением связки по RecId и проверкой выборки – возврата RecId = 0). ‘P_inventTrans’ – еще одна табличная переменная для той же таблицы. ‘RecID’ используется для выборки только необходимой для обновления:
X++:
ttsbegin;
inventTrans.selectLocked(false);
  
while select RecId from inventTrans
    where inventTrans.inventTransId == _movementissue.transId() &&
        inventTrans.transChildType == _movementIssue.transChildType() &&
        inventTrans.transChildRefId == _movementissue.transChildRefId() &&
        inventTrans.statusReceipt == StatusReceipt::None &&
        inventTrans.StatusIssue >= statusIssue::ReservPhysical &&
        inventTrans.InventRefTransId != ''
{
    select forupdate P_inventTrans            
        where P_inventTrans.RecId == inventTrans.RecId &&  
        P_inventTrans.transChildType == _movementIssue.transChildType() &&
        P_inventTrans.transChildRefId == _movementissue.transChildRefId() &&
        P_inventTrans.statusReceipt == StatusReceipt::None &&
        P_inventTrans.StatusIssue >= statusIssue::ReservPhysical &&
        P_inventTrans.InventRefTransId != ''

        if (P_inventTrans.RecID != 0)
        {
            inventTrans::DeleteMarking(P_inventTrans.InventRefTransId,
                               P_inventTrans.InventTransId,P_inventTrans.Qty,true);
            P_inventTrans.InventRefTransId = '';
            P_inventTrans.StatusIssue = statusIssue::OnOrder;
            P_inventTrans.update();
            ...
        }
    } 
ttscommit;
Что сделано в коде указанном выше:
· Использование “while select RecId” во внешнем цикле уменьшает сетевой трафик
· Без подсказки 'index hint' в коде X++ оптимизатор Microsoft SQL Server будет использовать более оптимальный индекс


Естественно, при чтении записей вне транзации (для отчетов, например), такой механизм не требуется. Достаточно использовать .selectLocked(false) для предотвращения блокировки на чтение.

О блокировках еще не все, в следующий раз – OCC и Microsoft SQL Server 2005…



Источник: http://blogs.msdn.com/aeremenk/archi...15/666176.aspx
 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Slava09: ErpRoadMap - ресурс для внедренцев ERP Blog bot DAX Blogs 0 07.11.2008 13:05
aEremenko: Поддержите! Blog bot DAX Blogs 0 28.10.2006 16:01
Ресурс dynamicsusers.org BETEPOK DAX: База знаний и проекты 1 25.10.2006 11:40
Журнал платежей заблокирован системой bucken DAX: Функционал 4 20.05.2005 19:31
"Пароль был заблокирован администратором" Yuri Safronov DAX: Администрирование 6 11.09.2002 23:18

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

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

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 21:34.