Имя: Пароль:
1C
1С v8
Как правильно сделать блокировку?
,
0 new1snik
 
05.11.13
13:59
День добрый.
Запросом получаю остатки товара на складах, данные берутся из РН. После этого на основании результатов запроса создаю документ резервирования товара. Достаточно редко, но все же, возникает ситуация, когда пользователи пытаются зарезервировать один и тот же товар одновременно, и при этом, суммарное кол-во резервируемого товара запросто может оказаться больше доступного остатка. Соответственно мне нужно каким-то образом предотвратить попытки резервирования товара на момент, например, заблокировать для чтения РН накопления из которого я собираю данные на время выполнения обработки резервирования.
Пытался сделать это с помощью постановки ДЛЯ ИЗМЕНЕНИЯ в текст запроса, но либо я неправильно что-то делаю, либо этот способ не так работает, но ничего не получилось.
Тестировал следующим образом: запускал отладку, ставил точку останова сразу после выполнения запроса, потом запускал еще один сеанс и пытался сделать резерв того же товара, но с количеством в сумме с первым резервом превышающим доступный остаток. Запрос во втором сеансе мог получить данные.
Каким образом будет правильно поступить?
1 GROOVY
 
05.11.13
14:04
2 Новиков
 
05.11.13
14:05
(0)
Какой режим управления блокировки на конфе, на доке, на РН?
3 new1snik
 
05.11.13
14:07
(2) Автоматический в обоих случаях.
4 GROOVY
 
05.11.13
14:08
И база небось файловая...
5 new1snik
 
05.11.13
14:08
(4) Ага
6 new1snik
 
05.11.13
14:09
(5) Хотя вру, не файловая. SQL.
7 Новиков
 
05.11.13
14:11
(6) запрос покажи
8 new1snik
 
05.11.13
14:12
(7)
ВЫБРАТЬ РАЗРЕШЕННЫЕ
    ВложенныйЗапрос.Номенклатура,
    СУММА(ВложенныйЗапрос.СвободныйОстаток) КАК СвободныйОстаток
ПОМЕСТИТЬ ТабОстатокКоробки
ИЗ
    (ВЫБРАТЬ
        Таб.Склад КАК МестоРезерва,
        Таб.Склад.Розничный_СВИТ КАК ЭтоРозница,
        Таб.КоличествоОстаток КАК Остаток,
        0 КАК РезервПоЗаказу,
        Таб.КоличествоОстаток КАК СвободныйОстаток,
        0 КАК РезервПоДругимЗаказам,
        Таб.Номенклатура КАК Номенклатура
    ИЗ
        РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, Склад = &СкладКоробок) КАК Таб
    
    ОБЪЕДИНИТЬ ВСЕ
    
    ВЫБРАТЬ
        Таб.Склад,
        Таб.Склад.Розничный_СВИТ,
        Таб.КоличествоОстаток,
        0,
        Таб.КоличествоОстаток,
        0,
        Таб.Номенклатура
    ИЗ
        РегистрНакопления.ТоварыВРознице.Остатки(&Период, Склад = &СкладКоробок) КАК Таб
    
    ОБЪЕДИНИТЬ ВСЕ
    
    ВЫБРАТЬ
        Таб.Склад,
        Таб.Склад.Розничный_СВИТ,
        0,
        0,
        -Таб.КоличествоОстаток,
        Таб.КоличествоОстаток,
        Таб.Номенклатура
    ИЗ
        РегистрНакопления.ТоварыВРезервеНаСкладах.Остатки(
                &Период,
                ДокументРезерва <> &ЗаказПокупателя
                    И Склад = &СкладКоробок) КАК Таб) КАК ВложенныйЗапрос

СГРУППИРОВАТЬ ПО
    ВложенныйЗапрос.Номенклатура
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВложенныйЗапрос.Номенклатура,
    СУММА(ВложенныйЗапрос.СвободныйОстаток) КАК СвободныйОстаток
ПОМЕСТИТЬ ТабОстатокБаза
ИЗ
    (ВЫБРАТЬ
        Таб.Склад КАК МестоРезерва,
        Таб.Склад.Розничный_СВИТ КАК ЭтоРозница,
        Таб.КоличествоОстаток КАК Остаток,
        0 КАК РезервПоЗаказу,
        Таб.КоличествоОстаток КАК СвободныйОстаток,
        0 КАК РезервПоДругимЗаказам,
        Таб.Номенклатура КАК Номенклатура
    ИЗ
        РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, Склад = &СкладБаза) КАК Таб
    
    ОБЪЕДИНИТЬ ВСЕ
    
    ВЫБРАТЬ
        Таб.Склад,
        Таб.Склад.Розничный_СВИТ,
        Таб.КоличествоОстаток,
        0,
        Таб.КоличествоОстаток,
        0,
        Таб.Номенклатура
    ИЗ
        РегистрНакопления.ТоварыВРознице.Остатки(&Период, Склад = &СкладБаза) КАК Таб
    
    ОБЪЕДИНИТЬ ВСЕ
    
    ВЫБРАТЬ
        Таб.Склад,
        Таб.Склад.Розничный_СВИТ,
        0,
        0,
        -Таб.КоличествоОстаток,
        Таб.КоличествоОстаток,
        Таб.Номенклатура
    ИЗ
        РегистрНакопления.ТоварыВРезервеНаСкладах.Остатки(
                &Период,
                ДокументРезерва <> &ЗаказПокупателя
                    И Склад = &СкладБаза) КАК Таб) КАК ВложенныйЗапрос

СГРУППИРОВАТЬ ПО
    ВложенныйЗапрос.Номенклатура
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ЗапросОстаткиРозница.Номенклатура,
    СУММА(ЗапросОстаткиРозница.СвободныйОстаток) КАК СвободныйОстаток
ПОМЕСТИТЬ ТабОстатокРозница
ИЗ
    (ВЫБРАТЬ
        Таб.Склад КАК МестоРезерва,
        Таб.Склад.Розничный_СВИТ КАК ЭтоРозница,
        Таб.КоличествоОстаток КАК Остаток,
        0 КАК РезервПоЗаказу,
        Таб.КоличествоОстаток КАК СвободныйОстаток,
        0 КАК РезервПоДругимЗаказам,
        Таб.Номенклатура КАК Номенклатура
    ИЗ
        РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, Склад = &СкладРозница) КАК Таб
    
    ОБЪЕДИНИТЬ ВСЕ
    
    ВЫБРАТЬ
        Таб.Склад,
        Таб.Склад.Розничный_СВИТ,
        Таб.КоличествоОстаток,
        0,
        Таб.КоличествоОстаток,
        0,
        Таб.Номенклатура
    ИЗ
        РегистрНакопления.ТоварыВРознице.Остатки(&Период, Склад = &СкладРозница) КАК Таб
    
    ОБЪЕДИНИТЬ ВСЕ
    
    ВЫБРАТЬ
        Таб.Склад,
        Таб.Склад.Розничный_СВИТ,
        0,
        0,
        -Таб.КоличествоОстаток,
        Таб.КоличествоОстаток,
        Таб.Номенклатура
    ИЗ
        РегистрНакопления.ТоварыВРезервеНаСкладах.Остатки(
                &Период,
                ДокументРезерва <> &ЗаказПокупателя
                    И Склад = &СкладРозница) КАК Таб) КАК ЗапросОстаткиРозница

СГРУППИРОВАТЬ ПО
    ЗапросОстаткиРозница.Номенклатура
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ЗаказПокупателяТовары.Номенклатура,
    ЕСТЬNULL(БольшиеКоробки.Коэффициент, 0) КАК КоличествоВБольшойКоробке,
    ЕСТЬNULL(МалыеКоробки.Коэффициент, 0) КАК КоличествоВМалойКоробке
ПОМЕСТИТЬ ТабКоробки
ИЗ
    Документ.ЗаказПокупателя.Товары КАК ЗаказПокупателяТовары
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК спрНоменклатура
            ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ЕдиницыИзмерения КАК БольшиеКоробки
            ПО спрНоменклатура.ЕдиницаБольшаяКоробка = БольшиеКоробки.Ссылка
            ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ЕдиницыИзмерения КАК МалыеКоробки
            ПО спрНоменклатура.ЕдиницаМалаяКоробка = МалыеКоробки.Ссылка
        ПО ЗаказПокупателяТовары.Номенклатура = спрНоменклатура.Ссылка
ГДЕ
    ЗаказПокупателяТовары.Ссылка = &ЗаказПокупателя
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ЗаказПокупателяТовары.Номенклатура,
    ТабКоробки.КоличествоВБольшойКоробке,
    ТабКоробки.КоличествоВМалойКоробке,
    ЗаказПокупателяТовары.Количество,
    ЕСТЬNULL(ТабОстатокНаСкладеКоробок.СвободныйОстаток, 0) КАК ОстатокНаСкладеКоробок,
    ЕСТЬNULL(ТабОстатокРозница.СвободныйОстаток, 0) КАК ОстатокНаСкладеРозница,
    ЕСТЬNULL(ТабОстатокБаза.СвободныйОстаток, 0) КАК ОстатокНаСкладеБаза,
    ЗаказПокупателяТовары.НомерСтроки КАК НомерСтроки,
    ЗаказПокупателяТовары.ЕдиницаИзмерения
ИЗ
    Документ.ЗаказПокупателя.Товары КАК ЗаказПокупателяТовары
        ЛЕВОЕ СОЕДИНЕНИЕ ТабОстатокКоробки КАК ТабОстатокНаСкладеКоробок
        ПО ЗаказПокупателяТовары.Номенклатура = ТабОстатокНаСкладеКоробок.Номенклатура
        ЛЕВОЕ СОЕДИНЕНИЕ ТабКоробки КАК ТабКоробки
        ПО ЗаказПокупателяТовары.Номенклатура = ТабКоробки.Номенклатура
        ЛЕВОЕ СОЕДИНЕНИЕ ТабОстатокРозница КАК ТабОстатокРозница
        ПО ЗаказПокупателяТовары.Номенклатура = ТабОстатокРозница.Номенклатура
        ЛЕВОЕ СОЕДИНЕНИЕ ТабОстатокБаза КАК ТабОстатокБаза
        ПО ЗаказПокупателяТовары.Номенклатура = ТабОстатокБаза.Номенклатура
ГДЕ
    ЗаказПокупателяТовары.Ссылка = &ЗаказПокупателя

УПОРЯДОЧИТЬ ПО
    НомерСтроки
9 new1snik
 
05.11.13
14:12
А можно как-то под спойлер самому помещать?
10 Новиков
 
05.11.13
14:13
и где в тексте: ДЛЯ ИЗМЕНЕНИЯ.
11 new1snik
 
05.11.13
14:18
(10) Это исходный запрос.

Делал же подобным образом:

ВЫБРАТЬ РАЗРЕШЕННЫЕ
    ВложенныйЗапрос.Номенклатура,
    СУММА(ВложенныйЗапрос.СвободныйОстаток) КАК СвободныйОстаток
ПОМЕСТИТЬ ТабОстатокКоробки
ИЗ
    (ВЫБРАТЬ
        Таб.Склад КАК МестоРезерва,
        Таб.Склад.Розничный_СВИТ КАК ЭтоРозница,
        Таб.КоличествоОстаток КАК Остаток,
        0 КАК РезервПоЗаказу,
        Таб.КоличествоОстаток КАК СвободныйОстаток,
        0 КАК РезервПоДругимЗаказам,
        Таб.Номенклатура КАК Номенклатура
    ИЗ
        РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, Склад = &СкладКоробок) КАК Таб
    
    ДЛЯ ИЗМЕНЕНИЯ
        РегистрНакопления.ТоварыНаСкладах.Остатки
    
    ОБЪЕДИНИТЬ ВСЕ
........
12 new1snik
 
05.11.13
15:28
(1) Прочитал вашу статью, там в разделе про управляемые блокировки написано:
"Теперь параллельно с нами никто не прочитает остатки по указанным товарам из регистра "СтоимостьТоваров". Обращаю внимание, так как мы не знаем заранее какие партии будут выбраны запросом, то фильтр по ним установить мы не можем и блокируем все партии. Чем меньше фильтров описано, тем больше данных блокируется."

Я сделал по аналогии, у меня есть небольшой запрос, перед ним я размещаю блокировку:

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

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

РежимБлокировки управляемый. После этого я ожидаю, что любые запросы к РН ТоварыВРезервеНаСкладах будут блокироваться. Но этого не происходит. ЧТо я не учел? Проверял следующим образом: точка останова после запроса, запуск отладки, выполнение кода приведенного выше, срабатывание точки останова, запуск второго сеанса и выполнение этого же кода.
13 new1snik
 
05.11.13
15:31
(12) Быть может создание нового объекта блокировки снимает блокировку поставленную первым выполнением кода и дает выполниться запросу?
14 Мимохожий Однако
 
05.11.13
15:50
Запрос по остаткам с проверкой возможности блокировки надо делать перед записью документа.
15 new1snik
 
06.11.13
08:00
Пока окончательно не оттестировал, но вроде набрел на подходящее решение:

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

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

Всем спасибо за потраченное на помощь время.
16 Новиков
 
06.11.13
08:37
Жесть. ПРОСТО ЖЕСТЬ!!!

А где ты (8) писал?
17 new1snik
 
06.11.13
08:41
(16) Так, что я натворил? Почему жесть?
(8) Расположено ниже этой блокировки.
18 Новиков
 
06.11.13
08:47
(17) еще раз. В каком обработчике какого модуля ты воял (8) и (15)?
19 new1snik
 
06.11.13
08:54
(18) Все это находится во внешней обработке, сначала идет:
НачатьТранзакцию(РежимУправленияБлокировкойДанных.Управляемый);
        Блокировка  = Новый БлокировкаДанных;
        ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.ТоварыНаСкладах");
        ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
        Блокировка.Заблокировать();

Потом запрос из (8), потом в цикле еще маленький запрос обращающийся к РегиструНакопления ТоварыНаСкладах, и в самом конце обработки
ЗафиксироватьТранзакцию();
20 Новиков
 
06.11.13
08:56
Ну. Поздравляю. Ты открыл для себя великую истину: транзакционные блокировки работают ТОЛЬКО в транзакции (явной или не явной).

Я так полагаю, поэтому в (0) у тебя ничего и не работало.
21 Новиков
 
06.11.13
08:58
кстати в (19) режим управления на конфе стоит автоматический?
22 new1snik
 
06.11.13
09:00
(21)Да, на РН стоит автоматический.
23 new1snik
 
06.11.13
09:01
(20)Благодарю. И умеешь же ты нагнать жути...
24 Новиков
 
06.11.13
09:03
(22) какой режим стоит на КОНФЕ?
25 new1snik
 
06.11.13
09:04
(24) Управляемый
26 Новиков
 
06.11.13
09:14
(25) Поздравлю тебя второй раз!

НачатьТранзакцию(<РежимБлокировок>)
Параметры:

<РежимБлокировок> (необязательный)

Тип: РежимУправленияБлокировкойДанных.
Установка параметра имеет смысл, если для свойства конфигурации "Режим управления блокировкой данных" выбрано значение "Автоматический и Управляемый".

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

О мир открытий чудный!!! :)))
27 Новиков
 
06.11.13
09:16
сегодня я веду передачу под слоганом: "получается, все что мы знали о мире - это территория заблуждений!"

Не переключайтесь! :)))
28 new1snik
 
06.11.13
09:20
(27)ЫЫЫыыы
29 Новиков
 
06.11.13
09:23
Ну. С раздуплением тебя, коллега. Передавай знания, полученные в этой ветке - из уст в уста. Палец подымай, при этом к верху, как бэ намекая.

За сим раскланиваюсь.
30 new1snik
 
06.11.13
09:26
(29) Всего доброго, коллега!
Кaк может человек ожидaть, что его мольбaм о снисхождении ответит тот, кто превыше, когдa сaм он откaзывaет в милосердии тем, кто ниже его? Петр Трубецкой