Форум 1С
Программистам, бухгалтерам, администраторам, пользователям
Задай вопрос - получи решение проблемы
22 ноя 2024, 23:31

БлокировкаДанных отключает механизм разделения итогов?

Автор bsn-chita, 08 июн 2017, 10:25

0 Пользователей и 1 гость просматривают эту тему.

bsn-chita


Движения.СтоимостьТоваров.БлокироватьДляИзменения = Истина;

То что эта строка отключает механизм разделения итогов до конца транзакций я знаю.

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

А такая блокировка так же отключает механизм или нет?

Kironten

Цитата: bsn-chita от 08 июн 2017, 10:25

Движения.СтоимостьТоваров.БлокироватьДляИзменения = Истина;

То что эта строка отключает механизм разделения итогов до конца транзакций я знаю.

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

А такая блокировка так же отключает механизм или нет?
Ну судя по тому что в сп указано: Предназначен для явной блокировки данных от чтения или изменения другими сессиями., то да, так же отключает.

ilyay

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

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

bsn-chita

Разбираю пример с проведением и если я вас правильно понял то код:

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

Логика по моему мнению там такая:
Блокировка данных по старому для табличной части(для "новых" товаров)
Если это перепроведение документа то чтобы не учитывались его старые движения(если дату поменял пользователь или документ который проведен сегодня перепроводиться и дата становиться на момент проведения) записываем пустые движения и ставим блокировку по новому на "старые" товары.
Теперь предположим что приходная записывает одновременно с нами по регистру данные тогда:
Для "старых" товаров она не сможет воспользоваться механизмом разделения итогов и будет ждать таимаут.
Для "новых" товаров она запишет итоги по механизму разделения итогов.
И тут как я понимаю может возникнуть ситуация что у нас неправильно будет рассчитана стоимость и это мы ни как не учитываем, а перекладываем на Последовательности эту работу. То есть как я думаю приходная в этом случае сдвинет последовательность и нам все равно надо будет перепроводить все документы в том числе и эту расходную(при условии что данные в приходной ее "зацепили").

ilyay

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

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

Поэтому блокировку "для изменения" надо устанавливать до того, как вы начнете проверять наличие, если вы планируете его списывать (т.е. в самом начале проведения). Это не позволит изменить параллельным проведением количество товара. Если другая транзакция наложит такую же блокировку, мы просто подождем окончания этого параллельного процесса.

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

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

bsn-chita

Еще хотелось бы уточнить пару моментов. В файловой 1С блокировки ставятся на таблицы целиком и нет параллельных проводок.
Отсюда делаю выводы: Во первых не важно включены ли разделяемые итоги или нет по факту они не будут работать. Во вторых строка БлокироватьДляИзменения = Истина в этом случае больше для красоты(любой первый документ заблокирует всю таблицу регистра и другие документы даже не смогут записать свой движения и следовательно не откуда будет пытаться сделать дополнительную строку разделяемых итогов).
И последнее в клиент-серверном варианте БлокироватьДляИзменения = Истина на уровне или 1С или СУБД сама ставит блокировки по измерениям которые были в табличной части до перепроводки(на случай если будет отмена проводки и ни кто не успел продать лишнего) и те что есть в текущем варианте.

Теги:

Похожие темы (5)

Рейтинг@Mail.ru

Поиск