mmofacts.com

MySQL: MyISAM vs. InnoDB

gepostet vor 17 Jahre, 10 Monate von DaBen
Ich habe nun schon viele Beiträge in diesem Forum und auch Suchergebnisse von Google bezüglich der Unterschiede zwischen MyISAM und InnoDB konsultiert, um mir eine Meinung über diese beiden Datenbank-Engines zu bilden. Doch neben allen sachlichen Analysen und Benchmarks würde mich doch einmal interessieren nach welchen Kriterien ihr euch für eines der beiden entscheidet.
Sicherlich - Transactions sind in Browsergames sehr nützlich und an manchen Stellen auch notwendig, aber lässt sich dies vielleicht auch ressourcensparender mit MyISAM durch Flags oder selbtgeschriebene Kontrollmechanismen umsetzen? Und welche der beiden Methoden ist in welcher Situation performanter? Wie entscheidet ihr?
Eure Meinung ist mir wichtig! Vielleicht entsteht ja eine kleine Diskussion, würde mich freuen...
So far
DaBen
gepostet vor 17 Jahre, 10 Monate von TheUndeadable
Ich persönlich nutze die MyISAM Tabellen, da ich momentan nahezu keine Logik in der Datenbank habe. Bei mir dient die Datenbank als reine Ablagefläche.
Die Transaktionssicherheit gewährleiste ich über Mutexe, die auf Systemebene erzeugt werden.
gepostet vor 17 Jahre, 10 Monate von unverbraucht
Mutexe sind elegant und ein Feature, dass ich in PHP vermisse (klar es gibt IPC-Mechanismen, aber die sind dahin sobald das Game auf mehrere Server verteilt ist). Ich nutze InnoDB vor allem fürs Locking als Mutex-Ersatz, damit sich die Eventhandler der einzelnen Spieler nicht in die Quere kommen. Hab dazu auch mal ne Frage hier gepostet und das als Tip bekommen, bin also sicher nicht der einzige, ders so macht
Abgesehen davon hat InnoDB den Vorteil, Row-Level-Locking anzubieten. Bei einem schreibenden Zugriff wird bei MyISAM immer die ganze Tabelle blockiert, bei InnoDB nur die Zeile, die gerade geändert wird. Ob die DB dann auch wirklich antwortet, wenn gerade viel Last ist, ist was anderes. Aber bei dem von uns verwendeten Forum (SMF) hats Wunder gewirkt, die oft beschriebenen Tabellen auf InnoDB umzustellen.
Tabellen, die sehr oft gelesen werden aber sich nie oder selten ändern, können auch als HEAP angelegt werden. Der Inhalt ist nach einem Mysqld-Neustart weg, aber da kann das Startupskript ja einen Dump reinladen. Gerade bei Join-Tabellen recht praktisch.
gepostet vor 17 Jahre, 10 Monate von Agmemon
Also ich entscheide mich gar nicht zwischen den beiden, sondern nutze beides.
Typische Lookup-Tabellen, z.B. Tabellen in denen sich Daten für Audits befinden, Statistiken, oder Tabellen, auf die nur ein einzelner Prozess Zugriff hat, setze ich mit MyISAM um.
Bei allen Tabellen, auf die schreibend zugegriffen wird, meist parallel von mehreren Instanzen aus, nutze ich InnoDB. Das selbe gilt bei Tabellen, auf die in Transaktionen zugegriffen wird.
Was das betrifft, wundern mich meine Vorredner ein wenig. Wie setzt ihr den Transaktionen mit Mutex/Semaphoren um? Beides sind Techniken für den gegenseitigen Ausschluss. Bricht man sich da nicht einen ab, wenn man darüber Transaktionen mit Commits und Rollbacks implementieren will?
Für den Gegenseitigen Ausschluss benutze ich optimistisches oder pessimistisches Locking ein, je nach dem was in dem Fall gerade Sinn macht. Das Framework, welches ich nutze, bietet dafür eine Datensatz-Versionierung an. Sehr praktisch.
gepostet vor 17 Jahre, 10 Monate von open_dimension
Ich würde gerne einmal eine Stufe tiefer ansetzten, mit meinen Fragen.
Ist die Einführung von InnoDB unproblematisch, oder kann man von MyISAM einfach umstellen ??
Und dann würde mich mal interessieren, warum man eine Datenbank überhaupt Locken sollte.
Ich mache es nie, und es ist noch keiner Inkonsetenz gekommen.
Obwohl gerade bei meinen Allianz-Städten gleichzeitig schreibend auf die Allianz-Tabellen zugegriffen wird.
gepostet vor 17 Jahre, 10 Monate von TheUndeadable
> Beides sind Techniken für den gegenseitigen Ausschluss. Bricht man sich da nicht einen ab, wenn man darüber Transaktionen mit Commits und Rollbacks implementieren will?
Ich persönlich lebe in einer 'optimistischen' Welt. Ich gehe grundsätzlich davon aus, dass meine Aktionen gelingen. Dies erreiche ich mit folgenden Schritten:
1. Mutex geholt
2. Überprüfung aller Voraussetzungen, falls diese nicht erfüllt sind: Abbruch
3. Durchführen der Aktionen. Diese gelingen, da die Voraussetzungen überprüft wurden.
3a. Kommt es dennoch zu einem Fehler, erhalte ich eine E-Mail/SMS und der Server wird gestoppt.
4. Mutexfreigabe
Bisher hatte ich keinen einzigen Ausfall. (MySQL unter Win)
> Und dann würde mich mal interessieren, warum man eine Datenbank überhaupt Locken sollte.
Benutzer A und Benutzer B buchen von einem gemeinsamen Konto ab.
A: Holt sich Geldvermögen: 100 EUR
B: Holt sich Geldvermögen: 100 EUR
A: Prüft Voraussetzungen. Ist gegeben. Abbuchung von Hypothetischen 30 EUR => 100 EUR - 30 EUR = 70 EUR werden geschrieben
B: Gleicher Fall. Dieser Thread weiß aber nur, dass aus der vorigen Holung des Vermögen 100 EUR drin war => 70 EUR werden geschrieben
Resultat: Beide Spieler haben 30 EUR, aber es wurden nur einmal 30 EUR abgebucht.
Dieses Verhalten kann man bei vielen Browsergames beobachten, wenn man sehr schnell auf 'Einheiten bauen' klickt. Das Geld wird nur einmal abgebucht, aber die Warteschlange wächst und wächst.
gepostet vor 17 Jahre, 10 Monate von Toby
Original von TheUndeadable
Dieses Verhalten kann man bei vielen Browsergames beobachten, wenn man sehr schnell auf 'Einheiten bauen' klickt. Das Geld wird nur einmal abgebucht, aber die Warteschlange wächst und wächst.

Wobei ich mich dabei frage, was da eigentlich schief läuft? Es ist doch so, das auf eine aktive Session nur ein Zugriff gestattet ist, das also keine zwei Prozesse sich die gleiche Session teilen dürfen (zumindest bei PHP).
Also kann doch bei einem BG, das ja normalerweise mit Sessions arbeitet, auch schnell klicken nichts ändern, da der zweite Klick erst dran ist, wenn das, was durch den 1. Klick angestoßen wurde abgearbeitet ist, denn PHP schließt die Session ja erst wieder, wenn das Script durch ist (außer man lässt die Session manuell vorher schließen).
Oder sehe ich das falsch?
Kann es evt. sein, das da die DB den Datensatz noch nicht richtig geschrieben hat oder sowas? MySQL cachet ja recht viel, kanns daran liegen?
gepostet vor 17 Jahre, 10 Monate von TheUndeadable
Nein.
Nehmen wir mal folgendes Pseudoskript an:
$nResources = SELECT xxx FROM resources WHERE playerid=123;
[*]
if ( $nResources < 5000 [Kosten] )
{
return;
}
$oHandler->RaumschiffInWarteschleife();
UPDATE resources SET xxx={$nResource-5000} WHERE playerid=123;
Der Nutzer klickt nun zweimal schnell auf den Link. Das Skript wird ZWEIMAL gestartet.
Nehmen wir mal an, es findet beim [*] ein Thread-Wechsel statt. Das zweite Skript lädt nun auch die Resourcen ein und prüft auf Un/Möglichkeit der Abbuchung. Beide Skripte sehen noch nicht, dass bald was abgebucht wird. => Zwei Raumschiffe in Warteschleife, einmal abgebucht.
> da der zweite Klick erst dran ist, wenn das, was durch den 1. Klick
> angestoßen wurde abgearbeitet ist, denn PHP schließt die Session ja
> erst wieder, wenn das Script durch ist (außer man lässt die Session
> manuell vorher schließen).
> Oder sehe ich das falsch?
Ja, PHP (bzw. jede mir bekannte Websprache) startet zwei Skripte mit der gleichen Session auch gleichzeitig. Dies ist ja prinzipiell kein Problem, bzw schon gewollt. Wenn der Nutzer in Tab 1 eine riesige Mitgliederliste lädt, kann er ja in Tab 2 mit der gleichen Session weitersurfen.
> MySQL cachet ja recht viel, kanns daran liegen?
Nein, wenn es im Cache liegt, so wird auch aus dem Cache gelesen. Bzw wenn was geschrieben wird, so wird der Query-Cache für diese Tabelle geleert (mein Stand aus MySQL 4).
Ein 'noch nicht richtig geschrieben' gibt es bei Datenbanken nicht. Ausgenommen MS Access ;-)
gepostet vor 17 Jahre, 10 Monate von open_dimension
Ersteinmal vielen Dank für Deine ausführlichen Erklärungen, TheUndeadable.
Ich habe daraufhin gleich einmal bei uns getestet, ob ich den Fehler produzieren kann. Es geht nicht. Entweder klicke ich zu langsam, oder die Antwortzeit des Servers ist zu schnell.
Bei uns würde das auch nur beim Ausbau von Gebäuden gehen, da die Ausbildung über Formular-Eingaben geregelt werden, die man so schnell gar nicht füllen könnte.
Also ist das für unsere Bedürfnisse nicht notwendig, die Datenbank zu Locken.
Aber ich werde das noch weiter im Auge behalten.
gepostet vor 17 Jahre, 10 Monate von Crafty-Catcher
Falls man sich beu euch 2 mal einloggen kann - logge dich doch mal auf den gleichen Account mit zwei verschiedenen Browsern ein und teste das
gepostet vor 17 Jahre, 10 Monate von Fornax
Man muss ja nicht 2x das Formular ausfüllen, einfach F5 und (bei Firefox) Enter drücken (wg. der Nachfrage, dass Post-Daten erneut gesendet werden)
gepostet vor 17 Jahre, 10 Monate von Störti
Einen solchen Fehler zu reproduzieren, ist recht schwierig, weil da extrem viel Zufall dabei ist.
Die beiden Anfragen müssen quasi zeitgleich beim Server ankommen und parallel ausgeführt werden, dass sich genau diese beiden "Lese-Bearbeite-Speichere"-Fenster überschneiden. Diese sind aber in der Praxis nur wenige Millisekunden lang. Du könntest den möglichen Fehler reproduzieren, indem du diesen Part manuell mit sleep() verlängerst und in deinem Browser den entsprechenden Link einfach zweimal anklickst, bei einigen Browsern funktioniert das...
gepostet vor 17 Jahre, 10 Monate von Crafty-Catcher
Das Problem trat auchmal auf bei zwei Browsern wie oben beschrieben und war einfach zu reproduzieren indem man vorher den gesamten Upload mit irgend nem P2P Programm o.ä. zugeballert hat. Hat recht zuverlässig funktioniert.
gepostet vor 17 Jahre, 10 Monate von knalli
Original von open_dimension
Ersteinmal vielen Dank für Deine ausführlichen Erklärungen, TheUndeadable.
Ich habe daraufhin gleich einmal bei uns getestet, ob ich den Fehler produzieren kann. Es geht nicht. Entweder klicke ich zu langsam, oder die Antwortzeit des Servers ist zu schnell.
Bei uns würde das auch nur beim Ausbau von Gebäuden gehen, da die Ausbildung über Formular-Eingaben geregelt werden, die man so schnell gar nicht füllen könnte.
Also ist das für unsere Bedürfnisse nicht notwendig, die Datenbank zu Locken.
Aber ich werde das noch weiter im Auge behalten.

Also reicht es, wenn ich per Socketzugriff bei dir x-mal das gleiche auf deinen Server abfeuere, und damit "cheaten" kann?
Merke: Nur weil man ein Formular nicht so schnell ausfüllen kann bzw. "F5-drücken" nicht wirkt, heißt das noch lange nicht, das Race Conditions nicht funktionieren.
gepostet vor 17 Jahre, 10 Monate von Toby
Dann habe ich falsch verstanden was unter
de.php.net/manual/de/function.session-write-close.php
steht...
Für mich las sich das so, das eben zur Laufzeit eines Scriptes nur dieses Script mit der Session interagieren kann und kein anderes. Nicht das da zwischen den Scripten hin und her geschaltet wird...
Nun ja, wenn man das Verhalten nicht will, sollte man die Sessions irgendwie manuell locken, oder nicht? So das wirklich nur ein Script nach dem anderen voll ausgeführt wird. Sollte, sofern es nicht sehr langwierige Abläufe sind, auch kaum negativ auffallen.
Man müsste nur einen möglichst atomaren Lock auf Sessionebene einbauen.
Oder man verlegt diese Abfragelogik in die DB und arbeitet da mit Stored Procedures usw., damit sollte man das Problem zumindest aus PHP-Sicht erledigen können.
gepostet vor 17 Jahre, 10 Monate von schokofreak
Original von Toby
Wobei ich mich dabei frage, was da eigentlich schief läuft? Es ist doch so, das auf eine aktive Session nur ein Zugriff gestattet ist, das also keine zwei Prozesse sich die gleiche Session teilen dürfen (zumindest bei PHP).

Sehr viele Coder scheitern schon daran, zu verhindern dass ein User mit mehr als einer Session eingeloggt ist.
Setzt man Sessions explizit als Locking mechanismus ein, so kann man verhindern dass ein User zwei Aktionen parallel ausführt. Und zwar 100 % sicher.
Allerdings, was wenn zwei User das machen? Einer Raidet, und der Andere baut gliechzeitig?
Oder eine Operation benötigt mehrere Update Schritte... der erste geht, danach kommt ein Script crash ohne Rollback?
Deshalb: IMMER Transaktionen. Mutexen Gebastel geht auch, aber nur wenn man wirklich weiss was man tut. Sprich; wenn man Transaktionen schon sehr gut kennt, somit die Stärken und Schwächen von Mutexen vs. Transaktionen abschätzen kann.
Gruss
gepostet vor 17 Jahre, 10 Monate von schokofreak
Original von Störti
Einen solchen Fehler zu reproduzieren, ist recht schwierig, weil da extrem viel Zufall dabei ist.

Oder man bringt den Server unter überlast. Sucht sich geeignete Aufrufe, welche die Lastverteilung bringen, welche man will (beispielsweise DB auf Überlast, Webserver knapp am anschlag). Danach wird aus den Millisekunden schnell sekunden bis Minuten.
Hab schon Scripts gesehen, welche mit Absicht 100'000 Einheiten von A nach B umgeladen haben; in EINE EINHEIT PRO REQUEST Schritten. Sprich 100'000 Serveranfragen.
Meiner Meinung sind solche Angriffe zu grossen Teilen für die Irrsinnigen Ressourcenanforderungen mancher BGs verantwortlich.
gepostet vor 17 Jahre, 10 Monate von Agmemon
Original von schokofreakDeshalb: IMMER Transaktionen. Mutexen Gebastel geht auch, aber nur wenn man wirklich weiss was man tut. Sprich; wenn man Transaktionen schon sehr gut kennt, somit die Stärken und Schwächen von Mutexen vs. Transaktionen abschätzen kann.

Ich weiß nicht, ob man von "versus" sprechen kann. Mutex/Semaphore bilden ja eigentlich nur Teilaspekte von ACID-konformen Transaktionen dar, nämlich Atomarität und Isoliertheit. Konsistenz und Dauerhaftigkeit können damit aber nur indirekt umgesetzt werden, wenn überhaupt.
gepostet vor 17 Jahre, 10 Monate von schokofreak
Dafür bieten sie andere Vorteile. Und wer da Vor / und Nachteile abschätzen kann, soll auch ne Entscheidung treffen.
Davon abgesehen, dass Mutexe in Punkto Performance bedeutend schlechter Abschneiden als geschickt eingesetzte Transaktionen.
gepostet vor 17 Jahre, 10 Monate von open_dimension
Ok, Ihr habt Recht. Wenn ich die Datenbank nicht Locke, gehe ich das Risiko ein, dass Scripts oder mit viel Aufwand betriebene Angriffe Löcher im System finden.
Aber dazu bedarf es eines wirklichen Freaks, der sich die Zeit nimmt diese Lücken zu finden und auszunutzen.
Ich baue ein Browserspiel und ich bin keine Bank, in der die Sicherheit an oberster Stelle steht.
Angriffe auf die Serverperformance würde ich über eine Firewall oder so lösen, und nicht über die Datenbank.
Ich denke ich werde einen Mittelweg gehen, zwischen Sicherheit und Performance, und so wie ich gelesen habe, ist der Locken der DB sehr nachteilig für die Perfomance.
Aber vielleicht sehe ich das in einem Jahr anders, wenn die Spieler mir 100 Mal das System geknackt haben.
gepostet vor 17 Jahre, 10 Monate von exe
Bei OGame wurde mit solchen Sachen mal richtig schön beschissen. Das ist wohl auch der Grund, warum man dort (wenn man schnell klickt) oft Fehlermeldungen kriegt ("Deine letzte Anfrage wurde noch nicht abgearbeitet blah blah"). Es ist durchaus keine hypothetische Situation. Wo eine Möglichkeit zum Beschiss existiert wird man sie früher oder später auch ausnutzen.
Deswegen lieber gleich richtig machen. Dann musst du später nicht ein großes Refactoring betreiben (oder eine Bastellösung wie bei OGame einführen...).
gepostet vor 17 Jahre, 10 Monate von Tron
Bevor man sich zwischen einer Transaktionssicheren Datenbank oder einem performanteren direkten Zugriff mit oder ohne Locking entscheidet sollte man auch noch einige andere Aspekte berücksichtigen.
Auch ohne transactions ist mysql meist sehr stabil, unvollständige Datenbankupdates geschehen viel häufiger durch Nachlässigkeiten z.B. auf PHP-Ebene.
Wenn ich z.B. zwischen Datenbankzugriffen schon Ausgaben habe, kann es zum Benutzerabbruch kommen. Dies kann ich hervorragend dadurch vermeiden, daß ich alle Datenbankzugriffe abschliesse und potentielle Ausgaben solange cache, bis ich die Datenbankzugriffe abgeschlossen haben.
Erreichen kann ich das zum Beispiel, indem ich jegliche Datenbankzugriffe ganz an den Anfang des Scriptes packe zwischen:
ob_start();
...
und:
...
ob_end_flush();
Hierdurch wird gewährleistet, daß der komplette DB-Zugriff bearbeitet ist, bevor mit der ersten Ausgabe der Benutzer die Möglichkeit zum Abbruch bekommt.
Alles in allem ist es für diese Entscheidung aber auch wichtig zu wissen, was ich in meiner Datenbank mache. Kritisch sind immer Zugriffe, bei denen ich Daten auslese, ausserhalb der DB verarbeite und dann (z.B. indiziert) zurückschreibe.
Beschränke ich mich auf überwiegend Lesezugriffe und direkte Datenbankupdates, kann ich meist auf Transaktionssicherheit verzichten. Unerlässlich ist jedoch, die Veraltensweise von mysql bei unterschiedlichen Funktionen zu kennen, und hierfür hilft nur eins: kenne deine Datenbank. In der Dokumentation finden sich eine ganze Reihe wichtiger Hinweise, wann und in wieweit Einträge und Tables bei welcher Art von Zugriff gelocked werden.
Gruss, Stefan
gepostet vor 17 Jahre, 10 Monate von mifritscher
oder man aktiviert ignore_user_abort, dann ist Schluss mit Scriptabbrüchen :-)
gepostet vor 17 Jahre, 10 Monate von Nuky
es hilft auch viel einfach nicht
"UPDATE table SET value='$newvalue' WHERE bla='$id'"
sondern
"UPDATE table SET value=value-'$newvalue' WHERE bla='$id'"
zu schreiben. dadurch ist wenigstens gewährleistet dass der aktuelle wert in der db steht..
gepostet vor 17 Jahre, 10 Monate von knalli
Original von Nuky
es hilft auch viel einfach nicht
"UPDATE table SET value='$newvalue' WHERE bla='$id'"
sondern
"UPDATE table SET value=value-'$newvalue' WHERE bla='$id'"
zu schreiben. dadurch ist wenigstens gewährleistet dass der aktuelle wert in der db steht..

Je nach Situation noch besser, sofern "bla" und "$id" keine unique-eindeutigen Schlüssel sind:
"UPDATE table SET value=value-'$newvalue' WHERE value='$value' AND bla='$id'"
gepostet vor 17 Jahre, 10 Monate von HSINC
das funzt aber auch nur bei atomaren querys. sobald es etwas komplexer wird, ist der aufwand den man ohne transactions betreiben muss, ungleich höher, als der aufwand transactions zu nutzen und etwas geschwindigkeit einzubüßen
gepostet vor 17 Jahre, 10 Monate von Nuky
@knalli:
bla muss natürlich eine unique id sein, sonst ist der sinn verhaut. aber deine zusatzabfrage zerstört wieder den sinn des ganzen, da es dann nur was abzieht wenn der wert gleich ist..
gepostet vor 17 Jahre, 10 Monate von knalli
Ja.. sollte auch größer-gleich heißen. Ka, was mich da geritten hat. Der Punkt ist der: Wenn beispielweise Geld, Energie, Gold oder whatever abgezogen werden soll - dann muss das natürlich relativ geschehen. Aber es muss zudem sichergestellt sein, dass der Wert nicht ins Negative gerät. Ohne Transactions (vorheriges Select, afaik) kannst du das sonst nicht sicherstellen.
gepostet vor 17 Jahre, 10 Monate von Drezil
bla int4 unsigned .. dann wirds schonmal nicht mehr negativ ..
ist aber dennoch keine entschuldigung für schlechtes locking ..
gepostet vor 17 Jahre, 10 Monate von Fasi
So wird ein Wert nie negativ:
"UPDATE table SET value=value-'$newvalue' WHERE value='$value' AND value>='$newvalue' AND bla='$id'"
Allerding muss man dann überprüfen ob der Update durchgeführt wurde und wenn nicht z.B. eine Meldung ausgeben: "Zuwenig Geld für den Ausbau"
gepostet vor 17 Jahre, 10 Monate von knalli
Original von Drezil
bla int4 unsigned .. dann wirds schonmal nicht mehr negativ ..
ist aber dennoch keine entschuldigung für schlechtes locking ..

Was wird das dann im Zweifel? Fängt der dann bei "groß" wieder runter an zu zählen, oder verbleibt er bei 0? Führt er das Query aus? Oder mit Fehler nicht?
gepostet vor 17 Jahre, 10 Monate von Drezil
ist ne eigenheit von mysql. alles, was mit < 0 in eine unsigned-spalte kommt wird auf 0 gesetzt. alles was > MAX_VALUE ist, wird auf MAX_VALUE gesetzt.
Ob da nen fehler geschmissen wird weiss ich nicht .. ich hab es nur mal bemerkt, als ich manuell 2-3 zeilen geändert hab und 1x einen negativen wert eingeben wollte .. ala "set value=-5" und nachher war value=0. direkt hab ich da keinen fehler gesehen. logging war aber auch ausgeschaltet .. und mir wars auch ziemlich wurscht, ob das nun geloggt wird oder nicht. unsaubere programmierung und verlassen auf db-fehlerbehandlung ist und bleibt nicht die feine englische art ..
also die kurzzusammenfassung für deine fragen:
< 0 -> 0
> MAX -> MAX
wird ausgefüht? -> ja
fehler? -> kein "error". ob es mitgeloggt wird weiss ich nicht.
gepostet vor 17 Jahre, 10 Monate von knalli
Mal wieder 'was neues gelernt. Man sollte zwar meinen, das wäre zu wissen, aber so etwas hab ich tatsächlich noch nie versucht
Mir wird's nur unwohl in der Magengegend, Programmierfehler in der Datenbank zu verhindern.. und zwar auf eine Art und Weise, die nicht 100% konsistent und sichergestellt ist
(constraints in oracle..)
gepostet vor 17 Jahre, 10 Monate von Toby
Jo, denn wenn du z.B. sowas machst:
UPDATE `test2` SET `test` = `test`-1000000 WHERE `test` =0 LIMIT 1 ;

Steht da dann z.B. 4294967295
gepostet vor 17 Jahre, 6 Monate von open_dimension
Ich wollte nochmal eben Rückmeldung geben:
Ich bin nämlich schon öfters an den Punkt gekommen, wo ich an diesen Thread denken musste, an das Problem mit dem Sperren der DB. Und ich wollte noch einmal Crafty-Catcher danken, für den Tip, wie man den Fehler reproduzieen kann, hat perfekt funktioniert.
Sperren tue ich die Datenbank aber trotzdem nicht
Bei Formularen ist es relativ einfach, den Button zu sperren und damit ein doppeltes Abschicken zu vermeiden:
Funktion:
i = parseInt(document.forms[0].elements.length);
i = i - 1;
document.forms[0].elements.disabled = true;
Und das dann per onsubmit im Formtag aufrufen.
Bei Textlinks die z.B. Upgrades aufrufen habe ich das komplett umbauen müssen ebenfalls auf Forms. Aber dann ist es easy
href="javascript:{form_bau.submit(); this.disabled=true;}"
Damit funktioniert das Ganze erst wieder, wenn alles abgearbeitet wird.
Das finde ich die bessere Lösung als das Sperren der DB, weil z.B. ich hab das einmal drin, das Sperren, nur in einer kleinen Ecke, weil ich dachte, dass ich dadurch einen Fehler unterbinde, und selbst dadurch habe ich Performance Einbußen. Laut phpMyAdmin erreiche ich ungefähr bei 5% aller Fällen keine sorftige Sperre. Und das muss ja nicht sein
gepostet vor 17 Jahre, 6 Monate von Toby
Bloß das deine Methode kein Schutz vor bösen Buben ist. Wer Javascript als Sicherheitsmaßnahme verwendet, macht etwas falsch.
Wieso sperrst du nicht einfach die komplette Session, bis das Script abgearbeitet ist? Einfach beim Start des Scriptes sowas wie

if ($_SESSION['locked']) die();
else $_SESSION['locked'] = true;
... Script ...
$_SESSION['locked'] = false;
Ist zwar kein 100%tiger Schutz, aber da eine Racecondition zu produzieren erfordert schon sehr großen Aufwand (bzw. hat evt. jemand Tipps wie man das atomar hinbekommt?).
gepostet vor 17 Jahre, 6 Monate von Fornax
Original von Toby

if ($_SESSION['locked']) die();
// [...]

Auch nicht das sauberste, wobei das schon wieder recht viel Aufwand ist:

while($_SESSION['locked']){
usleep(100); // unter Windows sleep(1), da usleep nicht unterstützt wird
}
Wobei mir gerade folgendes einfällt:
session_write_close
Somit dürfte das Problem garnicht erst auftreten.
gepostet vor 17 Jahre, 6 Monate von Klaus
Original von Toby
Bloß das deine Methode kein Schutz vor bösen Buben ist. Wer Javascript als Sicherheitsmaßnahme verwendet, macht etwas falsch.
Wieso sperrst du nicht einfach die komplette Session, bis das Script abgearbeitet ist? Einfach beim Start des Scriptes sowas wie

if ($_SESSION['locked']) die();
else $_SESSION['locked'] = true;
... Script ...
$_SESSION['locked'] = false;
Ist zwar kein 100%tiger Schutz, aber da eine Racecondition zu produzieren erfordert schon sehr großen Aufwand (bzw. hat evt. jemand Tipps wie man das atomar hinbekommt?).

Sollte das Skript mal abkratzen hast du sofort den Deadlock für den User.
gepostet vor 17 Jahre, 6 Monate von open_dimension
Ich benutz kein $_SESSION...
Sollte man das ??
Also ich habe ja extra gefragt, und genau diese Erfahrung gemacht, Lags führen zu solchen Problemen, nicht anderes...
Also:
Ob man das so macht oder nicht, ist mir eigentlich egal
Das Ergebnis zählt ....
Und wenn das nicht reicht, würde ich gerne bessere Argumente hören, wie:
"DAS macht man nicht"
gepostet vor 17 Jahre, 6 Monate von mifritscher
Ich nehme einen ähnlichen Ansatz wie Toby, allerdings speichere ich nen Timestamp, wenn das Lock älter als 5 sec ist wird es aufgehoben.
gepostet vor 17 Jahre, 6 Monate von Toby
@open_dimension: Wenns wirklich nur um Bequemlichkeit des Users geht, dann ist JS ja ok. Wenn du damit aber Sicherheit für deine Scripte erreichen willst, ist das keine gute Idee.
@Klaus: Das war eigentlich nur Pseudocode.
Das man es so nicht unbedingt machen sollte, ist mir auch bewusst (gerade auch nicht mit nem die(), eine richtige Fehlermeldung wäre schon feiner...).
gepostet vor 17 Jahre, 4 Monate von Hendrik
Hallo
Um zum Thema zurückzukommen
Als Faustregel kann man sich eigentlich merken
Wenn es sich um eine sehr UPDATE/INSERT-lastige Tabelle Tabelle handelt, dann sollte man InnoDB nehmen (z.B. die Rohstofftabellen). InnoDB ist beim schreiben schneller als MyISAM- beim lesen aber etwas langsamer.
Wird von einer Tabelle hauptsächlich gelesen (z.B. Accountdaten), so sollte man MyISAM nehmen, da MyISAM hier schneller ist.
~Hendrik
gepostet vor 17 Jahre, 4 Monate von Klaus
MyISAM ist die viel einfachere Engine kann es auch locker mit dem ach so leichten SQLite aufnehmen.
Wenn man also auf die Zusatzfunktionen (Transaktionen und Zeilenweises Sperren) bei InnoDB verzichten kann, würde ich MyISAM vorziehen.
Aber das ist auch Geschmackssache. Ich lade lieber nur das nötigste um Ressourcen zu schonen, während andere ihr BG mittels "Active Supercharged Pages .NET" schreiben. *g*

Auf diese Diskussion antworten