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

Публикация № 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. gzharkoj 06.12.18 10:40 Сейчас в теме
А есть какие-нибудь замеры по выигрышу производительности, хотя бы примерные, на вашей конфигурации?
2. _ASZ_ 104 06.12.18 12:09 Сейчас в теме
(1) Есть опыт увеличения в 7-8 раз скорости восстановления последовательности в одной из крупнейших энергосетевых организации сибирского федерального округа. Но это была не типовая конфигурация.

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

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

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

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

По существу:
Алгоритм генерирует большой объем новых задач и проведение одного документа действительно может приводить к лавинообразному росту заданий и, как следствие, необходимости проведения других документов по другим ключам. Но это происходит ТОЛЬКО когда это следует из логики данных (избыточности нет). Механизм рассчитан на переваривание такой ситуации. Нет необходимости переписывать процедуры проведения документов для реализации возможности проведения только по 1 ключу из нескольких, задетых документом.
Хотя не спорю, если заморочиться и переписать - работать будет быстрее и "лавины" не будет. Но здесь возникает вопрос целесообразности такой работы. Практический опыт показал, что её нет. Если обработка заданий включена онлайн и есть адекватное движение даты запрета редактирования по отношению к точке ввода данных, то критические ситуации маловероятны.
А даже если они случаются - они обрабатываются в фоне практически без влияния на оперативную работу пользователей.
8. DarkAn 947 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_ 104 07.12.18 10:51 Сейчас в теме
(8) 1. Не верно поняли. Когда ФЗ натыкается на ситуацию ожидания - обработка пакета завершается. ФЗ заканчивает свою работу, освобождая "слот" для других ФЗ. В следующий раз по этому ключу ФЗ стартует только при следующем старте управляющего потока. До этого момента - будут обрабатываться другие ключи.
2. В приведенном примере граница сдвигается автоматически при проведении документа.
10. DarkAn 947 07.12.18 13:26 Сейчас в теме
(9)
В приведенном примере граница сдвигается автоматически при проведении документа.

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

Сейчас занимаемся внедрением 1С:ТОиР. Уже введено более 1 млн объектов ремонта, формируются полностью заполненные паспорта ВЛ. Запустили геоинформационную систему, которая позволяет визуализировать сеть и топологию на Яндекс картах.
26. spock 592 09.12.18 17:39 Сейчас в теме
(25)Молодцы, неплохо. По ПУ зря - шикарное и быстрое решение могло получиться. Здорово, что смогли реализовать мои предложения.
27. Anchoret 39 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_ 104 10.12.18 10:17 Сейчас в теме
(27) Вашу ситуацию можно также можно попробовать решить с помощью предложенного алгоритма. Вы вводите в последовательность измерение Договор. Те документы, которые не имеют договора - также должны в эту последовательность попадать (Договор = ПустаяСсылка).

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

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

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

См. также

Многопоточность. Универсальный «Менеджер потоков» 2.1 Промо

Производительность и оптимизация (HighLoad) Инструментарий разработчика Математика и алгоритмы Универсальные функции v8 1cv8.cf Россия Платные (руб)

Восстановление партий или взаиморасчетов, расчет зарплаты, пакетное формирование документов или отчетов - теперь все это стало доступнее. * Есть желание повысить скорость работы медленных алгоритмов! Но... * Нет времени думать о реализации многопоточности? * о запуске и остановке потоков? * о поддержании потоков в рабочем состоянии? * о передаче данных в потоки и как получить ответ из потока? * об организации последовательности? Тогда ЭТО - то что надо!!!

3000 руб.

07.02.2018    74568    184    55    

Описание почти всех событий технологического журнала

Технологический журнал v8 Бесплатно (free)

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

19.08.2020    5123    YPermitin    22    

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

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

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

27.01.2020    25923    ids79    26    

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

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

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

15.01.2020    23279    John_d    22    

Использование программных перечислений, ч.1: строковые константы Промо

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

Часто ли у вас возникает необходимость в коде выполнять сравнение на строку?

10.12.2016    37288    unichkin    74    

Последовательности событий. Шпаргалка

Практика программирования v8 Россия Бесплатно (free)

Собрал информацию о событиях/подписках/расширениях в одном месте.

30.12.2019    17832    kuzyara    33    

Обслуживание баз данных. Не так просто, как кажется

Производительность и оптимизация (HighLoad) Администрирование СУБД v8 1cv8.cf Бесплатно (free)

Считаете, что обслуживание индексов и статистик дело простое? Что ж, это не всегда так.

14.10.2019    17589    YPermitin    28    

Таблица значений. Нюансы

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

Обзор некоторых аспектов использования общеизвестного инструмента 1С.

01.10.2019    32789    Yashazz    50    

Вспомогательные инструкции в коде 1С Промо

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

Помогаем редактору кода 1С помогать нам писать и анализировать код.

15.10.2018    30157    tormozit    100    

[Шпаргалка] Программное создание элементов формы

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

Программное создание практически всех популярных элементов формы.

06.09.2019    49019    rpgshnik    63    

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

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

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

05.09.2019    48796    ids79    54    

Регистры бухгалтерии. Общая информация

Практика программирования Математика и алгоритмы v8 v8::БУ БУ Бесплатно (free)

Общая информация о внутреннем устройстве регистров бухгалтерии.

05.09.2019    28075    YPermitin    24    

Оформление и рефакторинг сложных логических выражений Промо

Практика программирования v8 Россия Бесплатно (free)

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

20.09.2012    77918    tormozit    131    

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

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

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

03.09.2019    25382    YPermitin    80    

Иерархия без "В ИЕРАРХИИ"

Математика и алгоритмы v8 Бесплатно (free)

Говорится о том, как эффективно представлять иерархию в СУБД, как получать и использовать эти представления при решении задач в запросной технике. Уточняются и дополняются запросы из статьи "Уровни, глубина, прародители, циклы и аналоги запросом" [https://infostart.ru/public/160707/].

22.08.2019    12327    ildarovich    19    

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

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

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

17.08.2019    31264    ids79    16    

Запись значения в поле ввода/формы со срабатыванием события ПриИзменении Промо

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

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

11.07.2007    48295    tormozit    41    

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

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

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

08.08.2019    80640    ids79    49    

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

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

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

02.08.2019    34786    avalakh    22    

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

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

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

26.07.2019    58777    ids79    11    

Как сделать из &НаКлиентеНаСервереБезКонтекста почти &НаКлиентеНаСервере Промо

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

Как сделать метод формы, доступный на клиенте и на сервере одновременно, и сохранить при этом удобство разработки

10.09.2017    44704    tormozit    74    

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

Математика и алгоритмы v8 Бесплатно (free)

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

25.07.2019    49682    AlbinaAAA    28    

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

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

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

17.07.2019    35577    ids79    27    

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

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

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

04.07.2019    19589    SeiOkami    50    

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

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

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

25.04.2019    16032    m-rv    2    

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

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

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

25.06.2019    52042    ids79    25    

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

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

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

11.06.2019    24914    dmurk    145    

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

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

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

16.05.2019    42655    YPermitin    30    

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

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

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

16.04.2019    20202    m-rv    17    

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

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

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

18.04.2019    29714    ivanov660    77    

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

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

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

07.04.2019    35227    ellavs    126    

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

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

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

28.03.2019    27335    ellavs    89    

Как сделать запрос на изменение данных Промо

Практика программирования v8 v8::Запросы 1cv8.cf Бесплатно (free)

В статье приведены особенности внутренней архитектуры и примеры работы с расширением языка запросов 1С.

01.06.2018    30536    m-rv    21    

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

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

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

14.03.2019    31238    YPermitin    53    

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

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

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

03.02.2019    39201    ids79    9    

Многопоточная обработка данных Промо

Производительность и оптимизация (HighLoad) Администрирование данных 1С v8 v8::УФ 1cv8.cf Абонемент ($m)

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

1 стартмани

23.11.2018    20472    59    _ASZ_    15    

Новый подход к обмену данными EnterpriseData

Практика программирования Обмен через XML v8 v8::УФ Россия Бесплатно (free)

Хочу предложить Вашему вниманию цикл статей, посвященных обмену данными через универсальный формат (EnterpriseData или ED).

14.12.2018    41286    ids79    72    

Универсальные функции ЗУП 3.1 / ЗКГУ 3.1, которые помогут в разработке

Универсальные функции Зарплата Управление персоналом (HRM) Зарплата v8 v8::СПР ЗКГУ3.0 ЗУП3.x БУ Бесплатно (free)

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

14.11.2018    86599    GeterX    114    

Автоматические и управляемые блокировки применительно к типовым конфигурациям 1С

Математика и алгоритмы Практика программирования v8 v8::blocking 1cv8.cf Бесплатно (free)

Основные принципы работы с режимами автоматических и управляемых блокировок в 1С Предприятие 8. Теория и применение в типовых конфигурациях: БП, УТ, ЕРП

10.11.2018    34610    ids79    40    

Метод формирования движений в типовых регистрах нетиповыми регистраторами Промо

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

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

05.12.2017    28223    itriot11    34    

Новый режим реструктуризации (обновление базы данных на сервере в режиме v2)

Производительность и оптимизация (HighLoad) v8 1cv8.cf Бесплатно (free)

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

31.10.2018    28445    Dach    51    

Произвольный код в фоновом режиме

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

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

03.09.2018    27904    zarankony    42    

Основные понятия и механизмы оптимизации клиент-серверного взаимодействия в 1C

Математика и алгоритмы Практика программирования v8 Россия Бесплатно (free)

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

23.08.2018    38398    Rain88    46    

Использование классов .Net в 1С для новичков Промо

Практика программирования Разработка внешних компонент Универсальные функции v7.7 v8 Бесплатно (free)

Руководство для новичков. Написав статью http://infostart.ru/public/238584/, я понял, что многие не понимают того, что написано. Поэтому в этой статье постараюсь более подробно остановиться на азах и без кода на вражеском языке (C#)

27.01.2016    76278    Serginio    108    

Тестер: частые вопросы

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

Ошибкам бой - тесты норма жизни!

25.07.2018    29195    grumagargler    28    

Повышаем эффективность разработки правил обмена

Практика программирования Перенос данных из 1C8 в 1C8 v8 КД Бесплатно (free)

Как повысить скорость и качество разработки правил обмена? Как вести групповую разработку правил обмена? Как облегчить сопровождение правил обмена после передачи в эксплуатацию? Об этом и многом другом вы можете узнать из этой статьи.

25.06.2018    28314    olegtymko    47    

Введение в механизм представлений в ЗУП ред. 3

Практика программирования v8 v8::СПР ЗУП3.x Бесплатно (free)

В нашей организации на первом же телефонном собеседовании на должность разработчика по ЗУП ред. 3 вас обязательно спросят о том, что такое "Представления".

04.06.2018    38210    xrrg    84