Einfacher MySQL Fehler-Cache für MyISAM Lock Fehler

Im Artikel „MySQL MyISAM: Performance-Probleme auf der Spur“ haben wir festgestellt, dass MySQL MyISAM-Tabellen bei einem Schreibprozess die ganze Tabelle während des Schreibzuganges sperrt. Weitere Schreibprozesse werden in eine Warteschlange eingereiht. Wenn die vorangingen Schreibprozesse jedoch länger als der Timeout des hintenanstehenden Schreibprozesses dauern, erfolgt ein Abbruch (Fehler) des Prozesses.
Im hier untersuchten Projekt entstehen so rund 40 bis 50 Insert und Update-Fehler pro Tag. Alle Jobs sind in C# programmiert und schreiben ein ausführliches Logfile. Aktuell werden einmal am Tag die Logfiles geprüft und die fehlgeschlagenen SQL-Befehle, die im Logfile geschrieben sind, manuell nachgeholt. Eine unbefriedigende Lösung. Der nächste Schritt bestand darin, ein eigenes Logfile nur mit den fehlgeschlagenen Befehlen zu schreiben. Dies kann, wenn der MySQL-Server nicht ausgelastet ist, schnell nachgeholt werden. Da die Datenbankanwendung nur begrenzt auf Realtimedaten angewiesen ist (eine Verzögerung von einer Stunde ist hier akzeptabel), kann dies eine Lösung sein. Jedoch muss dies noch automatisiert werden. Eine weitere Möglichkeit, die Tabellen auf InnoDB umzustellen, werden wir in einem weiteren Schritt untersuchen.

Erster Lösungsansatz: Ein eigener MySQL-Fehler-Cache
Im vorliegenden Projekt bauen keine mehrere Insert und Updates nacheinander auf. Daher können einige fehlgeschlagene Insert oder Update-Befehle nachgeholt werden. In den vorliegenden C#-Programmen wurde jeder SQL-Zugriff mittels try-catch angefangen. Im Catch-Block schreiben wir ein zentrales Logfile rein mit den fehlgeschlagenen SQL-Befehlen. Diese Befehle können dann manuell nachgeholt werden:

string sSQL = "";
try
{
  using (MySqlConnection cn = new MySqlConnection(sConnection))
  {
     //Update-Befehl, der fehlschlagen kann
     sSQL = @"UPDATE [...];
     try
     {
         cn.Open();
         using (MySqlCommand cmd = new MySqlCommand(sSQL, cn))
         {
              cmd.ExecuteNonQuery();
          }
      }
      catch (MySqlException ex)
      {
         logfile("MySQL FEHLER: " + ex.Message);
         MySQL_Error_logfile(sSQL);
       }
     }
  }
catch (Exception ex)
{
   logfile("FEHLER: " + ex.Message);
}

Im obenstehenden C#-Code rufen wir im Fehlerfall die Funktion „logfile“ mit der SQL-Fehlermeldung auf. Die Funktion „MySQL_Error_logfile“ loggt zentral die fehlgeschlagenen MySQL-Befehle.

Zweiter Evolutionsschritt: MySQL_Error_logfile automatisch auslesen und abarbeiten
Da wir sicherlich alle keine Freunde von manuellem Eingreifen und Kontrolle sind, muss eine automatisierte Lösung gefunden werden. Also ist der folgende Schritt denkbar. Wir schreiben wie oben ein einzelnes Error-Logfile, auf das mehrere Tasks Zugriff haben. Dabei können ebenfalls Zugriffsprobleme auftauchen, die diese Lösung im Stadium des Gedankenexperimentes sterben lassen. Doch ich möchte es weiter ausführen.
Zu gegebener Zeit, spätestens am Ende eines Tasks, schaut dieser nach, ob sich ein „MySQL_Error_logfile“ am definierten Platz befindet. Wenn ja, liest dieser das gesamte Logfile in ein Array oder eine ArrayList ein. Wir machen uns den Vorteil der Zeilen zu nutze; jeder fehlgeschlagene SQL-Befehl ist in einer eigenen Zeile geschrieben und ist so schnell und einfach einzulesen.
Wenn das Logfile gelesen ist, wird es sofort gelöscht. So minimieren wir die Zugriffszeit. Wenn ein weiterer Task einen Fehler schreiben will, erstellt er automatisch ein neues Logfile.
Wir haben nun alle fehlgeschlagenen SQL-Befehle in einer ArrayList. Nun arbeiten wir in einer Schleife alle Befehle ab. Wenn der SQL-Server keine Locks auf die betroffenen Tabellen hat, werden die Befehle nun nachgeholt. Kommt es erneut zu einem Fehler, schreiben wir diese erneut in ein „MySQL_Error_logfile“, ein weiterer Task wird sich dann darum kümmern.

Im dritten Evolutionsschritt werden wir die SQL-Fehler in einer SQL-Datenbank schreiben? Was komisch klingt, verspricht spannend zu werden … Weiter: MyISAM-Tabellen-Locks in Cache abfangen und nacharbeiten

Alle Artikel aus dieser Serie
MySQL MyISAM: Performance-Probleme auf der Spur
Einfacher MySQL Fehler-Cache für MyISAM Lock Fehler
MyISAM-Tabellen-Locks in Cache abfangen und nacharbeiten

Schreibe einen Kommentar