ERPNext тормозит и медленно работает: Stock Reposting и deadlock
АйТи Фреш
Linux, Docker и DevOps

ERPNext тормозит и ловит Lock Wait Timeout: диагностика по шагам от отчётов до очереди пересчёта

Автор: , директор ООО «АйТи-Фреш» · · ~13 мин чтения
Склад как развязка: два потока грузовиков застряли в одной полосе, регулировщик отправляет часть на ночную дорогу
Deadlock — это две колонны в одной полосе, а окно пересчёта — ночная дорога.

Если ERPNext тормозит, чаще всего виноваты фоновый пересчёт склада (Repost Item Valuation), блокировки в журнале склада, тяжёлые отчёты и маленький буфер базы. За десять минут проверяют очередь воркеров, процессы MariaDB и открытые отчёты. Ниже диагностика по шагам и условный разбор компании на 35 мест.

С чего начать, если ERPNext тормозит: быстрая проверка за 10 минут

Если ERPNext тормозит, за десять минут нужно ответить на три вопроса: что сейчас делают фоновые воркеры, не упёрлась ли база в память и диск, и нет ли открытого тяжёлого отчёта. По этим трём пунктам в моей практике находится основная часть случаев, а глубокая диагностика нужна уже потом. Сначала проверяют дёшево и быстро.

Первое: очередь фоновых задач. Команда bench doctor показывает состояние планировщика и воркеров, bench show-pending-jobs выводит очереди и задачи в них. Если там сотни задач и очередь не уменьшается, система занята пересчётом, письмами или массовой обработкой, а пользователи ждут. Второе: память и диск сервера (htop, iostat) и параметр буфера базы. Третье: список активных запросов в MariaDB.

bench doctor
bench show-pending-jobs
bench --site example.com mariadb
-- внутри консоли MariaDB:
SHOW FULL PROCESSLIST;

Что смотреть в процессах MariaDB: запросы, висящие десятки секунд, состояния «Waiting for ... lock» и один и тот же запрос во многих экземплярах. Если видите длинную транзакцию по таблицам складского журнала и несколько ждущих за ней, это блокировка, и ею стоит заняться в разделе про deadlock. Если база простаивает, а страница тормозит, смотрите в сторону воркеров и сети.

Дерево решений, которое я держу перед глазами: «Request Timed Out при открытии отчёта» значит тяжёлый отчёт (Stock Balance или книга за год), лечится подготовленным отчётом или запуском вне часов. «Lock Wait Timeout Exceeded при массовой загрузке» значит параллельная запись, лечится очередью. «Deadlock при проведении складского документа» значит конфликт с пересчётом, лечится окном пересчёта. «Интерфейс виснет на большой заявке» значит много серверных вызовов при заполнении строк, лечится разбиением документа. | Симптом | Вероятная причина | Действие | |---|---|---| | Request Timed Out при открытии отчёта | тяжёлый Stock Balance или GL за год | подготовленный отчёт, запуск вне рабочих часов | | Lock Wait Timeout при массовой загрузке | параллельные записи через REST API | очередь и воркеры вместо синхронных вызовов | | Deadlock при проведении Stock Entry | пересчёт правит те же записи | окно пересчёта Limit timeslot for Stock Reposting | | Виснет форма большой заявки (сотни строк) | много серверных вызовов при заполнении строк и цен | разбить заявку, проверить на реальных объёмах |

Что такое Stock Reposting и как он съедает ресурсы по ночам и днём

Stock Reposting это автоматический пересчёт стоимости склада, и именно он чаще всего оказывается тем «тормозом», который нельзя увидеть на экране. Документ Repost Item Valuation создаётся сам, когда проводится документ задним числом или меняется цена, и затем фоновый воркер пересчитывает все последующие движения по позиции. Чем глубже дата, тем больше цепочка.

Пока пересчёт идёт, он пишет в те же таблицы (журнал склада и главная книга), с которыми работают пользователи. Поэтому днём, когда люди проводят документы, возникают конфликты: транзакции ждут друг друга. Ограничивает ситуацию настройка Stock Reposting Settings. Включите Limit timeslot for Stock Reposting, и пересчёт будет работать в заданные часы. Документация предупреждает, что глубокие записи задним числом (старше месяца) могут не уложиться во временное окно и таймаут (упоминается лимит 1500 секунд). Тот же лимит стоит у долгой очереди воркеров: по документации Frappe очереди short и default имеют таймаут 300 секунд, а long 1500.

Что делаю на практике. Во-первых, ограничиваю окно пересчёта ночью. Во-вторых, ввожу правило не проводить документы старше месяца без согласования; про бизнес-сторону метода оценки (FIFO или скользящая средняя) и проводок задним числом у меня отдельный материал, здесь разбираю только нагрузку.

В-третьих, регулярно смотрю отчёт Stock Ledger Variance Report. Он сравнивает Running Available Stock и Stock Balance с тремя фильтрами (по количеству, стоимости и ставке оценки), а выбранные строки исправляются кнопкой Create Reposting Entries. Это штатный путь исправления, а ручное редактирование записей журнала я не рекомендую.

Deadlock и Lock Wait Timeout: кто блокирует таблицу Stock Ledger Entry

Lock Wait Timeout Exceeded означает, что транзакция ждала блокировку дольше лимита (по умолчанию в MariaDB это 50 секунд, параметр innodb_lock_wait_timeout), а deadlock означает, что две транзакции ждут друг друга и база убивает одну из них. Оба случая выглядят как случайные ошибки при проведении документа, хотя причина всегда конкретная: две операции пытаются изменить одни и те же строки в разном порядке.

В ERPNext типичные пары такие: пересчёт Repost Item Valuation против пользовательского проведения; массовая загрузка через REST API против обычной работы; тяжёлый отчёт против записи. Чтобы найти виновника, воспроизводят ситуацию и смотрят состояние InnoDB.

SHOW FULL PROCESSLIST;
SHOW ENGINE INNODB STATUS\G

В разделе LATEST DETECTED DEADLOCK видно, какие два запроса столкнулись и в каких таблицах. Далее по тексту запроса определяют, это воркер пересчёта или пользовательский сеанс.

Лечение зависит от виновника. Если это пересчёт, ограничиваем окно и не проводим старые документы. Если массовая загрузка, заменяем синхронные вызовы на очередь: клиент складывает записи в очередь, воркеры обрабатывают порциями. Если это отчёт, переносим его на внерабочие часы или делаем подготовленным. Увеличивать таймаут блокировки как первый шаг я не советую: это маскирует симптом, но пользователь будет ждать ещё дольше.

Один сценарий я обязательно прогоняю на стенде до запуска: провести 50 и более складских документов одновременно, пока открыт отчёт Stock Balance. Если на вашем сервере проявятся таймауты и deadlock, то и в рабочей среде они будут. Лучше увидеть это до запуска, чем в день отгрузки.

Тяжёлые отчёты и таблицы: Stock Balance, GL за год, Error Log

Тяжёлые отчёты тормозят сильнее всего, когда их открывают в разгар рабочего дня за большой период. Stock Balance по всем складам за год и книга проводок (General Ledger) без фильтров читают миллионы строк, держат блокировки на чтение и отнимают память у воркеров. Пользователь видит Request Timed Out, а остальные видят общую медлительность.

Что работает. Во-первых, требовать фильтры по умолчанию: компания, склад, период не больше квартала. Во-вторых, для тяжёлых отчётов включать режим подготовленного отчёта (Prepared Report): он считается в фоне, а пользователь получает готовый результат. Проверьте в своей версии, для каких отчётов он доступен. В-третьих, большие выгрузки назначать на ночь.

Отдельный источник проблем: служебные таблицы. Журнал ошибок (Error Log) и глобальный поиск (таблица __global_search) растут и без чистки постепенно замедляют базу и резервное копирование. В регламенте обслуживания я закладываю регулярную очистку журналов, а размеры таблиц проверяю раз в месяц запросом к information_schema.

SELECT table_name, ROUND((data_length + index_length)/1024/1024) AS mb
FROM information_schema.tables
WHERE table_schema = DATABASE()
ORDER BY (data_length + index_length) DESC LIMIT 15;

Если по запросам видно конкретный медленный запрос, включите журнал медленных запросов MariaDB и разберите план через EXPLAIN. В вики ERPNext как пример приведён составной индекс для таблицы журнала склада. Но индексы добавляйте осторожно и с проверкой: лишний индекс замедляет запись, а добавленный руками индекс при обновлении схемы надо помнить. Для общей диагностики Linux-сервера пригодится чек-лист производительности сервера.

MariaDB и память: сколько RAM нужно и что проверить в настройках

ERPNext запускает на одном сервере MariaDB, Redis, веб-процессы Python и фоновые воркеры, и всё это конкурирует за память. Официальная документация Frappe минимального объёма памяти не называет; по моему опыту меньше 4 ГБ RAM под рабочую систему ставить не стоит, а для команды из 5 человек я беру 4–8 ГБ. Для 35 рабочих мест эту цифру считают по нагрузке, а не по таблице: пик числа одновременных пользователей, объём базы, число воркеров.

Самый влиятельный параметр базы это innodb_buffer_pool_size. Значение по умолчанию (128 МБ) слишком мало для рабочей системы. Вики ERPNext рекомендует выделять под буфер порядка 70–80 % памяти, но на сервере, где вместе с базой живут воркеры и Redis, такая доля оставит вас без памяти, и система уйдёт в своп. Я начинаю с 50–60 % от RAM на общем сервере и корректирую по метрикам. Конфигурационный файл не меняйте в основном my.cnf, который может быть перезаписан: используйте отдельный файл в каталоге conf.d.

# /etc/mysql/mariadb.conf.d/erpnext.cnf (пример, подберите под свою память)
[mysqld]
innodb_buffer_pool_size = 4G
innodb_buffer_pool_instances = 4

Что ещё проверить. Redis: кэш настраивается с политикой allkeys-lru и без записи на диск, а очередь и кэш должны быть разделены. Число веб-воркеров: по вики ERPNext формула 2 × число ядер + 1 в common_site_config.json, в современных развёртываниях проверьте актуальную рекомендацию для вашей версии. Диск: высокий Disk I/O при маленьком буфере базы — классический признак нехватки памяти для InnoDB.

Метрики, которые я смотрю после правки: свободная память и своп, загрузка диска, время ответа на типовые действия (открыть список заявок, провести приход). Меняйте по одному параметру и фиксируйте результат, иначе непонятно, что именно помогло. Про нагрузку на сервере другой системы похожий подход есть в материале про PostgreSQL и оптимизацию производительности.

Как «Дверной Мастер» разбирал зависания на 35 рабочих мест

Условный пример, данные вымышленные. «Дверной Мастер» продаёт и устанавливает двери, 35 рабочих мест: менеджеры, склад, монтажники, бухгалтерия, закупки. После трёх месяцев работы в ERPNext стали жаловаться: по утрам медленно проводятся приходы, раз в неделю падает ошибка Lock Wait Timeout, а директор не может открыть отчёт по остаткам.

Диагностика заняла полдня. bench show-pending-jobs показывал очередь Repost Item Valuation: накануне бухгалтер провёл документы за прошлый квартал, и пересчёт растянулся на сутки. В процессах MariaDB видны были длинные транзакции воркера, а рядом ждали пользовательские проведения. Буфер базы остался на значении по умолчанию, а на сервере с 16 ГБ памяти это самое слабое место. Отчёт по остаткам директор открывал на все склады и за год.

Что сделали по порядку. Включили Limit timeslot for Stock Reposting с окном ночью. Запретили проводить документы старше месяца без согласования главного бухгалтера и сдвинули Stock Frozen Up To на конец прошлого периода. Поставили innodb_buffer_pool_size 8 ГБ вместо 128 МБ. Отчёт по остаткам директору настроили с фильтром по складу и периодом на месяц, а годовой запускается ночью.

Условный итог: утренние проведения вернулись к нормальной скорости, ошибки таймаута перестали повторяться. Цифры скорости я не привожу, они измеряются на вашей системе до и после. Что осталось открытым: нагрузочное тестирование на реальных объёмах (50 одновременных проведений) сделали только через месяц, и им стоило заняться до запуска. Это урок, который я теперь закладываю в проект сразу.

Когда сервер надо делить или выносить отчёты на реплику

Делить сервер на базу и приложение, ставить реплику для отчётов и шардировать данные нужно далеко не всем, и для компании в 35 человек это скорее запас на будущее, чем первый шаг. Сначала выжимают пользу из настроек, окон пересчёта и дисциплины проводок. Дробление инфраструктуры без необходимости добавляет точки отказа и стоит сопровождения.

Признаки, что пора. Память и диск на пределе даже после настройки буфера. Тяжёлые отчёты нужны днём и не могут ждать ночи. Число одновременных пользователей и воркеров растёт, и конфликты остаются несмотря на окна пересчёта. Тогда первый разумный шаг: вынести базу на отдельный сервер, второй: реплика для отчётов только на чтение.

Что учесть заранее. Репликация добавляет задержку, и отчёт на реплике может отставать на секунды. Резервные копии придётся настраивать для двух серверов. Отказоустойчивость, мониторинг и обновление становятся задачей, у которой должен быть ответственный. Если такого человека у вас нет, это обычная услуга сопровождения.

Если вы только выбираете систему и прикидываете требования к серверу, посмотрите, как мы описываем ERPNext под ключ, и приходите на демостенд erp-demo.itfresh.ru по запросу: там можно воспроизвести массовое проведение и посмотреть очередь воркеров. Про мониторинг базы другой системы пригодится материал про мониторинг MS SQL для 1С в Zabbix: принципы мониторинга те же.

Частые вопросы

Почему ERPNext зависает при проведении складских документов?

Складские и финансовые документы параллельно пишут в журнал склада и главную книгу. Если фоновый пересчёт правит те же записи, транзакции ловят deadlock или Lock Wait Timeout. Помогает окно пересчёта Limit timeslot for Stock Reposting, запрет проводок старше месяца и очередь вместо массовой синхронной записи.

Что делает Repost Item Valuation и можно ли его отключить?

Он пересчитывает стоимость склада после проводок задним числом и изменений цены. Отключать его нельзя: стоимость и проводки станут неверными. Можно ограничить время пересчёта настройкой Limit timeslot for Stock Reposting и запускать тяжёлые ручные пересчёты вне рабочих часов, фильтруя по складу и дате.

Как найти расхождения между остатком и стоимостью склада?

Откройте Stock Ledger Variance Report: он ищет записи, где Running Available Stock и Stock Balance не совпадают, с фильтрами по количеству, стоимости и ставке оценки. Выберите проблемные строки и нажмите Create Reposting Entries, система создаст записи пересчёта пакетом.

Сколько оперативной памяти нужно ERPNext?

Официальная документация минимум RAM не называет. Система запускает MariaDB, Redis и Python-воркеры, и по моему опыту меньше 4 ГБ ставить не стоит, а для пяти пользователей разумно 4–8 ГБ. Для 35 рабочих мест считайте по нагрузке: одновременные пользователи, размер базы, воркеры и буфер innodb_buffer_pool_size.

Почему тормозит создание Purchase Order из большой заявки?

При создании заказа из заявки на материалы с сотнями строк форма делает много серверных вызовов: подставляет цены, единицы измерения и склады по каждой строке. На слабом сервере это заметные секунды ожидания. Помогает разбить заявку по поставщикам или разделам, а до запуска проверить время создания заказа на реальных объёмах своей версии.

Столкнулись с похожей задачей? Обращайтесь — решим

Если у вас происходит что-то из описанного в этой статье — или любая другая проблема с ИТ-инфраструктурой, — обращайтесь в любое время. Мои специалисты и я лично разберём ситуацию, найдём настоящую причину и доведём до решения.

Возьмёмся и за разовую задачу, и за постоянное обслуживание. Первичная консультация — бесплатно и без обязательств.

📞 +7 903 729-62-41 ✈ Telegram @ITfresh_Boss

С уважением, Семёнов Евгений Сергеевич, директор «АйТи Фреш» — IT-аутсорсинг для компаний до 50 рабочих мест, 15+ лет практики

Источники

© ООО «АйТи-Фреш» · Москва · Все статьи