1 мая 2016 г.

Состояние обновления базы

Всем привет. С тех пор, как пошли проекты на 1С: ERP, времени на блог совсем не осталось. Поэтому просто поделюсь своей обработкой мониторинга состояния обновления. Но сначала немного о механизме обновления 1С: ERP.

Начиная с релиза 2.1.2 необходимые для обработки данные регистрируются в плане обмена ОбновлениеИнформационнойБазы. Если верить статье Как разрабатывается 1С:ERP, то такой же механизм будет использоваться в новых Управлении Торговлей и Комплексной Автоматизации. Кстати, там же можно найти и ответ по поводу "странных" комментариев в коде ERP: УТКА / НЕ УТКА :)



Процесс регистрации блокирует базу и может действительно занимать длительное время. По началу даже подумал, что клиент завис на 100%, но через три часа (!!!) процесс обновления перешел к следующей стадии. При малых значениях времени засыпания и завершения сеансов в параметрах ИБ (Конфигуратор - Администрирование - Параметры информационной базы) есть шанс словить закрытие клиента. Поэтому на время регистрации объектов стоит выставить значения побольше.

Размер базы примерно 100 Гб, переход с 2.0.10.199 на 2.1.2.117
Далее, после подготовки, база переключается в многопользовательский режим, обработчики обрабатывают свои данные порциями по пятьсот объектов. Настройки приоритета влияют только на то, будут ли обработчики запускаться по расписанию или один за другим.


К сожалению, типовой функционал не дает возможности оценить примерное оставшееся время и объем данных к обработке. Поэтому решил набросать свой монитор состояния обновления базы. Читает данные раз в минуту, дает прогноз по оставшемуся времени, показывает количество данных к обработке, последние обработанные данные, среднюю и текущую скорость обработки данных. Ссылка в конце страницы, идеи принимаются :)




&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
 
 ПолучитьДанныеРегистрацийНаСервере();
 КоличествоЭлементовНачало = СоставОбмена.Итог("КоличествоЭлементов"); 
 ВремяЗамера = ТекущаяУниверсальнаяДатаВМиллисекундах(); 
 ПоследнееВремяЗамера = ВремяЗамера;
 Элементы.Счетчик.МаксимальноеЗначение = КоличествоЭлементовНачало;
 
КонецПроцедуры

&НаКлиенте
Процедура ПриОткрытии(Отказ)
 
 ПодключитьОбработчикОжидания("ПолучитьДанныеРегистраций", 60, Истина);
 
КонецПроцедуры

&НаКлиенте
Процедура КомандаОбновить(Команда)
 
 ПолучитьДанныеРегистраций();
 
КонецПроцедуры

&НаКлиенте
Процедура ПолучитьДанныеРегистраций()

 ОтключитьОбработчикОжидания("ПолучитьДанныеРегистраций");
 ПолучитьДанныеРегистрацийНаСервере();
 ПодключитьОбработчикОжидания("ПолучитьДанныеРегистраций", 60, Истина);
 
КонецПроцедуры // ПолучитьДанныеРегистраций()

&НаСервере
Процедура ПолучитьДанныеРегистрацийНаСервере()

 Запрос = Новый Запрос;
 СформироватьТекстЗапроса(Запрос);
 Запрос.УстановитьПараметр("СоставОбмена", СоставОбмена.Выгрузить());
 КоличествоЭлементовБыло = СоставОбмена.Итог("КоличествоЭлементов"); 
 СоставОбмена.Загрузить(Запрос.Выполнить().Выгрузить());
 СоставОбмена.Сортировать("ОбъектМетаданных"); 
 КоличествоЭлементов = СоставОбмена.Итог("КоличествоЭлементов"); 
 Дельта = ?(КоличествоЭлементовБыло, КоличествоЭлементовБыло - КоличествоЭлементов, 0);
 ТекущееВремяЗамера = ТекущаяУниверсальнаяДатаВМиллисекундах();
 ДельтаВремя = ?(ВремяЗамера, ТекущееВремяЗамера - ВремяЗамера, 0);
 Счетчик = Счетчик + Дельта;
 ТекущаяСкоростьОбработки = Дельта / (ТекущееВремяЗамера - ПоследнееВремяЗамера) * 1000;
 СкоростьОбработки = ?(ДельтаВремя, Счетчик / ДельтаВремя * 1000, 0);
 Если ДельтаВремя Тогда
  ОставшеесяВремяСекунд = Цел(КоличествоЭлементов / СкоростьОбработки);
  ОсталосьЧасов = Цел(ОставшеесяВремяСекунд / 3600);
  ОстатокСекунд = ОставшеесяВремяСекунд % 3600;
  ОсталосьМинут = Цел(ОстатокСекунд / 60);
  ОсталосьСекунд = ОстатокСекунд % 60;
  ОставшеесяВремя = Формат(ОсталосьЧасов, "ЧГ=0") + ":" + Формат(ОсталосьМинут, "ЧЦ=2; ЧВН=") + ":" + Формат(ОсталосьСекунд, "ЧЦ=2; ЧВН=");
 КонецЕсли;
 ПоследнееВремяЗамера = ТекущееВремяЗамера;
 
КонецПроцедуры // ПолучитьДанныеРегистраций()

&НаСервере
Функция СформироватьТекстЗапроса(Запрос)

 Запрос.Текст = 
 "ВЫБРАТЬ
 | СоставОбмена.ОбъектМетаданных,
 | СоставОбмена.Представление,
 | СоставОбмена.КоличествоЭлементов
 |ПОМЕСТИТЬ СоставОбмена
 |ИЗ
 | &СоставОбмена КАК СоставОбмена
 |;
 |
 |////////////////////////////////////////////////////////////////////////////////
 |" + ПолучитьТекстЗапросаКоличестваЭлементов(Запрос) + "
 |;
 |
 |////////////////////////////////////////////////////////////////////////////////
 |ВЫБРАТЬ
 | ЕСТЬNULL(СоставОбмена.ОбъектМетаданных, НовыйСоставОбмена.ОбъектМетаданных) КАК ОбъектМетаданных,
 | ЕСТЬNULL(СоставОбмена.Представление, НовыйСоставОбмена.Представление) КАК Представление,
 | ЕСТЬNULL(СоставОбмена.КоличествоЭлементов, 0) КАК КоличествоЭлементовБыло,
 | ЕСТЬNULL(НовыйСоставОбмена.КоличествоЭлементов, 0) КАК КоличествоЭлементов
 |ИЗ
 | СоставОбмена КАК СоставОбмена
 |  ПОЛНОЕ СОЕДИНЕНИЕ НовыйСоставОбмена КАК НовыйСоставОбмена
 |  ПО СоставОбмена.ОбъектМетаданных ПОДОБНО НовыйСоставОбмена.ОбъектМетаданных
 |ГДЕ
 | (ЕСТЬNULL(СоставОбмена.КоличествоЭлементов, 0) > 0
 |   ИЛИ ЕСТЬNULL(НовыйСоставОбмена.КоличествоЭлементов, 0) > 0)";

КонецФункции // СформироватьТекстЗапроса()

&НаСервере
Функция ПолучитьТекстЗапросаКоличестваЭлементов(Запрос)

 ЗапросТекст = "";
 ИндексЗапроса = 0;
 СоставОбновления = Метаданные.ПланыОбмена.ОбновлениеИнформационнойБазы.Состав;
 Для Каждого ЭлементСостава Из СоставОбновления Цикл
  ОбъектМетаданных = ЭлементСостава.Метаданные.ПолноеИмя();
  Представление = ЭлементСостава.Метаданные.Представление();
  ИндексСтрока = XMLСтрока(ИндексЗапроса);
  Запрос.УстановитьПараметр("ОбъектМетаданных" + ИндексСтрока, ОбъектМетаданных);
  Запрос.УстановитьПараметр("Представление" + ИндексСтрока, Представление);
  ЗапросТекст = ЗапросТекст + ПолучитьТекстЗапросаКоличества(ОбъектМетаданных, ИндексЗапроса);
  ИндексЗапроса = ИндексЗапроса + 1;
 КонецЦикла; 
 
 Возврат ЗапросТекст;

КонецФункции // ПолучитьТекстЗапросаКоличестваЭлементов()

&НаСервере
Функция ПолучитьТекстЗапросаКоличества(ОбъектМетаданных, ИндексЗапроса)

 Возврат ?(ИндексЗапроса, "
 |
 |ОБЪЕДИНИТЬ ВСЕ
 |", "") + СтрЗаменить(
 "ВЫБРАТЬ
 | &ОбъектМетаданных" + XMLСтрока(ИндексЗапроса) + " КАК ОбъектМетаданных,
 | &Представление" + XMLСтрока(ИндексЗапроса) + " КАК Представление,
 | КОЛИЧЕСТВО(ТаблицаИзменений.Узел) КАК КоличествоЭлементов" + ?(ИндексЗапроса, "", " 
 |ПОМЕСТИТЬ НовыйСоставОбмена") + " 
 |ИЗ
 | #ТаблицаИзменений КАК ТаблицаИзменений
 |ГДЕ
 | ТаблицаИзменений.Узел ССЫЛКА ПланОбмена.ОбновлениеИнформационнойБазы", "#ТаблицаИзменений", ОбъектМетаданных + ".Изменения");

КонецФункции // ПолучитьКоличествоРегистраций()

Обработка "Состояние обновления базы", 10 КБ


2 комментария:

  1. Добрый день. Как форматируете и встраиваете код 1С в блогспот?!

    ОтветитьУдалить
    Ответы
    1. Добрый день. Получаю HTML код с помощью сервиса (например, https://26226.selcdn.ru/paint_1c/) и встраиваю в страницу.

      Удалить