Sperrt lock tables auch zum lesen?
Bruno
- datenbank
Hi,
ich muß, um einen Wert zu generieren, aus einer Tabelle den Datensatz mit der höchsten ID ermitteln, dann den eine Spalte hernehnen, per explode (php) zerhacken, auf Basis der Zerhackten einen neuen Wert generieren und dann einen neuen Datensatz in die Tabelle einfügen.
Also:
select ...
...
Stelle XYZ
...
explode...
...
$neuer_wert=...
...
input $neuer_wert in db
Wie verhindere ich sinnvoll, dass an Stelle XYZ ein weiterer User genau dasselbe macht und so ein Wert doppelt eingetragen wird?
Ist hierfür Lock Tables das richtige Instrument?
Grüße, Bruno
Hallo,
ich muß, um einen Wert zu generieren, aus einer Tabelle den Datensatz mit der höchsten ID ermitteln, dann den eine Spalte hernehnen, per explode (php) zerhacken, auf Basis der Zerhackten einen neuen Wert generieren und dann einen neuen Datensatz in die Tabelle einfügen.
das sieht ganz danach aus, als wäre das Datenbankdesign sehr fehlerhaft. Für solche Aufgaben gibt es je nach DBMS Autoincrement, Sequenzen, Identity-Spalten, ...
Wenn man Werte aus Spalten "zerhacken" muss, um an gewünschte Werte zu kommen, hat man Daten nicht atomar gespeichert. Das ist fast immer keine gute Idee.
Wie verhindere ich sinnvoll, dass an Stelle XYZ ein weiterer User genau dasselbe macht und so ein Wert doppelt eingetragen wird?
Ist hierfür Lock Tables das richtige Instrument?
Refactoring der Anwendung wäre das richtige Instrument. Ein Write-Lock ein Workaround, um die selbstfabrizierte TOCTTOU-Problem zu verhindern. Solche Sperren sind eine wunderbare Performance-Bremse.
Freundliche Grüße
Vinzenz
das sieht ganz danach aus, als wäre das Datenbankdesign sehr fehlerhaft. Für solche Aufgaben gibt es je nach DBMS Autoincrement, Sequenzen, Identity-Spalten, ...
Nein, das ist so nicht richtig.
Der Kunde hat ein eigenes System der Durchnummerierung seiner Listen, das muss ich übernehmen.
Ich selber arbeite ab dem moment der Nummernvergabe nur noch mit der ID dieser Liste, aber ich muß die Nummer nunmal einmal vergeben!
Darüber hinaus gibt es verschiedenen Systeme, diese Nummer zu generieren. Somit kann ich auch nicht mal teilweise die Nummer in eine andere tabelle ausgliedern. Es hilft nix, die Nummer muß errechnet werden und in die Spalte eingetragen werden.
Insofern ist das db-Design schon völlig korrekt!
Wenn man Werte aus Spalten "zerhacken" muss, um an gewünschte Werte zu kommen, hat man Daten nicht atomar gespeichert. Das ist fast immer keine gute Idee.
Aber manchmal gehts halt nicht anders.
Gruß, Bruno
Hi!
Der Kunde hat ein eigenes System der Durchnummerierung seiner Listen, das muss ich übernehmen.
Ich selber arbeite ab dem moment der Nummernvergabe nur noch mit der ID dieser Liste, aber ich muß die Nummer nunmal einmal vergeben!
Vermutlich eher "darf" statt "muss". Für den Fall gibt es den Unique-Index. Der sorgt dafür, dass kein zweiter Datensatz mit dem selben Wert eingefügt werden kann. Und um TOCTTOU zu umgehen, fragt man nicht vorher, ob ein Wert existiert, sondern schreibt einfach auf gut Glück drauf los. Wenn er noch nicht existierte, gibt es nun einen neuen Datensatz, ansonsten meldet sich das DBMS mit einer Unique-Constraint-Verletzung, die man auswerten kann.
Lo!
Vermutlich eher "darf" statt "muss". Für den Fall gibt es den Unique-Index. Der sorgt dafür, dass kein zweiter Datensatz mit dem selben Wert eingefügt werden kann. Und um TOCTTOU zu umgehen, fragt man nicht vorher, ob ein Wert existiert, sondern schreibt einfach auf gut Glück drauf los. Wenn er noch nicht existierte, gibt es nun einen neuen Datensatz, ansonsten meldet sich das DBMS mit einer Unique-Constraint-Verletzung, die man auswerten kann.
Aha? Heißt also ungefähr, dass ich alles beim alten lasse und den Unique-Index auf die Spalte lege.
Danach müßte ich wissen, wie mysql eine Unique-Constraint-Verletzung meldet und für diesen Fall schick ich das Script wieder an den Punkt, an dem die max-Id ausgelesen wird?
Frage: Was macht denn mysql bei einer Unique-Constraint-Verletzung?
Gruß, Bruno
Frage: Was macht denn mysql bei einer Unique-Constraint-Verletzung?
Kann man das so lösen?
$link = mysql_connect("localhost", "mysql_user", "mysql_password");
$flag = 1062;
while ($flag == 1062) {
$query = "insert into table ...
...
if (mysql_errno($link) != 1062) {
$flag = 0;
}
}
Gruß, Bruno
Hi!
Frage: Was macht denn mysql bei einer Unique-Constraint-Verletzung?
Wie du schon herausgefunden hast, es teilt über den üblichen Weg mit, dass es einen Fehler gab.
Kann man das so lösen?
Ob du eine Schleife brauchst, weiß ich nicht. Sie dient wohl anscheinend eher deiner Geschäftslogik. Wichtig ist, dass du wie bei jeder Fehlerbehandlung den Rückgabewert der verwendeten Funktionen auswertest und die weiteren Informationen den mysql_err*-Funktionen entnimmst.
Lo!
Ob du eine Schleife brauchst, weiß ich nicht. Sie dient wohl anscheinend eher deiner Geschäftslogik.
Was meinst Du mit Geschäftslogik?
Gruß, Bruno
Hi!
Ob du eine Schleife brauchst, weiß ich nicht. Sie dient wohl anscheinend eher deiner Geschäftslogik.
Was meinst Du mit Geschäftslogik?
Mit Geschäftslogik bezeichnet man die Teile des Programms, die die eigentlich vorgesehene Aufgabe erfüllen sollen, also das was der Anwender letztlich haben will. Nebenhandlungen, die aus programmtechnischer Sicht notwendig sind, wie beispielsweise das Aufbauen einer Datenbankverbindung, Fehlerbehandlung, oder ein Template laden und ihm Daten übergeben, gehören in der Regel nicht zur Geschäftslogik.
Lo!
Hello,
Ob du eine Schleife brauchst, weiß ich nicht. Sie dient wohl anscheinend eher deiner Geschäftslogik.
Was meinst Du mit Geschäftslogik?
Zusätzlich zu Dedlfix' Ausführungen könntest Du auch in Wikipedia lesen:
http://de.wikipedia.org/wiki/Geschäftslogik
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Zusätzlich zu Dedlfix' Ausführungen könntest Du auch in Wikipedia lesen:
http://de.wikipedia.org/wiki/Geschäftslogik
Danke für beide Hilfen dazu.
Das wußte ich noch nicht.
Noch mal inhaltlich:
Welche php-Möglichkeiten außer einer while-Schleife gäbe es noch, bei errer-Nummer 1062 das Script wieder an einen bestimmtn Punkt zu führen?
GoTo gibts ja nicht in php.
Grüße, Bruno
Hi!
GoTo gibts ja nicht in php.
Goto gibt es mittlerweile. Allerdings empfiehlt es sich der Übersichtlichkeit wegen nicht, Schleifen oder wilde Sprünge damit zu programmieren, sondern es eher zum gezielten Verlassen von komplexen Verschachtelungen zu verwenden, wenn mit breaks und Abbruch-Hilfsvariablen sonst die Übersichtlichkeit leidet. (Vorher sollte man aber versuchen, eine generell übersichtlichere Variante zu finden, um die gewünschte Aufgabe zu erledigen.)
Welche php-Möglichkeiten außer einer while-Schleife gäbe es noch, bei errer-Nummer 1062 das Script wieder an einen bestimmtn Punkt zu führen?
Du hast dich noch nicht über den Sinn des Wiederzurückgehens geäußert. Ich habe nicht bemängelt, dass du eine while-Schleife verwendest, sondern nur nicht genau erkannt, was das Ziel dahinter ist. Ich spekuliere, dass du dann solange eine neue Nummer ermittelst, bis der Datensatz eingefügt werden kann. Da ich aber den Hintergrund deines Handels nicht kenne, kann ich dir keine genaueren Alternativen vorschlagen. Allerdings: do-while scheint mir sinnvoller, weil du zum Ende des Vorgangs auswerten willst, ob er erfolgreich war oder nicht. Mit der kopfgesteuerten while-Schleife brauchst du unbedingt eine Hilfsvariable - mit do-while kann diese entfallen.
Lo!
Hallo dedlfix,
Goto gibt es mittlerweile.
Danke für den Hinweis. Ich mag GoTo.
Allerdings habe ich noch php < 5.3
Welche php-Möglichkeiten außer einer while-Schleife gäbe es noch, bei errer-Nummer 1062 das Script wieder an einen bestimmtn Punkt zu führen?
Du hast dich noch nicht über den Sinn des Wiederzurückgehens geäußert.
Ich spekuliere, dass du dann solange eine neue Nummer ermittelst, bis der Datensatz eingefügt werden kann.
Diese Spekulation trifft es.
Allerdings: do-while scheint mir sinnvoller, weil du zum Ende des Vorgangs auswerten willst, ob er erfolgreich war oder nicht. Mit der kopfgesteuerten while-Schleife brauchst du unbedingt eine Hilfsvariable - mit do-while kann diese entfallen.
Ja ok. Deshalb habe ich gefragt, weil ich nicht sicher war, ob es eine sinnvollere Variante hierzu gibt.
Danke für Deine Hilfe, Dedlfix. Frohe Festtage.
Bruno
Hello,
Ich spekuliere, dass du dann solange eine neue Nummer ermittelst, bis der Datensatz eingefügt werden kann.
Diese Spekulation trifft es.
Das wäre aber unnötig, da man mittels SQL-Query auch Lücken finden kann in ordinalen Datenreihen. Und "Nummern" sind mMn ordinal, im Gegensatz zu Realzahlen.
[OK: manche Nummern sind auch einfach nur ordinär]
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Das wäre aber unnötig, da man mittels SQL-Query auch Lücken finden kann in ordinalen Datenreihen. Und "Nummern" sind mMn ordinal, im Gegensatz zu Realzahlen.
... aber darum geht es doch gar nicht?
Hast Du das Problem überhaupt verstanden?
Gruß, Bruno
Hello,
Das wäre aber unnötig, da man mittels SQL-Query auch Lücken finden kann in ordinalen Datenreihen. Und "Nummern" sind mMn ordinal, im Gegensatz zu Realzahlen.
... aber darum geht es doch gar nicht?
Hast Du das Problem überhaupt verstanden?
Das täte mir leid, wenn ich deine Aufgabenstellung bisher fehlinterpretiert hätte. Du könntest das aber kontrollieren, indem Du ausfühlich auf meine gestellten Fragen antworten würdest und dann noch ein paar Minuten Geduld hättest, dass ich mir diese Antworten auch ansehen und durchdenken kann.
Erst dann kann ich Dir die Frage aus diesem Posting beantworten.
Du bist am Zug. Leg die Karten auf den Tisch und komme mit realen Beispielen. Dann können wir Dir helfen. Deine bisherigen Auskünfte sind minderwertig.
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Dann können wir Dir helfen.
Frohe Weihnacht, Tom :-)
Mir ist doch durch Dedlfix längst geholfen.
Dir auch ein Danke für Deine Mühe und weiterhin frohe Festtage,
Bruno
Hello,
Dann können wir Dir helfen.
Frohe Weihnacht, Tom :-)
Mir ist doch durch Dedlfix längst geholfen.
Welches Posting meinst Du?
Soweit ich das überblicke im Moment hat Dedlfix Dir ausnahmsweise mal nicht die erforderlichen weiteren Hinweise gegeben, sondern nur auf Deine primäre Frage geantwortet. Dann ist er sicherlich noch nicht fertig mit seinen Tipps. Du solltest also ruhig nochmal gucken hier die nächsten Tage.
Bis dahin noch Frohe Weihnachten und einen guten Rutsch.
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Hello,
Zusätzlich zu Dedlfix' Ausführungen könntest Du auch in Wikipedia lesen:
http://de.wikipedia.org/wiki/GeschäftslogikDanke für beide Hilfen dazu.
Das wußte ich noch nicht.Noch mal inhaltlich:
Welche php-Möglichkeiten außer einer while-Schleife gäbe es noch, bei errer-Nummer 1062 das Script wieder an einen bestimmtn Punkt zu führen?
Es ist der falsche Ansatz!
Der richtige wäre, uns die
Dann können wir Dir helfen.
Andererseits scheint Dir aber auch das Verständnis für Programmierung zu fehlen, denn sonst hättest Du das Problem nicht "Schleife oder nicht-Schleife?". Eine Aufteilung in einzelne Funktionen mit genau definierten Aufgaben wäre schon mal ein Lösungsansatz. Und die würde man dann, wenn es denn die Datenbankmaschine wirklich nicht kann (was ich nicht glaube), tatsächlich in einer Schleife verwenden. Dazu müssten dann aber voraussichtlich auch die betroffenen Tabellen gesperrt werden. solange der Vorgang läuft.
Aber, wie schon geschrieben: Ein Insert ... Select wird zu 99% Wahrscheinlichkeit die Lösung für Deine Aufgabenstellung sein, die wir immer noch nicht ausreichend kennen!
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Hello,
Wie verhindere ich sinnvoll, dass an Stelle XYZ ein weiterer User genau dasselbe macht und so ein Wert doppelt eingetragen wird?
Ist hierfür Lock Tables das richtige Instrument?
Nur dann, wenn es nicht anders lösbar ist.
Es hängt von den Fähigkeiten der Datenbankmaschine ab, wie man es lösen kann.
Bei MySQL ist z.B. seitdem es subselects gibt, fast kein diskretes Locking mehr notwendig.
Wir hatten hier neulich erst so einen Fall. Da ging es zwar um Terminverwaltung, aber es musste auch sichergestellt werden, dass keine Überlappung möglich ist.
http://forum.de.selfhtml.org/archiv/2010/11/t201483/#m1359235
http://forum.de.selfhtml.org/archiv/2010/11/t201483/#m1359300
Und für die Berechnung des Schlüssels lohnt es sich vermutlich, eine benutzerdefinierte Funktion zu erstellen. Dann kann man alles mit einem einzigen Query mit der Datenbankmaschine machen und muss nicht erst Daten ins API holen und dann später wieder wegschreiben.
Nur zwischen genau ein Query passt kein zweites Query.
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Ist hierfür Lock Tables das richtige Instrument?
Nur dann, wenn es nicht anders lösbar ist.
Es hängt von den Fähigkeiten der Datenbankmaschine ab, wie man es lösen kann.Bei MySQL ist z.B. seitdem es subselects gibt, fast kein diskretes Locking mehr notwendig.
Ich brauche aber den String einer Spalte des Eintrages mit der max-ID. Und rechne dann mit einem Teilwert des Strings und dem aktuellen Datum weiter. Dazu kommen noch andere Infos, die den Vorgang definieren.
Da hilft mir ein subselect nicht wirklic weiter.
Gruß, Bruno
Hello,
Bei MySQL ist z.B. seitdem es subselects gibt, fast kein diskretes Locking mehr notwendig.
Ich brauche aber den String einer Spalte des Eintrages mit der max-ID. Und rechne dann mit einem Teilwert des Strings und dem aktuellen Datum weiter. Dazu kommen noch andere Infos, die den Vorgang definieren.
Da hilft mir ein subselect nicht wirklich weiter.
Wieso nicht? Hast Du es denn überhaupt schon ausprobiert?
insert ... select sollte Deine Lösung sein.
Welche Datenbankmaschine benutzt Du denn überhaupt?
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg