Проблема вызвана блокировкой, установленной обработчиком сеанса PHP. Так что это не Magento, явно блокирующее что-то и пытающееся блокировать запросы администратора, а почти побочный эффект как такового хранения файловых сеансов.
Блокировка записи помещаются в файл данных сессии , когда он открыт начальным (долгоиграющий) запрос, в результате чего второго запроса к блоку , пока блокировка не будет снята , когда она вызывает session_start
вMage_Core_Model_Session_Abstract_Varien::start
Это на 100% воспроизводимо. Я использовал тот же метод, что и вы, добавив sleep(30)
в началоMage_Adminhtml_IndexController::globalSearchAction
Стоит отметить, что это не может быть воспроизведено, если вы используете хранилище сеансов БД. После того, как я нашел основную причину, я установил «песочницу» в хранилище сеансов db и больше не мог воспроизвести проблему. Таким образом, обработчики сеансов db, которые Magento имеет, по-видимому, не используют блокировку на уровне строк для блокировки записи сеансов. Я нахожу это интересным, поскольку он может привести к потере данных сеанса, поскольку приложение, очевидно, не учитывает запись нескольких потоков в один и тот же сеанс. Примечание для читателей: я бы никогда не использовал хранилище сеансов в базе данных, чтобы попытаться решить эту проблему, это хорошо только для перегрузки базы данных MySql.
Я не пытался воспроизвести поведение, используя системы хранения сессий на основе памяти, такие как Redis, но я предполагаю, что блокировка записей в хранилище сессий, вероятно, также игнорировалась.
Чтобы избежать этого, можно использовать методы, такие как session_write_close
снятие блокировки перед началом длительной работы. Но это также помешает вам писать в сеанс, так как вы только что закрыли его. Таким образом, он вряд ли будет легко реализован в Magento, но потенциально может быть реализован на определенных маршрутах / контроллерах.
Моя методика закрепления этого как основной причины состояла в том, чтобы включить профилировщик Xdebug и проверить файл «cachegrind». По завершении второго запроса я загрузил выходной файл (журнал ~ 25 МБ) в MacCallGrind и углубился в трассировку, следуя пути вызовов, где время включения составляло 28 секунд или больше. В конечном итоге это привело меня к session_start
вызову, который занял ~ 28 секунд, что дало мне отличную возможность для исследования.
РЕДАКТИРОВАТЬ: Для заинтересованных, я опубликовал скриншот файла «cachegrind», который просматривается в MacCallGrind в Twitter.