Einfuegen von Daten in eine InnoDb

Einfuegen von Daten in eine InnoDb

am 12.11.2007 14:12:52 von Albert Hermeling

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

Re: Einfuegen von Daten in eine InnoDb

am 12.11.2007 14:16:52 von Claus Reibenstein

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

Re: Einfuegen von Daten in eine InnoDb

am 12.11.2007 15:20:46 von Albert Hermeling

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

Re: Einfuegen von Daten in eine InnoDb

am 15.11.2007 10:35:43 von Kris

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?=