2008-10-21 10 views
6

Ich verwende mysql (5.0.32-Debian_7etch6-lügt) und ich habe einen nächtlichen Lauf Bulk Load php bekomme (5.2.6) Skript (unter Verwendung von Zend_DB (1.5.1) über PDO), das macht folgendes:mysql doppelte Eintrag Fehler, wenn es kein doppelter Eintrag (bulk Last über php)

  1. einen Satz von 4 'Import' Tabellen Verkürzen
  2. bulk Daten in diese 4 'Import' Tabellen Einfügen (Wiederbenutzung von IDs, die zuvor in den Tabellen waren, aber ich habe die ganze Tabelle gekürzt, so dass kein Problem sein sollte, richtig ?)
  3. Wenn alles gut geht, benennen Sie die "Live" -Tabellen in 'temp', die 'Import' -Tabellen in 'live' und dann die 'temp' (alt 'live') -Tabellen zum 'Importieren'

Das funktionierte großartig seit Wochen. Jetzt bin ich occassionally dies immer, irgendwo in der Mitte des gesamten Bulkbeladung Prozesses:

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '911' for key 1

Wohlgemerkt, dass dies nicht das erste ID ist, die vor dem Abschneiden bereits in der Tabelle waren. Wenn ich das Skript manuell neu starte, funktioniert es wie ein Zauber.

Irgendwelche Ideen? übrig gebliebene Indizes, vielleicht etwas mit der Umbenennung zu tun?

Darüber hinaus, wenn ich die Tabelle für einen Eintrag mit der ID 911 später überprüfen, ist es nicht einmal da drin.

Antwort

0

Könnte ein anderes Skript in die Datenbank eingefügt werden, während das Import-Skript ausgeführt wird?

0

Haben Sie versucht, das Abfrageprotokoll zu aktivieren, um zu sehen, ob Sie wirklich ein Duplikat einfügen?

Können Sie es in Ihrer Testumgebung reproduzieren? Aktivieren Sie das Abfrageprotokoll nicht in der Produktion.

Es ist möglich, dass die Tabelle beschädigt wurde, wenn das Problem echt ist. Dies kann durch eine Reihe von Dingen verursacht werden, aber zweifelhafte Hardware oder Stromausfall sind Möglichkeiten.

Überprüfen Sie das mysql-Protokoll, um festzustellen, ob es kürzlich oder während des Zeitraums Probleme (oder einen Absturz) gab.

Noch einmal, alles, was ich vorschlagen kann, ist zu versuchen, es in Ihrer Testumgebung zu reproduzieren. Erstellen Sie sehr viele Testdaten und laden Sie sie wiederholt.

1

Anscheinend gab es einige Lock-Probleme oder etwas, ich war in der Lage, das Verhalten zu reproduzieren, indem Sie "SELECT" -Anweisungen auf die betroffenen und verwandten Tabellen in einer parallelen Verbindung schießen.

jetzt verwendet i DELETE FROM statt TRUNCATE und änderte die RENAME TABLE Aussagen (wobei i 3 auf einmal tat umbenennt jeweils) zu einem Bündel von Einzel ALTER TABLE xxx RENAME TO zzz Aussagen und nicht mehr den Fehler nicht reproduzieren kann.

so könnte dies gelöst werden. vielleicht kann jemand anderes von meinem Tag mit der Forschung und viel Versuch und Irrtum profitieren.

0

Verwenden Sie Transaktionen?Sie können viele dieser Arten von Problemen mit Transaktionen eliminieren, besonders wenn es möglich ist, entweder die Tabellen zu sperren oder den Transaktionsisolationsmodus auf serialisierbar zu setzen. Ich bin mit denen auf MySQL nicht wirklich vertraut, aber ich glaube, dass Transaktionen nur auf InnoDB-Tabellen funktionieren (oder das veraltete Wissen sein könnte).

2

Fehler wie diese können auftreten, wenn eine MyISAM-Tabelle beschädigt wird. Das Ausführen des Reparaturbefehls auf dem Tisch in Frage ist in der Regel alles, was es zu beheben erforderlich ist:

> repair table mytablename; 

Eine bessere Lösung ist nicht zu verwenden MyISAM für Tabellen, in denen die Daten ständig ändern - InnoDB ist viel mehr kugelsicher, und als Paul weist richtig darauf hin, dass Sie Transaktionen für InnoDB-Tabellen, aber nicht für MyISAM verwenden können.

Übrigens würde ich vermeiden, Tabellen im laufenden Betrieb umzubenennen - das ist eine ziemlich klobige Sache, regelmäßig zu tun, und könnte einige sehr unerwartete Ergebnisse verursachen, wenn Sie jemals andere Benutzer auf dem System während der Umbenennung haben geht weiter. Warum nicht einfach so etwas tun:

> truncate table temptable; 
> truncate table importtable; 

> #bulk insert new data 
> insert into importtable(col1,col2,col3) 
> values(1,2,3),(4,5,6),(7,8,9); 

> #now archive the live data 
> insert into temptable(col1,col2,col3) 
> select col1,col2,col3 from livetable; 

> #finally copy the new data to live 
> truncate table livetable; 
> insert into livetable(col1,col2,col3) 
> select col1,col2,col3 from importtable; 

Natürlich, wenn Sie eine sehr große Anzahl von Zeilen einfügen, dann würde die Gefahr bestehen, dass alle Ihre Live-Daten so lange nicht verfügbar ist, wenn der Einsatz in Anspruch nimmt, Aber insgesamt ist dieser Ansatz weniger für Indizes, Trigger oder irgendetwas anderes, das mit den fraglichen Tabellen in Verbindung gebracht werden kann, weniger schädlich.

0

Sie erstellen einen neuen Datensatz mit 'ID' Feld ausgelassen (oder NULL), ABER zuvor haben Sie einen anderen Datensatz aktualisiert und seine 'ID' auf '911' geändert. Mit anderen Worten, Sie können keinen anderen Datensatz erstellen, wenn der AUTO_INCREMENT-Wert Ihrer Tabelle verwendet wird.

Verwandte Themen