Версия для печати темы (https://pro1c.org.ua/index.php?s=3a80b0326e4aee67f681fc7bbcb68e38&showtopic=57223)

Нажмите сюда для просмотра этой темы в обычном формате

Украинский 1С форум: всё про 1С 8.3, 1С 8.2, 1С 8.1, 1С 8.0, 1С 7.7 _ Программирование в 1С Предприятие 8.3 _ Конфликт блокировок при выполнении транзакции

Автор: Мичман Харитонов 21.02.20, 13:01

Платформа 8.3.7.18.60
База самописная
В определенный момент без видимой причины (в тот день изменения в конфигурацию не вносились, был в командировке), начались проблемы с конфликтом блокировок.
С утра работает нормально, потом каждые пару часов приходится перезагружаться или перезапускать службы.
Пишет "По причине.... ошибка выполнения запроса." При чем, сам запрос простенький

Запрос.Текст = 
        "ВЫБРАТЬ
        |    ТоварыОтгруженные.Фирма КАК Фирма,
        |    ТоварыОтгруженные.ДокументПродажи,
        |    ТоварыОтгруженные.ДокументПродажи.Дата,
        |    ТоварыОтгруженные.Номенклатура КАК Номенклатура,
        |    ТоварыОтгруженные.СуммаОстаток КАК Сумма,
        |    ТоварыОтгруженные.Договор
        |ИЗ
        |    РегистрНакопления.ТоварыОтгруженные.Остатки(&МоментВремени, Контрагент = &Контрагент) КАК ТоварыОтгруженные
        |
        |УПОРЯДОЧИТЬ ПО
        |    Фирма,
        |    ТоварыОтгруженные.ДокументПродажи.Дата";
        
        Выборка = Запрос.Выполнить().Выбрать();

Подскажите пожалуйста, что могло случиться?

Автор: fly 21.02.20, 13:11

Цитата(Мичман Харитонов @ 21.02.20, 13:01) *
&МоментВремени


&МоментВремени - и где момент времени?
&Контрагент - ну и Контрагент

Автор: Мичман Харитонов 21.02.20, 13:18

Понял. Вот полностью

//Новая версия, попытка увеличить скорость процедуры
    Если Истина Тогда
        
        Запрос = Новый Запрос;
        ТекстЗапроса = "ВЫБРАТЬ
                       |    ОграниченияОтгрузок.Фирма,
                       |    ОграниченияОтгрузок.Контрагент КАК Контрагент,
                       |    ОграниченияОтгрузок.Номенклатура КАК Номенклатура,
                       |    ОграниченияОтгрузок.ДнейОтсрочки КАК ДнейОтсрочки
                       |ИЗ
                       |    РегистрСведений.ОграниченияОтгрузокКонтрагентам.СрезПоследних(
                       |            &МоментВремени,
                       |            Контрагент = &Контрагент
                       |                ИЛИ Контрагент = ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)) КАК ОграниченияОтгрузок";
        Запрос.Текст = ТекстЗапроса;
        Запрос.УстановитьПараметр("Контрагент", Контрагент);
        Запрос.УстановитьПараметр("МоментВремени", МоментВремени);
        тзОграниченияОтгрузок = Запрос.Выполнить().Выгрузить();
        тзОграниченияОтгрузок.Индексы.Добавить("Фирма, Контрагент, Номенклатура");
        
        НайденнаяСтрока = тзОграниченияОтгрузок.Найти(Контрагент, "Контрагент");
        Если НайденнаяСтрока <> Неопределено Тогда
            ЕстьОтсрочкиКонтрагенту = Истина;
        КонецЕсли;
        
        БуфферОграничений = тзОграниченияОтгрузок.СкопироватьКолонки("Фирма, Номенклатура, ДнейОтсрочки");
        СуммыПросроченнойЗадолженностиКонтрагентаПоФирмам = Новый Соответствие;
        МаксимальнаяОтсрочка = 0;
        ПредоплатаПоДоговору = Истина;
        
        Запрос.Текст =
        "ВЫБРАТЬ
        |    ТоварыОтгруженные.Фирма КАК Фирма,
        |    ТоварыОтгруженные.ДокументПродажи,
        |    ТоварыОтгруженные.ДокументПродажи.Дата,
        |    ТоварыОтгруженные.Номенклатура КАК Номенклатура,
        |    ТоварыОтгруженные.СуммаОстаток КАК Сумма,
        |    ТоварыОтгруженные.Договор
        |ИЗ
        |    РегистрНакопления.ТоварыОтгруженные.Остатки(&МоментВремени, Контрагент = &Контрагент) КАК ТоварыОтгруженные
        |
        |УПОРЯДОЧИТЬ ПО
        |    Фирма,
        |    ТоварыОтгруженные.ДокументПродажи.Дата";
        
        Выборка = Запрос.Выполнить().Выбрать();

Автор: fly 21.02.20, 13:26

Цитата(Мичман Харитонов @ 21.02.20, 13:01) *
"По причине.... ошибка выполнения запроса."

ну как бы желательно причину

и непосредственно, переменные МоментВремени и Контрагент код где определяется

Автор: Мичман Харитонов 21.02.20, 13:32

Этот код в процедуре Общего модуля, МоментВремени и Контрагент передаются из документа, в котором происходит проверка задолженности
Сообщение об ошибке вот

Автор: fly 21.02.20, 13:49

Мичман Харитонов @ Сегодня, 13:32 * ,
В управляемом режиме блокировки, при выполнении запроса данные не блокируются.
Посмотрите, какой режим блокировки установлен на регистре и документе.

Автор: Мичман Харитонов 21.02.20, 14:01

Автоматический режим, на всей конфигурации.


Толстый клиент

Допустим, если запустить Тестирование и Исправление, то базе, полегчает (насколько - сложный вопрос, но все же)?

Автор: fly 21.02.20, 14:07

Цитата(Мичман Харитонов @ 21.02.20, 14:01) *
тестирование и Исправление, то базе, полегчает (насколько - сложный вопрос, но все же)?

на блокировки не влияет
служит для диагностики и устранения ошибочных состояний информационной базы (реиндексация таблиц, проверка логической целостности и т.д.)
попробуйте поставить на базе "Управляемый" на Регистре и документе "управлемый" режим блокировки.

Автор: Мичман Харитонов 21.02.20, 14:12

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

Автор: fly 21.02.20, 15:16

Мичман Харитонов @ Сегодня, 14:12 * ,
Таблицы данных увеличиваются, в итоге может появиться "избыточная блокировка" (обычно этот эффект появляется при параллельном проведении документов, во время него самым первым документом блокируется большой объем записей регистров на все время проведения документа).
В автоматическом режиме в транзакциях используется уровень изоляции SERIALIZABLE (запрещает чтение и запись).
В управляемом режиме в транзакциях используется уровень изоляции ReadCommitted (запрещает запись и проверяет нет ли в этот момент параллельных записей, после завершения запроса блокировки снимаются не дожидаясь завершения транзакции).

Обычно лечение начинают переводом конфигурацию из «Автоматического» режима управления блокировкой данных в «Управляемый» (лично не встречал стандартные Конфигурации от 1С в режиме "Автоматического" режима блокировок, все шли в "Управляемом"), и транзакции начнут выполняться на уровне изоляции типа ReadCommitted, вместо SERIALIZABLE или Repeatable Read.

Если далее вдаваться в детали. то нужно идти SQL Server Profiler....... что точно уже дебри, но почитать можете, полезная вещь.

fly @ Сегодня, 14:56 * ,
..... бла/бла/бла про SQL - в итоге все завершается процессами "поиска" и "оптимизации".
Смыла нет выгружать ТЗ потом индексировать, находить строку, и уже по строке определять если найдена = есть отсрочка, не найдена = нет отсрочки.
А потом брать и копировать таблицу без колонки Контрагент.
достаточно просто проверить свойство РезультатаЗапроса - Пустой() - возврат Булево, если пустой - отсрочки нет.
И сразу результат выгрузить в итоговую таблицу и т.д.


Запрос = Новый Запрос;
        Запрос.МенеджерВременныхТаблиц = новый МенеджерВременныхТаблиц;
        ТекстЗапроса = "ВЫБРАТЬ
                       |    ОграниченияОтгрузок.Фирма,
                       |    ОграниченияОтгрузок.Номенклатура КАК Номенклатура,
                       |    МИНИМУМ(ОграниченияОтгрузок.ДнейОтсрочки) КАК ДнейОтсрочки,
                       |    СУММА(ВЫБОР КОГДА ОграниченияОтгрузок.Контрагент = &Контрагент ТОГДА 0 ИНАЧЕ 1 КОНЕЦ) КАК ЕстьОтсрочка
                       |    
                       |ИЗ
                       |    РегистрСведений.ОграниченияОтгрузокКонтрагентам.СрезПоследних(
                       |            &МоментВремени,
                       |            Контрагент = &Контрагент
                       |                ИЛИ Контрагент = ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)) КАК ОграниченияОтгрузок
                       |     СГРУППИРОВАТЬ ПО
                       |      ОграниченияОтгрузок.Фирма,
                       |    ОграниченияОтгрузок.Номенклатура КАК Номенклатура";
        Запрос.Текст = ТекстЗапроса;
        Запрос.УстановитьПараметр("Контрагент", Контрагент);
        Запрос.УстановитьПараметр("МоментВремени", МоментВремени);
        БуфферОграничений = Запрос.Выполнить();

        Если БуфферОграничений.Итог("Фирма") > 0 Тогда
            ЕстьОтсрочкиКонтрагенту = Истина;
        КонецЕсли;
        
                СуммыПросроченнойЗадолженностиКонтрагентаПоФирмам = Новый Соответствие;
        МаксимальнаяОтсрочка = 0;
        ПредоплатаПоДоговору = Истина;
        
        Запрос.Текст =
        "ВЫБРАТЬ
        |    ТоварыОтгруженные.Фирма КАК Фирма,
        |    ТоварыОтгруженные.ДокументПродажи,
        |    ТоварыОтгруженные.ДокументПродажи.Дата,
        |    ТоварыОтгруженные.Номенклатура КАК Номенклатура,
        |    ТоварыОтгруженные.СуммаОстаток КАК Сумма,
        |    ТоварыОтгруженные.Договор
        |ИЗ
        |    РегистрНакопления.ТоварыОтгруженные.Остатки(&МоментВремени, Контрагент = &Контрагент) КАК ТоварыОтгруженные
        |
        |УПОРЯДОЧИТЬ ПО
        |    Фирма,
        |    ТоварыОтгруженные.ДокументПродажи.Дата";
        
        Выборка = Запрос.Выполнить().Выбрать();

Автор: Vofka 21.02.20, 15:54

Цитата(Мичман Харитонов @ 21.02.20, 14:12) *
В автоматическом режиме в транзакциях используется уровень изоляции SERIALIZABLE (запрещает чтение и запись).

Repeatable read, если не ошибаюсь.

Автор: fly 21.02.20, 16:18

Vofka @ Сегодня, 15:54 * ,
https://pro1c.org.ua/redirect.php?https://its.1c.ru/db/metod8dev/content/1543/hdoc

"ок
я вроде так и написал
repeaable read и serializable


" транзакции начнут выполняться на уровне изоляции типа ReadCommitted, вместо SERIALIZABLE или Repeatable Read."

REPEATABLE READ
Этот уровень используется по умолчанию в MySQL. Добавленные данные уже будут доступны внутри транзакции, но не будут доступны до подтверждения извне.
Здесь может возникнуть теоретическая проблема «фантомного чтения». Когда внутри одной транзакции происходит чтение данных, другая транзакция в этот момент вставляет новые данные, а первая транзакция снова читает те-же самые данные.

fly @ Сегодня, 15:59 * ,
REPEATABLE-READ
каждая блокировка, полученная во время транзакции , удерживается на протяжении транзакции.
READ-COMMITTED
то locks, которые не соответствуют освобождены после заявления завершается.

это где то из описания...

что REPEATABLE-READ - все еще удерживает в транзации строки.
а в запросе - используется Контрагент.ПустаяСтрока() - что может пересекаться с запросом в Другой транзакции, я не очень силен в Транзакциях, но как мне кажется в том числе идет конфликт блокировок

fly @ Сегодня, 16:13 * ,
Table 13-1. Standard SQL Transaction Isolation Levels

Isolation Level - Dirty Read - Nonrepeatable Read - Phantom Read

Repeatable read - Not possible - Not possible - Possible
Serializable - Not possible - Not possible - Not possible

Автор: Vofka 21.02.20, 16:46

Цитата(fly @ 21.02.20, 16:18) *
repeaable read и serializable

Я видел, что именно так указано в документации, но это звучит странно, т.к. транзакция может выполняться в одном конкретном режиме. И в автоматическом режиме, если я не ошибаюсь, это именно repeatable read, а не serializable.

Автор: andr_andrey 21.02.20, 16:55

Мичман Харитонов @ Сегодня, 13:32 * ,
Из скрина ошибки видны две записи Объекта, что за объекты записываются в "ФормеСписка" и в модуле "ПолныеПрава", странные они?

Автор: fly 21.02.20, 16:57

Vofka @ Сегодня, 16:46 * ,
когда читал, литературу, по этому вопросу так и не нашел для себя ответа:
от чего зависит и какая именно выполняется блокировка Repeatable Read или Serializable....

Автоматический
MS SQL Server
Записей

если все же ставиться по умолчанию - repeatble read... а Serializable - как опция, если очень захотеть.... это одно, а если другие условия влияют.... оставил на потом по мере поступления проблемы.

Автор: Мичман Харитонов 21.02.20, 17:05

andr_andrey @ Сегодня, 16:55 * ,

Да уж... мягко говоря. Человека, который это писал, больше нет... меня взяли на его место, при чем передачи дел толком и не было. Вот, второй год с этим работаю. Потихоньку дописываю-переписываю, но почти вся база такая

Автор: andr_andrey 21.02.20, 17:39

Мичман Харитонов @ Сегодня, 17:05 * ,
Я не придираюсь, просто получается набор блокировок, понять бы какие действительно блокируют запись.

Украинский 1С форум: всё про 1С 8.3, 1С 8.2, 1С 8.1, 1С 8.0, 1С 7.7
https://pro1c.org.ua