Потеря данных в сессии
Давно уже задаюсь вопросом почему теряются данные в сесии и как этого избежать. Гуглил но ничего толкового не нашел.
Сессии, вроде где-то читал, что получают доступ к файлу где они хранятся атомарно, т.е. вторая сессия не должна открыться пока первая не закроется, может и не так, но даже если с файлами это не совсем понятно, с базой может быть проще.
Пример когда сессии работают не так как надо:
Допустим в сесии хранится 2 переменных temp1 и temp2 и они равны нулю.
Первый запрос установит перменную temp1 в 1
Второй запрос установит перменную temp2 в 2
Третьим запросом проверяем состаяние выходит:
Модкс хранит сессии в базе, если брать пример относящийся к системе:
1)Пользователь сворачивает/разворачивает категории в дереве друг за другом, обновляет страницу, и видит что категории которые он сворачивал — все еще не свернуты
2)Пользователь зашел в корзину минишопа и удаляет все товары из нее (допустим их там было 5) нажимая на крестик справа в таблице, в итоге после того как прощелкал все товары, они визуально удалились, но после обновления корзины осталось 2 товара
Примерно, этот случай выглядит как мне кажется следующим образом:
Пользователь отправляет первый запрос на изменение переменной temp1 в 1 и после отправляет запрос на изменение переменной temp2 в 2
Ответа от сервера к примеру нет, просто идет запись переменных.
В результате второй запрос открывает сессию до того как первый запрос успел записать в нее первое значение и в итоге в нашей сессии сохраняется только второе значение.
Вопрос прост: как этого избежать и возможно ли, именно при работе с сессиями?
Забыл написать что проблема актуальна в общем, с работой сессий, без привязки к движку, просто в качестве примера взят modx. И то что она проявляется только при аякс запросах которые были отправлены друг за другом. Не использовать аякс запросы или их синхронизировать не выход.
P.S. Можно записать 2 значения в 2 разных поля базы, но не удобно хранить целый набор значений таким образом.
Сессии, вроде где-то читал, что получают доступ к файлу где они хранятся атомарно, т.е. вторая сессия не должна открыться пока первая не закроется, может и не так, но даже если с файлами это не совсем понятно, с базой может быть проще.
Пример когда сессии работают не так как надо:
Допустим в сесии хранится 2 переменных temp1 и temp2 и они равны нулю.
Первый запрос установит перменную temp1 в 1
Второй запрос установит перменную temp2 в 2
Третьим запросом проверяем состаяние выходит:
temp1=0
temp2=2Но как же так?Модкс хранит сессии в базе, если брать пример относящийся к системе:
1)Пользователь сворачивает/разворачивает категории в дереве друг за другом, обновляет страницу, и видит что категории которые он сворачивал — все еще не свернуты
2)Пользователь зашел в корзину минишопа и удаляет все товары из нее (допустим их там было 5) нажимая на крестик справа в таблице, в итоге после того как прощелкал все товары, они визуально удалились, но после обновления корзины осталось 2 товара
Примерно, этот случай выглядит как мне кажется следующим образом:
Пользователь отправляет первый запрос на изменение переменной temp1 в 1 и после отправляет запрос на изменение переменной temp2 в 2
12>Запрос temp1
1234>открываем сессию
123456>temp1=1
12345678>записываем сессию
1234>Запрос temp2
123456>открываем сессию
12345678>temp2=2
1234567890>записываем сессиюЦифрами обозначил тут как бы единицу времени, можно сказать тайминг просто для наглядности.Ответа от сервера к примеру нет, просто идет запись переменных.
В результате второй запрос открывает сессию до того как первый запрос успел записать в нее первое значение и в итоге в нашей сессии сохраняется только второе значение.
Вопрос прост: как этого избежать и возможно ли, именно при работе с сессиями?
Забыл написать что проблема актуальна в общем, с работой сессий, без привязки к движку, просто в качестве примера взят modx. И то что она проявляется только при аякс запросах которые были отправлены друг за другом. Не использовать аякс запросы или их синхронизировать не выход.
P.S. Можно записать 2 значения в 2 разных поля базы, но не удобно хранить целый набор значений таким образом.
Комментарии: 14
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
Пробовал разные хостинги, начиная от таймвеба, заканчивая собственным дедиком, проблема как при обработке сессий по-умолчанию(файлы) так и через базу. Проблема воспроизводится на любом хостинге.
У меня проблем с сессиями нет.
Но если сразу 10 запросов будет, то возникнет проблема которую описал выше, но еще раз, если не понятно:
1)Возьмем modx, установленный и настроенный, например тестовый доступ можно получить по адресу minishop2.com/
2)Заходим в админку, элементы, в чанках категории у нас свернуты
3)быстро разворачиваем все категории, на сколько это возможно человеку
4)все категории развернуты как и надо
5)обновляем страницу — часть категорий все еще свернута
В чем проблема?
Скорее всего в том что одновременные запросы не дают монопольный доступ к сессии.
Если же за место 3го шага мы не быстро, а медленно развернем все категории (с интервалом в секунду-две между разворачиванием категорий), то после обновления страницы, они будут все развернуты как надо, а следовательно правильно сохранится состояние в сессии
Во-первых, оказывается был включен APC-кешер. Нахер apc. Столько с ним магии было, вспоминать страшно (как пример).
Во-вторых, оказывается у меня в одном из плагинов был редирект через
Добавил перед редиректом
и всё — все проблемы как рукой сняло. Просто я писал данные в сессию в другом плагине, который срабатывал раньше, чем этот, с редиректом. И без session_write_close сессия не сохранялась.
Поищите у себя — может у вас тоже где-то в коде есть подобные тонкости.
То есть, логика данных в сессии может нарушаться из-за того, что второй запрос выполняется, не дожидаясь результатов работы первого.
От себя могу добавить, что использую сессии в БД всегда и везде, каких либо проблем уже давно не испытывал (с тех пор, как отключил их всякое кэширование).
Переходить на сессии в файлах не советую, это очень неудобно.
Сессия — это просто массив с данными в памяти, куда можно что-то записать, а потом прочитать. Как писать и как читать решаешь ты сам.
Если у тебя одна команда выполняется раньше другой, а нужно наоборот — то вопрос не к сессиям, а к твоей логике.