Приветствуем вас! Сегодня мы с вами разберем одну из частых проблем, возникающих при работе с регистрами сведений в 1С:Предприятие, особенно в высоконагруженных системах. Рассмотрим ситуацию, когда возникает необходимость хранить статусы большого количества документов (например, заказов поставщикам), и при этом избежать конфликтов блокировок. Выясним, что происходит с набором записей регистра сведений при отказе от изменений, и проанализируем, как правильно выбрать режим управления блокировками.
Наш читатель столкнулся с проблемой: ему требовалось хранить статусы заказов, которых за день может быть более тысячи. Изначально статусы хранились в табличных частях документов, что приводило к постоянным конфликтам блокировок при их проведении. В качестве решения было предложено вынести статусы в отдельный регистр сведений. Но возник вопрос: что делать с записью набора записей регистра сведений, если основная операция, в рамках которой он изменяется, отменяется?
Давайте проанализируем ситуацию, когда в 1С происходит отказ от изменений. Это может случиться, если в обработчике события, например, ПередЗаписью, мы устанавливаем параметр Отказ = Истина, или если возникает любая другая ошибка, приводящая к отмене текущей транзакции.
Важно понимать: если транзакция отменяется, то все действия, выполненные в ее рамках, будут полностью отменены. Это означает, что любой набор записей регистра сведений, который был создан или изменен в этой транзакции, не будет записан в базу данных. Система откатит все изменения до состояния, которое было до начала транзакции.
Рассмотрим подробнее обработчик ПередЗаписью для набора записей регистра сведений. Он вызывается после начала транзакции записи, но до того, как набор записей фактически будет сохранен в базу данных. Если в этом обработчике мы установим Отказ = Истина, то вся транзакция будет прервана, и никаких изменений в базе данных по данному набору записей не произойдет. Это позволяет нам контролировать целостность данных и предотвращать запись некорректной информации.
Но что, если нам все же необходимо записать какую-либо информацию, например, причину отказа или логирование события, даже в случае отмены основной транзакции? В такой ситуации эта запись должна быть выполнена вне основной транзакции. Мы можем, например, временно сохранять нужные данные в таблицу значений или другую временную структуру, а затем записывать их в отдельный регистр (журнал) уже после завершения основной транзакции. Другой подход – использовать подписки на события, которые обрабатываются вне транзакции, позволяя выполнить нужные действия независимо от исхода основной операции.
Теперь давайте перейдем к одной из ключевых причин возникновения конфликтов и способам их предотвращения – к режимам управления блокировками. Именно здесь кроется решение проблемы, с которой столкнулся наш читатель.
В 1С:Предприятие существует два основных режима управления блокировками:
В этом режиме система 1С:Предприятие и используемая СУБД (система управления базами данных) берут на себя полное управление блокировками данных. Разработчику не требуется явно устанавливать или снимать блокировки. Система автоматически определяет, какие данные нужно заблокировать для обеспечения целостности. Обычно в этом режиме используются более высокие уровни изоляции транзакций, такие как Repeatable Read (повторяемое чтение) или Serializable (сериализуемое), что гарантирует согласованное и целостное чтение данных без дополнительных усилий со стороны разработчика.
Однако, у автоматического режима есть и обратная сторона. Высокие уровни изоляции могут приводить к большему количеству конфликтов блокировок и, как следствие, к снижению параллельности работы пользователей, особенно в условиях высокой нагрузки. Если несколько пользователей пытаются одновременно изменить или даже прочитать пересекающиеся данные, система может заблокировать более широкие диапазоны данных, чем это необходимо, что приводит к ожиданию и снижению общей производительности.
Управляемый режим, напротив, требует от разработчика явного управления блокировками с помощью специального объекта БлокировкаДанных. В этом режиме платформа 1С использует более низкий уровень изоляции транзакций СУБД, как правило, Read Committed (чтение зафиксированных данных). Это позволяет значительно повысить параллельность работы пользователей, поскольку блокировки накладываются "точнее" – только на те данные, которые действительно необходимо защитить от одновременного изменения.
Важный момент: если объект конфигурации (например, документ), который делает движения в регистры, работает в управляемом режиме блокировок, то все регистры, в которые он делает движения, также должны быть переведены в управляемый режим. Это обеспечивает согласованность работы механизмов блокировок.
Объект БлокировкаДанных предоставляет методы для установки блокировок на различные данные. Например, мы можем создать объект блокировки и добавить в него элементы блокировки для конкретного регистра сведений:
Перем мБлокировкаДанных;
// ... где-то при начале транзакции или перед записью
мБлокировкаДанных = Новый БлокировкаДанных;
ЭлементБлокировки = мБлокировкаДанных.Добавить("РегистрСведений.МойРегистрСтатусов");
ЭлементБлокировки.УстановитьРежим(РежимБлокировкиДанных.Исключительная); // или Разрешительный
ЭлементБлокировки.УстановитьЗначение("ИзмерениеКлюч", ЗначениеКлюча); // Если нужно заблокировать по измерению
ЭлементБлокировки.УстановитьЗначение("Период", ДатаПериода); // Если регистр периодический
// ...
Попытка
мБлокировкаДанных.Заблокировать();
// Ваши действия по записи или изменению данных
Исключение
Сообщить("Не удалось заблокировать данные: " + ОписаниеОшибки());
Отказ = Истина;
КонецПопытки;
Необходимо также помнить, что при использовании управляемых блокировок чтение данных запросом может игнорировать установленные управляемые блокировки. Это может привести к так называемому "фантомному чтению" или "неповторяющемуся чтению", когда запрос видит данные, которые были изменены другой транзакцией, но еще не зафиксированы. Объектное чтение (например, через НаборЗаписей.Прочитать()) в большинстве случаев учитывает управляемые блокировки, обеспечивая более надежное чтение защищенных данных.
В нашей исходной задаче, проблема с конфликтами блокировок была успешно решена путем переключения режима блокировки регистра сведений на "Автоматический". Это очень показательный результат.
Почему это сработало? Вероятнее всего, ранее в управляемом режиме блокировки либо были некорректно настроены, либо вовсе отсутствовали в коде. В такой ситуации, когда система ожидала явного управления блокировками, но не получала его, возникали конфликты и нарушения целостности данных. Переключение на автоматический режим гарантировало, что система сама возьмет на себя заботу о блокировках, обеспечив целостность данных, пусть даже ценой потенциально меньшей параллельности. Для данной конфигурации (УТ 11.5) и специфики работы это оказалось оптимальным решением.
Когда какой режим выбирать?
В заключение, хотим подчеркнуть, что вынесение статусов заказов в отдельный регистр сведений вместо хранения их в табличных частях документов является отличной практикой для уменьшения конфликтов блокировок. Это позволяет изменять статусы независимо от блокировок на самих документах, что особенно актуально при большом количестве заказов и частых изменениях статусов. Такой подход значительно повышает гибкость системы и ее производительность в условиях интенсивной работы.
Мы рассмотрели с вами ключевые аспекты работы с регистрами сведений, отказом от изменений и режимами блокировок. Надеемся, что эта информация поможет вам в вашей работе с 1С:Предприятие!
← К списку