При разработке систем управления задачами или корпоративных порталов на базе 1С часто возникает потребность в мониторинге изменений в реальном времени. Типичная ситуация: сотрудники должны получать уведомления о новых задачах практически мгновенно, что провоцирует разработчиков на создание механизмов опроса (polling) базы данных с интервалом в несколько секунд. В условиях большого количества пользователей и высокой интенсивности записи это неизбежно приводит к конфликтам блокировок. Разберем по шагам, как спроектировать архитектуру такого регистра, чтобы система оставалась отзывчивой.
Проанализируем сначала базовый объект метаданных. Для хранения состояний задач и оперативных отметок оптимальным выбором является Регистр сведений. Однако не любой регистр подойдет для высокой нагрузки. Рассмотрим ключевые настройки:
Сотрудник, Состояние и Задача. Важно помнить, что порядок измерений в конфигураторе напрямую влияет на порядок полей в кластерном индексе SQL. Первым должно идти то измерение, по которому чаще всего происходит фильтрация в запросах (в нашем случае — Сотрудник).Рассмотрим рекомендации по установке признака Ведущее. Хотя в некоторых случаях это удобно для автоматического удаления записей, в высоконагруженных системах признак Ведущее может стать причиной лишних транзакционных проверок. Если вы планируете управлять данными программно, лучше отказаться от этого признака в пользу ручного контроля целостности.
Одной из самых критичных ошибок, упомянутых в обсуждении, является фиксация прочтения задачи (запись в регистр) непосредственно в момент открытия формы. Выясним причину, почему это плохо: любая запись (INSERT или UPDATE) накладывает эксклюзивную блокировку (X-lock) на уровне СУБД. Если в этот же момент другой процесс (например, фоновое задание по распределению задач) пытается обновить этот же набор данных, возникает ожидание или Deadlock.
Посмотрим, как можно решить эту задачу иначе:
Для платформы 1С:Предприятие 8.3 крайне важно использование режима READ_COMMITTED_SNAPSHOT на стороне MS SQL Server. Это механизм версионности строк, который позволяет читающим транзакциям не блокироваться пишущими. Рассмотрим, как это работает: когда один процесс пишет данные в регистр, 1С (при включенном RCSI) позволяет остальным пользователям читать "последнюю зафиксированную" версию данных из tempdb, не выстраивая очередь ожиданий.
Важный нюанс: использование RCSI не отменяет необходимости грамотного проектирования управляемых блокировок в самой 1С. Мы должны четко ограничивать пространство блокировок с помощью объекта БлокировкаДанных, чтобы запись по одному сотруднику не мешала записи по другому.
// Пример установки управляемой блокировки перед записью в регистр
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрСведений.СостояниеЗадач");
ЭлементБлокировки.УстановитьЗначение("Сотрудник", ТекущийСотрудник);
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
Блокировка.Заблокировать();
Проверка новых задач каждые 5 секунд через прямой запрос к базе данных — это ресурсоемкая операция. Проанализируем альтернативные пути решения:
1. Система взаимодействия (Collaboration System). Это наиболее современный и правильный подход. Вместо того чтобы клиент "спрашивал" сервер, сервер сам "толкает" уведомление клиенту через WebSocket-соединение. Это полностью исключает нагрузку на SQL-сервер, связанную с постоянными холостыми запросами.
2. Использование буферных таблиц (Buffer Tables). Если запись в основной регистр происходит очень часто, можно применить стратегию "очереди". Данные сначала пишутся в максимально легкую таблицу (минимум индексов, никакой логики), а раз в минуту регламентное задание переносит накопленные данные в основной высоконагруженный регистр. Это позволяет распределить нагрузку на дисковую подсистему.
3. Секционирование данных на уровне логики.
Если количество записей в регистре исчисляется миллионами, а сотрудников тысячи, можно добавить измерение-разделитель (например, НомерГруппы). Это позволит СУБД более эффективно распределять данные по страницам памяти и уменьшит вероятность Page Locks (блокировок страниц данных).
Посмотрим на ситуацию со стороны системного администратора. Для регистра, в который пишут каждые несколько секунд, полезно настроить Fill Factor (коэффициент заполнения индексов). По умолчанию он равен 0 (или 100%), что означает максимально плотную упаковку данных. При частых вставках это вызывает "расщепление страниц" (Page Splits). Установив Fill Factor на уровне 80%, мы оставим свободное место в страницах данных для новых записей, что значительно ускорит операции INSERT.
Также рекомендуется включить параметр Optimize for Ad Hoc Workloads на уровне SQL Server. Поскольку запросы к регистру могут приходить с разными параметрами от сотен пользователей, это поможет не засорять кэш планов неэффективными одноразовыми планами выполнения.
Подводя итог, для создания стабильного высоконагруженного регистра задач мы должны: