Сеансы PHP являются основным кандидатом для «зависания» других запросов, поскольку файл сеанса блокируется от записи, поэтому, пока один запущенный экземпляр скрипта имеет открытый сеанс, все остальные должны ждать.
Решением этого является вызов session_write_close
как можно скорее.
Немного расширенное объяснение:
Механизм хранения по умолчанию для данных сеанса - это простофайловая система.Для каждого активного сеанса PHP просто помещает файл в сконфигурированный каталог сеанса и записывает в него содержимое $ _SESSION, чтобы его можно было прочитать оттуда при следующем запросе, который должен получить к нему доступ.
Теперь, если несколько экземпляров PHP-скрипта попытались записать измененные данные сеанса в этот файл «одновременно», это, очевидно, имело бы большой потенциал конфликта / ошибки.
Поэтому PHP устанавливает блокировку записи в файле сеанса, как толькопоскольку один экземпляр сценария обращается к сеансу - всем остальным, другим запросам (к тому же сценарию или другому, также использующему сеанс), придется ждать, пока первый сценарий не будет завершен с сеансом, и блокировка записи будет снята.снова.
По умолчанию это происходит, когда скрипт завершается.Но если у вас более длинные скрипты, это может легко привести к таким «блокирующим» эффектам, которые вы испытываете здесь.Решением этой проблемы является явное указание PHP (через session_write_close
): «Я закончил сессию здесь, с этого момента я не собираюсь записывать в нее какие-либо новые / измененные данные - так что не стесняйтесь снимать блокировку, поэтомучто следующий скрипт может начать чтение данных сеанса ».
Важно то, что вы делаете это только после того, как ваш скрипт завершил манипулирование любыми данными сеанса.Вы можете все еще читать из $ _SESSION в течение остальной части сценария - но вы больше не можете писать в него.(Таким образом, что-то вроде $_SESSION['foo'] = 'bar';
может завершиться сбоем после того, как вы выпустили сеанс.)
Если единственная цель, которую сеанс выполняет в данный момент (в этом конкретном сценарии), это проверка аутентификации пользователя, то вы можетезакройте сеанс сразу после этого.Затем оставшаяся часть сценария может запускаться сколько угодно, не блокируя другим сценариям доступ к тому же сеансу.
Это не ограничивается запросами AJAX - это только один изместа, где вы обычно замечаете подобные вещи, потому что в противном случае у вас обычно не так много запросов, использующих сеанс, запущенный «параллельно».Но если бы вам приходилось открывать долго выполняющийся скрипт несколько раз на нескольких вкладках браузера, вы бы заметили тот же эффект - на первой вкладке скрипт будет работать и работать, тогда как на следующих вкладках вы должны заметить, что этизапросы также «зависают», если предыдущий экземпляр скрипта удерживает блокировку записи в сеансе.