Как исправить ошибку «could not find replacement targetlist entry for attno» при проведении больничных листов в 1С на СУБД PostgreSQL

Системный администратор 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При переносе информационных баз «1С:Предприятие» (в частности, конфигураций «1С:Зарплата и кадры государственного учреждения» или «1С:Зарплата и управление персоналом») с файлового варианта на клиент-серверный под управлением СУБД PostgreSQL администраторы часто сталкиваются со специфическими ошибками СУБД. Одной из наиболее труднодиагностируемых является ошибка вида: ERROR: could not find replacement targetlist entry for attno [номер].

В рамках данной статьи мы подробно разберем природу этой ошибки, выясним, почему она возникает именно при проведении таких документов, как Документ.БольничныйЛист, и рассмотрим пошаговые сценарии её устранения.

Почему возникает ошибка планировщика СУБД

Для начала проанализируем техническую суть сбоя. Сообщение could not find replacement targetlist entry for attno генерируется непосредственно ядром СУБД PostgreSQL. Словосочетание attno расшифровывается как attribute number — это внутренний порядковый номер колонки в таблице базы данных или в результирующей выборке запроса.

Данная ошибка свидетельствует о внутреннем баге в оптимизаторе и планировщике запросов (query planner) PostgreSQL. Когда платформа «1С:Предприятие» генерирует сложный, многократно вложенный SQL-запрос со множеством соединений (JOIN), подзапросов и временных таблиц, планировщик PostgreSQL пытается переписать и оптимизировать дерево этого запроса. В определенных версиях СУБД алгоритм оптимизации дает сбой: он теряет соответствие физического номера колонки во временной таблице и логического списка полей (target list) в оптимизированном запросе.

Рассмотрим пример типичной структуры сложного запроса, который формируется платформой при анализе перерасчетов прошлых периодов:


SELECT
    recalc._Fld1500_ID,
    actual_data._Fld1501_Value
FROM
    _Document150 recalc
LEFT JOIN (
    SELECT
        _Fld1502_Ref,
        SUM(_Fld1503_Sum) AS _Fld1501_Value
    FROM
        _Document150_VT1504
    GROUP BY
        _Fld1502_Ref
) actual_data ON recalc._IDRRef = actual_data._Fld1502_Ref;

Когда оптимизатор СУБД пытается упростить подобную конструкцию (особенно при наложении механизмов ограничения доступа на уровне записей — RLS), происходит сбой сопоставления индексов полей, и выполнение транзакции аварийно прекращается.

Взаимосвязь ошибки с проведением больничных листов прошлым периодом

Многие пользователи замечают, что при проведении больничного листа в текущем периоде (например, когда период болезни полностью укладывается в расчетный месяц) ошибка отсутствует. Однако, как только дата начала болезни переносится в прошлый (уже закрытый) месяц, система моментально выдает ошибку СУБД.

Выясним причину такого поведения системы. При проведении документа БольничныйЛист «задним числом» запускаются сложные механизмы платформы «1С»:

  1. Система обращается к механизму регистрации перерасчетов (таблицы РегистрацияПерерасчетов).
  2. Инициируется автоматическое сторнирование начислений за прошлый период (вытеснение видов расчета).
  3. Для корректного расчета среднего заработка создаются объемные временные таблицы, содержащие информацию о фактически отработанном времени и начислениях сотрудника за предыдущие 2 года.

Этот процесс порождает колоссальные по объему и вложенности SQL-запросы к СУБД PostgreSQL. Нестабильные версии планировщика СУБД не справляются с обработкой этих запросов, в результате чего пользователи видят ошибку транзакции, хотя в файловом варианте базы данных (где используется собственный упрощенный движок СУБД от «1С») все проводится без нареканий.

Варианты решения проблемы

Существует несколько способов исправления данной ситуации — от быстрых временных «костылей» до фундаментального обновления серверного ПО. Рассмотрим каждый из них подробнее.

Способ 1. Кардинальное решение — обновление СУБД PostgreSQL

Поскольку проблема носит характер внутреннего бага планировщика СУБД, наиболее правильным решением является обновление версии PostgreSQL до стабильной сборки, в которой разработчики (в частности, Postgres Pro совместно со специалистами «1С») исправили данную ошибку.

Проанализируем хронологию исправлений в ветке PostgreSQL 10.x, адаптированной для «1С»:

Рекомендация: Произведите обновление вашей СУБД PostgreSQL до актуальной поддерживаемой версии (например, версии 11, 12 или старше в специальной сборке для «1С»). Это не только решит проблему с проведением документов, но и повысит общую производительность СУБД.

Способ 2. Откат на стабильную младшую ветку СУБД

Если в вашей ИТ-инфраструктуре по каким-либо причинам невозможно оперативно обновиться на старшие версии СУБД PostgreSQL (например, из-за совместимости с другими системами или требованиями платформы 1С версии 8.3.15), можно прибегнуть к откату на стабильные предыдущие релизы.

Разберем по шагам этот нюанс:

  1. Переход на версию 10.5-9.1C решает данную ошибку, однако крайне не рекомендуется. В этой версии присутствуют другие критические уязвимости и проблемы с блокировками временных таблиц.
  2. Наиболее надежным и проверенным вариантом для отката является версия 10.5-24.1C. В ней исправлены сопутствующие баги стабильности, а планировщик запросов работает корректно.

Способ 3. Временный обход проблемы (аварийный режим)

Если вам необходимо срочно рассчитать и выплатить больничный лист сотруднику «прямо сейчас», а времени на проведение технических работ по обновлению СУБД нет, воспользуйтесь временным обходным путем:

  1. Сделайте резервную копию информационной базы (создайте файл выгрузки .dt).
  2. Разверните эту копию на локальном компьютере в файловом варианте.
  3. Запустите базу в файловом режиме, зайдите в нужный документ «Больничный лист» и проведите его. В файловом режиме проведение завершится успешно.
  4. Выгрузите базу обратно в формат .dt и загрузите на SQL-сервер.

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

Способ 4. Временное отключение ограничений RLS

Поскольку усложнение структуры SQL-запроса часто вызвано наложением прав доступа RLS (Row Level Security), проведение документа пользователем с ограниченными правами может вызывать сбой. Попробуйте выполнить проведение этого документа под учетной записью пользователя с полными административными правами, у которого механизмы RLS полностью отключены. Это снизит нагрузку на планировщик PostgreSQL и позволит провести документ без ошибок планирования.

Мы надеемся, что приведенные рекомендации помогут вам успешно справиться с ошибкой СУБД и обеспечить стабильную и бесперебойную работу расчетного отдела вашей организации.

← На главную