Viele Leute haben mir gesagt, die UserId in der Session-Tabelle zu speichern wäre der falsche Ansatz. Unsauber, nicht den Normalformen entsprechend, usw. Sie empfehlen ein Feld is_online zur Tabelle users hinzuzufügen. Ich bin anderer Meinung.

Abgelaufene Sessions

Sessions sind etwas flüchtiges. Wenn ein Benutzer auf unsere Seite kommt bekommt er ein Cookie mit seiner SessionId. Er loggt sich ein und wir speichern seine UserId in der Session-Tabelle – damit wird er als online angezeigt. Er surft etwas auf unserer Seite bis es ihm zu langweilig wird. Dann schließt er seinen Browser und das Expiration-Handling unserer Sessions löscht irgendwann seine Session aus der Tabelle. Damit wird er wieder als offline angezeigt.

Merken wir uns den Online-Status der Benutzer über ein Feld in der Tabelle users, müssen wir das Expiration-Handling doppelt machen. Dass heißt im Klartext das Feld is_online durch last_activity zu ersetzen welches den Zeitpunkt des letzten Zugriffs speichert. Dieses Feld müssen wir nun bei jedem Request aktualisieren.

Schreiben und Lesen geht nicht gleichzeitig

Für unsere „Wer ist online?“-Anzeige fragen wir bei jedem Request die Datenbank, welche Benutzer gerade online sind. Dazu kommen noch weitere lesende Abfragen weil wir z.B. Kommentare der Benutzer anzeigen und dafür den Benutzernamen oder andere Daten aus der User-Tabelle brauchen. Wahrscheinlich werden wir die User-Tabelle ziemlich häufig abfragen müssen für unsere tolle „Web 2.0 (beta!)“-Anwendung – schließlich ist der User bei user generated content ziemlich wichtig. Falls wir uns den Online-Status über die Tabelle users merken, kommt dazu auch noch jeweils ein schreibender Zugriff auf den Benutzer pro Request. Bei 5 Usern geht das bestimmt super. Bei 50 auch. Bei 500, 5000 oder 50000 sicherlich nicht mehr. Schreiben dauert, denn es muss alles gleich direkt auf die Festplatte geschrieben werden. Lesen würde eigentlich ganz schnell gehen, unser dicker Datenbank-Server hat hoffentlich genug RAM um viel zu cachen. Nur leider werden die Zeilen(InnoDB) bzw. die ganze Tabelle(MyISAM) für Schreibvorgänge gelockt.