T-Rex: Id Sicherheit vor commit bei einer Transaktion

start_posting();

Ich starte eine Transaktion.
Dann speichere ich einen neuen Datensatz in die Datenbank.
Jetzt lasse ich mir die Id des Datensatzes zurück geben.
Mit der Id mache ich noch weitere Sachen.
Jetzt mache ich einen Commit.

Kann ich mich auf die Id verlassen oder kann die sich nach dem Commit und dem tatsächlichen Eintrag in die Datenbank nochmal ändern?

Gruß
T-Rex
commit();

  1. hi,

    Kann ich mich auf die Id verlassen oder kann die sich nach dem Commit und dem tatsächlichen Eintrag in die Datenbank nochmal ändern?

    Wenn mysql und last_insert_id() denke daran: last_insert_id() ist auf die DB-Session bezogen. D.h., wenn jeder Prozess seine eigene DB-Session bekommt, ist alles ok.

    Wenn sich allerdings mehrere Prozesse eine DB-Session teilen, knallts.

    Horst

    1. Wenn mysql und last_insert_id() denke daran: last_insert_id() ist auf die DB-Session bezogen. D.h., wenn jeder Prozess seine eigene DB-Session bekommt, ist alles ok.

      Und woher soll ich jetzt wissen ob jeder Prozess eine eigene DB-Session bekommt?

      Gruß
      Prozess beginnender
      T-Rex

      1. Wenn mysql und last_insert_id() denke daran: last_insert_id() ist auf die DB-Session bezogen. D.h., wenn jeder Prozess seine eigene DB-Session bekommt, ist alles ok.

        Und woher soll ich jetzt wissen ob jeder Prozess eine eigene DB-Session bekommt?

        Es kann Probleme geben bei persistenten DB-Sessions (DB-Handle), also DB-Sessions, die vor einem Prozessbeginn bereits etabliert sind. Mehrere Prozesse teilen sich dann die DB-Session, so kann es passieren, dass ein Prozess die last_insert_id() von einem anderen Prozess erfährt (in einer mir bekannten Fa kam sowas öfter vor, ich musste dann mühsam die binlogs auswerten zum Rekonstruieren von verlorengegangenen Warenkörben).

        Wenn jeder Prozess seine eigene DB-Session herstellt, kann sowas nicht passieren.

        Viele Grüße!

        1. Woher soll ich jetzt wissen ob jeder Prozess eine eigene DB-Session bekommt?

          Gruß
          Repeater
          T-Rex

          1. Woher soll ich jetzt wissen ob jeder Prozess eine eigene DB-Session bekommt?

            Frag den Programmierer der DB-Anwendung ;)

            PS: Auf der Konsole

            mysql dbname

            mysql> hier hast Du eine DB-Session
            mysql>\q

            _

      2. Hello T-Rex,

        Wenn mysql und last_insert_id() denke daran: last_insert_id() ist auf die DB-Session bezogen. D.h., wenn jeder Prozess seine eigene DB-Session bekommt, ist alles ok.

        Und woher soll ich jetzt wissen ob jeder Prozess eine eigene DB-Session bekommt?

        *Hä?*

        Das bestimmst Du doch als Programmierer, ob eine Datenbankverbindung besteht, oder nicht. Und solange sie besteht, werden die Queries auch mit demselben Cache ausgeführt, es sei denn, der Programmierer verlangt dediziert einen neuen. Die API von PHP nimmt auch darauf Rücksicht und leitet mWn auch alle dementsorechenden Anfragen transparent weiter und meldet die Ergebnisse zurück im Request/Error-Status

        Im Webumfeld (HTTP/s) solltest Du immer damit rechnen, dass jeder Request eine neue Datenbankverbindung aufbauen muss. Das ist für das "Update-Management" besonders interessant, weil man da erkennen muss, ob zwischen dem Lesen eines Datensatzes (Request 1) und dem Zurückschreiben irgendwelcher Änderungen (Request 1+n) schon Änderungen durch Dritte stattgefunden haben.

        Da hilft auch keine "Transaktion". Da hilft nur Nachdenken (*g*)

        Liebe Grüße aus dem schönen Oberharz

        Tom vom Berg

        --
         ☻_
        /▌
        / \ Nur selber lernen macht schlau
        http://bikers-lodge.com
  2. Hallo T-Rex,

    Ich starte eine Transaktion.

    wie?

    Dann speichere ich einen neuen Datensatz in die Datenbank.

    wie?

    Jetzt lasse ich mir die Id des Datensatzes zurück geben.

    was bedeutet "jetzt"? Hier ist doch schon viel Zeit vergangen

    Mit der Id mache ich noch weitere Sachen.

    ist sie hübsch? *scnr*

    Jetzt mache ich einen Commit.

    Du veranlasst einen Commit, aber wie das Ganze ablaufen soll, weiß bisher nur die NSA?

    Kann ich mich auf die Id verlassen oder kann die sich nach dem Commit und dem tatsächlichen Eintrag in die Datenbank nochmal ändern?

    Du kannst Dich auf das Self-Forum verlassen, auf niy sonst!

    Nun meine Fragen:

    Welches DBMS
    Wie findet der Zugriff statt? -> Protokoll!

    Welche weiteren Randbedingungen müssen beachtet werden?
    * mehrere gleichzeitige User auf der Datenbank?
    * hoher Datenbank-Traffic?
    * viele Veränderungen pro Zeiteinheit?

    Transaktionen sind üblicherweise nur in zustandsorientierten Systemen bei verbindungsorientierten Protokollen sinnvoll- Liegen diese Voraussetzungen bei Dir vor, oder erstrecken sich die Aktionen vielleicht über mehrere Roundturns einer HTTP/s-Sitzung?

    Mit grinsenden Grüßen

    GdG

    1. Ich starte eine Transaktion.

      wie?

      Meiner Ansicht nach ist das nicht relevant - aber wenn es dir hilft mittels php pdo transaction.

      Dann speichere ich einen neuen Datensatz in die Datenbank.

      wie?

      Meiner Ansicht nach ist das nicht relevant - aber wenn es dir hilft mittels php pdo exec.

      Jetzt lasse ich mir die Id des Datensatzes zurück geben.

      was bedeutet "jetzt"? Hier ist doch schon viel Zeit vergangen

      Meiner Ansicht nach ist das nicht relevant - aber wenn es dir hilft es ist sehr kurz.

      Mit der Id mache ich noch weitere Sachen.

      ist sie hübsch? *scnr*

      Meiner Ansicht nach ist das nicht relevant - aber wenn es dir hilft hübscher als du.

      Jetzt mache ich einen Commit.

      Du veranlasst einen Commit, aber wie das Ganze ablaufen soll, weiß bisher nur die NSA?

      Was soll wie ablaufen? Transaction starten und mittels commit abschliessen. Gibt es da so viele unterschiedliche verfahren?

      Nun meine Fragen:

      Welches DBMS

      MySQL 5.irgendwas.

      Wie findet der Zugriff statt? -> Protokoll!

      http

      Welche weiteren Randbedingungen müssen beachtet werden?

      Keine Ahnung?

      * mehrere gleichzeitige User auf der Datenbank?

      Nein

      * hoher Datenbank-Traffic?

      Das Spielt denke ich keine Rolle, da selbst 2 Verarbeitungen im Monat sich in die Quere kommen könnten. Die Chancen sind zwar nicht besonders groß aber theoretisch möglich.

      * viele Veränderungen pro Zeiteinheit?

      Meiner Ansicht nach ist das nicht relevant - aber wenn es dir hilft aktuell so gut wie gar nichts.

      Transaktionen sind üblicherweise nur in zustandsorientierten Systemen bei verbindungsorientierten Protokollen sinnvoll- Liegen diese Voraussetzungen bei Dir vor, oder erstrecken sich die Aktionen vielleicht über mehrere Roundturns einer HTTP/s-Sitzung?

      Also meine Frage ist natürlich durch ein aktuelles Projekt / Problem geboren. Dennoch hoffe ich dass man eine generelle Antwort treffen kann. Was ich nicht möchte ist, dass bei script a.php eine transaktion gestartet wird und bei b.php wird sie beendet. Es spielt sich alles innerhalb eines Scriptaufrufes ab. Um genau zu sein werden zwei aufeinander aufbauende Datensätze erstellt. Da der eine ohne den anderen nicht sinnvoll ist wollte ich um das Ganze Speichern eine Transaktion bauen und sie nur commiten wenn beide Speichervorgänge erfolgreich sind. Da der eine Datensatz die Id des anderen beinhaltet frage ich doch mal lieber wie sicher die Id ist. Eventuell ändert sich die Id ja, nach dem commit. Dann wäre die Referenz zerstört.

      Mit antwortendem Gruß
      T-Rex

      1. Hallo T-Rex,

        Deine Antwort ist - mit Verlaub - eine Unverschämtheit sondergleichen!

        Meiner Ansicht nach ist das nicht relevant - [...]
        Meiner Ansicht nach ist das nicht relevant - [...]
        Meiner Ansicht nach ist das nicht relevant - [...]
        Meiner Ansicht nach ist das nicht relevant - [---]

        Was soll wie ablaufen? Transaction starten und mittels commit abschliessen. Gibt es da so viele unterschiedliche verfahren?

        Nun meine Fragen:

        Welches DBMS

        MySQL 5.irgendwas.

        Aha!

        Wie findet der Zugriff statt? -> Protokoll!

        http

        Aha!

        Und finden die gesamten Datenbankaktionen innerhalb eines einzigen Requests statt?

        Welche weiteren Randbedingungen müssen beachtet werden?
        Keine Ahnung?

        Schon scheiße! Darüber verschafft man sich üblicherweise zuerst einen Überblick

        * mehrere gleichzeitige User auf der Datenbank?
        Nein

        Achso, Du übst nur und willst niemals einne Produktivzustand erreichen?

        * hoher Datenbank-Traffic?
        Das Spielt denke ich keine Rolle,

        Du hast doch gefragt, um herauszufinden, was Andere denken. Warum also jetzt diese Aussage?

        da selbst 2 Verarbeitungen im Monat sich in die Quere kommen könnten.

        Aha! Die Verbindung zur Datenbank fpe den einen Request / die eine Requestgruppe (an die Datenbank) bleibt also ggf. mehrere Monate aktiv?

        Die Chancen sind zwar nicht besonders groß aber theoretisch möglich.

        Chancen sind immer möglich - darum sind es Chancen.
        Ich übersetze jetzt mal: Konflikte sind möglich.
        Wie hoch die Wahrscheinlichkeit für Konflikte ist generell egal, wenn man sie vermeiden kann!

        * viele Veränderungen pro Zeiteinheit?
        Meiner Ansicht nach ist das nicht relevant - aber wenn es dir hilft aktuell so gut wie gar nichts.

        Aha!

        Transaktionen sind üblicherweise nur in zustandsorientierten Systemen bei verbindungsorientierten Protokollen sinnvoll- Liegen diese Voraussetzungen bei Dir vor, oder erstrecken sich die Aktionen vielleicht über mehrere Roundturns einer HTTP/s-Sitzung?

        Also meine Frage ist natürlich durch ein aktuelles Projekt / Problem geboren. Dennoch hoffe ich dass man eine generelle Antwort treffen kann. Was ich nicht möchte ist, dass bei script a.php eine transaktion gestartet wird und bei b.php wird sie beendet. Es spielt sich alles innerhalb eines Scriptaufrufes ab. Um genau zu sein werden zwei aufeinander aufbauende Datensätze erstellt. Da der eine ohne den anderen nicht sinnvoll ist wollte ich um das Ganze Speichern eine Transaktion bauen und sie nur commiten wenn beide Speichervorgänge erfolgreich sind. Da der eine Datensatz die Id des anderen beinhaltet frage ich doch mal lieber wie sicher die Id ist. Eventuell ändert sich die Id ja, nach dem commit. Dann wäre die Referenz zerstört.

        Also Transaktion innerhalb eines Requests an die API, der dann die x Requests an die DB auslösen soll?

        Da kann man viele Probleme schon beim Design des Datenmodells - strikte Trennung von Stammdaten und Bewegungsdaten -  vermeiden. Und wenn denn keine anderen Requests gleichzeitig zu erwarten sind, kann man sich die Transaktion normalerweise schenken. Da reicht es, die betroffenen Tabellen _vorher_ gegen andere Zugriffe zu sperren.

        Mit lieblich säuselndem Antwortgruß

        RdG

        1. Moin!

          Hallo T-Rex,

          Deine Antwort ist - mit Verlaub - eine Unverschämtheit sondergleichen!

          Nein. DEINE Antwort ist eine Unverschämtheit.

          Und zeugt auch von wenig Sachverstand, denn das hier:

          Da kann man viele Probleme schon beim Design des Datenmodells - strikte Trennung von Stammdaten und Bewegungsdaten -  vermeiden. Und wenn denn keine anderen Requests gleichzeitig zu erwarten sind, kann man sich die Transaktion normalerweise schenken. Da reicht es, die betroffenen Tabellen _vorher_ gegen andere Zugriffe zu sperren.

          ist Bullshit!

          Das Anwendungsszenario ist vollkommen "normal": In einer normalisierten Datenbank trägt man in der einen Tabelle einen Datensatz ein und erfragt die dabei erzeugte ID, und in einer zweiten Tabelle trägt man die dazu 1:n befindlichen weiteren Daten ein. Ganz offensichtlich ist unerwünscht und nicht sinnvoll, nur eine der beiden Tabellen zu befüllen. Ebenfalls ist es nicht sinnvoll, zuerst schon den einen Datensatz der ersten Tabelle für parallele Querys "sichtbar" zu machen ohne die weiteren Daten in die zweite Tabelle eingetragen zu haben.

          Insofern ist es absolut normal, den Vorgang in einer Transaktion zu kapseln.

          Du hättest in einer hilfreichen Antwort den guten T-Rex auf die MySQL-Dokumentation hinsichtlich der Erzeugung von auto_increment-Werten bei Transaktionen verweisen können. Beispielsweise dieser Link: https://dev.mysql.com/doc/refman/5.1/en/innodb-auto-increment-handling.html

          Wie man nachlesen kann, reserviert MySQL/InnoDB beim INSERT den nächsten Increment-Wert global (parallele oder später startende Transaktionen nehmen also den nächsthöheren Wert). Dieser wird dann dem neuen Datensatz zugewiesen. Bricht man die Transaktion ab (ROLLBACK), wird der Increment-Wert nicht wieder reduziert, sondern er ist verbraucht. Auf diese Weise entstehen Lücken in den IDs, was aber nichts macht, weil die ja nicht zum Durchzählen gedacht sind, sondern zum Identifizieren.

          Transaktionen kann man sich nur schenken, wenn man den Vorgang in exakt einem Query durchführen kann (oder Inkonsistenzen egal sind). Bei InnoDB führt dies automatisch zu einer nur den Query umfassenden Transaktion. Es ist allerdings gelegentlich hilfreich, auch mehrere gleichartige, voneinander im Prinzip unabhängige Querys innerhalb einer einzigen Transaktion durchzuführen, denn das Kapseln hat vermutlich Performancevorteile.

          Ganz verkehrt hingegen ist das Sperren der Tabelle. Damit tötet man die Performance allemal. Warum hattest du eigentlich nachgefragt, ob hoher DB-Traffic und viele parallele Connections vorliegen?

          - Sven Rautenberg

          1. Hello Sven,

            ist Bullshit!

            Das ist schon interessant, wie Du einen Beitrag zur passenden Fragetechnik als "Bullshit" klassifizierst. Ich kann mich an Postings erinnern, in denen Du zuerst nach dem Datenbanksystem gefragt hast.

            Es ist doch keinesfalls in jedem Datenbanksytem notwenig, immer gleich eine "Transaktion" zu starten. Es soll - meiner Erkenntnis nach - sogar Datenbanksystem geben, die die referenzielle Integrität, um die es hier augenscheinlich geht, von Haus aus unterstützten.

            Da wird dann das Statement (der Request), nebst automatisch ausgeführter Sub-Statements ohnehin gekaplselt.

            Die Rückfrage von Gerd, ob es sich hier um gebundene Statements oder um mehrere Roundturns zum selben Datenbank-Szenario in einem Webumfeld (in diesem Kontext befindet sich schließlich unser Forum) handelt, empfinde ich als absolut legitim und keinesfalls als "Bullshit".

            Könntest Du bitte zu deiner alten Güte mit der gewohnten Qualität zurückfinden?

            Liebe Grüße aus dem schönen Oberharz

            Tom vom Berg

            --
             ☻_
            /▌
            / \ Nur selber lernen macht schlau
            http://bikers-lodge.com
            1. Moin!

              Hello Sven,

              ist Bullshit!

              Das ist schon interessant, wie Du einen Beitrag zur passenden Fragetechnik als "Bullshit" klassifizierst. Ich kann mich an Postings erinnern, in denen Du zuerst nach dem Datenbanksystem gefragt hast.

              Das stellt sich nur so dar, wenn man mein Zitat aus dem Zusammenhang reißt.

              Wie unzweifelhaft nachzulesen ist, kritisiere ich die Kritik ("Unverschämtheit") an der Antwort als Unverschämtheit, und die inhaltliche Einlassung auf die gestellte Frage als Bullshit.

              Es ist doch keinesfalls in jedem Datenbanksytem notwenig, immer gleich eine "Transaktion" zu starten. Es soll - meiner Erkenntnis nach - sogar Datenbanksystem geben, die die referenzielle Integrität, um die es hier augenscheinlich geht, von Haus aus unterstützten.

              Es ist gefragt:

              • Ich starte eine Transaktion.
              • Die last_insert_id() vom ersten INSERT merke ich mir.
              • Verwende sie für weitere INSERTs.
              • Dann ein COMMIT.
              • Ändert sich bei dieser Aktion eventuell die ID vom ersten INSERT so, dass die weiteren INSERTs das mitbekommen sollten, aber nicht tun?

              * Nachfragen... *

              • DBMS ist MySQL 5

              In dieser Situation _kann_ man natürlich antworten: "Du brauchst überhaupt keine Transaktion, weil du ja kaum Traffic hast, der Query nur einmal im Monat standalone ausgeführt wird, und bei IrgendwasSQL werden sie auch garnicht unterstützt, also was reden wir hier - speichere doch direkt in eine Textdatei, dann brauchst du nichtmal die ID!"

              Da wird dann das Statement (der Request), nebst automatisch ausgeführter Sub-Statements ohnehin gekaplselt.

              Das ist genau der Punkt, den ich beantwortet habe, den du aber anscheinend übersehen hast:

              INSERT INTO a SET name = "foo";
              x = SELECT last_insert_id();
              INSERT INTO b SET friend = "bar", a_id = x;
              INSERT INTO b set friend = "baz", a_id = x;

              Diese Abfolge kann man mit und ohne Transaktion ausführen.

              Ohne Transaktion gibt es einen Zeitraum, in dem "foo" für den Rest der Datenbankwelt ohne Freunde dasteht, oder nur "bar" als Freund hat.

              Ich finde es absolut nicht verkehrt, sich darüber Gedanken zu machen.

              Zumal das Starten einer Transaktion auch verhindert, dass die DB dreimal einzelne Schreibzugriffe wirksam werden lassen muss. Zumindest der Schreibzugriff auf "b" meines Beispiels wird aggregiert werden und ZWEI Einträge gleichzeitig abarbeiten, nicht zweimal nur einen.

              Die Rückfrage von Gerd, ob es sich hier um gebundene Statements oder um mehrere Roundturns zum selben Datenbank-Szenario in einem Webumfeld (in diesem Kontext befindet sich schließlich unser Forum) handelt, empfinde ich als absolut legitim und keinesfalls als "Bullshit".

              Wie gesagt: Die Rückfragen habe ich nicht kritisiert. Die Kritik an den Antworten als "Unverschämtheit" kritisiere ich als Unverschämtheit, und die mangelhafte fachliche Qualität des restlichen Antwortversuchs als Bullshit.

              Könntest Du bitte zu deiner alten Güte mit der gewohnten Qualität zurückfinden?

              Auf Stackoverflow hätte ich Gerd's Antwort als nicht hilfreich abgewertet, dies evtl. entsprechend kommentiert, um meine Ansicht zu erläutern, und vermutlich die Antwort auch als "offensive, abusive or hate speech" geflaggt - Moderatoren hätten sich dann über eine Löschung Gedanken machen müssen. Das sind dort die vorgesehenen Mittel, um mit Nicht-Qualitätsantworten umzugehen.

              Hier muss man sich argumentativ mit dem Gegenüber auseinandersetzen - das heißt aber nicht, dass man jegliche Art von schlechten Antworten durchgehen lassen sollte. Fachlich schlechte Antworten, die einfach inhaltlich verbesserungsfähig sind aufgrund mangelnden Wissens oder durch Verbreitung von nicht mehr aktuellen Techniken, kann man tolerieren - also so stehen lassen, ohne dass es zu Verwerfungen im Universum kommt, andere können ja auch bessere inhaltliche Antworten geben.

              Toleranz hört bei mir auf, wenn ungerechtfertigt auf der persönlichen Ebene kritisiert wird. Und dies sehe ich hier als gegeben an. Ich empfinde es halt so, dass "Gerd" sich mit seiner "Unverschämtheit"-Antwort auf ein sehr hohes Ross setzt. Er hätte dieses eine Statement aber so stehen lassen können. Stattdessen schießt er sich selbst im hohen Bogen von seinem Ross, indem er dann auch noch eine schlechte fachliche Antwort hinzufügt.

              Meine eigene Antwort enthält natürlich dieselben Elemente, allerdings eröffne ich die persönliche Ebene nicht, sondern setze sie fort, und ich versuche, im Sinne des Fragenstellers eine korrekte Antwort zu geben. "Bullshit" verstehe ich in diesem Sinne als pauschal extrem negativ abwertende Kritik am fachlichen Teil - gekennzeichnet durch die Einrahmung des Zitats. Begründung dann nachfolgend.

              - Sven Rautenberg

          2. Wow also erstmal super Danke für deine Antwort !

            Wenn eine Transaction eine Id verbraucht, schätze ich ist die Id sicher. Zudem scheint mein kleiner Test wohl nicht besonders Seriös gewesen zu sein, da ich glaube beobachtet zu haben, dass die Id zurück gesetzt wird.

            Die Idee, keine Transaction zu benutzen sondern einen "großen" Query mit zwei Speicherungen klingt natürlich interessant. Dass wirft bei mir aber die Frage auf, wie ich die erzeugte Id der ersten Speicherung in den zweiten Query bekomme ohne eine zwischen Abfrage. Bei mir wären das Drei Zeilen php code:

            • speichere Query 1
            • hol id und füge in Query 2
            • speichere Query 2

            ******

            Hab beim verfassen dieses Artikels die Lösung auch gleich gefunden und möchte sie allen anderen suchenden nicht vorenthalten

            INSERT INTO foo (auto,text)
                VALUES(NULL,'text');         # generate ID by inserting NULL
            INSERT INTO foo2 (id,text)
                VALUES(LAST_INSERT_ID(),'text');  # use ID in second table

            http://dev.mysql.com/doc/refman/5.0/en/getting-unique-id.html

            *****

            Mal gucken wie das in mein Framework passt. Ich glaube der Einfachheit halber bleibe ich doch erstmal bei Transaktionen.

            Gruß
            Last insert
            T-Rex

      2. Mahlzeit,

        Wie findet der Zugriff statt? -> Protokoll!

        http

        Das halte ich für absolut unmöglich.

        --
        42
  3. Kann ich mich auf die Id verlassen oder kann die sich nach dem Commit und dem tatsächlichen Eintrag in die Datenbank nochmal ändern?

    ich würde jetzt mal sagen, du kannst dich darauf verlassen, wenn wir über dasselbe reden.

    die datenbank kann ja nicht einfach nach belieben eine andere id nehmen, dann müsste jeglicher code, den ich bisher mit transactions geschrieben habe, in den mülleimer wandern.

    1. ich würde jetzt mal sagen, du kannst dich darauf verlassen, wenn wir über dasselbe reden.

      die datenbank kann ja nicht einfach nach belieben eine andere id nehmen,

      Ja der Ansicht bin ich eigentlich auch. Nach meinem Verständnis müssten doch so Lücken entstehen?
      Ein Beispiel:

      • Eine Transaction wird gestartet
      • Datensatz wird gespeichert - Id wird reserviert
      • Anderer Request kommt -> Datensatz wird gespeichert mit einer höheren Id
      • Transaction wird verworfen - reservierte Id wird wieder frei gegeben

      Und schwups wurde eine Id ausgelassen.
      Oder werden solche Lücken mitprotokolliert und beim nächsten mal gefüllt?

      Auf der anderen Seite sagst du ja du hast Erfahrung mit Transactionen. Demnach kann man sich darauf verlassen. Wie das jetzt genau umgesetzt ist wissen hoffentlich die DBMS Programmierer.

      Auf jeden Fall Danke für deine Antwort!

      Gruß
      *Lücke*
      T-Rex

      1. Moin,

        Und schwups wurde eine Id ausgelassen.

        je nach Isolationstufe wird die Tabelle für's Schreiben gesperrt. Es sollten somit keine Lücken entstehen.

        1. Hello Susi,

          Und schwups wurde eine Id ausgelassen.

          je nach Isolationstufe wird die Tabelle für's Schreiben gesperrt. Es sollten somit keine Lücken entstehen.

          *hups*

          was ist denn eine "Isolationsstufe"? Ich kann mir nichts darunter vorstellen.

          Und wann, wielange durch wen und warum wird eine Tabelle fürs Schreiben gesperrt? Und durch wen und wann wird die Sperre wieder aufgehoben?

          Man bedenke: Der User aus der HTTP-Verbindung 1 kann zwar in der HTTP-Verbindung 97 wiedererkannt werden, muss aber bis zum Sankt-Nimmerleins-Tag nicht wieder auftauchen.

          Wenn man also keine "academic locks" benutzt, können leicht "lost locks" entstehen, abgesehen davon, dass "normale Datenbanken" die physischen Locks freigeben, wenn die Verbindung gelöst wird - hier also, wenn der HTTP-Request abschließend beantwortet wurde. Logische Locks müssen also in "akademischer Weise" kontrolliert werden, ob sie noch Bestand haben.

          Liebe Grüße aus dem schönen Oberharz

          Tom vom Berg

          --
           ☻_
          /▌
          / \ Nur selber lernen macht schlau
          http://bikers-lodge.com
          1. Moin,

            eigentlich habe ich mehr aus dem Bauch heraus geantwortet, was sicherlich nicht immer die beste Idee ist, ohne mir den ganzen Thread durchzulesen. Im Nachhinein ist mein Beitrag aber nicht gänzlich falsch und führt uns bei Transaktionen zum "Isolation Level" (Isolationsstufe).

            Die MYSQL-Doku sagt, dass im ISO das Level SERIALIZABLE (höchste Transaktionssicherheit) als Standard gesetzt ist, MYSQL aber die nächste niedrigere Stufe nutzt (REPEATABLE READ glaub ich war's). Das bezieht sich alles auf Transaktionen, wenn man denn eine durchführen möchte. Das je nach Isolationsstufe nicht nur Tabellen für's Lesen/Schreiben gesperrt werden können, sondern auch Zeilen, und dass es auch noch Zeilenversionen gibt/geben kann, und das es auch in den Tabellen selbst festgelegt werden kann, und dass es auch noch verteilte Transaktionen gibt ... na das kann man alles "ergoogeln", ich wollte das nur mal erwähnen. Die Dirty Reads und Phantome hast du ja schon erwähnt.

            Letztendlich ist das total wurscht, denn es ging ja um ein AUTO_INCREMENT, und ob hier Lücken (in der definierten Abstufung) entstehen. Ja die enstehen spätestens dann, wenn man den betreffenden Datensatz löscht.

            Wenn T-Rex meint, er hätte beobachtet, dass die ID nicht wieder frei gegeben wird, dann liegt das wahrscheinlich daran, dass beim manuellen Rollback last_insert_id() im Geltungsbereich der Sitzung nicht zurückgesetzt wird.

            Und wann, wielange durch wen und warum wird eine Tabelle fürs Schreiben gesperrt? Und durch wen und wann wird die Sperre wieder aufgehoben?

            Solange wie die Transaktion halt dauert :P
            Man sollte sich halt wirlich überlegen, ob man jetzt eine Transaktion braucht und wie hoch das Bedürfnis an Integrität ist. Wobei .. Integrität .. da denke ich eher an Fremdschlüssel, wieder aus dem Bauch heraus.

            Wenn man also keine "academic locks" benutzt ...

            Habe ich noch nicht gehört, ich vermute mal du beziehst dich hier auf die Logik im Programm? Am besten noch einen Timestamp abspeichern und dann nach 1 - 2 Tagen die Daten abgrasen/filtern. Gehört für mich in den Workflow.

            Gruß

            1. Hello,

              Wenn man also keine "academic locks" benutzt ...

              Habe ich noch nicht gehört, ich vermute mal du beziehst dich hier auf die Logik im Programm? Am besten noch einen Timestamp abspeichern und dann nach 1 - 2 Tagen die Daten abgrasen/filtern. Gehört für mich in den Workflow.

              Das ist eigentlich nur ein Spitzname für eine Sperre "ct", die also mit langer Verzögerung wirkt. Und es ist auch nur dann eine wirkliche Sperre, wenn die Datenbank das Verfahren unterstützt. Das konnten bereits frühe Versionen von bTrieve... MySQL unterstützt es allerdings nicht, da muss man sich das selber basteln, am besten mit Triggers oder strored Procedures.

              Es bezieht sich auf datenverändernde Aktionen, also in der Hauptsache UPDATE; DELETE gehört  auch dazu.

              Bevor man einen Datensatz ändern darf, muss man ihn sich geholt haben und zusammen mit den Daten den "Conflict-Counter" (so hieß das bei bTrieve) auslesen.

              Beim Zurückschreiben wird geprüft, ob der Zähler noch identisch ist und er wird dann erhöht. Wenn nein, wird das Schreiben eben abgelehnt. Bei MySQL realisiere ich das i. d. R. so, dass ich aus dem Zähler einen MD5-Hash bilde und an den Client (oder besser in dessen Session) mit ausliefere. Das verhindert Manipulation. Dass ein Hash doppelt auftritt uind so zum Zähler passt, sollte relativ unwahrscheinlich sein.

              Aber wie schon erwähnt, das ist nur eine Absicherung für zustandslose Protokolle, also eben fürs Web.

              Wenn es hier, aus welchem Grunde auch immer, um echte Transaktionen ging, dann vergiss meine Rede wieder.

              Liebe Grüße aus dem schönen Oberharz

              Tom vom Berg

              --
               ☻_
              /▌
              / \ Nur selber lernen macht schlau
              http://bikers-lodge.com
      2. Om nah hoo pez nyeetz, T-Rex!

        Und schwups wurde eine Id ausgelassen.
        Oder werden solche Lücken mitprotokolliert und beim nächsten mal gefüllt?

        Warum denkst du, das sei notwendig?

        Matthias

        --
        Der Unterschied zwischen Java und JavaScript ist größer als der zwischen XING und Xingyiquan.

        1. Und schwups wurde eine Id ausgelassen.
          Oder werden solche Lücken mitprotokolliert und beim nächsten mal gefüllt?

          Warum denkst du, das sei notwendig?

          Naja wenn es eine hoch frequentierte Datenbank ist können die Lücken schnell auswachsen. Bei Auto increment Ids vergeudet man somit Nummern.

          Gruß
          T-Rex1
          T-Rex2
          T-Rex3

          1. Naja wenn es eine hoch frequentierte Datenbank ist können die Lücken schnell auswachsen. Bei Auto increment Ids vergeudet man somit Nummern.

            Welche Datenmengen erwartest du? Wie oft erwartet du, dass eine Transaktion abgebrochen werden muss und eine Lücke entsteht?

            Auto Increment IDs mit Lücken sind für die Performance kein Problem, solange die Lücken einigermassen gleichmässig sind. Gibt es aber unregelmässige große Lücken, und die Datenbank erwartet bei binärer Suche über den Index eine gewissen Gleichmässigkeit, dann kostet das vielleicht ein bisschen was.

            Wenn du Lücken ausschliessen willst, musst du dir dein Auto Increment selbst basteln. Ist auch nichts abwegiges.

            1. Hello,

              Naja wenn es eine hoch frequentierte Datenbank ist können die Lücken schnell auswachsen. Bei Auto increment Ids vergeudet man somit Nummern.

              Das macht aber gar nix...

              Welche Datenmengen erwartest du? Wie oft erwartet du, dass eine Transaktion abgebrochen werden muss und eine Lücke entsteht?

              gute Frage. WEnn man bedenkt, dass man heutzutage den Upload von Bildern (also über das Internet) mit 16MB und mehr als "normal" ansieht, kann die Verarbeitung eines Index mit 16MB Größe (lokal) doch wohl keine ernsthafte Gefahr mehr darstellen, oder?

              Blöd wird es nur, wenn der Index "unbalancend" (je nach verwendetem System) wird, was Du wohl mit "größeren Lücken" gemeint haben könntest.

              Für reale Projekte jenseits von NSA und ähnlichen Diensten sehe ich persönlich da aber keinerlei Probleme. Um ein Rechnenzentrum platt zu machen, wie es z.B. Strato bereithält, muss man schon einige Hundert Besucher (x 100 Folgeanfragen) pro Sekunde haben.

              Liebe Grüße aus dem schönen Oberharz

              Tom vom Berg

              --
               ☻_
              /▌
              / \ Nur selber lernen macht schlau
              http://bikers-lodge.com
            2. Welche Datenmengen erwartest du? Wie oft erwartet du, dass eine Transaktion abgebrochen werden muss und eine Lücke entsteht?

              Das ist die richtige Frage!
              Wenn zu viele Lücken entstehen ist das mein Problem und nicht die von MySQL.

              Danke an (fast) alle für euren Fachkenntnis und Menschenverstand.

              Gruß
              fröhlicher Mensch
              T-Rex

      3. hi T-Rex,

        Ein Beispiel:

        • Eine Transaction wird gestartet
        • Datensatz wird gespeichert - Id wird reserviert
        • Anderer Request kommt -> Datensatz wird gespeichert mit einer höheren Id
        • Transaction wird verworfen - reservierte Id wird wieder frei gegeben

        Eine id = last_insert_id() bekommst Du vor dem commit(). Wenn die Transaktion nicht committed wird, wird die id verworfen.

        Du kannst jedoch mal prüfen, ob bei einem rollback() die id wieder freigegeben wird (ich vermute: nein).

        Fossile Grüße,
        Dino

        --
        Also die Dinos immer größer wurden... war das ihr Ende, gesiegt hat die Schwerkraft.
        1. Du kannst jedoch mal prüfen, ob bei einem rollback() die id wieder freigegeben wird (ich vermute: nein).

          Soweit ich das beurteilen kann - doch.

          Gruß
          Als die Hotties immer heißer wurden, wurden sie zu Sonnen und am Ende zu schwarzen Löchern - also würde ich keine Witze bezüglich der Schwerkraft reißen
          T-Rex

          1. hi T-Rex;

            wir Dinos sollten besser zusammenhalten ;)

            Als die Hotties immer heißer wurden, wurden sie zu Sonnen und am Ende zu schwarzen Löchern - also würde ich keine Witze bezüglich der Schwerkraft reißen

            Die Kunst des Lebens besteht u.a. auch darin, an todernsten Dingen seinen Spaß zu haben. Andere Erklärungen, warum die Dinos ausgestorben sind, kann ich hingegen nicht ernst nehmen. Irgendso ein alter Knacker aus Baden-Württemberg hat vor einiger Zeit im Radio(!) gesagt:

            "Wir sind noch nie so verarscht worden, wie jetzt und heute".

            Der Alte hat recht. Mach den Test, fahre an die Atlantikküste (oder woandershin, wo kaum Deutsch geredet wird) und zwei Wochen kein Radio, kein Fernsehen, kein Internet, kein Telefon. Prüfe, ob Dir somit irgendwas fehlt. Wenn Du, danach wieder zuhause angekommen, das Radio einschaltest, wird Dir jede Meldung wie ein schlecht gespielter Witz vorkommen.

            Kein Witz: Die Schwerkraft ist ein mächtiger Gegner in unserem Leben.

            Fossile Grüße, Horst, der jetzt seinen wohlverdienten Mittagsschlaf nachholt (Programmiert habe ich wie immer unterwegs, es war in einer halben Stunde getippt und funktioniert).

            1. હેલો

              "Wir sind noch nie so verarscht worden, wie jetzt und heute".

              Für diese Erkenntnis braucht man keinen Urlaub, sondern lediglich Mutter Natur höchst Persönlich ;)

              Wie Ali G einmal treffend sagte: „Ihr solltet alle mal runter kommen und einen durchziehen“.

              Dem ist nichts hinzuzufügen ;)

              બાય

              --
               .
              ..:
              1. hi,

                "Wir sind noch nie so verarscht worden, wie jetzt und heute".

                Für diese Erkenntnis braucht man keinen Urlaub, sondern lediglich Mutter Natur höchst Persönlich ;)

                Ok, wer's braucht, ich brauche es nicht, vielmehr bevorzuge ich meinen gesunden Menschenverstand.

                Viele Grüße!

                1. હેલો

                  "Wir sind noch nie so verarscht worden, wie jetzt und heute".

                  Für diese Erkenntnis braucht man keinen Urlaub, sondern lediglich Mutter Natur höchst Persönlich ;)

                  vielmehr bevorzuge ich meinen gesunden Menschenverstand.

                  Der bleibt ja, nur die Wahrnehmung wird intensiviert.

                  બાય

                  --
                   .
                  ..:
      4. Hello,

        • Transaction wird verworfen - reservierte Id wird wieder frei gegeben

        Das sollte allerdings in "normalen" DBMS nicht passieren. Da wird nur mit Lost Keys gearbeitet. Dazu fallen mir auch die Stichworte "Pessimistic Locking" und "Optimistic Locking" ein.

        Das ganze Leben besteht aus der Anreihung von Lücken :-)

        Liebe Grüße aus dem schönen Oberharz

        Tom vom Berg

        --
         ☻_
        /▌
        / \ Nur selber lernen macht schlau
        http://bikers-lodge.com
      5. Ja der Ansicht bin ich eigentlich auch. Nach meinem Verständnis müssten doch so Lücken entstehen?

        Ja, es entstehen Lücken. Aber das ist kein Problem. Du darfst dich halt nicht darauf verlassen, dass du die IDs einfach durchzählen kannst.