Dieser Post wurde aus meiner alten WordPress-Installation importiert. Sollte es Darstellungsprobleme, falsche Links oder fehlende Bilder geben, bitte einfach hier einen Kommentar hinterlassen. Danke.
mySQL sorgt für viele interessante Effekte, einer davon ist das myISAM Table Locking, welches gerne auch Queries auf andere Tabellen blockiert.
Ein 3-Minuten-Query lief kürzlich auf einem mySQL-Server-Cluster. Das mySQL zum Lesen einer Tabelle selbige komplett für Schreibzugriffe blockiert, ist noch weitgehend verständlich wobei andere Datenbanken an dieser Stelle Page Locks (Sperren nur der betroffenen Speicherseite) oder Row Locks (Sperren einzelner Tabellenzeilen) ermöglichen.
Besagte häufig geschriebene Tabelle wurde also für alle Schreibzugriffe gesperrt, allerdings stauten sich auch schnell andere Queries auf die beliebige andere Tabellen abfragen wollten, zunächst ohne sichtbare Erklärung.
Diese fand sich nach einiger Suche bei Mostly Harmless und offenbarte eine Besonderheit von myISAM:
A client issues a SELECT that takes a long time to run. Another client then issues an UPDATE on the same table. This client waits until the SELECT is finished.Another client issues another SELECT statement on the same table. Because UPDATE has higher priority than SELECT, this SELECT waits for the UPDATE to finish, and for the first SELECT to finish.mySQL's myISAM priorisiert alle Anfragen nach ihrem Typ: Steht jetzt ein Schreibquery (wie ein UPDATE) in der Schlange an und wartet auf eine gerade für Schreibzugriffe gesperrte Tabelle, dann blockiert es damit automatisch alle folgenden SELECT's.
Erst wenn das ursprünglich blockierende Query fertig ausgeführt wurde, sind auch wieder UPDATE's zulässig, soweit klar. Allerdings darf kein nach dem UPDATE angeforderter SELECT irgendwelche Tabellen lesen - auch wenn diese weder Teil des blockierenden Query noch des UPDATE's waren.
Als Lösung bleibt nur die Änderung der SELECT-Priorität, damit andere SELECT's nicht auf ein anstehendes UPDATE warten, allerdings halte ich diesen Eingriff für nicht ganz ungefährlich - einige Applikationen verlassen sich möglicherweise auf die Reihenfolge und eine hohe SELECT-Last kann Änderungen für längere Zeit blockieren. Theoretisch würde dieses Verhalten - wenn überhaupt - nur für die vom UPDATE betroffene Tabelle Sinn ergeben.
Wenigstens ist die Änderung schnell durchgeführt, in die mySQL-Konfigurationsdatei /etc/my.cnf muss lediglich eine Zeile eingefügt werden:
low_priority_updates=1Danach steht selbstverständlich ein Neustart des mySQL-Servers an.
Aufgefallen ist das Problem erst als ein Programmier-Bug das ursprüngliche 3-Sekunden-Query mehrere tausend Mal direkt hintereinander ausgeführt hat...
3 Kommentare. Schreib was dazu-
Sid Burn
1.12.2011 12:02
Antworten
-
Sebastian
1.12.2011 16:16
Antworten
-
Sid Burn
1.12.2011 18:01
Antworten
Warum wird überhaupt MyISAM genutzt? Genau deswegen empfiehlt sich eher InnoDB das Row-Locking macht, und die Faustregel das MyISAM schneller wäre stimmt genau wegen deiner beschreibung des Page-Locking nicht.
Dazu kommt noch das MyISAM Tabellen Grundsätzlich kaputt gehen können wenn nur schon der MySQL Prozess abstürzt.
Ich würde lieber raten die Tabellen nach InnoDB zu konvertieren, wenn möglich.
Nachdem mir bei der vorsichtigen Frage warum MyISAM benutzt wird bereits der Kopf abgerissen wurde, werde ich eine Umstellung nicht vorschlagen :-) Kommentar war seinerzeit: "Ich habe das getestet und InnoDB ist viiiieeeel zu langsam"
Aha, wahrscheinlich wurde es mit so sinnlos Benchmarks getestet wie. Zuerst 100.000 Zeilen erzeugen, danach 100.000 Zeilen auslesen und die Zeit gemessen. ;) Was bei Konkurierenden zugriffen passiert kam wohl nicht in Betracht.
Aber du kannst einen ja schon fast leid tun. :D Kleiner Tipp. Kauf demjenigen zu Weihnachten der die Entscheidung ob MyISAM oder InnoDB hat das Buch "Higher Performance MySQL" und leg es ihm unter dem Tannenbaum. Den dort wird ausführlich erklärt warum InnoDB schneller ist und warum man MyISAM nicht nutzen sollte. Vielleicht gibt es ja noch einen Sinneswandel. ;)