mmofacts.com

Kampf wird doppelt ausgeführt

gepostet vor 14 Jahre von sami06

hi
ich hab ein kleines BG in dem die Angriffe geladen werden und wenn sie angekommen sind, wird der kampf ausgeführt
nun haben wir zwei user die zur selben zeit die entsprechende php Datei aufrufen, in etwa so
Zeitpunkt (ZP)
ZP1: user1, 2 lädt die seite
ZP2: user 1, 2 laden aus der DB die angriffe, beiden laden den relevanten weil der jeweils andere noch nicht mitteilen konnte, das er fertig ist
ZP3: user1, 2 berechnen den kampf und alles
ZP4: user1, 2 kontrollieren, ob noch notwendig, alles in die DB einzutragen - beide denken JA
ZP5: beide tragen ein, dadurch teilweise doppelbuchungen, zu viele Rohstoffe etc
ZP6: beide sagen "fertig" aber zu spät
so in etwa denke ich läuft es ab, diese doppelbuchungen kommen leider vor und ich weiß nicht, wie ich sie verhindern kann
kann mir jmd. helfen

thx

topo

gepostet vor 14 Jahre von Drezil

aber ich denke mal er nutzt eh myisam .. und muss jetzt auf innodb umstellen :D

gepostet vor 14 Jahre von BlackScorp

Original von Drezil

aber ich denke mal er nutzt eh myisam .. und muss jetzt auf innodb umstellen :D

ich dachte myIsam kann keinen fremdschlüssel verwalten, wie soll man dan ein BG mit myIsam umsetzen?

gepostet vor 14 Jahre von RaydenDD

Original von BlackScorp

Original von Drezil

aber ich denke mal er nutzt eh myisam .. und muss jetzt auf innodb umstellen :D

ich dachte myIsam kann keinen fremdschlüssel verwalten, wie soll man dan ein BG mit myIsam umsetzen?

Zum Beispiel wenn man keine Fremdschlüssel nutzt :D

gepostet vor 14 Jahre von TheUndeadable

> und muss jetzt auf innodb umstellen

Oder man nutzt File-Locks...

gepostet vor 14 Jahre von sami06

erst mal danke für die antworten

dann habe ich ein wenig gelesen und denke drüber nach, auf innoDB umzustellen unter umständen

gibt es den mysql anweisungen die dann anders lauten?

muss ich mehr ändern als nur den Tabellen typen

desweiteren, wie löst das lock dings dann mein problem

wenn also User 1 den Datensatz ausliest, kann dann User2 erst gar nicht mehr lesen, bzw. was ist wenn user 1 geschrieben hat, kann dann user 2 nicht denoch einfach schreiben nachdem user 1 fertig wurde

mfg

topo

gepostet vor 14 Jahre von knalli

Ja, du musst schon Transaktionen nutzen. Alleine vom DB-Engine-Umschaltknopf wird sich nichts tun. :)

gepostet vor 14 Jahre von sami06

ich lese noch, wollte aber schon mal fragen

sowit bin ich, habe ich i einen fehler da drin

so, ich mache alles wie oben, rechnen etc.....

dann mache ich i wann wo es ans eintragen geht etwas wie folgt

mysql_query('begin');

GANZ VIELE mysql_query's alls SELECT * ... UPDATE * .... etc

DELETE * ...

dann schau ich nach,  ob der datensatz bereits aktualisiert wurde, z.B. SELECT * (eben versuchen den gelöschten aufzurufen)

wenn keiner zurückgegeben wird => mysql_query('rollback');

wenn einer zurückgegeben wird => mysql_query('commit');

das fürht dann dazu, dass die querys solange ausgeführt werden, wie der datensatz noch existiert

wenn der datensatz nicht mehr existiert, wird es auch nicht mehr ausgeführt

Vorraussetzung: alle Tabellen die ich da drin nutze müssen innoDB sein

oder habe ich da noch fehler

gepostet vor 14 Jahre von knalli

So rum:

  • Transaktion starten.
  • Prüfen, ob Bedingungen für die Operationen gelten.
  • Operationen ausführen.
  • Commit.

Ein weiteres Mal Prüfen vor dem Commit sollte bei InnoDB nicht notwendig sein.

gepostet vor 14 Jahre von NeoArmageddon

Original von BlackScorp

Original von Drezil

aber ich denke mal er nutzt eh myisam .. und muss jetzt auf innodb umstellen :D

ich dachte myIsam kann keinen fremdschlüssel verwalten, wie soll man dan ein BG mit myIsam umsetzen?

Ich habs getan... aber bereue es, ab sofort nur noch InnoDB^^

gepostet vor 14 Jahre von buhrmi

Also Transactions sind erst mit Row-Locking so richtig geil.

Denn ohne müsstest du immernoch prüfen, ob nicht jemand schneller war, und evtl. eine Fehlermeldung ausgeben. Der Vorteil jedoch ist, dass du mit einem "Rollback" alles wieder Rückgängig machen kannst. Oder alle Operationen nochmal "von Vorne" ausführen kannst.

Mit Row-Locking kannst du innerhalb einer Transaction mit einer SELECT Operation (Stichwort "FOR UPDATE") Datensätze locken. Alle anderen SELECT Anweisungen aus anderen Transaktionen warten dann automatisch so lange, bis die Transaktion, die den Datensatz gelockt hat, commited wurde.

Kleine Ergänzung: Es warten natürlich nur diejenigen Transaktionen, die ebenfalls die selben Datensätze mit "FOR UPDATE" locken wollen. Normale Select-Anweisungen laufen ohne Probleme durch.

gepostet vor 14 Jahre von BlackScorp

hm.. ich verstehe gerade nicht, wozu es sinnvoll ist datensätze zu schließen, ich meine hängt das nicht von der datenbank plannung ab? wenn ich meine datenbank so gestalte, dass wirklich jeder datensatz einem bestimmten user zugewiesen wird, dann braucht ich doch nichts zu schließen oder wieder öffnen?

gepostet vor 14 Jahre von sami06

na ja, zum beispiel wenn eine stadt angegriffen wird, dann kann das durchaus durch zwei user aufgerufen werden

zum einem durch den der angreift und den der verteidigt

nun wäre es ungünstig, wenn sowohl der eine als auch der andere die updates der einheiten etc. ausführt, dies würde nämlich dazu führen, dass ggf. doppelt rohstoffe abgezogen werden, was sicherlich nicht erwünscht ist

ich werde heute abend bei zeit noch ein wenig basteln und nochmals fragen, ob das ergebnis den gewünschten effekt haben wird

auf jeden fall herzlichen dank schonmal und ich meld mich später

topo

gepostet vor 14 Jahre von NeoArmageddon

Mmmhh... also bei mir ist sowas wie Kampf und Rohstoffabzug eine Sache des Eventhandlers... die User senden ihm quasi nur den Auftrag zum Kampf. So kommt es bei mir gar nicht vor, dass 2 User gleichzeitig sich angreifen. Beide erstellen Zeitgleich ihre Anfragen und der Handler nimmt sich dem ersten an und setzt in der DB ein vordefiniertes Flag. Kommt er zum 2. Eintrag sieht er das der User bereits am Kampf beteiligt war und überspringt das ganze.

Ich kann mir gerade nicht wirklich ausmalen, wie dein Kampfsystem gestrickt ist...

gepostet vor 14 Jahre von BlackScorp

Original von NeoArmageddon

Mmmhh... also bei mir ist sowas wie Kampf und Rohstoffabzug eine Sache des Eventhandlers... die User senden ihm quasi nur den Auftrag zum Kampf. So kommt es bei mir gar nicht vor, dass 2 User gleichzeitig sich angreifen. Beide erstellen Zeitgleich ihre Anfragen und der Handler nimmt sich dem ersten an und setzt in der DB ein vordefiniertes Flag. Kommt er zum 2. Eintrag sieht er das der User bereits am Kampf beteiligt war und überspringt das ganze.

Ich kann mir gerade nicht wirklich ausmalen, wie dein Kampfsystem gestrickt ist...

wie deiner , nur ohne eventhandler, bestimmt.

User greift an, geplünderte rohstoffe werden erreichnet und der angegriffenen stadt abgezogen, einer anderen stadt zugewiesen.

wenn 2 user angreifen, dann plündert jeder von der anfangssumme was, also bei der geplünderten stadt wird nur einmal ein wert abgezogen und die beiden angreifer, kriegen ihre geplünderten rohstoffe. obwohl der letzte weniger kriegen sollte, weil durch die erste plünderung , weniger rohstoffe in der stadt vorhanden ist... got oh got ist das verwirrend aber nun verstehe ich wieso man tupel closen sollte. wobei ich das ganze auch mti einem eventhandler geregelt hätte

Auf diese Diskussion antworten