|
8.2 Как распараллелить работу пользователей | ☑ | ||
---|---|---|---|---|
0
The_SpecialOne
09.12.13
✎
14:11
|
Добрый день! Столкнулся с вот такой задачей:
Есть непериодический, независимый регистр сведений "Номера" с 1 измерением "Порядковый номер". Режим управления блокировкой "Управляемый" Есть 30 пользователей, которые одновременно раз в секунду жмут кнопку, по которой в этот регистр должна добавиться запись с порядковым номером на 1 больше максимального. Если использовать след. вариант, то 29 пользователей, получив один и тот же номер, ждут 20 сек. установку блокировки, пока 1 записывает максимальный номер.
Понятно, что условие очень утрировано, но такая ситуация периодически возникает. Хотелось бы узнать, есть ли возможности в этой ситуации обойтись без блокировок? уменьшить частоту их наложения? уменьшить длительность ожидания на блокировку (кроме установки в параметрах ИБ в конфигураторе)? Вобщем хочется, чтобы когда 1 пользователь установил блокировку, то остальные, несумев установить такую же без ожидания 20 сек., сразу же пытались сделать запись с порядковым номером на 1 больше. |
|||
1
mikecool
09.12.13
✎
14:14
|
"Вобщем хочется, чтобы когда 1 пользователь установил блокировку, то остальные, несумев установить такую же без ожидания 20 сек., сразу же пытались сделать запись с порядковым номером на 1 больше." не взлетит
|
|||
2
Bober
09.12.13
✎
14:17
|
(0) перейти на справочник с автонумерацией
|
|||
3
Sammo
09.12.13
✎
14:20
|
Изменить задачу.
Например 2 Например, присваивать номера потом отдельным заданием |
|||
4
The_SpecialOne
09.12.13
✎
14:24
|
(2) На справочник перейти не вариант, уж больно много уже завязано на регистре. А вот прикрутить механизм нумерации в процедуру перед записью, впринципе, можно попробовать
(3) Задача бесспорно дурацкая, но увы ничего не поделать... Присваивать номера потом - тоже не вариант, пользователи используют те номера, которые генерят по нажатию своей кнопки |
|||
5
Eugene_life
09.12.13
✎
14:38
|
(4) а если просто по-тупому завести константу "Последний номер" и с нее выдавать номер, сразу его меняя в +1 ?
|
|||
6
The_SpecialOne
09.12.13
✎
14:45
|
(5) Вариант с константой не прокатит. На нее тоже нужно будет накладывать блокировку.
Иначе для пользователей А и Б возможна ситуация: А: прочитал константу Б: прочитал константу А: установил константу (+1) Б: установил константу (+1) Таким образом пользователи А и Б получили один и тот же порядковый номер, что критично в моей задаче. |
|||
7
mikecool
09.12.13
✎
14:48
|
(6) польз А получил код, отказался - что будет?
|
|||
8
Eugene_life
09.12.13
✎
14:49
|
(6) Понятно. Ну, а если порядковый номер вычислять из данных самого регистра? Скажем, пусть по нажатию кнопки данные запишутся в регистр, а вернется пользователю номер. например, номер = порядковый номер строки в регистре.
|
|||
9
The_SpecialOne
09.12.13
✎
15:01
|
(7) Отказ не принципиален, если какой-то Порядковый номер будет пропущен - проблем не будет.
(8) Интересно, сейчас попробую |
|||
10
The_SpecialOne
09.12.13
✎
15:30
|
(8) хм, а как получить номер строки в регистре?
"Выбрать Количество(Номера.ПорядковыйНомер) из Номера"? Тогда на время выполнения этого запроса нужно полностью блокировать регистр чтобы не было ситуации описанной в (6) |
|||
11
Мимохожий Однако
09.12.13
✎
15:35
|
Какой ресурс у регистра?
|
|||
12
mistеr
09.12.13
✎
15:40
|
(0) Во-первых, непонятно, где завершение транзакции.
Во-вторых, код по-моему неверный. Между Запрос.Выполнить().Выбрать() и НачатьТранзакцию() кто-то может успеть вставить новый номер, и блокировка будет наложена не на максимальный номер. В третьих, архитектура конечно так еще, почему с самого начало не использовались механизмы платформы, непонятно. Переходите на нумератор или на крайний случай на константу. Ситуация (6) решается так: 1. Начинаем транзакцию 2. Блокируем 2. Получаем максимальный номер 3. Записываем +1 4. Завершаем транзакцию 5. Возвращаем новое значение |
|||
13
The_SpecialOne
09.12.13
✎
15:48
|
(11) У регистра несколько ресурсов, которые должны идентифицироваться порядковым номером в измерении ресурса. (12) Код приведен неполностью и несовсем так, как он написан в реальной базе. Естественно завершение транзации есть.
В реальной базе сейчас устанавливается разделяемая блокировка и пользователи отбрасываются при попытке записать уже существующий номер. Вариант с константой никак не облегчает задачу. Разницы между тем блокировать 1 запись регистра или блокировать константу нет. Все равно часть пользователей будет висеть в ожидании завершения транзакции 1 пользователем |
|||
14
The_SpecialOne
09.12.13
✎
15:52
|
(12) Архитектуру формировали предшественники, я уже разгребаю за ними.
|
|||
15
Enders
09.12.13
✎
16:06
|
Ну если с блокировками проблему уже решили, а осталась с попыткой записать такой же номер. То делайте это в попытке исключении.
Что-то типо: Процедура Записи() Номер = 0; ЗаписатьНомер(Номер); КонецПроцедуры Процедура ЗаписатьНомер(Номер) Попытка //Записываем Исключение Если ОшибкаЗаписиСуществующего Тогда ЗаписатьНомер(Номер+1); Иначе Сообщить(ОписаниеОшибки()); КонецЕсли; КонецПопытки; КонецПроцедуры Криво конечно. Как анализировать что это именно ошибка записи существующего не думал ;) |
|||
16
The_SpecialOne
09.12.13
✎
16:31
|
(15) Нет, с блокировками проблема не решается установкой разделяемого режима блокировки. Просто в этом случае блокировка без проблем устанавливаются, а пользователи отваливаются уже при попытке записи недопустимого номера.
Основная проблема в том, что до того как пользователь отваливается, он ждет 20 сек. - стандартное время ожидания на блокировку. Пока вижу только одно решение - переход на справочник с автонумерацией. |
|||
17
The_SpecialOne
09.12.13
✎
17:03
|
(15) блин, прикольная идея. Можно же ориентироваться на то что у меня 1 ключевое измерение и отлавливать ошибки записи набора. При этом нет никакого ожидания. Блокировки вообще не нужны. Сделал так:
Запустил 10 сеансов, каждую секунду каждый сеанс делает новую запись. Периодически получаю сообщения: отвалился! Номер: 137669 время: 09.12.2013 14:51:32 отвалился! Номер: 137670 время: 09.12.2013 14:51:32 отвалился! Номер: 137671 время: 09.12.2013 14:51:32 Но никакой задержки на установку блокировки, рано или поздно каждый получает свой номер. |
|||
18
mistеr
09.12.13
✎
22:57
|
(13) Ты не понял похоже. Смысл в том, чтобы не держать блокировки долго, тогда не будет ожидания. Сейчас у тебя (если я правильно понял) блокировка держится до момента записи в регистр. А нужно выдать номер и сразу отпустить.
Константа нужна, чтобы хранить максимальный номер из *выданных* (но еще не записанных) |
|||
19
The_SpecialOne
09.12.13
✎
23:34
|
(18) ага, теперь понял. Теперь вопрос, что лучше: обработка Попытка/Исключение или блокировка на константу?
|
|||
20
EvgeniuXP
09.12.13
✎
23:44
|
(19) смотря какую версию платформы используешь, если до 8.2.14 - то константы хуже, если от - то лучше.
|
|||
21
The_SpecialOne
10.12.13
✎
00:12
|
(20) как раз таки 8.2.14, значит оставлю попытку исключение. Спасибо
|
|||
22
mistеr
10.12.13
✎
00:39
|
(19) Какая Попытка/Исключение? Если (17), то там жуть. Во-первых, ты не проверяешь ошибку, хотя (15) тебе показал. Это пахнет бесконечной рекурсией.
Во-вторых, кто будет удалять запись, если пользователь раздумает ее сохранять? И где гарантия, что не будет удалена чужая. |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |