Добрый день, коллеги.
Написал алгоритм формирования уникального артикула, в целом работает исправно , за исключением параллельных вызовов(когда два и более клиента вызывают метод одновременно, то всем вернется один и тот артикул), каким образом с такими проблемами справляются в 1с?
Алгоритм простой: запросом выбираем Артикул из таблицы номенклатура, плюсуем к нему 1 и записываем. Вызов метода "НовыйАртикул()" происходит в обработчике "ПриУстановкеНовогоКода".
Написал алгоритм формирования уникального артикула, в целом работает исправно , за исключением параллельных вызовов(когда два и более клиента вызывают метод одновременно, то всем вернется один и тот артикул), каким образом с такими проблемами справляются в 1с?
Алгоритм простой: запросом выбираем Артикул из таблицы номенклатура, плюсуем к нему 1 и записываем. Вызов метода "НовыйАртикул()" происходит в обработчике "ПриУстановкеНовогоКода".
По теме из базы знаний
- Загрузка картинок по артикулу
- Проверка уникальности номенклатуры по наименованию и/или артикулу в УНФ 1.6
- "1С:Розница 8. Ювелирный магазин" - кол. УИН в списках ДМДК, альтернативная печать DataMatrix, заполнение партий для ДМДК по артикулам/штрихкодам
- Формирование наименований для 1С:Розница 8. Ювелирный магазин, редакция 2.3
- Внесение изменений в выгрузку торгового каталога из 1С: УПП (обычные формы, платформа 8.3) на сайт с помощью стандартной обработки 1С Битрикс
Найденные решения
Все, задачу решил.
Если кому-то еще надо будет, то вот:
Если кому-то еще надо будет, то вот:
//Функция общего модуля которая делает запрос и выбирает максимальный из существующих
Функция МаксимальныйНомерАртикула(Префикс,Характеристика = Ложь) Экспорт
Попытка
БлокировкаДанных = Новый БлокировкаДанных;
БлокировкаКонстанты = БлокировкаДанных.Добавить("Константа.УА_Артикул");
БлокировкаДанных.Заблокировать();
Исключение
//Сообщить("Объект уже заблокирован");
Возврат Ложь;
КонецПопытки;
//
// тут код получения нужных данных и их возврата
//
КонецФункции
//Код в объекта где требуется получить уникальный номер
Процедура УстановитьАртикул()
НачатьТранзакцию(); //Использование транзакций обязательно для использования блокировки объекта
Артикул = Ложь;
Пока НЕ Число(Артикул) Цикл //Артикул возвращается строкой, а строка не может быть преобразована к
//булево, поэтому преобразуем к числу, а число легко преобразуется к
//булево, нулевого артикула у меня быть не может.
Артикул = Число(УА_ОбщийСервер.МаксимальныйНомерАртикула("Префикс-"))+1;
КонецЦикла;
Сообщить("Артикул :"+Артикул);
ЗафиксироватьТранзакцию(); //Возможно эту часть можно опустить , но у меня эта функция во внешней
//обработке , поэтому явно завершаю транзакцию.
КонецПроцедуры
ПоказатьОстальные ответы
Подписаться на ответы
Инфостарт бот
Сортировка:
Древо развёрнутое
Свернуть все
(2) Всего справочника? ведь по сути мы только читаем максимальное значение артикула и сам объект не меняем и тут либо блокировать весь справочник, что 100% является не верным решением, либо устанавливать эксклюзивную (исключительную) блокировку на объект содержащий максимальный артикул до завершения транзакции записи текущего элемента. А может есть еще какие-то варианты решения?
(11) Да, Вы правы.
Способ хранения констант в 1С:Предприятие 8 менялся в зависимости от версии платформы. Так, в платформе до версии 8.2.14 (или платформах выше версии, но с включенным режимом совместимости 8.2.13 и ниже), константы хранятся в одной таблице СУБД, начиная с версии 8.2.14, для каждой константы создается своя таблица СУБД. Данное изменение было сделано для увеличения параллельности работы пользователей.
Способ хранения констант в 1С:Предприятие 8 менялся в зависимости от версии платформы. Так, в платформе до версии 8.2.14 (или платформах выше версии, но с включенным режимом совместимости 8.2.13 и ниже), константы хранятся в одной таблице СУБД, начиная с версии 8.2.14, для каждой константы создается своя таблица СУБД. Данное изменение было сделано для увеличения параллельности работы пользователей.
В общем, решил сделать так: при старте системы получаем список возможных артикулов, для каждого из них формируем текущее максимальное значение и сохраняем в структуру , а дальше при каждом вызове этой процедуры возвращаем +1, не забывая увеличивать максимальный номер в структуре. Если это не полностью исключит возникновение дублей, то как минимум снизит количество таких ошибок, мне думается. Если не поможет, то буду мутить с константами и блокировками.
(9) Вопрос про блокировку структуры и "для всех сеансов одновременно" хороший. Я почему-то подумал, что оно там разок скомпилируется и будет висеть, типа как синглтон в других языках, но чувствую, ошибся тут. А что касается чем структура от справочника отличается, так ответ очевиден: из справочника мы получаем эти данные запросом и чем больше элементов, тем дольше это все выполняется, а в структуре просто плюсуем и все.
И по факту даже если мы блокируем константу в исключительном режиме мы все равно можем ее без проблем читать, не можем только изменить ее значение до момента пока первая транзакция не завершится. Так-что все наши рассуждения тут бесполезны в контексте решения поставленной задачи.
проверял след образом: Есть процедура которая получает максимальный номер артикула, добавил в нее блокировку константы, после блокировки установил точку останова. Накидал внешнюю обработку для установки и чтения нужной константы. Запускаю получение нового артикула, выполнение стопорится где нужно, из другого сеанса запускаю обработку, читаю константу - без проблем читается, пытаюсь записать - висит, завершаю транзакцию(снимается блокировка) обработка получает доступ к установке значения константы. Так что вариант не рабочий, к сожалению.
проверял след образом: Есть процедура которая получает максимальный номер артикула, добавил в нее блокировку константы, после блокировки установил точку останова. Накидал внешнюю обработку для установки и чтения нужной константы. Запускаю получение нового артикула, выполнение стопорится где нужно, из другого сеанса запускаю обработку, читаю константу - без проблем читается, пытаюсь записать - висит, завершаю транзакцию(снимается блокировка) обработка получает доступ к установке значения константы. Так что вариант не рабочий, к сожалению.
Вижу только одно решение на текущий момент, при условии, что нигде ничего не упустил из вида: использовать константу в качестве семафора. Заходит в процедуру общего модуля, проверяем нет ли блокировки на константе, если нет, значит никто сейчас не пытается получить артикул, устанавливаем блокировку, формируем новый номер, транзакция завершается, блокировка снимается и тогда уже след поток сможет ее заблокировать. Другие потоки в цикле ждут освобождения. Надеюсь, это ничто не помешает реализовать.
Все, задачу решил.
Если кому-то еще надо будет, то вот:
Если кому-то еще надо будет, то вот:
//Функция общего модуля которая делает запрос и выбирает максимальный из существующих
Функция МаксимальныйНомерАртикула(Префикс,Характеристика = Ложь) Экспорт
Попытка
БлокировкаДанных = Новый БлокировкаДанных;
БлокировкаКонстанты = БлокировкаДанных.Добавить("Константа.УА_Артикул");
БлокировкаДанных.Заблокировать();
Исключение
//Сообщить("Объект уже заблокирован");
Возврат Ложь;
КонецПопытки;
//
// тут код получения нужных данных и их возврата
//
КонецФункции
//Код в объекта где требуется получить уникальный номер
Процедура УстановитьАртикул()
НачатьТранзакцию(); //Использование транзакций обязательно для использования блокировки объекта
Артикул = Ложь;
Пока НЕ Число(Артикул) Цикл //Артикул возвращается строкой, а строка не может быть преобразована к
//булево, поэтому преобразуем к числу, а число легко преобразуется к
//булево, нулевого артикула у меня быть не может.
Артикул = Число(УА_ОбщийСервер.МаксимальныйНомерАртикула("Префикс-"))+1;
КонецЦикла;
Сообщить("Артикул :"+Артикул);
ЗафиксироватьТранзакцию(); //Возможно эту часть можно опустить , но у меня эта функция во внешней
//обработке , поэтому явно завершаю транзакцию.
КонецПроцедуры
Показать
Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот