24.01.2014, 03:23
|
#38
|
Талантливый разгвоздяй
Регистрация: 14.12.2008
Адрес: Москва
|
ИМХО: - Согласен с Belugin про целостность данных, суть транзакции никто не отменял!
- Best practice, которые привел MikeR не говорят о том, что надо вообще любые обновления данных делать вложенными в while select forupdate транзакциями. Они говорят как можно уменьшить количество обращений к базе данных и извлечь пользу от оптимистической модели. Это надо применять предельно осторожно и осознанно.
- Чтобы было совсем по best practice в пример MikeR необходимо в запрос добавить optimisticlock, чтобы оптимистичная модель применялась независимо от настроек таблицы в которой выполняется обновление данных:
X++: while select optimisticlock ...
- Касательно примера, который привел 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
|
|