phpBB.de - Die deutsche phpBB-Community
Stand: 30.12.2008 04:56
aktuelle Version auf phpBB.de
 
Apache At Work Communities Community Building Informationen und Hinweise Installation/Konfiguration/Update MySQL PHP phpBB-Optimierungen phpBB3 Rechtliches Server & Technik Snippets Templates und Mods
 



Knowledge Base Offline -> Server & Technik -> MySQL -> Fehler "phpbb_sessions is full"

Fehler "phpbb_sessions is full"
Autor: Leuchte
Stand: 30.12.2008 04:56
Neuste Version unter: http://www.phpbb.de/doku/kb/sessions

Fehler "phpbb_sessions is full"

Dieser Artikel beschreibt, was bei der Fehlermeldung "Error creating new session" zu tun ist.
Inhalt


Das Problem
Die Fehlermeldung

Bevor der Fehler behoben wird, schauen wir uns die Fehlermeldung an
Zitat:
Error creating new session

DEBUG

SQL Error : 1114 The table 'phpbb_sessions' is full

INSERT INTO phpbb_sessions (session_id, session_user_id, session_start, session_time, session_ip, session_page, session_logged_in) VALUES ('544c13e2eea831bb6402a4b35f78e96a', -1, 1041341439, 1041341439, '7f000001', 0, 0)

Was bedeutet das?? Es konnte keine neue Session erstellt werden. Eine Session sind Daten, die den Benutzer identifiziert, während er die Foren benutzt. Die Session wird für einige Dinge benötigt, beispielsweise um zu prüfen ob der Benutzer eingeloggt ist (um Befugnisse zu überprüfen, wenn eine bestimmte Seite aufgerufen wird) oder für die Wer-Ist-Online-Liste. Die Session wird an zwei Stellen gespeichert - beim Client (der Benutzer) und Serverseitig. Beim Benutzer wird die Session entweder in einem Cookie gespeichert oder im Forum an die URLs angehängt (z.B. index.php?sid=session_id). Serverseitig wird die Session in die Datenbank geschrieben (standardmässig phpbb_sessions). Und an dieser Stelle beginnt unser Problem - die Tabelle phpbb_sessions ist voll.

Was passiert

Warum passiert es an dieser Stelle? Die Störung hat nichts mit den Usern oder den eingebauten Mods zu tun. Was genau passiert, wird nun erklärt..

HEAP Tabellen

Damit man versteht warum der Fehler auftritt, sollte man wissen, warum die Session Tabelle existiert. Wenn es möglich ist, sollte die Session Tabelle den Typ HEAP, anstelle des Standards MyISAM haben. HEAP Tabellen haben gegenüber MyISAM Tabellen den Vorteil, dass sie alle Daten im Arbeitsspeicher ablegen und nicht auf der Festplatte. Dadurch sind sie schneller als MyISAM Tabellen, die alle Daten auf der Festplatte ablegen. Die einzigen Informationen die HEAP Tabellen auf der Festplatte ablegen, sind die Spalten und die Tabellendefinitionen die in einer *.frm-Datei gespeichert werden. Ein anderer wissenswerter Punkt von HEAP Tabellen ist der, dass alle Inhalte bei einem Crash oder Absturz von MySQL verloren gehen. MyISAM Tabellen dagegen behalten die Inhalte.

All diese Eigenschaften sind ideal für eine Tabelle, die temporäre Informationen abspeichern soll. Genau diese Informationen soll die Session Tabelle sichern - und das für die Sessionlänge, die im Administrationsbereich eingestellt wurde (der Standard ist eine Stunde, bzw. 3600 Sekunden).
Geht eine Zeile der Session Tabelle mit dem Typ HEAP verloren, muss sich der User lediglich neu einloggen (neue Beiträge, die zuvor nicht gelesen wurden, werden ebenfalls nicht mehr als neu angezeigt). Wird eine Zeile der User Tabelle (phpbb_users) gelöscht, so ist der Account des Users unwiederbringlich weg, was wohl schwerwiegender ist.

Obwohl das Löschen einer Zeile den gleichen Effekt bei beiden Typen von Tabellen hat (enthaltene Daten sind unwiederbringlich gelöscht), ist das Löschen einer Session weitaus weniger schwerwiegend, da die Session nur temporär und jederzeit wiederherstellbar ist.

HEAP ist ein Feature welches mit der MySQL Version 3.23.0 eingeführt wurde. Wird eine frühere Version genutzt, ist der Tabellentyp automatisch MyISAM. Trotz aller Differenzen zwischen MyISAM und HEAP, die Tabellen haben keine wahrnehmbaren Unterschiede, ausser das sie möglicherweise ein wenig langsamer sind.

Nützlicher Link: MySQL: HEAP Tabellen - Dokumentation zu MySQLs HEAP Tabellentyp

Warum ist die Tabelle voll

Um zu verhindern, dass HEAP Tabellen den kompletten Speicher nutzen, weil sie zuviele Zeilen aufnehmen, begrenzt man diese mit MAX_ROWS. Diese Begrenzung ist eine Zahl, die die Höchstzahl der Zeilen darstellt, die die Tabelle haben kann. Der Standard-Wert von MAX_ROWS schwankt von Server zu Server, ist aber meistens 550. Das heißt, dass, wenn eine Zeile (ein neuer Eintrag) in die Session Tabelle geschrieben werden soll und diese bereits 550 Zeilen enthält, die Tabelle einen Fehler ausgibt.

Es ist eine Sicherheitseinstellung, die verhindern soll, dass der komplette Speicher genutzt wird, wenn keine oder zu hohe MAX_ROWS gesetzt werden. Es kann keine HEAP Tabellen erstellt werden, die mehr MAX_ROWS angibt, als die interne MySQL Variable max_heap_table_size vorgibt. In den Versionen vor MySQL 3.23.2 wurde die "table is full" Meldung ausgegeben, wenn die HEAP Tabelle die Größe der Variable tmp_table_size überstieg. In neueren Versionen wird bei Überschreiten die Tabelle automatisch zu MyISAM konvertiert, wenn sie die Größe von tmp_table_size erreicht.
Es kann also MAX_ROWS oder tmp_table_size genutzt werden, um die Tabellengröße zu begrenzen. Üblich verursacht aber die Größe von MAX_ROWS den Fehler.

Nützlicher Link: MySQL: Table is full-Fehler - mögliche Gründe die diesen Fehler verursachen

"Session-Flooding"

Weil die Session Tabelle nicht automatisch geleert wird, können Ausgaben mit 'session flooding' vorkommen. Wenn ein Benutzer den Forum-Index aufruft, wird eine session_id erstellt, und eine neue Zeile wird in die Session Tabelle geschrieben. Ruft der Benutzer nun eine andere Seite auf (Mitgliederliste, ein Forum, oder was auch immer) ist die sessionid die selbe, die auf dem Index erstellt wurde und es muss keine neue Session in die Tabelle eingetragen werden. Ruft der Benutzer aber wieder den Index auf, ohne das die vorhandene Session genutzt wird, muss eine neue Session erstellt und somit auch in die Tabelle geschrieben werden. Das passiert, wenn der Browser des Users keine Cookies akzeptiert oder die Session-ID nicht an die URL anghängt wird (z.B. index.php?sid=session_id). Wenn die Session-ID nicht mehr an die URL angehangen wird, veraltet die session_id in der Datenbank und ist nicht mehr gültig. Sie existiert aber weiterhin und somit befinden sich mehrere session_ids des selben Users in der Datenbank, was diese weiter auffüllt. Passiert das öfter, wird bald die Grenze der MAX_ROWS erreicht und eine Fehlermeldung ausgegeben.

Wenn die Session Tabelle voll ist heisst das nicht, dass jemand das Forum angreift oder böswillig die Tabelle füllt. Es reicht schon aus, wenn eine Suchmaschine die Seite spidert und die Session-IDs entfernt und somit neue Sessions erstellt.

Die Lösung
Welche Lösung verwenden

Achtung: Bevor irgendeine der aufgelisteten Aktionen gelesen und durchgeführt werden, sollte dieser Abschnitt gelesen werden, der erklärt, welche der genannten Lösungen zu empfehlen ist.
Es ist auch wichtig, ein Backup der Datenbank (oder zumindest von der Tabelle phpbb_sessions) und der phpBB Daten (oder zumindest includes/sessions.php) durchzuführen!

Es gibt verschiedene Möglichkeiten den Fehler zu beheben. Jede entspricht einer anderen Situation. Als erstes sollte das Script zum "automatischen Leeren der Session Tabelle" genutzt werden. Wenn das nicht funktioniert, muss versucht werden, die Tabelle manuell zu leeren.
Wenn sich die Tabelle zu schnell füllt, muss versucht werden, die Sessionlänge einer IP zu begrenzen oder die MAX_ROWS der Tabelle zu erhöhen. Wenn alles nicht wirkt, kann die Session Tabelle in MyISAM konvertiert werden.

Tabelle automatisch leeren

Dieses Script sollte als erstes probiert werden, da es sogut wie immer funktioniert. Der Dank geht an den Script-Autor Ashe und morpheus2matrix.
Dazu muss die Datei includes/sessions.php geöffnet werden und folgende Codes bearbeitet werden (Zeile 152).
Code:
message_die(CRITICAL_ERROR, 'Error creating new session', '', __LINE__, __FILE__, $sql);
Dieser Code muss mit folgendem ersetzt werden.
Code:
$error = TRUE;
if (SQL_LAYER == "mysql" || SQL_LAYER == "mysql4")
{
    $sql_error = $db->sql_error($result);
    if ($sql_error["code"] == 1114)
    {
        $result = $db->sql_query('SHOW TABLE STATUS LIKE "'.SESSIONS_TABLE.'"');
        $row = $db->sql_fetchrow($result);
        if ($row["Type"] == "HEAP" || $row["Engine"] == "MEMORY")
        {
            if ($row["Rows"] > 2500)
            {
                $delete_order = (SQL_LAYER=="mysql4") ? " ORDER BY session_time ASC" : "";
                $db->sql_query("DELETE QUICK FROM ".SESSIONS_TABLE."$delete_order LIMIT 50");
            }
            else
            {
                $db->sql_query("ALTER TABLE ".SESSIONS_TABLE." MAX_ROWS=".($row["Rows"]+50));
            }
            if ($db->sql_query($sql))
            {
                $error = FALSE;
            }
        }
    }
}
if ($error)
{
    message_die(CRITICAL_ERROR, "Error creating new session", "", __LINE__, __FILE__, $sql);
}
Dieses Script löscht die ältesten 50 Zeilen (die nicht mehr genutzt werden) der Session Tabelle, wenn dort mehr als 2500 Zeilen existieren. Gibt es weniger als 2500 Zeilen in der Tabelle, werden 50 Zeilen den MAX_ROWS hinzugefügt. Das bedeutet im allgemeinen, dass die Kapazität der Tabelle immer größer und größer wird, bis die maximale Anzahl von 2500 Zeilen erreicht ist. Ab dann wird die Kapazität nicht mehr erhöht, sondern die ältesten und ungenutzten 50 Session-Zeilen gelöscht.

Tabelle manuell leeren

Mit dieser Aktion werden alle Zeilen der Session Tabelle gelöscht. Das löst das Problem, aber muss immer gemacht werden, wenn die Tabelle vollständig gefüllt ist. Diese Variante benötigt ein Datenbank-Administrations-Tool wie z.B. phpMyAdmin oder Kommandozeilen-Zugang. Auch hier sollte die Datenbank zuvor gesichert werden.

...benutze phpMyAdmin

Dazu muss phpMyAdmin im Browser aufgerufen und mit dem Usernamen und Passwort eingeloggt werden. Im linken Frame muss die von phpBB genutzte Datenbank ausgewählt werden. In der Strukturansicht findet sich nun im Hauptframe eine Übersicht aller Tabellen. Jetzt muss zur Session Tabelle (standard phpbb_sessions) heruntergescrollt werden. Auf der rechten Seite finden sich ein paar Links. Hier muss auf den Link 'Leeren' geklickt werden. Eine Pop-Up-Box springt hervor mit der Abfrage:[quote="phpMyAdmin"]Soll diese Abfrage ausgeführt werden: DELETE FROM `phpbb_sessions`[/quote]Diese Abfrage ist zur Sicherheit, dass nicht eine falsche Tabelle geleert wird. Wurde eine falsche ausgewählt, muss hier Nein/Abbrechen geklickt werden. Ansonsten wird mit OK bestätigt.

...benutze eine SQL-Query

Um die Tabelle zu leeren, muss folgende Query ausgeführt werden
Code:
DELETE FROM phpbb_sessions;
Hier muss sichergestellt sein, dass der Prefix (phpbb_ ) korrekt angepasst wird.

Die Anzahl der Sessions pro IP begrenzen

Wenn Probleme bekannt sind, dass für einen User zuviele Session erstellt werden, sollte die Variante bevorzugt werden.
Der Dank geht an den Autor R45.
Hier muss wieder die Datei includes/sessions.php bearbeitet werden (Zeile 136-145):
Code:
    //
    // Create or update the session
    //
    $sql = "UPDATE " . SESSIONS_TABLE . "
        SET session_user_id = $user_id, session_start = $current_time, session_time = $current_time, session_page = $page_id, session_logged_in = $login
        WHERE session_id = '" . $session_id . "'
            AND session_ip = '$user_ip'";
    if ( !$db->sql_query($sql) || !$db->sql_affectedrows() )
    {
        $session_id = md5(uniqid($user_ip));
Nach diesem Abschnitt muss folgender Code eingefügt werden (AFTER, ADD)
Code:
        $sql = "SELECT COUNT(*) as numrows FROM ". SESSIONS_TABLE ." WHERE session_ip = '$user_ip'";
        $result = $db->sql_query($sql);
        if ( !$result )
        {
            message_die(CRITICAL_ERROR, 'Error checking existing sessions', '', __LINE__, __FILE__, $sql);
        }
       
        $numrows = $db->sql_fetchrow($result);
        if($numrows['numrows'] > 4)
        {
            $delete_limit = $numrows['numrows'] - 4;
            switch( SQL_LAYER )
            {
                case 'mysql4':
                    $sql = "DELETE FROM ". SESSIONS_TABLE ." WHERE session_ip = '$user_ip' ORDER BY session_start ASC LIMIT $delete_limit";
                    break;
                default:
                    $sql = "SELECT session_start FROM ". SESSIONS_TABLE ." WHERE session_ip = '$user_ip' ORDER BY session_start DESC LIMIT 4";
                    $result = $db->sql_query($sql);
                   
                    if ( !$db->sql_query($sql) )
                    {
                        message_die(CRITICAL_ERROR, 'Error select session data', '', __LINE__, __FILE__, $sql);
                    }
                   
                    $session_rows = $db->sql_fetchrowset($result);
                   
                    $sql = "DELETE FROM ". SESSIONS_TABLE ." WHERE session_ip = '$user_ip' AND session_start < ".$session_rows[3]['session_start'];
            }
                   
            if ( !$db->sql_query($sql) )
            {
                message_die(CRITICAL_ERROR, 'Error deleting old sessions', '', __LINE__, __FILE__, $sql);
            }
        }
Dieses Script prüft, wieviele Session für einen User bereits existieren. Wenn 5 oder mehr in der Tabelle stehen, wird die älteste Session gelöscht (oder mehrere, je nach MySQL Version und wieviele Sessions bereits existieren) die zu einem User gehören, um so Platz für neue Sessions zu schaffen.

Um den Wert, wieviele Sessions pro IP erlaubt sind, zu ändern, kann die farbig markierte Ziffer in der Datei includes/sessions.php angepasst werden

Zitat:
if($numrows['numrows'] > 4)

Sollen beispielsweise die Sessions erst gelöscht werden, wenn mehr als zehn Sessions für einen User existieren, muss folgender Code verwendet werden
Zitat:
if($numrows['numrows'] > 10)


Es ist zu beachten, dass diese Vorgehensweise nicht zu empfehlen ist, wenn mehrere User hinter einem Proxy das Forum besuchen. Wenn 20 User hinter einem Proxy zur gleichen Zeit die Foren nutzen, wird die Anzahl der erlaubten Benutzer begrenzt, nicht die Verbindungen die ein User erstellt.

Im kommenden phpBB Release 2.2 wird es einen Code geben, der die Anzahl der Session in einer 60-Sekunden-Periode begrenzt.

Die MAX_ROWS der Tabelle erhöhen

Die MAX_ROWs für die Tabelle zu erhöhen, ist nicht wirklich eine Lösung. Es erhöht lediglich die Kapazität der Tabelle und schafft somit mehr Platz für zusätzliche Session-Zeilen.

...benutze phpMyAdmin

Dazu muss phpMyAdmin im Browser aufgerufen und mit dem Usernamen und Passwort eingeloggt werden. Im linken Frame muss die von phpBB genutzte Datenbank ausgewählt werden. Im Hauptframe findet sich nun der Tab 'SQL'. In diese Box wird folgende Query eingegeben:
Zitat:
ALTER TABLE phpbb_sessions MAX_ROWS = 2500;

Der Wert 2500 kann nach eigenen Ermessen angepasst werden. Die MySQL Variable max_heap_table_size schützt davor, dass eine zu große Tabelle angelegt wird. Danach muss wieder mit OK bestätigt werden. Auch hier muss sichergestellt sein, dass der Prefix (phpbb_ ) korrekt angepasst wird.

...benutze eine SQL-Query

Um die MAX_ROWs zu erhöhen muss folgende Query verwendet werden:
Zitat:
ALTER TABLE phpbb_sessions MAX_ROWS = 2500;

Auch hier kann der Wert 2500 kann nach eigenen Ermessen angepasst werden. Die MySQL Variable max_heap_table_size schützt davor, dass eine zu große Tabelle angelegt wird. Danach muss wieder mit OK bestätigt werden. Auch hier muss sichergestellt sein, dass der Prefix (phpbb_ ) korrekt angepasst wird.

Den Tabellentyp auf MyISAM ändern

Das ist die letzte Möglichkeit, wenn die Tabelle voll ist und die anderen Varianten nicht funktionieren. Es gibt keine größeren Unterschiede zwischen MyISAM und HEAP Tabellen, ausser das MyISAM Tabellen ein wenig langsamer sind. Für weitere Informationen, sollte der Abschnitt HEAP Tabellen gelesen werden.

...benutze phpMyAdmin

Dazu muss phpMyAdmin im Browser aufgerufen und mit dem Usernamen und Passwort eingeloggt werden. Im linken Frame muss die von phpBB genutzte Datenbank ausgewählt werden. Im Hauptframe muss nun zur Session Tabelle (Standard ist phpbb_session) herunter gescrollt werden. Dort findet sich der Link 'Eigenschaften'. Im oberen Bereich des Frames findet sich nun ein neuer Tab 'Optionen' zu dem wir wechseln.
In den Optionen gibt es das Feld Tabellentyp mit der gewählten Option HEAP. Dort wird jetzt MyISAM ausgewählt und mit OK bestätigt.

...benutze eine SQL-Query

Um die Session Tabelle zu MyISAM zu konvertieren, wird folgende Query genutzt:
Code:
ALTER TABLE phpbb_sessions TYPE = MYISAM;
Hier muss sichergestellt sein, dass der Prefix (phpbb_ ) korrekt angepasst wird.


Das Original dieses Artikels findet sich hier:
http://www.phpbb.com/kb/article.php?article_id=42

Nützlicher Beitrag dazu:
http://www.phpbb.de/viewtopic.php?t=78166



Knowledge Base Offline -> Server & Technik -> MySQL -> Fehler "phpbb_sessions is full"