Показать сообщение отдельно
Старый 24.01.2014, 03:23   #38  
Kabardian is offline
Kabardian
Талантливый разгвоздяй
Аватар для Kabardian
 
424 / 338 (12) ++++++
Регистрация: 14.12.2008
Адрес: Москва
Записей в блоге: 14
ИМХО:
  1. Согласен с Belugin про целостность данных, суть транзакции никто не отменял!
  2. Best practice, которые привел MikeR не говорят о том, что надо вообще любые обновления данных делать вложенными в while select forupdate транзакциями. Они говорят как можно уменьшить количество обращений к базе данных и извлечь пользу от оптимистической модели. Это надо применять предельно осторожно и осознанно.
  3. Чтобы было совсем по best practice в пример MikeR необходимо в запрос добавить optimisticlock, чтобы оптимистичная модель применялась независимо от настроек таблицы в которой выполняется обновление данных:
    X++:
    while select optimisticlock ...
  4. Касательно примера, который привел MikeR, я его не буду комментировать, но поясню на примерах из книги Inside Dynamics AX 2012 (см. стр. 444-446), где рассматривается пример обновления кредитного лимита для всех клиентов:

    ПРИМЕР №1:
    X++:
    static void UpdateCreditMax(Args _args) 
    { 
        CustTable custTable; 
        
        ttsBegin; 
        while select forupdate custTable where custTable.CreditMax == 0 
        { 
            if (custTable.balanceMST() < 10000) 
            { 
                custTable.CreditMax = 50000; 
                custTable.update(); 
            } 
        } 
        ttsCommit; 
    }
    Особенности:
    • В случае сбоя либо все данные обновятся, либо нет.
    • Записи блокируются на все время обновления, однако, если включена оптимистичная модель, то блокировка снимается с записей по мере их обновления
    • На уровне базы данных SQL будут выполнены операции: 1 select + 100 update

    ПРИМЕР №2:
    X++:
    static void UpdateCreditMax(Args _args) 
    { 
        CustTable custTable; 
        CustTable updateableCustTable; 
        
        while select custTable where custTable.CreditMax == 0 
        { 
            if (custTable.balanceMST() < 10000) 
            { 
                ttsBegin; 
                select forupdate updateableCustTable 
                where updateableCustTable.AccountNum == custTable.AccountNum; 
                updateableCustTable.CreditMax = 50000; 
                updateableCustTable.update(); 
                ttsCommit; 
            } 
        } 
    }
    Особенности:
    • В случае сбоя часть данных будет обновлена, а часть - нет
    • Блокируется только 1 запись, которая обновляется в данный момент
    • На уровне базы данных SQL будут выполнены операции: 1 select + 100 select + 100 update

    ПРИМЕР №3:
    X++:
    static void UpdateCreditMax3(Args _args) 
    { 
        CustTable custTable; 
        
        while select optimisticlock custTable where custTable.CreditMax == 0 
        { 
            if (custTable.balanceMST() < 10000) 
            { 
                ttsBegin; 
                custTable.CreditMax = 50000; 
                custTable.update(); 
                ttsCommit; 
            } 
        } 
    }
    Особенности:
    • В случае сбоя часть данных будет обновлена, а часть - нет
    • Блокируется только 1 запись, которая обновляется в данный момент
    • На уровне базы данных SQL будут выполнены операции: 1 select + 100 update

    ИТОГО:
    • Вариант № 2 не следует использовать совсем
    • Среди вариантов №1 и №2 выбирать необходимо в зависимости от конкретно поставленной задачи таким образом, чтобы в случае сбоя системы целостность данных не пострадала и для пользователя все было прозрачно и понятно - либо пан, либо пропал.
И еще, хорошая статья со сравнением пессимистичной и оптимистично модели обновления данных:
About locking and blocking in Dynamics AX and how to prevent it