При переносе информационных баз «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С»:
РегистрацияПерерасчетов).Этот процесс порождает колоссальные по объему и вложенности SQL-запросы к СУБД PostgreSQL. Нестабильные версии планировщика СУБД не справляются с обработкой этих запросов, в результате чего пользователи видят ошибку транзакции, хотя в файловом варианте базы данных (где используется собственный упрощенный движок СУБД от «1С») все проводится без нареканий.
Существует несколько способов исправления данной ситуации — от быстрых временных «костылей» до фундаментального обновления серверного ПО. Рассмотрим каждый из них подробнее.
Поскольку проблема носит характер внутреннего бага планировщика СУБД, наиболее правильным решением является обновление версии PostgreSQL до стабильной сборки, в которой разработчики (в частности, Postgres Pro совместно со специалистами «1С») исправили данную ошибку.
Проанализируем хронологию исправлений в ветке PostgreSQL 10.x, адаптированной для «1С»:
Рекомендация: Произведите обновление вашей СУБД PostgreSQL до актуальной поддерживаемой версии (например, версии 11, 12 или старше в специальной сборке для «1С»). Это не только решит проблему с проведением документов, но и повысит общую производительность СУБД.
Если в вашей ИТ-инфраструктуре по каким-либо причинам невозможно оперативно обновиться на старшие версии СУБД PostgreSQL (например, из-за совместимости с другими системами или требованиями платформы 1С версии 8.3.15), можно прибегнуть к откату на стабильные предыдущие релизы.
Разберем по шагам этот нюанс:
Если вам необходимо срочно рассчитать и выплатить больничный лист сотруднику «прямо сейчас», а времени на проведение технических работ по обновлению СУБД нет, воспользуйтесь временным обходным путем:
.dt)..dt и загрузите на SQL-сервер.Важное предупреждение: Данный метод является исключительно экстренным средством. При создании следующего аналогичного документа перерасчета ошибка повторится, поэтому планировать обновление СУБД все равно необходимо в кратчайшие сроки.
Поскольку усложнение структуры SQL-запроса часто вызвано наложением прав доступа RLS (Row Level Security), проведение документа пользователем с ограниченными правами может вызывать сбой. Попробуйте выполнить проведение этого документа под учетной записью пользователя с полными административными правами, у которого механизмы RLS полностью отключены. Это снизит нагрузку на планировщик PostgreSQL и позволит провести документ без ошибок планирования.
Мы надеемся, что приведенные рекомендации помогут вам успешно справиться с ошибкой СУБД и обеспечить стабильную и бесперебойную работу расчетного отдела вашей организации.