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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 08.05.2008, 15:37   #1  
Volodymyr is offline
Volodymyr
Участник
 
36 / 21 (1) +++
Регистрация: 03.11.2006
Адрес: Киев
Параллельная обработка данных
Всем привет!
Такой вопрос есть батч(пакет)-джоба, которая выполняет апдейт таблици.
PHP код:
run()
{
    
Trans trans;
    
Trans buffer;
    try
    {
        while 
select trans where trans.open == true
        
{
            
ttsbegin;
            
buffer Trans::find(trans.recidtrue);
            
buffer.open false;
            
buffer.update()
            
ttscommit;
        }
    }
    catch (
Exception::Deadlock)
    {
        
retry;
    }
    catch (
Exception::UpdateConflict)
    {
        
retry;
    }

Если запустить два батча, то что произойдет?

1) Первый батч выбирает из базы например 20 записей
2) Второй батч выбирает из базы теже 20 записей
3) Первы батч апдейтит первую запись - все ок
4) Второй батч апедйтит первую запись - конфликт апдейта
5) Второй батч зановов выбирает с базы, но уже 19 записей
6) Первый бачт апдейтит вторую линию
7) Второй батч апдейтит свою первую линию - кофликт апдейта ....

Получается что второй батч мешает всевремя первому. Можно ли сделать чтобы от двух был выигрышь?

Или я не правлиьно понимаю.
Спасибо!
Старый 08.05.2008, 15:47   #2  
tourist is offline
tourist
Участник
 
21 / 14 (1) ++
Регистрация: 03.05.2006
Перед транзакцией делайте trans.reread() и еще раз проверяйте условие селекта
т.е
trans.reread();
if(trans.open)
{
ttsbegin;
...
Старый 08.05.2008, 16:02   #3  
Volodymyr is offline
Volodymyr
Участник
 
36 / 21 (1) +++
Регистрация: 03.11.2006
Адрес: Киев
Это не решит проблемы.
Ведь всеравно два батча будут работать хуже чем один...

В реальности перед апдейтом транзакции идет достаточно большая по времени функциональность, и при апдейти транзакции если возникает конфликт, то откатывается все назад.

Наверное два всегда хуже чем один...
Интересно, можно ли как то в селекте выбрать линии, которые точно не проапдейтятся другим батчем?
Старый 08.05.2008, 16:20   #4  
tourist is offline
tourist
Участник
 
21 / 14 (1) ++
Регистрация: 03.05.2006
выбор по четным и нечетным recId
Старый 08.05.2008, 16:47   #5  
Volodymyr is offline
Volodymyr
Участник
 
36 / 21 (1) +++
Регистрация: 03.11.2006
Адрес: Киев
=) Смешно... но всетаки

Вобщем задача свелась к тому, что нужно в цикле проверить можнло ли залочить текущую линию , если да, то залочиеть ее , иначе продолжить цикл (т.е. перейти к следующей линии)

Как это реализовать пока незнаю
Старый 08.05.2008, 17:28   #6  
ivas is offline
ivas
Участник
Аватар для ivas
 
252 / 68 (3) ++++
Регистрация: 22.12.2005
а если так переписать?
X++:
run()
{
    Trans trans;
    Trans buffer;
    ;

    select trans where trans.open == true;

    while (trans)
    {
        try
        {
            ttsbegin;
            buffer = Trans::find(trans.recid, true);
            buffer.open = false;
            buffer.update()
            ttscommit;
        }
        catch (Exception::Deadlock)
        {
            next trans;
            retry;
        }
        catch (Exception::UpdateConflict)
        {
            next trans;
            retry;
        }
        next trans;
    } 
}
__________________
aLL woRk aNd nO JoY MAKes jAck a dULL Boy
Старый 08.05.2008, 17:37   #7  
Alex_KD is offline
Alex_KD
Участник
AxAssist
MCBMSS
Соотечественники
 
522 / 362 (14) ++++++
Регистрация: 06.07.2006
Адрес: Melbourne, Down Under
Может так?
X++:
UPDATE_RECORDSET trans SETTING open= false WHERE open = true;
__________________
AxAssist 2012 - Productivity Tool for Dynamics AX 2012/2009/4.0/3.0
Старый 08.05.2008, 18:16   #8  
Volodymyr is offline
Volodymyr
Участник
 
36 / 21 (1) +++
Регистрация: 03.11.2006
Адрес: Киев
To Ivas: можно. Только этого мало, потомучо между этими строками много чего делается.

PHP код:
            buffer Trans::find(trans.recidtrue);
            ...
            
buffer.open false;
            
buffer.update() 
Вот думаю можно ли как то залочить линию, чтобы можно было проверить если линия залочена то берем следующую
что-то вроде
PHP код:
        try
        {
            
ttsbegin;
            
select buffer pessimisticlock where buffer.recId == trans.recId;
            ...
            
buffer.open false;
            
buffer.update()
            
ttscommit;
        }
        catch(
Exception::PessimisticLock
        {
 
            continue;
        } 
Только вот пока не знаю по какому критерию можно определить залочена ли линия, Exception::PessimisticLock - фантазия )

To Alex_KD: так не подходит =(
Старый 08.05.2008, 18:52   #9  
online
Stitch_MS
Участник
Аватар для Stitch_MS
Соотечественники
 
397 / 478 (16) +++++++
Регистрация: 27.02.2006
Адрес: Дания
А ежели так?
X++:
    try
    {
        do
        {
            ttsbegin;
 
            select pessimisticLock firstonly trans
                where trans.open == true;
 
            if (trans.recId != 0)
            {
                // ...
                trans.open = false;
                trans.update()
            }
 
            ttscommit;
        }
        while (trans.recId != 0)
    }
    catch (Exception::Deadlock)
    {
        retry;
    }
    catch (Exception::UpdateConflict)
    {
        retry;
    }
Старый 08.05.2008, 19:36   #10  
Hyper is offline
Hyper
Участник
Соотечественники
 
163 / 29 (1) +++
Регистрация: 09.10.2003
:)
Цитата:
Сообщение от Volodymyr Посмотреть сообщение
Интересно, можно ли как то в селекте выбрать линии, которые точно не проапдейтятся другим батчем?
Вторым батчем пойти задом наперед.
X++:
run()
{
    Trans   trans;
    Trans   buffer;
    boolean reversed;
    ;
    
    try
    {
        select trans
            order by RecId asc
            where trans.open;

        while (trans)
        {
            buffer = Trans::find(trans.recid);
            
            if (!buffer.open)
            {
                if (!reversed)
                {
                    reversed = true;
                    
                    select trans
                        order by RecId desc
                        where trans.open;
                        
                    continue;
                }
                else
                {
                    break;
                }
            }
                
            ttsbegin;
            buffer.selectForUpdate(true);
            buffer.open = false;
            buffer.doUpdate();
            .......
            buffer.update()
            ttscommit;
            
            next trans;
        }
    }
    
    catch (Exception::Deadlock)
    {
        retry;
    }
    
    catch (Exception::UpdateConflict)
    {
        retry;
    }
}
Третий батч просто вылетит.
Старый 08.05.2008, 20:49   #11  
Volodymyr is offline
Volodymyr
Участник
 
36 / 21 (1) +++
Регистрация: 03.11.2006
Адрес: Киев
TO Stich_MS: К сожалению когда один батч выполняет
PHP код:
select pessimisticLock firstonly trans
    where trans
.open == true

То второй батч при выборе этой же линии, ждет пока снимется лок сделаный первым батчем. Т.е. получается вообще плохо.
To Hyper: вот это подход я понимаю , но всетаки запуск больше двух батчей не приведет к ускорению работы.

Пришлось сделать так:
1) Добавить на таблицу поле Blocked
2) Переделать метод так:
PHP код:
run()
{
    
Trans trans;
    
Trans buffer;
    
boolean setBlocked(boolean _blocked)
    {
        if (
_blocked && trans.blocked)
            return 
false;
 
        
ttsbegin;
        
buffer Trans::find(trans.recIdtrue);
        
buffer.blocked true;
        
buffer.update();
        
ttscommit;
        return 
buffer.blocked;
    }
    try
    {
        while 
select trans where trans.open == true && trans.blocked == false
        
{
            if(
setBlocked(true))
            {
                
ttsbegin;
                
buffer Trans::find(trans.recidtrue);
                ...
                
buffer.open false;
                
buffer.update();
                
ttscommit;
                
setBlocked(false);
            }
        }
    }
    catch (
Exception::Error)
    {
        
setBlocked(false);
    }
    catch (
Exception::UpdateConflict)
    {
        
retry;
    }


Всех с Праздником!
 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Невозможно выполнить команду языка определения данных в () iHomer13 DAX: Программирование 8 18.07.2008 10:56
Стандартный импорт данных. Обновление sparur DAX: Функционал 0 24.03.2008 19:07
Распределенная база данных на основе View Владимир Максимов DAX: Программирование 27 04.09.2007 13:21
Введение в Аксапту Роман Кошелев DAX: Прочие вопросы 0 18.12.2001 14:00

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

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

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