PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : MySQL bricht willkürlich weg


Marscel
2009-02-23, 23:17:45
Folgendes Experiment: Generiere für alle möglichen Zeichenkombinationen "a-zA-Z0-9" und ein paar Sonderzeichen den MD5-Hash und speichere diesen in eine Datenbank ab.

Dazu ein Script für Python 2.6 und MySQL 5.0 (auf localhost, WinXP 32bit).

Geschätzt kommen 5.000-10.000 MD5-Werte in der Datenbank pro Sekunde an. Die INSERT-Query-Operationen laufen in einem parallelen Thread neben Berechnung der String und Hashoperationen, das sollte das ganze ein paar Millisekunden pro Operation weniger aufhalten (wobei 1ms vorischtshalber Schlafenszeit zwischen jeder Operation ist, irgendwie hat man das bei C öfter so gemacht, damit das Programm beim Feuern nicht hängt).

Es besteht nur eine Verbindung! über die dann x000 Queries gesendet werden.

So weit so gut. Leider meckert das Programm irgendwann die MySQL-Fehler 2013 (Lost connection to MySQL server during query) und danach 2006 (MySQL server has gone away). Dass passiert irgendwann zwischen 1 und 230 Sekunden Laufzeit. Der Server rennt weiter und ist im nächsten Query wieder einsatzfähig, man kanns aber nicht einfach unbeaufsichtigt laufen lassen.

Eine MySQL-Config hat ja viele timeout-, max- und net-Werte. Aber so gänzlich weiß ich nicht, wo ich jetzt drehen muss oder ob das Script zu hart ist.

Ahnung anyone?


Und jetzt möge mir bitte keiner Erzählen, dass die Methode Zeitverschwendung ist, wenn ich MD5s umdrehen will. Hab ich mittlerweile auch raus gefunden. :upara: Aber das MySQL-Problem bleibt interessant.

rotalever
2009-02-24, 13:16:44
Kannst du nicht im Programm automatisch nach jedem Ausführen der Query feststellen, ob die Operation erfolgreich war und dann ggf. nochmal probieren?

Berni
2009-02-24, 13:20:51
Bist du sicher, dass du keine Synchronisationsprobleme zwischen den beiden Threads hast? Ich persönlich würde die Abfragen auch etwas bündeln, so dass du beispielsweise 1000 Werte auf einmal einträgst. Dann reicht auch ein Thread vollkommen aus...

Marscel
2009-02-24, 14:06:26
Kannst du nicht im Programm automatisch nach jedem Ausführen der Query feststellen, ob die Operation erfolgreich war und dann ggf. nochmal probieren?

Das wäre eine gute Idee, stimmt.

Bist du sicher, dass du keine Synchronisationsprobleme zwischen den beiden Threads hast? Ich persönlich würde die Abfragen auch etwas bündeln, so dass du beispielsweise 1000 Werte auf einmal einträgst. Dann reicht auch ein Thread vollkommen aus...

Ich synchronisiere nichts bei den Threads. Dass der eine irgendwann davon ziehen wird, das ist mir klar, aber ich dachte, dass die Queries sich anhäufen werden und eben sequentiell abgearbeitet werden (und dass man bei Python da nicht so pingelig sein muss).
Das funktioniert ja auch, nur mal eben kürzer oder länger.

Das Bündeln bau ich aber mal ein und schaue dann weiter.

Marscel
2009-02-24, 15:01:47
Argh, etwas blauäugig aufgebaut alles.

Das bündeln von Queries hat das Tempo erstmal verdoppelt.

Ich glaube doch, es gab Sync-Probleme, ich lasse über thread.join() nun warten, bis alles durch ist und mache dann erst den nächsten Durchlauf. Da verhakt sich auch nichts mehr.

War wohl nicht so klug, über den selben Bezeichner unkontrolliert in einer Schleife alles laufen zu lassen.

Und 1,3GB für alle möglichen vierstelligen Kombinationen zu verbraten ist auch nicht so das wahre.

rotalever
2009-02-24, 15:30:22
Ich glaube MySQL ist für soetwas auch nur bedingt geeignet. Da gibt es bestimmt schnelleres, da du sowieso nicht mehr als key->value Operationen benötigst.

Marscel
2009-02-24, 15:56:07
Ja, die Tabelle hat nur 2 Spalten. Was ist denn schneller? Plaintext macht das ganze sicher kleiner, aber schneller im Füllen/Suchen? Es sollte ja speicherbar sein.

rotalever
2009-02-24, 20:50:27
Ja, die Tabelle hat nur 2 Spalten. Was ist denn schneller? Plaintext macht das ganze sicher kleiner, aber schneller im Füllen/Suchen? Es sollte ja speicherbar sein.
Naja es gibt Datenbanken, die nichts anderes machen als für einen Key (dein Md5-hash) einen Wert (der dazugehörige String) speichern.
Z.B. http://memcachedb.org/

MySQL hat einfach viel zu viel Zeug drumherum, das du für so etwas Einfaches nicht brauchst.

Aber unabhängig davon: http://de.wikipedia.org/wiki/Rainbow_Tables

Marscel
2009-02-24, 22:30:43
Danke. Wenn ichs überedet bekomme, unter VS zu kompilieren, probiere ich es aus.

Sphinx
2009-02-25, 19:21:54
Klingt mir nach einem Time-Out Problem ~ Standard einstellung - 60 Seconds - Number of Seconds to wait for a Block to be written to a connection before aborting the write

Bzw. kenne mich mit Python gar nicht aus eventuell dort ein Time Out Problem ?

Marscel
2009-02-25, 23:17:15
Bzw. kenne mich mit Python gar nicht aus eventuell dort ein Time Out Problem ?

Nene, hat ja am Ende funktioniert. ;)

Ich hab jetzt mal memcachedb kompiliert, also volles Cygwin-Gefrickel für Win32 (wer ein spannendes Hobby sucht ... :ugly:). In der Linux-VM wollte ich es aus Performancegründen nicht ausprobieren, verhältnismäßig wenig Speicher und CPU.

Jetzt funktioniert es aber auch wie es soll. Wenn wer an der EXE interessiert ist, PM.

Mein Pythonscript produziert rund 10.000 MD5s pro Sekunde (ohne DB-Anbindungen) - gängige Brute-Force-Tools erreichen da das 5fache auf meinem PC, wenn ich mich richtig erinnere. Egal, Python und DAU-Scripting/Algos meinerseits. Sind doch deutlich mehr, wenn ich das Thread-Gespiel sein lasse.

Mit der nativen MySQL 5 Verbindung landen in etwa auch alle 10.000 Hashs/s in der Datenbank, vllt etwas weniger.
Bei memcachedb sind es aber nur umgerechnet 3.500 Hashs/s. Zum Lesen kann ich wenig sagen, lief in meinen paar Millionen aber für mich verzögerungsfrei.

Zusätzliches Manko ist, dass mcdb irgendein Write-Ahead benutzt, sodass in kurzer Zeit viele Hundert MB logs anfallen (liegt wohl am BDB-System, was darunter liegt), die angeblich mit der Zeit in die DB geschrieben werden. Tun sie aber nicht, oder nicht flott - auch wenn kein Schreiben ausgeführt wird. :|
Dass es nicht sonderlich flott ist, liegt, vermute ich, in erster Linie an Cygwin. Müsste es irgendwann mal auf dem Dual-Core Rechner nativ unter Linux ausprobieren und ein C-Programm zum Füttern nutzen.

Aber danke für den Tipp, im Prinzip läufts ja.

rotalever
2009-02-26, 13:39:50
Zusätzliches Manko ist, dass mcdb irgendein Write-Ahead benutzt, sodass in kurzer Zeit viele Hundert MB logs anfallen (liegt wohl am BDB-System, was darunter liegt), die angeblich mit der Zeit in die DB geschrieben werden. Tun sie aber nicht, oder nicht flott - auch wenn kein Schreiben ausgeführt wird. :|
Dass es nicht sonderlich flott ist, liegt, vermute ich, in erster Linie an Cygwin. Müsste es irgendwann mal auf dem Dual-Core Rechner nativ unter Linux ausprobieren und ein C-Programm zum Füttern nutzen.
Kann ich nicht viel zu sagen, da ich es selber noch nicht benutzt habe. Ich habe nur davon gehört, dass es größere Webseiten (z.B. digg) einsetzen um ihre MySQL Server zu entlasten und mehr Geschwindigkeit zu bekommen.
Aber dass das an cygwin liegt glaube ich nicht. Du kompilierst da ja soweit ich weiß nativ für Windows.

Coda
2009-02-26, 14:07:27
Ich würde mir mal SQLite anschauen.

Marscel
2009-02-26, 14:16:15
Aber dass das an cygwin liegt glaube ich nicht. Du kompilierst da ja soweit ich weiß nativ für Windows.

Nativ ist es, aber einiges im Bereich Threads, Benutzer, Netzwerk und sicher mehr wird von Microsoft aus nicht/anders unterstützt. Das geht dann durch den Cygwin-Layer, der das Windowskompatibel handelt.
Aber wo du es sagst, der Killer kanns ja nicht sein, PGSQL 7 lief, soweit ich weiß, recht anstandslos unter Windows über Cygwin.

Jetzt, wo ich Übung im Kompilieren habe, werd ich mal andere Lösungen angucken und probieren.

EDIT: SQLite... Oh Mann, darauf hätte ich kommen müssen. Danke.

Marscel
2009-02-26, 15:10:01
Wenn der Hash der Primary Key ist, fängt SQLite bei 10k Hashs pro Sekunde an und ist nach 500.000 etwa beo 700 Hs/s. Suboptimal.

Ist der Key einfach eine fortlaufende ID, ist die SQLite natürlich deutlich flotter (20k). Aber Lesen macht dann weniger Spaß. Im Grunde müsste man periodisch Hot-Backups der ID->MD5;String Tabelle machen, und diese dann am besten seperat sortieren und für den Lesezugriff öffnen. Das wäre doch, unabhängig vom DBMS, eine sehr performante Lösung, oder?

Allerdings dürfte das Sortieren irgendwann immer längere Schlagen stehen, wenn konsequent neue Werte generiert werden.

Ist ja auch interessant, in derselben Konfiguration ist SQLite immer noch spürbar schneller als MySQL, was Schreiben angeht.