Andi123: Mysql: Tabelle sperren

Hallo!

Auf meiner Webseite wird täglich ein anderes Bild ausgegeben. Das Bild wird per Zufall aus einem Pool von Fotos ausgewählt. Der erste Benutzer der nach 0 Uhr die Webseite aufruft, stößt die Zufallsroutine an.

Jetzt kommt es ab und zu vor, dass zwei Webseitenbesucher zur gleichen Zeit die Seite aufrufen und dann zwei Bilder für einen Tag ausgewählt werden.

Das möchte ich verhindern, indem ich die Mysql-Tabelle, welche die Bildinformationen enthält, vor dem Update-Befehl sperre.
Ist es richtig, wenn ich mit "LOCK tabelle; UPDATE tabelle; UNLOCK tabelle;" vorgehe?

Danke,
Andi

  1. Hi,

    Jetzt kommt es ab und zu vor, dass zwei Webseitenbesucher zur gleichen Zeit die Seite aufrufen und dann zwei Bilder für einen Tag ausgewählt werden.

    Das möchte ich verhindern, indem ich die Mysql-Tabelle, welche die Bildinformationen enthält, vor dem Update-Befehl sperre.
    Ist es richtig, wenn ich mit "LOCK tabelle; UPDATE tabelle; UNLOCK tabelle;" vorgehe?

    Kann man so machen.

    Wie sieht denn dein DB-Design aus, wenn ein Tag nur ein Bild des Tages haben darf, du aber mehrere speichern kannst? Da scheint mir ein Fehler im Datenmodell vorzuliegen? Ggf. hilft ein einfacher Unique-Index, um dein Problem zu lösen…

    Bis die Tage,
    Matti

    1. Hello,

      Jetzt kommt es ab und zu vor, dass zwei Webseitenbesucher zur gleichen Zeit die Seite aufrufen und dann zwei Bilder für einen Tag ausgewählt werden.

      Das möchte ich verhindern, indem ich die Mysql-Tabelle, welche die Bildinformationen enthält, vor dem Update-Befehl sperre.
      Ist es richtig, wenn ich mit "LOCK tabelle; UPDATE tabelle; UNLOCK tabelle;" vorgehe?

      Kann man so machen.

      kommt darauf an, ob innerhalb _eines_ Requests gelesen und geschrieben wird, oder ob der Vorgang auf zwei oder mehr verteilt ist.

      Man muss die Tebelle nicht sperren. Man muss sich nur merken, ob die Auswahl für den Tag schon stattgefunden hat. Dieses Kriterium kann man dann auch in die Abfrage einsetzen.

      Dazu müsste die Tabelle dann eine Spalte für das Auswahldatum des Bildes haben.

      Beim Schreiben stellt man dann fest, ob die Tabelle schon einen Datensatz mit dem aktuellen Datum enthält. Wenn ja, wird das Update nicht durchgeführt, wenn nein, darf es durchgeführt werden und das Datum wird aktualisiert.

      Der erste, der schreibt, gewinnt dann. Das muss allerdings nicht der erste sein, der gelesen hat.

      Liebe Grüße aus dem schönen Oberharz

      Tom vom Berg

      --
       ☻_
      /▌
      / \ Nur selber lernen macht schlau
      http://bergpost.annerschbarrich.de
      1. Hello,

        Ist es richtig, wenn ich mit "LOCK tabelle; UPDATE tabelle; UNLOCK tabelle;" vorgehe?

        Kann man so machen.

        kommt darauf an, ob innerhalb _eines_ Requests gelesen und geschrieben wird, oder ob der Vorgang auf zwei oder mehr verteilt ist.

        Man muss die Tebelle nicht sperren. Man muss sich nur merken, ob die Auswahl für den Tag schon stattgefunden hat. Dieses Kriterium kann man dann auch in die Abfrage einsetzen.

        Dazu müsste die Tabelle dann eine Spalte für das Auswahldatum des Bildes haben.

        Beim Schreiben stellt man dann fest, ob die Tabelle schon einen Datensatz mit dem aktuellen Datum enthält. Wenn ja, wird das Update nicht durchgeführt, wenn nein, darf es durchgeführt werden und das Datum wird aktualisiert.

        Der erste, der schreibt, gewinnt dann. Das muss allerdings nicht der erste sein, der gelesen hat.

        Und wenn man die Date-Spalte mit einem Unique-Index belegt, würde jeder weitere Updateversuch mit demselben Datum abgelehnt werden.

        Vermutlich wird es aber konzeptionell sowieso besser sein, sowieso zwei Tabellen zu bentzen, eine für die Stammdaten und eine für die Bewegungsdaten.

        Liebe Grüße aus dem schönen Oberharz

        Tom vom Berg

        --
         ☻_
        /▌
        / \ Nur selber lernen macht schlau
        http://bergpost.annerschbarrich.de
  2. hi,

    Auf meiner Webseite wird täglich ein anderes Bild ausgegeben. Das Bild wird per Zufall aus einem Pool von Fotos ausgewählt. Der erste Benutzer der nach 0 Uhr die Webseite aufruft, stößt die Zufallsroutine an.

    Jetzt kommt es ab und zu vor, dass zwei Webseitenbesucher zur gleichen Zeit die Seite aufrufen und dann zwei Bilder für einen Tag ausgewählt werden.

    Deine "Zufallsroutine" würde ich mir gerne mal angucken.

    Hotti

  3. Moin!

    Das möchte ich verhindern, indem ich die Mysql-Tabelle, welche die Bildinformationen enthält, vor dem Update-Befehl sperre.
    Ist es richtig, wenn ich mit "LOCK tabelle; UPDATE tabelle; UNLOCK tabelle;" vorgehe?

    Nein, ist nicht hilfreich. UPDATE sperrt die Tabelle schon von sich aus, und da du nur genau ein UPDATE hast, kann es schon von daher nicht passieren, dass dir irgendwer dazwischenfunkt.

    Das Problem ist deine Logik zur Auswahl "des ersten Besuchers". Sowas ist im Web-Kontext zwingend als konkurrierende Situation zwischen mindestens zwei Requests zu betrachten, d.h. dass teilweise tatsächlich nur einen User hast, der dir das Bild auswählt, ist Zufall, aber nicht der Regelfall.

    Wie wählst du das Bild aus? Was tust du, um festzustellen, dass schon ein Bild ausgewählt wurde? Warum kann man pro Tag mehr als ein "das ausgewählte Bild für den Tag" wählen?

    - Sven Rautenberg

  4. Hallo,

    Wie andere schon angemerkt haben hast du das Problem dass du es zulässt dass zwei verschiedene Bilder in der Datenbank als das Bild des tages eingetragen werden können. Hier eine Lösungsmöglichkeit für dein Problem (die image_id 5 steht dabei für eine zufällige bild-ID aus deiner Bildertabelle):

    CREATE TABLE daily_image (  
        image_id INT NOT NULL,  
        date DATE,  
        PRIMARY KEY (date)  
    );  
      
    INSERT IGNORE INTO daily_image (image_id, date) VALUES (5, NOW());  
    ...1 row(s) affected  
      
    -- ausführen am gleichen Tag  
    INSERT IGNORE INTO daily_image (image_id, date) VALUES (5, NOW());  
    ...0 row(s) affected  
      
    -- ausführen am nächsten Tag  
    INSERT IGNORE INTO daily_image (image_id, date) VALUES (5, NOW());  
    ...1 row(s) affected
    

    Jeena

    1. Hi,

      CREATE TABLE daily_image (

      image_id INT NOT NULL,
          date DATE,
          PRIMARY KEY (date)
      );

        
      Dies entspricht btw im Wesentlichen meinem Vorschlag, einen Unique-Index zu setzen. Ob man die zusätzliche Tabelle braucht/will, sei dann das Entscheidungskriterium für eine der beiden Lösungen.  
        
      Bis die Tage,  
      Matti
      
      -- 
      [Webapplikationen in C++ entwickeln](http://tntnet.org/)
      
      1. Hallo,

        Dies entspricht btw im Wesentlichen meinem Vorschlag, einen Unique-Index zu setzen. Ob man die zusätzliche Tabelle braucht/will, sei dann das Entscheidungskriterium für eine der beiden Lösungen.

        Ja, ich wollte das nur in Quellcode gießen und das Stichword IGNORE mit ins Beispiel bekommen.

        Jeena

  5. Hallo,

    Auf meiner Webseite wird täglich ein anderes Bild ausgegeben. Das Bild wird per Zufall aus einem Pool von Fotos ausgewählt.

    kommt mir bekannt vor :-)

    Der erste Benutzer der nach 0 Uhr die Webseite aufruft, stößt die Zufallsroutine an.

    Ich ermittele das Zufallsbild über den Julianischen Tag und somit unabhängig vom ersten Zugriff nach 0 Uhr ...

    Freundliche Grüße

    Vinzenz

    1. Hallo,

      Ich ermittele das Zufallsbild über den Julianischen Tag

      Was ist daran denn Zufall?

      Jeena

      1. Hallo Jeena,

        Ich ermittele das Zufallsbild über den Julianischen Tag
        Was ist daran denn Zufall?

        ich initialisiere mit diesem Wert den Pseudozufallszahlengenerator :-)

        Freundliche Grüße

        Vinzenz

        1. Hallo,

          ich initialisiere mit diesem Wert den Pseudozufallszahlengenerator :-)

          Aber wenn ich dann die ersten drei bilder gesehen habe dann weiß ich ab da genau welches Bild wann kommt, ich war der Meinung dass genau das ist was er verhindern wollte und jeden Tag einzufälliges Bild zeigen wollte.

          Jeena