Обслуживание баз данных объемом более 500 Гб, работающих в режиме 24/7 с сотнями активных пользователей, представляет собой сложную задачу. Стандартные средства MS SQL Server часто не справляются, вызывая взаимоблокировки (deadlocks) и прерывая работу пользователей или само регламентное задание. Проанализируем, почему это происходит и как настроить стабильную реиндексацию.
Ошибки вида Транзакция стала жертвой взаимоблокировки при выполнении DBCC DBREINDEX или ALTER INDEX ... REBUILD возникают из-за того, что процесс перестроения индекса требует монопольной блокировки таблицы. Если в этот момент пользователь пытается записать данные в ту же таблицу, SQL Server сталкивается с конфликтом интересов. В высоконагруженных системах 1С такие конфликты неизбежны.
Рассмотрим основные причины проблем в вашем сценарии:
DBCC DBREINDEX официально признана устаревшей (deprecated) и работает исключительно в режиме OFFLINE, блокируя доступ к данным.REBUILD всегда блокирует таблицу.Первым делом нам необходимо отказаться от использования DBCC DBREINDEX. Вместо этого мы будем использовать ALTER INDEX. Разберем разницу между двумя методами обслуживания:
ONLINE=ON).Вместо того чтобы перестраивать все индексы подряд, мы воспользуемся скриптом, который сначала проанализирует уровень фрагментации и выберет подходящее действие. Проанализируем следующий пример кода, который доказал свою эффективность на практике:
USE [Имя_Вашей_Базы]
GO
DECLARE @minRows INT = 10000; -- Не трогаем маленькие таблицы
DECLARE @reindexQuery NVARCHAR(MAX);
SET @reindexQuery = REPLACE(REPLACE(CAST((
SELECT
'BEGIN TRY ' +
CASE
WHEN st.avg_fragmentation_in_percent > 30
THEN 'ALTER INDEX [' + idx.name + '] ON [' + sc.name + '].[' + t.name + '] REBUILD WITH (ONLINE = OFF);'
ELSE 'ALTER INDEX [' + idx.name + '] ON [' + sc.name + '].[' + t.name + '] REORGANIZE;'
END +
' END TRY BEGIN CATCH PRINT ''Ошибка при обработке индекса ' + idx.name + '''; END CATCH; ' AS [query]
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, NULL) st
JOIN sys.tables t ON st.object_id = t.object_id
JOIN sys.schemas sc ON sc.schema_id = t.schema_id
JOIN sys.indexes idx ON t.object_id = idx.object_id AND st.index_id = idx.index_id
JOIN sys.partitions p ON p.index_id = idx.index_id AND p.object_id = idx.object_id
WHERE p.rows > @minRows
AND st.avg_fragmentation_in_percent > 10 -- Порог фрагментации
AND idx.name IS NOT NULL
ORDER BY st.avg_fragmentation_in_percent DESC
FOR XML PATH(''), TYPE
) AS NVARCHAR(MAX)), '</query>', ''), '<query>', '');
-- Выполняем сформированный запрос
EXEC sp_executesql @reindexQuery;
Важное примечание: Обратите внимание на блок BEGIN TRY ... END CATCH. Он позволяет скрипту не "падать" целиком, если какой-то индекс заблокирован пользователем, а просто пропускать его и двигаться дальше.
Чтобы процесс обслуживания не мешал пользователям, мы можем применить несколько системных настроек в начале нашего скрипта:
SET DEADLOCK_PRIORITY LOW сообщает SQL Server, что если возникнет конфликт между скриптом обслуживания и пользователем, то "жертвой" должен стать скрипт. Это гарантирует, что работа в 1С не прервется.MAXDOP = 1 или 2 в параметры перестроения индекса позволит серверу оставить мощность для обработки пользовательских запросов.SET LOCK_TIMEOUT 5000, чтобы скрипт ждал освобождения таблицы не более 5 секунд, прежде чем перейти к следующей задаче.Часто производительность 1С падает не из-за фрагментации индексов, а из-за неактуальной статистики. Помните, что команда REORGANIZE не обновляет статистику, в то время как REBUILD делает это автоматически.
Если ваша стратегия обслуживания опирается на реорганизацию (чтобы избежать блокировок), вам необходимо добавить в регламентное задание отдельный шаг по обновлению статистики. Разберем команду:
UPDATE STATISTICS [Имя_Таблицы] WITH FULLSCAN;
Для систем 1С рекомендуется использовать FULLSCAN, так как выборочное сканирование часто дает неточные планы запросов на сложных таблицах регистров.
При объеме базы в 500 Гб любая операция по перестроению индексов порождает колоссальное количество записей в логе транзакций. Проанализируем два момента:
FULL, убедитесь, что бэкап лога транзакций выполняется достаточно часто во время реиндексации (например, раз в 15 минут), чтобы диск не переполнился.BULK_LOGGED на время проведения масштабных работ по обслуживанию, однако это требует осторожности и понимания стратегии восстановления.Для профессионального обслуживания баз данных 1С рекомендуем рассмотреть решение SQL Server Maintenance Solution от Олы Халленгрена. Это признанный мировой стандарт, который включает в себя:
Подведем итог: для стабильной работы 1С в режиме 24/7 на базе 500 Гб необходимо уйти от стандартных планов обслуживания в пользу гибких T-SQL скриптов с обработкой исключений, отдавать приоритет REORGANIZE для снижения блокировок и не забывать про качественное обновление статистики UPDATE STATISTICS.