Потеря данных в сессии
Давно уже задаюсь вопросом почему теряются данные в сесии и как этого избежать. Гуглил но ничего толкового не нашел.
Сессии, вроде где-то читал, что получают доступ к файлу где они хранятся атомарно, т.е. вторая сессия не должна открыться пока первая не закроется, может и не так, но даже если с файлами это не совсем понятно, с базой может быть проще.
Пример когда сессии работают не так как надо:
Допустим в сесии хранится 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
На каких то хостингах глючит да, на каких то все все ок, где то это не так критично. В любом случае никто же не обязывает пользоваться modSessionHandler, выставь стандартный обработчик сессий и все.
Проблема с любым обработчиком сессий, без привязки к modx даже, поэтому и задаю вопрос как быть?
Пробовал разные хостинги, начиная от таймвеба, заканчивая собственным дедиком, проблема как при обработке сессий по-умолчанию(файлы) так и через базу. Проблема воспроизводится на любом хостинге.
Пробовал разные хостинги, начиная от таймвеба, заканчивая собственным дедиком, проблема как при обработке сессий по-умолчанию(файлы) так и через базу. Проблема воспроизводится на любом хостинге.
А изменения через ajax?
да, конечно, в предпоследнем сообщении написал об этом, в примере рассмотрел 2 изменения, по факту может быть 10 и больше
Для ajax запроса лучше делать так
1. Запрос
2. Открываем сессию
3. Записываем в сессию.
4. Закрываем сессию session_write_close();
У меня проблем с сессиями нет.
Так и работает, чем мой пример отличается от этого?
Но если сразу 10 запросов будет, то возникнет проблема которую описал выше, но еще раз, если не понятно:
1)Возьмем modx, установленный и настроенный, например тестовый доступ можно получить по адресу minishop2.com/
2)Заходим в админку, элементы, в чанках категории у нас свернуты
3)быстро разворачиваем все категории, на сколько это возможно человеку
4)все категории развернуты как и надо
5)обновляем страницу — часть категорий все еще свернута
В чем проблема?
Скорее всего в том что одновременные запросы не дают монопольный доступ к сессии.
Если же за место 3го шага мы не быстро, а медленно развернем все категории (с интервалом в секунду-две между разворачиванием категорий), то после обновления страницы, они будут все развернуты как надо, а следовательно правильно сохранится состояние в сессии
Но если сразу 10 запросов будет, то возникнет проблема которую описал выше, но еще раз, если не понятно:
1)Возьмем modx, установленный и настроенный, например тестовый доступ можно получить по адресу minishop2.com/
2)Заходим в админку, элементы, в чанках категории у нас свернуты
3)быстро разворачиваем все категории, на сколько это возможно человеку
4)все категории развернуты как и надо
5)обновляем страницу — часть категорий все еще свернута
В чем проблема?
Скорее всего в том что одновременные запросы не дают монопольный доступ к сессии.
Если же за место 3го шага мы не быстро, а медленно развернем все категории (с интервалом в секунду-две между разворачиванием категорий), то после обновления страницы, они будут все развернуты как надо, а следовательно правильно сохранится состояние в сессии
Стоит добавить что при переносе сессии в файлы пропадет возможность доступа к чужим сессиям, это может понадобится для аналитики или чего-то подобного.
Вот меня тоже подобные выкрутасы с сессиями порядком задолбали. У вас не нашлось стабильного рецепта?
Я забил, самый лучший вариант наверное перенести их из базы в файлы, по началу, если с файлами будет работать конечно стандартный обработчик сессий, это решит проблему, а так по сути надо блокировать запись в таблице и ждать ее анлока, что неудобно и практически невозможно сделать. Или реализовать свой механизм сохранения данных аналогичный сессиям, что тоже достаточно удобно для последующего использования где либо.
Я, кстати, у себя решил вопрос. Забыл сразу отписаться)
Во-первых, оказывается был включен APC-кешер. Нахер apc. Столько с ним магии было, вспоминать страшно (как пример).
Во-вторых, оказывается у меня в одном из плагинов был редирект через
Поищите у себя — может у вас тоже где-то в коде есть подобные тонкости.
Во-первых, оказывается был включен APC-кешер. Нахер apc. Столько с ним магии было, вспоминать страшно (как пример).
Во-вторых, оказывается у меня в одном из плагинов был редирект через
header('Location: '.$url, true, 301);
Добавил перед редиректом@session_write_close();
и всё — все проблемы как рукой сняло. Просто я писал данные в сессию в другом плагине, который срабатывал раньше, чем этот, с редиректом. И без session_write_close сессия не сохранялась.Поищите у себя — может у вас тоже где-то в коде есть подобные тонкости.
И то что она проявляется только при аякс запросах которые были отправлены друг за другом. Не использовать аякс запросы или их синхронизировать не выход.Нужно учитывать, что Ajax запросы отправленные друг за другом выполняются асинхронно, и второй запросы может отработать раньше, чем первый.
То есть, логика данных в сессии может нарушаться из-за того, что второй запрос выполняется, не дожидаясь результатов работы первого.
От себя могу добавить, что использую сессии в БД всегда и везде, каких либо проблем уже давно не испытывал (с тех пор, как отключил их всякое кэширование).
Переходить на сессии в файлах не советую, это очень неудобно.
Об этом и речь, синхронизировать запросы не всегда возможно, особенно когда код раздувается и где-то бывает написано без jQuery вообще все, понятное дело что надо проектировать изначально все, но учитывая потребности и реалии заказчиков это не всегда возможно. Поэтому и интересовало можно ли получить синхронный доступ к сессиям в базе, но как оказалось это трудно и игра не стоит свеч.
Поэтому и интересовало можно ли получить синхронный доступ к сессиям в базеЭто тоже самое, как получить синхронный доступ к таблице в БД, или файлу.
Сессия — это просто массив с данными в памяти, куда можно что-то записать, а потом прочитать. Как писать и как читать решаешь ты сам.
Если у тебя одна команда выполняется раньше другой, а нужно наоборот — то вопрос не к сессиям, а к твоей логике.
важно не выполнение одной команды раньше другой, а цель выполнить все команды сразу, ну или друг за другом, не всегда синхронность на стороне юзера удобна и оправдана. Это конечно тонкости реализации, но все же удобство того что сессии синхронны некоторое есть, а так при использовании в качестве хранилища БД теряется по сути функционал который необходим.
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.