Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: И снова перевод на управляемые блокировки
Украинский 1С форум: всё про 1С 8.3, 1С 8.2, 1С 8.1, 1С 8.0, 1С 7.7 > Программисту > Программирование в 1С Предприятие 8.3
vbi
Конфигурация УТ для Украины 2.3 (доработанная много чем), платформа 8.3.8.1784.
И вот снова конфликт блокировки транзакций, где около 200 пользователей одновременно блокируют друг друга. Отложенное проведение по партиям уже не помагает, прижало до реализации управляемых блокировок.
На основе необходимо зарегистрироваться для просмотра ссылки придумал реализовать блокировки по складу следующим образом:

1. Переводим саму конфигурацию на чисто управляемые блокировки.
2. Создаем подписку на событие "ОбработкаПроверкиЗаполнения", источник - ДокументОбъект.
3. Процедура подписки:

необходимо зарегистрироваться для просмотра ссылки
   Процедура УправляемыеБлокировкиОбработкаПроверкиЗаполнения(Источник, Отказ, ПроверяемыеРеквизиты) Экспорт
       Если Отказ Тогда
           Возврат;
       КонецЕсли;
       РежимБлокировки = РежимБлокировкиДанных.Исключительный;
      
       Блокировка = Новый БлокировкаДанных();
      
       //Определения имени пространства для "Документ"
      
       Если Метаданные.Документы.Индекс(Источник.Метаданные()) <> - 1 Тогда
           ИмяОбъектаПространстваБлокировок = "Документ." + Источник.Метаданные().Имя;
          
           //Блокировка самого документа
          
           ЭлементБлокировки = Блокировка.Добавить(ИмяОбъектаПространстваБлокировок);
           ЭлементБлокировки.Режим = РежимБлокировки;
           ЭлементБлокировки.УстановитьЗначение("Ссылка", Источник.Ссылка);
          
       КонецЕсли;  
      
       //Определения имени пространства для "Последовательность"
      
       Для Каждого ТекПоследовательность Из Последовательности Цикл
           Если ТекПоследовательность.Принадлежит(Источник.Ссылка) Тогда
               //Необходимо заблокировать последовательность  
              
               ЭлементБлокировки = Блокировка.Добавить("Последовательность." + Прав(Строка(ТекПоследовательность), СтрДлина(Строка(ТекПоследовательность)) - Найти(Строка(ТекПоследовательность), ".")) + ".НаборЗаписей");
               ЭлементБлокировки.Режим = РежимБлокировки;
           КонецЕсли;  
       КонецЦикла;  
      
       //Определения имени пространства для "Регистров"
      
       КоллекцияДвижений = Источник.Метаданные().Движения;
       Для Каждого ТекРегистрДвижения Из КоллекцияДвижений Цикл
          
           ИмяРегистра = ТекРегистрДвижения.Имя;
           ТипРегистра = "";
          
           Если Метаданные.РегистрыНакопления.Найти(ИмяРегистра) <> Неопределено Тогда
               ТипРегистра = "РегистрНакопления";
           ИначеЕсли Метаданные.РегистрыБухгалтерии.Найти(ИмяРегистра) <> Неопределено Тогда
               ТипРегистра = "РегистрБухгалтерии";
           Иначе
               ТипРегистра = "РегистрСведений";
           КонецЕсли;  
          
           Если ТипРегистра <> "" Тогда
               ЭлементБлокировки = Блокировка.Добавить(ТипРегистра + "." + ИмяРегистра + ".НаборЗаписей");
               ЭлементБлокировки.Режим = РежимБлокировки;
              
               Если ТекРегистрДвижения.Измерения.Найти("Склад") <> Неопределено Тогда
                  
                   Если Источник.Метаданные().Реквизиты.Найти("СкладОрдер") <> Неопределено Тогда
                       ЭлементБлокировки.УстановитьЗначение("Склад", Источник.СкладОрдер);
                   ИначеЕсли Источник.Метаданные().Реквизиты.Найти("Склад") <> Неопределено Тогда
                       ЭлементБлокировки.УстановитьЗначение("Склад", Источник.Склад);
                   ИначеЕсли Источник.Метаданные().Реквизиты.Найти("СкладОтправитель") <> Неопределено Тогда
                       тз = Новый ТаблицаЗначений;
                       тз.Колонки.Добавить("Склад");
                       строка = тз.Добавить();
                       строка.Склад = Источник.СкладОтправитель;
                       строка = тз.Добавить();
                       строка.Склад = Источник.СкладПолучатель;
                       ЭлементБлокировки.ИсточникДанных = тз;
                       ЭлементБлокировки.ИспользоватьИзИсточникаДанных("Склад", "Склад");
                      
                   КонецЕсли;
               КонецЕсли;
              
           КонецЕсли;  
          
       КонецЦикла;  
      
       //Установка блокировки
      
       Попытка
           Блокировка.Заблокировать();
       Исключение
           ОбщегоНазначения.СообщитьОбОшибке(ОписаниеОшибки(), Отказ, "Не удалось заблокировать объекты");
           ВызватьИсключение "Операция не выполнена";
       КонецПопытки;
   КонецПроцедуры


Подписка на "ОбработкаПроверкиЗаполнения" выполняется раньше чем "ПередЗаписью" в модуле объекта. Блокировка работает так:
По умолчанию блокируется все без отбора. Но если регистр имеет измерение "Склад", а источник "Склад", "СкладОрдер", "СкладОтправитель" - то устанавливается отбор по складу. Теоретически такая блокировка должна увеличить параллельность. Кто что думает?

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

У вас что именно?
vbi
Цитата
С блокировками существует 2 проблемы:
1) кто-то отваливается по таймауту, потому что не дожидается освобождения ресурсов
2) кто-то отваливается из-за взаимоблокировок

У вас что именно?

По таймауту
vbi
По таймауту в центральной базе. А в этом примере - жертва взаимоблокировок.
Vofka
Перечитываю много раз что вы написали, но непонятно нифига что у вас происходит. Кроме того вы, видимо, путаете между собой эти две проблемы (о которых я выше писал), считая, что это одно и то же. Вы сейчас запускаете проведение расходных накладных под двумя пользователями по разным складам и у вас в какой-то момент возникают именно взаимоблокировки?
vbi
Цитата
Перечитываю много раз что вы написали, но непонятно нифига что у вас происходит. Кроме того вы, видимо, путаете между собой эти две проблемы (о которых я выше писал), считая, что это одно и то же. Вы сейчас запускаете проведение расходных накладных под двумя пользователями по разным складам и у вас в какой-то момент возникают именно взаимоблокировки?


Да, путаю. Но уже не путаю, уже вроде разобрался в их различии.
Именно взаимоблокировки, так как пишет ошибку "... стала жертвой взаимоблокировки". - Значит менеджер взаимоблокировок одну транзакцию принес в жертву.


Но вот незадача: отключил ту процедуру что описал выше, которая осуществляет блокировки. - результат тот же. Блокировок не ставлю - откуда взаимоблокировки?Конфигурация в режиме чисто управляемых блокировок.
Vofka
Ошибку пишет русским языком? Кстати, а какая СУБД?
vbi


MS SQL 2014
Vofka
Сейчас у вас конфа стоит в режиме Управляемый, вы проводите под разными пользователями только Расходные накладные и возникает взаимоблокировка? А не видно в каком именно месте в коде?
vbi
Другие документы не пробовал.
Ошибка возникает в строчке: "Запрос.Выполнить()" в процедуре:

необходимо зарегистрироваться для просмотра ссылки
   Функция ПолучитьДеревоПартийНаСкладахУпр (МоментКон, СтруктураПараметров)
  
          
       Запрос = Новый Запрос;
      
       ОсновнойДокумент = Неопределено;
       СтруктураПараметров.Свойство("ОсновнойДокумент",ОсновнойДокумент);
      
       Регистратор = СтруктураПараметров.Регистратор;
       СпособОценкиМПЗ = СтруктураПараметров.СпособОценкиМПЗУпр;
       СтратегияСтатусПартии = СтруктураПараметров.СтратегияСтатусПартииУпр;
       ВестиПартионныйУчетПоСкладам = СтруктураПараметров.ВестиПартионныйУчетПоСкладамУпр;
  
       // Для повышения быстродействия остатки партий получаются различными способами
       Если СтруктураПараметров.Свойство("ЗакрытиеЗаказовПокупателей") Тогда
           ЗаполнитьЗапросПартийНаСкладахДляЗакрытияЗаказовПокупателей(Запрос);
          
       ИначеЕсли ОсновнойДокумент <> Неопределено И НЕ СтруктураПараметров.СписыватьПартииРасходнымОрдером
           И ТипЗнч(ОсновнойДокумент) = Тип("ДокументСсылка.РеализацияТоваровУслуг")тогда
           // Списание расходным ордером товара реализованного и принятого на ответственное хранение (отложенная отгрузка)
           ЗаполнитьЗапросПартийНаСкладахДляОтложеннойОтгрузкиУпр(Запрос, ВестиПартионныйУчетПоСкладам);
      
       ИначеЕсли ОсновнойДокумент <> Неопределено тогда
           // Списание партий по ордерной схеме:
           // - Списание партий по расходному ордеру
           // - Перемещение партий по приходному ордеру
           // - Перемещение партий поступлением товаров и услуг в НТТ
           // Движения реализации выполняет расходный ордер, движения перемещения выполняет приходный ордер
           ЗаполнитьЗапросПартийНаСкладахДляСписанияПоОрдернойСхемеУпр(Запрос, ВестиПартионныйУчетПоСкладам, СтратегияСтатусПартии, СпособОценкиМПЗ);
          
       Иначе
           // Общий случай списания
           ЗаполнитьЗапросПартийНаСкладахУпр(Запрос, ВестиПартионныйУчетПоСкладам, СтратегияСтатусПартии, СпособОценкиМПЗ);
          
              
           Если НЕ СтруктураПараметров.ИспользоватьУказаниеСерийНоменклатурыПриРезервировании тогда
               Запрос.Текст = СтрЗаменить(Запрос.Текст,"ИЛИ ПартииТоваровНаСкладах.СерияНоменклатуры = &ПустаяСерияНоменклатуры",
               "ИЛИ ПартииТоваровНаСкладах.СерияНоменклатуры = &ПустаяСерияНоменклатуры
               |ИЛИ СписанныеТовары.КодОперацииПартииТоваров = &КодРезервирование");
               Запрос.УстановитьПараметр("КодРезервирование" , СтруктураПараметров.КодыОпераций.РезервированиеПодЗаказ)
           КонецЕсли;
          
       КонецЕсли;
      
       Запрос.УстановитьПараметр("ПустаяСерияНоменклатуры", Справочники.СерииНоменклатуры.ПустаяСсылка());
       Запрос.УстановитьПараметр("ПустойЗаказ", Документы.ЗаказПокупателя.ПустаяСсылка());
       Запрос.УстановитьПараметр("ПустойСтатус", Перечисления.СтатусыПартийТоваров.ПустаяСсылка());
       Запрос.УстановитьПараметр("СтатусПартииПоОрдеру", Перечисления.СтатусыПартийТоваров.ПоОрдеру);    
       Запрос.УстановитьПараметр("ПустоеКачество", Справочники.Качество.ПустаяСсылка());
       Запрос.УстановитьПараметр("КачествоНовый", Справочники.Качество.Новый);
       Запрос.УстановитьПараметр("ПустойСклад", Справочники.Склады.ПустаяСсылка());
      
       Запрос.УстановитьПараметр("Ссылка", Регистратор);
      
       Если  ОсновнойДокумент <> Неопределено Тогда
           Запрос.УстановитьПараметр("ОсновнойДокумент", ОсновнойДокумент);
       Иначе
           Запрос.УстановитьПараметр("ОсновнойДокумент", Регистратор);
       КонецЕсли;
      
       Запрос.УстановитьПараметр("Дат", МоментКон);
      
       Запрос.УстановитьПараметр("НаКомиссию", Перечисления.СтатусыПартийТоваров.НаКомиссию);
      
  
       Если ТипЗнч(Регистратор) = Тип("ДокументСсылка.ОтчетОРозничныхПродажах") или ТипЗнч(Регистратор) = Тип("ДокументСсылка.РеализацияТоваровУслуг")  ИЛИ ТипЗнч(Регистратор) = Тип("ДокументСсылка.ПеремещениеТоваров") Тогда
           //или ТипЗнч(Регистратор) = Тип("ДокументСсылка.ВозвратТоваровПоставщику") Тогда
          
           Запрос.Текст = "ВЫБРАТЬ РАЗРЕШЕННЫЕ
           |    СписанныеТовары.НомерСтрокиДокумента КАК НомерСтрокиДокумента,
           |    ПартииТоваровНаСкладах.Номенклатура,
           |    ПартииТоваровНаСкладах.ДокументОприходования КАК ДокументОприходования,
           |    ПартииТоваровНаСкладах.ДокументОприходования.Дата КАК ДокументОприходованияДата,
           |    ПартииТоваровНаСкладах.Склад,
           |    ПартииТоваровНаСкладах.ХарактеристикаНоменклатуры,
           |    ПартииТоваровНаСкладах.СерияНоменклатуры,
           |    ПартииТоваровНаСкладах.Качество,
           |    ПартииТоваровНаСкладах.Заказ,
           |    ПартииТоваровНаСкладах.КоличествоОстаток КАК Количество,
           |    ПартииТоваровНаСкладах.СтоимостьОстаток КАК Стоимость,
           |    ПартииТоваровНаСкладах.СтатусПартии,
           |    ВЫБОР
           |        КОГДА СписанныеТовары.СерияНоменклатуры = ПартииТоваровНаСкладах.СерияНоменклатуры
           |            ТОГДА 0
           |        ИНАЧЕ 1
           |    КОНЕЦ КАК ЧислоСерияНоменклатуры,
           |    ВЫБОР
           |        КОГДА СписанныеТовары.ДокументПартии = НЕОПРЕДЕЛЕНО
           |            ТОГДА 0
           |        ИНАЧЕ ВЫБОР
           |                КОГДА СписанныеТовары.ДокументПартии = ПартииТоваровНаСкладах.ДокументОприходования
           |                    ТОГДА 0
           |                ИНАЧЕ 1
           |            КОНЕЦ
           |    КОНЕЦ КАК ЧислоДокументОприходования,
           |    ВЫБОР
           |        КОГДА СписанныеТовары.ЗаказПартии = НЕОПРЕДЕЛЕНО
           |            ТОГДА 0
           |        ИНАЧЕ ВЫБОР
           |                КОГДА ПартииТоваровНаСкладах.Заказ = &ПустойЗаказ
           |                    ТОГДА 1
           |                ИНАЧЕ 0
           |            КОНЕЦ
           |    КОНЕЦ КАК ЧислоЗаказ,
           |    ВЫБОР
           |        КОГДА ПартииТоваровНаСкладах.СтатусПартии = &НаКомиссию
           |            ТОГДА 1
           |        ИНАЧЕ 0
           |    КОНЕЦ КАК ЧислоСтатусПартии
           |ИЗ
           |    РегистрСведений.СписанныеТовары КАК СписанныеТовары
           |        ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрНакопления.ПартииТоваровНаСкладах.Остатки(&Дат, Склад = &Склад) КАК ПартииТоваровНаСкладах
           |            ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.СписанныеТовары КАК СписанныеТовары1
           |            ПО СписанныеТовары1.Номенклатура = ПартииТоваровНаСкладах.Номенклатура
           |        ПО СписанныеТовары.Номенклатура = ПартииТоваровНаСкладах.Номенклатура
           |            И СписанныеТовары.ХарактеристикаНоменклатуры = ПартииТоваровНаСкладах.ХарактеристикаНоменклатуры
           |            И (ВЫБОР
           |                КОГДА ПартииТоваровНаСкладах.Качество = &ПустоеКачество
           |                    ТОГДА ИСТИНА
           |                ИНАЧЕ ВЫБОР
           |                        КОГДА СписанныеТовары.Качество = &ПустоеКачество
           |                            ТОГДА ПартииТоваровНаСкладах.Качество = &КачествоНовый
           |                        ИНАЧЕ ПартииТоваровНаСкладах.Качество = СписанныеТовары.Качество
           |                    КОНЕЦ
           |            КОНЕЦ)
           |            И (ПартииТоваровНаСкладах.Склад = СписанныеТовары.Склад
           |                ИЛИ ПартииТоваровНаСкладах.Склад = &ПустойСклад)
           |            И (ВЫБОР
           |                КОГДА СписанныеТовары.ДопустимыйСтатус1 <> &ПустойСтатус
           |                        ИЛИ СписанныеТовары.ДопустимыйСтатус2 <> &ПустойСтатус
           |                        ИЛИ СписанныеТовары.ДопустимыйСтатус3 <> &ПустойСтатус
           |                        ИЛИ СписанныеТовары.ДопустимыйСтатус4 <> &ПустойСтатус
           |                    ТОГДА ПартииТоваровНаСкладах.СтатусПартии = &ПустойСтатус
           |                            ИЛИ ПартииТоваровНаСкладах.СтатусПартии = &СтатусПартииПоОрдеру
           |                            ИЛИ ПартииТоваровНаСкладах.СтатусПартии = СписанныеТовары.ДопустимыйСтатус1
           |                            ИЛИ ПартииТоваровНаСкладах.СтатусПартии = СписанныеТовары.ДопустимыйСтатус2
           |                            ИЛИ ПартииТоваровНаСкладах.СтатусПартии = СписанныеТовары.ДопустимыйСтатус3
           |                            ИЛИ ПартииТоваровНаСкладах.СтатусПартии = СписанныеТовары.ДопустимыйСтатус4
           |                ИНАЧЕ ИСТИНА
           |            КОНЕЦ)
           |            И (ВЫБОР
           |                КОГДА СписанныеТовары.СписыватьТолькоПоЗаказу = ИСТИНА
           |                    ТОГДА ВЫБОР
           |                            КОГДА ПартииТоваровНаСкладах.Заказ <> СписанныеТовары.ЗаказПартии
           |                                ТОГДА ВЫБОР
           |                                        КОГДА НЕ СписанныеТовары.ЗаказПартии = НЕОПРЕДЕЛЕНО
           |                                            ТОГДА ЛОЖЬ
           |                                        ИНАЧЕ ПартииТоваровНаСкладах.Заказ = &ПустойЗаказ
           |                                    КОНЕЦ
           |                            ИНАЧЕ ИСТИНА
           |                        КОНЕЦ
           |                ИНАЧЕ ВЫБОР
           |                        КОГДА ПартииТоваровНаСкладах.Заказ <> СписанныеТовары.ЗаказПартии
           |                            ТОГДА ПартииТоваровНаСкладах.Заказ = &ПустойЗаказ
           |                        ИНАЧЕ ИСТИНА
           |                    КОНЕЦ
           |            КОНЕЦ)
           |            И (СписанныеТовары.СерияНоменклатуры = ПартииТоваровНаСкладах.СерияНоменклатуры
           |                ИЛИ ПартииТоваровНаСкладах.СерияНоменклатуры = &ПустаяСерияНоменклатуры
           |                ИЛИ СписанныеТовары.КодОперацииПартииТоваров = &КодРезервирование)
           |ГДЕ
           |    СписанныеТовары.Регистратор = &ОсновнойДокумент
           |    И СписанныеТовары.Склад = &Склад
           |    И СписанныеТовары1.Регистратор = &Ссылка
           |
           |УПОРЯДОЧИТЬ ПО
           |    ЧислоСерияНоменклатуры,
           |    ЧислоДокументОприходования,
           |    ЧислоЗаказ,
           |    ЧислоСтатусПартии,
           |    ДокументОприходованияДата,
           |    ДокументОприходования
           |ИТОГИ ПО
           |    НомерСтрокиДокумента";
  
          
          
           Если ТипЗнч(Регистратор) = Тип("ДокументСсылка.ПеремещениеТоваров") Тогда
               Запрос.УстановитьПараметр("Склад", Регистратор.СкладОтправитель);
           Иначе    
               Запрос.УстановитьПараметр("Склад", Регистратор.Склад);
           КонецЕсли;
       КонецЕсли;
  
       Возврат Запрос.Выполнить().Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам);
  
   КонецФункции//ПолучитьДеревоПартийНаСкладахУпр


причем всегда на том же месте ошибка. Запрос выполняется по партиям. На партии стоит отбор по складу. На списанные товары блокировку вообще не ставил. Да и проблема в том что если вообще блокировку не ставить то ошибка та же. Такое впечатление что как то они автоматически ставятся.
Acid
Регистр Партии товаров на складах заблокирован в следствии транзакции при групповом проведении документов. Вы хотите во время данной транзакции параллельно запустить еще одно групповое проведение по данному регистру?
Vofka
Попробуйте где-то перед этим запросом установить управляемую блокировку на регистр Партий по измерению Склад.
vbi
Цитата
Вы хотите во время данной транзакции параллельно запустить еще одно групповое проведение по данному регистру?

Да, но с отбором по разным складам.

Цитата
Попробуйте где-то перед этим запросом установить управляемую блокировку на регистр Партий по измерению Склад.


Попробовал, но результат - тот же:

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

КонецФункции//ПолучитьДеревоПартийНаСкладахУпр


На возврате - ошибка.
Acid
vbi @ Вчера, 22:06 необходимо зарегистрироваться для просмотра ссылки ,
Не нужно использовать транзакции, в вашем случае.
Vofka
Цитата(vbi @ 05.11.17, 21:06) необходимо зарегистрироваться для просмотра ссылки
Попробовал, но результат - тот же

А если эту блокировку сделать в самом начале ОбработкиПроведения?

Цитата(Acid @ 06.11.17, 8:33) необходимо зарегистрироваться для просмотра ссылки
Не нужно использовать транзакции, в вашем случае.

А подробней можно?
Acid
Цитата(Vofka @ 06.11.17, 10:28) необходимо зарегистрироваться для просмотра ссылки
Цитата(Acid @ 06.11.17, 8:33) *
Не нужно использовать транзакции, в вашем случае.

А подробней можно?

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


Я проведение делаю там и там в Запроснику. Выполняю запрос - нахожу все реализации по складу, В обработке результата запроса - перепровожу.


Вообщем может делаю что не так:
Есть УТ. Включаю в настройках конфигурации режим блокировок "Управляемый". Дальше что делать, чтобы реализации одновременно проводились по партиям, по разным складам. Как блокировать партии только по конкретному складу?
vbi
Разобрался. необходимо зарегистрироваться для просмотра ссылки:
Цитата
Управляемый режим позволяет повысить параллельность работы пользователей в клиент-серверном варианте работы за счет использования более низкого уровня изоляции транзакций базы данных (Read Committed). При записи данных в транзакции объекты встроенного языка автоматически блокируют необходимые данные. Разработчику требуется управлять блокировками данных в тех случаях, когда бизнес-логика требует согласованного и целостного чтения данных в транзакции.


То есть, насколько я понял, если не блокировать в коде при управляемом режиме, то конфигурация всеравно блокирует данные но более на низком уровне. Но если блокировать - тогда работает твой код. Следовательно в примере выше я не блокировал регситр сведений "СписанныеТовары". Когда я прописал в коде:
    Блокировка = Новый БлокировкаДанных();

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

- блокировки исчезли. Мы в СписанныеТовары ничего не пишем - только читаем из него. Если мы его явно в коде не упоминали - он блокировался полностью и исключительно.

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