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