F: mysql_insert_id
am 11.07.2006 11:16:04 von Martin Krammer
hallo,
eine frage hätte ich da: mysql_insert_id() gibt mir in PHP den
auto_increment wert der letzten insert-operation zurück. ist diese
funktion 100% resistent gegenüber mehrfachem zugriff auf die datenbank?
soll heissen wenn mehrere benutzer (natürlich nur fast) zeitgleich auf
der datenbank arbeiten, kommt es zu keinen "überschneidungen" der
zurückgegebenen ID?
Danke
Martin
Re: F: mysql_insert_id
am 11.07.2006 11:25:27 von Christian Kirsch
Martin Krammer schrieb:
> hallo,
>
> eine frage hätte ich da: mysql_insert_id() gibt mir in PHP den
> auto_increment wert der letzten insert-operation zurück. ist diese
> funktion 100% resistent gegenüber mehrfachem zugriff auf die datenbank?
PHP ist hier Off-topic.
> soll heissen wenn mehrere benutzer (natürlich nur fast) zeitgleich auf
> der datenbank arbeiten, kommt es zu keinen "überschneidungen" der
> zurückgegebenen ID?
Schaust Du hier:
http://dev.mysql.com/doc/refman/5.1/en/information-functions .html
LAST_INSERT_ID()
Re: F: mysql_insert_id
am 11.07.2006 11:26:25 von Andreas Delp
Martin Krammer wrote:
> hallo,
>
> eine frage hätte ich da: mysql_insert_id() gibt mir in PHP den
> auto_increment wert der letzten insert-operation zurück. ist diese
> funktion 100% resistent gegenüber mehrfachem zugriff auf die datenbank?
> soll heissen wenn mehrere benutzer (natürlich nur fast) zeitgleich auf
> der datenbank arbeiten, kommt es zu keinen "überschneidungen" der
> zurückgegebenen ID?
>
Nein. Diese ID ist wirklich die des von dir in dieser Anwendung zuletzt
angelegten Datensatzes.
Andreas
--
Wer mir per Mail antworten möchte sollte 'erdbeere' im Betreff erwähnen,
sonst wird die Mail zusammen mit SPAM und Würmern ungelesen gelöscht.
Re: F: mysql_insert_id
am 11.07.2006 11:34:12 von Martin Krammer
Andreas Delp wrote:
> Nein. Diese ID ist wirklich die des von dir in dieser Anwendung
> zuletzt angelegten Datensatzes.
Danke!
Martin :-)
Re: F: mysql_insert_id
am 11.07.2006 12:35:59 von Thomas Rachel
Christian Kirsch wrote:
>> eine frage hätte ich da: mysql_insert_id() gibt mir in PHP den
>> auto_increment wert der letzten insert-operation zurück. ist diese
>> funktion 100% resistent gegenüber mehrfachem zugriff auf die datenbank?
>
> PHP ist hier Off-topic.
Das PHP-Interface ist aber eine nahezu 1:1-Abbildung des C-API. Ist das denn
generell auch offtopic?
Thomas
Re: F: mysql_insert_id
am 11.07.2006 12:57:13 von Axel Schwenke
Andreas Delp wrote:
> Martin Krammer wrote:
>
>> eine frage hätte ich da: mysql_insert_id() gibt mir in PHP den
>> auto_increment wert der letzten insert-operation zurück. ist diese
>> funktion 100% resistent gegenüber mehrfachem zugriff auf die datenbank?
>> soll heissen wenn mehrere benutzer (natürlich nur fast) zeitgleich auf
>> der datenbank arbeiten, kommt es zu keinen "überschneidungen" der
>> zurückgegebenen ID?
>>
> Nein. Diese ID ist wirklich die des von dir in dieser Anwendung zuletzt
> angelegten Datensatzes.
Falsch!
mysql_insert_id() bzw. die entsprechenden Äquivalente in den verschie-
denen APIs liefern die letzte vergebene AUTO_INCREMENT Nummer für die
jeweilige Datenbank-Verbindung. Nix Anwendung. Verbindung! Anwendungen
können durchaus mehrere Datenbank-Verbindungen benutzen.
Dummerweise hat PHP die Angewohnheit, Verbindungen zur Datenbank zu
sharen - zumindest solange man nicht explizit eine neue Verbindung
verlangt. Also Augen aufmachen!
XL
Re: F: mysql_insert_id
am 11.07.2006 13:25:26 von Christian Kirsch
Thomas Rachel schrieb:
> Christian Kirsch wrote:
>
>>> eine frage hätte ich da: mysql_insert_id() gibt mir in PHP den
>>> auto_increment wert der letzten insert-operation zurück. ist diese
>>> funktion 100% resistent gegenüber mehrfachem zugriff auf die datenbank?
>> PHP ist hier Off-topic.
>
> Das PHP-Interface ist aber eine nahezu 1:1-Abbildung des C-API. Ist das denn
> generell auch offtopic?
>
>
Ich denke eher nein. Aber ob und wie ggfs. ein Interface in einer
anderen Sprache (PHP, Lisp, Perl) Das Richtige tut, kann man hier
schlecht beurteilen. Leider half im konkreten Fall nicht mal die
Lektüre der PHP-"Dokumentation" zu dieser Funktion - die ist nicht
sonderlich klar und geht leider auf den Aspekt "welche ID bekomme ich
da eigentlich" auch nicht ein.
Re: F: mysql_insert_id
am 11.07.2006 14:54:26 von Thomas Rachel
Christian Kirsch wrote:
>> Das PHP-Interface ist aber eine nahezu 1:1-Abbildung des C-API. Ist das
>> denn generell auch offtopic?
>>
>>
> Ich denke eher nein. Aber ob und wie ggfs. ein Interface in einer
> anderen Sprache (PHP, Lisp, Perl) Das Richtige tut, kann man hier
> schlecht beurteilen.
ACK - soweit es sich um eine "Neumodellierung" handelt (bspw. mit Hilfe von
OOP). Beispielsweise werden in Python MySQL-Zugriffe mittels eines mehr
oder weniger versteckten 1:1-Interfaces realisiert, um welches dann ein
Klassenkonstrukt als Interface drumrummodelliert wurde.
Hat man mit jenem äuÃeren Interface ein Problem, ist es selbstredend hier
offtopic. Hat man ein Problem mit einer "Anwendung", die in einer
x-beliebigen Sprache geschrieben ist, ist das ebenfalls hier offtopic
(konkret denke ich an phpMyAdmin).
Hat man jedoch ein Interface, das fast 1:1 dem C-Interface entspricht, sind
Nachfragen hier IMHO legitim. Vielleicht sollte man sich zur Sicherheit
vergewissert haben, daà das genannte Problem direkt mit dem C-Interface
auch auftritt...
> Leider half im konkreten Fall nicht mal die
> Lektüre der PHP-"Dokumentation" zu dieser Funktion - die ist nicht
> sonderlich klar und geht leider auf den Aspekt "welche ID bekomme ich
> da eigentlich" auch nicht ein.
| ... liefert die ID, die bei der letzten INSERT-Operation für ein Feld vom
| Typ AUTO_INCREMENT vergeben wurde. Wenn die Verbindungs-Kennung nicht
| angegeben wird, wird die zuletzt geöffnete Verbindung angenommen.
Thomas
Re: F: mysql_insert_id
am 11.07.2006 15:42:15 von Christian Kirsch
Thomas Rachel schrieb:
> Christian Kirsch wrote:
>
>> Leider half im konkreten Fall nicht mal die
>> Lektüre der PHP-"Dokumentation" zu dieser Funktion - die ist nicht
>> sonderlich klar und geht leider auf den Aspekt "welche ID bekomme ich
>> da eigentlich" auch nicht ein.
>
> | ... liefert die ID, die bei der letzten INSERT-Operation für ein Feld vom
> | Typ AUTO_INCREMENT vergeben wurde. Wenn die Verbindungs-Kennung nicht
> | angegeben wird, wird die zuletzt geöffnete Verbindung angenommen.
>
>
Was in dieser Beschreibung fehlt, ist das, was der OP wissen wollte
(und was in der Beschreibung von LAST_INSERT_ID() steht): Dass man die
ID für genau *diese* Verbindung bekommt, und dass da niemand anders
zwischen pfuschen kann. D.h. bei direkt aufeinanderfolgenden Aufrufe von
INSERT
und
SELECT LAST_INSERT_ID()
liefert der zweite immer die ID, die der erste erzeugt hat.
*Vorausgesetzt*, das läuft über dieselbe Verbindung. Steht so leider
nicht in der PHP-Dokumentation, dafür kryptisches Zeug in eigenartiger
Rechtschreibung: "Wenn die Verbindungs-Kennung nicht angegeben wird,
wird die zuletzt geöffnete Verbindung angenommen." Oder sollte das
wirklich so krank implementiert sein: Anwendung A führt ein INSERT
aus, Anwendung B öffnet eine Verbindung und führt ein INSERT aus,
Anwendung A fragt nach der last_insert_id und bekommt die von
Anwendung B?
Bei PHP ist vermutlich auch sowas möglich :-(
Übrigens (PHP)mysql_last_id() eben gerade keine 1:1-Abbildung von
(C)mysql_last_id(MYSQL *mysql) zu sein: Letzteres funktioniert gar
nicht *ohne* Parameter.
Re: F: mysql_insert_id
am 11.07.2006 17:01:48 von Carsten Wiedmann
Axel Schwenke schrieb:
> Andreas Delp wrote:
> > Martin Krammer wrote:
> >
> > > eine frage hätte ich da: mysql_insert_id() gibt mir in PHP den
> > > auto_increment wert der letzten insert-operation zurück. ist diese
> > > funktion 100% resistent gegenüber mehrfachem zugriff auf die
> > > datenbank?
> > > soll heissen wenn mehrere benutzer (natürlich nur fast) zeitgleich auf
> > > der datenbank arbeiten, kommt es zu keinen "überschneidungen" der
> > > zurückgegebenen ID?
> > >
> > Nein. Diese ID ist wirklich die des von dir in dieser Anwendung zuletzt
> > angelegten Datensatzes.
>
> Falsch!
>
> mysql_insert_id() bzw. die entsprechenden Äquivalente in den verschie-
> denen APIs liefern die letzte vergebene AUTO_INCREMENT Nummer für die
> jeweilige Datenbank-Verbindung. Nix Anwendung. Verbindung! Anwendungen
> können durchaus mehrere Datenbank-Verbindungen benutzen.
>
> Dummerweise hat PHP die Angewohnheit, Verbindungen zur Datenbank zu
> sharen - zumindest solange man nicht explizit eine neue Verbindung
> verlangt. Also Augen aufmachen!
Es "shared" die Verbindung innerhalb diesen einen Script(-prozesses):
Gibt man in einer MySQL-Funktion keine Verbindung an, wird eine in diesem
Scriptablauf schon vorhandene (zuletzt geöffnete) Verbindung benutzt, oder
versucht eine neue Verbindung zuvor aufzubauen. (i.d.R. öffnet man ja auch
meist nur eine Verbindung zur DB am Scriptanfang, macht seine Abfragen und
beendet dann die Verbindung vor Scriptende wieder. Ausnahmen bestätigen die
Regel *g*)
Wird das Script ein zweites Mal gestartet ("zeitgleicher" 2. Request auf
dieses Script), wird auch eine neue Verbindung benutzt/aufgebaut und nicht
eine Verbindung vom evtl. noch laufenden 1. Script benutzt.
Etwas anders sicht die Sache mit persistent connections aus. Ansonsten
arbeitet diese Funktion wie die C API function mysql_insert_id().
Zusammenfassend:
Aus Sicht der Frage vom OP, kommt es also beim Benutzen von mysql_connect()
nicht zu "Überschneidungen zurückgegebenen ID's", da immer nur die ID vom
letzten INSERT in diesem Scriptablauf (Prozess/Request) zurückgegeben wird.
Gruß
Carsten
Re: F: mysql_insert_id
am 11.07.2006 17:38:16 von Axel Schwenke
"Carsten Wiedmann" wrote:
> Axel Schwenke schrieb:
>
>> mysql_insert_id() bzw. die entsprechenden Äquivalente in den verschie-
>> denen APIs liefern die letzte vergebene AUTO_INCREMENT Nummer für die
>> jeweilige Datenbank-Verbindung.
....
>> Dummerweise hat PHP die Angewohnheit, Verbindungen zur Datenbank zu
>> sharen - zumindest solange man nicht explizit eine neue Verbindung
>> verlangt. Also Augen aufmachen!
>
> Es "shared" die Verbindung innerhalb diesen einen Script(-prozesses):
> Gibt man in einer MySQL-Funktion keine Verbindung an, wird eine in diesem
> Scriptablauf schon vorhandene (zuletzt geöffnete) Verbindung benutzt, oder
> versucht eine neue Verbindung zuvor aufzubauen. (i.d.R. öffnet man ja auch
> meist nur eine Verbindung zur DB am Scriptanfang, macht seine Abfragen und
> beendet dann die Verbindung vor Scriptende wieder. Ausnahmen bestätigen die
> Regel *g*)
Nicht nur. Folgendes PHP Schnipsel
$conn1 = mysql_connect("host", "user", "pass");
$conn2 = mysql_connect("host", "user", "pass");
?>
*scheint* zwei MySQL-Connections aufzubauen. In Wirklichkeit ist das
nur eine. Wenn man jetzt also in $conn1 ein INSERT macht, in $conn2 ein
INSERT macht und dann in $conn1 nach LAST_INSERT_ID() fragt, bekommt
man tatsächlich die ID von dem $conn2 INSERT.
Mit ein paar Funktionsaufrufen und evtl. etwas API-Kapselung a'la
PEAR::DB kann man das problemlos hinbekommen, ohne daß es so offensicht-
lich wäre wie in o.g. Beispiel.
Fairerweise muß man sagen, daß man mysql_connect() auch anweisen kann,
jedes Mal eine neue Verbindung aufzumachen. Aber das ist nicht der
Default.
> Wird das Script ein zweites Mal gestartet ("zeitgleicher" 2. Request auf
> dieses Script), wird auch eine neue Verbindung benutzt/aufgebaut und nicht
> eine Verbindung vom evtl. noch laufenden 1. Script benutzt.
Ja. Noch(!) ist das so. Warte mal, bis multithreading und global
Connection pooling auch für PHP funktionieren.
> Etwas anders sicht die Sache mit persistent connections aus.
Nicht wirklich. Die persistente Connection überlebt lediglich das
implizite am Ende jedes PHP-Skripts. Man könnte also
schlimmstenfalls mit einem LAST_INSERT_ID() ohne vorheriges INSERT die
vergebene ID aus dem vorigen Skript-Aufruf erfahren. Das ist zwar
unschön, aber kein Beinbruch (evtl. ein Sicherheitsloch). Allerdings
will man persistente MySQL-Connections sowieso nicht verwenden.
> Zusammenfassend:
> Aus Sicht der Frage vom OP, kommt es also beim Benutzen von mysql_connect()
> nicht zu "Überschneidungen zurückgegebenen ID's", da immer nur die ID vom
> letzten INSERT in diesem Scriptablauf (Prozess/Request) zurückgegeben wird.
Es sei denn, sein Skript nutzt mehrfach die gleiche MySQL-Verbindung
und es wird zwischen INSERT und mysql_insert_id() noch etwas gemacht,
das potentiell diese MySQL-Verbindung benutzt.
XL
Re: F: mysql_insert_id
am 11.07.2006 18:18:28 von Axel Schwenke
Christian Kirsch wrote:
[PHP Doku]
> Was in dieser Beschreibung fehlt, ist das, was der OP wissen wollte
> (und was in der Beschreibung von LAST_INSERT_ID() steht): Dass man die
> ID für genau *diese* Verbindung bekommt, und dass da niemand anders
> zwischen pfuschen kann. D.h. bei direkt aufeinanderfolgenden Aufrufe von
> INSERT
> und
> SELECT LAST_INSERT_ID()
> liefert der zweite immer die ID, die der erste erzeugt hat.
> *Vorausgesetzt*, das läuft über dieselbe Verbindung. Steht so leider
> nicht in der PHP-Dokumentation, dafür kryptisches Zeug in eigenartiger
> Rechtschreibung: "Wenn die Verbindungs-Kennung nicht angegeben wird,
> wird die zuletzt geöffnete Verbindung angenommen." Oder sollte das
> wirklich so krank implementiert sein: Anwendung A führt ein INSERT
> aus, Anwendung B öffnet eine Verbindung und führt ein INSERT aus,
> Anwendung A fragt nach der last_insert_id und bekommt die von
> Anwendung B?
Nein. Aber es gibt eine globale Variable [1] für die "zuletzt benutzte"
MySQL-Connection (technisch ist das ein Ressource-Typ, also in etwa
eine Objekt-Referenz). Der Connection-Parameter ist nun bei den meisten
API-Funktionen optional und nutzt als Default o.g. globale Variable.
Warum das PHP-API für MySQL so designt wurde, will ich ehrlich gesagt
gar nicht wissen. Vermutlich eine Mischung aus Tippfaulheit und "mehr
als eine Datenbankverbindung braucht sowieso keiner". Oder Drogen.
[1] global für die Instanz des PHP-Interpreters. Im gegebenen Kontext
ist das ein Apache-Worker-Prozeß, der immer nur genau ein PHP-
Skript ausführt. Wenn man PHP mit multithreading baut, wird das
hoffentlich(!) thread-local.
XL
Re: F: mysql_insert_id
am 11.07.2006 18:35:42 von Nico Haase
Hallöchen,
*Axel Schwenke* schrub:
>> Gibt man in einer MySQL-Funktion keine Verbindung an, wird eine in diesem
>> Scriptablauf schon vorhandene (zuletzt geöffnete) Verbindung benutzt, oder
>> versucht eine neue Verbindung zuvor aufzubauen. (i.d.R. öffnet man ja auch
>> meist nur eine Verbindung zur DB am Scriptanfang, macht seine Abfragen und
>> beendet dann die Verbindung vor Scriptende wieder. Ausnahmen bestätigen die
>> Regel *g*)
>
> Nicht nur. Folgendes PHP Schnipsel
>
>
> $conn1 = mysql_connect("host", "user", "pass");
> $conn2 = mysql_connect("host", "user", "pass");
> ?>
>
> *scheint* zwei MySQL-Connections aufzubauen. In Wirklichkeit ist das
> nur eine. Wenn man jetzt also in $conn1 ein INSERT macht, in $conn2 ein
> INSERT macht und dann in $conn1 nach LAST_INSERT_ID() fragt, bekommt
> man tatsächlich die ID von dem $conn2 INSERT.
Und? Genau das steht doch auch in der Dokumentation:
| Für den Fall, dass ein zweiter Aufruf von mysql_connect() mit den
| gleichen Argumenten erfolgt, wird keine neue Verbindung aufgebaut,
| sondern die Verbindungs-Kennung der schon bestehenden Verbindung
| zurückgeliefert. Der Parameter neue_Verbindung beeinflusst dieses
| Verhalten und mysql_connect() öffnet immer eine neue Verbindung,
| sogar dann, wenn mysql_connect() zu einem früheren Zeitpunkt mit
| den gleichen Parametern aufgerufen wurde.
(aus http://de2.php.net/mysql_connect)
mfg
Nico
--
www.buchtips.net - Rezensionen online
Re: F: mysql_insert_id
am 11.07.2006 18:37:36 von Carsten Wiedmann
Axel Schwenke schrieb:
> "Carsten Wiedmann" wrote:
> >
> > Es "shared" die Verbindung innerhalb diesen einen Script(-prozesses):
> > Gibt man in einer MySQL-Funktion keine Verbindung an, wird eine in
> > diesem
> > Scriptablauf schon vorhandene (zuletzt geöffnete) Verbindung benutzt,
> > oder
> > versucht eine neue Verbindung zuvor aufzubauen. (i.d.R. öffnet man ja
> > auch
> > meist nur eine Verbindung zur DB am Scriptanfang, macht seine
> > Abfragen und beendet dann die Verbindung vor Scriptende wieder.
> > Ausnahmen bestätigen die Regel *g*)
>
> Nicht nur. Folgendes PHP Schnipsel
>
>
> $conn1 = mysql_connect("host", "user", "pass");
> $conn2 = mysql_connect("host", "user", "pass");
> ?>
>
> *scheint* zwei MySQL-Connections aufzubauen. In Wirklichkeit ist das
> nur eine. Wenn man jetzt also in $conn1 ein INSERT macht, in $conn2 ein
> INSERT macht und dann in $conn1 nach LAST_INSERT_ID() fragt, bekommt
> man tatsächlich die ID von dem $conn2 INSERT.
Stimmt. Jetzt weis ich auch worauf du hinauswolltest.
> Fairerweise muß man sagen, daß man mysql_connect() auch anweisen kann,
> jedes Mal eine neue Verbindung aufzumachen. Aber das ist nicht der
> Default.
Nicht der Default, aber auch im PHP-Manual dokumentiert das dem so ist. (Zum
Default haben sie das nicht gemacht, da es diese Option erst seit 4.2.0
gibt.)
> > Zusammenfassend:
> > Aus Sicht der Frage vom OP, kommt es also beim Benutzen von
> > mysql_connect()
> > nicht zu "Überschneidungen zurückgegebenen ID's", da immer nur die ID
> > vom
> > letzten INSERT in diesem Scriptablauf (Prozess/Request) zurückgegeben
> > wird.
>
> Es sei denn, sein Skript nutzt mehrfach die gleiche MySQL-Verbindung
> und es wird zwischen INSERT und mysql_insert_id() noch etwas gemacht,
> das potentiell diese MySQL-Verbindung benutzt.
Stimmt. Nicht ohne Grund steht im PHP-Manual, dass sich mysql_insert_id()
auf das letzte INSERT (Funktion welche die ID beinflusst) bezieht, und man
mysql_insert_id() direkt nach dem mysql_query() (mit dem INSERT) ausführen
sollte. Nich anders, als auch die C API Funktion von MySQL worauf diese
Ausetzt.
Muss aber auch sagen, dass ich selbst noch nie in der Versuchung war, in
einem Script / C-Prog zwei gleiche Verbindungen gleichzeitig aufzubauen.
Gruß
Carsten