Seite 1 von 1

MySQLdb, id des grade eingefügten Objektes

Verfasst: Freitag 18. Dezember 2009, 13:37
von Jutus
Hallo,

ich habe da mal ne Frage. Ich habe eine mySQL Datenbank mit einer Tabelle die automatisch neuen Objekten eine ID zuweist. Wenn ich jetzt mit MySQLdb ein neues Objekt einfüge, wie kann ich die ID des neuen Objektes abfragen?

Ich hab scho in die API gesehen aber noch nichts gefunden, ich weiß auch nicht wirklich wonach ich suchen sollte.

Re: MySQLdb, id des grade eingefügten Objektes

Verfasst: Freitag 18. Dezember 2009, 13:56
von /me
Jutus hat geschrieben:ich habe da mal ne Frage. Ich habe eine mySQL Datenbank mit einer Tabelle die automatisch neuen Objekten eine ID zuweist. Wenn ich jetzt mit MySQLdb ein neues Objekt einfüge, wie kann ich die ID des neuen Objektes abfragen?

Ich hab scho in die API gesehen aber noch nichts gefunden, ich weiß auch nicht wirklich wonach ich suchen sollte.
Eine Suche mit Google nach mysqldb autoincrement python bringt mich als ersten Treffer zu http://www.mikusa.com/python-mysql-docs ... tions.html und dort finde ich die Methode insert_id(). Schau dir das mal an, das könnte exakt das sein was du suchst.

Verfasst: Samstag 19. Dezember 2009, 16:45
von Jutus
ja, danke damit geht es.

für alle anderen die vielleicht auch danach suchen, der Aufruf könnte so aussehen:

Code: Alles auswählen


mysql = MySQLdb.connect(....)
cursor = mysql.cursor()
cursor.execute("INSERT ....")
id = mysql.insert_id()


Verfasst: Montag 28. Dezember 2009, 12:03
von noisefloor
Hallo,

ah, gut. Eine ähnlich Sache hatte ich letzthin auch. :-)

Frage: gibt insert_id immer die id des zugehörigen Schreibvorgangs zurück oder die des letzten? Wenn es letzten wäre hätte man ja in DBs mit vielen Queries ggf. eine Art Race-Condition und würde nicht automatisch die korrekt ID bekommen...

EDIT: Habe gerade nachgelesen - es kann die "Race-Condition" vorkommen...

Gruß, noisefloor

Verfasst: Montag 28. Dezember 2009, 15:59
von Darii
noisefloor hat geschrieben:Frage: gibt insert_id immer die id des zugehörigen Schreibvorgangs zurück oder die des letzten? Wenn es letzten wäre hätte man ja in DBs mit vielen Queries ggf. eine Art Race-Condition und würde nicht automatisch die korrekt ID bekommen...
Inwiefern? Wie sollte man überhaupt den „dazugehörigen“ Schreibvorgang ermitteln können? Und mit einer Race Condition hat das auch nichts zu tun.

Verfasst: Montag 28. Dezember 2009, 19:00
von noisefloor
Hallo,
Und mit einer Race Condition hat das auch nichts zu tun.
Nein, mit einer Race-Condition im eigentlichen Sinne nicht. Deswegen hatte ich es in "" gesetzt.

Was ich meine ist, dass man bei dieser Methode nicht automatisch das Ergebnis (=die ID) bekommt, die man "erwartet".

Gruß, noisefloor

Verfasst: Montag 28. Dezember 2009, 19:42
von BlackJack
Falls ich das nicht falsch verstehe ist das IMHO eine astreine Race-Condition. Das Ergebnis ist davon abhängig welche der beiden Einfügeoperationen das "Rennen" gewinnt.

Verfasst: Montag 28. Dezember 2009, 20:11
von noisefloor
Hallo,

so ähnlich: Die Frage ist, ob die Abfrage der ID oder ein zwischenzeitlich ausgelöster, 2. Schreibquery das Rennen gewinnt.

Jedenfalls ist die Methode daher IMHO für Seiten mit viel Traffic = vielen DB-Zugriffen nicht geeignet.

Ich habe es bei mir so gelöst, dass ich ein

Code: Alles auswählen

SELECT id FROM foobar WHERE spam LIKE 'wert' AND egg LIKE 'wert2' AND usw.
wobei ich die Werte der gerade selber eingefügten Felder abfrage. Das ist sicherlich auch nicht die ultimative Lösung, sollte aber hinreichend "genau" sein, sofern man davon ausgehen kann, dass die Kombination der Werte der eingefügten Felder einmalig ist.

Gruß, noisefloor

Verfasst: Montag 28. Dezember 2009, 20:12
von Darii
noisefloor hat geschrieben:Was ich meine ist, dass man bei dieser Methode nicht automatisch das Ergebnis (=die ID) bekommt, die man "erwartet".
Verstehe ich nicht, die bekommt man doch(insert_id ist an die aktuelle Verbindung gebunden, was auf anderen Verbindungen passiert ist egal). Ich meine wenn ich 10 Inserts mache und dann insert_id() kann man nicht erwarten dass man die id vom 1. Insert bekommt. Oder meinst du etwas anderes?
so ähnlich: Die Frage ist, ob die Abfrage der ID oder ein zwischenzeitlich ausgelöster, 2. Schreibquery das Rennen gewinnt.
Das verstehe ich eben nicht, wo soll die 2. Schreibquery herkommen?

Verfasst: Dienstag 29. Dezember 2009, 12:16
von noisefloor
Ich meine wenn ich 10 Inserts mache und dann insert_id() kann man nicht erwarten dass man die id vom 1. Insert bekommt. Oder meinst du etwas anderes?
Ja. :-)
Das verstehe ich eben nicht, wo soll die 2. Schreibquery herkommen?
Genau das ist der Punkt. Wenn du weißt, dass du die Verbindung zur DB exklusiv hast, dann funktioniert das. Wenn du aber z.B. eine stark frequentierte Web-Anwendung hast (z.B. Forum, Wiki...), dann kannst du eben nicht sicher sein, dass dein Abfrage der ID direkt nach deinem Schreib-Query kommt. Daher die Race-Condition.

Zumindest verstehe ich die Aussagen in http://www.mikusa.com/python-mysql-docs ... tions.html so:
Also note that the value of the SQL LAST_INSERT_ID() function always contains the most recently generated AUTO_INCREMENT value, and is not reset between queries because the value of that function is maintained in the server.
Gruß, noisefloor

Verfasst: Dienstag 29. Dezember 2009, 12:45
von sma
Die zitierte Text ist zugegeben nicht eindeutig, aber IMHO MUSS die "last insertion ID" für jede Connection existieren, sodass sich verschiedene Connections nicht in die Quere kommen und es KEINE racing condition gibt. Alles andere wäre ein sehr fragwürdiges Design.

Auch ein stark frequentiertes Forum oder Wiki muss (sollte) pro HTTP request eine Connection benutzen und nicht versuchen, diese (über mehrere threads) wieder zu verwenden. Macht man's hier richtig, würde ich im Gegenzug erwarten, dass MySQL es korrekt macht.

Das lässt sich einfach probieren: Zwei Connections anlegen, in der ersten ein INSERT machen, in der zweiten danach ebenfalls. Jetzt zuerst in der ersten, dann in der zweiten nach der ID fragen.

Stefan

Verfasst: Dienstag 29. Dezember 2009, 13:29
von Darii
noisefloor hat geschrieben:Genau das ist der Punkt. Wenn du weißt, dass du die Verbindung zur DB exklusiv hast, dann funktioniert das. Wenn du aber z.B. eine stark frequentierte Web-Anwendung hast (z.B. Forum, Wiki...), dann kannst du eben nicht sicher sein, dass dein Abfrage der ID direkt nach deinem Schreib-Query kommt. Daher die Race-Condition.
Das ist dann wirklich ein klarer Fall von selbst Schuld. Normalerweise hat man eine Verbindung exklusiv. Wenn nicht, dann hast du die selber „freigegeben“. Wenn du das gemacht hast, dann sollte es ein leichtes sein, die Verbindung für dieses Moment zu „locken“, deine zwei Abfragen abzusetzen und dann wieder freizugeben.

Eine wirkliche Race-Condition sehe ich nur, wenn sich verschiedene Verbindungen in die Quere kommen könnten, das tun sie aber nicht.
http://dev.mysql.com/doc/refman/5.5/en/information-functions.html#function_last-insert-id hat geschrieben: The ID that was generated is maintained in the server on a per-connection basis. This means that the value returned by the function to a given client is the first AUTO_INCREMENT value generated for most recent statement affecting an AUTO_INCREMENT column by that client. This value cannot be affected by other clients, even if they generate AUTO_INCREMENT values of their own. This behavior ensures that each client can retrieve its own ID without concern for the activity of other clients, and without the need for locks or transactions.

Verfasst: Dienstag 29. Dezember 2009, 22:14
von noisefloor
Hallo,

@Darli: THX, das ist eindeutig. :-) Also entspannen ;-)

Gruß, noisefloor