08.05.2008, 15:37 | #1 |
Участник
|
Параллельная обработка данных
Всем привет!
Такой вопрос есть батч(пакет)-джоба, которая выполняет апдейт таблици. PHP код:
1) Первый батч выбирает из базы например 20 записей 2) Второй батч выбирает из базы теже 20 записей 3) Первы батч апдейтит первую запись - все ок 4) Второй батч апедйтит первую запись - конфликт апдейта 5) Второй батч зановов выбирает с базы, но уже 19 записей 6) Первый бачт апдейтит вторую линию 7) Второй батч апдейтит свою первую линию - кофликт апдейта .... Получается что второй батч мешает всевремя первому. Можно ли сделать чтобы от двух был выигрышь? Или я не правлиьно понимаю. Спасибо! |
|
08.05.2008, 15:47 | #2 |
Участник
|
Перед транзакцией делайте trans.reread() и еще раз проверяйте условие селекта
т.е trans.reread(); if(trans.open) { ttsbegin; ... |
|
08.05.2008, 16:02 | #3 |
Участник
|
Это не решит проблемы.
Ведь всеравно два батча будут работать хуже чем один... В реальности перед апдейтом транзакции идет достаточно большая по времени функциональность, и при апдейти транзакции если возникает конфликт, то откатывается все назад. Наверное два всегда хуже чем один... Интересно, можно ли как то в селекте выбрать линии, которые точно не проапдейтятся другим батчем? |
|
08.05.2008, 16:20 | #4 |
Участник
|
выбор по четным и нечетным recId
|
|
08.05.2008, 16:47 | #5 |
Участник
|
=) Смешно... но всетаки
Вобщем задача свелась к тому, что нужно в цикле проверить можнло ли залочить текущую линию , если да, то залочиеть ее , иначе продолжить цикл (т.е. перейти к следующей линии) Как это реализовать пока незнаю |
|
08.05.2008, 17:28 | #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 |
|
08.05.2008, 17:37 | #7 |
Участник
|
Может так?
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 |
Участник
|
To Ivas: можно. Только этого мало, потомучо между этими строками много чего делается.
PHP код:
что-то вроде PHP код:
To Alex_KD: так не подходит =( |
|
08.05.2008, 18:52 | #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; } |
|
08.05.2008, 19:36 | #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; } } |
|
08.05.2008, 20:49 | #11 |
Участник
|
TO Stich_MS: К сожалению когда один батч выполняет
PHP код:
То второй батч при выборе этой же линии, ждет пока снимется лок сделаный первым батчем. Т.е. получается вообще плохо. To Hyper: вот это подход я понимаю , но всетаки запуск больше двух батчей не приведет к ускорению работы. Пришлось сделать так: 1) Добавить на таблицу поле Blocked 2) Переделать метод так: PHP код:
Всех с Праздником! |
|