Многопоточное восстановление последовательностей

Публикация № 958104

Администрирование - Производительность и оптимизация (HighLoad)

HiLoad Последовательности Перепроведение Восстановление Многопоточность Пакеты данных Универсальные механизмы

Универсальный алгоритм многопоточного фонового восстановления любой последовательности.

Работа «задним числом»

1С – одна из немногих учетных систем, которая настолько лояльна к пользователю, что позволяет ему работать «задним числом».  Такая работа интуитивно понятна, позволяет исправлять ошибки «в прошлом», получать корректные ретроспективные отчеты и многое другое, но порождает ряд проблем, главная из которых – восстановление последовательности проведения документов.

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

В платформе 1С есть объект метаданных «Последовательности», предназначенный для отслеживания актуальных границ последовательности документов, а также для восстановления последовательности. Само восстановление последовательности технически выглядит просто - проведение документов, входящих в эту последовательность, по порядку. Платформа, да и типовые конфигурации 1С, умеют это делать, и в ситуации небольшого объема данных, либо низкой интенсивности работы пользователей это работает неплохо. Однако в HiLоad системах восстановление последовательности становится большой проблемой:

  • Типовое восстановление последовательности выполняется в 1 поток очень долго.
  • Необходимо организовывать регулярный запуск восстановления последовательности силами пользователей.
  • Восстановление последовательности зачастую полностью блокирует работу пользователей с документами, входящими в эту последовательность.

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

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

Многопоточное восстановление последовательности

Разработанный алгоритм восстановления последовательности:

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

Рассмотрение алгоритма ведется на примере решения классической задачи восстановления последовательности.

Постановка задачи

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

  • Монтаж ПУ
  • Ввод показаний  ПУ
  • Демонтаж ПУ

Документы работы с ПУ должны вводиться с соблюдением логики (к примеру, нельзя ввести показания или демонтировать прибор учета, который не был смонтирован). При проведении документа логика проверяется и, если она нарушена, пользователю выдается соответствующее предупреждение. В каждом из перечисленных документов есть табличная часть «Показания», в которой, кроме прочего, фиксируется:

  • Прибор учета
  • Показание прибора учета

Расход электроэнергии рассчитывается при проведении документов «Ввод показаний» и «Демонтаж» как разница между показанием прибора учета в текущем документе и предыдущим показанием ПУ.

В типовой конфигурации есть последовательность «РаботаСПриборамиУчета» с одним измерением «ПриборУчета».

 

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

Общее описание алгоритма решения задачи

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

Принцип работы алгоритма по восстановлению последовательности простой, он работает в 2 этапа:

  • Создание заданий на восстановление последовательности при записи документов.
  • Обработка заданий в несколько параллельных потоков.

Для реализации алгоритма нам нужно будет:

  1. Встроить конфигурацию «Универсальные механизмы: пакеты данных».
  2. Реализовать создание заданий на восстановление последовательности.
  3. Настроить параметры многопоточной обработки этих заданий.
  4. Написать функцию – обработчик для одного задания.

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

1. Встраивание конфигурации «Универсальные механизмы: пакеты данных»

Отказоустойчивая многопоточная работа алгоритма будет организована с использованием конфигурации «Универсальные механизмы: пакеты данных».  Эта конфигурация может быть внедрена в любую конфигурацию на платформе 1С 8.3 без доработок. Она полностью независима и самодостаточна.

Для понимания принципа работы описываемого алгоритма рекомендуется ознакомиться с особенностями работы конфигурации «Универсальные механизмы: пакеты данных» в этой статье.

2. Создание задания на восстановление последовательности

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

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

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

  • Организация
  • Склад
  • Номенклатура

Если же речь идет о последовательности взаиморасчетов, то измерениями ключа могут быть:

  • Организация
  • Контрагент
  • Договор

Один документ при записи может создавать несколько заданий, если этот документ двигает последовательность в нескольких разрезах.

Само задание – это пакет данных. В качестве данных пакета выступает структура – ключ последовательности. Создание заданий – пакетов данных – мы вынесем в новые подписки на события «ПередЗаписью» и «ПриЗаписи» документов, входящих в последовательность. Это позволит не изменять код типовых модулей.

Код обработчика «ПередЗаписью» документов последовательности

Процедура ПередЗаписью(Источник, Отказ, РежимЗаписи, РежимПроведения)
	
	// Получим ключи последовательности, по которым проходил документ до записи
	КлючиПоследовательностиДоЗаписи = Новый Массив;	
	Если НЕ Источник.ЭтоНовый() Тогда
		ТекстЗапроса = 
		"ВЫБРАТЬ
		|	РаботаСПриборамиУчетаПоказания.ПриборУчета
		|ИЗ
		|	«+Источник. Метаданные().Имя+».Показания КАК РаботаСПриборамиУчетаПоказания
		|ГДЕ
		|	РаботаСПриборамиУчетаПоказания.Ссылка = &Ссылка";		
		Запрос = Новый Запрос(ТекстЗапроса);
		Запрос.УстановитьПараметр("Ссылка", Источник.Ссылка);
		Выборка = Запрос.Выполнить().Выбрать();		
		Пока Выборка.Следующий() Цикл
			Ключ = Новый Структура;
			Ключ.Вставить("ИдентификаторКлюча",  Строка(Выборка.ПриборУчета.УникальныйИдентификатор()));
			Ключ.Вставить("ПриборУчета", Выборка.ПриборУчета); // измерения последовательности
			КлючиПоследовательностиДоЗаписи.Добавить(Ключ);
		КонецЦикла;				
	КонецЕсли;				
	ДополнительныеСвойства.Вставить("КлючиПоследовательностиДоЗаписи", КлючиПоследовательностиДоЗаписи);

КонецПроцедуры // ПередЗаписью()

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

Важно! Помимо прочего в ключе последовательности мы формируем уникальный строковый идентификатор ключа:

Ключ.Вставить("ИдентификаторКлюча", Строка(Выборка.ПриборУчета.УникальныйИдентификатор()));

Он нам пригодится позднее. По сути это уникальная строка, сформированная из измерений ключа последовательности. Если ключ последовательности содержит не одно измерение, а несколько, идентификатор ключа нужно собирать вот так:

ИдентификаторКлюча = «»+Измерение1.УникальныйИдентификатор()+Измерение2.УникальныйИдентификатор();
Ключ.Вставить("ИдентификаторКлюча", ИдентификаторКлюча);

Теперь рассмотрим порядок создания заданий на восстановление последовательности в подписке «ПриЗаписи» документов, входящих в последовательность.

Код обработчика «ПриЗаписи» документов последовательности

Процедура ПриЗаписи(Источник, Отказ)
	
	// 1. Создадим полную таблицу ключей последовательности, которые затронула запись этого документа	
	// 1.1. Новые ключи последовательности
	ТаблицаКлючей = Источник.Показания.Выгрузить(,"ПриборУчета");
	ТаблицаКлючей.Колонки.Добавить("ИдентификаторКлюча", Новый ОписаниеТипов("Строка",,Новый КвалификаторыСтроки(200,ДопустимаяДлина.Переменная)));
	Для каждого СтрКлюч из ТаблицаКлючей Цикл
		СтрКлюч.ИдентификаторКлюча = Строка(СтрКлюч.ПриборУчета.УникальныйИдентификатор());
	КонецЦикла;	     	
	// 1.2. Ключи последовательности, по которым проходил документ до записи
	КлючиПоследовательностиДоЗаписи = ДополнительныеСвойства["КлючиПоследовательностиДоЗаписи"];
	Для каждого КлючДоЗаписи из КлючиПоследовательностиДоЗаписи Цикл
		СтрКлюч = ТаблицаКлючей.Добавить();
		ЗаполнитьЗначенияСвойств(СтрКлюч, КлючДоЗаписи);		
	КонецЦикла;		
	
	// 2. Для каждого ключа из таблицы ключей нужно создать задание на восстановление последовательности - новый ПАКЕТ ДАННЫХ.	
	//    При этом не будем создавать пакет для ключей, для которых уже создан пакет, ожидающий обработки. 	
	// 2.1. Найдем наш способ обработки
	ИмяСпособаОбработки = "Восстановление последовательности работы с ПУ";
	СпособОбработки = Справочники.ум_СпособыОбработкиПакетов.НайтиПоНаименованию(ИмяСпособаОбработки);
	Если НЕ ЗначениеЗаполнено(СпособОбработки) Тогда
		ВызватьИсключение "Не найден способ обработки пакетов """+ИмяСпособаОбработки+"""!"; 
	КонецЕсли; 
	
	// 2.2. Отбросим ключи, по которым уже есть пакеты по нашему способу в статусе "К обработке".
	//      Ключ последовательности - в поле ДополнительнаяИнформация пакета.
	ТекстЗапроса = 
	"ВЫБРАТЬ
	|	ТаблицаКлючей.ИдентификаторКлюча,
	|	ТаблицаКлючей.ПриборУчета
	|ПОМЕСТИТЬ ТаблицаКлючей
	|ИЗ
	|	&ТаблицаКлючей КАК ТаблицаКлючей
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ
	|	ТаблицаКлючей.ИдентификаторКлюча,
	|	ТаблицаКлючей.ПриборУчета
	|ИЗ
	|	ТаблицаКлючей КАК ТаблицаКлючей
	|		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ум_ПакетыДанных КАК ум_ПакетыДанных
	|		ПО (ум_ПакетыДанных.СпособОбработки = &СпособОбработки)
	|			И (ум_ПакетыДанных.Состояние = &КОбработке)
	|			И ТаблицаКлючей.ИдентификаторКлюча = ум_ПакетыДанных.ДополнительнаяИнформация
	|ГДЕ
	|	ум_ПакетыДанных.ИдентификаторПакета ЕСТЬ NULL 
	|
	|СГРУППИРОВАТЬ ПО
	|	ТаблицаКлючей.ПриборУчета,
	|	ТаблицаКлючей.ИдентификаторКлюча";   	
	Запрос = Новый Запрос(ТекстЗапроса);
	Запрос.УстановитьПараметр("ТаблицаКлючей"		, ТаблицаКлючей);  	 	
	Запрос.УстановитьПараметр("СпособОбработки"	, СпособОбработки);
	Запрос.УстановитьПараметр("КОбработке"		, Перечисления.ум_СостоянияПакетаДанных.КОбработке);
	
	// 3. Создадим ПАКЕТЫ ДАННЫХ - задания на восстановление последовательности по нашим ключам
	Выборка = Запрос.Выполнить().Выбрать();
	Пока Выборка.Следующий() Цикл	
		// Данные пакета - разрезы последовательности, по которым будет восстанавливаться последовательность
		ДанныеПакета = Новый Структура;
		ДанныеПакета.Вставить("ИдентификаторКлюча"	, Выборка.ИдентификаторКлюча);
		ДанныеПакета.Вставить("ПриборУчета"			, Выборка.ПриборУчета); // измерения последовательности

		Результат = ум_ПакетыДанныхСерверПривилегированный.СоздатьНовыйПакетДанных(ДанныеПакета, ИмяСпособаОбработки, ,ДанныеПакета.ИдентификаторКлюча, "Прибор учета: "+Выборка.ПриборУчета);
		Если Результат.ОшибкаЗаписиПакета Тогда
			ВызватьИсключение Результат.ОписаниеОшибки;
		КонецЕсли;		         		
	КонецЦикла;	
	
КонецПроцедуры

Разберем представленный код по пунктам:

№ 1. Создаем полную таблицу ключей последовательности

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

№ 2. Определяем, для каких ключей нужно создать задания

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

№ 3. Сохранение заданий

Создание задания – пакета данных – выполняется стандартным для конфигурации «Универсальные механизмы: пакеты данных» образом. Данные пакета – это ключ последовательности. Строковый идентификатор ключа мы помещаем в поле ДополнительнаяИнформация пакета данных для того, чтобы избежать дублирования заданий.

3. Настройка многопоточной обработки заданий

Мы настроили механизм создания заданий на восстановление последовательностей. Теперь при работе пользователей или программной записи документов, входящих в последовательность, генерируются пакеты данных по способу обработки «Восстановление последовательности работы с ПУ».

Настроим способ обработки пакетов «Восстановление последовательности работы с ПУ». Для этого откроем в клиенте 1С справочник «Способы обработки пакетов» и создадим в нем новый элемент. Заполним его как показано на рисунке ниже.

Наименование способа обработки «Восстановление последовательности работы с ПУ» значимо, т.к. ранее (при создании пакета данных) мы указывали способ обработки пакета, который искали по его наименованию.

В поле «Имя функции» мы укажем имя функции, которая будет заниматься обработкой одного пакета данных. Ее мы создадим чуть позже.

Время жизни управляющего потока – мы указали 25 секунд. Такой тайминг был указан исходя из того, что интервал запуска регламентного задания обработки пакетов был установлен 30 секунд.

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

Время жизни рабочего ФЗ – указано значение 60 секунд. Данное значение не означает, что пакет данных обязательно будет обрабатываться 60 секунд. Это означает, что по истечении 60 секунд система завершит рабочее фоновое задание, т.к. оно стало иметь признаки «зависания».

Количество параллельных рабочих потоков мы указали 20 параллельных потоков. Значение здесь необходимо указывать, исходя из характеристик «железа» сервера 1С и СУБД с учетом нагрузки, которую создают пользователи системы.

Также заполним вкладку «Повторная обработка» следующим образом:

Количество попыток обработки пакета – здесь мы указали значение 200. По сути, этот параметр определяет время, в течение которого система будет пытаться обработать наш пакет данных. Количество попыток (200) * интервал запуска регламентного задания (30 секунд) = 100 минут. Т.е. мы предполагаем, что за 100 минут и за 200 попыток последовательность по данному ключу должна быть восстановлена. Если этого не произойдет – пакету данных будет присвоен статус «Ошибка». Разбор возникшей ситуации должен быть произведен администратором системы.

Таймаут повторной обработки – система должна обрабатывать наш пакет повторно без таймаута в максимальном темпе.

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

4. Функция – обработчик пакета данных

Для того чтобы наша система заработала, нам необходимо создать один новый регистр сведений. Данные в этот регистр сведений мы не будем писать НИКОГДА. Он нужен нам только для того, чтобы организовать блокировки в обработчике пакета данных.

Структура регистра приведена на рисунке. Это не периодический регистр сведений с одним измерением «ИдентификаторДанных» типа Строка(36). Работа с регистром будет описана ниже.

 

 

 

Теперь приступим к самому интересному – обработке пакета данных. Для этого в серверном модуле МойСерверныйМодуль создадим экспортную функцию – обработчик пакета данных.

Функция ОбработчикПакетаДанных_ВосстановлениеПоследовательностиРаботыСПУ(Данные, ПараметрыПакетаДанных, ПараметрыСпособаОбработки) Экспорт

	МассивПроведенныхДокументов = Новый Массив; // это будет результат обработки пакета
	Пока МассивПроведенныхДокументов.Количество() < 10  Цикл  // Зададим размер порции для этого пакета данных		
		// 1. Получим один первый документ, который нужно провести для восстановления последовательности по ключу пакета
		// Для этого в запросе выполним следующие действия:
		// 1.1	Получим 1 НАШ ДОКУМЕНТ по НАШЕМУ КЛЮЧУ последовательности, который нужно провести следующим.
		// 1.2	Получим перечень ключей последовательности, по которым проходит НАШ ДОКУМЕНТ кроме НАШЕГО КЛЮЧА.
		// 1.3	Посмотрим, а не нужно ли подождать восстановления последовательности по другим ключам. Найдем, есть ли по 
		//		другим ключам документы в последовательности, которые нужно провести ранее НАШЕГО ДОКУМЕНТА.
		ТекстЗапроса =
		"ВЫБРАТЬ ПЕРВЫЕ 1
		|	РаботаСПриборамиУчета.Регистратор,
		|	РаботаСПриборамиУчета.Регистратор.ВерсияДанных КАК ВерсияДанных,
		|	РаботаСПриборамиУчета.Период,
		|	РаботаСПриборамиУчета.ПриборУчета,
		|	РаботаСПриборамиУчета.МоментВремени
		|ПОМЕСТИТЬ ДокументПоНашемуКлючу
		|ИЗ
		|	Последовательность.РаботаСПриборамиУчета КАК РаботаСПриборамиУчета
		|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ Последовательность.РаботаСПриборамиУчета.Границы КАК РаботаСПриборамиУчетаГраницы
		|		ПО РаботаСПриборамиУчета.ПриборУчета = РаботаСПриборамиУчетаГраницы.ПриборУчета
		|			И РаботаСПриборамиУчета.МоментВремени > РаботаСПриборамиУчетаГраницы.МоментВремени
		|ГДЕ
		|	РаботаСПриборамиУчета.ПриборУчета = &ПриборУчета
		|	И РаботаСПриборамиУчета.Регистратор.Проведен
		|
		|УПОРЯДОЧИТЬ ПО
		|	РаботаСПриборамиУчета.МоментВремени
		|;
		|
		|////////////////////////////////////////////////////////////////////////////////
		|ВЫБРАТЬ
		|	РаботаСПриборамиУчета.ПриборУчета
		|ПОМЕСТИТЬ КлючиДругихПоследовательностейДокумента
		|ИЗ
		|	ДокументПоНашемуКлючу КАК ДокументПоНашемуКлючу
		|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ Последовательность.РаботаСПриборамиУчета КАК РаботаСПриборамиУчета
		|		ПО ДокументПоНашемуКлючу.Регистратор = РаботаСПриборамиУчета.Регистратор
		|			И ДокументПоНашемуКлючу.ПриборУчета <> РаботаСПриборамиУчета.ПриборУчета
		|;
		|
		|////////////////////////////////////////////////////////////////////////////////
		|ВЫБРАТЬ
		|	ДокументПоНашемуКлючу.Регистратор,
		|	ДокументПоНашемуКлючу.ВерсияДанных
		|ИЗ
		|	ДокументПоНашемуКлючу КАК ДокументПоНашемуКлючу
		|;
		|
		|////////////////////////////////////////////////////////////////////////////////
		|ВЫБРАТЬ
		|	РаботаСПриборамиУчета.ПриборУчета,
		|	РаботаСПриборамиУчета.Регистратор
		|ИЗ
		|	КлючиДругихПоследовательностейДокумента КАК КлючиДругихПоследовательностейДокумента
		|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ Последовательность.РаботаСПриборамиУчета КАК РаботаСПриборамиУчета
		|			ВНУТРЕННЕЕ СОЕДИНЕНИЕ Последовательность.РаботаСПриборамиУчета.Границы КАК РаботаСПриборамиУчетаГраницы
		|			ПО РаботаСПриборамиУчета.ПриборУчета = РаботаСПриборамиУчетаГраницы.ПриборУчета
		|				И РаботаСПриборамиУчета.МоментВремени > РаботаСПриборамиУчетаГраницы.МоментВремени
		|		ПО КлючиДругихПоследовательностейДокумента.ПриборУчета = РаботаСПриборамиУчета.ПриборУчета,
		|	ДокументПоНашемуКлючу КАК ДокументПоНашемуКлючу
		|ГДЕ
		|	РаботаСПриборамиУчета.Регистратор.Проведен
		|	И РаботаСПриборамиУчета.МоментВремени < ДокументПоНашемуКлючу.МоментВремени";
		
		Запрос = Новый Запрос(ТекстЗапроса);
		Запрос.УстановитьПараметр("ПриборУчета", Данные.ПриборУчета); // изменерния последовательности
		МассивРезультатов = Запрос.ВыполнитьПакет();
		РезультатНашДокумент = МассивРезультатов[2];
		РезультатДругиеКлючи = МассивРезультатов[3];
		
		// 2. Проверим, возможно последовательность восстановлена
		Если РезультатНашДокумент.Пустой() Тогда					
			РезультатОбработки = Новый Структура;
			РезультатОбработки.Вставить("СостояниеПакетаДанных"	, Перечисления.ум_СостоянияПакетаДанных.Обработан);
			РезультатОбработки.Вставить("Сообщение"			, "Проведено " + МассивПроведенныхДокументов.Количество() + " документов (см. результат).	
										|Последовательность восстановлена!");
			РезультатОбработки.Вставить("РезультатОбработки"	, МассивПроведенныхДокументов);  			
			Возврат РезультатОбработки; 
		КонецЕсли;	
		
		// 3. Посмотрим, может нужно подождать восстановления других ветвей последовательности
		Если НЕ РезультатДругиеКлючи.Пустой() Тогда					
			РезультатОбработки = Новый Структура;
			РезультатОбработки.Вставить("СостояниеПакетаДанных"	, Перечисления.ум_СостоянияПакетаДанных.КОбработке);
			РезультатОбработки.Вставить("Сообщение"			, "Проведено "+МассивПроведенныхДокументов.Количество()+" документов.	
										|Ожидание восстановления последовательности в смежных ветвях (см. результат).");
			РезультатОбработки.Вставить("РезультатОбработки"	, РезультатДругиеКлючи.Выгрузить());  			
			Возврат РезультатОбработки; 
		КонецЕсли;	
		
		Выборка = РезультатНашДокумент.Выбрать(); 
		Выборка.Следующий(); // Получим наш документ
		
		// 4. Заблокируем наш документ от проведения в ТОЛЬКО в других пакетах данных.
		НачатьТранзакцию();	     			
		Блокировка = Новый БлокировкаДанных;
		ЭлементБлокировки = Блокировка.Добавить("РегистрСведений.БлокировкиДанныхПакетов");
		ЭлементБлокировки.УстановитьЗначение("ИдентификаторДанных", Строка(Выборка.Регистратор.УникальныйИдентификатор()));
		ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;		
		Блокировка.Заблокировать();
		
		// 5. Проверим не изменили ли документ за время с момента чтения последовательности и установки блокировки данных.		
		ОбъектДокумент = Выборка.Регистратор.ПолучитьОбъект();                                                                  		
		Если НЕ ОбъектДокумент.ВерсияДанных = Выборка.ВерсияДанных Тогда                                                                               			
			ОтменитьТранзакцию();
			Продолжить;
		КонецЕсли;
		
		// 6. Пытаемся провести документ
		Попытка			
			ОбъектДокумент.Записать(РежимЗаписиДокумента.Проведение);				
		Исключение   	
			ОтменитьТранзакцию();
			// Определимся с характером возникшей ошибки
			Если ОбъектДокумент.ДополнительныеСвойства.Свойство("ЭтоОшбикаПоследовательности") и ОбъектДокумент.ДополнительныеСвойства.ЭтоОшбикаПоследовательности Тогда				 				
				// это ошибка последовательности - остановим обработку порции данных
				РезультатОбработки = Новый Структура;
				РезультатОбработки.Вставить("СостояниеПакетаДанных"	, Перечисления.ум_СостоянияПакетаДанных.Обработан);
				РезультатОбработки.Вставить("Сообщение"			, "Ошибка восстановления последовательности для документа "+Выборка.Регистратор+"
											|"+ОбъектДокумент.ДополнительныеСвойства.ОписаниеОшибкиПоследовательности+"
											|Проведено "+МассивПроведенныхДокументов.Количество()+" документов (см. результат).");
				РезультатОбработки.Вставить("РезультатОбработки"	, МассивПроведенныхДокументов);				
				Возврат РезультатОбработки;    			
			Иначе
				// Это иная ошибка - оставим её для разбора
				ВызватьИсключение ОписаниеОшибки();				
			КонецЕсли;    			
		КонецПопытки;    		
		ЗафиксироватьТранзакцию();		
		МассивПроведенныхДокументов.Добавить(Выборка.Регистратор);   				
	КонецЦикла;	
	
	// 7. Порция данных обработана - завершаем обработку пакета данных
	РезультатОбработки = Новый Структура;
	РезультатОбработки.Вставить("СостояниеПакетаДанных"	, Перечисления.ум_СостоянияПакетаДанных.Обработан);
	РезультатОбработки.Вставить("Сообщение"			, "Проведено "+МассивПроведенныхДокументов.Количество()+" документов (см. результат).
								|Обработка порции данных текущего пакета завершена.");
	РезультатОбработки.Вставить("РезультатОбработки"	, МассивПроведенныхДокументов);	 	
	Возврат РезультатОбработки;	  
	
КонецФункции

Эта небольшая функция (150 строк кода с комментариями) выполняет весь объем работ по восстановлению последовательности. В функции мы пытаемся провести документы из последовательности по нашему ключу в нужном порядке. В начале процедуры мы определяем массив:

МассивПроведенныхДокументов = Новый Массив; // это будет результат обработки пакета

В этом массиве хранится информация о проведенных при обработке этого пакета документах.

А здесь мы, по сути, указали размер порции данных, которую обработает данный пакет:

Пока МассивПроведенныхДокументов.Количество() < 10  Цикл  // Зададим размер порции для этого пакета данных

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

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

Далее мы в цикле выбираем из последовательности по одному документу для проведения, анализируем ситуацию «вокруг» документа и проводим его, если для этого наступили благоприятные условия.

№ 1. Получение следующего документа для проведения

Здесь заложена основная суть работы алгоритма. При помощи простого запроса мы:

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

Данный запрос очень легкий, время его выполнения и нагрузка на север минимальны. В результате выполнения он возвращает 2 таблицы:

  • Таблица со следующим документом в последовательности по нашему ключу.
  • Таблица документов по корреспондирующим ключам, восстановления последовательности по которым нам нужно дождаться.

№ 2. Проверим, возможно, последовательность восстановлена

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

Если документ для проведения найден – производим анализ условий для проведения документа.

№ 3. Посмотрим, может нужно подождать восстановления других ветвей последовательности

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

Для того, чтобы наш пакет «подождал» обработку других пакетов, мы завершаем обработку нашего пакета с указанием результирующего статуса «К Обработке». Это означает, что при следующем запуске процедуры обработки пакетов (в нашем случае – раз в 30 секунд), этот пакет будет вновь принят к обработке. С учетом заданных нами параметров многопоточной обработки наш пакет будет повторно принят к обработке не более 200 раз в течение 100 минут.

Если же нам ничего ждать не надо, то приступим к проведению нашего документа.

№ 4. Заблокируем наш документ

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

Для того чтобы избежать лишних действий, наложим блокировку на проведение данного документа ТОЛЬКО в других потоках. Наложить блокировку на документ невозможно, поэтому мы наложим блокировку на уникальный идентификатор данного документа в нашем специальном регистре сведений. Эта операция заблокирует документ для других потоков, но не пользователей.

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

№ 5. Сверка версий документа

Мы смогли заблокировать наш документ. Получим объект нашего документа, и сравним версию нашего объекта с версией, которая была актуальна на момент выполнения запроса в п № 1. Ведь пока мы выполняли запрос и анализировали его результат, документ уже мог быть проведен в параллельном фоновом задании или пользователем вручную.

Если данные устарели – мы идем на новый круг цикла – запрашиваем новую актуальную порцию данных.

№ 6. Проведение документа

Мы убедились, что работаем с актуальной версией объекта документа. Теперь мы можем провести документ.

Здесь есть определенное упрощение. Часто типовые конфигурации содержат специальные процедуры для проведения документа только с целью восстановления определённой последовательности. Такие процедуры не проводят документ «целиком», перезаписывая весь объем его движений, а лишь обновляют движения документа только по одному разделу учета, что ускоряет процесс. Такую процедуру легко найти, если посмотреть типовую однопоточную обработку восстановления последовательности. Будет правильней здесь вызывать для нашего документа именно такую специальную процедуру, однако и приведенный выше код также будет работать корректно.

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

Если же при проведении возникла ошибка – мы её анализируем.

Если это логическая ошибка восстановления последовательности, например:

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

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

При решении прикладных задач ошибки логики могут выглядеть иначе:

  • не хватило партий (если мы что-то делаем с остатками на складе),
  • нет остатков по взаиморасчетам (если наша последовательность – взаиморасчеты),
  • и пр.

Пользователь увидит, что последовательность восстановлена не полностью при анализе отчетов или выполнении других действий. Когда он исправит ситуацию (изменит документы) – будут созданы новые задания, которые «доведут работу» до конца.

В приведенном примере мы исходим из того, что при осуществлении проверок проведения у объекта документа в дополнительных свойствах устанавливается флаг «ЭтоОшбикаПоследовательности», если причиной ошибки проведения была логическая ошибка. В типовых конфигурациях информирование о логической ошибке (нехватке партий или остатков взаиморасчетов) происходит иначе. Может не вызываться исключение, но могут быть иные признаки. Здесь разработчик должен организовать выявление этой ошибки самостоятельно.

Если это иная ошибка, например, синтаксическая ошибка в исполняемых модулях – мы вызываем исключение с описанием этой ошибки. Статус пакета будет автоматически установлен в «Ошибка» и описание этой ошибки будет доступно администратору.

№ 7. Порция данных обработана

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

Как это работает

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

ШАГ 1

На первом шаге работы алгоритма будут запущены два рабочих фоновых задания для восстановления последовательности по ключу 1 и 2.

ШАГ 2

После проведения первых документов в каждом ФЗ анализируется ситуация со следующим документом в последовательности. Восстановление последовательности по ключу 1 предполагает проведение документа № 4, что нецелесообразно. Этот документ «задевает» последовательность по ключу 2, которая еще не восстановлена. Как итог – обработка пакета с заданием по ключу 1 завершается.

Фоновое задание по ключу 2 успешно продолжает проводить документы.

ШАГ 3

Фоновое задание провело документ № 3. Анализ документа № 4 показал, что его можно провести, т.к. последовательность по корреспондирующему ключу 1 восстановлена вплоть до документа № 4. Документ № 4 проводится, продвигая последовательности как по ключу 2, так и по ключу 1.

ШАГ 4

Фоновое задание по ключу 2 продолжает свою работу, не прерываясь. В это время по ключу 1 была начата обработка пакета в новом фоновом задании. Восстановление последовательности по ключу 1 будет начато сразу с документа № 6.

Что получилось в итоге:

  • Организовано многопоточное отказоустойчивое восстановление последовательности.
  • Все изменения конфигурации не коснулись типовых объектов. Мы практические не усложнили процесс обновления конфигурации.
  • Ни в одном месте алгоритма мы не накладываем блокировок на саму последовательность или на любой другой объект, используемый при оперативной работе пользователя.
  • Запись документов пользователем и в пакетах данных производится одновременно. Пользователь может увидеть замедление работы системы, но вероятность получения ошибки блокировки данных минимальна.
  • Алгоритм самостоятельно адаптируется к изменяющимся первичным данным. Мы не рассчитываем граф проведения документов, который будет регулярно устаревать. Определение действий для каждого задания ведется с учетом актуальной учетной ситуации.
  • Инициация процесса восстановления последовательности происходит автоматически по факту совершения пользователем действий в учетной системе.

Ограничения

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

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

Приведу небольшой пример. Есть проблема проведения складских документов по партиям в организации, у которой:

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

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

2. Последовательность должна корректно разделять данные на независимые ветви.

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

Рассмотрим ситуацию восстановления последовательности складского учета в организации с множеством складов и различной номенклатуры. Первичные данные однозначно позволяют распараллелить процесс восстановления последовательности (к примеру, по складам). Однако сама последовательность имеет только одно измерение – «Организация». В данной ситуации говорить о многопоточной обработке также не приходится.

3. Нет технологических ограничений многопоточной обработки.

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

Чаще всего блокировки возникают при записи движений регистров накопления. А точнее при обновлении записей в таблице итогов регистров накопления. Данную проблему легко устранить включением для регистров накопления режима разделения итогов.

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

Если разделения итогов оказалось мало, нужно произвести рефакторинг процедур проведения документа.

Специальные предложения

Комментарии
Избранное Подписка Сортировка: Древо развёрнутое
Свернуть все
1. ifal 329 06.12.18 10:40 Сейчас в теме
А есть какие-нибудь замеры по выигрышу производительности, хотя бы примерные, на вашей конфигурации?
2. _ASZ_ 95 06.12.18 12:09 Сейчас в теме
(1) Есть опыт увеличения в 7-8 раз скорости восстановления последовательности в одной из крупнейших энергосетевых организации сибирского федерального округа. Но это была не типовая конфигурация.

На типовых конфигурациях подобный алгоритм ускорял восстановление последовательности расчетов в 4-5 раз (УПП 1.2), но такой "не революционный" результат был больше обусловлен характером данных в учетной системе. Есть также опыт восстановления последовательности партионного учета в УПП с аналогичным результатом.
3. starik-2005 2029 06.12.18 14:40 Сейчас в теме
Правильная статья. Эффект от многопоточности пропорционален количеству потоков и обратно пропорционален количеству блокирующих факторов, заставляющих один поток ждать другой поток.

Реальным решением, позволяющим в достаточно большое количество раз увеличить скорость проведения документов, является механизм, позволяющий читать исторические данные одномоментно и хранить их изменения для последующих документов. Дальше полученные записи регистров передаются многопоточному механизму записи. В итоге так и в 100 раз можно скорость восстановления последовательности повысить, т.к. нет конфликтов чтения данных. Но такой подход может быть реализован лишь в монопольном режиме, когда разные пользователи не изменяют данные.
4. _ASZ_ 95 06.12.18 14:53 Сейчас в теме
(3) Поддержу.

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

При реализации описанного подхода последовательность восстанавливается самостоятельно. В организациях где это было реализовано, граница последовательности продвигается до максимального уровня сразу после изменения данных без трудозатрат пользователя. В итоге "запущенная" ситуации когда нужно что-то долго восстанавливать не наступает практически никогда.
5. starik-2005 2029 06.12.18 15:32 Сейчас в теме
(4)
В итоге "запущенная" ситуации когда нужно что-то долго восстанавливать не наступает практически никогда.
Основная проблема - это изменение "древних" документов, результаты проведения которых могут влиять на будущие данные. Самое простое и правильное решение - запрет изменения данных в пределах дня (или, как это сделано в серьезных системах - вообще, а все изменения производятся корректирующими операциями). Но уж если политика компании в плане учета позволяет изменять данные в широком диапазоне периодов, то это решить каким-то простым методом, конечно, не получается.
6. bulpi 169 06.12.18 22:20 Сейчас в теме
Черезвычайно интересно.
Но я не понял, как Вы решаете следующую проблему :
Допустим, нужно восстановить последовательность за месяц по 1 товару. Но при перепроведении документов получается, что в ТЧ этих документов попадаются и другие товары. Что, в свою очередь, порождает новые "пакеты задач" на восстановление последовательности. И т.д, Для того , чтобы восстановить последовательность по 1 товару, в конечном счете придется перепровести целое дерево документов, которое может по размеру захватить и 100% документов за месяц (зависит от связности товаров в ТЧ)
Чтобы этого избежать, придется переписывать алгоритмы проведения так, чтобы перепроводился не полностью документ, а только 1 товар из документа. А это очень сложно, а иногда даже принципиально невозможно.
7. _ASZ_ 95 07.12.18 04:07 Сейчас в теме
(6) При выборе примера я намеренно взял ситуацию, когда один документ может проходить по нескольким ключам последовательности. Но такую ситуацию, как Вы описываете я не стал рассматривать в картинках, т.к. это значительно бы усложнило восприятие.

По существу:
Алгоритм генерирует большой объем новых задач и проведение одного документа действительно может приводить к лавинообразному росту заданий и, как следствие, необходимости проведения других документов по другим ключам. Но это происходит ТОЛЬКО когда это следует из логики данных (избыточности нет). Механизм рассчитан на переваривание такой ситуации. Нет необходимости переписывать процедуры проведения документов для реализации возможности проведения только по 1 ключу из нескольких, задетых документом.
Хотя не спорю, если заморочиться и переписать - работать будет быстрее и "лавины" не будет. Но здесь возникает вопрос целесообразности такой работы. Практический опыт показал, что её нет. Если обработка заданий включена онлайн и есть адекватное движение даты запрета редактирования по отношению к точке ввода данных, то критические ситуации маловероятны.
А даже если они случаются - они обрабатываются в фоне практически без влияния на оперативную работу пользователей.
8. DarkAn 927 07.12.18 10:44 Сейчас в теме
Правильно ли я понял, что по одному картина получается примерно следующая: По каждому прибору учета запускается отдельное ФЗ?
Если да, тогда вопрос:
Предположим, для краткости мы запускаем восстановление в 5 потоков

ФЗ1: (Док1, ключ1) ->(Док2, ключ1)----->
ФЗ2: (Док3, ключ2) ->(Док4, ключ2)----->
ФЗ3: (Док5, ключ3) ->(Док6, ключ3)----->(Док12, Ключ1,Ключ2,Ключ3,Ключ4,Ключ5,Ключ6)
ФЗ4: (Док7, ключ4) ->(Док8, ключ4)----->
ФЗ5: (Док9, ключ5) ->(Док10, ключ5)--->
(Док11, ключ6)----------------------->

Поясню, Каждое ФЗ восстанавливает свой ключ, но у нас ограничение в 5 ФЗ, и дойдя до документа 12 с 6 ключами, все наши ФЗ встали, т.к. ждут восстановления ключа 6, а на него ФЗ не хватило?

Так же вопрос, не понял где происходит сдвиг границы последовательности?
9. _ASZ_ 95 07.12.18 10:51 Сейчас в теме
(8) 1. Не верно поняли. Когда ФЗ натыкается на ситуацию ожидания - обработка пакета завершается. ФЗ заканчивает свою работу, освобождая "слот" для других ФЗ. В следующий раз по этому ключу ФЗ стартует только при следующем старте управляющего потока. До этого момента - будут обрабатываться другие ключи.
2. В приведенном примере граница сдвигается автоматически при проведении документа.
10. DarkAn 927 07.12.18 13:26 Сейчас в теме
(9)
В приведенном примере граница сдвигается автоматически при проведении документа.

Есть ли смысл двигать границу каждым документом?

Как быть в типовых решениях, где нет измерений? Двигать каждым документом? Но тогда не будет параллельности. Или встраивать измерение и править типовые механизмы?
11. _ASZ_ 95 07.12.18 15:19 Сейчас в теме
(10) Тестовом примере двигать границу каждым документом, как мне кажется, вполне уместно :) Да и не в тестовом - тоже можно (зачастую, так и происходит в типовых конфигурациях от 1С).

По второму вопросу - мне кажется Вам стоит прочитать главу Ограничения в самом конце статьи. Там четко обозначено, что:
2. Последовательность должна корректно разделять данные на независимые ветви., также приведен соответствующий пример.
Ситуация, когда в типовой конфигурации от фирмы 1С последовательность не содержала бы измерений, мне не встречалась.
12. DarkAn 927 07.12.18 16:17 Сейчас в теме
(11)
Ситуация, когда в типовой конфигурации от фирмы 1С последовательность не содержала бы измерений, мне не встречалась

Да - в типовой УПП при восстановлении партий БУ есть измерение, но это только Организация, а ни как не Организация + Склад + Номенклатура.

Отсюда вопрос, что еще необходимо будет доработать в типовой УПП 1.3 для восстановления последовательности партий?
Что добавить - ясно:
* подсистема "Универсальные механизмы: пакеты данных";
* РС для блокировок;
* Общий модуль с вышеизложенными модулями;

Последовательность должна корректно разделять данные на независимые ветви


А вот что придется изменить в типовых метаданных?
* последовательность - добавить в нее измерения, да еще и не одно, а несколько (Организация - есть, + Склад + Номенклатура)?
* а так же закомментировать весь код типового движения по этой последовательности?
* еще что-то?

Или я все не так понял?

А как быть с последовательностями, если мы отдаем материалы в производств стороннему контрагенту и на выходе получаем готовую продукцию, которую списываем в производство? Ведь те документы кроме как "Заказом" ни как не связаны?

Т.е. Передача:
Склад1 + Затрата1
Склад1 + Затрата2
Заказ1

Поступление:
Склад5 + Продукция1
Заказ1

Как с учетом и обычного списания материалов со склада и с таким производство доработать последовательность???
EMelihoff; +1 Ответить
13. _ASZ_ 95 07.12.18 16:47 Сейчас в теме
(12) Если последовательность не разделяет данные на независимые ветви, то такую последовательность нужно дорабатывать. В противном случае о многопоточной обработке можно забыть.

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

P.s.: про поблемы в УПП я знаю. И если вы посмотрите внимательно, на ситуацию, которой я демонстрирую ограничение №2, возможно вы узнаете свою проблему :).
P.p.s.: эту проблему я решал на УПП 1.2 путем доработки последовательности, но приводить описание своих действий здесь не считаю целесообразным.
14. DarkAn 927 07.12.18 17:01 Сейчас в теме
(13)
С решением прикладной задачи я думаю Вы сможете справится самостоятельно.

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


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

Зачем забывать?
Многопоточность. Универсальный «Менеджер потоков» 2.0 - позволяет решить вопрос восстановления без доработок последовательности, без добавления "фиктивных" объектов метаданных.
15. _ASZ_ 95 07.12.18 17:30 Сейчас в теме
(14) Ясно откуда ноги растут :) сразу не догадался.

Ваше решение также заслуживает внимания. Я рад, что Вы нашли место для его продвижения здесь.
16. DarkAn 927 07.12.18 17:52 Сейчас в теме
(15)
Я рад, что Вы нашли место для его продвижения здесь.

Вопрос не только в продвижении.
Мне действительно интересны статьи и разработки связанные с многопоточностью.
В предложном Вами решении я так же нашел массу интересных направлений натолкнувших меня на ряд идей :).
17. logarifm 1073 08.12.18 14:28 Сейчас в теме
Ну все это хорошо. Вот тут вопрос к 1С скажите, а почему зная о колосальной проблеме в типовых решениях не сделать многопоточность в качестве инструментария типовых решений, почему люди пилят вот такие собственные "костыли" ?...

К сожалению 1С этот вопрос никогда не увидит и точно ответа не дадут. Но из ряда вон у меня есть масса претензий к этим умным людям. Вместо того чтобы разрабатывать действительно требовательные механизмы затрагивающие область оптимизации (это не только многопоточность), а вообще маштабированность кластеров и стабильность их. Вот вместо этого мы на зазеркалье читаем (мы вот тут добавляем чат в 1С назвав это крутым словом ВЗАИМОДЕЙСТВИЕ).

А потом через некоторое время еще: мы тут такую крутую штуку придумали к этому чату, теперь вы можете через нее файлы передевать.
18. acanta 73 08.12.18 14:30 Сейчас в теме
Потому что для файловой базы это работать не должно, а конфигурация та же. Тот кто покупает серверную версию должен понимать, что конфигурация у него все равно для файловой базы с некоторыми встренными готовыми костылями.
19. logarifm 1073 08.12.18 14:31 Сейчас в теме
(18) это элементарно отбивается двумя строчками кода Если ФайловыйРежим Тогда по обычной схеме!
20. logarifm 1073 08.12.18 14:33 Сейчас в теме
(18) Вообще покажите мне хоть одно предприятие где людей в базе от 50 человек, что они работают в файловой базе - это как минимум кощунство или банально ЖЛОБСТВО я бы точно там никогда бы не работал программистом!
21. acanta 73 08.12.18 14:35 Сейчас в теме
Причем здесь предприятие мы говорим об архитектуре тиражных решений. Либо все предприятия до 10 пользователей будут работать на системе для серверных версий, либо всем серверным придется мириться с принципами работы небольших баз. Как по вашему, чьими интересами пожертвуют?
22. logarifm 1073 08.12.18 14:36 Сейчас в теме
23. acanta 73 08.12.18 14:49 Сейчас в теме
Предприятия в принципе растут или в кризис сокращаются и если сегодня на нем 10, то завтра может быть 70,и наоборот. 1с этого не предусматривает.
24. spock 591 08.12.18 22:45 Сейчас в теме
Саша, вы продолжаете развиваться КЭО? Смотрю, Учет приборов учета прижился )
25. _ASZ_ 95 09.12.18 06:58 Сейчас в теме
(24) В КЭО практически нет нового функционала. Последний год мы только переписываем/рефакторим КЭО. В частности переписали полностью пофидерный анализ. Старые документы и всю подсистему приборов учета выкорчевали, т.к. она оказалась нежизнеспособной. Создали новые объекты/регистры и пр.

Сейчас занимаемся внедрением 1С:ТОиР. Уже введено более 1 млн объектов ремонта, формируются полностью заполненные паспорта ВЛ. Запустили геоинформационную систему, которая позволяет визуализировать сеть и топологию на Яндекс картах.
26. spock 591 09.12.18 17:39 Сейчас в теме
(25)Молодцы, неплохо. По ПУ зря - шикарное и быстрое решение могло получиться. Здорово, что смогли реализовать мои предложения.
27. Anchoret 38 10.12.18 09:53 Сейчас в теме
Сейчас как раз пытаюсь реализовать подобное у бухгалтерии 3.0, за пример взял статью с ИТС (https://its.1c.ru/db/metod8dev/content/5843/hdoc), то есть добавил в последовательности "ДокументыОрганизаций" измерение "ДоговорКонтрагента". Казалось, что всё довольно просто, но как оказалось проблема не в том, как распараллелить, а в том, что далеко не во всех документам последовательности есть такой реквизит и не каждый документ можно отнести к конкретному договору (требования-накладные, операция, перемещение товаров, передача ОС и т. п.). В итоге оказалось, что документов с договорами совсем немного больше, чем документов без договоров. Результат получился следующий:
Формируется таблица документов из последовательности, документы без договора проводятся последовательно, когда доходит до документов с договорами, такие документы разбиваются на 5 потоков и проводятся параллельно

Количество документов: 32585
Время проведения: 8:32:57 (6:31:52)

Количество документов: 38958 (документов с договорами стало гораздо больше)
Время проведения: 11:06:13 (8:27:17)

Как видно, выгода по времени есть, но нельзя сказать, что у меня она получилась особо впечатляющей
28. _ASZ_ 95 10.12.18 10:17 Сейчас в теме
(27) Вашу ситуацию можно также можно попробовать решить с помощью предложенного алгоритма. Вы вводите в последовательность измерение Договор. Те документы, которые не имеют договора - также должны в эту последовательность попадать (Договор = ПустаяСсылка).

Нужно будет запрос в обработчике пакета доработать следующим образом: если в текущем ключе договор - пустая ссылка, то мы не ищем корреспондирующие ключи, а смотрим есть ли в последовательности документы (вообще без отбора по измерениям) , которые нужно проводить ранее нашего. В этом случае текущее задание будет ждать пока все документы, ранее текущего будут проведены в нужной последовательности.
29. Manoshkin 349 11.12.18 10:18 Сейчас в теме
Насколько я понял задания создаются по документам проведенным "задним числом". Мы использовали иной подход: выявляли ошибки в партиях (это можно сделать одним запросом и достаточно быстро) за период и перепроводили только документы с ошибками. Далее проверяли следующий период. И чем меньше ошибок, тем быстрее восстановление. Штатно на УПП 1.3 тратили несколько дней, теперь для предварительной оценки месяца достаточно полчаса-час. На чистовую побольше. https://infostart.ru/public/805321/
30. Leonardo2000 20.02.20 17:56 Сейчас в теме
Добрый день как можно получить данную обработку ?
31. _ASZ_ 95 27.02.20 09:19 Сейчас в теме
Здравствуйте. В статье описана не конкретная обработка, а способ реализации многопоточного восстановления последовательностей с использованием конфигурации для многопоточная обработки данных (лежит тут).
32. maxx 887 22.03.20 20:43 Сейчас в теме
Скажите по опыту, если вот такая ситуация.

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

Есть какие-то "заградительные" меры, чтобы задания не порождались? Какие подходы?
33. _ASZ_ 95 23.03.20 06:47 Сейчас в теме
(32) А тут кто во что горазд... Я обычно при генерации пакета в комментарий к пакету записываю информацию о том, кто и в каких обстоятельствах создал пакет. В вашем случае достаточно указать "Иванова Иванна Ивановна - Док №6 от 01.01.80".
В тот момент, когда я Иванову запускаю руками "ювелирить" - просто отключаю активность способа обработки пакетов. Пакеты будут генерироваться, но обрабатываться не будут. После того, как она сделала свои дела - удаляю еще не обработанные пакеты и программно двигаю последовательность на дату запрета.
Оставьте свое сообщение

См. также

Программная работа с настройками СКД

Статья Программист Нет файла v8 v8::СКД 1cv8.cf Бесплатно (free) Практика программирования

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

27.01.2020    9154    ids79    26       

Программы для исполнения 488-ФЗ: Маркировка товаров Промо

1 января 2019 года вступил в силу ФЗ от 25.12.2018 № 488-ФЗ о единой информационной системе маркировки товаров с использованием контрольных (идентификационных) знаков, который позволяет проследить движение товара от производителя до конечного потребителя. Инфостарт предлагает подборку программ, связанных с применением 488-ФЗ и маркировкой товаров.

[СКД] Программное создание схемы компоновки данных

Статья Программист Стажер Нет файла v8 v8::СКД 1cv8.cf Бесплатно (free) Практика программирования

Сделаем отчет на СКД полностью программно, без использования макета "схема компоновки данных".

15.01.2020    10588    John_d    22       

Онлайн-курс «Автоматизация процессов управления МТО: методика сбора и формализации требований» с 1 апреля по 13 мая 2020 года. Промо

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

40000 рублей

Агрегатные функции СКД, о которых мало кто знает

Статья Программист Нет файла v8 v8::СКД 1cv8.cf Бесплатно (free) Практика программирования

Пользуетесь ли Вы всеми возможными агрегатными функциями, которые предоставляет система компоновки данных? Если Вы используете только: СУММА, КОЛИЧЕСТВО, МИНИМУМ, МАКСИМУМ, СРЕДНЕЕ, то эта статья для Вас.

05.09.2019    30660    ids79    50       

Новый раздел на Инфостарте - Electronic Software Distribution Промо

Инфостарт напоминает: на нашем сайте можно купить не только ПО, связанное с 1С. В нашем арсенале – ESD-лицензии на ПО от ведущих вендоров: Microsoft, Kaspersky, ESET, Dr.Web, Аскон и другие.

  • Низкие цены, без скрытых платежей и наценок
  • Оперативная отгрузка
  • Возможность оплаты с личного счета (кешбек, обмен стартмани на рубли и т.п.)
  • Покупки идут в накопления для получения скидочных карт лояльности Silver (5%) и Gold (10%)

Три костыля. Сказ про фокусы в коде

Статья Программист Нет файла v8 Бесплатно (free) Практика программирования

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

03.09.2019    19072    YPermitin    80       

Отслеживание выполнения фонового задания

Статья Программист Нет файла v8 1cv8.cf Бесплатно (free) Практика программирования Универсальные функции Разработка

Запуск фонового задания из модуля внешней обработки. Отслеживание выполнения задания в виде прогресса, расположенного на форме.

17.08.2019    21806    ids79    16       

Подборка программ для взаимодействия с ЕГАИС Промо

ЕГАИС (Единая государственная автоматизированная информационная система) - автоматизированная система, предназначенная для государственного контроля за объёмом производства и оборота этилового спирта, алкогольной и спиртосодержащей продукции. Инфостарт рекомендует подборку проверенных решений для взаимодействия с системой.

Функции СКД: ВычислитьВыражение, ВычислитьВыражениеСГруппировкойМассив

Статья Программист Нет файла v8 v8::СКД 1cv8.cf Бесплатно (free) Практика программирования

Подробное описание и использование внутренних функций системы компоновки данных: Вычислить, ВычислитьВыражение, ВычислитьВыражениеСГруппировкойМассив, ВычислитьВыражениеСГруппировкойТаблицаЗначений.

08.08.2019    42690    ids79    36       

Фоновое выполнение кода в 1С - это просто

Статья Программист Нет файла v8 1cv8.cf Бесплатно (free) Практика программирования

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

02.08.2019    21799    avalakh    21       

DevOps для 1С. Онлайн-курс проходит с 16 апреля по 11 июня 2020 года. Промо

Данный онлайн-курс предусматривает изучение процессов DevOps, их применение при разработке на платформе 1С. В результате прохождения онлайн-курса вы сможете: настроить ПО необходимое для проведения проверок и тестирования, создавать сценарии тестирования и объединять их в комплексные процессы, создавать скрипты для автоматизации процессов DevOps.

12000 рублей

СКД - наборы данных и связи между ними, создание собственной иерархии, вложенные отчеты

Статья Программист Нет файла v8 v8::СКД 1cv8.cf Бесплатно (free) Практика программирования

Набор данных объект. Использование в схеме компоновки нескольких наборов данных. Различные варианты связи наборов: объединение, соединение. Использование иерархии в отчетах на СКД. Создание собственной иерархии, иерархия детальных записей. Использование вложенных схем в отчетах на СКД.

26.07.2019    33539    ids79    11       

Обработчики событий при записи объектов. Зачем и что за чем?

Статья Программист Нет файла v8 Бесплатно (free) Математика и алгоритмы

Программисту, имеющему немного опыта на платформе 1С 8.3, бывает сложно разобраться: ПередЗаписью, ПриЗаписи, ПослеЗаписи, на сервере, на клиенте, в модуле формы, в модуле объекта.... Эта шпаргалка была создана в процессе обучения и реального опыта с целью разложить всё по полочкам, чтобы было четкое понимание в каком случае какой обработчик нужно использовать и в какой последовательности они запускаются при записи и проведении документов. Данная статья будет полезна в большей степени начинающим разработчикам. Но и опытным позволит освежить информацию, упорядочить её.

25.07.2019    28531    4    AlbinaAAA    25       

Подборка решений для взаимодействия со ФГИС «Меркурий» Промо

С 1 июля 2019 года все компании, участвующие в обороте товаров животного происхождения, должны перейти на электронную ветеринарную сертификацию (ЭВС) через ФГИС «Меркурий». Инфостарт предлагает подборку программ, связанных с этим изменением.

СКД - использование расширений языка запросов, секция ХАРАКТЕРИСТИКИ

Статья Программист Нет файла v8 v8::СКД Бесплатно (free) Инструментарий разработчика Практика программирования

Автоматическое и не автоматическое заполнение полей компоновки данных. Использование расширений языка запросов для СКД «{…}», секция ВЫБРАТЬ, секция ГДЕ, параметры виртуальных таблиц. Автоматизированное использование дополнительных данных в запросе: секция ХАРАКТЕРИСТИКИ.

17.07.2019    23328    ids79    27       

"Меньше копипаста!", или как Вася универсальную процедуру писал

Статья Программист Стажер Нет файла v8 v8::СКД 1cv8.cf Бесплатно (free) Практика программирования Разработка

Программист Вася разбирает подход создания универсальных методов на примере программного вывода СКД.

04.07.2019    14449    SeiOkami    49       

Программы для исполнения 54-ФЗ Промо

С 01.02.2017 контрольно-кассовая техника должна отправлять электронные версии чеков оператору фискальных данных - правила установлены в 54-ФЗ ст.2 п.2. Инфостарт предлагает подборку программ, связанных с применением 54-ФЗ, ККТ и электронных чеков.

Создание отчетов с помощью СКД - основные понятия и элементы

Статья Программист Нет файла v8 v8::СКД Бесплатно (free) Практика программирования Математика и алгоритмы

Основные принципы работы СКД. Понятия схемы компоновки и макета компоновки. Описание основных элементов схемы компоновки: наборы данных, поля, вычисляемые поля, ресурсы, параметры.

25.06.2019    36243    ids79    17       

Многопоточное ускорение однопользовательских нагрузок в 1С + Microsoft SQL Server 2017

Статья Программист Нет файла v8 v8::Запросы Бесплатно (free) Практика программирования Производительность и оптимизация (HighLoad)

Взаимодействие с Microsoft SQL Server нередко вызывает трудности у 1С-ников, а потому интересны любые моменты, связанные с его использованием. О своем опыте работы с новым SQL Server 2017 участникам конференции Infostart-2018 рассказал директор ООО «Аналитика софт» Дмитрий Дудин.

11.06.2019    18931    dmurk    144       

Базовый курс для начинающих 1С-программистов. Онлайн-интенсив со 2 июня по 2 июля 2020 г. Промо

Данный онлайн-курс является начальной ступенью по изучению базовых принципов программирования в системе “1С:Предприятие” и предназначен для обучения 1С-программированию “с нуля”.

4500-9500 рублей

Регистры накопления. Структура хранения в базе данных

Статья Программист Нет файла v8 1cv8.cf Бесплатно (free) Практика программирования Разработка

Структура хранения регистров накопления в базе данных для платформы 1С:Предприятие 8.x. Первая часть в серии публикаций.

16.05.2019    31242    YPermitin    30       

Выполнение внешней обработки в фоновом задании

Статья Программист Нет файла v8 1cv8.cf Бесплатно (free) Практика программирования Разработка

Подробное описание подхода к созданию длительной операции на основе внешней обработки. Реализация протестирована на 1С 8.3.12.1714 (x64).

11.05.2019    20417    Eret1k    23       

Онлайн-интенсив "1C:Предприятие для программистов: Бухгалтерские задачи" с 22 июня по 8 июля 2020 г. Промо

Данный онлайн-курс предусматривает изучение механизмов платформы “1С:Предприятие”, которые предназначены для решения задач бухгалтерского учета. Курс предназначен для тех, кто уже имеет определенные навыки конфигурирования и программирования в системе “1С:Предприятие”, а также для опытных пользователей прикладного решения “1С:Бухгалтерия” и прочих прикладных решений, в которых реализованы соответствующие механизмы для автоматизации бухгалтерских задач.

4900 рублей

Выгрузка документа по условию

Статья Программист Нет файла v8 Бесплатно (free) Практика программирования Разработка

Что делать, если документы нужно выгружать не все подряд, а по какому-то фильтру: статусу, дате, набору условий... А что если он соответствовал этим условиям, а потом перестал? А если потом опять начал? Такие ситуации заставили попотеть не одного программиста.

25.04.2019    11665    m-rv    2       

5 простых шагов и 15 минут на разворачивание инструмента мониторинга проблем производительности базы 1С

Статья Системный администратор Программист Нет файла v8 Windows Бесплатно (free) Производительность и оптимизация (HighLoad)

В этой статье мы разберем механизм использования конфигурации "Анализ технологического журнала" на практике, и всего через 15 минут работы вы получите функциональный, удобный инструмент мониторинга проблем производительности базы 1С.

18.04.2019    24298    ivanov660    77       

1C:Предприятие для программистов: Расчетные задачи (зарплата). Онлайн-интенсив с 01 по 17 июня 2020 г. Промо

Данный онлайн-курс предусматривает изучение механизмов платформы “1С:Предприятие”, которые предназначены для автоматизации периодических расчетов, а именно - для расчета зарплаты. Курс предназначен для тех, кто уже имеет определенные навыки конфигурирования и программирования в системе “1С:Предприятие”, а также для опытных пользователей прикладного решения “1С:Зарплата и управление персоналом” и прочих прикладных решений, в которых реализован функционал расчета зарплаты.

4900 рублей

Как прикрутить ГУИД к регистру сведений

Статья Программист Нет файла v8 Бесплатно (free) Практика программирования Перенос данных из 1C8 в 1C8 Разработка

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

16.04.2019    15047    m-rv    16       

О расширениях замолвите слово...

Статья Программист Стажер Нет файла v8 Бесплатно (free) Практика программирования Разработка

О чём стоит задуматься при принятии решения о создании расширения конфигурации…

07.04.2019    26003    ellavs    125       

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

Рекомендуем готовые решения для переноса данных из различных конфигураций 1C. C техподдержкой от разработчиков и гарантией от Инфостарт.

Git-репозитории для 1С-кода (опыт использования при небольших проектах)

Статья Программист Стажер Нет файла v8 Windows Бесплатно (free) Практика программирования Разработка

Инструкции по взаимодействию с Git-репозиторием, которые писались для тех наших программистов, которые вообще никогда не работали с Git (руководства в духе "Как получить код из git-репозитория?", "Как отправить код в git-репозиторий")...

28.03.2019    20779    ellavs    83       

Трюки с внешними источниками данных

Статья Программист Нет файла v8 1cv8.cf Бесплатно (free) Практика программирования Разработка

Некоторые трюки для преодоления ограничений внешних источников данных.

14.03.2019    23078    YPermitin    53       

Базовый курс по обмену данными в системе 1С:Предприятие. Онлайн-интенсив с 12 по 28 мая 2020 г. Промо

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

5500 рублей

Возможности типовых шаблонов ограничения доступа на уровне записей (RLS)

Статья Программист Нет файла v8 v8::Права Бесплатно (free) Практика программирования БСП (Библиотека стандартных подсистем) Роли и права

Краткий обзор применения типовых шаблонов ограничения доступа на уровне записей в конфигурациях, созданных на базе БСП: #ПоЗначениям, #ПоНаборамЗначений, #ПоЗначениямРасширенный, #ПоЗначениямИНаборамРасширенный

03.02.2019    27308    ids79    9