Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Śledzenie zalogowanych
Forum PHP.pl > Forum > Bazy danych > MySQL
voytass
czesc

robie sledzenie zalogowanych uzytkownikow.
zrobilem tabele do skladowanua danych ze sledzenia, sklada sie ona z pol:
1. identyfikator sesji [sid]
2. identyfikator uzytkownika [uzkid]
3. IP uzytkownika [ip]
4. data [data]
5. strona odwiedzana przez uzytkowniika [str]

i chcialbym wysweitlac wszystkich uzytkonikow, ktorzy byli 'czynni' przez ostatnie 5 min.

mam wiec zapytanie:

  1. SELECT uzkid, DATA, ip, sid
  2. FROM track WHERE DATA > NOW() - INTERVAL 5 MINUTE GROUP BY uzkid ORDER BY DATA DESC LIMIT 0 ,$ile


no i nie otrzymuje tego co chce, poniewaz:
1. wiadomo, ze jeden uzytkownik bedzie mial duzo rekordow w tej tabeli wiec dlatego group ale chce by wybieral taki wiersz z danym ip, uzkid uzytkownika dla ktorego data jest najwyzsza (teraz niestety tak nie jest - tak jaby nie dzialalo ORDER BY data DESC) pojawia sie najnizsza data.
2. czy w ogole dobrze sie do tego zabralem - czy jest jakies lepsze rozwiazanie koncepcji sledzenia zuytkownika
3. co zrobic z tymi rekordami , ktore sa starsze od NOW() - INTERVAL 5 MINUTE? chcialbym je jakos skasowac? musze np. w crona dorzucicc odpowiednie skrypty?

pozdrawiam,
janek
1. Nie wiem jaką masz konstrukcję sesji, ale jeden użytkownik powinien mieć jeden rekord w bazie. Przy przejściu do kolejnej strony robisz update tego rekordu, zmieniając czas i zmienne sesji (jeżeli potrzeba). Dzięki temu nie potrzebujesz group by.

2. Pomysł jest ok, sam stosowałem i działa do dzisiaj, ale przy założeniu że masz jeden rekord dla jednego uzyt - jak pisałem wyżej.

3. A nie czyści Ci jej funkcja odpowiedzialna za odśmiecanie sesji?

Jeżeli (tak jak piszesz) chcesz kasować wpisy starsze niż 5 min to najpierw napisz zapytanie delete, które to zrobi, a potem po prostu
  1. SELECT count(*)
  2. FROM track
i już wiesz ile osób było u Ciebie w ciągu ostatnich 5 min.
popo
Nie jestem pewien czy dobrze mi sie kojarzy ale sprobuj dac order by DATA asc
Prosciej jednakrze byloby modyfikowac rekord istniejacego juz w bazie usera
np. najpierw szukasz czy masz dane o tym userze czyli robisz selecta po username
  1. SELECT count(*)
  2. FROM track WHERE uzkid = %uzkid AND sid = %sid AND ip = %ip

jesli bedzie wieksze od zera to modyfikujesz rekord ktory zwrocilo czyli update przy identycznych warunkach w klauzuli where jesli zwroci 0 dodajesz nowy.
Co do kasowania rekordow to mozna to z poziomu php zrobic
  1. DELETE
  2. FROM `track` WHERE DATA < NOW() - INTERVAL 5 MINUTE

Wykonujesz takie zapytanie na poczatku skryptu wyswietlajacego strone i po klopocie. Rekordy zostana skasowane zanim nastepne zapytanie zacznie je wyswietlac, czyli uzytkownik zobaczy tylko aktualne wpisy. Kiedy ktos znowu wywola strone stare wpisy zostana usuniete snitch.gif
Mozna tez dodac to zapytanie przed zapytaniem dodajacym usera do bazy track, wtedy automatycznie najpierw bedziemy kasowac stare wpisy a potem dodawac nowe. Jeszcze lepszym rozwiazaniem moze byc najpierw dodawac nowe / modyfikowac istniejace rekordy, a potem usuwac stare (przy modyfikacji jest chyba mniejsze obciazenie bazy chyba niz jak kasujesz rekord i za chwile dodajesz nowy)

Zastosowanie tego rozwiazania ma jednak pewien minus (generuje wieksze obciazenie bazy niz wywolana z crona raz na minute komenda sqla w sytuacjach kiedy twoj serwis jest popularny) wiec w zaleznosci od sytuacji trzeba rozwazyc co berdzie lepsze cron czy kasowanie z poziomu php
janek
Cytat(popo @ 2005-07-25 22:13:45)
Prosciej jednakrze byloby modyfikowac rekord istniejacego juz w bazie usera
np. najpierw szukasz czy masz dane o tym userze czyli robisz selecta po username
  1. SELECT count(*)
  2.  
  3. FROM track WHERE uzkid = %uzkid AND sid = %sid AND ip = %ip

jesli bedzie wieksze od zera to modyfikujesz rekord ktory zwrocilo czyli update przy identycznych warunkach w klauzuli where jesli zwroci 0 dodajesz nowy.

Mam trochę inny pomysł.
mozna by zrobić od razu update, z pominięciem select. Funkcją mysql_affected_rows można by sprawdzić czy jakiś rekord został uaktualniony

możliwość a ) jeżeli mysql_affected_rows > 0 to sesja już trwa (bo jakiś wiersz został uaktualniony)
możliwość b ) jeżeli mysql_affected_rows ==0 to rozpoczynamy nową sesję.

Zaleta: jeżeli sesja użytkownika już trwa, sprawdzenie tego i zminana czasu ostatniego odświeżenia strony wymaga jednego zapytania, nie dwóch

Wada: jeżeli sesja trwa (czyli rekord w bazie istnieje) a strona zostanie przeładowana dwa razy w tej samej sekundzie, to za drugim razem update nie ma czego nadpisać (nie ma żadnych nowych danych) i mysql_affected_rows zwróci 0, mimo tego że rekord sesji istnieje. Można by to rozwiązać dodaniem kolumny przechowującej np. miliskundy ostatniego update, mając pewność że ta wartość zawsze się będzie zmieniać czyli update zawsze ją nadpisze jeżeli tylko będzie odpowiedni rekord w bazie i to zapewni właściwe dla skryptu dane z mysql_affected_rows

Brzmi pięknie, ale własnie oglądałem książkowy przykład funkcji obsługi sesji i tam są jednak dwa zapytania, select a potem update. Nie mogę znaleźć słabego punktu mojego pomysłu "oszczędzającego" jedno zapytanie. Moze Wy go widzicie?
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.