Имя: Пароль:
1C
1С v8
Некорректная выборка в запросе из регистра сведений. Формирование штрихкода.
0 Bigot1979
 
31.01.17
10:58
Появилась тут нешуточная проблема после обновления субд....
В конфе на базе УТ 10.3 допилено формирование штрихкодов для документов.  Добавлен для этого отдельный регистр сведений ШтрихкодыДокументов.
[URL=http://shot.qip.ru/00eASM-6768CoQfb/][IMG]http://f6.s.qip.ru/~768CoQfb.png[/IMG][/URL]
До прошлой недели было всё нормально пока не обновили постгрес. Плюсом немного изменили регистр сведений ( Для измерения "документ" явно указали типы документов).
Формирование штрихкода организовано через подписку на события при записи документа. При записи вызывается УстановкаШКДокументаПриЗаписи;
Изначально для регистра стоял режим управления блокировками автоматический. В принципе вероятность формирования одинакового ШК была. Ну блин в ночь переделал на управляемый, наложил исключительную блокировку.... не помогло...
Куда копать не знаю...

Функция СформироватьШтрихКодДокумента(Знач ПрефиксВнутреннегоШтрихкода = Неопределено)
    Если ПрефиксВнутреннегоШтрихкода = Неопределено Тогда
        ПрефиксВнутреннегоШтрихкода = Константы.ПрефиксВнутреннегоШтрихкода.Получить();
    КонецЕсли;

    ПрефиксВнутреннегоШтрихкода = Формат(ПрефиксВнутреннегоШтрихкода, "ЧЦ=2; ЧН=; ЧВН=");
    ПрефиксКодаДокумента="9";

        Запрос = Новый Запрос("
    |ВЫБРАТЬ
    |    МАКСИМУМ(РегШтрихКоды.Штрихкод) КАК Код
    |ИЗ
    |    РегистрСведений.ШтрихКодыДокументов КАК РегШтрихКоды
    |");

    Выборка = Запрос.Выполнить().Выбрать();
    Выборка.Следующий();
    Если Выборка.Код = NULL ТОгда
        ВыбКод = 1;
    Иначе
        ВыбКод=Сред(Выборка.Код,5,8);
    КонецЕсли;    
    ТекКод = Мин(ОбщегоНазначения.ПривестиСтрокуКЧислу(ВыбКод) + 1, 99999999);

    Штрихкод = "2" + ПрефиксКодаДокумента + ПрефиксВнутреннегоШтрихкода + Формат(ТекКод, "ЧЦ=8; ЧВН=; ЧГ=");
    Штрихкод = Штрихкод + КонтрольныйСимволEAN(ШтрихКод, 13);

    Возврат Штрихкод;
КонецФункции

Процедура УстановкаШКДокументаПриЗаписи(Источник, Отказ) Экспорт
    #Если Клиент Тогда
    СписокДокументовШК=Новый СписокЗначений;
    СписокДокументовШК.Добавить("РеализацияТоваровУслуг");
    СписокДокументовШК.Добавить("ПоступлениеТоваровУслуг");
    СписокДокументовШК.Добавить("РасходныйОрдерНаТовары");
    СписокДокументовШК.Добавить("ПриходныйОрдерНаТовары");
    СписокДокументовШК.Добавить("ПеремещениеТоваров");    
    СписокДокументовШК.Добавить("ВозвратТоваровОтОптовогоПокупателя");    СписокДокументовШК.Добавить("МаршрутныйЛист");    
    СписокДокументовШК.Добавить("НарядНаРазгрузку");
    СписокДокументовШК.Добавить("ПретензияВходящая");    
    СписокДокументовШК.Добавить("АктУстраненияПретензииПокупателя");    

    Если СписокДокументовШК.НайтиПоЗначению(Источник.Метаданные().Имя)<>Неопределено тогда
        Запрос=Новый Запрос;
        Запрос.Текст="ВЫБРАТЬ
                     |    ШтрихкодыДокументов.ШтрихКод
                     |ИЗ
                     |    РегистрСведений.ШтрихкодыДокументов КАК ШтрихкодыДокументов
                     |ГДЕ
                     |    ШтрихкодыДокументов.Документ = &Документ";
        Запрос.УстановитьПараметр("Документ",Источник.Ссылка);            
        Результат=Запрос.Выполнить().Выбрать();            
        Если Результат.Количество()=0 тогда
            НачатьТранзакцию(РежимУправленияБлокировкойДанных.Управляемый);
            Блокировка = Новый БлокировкаДанных;
            ЭлементБлокировки = Блокировка.Добавить();
            ЭлементБлокировки.Область = "РегистрСведений.ШтрихкодыДокументов";
            ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
            Блокировка.Заблокировать();    
            
            ЗаписьШтрихКод=РегистрыСведений.ШтрихкодыДокументов.СоздатьМенеджерЗаписи();
            ЗаписьШтрихКод.Документ=Источник.Ссылка;
            ЗаписьШтрихКод.ТипШтрихКода=ПланыВидовХарактеристик.ТипыШтрихкодов.EAN13;
            ЗаписьШтрихКод.ШтрихКод=СформироватьШтрихКодДокумента();
            ЗаписьШтрихКод.Записать(ложь);
            
            ЗафиксироватьТранзакцию();
        КонецЕсли;    
    КонецЕсли;    
    #КонецЕсли
КонецПроцедуры
1 Мимохожий Однако
 
31.01.17
11:11
Как проявляется ошибка? Описание ошибки дословно есть?
2 Bigot1979
 
31.01.17
11:21
по сути в текущем варианте непонятно КАК второй сеанс может получить доступ на чтение к регистру пока первый не закончил туда запись и не закончил транзакцию.
На практике имеем формирование ОДИНАКОВЫХ штрихкодов для разных документов.
отсюда напрашивается пара вариантов:
1. некорректное считывание последней (максимум) записи в запросе.
2. Доступ на чтение сохраняется не смотря на наложенную блокировку.
По второму варианту на тестовой базе проверил поставив точку остановки после блокировки и во втором сеансе пробовал записать документ. Вылетел дэдлок.
3 Bigot1979
 
31.01.17
11:31
Сейчас ещё раз проверил. Поставил точку остановки на строчку "ЗафиксироватьТранзакцию". Во втором сеансе доступа к чтению регистра нет. Получается блокировка ставится нормально.
Мистика какая то блин.
Раньше версия Постгреса была 9.2.1-1.1C. Сейчас на новом сервере 9.4.2-1.1C

Может какие настройки постгреса могут влиять на получение "устаревших" данных из регистра ?
4 BeerHelpsMeWin
 
31.01.17
11:35
в РС не осталось ли какого-нибудь мусора?
что возвращает
|ВЫБРАТЬ
|    МАКСИМУМ(РегШтрихКоды.Штрихкод) КАК Код
?
5 Альбатрос
 
31.01.17
11:41
(0) Может считали "одновременно", до начала блокировки.
6 Мимохожий Однако
 
31.01.17
11:43
(2) У тебя есть третье измерение ТипШтрихкода. Если тип разный, то возможно сочетание одного штрихкода для разных документов. Какой тип у реквизита Штрихкод?
7 Bigot1979
 
31.01.17
11:48
(4) Мусора какого плана ? Туда же чисто штрихкоды документов пишутся и всё.
В консоли запросов мальца потыкал... вроде нормально читается последний штрихкод... Но опять же, поток документов в базе большой. В день несколько сотен со штрихкодами. Дубли появляются периодически и закономерности я так и не отследил. За вчерашний день порядка 50 дублей вылезло. За сегодня вот пока только два раза было.
Расходный ордер на товары УТТС0000931 от 31.01.2017 11:45:30    2900013172016    На склад
Расходный ордер на товары УТСК0004725 от 31.01.2017 11:45:29    2900013172016    На склад
8 Bigot1979
 
31.01.17
11:51
(5) это было моё предположение до того, как я вменил режим блокировок на управляемый. Ну думаю на новом серваке быстро писаться стало... аж дубли появились...
Сейчас до чтения последнего ставится исключительная блокировка. Вызов повторный подписки на событие при записи будет ждать пока первая не отработает.

Кстати... а если в одном сеансе скажем так обработкой формируются документы и в этом же сеансе подписки на события срабатывают... но блокировка то один хрен должна быть в рамках транзакции... или нет ????
9 Bigot1979
 
31.01.17
11:57
(6) Характеристика.ТипыШтрихкодов
Да всё как обычно. Там всё EAN13
10 Мимохожий Однако
 
31.01.17
12:08
Попробуй в тексте запроса использовать ДЛЯ ИЗМЕНЕНИЯ
11 Bigot1979
 
31.01.17
12:25
"сижу курю" настройки постргреса...
Есть тут один интересный параметр..
#commit_delay = 1000            # range 0-100000, in microseconds
#commit_siblings = 5            # range 1-1000

Это я сейчас закомментировал, изначально были установлены. Может как раз из-за задержки в опускании  WAL причина ?
12 Bigot1979
 
31.01.17
12:26
(10) Это как ? Подскажите подробнее плиз.
13 Bigot1979
 
31.01.17
12:37
(10) почитал... при управляемых блокировках эта шняга игнорируется. А у меня сейчас управляемый режим и блокировка накладывается в явном виде.
14 zva
 
31.01.17
12:45
Я вот не понимаю, какой смысл в #Если Клиент Тогда
в процедуре УстановкаШКДокументаПриЗаписи.
Также не понимаю смысла вариации блокировки у регистра целиком, когда при проведении документа блокируется весь регистр. Блокировка на РС всегда лежит внутри другой блокировки "При записи" документа, и если первая блокировка хотя бы для одного из типов документов начинается в автоматическом режиме, то не важно что прописано в коде, и какой режим блокировок стоит у РС, блокировка на РС внутри записи данного документа будет автоматическая.

http://its.1c.ru/db/metod8dev#content:5839:hdoc
Рассмотрим другой пример - интерактивное проведение документа, который выполняет движения по регистру накопления. В этом случае «первой» (неявной) транзакцией будет транзакция, открываемая системой при записи документа, а «второй» (также неявной) будет транзакция, открываемая системой при записи набора записей регистра накопления.
Далее все аналогично предыдущему примеру. Если для документа в метаданных установлен автоматический режим управления блокировками, то независимо от того, какой режим установлен в метаданных для регистра накопления, запись его набора записей всегда будет выполняться в автоматическом режиме.
15 Bigot1979
 
31.01.17
14:30
(14)#Если Клиент особо не нужно, исторически осталось. При групповых обработках делали что бы не выполнялось. На код не влияет в текущий момент.
/Блокировка на РС всегда лежит внутри другой блокировки "При записи" документа/
Регистр сведений у нас независимый, так что автоматической блокировки не будет по всей видимости. Или я туплю не по детски ?

/«первой» (неявной) транзакцией будет транзакция/
и как быть ?
на MSSQL 2012 работало нормально.
На PostgreSQL 9.2.1 работало нормально.
16 zva
 
01.02.17
04:49
Мне сама идея регистра, который блокируется целиком при записи любого документа из 10 видов не нравится от слова совсем. Почему не использовать другой тип штрих-кода, например, Code128. Даже если использовать EAN13, можно же сделать что то вроде:
двумя цифрами кодируем тип документа, двумя последние две цифры года, дальше одна цифра - код организации (если их несколько) и числовой номер документа без всяких префиксов, чтоб генерировать уникальный штрих-код для каждого документа без всяких блокировок.
17 Bigot1979
 
03.02.17
11:45
(16) дата документа может измениться, фирма документа тоже... да всё, что угодно поменять могут. В итоге не уникальные штрихкоды.
Единственный вариант как-то к UID привязываться наверное.


Короче попробовал вернуть режим управления блокировками для регистра на "Автоматический". В запросе прописал "|ДЛЯ ИЗМЕНЕНИЯ".
Не прокатило. :-(

Сегодня установил другую версию платформы 8.3.8.2322, будь она неладна. Заколебали вылетать вопросы про безопасность открытия файлов. Эту хрень вообще отключить можно ???
ПС пока дублей штрихкодов нет... смотрим дальше...
18 Bigot1979
 
03.02.17
13:48
Пол дня, полёт нормальный. Отсюда напрашивается вопрос про корректность... ну или некоторые нюансы наложения блокировок на платформе 8.3.9.1850.
На выходных посмотрю наверное на тестовой базе какие блокировки эта сволочь накладывает.
Компьютер — устройство, разработанное для ускорения и автоматизации человеческих ошибок.