Показать сообщение отдельно
Старый 07.10.2019, 22:59   #27  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,867 / 3123 (112) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Вот пример джоба по работе с разными типами блокировок
X++:
static void example(Args _args)
{
    #define.RetryNum(5)
    
    void test(
        ConcurrencyModel    _concurrencyModel = ConcurrencyModel::Auto,
        boolean             _readPast = false)
    {
        InventTable     inventTable;
        ;
        
        try
        {
            ttsbegin;
            inventTable.concurrencyModel(_concurrencyModel);
            if (_readPast)
            {
                inventTable.readPast(_readPast);
            }
            select forceliterals inventTable
                where   inventTable.ItemId == "0000001";
            inventTable.NameAlias += "1";
            inventTable.doupdate();
            ttscommit;
        }
        catch (exception::UpdateConflict)
        {
            if (appl.ttsLevel() == 0)
            {
                if (xSession::currentRetryCount() >= #RetryNum)
                {
                    throw Exception::UpdateConflictNotRecovered;
                }
                else
                {
                    retry;
                }
            }
            else
            {
                throw Exception::UpdateConflict;
            }
        }
    }
    ;

    test(ConcurrencyModel::Optimistic);
    test(ConcurrencyModel::Pessimistic);
}
для случая оптимистичной модели будут такие запросы:
X++:
SELECT A.ITEMID, ... A.RECVERSION,A.RECID 
FROM INVENTTABLE A 
WHERE ((DATAAREAID=N'MRC') AND (ITEMID=N'0000001'))
/* блокировки не накладывается */

X++:
UPDATE INVENTTABLE SET NAMEALIAS=?,RECVERSION=?,MODIFIEDDATE=?,MODIFIEDTIME=?,MODIFIEDBY=? 
WHERE (((DATAAREAID=?) AND (RECID=?)) AND (RECVERSION=?))
/* блокировка накладывается, но добавлено условие на RECVERSION - если другая сессия успела влезть и поменять данные то тогда в базе будет другой RecVersion и наш запрос обновить 0 записей. Ядро этой поймет и бросит исключение Exception::UpdateConflict - которое мы на X++ сможем обработать */


для случая пессимистичной модели будут такие запросы:
X++:
SELECT  A.ITEMID, ... A.RECVERSION,A.RECID 
FROM INVENTTABLE A WITH( UPDLOCK)
WHERE ((DATAAREAID=N'MRC') AND (ITEMID=N'0000001'))
/* блокировка накладывается из-за явного указания WITH( UPDLOCK) */

X++:
UPDATE INVENTTABLE SET NAMEALIAS=?,RECVERSION=?,MODIFIEDDATE=?,MODIFIEDTIME=?,MODIFIEDBY=? 
WHERE ((DATAAREAID=?) AND (RECID=?))
/* блокировка уже есть. Обновляем запись, ее все равно никто не трогал из-за блокировки */



Все запросы работают в READ COMMITTED
В случае оптимистической модели вероятность блокировок значительно ниже. Проверено на практике.

Последний раз редактировалось Logger; 07.10.2019 в 23:07.