Doppler vermeiden

Doppler vermeiden

am 11.09.2007 13:20:57 von Daniel Schmidt

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();

auto_increment kommt für mich nicht in Frage


MFG Daniel

Re: Doppler vermeiden

am 11.09.2007 13:43:21 von struebig

Daniel Schmidt schrieb:
> auto_increment kommt für mich nicht in Frage

Wieso nicht?

Re: Doppler vermeiden

am 11.09.2007 13:44:11 von Andreas Kretschmer

Andreas
--
Andreas Kretschmer
Linux - weil ich es mir wert bin!
GnuPG-ID 0x3FFF606C http://wwwkeys.de.pgp.net
http://a-kretschmer.de/pict4592.jpg

Re: Doppler vermeiden

am 11.09.2007 13:47:55 von Peter Henschel

Daniel Schmidt wrote:

> 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.

Kannst mal folgenden query probieren:
INSERT INTO tab(id) SELECT id+1 FROM tab LIMIT 1

Vielleicht hast du aber nur Probleme weil du das sortieren mittels ORDER BY
vergessen hast.

> MFG Daniel

Peter
--
http://tut.php-quake.net/

Re: Doppler vermeiden

am 11.09.2007 23:28:05 von Daniel Schmidt

> Tja, die Welt ist schlecht und früher war alles besser. Aber Hilfe naht,
> in Form von auto_increment.

Ok, zu auto_increment wird es wohl keine Alternative geben. Nun brauche
ich diese id aber als Variable in dem Script, dass diese speichert und
hier habe ich doch wieder mein Problem. Wie frage ich diesen Wert wieder
ab, ohne das mit der nächste User eine schon die nächsthöhere id
geschrieben hat?

Gruß Daniel

Re: Doppler vermeiden

am 11.09.2007 23:44:08 von Michael Fesser

..oO(Daniel Schmidt)

>Ok, zu auto_increment wird es wohl keine Alternative geben.

Gibt es. Auch in dclpd wurde noch eine angesprochen (Sequenzen).

>Nun brauche
>ich diese id aber als Variable in dem Script, dass diese speichert und
>hier habe ich doch wieder mein Problem. Wie frage ich diesen Wert wieder
>ab, ohne das mit der nächste User eine schon die nächsthöhere id
>geschrieben hat?

in SQL: LAST_INSERT_ID()
in PHP: mysql_insert_id() oder PDO->lastInsertId()

Micha

Re: Doppler vermeiden

am 11.09.2007 23:48:44 von Daniel Schmidt

> in SQL: LAST_INSERT_ID()
> in PHP: mysql_insert_id() oder PDO->lastInsertId()

Das ist ja das Problem! Und wenn zwischenzeitlich schon ein neuer User
die letzte id besetzt? Da bekomme ich doch nicht mehr die id des
aktuellen Users.

Gruß Daniel

Re: Doppler vermeiden

am 12.09.2007 00:08:09 von Sven Paulus

Daniel Schmidt wrote:
>> in SQL: LAST_INSERT_ID()
>> in PHP: mysql_insert_id() oder PDO->lastInsertId()
> Das ist ja das Problem! Und wenn zwischenzeitlich schon ein neuer User
> die letzte id besetzt? Da bekomme ich doch nicht mehr die id des
> aktuellen Users.

Doch. Die LAST_INSERT_ID() ist Connection-spezifisch.

Re: Doppler vermeiden

am 12.09.2007 08:07:14 von Claus Reibenstein

Daniel Schmidt schrieb:

>> in SQL: LAST_INSERT_ID()
>> in PHP: mysql_insert_id() oder PDO->lastInsertId()
>
> Das ist ja das Problem! Und wenn zwischenzeitlich schon ein neuer User
> die letzte id besetzt? Da bekomme ich doch nicht mehr die id des
> aktuellen Users.

Wie kommst Du denn darauf? Doku nicht gelesen?

Du bekommst immer _die_ ID geliefert, die _Du_ in _Deiner_ Session als
letztes besetzt hast. Was andere User in der Zwischenzeit mit der DB
anstellen, braucht Dich nicht zu interessieren.

Gruß. Claus

Re: Doppler vermeiden

am 12.09.2007 08:29:17 von Claus Reibenstein

Michael Fesser schrieb:

> in PHP: mysql_insert_id() oder PDO->lastInsertId()

Wieso PHP? In dieser Gruppe geht es um MySQL, nicht um PHP oder sonstige
Programmiersprachen. PHP hat eine eigene Subhierarchie in de.comp.lang
und darin auch eine eigene Gruppe für Datenbanken.

Gruß. Claus

Re: Doppler vermeiden

am 12.09.2007 15:05:24 von Dominik Echterbruch

Claus Reibenstein schrieb:
> Daniel Schmidt schrieb:
>
>>> in SQL: LAST_INSERT_ID()
>>> in PHP: mysql_insert_id() oder PDO->lastInsertId()
>> Das ist ja das Problem! Und wenn zwischenzeitlich schon ein neuer User
>> die letzte id besetzt? Da bekomme ich doch nicht mehr die id des
>> aktuellen Users.
>
> Wie kommst Du denn darauf? Doku nicht gelesen?

@Claus: In PHP (ja, ich weiß...) gibt es persistente Verbindungen, die
über verschiedene Skripte hinweg genutzt werden können. Insbesondere
auch von verschiedenen Benutzern für die selbe Aktion.

@Daniel: verwende nicht-persistente Verbindungen und alles wird gut (wie
von Claus beschrieben).
Der Verbindungsaufbau zu MySQL ist vergleichsweise günstig. Es schadet
also nicht allzuviel, eine neue Verbindung am Beginn des Skriptes zu
öffnen und am Ende des Skriptes wieder zu schließen

Grüße,
Dominik
--
Wo kämen wir denn hin, wenn jeder sagen würde wo kämen wir hin, aber
niemand gehen würde um zu sehen, wohin wir kämen, wenn wir gingen?
(Autor unbekannt)

Re: Doppler vermeiden

am 12.09.2007 16:43:10 von Sven Paulus

Dominik Echterbruch wrote:
> @Claus: In PHP (ja, ich weiß...) gibt es persistente Verbindungen, die=
=20
> über verschiedene Skripte hinweg genutzt werden können. Insbesondere=
=20
> auch von verschiedenen Benutzern für die selbe Aktion.

Aber nur sequentiell. PHP macht ja kein connection pooling, d.h. ein
PHP-"Prozess" (also z.B. ein Apache-Kindprozess mit geladenem PHP-Modul) h=
at
waehrend seine connection exklusiv fuer sich, d.h. auch waehrend der
Bearbeitung eines Requests ist dieser Verbindung immer nur von einer Insta=
nz
genutzt. Somit kann man problemlos "INSERT INTO ..." und "SELECT
LAST_INSERT_ID()" verwenden.

Wuerde das alles mit einem fixen pool von connections funktionieren, auf d=
en
die einzelnen Prozesse requestweise zugreifen, waere es ein voelliges Chao=
s,
sowas wie Transaktionen waere komplett unmoeglich.

Klar, persistente connections haben Nachteile (Zahl offener
Datenbankconnections, nicht definierter Anfangszustand, ...), aber obiges
ist keiner.

Re: Doppler vermeiden

am 12.09.2007 17:21:54 von Claus Reibenstein

Dominik Echterbruch schrieb:

> Claus Reibenstein schrieb:
>
>> Daniel Schmidt schrieb:
>>
>>> Das ist ja das Problem! Und wenn zwischenzeitlich schon ein neuer User
>>> die letzte id besetzt? Da bekomme ich doch nicht mehr die id des
>>> aktuellen Users.
>>
>> Wie kommst Du denn darauf? Doku nicht gelesen?
>
> @Claus: In PHP (ja, ich weiß...) gibt es persistente Verbindungen, die
> über verschiedene Skripte hinweg genutzt werden können. Insbesondere
> auch von verschiedenen Benutzern für die selbe Aktion.

Stimmt. An persistente Verbindungen habe ich nicht gedacht. Vermutlich
deshalb, weil ich sie bisher nie benutzt habe.

Gruß. Claus

Re: Doppler vermeiden

am 12.09.2007 19:43:07 von Michael Fesser

..oO(Claus Reibenstein)

>Michael Fesser schrieb:
>
>> in PHP: mysql_insert_id() oder PDO->lastInsertId()
>
>Wieso PHP?

Weil der OP das verwendet und somit ein ergänzender Hinweis durchaus
angebracht war.

>In dieser Gruppe geht es um MySQL, nicht um PHP oder sonstige
>Programmiersprachen. PHP hat eine eigene Subhierarchie in de.comp.lang
>und darin auch eine eigene Gruppe für Datenbanken.

Ach?!

Fup2 poster
Micha

Re: Doppler vermeiden

am 15.09.2007 10:44:06 von Thomas Rachel

Claus Reibenstein schrieb:
> Michael Fesser schrieb:
>
>> in PHP: mysql_insert_id() oder PDO->lastInsertId()
>
> Wieso PHP? In dieser Gruppe geht es um MySQL, nicht um PHP oder sonstige
> Programmiersprachen.

ACK. Man betrachte den Hinweis daher auf die gleichnamige Funktion in
der MySQL-API, die hier durchaus OnT ist.


Thomas

Re: Doppler vermeiden

am 13.11.2007 10:08:18 von Boris Stumm

Daniel Schmidt wrote:
> mysql_tab_fuer_fremde_zugriffe_sperren();
> ... mysql_query("SELECT ...
> ... mysql_query("INSERT INTO ...
> mysql_tab_sperren_aufheben();

Schon mal mit Transaktionen probiert?

http://dev.mysql.com/doc/refman/4.1/en/commit.html