11 июля 2015

Решения задачи прореживания котировок для FOREX и банков через MATERIALIZED VIEW REFRESH FAST ON COMMIT

Передо мной была поставлена такая задача:

1) В таблицу ежеминутно добавляются котировки FOREX
2) Строка котировки состоит из таких значений: время (в секундах, относительно точки отсчёта, в примере далее -- смещение относительно 1 января 2014 года), курс, который существовал на момент начала интервала, на момент конца интервала, минимальный достигнутый курс в интервале, максимальный, и объём операций.
Строка котировок -- типична для рынка FOREX и для фондового рынка
3) Необходимо из минутных строк сформировать пятиминутные, 15-минутные, получасовые, и часовые строки.
Алгоритм расчёта: OPEN -- first open, CLOSE -- last close, min -- MIN(), max -- MAX (), объём -- SUM ()
4) Сделать максимально эффективно, удобно, и _надёжно_


На момент постановки задачи мне было предложено три варианта решения:
1. Процедура, перебирающая построчно (отбросил сразу, как низкопроизводительный вариант)
2. MERGE (отбросил, потому что может выполняться UPDATE, а для транзакционных таблиц нужно установить PCTFREE 0, и могут появляться сцепленные и мигрировавшие строки)
3. INSERT ALL (отбросил, потому что громоздко)

В итоге пока я сделал четвёртый вариант, с подходом "одним оператором", как рекомендовал Кайт.
Подход "Одним оператором" не означает, что оператор будет только один. Это означает, что не будет циклов, перебирающих строки по одной.
В итоге операторов получилось 3 (выбор таблицы осуществляется с помощью динамического SQL).

Эти три оператора:
1) Расчёт верного прореживания во временную таблицу
2) Удаление строк, которые есть в фактической таблице, но нет во временной
3) Добавление строк, которые есть во временной таблице, но нет в фактической

Но поразмыслив, сделал пятый вариант -- на MATERIALIZED VIEW REFRESH FAST ON COMMIT.

Вот путь решения

Сама по себе задача прореживания решается таким запросом

select trunc (ASECONDS / 300) * 300 as ASECONDS
     , avg (AOPEN) keep (dense_rank first order by ASECONDS) as AOPEN
     , avg (ACLOSE) keep (dense_rank last order by ASECONDS) as ACLOSE
     -- для FIRST и LAST агрегатная функция может быть любая
     , min (AMIN) as AMIN
     , max (AMAX) as AMAX
     , sum (AVOLUME) as AVOLUME
from V5_RATES_1MIN
group by trunc (ASECONDS / 300) * 300


Здесь прореживается из минутных интервалов до пятиминутных (300 сек)

Здесь и далее в качестве даты используется не поле типа DATE, а число, указывающее смещение в секундах от 1 января 2014. Это везде поле ASECONDS

Для такой трансляции я применяю такие функции

create or replace function DATE2SECONDS (parm date) return number deterministic is
begin return round ((parm - to_date ('01.01.2014', 'DD.MM.YYYY')) * 86400); end;
/
create or replace function SECONDS2DATE (parm number) return date deterministic is
begin return to_date ('01.01.2014', 'DD.MM.YYYY') + parm / 86400; end;
/

Было бы отлично, если бы из этого запроса можно было сделать MATERIALIZED VIEW с REFRESH FAST желательно, с опцией ON COMMIT

К сожалению, это невозможно. Этому препятствуют функции FIRST и LAST

Но решить эту задачу всё таки возможно иным путём.

Для этого запрос придётся переписать в несколько шагов
with
T1 as (select trunc (ASECONDS / 300) * 300 as ASECONDS
            , min (ASECONDS) as ASECONDS_OPEN
            , max (ASECONDS) as ASECONDS_CLOSE
            , min (AMIN) as AMIN
            , max (AMAX) as AMAX
            , sum (AVOLUME) as AVOLUME
       from V5_RATES_1MIN
       group by trunc (ASECONDS / 300) * 300)
select a.ASECONDS
     , b.AOPEN, c.ACLOSE -- из связанных таблиц
     , a.AMIN, a.AMAX
     , a.AVOLUME
from V5_RATES_5MIN_T1 a
   , V5_RATES_1MIN b, V5_RATES_1MIN c -- связанные таблицы
where a.ASECONDS_OPEN = b.ASECONDS and a.ASECONDS_CLOSE = c.ASECONDS


Напрямую из этого запроса тоже создать MATVIEW REFRESH FAST тоже нельзя, но этот запрос можно разбить на 2 части:

1) Верхняя часть, вычисляющая минимальное и максимальное время, из которого мы потом будем брать значения OPEN и CLOSE (на картинке далее эти MATVIEW называются *_PRELIMINARY). Тип MATVIEW -- "с предпосчитанными агрегатами"

2) Собственно, вычисление значений OPEN и CLOSE. Тип MATVIEW -- "join matview"

А вот эти 2 части уже можно превратить в MATERIALIZED VIEW REFRESH FAST

И соединить их каскадно.


Теперь вычисление прореженных данных может выполняться по такому алгоритму (с минуты до часа)





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

Причём на все MAT VIEW можно установить атрибуты REFRESH FAST ON COMMIT (!)

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

Можно быть уверенными в том, что котировки всех периодов актуальны. Запуск процедур пересчёта через планировщик не требуется.

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





DROP TABLE ORIG_RATES_1MIN CASCADE CONSTRAINTS;
 
CREATE TABLE ORIG_RATES_1MIN
(
  SNAPSHOT_TIME  DATE               not null,
  AOPEN          CHAR(128 BYTE)     not null,
  ACLOSE         CHAR(128 BYTE)     not null,
  AMIN           CHAR(128 BYTE)     not null,
  AMAX           CHAR(128 BYTE)     not null,
  AVOLUME        CHAR(128 BYTE)     not null
)
TABLESPACE USERS PCTFREE 0;
 
DROP TABLE ORIG_RATES_60MIN CASCADE CONSTRAINTS;
 
CREATE TABLE ORIG_RATES_60MIN
(
  SNAPSHOT_TIME  DATE               not null,
  AOPEN          CHAR(128 BYTE)     not null,
  ACLOSE         CHAR(128 BYTE)     not null,
  AMIN           CHAR(128 BYTE)     not null,
  AMAX           CHAR(128 BYTE)     not null,
  AVOLUME        CHAR(128 BYTE)     not null
)
TABLESPACE USERS PCTFREE 0;
 
drop materialized view        V5_RATES_60MIN;
drop materialized view log on V5_RATES_60MIN_PRELIMINARY;
drop materialized view        V5_RATES_60MIN_PRELIMINARY;
drop materialized view log on V5_RATES_30MIN;
 
drop materialized view        V5_RATES_30MIN;
drop materialized view log on V5_RATES_30MIN_PRELIMINARY;
drop materialized view        V5_RATES_30MIN_PRELIMINARY;
drop materialized view log on V5_RATES_15MIN;
 
drop materialized view        V5_RATES_15MIN;
drop materialized view log on V5_RATES_15MIN_PRELIMINARY;
drop materialized view        V5_RATES_15MIN_PRELIMINARY;
drop materialized view log on V5_RATES_5MIN;
 
drop materialized view        V5_RATES_5MIN;
drop materialized view log on V5_RATES_5MIN_PRELIMINARY;
drop materialized view        V5_RATES_5MIN_PRELIMINARY;
drop materialized view log on V5_RATES_1MIN;
 
drop table V5_RATES_1MIN;
 
 
create or replace function DATE2SECONDS (parm date) return number deterministic s
begin return round ((parm - to_date ('01.01.2014', 'DD.MM.YYYY')) * 86400); end;
/
 
create or replace function SECONDS2DATE (parm number) return date deterministic s
begin return to_date ('01.01.2014', 'DD.MM.YYYY') + parm / 86400; end;
/

create table V5_RATES_1MIN (
    ASECONDS            number     not null,
    AOPEN               number     not null,
    ACLOSE              number     not null,
    AMIN                number     not null,
    AMAX                number     not null,
    AVOLUME             number     not null)
tablespace USERS pctfree 0;
 
create unique index V5_RATES_1MIN_I1 on V5_RATES_1MIN (ASECONDS);
 
-- 5 minutes *******************************************************************
 
create materialized view log on V5_RATES_1MIN
tablespace USERS pctfree 0
with rowid, commit scn, sequence (ASECONDS, AOPEN, ACLOSE, AMIN, AMAX, AVOLUME)
including new values;
 
create materialized view V5_RATES_5MIN_PRELIMINARY
            tablespace USERS pctfree 0 build immediate
using index tablespace USERS pctfree 0
refresh fast on commit with rowid
as
select trunc (ASECONDS / (5 * 60)) * (5 * 60)   as ASECONDS
     , min   (ASECONDS)          as ASECONDS_OPEN
     , max   (ASECONDS)          as ASECONDS_CLOSE
     , min   (AMIN)              as AMIN
     , max   (AMAX)              as AMAX
     , sum   (AVOLUME)           as AVOLUME
     , count (*)                 as COUNT_DUMMY
     , count (AVOLUME)           as COUNT_DUMMY2
from V5_RATES_1MIN
group by trunc (ASECONDS / (5 * 60)) * (5 * 60);
 
create unique index V5_RATES_5MIN_PRELIMINARY_I1 on V5_RATES_5MIN_PRELIMINARY (ASECONDS);
 
create materialized view log on V5_RATES_5MIN_PRELIMINARY
tablespace USERS pctfree 0
with rowid, commit scn, sequence (ASECONDS, ASECONDS_OPEN, ASECONDS_CLOSE)
including new values;
 
create materialized view V5_RATES_5MIN
            tablespace USERS pctfree 0 build immediate
using index tablespace USERS pctfree 0
refresh fast on commit with rowid as
select a.ASECONDS
     , b.AOPEN, c.ACLOSE                           -- из связанных таблиц
     , a.AMIN, a.AMAX
     , a.AVOLUME
     , a.rowid as R1, b.rowid as R2, c.rowid as R3 -- это необходимо для join matview
from V5_RATES_5MIN_PRELIMINARY a, V5_RATES_1MIN b, V5_RATES_1MIN c
where a.ASECONDS_OPEN = b.ASECONDS and a.ASECONDS_CLOSE = c.ASECONDS;

--create unique index V5_RATES_5MIN_I1 on V5_RATES_5MIN (ASECONDS);
alter table V5_RATES_5MIN add constraint V5_RATES_5MIN_I1 unique (ASECONDS) initially deferred;

-- 15 minutes ******************************************************************
 
create materialized view log on V5_RATES_5MIN
tablespace USERS pctfree 0
with rowid, commit scn, sequence (ASECONDS, AOPEN, ACLOSE, AMIN, AMAX, AVOLUME)
including new values;
 
create materialized view V5_RATES_15MIN_PRELIMINARY
            tablespace USERS pctfree 0 build immediate
using index tablespace USERS pctfree 0
refresh fast on commit with rowid
as
select trunc (ASECONDS / (15 * 60)) * (15 * 60) as ASECONDS
     , min   (ASECONDS)          as ASECONDS_OPEN
     , max   (ASECONDS)          as ASECONDS_CLOSE
     , min   (AMIN)              as AMIN
     , max   (AMAX)              as AMAX
     , sum   (AVOLUME)           as AVOLUME
     , count (*)                 as COUNT_DUMMY
     , count (AVOLUME)           as COUNT_DUMMY2
from V5_RATES_5MIN
group by trunc (ASECONDS / (15 * 60)) * (15 * 60);
 
create unique index V5_RATES_15MIN_PRELIMINARY_I1 on V5_RATES_15MIN_PRELIMINARY (ASECONDS);
 
create materialized view log on V5_RATES_15MIN_PRELIMINARY
tablespace USERS pctfree 0
with rowid, commit scn, sequence (ASECONDS, ASECONDS_OPEN, ASECONDS_CLOSE)
including new values;
 
create materialized view V5_RATES_15MIN
            tablespace USERS pctfree 0 build immediate
using index tablespace USERS pctfree 0
refresh fast on commit with rowid as
select a.ASECONDS
     , b.AOPEN, c.ACLOSE                           -- из связанных таблиц
     , a.AMIN, a.AMAX
     , a.AVOLUME
     , a.rowid as R1, b.rowid as R2, c.rowid as R3 -- это необходимо для join matview
from V5_RATES_15MIN_PRELIMINARY a, V5_RATES_5MIN b, V5_RATES_5MIN c
where a.ASECONDS_OPEN = b.ASECONDS and a.ASECONDS_CLOSE = c.ASECONDS;
 
--create unique index V5_RATES_15MIN_I1 on V5_RATES_15MIN (ASECONDS);
alter table V5_RATES_15MIN add constraint V5_RATES_15MIN_I1 unique (ASECONDS) initially deferred;

-- 30 minutes ******************************************************************
 
create materialized view log on V5_RATES_15MIN
tablespace USERS pctfree 0
with rowid, commit scn, sequence (ASECONDS, AOPEN, ACLOSE, AMIN, AMAX, AVOLUME)
including new values;
 
create materialized view V5_RATES_30MIN_PRELIMINARY
            tablespace USERS pctfree 0 build immediate
using index tablespace USERS pctfree 0
refresh fast on commit with rowid
as
select trunc (ASECONDS / (30 * 60)) * (30 * 60) as ASECONDS
     , min   (ASECONDS)          as ASECONDS_OPEN
     , max   (ASECONDS)          as ASECONDS_CLOSE
     , min   (AMIN)              as AMIN
     , max   (AMAX)              as AMAX
     , sum   (AVOLUME)           as AVOLUME
     , count (*)                 as COUNT_DUMMY
     , count (AVOLUME)           as COUNT_DUMMY2
from V5_RATES_15MIN
group by trunc (ASECONDS / (30 * 60)) * (30 * 60);
 
create unique index V5_RATES_30MIN_PRELIMINARY_I1 on V5_RATES_30MIN_PRELIMINARY (ASECONDS);
 
create materialized view log on V5_RATES_30MIN_PRELIMINARY
tablespace USERS pctfree 0
with rowid, commit scn, sequence (ASECONDS, ASECONDS_OPEN, ASECONDS_CLOSE)
including new values;
 
create materialized view V5_RATES_30MIN
            tablespace USERS pctfree 0 build immediate
using index tablespace USERS pctfree 0
refresh fast on commit with rowid as
select a.ASECONDS
     , b.AOPEN, c.ACLOSE                           -- из связанных таблиц
     , a.AMIN, a.AMAX
     , a.AVOLUME
     , a.rowid as R1, b.rowid as R2, c.rowid as R3 -- это необходимо для join matview
from V5_RATES_30MIN_PRELIMINARY a, V5_RATES_15MIN b, V5_RATES_15MIN c
where a.ASECONDS_OPEN = b.ASECONDS and a.ASECONDS_CLOSE = c.ASECONDS;
 
--create unique index V5_RATES_30MIN_I1 on V5_RATES_30MIN (ASECONDS);
alter table V5_RATES_30MIN add constraint V5_RATES_30MIN_I1 unique (ASECONDS) initially deferred;
 
-- 60 minutes ******************************************************************
 
create materialized view log on V5_RATES_30MIN
tablespace USERS pctfree 0
with rowid, commit scn, sequence (ASECONDS, AOPEN, ACLOSE, AMIN, AMAX, AVOLUME)
including new values;
 
create materialized view V5_RATES_60MIN_PRELIMINARY
            tablespace USERS pctfree 0 build immediate
using index tablespace USERS pctfree 0
refresh fast on commit with rowid
as
select trunc (ASECONDS / (60 * 60)) * (60 * 60) as ASECONDS
     , min   (ASECONDS)          as ASECONDS_OPEN
     , max   (ASECONDS)          as ASECONDS_CLOSE
     , min   (AMIN)              as AMIN
     , max   (AMAX)              as AMAX
     , sum   (AVOLUME)           as AVOLUME
     , count (*)                 as COUNT_DUMMY
     , count (AVOLUME)           as COUNT_DUMMY2
from V5_RATES_30MIN
group by trunc (ASECONDS / (60 * 60)) * (60 * 60);
 
create unique index V5_RATES_60MIN_PRELIMINARY_I1 on V5_RATES_60MIN_PRELIMINARY (ASECONDS);
 
create materialized view log on V5_RATES_60MIN_PRELIMINARY
tablespace USERS pctfree 0
with rowid, commit scn, sequence (ASECONDS, ASECONDS_OPEN, ASECONDS_CLOSE)
including new values;
 
create materialized view V5_RATES_60MIN
            tablespace USERS pctfree 0 build immediate
using index tablespace USERS pctfree 0
refresh fast on commit with rowid as
select a.ASECONDS
     , b.AOPEN, c.ACLOSE                           -- из связанных таблиц
     , a.AMIN, a.AMAX
     , a.AVOLUME
     , a.rowid as R1, b.rowid as R2, c.rowid as R3 -- это необходимо для join matview
from V5_RATES_60MIN_PRELIMINARY a, V5_RATES_30MIN b, V5_RATES_30MIN c
where a.ASECONDS_OPEN = b.ASECONDS and a.ASECONDS_CLOSE = c.ASECONDS;
 
--create unique index V5_RATES_60MIN_I1 on V5_RATES_60MIN (ASECONDS);
alter table V5_RATES_60MIN add constraint V5_RATES_60MIN_I1 unique (ASECONDS) initially deferred;

 

 

 

 

28 мая 2015

О создании Центра компетенции по СУБД в компаниях-интеграторах

Резюме

В статье изложено моё мнение о возможностях создания Центра компетенции по Системам управления Базами данных (далее — Центра) в компанииях-интеграторах (далее — компании).

Предпосылками для создания Центра является потенциальная выгода использования эффекта масштаба и эффекта опыта как конкурентного преимущества компаний, в рамках выбранной многими компаниями стратегии фокусирования на отраслях.

Функционирование Центра приведёт к снижению издержек на текущих проектах. Ожидаю, что через некоторое время (полгода...год) деятельность Центра может стать прибыльной. 

Методы монетизации описаны ниже в разделе «Задачи, которые должны быть решены» и выделены так.

Цель создания Центра компетенции по СУБД

Центр компетенции должен предлагать и реализовывать решения, повышающие эффективность автоматизируемого бизнеса в части обработки данных. Должна быть получена практическая польза, например, упрощение работы конкретных сотрудников, снижение потерь времени и организационных издержек для клиента, обеспечение непрерывности ведения бизнеса.

Предпосылки

Комплексная информационная система работает в следующей архитектуре:
Аппаратное обеспечение –> Операционная система –> База данных –> Приложение.
По моим наблюдениям, клиенты либо не сталкиваются с проблемами с аппаратным обеспечением и ОС, либо такие проблемы решают сами. Эти проблемы редко становятся критическими. И решение таких проблем, в большинстве случаев — сфера ответственности клиента.

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

С уровнем Баз данных ситуация иная.

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

Кроме того, сервер БД — это большой и дорогой продукт, а используется он только в той части, которая нужна бизнес-приложению.

Но такой подход нельзя назвать эффективным с точки зрения ROI (количественная оценка) и фондоотдачи (качественная оценка).

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

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

История создания Центров компетенции

Концепция создания Центров компетенции не нова, ей уже порядка 10 лет. Но в этом предложении описывается принципиально новый тип Центра компетенции, об этом ниже.

А в течение 10 лет Центры создавались так:

Согласно [1], Центры компетенции делятся по своему назначению на:

1) Центры инноваций — продвижение решений конкретных производителей;

2) Отраслевые центры компетенции — проведение работ или предоставление услуг по автоматизации в конкретной отрасли.

Согласно [3] может существовать такое разделение:

1) Накопление передового опыта. Сбор, формализация и распространение образцов лучшего опыта (best practices). Выработка технических рекомендаций.

2) Разработка технологических стандартов. Акцент на технической составляющей — разработке программного обеспечения и выборе компьютерного оборудования.

3) Распределенное обслуживание. Оптимизация использования ресурсов среди различных команд проекта. Центр определяет процессы и стандартизирует архитектуру системы для обеспечения распределенной работы. Обучение по продуктам, технологический бенчмаркинг, управление метаданными, оценка программного обеспечения и пр. Данная модель считается одной из наиболее используемых моделей интеграции процессов в западных компаниях.

4) Централизованное обслуживание. Интеграция процессов и данных на всем предприятии, поддерживает те же процессы, что и другие модели, но в дополнение обычно имеет свой бюджет и методологию возврата затрат. Сопровождает множество проектов. Занимается развитием ресурсов, качеством данных, разрабатывает требования и стандарты к информационным и техническим подсистемам, способствует обмену этими знаниями и повторному их использованию.

Модель будущего центра компетенции

Есть предложение реализовать новую модель, которая не подпадает под указанную выше классификацию, а именно, описанные выше модели — «подтягивающиеся» к уже состоявшимся проектам, я же предлагаю проактивную модель, которая будет толкать проекты вперёд.

Основных целей — две:

1) Собственно проактивная составляющая: мониторинг направления обработки данных в решениях и разработках вендоров Microsoft и Oracle, сбор соответствующих знаний, нахождение способов получить от этих знаний максимальную для клиента пользу, проталкивание новых работ по внедрению таких технологий на проекты;

2) Управление знаниями, включая развитие персонала в виде тренингов и пр. Применение таких знаний и контроль за применением.

Характер такого Центра можно описать как «Инициативный Центр компетенции», «Проактивный Центр компетенции», Толкающий или движущий центр.

Управление знаниями в Центре компетенции [3]

(Здесь я исхожу из того, что вопрос Управления знаниями раскрыт в прессе и понятен читателям и необходимости детализировать его здесь, нет. Эти работы нужно выполнить ровной в той степени, в которой необходимо)

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

На практике знания, создаваемые в ходе выполнения проектов, нередко теряются из-за того, что команда расформировывается, сотрудники переходят к другим задачам или увольняются. Иногда случается, что время и деньги тратятся снова на изобретение «колеса», которое уже давно есть в организации, но об этом давно забыли.

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

Задачи, которые должны быть решены


1) Должен производиться мониторинг продуктов и технологий от Oracle и Microsoft и сопоставление новых возможных выгод с потребностями клиентов (вероятно, в сотрудничестве с Отделом продаж). Способ монетизации — новые продажи лицензий.

2) Должны быть проанализированы проекты по клиентам, которые ещё не находятся на фазе спада в жизненном цикле проекта. Будут предложены решения по повышению эффективности работы приложений — более эффективный код, перенос части бизнес-логики с сервера приложений на сервер БД. Монетизация — продажи работ.

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


4) Полагаю, администраторов баз данных необходимо объединить в одно подразделение. Использовать факт наличия такого подразделения и его высокую квалификацию, подтверждённую сертификатами, которые предстоит получить, как конкурентное преимущество на тендерах — «У нас не будет проблем с производительностью, потому что у нас есть целый департамент…». Снижение издержек, большая эффективность.

5) Должна предоставляться информационная и техническая поддержки по вопросам, связанным с функционирование серверов Баз данных и обработкой данных (программированием, разработкой кода и алгоритмами) — для внутренних и внешних заказчиков. Монетизация—поддержка внешних заказчиков. Поддержку Oracle заменить не удастся, но в поддержке Microsoft, полагаю, можно найти лазейку, когда наша поддержка окажется лучше по соотношению цена/качество, чем у Microsoft, пример — повышение производительности закрытия склада в Dynamics Ax. Microsoft за это возьмётся только за очень большие деньги. Такую методику предстоит разработать.

6) Выпускаемые проекты должны сертифицироваться на предмет того, что функциональность сервера баз данных используется максимально полно при текущих потребностях, производительность его проверена путём независимой оценки Центром (для этого Центр Компетенции должен являться независимым от других подразделений. Это позволит сохранить объективность мнения Центра), и соответствует заявленным требованиям, возможно, с гарантией. Монетизация — включение стоимости таких работ в проекты.

7) Должны выдаваться рекомендации относительно администрирования серверов, планирования резервного копирования, обеспечения отказоустойчивости и непрерывности бизнеса. Монетизация — как новая услуга.

8) Центр должен будет гарантировать достаточность квалификации персонала заказчика (DBA). Новая услуга по обучению и тестированию персонала.

9) Центр должен будет поддерживать постоянный контакт с DBA клиента с целью превентивного мониторинга производительности и возможных затруднений в работе серверов БД. Этот шаг можно монетизировать сразу.

Ожидаемые результаты работы Центра

1) Повышенное качество внедрения Информационных систем, которое Отделам продаж и маркетинга нужно будет представить как конкурентное преимущество;

2) Новые объёмы оплачиваемых работ для практик;

3) На втором этапе, предполагаются проекты по обработке данных или разработке механизмов обработки данных, которые будут выполняться исключительно Центром.

И кто-то сможет выиграть на обслуживании.

Этот документ был отправлен мной в одну из компаний-интеграторов. Они его отклонили

Список использованных источников

08 февраля 2015

Об исправлении расхождений склада и ГК в проектах по Axapta 2009

Насколько мне известно, расхождения склада и ГК имеют место почти на всех проектах по Axapta 2009.

На проектах эта задача решается, но в частных случаях.
И на каждом проекте причина своя.
Если бы причина была бы одна и та-же -- её следовало бы запостить в Микрософт, чтобы они исправили. Но этого не происходит.

В этом посте я расскажу о своей идее, как можно исправлять расхождения.
Во время исправления будет выявлена и истинная причина.
Если она повторится на нескольких проектах -- можно будет запостить в Микрософт.

Ниже на картинке приведена взаимосвязь между таблицами для двух модулей -- контрагенты (на примере поставщиков) и склад.
Стрелки показывают -- что от чего зависит.



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

Иное дело -- склад.
Глядя на рисунок, там есть только один путь -- слева направо. Даже петля, которая содержит складские сопоставления, кольцом не является, потому что путь по петле только в одну сторону.
Иными словами, располагая только таблицей INVENTTRANS, можно воспроизвести всё, что из неё следует -- и постинг, и даже складскую сторону LEDGERTRANS, т.е. совсем всё, кроме пересчётов себестоимости, но их всегда можно пересчитать.

У меня есть своя методика, как можно исправлять ошибки по складу
Пока реализовать не удалось, не было подходящего клиента.

Выгоды, которые могут быть достигнуты:
1) Повышается производительность, за счёт того, что удалятся ненужные строки (отменённые сопоставления, например)
2) Сойдётся склад с ГК (есть только одна причина, по которой временно склад может не сойтись с ГК -- отмена пересчёта себестоимости не тем периодом, который отменяется. Эту причину устранить не удастся)
3) Повышается достоверность складских отчётов


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

Формируем список правил такого плана :
  1. При обработке записи в INVENTTRANS нам надо: создать запись в постинге, заполнить поля -- тип постинга в соответствии с источником проводки, счёт постинга -- в соответствии с источником и настройками, то же самое для корреспондирующей стороны. Проделать эту операцию один или два раза в зависимости от того, включена ли физическая разноска
  2. Создать запись в LEDGERTRANS на основании сумм из INVENTTRANS и счетов из INVENTTRANSPOSTING
(Правила моделируют разноску)

Располагая такими правилами можно построить в памяти (или на диске, рядом) копию таблицы INVENTRRANSPOSTING, после чего сравнить её с оригинальной.

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

Сначала нужно получить список расхождений, не применяя их ("Семь раз отмерь -- один отрежь").
Проанализировать их.
По логике, если мы не ожидали, что база сильно битая, а расхождений получилось много, то надо проверить правила и возможно подкорректировать их.
А если расхождений не много, и мы согласны с каждой строкой исправления -- применить.
Применять исправления можно, только если мы согласны с каждой строкой исправлений.

Таким же образом строится и копия складской стороны LEDGERTRANS и сравнивается с оригинальной.
Применять исправления там сложнее, т.к. может быть затронута и корр. сторона, но, думаю, это, возможно.

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




27 января 2015

Авторский надзор в проектах по Аксапте

Данный документ разработан мной по результатам моей работы в одной из компаний-внедренцев Аксапта в 2013…2014 годах. Я участвовал в нескольких проектах. Я увидел, что наибольшие затруднения у клиентов возникают в моменты закрытия периодов.

Я полагаю, что такие временные затруднения имеют место у всех партнёров, у всех клиентов и на всех учётных системах.
Но в случае Аксапты тому есть 2 причины:

  • операции закрытия периодов — разовые и очень ответственные, предугадать результат их выполнения не представляется возможным, а результат может оказаться неудовлетворительным вследствие ошибок;
  • расхождения в данных.

Поскольку у клиента возникают затруднения  здесь есть потенциал для консалтинга.
Поскольку затруднения бывают, полагаю, на всех системах, я вижу здесь потенциал для формирования конкурентного преимущества Аксапты относительно других систем.
Обе задачи решаемы, и путей решения обоих задач несколько. Я их сгруппировал в понятие «Услуга «Авторский надзор» MBS»

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

Цель
У всех клиентов, или у клиентов, проявивших заинтересованность, обеспечить полностью корректные, непротиворечивые, достоверные данные в Базе данных Аксапты.
Получить непротиворечащие друг другу отчёты.
Прояснить клиентам и аудиторам логику ведения учёта и формирования отчётов, тем самым сделать отчётность простой и понятной.

Ожидаемый результат
За 1-1.5-2 года можно сделать всё так, что все отчёты в Аксапте будут сходиться, и партнёры смогут сосредоточиться на реализации клиентской специфики, а не делать все дружно одно и то же, исправляя одни и те-же ошибки и «наступая на те же грабли».
Будут построены отношения с аудиторами таким образом, что они станут предпочитать систему Axapta системе 1C, что скажется на продажах в некоторой степени.

План работ
Необходимо выполнить следующие работы

  1. Разработка механизмов проверки корректности введённых данных и предоставление таких механизмов партнёрам
  2. Контроль того, что партнёр применяет эти механизмы самостоятельно и следит за корректностью введённых данных в систему. Для этого партнёры должны включить в планы проектов задачу «Контроль введённых данных»
  3. Содействие партнёрам в исправлении ошибочных данных.
  4. Контроль того, что партнёр провёл соответствующее обучение для сотрудников клиента, в случае возникновения ошибок в данных по вине клиента.
  5. Обобщение информации об имевших место ошибках в данных, в случае, если ошибки возникли из-за человеческого фактора — для того, чтобы проактивно сформировать соответствующие программы обучения, если имела место техническая ошибка — для того, чтобы оперативно зарегистрировать её в системе регистрации ошибок MBS и оперативно её исправить.
  6. Формирование «Лучших практик»
  7. Публикация статей, участие в форумах
  8. Взаимодействие с аудиторскими компаниями для разъяснения и демонстрации возможностей MS Dynamics Ax для исполнения требований ФЗ № 307-ФЗ «Об аудиторской деятельности»
  9. Оказание содействия разработчикам в формировании планов разработки и включения в планы адаптированной рос. отчётности.

О совершенствовании базовых отчётов
Иногда базовые (стандартные отчёты) тоже содержат ошибки.
Обычно эти отчёты исправляются на проектах без информирования MBS и без регистрации Bug Report. Исправления делают все партнёры, но их код несколько отличается. В результате имеем зоопарк различных отчётов.
В рамках реализации услуги мы будем принимать от партнёров не только Bug Report, а и предложения по внесении изменений в код и тестовые кейсы. После прохождения Code Review и тестирования такие исправления можно внести в пакеты обновлений.
Наиболее продуктивного партнёра в части поиска ошибок в базовых отчётах следует наградить каким-либо званием, тем самым подтвердить его экспертизу и дать ему возможность использовать это звание как преимущество при своём участии в тендерах.

Этот документ был отправлен в MBS три месяца назад  реакция нулевая. Чтобы мысль не пропала  опубликовал его здесь.

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.