Настройка ограничений на уровне записей (RLS — Record Level Security) является одной из самых сложных и ответственных задач для разработчика 1С. Ошибка в условии не только может привести к несанкционированному доступу или, наоборот, к чрезмерным ограничениям, но и способна катастрофически замедлить работу всей системы. В данной статье мы разберем практический пример настройки условий доступа, проанализируем типичные ошибки при работе с пустыми значениями и рассмотрим современные механизмы оптимизации производительности RLS.
Разберем одну из самых частых ошибок, с которой сталкиваются начинающие разработчики. В первом сообщении темы автор пытается комбинировать проверку на NULL и пустую ссылку. Важно четко понимать разницу:
ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)) — это физическое значение типа «Ссылка», которое реально хранится в полях базы данных.NULL чаще всего появляется при использовании левых соединений (LEFT JOIN). Если в условии ограничения вы обращаетесь к реквизиту через точку (например, Контрагент.Менеджер.Отдел), и менеджер не указан, система может вернуть NULL.Рассмотрим ситуацию с параметрами сеанса. Если параметр сеанса &ПМЗонаДоступа не инициализирован, обращение к нему в коде RLS вызовет ошибку исполнения, а не вернет NULL. Поэтому проверка &ПМЗонаДоступа ЕСТЬ NULL часто является избыточной или ошибочной, если параметр гарантированно инициализируется в модуле сеанса.
Проанализируем предложенный в обсуждении вариант условия, который призван объединить доступ по зонам и обработку исключений. Рассмотрим, как можно переписать «дикое» условие в более читаемый вид с использованием конструкции ВЫБОР КОГДА:
ГДЕ ВЫБОР
КОГДА Контрагент.ПМЗонаДоступа = &ПМЗонаДоступа
И Контрагент.ПМЗонаЗапрета <> &ПМЗонаЗапрета
И &ПМЗонаДоступа <> ЗНАЧЕНИЕ(Справочник.ПМЗоныДоступа.ПустаяСсылка)
ТОГДА ИСТИНА
КОГДА &ПМЗонаДоступа = ЗНАЧЕНИЕ(Справочник.ПМЗоныДоступа.ПустаяСсылка)
И Контрагент.ПМЗонаЗапрета <> &ПМЗонаЗапрета
ТОГДА ИСТИНА
ИНАЧЕ ЛОЖЬ
КОНЕЦ
Хотя такая запись выглядит логичной, использование ВЫБОР КОГДА непосредственно в теле RLS-запроса создает огромную нагрузку на оптимизатор SQL-сервера. Вычисление этого выражения происходит для каждой строки таблицы, что при больших объемах данных (например, в справочнике Контрагенты или в журналах документов) приведет к значительным задержкам.
В первом сообщении автор использует оператор ИЛИ. Выясним причину, почему это считается плохой практикой в RLS. Когда SQL-сервер встречает OR в условии WHERE, он часто отказывается от использования индексов и переходит к полному сканированию таблицы (Table Scan). Это и есть причина того, что «о производительности можно забыть».
Рекомендация: Вместо одного сложного условия с ИЛИ, старайтесь разделять логику на несколько простых ролей. В 1С права суммируются: если пользователю разрешено чтение хотя бы по одной из ролей, он получит доступ к записи. Несколько простых запросов в разных ролях обычно работают быстрее, чем один громоздкий запрос со сложной логикой ИЛИ.
Начиная с версии платформы 1С:Предприятие 8.3.12, разработчикам доступен механизм «Производительного RLS». Разберем, как он меняет ситуацию. В классическом RLS платформа каждый раз при выполнении запроса динамически добавляет к нему условия ГДЕ. В производительном режиме система заранее рассчитывает ключи доступа и записывает их в специальные вспомогательные таблицы.
Преимущества производительного режима:
ВЫБОР КОГДА) больше не влияет на скорость выборки данных пользователем, так как расчет прав происходит в фоновом режиме при изменении данных.Вместо того чтобы вручную прописывать сложные условия, проанализируем возможности шаблонов. В типовых конфигурациях на базе БСП (Библиотека стандартных подсистем) используются стандартные шаблоны, такие как #ПоЗначениям. Использование шаблонов позволяет:
Если вы столкнулись с тем, что динамический список начал «тормозить» после внедрения RLS, необходимо выяснить причину с помощью инструментов анализа. Выясним, во что превращается ваше условие на уровне СУБД:
Воспользуйтесь Профайлером SQL-сервера или настройте Технологический журнал (событие DBMSSQL). Вы увидите реальный текст SQL-запроса. Ищите в нем фрагменты, добавленные платформой — они будут содержать ваши условия. Обратите внимание на то, используются ли индексы (Index Seek) или происходит сканирование (Scan). Если вы видите Full Table Scan, значит, ваше условие ГДЕ (особенно с ИЛИ или ВЫБОР) не дает СУБД работать эффективно.
Посмотрим на ситуацию, когда RLS мешает выполнению служебных операций. Например, при проведении документа пользователю может понадобиться информация об остатках, к которым у него нет прямого доступа. В таких случаях следует использовать УстановитьПривилегированныйРежим(Истина). Это временно отключает проверку RLS для текущего потока выполнения на сервере, что не только позволяет обойти ограничения, но и значительно ускоряет работу кода, так как условия RLS не добавляются к запросам.
Подведем итог: При проектировании RLS для «чайников с гранатой» (как иронично заметил автор темы) важно помнить, что простота — залог скорости. Избегайте NULL там, где можно обойтись пустой ссылкой, минимизируйте использование ИЛИ и ВЫБОР, а при возможности — переходите на производительный режим RLS версии 8.3.12 и выше.