Как хранить время последней активности пользователя в MySQL?

Вопрос прост: как хранить в MySQL (MariaDB 10) последнюю активность пользователя?

Сейчас реализация такова: имеется база users, в которой хранится основная информация о пользователях (MyISAM (Aria)) и таблица action_history, где хранится последнее действие пользователя (id = primary_key = users.id), timestamp и action (enum поле по известным операциям с аккаунтом, вроде загрузки страницы или выхода из аккаунта). Сама таблица является InnoDB (XtraDB).

Ранее, когда запрос на обновление информации уходил при каждом запросе к DI к текущему юзеру это вызывало нереальные тормоза из-за постоянного обновления этой таблицы и дальнейшего ожидания её разблокировки. Сейчас эти запросы происходят только в пулах списка уведомлений и т.д., т.е. в невидимых для пользователя запросах, но тем не менее эта конструкция всё ещё является узким местом проекта.

И ещё раз повторю вопрос: как хранить время последней активности пользователя, чтобы по нему в последствии можно было выбирать пользователей?
  • Вопрос задан
  • 1201 просмотр
Пригласить эксперта
Ответы на вопрос 3
ruFelix
@ruFelix
Предсказание будущего по руке, таро, кофе.
Общее для всех mysql:
Проверить какой запрос отрабатывает система если replace то плохо если update или insert on duplicate key update - то ок.
Если в action_history есть индексы кроме примари кей то их скорее всего стоит убрать т.к. вероятно запросы ( сортировки или агрегации) по этим полям будут приводить в любом случае к фулскану и индекс не будет иметь смысла, а при апдейте перестройка будет постоянно всё класть.

Для Maria: убедиться, что в Maria XtraDB не сломана построчная блокировка (всё таки опыт продакшена у марии неё вялый ). Потом вызывает опасение реализация внешнего индекса в таблицах разного типа, возможно это как то может ломать построчную блокировку. Если у вас лок всей таблицы разберитесь откуда, так не должно быть

В общем и целом, поразмышлять что INSERT DELAYED VALUES (1,2,3),(..,..,..),(N,N,N) для записи всех действий будет работать заметно веселее особенно без индексов и в одном потоке, а после некоторых шаманств с агрегацией по крону ещё не будет деградировать от распухания. Что можно про крону парсить access.log (понимать что он не рилтайм), в этом случае будет одна пачка апдейтов допустим раз в минуту и user_id будет заапдейчен только один раз, это будет пожалуй самой простой реализацией задачи упорядочивания и фильтрации потока апдейтов к mysql. Парсинг лога можно заменить на RabbitMQ, или написать своего демона который будет висеть на соке и рулить.

Но смотрите если у вас задача в стиле показать последние 10 пользователей сделавших, что то, то это решается сильно иначе.
Ответ написан
@maxtm
Make money, not job
1) Сделайте отдельную таблицу user_last_activity (user_id, timestamp), InnoDB
2) Информацию о последней активности пишите в memcache (обновляйте не чаще раза в минуту, сверяйтесь с сессией)
3) Демоном раз минуту берите данные из memcache и вставляйте в user_last_activity
4) last_activity юзера также кэшируйте на одну минуту
Ответ написан
Комментировать
@heartdevil
плыву как воздушный шарик
Привет.

Я в этом деле тоже не компетентен, но зачем вы сразу пишите данные в базу? У вас же есть сессия? Сначала храните данные там, а на выход из аккаунта или скажем интервал бездействия в минуту или меньше, можете сливать данные из сессии в базу.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы