Ankündigung

Einklappen
Keine Ankündigung bisher.

Zugriff synchronisieren?

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Zugriff synchronisieren?

    Hallo

    ich habe folgendes Problem: Ich habe in einer Datenbank verschiedene Geschenke für die User hinterlegt und ein Spezialgeschenk, was nur ein einziger User (durch Zufallsgenerator) bekommen soll.

    Aktuell ist mein Ablauf:

    1. User loggt sich ein
    2. via Zufalls generator wird ermittelt, ob User das Spezialgeschenk erhalten soll
    3. wenn ja, wird in der DB (MySql) nachgeschaut, ob das Geschenk noch frei ist
    4. Geschenk wird via Flag als vergeben markiert und dem User angezeigt

    Mein Problem ist nun: Wenn mehrere User parallel das php Script aufrufen könnte es nun sein, daß bei Schritt 3 mehreren Usern gleichzeitig das Geschenk als frei angezeigt wird.

    Wie kann ich das verhindern? Gibt es einen Weg, das man beim Prüfen ob das Geschenk noch frei ist, auch in der gleichen Abfrage das reserviert-Flag in der Tabelle setzt? Oder gibt es eine andere Lösung für das Problem?


  • #2
    Schritt 3 VOR Schritt 2 (wozu sollte man den User ermitteln, wenn das Geschenk gar nicht mehr frei ist?)

    Problem ist, das zwischen 2 und 4 immer noch ein Request passt.

    Eigentlich müsste es so laufen:
    - Geschenk "frei" und "nicht geblockt"? => Blocke "Geschenk"
    - Darf User Geschenk erhalten? => vergebe Geschenk, Geschenk als "nicht frei" markieren
    - Geschenkt "entblocken"

    Das "Blocking" ist eine Mutex-Operation (Mutex = Mutual Exclusion), etwas das exklusiven Zugriff sicherstellen soll.
    Über 90% aller Gewaltverbrechen passieren innerhalb von 24 Stunden nach dem Konsum von Brot.

    Kommentar


    • #3
      Du kannst in deinem Update-Query einbauen das er nur dann Updaten soll wenn der Wert noch leer ist.

      Also sowas:

      Code:
      UPDATE items SET user_id = 123 WHERE id = 15 AND user_id IS NULL

      Kommentar


      • #4
        Schritt 3 und 4 in eine Transaktion packen und Query 3 mit FOR UPDATE ausführen.

        Kommentar


        • #5
          das mit dem "For update" hab ich inzwischen auch schon gefunden. Benötige ich dafür trotzdem noch zusätzlich eine Transaction drumherum? Wenn ja, wie mache ich die?

          Wie läuft das dann bei dem User ab, der das Script parallel gerade nutzt? Meldet das einen Fehler oder wartet es bis User1 mit seiner Transaktion fertig ist und führt es danach erst aus

          Kommentar


          • #6
            Der Lock, der durch FOR UPDATE gesetzt wird, wird bei beedigung der Transaktion aufgehoben. Wenn du nicht explizit eine Transaktion startest dann wird jeder Query als eine eigenen Transaktion ausgeführt. Also ja, du musst eine Transaktion starten.
            Wie du das machst hängt von der Datenbankschnittstelle ab. Bei PDO z.B. $pdo->beginTransaction() und $pdo->commit();

            Wenn eine Transaktion mit einem Lock in konflikt kommt wartet diese bis der Lock wieder freigegeben wurde.

            Kommentar


            • #7
              Zitat von erc Beitrag anzeigen
              Der Lock, der durch FOR UPDATE gesetzt wird, wird bei beedigung der Transaktion aufgehoben. Wenn du nicht explizit eine Transaktion startest dann wird jeder Query als eine eigenen Transaktion ausgeführt. Also ja, du musst eine Transaktion starten.
              Wie du das machst hängt von der Datenbankschnittstelle ab. Bei PDO z.B. $pdo->beginTransaction() und $pdo->commit();

              Wenn eine Transaktion mit einem Lock in konflikt kommt wartet diese bis der Lock wieder freigegeben wurde.
              Depends.

              Code:
              test=# select * from foo where id = 1 for update;
              ^CCancel request sent
              ERROR:  canceling statement due to user request
              Time: 1622,247 ms
              test=*# select * from foo where id = 1 for update nowait;
              ERROR:  could not obtain lock on row in relation "foo"
              Time: 0,344 ms
              test=*#
              PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

              Kommentar

              Lädt...
              X