Книга знаний

1С:Предприятие / v8

v8: Парциальная регистрация изменений в базе данных

Как регистрировать не только, какие объекты менялись, но и какие именно реквизиты объектов менялись.Автор статьи: Гений 1С | Редакторы:
Последняя редакция №6 от 15.01.08 | История
URL: http://kb.mista.ru/article.php?id=288

Ключевые слова: протокол,журнал регистрации,регистрация


Протоколирование.



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

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

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

Состояние объекта мы получаем из переменной ЭтотОбъект.
Состояние объекта в базе данных мы получаем с помощью выражения ЭтотОбъект.Ссылка.ПолучитьОбъект().
Изменения объекта получаем через перебор его реквизитов шапки и табличных частей по метаданным.

Изменения объекта можно представить в виде таблицы со структурой Изменения(ИмяРеквизита, ИмяТЧ, СтрокаТЧ, СтароеЗначение, Значение).
Для реквизитов объекта ИмяТЧ=Неопределено.
Для уменьшения объема протокола нужно сохранять только измененные реквизиты.

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

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

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

Использование справочника для журнала регистрации.


По идее, использование справочника для журнала регистрации более быстро, т.к. справочник без кода и автонумерации быстрее записывается, чем регистр сведений (не нужно контролировать уникальность). Эта тема пока еще не исследована. Нужно произвести замеры производительности на файловой и SQL версии.

Буферизация.


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

Буферизация в журнале регистрации.


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

Реализация в коде


Рассмотрим реализацию без буферизации, с двумя связанными по GUID регистрами сведений.

Используется функция сравнения двух объектов: Книга знаний: v8: Функция сравнения двух объектов одного типа

Функция    п_ЗафиксироватьИзменениеОбъекта(Объект, РежимЗаписи=Неопределено, РежимПроведения=Неопределено) Экспорт
    Ссылка=ДокументСсылкаДатьТочную(Объект);
    //Фиксируем факт записи
 
    
    ГУИД=Новый УникальныйИдентификатор();
    Ключ=GUIDВСтроку(ГУИД);
    МЗ=РегистрыСведений.п_ЛогИзменений.СоздатьМенеджерЗаписи();
    МЗ.Дата=ТекущаяДата();
    МЗ.Пользователь=ПараметрыСеанса.ТекущийПользователь;
    МЗ.Объект=Ссылка;
    МЗ.РежимЗаписи=РежимЗаписи;
    МЗ.РежимПроведения=РежимПроведения;
    МЗ.Ключ=Ключ;
    МЗ.Новый=ЗначениеНеЗаполнено(Объект.Ссылка);
    МЗ.ОбъектСтрокой=Строка(Объект);
    МЗ.Записать();
 
    //Сравниваем старый и новый объекты - получаем таблицу разниц
 
    Если ЗначениеНеЗаполнено(Объект.Ссылка) Тогда
        СравнОбъект=Объект;
    Иначе
        СравнОбъект=Объект.Ссылка.ПолучитьОбъект();
    КонецЕсли;
    Т=СравнитьДваОбъекта(СравнОбъект, Объект);
    Если Т.Количество()>0 Тогда
        НЗ=РегистрыСведений.п_ЛогИзмененийТЧ.СоздатьНаборЗаписей();
        НЗ.Отбор.КлючВладельца.Значение=Ключ;
        НЗ.Отбор.КлючВладельца.ВидСравнения=ВидСравнения.Равно;
        НЗ.Отбор.КлючВладельца.Использование=истина;
        Для Каждого Стр Из Т Цикл
            МЗ=НЗ.Добавить();
            МЗ.КлючВладельца=Ключ;
            МЗ.Реквизит=Стр.Реквизит;
            МЗ.НомСтроки=Стр.НомерСтроки;
            МЗ.ТабличнаяЧасть=Стр.ТабличнаяЧасть;
            МЗ.Значение1=Стр.Значение1;
            МЗ.Значение2=Стр.Значение2;
            МЗ.ТипЗнч1=ТипЗнч(Стр.Значение1);
            МЗ.ТипЗнч2=ТипЗнч(Стр.Значение2);
            МЗ.ЗначениеСтрокой1=Строка(Стр.Значение1);
            МЗ.ЗначениеСтрокой2=Строка(Стр.Значение2);
        КонецЦикла;
        НЗ.Записать();
    КонецЕсли;
    
КонецФункции

Функция ДокументСсылкаДатьТочную(Объект) Экспорт
    Перем Ссылка, Вид;
    
    Ссылка=Объект.Ссылка;
    Если Ссылка.Пустая() Тогда
        Ссылка = Объект.ПолучитьСсылкуНового();
        Если Ссылка.Пустая() Тогда
            Вид=Объект.Метаданные().Имя;
            Ссылка = Документы[Вид].ПолучитьСсылку();
            Объект.УстановитьСсылкуНового(Ссылка);
        КонецЕсли;
    КонецЕсли;
    Возврат Ссылка;
КонецФункции


Структура регистров



- РегистрыСведений.п_ЛогИзменений
            Имя: "п_ЛогИзменений"
            Синоним: "Лог изменений"
            Комментарий: ""
            Подсистемы:
                "Конфигурация.УправлениеПроизводственнымПредприятием"
            СпособРедактирования: "ВСписке"
            ОсновнаяФормаЗаписи: ""
            ОсновнаяФормаСписка: "РегистрСведений.п_ЛогИзменений.Форма.ФормаСписка"
            ПериодичностьРегистраСведений: "Непериодический"
            РежимЗаписи: "Независимый"
            ОсновнойОтборПоПериоду: "Ложь"
            ВключатьСправкуВСодержание: "Ложь"
            - РегистрыСведений.п_ЛогИзменений.Ресурсы.Описание
                Имя: "Описание"
                Синоним: "Описание"
                Комментарий: ""
                Тип:
                    "Строка(0)"
                Индексирование: "НеИндексировать"
            - РегистрыСведений.п_ЛогИзменений.Ресурсы.РежимЗаписи
                Имя: "РежимЗаписи"
                Синоним: "Режим записи"
                Комментарий: ""
                Тип:
                    "Строка(32)"
                Индексирование: "НеИндексировать"
            - РегистрыСведений.п_ЛогИзменений.Ресурсы.РежимПроведения
                Имя: "РежимПроведения"
                Синоним: "Режим проведения"
                Комментарий: ""
                Тип:
                    "Строка(32)"
                Индексирование: "НеИндексировать"
            - РегистрыСведений.п_ЛогИзменений.Ресурсы.Новый
                Имя: "Новый"
                Синоним: "Новый"
                Комментарий: ""
                Тип:
                    "Булево"
                Индексирование: "НеИндексировать"
            - РегистрыСведений.п_ЛогИзменений.Ресурсы.ОбъектСтрокой
                Имя: "ОбъектСтрокой"
                Синоним: "Объект строкой"
                Комментарий: ""
                Тип:
                    "Строка(0)"
                Индексирование: "НеИндексировать"
            - РегистрыСведений.п_ЛогИзменений.Измерения.Дата
                Имя: "Дата"
                Синоним: "Дата"
                Комментарий: ""
                Тип:
                    "Дата(ДатаВремя)"
                Ведущее: "Ложь"
                ОсновнойОтбор: "Истина"
                ЗапрещатьНезаполненныеЗначения: "Ложь"
                Индексирование: "ИндексироватьСДопУпорядочиванием"
            - РегистрыСведений.п_ЛогИзменений.Измерения.Пользователь
                Имя: "Пользователь"
                Синоним: "Пользователь"
                Комментарий: ""
                Тип:
                    "СправочникСсылка.Пользователи"
                Ведущее: "Истина"
                ОсновнойОтбор: "Истина"
                ЗапрещатьНезаполненныеЗначения: "Ложь"
                Индексирование: "НеИндексировать"
            - РегистрыСведений.п_ЛогИзменений.Измерения.Объект
                Имя: "Объект"
                Синоним: "Объект"
                Комментарий: ""
                Тип:
                    "ЛюбаяСсылка"
                Ведущее: "Истина"
                ОсновнойОтбор: "Истина"
                ЗапрещатьНезаполненныеЗначения: "Ложь"
                Индексирование: "НеИндексировать"
            - РегистрыСведений.п_ЛогИзменений.Измерения.Ключ
                Имя: "Ключ"
                Синоним: "Ключ"
                Комментарий: ""
                Тип:
                    "Строка(32)"
                Ведущее: "Ложь"
                ОсновнойОтбор: "Истина"
                ЗапрещатьНезаполненныеЗначения: "Ложь"
                Индексирование: "НеИндексировать"
            - РегистрыСведений.п_ЛогИзменений.Формы.ФормаСписка
                Имя: "ФормаСписка"
                Синоним: "Форма списка"
                Комментарий: ""
                ВключатьСправкуВСодержание: "Ложь"
        - РегистрыСведений.п_ЛогИзмененийТЧ
            Имя: "п_ЛогИзмененийТЧ"
            Синоним: "Лог изменений ТЧ"
            Комментарий: ""
            Подсистемы:
                "Конфигурация.УправлениеПроизводственнымПредприятием"
            СпособРедактирования: "ВСписке"
            ОсновнаяФормаЗаписи: ""
            ОсновнаяФормаСписка: ""
            ПериодичностьРегистраСведений: "Непериодический"
            РежимЗаписи: "Независимый"
            ОсновнойОтборПоПериоду: "Ложь"
            ВключатьСправкуВСодержание: "Ложь"
            - РегистрыСведений.п_ЛогИзмененийТЧ.Ресурсы.Значение1
                Имя: "Значение1"
                Синоним: "Значение1"
                Комментарий: ""
                Тип:
                    "ЛюбаяСсылка,
                     Булево,
                     Строка(10),
                     Дата(Дата),
                     Число(10, 0)"
                Индексирование: "НеИндексировать"
            - РегистрыСведений.п_ЛогИзмененийТЧ.Ресурсы.Значение2
                Имя: "Значение2"
                Синоним: "Значение2"
                Комментарий: ""
                Тип:
                    "ЛюбаяСсылка,
                     Булево,
                     Строка(10),
                     Дата(Дата),
                     Число(10, 0)"
                Индексирование: "НеИндексировать"
            - РегистрыСведений.п_ЛогИзмененийТЧ.Ресурсы.ТипЗнч1
                Имя: "ТипЗнч1"
                Синоним: "Тип значения 1"
                Комментарий: ""
                Тип:
                    "Строка(100)"
                Индексирование: "НеИндексировать"
            - РегистрыСведений.п_ЛогИзмененийТЧ.Ресурсы.ТипЗнч2
                Имя: "ТипЗнч2"
                Синоним: "Тип значения 2"
                Комментарий: ""
                Тип:
                    "Строка(100)"
                Индексирование: "НеИндексировать"
            - РегистрыСведений.п_ЛогИзмененийТЧ.Ресурсы.ЗначениеСтрокой1
                Имя: "ЗначениеСтрокой1"
                Синоним: "Значение строкой 1"
                Комментарий: ""
                Тип:
                    "Строка(0)"
                Индексирование: "НеИндексировать"
            - РегистрыСведений.п_ЛогИзмененийТЧ.Ресурсы.ЗначениеСтрокой2
                Имя: "ЗначениеСтрокой2"
                Синоним: "Значение строкой 2"
                Комментарий: ""
                Тип:
                    "Строка(0)"
                Индексирование: "НеИндексировать"
            - РегистрыСведений.п_ЛогИзмененийТЧ.Измерения.КлючВладельца
                Имя: "КлючВладельца"
                Синоним: "Ключ владельца"
                Комментарий: ""
                Тип:
                    "Строка(32)"
                Ведущее: "Ложь"
                ОсновнойОтбор: "Истина"
                ЗапрещатьНезаполненныеЗначения: "Ложь"
                Индексирование: "НеИндексировать"
            - РегистрыСведений.п_ЛогИзмененийТЧ.Измерения.Реквизит
                Имя: "Реквизит"
                Синоним: "Реквизит"
                Комментарий: ""
                Тип:
                    "Строка(100)"
                Ведущее: "Истина"
                ОсновнойОтбор: "Истина"
                ЗапрещатьНезаполненныеЗначения: "Ложь"
                Индексирование: "НеИндексировать"
            - РегистрыСведений.п_ЛогИзмененийТЧ.Измерения.НомСтроки
                Имя: "НомСтроки"
                Синоним: "Номер строки"
                Комментарий: ""
                Тип:
                    "Число(10, 0)"
                Ведущее: "Ложь"
                ОсновнойОтбор: "Истина"
                ЗапрещатьНезаполненныеЗначения: "Ложь"
                Индексирование: "НеИндексировать"
            - РегистрыСведений.п_ЛогИзмененийТЧ.Измерения.ТабличнаяЧасть
                Имя: "ТабличнаяЧасть"
                Синоним: "Табличная часть"
                Комментарий: ""
                Тип:
                    "Строка(100)"
                Ведущее: "Ложь"
                ОсновнойОтбор: "Истина"
                ЗапрещатьНезаполненныеЗначения: "Ложь"
                Индексирование: "НеИндексировать"





Похожие ссылки:
Книга знаний: v8: Регистрация изменений в справочнике

Описание | Рубрикатор | Поиск | ТелепатБот | Захваченные статьи | Установки | Форум
© Станислав Митичкин (Волшебник), 2005-2025 | Mista.ru

Яндекс.Метрика