|
|
#1 |
|
Участник
|
Параллельная обработка данных
Всем привет!
Такой вопрос есть батч(пакет)-джоба, которая выполняет апдейт таблици. PHP код:
1) Первый батч выбирает из базы например 20 записей 2) Второй батч выбирает из базы теже 20 записей 3) Первы батч апдейтит первую запись - все ок 4) Второй батч апедйтит первую запись - конфликт апдейта 5) Второй батч зановов выбирает с базы, но уже 19 записей 6) Первый бачт апдейтит вторую линию 7) Второй батч апдейтит свою первую линию - кофликт апдейта .... Получается что второй батч мешает всевремя первому. Можно ли сделать чтобы от двух был выигрышь? Или я не правлиьно понимаю. Спасибо! |
|
|
|
|
#2 |
|
Участник
|
Перед транзакцией делайте trans.reread() и еще раз проверяйте условие селекта
т.е trans.reread(); if(trans.open) { ttsbegin; ... |
|
|
|
|
#3 |
|
Участник
|
Это не решит проблемы.
Ведь всеравно два батча будут работать хуже чем один... В реальности перед апдейтом транзакции идет достаточно большая по времени функциональность, и при апдейти транзакции если возникает конфликт, то откатывается все назад. Наверное два всегда хуже чем один... Интересно, можно ли как то в селекте выбрать линии, которые точно не проапдейтятся другим батчем? |
|
|
|
|
#4 |
|
Участник
|
выбор по четным и нечетным recId
|
|
|
|
|
#5 |
|
Участник
|
=) Смешно... но всетаки
Вобщем задача свелась к тому, что нужно в цикле проверить можнло ли залочить текущую линию , если да, то залочиеть ее , иначе продолжить цикл (т.е. перейти к следующей линии) Как это реализовать пока незнаю |
|
|
|
|
#6 |
|
Участник
|
а если так переписать?
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 |
|
|
|
|
#7 |
|
Участник
|
Может так?
X++: UPDATE_RECORDSET trans SETTING open= false WHERE open = true;
__________________
AxAssist 2012 - Productivity Tool for Dynamics AX 2012/2009/4.0/3.0 |
|
|
|
|
#8 |
|
Участник
|
To Ivas: можно. Только этого мало, потомучо между этими строками много чего делается.
PHP код:
что-то вроде PHP код:
To Alex_KD: так не подходит =( |
|
|
|
|
#9 |
|
Участник
|
А ежели так?
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;
} |
|
|
|
|
#10 |
|
Участник
|
Цитата:
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;
}
} |
|
|
|
|
#11 |
|
Участник
|
TO Stich_MS: К сожалению когда один батч выполняет
PHP код:
То второй батч при выборе этой же линии, ждет пока снимется лок сделаный первым батчем. Т.е. получается вообще плохо. To Hyper: вот это подход я понимаю , но всетаки запуск больше двух батчей не приведет к ускорению работы.Пришлось сделать так: 1) Добавить на таблицу поле Blocked 2) Переделать метод так: PHP код:
Всех с Праздником! |
|
|