Для воспроизведения я подготовил тестовую демобазу 1С:Бухгалтерии со встроенным Тест-центром и тестовый сценарий, который портит итоги.
Перед запуском сценария мы проверяем, что итоги в базе правильные:
-
на конец 2016 года у нас остаток по регистру бухгалтерии в базе – 46 085,34
-
на начало 2017 года – тот же остаток, 46 085,34.
Запускаем тест, который портит итоги.
Пока тест выполняется, я расскажу, что он делает.
Суть теста в том, что во время перестановки границы итогов одновременно в цикле постоянно меняется сумма проводки.
Первая роль в цикле изменяет сумму проводки, меняя остаток.
-
Сначала сумма проводки уменьшается на 1000 рублей.
-
Потом в цикле 100 раз увеличивается на 10 рублей.
-
И в конце теста сумма проводки становится первоначальной – соответственно, остаток тоже должен быть первоначальным.
А вторая роль переставляет границу итогов.
-
Вначале она удаляет итоги на начало 2017 года.
-
Потом переставляет границу итогов таким образом, чтобы оборот тестовой проводки влиял на остаток.
При перестановке итогов вторая роль:
-
Считывает остаток на начало декабря;
-
Определяет оборот за декабрь,
-
Производит вычисления (к остатку на начало декабря прибавляет обороты за декабрь) и записывает новый остаток на начало 2017 года.
Тест у нас выполнился.
-
Мы видим, что на конец 2016-го года у нас была сумма 46 085 рублей 34 копейки.
-
И вдруг на начало 2017 года у нас сумма получилась на 10 рублей меньше – 46 075 рублей 34 копейки.
Будем разбираться, что произошло.
Мы выполнили перестановку границы итогов одновременно с изменением суммы проводки. Рассмотрим момент пересечения.
-
При очередной итерации сумма проводки увеличивается на 10 рублей, соответственно оборот увеличивается на 10 рублей, и в текущие итоги записывается итог больше на 10 рублей.
-
В параллельном сеансе перестановка границы итогов считывает оборот. После того как перестановка границы итогов считала оборот, успевает пролететь еще одна проводка с изменением суммы, которая увеличивает сумму проводки на 10 рублей, оборот на 10 рублей и текущий итог увеличивает на 10 рублей.
-
Когда перестановка границы итогов заканчивает свою операцию, она создает запись итогов на начало 2017 года, которая не учла приращение одной из транзакций. В результате остаток на 2017 год получается неактуальный – меньше на 10 рублей.
-
Дальнейшее увеличение суммы проводки оборот изменяет правильно, но остаток изменяется на приращение, на разницу. Поэтому расхождение никуда не девается – оно сохраняется. И в конце мы видим эти 10 рублей разницы между итогами на начало 2017 года и текущими итогами.
Чтобы такого не происходило, в операции должна быть блокировка, не позволяющая менять движения при перестановке границы итогов. Давайте посмотрим в технологический журнал, что там сейчас есть.
На слайде – две строчки из технологического журнала.
-
Первая строчка – это единственная управляемая блокировка, которая накладывается при перестановке границы итогов. Она накладывается по пространству итогов.
-
Вторая строка – блокировка по тому же пространству итогов, но при изменении суммы проводки.
Обе блокировки исключительные, разделители учета одинаковы, и период пересекается. Раз есть пересечение, параллельной работы не должно быть.
-
Период перестановки границы итогов – от пустой даты до начала 2017 года.
-
А при изменении проводки – блокировка по периоду от 1 декабря 2016 года и до бесконечности.
То есть по технологическому журналу все в норме, но на практике мы наблюдаем, что в таблице итогов возможна параллельная запись.
Мы сделали вывод о недостаточной блокировке, поэтому делаем второй тест, в котором:
-
заворачиваем нашу перестановку границы итогов в программную транзакцию;
-
и с запасом устанавливаем исключительную блокировку по всему пространству итогов.
Это должно помочь, потому что:
-
Во-первых, блокировки одного сеанса не конфликтуют друг с другом.
-
Во-вторых, блокировки снимаются только в конце транзакции – блокировка должна сохраниться и помочь.
Смотрим результаты теста – не помогло, каким-то чудесным образом блокировка снялась до окончания транзакции. Как такое возможно в платформе – непонятно.
У нас есть третий, точно исправленный сценарий, который использует другое пространство блокировок для регистра.
-
У нас есть еще одно пространство блокировок для регистров бухгалтерии и накопления – это пространство движений или регистраторов. Мы заменили пространство итогов на пространство наборов записей. Если мы не указываем регистратор, это значит, что блокируется движение всех регистраторов.
-
Так же заворачиваем блокировку в программную транзакцию и смотрим, что у нас получилось.
Теперь на начало 2017 года сумма у нас правильная – 46 085 рублей 34 копейки.
Выводы:
-
Борьба с последствиями ошибки при перестановке границы бухгалтерских итогов может отнять много ресурсов у пользователей и команд разработки.
-
Аналогичная ошибка зарегистрирована в фирме «1С» для регистра накопления https://bugboard.v8.1c.ru/error/000060448. Она уже исправлена в платформе, начиная с 8.3.17.1496. Здесь я приложил ссылку на GitHub, где можно скачать пример для воспроизведения ошибки для регистра накопления. Туда же я выгрузил сценарии из Тест-центра.
-
Есть обходное программное решение в виде дополнительной управляемой блокировки. Оно работает как для регистров накопления, так и для регистров бухгалтерии.
Вопросы и ответы
По регистру включено разделение итогов?
Да.
А не думали, что результат неправильных остатков как раз в нем?
Нет. Разделение итогов работает корректно, потому что управляемая блокировка накладывается в разрезе разделителей. Причина ошибки не в этом.
Вы можете скачать примеры и воспроизвести, это не проблема. Лучше проверяйте.
В какой версии платформы это исправлено?
Ошибка для регистра накопления исправлена в релизе 8.3.17.1496. Для регистра бухгалтерии ошибка еще не исправлена. Этот пример и показывает, что в платформе 8.3.20.1710 ошибка сохранилась.
Лучше проверить проблему на своей базе, в своем режиме совместимости. Потому что помимо версии платформы, очень важен еще и режим совместимости конфигурации. Если у вас на УПП стоит режим совместимости 8.2.11, вам обновление на 8.3.20 вряд ли поможет. Это сочетание очень важно, потому что от уровня совместимости конфигурации зависит, будет ли исполняться новый код платформы или нет.
Как вы это выявляли, диагностировали?
Была очень большая проблема с тем, что итоги постоянно расходятся – надо было постоянно искать расхождения, пересчитывать их.
Я автоматизировал сверку итогов и автоматизировал перерасчет.
Потом переставлял границу итогов на месяц вперед – у меня не за месяц данные обрабатывались, а в небольшом промежутке за текущий месяц.
В результате расхождение получилось именно на сумму конкретного документа.
Дальше уже было дело техники это воспроизвести и найти решение.
*************
Статья написана по итогам доклада (видео), прочитанного на конференции Infostart Event 2022 Saint Petersburg.