RLS — дубли условий в запросах к СУБД













«Подводные камни», возникающие при бездумном копировании ролей с ограничениями RLS, как это отражается на производительности, разбор примера и инструмент для анализа.

 

Для тех, кто не в курсе

RLS или Record Level Security или Доступ на уровне записи, механизм призванный сделать оптимальным процесс ограничения доступа к данным в зависимости от их наполнения, например, в документе один из реквизитов — филиал, при настройке ограничений RLS, можно ограничить просмотр документов с определенным составом филиалов для каждого пользователя индивидуально.

Как-то недавно на базе 1С:ЗУП, немного доработанной, я столкнулся с ошибкой, когда MSSQL Server отказался формировать запрос ввиду его большого размера. Анализ показал, что 1С действительно формирует огромный запрос, более 1000 строк (сейчас точнее уже не помню) и весомую часть запроса составляли добавленные ограничения RLS. Базу дорабатывало крупное франчайзи и специалисты у них неплохие, однако и они "наступили на грабли".

 

Тестовый пример

Для теста написана простая конфигурация, справочники:

  • "Филиалы"
  • "Пользователи" (Табличная часть "ФилиалыРазрешенные", в ней реквизит "Филиал" для установки пользователю разрешенных филиалов)

документ:

  • "Передача денег", реквизиты "Филиал", "Сумма"

роли:

  • "Полные права" — без ограничений RLS 
  • "Бухгалтер", "ИЗМ_Бухгалтер", "ИЗМ_БухгалтерПоФилиалам" имеют идентичное по смыслу ограничение RLS по филиалам на чтение документа "Передача денег", в каждой RLS-роли добавлено незначительное изменение (Условие 1 = 1, 2 = 2 и т.д.).

Пользователь с ограниченными правами, будет видеть только документы разрешенных ему филиалов. В качестве теста будем использовать форму списка вышеуказанного документа, будем ее обновлять по F5 и смотреть трассировку запросов в SQL Profiler. 

 

 Скрины тестовой конфигурации

 

SQL — запрос здорового человека админа — роль ПолныеПрава, органичений RLS нет

На скрине видно, что никаких ограничений про филиалам нет

 

SQL — запрос курильщика пользователя с одной ролью RLS, ограничение по списку филиалов для пользователя

В данном случае пользователю назначена одна роль "Бухгалтер", видим отсечение записей через EXISTS:

 

SQL — запрос заядлого курильщика пользователя с тремя дублирующими ролями RLS, ограничение как в предыдущей теме

Пользователю добавлены роли "ИЗМ_Бухгалтер", "ИЗМ_БухгалтерПоФилиалам", итого 3 роли с RLS, обратите внимание, что EXISTS-ы соединяются через OR, как и задумано платформой. Для реализации этого примера, ограничения RLS в ролях были дополнены пустыми условиями 1 = 1, 2 = 2 и т.д. , это для теста, а в жизни могут отредактировать существующее условие или дописать новое.

 

Ложка дегтя

Как такое получается в жизни? Очень просто, для пользователя надо модифицировать права, скопировали роль, подправили RLS, в результате, никто не отменил ранее установленные роли у пользователя, а платформа формируя запрос, собрала почти идентичные условия со всех трех ролей с RLS.

Ситуация усугубляется тем, что условия разных RLS соединяется через OR, часто сервер СУБД отказывается искать оптимальный план для запроса и назначает наиболее тривиальный, который содержит FULL-сканы по таблицам или индексам и конечно, это может значительно снижать производительность.

 

Ложка меда

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

Ниже пример, когда у пользователя 3 роли с RLS с полностью совпадающим ограничением Read, как видим дублей ограничения нет, но мы понимаем, что роли чаще копируют, чтобы потом их модифицировать и говорил ранее, старую роль не снимают, а новую добавляют.

 

Как найти "задвоенный" RLS в конфигурации

Проблема становиться актуальной, когда:

  • роли, имеющие одинаковые по смыслу ограничения RLS назначены одному пользователю;
  • таблицы имеющие ограничения RLS содержат большое количество записей;
  • к ним часто обращаются.

В платформе 8.3, есть функция:

ПараметрыДоступа(НаименованиеПрава, ОбъектМетаданных, СписокПолей, Роль/пользователь)

она возвращает информацию о наличии права у роли (в нашем случае), а также о наличии ограничений RLS. Подробнее в документации.

Алгоритм анализа:

  1. Выбираем пользователя.
  2. Выбираем все роли установленные у пользователя.
  3. Для каждой роли проверяем права (Read, Insert, Update, Delete) для всех объектов, на которые можно наложить ограничения RLS через роли. Обратите внимание, для регистров и др.объектов используются не виды прав, если не знаете какие, проверяйте через конфигуратор.

На нашей тестовой БД получилась такая таблица:

Все три роли выделены "красным" и имеют ограничение RLS на чтение документа "ПередачаДенег". Не в нашем случае, но в каких-то случаях это может быть оправдано, поэтому всегда нужно перепроверять.

 

Далее, я сформировал на нашей рабочей БД 1С:ЗУП и картина оказалась весьма любопытной, покажу только часть таблицы (префиксы измененных ролей подтерты):

Видим что роль "ИЗМ_ЧтениеКадровойИнформации" по сути дублирует стандартную роль, имеет ограничения RLS типа "Read", а также вероятно имеет некоторые изменения, вполне возможна ситуация задвоения условий в запросе к СУБД, конечно это требует анализа и дальнейших действий по мере необходимости. Также наблюдается проблема с ролью "ЧтениеРабочегоВремени".

Обработка не сложная, работает на управляемых формах, конфигурация любая, разрабатывалась и тестировалась на платформе 8.3.14.1854. Вводится имя пользователя (как текст), которое используется для входа в 1С. Анализируемые объекты: справочники, документы, все виды регистров, бизнес-процессы, задачи, журнал документов.

Обработку выложу ниже, к материалам статьи прилагаю выгрузку тестовой конфигурации. Если скачаете — спасибо за поддержку!

 

Что еще можно посоветовать

Иногда плохо реализованный RLS необязательно является проблемой, если запрос к объекту выполняется раз в час/день и не потребляет много ресурсов, то он не стоит внимания. Надо искать часто выполняемые запросы, а они в купе с "плохим" RLS могут вызывать серьезные проблемы производительности. Определить наиболее затратный по ресурсам запрос Duration/CPU/Disk IO вам поможет Курс по подготовке к экзамену 1С:ЭКСПЕРТ и 1С:Профессионал по технологическим вопросам, его проводят несколько преподавателей, рекомендую попасть к Богачеву Виктору.

 

Другие ссылки:

Типичные ошибки при разработке прав доступа

Консоль запросов RLS

Использование RLS

4 Comments

  1. acanta

    Спасибо большое.

    Правильно ли я понимаю, что РЛС на журналах в управляемых формах не применяется, если в форме не указано РЛС ( обработка, ещё одна форма журнала) или если в ней в динамическом списке написан собственный запрос?

    Reply
  2. geron4

    (1) Журнал документов это физическая таблица, на него можно наложить RLS только на чтение (read), если у пользователя есть роль с наложенными ограничениями RLS для Журнала документов, то ограничения будут всегда применяться при любом запросе к объекту метаданных, т.к. это добавляется платформой к запросу к СУБД. На счет указания в форме RLS — не в курсе.

    Reply
  3. YurySigolaev

    (1) RLS в журналах (списках) к динамическому списку применяется .

    Точно также как и к любому другому запросу.

    А формы вообще к RLS отношения не имеют.

    Reply
  4. k.dm.v@mail.ru

    Полезная статья! Спасибо!

    Reply

Добавить коментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *