Работа в 1С:Предприятии 7.7 в связке с MS SQL Server часто преподносит сюрпризы, особенно когда количество одновременно работающих пользователей переваливает за десяток. Одна из самых неприятных ситуаций — сообщение о том, что таблица занята, или возникла взаимоблокировка (Deadlock), после чего в системе обнаруживаются дублирующиеся документы или элементы справочников. Разберем детально, почему это происходит и как настроить систему для стабильной работы.
Первым делом проанализируем сообщение, которое часто видят пользователи: «Транзакция (с идентификатором процесса) вызвала взаимоблокировку ресурсов с другим процессом и была выбрана в качестве жертвы». Это классический Deadlock на стороне SQL Server.
В 1С 7.7 механизмы управления блокировками реализованы достаточно «грубо» по современным меркам. Когда один пользователь начинает записывать документ, система пытается заблокировать соответствующие таблицы. Если в этот же момент другой пользователь инициирует аналогичное действие, SQL Server может зайти в тупик, не зная, кому отдать приоритет. В итоге одна из транзакций принудительно прерывается (откатывается), а пользователь получает пугающее сообщение.
Рассмотрим, почему это приводит к задвоению. Проблема часто кроется в обработке этой ошибки. Если 1С 7.7 не смогла корректно обработать откат на уровне драйвера bkend.dll, данные могут физически записаться в таблицу SQL, но клиентское приложение «считает», что запись не удалась. Пользователь нажимает «Повторить», и система создает вторую запись.
Прежде чем приступать к исправлению кода, нам необходимо выяснить: имеем ли мы дело с реальными записями в базе данных или это артефакты отображения. Проанализируем два сценария:
Разберем ситуацию с редактированием в списке. В 1С 7.7 это один из самых опасных режимов. Как показывает практика, включенный отбор в сочетании с редактированием в списке часто приводит к тому, что идентификаторы ID объектов начинают дублироваться в представлении списка, хотя в самой таблице SQL запись остается единственной.
Проанализируем программные способы предотвращения подобных коллизий. Основная задача — обеспечить корректное завершение транзакции. Если мы используем сложные доработки, важно следить за конструкциями НачатьТранзакцию() и ЗафиксироватьТранзакцию().
Посмотрим на пример правильной обработки, которая поможет избежать «зависания» транзакций при ошибках:
Процедура ВыполнитьЗапись()
НачатьТранзакцию();
Попытка
// Логика записи документа или справочника
Записать();
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
Сообщить("Ошибка при записи: " + ОписаниеОшибки());
// Здесь важно не давать пользователю просто нажимать "Повторить"
// без понимания, откатилась ли транзакция полностью
КонецПопытки;
КонецПроцедуры
Важно помнить, что в 1С 7.7 штатный механизм Попытка...Исключение не всегда перехватывает низкоуровневые ошибки SQL Server (те самые дедлоки). Поэтому научим пользователей правилу: если возникла ошибка транзакции, лучше нажать «Нет» или «Отмена», закрыть форму и проверить, не создался ли объект, прежде чем пытаться записать его снова.
Для минимизации вероятности возникновения дедлоков и последующих задвоений, проанализируем настройки серверной части:
1204 или 1222. Это позволит записывать подробную информацию о заблокированных ресурсах в лог SQL Server, что поможет программисту понять, какие именно таблицы конфликтуют.bkend.dll, которые оптимизируют работу 1С 7.7 с современными версиями SQL Server, улучшая обработку ожиданий и блокировок.1cpp.dll. Работа через прямые SQL-запросы позволяет обходить тяжеловесные стандартные механизмы блокировок 1С TABLOCKX (блокировка всей таблицы), которые и являются основной причиной дедлоков.Подведем итоги нашего исследования. Задвоение в 1С 7.7 на SQL — это симптом «усталости» стандартного движка при высокой нагрузке. Для решения проблемы мы должны действовать комплексно:
Соблюдение этих правил и глубокое понимание механики транзакций позволит значительно снизить количество ошибок и обеспечить целостность данных в вашей системе.