Datenbank - nächsten Index abfragen und neue Datenzeile einfügen

3 Antworten

Vom Fragesteller als hilfreich ausgezeichnet

Leider ist dieser Algorythmus nicht Mehrbenutzertauglich! Denn es ist möglich und es passiert auch im Test, dass zwei Personen gleichzeitig die nächste (gleich) Indexnummer bekommen und beide dann versuchen mit dieser Nummer die neue Datenzeile einzufügen.

Du solltest die Logik der Datenhaltung und der Datenbearbeitung strikt trennen, dann ist die Lösung einfacher. ;)

  1. Überlasse der Datenbank die Inidzierung! (Stichwort: Autoincrement)
  2. Nutze Transaktionen! (entweder RDBMS-eigene Transaktionen oder eigene Scripte, wie wotan38 sie beschreibt)
  3. Lasse dir ggf. von der Datenbank die Information zurückgeben, welche "echte" Index-Nummer dein Datensatz bekommen hat. (Arbeite solange nur mit "lokalen temporären" Indizes im Arbeitsspeicher.)

Wenn du dennoch unmittelbar eindeutige Nummern - etwa Rechnungsnummern - brauchst, dann erfinde entsprechende Algorithmen, die von der Datensatz-Indizierung losgelöst sind. (Beispielsweise kannst du Rechnungen "vorspeichern", sobald sie angelegt - und noch bevor sie vom Benutzer ausgefüllt - werden. Damit hat die Datenbank die Möglichkeit, ihre Stärken in der Indizierung auszuspielen und kann dir eine Rechnungsnummer zurückgeben. Diese Nummer kann wieder freigegeben und für nachfolgende Rechnungen zur Verfügung gestellt werden, wenn die Rechnung doch nicht geschrieben werden soll.)

Ich habe das gleiche Problem mit der Vergabe einer Rechnungs-Nr. Bei mir ist das so, dass beim Lesen automatisch alle gelesenen Sätze gesperrt werden und erst nach einem commit-Befehl diese Sperre aufgehoben wird. Die aktuelle Nr (letzte verwendete) habe ich irgendwo gespeichert. Dann schicke ich

UPDATE tabelle set rechnr = rechnr + 1 WHERE id = 0; SELECT rechnr from tabelle WHERE id = 0; commit

mit dem SELECT bekomme ich meine Nr. Da diese 3 Anweisungen in ihrer Logik nicht von einem andern Benutzer unterbrechbar sind, kann jede Nr nur einmal vergeben werden. Das Sperren der Tabelle ist nicht notwendig, es genügt, wenn der Satz gesperrt wird, der die aktuelle Nr. enthält. Notfalls kannst dafür auch eine eigene Tabelle mit nur einem Satz einrichten.

Ich benutze allerdings eine professionelle transaktionsgesteuerte Datenbank mit allem Drum und Dran, keine kostenlose Testversion.

Eventuell musst Du bei den Einstellungen festlegen, dass Du transaktionsmäßig arbeiten möchtest. Mit dem ROLLBACK warst schon nahe dran, hat auch was mit Transaktionen zu tun. Eine Transaktion bedeutet zum einen, dass vom Beginn der Transaktion bis zum Abschluss Dich kein Mitbenutzer unterbrechen kann, zum anderen, dass nicht abgeschlossene Transaktionen bei Programmabsturz automatisch zurückgesetzt werden oder dies vom Programmierer im Fehlerfall selbst per ROLLBACK durchgeführt werden kann. Eine Transaktion wird damit grundsätzlich immer oder garnicht durchgeführt, niemals bruchstückhaft. Der Programmierer muss allerdings selbst dafür sorgen, dass innerhalb der Transaktion alles richtig gemacht wird. Bei komplizierten Anwendungenkann es vorkommen, dass zwei Anwender sich gegenseitig sperren und jeder auf den anderen wartet (deadlock). Da muss der Programmierer bei einer entsprechenden Fehlermeldung die Transaktion mit ROLLBACK abbrechen und erneut versuchen. Noch ein Tipp: Beim Warten auf eine Eingabe sollte im Programm keine Transaktion offen sein, am besten vor jeder Anfrage einen COMMIT abschicken, damit auch Sätze freigegeben werden, die nur gelesen wurden.

Gibt sicherlich haufenweise Möglichkeiten, aber schwer zu entscheiden ohne den genaueren Programmcode zu kennen. Daher würde ich einfach die Tabelle vor einer Operation sperren (LOCK TABLES). Nachdem das Script durchgelaufen ist, dann halt wieder mit UNLOCK entsperren.

http://dev.mysql.com/doc/refman/5.1/de/lock-tables.html

Was möchtest Du wissen?