sqlite3 crasht Server

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
Brainsucker
User
Beiträge: 68
Registriert: Mittwoch 16. November 2011, 23:20

Hallo Leute,


Habe nun ein Serverseitiges-Script geschrieben (für Counter-Strike: Source) mit einer sqlite3 Datenbank. Ein Kollege von mir hat sich freundlicherweise bereit erklärt das Script auf seinem Server zu testen. Anfangs lief alles bestens. Allerdings hat er mir vor ein paar Tagen gesagt, dass der Server beim Laden und Entladen des Scripts kurz einfriert (trotz sqlite3 Datenbank). Ich glaube zu diesem Zeitpunkt war die größe der Datenbank etwa 1000-1200 Einträge, bei einer Dateigröße von knapp 251 KiloBytes.

Hier ist mal der Vollständige Sourcecode, der die Crashes verursacht:

http://dpaste.com/694454/

Jemand evtl ne Idee woran das liegen könnte?


MfG Brainsucker
Zuletzt geändert von Brainsucker am Samstag 28. Januar 2012, 23:13, insgesamt 1-mal geändert.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Solche langen Code solltest Du in einem Pastebin posten, etwa paste.pocoo.org.

Wie lautet denn die Fehlermeldung? Wir können das Script ja nicht laufen alssen, noch sind wir Hellseher! Und bei einer solchen Komplexität des Scriptes sieht man das auch eher selten durch "Hingucken"...
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Brainsucker
User
Beiträge: 68
Registriert: Mittwoch 16. November 2011, 23:20

Hyperion hat geschrieben:Wie lautet denn die Fehlermeldung?

Genau das is wohl das Problem. Der Server schmiert einfach ab ohne Fehlermeldung. Daher bin ich selber auch auf hilfe angewiesen, ob evtl im SQL-Teil des Codes etwas enthalten ist, das einen solchen Crash oder Lags verursacht.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Also wenn es nicht mal ein Log gibt, dann sehe ich schwarz! Oder kann man das auch Stand-alone testen?
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@Brainsucker: 1000—1200 Einträge ist nicht wirklich viel. Du schreibst ja weder wie lange es „hängt”, noch wo diese Zeit verbraucht wird. Gibt es Logs? Was steht da drin?

Eventuell könnte es helfen die Primärschlüssel auch tatsächlich als solche zu markieren. Oder explizit Indexe dafür zu erstellen.

Dann sieht mir `getSQLData()` ziemlich komisch aus. Einmal von der Semantik und dann ist die zweite Schleife wahrscheinlich langsamer als sie sein müsste, weil dort für jedes Element aus `display_times` jedes aus `pl_lo` verarbeitet wird. Da würde man mit sortieren und gruppieren eventuell besser fahren. `pl_lo` erscheint mir als Datenstruktur ziemlich sinnbefreit Da wird ein Tupel mit einem einzigen Element (Zeitstempel) auf ein `datetime`-Objekt mit dem Wert von dem Zeitstempel abgebildet. Der Schlüssel unnötig komplex und wird auch gar nicht wirklich verwendet. Wo ich da noch ein Problem sehe: es kann durchaus passieren, dass ``d['total']`` am Ende nicht mit der Anzahl der Einträge in `pl_lo` übereinstimmt!? Ich weiss jetzt nicht ob das gewollt war, denn wenn nicht, ist ``d['total']`` redundant, weil man da auch mit der `len()`-Funktion mit weniger Aufwand heran käme.
Brainsucker
User
Beiträge: 68
Registriert: Mittwoch 16. November 2011, 23:20

Also hab mich mal eben mit dem Kollegen kurzgeschlossen, der das Script für mich testet.

Er meinte beim Laden/entladen friert der Server für etwa 2 Sekunden ein. Erfahrungsgemäß weiß ich, dass alle Aufrufe, die in der Funktion unload() passieren keinen lag verursachen sollten (ähnlich beim Laden allerdings werden bei laden noch viele andere Dinge gemacht, wie z.B. globale variablen etc.). Daher habe ich mal instinktiv auf die SQL Datenbank getippt, dass diese für die Probleme verantwortlich ist.

Also die Funktion getSQLData() habe ich eher aus der Not heraus geschrieben, da ich nicht genau wusste wie ich das mit den Daten bewältigen sollte.
Dennoch weiß ich, dass diese Funktion nicht für die Probleme verantwortlich sein kann, da diese Funktion nur nach der eingabe eines Bestimmten Chatbefehls aufgerufen wird. Da nur ich und der Serverbesitzer den Chatbefehl kennen, ist es relativ unwahrscheinlich, dass diese Funktion die Probleme verursacht.

Ich finde es zwar sehr freundlich wenn ihr mir in dieser Sache weiter helfen wollt, um die Funktion "ressourcenfreundlicher" zu machen allerdings mein Problem wird es wohl nicht beheben.

Wie schon gesagt, Logs dazu gibt es leider keine, da der Server einfach abschmiert.
BlackJack

@Brainsucker: Du könntest in Dein Skript vielleicht mal Logausgaben einbauen. An deren Zeitangaben kann man dann vielleicht sehen, was daran die Zeitverzögerungen verursacht und vielleicht auch, ob es immer an der selben Stelle den Server zum abstürzen bringt.

Kann es vielleicht sein, dass der Gameserver die Funktionen in verschiedenen Threads aufruft? `sqlite3.threadsafety` sagt nämlich „Threads may share the module, but not connections.”
Brainsucker
User
Beiträge: 68
Registriert: Mittwoch 16. November 2011, 23:20

Oke, dann werd ich morgen mal ne kleine Logfunktion in das Script einbauen und für 1-2 Tage auf dem Server laufen lassen um es zu testen und auszuwerten.

Meines wissens nach, arbeitet der Interpreter alle Funktionen der reihe nach ab. Also im Klartext wird nur das gethreaded, was auch tatsächlich mit threading.Thread aufgerufen wurde. Daher solle die threadsafety in diesem Fall keine Rolle spielen.

Würde es sich denn überhaupt lohnen bei sqlite3 threads einzusetzen?
BlackJack

@Brainsucker: Der Gameserver ruft doch die Funktionen auf. Das könnte er durchaus in verschiedenen Threads tun. Oder kennst Du den Quelltext des Servers und kannst das ausschliessen!?
Brainsucker
User
Beiträge: 68
Registriert: Mittwoch 16. November 2011, 23:20

Naja sagen wirs mal so:

Wenn der Server die Funktionen bereits in einzelnen Threads aufrufen würde, würde es keinen Sinn mehr machen dass der Interpreter den Scripts erlaubt ebenfalls eigene Threads zu starten. Allerdings da man durchaus auf das modul threading zugriff hat (und man somit eigene threads starten kann), würde ich es eher ausschließen, dass die Funktionen bereits als threads aufgerufen werden.
BlackJack

@Brainsucker: Die Argumentation kann ich so gar nicht nachvollziehen. Ob der Server Threads benutzt oder nicht, ist doch nicht davon abhängig ob man in dem Skript welche starten könnte, sondern ob es für den Server Sinn macht mit mehreren Threads zu arbeiten. Und das ist völlig unabhängig von Deinem Skript. Da der Server mehrere Clients bedient, muss er entweder einen Ereignisbasierten Ansatz oder aber Threads verwenden um *seine* ganz normale Arbeit zu erledigen. Dein Skript wird ja nicht einfach wie von Dir behauptet einfach der Reihe nach vom Interpreter abgearbeitet, sondern die Funktionen werden bei bestimmten Ereignissen vom Server aufgerufen. Wann das passiert und ob vielleicht auch parallel aus mehreren Threads, entscheidet der Server.

Bist Du übrigens sicher dass Benutzer den Chatbefehl nicht heraus finden können? Das letzte Argument beim Registrieren der Funktion scheint ein Hilfe-Text zu sein. Bei den meisten CLI-Hilfesystemen kann man sich die Befehle alle auflisten lassen.
Brainsucker
User
Beiträge: 68
Registriert: Mittwoch 16. November 2011, 23:20

ups, ich glaube das liegt wohl ein missverständniss vor. Natürlich gibt es funktionen die automatisch vom Server bei bestimmten Ereignissen aufgerufen werden.

Die funktionen player_connect und es_player_validated sind 2 dieser Funktionen.

Also eigentlich lässt sich das mit den Threads ganz einfach Testen, indem ich folgendes Script auf den Server lade:

Code: Alles auswählen

import time
time.sleep(5)
Wenn dann der Server für 5 Sekunden einfriert, weiß ich, dass keine Threads zugange sind. Selbes lässt sich natürlich bei einem der grade Angesprochenen Serverereignissen Testen. Ich bin mir schon fast sicher, dass der Server einfrieren wird, wenn ich dies Teste und somit auch KEINE threads verwendet werden.

Zu deiner Frage mit dem Chatbefehl kann ich nur sagen dass der Befehl ausschließlich Serverseitig registriert wird. Die einzige Möglichkeit für einen Spieler diesen Befehl herauszufinden wäre über ein zweites Script (von dem ich nichts weiß), das alle möglichen Chatbefehle für einen Spieler auflistet. Aber da gehen wir mal sehr stark davon aus, dass diese Möglichkeit nicht besteht und somit ist und bleibt der Befehl für alle 'normalen' Spieler unbekannt.
lunar

@Brainsucker: Das testet allenfalls, ob der Thread, welcher das Skript lädt, derselbe ist wie derjenige, der die Benutzerschnittstelle steuert, an welcher Du merkst, dass der Server "einfriert". Es sagt aber nichts darüber aus, ob die Funktionen, die der Server aufruft, nicht aus anderen Threads heraus aufgerufen wurde, und ob im Hintergrund wirklich keine anderen Threads laufen.
Brainsucker
User
Beiträge: 68
Registriert: Mittwoch 16. November 2011, 23:20

@lunar
Brainsucker hat geschrieben:Selbes lässt sich natürlich bei einem der grade Angesprochenen Serverereignissen Testen

Code: Alles auswählen

import time
def player_say(ev):
   # Eine weitere Funktion die vom Server automatisch aufgerufen wird ;)
   time.sleep(5)
What about that? :)
Antworten