MySQL Cluster oder Hot-Stand-By Lösung? Eine Frage der Hochverfügbarkeit

Gerade bei größeren Projekten ist die Frage nach einer Datenbank-Hochverfügbarkeit eine elementare Frage. Wenn bei einem Webshop der Datenbankserver wegbricht, entgeht dem Händler Umsatz. Vom Imageschaden ganz zu schweigen. Aus diesem Grund wird kaum ein größeres Webprojekt ohne einen Hot- oder Cold-Stand-By Datenbankserver auskommen.

Warum langt eine Datenbanksicherung nicht?
Im Artikel „MySQL Datenbank oder einzelne Tabelle kopieren“ habe ich eine Datenbanksicherung mit MySQL-Boardmitteln beschrieben. Prinzipiell ist dies schon mal ein guter Ansatz. Die Datenbank als Sicherung räumlich getrennt auf einem externen Datenträger aufzubewahren, kann im Bedarfsfall viel Arbeit ersparen. Löst aber unser Problem nicht. Wenn ein Datenbankserver ausfällt, muss sofort ein anderer Server die Arbeit übernehmen, so dass man keine Offline-Zeit hat und ich Ruhe sich um den ausgefallenen Server kümmern kann.

Was ist ein Cluster-System?
Cluster oder Clustering bezieht sich auf den Gedanken, die Verfügbarkeit von Systemen und Anwendungen über standardisierte und preiswerte Hardware zu erhöhen. Heißt also nichts anderes, als dass mehrere Standard-Rechner einen Verbund bilden, aber nach außen als ein Rechner oder Datenbank sich zu erkennen geben. Steigt die Last, teilt sich diese auf die einzelnen Maschinen (Cluster-Member oder Knoten genannt) auf. Fällt ein Cluster-Member aus, steigt die Last der verbleibenden Member, aber das System (Datenbank) bleibt nach außen verfügbar.

Was ist Hot-Stand-By, was ist Cold-Stand-By und was ist der Unterschied?
Ein Cluster ist der Königsweg, keine Frage. Je nach Projekt und Verfügbarkeit kann man sich auch mit einer Hot- oder Cold-Stand-By-Lösung behelfen. Beide Lösungen setzen auf einen zweiten Server auf. Während bei einer Hot-Stand-By-Lösung der zweite Server ständig in Betrieb ist und die Daten mit dem Master-Server ständig repliziert (also die Daten in Realzeit aktuell hält), ist der zweite Server bei einer Cold-Stand-By-Lösung aus. Erst im Bedarfsfall wird der zweite Server eingeschaltet und auf den aktuellen Stand gebracht (einige Lösungen gleichen sich zu definierten Zeitpunkten automatisiert ab). Beiden Lösungen gemein ist, dass die eigentliche Arbeit der Master-Server macht, der Slave-Server nur bei Ausfall des Masters ins Spiel kommt.

MySQL-Replikation, Überlegungen zur Hochverfügbarkeit
In diesem Artikel möchten wir folgenden Fall beschreiben: Wir haben eine Master-MySQL-Datenbank sowie mehrere Slave-Datenbanken. Die Aufbereitung der Daten auf dem Master-Server ist so aufwändig und CPU-hungrig, dass zu mehreren Zeitpunkten untertags ein Webzugriff auf die Datenbank nicht oder nur schwer möglich ist. Aus diesem Grund soll die fertige Datenbank auf einen Slave-Datenbank-Server gespiegelt werden; der Zugriff der Webfrontend-Server soll nur auf die gespiegelten Slave-Server erfolgen. Somit kann bei der Datenbankaufbereitung der Master-Server seine volle Leistung nutzen und kein Webzugriff stört ihn. Nachteil dieser Lösung: Die Daten der Slave-Server hinken in der Aktualität dem Master-Server hinterher, was aber in unserer Lösung akzeptiert werden kann.
Ferner muss sichergestellt werden, dass die Berechnungen durch die Replikation nicht noch von den Slave-Servern durchgeführt wird. Diese sollen nur das fertige Ergebnis replizieren. Dies kann durch die Einschränkungen der Replikation aus Datenbanken und Tabellen sichergestellt werden.
Wir replizieren also die Datenbank auf mehrere Slave-Server. Jeder Slave-Server ist zugleich ein Webfrontend-Server. Per Network-Load-Balancing (NLB) werden die Web-Besucher auf die einzelnen Webfrontend-Server, also auf unsere MySQL-Slave-Server, verwiesen.

Im nächsten Teil („MySQL Replikation (Master/Slave) einrichten“ #######) beschäftigen wir uns nach soviel Vorüberlegung mit der eigentlichen Einrichtung der MySQL-Replikation.

Firefox Lesezeichen (Bookmarks) und seine History

Seit der Version 3 des Firefox-Browsers werden die internen Daten wie Lesezeichen, History (Chronik) sowie viele weitere Daten in einer internen Datenbank zusammengefasst. Diese SQL-Datenbank finden wir unter dem Namen „places.sqlite“ im Dateisystem. Je nach Installation im Userverzeichnis oder bei der portablen Firefox-Installation beispielsweise im Installationsverzeichnis „Dataprofile“. Im Zweifelsfall einfach die Windows-interne Suche benutzen.

Firefox Lesezeichen nach Windows Neuinstallation wiederherstellen
Da die meisten Einstellungen des Browsers in dieser Datei gespeichert sind, kann man diese Datei durchaus auf einen anderen Rechner kopieren. So ist es beispielsweise möglich, von einem alten Rechner diese Datei zu sichern und nach einer Neuinstallation von Windows samt Firefox die bisherigen Lesezeichen und die History wiederhezustellen. Wichtig dabei ist, dass für diese Aktion der Firefox geschlossen ist.

Lesezeichen mitnnehmen (migrieren)
So sind mir auch schon Kunden untergekommen, die diese Datei auf einem USB-Stick von Rechner zu Rechner mitnehmen, um ihre History und ihre Lesezeichen jedezeit parat zu haben. Dies mag Geschmackssache sein. Denn genau für diese Vorgehensweise wurde die portable Version von Firefox geschaffen.

Die Datei places.sqlite verkleinern
Wie jede Datenbank wächst auch die places.sqlite stetig. Bookmarks, History und Favicons blähen die Datei auf. Natürlich kann man über Firefox-Boardmittel versuchen, unnötigen Ballast zu entfernen. Jedoch wird die Datei nicht so klein, wie sich mancher Nutzer wünscht.
Wenn man die „places.sqlite“-Datei bei geschlossenem Firefox löscht (ich empfehle eher umbenennen!), erstellt der Firefox beim Start die Datei anhand der letzten json-Sicherungsdatei die places.sqlite neu. Ein alternativer Weg ist die Wiederherstellung einer json-Sicherungsdatei mit Bordmitteln des Firefox-Browsers. So kann die aktuelle History gesichert und wiedereingespielt werden. Nach diesem Vorgang ist die neue places.sqlite deutlich verkleinert.
Warum ist das so? Die wiederhergestellte Datei beinhaltet beispielsweise keine Favicons mehr. Diese Grafikdaten sind auch nicht wirklich nötig. Der Browser läd sie bei Bedarf von der besuchten Webseite neu herunter.

Sichern oder Wiederherstellen der places.sqlite
Über „Lesezeichen/Alle Lesezeichen anzeigen“ öffnet sich die Bibliothek des Firefox-Browsers. Mittels des Button „Importieren und Sichern“ kann ein Kontextmenü geöffnet werden.. Über die Auswahl „Wiederherstellen“ kann auf eine bestehende json-Sicherung zugegriffen werden. Die Auswahl „Datei wählen“ erlaubt das Einspielen einer externen Sicherung.

Zugriff auf die sqlite-Datenbank
Um sich die systemeigene Datenbank ein wenig näher anzuschauen, gibt es für den Firefox ein Add-On (SQLite Manager). Dieses Tool erlaubt vollen Zugriff auf die Datenbank und ist daher mit Vorsicht zu bedienen. Wer nicht weiss, was er macht, sollte auf jeden Fall vorher eine Sicherung seiner places.sqlite anfertigen. Prinzipiell gilt: Das Add-On SQLite Manager ist ein Systemwerkzeug und sollte nicht unbedarft eingesetzt werden!

Verkeinern der places.sqlite mittels vacuum
Auch die Datenbank selbst kann – wie nahezu jede andere Datenbank selbst – mittels SQL-Boardmitteln verkleinert werden. Der Befehl dazu heisst „Vacuum“. Letztlich entfernt Vacuum die Fragmentierung der Datenbank und befreit sie von unnötigem Ballast.
Um den Befehl absetzen zu können, benötigen wir den SQLite Manager als Add-On im Firefox. Nach Aufruf des Managers wird die places.sqlite geöffnet. Unter dem Register Execute SQL kann nun der Befehl vacuum eingegeben und mit Run SQL zur Ausführung gebracht werden. Der Erfolg der Verkleinerung wird im Feld Last Error angezeigt.

Windows Home Server Restore: Windows Home Server not found – Wiederherstellung schlägt fehl

Für kleinere private Netzwerke ist der Windows Home Server (WHS) eine feine Sache. Ein zentraler Datenspeicher und die Möglichkeit, alle Client-PCs automatisch zu sichern. Durch diese Automation kann man im Bedarfsfall einzelne Laufwerke mit dem Datenstand eines bestimmten Sichtages hinzufügen, so dass einzelne Dateien vergleichen und ggfls. ersetzt/wiederhergestellt werden können. Eine tolle Sache. Aber auch wenn der Recher komplett seinen Geist aufgibt, kann man ihn mittels der „Windows Home Server Restore CD“ auf jedes verfügbare Image neu aufsetzen. Letzteres geht schnell von der Hand. Es gibt jedoch zwei entscheidende Dinge VORAB zu prüfen und zu testen: Für das Zurückspielen eines Images vom Windows Home Server ist einerseits die CD „Windows Home Server Restore CD“ Voraussetzung. Das Image hält der WHS vor, sie kann jederzeit im Bedarfsfall auch nachträglich gebrannt werden. Doch hat der wiederherzustellende PC überhaupt ein CD-Laufwerk? Wenn nein, kann das Image über diverse Tools auf einen USB-Stick kopiert und der Rechner von diesem gebootet werden. Dies klappt sehr gut, sollte jedoch vorher schon erstellt und getestet werden, denn im Bedarfsfall hat man wenig Zeit und Nerven, sich mit möglichen „Problemen“ herumzuschlagen. Vor allem das folgende problem: Der Netzwerkkartentreiber.

Fehlermeldung: „Windows Home Server Not Found. Search again?”
Im Normalfall ist das Zurückspielen eines im Netz befindlichen Client-PCs mittels der WHS Restore CD kein Problem. Wenn jedoch die CD keinen passenden Netzwerkkartentreiber für das Mainboard finden kann, schlägt die Verbindung mit der Fehlermeldung „Windows Home Server Not Found. Search again?” fehl. Der Restore-Vorgang erlaubt das Einbinden von Treibern, ist jedoch nicht sehr „innovativ“.

Einbinden von alternativen Treibern im WHS-Restore-Vorgang
Wenn die Restore-CD gebootet und die Sprache ausgewählt wurde, kommt nach geraumer Zeit das Fenster „Detect Hardware“. Es zeigt die Meldung „The following network and storage devices have been found on this computer“. Unter anderem werden unter (1) die “Network devices” aufgelistet. Wenn dieser Treiber nicht passt, kann durch drücken des Buttons “Show Details” ein weiteres Fenster geöffnet werden. Hier den Button „Install Driver“ klicken. Es erscheint die Meldung „Insert a USB flasch drive or a floppy disc…“. Der Treiber (ungepackt und kein EXE-File!) muss also über ein USB-Stick oder einer Diskette zugespielt werden. Mit dem Button „Scan“ (dauert ein wenig) liest das Restore-Programm die Treiber ein. Es sollte die Meldung „Drivers were found for your hardware“ erscheinen. Mit dem Button „Continue“ geht der Vorgang weiter und der WHS sollte gefunden werden.

„Please wait while your Home Server is located, Finding your Windows Home Server“
Es sollte also schon vorab jeder Client daraufhin geprüft werden, ob der Restore-Vorgang koeekt verläuft bzw. ob die Software mittels Standard-Netzwerkkartentreiber den WHS findet. Wenn nicht, muss dieser in ungepackter Version auf ein Medium (USB-Stick) gesichert werden, so dass es im Bedarfsfall keine Probleme gibt.

Speichern des Netzwerkkartentreibers eines bestehenden Windows-PCs
Normalerweise liegt eine Treiber-CD jedem Mainboard oder neuem PC bei. Nach Jahren ist diese verschwunden oder je nach Qualität des PCs sind die Treiber nicht auf CD, sondern auf einem Festplattenlaufwerk verfügbar. Wenn aber die Festplatte defekt ist, dürfte dieser Lagerort eine sehr schlechte Idee gewesen sein. Es empfiehlt sich daher, die passenden Treiber auf einem USB-Stick zu sammeln. Wenn der Treiber nicht mehr verfügbar ist, dann das Freeware-Tool „Double Driver“ weiterhelfen. Dieses kleine Tool kann alle Treiber einer bestehenden Windows-Installation sichern. Dies muss jedoch vorab geschehen.

Laufwerksbuchstabe einer Systempartition ändern

Wer Windows neu auf einer bereits bestehenden HDD mit Windows installiert, stand sicherlich schon vor dem Problem, dass der Systempartition plötzlich nicht den gewünschten Laufwerksbuchstabe zugeordnet ist. Aber auch bei Partitionsverschiebungen können so ungewünschte Effekte auftreten.

Prinzipiell ist es recht einfach, unter Windows einer Partition oder einem Laufwerk einen anderen Laufwerksbuchstaben zuzuordnen. Über „Start/ Systemsteuerung“  kann man den Eintrag „Verwaltung“ wählen. Über den Eintrag „Verwaltung“ kommt man zur „Computerverwaltung“. Dort wählt man den Eintrag „Datenträgerverwaltung“. Wenn das Fenster geöffnet ist, erhält man eine Übersicht über alle physikalischen Laufwerke und deren Partitionierung.

Mittels eines Rechtsklick auf ein Laufwerk öffnet sich ein Kontextmenü. In diesem wählt man „Laufwerksbuchstabe und –pfad ändern“ aus. Nun kann man dem Laufwerk einen neuen (freien) Laufwerksbuchstaben zuordnen. Zu beachten ist, dass ein Laufwerksbuchstabe, der durch eine Änderung freigeworden ist, erst nach einem Systemneustart wieder zur Verfügung steht.
Soweit bereitet Windows keine Probleme. Jedoch können auf dieser Weise keine Laufwerke geändert werden, die als „Systempartition“ gekennzeichnet sind. Wie wir auf dieser Hardcopy sehen können, existiert eine D-Platte als Systempartition, die jedoch nach einer erneuten Windows-Installation von D auf E „gewandert“ ist. Die hier vorhandene „F“-Partition lässt sich beliebig verschieben.
Es ist auch der Fall denkbar, dass nach dem Hinzufügen einer weiteren Festpatte in einen Rechner die Systempartition C einem X-beliebigen Laufwerksbuchstaben zugeordnet wird. Da alle Pfade auf C zeigen, dürfte man mit dieser Konstellation nicht glücklich werden.
Der folgende Weg zur Änderung des Laufwerksbuchstaben einer Systempartition führt über die Registry. Auch hier gilt, dass der Laufwerkbuchstaben frei sein muss; er darf also von keinem Laufwerk belegt sein. Ich weise an dieser Stelle ausdrücklich darauf hin, dass Änderungen in der Registry auf eigene Gefahr erfolgen!

Öffnen Sie die Registry mittels „Start/Ausführen/regedit“ und navigieren Sie zu dem Eintrag „HKEY_LOCAL_MACHINESYSTEMMounted Devices“. Werfen Sie zuerst einen Blick auf den Eintrag „DosDeviceIhr-zukünftiger-Laufwerksbuchstabe“. Ist er frei? Wenn er hier belegt ist, aber das Laufwerk phsikalisch nicht existiert (auch nicht im Explorer ersichtlich ist), kann dieser Eintrag in der Registry gelöscht werden. Achtung: Auch hier gilt – Löschen auf eigene Gefahr!
Wenn der zukünftige Laufwerksbuchstabe frei ist, kann der bisherige Eintrag („DosDeviceAlter-Laufwerksbuchstabe“) mittels rechter Maustaste/Umbenennen  oder F2 – Taste (der Eintrag kann dannn geändert werden) umbenannt werden. Nach einem Neustart sollte das Laufwerk nun den gewünschten Laufwerksbuchstaben zugeordnet haben.
Überprüfen Sie die Änderungen in der Computerverwaltung. Je nach Konstellation müssen Sie Zwischenschritte einlegen, bis Sie den Datenträger dem gewünschten Laufwerksbuchstaben zuordnen können.

Achten Sie bei den Änderungen darauf, dass keine Programme, vor allem keine Systemprogramme, auf Laufwerksbuchstaben zugreifen, die nach Ihrer Änderung nicht mehr vorhanden sind! Wenn dies der Fall ist, kann Ihr Windows eventuell nicht mehr starten! Prüfen Sie vor dem Neustart ggfls. mittels Durchsuchen der Registry, ob es Pfade gibt die auf den alten Laufwerksbuchstaben (beispielsweise „E:programm …“) verweisen. Ändern Sie diese Einträge vor Neustart auf den neue zugewiesenen Laufwerksbuchstaben.

Webalizer oder AWStats für Plesk aktivieren

Hinweis: Plesk 11.x-Update siehe unten!

Wer sich nicht durch gigabytegroße Logfiles wühlen möchte, sondern hübsch aufbereitete Log-Übersichtsseiten wünscht, ist mit den Logfiles-Aufbereitungs-Tools AWStats oder Webalizer bestens bedient. Beide Programme sind Freeware und schnell auf einem Webserver installiert. Beide Statistik-Tools liefern schnell einen Überblick über die Besucher, die eine Webseite oder ein Server vorweisen kann.

Unter der Server-Verwaltungssoftware Plesk findet man sehr schnell einen Schalter, der scheinbar die Statistiken aktiviert. Unter „Domain/Hosting/Setup“ kann man Webalizer oder AWStats einer Domain zuordnen. Plesk selbst hat beide Statistik-Tools bereits in seiner Installation integriert. Man muss sich nur noch entscheiden, welches Tool einem eher zusagt. Ich persönlich bin nach jahrelangem Nutzen von Webalizer nun zu AWStats gewechselt. Aber dies ist reine Geschmackssache.
Die Verwaltungsoberfläche von Plesk zeigt einem nach der Auswahl an, dass Plesk ein geschütztes Verzeichnis unter „domain/plesk-stat/“ anlegt, in dem die Statitikdaten über den Browser abrufbar sind. Per Standard wird dem Verzeichnis der Benutzername und das Passwort des FTP-Zuganges der Domain zugewiesen. Wer die Benutzerdaten des Verzeichnisses „plesk-stat“ ändern möchte, kann dies über den Punkt „Geschützte Verzeichnisse“ jederzeit ändern.

Nun wird es spannend und führt zur ersten Enttäuschung. Ein Aufruf der URL „domain/plesk-stat/“ per Browser führt zu folgendem Hinweis:

This is the placeholder for Webalizer statistics. If you see this page that means that … This page has been automatically generated by Server Administrator.

Was genau will uns Plesk damit sagen? Nun, beide Statistik-Tools benötigen beim ersten Start – und vor allem, wenn schon große Logfiles vorliegen – eine Menge CPU und Zeit, um die notwendigen Daten aufzubereiten und die Webseiten zu generieren. Und Plesk selbst legt zwar ein passwortgeschütztes Verzeichnis an, gibt aber keine Möglichkeit, den notwendigen Cron-Job zu definieren. Dies muss vom Server-Administrator manuell nachgeholt werden. Der erste Start ist schnell erledigt. Man verbindet sich via Putty auf die Unix-Konsole und loggt sich möglichst als „root“ ein. Dann setzt man folgenden Befehl ab:

/usr/local/psa/admin/sbin/statistics

Je nach Menge und Größe des dauert jetzt der Aufruf, denn nun legt Webalizer oder AWStats los und bereitet die Apache Logfiles erstmalig auf. Ich empfehle diesen Schritt auf jeden Fall zu einem Zeitpunkt, bei dem entweder noch kaum Logfiles vorhanden sind, oder die Serverlast niedrig ist (beispielsweise nachts).
Es ist unerheblich, welches Statistik-Tool man ausgewählt hat oder ob vielleicht auf einem Server unterschiedlichen Domains unterschiedliche Tools zugewiesen wurden. Der oben genannte Befehl sorgt für die Statistiken beider Statistik-Tools.

Wenn man nun via Browser die URL „domain/plesk-stat“ aufruft, erhält man seine gewünschten Statistiken. Für die weitere und regelmäßige Auswertung der Logfiles muss man den Aufruf per Cronjob einrichten. Ich empfehle diesen Aufruf per Root und in den Nachtstunden (3-6 Uhr nachts ist gewöhnlich die Serverlast anhand realer Besucher gering) täglich vorzunehmen. Die Einrichtung eines Cronjobs erfolgt in Plesk unter „Start/Scheduled Tasks (Geplante Aufgaben)“. Dort wählt man das Konto („root“) aus, klickt auf NEXT und definiert den Cronjob.

Die Einstellung AWStat oder Webalizer ist in Plesk 11.x sehr gut versteckt
In Plesk 11.x findet man die Einstellung der Statistik-Programme AWStat oder Webalizer für eine Domain wie im Bild ersichtlich.

UPDATE: 11.2012: Hinweise für Plesk 11.x Statistik
Auswählen von AWStat oder Webalizer

Zuerst etwas erfreuliches: In Plesk 11.x muss der Cron nicht mehr selbst angelegt werden. Die Statistiken werden selbstständig erstellt. Allerdings kommt Plesk 11 immer noch mit jeweils völlig veralteten Versionen von Webalizer und AWStat daher. Aus dem Plesk-Forum ist zu entnehmen, dass sich schon mehr Personen die Zähne daran ausgebissen haben, die Statistikprogramme upzudaten. Ein Moderator schreibt, dass Webalizer bzw. AWStat so tief in Plesk „verankert“ sind, dass ein Update durch den Nutzer nicht machbar ist. Unbefriedigend.
Und nochwas ist unbefriedigend: Die Einstellung, ob man für eine Domain/Web AWStat oder Webalizer nutzen möchte, ist sehr gut versteckt. Ich selbst habe lange, SEHR lange danach gesucht. Die Einstellung ist unter „Abonnements/Websites&Domains“ und dann unten unter „Domain“->Domainnamen erreichbar.

 

MySQL-Collation latin1_german1_ci oder latin1_german2_ci?

Die Collation oder Kollation in einem SQL-Server wird häufig mit dem verwendeten Zeichensatz verwechselt. Naheliegend, dass bei der Bezeichnung „latin1_german“ oder „utf-8“ sofort an den zugrundeliegenden Zeichensatz gedacht wird. Zumal der Gedanke keineswegs so abwegig ist, worauf ich später noch zurückkomme.

Was bestimmt die Collation in der MySQL-Datenbank?
Collations bestimmen die Sortierreihenfolgen eines SQL-Servers, beispielsweise in ORDER BY-Abfragen. Wenn eine SQL-Abfrage Textfelder auf- oder absteigend sortieren soll, ist es wichtig zu wissen, wie beispielsweise deutsche Umlaute behandelt werden sollen. Dies wird durch die verwendete Collation festgelegt.

Für den deutschen Sprachraum sind zwei Collations in MySQL vorhanden: „latin1_german1_ci“ und „latin1_german2_ci“. Diese basieren auf DIN-1 und DIN-2-Normen (Deutsches Institut für Normung) und werden gerne im Sprachgebrauch mit „Wörterbuchsortierung“ (DIN-1) und „Telefonbuchsortierung“ (DIN-2) bezeichnet. Vereinfacht kann gesagt werden, dass die „Wörterbuchsortierung“ („latin1_german1_ci“) einen Deutschen Umlaute wie beispielsweise das „Ä“ als „A“, das „Ö“ als „O“, das „Ü“ als „U“ und das „ß“ als „s“ bei der Sortierung behandelt. Die „Telefonbuchsortierung“ („latin1_german2_ci“) setzt das „Ä“ als „AE“, das „Ö“ als „OE“ und das „Ü“ als „UE“ für die Sortierung um. Weitere Informationen über die Collation und deren Unterschiede können im MySQL-Referenzhandbuch nachgelesen werden.

Warum verwendet MySQL per Standard die Collation „latin1_swedish_ci“?
Eine gute Frage, auf die ich auch keine erklärende Antwort habe. Je nach Datenbank ist die Angabe der Collation auch relativ unwichtig (eben nur wichtig, wenn per „ORDER BY text“ sortiert werden soll) und muss nur bei Bedarf geändert werden. In der my.ini kann die Collation für neu zu erstellende Tabellen geändert werden:

[mysqld]
default-character-set=latin1
default-collation=latin1_german1_ci

[mysql]
default-character-set=latin1
default-collation=latin1_german1_ci

Bereits bestehende Tabellen werden von dieser Änderung nicht erfasst. Wer „phpmysql“ auf seinem Datenbankserver installiert hat, kann die Collation mit wenigen Mausklicks je Tabelle ändern.

Ändern der Collation per Command-Line:
In die MySQL-Command möglichst per SSH einloggen:

mysql -h [LOCALHOST] -u [USER] – p [PASSWORD]

ALTER DATABASE db_ Tabellen_Name
CHARACTER SET [charset_name]
COLLATE [collation_name]

Also beispielsweise:

ALTER TABLE Tabellen_Name CHARACTER SET utf8 COLLATE utf8_general_ci;

Weitere Informationen über das Ändern der Collation im MySQL können direkt aus dem MySQL-Referenzhandbuch übernommen werden.

Ist die Collation „utf8_general_ci“ eine gute Wahl?
Mit einem Wort: Ja. UTF-8 ist sozusagen die „Eierlegende-Wollmilch-Sau“. Ich persönlich hinterlege die Collation immer als Standard und hatte bisher noch nie das Bedürfniss, diese dann noch einmal in „latin1_german1_ci“ oder „latin1_german2_ci“ zu ändern. Im Hinterkopf sollte man einfach behalten, dass die Sortierung der Umlaute UTF-8 nicht unbedingt so erfolgt, wie man dies vielleicht erwartet; bei Bedarf kann man dies jederzeit durch die Änderung der Collation ändern.
Und nun die Preisfrage: Wie genau sortiert die Collation „utf8_general_ci“? Einfach eine kleine Tabelle mit ein paar Begriffen inklusive deutschen Umlauten aufbauen und ausprobieren!

MySQL Datenbank oder einzelne Tabelle kopieren

Neben der Notwendigkeit, eine Datenbank ab und an zu sichern, kann auch das Problem auftauchen, dass man eine einzelne Tabelle unter MySQL kopieren muss. Zur automatisierten Vollsicherung empfehle ich MySQLDumper, dem Standardtool, das kaum Wünsche offenlässt.
Für eine gelegentliche Sicherung ist das Kommandozeilen-Tool „mysqldump“ zu empfehlen, das neben einer kompletten Datenbank auch einzelne Tabellen sichern und somit auch kopieren kann.

Hinweis (zwei Programme, nahezu gleicher Name)
Mysqldumper: PHP-Skriptsammlung zur automatisierten Sicherung/Wiederherstellung von MySQL Datenbanken auf einem Webserver
Mysqldump: MySQL-Tool zur Datensicherung (Kommandozeile)

So sichert man eine Datenbank unter MySQL
Das Tool „mysqldump“ ist in der Windows-Installation beispielsweise unter „C:ProgrammeMySQLMySQL Workbench 5.2 CE“ vorhanden. Da es sich bei mysqldump um ein Kommandozeilenprogramm handelt, sollte via „cmd“ in das Verzeichnis gewechselt und das Programm mit entsprechenden Parametern aufgerufen werden. Ein Doppelklick per Windows-Explorer bringt mangels Übergabeparameter und GUI nichts.
Unter Linux langt der Aufruf „mysqldump“ unter der Shell bzw. mit einer Putty-Verbindung.

Um eine Sicherung durchzuführen, ist das Tool wie folgt aufzurufen:

mysqldump  -hlocalhost  -uUser  -pPasswort [ZuSicherndeDatenbank] > datensicherung.sql

Nur einzelne Tabelle sichern:
mysqldump  -hlocalhost  -uUser  -pPasswort [ZuSicherndeDatenbank] [Tabellenname] > datensicherung.sql

Erklärung:
-h: Hostname, beispielsweise „localhost“
-u: Username
-p: Passwort
[ZuSicherndeDatenbank]: Name der Datenbank
[Tabellenname]: optional

Mysqldump sichert im obigen Beispiel die Datenbank [ZuSicherndeDatenbank] im File „datensicherung.sql“. Dieses File wird im aktuellen Verzeichnis geschrieben.

Rücksicherung der MySQL-Sicherung
Die Rücksicherung erfolgt nicht über mysqldump, sondern über mysql selbst. Wichtig ist, dass die Datenbank auf dem Zielsystem bereits bestehen muss. Die im Sicherungsfile enthaltenen Tabellen und Views dürfen jedoch auf dem Zielsystem nicht enthalten sein.

mysql -hlocalhost -uUser -pPasswort [ExisitierendeDatenbank]  < datensicherung.sql

Dieser Weg eignet sich auch hervorragend, um eine Datenbank über Servergrenzen hinweg zu sichern bzw. zu kopieren, da das Ausgabefile („datensicherung.sql“) hierfür einfach auf den Zielhost kopiert und importiert werden muss.

Kopieren einer einzelnen Tabelle unter MySQL innerhalb einer Datenbank
Wie wir oben gesehen haben, können wir per mysqldump auch einzelne Tabellen sichern. Um eine Tabelle zu kopieren, sichern wir hierfür via mysqldump die Tabelle in ein File („datensicherung.sql“). Dann ändern wir den Tabellenamen der Quelltabelle ab (zum Beispiel „tabelle_old“), denn beim Kopieren (richtigerweise: Rücksichern“) wird die Tabelle mit dem Originalnamen neu angelegt. Dies würde zu einem Fehler führen, wenn die Tabelle bereits existent ist.
Per „mysql“ wird das File importiert und wir haben nach erfolgreicher Ausführung eine Kopie der Tabelle in der Datenbank.

Warum nutzen wir nicht phpmyadmin?
Wer „phpmyadmin“ auf seinem Server installiert hat, kann natürlich eine Tabelle skripten, ggfls das Skript anpassen (neuer Tabellenname) und ausführen. Jedoch ist phpmyadmin nicht auf jedem Host vorhanden oder soll aus Sicherheitsgründen dort installiert sein. Wer große Tabellen oder Datenbanken kopieren oder sichern möchte, sollte die Kommandozeile via „mysqldump“ nutzen und nicht per Skript unter phpmysql eine Kopie anfertigen.
UPDATE: Wer phpmyadmin auf seinem MySQL-Server installiert hat, kann unter „Optionen“ auch große Tabellen kopieren.

MyISAM-Tabellen-Locks in Cache abfangen und nacharbeiten

Im Artikel „MySQL MyISAM: Performance-Probleme auf der Spur“ sind wir dem Problem der gesperrten MyISAM-Tabellen auf die Spur gekommen. Eine einfache Möglichkeit, die SQL-Locks mittels Timeout zu umgehen und letztlich auch zu protokollieren, haben wir ausprobiert. Im Artikel „Einfacher MySQL Fehler-Cache für MyISAM Lock Fehler“ haben wir mittels Textfile einen Fehlercache gebaut, so dass wir die fehlgeschlagenen Befehle nachholen können. Da dies nach wie vor nicht unseren Bedürfnissen genügt, werden wir heute einen automatisierten Cache auf Datenbankebene erstellen. Auf Datenbankebene? Ja, denn wenn ein Insert oder Update auf eine MyISAM-Tabelle gesperrt ist, bedeutet dies ja nicht, dass der SQL-Server nicht in eine andere Tabelle speichern kann. Und dieses verhalten machen wir uns heute zu Nutze.
In unserem C#-Programm haben wir aktuell folgende Update-Funktion:

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 Fehlerfall schreiben wir ein Logfile; den eigentlichen SQL-Befehl schreiben in der Funktion „MySQL_Error_logfile“ in ein Textfile.

private static void MySQL_Error_logfile(string sText)
{
string sLogfilePfad = „logs\“;
try
{
//Abschliessendes Semikolon
if (!sText.EndsWith(„;“)) sText += „;“;

//Pfad hinzufügen
string sFile = @sLogfilePfad + „MySQL_“ + DateTime.Now.ToString(„yyyyMMdd“) + „.txt“;

//Erzeuge die Datei
FileStream outStream = new FileStream(sFile, FileMode.Append);
StreamWriter myWriter = new StreamWriter(outStream, System.Text.Encoding.Default);
myWriter.WriteLine(sText);
myWriter.Close();
}
catch (Exception ex)
{
Console.WriteLine(„FEHLER in MySQL-logfile: “ + ex.Message);
}
}

Die Funktion „MySQL_Error_logfile“ macht also nichts anderes, als ein Textfile zu schreiben. Es sorgt dafür, dass jeder SQL-Befehl ein abschließendes Semikolon hat für die Ausführung mehrerer Befehle hintereinander. Zudem erstellt es ein neues Logfile, sollte noch keines existieren. Um die bestehenden Programme möglichst wenig ändern zu müssen, wird der zu programmierende Cache auf der Basis der Funktion „MySQL_Error_logfile“ realisiert, da bereits jeder Task im Fehlerfall bereits hier seine Daten abliefert.

Wir legen also eine weitere Tabelle an. Ich habe sie „error_cache“ genannt. Es würde bereits eine Spalte genügen; ich persönlich bin jedoch ein Freund von eindeutigen ID-Feldern in einer Tabelle. Da ich MySQL 5.5.x nutze, habe ich die Standard-Storage-Engine „InnoDB“ für diese Tabelle nicht geändert.

DROP TABLE IF EXISTS `products`.`error_cache`;
CREATE TABLE  `products`.`error_cache` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`befehl` text NOT NULL,
`fehler` tinyint(3) unsigned NOT NULL DEFAULT ‚0‘,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;

Hier die modifzierte Funktion “MySQL_Error_logfile”. Diese schreibt nun einen MySQL-Fehler in den Cache. Die Hilfsfunktion „SQLEscape“ maskiert vorhandene Hochkommas.

private static void MySQL_Error_logfile(string sSQLFehler)
{
string sSQL = „“;
try
{
//Schreiben des fehlheschlagenen Befehls in die MySQL-Tabelle
using (MySqlConnection cn = new MySqlConnection(sConnection))
{
//Update-Befehl, der fehlschlagen ist
//Hochkommas müssen maskiert werden
sSQL = @“INSERT into error_cache (befehl) VALUES (‚“ + SQLEscape(sSQLFehler) + „‚);“;
try
{
cn.Open();
using (MySqlCommand cmd = new MySqlCommand(sSQL, cn))
{
cmd.ExecuteNonQuery();
}
}
catch
{
//Sollte beim Schreiben ein Fehler auftreten,
//schreiben wir ihn in ein Logfile
logfile(„MySQL FEHLER beim Schreiben in Cache: “ + sSQL);
}
}
}
catch (Exception ex)
{
Console.WriteLine(„FEHLER in MySQL-logfile: “ + ex.Message);
}
}

public static string SQLEscape(string sValue)
{
// SQL Encoding: r, n, x00, x1a, Backslash, einfache und doppelte Hochkommas
//benötigt: using System.Text.RegularExpressions;
if (sValue == null) return null;
else return Regex.Replace(sValue, @“[rnx00x1a\'““]“, @“$0″);
}

Doch damit ist es noch nicht getan. Denn uns hilft es wenig, wenn die MySQL-Fehler in einer Tabelle auflaufen; sie müssen auch nach dem Tabellen-Lock wieder abgearbeitet werden. Hierzu schreiben wir zwei weitere Funktionen:

private static void Clear_MySQL_Error_Cache()
{
//Hole die fehlerhaften Befehle
ArrayList list = GetErrorCache();
string sSQL=““;

if (list.Count > 0)
{
//Es sind Fehler vorhanden
foreach (ArrayList buffer in list)
{
using (MySqlConnection conn = new MySqlConnection(sConnection))
{
try
{
//Arbeite nun den SQL-Befehl ab
conn.Open();

//der fehlgeschlagene Befehl aus der Datenbank
sSQL= buffer[1].ToString();

using (MySqlCommand cmd = new MySqlCommand(sSQL, conn))
{
cmd.ExecuteNonQuery();
}

//Lösche nun den Eintrag
conn.Close();
conn.Open();
sSQL = „DELETE FROM error_cache WHERE id=“ + buffer[0].ToString();
using (MySqlCommand cmd = new MySqlCommand(sSQL, conn))
{
cmd.ExecuteNonQuery();
}
}
catch
{
//Der Befehl hat wieder nicht geklappt. Erhöhe den Fehlercount
//um Endlosschleife zu verhindern
conn.Close();
conn.Open();
sSQL = „UPDATE error_cache SET fehler=fehler+1 WHERE id=“ + buffer[0].ToString();
using (MySqlCommand cmd = new MySqlCommand(sSQL, conn))
{
cmd.ExecuteNonQuery();
}
}
}
}

}
}

private static ArrayList GetErrorCache()
{
ArrayList list = new ArrayList();
try
{
using (MySqlConnection conn = new MySqlConnection(sConnection))
{
MySqlDataReader rdr = null;
conn.Open();

//Fehleranzahl hier maximal 3
string sSQL = „SELECT id, befehl FROM error_cache WHERE fehler < 3 ORDER BY fehler“;
using (MySqlCommand cmd = new MySqlCommand(sSQL, conn))
{
rdr = cmd.ExecuteReader();
if (rdr.HasRows)
{
while (rdr.Read())
{
ArrayList buffer = new ArrayList();
buffer.Add(rdr[„id“].ToString());
buffer.Add(rdr[„Befehl“].ToString());

//Der Rückgabe ArrayList hinzufügen
list.Add(buffer);
}
}
}
}
}
catch { }
return list;
}

Aufzurufen ist die Cache-Abarbeitung nun mit „Clear_MySQL_Error_Cache();“. Die Funktion holt sich durch die Hilfsfunktion „GetErrorCache()“ alle Befehle aus dem Cache, die eine Fehleranzahl < 3 besitzen. Somit werden alle Befehle maximal dreimal probiert. Es ist davon auszugehen, dass ein Befehl, der dreimal als fehlerhaft vom SQL-Server zurückgegeben wurde, einen Fehler im Befehl selbst beinhaltet. Eine Verbesserung wäre hier bereits beim Schreiben des Befehles in den Cache sicherzustellen, dass nur Befehle in den Cache gelangen, die aufgrund eines Lock-Timeout entstehen.
Ich persönlich bevorzuge diese Lösung, da ich nun an zentraler Stelle sehe, ob es auch fehlerhafte SQL-Statements aus den Jobs gibt.
Wenn die die Hilfsfunktion „GetErrorCache()“ der Funktion „Clear_MySQL_Error_Cache()“ Werte zurückgibt, arbeitet diese alle Werte hintereinander ab. Wenn kein anderer Task die Tabellen blockiert, werden alle Befehle nacheinander abgearbeitet. Wenn weiterhin ein Lock vorhanden ist, schlägt das SQL-Statement erneut fehl, der Fehler-Counter wird erhöht.

Bewertung dieses Vorschlages
Ich bin mir bewusst, dass dieses Vorgehen nicht optimal ist. Aber es erfüllt seinen Zweck. Der C#-Code kann noch weiter optimiert werden. Je nach Anwendungsfall ist auch eine Datenbank-Lösung vorzuziehen. Die Umstellung der Tabelle in eine InnoDB-Tabelle werden wird zu einem späteren Zeitpunkt beschreiten.
Wer sich noch weiter mit einem Tabellen-Lock oder Commit beschäftigen möchte, dem empfehle ich die ausführliche Dokumentation unter mysql.com.

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

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

MySQL MyISAM: Performance-Probleme auf der Spur

Welche MySQL-Storage-Engine ist besser? MyISAM oder InnoDB? Eine oft gestellte Frage, auf die es keine eindeutige Lösung gibt. MyISAM wird oft als die modernere Engine angesehen, bis zur Version 5.4 war MyISAM auch die Standard-Engine von MySQL; nun ist die oftmals als veraltet beschimpfte InnoDB-Engine die Standard-Engine. Inzwischen haben die Entwickler von InnoDB viele Nachteile ausgebügelt. Aber auch ohne die neue Version der InnoDB-Engine lohnt sich vielleicht ein Umstieg. Einen Fall werde ich hier untersuchen.

Die vorliegende Datenbank ist über 5 GB groß. Sie gehört zu einem umfangreichen Projekt, zu dem mehrere Server, einige Clients und ein öffentliches Webprojekt gehören. Wir untersuchen zuerst einen reinen Datenbankserver im lokalen Netzwerk. MyISAM wurde am Anfang gewählt weil es einerseits bei der Anlage der Datenbank Standard war, andererseits der Fulltext-Index damals nur unter MyISAM möglich war. Inzwischen ist der Fulltext-Index auch unter InnoDB möglich.

Probleme mit der MyISAM-Tabelle
Wer MyISAM-Datenbanken betreibt, die einen größeren Umfang angenommen haben, wird von einer Tabellen-Beschädigung nicht verschont bleiben. Mittels des MySQL-Befehls „CHECK TABLE“ kann die Tabelle jederzeit geprüft, und mit dem Befehl „REPAIR TABLE“ auch wieder repariert werden. Beides kann in der MySQL-Webseite ausführlich nachgelesen werden. Eine korrupte MyISAM-Tabelle ist kein Problem; ärgerlich ist dies dennoch. Zumal das Reparieren der Tabelle je nach Tabellengröße mehrere Stunden in Anspruch nehmen kann. So lange ist die Datenbanktabelle offline.

Performance-Probleme durch gesperrte MyISAM-Tabellen
Fehlermeldungen wie „Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.“ beim Insert oder Update auf MyISAM-Tabellen kommen daher, da die Storage-Engine MyISAM bei Zugriff auf die Tabelle nicht die betreffenden Datensätze sperrt, wie die Storage-Engine InnoDB, sondern gleich die komplette Tabelle sperrt. Greifen mehrere Tasks gleichzeitig speichernd auf eine MyISAM-Tabelle zu, kann es zu einem Timeout kommen. Im hier zu untersuchenden Fall sind mehrere Jobs vorhanden, die leider einige Stunden am Tag gleichzeitig schreibend auf bis zu zwei MyISAM-Tabellen zugreifen. So „kämpfen“ mehrere Tasks um Schreibrechte auf den Tabellen. Der erste gewinnt. Der Zweite wird in eine Warteschlange eingereiht und darf schreiben, wenn der erste Task abgearbeitet wurde. Doch oftmals wird die Schreibanforderung mittels Timeout beendet. Die erste Möglichkeit, dieses Problem zu umgehen, ist den Timeout zu erhöhen.

Ein MySQL-Connection-String sieht ungefähr wie folgt aus:
ConnectionString=data source=mysql;DATABASE=mydatabase;UID=myuser;PASSWORD=mypassword;Connection Timeout=60

Wir können also ein “Connection Timeout” mit angeben. In diesem Connection-String wurde der Timeout bereits auf 60 Sekunden erhöht (wenn dieser Parameter nicht mit angegeben wird, verwendet MySQL den Standard-Timeout).
Im vorliegenden Fall haben alle Tasks diesen Timeout. Dennoch kommt es mehrmals am Tag zu Schreibproblemen. Eine weitere Erhöhung des Timeouts (größer 60 Sekunden) kann nicht die Lösung sein.

Wir suchen also eine Lösung für unser Performance-Problem. Im nächsten Teil werden wir einen Cache ausprobieren: Einfacher MySQL Fehler-Cache für MyISAM Lock Fehler

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