Имя: Пароль:
1C
1С v8
Обеспечение уникальности реквизита справочника.
,
0 kdenis
 
04.10.15
17:32
Доброго дня!
8.3.6

Прошу помощи в решении задачи обеспечения уникальности реквизита справочника.
Есть справочник Штрихкоды (Штрихкод - строка()15, ТипШтрихкода - ПланВидовХарактеристик.ТипыШтрихкодов, прочие реквизиты...). Необходимо обеспечить уникальность реквизита Штрихкод при многопользовательской работе. Элементы справочника в большинстве своем создаются массово обработкой (от 300 штук), запускать процесс создания могут несколько пользователей одновременно.

Алгоритм создания каждого элемента:
1. Создаем элемент справочника.
2. Запросом получаем текущий максимальный Штрихкод.
3. Присваиваем новый штрихкод созданному в 1 элементу (НовыйШтрихкод = Штрихкод + 1)
4. Записываем элемент справочника.
5. В событии ПередЗаписью запросом контролируем уникальность реквизита Штрихкод, в случае, если он не уникален - Отказ (необходимо в том случае, если элемент создавался вручную, а не обработкой)

Проблема.
Если несколько пользователей запускают создание штрихкодов одновременно или с небольшим интервалом, возникает такая ситуация:
1. Два пользователя одновременно получили запросом текущий максимальный штрихкод.
2. Вычислили новый штрихкод.
3. Записали каждый свой элемент с одинаковым штрихкодом.
4. У того пользователя, который записал элемент первым проблем не возникло. Другой же пользователь в обработчике ПередЗаписью получил отказ, т.к. его штрихкод уже содержится в справочнике.

Прошу тех, кто решал подобную задачу поделиться опытом, а тех кто не решал - идеями.

Мои мысли:
Вычисление нового штрихкода и запись элемента делать в транзакции, и в начале этой транзакции заблокировать справочник целиком для чтения другим транзакциям.
Не могу придумать механизм блокировки справочника целиком.
Изучал объект БлокировкаДанных, но в документации не нашел примеров блокировки именно справочника целиком. Если есть те, кто разбирался с этим объектом, подскажите как решить задачу с помощью него.
1 Garykom
 
гуру
04.10.15
17:35
а заснуть ШК в код? с уникальностью оных?
2 mehfk
 
04.10.15
17:35
Создавай штрихкоды в обратном порядке.
3 Garykom
 
гуру
04.10.15
17:36
или в регистр сведений ШК заносить а не в справочник
4 бомболюк
 
04.10.15
17:36
получение текущего макс. штрихкода и его изменение делаем в транзакции, получение делаем запросом с хинтом ДЛЯ ИЗМЕНЕНИЯ.
5 ДенисЧ
 
04.10.15
18:03
транзакции не предлагать?
6 kdenis
 
04.10.15
18:07
(1) Нет, штрихкод может быть различной длины (EAN8, EAN13). Автоматическое создание следующего невозможно. Т.е. новый штрихкод снова получить запросом. Следовательно, задача не решена.
(2) Не понял, как это поможет мне контролировать уникальность.
(3) А таблицу регистра сведений можно заблокировать целиком для чтения другими транзакциями?
(4) А разве при этом блокировка не снимается по окончании выполнения запроса? Запись-то происходит после него.
(5) Конечно предлагать, только по возможности пояснить, как заблокировать справочник в одной транзакции для чтения его другими транзакциями.
7 бомболюк
 
04.10.15
18:13
(6) блокировка снимается по окончании транзакции.
8 rphosts
 
04.10.15
18:16
(6)самый надёжный способ - блокировать запуск обработки несколькими пользователями.
9 kdenis
 
04.10.15
18:20
(7) По-моему предложение ДЛЯ ИЗМЕНЕНИЯ не защитит таблицу от чтения другими транзакциями. Т.е. несколько транзакций смогут получить одинаковый штрихкод. Так?
10 kdenis
 
04.10.15
18:22
(8) Это понятно, но работа этих пользователей и заключается именно в использовании этой обработки. И неплохо было бы программно разрулить эту очередь, а не заставлять пользователей договариваться.
11 rphosts
 
04.10.15
18:26
(10) ок, если у кого-то выполняется генерация кодов - другой по клику на эту кнопку получит сообщение, что покури пару сек и повтори.
12 Garykom
 
гуру
04.10.15
18:31
(6) ну тогда сделать регистр сведений "зарезервированные номера ШК"
т.е. сначала резервируем номера, если не получилось то читаем что там и снова резервируем
и только потом создаем ШК
13 бомболюк
 
04.10.15
18:31
(9) если кто то читает с ДЛЯ ИЗМЕНЕНИЯ, то ты уже не прочитаешь с ДЛЯ ИЗМЕНЕНИЯ, оно для этого и придумано.
14 Garykom
 
гуру
04.10.15
18:33
(12) +
еще можно извратиться с регламентным заданием или еще каким сервисом ))
который будет в единственном экземпляре на базу запускаться
и выдавать номера ШК по запросу
15 Garykom
 
гуру
04.10.15
18:34
(14) +
т.е. нечто вроде очереди, куда помещается номер (код, гуид и т.д.) и типШК, с пустым значением шк
далее отрабатывает регламентное и читаем оттуда заполненные (присвоенные) ШК
16 torgm
 
04.10.15
19:55
(0) Выделяй манагерам диапазоны по 50-100-200 штрихкодов (в зависимости от твоих условий) , если использовали то следующий.
17 dmpl
 
04.10.15
20:24
(0) Процедура на сервере ПолучитьСледующийШтрихКод(), которая блокирует некий объект (один на всех) и раздает централизованно номера.
18 kdenis
 
04.10.15
23:38
(12) За идею спасибо. Рассматривал похожий вариант на крайний случай, но не хотелось дублировать данные.
(13) Вот это поизучаю подробнее и потестирую. Не догадывался, что два запроса могут вытеснить друг друга. Спасибо. Пока единственный предложенный способ, опирающийся именно на блокировки.
(14) Слишком загонно. Но спасибо.
(17) Такая процедура есть, в ней запрос с выборкой максимального штрихкода. Остается открытым вопрос как заблокировать "некий объект", в моем случае справочник штрихкодов.
19 itlikbez
 
05.10.15
01:03
(18) заблокировать можно блокировкой.
20 FIXXXL
 
05.10.15
07:11
А может нумератор сэмулировать? Константа к примеру "макс.номер". Ее и блокировать до конца записи элемента справочника.
21 DCKiller
 
05.10.15
07:38
(0) Лучше сделай обработку исключительной ситуации, чтобы в случае, если такой ШК уже кто-то ввел, программа автоматически добавляла 1 к ШК, который не хочет записываться, и в таком виде сохраняла его в справочнике, предварительно уведомив юзера. Можно даже сделать, чтобы в этом случае у юзера выдавалось на экран подтверждение, нужно ли записать элемент с таким ШК.
22 FIXXXL
 
05.10.15
09:19
(21) и пока юзер чай пьет и +1 и +еще сто номеров уже займут :)
23 kdenis
 
05.10.15
09:30
(20) Спасибо за участие. Эта идея тоже в резерве на крайний случай, наряду с регистром штрихкодов.

На самом деле рассчитывал обойтись блокировкой справочника, а не изобретать костыли. Но раз заведомо рабочего примера с блокировкой никто не дал, возможно платформа не позволяет решить задачу встроенными механизмами.
24 ЧеловекДуши
 
05.10.15
09:31
(23) На УФ блокировки справочника уже не блокируют :)
25 kdenis
 
05.10.15
09:32
(24) Это вопрос или утверждение?
26 DCKiller
 
05.10.15
09:58
(22) Нефиг столько времени пить чай.
27 Bober
 
05.10.15
10:00
(0) В 8.3 реализовали возможность накладывать блокировки на реквизиты справочников.
Перед записью накладываешь блокировку на спр по реквизиту и запросом проверяешь уникальность (за исключением ссылки на текущий элемент).
28 kdenis
 
05.10.15
10:09
(27) Уже ближе к истине. Можете подсказать, где прочитать про эту возможность?
29 Bober
 
05.10.15
10:26
(28) в конфигураторе, синтакс-помощник, раздел общие объекты - Управление блокировкой данных. там и примеры кода есть.
30 kdenis
 
06.10.15
13:00
(29) Читал про объект БлокировкаДанных и в СП, и в Профессиональной разработке в системе "1С:Предприятие 8".

Везде написано как по шаблону:
1. Создать объект.
2. Добавить элемент, указав пространство блокировки.
3. Установить значение, которое будет заблокировано.
4. Установить режим.
5. Заблокировать

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

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

"Рабочее" (в кавычках, т.к. выводы по результатам эксперимента на файловой СУБД и PostgreSQL) решение следующее:
1. Начинаем транзакцию (РежимУправленияБлокировкойДанных.Управляемый)
2. Объектом БлокировкаДанных устанавливаем блокировку (Имя пространства имен - мой справочник). Значение не указываем.
3. Запросом вычисляем текущий штрихкод, и вычисляем значение нового.
4. Создаем элемент справочника, присваиваем штрихкод и записываем его.
5. Фиксируем транзакцию.

На сколько это решение действительно рабочее неизвестно, т.к. теоретического обоснования найти не удалось.
31 asady
 
06.10.15
13:15
(0) может тупо генерить штрихкоды как уиды? - в смысле отказаться от автоинкремента.
32 kdenis
 
06.10.15
15:38
(31) Спасибо и за эту идею.
Есть два вида языков, одни постоянно ругают, а вторыми никто не пользуется.