При работе в классической конфигурации 1С:Предприятие 7.7 (особенно на связке с СУБД Microsoft SQL Server и при использовании терминального доступа) администраторы и разработчики часто сталкиваются с труднообъяснимыми зависаниями системы. Пользователи жалуются на бесконечные ожидания при попытке провести документ, а администратор не может зайти в Конфигуратор для изменения списка пользователей из-за ошибки разделения доступа к файлу users.usr.
В этой статье мы подробно разберем, почему возникает эта взаимосвязанная цепочка проблем, как модальные окна внутри транзакций ломают стабильность СУБД, и какие шаги необходимо предпринять для полного устранения этих сбоев.
Давайте детально проанализируем, что происходит на уровне платформы 1С 7.7 и СУБД SQL в момент проведения любого документа. Когда пользователь нажимает кнопку «ОК» или «Провести», платформа автоматически открывает транзакцию СУБД и начинает выполнять код предопределенной процедуры ОбработкаПроведения.
Транзакция — это неделимая последовательность операций с базой данных. Чтобы гарантировать согласованность данных, СУБД накладывает жесткие монопольные блокировки на используемые таблицы (в первую очередь на таблицы журнала документов 1SJOURN, таблицы итогов и регистров). Пока транзакция не завершится (командами Commit или Rollback), ни один другой пользователь не может изменять данные в этих таблицах.
Если внутри процедуры ОбработкаПроведения (или в вызываемых ею функциях общих модулей) программно открывается интерактивное окно, требующее реакции пользователя (например, вывод предупреждения, вопроса или модальной формы), происходит следующее:
Ситуация усугубляется при работе через терминальный сервер (особенно по технологии RemoteApp). В этом режиме модальные окна очень часто теряют фокус, сворачиваются под основное окно программы или становятся невидимыми. Пользователю кажется, что программа просто зависла, и он завершает сеанс аварийно.
Файл users.usr, расположенный в каталоге \USRDEF базы данных, содержит информацию о пользователях и их правах. Мы часто сталкиваемся с ошибкой доступа к этому файлу при попытке сохранить изменения в Конфигураторе. Эта проблема напрямую вытекает из описанного выше зависания транзакций:
1cv7.exe (или 1cv7s.exe) продолжает висеть в фоновом режиме на сервере как «зомби», удерживая открытыми файлы базы данных и дескриптор файла users.usr.users.usr на чтение/запись на короткое время. Если система зависла из-за блокировки транзакции в SQL, новые пользователи «застревают» на этапе авторизации, оставляя дескриптор файла заблокированным.*.LCK). При зависании одного сеанса блокируются файлы настроек всей системы.Для устранения этих ошибок нам потребуется провести комплексную работу: скорректировать программный код и правильно настроить системную среду.
Проанализируем программный код глобального модуля и модулей документов. Нам необходимо полностью исключить любые интерактивные вызовы из процедур проведения. Рассмотрим пример плохого кода, который гарантированно приведет к зависанию базы:
Процедура ОбработкаПроведения()
// НЕПРАВИЛЬНО: Вызов модального предупреждения внутри транзакции
Если ОстатокТовара < 0 Тогда
Предупреждение("Недостаточно товара на складе! Проведение отменено.");
СтатусВозврата(0);
Возврат;
КонецЕсли;
КонецПроцедуры
Перепишем этот алгоритм правильно. Вместо блокирующего вызова Предупреждение() задействуем неблокирующий вывод информации через метод Сообщить():
Процедура ОбработкаПроведения()
// ПРАВИЛЬНО: Вывод сообщения в окно комментариев без остановки транзакции
Если ОстатокТовара < 0 Тогда
Сообщить("Внимание! Недостаточно товара на складе. Документ не проведен!", "!");
СтатусВозврата(0);
Возврат;
КонецЕсли;
КонецПроцедуры
Если по логике бизнес-процесса обойтись без предупреждения абсолютно невозможно, мы обязаны использовать параметр таймаута (время автоматического закрытия окна в секундах). Посмотрим на пример вызова окна, которое закроется само через 3 секунды, если пользователь отошел от компьютера:
// Окно автоматически закроется через 3 секунды, не заблокировав базу данных
Предупреждение("Проведение выполнено с предупреждениями!", 3);
Если Конфигуратор уже ругается на ошибку разделения доступа, нам нужно оперативно снять блокировку с файла без перезагрузки сервера. Выполним следующие действия:
users.usr.Для автоматизации этого процесса или в случаях локальной блокировки можно использовать консольную утилиту Sysinternals Handle. Запустим командную строку от имени администратора и выполним поиск процесса, удерживающего файл:
handle.exe users.usr
Получив ID дескриптора и PID процесса, мы сможем принудительно завершить зависший сеанс 1cv7.exe.
Чтобы временные файлы пользователей не конфликтовали между собой при аварийных завершениях работы, настроим для каждого пользователя индивидуальный рабочий каталог:
\Base1C\Users\Ivanov).Для предотвращения появления «зомби»-процессов настроим автоматическое завершение неактивных сессий на терминальном сервере:
1cv7.exe, освободив все удерживаемые им файлы и таблицы СУБД.Применяя данные методы в комплексе, мы полностью избавим информационную базу 1С 7.7 от зависаний при проведении документов и обеспечим стабильную многопользовательскую работу.