31 KiB
sidebar_position, sidebar_label, title
| sidebar_position | sidebar_label | title |
|---|---|---|
| 6 | Блокировки | Блокировки |
🚀 Полное руководство по блокировкам
📋 Содержание
- Основные понятия и назначение блокировок
- Типы блокировок в 1С
- Объектные блокировки
- Транзакционные блокировки: режимы и уровни изоляции
- Работа с блокировками из кода
- Ответственное чтение данных
- Оптимизация и практические рекомендации
- Механизмы контроля остатков в типовых конфигурациях
- Частые проблемы и их решения
- Ответы на вопросы
🎯 1. Основные понятия и назначение блокировок
Что такое блокировка?
Блокировка данных — механизм, обеспечивающий конкурентный доступ пользователей к информационной базе и целостность данных при одновременных изменениях. Она предотвращает конфликты, когда несколько пользователей пытаются изменить одни и те же данные.
Проблемы, которые решают блокировки:
- Потерянное изменение — когда изменения одной транзакции перезаписываются другой
- "Грязное" чтение — чтение незафиксированных данных
- Неповторяемое чтение — разные результаты при повторном чтении тех же данных
- Чтение фантомов — появление новых данных между чтениями (актуально для необъектных сущностей, например, регистры сведений и накопления)
Простой аналог:
Продавец блокирует яблоко для покупателя, пока тот отсчитывает деньги. Другие покупатели не могут выбрать это яблоко до завершения операции.
🏗️ 2. Типы блокировок в 1С
1. Объектные блокировки (для работы с объектами: справочники, документы)
- 1.1. Пессимистические блокировки
- Явные (через метод
Заблокировать()илиЗаблокироватьДанныеДляРедактирования()) - Неявные (в форме) (автоматически при редактировании в форме)
- Явные (через метод
- 1.2. Оптимистические блокировки (проверяют версию при записи)
2. Транзакционные блокировки (для работы с данными в транзакциях)
- 2.1. Автоматические блокировки (управляются СУБД, используются высокие уровни изоляции)
- 2.2. Управляемые блокировки (управляются разработчиком через 1С, используются низкие уровни изоляции)
- Явные (создаются через объект БлокировкаДанных)
- Неявные (устанавливаются платформой автоматически)
Краткая характеристика:
- Объектные блокировки: Не позволяют интерактивно изменить двум пользователям один объект (элемент справочника или документ)
- Транзакционные блокировки: Позволяют программно оперировать актуальными данными при выполнении движений по регистрам
👤 3. Объектные блокировки
3.1. Пессимистическая блокировка
Назначение: Запрещает изменение объекта другими сеансами или данным сеансом до снятия блокировки.
Как работает:
- Автоматически устанавливается при редактировании объекта в форме
- Вручную можно использовать через
Заблокировать()илиЗаблокироватьДанныеДляРедактирования()
Важно: Факт блокировки не мешает изменению объекта — для защиты нужно всегда пытаться заблокировать объект перед изменением.
Пример кода:
ФайлОбъект = ДанныеФайла.Ссылка.ПолучитьОбъект();
Попытка
ФайлОбъект.Заблокировать();
// Изменяем объект
ФайлОбъект.Записать();
Исключение
// Обработка ошибки блокировки
КонецПопытки;
3.2. Оптимистическая блокировка
Назначение: Проверяет, не изменился ли объект с момента его чтения.
Принцип работы:
- При вызове
ПолучитьОбъект()платформа считывает версию данных объекта (ВерсияДанных) - Если другой сеанс параллельно изменит и запишет этот же объект, его версия изменится
- При попытке записи объекта из первого сеанса происходит сравнение версий
- Если версии не совпадают — возникает ошибка "Нарушение целостности чтения объекта базы данных из-за параллельного изменения объекта другим сеансом"
🔄 4. Транзакционные блокировки: режимы и уровни изоляции
Уровень изоляции транзакций — это параметр СУБД, который определяет степень защиты данных от конфликтов при одновременной работе нескольких транзакций. Он представляет собой компромисс между:
- Целостностью данных (предсказуемость, непротиворечивость)
- Параллельностью работы (скорость, производительность)
4.1. Два режима работы
| Аспект | Автоматический режим | Управляемый режим |
|---|---|---|
| Уровень изоляции СУБД | Repeatable Read или Serializable |
Read Committed |
| Управление блокировками | Система полагается на механизмы СУБД | Разработчик сам управляет блокировками |
| Производительность | Ниже (избыточные блокировки) | Выше (точные блокировки) |
| Рекомендация | Для обратной совместимости | Для современных конфигураций (рекомендуется) |
4.2. Уровни изоляции транзакций в СУБД
Сравнение уровней изоляции:
| Проблема / Уровень | READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE |
|---|---|---|---|---|
| Грязное чтение | ✅ Возможно | ❌ Запрещено | ❌ Запрещено | ❌ Запрещено |
| Неповторяемое чтение | ✅ Возможно | ✅ Возможно | ❌ Запрещено | ❌ Запрещено |
| Фантомы | ✅ Возможно | ✅ Возможно | ✅ Возможно | ❌ Запрещено |
| Параллельность | Высокая | Средняя | Низкая | Очень низкая |
Read Committed Snapshot (RCSI): Режим версионирования, поддерживается в PostgreSQL, Oracle и MS SQL (с 8.3). Нет ожиданий на блокировках при чтении т.к если другая транзакция пишет данные, ваш запрос не ждет, а читает "старый снимок" данных, которые были до начала записи. Рекомендуется включать для MS SQL в управляемом режиме.
📊 Сравнение Read Committed vs Read Committed Snapshot
| Критерий | Read Committed | Read Committed Snapshot |
|---|---|---|
| 🛡️ Проблемы, которые решает | Только "грязное чтение" | "Грязное чтение" + ожидания на блокировках |
| 📖 Как работает чтение | Читает последние зафиксированные данные | Читает "старый снимок" данных на момент начала запроса |
| ⏳ Поведение при конфликте | Если данные пишутся другой транзакцией → ждет (блокируется) | Если данные пишутся другой транзакцией → не ждет, читает предыдущую версию |
| 📈 Параллельность | Средняя (чтение может блокироваться на запись) | Высокая (чтение и запись не блокируют друг друга) |
| 💾 Использование памяти | Низкое (не хранит старые версии) | Высокое (хранит старые версии строк в tempdb до конца транзакции) |
| ⚙️ Включение в MS SQL | Уровень по умолчанию | Нужно включать отдельно: ALTER DATABASE SET READ_COMMITTED_SNAPSHOT ON |
Простая аналогия:
| Read Committed | Read Committed Snapshot |
|---|---|
| Библиотека с одной книгой: Читатель ждет, пока другой читатель закончит писать заметки на полях. | Библиотека с ксероксом: Читатель сразу получает копию книги в том виде, в котором она была до начала написания заметок. |
4.3. Настройка режима в конфигурации
Свойство конфигурации "Режим управления блокировкой данных":
- Автоматический — все объекты в автоматическом режиме
- Управляемый — все объекты в управляемом режиме (по умолчанию для новой конфигурации)
- Автоматический и управляемый — объекты работают в режиме, указанном в их свойствах
Важно: Режим явной транзакции определяется параметром РежимБлокировок метода НачатьТранзакцию(), а не свойством объекта.
💻 5. Работа с блокировками из кода
5.1. Объект БлокировкаДанных — основной инструмент
// Пример установки исключительной блокировки
Блокировка = Новый БлокировкаДанных;
Элемент = Блокировка.Добавить("РегистрНакопления.ОстаткиНоменклатуры");
Элемент.УстановитьЗначение("Склад", Склад);
Элемент.Режим = РежимБлокировкиДанных.Исключительный; // По умолчанию уже Исключительный
Блокировка.Заблокировать();
5.2. Режимы управляемых блокировок
Таблица совместимости:
| Разделяемая | Исключительная | |
|---|---|---|
| Разделяемая | ✅ | ❌ |
| Исключительная | ❌ | ❌ |
Когда какой режим использовать:
- Разделяемый: Данные нельзя изменить до конца транзакции (другие могут читать)
- Исключительный: Данные нельзя ни изменить, ни прочитать с разделяемой блокировкой
5.3. Особенности чтения разных объектов
Сравнение блокировок при чтении в 8.2 и 8.3:
| Аспект / Платформа | 1С:Предприятие 8.2 (и 8.3 в режиме совместимости) | 1С:Предприятие 8.3 (без режима совместимости) | Рекомендация |
|---|---|---|---|
Запрос.Выполнить() |
Ставится S-блокировка (разделяемая) в СУБД | Блокировка на чтение отсутствует | 8.3 выигрывает в параллельности |
НаборЗаписей.Прочитать() |
Управляемая разделяемая блокировка до конца транзакции | Аналогично 8.2 | Для чистого чтения используйте Запрос! |
| Объектное чтение (справочники, документы) | Управляемые блокировки не устанавливаются | Аналогично 8.2 | Для чтения безопаснее, чем НаборЗаписей |
📌 Ключевая проблема: НаборЗаписей.Прочитать() всегда устанавливает управляемую разделяемую блокировку, которая держится до конца транзакции!
📖 6. Ответственное чтение данных
6.1. Что такое ответственное чтение?
Это любое чтение данных, на основе результатов которого производятся изменения в базе или принимаются решения.
Примеры:
- Чтение остатков при проведении документа для формирования движений
- Получение данных для последующей целостной передачи в другую систему
- Групповая обработка в обновлениях ИБ
6.2. Как обеспечить ответственное чтение?
❌ Неправильный подход (риск потери данных):
КоличествоЗаметок = ЗапросНаЧтениеЗаметок().Выполнить();
// МЕЖДУ ЧТЕНИЕМ И ЗАПИСЬЮ ДРУГОЙ СЕАНС МОЖЕТ ИЗМЕНИТЬ ДАННЫЕ!
ЗаписатьНовуюЗаметку(КоличествоЗаметок + 1);
✅ Правильный подход (с блокировками):
НачатьТранзакцию();
Попытка
// 1. Блокируем данные ПЕРЕД чтением
Блокировка = Новый БлокировкаДанных;
Элемент = Блокировка.Добавить("РегистрСведений.ЗаметкиПоПредмету");
Элемент.УстановитьЗначение("Предмет", ПредметЗаметок);
Элемент.Режим = РежимБлокировкиДанных.Исключительный;
Блокировка.Заблокировать();
// 2. Читаем и изменяем данные
КоличествоЗаметок = ЗапросНаЧтениеЗаметок().Выполнить();
ЗаписатьНовуюЗаметку(КоличествоЗаметок + 1);
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
// Обработка ошибки
КонецПопытки;
6.3. Когда ответственное чтение НЕ требуется?
- Получение данных для отображения: Динамические списки, поиск, отчеты
- Работа с условно-постоянными данными: Константы, учетная политика
- Монопольный режим: Обновление базы, первоначальное заполнение
- Персональные/уникальные данные: Данные в разрезе пользователей, мобильное приложение
6.4. Выбор типа блокировки
Основные правила:
- Читаете и потом изменяете те же данные → Исключительная блокировка
- Читаете данные (чтобы они не менялись), но изменяете другие → Разделяемая блокировка на читаемые + исключительная на изменяемые
- Только чтение без последующих изменений → Блокировка не нужна
⚡ 7. Оптимизация и практические рекомендации
7.1. Ключевые принципы оптимизации
1. Минимизация времени удержания блокировок
❌ Плохо (долгая блокировка):
НачатьТранзакцию();
Блокировка(); // Ранняя блокировка
// ... долгие расчеты (10 секунд) ...
Записать();
ЗафиксироватьТранзакцию();
✅ Хорошо (короткая блокировка):
// Расчеты БЕЗ транзакции (10 секунд)
НачатьТранзакцию();
Блокировка(); // Блокировка в конце
Записать();
ЗафиксироватьТранзакцию(); // Блокировка всего 0.1 секунды
2. Правильный выбор метода доступа к данным
- Для чтения: Всегда используйте Запрос вместо
НаборЗаписей.Прочитать() - Для изменения: Используйте объектную модель с блокировками
3. Использование разделителя итогов
Включите галочку "Разрешить разделение итогов" для регистров без контроля остатков. Это позволяет параллельно обновлять итоги по одному набору измерений.
7.2. Эскалация блокировок
Что это: Когда блокируется не строка, а вся таблица или пространство.
Пороги эскалации:
- MS SQL Server: >5 000 блокировок одной инструкцией
- 1С:Предприятие 8.2: ~20 000 блокировок на одно пространство
- 1С:Предприятие 8.3: ~100 000 блокировок на одно пространство
Решение: Делите большие операции на пакеты (по 1000-2000 записей).
7.3. Рекомендации по оптимизации
- ✅ Перейти на управляемый режим блокировок
- ✅ Включить RCSI (Read Committed Snapshot) для MS SQL
- ✅ Включить разделитель итогов для регистров без контроля остатков
- ✅ Использовать Запрос вместо
НаборЗаписей.Прочитать()для чтения - ✅ Делать транзакции короткими
- ✅ Использовать многопоточность для массовых операций
- ✅ Мониторить блокировки специальными инструментами
🏢 8. Механизмы контроля остатков в типовых конфигурациях
8.1. Два механизма контроля остатков
| Аспект | Старый механизм (OLD) | Новый механизм (NEW) |
|---|---|---|
| Принцип работы | 1. Контроль остатков (запрос) 2. Запись движений | 1. Запись движений 2. Проверка на отрицательные остатки |
| Использование | Бухгалтерия 3.0, некоторые алгоритмы УТ 11, КА 2, ЕРП 2 | УТ 11, КА 2, ЕРП 2 (основной механизм) |
| Преимущества | — | 1. Выше скорость проведения 2. Нет перезаписи пустых наборов 3. Нет необходимости в предварительной блокировке |
| Недостатки | Требует блокировки данных при чтении (снижает параллельность) | Если для проведения нужны данные из регистров, блокировка при чтении все равно требуется |
Вывод: Используйте новый механизм (NEW), если проведение документа не требует предварительных запросов к данным.
8.2. Стратегии блокировок для разных режимов
Для управляемого режима с NEW механизмом:
// Ключевая настройка для регистров с разделением итогов!
НаборЗаписей.БлокироватьДляИзменения = Истина;
Эта настройка временно отключает разделение итогов для данного набора, предотвращая конфликты. Устанавливается обычно перед записью.
🚨 9. Частые проблемы и их решения
9.1. Взаимоблокировки (Deadlock)
Симптом: Две транзакции ждут друг друга.
Причины:
- Неоптимальный порядок блокировок
- Длительные транзакции
- Отсутствие индексов
Решение:
- Устанавливать блокировки в одинаковом порядке
- Делать транзакции короткими
- Использовать правильные индексы
9.2. Ожидания на блокировках
Причины:
НаборЗаписей.Прочитать()в транзакции- Длительные запросы со сканированием
- Отсутствие разделителя итогов в регистрах
Решение:
- Заменять
НаборЗаписейна Запросы - Оптимизировать запросы
- Включать разделитель итогов
9.3. Сводная таблица решений
| Проблема | Суть | Решение |
|---|---|---|
| Грязное чтение | Читаем незафиксированные данные | S-блокировка на время чтения |
| Потеря изменений | Перезапись изменений другого процесса | X-блокировка на всю транзакцию |
| Неповторяемое чтение | Данные меняются между чтениями в одной транзакции | S-блокировка на всю транзакцию |
| Чтение фантомов | Появление новых строк между запросами | Блокировка диапазона |
❓ 10. Ответы на ключевые вопросы
Базовые вопросы:
- Какие типы блокировок существуют в 1С? → Объектные и транзакционные
- В чем разница между пессимистической и оптимистической блокировкой? → Пессимистическая блокирует сразу, оптимистическая проверяет при записи
- Что такое ответственное чтение? → Чтение, после которого происходят изменения или принимаются решения
Практические вопросы:
- Когда нужно использовать
ЗаблокироватьДанныеДляРедактирования()? → Перед изменением объекта из кода - Почему
НаборЗаписей.Прочитать()может вызывать проблемы? → Ставит управляемую блокировку до конца транзакции - Как перевести конфигурацию на управляемые блокировки? → Установить режим "Управляемый" и настроить блокировки в коде
Глубинные вопросы:
- В чем разница между автоматическим и управляемым режимом? → Автоматический использует высокие уровни изоляции СУБД, управляемый — низкие с ручным управлением
- Как избежать взаимоблокировок при проведении документов? → Правильный порядок блокировок, короткие транзакции, использование
БлокироватьДляИзменения - Что такое эскалация блокировок и как с ней бороться? → Укрупнение блокировки при большом количестве; делить операции на пакеты
Вопросы на понимание:
- Когда НЕ нужно устанавливать блокировки? → При чтении для отображения, работе с константами, в монопольном режиме
- Какой уровень изоляции используется в управляемом режиме и почему? →
Read Committedдля большей параллельности - В чем преимущество нового механизма контроля остатков (NEW)? → Не требует предварительной блокировки, выше скорость
🎓 Ключевые выводы
- Блокировки — обязательный механизм для обеспечения целостности данных в многопользовательской среде
- Используйте управляемый режим для современных конфигураций — он дает большую гибкость и производительность
- Всегда блокируйте данные перед изменением из кода, используя
Заблокировать()илиБлокировкаДанных - Избегайте
НаборЗаписей.Прочитать()для чтения — используйте Запросы - Делайте транзакции короткими — выносите расчеты за пределы транзакции
- Понимайте разницу между механизмами контроля остатков OLD и NEW
- Используйте инструменты мониторинга для анализа блокировок в реальном времени
- Помните об эскалации при работе с большими объемами данных в