Doppler vermeiden
Hallo,
ich schreibe eine laufende Nummer in eine MySQL-DB, indem ich die letzte
Nummer in der DB abrufe, dieser eine dazuaddiere und wieder in die DB
schreibe. Das Ganze sieht momentan so aus:
$ergebnis = mysql_query("SELECT id FROM tab LIMIT 1") OR die mysql_error());
while($row = mysql_fetch_object($ergebnis)) {
$id=$row->id+1;
mysql_query("INSERT INTO tab (id) VALUES ('$id')") OR die (mysql_error());
}
Nun passiert es bei vielen Zugriffen das einige gleichzeitig zugreifen
und dieselbe id bekommen.
Nun meine Frage, lässt sich das vermeiden, dass man z.B. nur einen
Zugriff macht bzw. den Vorgang für die Abfrage und das schreiben sperrt,
z.B.:
mysql_tab_fuer_fremde_zugriffe_sperren();
.... mysql_query("SELECT ...
.... mysql_query("INSERT INTO ...
mysql_tab_sperren_aufheben();
MFG Daniel
Re: Doppler vermeiden
..oO(Daniel Schmidt)
>ich schreibe eine laufende Nummer in eine MySQL-DB, indem ich die letzte
>Nummer in der DB abrufe, dieser eine dazuaddiere und wieder in die DB
>schreibe. Das Ganze sieht momentan so aus:
Blöde Idee, Stichwort: race condition.
>Nun passiert es bei vielen Zugriffen das einige gleichzeitig zugreifen
>und dieselbe id bekommen.
Logisch. Das Abfragen und Erhöhren der ID muß atomar, d.h. in einer
einzigen Operation erfolgen, was bei Dir aber nicht der Fall ist.
>Nun meine Frage, lässt sich das vermeiden, dass man z.B. nur einen
>Zugriff macht bzw. den Vorgang für die Abfrage und das schreiben sperrt,
>z.B.:
>
>
>mysql_tab_fuer_fremde_zugriffe_sperren();
>... mysql_query("SELECT ...
>... mysql_query("INSERT INTO ...
>mysql_tab_sperren_aufheben();
Das funktioniert nicht. Was aber funktioniert, ist z.B. eine Spalte mit
AUTO_INCREMENT. Spricht was dagegen bei Deiner DB? Brauchst Du die ID
_vor_ dem Einfügen eines Datensatzes oder erst hinterher?
Ist hier aber OT, daher Xpost & Fup2 dclpd
Micha
Re: Doppler vermeiden
Daniel Schmidt schrieb:
> Hallo,
>
> ich schreibe eine laufende Nummer in eine MySQL-DB, indem ich die letzte
> Nummer in der DB abrufe, dieser eine dazuaddiere und wieder in die DB
> schreibe. Das Ganze sieht momentan so aus:
>
>
> $ergebnis = mysql_query("SELECT id FROM tab LIMIT 1") OR die
> mysql_error());
> while($row = mysql_fetch_object($ergebnis)) {
> $id=$row->id+1;
> mysql_query("INSERT INTO tab (id) VALUES ('$id')") OR die (mysql_error());
> }
>
>
> Nun passiert es bei vielen Zugriffen das einige gleichzeitig zugreifen
> und dieselbe id bekommen.
>
> Nun meine Frage, lässt sich das vermeiden, dass man z.B. nur einen
> Zugriff macht bzw. den Vorgang für die Abfrage und das schreiben sperrt,
> z.B.:
Warum vergibst du die ID selbst und nutzt nicht AUTO_INCREMENT (Serial)?
Guck dir einfach mysql_insert_id() an, damit bekommst du die ID die bei
letzten Insert vergeben wurde.
>
>
> mysql_tab_fuer_fremde_zugriffe_sperren();
> ... mysql_query("SELECT ...
> ... mysql_query("INSERT INTO ...
> mysql_tab_sperren_aufheben();
>
>
>
> MFG Daniel
>
Re: Doppler vermeiden
> Nun passiert es bei vielen Zugriffen das einige gleichzeitig zugreifen
> und dieselbe id bekommen.
>
> Nun meine Frage, lässt sich das vermeiden, dass man z.B. nur einen
> Zugriff macht bzw. den Vorgang für die Abfrage und das schreiben sperrt,
> z.B.:
>
>
> mysql_tab_fuer_fremde_zugriffe_sperren();
> ... mysql_query("SELECT ...
> ... mysql_query("INSERT INTO ...
> mysql_tab_sperren_aufheben();
Du hast vielleicht Deine Gründe, weshalb Du AUTO_INCREMENT nicht
verwenden willst. Für den Fall empfehlen sich Transaktionen:
mysql_query("begin transaction");
mysql_query("select...");
mysql_query("insert...";
mysql_query("commit");
Geht bei MySQL nur bei bestimmten Tabellentypen (z. B. InnoDB).
--
Mein Zeugs:
http://www.hadanite-marasek.de/classes.php
http://www.objektivsuche.de/