"Невозможно реорганизовать индекс": Как исправить ошибку после обновления платформы 1С до 8.3.22 и выше?

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

После обновления платформы 1С:Предприятие до версии 8.3.22.1603 и более новых релизов, многие системные администраторы, выполняющие настройку регламентных операций MS SQL Server под 1С, сталкиваются с неожиданной проблемой: автоматическое резервное копирование баз данных, а также задачи по реорганизации индексов, начинают завершаться с ошибкой.

Типичное сообщение об ошибке звучит так: "Невозможно реорганизовать индекс "_{ИмяИндекса}" в таблице "_{ИмяТаблицы}", поскольку отключена блокировка на уровне страницы." Это касается десятков тысяч индексов во всех базах. Чтобы лучше понять контекст происходящего, можно проанализировать SQL сервер глазами 1С-ника и оценить текущие настройки блокировок и нагрузки.

Причина возникновения проблемы: Изменения в логике блокировок 1С:Предприятия

Изначально, до обновления платформы 1С, параметр ALLOW_PAGE_LOCKS для индексов в базах данных MS SQL Server был установлен в значение ON. Однако, после обновления до версий 8.3.22 и выше, система 1С изменила свою логику. Если изучить внутреннюю структуру хранения базы данных, можно заметить, что для многих индексов этот параметр автоматически переключается в состояние OFF.

Для чего 1С это сделала?

Согласно официальной информации, система 1С:Предприятие, начиная с версии 8.3.22, устанавливает гранулярность блокировок на уровне строк (ROW_LOCKS), если используется Microsoft SQL Server версии 2008 и последующие версии. Основная цель такого изменения — исключить возможность эскалации блокировок. Эскалация блокировок происходит, когда множество мелких блокировок преобразуются в более крупные (на уровне всей таблицы), что может значительно снизить производительность и увеличить количество взаимоблокировок — для диагностики этих проблем есть инструмент мониторинга блокировок и производительности 1С.

Поддерживая блокировки на уровне строки, 1С стремится повысить конкурентность работы пользователей. Однако это имеет и обратную сторону: возможно увеличение потребления оперативной памяти MS SQL Server.

Последствия отключения ALLOW_PAGE_LOCKS

Когда параметр ALLOW_PAGE_LOCKS установлен в OFF, это напрямую влияет на операции обслуживания индексов:

  1. Невозможность реорганизации индекса: Операция ALTER INDEX ... REORGANIZE требует наличия страничных блокировок. Если они отключены, операция завершится с ошибкой.
  2. Перестроение индекса работает: В отличие от реорганизации, операция ALTER INDEX ... REBUILD может выполняться независимо от состояния этого параметра.

Решения проблемы

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

Решение 1: Официальный подход 1С – временное включение и отключение блокировок страниц

Наиболее безопасный способ заключается в следующем алгоритме:

  1. До реорганизации: необходимо включить страничные блокировки.
  2. Выполнить реорганизацию: запустить стандартные задачи обслуживания.
  3. Обратно выключить страничные блокировки: вернуть параметр ALLOW_PAGE_LOCKS в состояние OFF.

Подробная инструкция по настройке регламентных операций поможет правильно интегрировать эти шаги в планы обслуживания SQL Server — для подготовки базы к обслуживанию пригодится утилита принудительного завершения сеансов пользователей 1С.

Реализация с использованием SQL-скриптов в плане обслуживания

Шаг 1: Включение блокировок страниц перед реорганизацией


USE [ИмяБазы];
GO
EXEC sp_MSforeachtable 'ALTER INDEX ALL ON ? SET (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON)';
GO

Шаг 2: Выполнение реорганизации индексов

Запустите стандартную задачу "Reorganize Index Task". Теперь она пройдет без ошибок.

Шаг 3: Отключение блокировок страниц после реорганизации


USE [ИмяБазы];
GO
EXEC sp_MSforeachtable 'ALTER INDEX ALL ON ? SET (ALLOW_PAGE_LOCKS = OFF, ALLOW_ROW_LOCKS = ON)';
GO

Решение 2: Использование адаптированных скриптов обслуживания индексов

Многие администраторы предпочитают использовать профессиональные решения. Например, существует MaintenanceSolution от Ola Hallengren с доработанной IndexOptimize под 8.3.22, которая автоматически корректирует ALLOW_PAGE_LOCKS в процессе работы, избавляя вас от необходимости писать скрипты вручную.

Для понимания логики кастомного скрипта, приведем пример структуры, которая проверяет состояние блокировок перед выполнением операции:


-- [Фрагмент скрипта для анализа и выбора между REBUILD и REORGANIZE]
-- Если фрагментация > 30%, выполняем REBUILD (ему не важен ALLOW_PAGE_LOCKS)
-- Если фрагментация 5-30% и ALLOW_PAGE_LOCKS = OFF, также делаем REBUILD или пропускаем
IF @fragmentation_in_percent > 30.0
    SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @objectname + N' REBUILD WITH (ALLOW_PAGE_LOCKS = OFF, ALLOW_ROW_LOCKS = ON)';

Решение 3: Перестроение индексов вместо реорганизации

Если ваша инфраструктура позволяет, можно полностью отказаться от реорганизации в пользу перестроения (REBUILD). Это снимет проблему с блокировками страниц, но потребует больше ресурсов. В этом случае значительно ускорить процесс поможет переиндексация в несколько потоков, что особенно актуально для высоконагруженных систем.

Заключение

Проблема "Невозможно реорганизовать индекс" — это следствие оптимизации платформы 1С для работы с блокировками. Для ее решения вы можете либо использовать готовое доработанное решение на базе скриптов Ola Hallengren, либо адаптировать свои регламентные задания, временно переключая параметры индексов.

Правильный выбор стратегии обслуживания позволит сохранить высокую производительность базы данных и избежать ошибок при выполнении регламентных процедур.

← На главную