При разработке на платформе 1С:Предприятие часто возникает вопрос о том, насколько быстро изменения, внесенные одним пользователем, становятся доступны другим. Особое место в этом вопросе занимают константы. В этой статье мы подробно разберем механизмы чтения и записи констант, выясним, почему «мгновенное» обновление не всегда происходит на уровне интерфейса, и проанализируем, почему использование константы в качестве счетчика — это опасная архитектурная практика.
Начнем с базового принципа работы платформы. Когда один пользователь записывает новое значение константы, данные физически попадают в таблицу базы данных (обычно это таблица _Consts). Для другого пользователя эти данные становятся доступны сразу же, как только его сеанс инициирует чтение этой константы из базы данных. Однако понятие «сразу» в 1С имеет свои нюансы, связанные с тем, как именно программный код обращается к данным.
Рассмотрим два основных способа получения значения:
Константы.ИмяКонстант.Получить() обращается к базе данных. Если значение в базе уже изменено и транзакция записи завершена, второй пользователь получит актуальное значение.Проанализируем ситуацию: если программист считывает константу один раз при старте системы и сохраняет ее в переменную, то, разумеется, изменение в базе данных не обновит эту переменную автоматически. Это подводит нас к критически важному вопросу кэширования.
Даже если в таблице SQL значение обновилось, пользователь может продолжать видеть старые данные. Разберем по шагам, почему это происходит:
Параметры сеанса. Часто для повышения производительности значения констант считываются в параметры сеанса при запуске (в модуле сеанса). Параметры сеанса живут на протяжении всей работы пользователя. Если вы изменили константу, а код системы продолжает обращаться к ПараметрыСеанса.ТекущийСчетчик, значение не обновится до тех пор, пока сеанс не будет перезапущен или параметр не будет перезаписан программно в текущем сеансе.
Функциональные опции (ФО). Если константа является источником для функциональной опции, ситуация усложняется. Платформа активно кэширует значения ФО для отрисовки интерфейса. Чтобы изменения вступили в силу (например, появилась скрытая кнопка), может потребоваться вызов метода ОбновитьИнтерфейс(). В некоторых случаях изменения видны только после повторного входа в программу.
Повторное использование возвращаемых значений. Проанализируем работу общих модулей. Если чтение константы обернуто в функцию модуля, у которого включено свойство «Повторное использование возвращаемых значений» (на время вызова или на время сеанса), платформа вернет старое значение из своего внутреннего кэша, не обращаясь к СУБД.
Иногда у разработчиков возникает соблазн использовать константу для хранения номера следующей печатной формы или документа. Например, при каждой печати считывать значение, прибавлять единицу и записывать обратно. Выясним, почему это приведет к проблемам в многопользовательской среде.
Блокировки базы данных. В 1С все константы хранятся в одной общей таблице. При записи константы происходит блокировка. Если одновременно 10 пользователей попытаются «взять номер» и обновить константу, они выстроятся в очередь (lock contention). В худшем случае это приведет к ошибкам превышения времени ожидания блокировки. Система начнет «тормозить» на пустом месте.
Транзакционные коллизии. Представим ситуацию:
// Псевдокод инкремента
ТекущийНомер = Константы.НомерПечатнойФормы.Получить();
НовыйНомер = ТекущийНомер + 1;
Константы.НомерПечатнойФормы.Установить(НовыйНомер);
Если нам необходимо реализовать надежный счетчик, который работает быстро и без конфликтов, рассмотрим следующие варианты:
СчетчикиПечати), где каждый элемент — это отдельный счетчик. При записи элемента справочника блокируется только одна конкретная строка, а не вся таблица «всех настроек системы» (как в случае с константами). Это значительно повышает параллельность работы.Последовательность, хотя это более тяжеловесный механизм.Если вам все же необходимо гарантированно получить актуальное значение константы в коде, минуя все возможные кэши, рекомендуется использовать запрос. Посмотрим на пример кода:
Функция ПолучитьАктуальноеЗначениеКонстанты() Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Константы.МояВажнаяНастройка КАК Значение
|ИЗ
| Константы КАК Константы";
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Если ВыборкаДетальныеЗаписи.Следующий() Тогда
Возврат ВыборкаДетальныеЗаписи.Значение;
КонецЕсли;
Возврат Неопределено;
КонецФункции
Этот метод гарантирует, что вы обращаетесь напрямую к таблице базы данных. Однако помните, что частое использование запросов к константам в циклах может создать излишнюю нагрузку на SQL-сервер. Всегда ищите баланс между актуальностью данных и производительностью системы.
Подведем итоги нашего анализа. Значение константы обновляется в базе данных мгновенно, но механизмы оптимизации 1С (кэширование интерфейса, параметры сеанса) могут скрывать это изменение от пользователя до определенных событий. Использовать константы для счетчиков — плохая практика из-за блокировок таблицы _Consts. Для этих целей лучше использовать элементы справочников или типовую автонумерацию объектов платформы.