PHP MYSQL / PHP Race Conditions

isyyy

Lieutenant
Dabei seit
Aug. 2010
Beiträge
666
Hallo zusammen,

ich hab da mal eine Grundlegende frage über PHP und MYSQL.
Ich bin ein C++/Java Entwickler und Programmiere derzeit ein Spiel für
Android und iOS.

In dem Spiel können sich Spieler gegeneinander Duellieren.
Startet ein Spieler ein neues Spiel wird zuerst in der Datenbank auf einer Tabelle geschaut ob offene Spiele,
also noch nicht zugewiesene Spiele vorhanden sind.

Sind alle Spiele schon anderen Spielern zugewiesen wird ein neues Spiel angelegt und der Status wird in der Tabelle auf 0 gesetzt. Der Status 1 würde bedeuten das dieses Spiel schon einem anderem Spieler zugewiesen wurde.

Nun ist meine Frage folgende:

Kann es vorkommen das in einer Tabelle mehrere nicht zugewiesene Spiele vorhanden sein können?

Situation1:

Es sind derzeit 2 Spieler online.
Spieler 1. sucht ein Spiel. Es ist aber keins vorhanden. In die Tabelle "offeneSpiele" wird jetzt ein Eintrag erstellt welches den Status 0 hat. Kurz nachdem Dieses Spiel in die Tabelle eingetragen wurde sucht Spieler 2. ein Spiel.
Nun wird ein SELECT ausgeführt mit dem LIMIT 1 wo Status = 0 ist. Demzufolge wird das Spiel vom Spieler 1. ausgewählt und der Status auf 1 gesetzt. Dadurch ist das Spiel jetzt vergeben.

Situation 2:
Mehrere Spieler > 500 suchen zum gleichen Zeitpunkt ein Spiel. Wie werden diese SELECT Querys auf MYSQL jetzt ausgeführt?
Hintereinander? Parallel? Kann es vorkommen das mehrere Spieler von diesen 500 Spielern zufälligerweise ein gleichen Spiel SELECTED bekommen wo der Status auf 0 st? Weil ein Spiel darf nur 2 Spieler beinhalten.
Oder wird die Tabelle bei einem SELECT gelocked?
Oder passiert das so schnell das nie ein Spiel mit Status 0 von mehreren Spielern SELECTIERT werden kann weil der Status zu schnell auf 1 gesetzt wird?

Oder muss ich per Code die Tabelle sperren?

Würde mich freuen falls mir jemand eine Hilfreiche Antwort schreiben könnte.

Viele Liebe Grüße
 
Zuletzt bearbeitet:
Meinst Du wirklich MySQL?
Falls ja: Wird das ein Open Source Spiel?
Falls nein: Oracle verlangt in dem Fall tausende Dollar Lizenzgebühren.

Bevor Du dich also ins Getümmel stürzt solltest Du das prüfen und ggf. von vornherein auf eine andere Datenbank ausweichen.
 
Moin,

das Problem, was du ansprichst wird als sogenannte Anomalie bezeichnet. Anomalien können in verschiedenen Formen vorkommen, sind aber meistens das Resultat von Mehrbenutzerzugriffen auf eine Datenbank, die verschiedene Lese-und Schreiboperationen beinhalten.

Datenbanken versuchen Änderungen folglich immer erst mit einer "comitted"-Nachricht zu bestätigen, bevor die nächste Schreiboperation stattfinden kann. Dies wird als Isolation bezeichnet und ist eine der grundlegenden ACID-Eigenschaften. Scroll mal ein bisschen runter im Artikel bezüglich der Isolation, da findest du den Ablauf von Transaktionsinsolation für SQL.

Hoffe die Stichpunkte helfen dir als Anhaltspunkt für die weitere Recherche.
 
Bezüglich der Matchmaking Problematik und der Transaktionsfestigkeit von relationalen Datenbanken:

Ich würde es so handhaben, dass freie Spieler in einer Tabelle (Lobby) eingetragen werden.
Ein Matchmaking-Prozess pickt sich aus dieser Tabelle mittels eines Algorithmus (Random und/oder unter Beachtung von Level, Skills etc.) zwei Vögel raus und erstellt in einer "Game-Matching" Tabelle exklusiv für diese beiden Spieler transaktionsfest ein Spiel.
Sollte einer von beiden das Spiel verlassen, muss deine Anwendung entscheiden, was passiert (Sieg-Wertung für den Verbleibenden etcpp.)

Offene "Zombi-Spiele" dürfte es so nicht geben und Transaktionsprobleme bei einem großen Ansturm ebenfalls nicht.

Edit: Abgesehen davon, dass PHP einen großen Ansturm von mehrere tausend Spieler gleichzeitig nicht überlebt(!)
 
Es wird seit einigen Jahren von PHP auf Hack umgestellt (was auch nur erweitertes und kompiliertes PHP ist), aber Facebook gab es nun lange genug auf PHP Basis dass man davon ausgehen könnte dass es die meisten Webseiten bedienen kann...
Mal abgesehen davon dass man nicht zwingend immer die Wahl der Programmiersprache hat. Wie das beim TE ist ist natürlich eine andere Sache.
 
Zitat von ayngush:
Meinst Du wirklich MySQL?
Falls ja: Wird das ein Open Source Spiel?
Falls nein: Oracle verlangt in dem Fall tausende Dollar Lizenzgebühren.

Bevor Du dich also ins Getümmel stürzt solltest Du das prüfen und ggf. von vornherein auf eine andere Datenbank ausweichen.

Bist du dir dabei sicher? Nach deiner Aussage müsste jedes Forum wo Werbung eingebunden ist eine MYSQL Lizenz besitzen.
Meines Wissens nach wird das durch den Server Hosting Provider geregelt, solang ein Server gemietet ist sollte das kein Problem darstellen.
 
Ja, ich bin mir Sicher
Wahrscheinlich läuft da dann bei deinen Hoster eine zu MySQL kompatible MariaDB und kein MySQL mehr - da MariaDB jedoch ein Fork von irgendwann ist, kann sich eine MariaDB von MySQL was das Sperrverhalten etc. angeht unterscheiden.
 
Zitat von ayngush:
Ja, ich bin mir Sicher
Wahrscheinlich läuft da dann bei deinen Hoster eine zu MySQL kompatible MariaDB und kein MySQL mehr - da MariaDB jedoch ein Fork von irgendwann ist, kann sich eine MariaDB von MySQL was das Sperrverhalten etc. angeht unterscheiden.

Hab mal nachgeschaut was auf dem Server läuft. Es ist die MySQL Community Server Edition https://dev.mysql.com/downloads/mysql/

Diese läuft unter GPL License. Hier der Link dazu http://www.gnu.org/licenses/old-licenses/gpl-2.0.html

Kann man die denn jetzt Kommerziell nutzen?

Nachtrag, nach dieser Quelle ist es Kein Problem: https://www.xaprb.com/blog/2009/02/17/when-are-you-required-to-have-a-commercial-mysql-license/
 
Zuletzt bearbeitet:
Solange MySql nur auf dem Server läuft und nicht mit dem Spiel geliefert wird also in den binären Dateien ist die Nutzung in meinem Fall kostenlos.
 
Nur, wenn es unter GPLv2 veröffentlicht wird!
Das ist ja gerade die beschissene Einschränkung von MySQL, weswegen viele Hoster und nahezu alle Linux-Distros dazu übergegangen sind MySQL rauszuschmeißen und durch MariaDB zu ersetzen.
 
Du verstehst das ganze falsch.

Da ich MySQL nicht integrierst sondern lediglich als DB Server einsetzt, muss das Projekt NICHT unter der GPL liegen, darf also ganz normal kommerziell und closed source sein.

Ich verkaufe nämlich nicht einen MySql Server sondern nutze diesen als DB im Backend. Wieso sollte ich meinen C++/Java Code offen legen müssen wenn dort kein MySql intrigiert ist? Gilt natürlich nur für die Community Edition.

Solang ich keine libMySQL.dll etc in meiner App eingebunden habe und die Daten durch Php an meine App reiche muss ich keinen Cent dafür bezahlen.
 
Richtig. MySQL muß nur explizit lizensiert werden (unter der Dual-Lizenz-Option), wenn man das in seine Applikation einbaut (die "embedded"-Option), egal ob als Client oder als embedded Server, UND man nicht willens ist, das Endergebnis unter GPL zu stellen (ie: mit seiner Anwendung Geld verdienen will).

Andere Auslegungen gehen auch, sind aber eher vorauseilender Gehorsam.

Andererseits: alles was Oracle eingekauft hat von SUN kann man inzwischen vergessen (möglicherweise(!) außer JAVA). Oracle hält aber lediglich die Namen/Warenzeichen - die Entwickler sind längst über alle Berge und haben LO aufgemacht bzw haben MariaDB aufgemacht.

Warum also eine Software verwenden, die den NAMEN MySQL trägt, wenn das, was MySQL ausmacht, inzwischen unter anderem Namen firmiert? Oracle kann bestenfalls Support liefern (an dieser Stelle produktiven/kostenpflichtigen) aber das kann man bei MariaDB auch haben.


In jedem Fall hat das NICHTS damit zu tun, daß man ja MySQL lizensieren müßte.... oder irgendeine Software mit einer Dual-Lizenz-Option, wenn da "Open Source" ein Modell davon ist (und man sich an die OSS-Bedingungen halten kann/will).



PS. MySQL ist eigentlich für den Anfang eine eher schlechte Option. Inzwischen ist PostgreSQL das Mittel der Wahl --- bevor man sich in eine Umgebung reingerannt hat und es mit dem Wechseln schwierig wird, würd ich persönlich die Finger von MySQL(und Ablegern) lassen und auf Pg setzen.
 
Die wichtigen Konzepte hier sind Transaktionen selbst, und das transaction isolation level bei SQL (https://dev.mysql.com/doc/refman/5.7/en/innodb-transaction-isolation-levels.html). Du kannst mehrere SQL statements in einer Transaktion zusammenfassen, und dann ist immer nur das Endergebnis sichtbar für andere Anfragen, kein Zwischenzustand.

Reads locken nicht von selbst, man kann aber mit SELECT FOR UPDATE angeben das diese row bis zum Ende der Transaktion für Schreibzugriffe gelockt ist.

Bei dem höchsten transaction isolation level SERIALIZED treten viele Probleme dieser Art nicht auf, Standard ist aber ein niedrigeres Level wie READ COMMITTED oder REPEATABLE READ.


Der folgende Artikel ist eine gute Beschreibung der Problematik und möglicher Lösungen, ist zwar für Postgresql, sollte aber im wesentlichen auch auf MySQL zutreffen:

https://blog.2ndquadrant.com/postgresql-anti-patterns-read-modify-write-cycles
 
Zuletzt bearbeitet:
Hab leider keine Erfahrung mit PostgreSQL. Bin Mit PHP und MySql "aufgewachsen".
Aber zurück zu dem Thema "Race Conditions".

Theoretisch würde es doch reichen wenn ich die Tabelle während ein UPDATE läuft "locke" also sperre.

HTML:
SELECT * FROM openGames WHERE gameStatus = 0 FOR UPDATE LIMIT 1

Würde ich damit die komplette Tabelle sperren?
Oder würde ich hiermit nur die Einzelne Row sperren?

Wenn die Row gesperrt ist und der GameStatus noch nicht auf 1 gesetzt sein sollte, kann dann eine andere Connection diese trotzdem SELECTEN? :freak:

NACHTRAG: Okey wenn ich den Artikel richtig verstanden haben sollte,
sollte ein einfaches FOR UPDATE das Problem beheben. Oder :D ?
 
Zuletzt bearbeitet:
Zurück
Top