В работе розничных магазинов на базе решения 1С:Розница 2.2 / 2.3 стабильность кассовой линейки является критически важным фактором. Любая задержка при пробитии чека на рабочем месте кассира (РМК) приводит к очередям, недовольству покупателей и прямым финансовым потерям. Одной из самых коварных технических проблем является внезапное появление ошибки: «Ошибка проведения чека. Конфликт блокировок при выполнении транзакции. Превышено время ожидания запроса на блокировку».
Особенно часто эта ситуация возникает «на ровном месте» после аварийного отключения электроэнергии, даже если в базе работает всего один кассир. В данной статье мы подробно проанализируем причины возникновения этой проблемы, разберем внутренние механизмы СУБД MS SQL Server и 1С, а также разработаем пошаговый план полного устранения и предотвращения подобных зависаний.
Рассмотрим ситуацию, когда сервер и кассы работали стабильно, но после внезапного отключения света и последующего перезапуска системы начались периодические зависания при проведении чеков. На первый взгляд кажется, что если в базе работает один кассир, конфликту блокировок взяться неоткуда. Однако аварийное завершение работы MS SQL Server под нагрузкой приводит к скрытым системным проблемам:
Index Seek) СУБД начинает выполнять полное сканирование таблиц (Table Scan). Время выполнения простейших транзакций записи чека вырастает с миллисекунд до десятков секунд или даже минут.Давайте разберем по шагам, как именно эти факторы приводят к полной блокировке работы кассы.
Чтобы понять, почему фоновый обмен блокирует проведение чеков ККМ, разберем внутреннюю логику работы СУБД. Когда 1С запускает фоновое задание синхронизации данных, система считывает и записывает изменения. В штатном режиме СУБД накладывает строчные блокировки (Row Locks) — блокируются только те конкретные строки таблиц, которые обрабатываются в данный момент. Кассир при этом спокойно проводит чеки, так как его транзакции работают с другими строками.
Но что происходит, когда из-за сбоя в очереди обмена накапливается огромный пакет данных (например, 100 000 объектов объемом 260 МБ)?
ТоварыНаСкладах, Продажи, РасчетыСКлиентами).ТоварыНаСкладах, но вся таблица уже намертво заблокирована процессом обмена.Для предотвращения подобных ситуаций необходимо правильно настроить сервер СУБД. Проанализируем две ключевые настройки, которые снижают вероятность взаимных блокировок в разы.
1. Включение режима версионирования строк (Read Committed Snapshot Isolation - RCSI)
По умолчанию в MS SQL Server операции чтения блокируются операциями записи. Если обмен записывает данные, кассир не может даже прочитать остатки по задействованным таблицам. Включение RCSI позволяет читающим транзакциям получать согласованную версию данных из базы tempdb, не дожидаясь окончания пишущих транзакций. Для включения RCSI выполним следующий SQL-скрипт:
ALTER DATABASE [ИмяВашейБазы] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
ALTER DATABASE [ИмяВашейБазы] SET READ_COMMITTED_SNAPSHOT ON;
ALTER DATABASE [ИмяВашейБазы] SET MULTI_USER;
2. Настройка параметра MAXDOP (Max Degree of Parallelism)
Для баз данных 1С крайне рекомендуется ограничивать максимальную степень параллелизма. По умолчанию параметр MAXDOP равен 0 (использовать все доступные ядра процессора для одного запроса). При «тяжелом» обмене один запрос может занять все ядра процессора, вызвав зависание всей операционной системы и взаимные внутренние блокировки (deadlocks). Рекомендуется установить значение MAXDOP = 1 (или максимум 2–4 в зависимости от архитектуры процессора, но для 1С оптимально именно 1 для предотвращения распараллеливания запросов СУБД).
Если кассы уже стоят, а сервер зациклился на попытках провести гигантский обмен, выполним следующие последовательные шаги по восстановлению работоспособности системы.
Прежде всего, необходимо прекратить текущие попытки обмена, которые блокируют таблицы. Зайдем в базу под правами администратора:
1C:Enterprise 8.3 Server Agent, если это допустимо в текущий момент времени) для принудительного завершения сеансов обмена. В крайнем случае может потребоваться перезапуск службы MS SQL Server.Чтобы исключить влияние некорректных планов запросов, возникших после отключения электричества, запустим принудительное обновление статистик. Откроем SQL Server Management Studio (SSMS), создадим новый запрос к нашей базе данных и выполним:
USE [ИмяВашейБазы];
EXEC sp_updatestats;
Эта процедура быстро обновит статистику по всем таблицам базы данных, что позволит оптимизатору строить корректные и быстрые планы запросов.
Попытка загрузить пакет в 260 МБ «в лоб» гарантированно приведет к повторному зависанию. Нам необходимо временно разгрузить очередь:
Если провести обмен жизненно необходимо, но он все же вызывает кратковременные подвисания касс, мы можем временно увеличить время ожидания блокировки, чтобы транзакции кассиров не падали по таймауту в 20 секунд, а успевали дождаться своей очереди. Для этого зайдем в Конфигуратор -> Администрирование -> Параметры информационной базы:
Чтобы избежать подобных коллизий в будущем, проанализируем и перенастроим расписание регламентных заданий:
Применяя предложенный комплекс мер, мы не только решим текущую проблему с зависанием проведения чеков ККМ, но и существенно повысим общую отказоустойчивость всей ИТ-инфраструктуры розничной точки продаж.