Problem Datenbankdesign, doppelte Wertevergabe verhindern

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

  • Problem Datenbankdesign, doppelte Wertevergabe verhindern

    Hallo,


    folgende Tabelle:
    Code:
    Spalte_Zaehler  ;  Spalte_TimeStamp  ;  Spalte_Aufruf_ID  ;  Spalte_Attribut  ;  Spalte_Attribut_Wert
    
    (auto_increment); (ON UPDATE CURRENT ;       (INT)        ;     (Varchar)     ;         (Text)
    (Primär)        ;     _TIMESTAMP)    ;                    ;
    
          1           2006-02-01 00:24:41          1            HTTP_REFERER            [url]http://localhost/[/url]
          2           2006-02-01 00:24:41          1            HTTP_ACCEPT_LANGUAGE    de
          3           2006-02-01 00:24:41          1            HTTP_USER_AGENT         Mozilla/4.0
          4           2006-03-03 00:24:41          2            HTTP_REFERER            [url]http://localhost/[/url]
          5           2006-03-03 00:24:41          2            HTTP_ACCEPT_LANGUAGE    de
          6           2006-03-03 00:24:41          2            HTTP_USER_AGENT         Mozilla/4.0
          7           2006-04-02 00:24:41          3            HTTP_REFERER            [url]http://localhost/[/url]
          8           2006-04-02 00:24:41          3            HTTP_ACCEPT_LANGUAGE    de
          9           2006-04-02 00:24:41          3            HTTP_USER_AGENT         Mozilla/4.0

    soll durch diese Schelife gefüllt werden:

    PHP-Code:
    foreach ($_SERVER as $key => $value
    {
     
    $sql 'INSERT INTO `Datenbank` 
                (`Spalte_Zaehler`, ` Spalte_TimeStamp`, ` Spalte_Aufruf_ID`, ` Spalte_Attribut`, ` Spalte_Attribut_Wert`) 
             VALUES 
                (NULL, NOW(), \''
    .$Aufruf_ID.', \' '.$key.'   \', \''   .  $value   .   '\');';
     
    $result mysql_query($sql$db);


    Das Array "$_SERVER" enthält immer mindestens die 3 Attribute ("HTTP_REFERER", "HTTP_ACCEPT_LANGUAGE", "HTTP_USER_AGENT") mit den dazugehörigen Werten, pro Aufruf der Schleife.
    Die Schleife wird immer durch Aufruf des PHP Skriptes aufgerufen.


    Die Spalt "Spalte_Aufruf_ID" soll immer eine Integer Nummer bekommen.
    Diese Nummer bekommen alle Datensätze die zu demselben Schleifendurchlauf gehören.
    Daran soll dann später erkannt werden welche Datensätze zusammengehören (von einem Seitenaufruf stammen).


    Jetzt habe ich dazu 2 Fragen:

    Der Ansatz sieht vor das:
    das Script sich die höchste Nummer aus der Spalte "Spalte_Aufrufer_ID" sucht,
    den um einen Wert erhöht und diesen
    Wert für den Schleifendurchlauf immer als Variable "$Aufruf_ID" benutzt.

    Frage A:
    Wie kann ich gewährleisten das:
    2 oder mehr zeitgleich erfolgende Aufrufe von 2 oder eben mehr Usern,
    die Integer Zahlen der Spalte "Spalte_Aufruf_ID" nicht doppelt vergeben werden?

    Kann es passieren das User A das scrippt aufruft,
    sich die höchste ID (Nummer) aus der Spalte "Spalte_Aufruf_ID" um 1 addiert und verwendet.
    Und dann anfängt den ersten Datensatz in die DB zu schreiben.
    User B aber auch kurz nach User A auf das Scrippt zugreift und
    bevor der erste Datensatz von User A in die Datenbank geschrieben wurde,
    sich das Scrippt auch die höchste ID (Nummer) aus der Spalte "Spalte_Aufruf_ID" holt und
    um eines erhöht.
    Problem:
    Jetzt müsste ja User A und User B dieselbe ID (Nummer) haben,
    weil noch nicht der erste Datensatz von User A in die Datenbank eingetragen wurde,
    bevor User B sich den aktuell höchsten Wert ausgelesen hat, oder?
    Wie kann ich das verhindern, dass User A Datensätze mit User B Datensätzen die Selber Aufruf_ID bekommen?

    Muss ich eine 2. Tabelle anlegen die immer die höchste Aufruf_ID enthält und
    bevor Datensätze in die Tabelle 1 geschrieben werden, erst hier in Tabelle 2
    der Aufruf_ID Counter um eines erhöht wird?

    Frage B:
    Ist es möglich durch bestimmt "gefälschte" Strings die in die Variablen $key (VARCHAR) und $value(TEXT)
    MySQL Befehle ausführen zu lassen? Kann also ein User mit gefälschten Strings für die Variablen Kontrolle
    über die Datenbank erhalten? Oder wird der Inhalt der Variabeln immer als Zeichenkette gewertet?
    Was passiert wenn der String in einer der Variablen ein Komma, Hochkomma, Semikolon oder andere Steuerzeichen enthält?
    Gibt es da einen Schutz / Funktion dafür?

    MfG

  • #2
    Mach einfach mehrere Spalten und vergiss die Aufruf_id.

    id, timestamp, referer, accept_language, users_agent, etc..,


    Wenn du sowas wirklich machen willst (was dich nachher bei der Abfrage in das reinste Chaos stürzen wird) benutze einfach im script uniqid() - damit hat dann jedes scritp seine eigene id und schreibt damit in die DB.

    Kommentar


    • #3
      Hallo Prego,

      Original geschrieben von prego
      Mach einfach mehrere Spalten und vergiss die Aufruf_id.

      id, timestamp, referer, accept_language, users_agent, etc..,
      das mit den mehreren Spalten ist so eine Sache. Ich wieß nicht was für Spalten ich benötige. Die hängt davon ab was der Webserver zurückgibt
      (das ist von den Einstellungen des Admins abhänig). Auch ist es vom User abhänig was es für Spalten gibt. Zum Beispiel hat ein User der hinter einer NAT sitz keine Spalte [HTTP_VIA] und auch keine Spalte [HTTP_X_FORWARDED_FOR], ein User der hinter einem Proxy in einem privaten Adressbereich sitzt hat dies Werte aber schon. Was aber sehr interessant ist. Diesen Unterschiede habe ich auch erst später durch testen ermittelt. Deshalb wolte ich erstmal das ein paar Tage lang so testen um zu sehen was alles für Attribute überhaupt möglich sind.

      Wenn du sowas wirklich machen willst (was dich nachher bei der Abfrage in das reinste Chaos stürzen wird) benutze einfach im script uniqid() - damit hat dann jedes scritp seine eigene id und schreibt damit in die DB.
      Mit "jedes Script seine eigene ID" meist du damit das Script A eine ID bekommt und Script B eine andere? Oder meinst du das jede Instanz eienes Scripte eine neue ID bekommt? Anhand dieser ID müsste ich dann ja unterscheiden ob die Datensätzte von User A oder von User B sind. Auch müsste die ID sich ändern wenn ein und der selbe Usder die Seite 2 oder mehrmals hintereinander aufruft.

      MfG

      Kommentar


      • #4
        Wie im anderen Thread schon geschrieben, bekommst du die Variablen die $_SERVER für dich bereit hält über PHP info.


        Mit uniqid() mein ich folgendes:

        PHP-Code:
        $id uniqid();


        $sql "INSERT INTO tab SET Aufruf_ID = '".$id."', feld1 = 'xy', etc.."

        Kommentar


        • #5
          Ich habe mir das hier zu
          uniqid() durchgelesen. Wie es scheint wird für Jeden Aufruf (Instanz) des Scriptes eine ID genneriert.

          Zu phpinfo();
          PHP-Code:
          <?php
           
          echo phpinfo();
          ?>
          kann ich aber keine Angaben finden wie [HTTP_X_FORWARDED_FOR] oder [HTTP_ACCEPT_LANGUAGE].

          Kommentar


          • #6
            Original geschrieben von php-linux-fan
            Ich habe mir das hier zu
            uniqid() durchgelesen. Wie es scheint wird für Jeden Aufruf (Instanz) des Scriptes eine ID genneriert.
            Ja, das ist doch genau das was du willst, oder nicht? Jedes Script das aufgerufen wird soll zu seiner laufzeit eine eindeutige ID haben...


            zu phpinfo();

            PHP-Code:
            <?php
             
            echo phpinfo();
            ?>
            kann ich aber keine Angaben finden wie [HTTP_X_FORWARDED_FOR] oder [HTTP_ACCEPT_LANGUAGE].
            Die wirst du natürlich dort nur finden wenn sie auch zur Verfügung stehen - will sagen: Wenn du PHP-Info über einen Proxy aufrufst und der Proxy die Information preis gibt wirst du die Variablen dort auch gefüllt sehen.

            Kommentar


            • #7
              Hi,

              genau dieses problem sahen auch andere schon vor dir.
              Aus sicht einer zweiten session ist das ein dirty-read.
              Aus sicht der ersten session ist das ein non-repeatable read.
              Dafür gibt es isolation-levels innerhalb von transaktionen in modernen
              rdbms.

              greets
              (((call/cc call/cc) (lambda (x) x)) "Scheme just rocks! and Ruby is magic!")

              Kommentar


              • #8
                Original geschrieben von closure
                Hi,

                genau dieses problem sahen auch andere schon vor dir.
                Aus sicht einer zweiten session ist das ein dirty-read.
                Aus sicht der ersten session ist das ein non-repeatable read.
                Dafür gibt es isolation-levels innerhalb von transaktionen in modernen
                rdbms.

                greets
                Köntest du das etwas näher erklären?

                Kommentar

                Lädt...
                X