Проблема з deadlocks (deadlock issue) є однією з найбільших і найскладніших помилок Magento 2, з якою рано чи пізно стикається кожен розробник Magento. Коли ви почнете шукати, як вирішити проблеми з deadlocks в Magento, вам буде важко знайти хорошу інструкцію.
Отже, я припускаю, мабуть, це не перша стаття, з якою ви стикаєтеся. Але, сподіваюся, ви знайдете тут остаточну відповідь.
У цій статті ви дізнаєтеся все, що вам потрібно знати, щоб зрозуміти та вирішити проблеми з deadlocks. Або принаймні значно зменшити їх.
Зміст [приховати]
Чому індекси Magento стають недійсними?
Коли ви зіткнулися з проблемою Magento deadlock, перш за все перевірте індекси Magento та дізнайтеся, чому вони стають недійсними (invalidated). Для цього підіть у System > Tools > Index Management, переконайтеся, що ви правильно налаштували режим індексування та що ваші крони виконуються.
Режими індексування Magento
Magento має два режими індексування:
- Update on Save — реіндекс виконується під час збереження продукту (не рекомендується вмикати цей режим у production, оскільки це може значно збільшити час збереження продукту).
- Update by Schedule — реіндекс виконується cron задачами indexer_reindex_all_invalid і indexer_update_all_views.
Сторінка керування індексами в Magento з недійсними індексами
Ви також можете побачити IDLE(n) IN BACKLOG у розділі керування індексами, що означає, що індекси для (n) продуктів недійсні, і потрібно зробити реіндекс. Однак після повторного індексування всі індекси мають бути дійсними.
Сторінка керування індексами в Magento з дійсними індексами
Перевірте індексери Magento
Проведемо невеликий тест:
Змініть режим індексування на Update by Schedule і запустіть реіндекс за допомогою такої команди:
bin/magento indexer:reindex
Потім відкрийте Index Management. Усі індекси повинні мати режим Update by Shedule і IDLE - 0, як на малюнку вище.
Після цього перейдіть на будь-який продукт та збережіть його. Не потрібно змінювати значення атрибутів. Відкрийте Index Management у новій вкладці та порівняйте його з попереднім. Ви можете помітити, що деякі індекси змінилися з IDLE - 0 на IDLE - 1 (якщо ви редагували 5 продуктів, ви побачите IDLE - 5 і так далі).
Моніторте індексери Magento
Тепер, коли ви знаєте, як зробити індекс недійсним, ми повинні перейти до прикладу з реального життя.
Вам потрібно стежити за сторінкою Index Management, щоб переконатися, що всі індекси дійсні (зелені). Magento виконує задачі з реіндексу щохвилини, і якщо всі індекси дійсні, це займе не більше кількох секунд.
Як ви, напевно, знаєте, Magento зберігає дані атрибутів продукту в таблицях catalog_product_entyty_*. Ці таблиці мають тригери MySQL, які роблять індекси невалідними при зміні даних. Отже, якщо ваші індекси недійсні (червоні) щоразу, коли ви їх перевіряєте (напр, кожні 2 години), це тому, що процес повторного індексування використовує багато ресурсів і таблиць, які блокуються (get LOCKED) під час процесу.
Як ви вже здогадалися, реіндекс в цьому випадку буде не таким швидким. І саме тоді починають з’являтися проблеми Magento deadlock, проблеми зі збереженням продукту.
Таким чином, причиною, чому ваші індекси стають недійсними, є зміна значень атрибутів.
Коли виникає проблема Magento deadlock?
Припустімо, у вас є сайт із 3 представленнями магазину і приблизно 20-ма тисячами товарів, 200-ма категоріями. Повний реіндекс займе приблизно 40 хвилин.
У вас є розширення, яке динамічно оновлює атрибут is_new product за умови — якщо продукт створено (created_at ) менше 30 днів тому, позначати продукт як новий.
Розширення має cron задачу, яка оновлює атрибут щогодини. Дані оновлюються таким чином:
- Зміна значення атрибута is_new на 0 для всіх продуктів
- Пошук продуктів, створених менше ніж 30 днів тому, і задавання значення атрибута - 1
Якщо скрипт виконується щогодини, потрібно змінити дуже мало значень атрибутів. Таким чином, кількість нових продуктів, швидше за все, залишатиметься незмінною протягом декількох годин або навіть днів.
Скрипт маніпулюватиме даними (змінюватиме значення всіх атрибутів на 0, а деякі на 1), а кінцевий результат залишатиметься незмінним. Але дані були оброблені, а індекси визнані недійсними — потрібно уникати такої ситуації.
Отже, після виконання скрипту ми отримали 20 тисяч недійсних індексів.
Як ми вже згадували вище, повний реіндекс займає 40 хвилин. Якщо ваш режим індексування — Update by Schedule, Magento виконує певний реіндекс (лише для недійсних індексів), коли виконуються cron задачі indexer_reindex_all_invalid і indexer_update_all_views. Конкретний реіндекс є швидшим, ніж повний реіндекс, але також займає деякий час і створює непотрібне перевантаження бази даних.
Саме під час такого процесу повторного реіндексу з’являється проблема Magento deadlock.
Як знайти причину недійсності індексу?
Оскільки ви вже знаєте, що ваші індекси стають недійсними через зміну значень атрибутів, вам також потрібно знати, які саме значення це спричиняють. Щоб зрозуміти це, спробуйте один із наведених нижче методів.
1. Встановіть розширення Cron Manager, яке допоможе вам контролювати cron задачі.
Приклад розширення для керування кронами
2. Запустіть full reindex bin/magento ind:reind
, щоб зробити всі індекси дійсними (зеленими).
3. Збільште час існування History в Stores > Configuration > Advanced > System > Cron (Scheduled Tasks) на 1440 хв = 24 години. Це дозволить дізнатися, що відбувається на сайті впродовж 24 годин.
Примітка: за замовчуванням історія зберігається впродовж 3 годин.
Налаштування Cron (Scheduled Tasks)
4) Слідкуйте за задачами indexer_update_all_views та індексами в розділі Index Management.
Timeline - візуалізація таблиці cron_schedule
У нашому випадку задача indexer_update_all_views виконується кожні 5 хвилин і в більшості випадків час виконання становить 1 секунду — всі індекси дійсні і не перевантажують базу даних.
Ви можете помітити, що після червоного блоку виконання indexer_update_all_views займає 6 хвилин. Це означає, що деякі дії призвели до того, що деякі індекси стали недійсними. Зазвичай ви можете знайти задачі, які роблять індекси недійсними в проміжках між виконанням завдань — червоний блок.
Тепер вам потрібно з’ясувати, яка задача викликає недійсність індексу. Для цього вам потрібно виконати cron задачу, яка, як ви можете здогадатись, спричинила недійсність індексу. Не забудьте перед цим зробити reindex.
Тож ви просто виконуєте cron задачу та перевіряєте індекси. Якщо індекси стають недійсними, вам потрібно перевірити, чи розширення працює належним чином і чи потрібні будь-які зміни в даних. Ви також можете перепланувати cron задачу для виконання деяких дій у нічний час, коли ніхто не працює з адмін панеллю та трафік менший, ніж вдень.
Як вирішити проблему Magento 2 deadlock?
Якщо проблема Magento dead виникає під час збереження продукту чи іншої дії, ви можете дізнатися причину, виконавши наступні дії:
1. Відкрийте phpMyAdmin і виберіть свою базу даних.
2. Відкрийте вкладку Status і виберіть вкладку Process. Тут ви можете побачити поточні запити та час, потрібний для їх виконання.
Запущені SQL запити у phpMyAdmin
Якщо ви бачите якийсь запит, який виконується більше 1 хвилини, вам потрібно звернути на це увагу. Можливо, запит заблоковано в таблицях, і тому Magento не може зберегти продукт.
Щоб перевірити це, ви можете дочекатися завершення запиту або закрити запит (kill the query) і спробувати повторити дію, яку ви намагалися виконати (збереження продукту або будь-яка інша дія, яка не вдалася через проблему deadlock).
Примітка: закривання запитів не рекомендується для production режиму.
Перевірте налаштування бази даних
Magento рекомендує використовувати наступні налаштування бази даних для кращої продуктивності. Отже, якщо у вас виникли проблеми з deadlock в Magento, перевірте це.
Ви також можете зіткнутися з такою проблемою:
SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction, query was...
Ви можете спробувати змінити вузол блокування у вашому app/etc/env.php файлі і змінити префікс у внутрішньому вузлі налаштування.
<?php
return [
'lock' => [
'provider' => 'db',
'config' => [
'prefix' => 'new-prefix-here'
]
]
];
Потім просто скиньте індексатори (reset the indexers) та спробуйте зробити реіндекс Magento знову.
Виправлення проблеми Magento deadlock не є таким складним, як здається, якщо ви знаєте, з чого почати. Сподіваюся, ця стаття допоможе вам краще зрозуміти проблему та причини її появи.