Разнятся данные табличной части документа в разных сеансах 1С: как решить проблему

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

В практике администрирования и разработки на платформе 1С:Предприятие иногда возникают крайне загадочные и трудновоспроизводимые ошибки. Одна из таких проблем — расхождение данных в табличной части одного и того же документа у разных пользователей. Представьте ситуацию: один пользователь открывает документ и видит в табличной части 8 строк, а другой в то же самое время в своем сеансе видит только 7 строк. При этом перезапуск сеанса временно решает проблему. Ситуация усугубляется, если в «проблемном» варианте в одном из полей (например, «Договор») отображается битая ссылка <Объект не найден>.

В данной статье мы подробно проанализируем эту ситуацию на примере конфигурации «Управление торговлей 10.3», работающей на СУБД IBM DB2, выясним истинные технические причины этого поведения и выработаем пошаговый план устранения неисправности.

В чем кроется причина расхождения данных?

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

Рассмотрим четыре главные причины, которые могут приводить к подобному эффекту:

  1. Сбои в механизме RLS (Record Level Security) и параметрах сеанса. Это наиболее вероятная причина, особенно учитывая появление надписи <Объект не найден> в поле «Договор». В 1С ограничения доступа накладываются динамически при выполнении запросов к базе данных. Если у пользователя в одном из сеансов не до конца или некорректно инициализировались параметры сеанса (например, список разрешенных контрагентов или организаций), система RLS начинает скрывать записи. Платформа 1С при этом может вести себя двояко: либо полностью скрыть строку табличной части, где фигурирует «запрещенный» договор (тогда строк становится меньше), либо отобразить строку, но заменить ссылку на договор битой ссылкой.
  2. Рассинхронизация кэша между рабочими процессами сервера (rphost). В многопоточном или многопроцессорном кластере 1С сеансы пользователей могут обслуживаться разными процессами rphost. Платформа активно кэширует данные объектов на сервере приложений. Если синхронизация кэша между процессами дает сбой (например, из-за микросекундных сетевых задержек или нехватки оперативной памяти), один процесс выдает актуальные данные из СУБД, а второй — устаревшие данные из локального кэша сеансов (каталог snccntx).
  3. Особенности управления блокировками и транзакциями в IBM DB2. Использование СУБД IBM DB2 накладывает свой отпечаток. При неверно настроенных уровнях изоляции транзакций (например, при использовании «грязного чтения» — Uncommitted Read) или при эскалации блокировок из-за дефицита памяти СУБД может позволить одному из сеансов прочитать промежуточные данные транзакции, которая впоследствии была отменена. Это порождает фантомные строки и «несуществующие» объекты.
  4. Устаревшая статистика и фрагментация индексов СУБД. Если регламентные операции на уровне базы данных не выполняются вовремя, оптимизатор запросов СУБД строит неэффективные планы. При сложном соединении таблиц (которое всегда происходит при активном RLS) это может приводить к физическому выпадению строк из результирующей выборки СУБД.

---

Шаг 1. Диагностика и исправление ограничений RLS

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

Проанализируем код модуля сеанса. Откроем конфигуратор и найдем предопределенную процедуру УстановкаПараметровСеанса. Обратите внимание на то, как происходит заполнение параметров. Инициализация должна происходить атомарно и без возможности пропуска из-за случайных ошибок выполнения.

Рекомендуется использовать безопасную конструкцию инициализации параметров «по требованию». Посмотрим на пример реализации:


Процедура УстановкаПараметровСеанса(ТребуемыеПараметры)
    
    // Если массив требуемых параметров пуст, инициализируем критически важные параметры RLS
    Если ТребуемыеПараметры = Неопределено Тогда
        ИнициализироватьПараметрыДоступаПользователя();
    Иначе
        // Инициализация конкретных параметров по запросу платформы
        Для Каждого ИмяПараметра Из ТребуемыеПараметры Цикл
            Если ИмяПараметра = "РазрешенныеКатегорииНоменклатуры" Тогда
                ПараметрыСеанса.РазрешенныеКатегорииНоменклатуры = ПолучитьДоступныеКатегории();
            КонецЕсли;
        КонецЦикла;
    КонецЕсли;

КонецПроцедуры

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

---

Шаг 2. Очистка кэша на стороне сервера и клиентов

Поскольку перезапуск сеанса решает проблему, кэширование является вторым главным подозреваемым. Выполним полную очистку кэша по шагам.

Очистка серверного кэша сеансов (snccntx):

  1. Остановим службу сервера 1С:Предприятие (1C:Enterprise 8.3 Server Agent).
  2. Перейдем в каталог локального кластера (по умолчанию это C:\Program Files\1cv8\srvinfo\reg_1541).
  3. Найдем все папки с именем snccntx (именно в них хранится NoSQL-кэш сеансовых данных) и полностью удалим их содержимое.
  4. Запустим службу сервера 1С.

Для борьбы с зависанием кэша функций в общих модулях (если используется свойство «Повторное использование возвращаемых значений») в коде конфигурации в критических местах (например, при открытии формы документа) можно программно вызывать очистку:


ОбновитьПовторноИспользуемыеЗначения();

Это принудительно заставит платформу сбросить устаревшие закешированные данные функций на сервере для текущего сеанса.

---

Шаг 3. Регламентное обслуживание СУБД IBM DB2

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

Для IBM DB2 критически важно регулярно выполнять команды утилит RUNSTATS и REORG. Разберем, как выполнить их через командную строку DB2 (Command Line Processor):

  1. Подключимся к базе данных:
    
    db2 connect to ИМЯ_БАЗЫ_ДАННЫХ user ИМЯ_ПОЛЬЗОВАТЕЛЯ using ПАРОЛЬ
    
  2. Запустим реорганизацию таблиц документов и их табличных частей (например, для таблицы табличной части _Document150_VT1200):
    
    db2 REORG TABLE SCHEMA._Document150_VT1200
    
  3. Обновим статистику по этой таблице и ее индексам, чтобы оптимизатор DB2 строил верные планы запросов:
    
    db2 RUNSTATS ON TABLE SCHEMA._Document150_VT1200 ON ALL COLUMNS WITH DISTRIBUTION AND DETAILED INDEXES ALL
    

Также проверим параметры конфигурации базы данных DB2, отвечающие за управление блокировками. Для этого выполним команду:


db2 get db cfg for ИМЯ_БАЗЫ_ДАННЫХ

Обратим внимание на параметры LOCKLIST (размер памяти под блокировки) и MAXLOCKS (процент памяти блокировок, после которого происходит эскалация блокировок строк до блокировки всей таблицы). Если эти значения слишком малы, СУБД будет принудительно блокировать таблицы целиком или переходить на более слабые уровни изоляции транзакций, что и приводит к фантомным чтениям в параллельных сеансах 1С. Увеличим их при необходимости.

---

Шаг 4. Настройка логирования через Технологический журнал

Если проблема плавающая и возникает очень редко, идеальным способом поймать ее за руку является настройка Технологического журнала (ТЖ) 1С. Мы можем настроить сбор логов таким образом, чтобы фиксировать только запросы, связанные со специфическим документом, в котором разнится число строк.

Создадим файл конфигурации ТЖ logcfg.xml в каталоге C:\Program Files\1cv8\conf на сервере 1С следующего содержания:


<config xmlns="http://v8.1c.ru/v8/tech-log">
    <log location="C:\v8logs\db_queries" history="72">
        <event>
            <eq property="Name" value="DBMSSQL"/>
        </event>
        <event>
            <eq property="Name" value="SDBL"/>
        </event>
        <property name="all"/>
    </log>
</config>

Важное примечание: Событие DBMSSQL в терминологии технологического журнала 1С отвечает за все SQL-запросы к СУБД, включая СУБД IBM DB2 и PostgreSQL (несмотря на название).

Когда пользователь снова сообщит, что видит неверное количество строк, мы сможем открыть логи технологического журнала за эту минуту, найти SQL-запрос от его сеанса к табличной части документа и сопоставить его с запросом из «правильного» сеанса. Это даст 100% ответ на вопрос, вернула ли СУБД некорректные данные или же платформа отфильтровала их на своей стороне по механизму RLS.

← На главную