Einfuegen von Daten in eine InnoDb

Hallo,

ich habe eine kleine Tabelle von Type InnoDb Aufbau wie folgt:

hashurl | url | status | timestamp | ecount | rcode

die Spalte hashurl ist als Primary Key gekennzeichnet, in ihr wird der Hash
Wert der URL gespeichert. Neue Daten füge ich nach folgendem Schema ein:

for item in liste_mit_urls
urlhash = hash(item)
try:
cursor.execute("INSERT INTO UrlDb(hashurl, url)
VALUES (%s, %s)", (urlhash, item)):
hashurllist.append(urlhash)
except _mysql_exceptions.IntegrityError:
pass

Am Ende mache ich cursor.connection.commit() und schließe somit die
Verarbeitung ab.

1.
Ist mein Vorgehen, INSERT versuchen im Fehlerfall diesen Abfangen, Sinnvoll?
Unterumständen können sehr viele Fehler ausgelöst werden, da in einer Recht
kurzen Zeit viele URLs (pro Stunde ca. 60.000) neu eingefügt werden.
Vieleicht doch mit SELECT feststellen ob die URL schon vorhanden ist?

2.
Ich mache, wenn die Schleife durchgelaufen ist, ein commit, sollte man das
so machen oder ist es besser nach jeder geglückten Einfügeoperation das zu
machen?

3.
Mehrere Prozesse greifen auf die gleiche Tabelle schreibend zu; im Test
waren es bis jetzt 5. Nach dem sie einige Zeit klaglos ihren Dienst
verrichtet haben wurde folgende Exception ausgelöst:

_mysql_exceptions.OperationalError: (1205, 'Lock wait timeout exceeded; try
restarting transaction'

Was der Fehler bedeutet ist mir klar, es wurde zu lange auf das erhalten des
Locks gewartet. Startet man in so einem Fall, wie aus der Meldung zu sehen,
die Transaction einfach neue? Kann man den Fehler auch anderes her werden?

Schon mal danke für die Hilfe

Mit freundlichen Grüßen

Albert

Mein Rechner
openSuse 10.3, MySQL 5.0.45-Max
Hardware: AMD Athlon(tm) 64 X2 Dual Core, 1 GB Ram
Albert Hermeling [ Mo, 12 November 2007 14:12 ] [ ID #1868419 ]

Re: Einfuegen von Daten in eine InnoDb

Albert Hermeling schrieb:

> for item in liste_mit_urls
> urlhash = hash(item)
> try:
> cursor.execute("INSERT INTO UrlDb(hashurl, url)
> VALUES (%s, %s)", (urlhash, item)):
> hashurllist.append(urlhash)
> except _mysql_exceptions.IntegrityError:
> pass

Was ist das für eine Sprache? Versteht MySQL die?

SQL ist es jedenfalls nicht. PHP auch nicht.

Gruß. Claus
Claus Reibenstein [ Mo, 12 November 2007 14:16 ] [ ID #1868420 ]

Re: Einfuegen von Daten in eine InnoDb

Claus Reibenstein wrote:

> Albert Hermeling schrieb:
>
>> for item in liste_mit_urls
>> urlhash = hash(item)
>> try:
>> cursor.execute("INSERT INTO UrlDb(hashurl, url)
>> VALUES (%s, %s)", (urlhash, item)):
>> hashurllist.append(urlhash)
>> except _mysql_exceptions.IntegrityError:
>> pass
>
> Was ist das für eine Sprache? Versteht MySQL die?
Entschuldige Bitte als Sprache verwende ich Python 2.5 Als API benütze ich
MySQLdb. Diese Angaben sollten unter "Mein Rechner" stehen. Habe ich leider
vergessen :-(
>
> SQL ist es jedenfalls nicht. PHP auch nicht.
>
> Gruß. Claus
Albert Hermeling [ Mo, 12 November 2007 15:20 ] [ ID #1868422 ]

Re: Einfuegen von Daten in eine InnoDb

Albert Hermeling wrote:
> Ist mein Vorgehen, INSERT versuchen im Fehlerfall diesen Abfangen,
> Sinnvoll? Unterumständen können sehr viele Fehler ausgelöst werden, da in
> einer Recht kurzen Zeit viele URLs (pro Stunde ca. 60.000) neu eingefügt
> werden. Vieleicht doch mit SELECT feststellen ob die URL schon vorhanden
> ist?

Du kannst

1. BEGIN; SELECT ... FOR UPDATE; INSERT...; COMMIT machen, und so einen
sauberen RMW-Zyklus hinlegen.

2. REPLACE INTO verwenden und so das Problem prinzipiell vermeiden.

3. INSERT ON DUPLICATE KEY UPDATE verwenden und so das Problem prinzipiell
vermeiden.

> 2.
> Ich mache, wenn die Schleife durchgelaufen ist, ein commit, sollte man das
> so machen oder ist es besser nach jeder geglückten Einfügeoperation das zu
> machen?

Du sollst so ca. alle 1000 INSERTS ein COMMIT machen, das wäre für die
Performance optimal.

> Was der Fehler bedeutet ist mir klar, es wurde zu lange auf das erhalten
> des Locks gewartet. Startet man in so einem Fall, wie aus der Meldung zu
> sehen, die Transaction einfach neue? Kann man den Fehler auch anderes her
> werden?

Nein, Du generierst hier Deadlocks aus INSERT LOCK upgrades.

Kris

--
Kristian =?iso-8859-15?q?Köhntopp?= <kris [at] xn--khntopp-90a.de>
Kris [ Do, 15 November 2007 10:35 ] [ ID #1871337 ]
Datenbanken » de.comp.datenbanken.mysql » Einfuegen von Daten in eine InnoDb

Vorheriges Thema: Manuell synchronisieren
Nächstes Thema: Suche SQL Forum