При работе с базами данных 1С:Предприятие в клиент-серверном режиме можно столкнуться с ситуацией, когда попытка пометить на удаление или выгрузить элемент справочника (например, ХранилищеДополнительнойИнформации) приводит к зависанию сеанса и последующему падению процесса с ошибкой «Соединение не удерживается сервером».
В этой статье мы подробно проанализируем причины возникновения этой проблемы и разберем по шагам, как восстановить работоспособность базы данных.
Сбой происходит при попытке вызова метода ПолучитьОбъект() или использовании явного удаления через объект УдалениеОбъекта:
// Примеp кода, вызывающего сбой при битых данных:
Удаление = Новый УдалениеОбъекта(Ссылка);
Удаление.Записать();
Выясним, почему это происходит:
ХранилищеЗначения. В СУБД (например, MS SQL Server) эти данные размещаются в специальных бинарных структурах (LOB-страницах). При физических сбоях дисковой подсистемы, аварийном перезапуске сервера или сбоях питания структура этих страниц может повредиться.ПолучитьОбъект(): В отличие от чтения отдельных реквизитов через запрос или получения ссылки, метод ПолучитьОбъект() полностью считывает из базы всю строку таблицы со всеми хранилищами значений. При попытке прочитать битый бинарный блок драйвер СУБД или рабочий процесс 1С (rphost) сталкивается с необрабатываемым исключением.Попытка ... Исключение не помогает — рабочий процесс rphost аварийно завершается, и клиентский сеанс теряет связь с сервером.Если проблема вызвана битыми бинарными страницами в MS SQL Server, наиболее эффективным решением является проверка и восстановление целостности конкретной таблицы СУБД.
Разберем порядок действий:
ПолучитьСтруктуруХраненияБазыДанных() или обработку «Структура хранения базы данных».CHECKTABLE:
DBCC CHECKTABLE ('_Reference123'); -- Укажите реальное имя таблицы из структуры хранения
DBCC CHECKDB с параметрами исправления (потребуется перевод базы в монопольный режим):
ALTER DATABASE [Имя_Базы] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
DBCC CHECKDB ('Имя_Базы', REPAIR_ALLOW_DATA_LOSS);
ALTER DATABASE [Имя_Базы] SET MULTI_USER;
После успешного исправления структуры LOB-страниц на стороне СУБД обращение к объекту ПолучитьОбъект() перестанет вызывать падение рабочего процесса.
Если нет возможности работать напрямую с СУБД, рассмотрим вариант выполнения штатных процедур платформы 1С:
Если битая картинка не представляет ценности, но сам элемент справочника удалять нельзя, можно обнулить поле с хранилищем значений прямо в СУБД:
_IDRRef).
UPDATE _Reference123
SET _Fld456 = 0x
WHERE _IDRRef = 0x80C100155D010B0111E2A3C4D5E6F700;
ПолучитьОбъект() снова начнет корректно считывать объект.Важно: Любые операции с принудительным выполнением SQL-запросов и исправлением структуры таблиц должны производиться только при наличии свежей резервной копии и при полном отсутствии активных пользователей в базе.