Простой механизм версионирования для нетиповых конфигураций, или зачем нужны утки и медведи

16.08.15

База данных - Журнал регистрации

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

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

Тем не менее, вопросы пользователей, кто изменил "мой" документ (справочник), а главное ЧТО изменил, остаются актуальными.

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

Суть в следующем.

В процедуре общего модуля по подписке на событие "ПередЗаписью" документа или справочника выполняем поиск различий по значениям совпадающих по наименованиям реквизитов метаданных объекта и ссылки (аналогичным образом выполняется и сравнение табличных частей).

Процедура ПередЗаписьюКонтрольИзмененияРеквизитовДокументов(Источник, Отказ) Экспорт

    Если НЕ Отказ И НЕ Источник.ЭтоНовый() Тогда
        ТЗРазличий = Новый ТаблицаЗначений;
        ТЗРазличий.Колонки.Добавить("ИмяРеквизита");
        ТЗРазличий.Колонки.Добавить("До");
        ТЗРазличий.Колонки.Добавить("После");
        МетаданныеДок = Источник.Метаданные();
        Для Каждого Реквизит Из МетаданныеДок.Реквизиты Цикл
            Если Источник[Реквизит.Имя] <> Источник.Ссылка[Реквизит.Имя] Тогда
                СтрокаТЗ = ТЗРазличий.Добавить();
                СтрокаТЗ.ИмяРеквизита = Реквизит.Имя;
                СтрокаТЗ.До = Строка(Источник[Реквизит.Имя]);
                СтрокаТЗ.После = Строка(Источник.Ссылка[Реквизит.Имя]);
            КонецЕсли;
        КонецЦикла;

...

КонецПроцедуры

Как видно из кода, значения реквизитов Источника, это то, что было ДО изменения, значения реквизитов Источник.Ссылка - это то, что БУДЕТ ПОСЛЕ записи изменения в случае, если объект таки будет записан.

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

СтруктураРазличий = Новый Структура
СтруктураРазличий.Вставить("РазличияРеквизитов", ТЧРазличий)

Структуру помещаем в системное строковое представление при помощи ЗначениеВСтрокуВнутр.

СтруктураВнутр = ?(БылиИзменения, ЗначениеВСтрокуВнутр(СтруктураРазличий);

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

ЗаписьЖурналаРегистрации("Изменение реквизитов документа", УровеньЖурналаРегистрации.Информация, Источник.Метаданные(), Источник.Ссылка, СтруктураВнутр);

В дальнейшем при необходимости это представление извлекается,

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

вытаскивается из колонки "Комментарий", преобразовывается обратно в структуру через ЗначениеИзСтрокиВнутр

СтруктураИзВнутр = ЗначениеИзСтрокиВнутр(СтруктураВнутр);

и обратной обработкой развертывается в удобочитаемом виде.

Ну а дальше сложность анализа, как справедливо заметили коллеги к публикации с "уткой", может нарастать, как минимум должно быть нечеткое сравнение табличных частей, потому что уже выявлен недостаток вышеописанного метода: при добавлении строки в документ механизм фиксирует только изменение суммы документа, ведь первые N строк табличных частей до записи совпадают...

И последнее, к вопросу о скорости работы механизма. Видимого замедления записи или проведения объекта не замечено. Восстановление последовательности партионного учета при включенном механизме также прошло без замеченных тормозов. Механизм внедрен и работает на нетиповой УТ 10.3.

P.S. Закономерный вопрос: "Причем здесь утки?!"
Отвечаю. Если интересует полный код анализа различий по значениям совпадающих по наименованию реквизитов объектов, помещение в структуру и развертывание обратно из структуры с выводом в удобочитаемый вид, прошу сюда, в публикацию с "уткой":

//infostart.ru/public/388917/

P.P.S. И второй закономерный вопрос: "Ну хорошо, а причем здесь медведи?!"
А это уже вариант, как может быть реализовано для конечного использования. В ту самую простую обработку, которая показывает изменения документа, можно добавить вывод вида события "Изменения реквизитов документа (справочника)" и по двойному щелчку развертывать расшифровку этих изменений. За обработкой прошу сюда, в публикацию с "медведями":

//infostart.ru/public/372472/

журнал регистрации изменения документа анализ изменений запись изменений

См. также

Журнал регистрации Мониторинг Системный администратор Программист Бизнес-аналитик Руководитель проекта Платформа 1С v8.3 Платные (руб)

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

9000 руб.

28.08.2019    34066    22    21    

75

Журнал регистрации Системный администратор Платформа 1С v8.3 Конфигурации 1cv8 Платные (руб)

Конфигурация LogiCH эффективно решает проблему хранения и анализа записей журналов регистрации. Разработка использует столбцовую СУБД ClickHouse, одну из самых быстрых Big Data OLAP СУБД. Любой анализ журнала можно выполнить в одном отчете, в котором доступны все возможности СКД с учетом ограничений RLS. Количество подключаемых баз не ограничено и не влияет на скорость построения анализа.

5000 руб.

28.11.2018    20824    17    6    

42

Журнал регистрации Программист Россия Бесплатно (free)

В материале рассматривается сравнение двух инструментов для работы с журналом регистрации 1С: утилиты ibcmd и платформы Vector. Описаны их функциональные возможности, тестирование производительности и практическое применение для преобразования логов в формат JSON.

20.11.2024    1037    user1913000    11    

18

Журнал регистрации Тестирование QA Программист Бесплатно (free)

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

21.10.2024    2986    leemuar    8    

22

Инструменты администратора БД Журнал регистрации Системный администратор Платформа 1С v8.3 1С:Управление торговлей 11 Абонемент ($m)

Внешняя обработка для регламентного сокращения журнала регистрации для конфигураций на базе БСП и платформы 8.3.20+

1 стартмани

29.12.2023    2191    31    dima_gsv    3    

13

Журнал регистрации Мониторинг Системный администратор Программист Абонемент ($m)

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

1 стартмани

19.11.2023    1478    5    AlexSTAL    0    

8

Мониторинг Журнал регистрации Технологический журнал Системный администратор Программист Абонемент ($m)

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

1 стартмани

13.11.2023    4811    9    AlexSTAL    0    

47

Журнал регистрации Инструменты администратора БД Мониторинг Мессенджеры и боты Системный администратор Программист Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Управление холдингом 1С:Комплексная автоматизация 2.х Абонемент ($m)

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

3 стартмани

26.09.2023    2885    19    doom2good    16    

14
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. Идальго 235 16.08.15 21:34 Сейчас в теме
Мне кажется, что правильнее говорить не о версионировании, а о записи в ЖР информации об измененных значениях реквизитов.
2. cargobird 308 16.08.15 21:45 Сейчас в теме
(1) Идальго, да, согласен с вами, версионированием это можно назвать с очень большой натяжкой, нулевая точка отсчета для последующей возможной его реализации.
3. cargobird 308 16.08.15 22:07 Сейчас в теме
Еще один возможный минус такой записи изменений. Поскольку порядок выполнения однотипных подписок на событие не определен, вполне возможно, что после записи в журнал регистрации изменения объекта, следующая подписка на событие ПередЗаписью вызовет Отказ и объект не запишется. А в журнал регистрации уже попала запись об изменении объекта. То, что это "ложное срабатывание", можно будет определить только наличием после события об изменении реквизитов объекта события об отмене транзакции...
4. maljaev 789 17.08.15 10:38 Сейчас в теме
В моем варианте версионирования:

Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
	Если (Не Отказ) И (Не ОбменДанными.Загрузка) Тогда
		ВерсионныйКонтроль.ЗапомнитьМодифицированность(ЭтотОбъект);
	КонецЕсли;
КонецПроцедуры

Процедура ПриЗаписи(Отказ)
	Если (Не Отказ) И (Не ОбменДанными.Загрузка) Тогда
		ВерсионныйКонтроль.СоздатьВерсию(ЭтотОбъект);
	КонецЕсли;
КонецПроцедуры
Показать


Запоминается состояние документа в событии "ПередЗаписью", потом в событии "ПриЗаписи" (если не было отказов) сравниваются реквизиты и ТЧ целиком. Создается запись в специальном регистре сведений, туда записывается сам факт действия и все измененные реквизиты и ТЧ, упакованные в один пакет с максимальным сжатием. Потом можно сформировать как глобальный отчет по изменениям, так и по конкретному документу посмотреть/сравнить/откатить.
Прикрепленные файлы:
cargobird; +1 Ответить
6. cargobird 308 17.08.15 11:02 Сейчас в теме
(4) maljaev, спасибо, интересно посмотреть другие варианты.
22. cargobird 308 30.11.15 08:35 Сейчас в теме
(4) maljaev, внедрил доп.контроль при записи, как у вас.
Обнаружил такую штуку.
Если отказ происходит в обработчике проведения (например, не заполнено количество), документ не записывается, но запись об изменении реквизитов все равно попадает в журнал регистрации (у вас - в механизм версионирования).
Делать дополнительную подписку на событие ПриПроведении тоже смысла нет, т.к. порядок подписок не определен.
Так что стопроцентного доп.контроля для документов, видимо, не сделать.
А для справочников годится.
5. kapustinag 17.08.15 10:52 Сейчас в теме
(0) Сомнительное решение, по-моему. Журнал регистрации распухает очень быстрыми темпами в любой активно использующейся базе. А тут еще в него будут записываться довольно объемные записи. Причем, если такой механизм прикручен ко многим объектам, и их активно изменяют - таких записей будет много. В результате штатными средствами с Ж.Р. будет еще хуже работать.
Может быть, если Ж.Р переделан на хранение во внешней SQL-базе - есть публикация на Инфостарте об этом - будет нормально работать.
7. cargobird 308 17.08.15 11:06 Сейчас в теме
(5) kapustinag, регистрация изменений установлена только на критичные объекты - на несколько ключевых справочников и на все товаросодержащие документы, поэтому пока существенного увеличения ЖР не ожидаем. За наводку на SQL-ный журнал спасибо, мысль хорошая, подумаю.
8. karapuzzzz 63 18.08.15 11:49 Сейчас в теме
Как видно из кода, значения реквизитов Источника, это то, что было ДО изменения, значения реквизитов Источник.Ссылка - это то, что БУДЕТ ПОСЛЕ записи изменения в случае, если объект таки будет записан.

Скорее наоборот. Значение реквизитов Источника это то, что будет после принятия изменений. По ссылке мы обращаемся к записям БД, которые как раз и есть значениями до изменения
10. cargobird 308 18.08.15 15:52 Сейчас в теме
(8) karapuzzzz, спасибо, посмотрю, может и правда перемудрил.
9. karapuzzzz 63 18.08.15 11:53 Сейчас в теме
Вместо журнала используйте регистр сведений, который можно периодически чистить. Отчет по записям регистра будет строиться несоизмеримо быстрее, чем анализировать записи журнала регистрации. Тем более, что подчищать регистр сведений опять таки проще.
11. cargobird 308 18.08.15 15:55 Сейчас в теме
(9) karapuzzzz, ставилась цель без особых механизмов сделать простой инструмент для того, чтобы пользователь мог просматривать изменения документа. Поэтому решили по максимуму использовать штатные средства. Как я уже написал в (5), изменения регистрируются у нескольких справочников и документов, поэтому распухание ЖР скорее всего не грозит.
15. karapuzzzz 63 19.08.15 13:36 Сейчас в теме
(11) Если отбросить проблему распухания журнала регистрации, то остается еще 3:
1. Формирование отчета. Можно просмотреть информацию по документу из ЖР, но сформировать отчет можно быстрее. Даже не так. НАМНОГО БЫСТРЕЕ. Отчет предоставить больше данных. Это и отбор по периоду документа (ЖР такого не даст), и удобочитаемая форма, и представление ссылок как ссылок с возможностью открыть элемент справочника (например, если наименование у двух элементов одинаковое).
2. Разделение доступа. Человек, анализирующий записи может не иметь доступа на чтение ЖР и наоборот - человек, имеющий доступ к ЖР не должен иметь доступа к протоколу изменений (там же конкретные данные документов)
3. Очистка данных. Если использовать ЖР, то вместе с чисткой протокола изменений будет очищен и журнал. И наоборот.
16. cargobird 308 19.08.15 14:18 Сейчас в теме
(15) karapuzzzz, у нас была задача максимальной простоты реализации и максимального удобства для пользователя с минимумом выводимой информации.
Поэтому
1. Пользуемся вариантом обработки Кто сидел на моем стуле и сломал его? (анализ изменений документа по журналу регистрации). При выборе документа автоматически ставится период с даты документа по текущую дату, в общем случае этого достаточно, период при желании можно изменить.
2. В журнал регистрации никто не смотрит, т.к. большинство не умеют пользоваться отборами, работы хватает, не до этого и т.д.
3. Сейчас мы наоборот, на этапе накопления информации, вопрос пока не стоит.
В нашу специфику описанный метод вписывается вполне, осталось только сделать нормальный анализ таблиц.
17. karapuzzzz 63 19.08.15 15:16 Сейчас в теме
(16) специфика журнала регистрации предполагает выборку всех данных, а потом ее анализ. Отбор можно установить только на конкретный документ, на пользователя, на период записей в журнале. Это и все, если не считать еще несколько отборов не нужных пользователям. Остальные отборы только на уже готовую выборку. А это время. Это очень большая нагрузка на систему.
Вы сейчас идете по принципу "система маленькая, нам хватает, развиваться не будем". Придет время рвать волосы и думать - чего раньше не сделали по уму. Я пытаюсь дать Вам понять, что реализация версионирования (протоколирования и т.п.) с использованием журнала регистрации это очень плохая идея. Многие настраивают перечень действий, вносимых в журнал регистрации, чтобы данных было минимум. Время от времени выгружают журнал и архивируют, оставляя только некий последний период. Все механизмы в системе стараются для ведения своего лога использовать свои таблицы, а не общую песочницу.
Если Вы уже добавили подписку на событие и процедуру в одном из общих модулей, что мешает добавить регистр сведений? Подумайте о своих коллегах, которым после Вас поддерживать продукт и анализировать, почему база пухнет. Простой анализ дает понять, что ссылка занимает меньше места, чем представление ссылки, а каждая запись журнала регистрации помимо осмысленных данных хранит еще кучу системной информации о клиенте, подключении и т.п. Строить правильную систему надо сначала, когда база это позволяет.
cargobird; +1 Ответить
18. cargobird 308 19.08.15 19:26 Сейчас в теме
(17) karapuzzzz, я с вами ни в коей мере не спорю, коллега, а только обрисовываю ситуацию какая у нас сейчас.
Да, согласен, что в скором времени надо реализовывать более быстрый и оптимальный механизм.
Если резюмировать ваши комментарии, и комментарии коллеги в (4) и (13) надо реализовать примерно следующее:
1. В обработчике ПередЗаписью запомнить разницу между объектом и ссылкой, причем просматривать только необходимые реквизиты.
2. В обработчике ПриЗаписи, если не Отказ, окончательно записать изменения в свой созданный регистр сведений, желательно в реквизит типа ХранилищеЗначения чтобы иметь возможность упаковки с максимальной степенью сжатия:
Хранилище = Новый ХранилищеЗначения(Знач, Новый СжатиеДанных(9));

3. Затем обработкой/отчетом извлекать полученные данные, конвертируя их в удобочитаемый вид.
Так что есть над чем поработать, и спасибо всем за ценную информацию, это пригодится не только мне.
19. V.Nikonov 120 20.08.15 11:54 Сейчас в теме
(18) Есть ещё несколько соображений по поводу протоколирования:
1) Далеко не всегда известен объект анализа! Например, часто требуется найти все Документы в которых изменено количество некоторого Товара... Соответственно, изменяется Табличная Часть документа, реквизит Количество, а поиск удобнее организовать по ссылке Номенклатуры. При сворачивании Таблицы изменений - поиск по дополнительным признакам резко осложняется.
2) Штатное сравнение Табличных частей будет реагировать на изменение порядка строк в ТЧ! Частным случаем для накладных окажется изменение Единицы измерения с соответствующим пересчетом реквизита Количество...

Для борьбы с первой проблемой - указывал в ЖР ссылку Номенклатуры (вместо изменяемого документа), при сохранении ВидаМетаданных
Для борьбы со второй проблемой - особая ветка анализа ТЧ "Товары". Сравнивались Свернутые по измерениям (Номенклатура, Характеристика, Серия, Качество и т.п.) и приведенное к Единицам хранения количество... одновременно отбрасывались неактуальные реквизиты строк.
cargobird; +1 Ответить
20. cargobird 308 20.08.15 16:01 Сейчас в теме
(19) V.Nikonov, да, предложенная в статье методика, что называется "просто и быстро", нулевой вариант. Отчета с отборами не получишь, а только фактическую информацию об изменениях всего чего можно. Изменения порядка строк в табличных частях выдадут большое количество изменений, среди которых нужное не найдешь и т.д.
Сейчас работаю над тем, чтобы этот вариант работал более-менее корректно с табличными частями. А там и до регистра сведений с настройками реквизитов вообще и табличных частей в частности доберемся.
За дельные советы спасибо)
13. vde69 925 19.08.15 08:38 Сейчас в теме
во первых решение действительно "сомнительное", по тому как в реквизитах "ссылки" а не строки и там "моментов" много

во вторых банально туповато сделано в цикле....

я например вот так сделал (тут то же есть спорные моменты, но куда лучше чем дергать каждый реквизит отдельно):

	МассивНеПроверяемыхРеквизитов.Добавить("ИмяПредопределенныхДанных");
	МассивНеПроверяемыхРеквизитов.Добавить("Предопределенный");
	МассивНеПроверяемыхРеквизитов.Добавить("Ссылка");
	МассивНеПроверяемыхРеквизитов.Добавить("ЭтоГруппа");

	// проверяем, что в объекте действительно поменяли что-то важное
	Мета = Объект.Метаданные();
	Запрос = Новый Запрос;
	Запрос.Текст = 
	"ВЫБРАТЬ
	|	ИСТИНА КАК П
	|ИЗ
	|	"+Мета.ПолноеИмя()+" КАК Т
	|ГДЕ Т.Ссылка = &Ссылка 
	|	 И (ЛОЖЬ";	
	
	Запрос.УстановитьПараметр("Ссылка", Объект.Ссылка);
	
	
	Для Каждого мРек из Мета.Реквизиты Цикл 
		мИмя = мРек.Имя;
		Если МассивНеПроверяемыхРеквизитов.Найти(мИмя) = Неопределено Тогда 
			Запрос.Текст = Запрос.Текст + " 
			|			ИЛИ Т."+мИмя+" <> &"+мИмя;
			Запрос.УстановитьПараметр(мИмя, Объект[мИмя]);
		КонецЕсли;
	КонецЦикла;
	
	Для Каждого мРек из Мета.СтандартныеРеквизиты Цикл 
		мИмя = мРек.Имя;
		Если МассивНеПроверяемыхРеквизитов.Найти(мИмя) = Неопределено Тогда 
			Запрос.Текст = Запрос.Текст + "
			|			ИЛИ Т."+мИмя+" <> &"+мИмя;
			Запрос.УстановитьПараметр(мИмя, Объект[мИмя]);
		КонецЕсли;
	КонецЦикла;
	
	Запрос.Текст = Запрос.Текст + ")";

	Если Запрос.Выполнить().Пустой() Тогда 
		Возврат; // изменений важных реквизитов не найдено....
	КонецЕсли;
Показать
14. cargobird 308 19.08.15 08:48 Сейчас в теме
(13) vde69, спасибо за уточнение, посмотрю. Пользователю, правда, на форме доступны именно те реквизиты, которые могут на что-то повлиять, остальные можно не трогать. А Полные права всегда что-то меняют под флагом ОбменДанными.Загрузка = Истина, поэтому их изменения не регистрируются.
21. cargobird 308 23.10.15 13:44 Сейчас в теме
Успешное использование механизма: менеджер случайно изменила в существующей позиции номенклатуры часть реквизитов - восстановили оригинал обратно в короткие сроки.
Оставьте свое сообщение