Кто держит документ и почему 1С не даёт его записать: разбор блокировок
Содержание
Чаще всего ошибку блокировки объекта в 1С устраняют за пару минут: находят пользователя, у которого этот же документ или элемент справочника открыт и изменён, и просят его записать или закрыть форму. Если сообщение звучит как Конфликт блокировок при выполнении транзакции, дело уже не в открытой форме, а в долгой транзакции или взаимоблокировке. Тогда виновника ищут через консоль кластера и технологический журнал.
Типичная картина: бухгалтер перепроводит реализацию, а 1С отвечает Не удалось заблокировать объект. В соседнем кабинете менеджер с утра держит эту же накладную открытой и что-то поправил в табличной части. Пока он не сохранит изменения, второй сеанс записать документ не сможет. Это не сбой, а защита от того, чтобы двое не затёрли правки друг друга.
Всё ниже относится к платформе 1С:Предприятие 8.3 и одинаково работает в Бухгалтерии, ЗУП, УТ и других типовых конфигурациях: блокировки — механизм платформы, а не конкретной программы.
Какие бывают блокировки в 1С и откуда берётся ошибка
Под словом «блокировка» в 1С скрываются четыре разных механизма. От того, какой сработал, зависит способ лечения.
| Вид блокировки | Когда срабатывает | Как выглядит ошибка | Кто виноват |
|---|---|---|---|
| Объектная пессимистическая | Пользователь начал менять объект в форме | Не удалось заблокировать объект или Ошибка блокировки объекта. Объект уже заблокирован с указанием пользователя и компьютера | Другой сеанс с открытой изменённой формой |
| Объектная оптимистическая | При записи версия объекта в базе уже другая | Объект изменен или удален в другом сеансе | Кто-то успел записать объект раньше вас |
| Транзакционная (управляемая) | Две транзакции претендуют на одни данные | Конфликт блокировок при выполнении транзакции: Превышено максимальное время ожидания предоставления блокировки | Долгая транзакция в другом сеансе |
| Блокировка СУБД | Конфликт на уровне MS SQL или PostgreSQL | Текст ошибки СУБД, например Lock request time out period exceeded | Запрос, который держит строки или таблицу |
Первые две — бытовые, их снимают сами пользователи. Две вторые — инструмент администратора и программиста.
😐 Объектная блокировка не мешает читать документ и печатать его. Она мешает только записать изменения второму человеку.
⏱ Транзакционная блокировка живёт до конца транзакции. Пока идёт проведение, закрытие месяца или загрузка из обмена, данные под ней заняты.
🗂 В файловой базе блокировки ставятся на таблицы целиком. Поэтому там ожидания возникают чаще: два бухгалтера, проводящие документы по одному регистру, уже мешают друг другу.
Сообщение Объект изменен или удален в другом сеансе лечится проще всего. Закройте форму без записи, откройте объект заново и повторите правку. Данные в форме устарели, перечитывать их нужно из базы.
Как найти, кто заблокировал объект
Для объектной блокировки текст ошибки часто сам называет виновника: пользователя, компьютер и номер сеанса. Если этих данных нет, есть три способа их получить.
Список активных пользователей
- В пользовательском режиме откройте
Все функции → Обработки → Активные пользователи. Если пункта «Все функции» нет, включите его: меню с тремя полосками →Сервис → Параметры→ флажок «Отображать команду «Все функции»». - Найдите сеансы с давним временем начала или пользователей, работающих с тем же разделом.
- Свяжитесь с человеком и попросите записать или закрыть форму.
В Конфигураторе тот же список открывается через Администрирование → Активные пользователи.
Консоль администрирования кластера
В клиент-серверной базе информативнее консоль кластера серверов 1С.
- Запустите «Администрирование серверов 1С Предприятия».
- Раскройте
Центральные серверы → <сервер> → Кластеры → <кластер> → Информационные базы → <база>. - Откройте узел «Блокировки». Там видно, какой сеанс держит какой объект.
- В узле «Сеансы» по номеру сеанса найдите пользователя, компьютер и время начала.
Из командной строки то же самое показывает утилита rac: список сеансов выдаёт rac session list, блокировки — режим lock (параметры смотрите в rac help lock).
Когда виновник недоступен
Сотрудник ушёл домой, а форма с изменениями осталась открытой. Сеанс можно завершить принудительно: в консоли кластера правой кнопкой по сеансу → «Удалить».
Принудительное завершение сеанса обрывает работу пользователя. Несохранённые изменения в его формах пропадут, а начатая операция (например, проведение) откатится. Перед удалением сеанса убедитесь, что в нём не идёт закрытие месяца или загрузка обмена.
Если сеанс «завис» после аварийного выключения компьютера, платформа освобождает его блокировки сама, когда сеанс закрывается по таймауту. Ждать не хочется — удаляйте сеанс из консоли.
Как вычислить проблемную транзакцию: техжурнал и отладчик
Ошибку Превышено максимальное время ожидания предоставления блокировки видит тот, кто ждал. Виновник же — другой сеанс, который в это время держал данные. Найти его по одному сообщению нельзя, нужен журнал.
Технологический журнал
Технологический журнал пишет события блокировок на сервере. Для разбора нужны три события:
- 🔒
TLOCK— установка управляемой блокировки; - ⏳
TTIMEOUT— превышено время ожидания; в свойствеWaitConnectionsвидно, какое соединение мешало; - 💥
TDEADLOCK— взаимоблокировка; в свойствеDeadlockConnectionIntersectionsперечислены участники и ресурсы.
Журнал настраивают файлом logcfg.xml в каталоге conf платформы на сервере 1С (например, C:\Program Files\1cv8\conf\). Минимальная настройка:
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="http://v8.1c.ru/v8/tech-log">
<log location="D:\techlog" history="24">
<event>
<eq property="name" value="TLOCK"/>
</event>
<event>
<eq property="name" value="TTIMEOUT"/>
</event>
<event>
<eq property="name" value="TDEADLOCK"/>
</event>
<property name="all"/>
</log>
</config>
Параметр history задаёт, сколько часов хранить логи. Платформа подхватывает изменения файла сама, перезапуск службы не нужен.
Событие TLOCK на нагруженной базе пишет гигабайты за час. Включайте журнал на время воспроизведения ошибки, кладите логи на диск с запасом места и после разбора удаляйте файл logcfg.xml.
В записи TTIMEOUT ищите номер соединения из WaitConnections. Затем найдите это соединение в событиях TLOCK по тому же времени: в свойстве Context будет модуль и строка кода, где поставлена блокировка. Это и есть место, которое держит данные дольше нужного.
Отладчик и консоль запросов
Когда место в коде известно, открывайте Конфигуратор и смотрите, что происходит внутри транзакции.
- Включите отладку на сервере: служба агента сервера должна быть запущена с ключом
-debug. - В Конфигураторе выберите
Отладка → Подключениеи подключитесь к сеансу. - Поставьте точку останова перед
НачатьТранзакцию()или в обработчикеОбработкаПроведения. - Пошагово пройдите код и отметьте, что выполняется между установкой блокировки и концом транзакции.
Частая находка — тяжёлый запрос внутри транзакции. Скопируйте его в консоль запросов и выполните отдельно: если он работает 15–30 секунд, то всё это время данные под блокировкой, а соседние сеансы ждут.
Точка останова на рабочем сервере замораживает транзакцию пользователя вместе с её блокировками. Отлаживайте на копии базы или в нерабочее время.
Взаимоблокировки (deadlock): почему возникают и как разорвать
Взаимоблокировка — это когда двое ждут друг друга. Сеанс А занял остатки по складу и хочет взять взаиморасчёты. Сеанс Б уже держит взаиморасчёты и ждёт склад. Ни один не уступит, поэтому платформа или СУБД обрывает одну из транзакций.
Пользователь видит что-то вроде Конфликт блокировок при выполнении транзакции с упоминанием взаимоблокировки. На MS SQL текст бывает английским: Transaction ... was deadlocked on lock resources with another process and has been chosen as the deadlock victim.
Три типичных сценария
- Разный порядок блокировок. Документ «Реализация» сначала пишет регистр товаров, потом взаиморасчёты. Документ «Возврат» — наоборот. При одновременном проведении они встают друг против друга.
- Повышение уровня блокировки. Транзакция читает остатки с разделяемой блокировкой, а потом пытается поставить на них исключительную. Если так же поступила вторая транзакция, обе ждут.
- Неуправляемое чтение остатков. Остатки читают запросом без предварительной блокировки, затем пишут движения. В управляемом режиме это ещё и риск ухода в минус.
Как исправить
- Блокируйте ресурсы в одинаковом порядке во всех документах: например, всегда сначала склад, потом расчёты.
- Ставьте исключительную блокировку сразу, до чтения остатков, а не после.
- Блокируйте только нужные измерения, а не весь регистр.
Пример установки исключительной блокировки перед контролем остатков:
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.ТоварыНаСкладах");
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
ЭлементБлокировки.ИсточникДанных = Товары;
ЭлементБлокировки.ИспользоватьИзИсточникаДанных("Номенклатура", "Номенклатура");
ЭлементБлокировки.УстановитьЗначение("Склад", Склад);
Блокировка.Заблокировать();
// Теперь остатки по этим товарам на этом складе можно читать запросом:
// другие транзакции не изменят их до конца нашей транзакции.
Здесь Товары — табличная часть документа, Склад — реквизит шапки. Блокируются только строки регистра с этим складом и номенклатурой из документа, а не весь регистр.
Разовую взаимоблокировку пользователь лечит повтором операции. Регулярные — признак ошибки в коде, и их нужно разбирать по TDEADLOCK.
Как сократить ожидание блокировок в запросах и коде
Ошибка по таймауту возникает, когда транзакция держит данные дольше, чем соседи готовы ждать. Значит, лечение — укорачивать транзакции и сужать область блокировки.
| Приём | Когда помогает | Риски |
|---|---|---|
| Вынести тяжёлые запросы из транзакции | Отчётный запрос или расчёт стоит внутри проведения | Данные могут измениться между чтением и записью — проверяйте |
| Перевести конфигурацию на управляемый режим блокировок | Самописная или старая конфигурация в автоматическом режиме | Нужно вручную ставить БлокировкаДанных везде, где читаются остатки |
| Блокировать по измерениям | Блокируется весь регистр или вся таблица | Почти нет, если измерения выбраны правильно |
| Разбить длинную обработку на порции | Групповое перепроведение, загрузка тысяч документов одной транзакцией | Частичный результат при сбое — нужна возможность продолжить |
| Добавить индексы и обновить статистику СУБД | Запрос сканирует таблицу целиком и держит много строк | Индексы увеличивают базу и замедляют запись |
Режим блокировок задаётся в свойствах корневого элемента конфигурации: свойство «Режим управления блокировкой данных» с вариантами «Автоматический», «Управляемый» и «Автоматический и управляемый». Типовые конфигурации на 8.3 уже работают в управляемом режиме. В нём конструкция ДЛЯ ИЗМЕНЕНИЯ в запросе игнорируется, блокировку ставят только объектом БлокировкаДанных.
Три правила, которые убирают большую часть ожиданий в доработках:
- 🚫 Внутри транзакции не обращайтесь к внешним ресурсам: веб-сервисам, файлам, почте. Сетевая задержка в 10 секунд — это 10 секунд блокировки.
- 🚫 Не открывайте диалоги и не ждите ответа пользователя внутри транзакции.
- ✅ Пишите движения регистров одним набором, а не по строке в цикле.
Если у вас типовая конфигурация без доработок, код править не нужно. Ищите, какая обработка или регламентное задание запускается одновременно с проведением: обмен с сайтом, пересчёт итогов, загрузка выписок.
Настройка сервера и базы, чтобы ошибка не возвращалась
Время ожидания блокировки
По умолчанию сеанс ждёт управляемую блокировку 20 секунд, потом выдаёт ошибку. Это значение меняется для каждой базы в Конфигураторе: Администрирование → Параметры информационной базы → поле времени ожидания блокировки данных. Программно — методом УстановитьВремяОжиданияБлокировкиДанных().
Увеличивать таймаут стоит осторожно. Если поставить 120 секунд, ошибка пропадёт, но пользователи будут по две минуты смотреть на «песочные часы». Это маскировка, а не решение. Разумно поднимать значение до 30–60 секунд только на время, пока ищете и исправляете долгую транзакцию.
Расписание тяжёлых операций
Многие конфликты рождаются из совпадений по времени. Разведите их:
- закрытие месяца, перепроведение и пересчёт итогов — вне рабочего времени;
- обмены с другими базами — с интервалом, который не совпадает с пиком проведения;
- выгрузку резервных копий средствами СУБД — ночью.
Расписание регламентных заданий в типовых конфигурациях находится в Администрирование → Обслуживание → Регламентные операции → Регламентные и фоновые задания.
Сервер и СУБД
- 🖥 Следите за загрузкой процессора и дисков сервера СУБД: медленный диск растягивает каждую транзакцию.
- 📊 Настройте регулярное обновление статистики и обслуживание индексов в СУБД. Устаревшая статистика ведёт к плохим планам запросов и лишним блокировкам.
- 🗂 Если в файловой базе одновременно проводят документы несколько человек и ожидания стали ежедневными, это повод перейти на клиент-серверный вариант. Там блокировки ставятся на записи, а не на целые таблицы.
Если ничего не помогло
Бывает, что блокировка возникает при пустом списке пользователей или держится после перезагрузки клиентов. Проверьте по порядку:
- Фоновые задания. Их не видно в списке пользователей как людей, но в консоли кластера это сеансы с приложением «Фоновое задание». Длинное задание обмена может держать данные часами.
- Внешние соединения. COM-подключения и веб-сервисы тоже открывают сеансы. В консоли у них своё имя приложения.
- Зависший рабочий процесс. Если сеанс не удаляется из консоли, проблема в рабочем процессе
rphost. Его можно перезапустить через консоль кластера.
Перезапуск рабочего процесса или службы сервера 1С обрывает все сеансы, которые на нём работают, включая чужие проведения и обмены. Делайте это в нерабочее время или после предупреждения всех пользователей.
- Блокировка на уровне СУБД. Если 1С ничего не показывает, а запросы стоят, смотрите активные блокировки средствами самой СУБД: в MS SQL — монитор активности в Management Studio, в PostgreSQL — системное представление
pg_locks.