Планы обмена. Управляемый режим блокировок

08.12.16

Интеграция - Перенос данных 1C

Статья о том, как устроен объект конфигурации 1С:Предприятие 8 "План обмена", в том числе на уровне СУБД SQL Server. Анализируются особенности его использования при управляемом режиме блокировок.

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

Работа с РИБ в рамках данной статьи рассмотрена не будет, так как РИБ полностью основан на описанных в статье механизмах.

Структуры данных.

План обмена на уровне СУБД это таблица, которая имеет название вида "_Node[N]", где N - это внутренний числовой код типа данных 1С:Предприятие 8. В данном случае этот код будет соответствовать плану обмена.

Создадим тестовый план обмена. В конфигураторе 1С (изображение слева) и в SQL Server Management Studio (изображение справа) это будет выглять следующим образом:

Как мы видим по структуре таблицы справа, план обмена очень похож на справочник. Это тоже ссылочный тип данных. Однако, от справочников его отличает то, что он не может иметь групп и быть иерархическим.

Структура таблицы "_Node69" плана обмена "Тестовый"

  Наименование поля      Имя реквизита   Описание поля
 _IDRRef  Ссылка  Ссылка на узел плана обмена
 _Version  Версия записи таблицы СУБД
 _Marked  ПометкаУдаления  Пометка удаления
 _Code  Код  Код узла
 _Description  Наименование  Наименование узла
 _SentNo  НомерОтправленного    Номер отправленного сообщения
 _ReceivedNo  НомерПринятого  Номер принятого сообщения
 _PredefinedID  Идентификатор предопределённого элемента  

Следует отметить, что при создании плана обмена, платформа автоматически создаёт предопределённый узел, соответствующий текущей информационной базе, в которой он создаётся. Реквизиты "Код" и "Наименование" по умолчанию имеют пустые значения, их необходимо заполнить самостоятельно. Для того, чтобы убедиться в этом, выполним следующий код в SQL Server Management Studio:

После того, как мы добавили план обмена, необходимо включить в его состав какой-нибудь объект, чтобы начать ослеживать изменения его данных. Включим в наш тестовый план обмена справочник "Номенклатура". После сохранения конфигурации платформа создаёт для этого справочника служебную таблицу регистрации изменений. Такую таблицу платформа создаёт для каждого включённого в план обмена объекта. Если объект включается в состав нескольких планов обмена, то таблица для регистрации изменений на уровне СУБД используется одна и та же.

Структура таблицы "_ReferenceChngR71" справочника "Номенклатура".

Наименование поля Имя Реквизита Описание поля
 _NodeTRef  Узел  Код типа плана обмена, например, у плана обмена "Тестовый" этот код равен значению "69".
 _NodeRRef  Узел  Ссылка на узел плана обмена
 _MessageNo  НомерСообщения   Номер сообщения, в котором данное изменение было выгружено для соответствующего узла плана обмена
 _IDRRef  Ссылка  Ссылка на элемент справочника "Номенклатура", который изменился

Таким образом, таблица регистрации изменений состоит из трёх обязательных полей и одного и более полей, которые необходимы для поиска изменившихся данных в основной таблице объекта. Для ссылочных типов данных таких, как справочники или документы, достаточно одного поля - "Ссылка". Однако для табличных типов данных, как, например, регистры сведений или регистры накопления, этих полей может быть несколько. Это зависит от установленного для измерений таких объектов свойства "Основной отбор". Более подробно об этом можно прочитать в книге "Профессиональная разработка в системе 1С:Предприятие 8. Издание 2." на странице 484.

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

Индексы таблиц регистрации изменений.

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

1. Ключ + Узел (кластерный).

2. Узел + Номер сообщения + Ключ.

Момент выполнения регистрации изменений.

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

1. Начало транзакции записи документа.

2. ПередЗаписью.

3. ПередЗаписью (подписка на событие).

4. ПриЗаписи.

5. ПриЗаписи (подписка на событие).

6. ОбработкаПроведения.

7. ОбработкаПроведения (подписка на событие).

8. Регистрация изменения объекта во всех планах обмена, в состав которых он входит, а также для всех узлов этих планов обмена.

9. Фиксация транзакции записи документа.

Почему важно понимать в какой момент происходит регистрация изменений? И почему я привёл в пример именно документ? Дело в том, что регистрация изменений выполняется в одной транзакции с записью и проведением документа. Это обеспечивает согласованность этих двух операций: проведения и регистрации. Следовательно, любая логика регистрации изменений влияет на продолжительность этой транзакции, а также на момент выполнения запроса на блокировку записей таблицы регистрации изменений. В высоко нагруженных системах такой запрос часто приводит к ожиданию на блокировках, которые ранее уже наложила, например, процедура выгрузки изменений. Далее в статье я расскажу об этом более подробно.

Регистрация изменений.

Для регистрации изменения выполним следующий код 1С:

Если мы воспользуемся SQL Server Profiler и посмотрим, что происходит при вызове процедуры "ЗарегистрироватьИзменения", то мы увидим следующий код (для удобства восприятия код немного "причёсан"):

Как мы видим, на 2-ом шаге транзакции 1С сразу же пытается наложить эксклюзивную блокировку на запись регистрации изменения элемента справочника "Номенклатура" по соответствующему узлу плана обмена. Кроме этого, предпринимается попытка установить своеобразный флаг, сигнализирующий о том, что это изменение необходимо выгрузить в новом/следующем сообщении обмена. Этим флагом является реквизит "НомерСообщения" (поле "_MessageNo"), значение которого устанавливается равным NULL.

Обратите внимание, что если мы изменим один и тот же объект несколько раз, то запись изменений для этого объекта будет только одна. Это ключевая особенность планов обмена! Фактически это делает такую запись дефицитным ресурсом, за захват которого конкурируют разные транзакции. Если быть более точным, то таким ресурсом является поле "_MessageNo" этой записи.

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

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

Кроме этого очень важно то, что изменение регистрируется для всех узлов плана обмена. То есть если бы в нашем плане обмена было 10 узлов, то изменение одного объекта потребовало бы создания 10 записей, 100 узлов - 100 записей и так далее. И это только для одного изменения. Этот факт тоже важно учитывать.

Просмотр изменений.

Теперь попробуем изменить что-нибудь в нашем справочнике "Номенклатура" и посмотрим как это отразится в таблице регистрации изменений. Для этого можно воспользоваться следующими запросами 1С или T-SQL:

Запрос = Новый Запрос();
Запрос.Текст = "ВЫБРАТЬ * ИЗ Справочник.Номенклатура.Изменения";
SELECT * FROM [_ReferenceChngR71]

Однако, мы ничего не увидим ... Дело в том, что регистрация изменений выполняется только в контексте узлов плана обмена. Это ещё одна ключевая особенность этого объекта конфигурации: все изменения регистрируются только в контексте какого-нибудь узла обмена. Поэтому добавляем новый узел в созданный ранее план обмена "Тестовый", и пытаемся изменить что-нибудь в справочнике "Номенклатура" снова. После этого проверяем таблицы изменений ещё раз и видим, что там появились записи.

Удаление регистрации изменений.

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

На этот раз 1С ограничивается одной командой SQL, пытаясь наложить всю ту же самую эксклюзивную блокировку по тому же самому ключу, что в общем-то ожидаемо и вполне нормально:

Запись изменений в сообщение обмена.

Для того, чтобы выгрузить изменения в другой узел распределённой информационной системы, необходимо эти изменения сначала прочитать, а затем записать в сообщение обмена. Механизм обмена сообщениями тесно интегрирован с планами обмена. В данном случае имеется в виду то, что запись сообщения обмена в файл сопровождается изменением реквизита "НомерСообщения" в таблице регистрации изменений объекта и ревизита "НомерОтправленного" в таблице плана обмена для соответствующего узла, для которого выполняется выгрузка данных. Чтобы реализовать всё это необходимо использовать объект "ЗаписьСообщенияОбмена". Именно этот объект позволяет нам управлять номером отправляемого сообщения: получать новый порядковый номер, записывать его в сообщение обмена, в таблицу регистрации изменений и реквизит узла плана обмена.

Чтобы исследовать код, который необходимо выполнить для записи сообщения обмена, я настроил технологический журнал 1С на регистрацию событий TLOCK, EXCP и TTIMEOUT. Эти события позволяют анализировать установление управляемых блокировок и ошибок, связанных с неудачными попытками установить их. Кроме этого я настроил SQL Server Profiler, чтобы посмотреть какие запросы платформа 1С генерирует на уровне СУБД.

Версия платформы 1С:Предприятие 8.3.7.2027. Управляемый режим блокировок.

// 0. Подготавливаем необходимые объекты.
ФайлСообщенияОбмена = "C:\export\message.xml";
ЗаписьXML = Новый ЗаписьXML();
ЗаписьXML.ОткрытьФайл(ФайлСообщенияОбмена);

УзелОбмена = ПланыОбмена.Тестовый.НайтиПоНаименованию("Тестовый узел", Истина);

// 1. Создаём объект "ЗаписьСообщенияОбмена".
ЗаписьСообщения = ПланыОбмена.СоздатьЗаписьСообщения();

// 2. Начинаем запись сообщения для выбранного узла в файл XML.
ЗаписьСообщения.НачатьЗапись(ЗаписьXML, УзелОбмена);

В книге "Профессиональная разработка в системе "1С:Предприятие 8" (издание 2) от 2012 года на странице 491 написано следующее:

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

Если посмотреть ТЖ 1С, то там мы не увидим установки блокировки. Значит управляемая блокировка не устанавливается. На уровне СУБД мы увидим обычный запрос, который характерен для вызова метода ссылки "ПолучитьОбъект":

SELECT
	T1._IDRRef,
	T1._Version,
	T1._Marked,
	T1._Code,
	T1._Description,
	T1._SentNo,
	T1._ReceivedNo,
	T1._PredefinedID
FROM
	dbo._Node69 T1 -- План обмена "Тестовый"
WHERE
	T1._IDRRef = 0x9BD9408D5C93CC8E11E6A9E8C5C37A96 -- Узел обмена "Тестовый узел"

Постольку поскольку наша конфигурация находится в режиме управляемых блокировок, то такой запрос не является блокирующим. Блокировок нет. В книге ошибка? Давайте попробуем зарегистрировать какое-нибудь изменение по нашему узлу. Воспользуемся кодом из раздела "Регистрация изменений". Но сначала убедимся, что изменение уже есть, выполнив код SQL:

Получается в данный момент мы пытаемся выгрузить сообщение, которое ранее уже выгружалось под номером 13. Повторная выгрузка. В данный момент первая сессия 1С остановлена в точке останова после выполнения метода "НачатьЗапись". Теперь откроем вторую сессию 1С и попробуем зарегистрировать изменение этого объекта ещё раз в тот момент как оно отправляется:

ПланыОбмена.ЗарегистрироватьИзменения(УзелОбмена, СсылкаДляОбмена);

Теперь проверим, что изменилось:

Ошибок блокировки не было. Поле "_MessageNo" изменилось, сигнализируя нам, что его необходимо выгрузить. Так какая же блокировка имелась ввиду в книге? Неужели всё-таки ошибка? Ошибки никакой нет. Чтобы убедиться в этом выполним в сессии № 2 следующий код 1С:

Узел = ПланыОбмена.Тестовый.НайтиПоНаименованию("Тестовый узел", Истина);
Объект = Узел.ПолучитьОбъект();
Объект.Заблокировать();

В результате мы получим следующее сообщение об ошибке (эту же ошибку мы увидим в ТЖ, событие EXCP):

{ВнешняяОбработка.ИсследованиеПлановОбмена.МодульОбъекта(103)}: Ошибка при вызове метода контекста (Заблокировать): Не удалось заблокировать запись. Действие (изменение, удаление или блокировка записи) не выполнено.
Ошибка блокировки объекта. Объект уже заблокирован:
компьютер: Zhichkin, сеанс: 45, начат: 24.11.2016 в 1:00:46, приложение: Толстый клиент

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

// 3. Выбираем изменения для выгрузки
Выборка = ПланыОбмена.ВыбратьИзменения(УзелОбмена, ЗаписьСообщения.НомерСообщения);
BEGIN TRANSACTION

UPDATE
	[_ReferenceChngR71] -- Таблица регистрации изменений
SET
	[_MessageNo] = 26 -- Очередной номер отправленного сообщения
WHERE
	[_NodeTRef] = 0x00000045 -- План обмена "Тестовый"
	AND
	[_NodeRRef] = 0x9BD9408D5C93CC8E11E6A9E8C5C37A96 -- Узел "Тестовый узел"
	AND
	[_MessageNo] IS NULL -- Устанавливаем номер для ещё не отправленных сообщений

-- Выбираем все изменения, в том числе отправленные в других сообщениях
SELECT
	[_IDRRef]
FROM
	[_ReferenceChngR71]
WHERE
	[_NodeTRef] = 0x00000045
	AND
	[_NodeRRef] = 0x9BD9408D5C93CC8E11E6A9E8C5C37A96

COMMIT TRANSACTION

Этот код будет выполнен для всех типов объектов, которые включены в состав плана обмена. Каждый тип в своей собственной транзакции. На время транзакции будет установлена эксклюзивная транзакционная блокировка SQL Server на все записи узла, которые ещё не отправлялись. Это означает, что повторное изменение уже заблокированных объектов будет ожидать окончания этой транзакции, а, в случае превышения времени ожидания, будет сгенерировано сообщение об ошибке:

При этом если мы зарегистрируем по этому узлу и типу объекта новое изменение, то оно успешно запишется. Более того, если это произойдёт до команды SELECT, то в выборку изменений попадут и эти новые изменения. Что интересно номер отправленного у них будет равен NULL, хотя это совершенно не так.

Кроме этого если записей будет более 5000, то может произойти эскалация блокировок SQL Server. В таком случае может оказаться заблокированной вся таблица. Чтобы этого не происходило, администраторы баз данных часто отключают на уровне SQL возможность возникновения такой эскалации, однако это не запрещает эскалации до уровня страниц (имеют размер 8 Kb), что может приводить к избыточной блокировке записей не попадающих в условия отбора команды UPDATE, но находящихся на одной странице вместе с нужными записями.

Таким образом к негативным последствиям выполнения операции выборки изменений можно отнести следующие:

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

2. Избыточные блокировки при больших объёмах изменений из-за эскалации блокировок SQL Server. Усугубляет последствия первого пункта.

3. Рассогласованность нумерации сообщений для новых регистраций объектов, которые не попали в первоначальный UPDATE. Следствием этого может быть повторная выгрузка одних и тех же данных.

Все выбранные изменения обрабатываются в оперативной памяти. Это происходит в следующем цикле:

// 4. Обработка выбранных изменений
Пока Выборка.Следующий() Цикл
	Данные = Выборка.Получить();
	ЗаписатьXML(ЗаписьXML, Данные);
КонецЦикла;

На этом этапе на уровне SQLServer ничего интересного не происходит: выполнение метода Выборка.Получить() получает данные объекта по его ссылке так, как если бы мы вызвали метод Ссылка.ПолучитьОбъект() или Набор.Прочитать(). Единственным недостатком можно назвать то, что это выполняется в цикле для каждого объекта, что трудно назвать оптимальным решением. Каждый объект записывается в сообщение обмена в формате XML. Это самый длительный этап выгрузки данных. К сожалению его практически невозможно распараллелить, так как запись ведётся в один файл.

В случае успешной записи сообщения обмена, завершаем сеанс выгрузки данных:

// 5. Завершаем сеанс выгрузки данных
ЗаписьСообщения.ЗакончитьЗапись();
UPDATE
	[_Node69] -- План обмена "Тестовый"
SET
	[_Marked]       = 0x00,
	[_Code]         = N'1',
	[_Description]  = N'Тестовый узел',
	[_SentNo]       = 26, -- Номер только что отправленного сообщения обмена
	[_ReceivedNo]   = 0,
	[_PredefinedID] = 0x00000000000000000000000000000000
WHERE
	[_IDRRef] = 0x9BD9408D5C93CC8E11E6A9E8C5C37A96 -- Узел "Тестовый узел"
	AND
	[_Version] = 0x00000000000077E8

Завершение сеанса выгрузки заключается в том, что для соответствующего узла плана обмена записывается номер только что отправленного сообщения обмена и вызывается метод объекта "Записать". В результате этого на узел плана обмена устанавливается управляемая блокировка - в техническом журнале 1С фиксируется событие TLOCK. Это очень короткая транзакция.

Чтение изменений из сообщения обмена.

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

ЧтениеXML = Новый ЧтениеXML();
ЧтениеXML.ОткрытьФайл(ПолноеИмяФайла);
ЧтениеСообщения = ПланыОбмена.СоздатьЧтениеСообщения();
ЧтениеСообщения.НачатьЧтение(ЧтениеXML, ДопустимыйНомерСообщения.Больший);
Пока ВозможностьЧтенияXML(ЧтениеXML) Цикл
    Данные = ПрочитатьXML(ЧтениеXML);
    Данные.ОбменДанными.Отправитель = ЧтениеСообщения.Отправитель;
    Данные.ОбменДанными.Загрузка = Истина;
    Данные.Записать();
КонецЦикла;
//ПланыОбмена.УдалитьРегистрациюИзменений(ЧтениеСообщения.Отправитель, ЧтениеСообщения.НомерПринятого); 
ЧтениеСообщения.ЗакончитьЧтение();

Заключение.

Плюсы планов обмена:

    1. Простота программирования и настройки.

Минусы планов обмена:

    1. Избыточные блокировки данных.

    2. Конфликты блокировок транзакций.

    3. Регистрация одного изменения для каждого узла. На мой взгляд это избыточно, а кроме того интегрирует логику маршрутизации сообщений в подсистему регистрации изменений. Нарушается архитектурный принцип разделения ответственности между программными компонентами.

    4. Гранулярность обработки данных - узел обмена.

    5. Дублирование выгрузки данных.

    6. Плохие возможности для распараллеливания процессов.

    7. Тесная интеграция механизма регистрации изменений и инфраструктуры сообщений (их нумерация) диктует свои правила и ограничивает возможности реализации каких-то своих оптимизационных решений. См. также пункт 3.

план обмена обмен данными интеграция регистрация изменений

См. также

SALE! 10%

Перенос данных 1C Программист Платформа 1С v8.3 1С:Управление производственным предприятием 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Платные (руб)

Перенос документов, начальных остатков и справочной информации из УПП 1.3 в ERP 2 | из УПП 1.3 в УТ 11 | из УПП в КА 2 | Правила конвертации (КД 2) | Более 360 предприятий выполнили переход с использованием этого продукта! | Сэкономьте время - используйте готовое решение для перехода! | Позволяет перенести из УПП 1.3 в ERP / УТ 11 / КА 2 всю возможную информацию | В переносе есть фильтр по организации и множество других опциональных параметров выгрузки | Есть несколько алгоритмов выгрузки остатков на выбор

55778 50200 руб.

04.08.2015    166459    333    277    

373

SALE! 20%

Перенос данных 1C Файловый обмен (TXT, XML, DBF), FTP Системный администратор Программист Платформа 1С v8.3 1С:Розница 2 1С:Управление нашей фирмой 1.6 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 1С:Розница 3.0 Россия Платные (руб)

Правила в универсальном формате обмена для ERP 2.5, КА 2.5, УТ 11.5, БП 3.0, Розница, УНФ, для последних версий конфигураций. Ссылки на другие конфигурации в описании публикации. Правила совместимы со всеми другими версиями конфигураций новыми и старыми, поддерживающими обмен и синхронизацию в формате EnterpriseData. Не требуется синхронного обновления правил после обновления другой конфигурации, участвующей в обмене. Типовой обмен через планы обмена кнопкой Синхронизация вручную или автоматически по расписанию, или вручную обработкой.

26280 22338 руб.

12.06.2017    141508    798    297    

419

SALE! 10%

Перенос данных 1C Файловый обмен (TXT, XML, DBF), FTP Системный администратор Программист Платформа 1С v8.3 1С:Управление производственным предприятием 1С:Бухгалтерия 3.0 Россия Бухгалтерский учет Управленческий учет Платные (руб)

Перенос данных из 1С:Управление производственным предприятием 1.3 в 1С:Бухгалтерия предприятия 3.0 с помощью правил обмена. Переносятся остатки, документы (обороты за период), справочная информация. Правила проверены на конфигурациях УПП 1.3 (1.3.234.x) и БП 3.0 (3.0.161.x). Правила подходят для версии ПРОФ и КОРП.

35000 31500 руб.

15.12.2021    24012    169    51    

127

SALE! 10%

Перенос данных 1C Файловый обмен (TXT, XML, DBF), FTP Системный администратор Программист Платформа 1С v8.3 Оперативный учет 1С:Управление торговлей 10 Россия Управленческий учет Платные (руб)

Перенос данных из 1С:Управление торговлей 10.3 в 1С:Управление торговлей 11.5 с помощью правил обмена. Переносятся остатки, документы (обороты за период), справочная информация. Правила проверены на конфигурациях УТ 10.3 (10.3.88.x) и УТ 11.5 (11.5.19.x).

35000 31500 руб.

23.07.2020    51240    228    69    

185

SALE! 10%

Перенос данных 1C Файловый обмен (TXT, XML, DBF), FTP Программист Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Комплексная автоматизация 2.х 1С:Зарплата и Управление Персоналом 3.x Россия Бухгалтерский учет Управленческий учет Платные (руб)

Перенос данных из ERP в ЗУП 3 | из КА 2 в ЗУП | Готовые правила конвертации данных (КД 2) для переноса остатков, документов с движениями и справочной информации 3 | Есть перенос начальной задолженности по зарплате и начальной штатной расстановки на выбранную дату | Обороты за прошлые годы (данные для расчета среднего) переносятся свернуто в документ "Перенос данных" | Есть фильтр по организациям | Документы за текущий период переносятся сразу с движениями, поэтому не потребуется делать перерасчеты | Перенос можно проверить перед покупкой, обращайтесь!

53111 47800 руб.

03.12.2020    36584    94    66    

89

SALE! 10%

Перенос данных 1C Файловый обмен (TXT, XML, DBF), FTP Программист Платформа 1С v8.3 Сложные периодические расчеты 1С:Комплексная автоматизация 1.х 1С:Управление производственным предприятием 1С:Зарплата и Управление Персоналом 3.x Россия Бухгалтерский учет Платные (руб)

Правила переноса кадровых и расчетных данных и справочной информации из "1С:УПП1.3" или "1С:КА 1.1" в "1С:ЗУП 3.1 | Разработан в формате КД 2 (правила конвертации данных) | При выгрузке есть фильтр по организациям | Обновляется при выходе новых релизов 1С | Развитие алгоритмов | Расчетные документы переносятся в документ "Перенос данных" | Создаются документы "Начальная штатная расстановка" и "Начальная задолженность по зарплате", переносятся кадровые документы

55778 50200 руб.

29.10.2018    56207    59    105    

61

SALE! 10%

Перенос данных 1C Файловый обмен (TXT, XML, DBF), FTP Системный администратор Программист Платформа 1С v8.3 1С:Комплексная автоматизация 1.х 1С:Управление производственным предприятием 1С:Бухгалтерия 3.0 Россия Бухгалтерский учет Платные (руб)

Перенос данных из 1С:Управление производственным предприятием 1.3 в 1С:Бухгалтерия предприятия 3.0 с помощью правил обмена | Можно выполнить переход с УПП на БП 3 или запускать выгрузку данных за выбранный период времени | Переносятся документы, начальные остатки и вся справочная информация | Есть фильтр по организации и множество других параметров выгрузки | Поддерживается несколько сценариев работы: как первичный полный перенос, так и перенос только новых документов | Перенос данных возможен в "1С: Бухгалтерия 3.0" версии ПРОФ, КОРП или базовую | Переход с "1С: УПП1.3" / "1С:КА 1.1" на "1С:БП3.0" с помощью правил конвертации будет максимально комфортным! | Можно бесплатно проверить перенос на вашем сервере!

48278 43450 руб.

25.02.2015    171171    303    257    

378

SALE! 15%

Перенос данных 1C Файловый обмен (TXT, XML, DBF), FTP Системный администратор Программист Платформа 1С v8.3 Платформа 1C v8.2 1С:Комплексная автоматизация 1.х 1С:Управление торговлей 10 1С:Управление производственным предприятием Россия Платные (руб)

Регулярный обмен, выгрузка, перенос из КА 1.1, УПП 1.3, УТ 10.3 для обмена с любыми конфигурациями, поддерживающими обмен в формате EnterpriseData (КД3) - БП 3.0, ERP, КА 2, УТ 11, Розница 2, УНФ 1.6 и другими. Правила для старых и доработанных конфигураций не требуют синхронного обновления и совместимы с новыми и будущими конфигурациями. Обмен по расписанию, через папку, FTP, почту.

15300 13005 руб.

18.02.2016    186873    589    509    

526
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. Evil Beaver 8244 28.11.16 16:14 Сейчас в теме
Я, может быть, не прав, но по-моему, транзакция начинается еще до момента вызова ПередЗаписью. Т.е. в обработчике ПередЗаписью транзакция уже открыта.
2. zhichkin 1524 28.11.16 17:35 Сейчас в теме
(1) Вы абсолютно правы! Спасибо за замечание. Поправил.
3. headMade 144 28.11.16 17:42 Сейчас в теме
Посмотрите - вроде часть скринов пропала. Например там где "выполнив код SQL:".
Tamadosky; user865160; bulpi; +3 Ответить
4. zhichkin 1524 28.11.16 17:44 Сейчас в теме
(3) Да, есть такое дело. Честно говоря, устал бороться с этим явлением =(
5. spezc 792 29.11.16 12:52 Сейчас в теме
Так как в итоге то? Какое лекарство, когда например 100 узлов решили обменяться информацией с центром?
EMelihoff; +1 Ответить
7. zhichkin 1524 04.12.16 16:59 Сейчас в теме
(5) Прошу прощения, но Вы бы не могли уточнить, что конкретно имеется ввиду? Например, я понял вопрос так: есть 100 входящих сообщений обмена для центральной базы. Вероятно это РИБ. Если каждое сообщение имеет по 1 объекту, то я не вижу в этом вообще никакой проблемы ... Дайте, пожалуйста, цифры.
8. zhichkin 1524 04.12.16 20:43 Сейчас в теме
(5) Если отвечать на Ваш вопрос глобально, то, при условии, что были исчерпаны все варианты оптимизации планов обмена, нужно использовать альтернативные варианты. Например, можно использовать свою реализацию регистрации изменений. Это как минимум. Некоторые размышления по этому поводу я зафиксировал здесь. Есть и другие публикации по этому поводу. Ссылки на них можно найти в моём профиле.

В ближайшее время я планирую сделать ещё пару публикаций на тему того как можно оптимизировать работу планов обмена. Если проблемы серьёзные и требуется частная консультация, то я готов оказать посильную помощь. Пишите в личку.
11. sommid 11.01.17 18:07 Сейчас в теме
(8)
В ближайшее время я планирую сделать ещё пару публикаций на тему того как можно оптимизировать работу планов обмена

- если не сложно, то отпишитесь в комментариях этой темы. Интересно будет почитать. Спасибо.
6. tormozit 7230 29.11.16 14:57 Сейчас в теме
9. kolya_tlt 88 11.01.17 13:53 Сейчас в теме
Добрый день.
было бы здорово добавить в статью информацию по автоматическому режиму или отличий с управляемым
10. zhichkin 1524 11.01.17 15:07 Сейчас в теме
(9) Тут не так много мест где будут отличия. Пожалуй это все те места, где выполняется команда SELECT. Если Вы хорошо понимаете разницу между READ COMMITED (автоматический режим) и READ COMMITED SNAPSHOT (управляемый режим), то без труда поймёте где и какая разница возникает.

Если отвечать упрощённо, то разница между этими двумя режимами такова, что:
1. При чтении данных:
в первом случае мы получаем версию записи после её изменения в другой транзакции. При этом мы ждём её завершения (нас блокируют - мы ждём, чтобы прочитать). А в случае со snapshot, мы получаем версию записи, которая была до начала второй транзакции. При этом мы ничего не ждём и допускаем "грязное чтение".
2. В процессе чтения данных:
в первом случае мы блокируем транзакции, которые желают изменить данные, которые мы читаем (мы блокируем - нас ждут, чтобы изменить). А в случае со snapshot мы никого не блокируем.

Некоторые могут подумать, что в первом случае прочитанные нами данные блокируются до конца транзакции, но это не так. Уточняю: речь идёт о первом случае (автоматический режим блокировок), когда опция read_commited_snapshot на уровне базы данных имеет значение OFF (выключено).
Это зависит от режима изоляции транзакции. В случае с планами обмена используется режим изоляции транзакции SQL Server по умолчанию, а он чаще всего равен READ COMMITED, то есть данные блокируются только на время их чтения.
То есть одна запись блокируется пока она читается в выборку, затем блокировка снимается, делается попытка получить разрешение на чтение следующей записи, устанавливается блокировка чтения и читается следующая запись. И так до тех пор, пока все, попавшие в условие отбора, записи не будут прочитаны.
13. kolya_tlt 88 12.01.17 09:26 Сейчас в теме
(10)
А в случае со snapshot, мы получаем версию записи, которая была до начала второй транзакции. При этом мы ничего не ждём и допускаем "грязное чтение".

хм, где про снэпшот такую информацию пишут ? мне казалось COMMTITED исключает грязное чтение
14. zhichkin 1524 12.01.17 14:01 Сейчас в теме
(13) Очень много информации по этим вопросам можно найти в сети Интернет, например:
https://msdn.microsoft.com/ru-ru/library/tcbchxcb(v=vs.110).aspx
https://habrahabr.ru/post/305600/
15. zhichkin 1524 12.01.17 14:06 Сейчас в теме
(13) Коротко отвечу всё же:
READ COMMITTED - это уровень изоляции транзакций, как правило, используемый SQL Server.
read_committed_snapshot - это опция уровня базы данных, которая может изменять поведение уровня изоляции READ COMMITTED, принятое по умолчанию. По умолчанию read_committed_snapshot = OFF. Однако при включении управляемого режима блокировок 1С переключает это значение в положение ON. Это меняет поведение уровня изоляции транзакций READ COMMITTED принятое по умолчанию.
1cprogr_nsk; +1 Ответить
16. VVi3ard 52 06.09.17 09:55 Сейчас в теме
Интересная статья, для полноты не хватает описания того как работает платформа при использовании: ЗаписатьИзменения, и особенно в части работы параметра "ЭлементовВТранзакции".
17. EvgeniyEY 15.06.20 18:01 Сейчас в теме
Полезная статья, спасибо.
18. Sirruf 195 28.01.21 11:19 Сейчас в теме
А кто-нибудь задумывался почему ВыбратьИзменения() выполняется в транзакции? Что произойдет (сломается), если гипотетически убрать транзакцию?
19. zhichkin 1524 28.01.21 11:58 Сейчас в теме
(18) Можно легко предположить что будет. При управляемых блокировках SEL ECT будет выполняться как READ COMMITTED SNAPSHOT, так как BEGIN TRANSACTION вызывается без параметров, а следовательно с уровнем изоляции транзакции используемой SQL Server по умолчанию. По умолчанию это READ COMMITTED. Так как 1С включает на своих базах данных параметр read_committed_snapshot равным значению 1 (включено), то имеем в итоге READ COMMITTED SNAPSHOT.
SELECT is_read_committed_snapshot_on FR OM sys.databases WHERE name = '1c_database_name';

Таким образом если вынести UPDATE и SELECT в разные транзакции, то от этого ничего не изменится. Если выполнить UPDATE без явного объявления транзакции BEGIN TRANSACTION, то в любом случае эта команда будет выполняться в неявной транзакции с уровнем изоляции по умолчанию.
Короче говоря, таким образом можно уменьшить время выполнения транзакции и удержания эксклюзивных блокировок, установленных командой UPDATE, на время выполнения SELECT. В некоторых случаях это может облегчить жизнь, но не думаю, что это принципиально менят ситуацию с блокировками на таблицах изменений планов обмена.
20. Sirruf 195 28.01.21 13:41 Сейчас в теме
(19) То есть вы согласны с моим мнением, что транзакция в данном случае избыточна?
22. zhichkin 1524 28.01.21 14:21 Сейчас в теме
(20) Да, это очевидно: SELECT нужно убирать из транзакции.
24. Sirruf 195 28.01.21 18:08 Сейчас в теме
(22) Хорошо, попробуем на партнерском форуме написать об этом разработчикам :)
21. Sirruf 195 28.01.21 13:46 Сейчас в теме
Таким образом, для решения проблемы с блокировками нам нужно выбирать изменения порциями, то есть передавать в качестве третьего параметра в функцию ВыбратьИзменения() предварительно подготовленный массив объектов, размер которого не приведет к длительным блокировкам и эскалациям.
23. zhichkin 1524 28.01.21 14:26 Сейчас в теме
(21) Косвенно пишу об этом в своей статье "Анализ блокировок СУБД: таблица изменений плана обмена 1С", пункт 4 "Анализ технологического журнала 1С":
Разница заключается в использовании временной таблицы для передачи фильтра в виде массива ссылок в метод менеджера планов обмена "ВыбратьИзменения". Это говорит о том, что в каких-то случаях 1С считает, что массив достаточно большой, чтобы начать использовать временную таблицу. Экспериментальным путём удалось выяснить, что количество ссылок в массиве, начиная с которого создаётся временная таблица, равно 129. Создание временной таблицы означает нагрузку на tempdb и дисковую систему сервера СУБД. Это может влиять на продолжительность выполнения всего метода "ВыбратьИзменения" (транзакции СУБД), особенно учитывая тот факт, что в нём выполняются последовательно сначала UPDATE, а только затем SELECT.

Для решения проблем блокировок мой совет: не используйте механизм планов обмена =)
25. alexander-lubich 19 14.07.22 15:24 Сейчас в теме
(23) Дмитрий , интересно Ваше мнение по вопросу "Когда заканчивается Enterprise Data и начинается RabbitMQ ?"

http://forum.infostart.ru/forum15/topic284494/message2848287/#message284828

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

да книжка классная , сейчас читаю.
Прикрепленные файлы:
PROGRAMMING_Shablony_integratsii_korporativnykh_prilozhenii_774.pdf
26. Sander80 100 21.08.24 00:48 Сейчас в теме
Статья старая, возможно, никто не ответит, но вдруг...

Есть ли понимание, ВыбратьИзменения примерно в цикле идет по всем метаданным и делает Update, а за ним Select?

Не следует ли из этого опасность дедлока, если он апдейтом заблокировал справочник1, тут кто-то другой меняет что-то в справочнике 2 и хочет пойти в 1...

В таком случае выглядит разумным сначала самому сделать select в цикле и установить управляемые блокировки по всем метаданным
27. zhichkin 1524 21.08.24 01:44 Сейчас в теме
(26) Статья старая, но до сих пор актуальная =)
Отвечаю коротко:
1. Да, выборка изменений по типам метаданных идёт в цикле.
2. Дэдлоков быть не должно, так как порядок следования этих типов в цикле гарантируется системой.
3. Предварительная выборка ссылок/ключей из таблиц регистрации изменений это одна из широко известных и хорошо описанных методик оптимизации. Конечно же можно при этом самому себе накидать граблей с дэдлоками - нужно делать аккуратно.

Если коротко, то как-то так ...
28. Sander80 100 21.08.24 08:38 Сейчас в теме
(27) Спасибо! А дедлок это не с другой ВыбратьИзменения, а если где-то идет работа без установки блокировки видимо. Но хотя в таком случае, видимо, проще в тот другом месте блокировки ставить
29. Sander80 100 21.08.24 17:30 Сейчас в теме
(27) Продолжаю бороться с блокировками, меня случай ставит в тупик один. Может, у специалиста будут свежие идеи? (кроме послать к черту план обмена)

Проведение вызывается через код (выкинул все не относящееся к делу)

НачатьТранзакцию(РежимУправленияБлокировкойДанных.Управляемый);
Попытка
	БлокировкаДанных = Новый БлокировкаДанных; 
	ЭлементБлокировки = БлокировкаДанных.Добавить("РегистрСведений.ПоследниеДатыРаботы");	
	ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
	ЭлементБлокировки.ИсточникДанных = Ссылка.СписокФизическихЛиц;
	ЭлементБлокировки.ИспользоватьИзИсточникаДанных("ФизЛицо", "ФизЛицо");		
	БлокировкаДанных.Заблокировать();
	Документ = Ссылка.ПолучитьОбъект();
	Документ.Записать(РежимЗаписиДокумента.Проведение);

	ЗафиксироватьТранзакцию();
Исключение
	Если ТранзакцияАктивна() Тогда
		ОтменитьТранзакцию();
	КонецЕсли;    
КонецПопытки;

Показать


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

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

По журналу регистрации видно, что события проведения шли, потом прервались на 20 секунд. И фоновое задание по плану обмена начало транзакцию и встало на 20 секунд. Потом пользователь допроводит документ, начиная с записи в тот самый регистр ПоследниеДатыРаботы, а фоновое задание обламывается на невозможности получить блокировку.

Может, есть очевидные идеи, на чем я могу тупить? Уже пару недель это гоняю. Ведь если они друг друга ждут, там взаимоблокировки. Но я же установил блокировку в проведении, что ему мешает взять и сделать запись в регистр, почему оно может ждать фоновое задание? Ведь если бы то установило транзакционную блокировку на регистр, то пользователь вообще бы не смог пройти через Заблокировать(). А если он прошел, то что ему мешает писать... тупик
31. zhichkin 1524 21.08.24 19:31 Сейчас в теме
(29) Добрый день. Использование менеджера блокировки данных, а также открытие новой транзакции, из примера который Вы привели, выглядит избыточным. Вызов метода документа "Записать" под капотом и так создаст транзакцию и заблокирует всё, что нужно, на сервере 1С.
Для начала я бы настроил сбор данных по блокировкам при помощи соответствующих инструментов. Чтобы решить проблему, нужно точно понимать в чём она заключается. Пока что всё это выглядит как гадание.
Например, попробуйте для начала ТОЧНО ответить на вопрос какой прикладной код 1С (вплоть до номера строки в исходниках) является виновником блокировок. Второй вопрос: какой прикладной код 1С является жертвой ожидания КОНКРЕТНО на этих блокировках ?
В комменатриях выше я привожу пример такого анализа блокировок: ссылка на статью. Только после выполнения такого анализа можно будет понять что и как делать. Боюсь, что простого ответа на Ваш вопрос у меня нет =)
33. Sander80 100 21.08.24 20:23 Сейчас в теме
(27)
(31) Спасибо, буду искать.

Пока обнаружил загадочную вещь, что если сделать руками

(30) Вообще все это выглядит как бред, но если руками сделать

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


Перед ВыбратьИзменения(), то тоже нет дедлока.

В общем, ладно, что я вас мучаю, просто думал, не наткнулся ли на что-то общеизвестное (в узких кругах). Пойду сам журналы копать
30. Sander80 100 21.08.24 19:21 Сейчас в теме
(27) Очень интересно. Вы пишите

Этот код будет выполнен для всех типов объектов, которые включены в состав плана обмена. Каждый тип в своей собственной транзакции. На время транзакции будет установлена эксклюзивная транзакционная блокировка SQL Server на все записи узла, которые ещё не отправлялись


Однако судя по технологическому журналу ВыбратьИзменения накладывает разделяемую блокировку.
Если перед его вызовом наложить руками эксклюзивную, то дедлока не происходит, похоже
32. zhichkin 1524 21.08.24 19:37 Сейчас в теме
(30) Команда UPDATE на уровне СУБД накладывает эксклюзивные блокировки на все записи таблицы согласно предикату WHERE. Это без учёта возможных эскалаций и прочих оптимизаций, применяемых ядром СУБД. Данное утверждение одинаково справделиво, как для MS SQL Server, так и для PostgreSQL.
Sander80; +1 Ответить
34. Sander80 100 21.08.24 22:29 Сейчас в теме
(32) Вот в том-то и дело, что везде про это пишут, а я в своем технологическом журнале такого не увидел, и это становится загадкой. Может быть, позже сделаю полный лог, не только по блокировкам, и попробую его разобрать.

А пока предположение такое. ВыбратьИзменения делает Update, с этим сложно поспорить, но делает его по таблицам chng. Соответственно, и блокировка эксклюзивная идет на эти таблицы.

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

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

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

Так и возникает дедлок, поскольку один сеанс держит базовую таблицу, а другой таблицу изменений.
35. zhichkin 1524 22.08.24 00:53 Сейчас в теме
(34) Судя по всему, речь идёт о так называемой "распределённой взаимоблокировке". Рекомендую посмотреть следущие статьи от компании SoftPoint. Думаю, что это как раз то, что Вам нужно.
1. Распределенные взаимоблокировки в 1С системах
2. 1С РИБ опять тормозит. Как лечить ?
Sander80; +1 Ответить
36. Sander80 100 22.08.24 09:56 Сейчас в теме
(35) Спасибо, буду изучать
37. Sander80 100 22.08.24 11:01 Сейчас в теме
(35) Да, это оно. Я почему-то был уверен, что управляемая блокировка 1с ставится средствами бд и является тем же, что и блокировка, ставящаяся базой данных, а это выходит не так. Вот совсем ни разу не очевидно (хотя я все ваши и не только статьи на инфостарте несколько раз штудировал)
Оставьте свое сообщение