Table definition has changed

apophis171

Benutzer
Beiträge
22
Moin Moin

Folgende Fehlermeldung bekomme ich manchmal:

1412 (HY000): Table definition has changed, please retry transaction

Was sie bedeutet weiß ich, allerdings hab ich keine Ahnung warum sie kommt.

Was mache ich: Über ein Python Skript lade ich von openweathermap.org alle 3 Stunden die Wetterdaten und trage sie in die Datenbank ein (Das Skript wird mit Cron ausgeführt und funktioniert perfekt, von dort kamen nie Fehlermeldungen (außer mal n 500er vom Server :) )). Vom Hauptprogramm (auch in Python geschrieben) wird in regelmäßigen Abständen diese Daten abzufragen und von dort kommt ab und zu der Fehler und lässt den entsprechenden Thread abstürzen.

Ich hab die beiden Abfragen jetzt zeitlich so abgestimmt, dass sie sich nicht in die quere kommen (also, dass das cron skript nicht genau dann die Tabelle löscht und neu schreibt, wenn gerade versucht wird zu lesen). Laut meinem debuglog scheint das auch hinzuhauen.

Jetzt die Frage: Wie kann dieser Fehler entstehen, obwohl es keine Änderungen in der Tabelle gab?
 
Werbung:
Also, das Script, was über Cron ausgeführt wird, lädt die daten von openweathermap, ist das laden erfolgreich gewesen werden die alten Daten gelöscht (TRUNCATE TABLE) und die neuen Daten werden in die Tabelle eingetragen. Hier ist alles perfekt. Der Fehler kommt sporadisch bei einer Abfrage der Daten.
 
Vergessen zu erwähnen, ich nutze MariaDB. Allerdings muss ich sagen, dass ich MySQL seit über 14 Jahre in der Webentwicklung nutze und nie wirklich Probleme hatte. Das hat alles mit MariaDB und Raspbian OS angefangen.
 
Der Grund liegt daran, dass offenbar bei einem TRUNCATE manchmal in Wirklichkeit im Hintergrund ein DROP TABLE gemacht wird weil das schneller ist:

Ok, das würde den Fehler jedenfalls erklären und bietet mir einen Ansatz für eine Lösung. Allerdings: Das Skript, was ich jetzt mit Cron ausführen lasse, war vorher Teil des Hauptprogramms und lief lediglich in einem separaten Thread, dort hatte ich den Fehler nie gehabt.

Randnotiz: genau an dem Tag wo ich das Skript separiert habe hatte ich auch mal wieder ein update des Systems gemacht. Keine Ahnung ob es da Zusammenhänge geben könnte.
 
Ok, hier mal ein Zitat aus den manpages:
Truncate operations drop and re-create the table, which is much faster than deleting rows one by one, particularly for large tables.
Ich mach das jetzt mit DELETE. Soviel Daten sind da nicht drin, dass es ewig dauern könnte. :)

Danke für eure Unterstützung.
 
Mal als Info aus einer funktionierenden Welt:

  • TRUNCATE ist in der Tat erheblich schneller
  • TRUNCATE kann in einer Transaktion laufen
  • TRUNCATE erstellt in der Tat qusi die Tabelle neu - nur bleiben die Kataloge sauber
  • DELETE erzeugt enorm viel Transaction Log
  • DELETE hinterläßt dead tuple

mal so als schnelle Gedanken. Wenn ein System wie MySQL beim TRUNCATE ab und an die Systemkataloge kapott macht, so daß nachfolgende Abfrage wie bei Dir enden - ja, dann würde ich das einfach in die Tonne treten.
 
Meinst du mein Skript bzw. das query oder die Datenbank? :)
die DB ;-)

Wie kann ich das verhindern? Darüber hab ich mir nie Gedanken gemacht.

ich weiß nicht (genau), wie MVCC bei MySQL & Co arbeitet. In PG hat jeder Datensatz u.a. 2 hidden fields: xmin/xmax. Diese geben die Sichtbarkeit an, also in welchen Transaktionen der Datensatz sichtbar ist. Bei einem DELETE oder auch UPDATE wird da einfach xmax gesetzt: dieser Datensatz ist nur bis zur Transaktionsnummer = xmax sichtbar. Er wird NICHT physisch gelöscht. Später dient VACUUM zur Freigabe des Speicherplatzes. Bis dahin ist dieser Datensatz für Transaktionen mit einer Transaktionsnummer kleiner xmax halt sichtbar. Und das ist auch gut so ...
Bei einem TRUNCATE bleiben die Metadaten der 'alten' Tabelle halt solange bestehen, bis diese in keiner Transaktion mehr sichtbar sind, es entsteht kein BLOAT in der Tabelle, weil die alte Tabelle für noch laufende Transaktionen sichtbar ist - und neue Transaktionen sehen die geTRUNCATEete tabelle.

tl;dr

das funktioniert halt einfach. Einfach so, seit 20 Jahren oder länger. In PostgreSQL.
 
Macht es viel Arbeit, die Datenbank von MariaDB auf PostgreSQL umzustellen?

Depends. Ich sag mal so: bis auf Ausnahmen (dazu später mehr) kann PG alles, was MariaDB kann. Fast immer besser. Und dazu sehr, sehr viel mehr. Ausnahme: die Bugs, die MySQL/MariaDB hat, und auf die vielleicht auch so manche Software aufbaut - nun, die gibt es in PG nicht. Zum Beispiel:

  • MySQL prüft die Syntax von Check-Constraints - mißachtet sie aber dann
  • select a,b,c,max(d) from table group by a; funktioniert in MySQL (und liefert ein zufälliges Resultat), in PG liefert sowas eine Fehlermeldung
  • ...

Oder anders formuliert: Du kommst von etwas, was nur nur sehr, sehr primitiv ist, und wechselst auf etwas, was um Größenordnungen mehr kann. Im Normalfall ist das also kein Ding. Was problematisch ist: bei einer 1:1 - Migration schleppst Du alle negativen Dinge mit. Also z.B. falsche Datentypen, falsche Indexe, ... PostgreSQL hat SOOOOO viel mehr, an Datentypen, Indexen, ...

tl;dr

eher nein, aber um die volle Macht von PG auszunutzen mußt Du evtl. auch etwas mehr Zeit investieren, sonst kratzt Du nur an der Oberfläche.
 
Werbung:
Bei meinem aktuellen Projekt gehe ich generell neue Wege, weshalb nicht auch ne neu DB einführen :) Problem: Die Daten und Kommentare in der DB haben eine menge Arbeit gemacht und ich hab wenig Lust das neu anzulegen. Gibt es kein Skript, was mir die Migration erleichtern kann?
 
Zurück
Oben