03 декабря 2014

Оборотно-сальдовая ведомость по складу для Axapta 2009

Разработал новую версию Оборотно-сальдовой ведомости по складу (ОСВСк) для Axapta 2009.
Это только финансовая оборотка — строится только по "Куплено" и "Продано"

Эта версия — двухпропроходная (два раза обращается к InventTrans), прошлая была пятипроходная. На прошлую версию совсем не похоже.

Полагаю, на средних по объёму базах (около 20 млн записей в InventTrans) будет работать
достаточно быстро.




Лицензионное соглашение:
Скачать и запускать можно бесплатно для некоммерческого использования

Описание

Ранее проблемы производительности ОСВСк упирались в то, что производительность проседала при правильной подвязке расчёта корректировок.
У меня эта проблема решена таким образом:
1. В InventTrans создаём поле LedgerAccount с типом LedgerAccount. В это поле будет переноситься бухсчёт из InventTransPosting
2. Ставим в планировщик выполнение оператора, который будет заполнять это поле. Это оператор

with T1 as (select * from INVENTTRANS
            where LEDGERACCOUNT = '' and (STATUSRECEIPT = 1 or STATUSISSUE = 1))
merge into T1 a
using INVENTTRANSPOSTING b
on a.DATAAREAID = b.DATAAREAID and a.INVENTTRANSID = b.INVENTTRANSID
and a.VOUCHER = b.VOUCHER and b.INVENTTRANSPOSTINGTYPE = 1
when matched then
update set a.LEDGERACCOUNT = case when b.ACCOUNT <> '' then b.ACCOUNT else 'IsEmpty' end
when not matched by source then update set a.LEDGERACCOUNT = 'NotFound';

Первый раз оператор будет выполняться медленно, потому что надо все строки обновить.
Последующие разы — должен быстро, поскольку обновление инкрементное (обновляет только добавленные строки).
Надо создать индекс по полю LEDGERACCOUNT и, если SQL его не использует — возможно добавить табличный хинт with (index (I_177INDEX1) или применить иные методы оптимизации.

Этот оператор при желании можно запускать каждый раз перед запуском отчёта (если ваши ресурсы это позволяют)

Обратите внимание — оператор может поставить в поле LEDGERACCOUNT и такие значения как 'IsEmpty' (значит запись в постинге найдена, но там счёт пустой) и 'NotFound' (значит постинг не найден). И то и другое означает ошибки в данных, но об этом отдельный разговор.

Для сторно сейчас не учитывается реверсирование — знак проводки определяется по полям STATUSISSUE или STATUSRECEIPT


Установка
1. Скачать файл
2. Установить на SSRS
3. Изменить DataSource на ваш сервер
4. Выполнить единоразово указанный выше оператор при отсутствии другой нагрузки, и сначала на тестовом, чтобы оценить производительность
5. Поставить в планировщик этот оператор




10 октября 2014

Организация экземпляра "Минус день с подхватом логов" для Axapta

В статье я покажу, как можно организовать БД "Минус день" с ежедневным обновлением для баз любого размера.
Метод также пригоден для освежения баз TEST и DEV нужно только отключить копирование слоя USR.

Возможные сценарии использования:
  1. Тестирование новой функциональности. После того, как прошло тестирование на TEST на тестовых данных можно провести тестирование на самых последних вчерашних данных.
  2. Уменьшить количество сторно. Вы создали журнал\заказ с новыми настройками и хотите проверить, как он разнесётся. Разнесите этот же журнал\заказ сначала на "Минус дне", если всё ок разнесёте на рабочей. В особых случаях БД "Минус день" можно настроить как БД "Минус 3 часа", тогда ждать следующего дня не придётся
  3. Снижение ошибок при обучении новых сотрудников прямое следствие предыдущего пункта. Ту операцию, которую нужно сделать на PROD, но опыта пока нет попробуйте сначала на "Минус дне".
  4. Моделирование расчёта себестоимости. Если были сделаны новые настройки (например), и они оказались неподходящими по результатам расчёта, то потом придётся отменять расчёт себестоимости (это затратно по времени и плодит много строк в сопоставлениях), и делать по новой. Проверив сначала на "Минус дне" отмены можно избежать.
  5. Избегать сторнирования при разноске входящих сальдо. На "Минус дне" это можно отлаживать несколько раз без restore БД 



В этой статье я хотел бы поделиться опытом организации среды разработки на проектах по внедрению Axapta.
Метод, изложенный в этой статье, полагаю, может облегчить работу консультантов и пользователей Axapta, сделать её более эффективной, существенно снизить вероятность ошибок и повысить фондоотдачу от IT-инфраструктуры Axapta (не употребляю термин ROI, потому что он требует количественной оценки, а "фондоотдача" может оцениваться качественно).
Идея метода возникла довольно давно, но, к сожалению, ранее я не располагал технической возможностью, чтобы проверить реализуемость метода.

На большинстве проектов среда разработки состоит, как минимум, из таких экземпляров: DEV, TEST, PROD. На одном из проектов мне встретился экземпляр "Минус день", о нём и пойдёт речь.

Экземпляр "Минус день" содержит БД вчерашнего дня. У клиента каждую ночь автоматизированно выполняется backup БД, и автоматизированно же он восстанавливается на экземпляре "Минус день".
Наличие такого экземпляра даёт существенные выгоды как для консультанта, так и для пользователя это даёт оперативность решения проблем.

При качественной постановке процесса внедрения каждая модификация и каждая новая настройка должны быть протестированы на TEST. Но БД TEST обновляется не слишком часто. И чтобы проверить модификацию или новую настройку системы консультанту нужно занести подходящие данные на TEST. Это требует времени.
Экземпляр "Минус день" позволяет легко решить такое затруднение там всегда свежие данные, и не случится никаких проблем, если настройка или модификация отработают неверно БД восстановится уже к следующему дню (или "по запросу").

Но алгоритм обновления (освежения данных) в виде Backup\Restore на БД "Минус день" будет работать только пока база невелика в начале проекта.
Когда размер БД приближается к сотне гигабайт, подход Backup\Restore уже не работает, хотя польза от БД "Минус день" с течение времени увеличивается, за счёт того, что при росте БД увеличивается цена ошибки. А с "Минус день" их можно избежать.

Здесь я опишу, как оперативно обновлять БД любого размера

Я назвал этот метод "Минус день с подхватом логов".

Метод базируется на:
  • Transaction Log Shipping (штатное средство MS SQL)
  • Virtual Machine Snapshots (возможность Microsoft Hyper-V)
Transaction Log Shipping в чистом виде не применим для решения той задачи, которую я назвал в начале статьи потому что метод Log Shipping используется:
  • либо для организации горячего резерва сервера БД (т.е. свежая реплика БД есть, но работать с ней нельзя мы переключимся на реплику только в случае отказа основного сервера),
  • либо как сервер для отчётности мы открываем БД в режиме "Только чтение" и формируем на нём долгоиграющие отчёты, не нагружая производственный сервер.

Разрешить противоречие "Хотим иметь и свежую реплику БД, и открыть её по записи" можно, для этого нужно скомбинировать концепцию TLS с возможностями виртуализации Hyper-V, а именно — использованием чекпоинтов (Checkpoints).

Чекпоинты здесь нам помогают тем, что они используют дифференциальные виртуальные диски. В двух словах это выглядит так:
  1. Создаём виртуальную машину.
  2. Что-то делаем с ней.
  3. Ставим чекпоинт. При этом базовый диск (VHDX) теперь фиксируется, к нему создаётся дифференциальный виртуальный диск (AVHDX). С этого момента все обращения по записи, которые производит виртуальная машина, будут записываться в дифференциальный диск как изменения секторов. Для ОС внутри виртуальной машины это не заметно никак.
  4. Можно создать цепочку чекпоинтов. Для каждого чекпоинта из этой цепочки будет создан свой собственный дифференциальный диск, содержащий только изменённые сектора, по отношению к родительскому диску.

Наличие диффдисков даёт возможность "вернуться назад во времени" отбросив чекпоинт с его диффдиском мы получим такое состояние содержимого диска, которое существовало на момент установки чекпоинта, а изменения после как будто бы и не происходили вовсе.

Архитектура методики организации сервера "Минус день с подхватом логов" кратко состоит в следующем: мы используем штатную методику TLS, но перед открытием БД по записи ставим чекпоинт. Когда нам требуется освежить БД мы отбрасываем последний чекпоинт (с уже открытой базой с результатами нашего тестирования и непригодной для дальнейшего наката логов), докатываем новые пришедшие логи, ставим чекпоинт, и опять по кругу.

Замечу, что операция возврата к чекпоинту в Hyper-V выполняется мгновенно это просто указатель переписать.
Мы исключаем многократный Restore базы данных. Restore выполняется только один раз.

На рисунке изображена архитектура:



Слева производственный сервер. Он может быть либо физическим, либо виртуальным. Какой гипервизор при этом используется не имеет значения. Сервер БД и AOS могут быть как на одном сервере, так и на разных.

Справа — виртуальный сервер "Минус день с подхватом логов". Для упрощения я показал, что на одном виртуальном сервере работает и AOS, и сервер БД.

Именно внутренний AX-MINUSDAY будет виден пользователям.

Если в качестве сервера вы будете использовать физический сервер, то одного внутреннего гипервизора достаточно, внешний просто не нужен. Но многие клиенты используют облачную инфраструктуру, где непроизводственное окружение развёрнуто в арендованной части облака. Внешний гипервизор это и есть инфраструктура облака.

Второй (внешний) гипервизор здесь нужен лишь по той причине, что права администратора для работы с чекпоинтами сотрудникам клиента на гипервизор облака не дадут там работает много чужих серверов. Мы выходим из этой ситуации, создавая внутри свой гипервизор, на который у нас есть все права.

Внешний гипервизор может быть только VMWare. Это связано с тем, что Windows Server 2012 Hyper-V не поддерживает вложенность если мы создали одну виртуальную машину, то вторую в ней уже не развернём. А VMWare вложенность серверов поддерживает.
Но, если есть возможность (подходящее железо), конечно лучше обойтись без внешнего гипервизора.

Внутренний гипервизор может быть только Windows Server 2012, потому что только здесь Hyper-V может управляться из командной строки (устанавливать и удалять чекпоинты). Это потребуется для автоматизации процесса (цикла) освежения БД.


ОБЛАСТЬ ПРИМЕНИМОСТИ

Эта статья написана для версии Axapta 2009. Методика применима и к версии Axapta 2012 с небольшими изменениями: копировать слой USR в виде файла не надо, но вместо одной БД для данных нужно будет реплицировать и вторую БД с кодом приложения.


АЛГОРИТМ

На рисунке приведена циклограмма, слева единоразовые операции, справа отмечен цикл обновления.





ПРЕРЕКВИЗИТЫ

Перед началом работ по настройке сервера вы должны обладать следующими правами:

1. Потребуется знать текущую схему бэкапирования производственной БД как минимум, знать, куда и как часто кладутся бэкапы
2. Знать, генерируются ли на данный момент Transaction Log'и? Знать пути куда они складываются.
3. Потребуется доступ "Только чтение" к пути, куда складываются или будут складываться Transaction Logs.
4. Для сервера "Минус день" требуется созданная виртуальная машина во внешнем гипервизоре или физический сервер.
5. Знать, с какими внешними системами интегрирован PROD и какие пакетные задания на нём исполняются. Это потребуется чтобы отключить интеграцию и пакеты на MINUSDAY





ТЕРМИНЫ

В этой статье используются следующе термины и названия:

Производственный сервер: T2-AX-PROD (его реальное имя) в моём тестовом окружении, вы увидите его на скриншотах, также буду называть его сокращённо PROD. Его БД называется AX-PROD

Сервер "Минус день", который самый внутренний и виден пользователям T2-AX-MINUSDAY, или MINUSDAY, его БД AX-MINUSDAY

Все службы SQL, включая агента, работают под учётной записью Local System и не имеют доступа к сети.


ПРОЦЕДУРА НАСТРОЙКИ

1. Подготовка сервера PROD

Этот сервер необходимо сконфигурировать как источник данных для Transaction Log Shipping (если это ещё не сделано ранее). Необходимо сделать следующие действия:

1.1. Проверить Recovery Model у производственной БД.
Открыть БД AX-PROD \ Properties \ Options \ Recovery model. Установить Full.

1.2. В домене создать пользователя User1, под учётной записью которого будет происходить копирование логов с PROD на MINUSDAY

1.3. Создать папку, в которую сервер PROD будет записывать Transaction Logs для копирования на MINUSDAY — C:\SQLTLSSource.
Расшарить её, и в свойствах шары указать доступ "только чтение" для пользователя User1. В целях корпоративной безопасности давать права на эту шару другим пользователям не следует.
В данном примере, UNC имя такой шары будет \\T2-AX-PROD\SQLTLSSource

1.4. Один раз выполняем бэкап БД и сохраняем его в любом месте.
Убедиться, что мы выполняем полный бэкап и с полной моделью восстановления.



1.5. Настраиваем генерацию TransactionLogs на сервере T2-AX-PROD.
Открыть БД AX-PROD \ Properties \ Transaction Log Shipping

Установить значения полей:
Enable this is a primary database in a log shipping configuration Yes
В группе полей Secondary databases пока ничего не делаем.



Нажать Backup Settings, далее в форме:
Network path... \\T2-AX-PROD\SQLTLSSource
If the backup folder located on the primary server... C:\SQLTLSSource



Нажать Ok.

Будут созданы два задания, которые можно увидеть в узле SQL Server Agent \ Jobs: LSAlert_T2-AX-PROD и LSBackup_AX-PROD

1.6. Проверить генерацию логов.
Для этого вручную запустить несколько раз задание LSAlert_T2-AX-PROD и убедиться, что новые файлы появляются в папке, которую мы задали для логов.

На этом настройка производственного сервера, как источника Transaction logs, завершена.
С этого момента логи будут генерироваться автоматически, в соответствии с тем расписанием, которое было задано. По умолчанию это 15 минут. При настройках по умолчанию логи, старше, чем 72 часа будут удаляться (поэтому за это время сервер "Минус день" должен успеть их забрать)

Это расписание и периодичность можно изменить в любое время.

К настройке производственного сервера ещё придётся вернуться один раз, чтобы подключить сервер MINUSDAY к PROD

2. Подготовка сервера MINUSDAY

2.1. На виртуальной машине внешнего облачного гипервизора или нашем физическом сервере устанавливаем ОС Microsoft Windows Server R2. В этой статье этот экземпляр будет называться MYCLOUD. Включаем Hyper-V.

2.2. На сервере MYCLOUD создаём виртуальную машину T2-AX-MINUSDAY.
Устанавливаем ОС, называем сервер T2-AX-MINUSDAY, вводим в домен.

2.3. На сервере T2-AX-MINUSDAY устанавливаем SQL Server, Axapta 2009 согласно Installation Guide.
Инсталлятор Axapta проходим только до момента, когда Axapta запустилась первый раз и предлагает пройти стартовый чек-лист. Проходить его не нужно.

2.4. Останавливаем AOS T2-AX-MINUSDAY

2.5. Создать папку для временного хранения логов, которые были скопированы с производственного сервера.
В моём примере это C:\SQLTLSTarget
Расшаривать её не нужно.

2.6. Вручную копируем файл бэкапа производственной БД на сервер MINUSDAY в любой путь.
Вручную восстанавливаем бэкап на серевере MINUSDAY с опцией RESTORE WITH NORECOVERY





Сервер AX_MINUSDAY готов к подхвату логов.


3. Подключение сервера MINUSDAY к PROD.

Строго говоря, на данном шаге производится не подключение MINUSDAY к PROD, а сервер MINUSDAY настраивается (на нём создаются задания) средствами консоли сервера PROD.
В результате тех операций, которые описаны ниже, никаких изменений на PROD не произойдёт, изменения будут внесены на MINUSDAY, но Майкрософт почему-то сделал инициацию таких изменений с исходного сервера, хотя на мой взгляд, эти операции было бы логичнее делать с целевого.

3.1. Открыть БД AX-PROD \ Properties \ Transaction Log Shipping (то-же самое окно, что и в пункте 1.5)
В группе полей Secondary databases нажать Add...
Далее задаются параметры, по которым исходный сервер создаст задания на целевом для подхвата и наката логов.
Нажать Connect, подключиться к серверу T2-AX-MINUSDAY
Указать БД AX-MINUSDAY

На первой вкладке выбрать третью опцию "No, the secondary database is initialized" (мы сделали это на шаге 2.6)



На второй вкладке указать путь на сервере MINUSDAY для временного хранения скопированных логов.
Несмотря на то, что сейчас мы подключены к PROD, путь указывается для MINUSDAY


На третьей вкладке значения полей оставляем по умолчанию не восстанавливать и не открывать БД.



Это позволяет базе находиться в горячем резерве быть готовой к приёму новых логов с PROD, сразу же их накатывать т.е. данные в БД MINUSDAY будут попадать c PROD с отставанием всего лишь до 45 минут (15 + 15 + 15) при автоматическом выполнении заданий репликации или до 15 минут, если для автоматизирования будет применяться скрипт
Открывать базу "по записи" для AOS мы будем иным путём.

При нажатии ОК на сервере MINUSDAY будут созданы три задания: для копирования свежих логов на MINUSDAY, для их наката, и для информирования о прогрессе.

Конфигурирование сервера PROD завершено.

4. Настройка безопасности на сервере MINUSDAY
По умолчанию SQL Agent работают под учётной записью Local System, что не даёт доступа к сети и не позволяет серверу MINUSDAY забрать свежие логи с сервера PROD.

Поэтому для копирования логов нужно сделать настройки безопасности на сервере MINUSDAY. Менять учётку SQL Agent мы не будем, а воспользуемся логином User1, который создали на шаге 1.2.

На сервере MINUSDAY:

4.1. В узле . \ Security \ Credentials создаём новое полномочие (Credential)
Заполняем поля, как указано на рисунке



4.2. В узле . \ SQL Server Agent \ Proxies \ Operating System (CmdExec) создаём новый прокси
Заполняем поля, как указано на рисунке



4.3. Изменяем пользователя, под которым будет происходить копирование логов с PROD на MINUSDAY.
Для этого открыть узел  . \ SQL Server Agent \ Jobs \ LSCopy_T2-AX-PROD_AX-PROD, открыть свойства задания, перейти на вторую закладку Steps, для единственного шага нажать Edit, в поле Run As указать ProxyUser1



4.4. Пробуем выполнить вручную задание LSCopy-T2-AX-PROD_AX-PROD
Если все шаги были сделаны верно, то в целевой папке должны появиться файлы логов

4.5. Пробуем выполнить вручную задание LSRestore_T2-AX-PROD_AX-PROD.
При этом логи должны накатиться на БД и задание должно завершиться без ошибок.

Но БД пока не открыта и не готова к открытию, потому что не были отменены изменения, сделанные транзакциями, которые либо не завершились к моменту снятия лога, либо потом были отменены на сервере PROD.

Конфигурирование обоих серверов завершено. Сервер MINUSDAY подхватывает логи, накатывает их и теперь находится в горячем резерве.

4.6. Перейти к шагу 5.5. В дальнейшем выполнять цикл, описанный в следующем разделе

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


5. Цикл освежения БД MINUSDAY и открытия для пользователей

Синим цветом показаны операции над гипервизором MYCLOUD

5.1. На сервере MYCLOUD выполнить Revert to checkpoint "$$BEFORE_OPEN_AXDB" через контекстное меню к виртуальной машине.
Предыдущие чекпоинты здесь выполняют защитную функцию к ним можно было бы вернуться при необходимости. Они не имеют отношения к алгоритму
5.2. Удалить чекпоинт "$$BEFORE_OPEN_AXDB"
Удаление чекпоинта доступно через контекстное меню к чекпоиту, а не к виртуальной машине

5.3. Скопировать логи выполнить задание LSCopy-T2-AX-PROD_AX-PROD

5.4. Накатить логи выполнить задание LSRestore_T2-AX-PROD_AX-PROD

5.5. Поставить чекпоинт "$$BEFORE_OPEN_AXDB" на сервере MYCLOUD

Здесь создаётся новый дифференциальный диск. Дальнейшие действия, при которых мы будем открывать БД, станут препятствовать дальнейшему накату свежих логов, поэтому мы делаем такие изменения на диффдиске, который потом сможем удалить.

5.6. Выполнить на сервере MINUSDAY в MS SQL Server Management Studio следующие команды

RESTORE DATABASE [AX-MINUSDAY] WITH RECOVERY
Gdelete from [AX-MINUSDAY].dbo.BATCH
-- и иные команды, которые требуются для отключения MINUSDAY
-- от интегрированных с сервером PROD внешних систем

-- это те команды, которые обычно делает администратор,
-- вручную поднимая backup на TEST или DEV

5.7. Скопировать слой USR с PROD на MINUSDAY

5.8. Стартовать AOS, сообщить пользователям о готовности Аксапты

5.9. Ждать необходимости обновления сервера MINUSDAY, потом вернуться к шагу 5.1



ВЫВОДЫ

Освежение БД MINUSDAY и любые другие операции на сервере MINUSDAY никак не будут затрагивать производственный сервер.

На сервере MINUSDAY можно тестировать любую функциональность.

Задержка переноса транзакций будет составлять до 15 минут при автоматизации с помощью скрипта. Время освежения сервера MINUSDAY будет определяться временем, необходимым для копирования и наката логов. Если этот цикл делать, по крайней мере 1 раз в день то логов за 1 день будет накапливаться не слишком много, и этот цикл будет выполняться относительно быстро, до 15 минут. При этом объём исходной базы не будет оказывать влияния на длительность цикла. Длительность цикла будет определяться только количеством сделанных изменений на сервере PROD.


16 сентября 2014

Проверка и исправление INVENTSUM в Axapta 2009 (международная версия без пакетов обновлений). V. 2

Данная информация представлена исключительно в ознакомительных целях.

Действия, описанные в этом посте, нельзя выполнять в производственном окружении.

Статья относится к международной версии Microsoft Axapta 2009 5.0.593.0, без российской локализации.

В Аксапте уже существует метод InventSumRecalcItem. Данная статья является не заменой, а дополнением к этому методу.

Причина создания этой статьи в том, что проблемы, связанные с корректностью данных склада встречаются не редко и исправление таких ошибок даётся нелегко. В статье описываются действия по исправлению одной из возможных причин.

Наличие ошибок в данных (битых данных, или ненужных данных), может приводить к трудноуловимым ошибкам в функционировании и может оказывать негативное влияние на надёжность системы. Искать и исправлять такие ошибки — нужно. По моему личному мнению, это лучше делать превентивно.

INVENTSUM — первая таблица, которую стоит проверить. Строки с некорректными количествами будут приводить к ошибкам в отчётах, т.к. многие отчёты для расчета количеств «на дату» берут последние количества из INVENTSUM и отнимают проводки до указанной даты.

Моя методика основывается на аксиоме, что информация в INVENTSUM полностью зависит от складских проводок и ни от чего больше.

Т.е. мы можем взять складские проводки, пересчитать их, получить в памяти копию верной рассчитанной INVENTSUM. После этого сравним её с физической таблицей и внесём необходимые правки в физическую таблицу — добавим нужные строки, поправим количества и стоимости, ненужные строки удалим.

Я так и сделал. Вот скрипт Это версия 8.

В скрипте есть одно ограничение:

Для существующих строк не проверяются и не изменяются поля LastUpdDateExpected и LastUpdDatePhysical. Для созданных в ходе проверки строк в них проставляется текущая дата.

Реализовать проверку этих полей, в принципе, возможно, но такой расчёт будет относительно сложным (в противовес простой функции sum(), которая применена для расчёта количеств). Я могу сделать это по запросу. Для этого пишите по почте.

Проверка и исправление выполняются в 2 фазы:

1. Пересчёт полей, которые зависят от INVENTTRANS. Это: POSTEDQTY, RECEIVED, REGISTERED, ARRIVED, ORDERED, QUOTATIONRECEIPT, DEDUCTED, PICKED, RESERVPHYSICAL, RESERVORDERED, ONORDER, QUOTATIONISSUE, POSTEDVALUE, PHYSICALVALUE

2. Пересчёт полей, которые зависят от полей первой группы, это: AVAILORDERED, AVAILPHYSICAL, PHYSICALINVENT, CLOSEDQTY, CLOSED

Исправления выполняется оператором MERGE. Этот оператор хорош тем, что в одной команде можно сделать и INSERT и UPDATE и DELETE — синхронизировать физическую таблицу INVENTSUM с рассчитанной в памяти таблицей INVENTSUM одной командой.

Оператор содержит фразу OUTPUT, которая даёт подробный лог того, что было сделано.

Перед тем как применять изменения (COMMIT) на тестовой базе, надо просмотреть и проанализировать лог. И применять изменения есть смысл лишь в том случае, если вы согласны с каждой строкой лога. Не бывает таких скриптов, чтобы год хранить в БД ошибки, потом запустить скрипт, и база стала конфеткой.

Все операторы надо выполнять в режиме NO AUTOCOMMIT. Так есть возможность получить лог для анализа, и сказать серверу ROLLBACK — т.е. получить лог оператора НЕ применяя изменения оператора — откатив транзакцию.

Оператор первой фазы большой, но большая часть его относится к форматированию лога.

Если кто-то решить применить мой метод у себя — я очень рекомендую разобраться с тем, как работают операторы.

А именно, в первой фазе в представление T1 собираются рассчитанные значения полей первой группы. Но эти значения для каждой строки INVENTSUM пока расположены «в столбик», а не в строку.

Представление T2 производит транспонирование «столбец в строку».

Представление T3 удаляет строки, относящиеся к услугам и добавляет поле NEW_RECID, которое нам понадобится, если дальше оператору MERGE придётся добавлять строки в INVENTSUM. Алгоритм расчёта RecID такой: определяется минимальный RECID, который существует в таблице INVENTSUM, и для добавляемых строк он отматывается вниз. Аксапта добавляет «вверх», а мы будем «вниз», поэтому мы никогда не пересечёмся.


Дальше идёт тело оператора MERGE. Вначале указываются две таблицы — в качестве целевой использовать физическую таблицу INVENTSUM, в качестве исходной — полученное нами ранее представление T3 (представление T3 по сути представляет собой полностью посчитанную «в уме» INVENTSUM, основываясь только на складских проводках).

Напомню, что первичным ключом в INVENTSUM являются поля DATAAREAID, ITEMID, INVENTDIMID. По этим полям две таблицы и соединяются.

Потом идёт указание о том, как поступать, если строки, совпадающие по ключу:

А) найдены, и значения полей первой группы в чём-то не совпадают. Тогда — обновить в целевой таблице.

Б) есть строка в физической таблице, для которой нет пары в рассчитанной таблице. Удалить.

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

А после фразы OUTPUT идёт форматирование вывода лога

Оператор второй фазы похож на первый, за исключением того, что там уже нет команд вставки новых строк и удаления ненужных — это всё было сделано на первой фазе, осталось только проверить поля, которые зависят от полей первой фазы, а не от INVENTTRANS.

В оба лога слева выводятся три ключевых поля.

Справа в логах идут поля INVENTSUM. Поля идут парами, сначала прежнее значение, потом новое.

Неизменённые значения не выводятся. Благодаря это в логе видно, какие именно поля пересчитали операторы.

Это была теория, а теперь практика.

Я тестировал на демобазе от Аксапты 2009.

Перед запуском я удалил одну строку из INVENTSUM, и в одной изменил количество.
В результате запуска удалённая строка восстанавливается, изменённая — исправляется.
И удаляется — 121 строка. Это оправданно, потому что такой комбинации DATAAREAID + ITEMID + INVENTDIMID в проводках действительно нет.

Во второй фазе обновляется 1 строка. Это та строка, которую я добавил на первой фазе. При добавлении поля второй группы были пустыми, и сейчас мы их пересчитали.

Если у кого-то возникнет реальная необходимость поправить такие ошибки в производственном окружении — обращайтесь ко мне по почте.

Что касается комментария Anonymous’а, то он наверно имел ввиду не ACID (концепцию), а уровни изоляции транзакций (Transaction Isolation Level), это варианты реализации ACID'а.

Это верное замечание. Но мне неизвестно, использует ли Axapta dirty reads, да и обсуждение TIL выходит за рамки данной статьи, поэтому я решил поступить по-простому — запускайте на тестовой и в однопользовательском режиме (чтобы пользователи в Управлении запасами не ютились).

Благодарности за комментарии пользователям Logger, raz и Anonymous