manual.de_Table_types.html
MySQL-Referenzhandbuch für Version 4.1.1-alpha - 8 MySQL-Tabellentypen
Go to the first, previous, next, last section, table of contents.
AB MySQL-Version 3.23.6 können Sie unter drei grundlegenden
Tabellenformaten (ISAM, HEAP und MyISAM wählen. Neuere
MySQL-Versionen können zusätzliche Tabellentypen unterstützen
(InnoDB, oder BDB), abhängig davon, wie Sie sie kompilieren.
Beim Erzeugen einer neuen Tabelle können Sie MySQL mitteilen, welcher
Tabellentyp dafür benutzt werden soll. MySQL erzeugt immer eine
.frm-Datei, die die Tabellen- und Spaltendefinitionen enthält.
Abhängig vom Tabellentyp werden Index und Daten in anderen Dateien
gespeichert.
Beachten Sie, dass Sie für die Benutzung von InnoDB-Tabellen
zumindest die innodb_data_file_path-Startoption benötigen.
See section 8.5.2 Mit InnoDB anfangen - Optionen.
Der vorgabemäßige Tabellentyp in MySQL ist MyISAM. Wenn Sie
versuchen, einen Tabellentyp zu benutzen, der nicht einkompiliert oder
aktiviert ist, erzeugt MySQL statt dessen eine Tabelle vom Typ
MyISAM. Das ist ein sehr nützliches Feature, wenn Sie Tabellen
zwischen unterschiedlichen SQL-Servern kopieren wollen, die
unterschiedliche Tabellentypen unterstützten (zum Beispiel Tabellen zu
einem Slave kopieren, der für Geschwindigkeit optimiert ist, aber keine
transaktionalen Tabellen hat). Dieses automatische Ändern des Tabellentyps
kann andererseits für neue MySQL-Benutzer sehr verwirrend sein. Wir planen
für MySQL 4.0, das zu beheben, indem eine Warnung ausgegeben wird, wenn ein
Tabellentyp automatisch geändert wird.
Sie können Tabellen zwischen unterschiedlichen Typen mit dem ALTER
TABLE-Statement umwandeln. See section 7.5.4 ALTER TABLE-Syntax.
MySQL unterstützt zwei unterschiedliche Arten von Tabellen:
transaktionssichere Tabellen (InnoDB und BDB) und nicht
transaktionssichere Tabellen (HEAP, ISAM, MERGE und
MyISAM).
Vorteile transaktionssicherer Tabellen (TST):
-
Sicherer. Selbst wenn MySQL abstürzt oder wenn Sie Hardware-Probleme
bekommen, bekommen Sie Ihre Daten zurück, entweder über automatische
Wiederherstellung oder von einer Datensicherung plus Transaktionslog-Datei.
-
Sie können viele Statements kombinieren und alle in einem Rutsch mit dem
COMMIT-Befehl akzeptieren.
-
Sie können
ROLLBACK ausführen, um Ihre Änderungen zu ignorieren
(wenn Sie nicht im Auto-Commit-Modus fahren).
-
Wenn eine Aktualisierung fehlschlägt, werden Ihre Änderungen
zurückgesichert. (Bei nicht transaktionssicheren Tabellen sind
durchgeführte Änderungen permanent.)
Vorteile nicht transaktionssicherer Tabellen (NTST):
-
Viel schneller, da es keinen Transaktionsoverhead gibt.
-
Benötigen aufgrund des fehlenden Transaktionsoverheads weniger
Speicherplatz.
-
Benötigen weniger Arbeitsspeicher für Aktualisierungen.
Sie können TST- and NTST-Tabellen in denselben Statements kombinieren, um
das Beste aus beiden Welten zu bekommen.
MyISAM ist der vorgabemäßige Tabellentyp in MySQL-Version 3.23. Er
basiert auf dem ISAM-Code und hat viele nützliche Erweiterungen.
Der Index wird in einer Datei mit der Endung .MYI (MYIndex)
gespeichert, die Daten in einer Datei mit der Endung .MYD (MYData).
Sie können MyISAM-Tabellen mit dem myisamchk-Dienstprogramm
überprüfen und reparieren. See section 5.4.6.9 Wie Tabellen repariert werden. Sie können
MyISAM-Tabellen mit myisampack komprimieren, damit sie viel
weniger Speicherplatz benötigen. See section 5.7.4 myisampack, MySQL-Programm zum Erzeugen komprimierter Nur-Lese-Tabellen.
Folgende Neuerungen gibt es bei MyISAM:
-
Es gibt einen Flag in der
MyISAM-Datei, der anzeigt, ob die Tabelle
korrekt geschlossen wurde. Wenn mysqld mit --myisam-recover
gestartet wird, werden MyISAM-Tabellen beim Öffnen automatisch
geprüft und / oder repariert, falls die Tabelle nicht korrekt geschlossen
wurde.
-
Sie können neue Zeilen in eine Tabelle, die keinerlei freie Blöcke mitten
in der Daten-Datei hat, einfügen (
INSERT), während zeitgleich
andere Threads aus der Tabelle lesen (zeitgleiches Einfügen). Ein freier
Block kann entstehen, wenn eine Aktualisierung einer Zeile dynamischer
Länge, die viele Daten enthält, mit weniger Daten durchgeführt wird, oder
wenn Zeilen gelöscht werden. Wenn alle freien Blöcke aufgebraucht sind,
können alle zukünftigen Einfügeoperationen auf die zeitgleiche Art
erfolgen.
-
Unterstützung für große Dateien (63-Bit) auf Dateisystemen /
Betriebssystemen, die große Dateien unterstützen.
-
Alle Daten werden mit dem niedrigen Byte zuerst gespeichert. Das macht die
Daten Maschinen- und Betriebssystem-unabhängig. Die einzige Anforderung
ist, dass die Maschine zweien-komplementäre vorzeichenbehaftete Ganzzahlen
(two's-complement signed integers) benutzt, was bei jeder Maschine in den
letzten 20 Jahren der Fall war), sowie das IEEE-Fließkomma-Format (bei
Mainstream-Maschinen absolut dominierend). Die einzige Art von Maschinen,
die vielleicht keine Binärkompatibilität unterstützen, sind eingebettete
Systeme (Embedded Systems), weil diese manchmal eigentümliche Prozessoren
haben.
Wenn Daten mit dem niedrigen Byte zuerst gespeichert werden, ergibt sich
daraus kein großer Geschwindigkeitsnachteil. Die Bytes in einer
Tabellenzeile sind normalerweise unzusammenhängend und man benötigt kaum
mehr Ressourcen, um ein unzusammenhängendes Byte in Reihenfolge statt in
umgekehrter Reihenfolge zu lesen. Der tatsächliche Hole-Spaltenwert-Code
ist im Vergleich zu sonstigem Code ebenfalls nicht zeitkritisch.
-
Alle Zahlenschlüssel werden mit dem hohen Byte zuerst gespeichert, um
bessere Index-Kompression zu erzielen.
-
Die interne Handhabung einer
AUTO_INCREMENT-Spalte. MyISAM
aktualisiert diese automatisch bei INSERT / UPDATE. Der
AUTO_INCREMENT-Wert kann mit myisamchk zurückgesetzt werden.
Das macht AUTO_INCREMENT-Spalten schneller (mindestens 10%), und
alten Zahlen werden im Gegensatz zum alten ISAM nicht wieder
benutzt. Beachten Sie, dass das alte Verhalten immer noch da ist, wenn ein
AUTO_INCREMENT am Ende eines mehrteiligen Schlüssels definiert wird.
-
Wenn er in sortierter Reihenfolge eingefügt wird (wie bei der Benutzung
einer
AUTO_INCREMENT-Spalte), wird der Schlüsselbaum gespalten, so
dass der hohe Knoten nur einen Schlüssel enthält. Das verbessert die
Platzausnutzung im Schlüsselbaum.
-
BLOB- und TEXT-Spalten können indiziert werden.
-
NULL-Werte sind in indizierten Spalten erlaubt. Dafür werden 0 bis 1
Byte pro Schlüssel benötigt.
-
Die maximale Schlüssellänge beträgt vorgabemäßig 500 Bytes (das kann beim
Neukompilieren geändert werden). Wenn Schlüssel länger als 250 Bytes sind,
wird für diese eine höhere Schlüsselblockgröße als die vorgabemäßigen
1024 Bytes benutzt.
-
Die maximale Anzahl von Schlüsseln pro Tabelle beträgt vorgabemäßig 32.
Diese kann bis auf 64 erhöht werden, ohne dass
myisamchk neu
kompiliert werden muss.
-
myisamchk kennzeichnet Tabellen als geprüft, wenn es mit
--update-state läuft. myisamchk --fast prüft nur die
Tabellen, die diese Kennzeichnung nicht haben.
-
myisamchk -a speichert Statistiken für Schlüsselteile (und nicht nur
für gesamte Schlüssel wie bei ISAM).
-
Zeilen dynamischer Größe werden viel weniger fragmentiert werden, wenn
Lösch- mit Aktualisierungs- und Einfügeoperationen gemischt werden. Dafür
wird gesorgt, indem angrenzende gelöschte Blöcke automatisch kombiniert
werden und dadurch, dass Blöcke erweitert werden, wenn der nächste Block
gelöscht wird.
-
myisampack kann BLOB- and VARCHAR-Spalten
komprimieren.
-
Sie können die Daten-Datei und die Index-Datei in unterschiedliche
Verzeichnisse legen, um mehr Geschwindigkeit zu erhalten (mit der
DATA/INDEX DIRECTORY="pfad"-Option für CREATE TABLE).
See section 7.5.3 CREATE TABLE-Syntax.
MyISAM unterstützt ausserdem die folgenden Dinge, die MySQL in naher
Zukunft benutzen können wird:
-
Unterstützung für einen echten
VARCHAR-Typ. Eine
VARCHAR-Spalte fängt mit einer in 2 Bytes gespeicherten Länge an.
-
Tabellen mit
VARCHAR können eine feste oder dynamische
Datensatzlänge haben.
-
VARCHAR und CHAR können bis zu 64 KB Groß sein. Alle
Schlüsselsegmente haben ihre eigene Sprachdefinition. Das versetzt MySQL in
die Lage, unterschiedliche Sprachdefinitionen pro Spalte zu haben.
-
Ein gehashter berechneter Index kann für
UNIQUE benutzt werden. Das
erlaubt Ihnen, UNIQUE auf jeder beliebigen Kombination von Spalten
in einer Tabelle zu haben. (Sie können jedoch auf einem UNIQUE
berechneten Index nicht suchen.)
Beachten Sie, dass Index-Dateien bei MyISAM üblicherweise viel
kleiner sind als bei ISAM. Das bedeutet, dass MyISAM
normalerweise weniger Systemressourcen verbraucht als ISAM,
allerdings mehr Prozessorleistung beim Einfügen von Daten in einen
komprimierten Index.
Folgende Optionen für mysqld können benutzt werden, um das Verhalten
von MyISAM-Tabellen zu ändern. See section 5.5.5.4 SHOW VARIABLES.
| Option | Beschreibung
|
--myisam-recover=#
| Automatische Wiederherstellung beschädigter Tabellen.
|
-O myisam_sort_buffer_size=#
| Der beim Wiederherstellen von Tabellen benutzte Puffer.
|
--delay-key-write-for-all-tables
| Keine Schlüsselpuffer zwischen Schreibvorgängen auf jedwede
MyISAM-Tabelle zurückschreiben (flush).
|
-O myisam_max_extra_sort_file_size=#
| Wird benutzt, um MySQL bei der Entscheidung zu helfen, wann die
langsame, aber sichere Schlüssel-Cache-Index-Erzeugungsmethode benutzt
werden sollte. Hinweis: Dieser Parameter wird in Megabytes
angegeben!
|
-O myisam_max_sort_file_size=#
| Die schnelle Index-Sortiermethode beim Erzeugen eines Indexes nicht
benutzen, wenn die temporäre Datei größer als dieser Wert werden würde.
Hinweis: Dieser Parameter wird in Megabytes angegeben!
megabytes!--
|
-O myisam_bulk_insert_tree_size=#
| Die Größe des Baum-Caches, der bei der Optimierung von
Massen-Einfügeoperationen benutzt wird. Hinweis: Das ist die
Begrenzung pro Thread!
|
Die automatische Wiederherstellung wird aktiviert, wenn Sie mysqld
mit --myisam-recover=# starten. See section 5.1.1 mysqld-Kommandozeilenoptionen. Beim
Öffnen wird geprüft, ob die Tabelle als beschädigt gekennzeichnet ist oder
ob die Zählvariable für die Tabelle nicht 0 ist und Sie mit
--skip-locking laufen lassen. Wenn eine dieser Bedingungen erfüllt
ist, geschieht folgendes:
-
Die Tabelle wird auf Fehler geprüft.
-
Wenn ein Fehler gefunden wird, wird eine schnelle Reparatur der Tabelle
versucht (mit Sortieren und ohne Neuerzeugung der Daten-Datei).
-
Wenn die Reparatur wegen eines Fehlers in der Daten-Datei fehlschlägt (zum
Beispiel ein Fehler wegen eines doppelten Schlüsseleintrags), wird die
Reparatur noch einmal versucht, diesmal allerdings mit Neuerzeugung der
Daten-Datei.
-
Wenn dieser Versuch fehlschlägt, wird die Reparatur noch einmal mit der
alten Reparaturoption versucht (Zeile für Zeile ohne Sortieren schreiben),
was jede Sorte von Fehler beheben sollte, bei gewissen
Festplatten-Erfordernissen ...
Wenn die Wiederherstellung nicht in der Lage ist, alle Zeilen aus einem
vorher abgeschlossenen Statement wiederherzustellen, und Sie nicht
FORCE als Option für myisam-recover angegeben haben, wird die
automatische Reparatur mit einer Fehlermeldung in der Fehlerdatei
abgebrochen:
Error: Couldn't repair table: test.g00pages
Hätten Sie in diesem Fall die FORCE-Option benutzt, würden Sie statt
dessen in der Fehlerdatei eine Warnung erhalten:
Warning: Found 344 of 354 rows when repairing ./test/g00pages
Wenn Sie automatisches Wiederherstellung mit der BACKUP-Option
laufen lassen, beachten Sie, dass Sie ein Cron-Skript haben sollten, dass
automatisch Dateien mit Namen wie `tabellenname-datetime.BAK' aus den
Datenbank-Verzeichnissen auf ein Sicherungsmedium verschiebt.
See section 5.1.1 mysqld-Kommandozeilenoptionen.
MySQL unterstützt unterschiedliche Index-Typen, doch der normale Typ ist
ISAM oder MyISAM. Diese benutzen einen B-Baum-Index, und Sie können die
Größe der Index-Datei grob als (schluessel_laenge+4)/0.67
kalkuliert, summiert über alle Schlüssel. (Das ist der schlechteste Fall,
bei dem alle Schlüssel in sortierter Reihenfolge eingeordnet werden und es
keinerlei Schlüssel-Komprimierung gibt.)
Zeichenketten-Indexe werden Leerzeichen-komprimiert. Wenn der erste
Index-Teil eine Zeichenkette ist, wird er zusätzlich Präfix-komprimiert.
Leerzeichen-Kompression macht die Index-Datei kleiner als in den obigen
Zahlen dargestellt, wenn die Zeichenkettenspalte viele Leerzeichen am Ende
hat oder eine VARCHAR-Spalte ist, die nicht immer in voller Länge
genutzt wird. Präfix-Kompression wird bei Schlüsseln benutzt, die mit einer
Zeichenkette beginnen. Präfix-Kompression hilft, wenn es viele
Zeichenketten mit identischem Präfix gibt.
Bei MyISAM-Tabellen können Sie auch Zahlen Präfix-komprimieren,
indem Sie beim Erzeugen der Tabelle PACK_KEYS=1 angeben. Das hilft,
wenn Sie viele Ganzzahl-Schlüssel mit identischem Präfix haben, wenn die
Zahlen mit dem hohen Byte zuerst gespeichert werden.
MyISAM unterstützt 3 verschiedene Tabellentypen. Zwei von ihnen
werden automatisch gewählt, abhängig vom Spaltentyp, den Sie benutzen. Der
dritte, komprimierte Tabellen, kann nur mit dem
myisampack-Dienstprogramm erzeugt werden.
Wenn Sie eine Tabelle erzeugen (CREATE) oder ändern (ALTER),
können Sie bei Tabellen, die kein BLOB enthalten, ein dynamisches
(DYNAMIC) oder festes (FIXED) Tabellenformat mit der
ROW_FORMAT=#-Tabellenoption erzwingen. Zukünftig werden Sie in der
Lage sein, Tabellen zu komprimieren / dekomprimieren, indem Sie
ROW_FORMAT=compressed | default für ALTER TABLE angeben.
See section 7.5.3 CREATE TABLE-Syntax.
Das ist das vorgabemäßige Format. Es wird benutzt, wenn die Tabelle keine
VARCHAR-, BLOB- oder TEXT-Spalten enthält.
Dieses Format ist das einfachste und sicherste Format. Es ist auch das
schnellste der Formate auf Platte. Die Geschwindigkeit ergibt sich aus der
einfachen Weise, wie Daten auf der Platte gefunden werden können. Wenn man
etwas mit einem Index und statischem Format nachschlägt, ist es sehr
einfach. Man multipliziert einfach die Zeilennummer mit der Zeilenlänge.
Wenn eine Tabelle gescannt wird, ist es ausserdem sehr einfach, mit jedem
Plattenzugriff eine konstante Anzahl von Datensätzen zu lesen.
Die Sicherheit zeigt sich, wenn Ihr Computer beim Schreiben in eine
MyISAM-Datei fester Länge abstürzt. In diesem Fall kann myisamchk
leicht herausfinden, wo jede Zeile anfängt und aufhört. Daher kann es
üblicherweise alle Datensätze mit Ausnahme desjenigen, in den nur teilweise
geschrieben wurde, wieder herstellen. Beachten Sie, dass in MySQL alle
Indexe in jedem Fall wiederhergestellt werden können:
-
Alle
CHAR-, NUMERIC- und DECIMAL-Spalten werden mit
Leerzeichen auf die Spaltenbreite aufgefüllt.
-
Sehr schnell.
-
Leicht zu cachen.
-
Nach einem Absturz leicht zu rekonstruieren, weil sich Datensätze an festen
Positionen befinden.
-
müssen nicht (mit
myisamchk) reorganisiert werden, es sei denn, eine
riesige Anzahl von Datensätzen wurde gelöscht und Sie wollen dem
Betriebssystem freien Speicherplatz zurückgeben.
-
Benötigen normalerweise mehr Speicherplatz als dynamische Tabellen.
Dieses Format wird benutzt, wenn die Tabelle irgend welche VARCHAR-,
BLOB- oder TEXT-Spalten enthält, oder wenn die Tabelle mit
ROW_FORMAT=dynamic erzeugt wurde.
Dieses Format ist etwas komplexer, weil jede Zeile einen Header haben muss,
der aussagt, wie lang sie ist. Ein Datensatz kann ausserdem an mehr als
einem Speicherplatz enden, wenn er bei einer Aktualisierung verlängert
wird.
Sie können OPTIMIZE table oder myisamchk benutzen, um eine
Tabelle zu defragmentieren. Wenn Sie statische Daten haben, auf die Sie oft
zugreifen oder die Sie in derselben Tabelle oft ändern, als VARCHAR-
oder BLOB-Spalten haben, ist es eine gute Idee, die dynamischen
Spalten in andere Tabellen zu verschieben, einfach um Fragmentierung zu
vermeiden:
-
Alle Zeichenketten-Spalten sind dynamisch (ausser denen mit einer Länge
kleiner 4).
-
Jedem Datensatz ist eine Bitmap vorangestellt, die angibt, welche Spalten
bei Zeichenketten-Spalten leer (
'') sind oder 0 bei numerischen
Spalten. (Das ist nicht dasselbe wie Spalten, die NULL-Werte
enthalten.) Wenn eine Zeichenketten-Spalte nach der Entfernung von
Leerzeichen am Ende eine Länge von 0 hat oder eine numerische Spalte einen
Wert von 0 hat, wird sie in der Bitmap markiert und nicht auf Platte
gespeichert. Nicht leere Zeichenketten werden als ein Längen-Byte plus dem
Zeichenketten-Inhalt gespeichert.
-
Benötigen üblicherweise weniger Plattenplatz als Festlängen-Tabellen.
-
Jeder Datensatz benutzt nur so viel Speicherplatz wie erforderlich. Wenn
ein Datensatz größer wird, wird er in so viele Teile wie erforderlich
aufgeteilt. Hierdurch wird Datensatzfragmentierung hervorgerufen.
-
Wenn Sie eine Zeile mit Informationen aktualisieren, die die Zeilenlänge
überschreiten, wird die Zeile fragmentiert. In diesem Fall sollten Sie von
Zeit zu Zeit
myisamchk -r laufen lassen, um bessere Performance zu
erzielen. Benutzen Sie myisamchk -ei tabellen_name, um einige
statistische Informationen zu erhalten.
-
Sind nach einem Absturz nicht so einfach zu rekonstruieren, weil ein
Datensatz in viele Teile fragmentiert sein und ein Link (Fragment) fehlen
kann.
-
Die erwartete Zeilenlänge bei Datensätzen dynamischer Länge ist:
3
+ (anzahl_der_spalten + 7) / 8
+ (anzahl_der_zeichenketten_spalten)
+ komprimierte_groesse_numerischer_spalten
+ laenge_von_zeichenketten
+ (anzahl_von_NULL_spalten + 7) / 8
Für jeden Link kommen 6 Bytes hinzu. Ein dynamischer Datensatz wird immer
dann verknüpft (linked), wenn eine Aktualisierung eine Vergrößerung des
Datensatzes bewirkt. Jede neue Verknüpfung hat mindestens 20 Bytes, so dass
die nächste Vergrößerung wahrscheinlich in dieselbe Verknüpfung passt.
Wenn nicht, entsteht eine weitere Verknüpfung. Sie können mit
myisamchk -ed prüfen, wie viele Verknüpfungen es gibt. Alle
Verknüpfungen können mit myisamchk -r entfernt werden.
Das ist ein Nur-Lese-Typ, der mit dem optionalen
myisampack-Dienstprogramm (pack_isam für
ISAM-Tabellen) erzeugt wird:
-
All MySQL-Distributionen, selbst diejenigen, die es vor der GPL-Version von
MySQL gab, können Tabellen lesen, die mit
myisampack komprimiert
wurden.
-
Komprimierte Tabellen benötigen viel weniger Speicherplatz. Das minimiert
Plattenzugriffe, was sehr nett ist, wenn Sie langsame Platten benutzen (wie
CD-ROMs).
-
Jeder Datensatz wird separat komprimiert (sehr geringer Zugriffs-Overhead).
Der Header für einen Datensatz hat eine feste Länge (1 bis 3 Bytes),
abhängig vom größten Datensatz in der Tabelle. Jede Spalte wird
unterschiedlich komprimiert. Einige Kompressionstypen sind:
-
Für jede Spalte gibt es üblicherweise eine unterschiedliche
Huffman-Tabelle.
-
Komprimierung von Leerzeichen am Ende.
-
Komprimierung von Leerzeichen am Anfang.
-
Zahlen mit dem Wert
0 werden mit 1 Bit gespeichert.
-
Wenn Werte in einer Ganzzahl-Spalte einen kleinen Wertebereich haben, wird
die Spalte mit dem kleinsten möglichen Typ gespeichert. Eine
BIGINT-Spalte (8 Bytes) kann beispielsweise als
TINYINT-Spalte (1 Byte) gespeichert werden, wenn sich alle Werte im
Bereich von 0 bis 255 befinden.
-
Wenn eine Spalte nur einen kleinen Satz möglicher Werte besitzt, wird der
Spaltentyp zu
ENUM umgewandelt.
-
Eine Spalte kann auch eine Kombination der obigen Komprimierungen benutzen.
-
Kann Datensätze fester oder dynamischer Länge handhaben, aber nicht
BLOB- oder TEXT-Spalten.
-
Kann mit
myisamchk dekomprimiert werden.
Das Dateiformat, das MySQL benutzt, um Daten zu speichern, wurde ausgiebig
getestet, aber es gibt immer Umstände, die dazu führen können, dass
Datenbanktabellen beschädigt werden.
Obwohl das MyISAM-Tabellenformat sehr zuverlässig ist (alle Änderungen an
einer Tabelle werden geschrieben, bevor das SQL-Statement zurückkehrt),
können Sie dennoch beschädigte Tabellen bekommen, wenn eines der folgenden
Dinge passiert:
-
Der
mysqld-Prozess wird mitten in einem Schreibvorgang gekillt.
-
Unerwartetes Herunterfahren des Computers (wenn der Computer beispielsweise
abgeschaltet wird).
-
Ein Hardware-Fehler.
-
Sie benutzen ein externes Programm (wie myisamchk) auf einer benutzten
Tabelle.
-
Ein Software-Bug im MySQL- oder MyISAM-Code.
Typische Symptome einer beschädigten Tabelle sind:
-
Sie erhalten den Fehler
Incorrect key file for table: '...'. Try to
repair it, wenn Sie Daten aus der Tabelle auswählen.
-
Anfragen finden keine Zeilen in der Tabelle oder geben unvollständige Daten
zurück.
Sie können mit dem Befehl CHECK TABLE prüfen, ob eine Tabelle in
Ordnung ist. See section 5.4.4 CHECK TABLE-Syntax.
Sie können eine beschädigte Tabelle mit REPAIR TABLE reparieren.
See section 5.4.5 REPAIR TABLE-Syntax. Wenn mysqld nicht läuft, können Sie eine
Tabelle auch mit dem myisamchk-Befehl reparieren.
myisamchk-Syntax.
Wenn Ihre Tabellen oft beschädigt werden, sollten Sie versuchen, den Grund
dafür herauszufinden! See section A.4.1 Was zu tun ist, wenn MySQL andauernd abstürzt.
In diesem Fall ist es am wichtigsten zu wissen, ob die Tabelle durch einen
Absturz von mysqld beschädigt wurde (das können Sie leicht
feststellen, wenn es eine aktuelle Zeile restarted mysqld in der
mysqld-Fehlerdatei gibt). Wenn das nicht der Fall ist, sollten Sie
versuchen, daraus einen Testfall zu machen. See section E.1.6 Einen Testfall herstellen, wenn Sie Tabellenbeschädigung feststellen.
Jede MyISAM-.MYI-Datei hat im Header einen Zähler, der
benutzt werden kann, um zu prüfen, ob die Tabelle korrekt geschlossen
wurde.
Wenn Sie folgende Warnmeldung von CHECK TABLE oder myisamchk
erhalten:
# client is using or hasn't closed the table properly
heißt das, dass der Zähler nicht mehr synchron ist. Das bedeutet nicht,
dass die Tabelle beschädigt ist, aber Sie sollten zumindest eine
Überprüfung vornehmen, um sicherzustellen, dass die Tabelle in Ordnung ist.
Der Zähler funktioniert wie folgt:
-
Wenn die Tabelle das erste Mal in MySQL aktualisiert wird, wird der Zähler
im Header der Index-Dateien heraufgezählt.
-
Der Zähler wird während weiterer Aktualisierungen nicht verändert.
-
Wenn die letzte Instanz einer Tabelle geschlossen wird (wegen eines
FLUSH oder weil es nicht mehr genug Platz im Tabellen-Cache gibt),
wird der Zähler heruntergezählt, wenn die Tabelle zu irgend einem Zeitpunkt
aktualisiert wurde.
-
Wenn Sie eine Tabelle reparieren oder prüfen und sie in Ordnung ist, wird
der Zähler auf 0 zurückgesetzt.
-
Um Probleme zu vermeiden, die durch Interaktion mit anderen Prozessen
entstehen, die vielleicht eine Prüfung der Tabelle durchführen, wird der
Zähler beim Schließen nicht heruntergezählt, wenn er 0 war.
Mit anderen Worten kann der Zähler nur in folgenden Fällen nicht mehr
synchron sein:
-
Die
MyISAM-Tabellen werden ohne LOCK und FLUSH TABLES
kopiert.
-
MySQL ist zwischen einer Aktualisierung und dem endgültigen Schließen
abgestürzt. (Beachten Sie, dass die Tabelle trotzdem in Ordnung sein kann,
weil MySQL stets für alles zwischen jedem Statement Schreibvorgänge
durchführt.
-
Jemand hat
myisamchk --repair oder myisamchk --update-state
auf eine Tabelle ausgeführt, die durch mysqld in Benutzung war.
-
Viele
mysqld-Server benutzen die Tabelle und einer davon hat
REPAIR oder CHECK der Tabelle ausgeführt, während sie durch
einen anderen Server in Benutzung war. Hierbei kann CHECK sicher
ausgeführt werden (selbst wenn Sie Warnungen von anderen Servern erhalten
werden), aber REPAIR sollte vermieden werden, weil es momentan die
Daten-Datei durch eine neue ersetzt, was anderen Servern nicht signalisiert
wird.
MERGE-Tabellen sind neu seit MySQL-Version 3.23.25. Der Code ist
noch Gamma, sollte aber ausreichend stabil sein.
Eine MERGE-Tabelle (auch bekannt als MRG_MyISAM-Tabelle) ist
eine Sammlung identischer MyISAM-Tabellen, die wie eine benutzt
werden können. Sie können auf dieser Sammlung von Tabellen nur
SELECT, DELETE und UPDATE ausführen. Wenn Sie eine
MERGE-Tabelle löschen (DROP), löschen Sie nur die
MERGE-Spezifikation.
Beachten Sie, dass DELETE FROM merge_tabelle ohne WHERE nur
das Mapping für die Tabelle löscht, nicht alles in den gemappten Tabellen.
(Geplant ist, das in Version 4.1 zu beheben.)
Mit identischen Tabellen ist gemeint, dass alle Tabellen mit identischen
Spalten- und Schlüsselinformationen erzeugt wurden. Sie können kein MERGE
auf Tabellen ausführen, deren Spalten unterschiedlich komprimiert sind,
nicht genau dieselben Spalten oder die Schlüssel in unterschiedlicher
Reihenfolge haben. Einige der Tabellen können jedoch mit myisampack
komprimiert sein. See section 5.7.4 myisampack, MySQL-Programm zum Erzeugen komprimierter Nur-Lese-Tabellen.
Wenn Sie eine MERGE-Tabelle erzeugen, erhalten Sie eine
.frm-Tabellendefinitionsdatei und eine
.MRG-Tabellenlistendatei. Die .MRG enthält lediglich eine
Liste der Index-Dateien (.MYI-Dateien), die wie eine benutzt werden
sollen. Alle benutzten Tabellen müssen in derselben Datenbank wie die
MERGE-Tabelle selbst sein.
Momentan benötigen Sie SELECT-, UPDATE- und
DELETE-Berechtigungen für die Tabellen, die Sie auf eine
MERGE-Tabelle mappen.
MERGE-Tabellen können bei der Lösung folgender Probleme helfen:
-
Auf einfache Weise einen Satz von Log-Tabellen verwalten. Beispielsweise
können Sie Daten aus unterschiedlichen Monaten in separaten Dateien
speichern, einige davon mit
myisampack komprimieren und dann eine
MERGE-Tabelle erzeugen, um sie wie eine zu benutzen.
-
Mehr Geschwindigkeit. Sie können eine große Nur-Lese-Tabelle nach
bestimmten Kriterien aufspalten und die verschiedenen Tabellenteile auf
unterschiedlichen Festplatten speichern. Eine
MERGE-Tabelle darauf
könnte viel schneller sein als die große Tabelle zu benutzen. (Natürlich
können Sie auch ein RAID benutzen, um dieselben Vorteile zu erzielen.)
-
Effizientere Suchen durchführen. Wenn Sie genau wissen, wonach Sie suchen,
können Sie mit einigen Anfragen in lediglich einer der aufgespaltenen
Tabellen suchen und die MERGE-Tabelle für andere benutzen. Es
können sogar viele unterschiedliche
MERGE-Tabellen aktiv sein,
möglicherweise mit Dateien, die sich überlappen.
-
Effizientere Reparaturen durchführen. Es ist leichter, die individuellen
Dateien zu reparieren, die auf eine
MERGE-Datei gemappt sind, als
eine wirklich große Datei zu reparieren.
-
Sofortiges Mappen vieler Dateien als einer. Eine
MERGE-Tabelle
benutzt den Index der individuellen Tabellen. Sie muss selbst keinen
eigenen Index warten. Dadurch können Sie MERGE-Tabellensammlungen
SEHR schnell erzeugen oder neu mappen. Beachten Sie, dass Sie die
Schlüsseldefinitionen angeben, wenn Sie eine MERGE-Tabelle erzeugen!
-
Wenn Sie einen Satz von Tabellen bei Bedarf oder im Stapel zu einer großen
Tabelle vereinigen, sollten Sie statt dessen bei Bedarf eine
MERGE-Tabelle darauf erzeugen. Das ist viel schneller und spart eine
Menge Speicherplatz.
-
Umgehen der Dateigrößengrenze des Betriebssystems.
-
Sie können ein Alias / Synonym für eine Tabelle erzeugen, indem Sie sie
einfach ein MERGE über eine Tabelle benutzen. Das sollte keine spürbaren
Performance-Auswirkungen haben (nur eine Reihe indirekter Aufrufen und
memcpy's bei jedem Lesen).
Die Nachteile von MERGE-Tabellen sind:
-
Sie können nur identische
MyISAM-Tabellen für eine
MERGE-Tabelle benutzen.
-
AUTO_INCREMENT-Spalten werden bei INSERT nicht automatisch
aktualisiert.
-
REPLACE funktioniert nicht.
-
MERGE-Tabellen benutzen mehr Datei-Deskriptoren. Wenn Sie eine
MERGE benutzen, die über 10 Tabellen mappt, und 10 Benutzer diese
benutzen, benötigen Sie 10 * 10 + 10 Datei-Deskriptoren (10 Daten-Dateien
für 10 Benutzer und 10 gemeinsam genutzte Index-Dateien).
-
Lesevorgänge von Schlüsseln sind langsamer. Wenn Sie eine Leseoperation auf
einen Schlüssel durchführen, muss der
MERGE-Handler ein Lesen auf
alle zugrunde liegenden Tabellen ausführen, um zu prüfen, welche am
nächsten zum angegebenen Schlüssel passt. Wenn Sie ein 'Lese nächsten'
ausführen, muss der MERGE-Handler die Lese-Puffer durchsuchen, um
den nächsten Schlüssel zu finden. Erst wenn ein Schlüsselpuffer
aufgebraucht ist, muss der Handler den nächsten Schlüsselblock lesen. Das
macht MERGE-Schlüssel bei eq_ref-Suchen viel langsamer, aber
nicht viel langsamer bei ref-Suchen.
See section 6.2.1 EXPLAIN-Syntax (Informationen über ein SELECT erhalten).
-
Sie können kein
DROP TABLE, ALTER TABLE oder DELETE
FROM tabelle ohne eine WHERE-Klausel auf jeder Tabelle, die von
einer MERGE-Tabelle gemappt ist, ausführen, wenn diese 'offen' ist.
Wenn Sie das tun, könnte die MERGE-Tabelle immer noch auf die
Originaltabelle verweisen, und Sie würden unerwartete Ergebnisse erhalten.
Wenn Sie eine MERGE-Tabelle erzeugen, müssen Sie mit
UNION(liste-von-tabellen) angeben, welche Tabellen Sie wie eine
benutzen wollen. Optional können Sie mit INSERT_METHOD angeben, ob
Sie wollen, dass Einfügungen in die MERGE-Tabelle in der ersten oder
der letzten Tabelle in der UNION-Liste geschehen sollen. Wenn Sie
keine INSERT_METHOD oder NO angeben, geben alle
INSERT-Befehle auf die MERGE-Tabelle einen Fehler zurück.
Folgendes Beispiel zeigt, wie Sie MERGE-Tabellen benutzen:
CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY, nachricht CHAR(20));
CREATE TABLE t2 (a INT AUTO_INCREMENT PRIMARY KEY, nachricht CHAR(20));
INSERT INTO t1 (nachricht) VALUES ("test"),("tabelle"),("t1");
INSERT INTO t2 (nachricht) VALUES ("test"),("tabelle"),("t2");
CREATE TABLE gesamt (a INT NOT NULL, nachricht CHAR(20), KEY(a)) TYPE=MERGE UNION=(t1,t2) INSERT_METHOD=LAST;
Beachten Sie, dass wir keinen UNIQUE- oder PRIMARY
KEY-Schlüssel in der gesamt-Tabelle angegeben haben, weil der
Schlüssel in der gesamt-Tabelle nicht eindeutig sein wird.
Beachten Sie auch, dass Sie die .MRG-Datei direkt von ausserhalb des
MySQL-Servers manipulieren können:
shell> cd /mysql-data-verzeichnis/aktuelle-datenbank
shell> ls -1 t1.MYI t2.MYI > gesamt.MRG
shell> mysqladmin flush-tables
Jetzt können Sie Dinge wie folgendes tun:
mysql> select * from gesamt;
+---+-----------+
| a | nachricht |
+---+-----------+
| 1 | test |
| 2 | table |
| 3 | t1 |
| 1 | test |
| 2 | table |
| 3 | t2 |
+---+-----------+
Um eine MERGE-Tabelle neu zu mappen, können Sie folgendes tun:
-
Die Tabelle löschen (
DROP) und neu erzeugen.
-
ALTER TABLE tabelle UNION(...) benutzen.
-
Die
.MRG-Datei ändern und ein FLUSH TABLE auf die
MERGE-Tabelle und alle zugrunde liegenden Tabellen ausführen, um den
Handler zu zwingen, die neue Definitionsdatei einzulesen.
Folgende Probleme sind bei MERGE-Tabellen bekannt:
-
DELETE FROM merge_tabelle ohne WHERE löscht nur das Mapping
für die Tabelle, nicht alles in den gemappten Tabellen.
-
RENAME TABLE auf eine Tabelle, die in einer aktiven
MERGE-Tabelle benutzt wird, kann die Tabelle beschädigen. Das wird
in MySQL 4.0.x behoben.
-
Beim Erzeugen einer Tabelle des Typs
MERGE wird nicht geprüft, ob
die zugrunde liegenden Tabellen kompatible Typen sind. Wenn Sie
MERGE-Tabellen in dieser Weise benutzen, ist es sehr wahrscheinlich,
dass merkwürdige Probleme auftauchen.
-
Wenn Sie
ALTER TABLE benutzen, um als erstes eine
UNIQUE-Index zu einer Tabelle hinzuzufügen, die in einer
MERGE-Tabelle benutzt wird, und dann ALTER TABLE benutzen, um
einen normalen Index auf die MERGE-Tabelle hinzuzufügen, wird die
Schlüssel-Reihenfolge für die Tabellen anders sein, wenn es einen alten,
nicht eindeutigen Schlüssel in der Tabelle gab. Das liegt daran, dass
ALTER TABLE UNIQUE-Schlüssel vor normale Schlüssel einfügt,
um in der Lage zu sein, doppelte Schlüsseleinträge so früh wie möglich zu
erkennen.
-
Der Bereichsoptimierer kann
MERGE-Tabellen noch nicht effizient
benutzen und kann manchmal nicht optimale Joins produzieren. Das wird in
MySQL 4.0.x behoben.
-
DROP TABLE auf eine Tabelle, die in einer MERGE-Tabelle
benutzt wird, funktioniert unter Windows nicht, weil der
MERGE-Handler das Tabellen-Mapping versteckt vor der oberen Ebene
von MySQL durchführt. Weil Windows es nicht zuläßt, dass Dateien gelöscht
werden, die offen sind, müssen Sie zuerst alle MERGE-Tabellen auf
Platte zurückschreiben (mit FLUSH TABLES) oder die
MERGE-Tabelle löschen, bevor Sie die Tabelle löschen. Das wird zu
dem Zeitpunkt behoben, wenn Sichten (VIEWs) eingeführt werden.
Sie können auch den veralteten ISAM-Tabellentyp benutzen. Dieser
wird recht bald verschwinden (wahrscheinlich in MySQL 4.1), weil
MyISAM eine bessere Implementation derselbe Sache ist. ISAM
benutzt einen B-tree-Index. Der Index wird in einer Datei mit der
Endung .ISM gespeichert, und die Daten in einer Datei mit der Endung
.ISD. Sie können ISAM-Tabellen mit dem
isamchk-Dienstprogramm prüfen / reparieren. See section 5.4 Katastrophenschutz und Wiederherstellung.
ISAM hat folgende Features / Eigenschaften:
- Komprimierte und Festlängen-Schlüssel
- Feste und dynamische Datensatzlängen
- 16 Schlüssel mit 16 Schlüsselteilen pro Schlüssel
- Maximale Schlüssellänge 256 (Vorgabe)
- Daten werden im Maschinenformat gespeichert. Das ist schnell, aber
Maschinen- / Betriebssystem-abhängig.
Die meisten Dinge, die für MyISAM-Tabellen gelten, gelten auch für
ISAM-Tabellen. See section 8.1 MyISAM-Tabellen. Die größten Unterschiede im Vergleich
zu MyISAM sind:
ISAM-Tabellen sind nicht binärportabel zwischen verschiedenen
Betriebssystemen / Plattformen.
- Handhabt keine Tabellen > 4 GB.
- Unterstützt nur Präfix-Komprimierung von Zeichenketten.
- Kleinere Schlüssel-Beschränkungen.
- Dynamische Tabelle werden schneller fragmentiert.
- Tabellen werden mit
pack_isam statt mit myisampack
komprimiert.
Wenn Sie eine ISAM-Tabelle in eine MyISAM-Tabelle umwandeln
wollen, können Sie Dienstprogramme wie mysqlcheck oder ein
ALTER TABLE-Statement benutzen:
mysql> ALTER TABLE tabelle TYPE = MYISAM;
Die eingebetteten (embedded) MySQL-Versionen unterstützen keine
ISAM-Tabellen.
HEAP-Tabellen benutzen eine gehashten Index und werden im
Arbeitsspeicher gespeichert. Das macht sie sehr schnell, aber wenn MySQL
abstürzt, verlieren Sie alle darin gespeicherten Daten. HEAP ist
sehr nützlich für temporäre Tabellen.
Die MySQL-internen HEAP-Tabellen benutzen 100% dynamisches Hashen
ohne Overflow-Bereiche. Es wird kein zusätzlicher Platz für freie Listen
benötigt. HEAP-Tabellen haben auch keine Probleme mit Löschen plus
Einfügen, was normalerweise bei gehashten Tabellen häufig vorkommt:
mysql> CREATE TABLE test TYPE=HEAP SELECT ip,SUM(downloads) as down
FROM log_tabelle GROUP BY ip;
mysql> SELECT COUNT(ip),AVG(down) FROM test;
mysql> DROP TABLE test;
Einige Dinge sollten Sie bei der Benutzung von HEAP-Tabellen in
Betracht ziehen:
-
Sie sollten immer
MAX_ROWS im CREATE-Statement angeben, um
sicherzustellen, dass Sie nicht versehentlich den gesamten Arbeitsspeicher
benutzen.
-
Indexe werden nur bei
= und <=> benutzt (sind aber SEHR
schnell).
-
HEAP-Tabellen können nur ganze Schlüssel benutzen, um nach einer
Zeile zu suchen. Vergleichen Sie das mit MyISAM-Tabellen, bei denen
jedes Präfix des Schlüssels für das Suchen von Zeilen benutzt werden kann.
-
HEAP-Tabellen benutzen ein festes Datensatzlängenformat.
-
HEAP unterstützt keine BLOB/TEXT-Spalten.
-
HEAP unterstützt keine AUTO_INCREMENT-Spalten.
-
HEAP unterstützt keinen Index auf eine NULL-Spalte.
-
Es darf keine nicht eindeutigen Schlüssel auf eine
HEAP-Tabelle
geben (das ist ungebräuchlich für gehashte Tabellen).
-
HEAP-Tabellen werden von allen Clients gemeinsam benutzt (so wie
jede andere Tabelle).
-
Sie können nicht nach dem nächsten Eintrag in der Reihenfolge suchen (also
den Index benutzen, um ein
ORDER BY zu machen).
-
Die Daten für
HEAP-Tabellen werden in kleinen Blöcken zugewiesen.
Die Tabellen sind 100% dynamisch (beim Einfügen). Es werden keine
Overflow-Bereiche und kein zusätzlicher Platz für Schlüssel benötigt.
Gelöschte Zeilen werden in eine verknüpfte Liste geschrieben und wieder
benutzt, wenn Sie neue Daten in die Tabelle einfügen.
-
Sie brauchen genug zusätzlichen Arbeitsspeicher für alle
HEAP-Tabellen, die Sie zugleich benutzen wollen.
-
Um Speicher freizugeben, führen Sie
DELETE FROM heap_tabelle,
TRUNCATE heap_tabelle oder DROP TABLE heap_tabelle aus.
-
MySQL kann nicht herausfinden, wie viele Zeilen es zwischen zwei Werten
ungefähr gibt (das wird vom Bereichsoptimierer benötigt, um zu entscheiden,
welcher Index benutzt wird). Das kann einige Anfragen betreffen, wenn Sie
eine
MyISAM-Tabelle in eine HEAP-Tabelle umwandeln.
-
Um sicherzustellen, dass Sie nicht versehentlich etwas Unkluges tun, können
Sie keine
HEAP-Tabellen größer als max_heap_table_size
erzeugen.
Der für eine Zeile in einer HEAP-Tabelle benötigte Speicher ist:
SUM_OVER_ALL_KEYS(max_length_of_key + sizeof(char*) * 2)
+ ALIGN(length_of_row+1, sizeof(char*))
sizeof(char*) ist 4 auf 32-Bit-Maschinen und 8 auf 64-Bit-Maschinen.
InnoDB stellt MySQL einen transaktionssicheren (ACID-kompatiblen)
Tabellen-Handler mit Fähigkeiten für Commit, Rollback und Reparatur nach
Absturz zur Verfügung. InnoDB beherrscht Sperren auf Zeilenebene sowie ein
konsistentes, nicht sperrendes Lesen in der Art von Oracle bei
SELECTs. Diese Features steigern die Handhabung gleichzeitiger
Verbindungen und die Performance. Es gibt bei InnoDB keine Notwendigkeit
für Sperr-Eskalation, weil die Sperren auf Zeilenebene bei InnoDB in sehr
wenig Speicherplatz passen. InnoDB-Tabellen unterstützen als erster
Tabellentyp in MySQL FOREIGN KEY-Beschränkungen.
InnoDB wurde für maximale Performance bei der Bearbeitung großer
Datenmengen entworfen. Seine Prozessor-Effizienz wird wahrscheinlich von
keiner anderen Festplatten-basierenden relationalen Datenbank-Engine
erreicht.
Technisch gesehen ist InnoDB ein komplettes Datenbank-Backend, das unter
MySQL platziert ist. InnoDB hat seinen eigenen Puffer-Pool, um Daten und
Indexe im Hauptspeicher zu cachen. InnoDB speichert seine Tabellen und
Indexe in einem Tabellenplatz (Tablespace), der aus mehreren Dateien
bestehen kann. Das unterscheidet sich beispielsweise von MyISAM-Tabellen,
bei denen jede Tabelle als separate Datei gespeichert ist. InnoDB-Tabellen
können jede beliebige Größe annehmen, sogar auf Betriebssystemen, deren
Dateigröße auf 2 GB beschränkt ist.
Die neuesten Informationen über InnoDB finden Sie unter
http://www.innodb.com/. Die aktuellste Version des InnoDB-Handbuchs
ist immer dort zu finden, und Sie können auch kommerzielle Lizenzen und
kommerziellen Support für InnoDB bestellen.
InnoDB wird momentan (Oktober 2001) für die Produktion auf mehreren großen
Datenbank-Sites benutzt, die hohe Performance benötigen. Die bekannte
Internet-Newssite Slashdot.org läuft auf InnoDB. Mytrix Inc. speichert über
1 TB an Daten in InnoDB, und eine andere Site handhabt eine
durchschnittliche Last von 800 Einfüge- und Update-Operationen pro Sekunde
mit InnoDB.
InnoDB-Tabellen sind in der MySQL-Quelldistribution ab Version 3.23.34a
enthalten und in der MySQL-Max-Binärversion aktiviert. Für Windows sind die
Max-Binärdateien in der Standarddistribution enthalten.
Wenn Sie eine Binärversion von MySQL herunter geladen haben, die
Unterstützung für InnoDB enthält, folgen Sie einfach den Anweisungen im
Handbuch für die Installation einer Binärversion von MySQL. Wenn Sie
bereits MySQL-3.23 installiert haben, können Sie MySQL-Max am einfachsten
installieren, indem Sie die ausführbare Datei für den Server
(`mysqld') durch die entsprechende ausführbare Datei in der
Max-Distribution ersetzen. MySQL and MySQL-Max unterscheiden sich nur in
Bezug auf die ausführbare Datei für den Server. See section 3.2.6 MySQL-Binärdistributionen, die von MySQL AB kompiliert wurden. See section 5.7.5 mysqld-max, ein erweiterter mysqld-Server.
Um MySQL mit InnoDB-Unterstützung zu kompilieren, laden Sie MySQL-3.23.34a
oder neuer von http://www.mysql.com/ herunter und konfigurieren Sie
MySQL mit der --with-innodb-Option. Sehen Sie im Handbuch unter
section 3.3 Installation der Quelldistribution nach.
cd /pfad/zur/quelldistribution/von/mysql-3.23.37
./configure --with-innodb
Um InnoDB zu benutzen, müssen Sie InnoDB init in Ihrer `my.cnf'- oder
`my.ini'-Datei angeben. In dieser Datei müssen Sie mindestens
folgenden Zeile im [mysqld]-Abschnitt hinzufügen:
innodb_data_file_path=ibdata:30M
Für eine gute Performance ist es jedoch am besten, Optionen wie die unten
im Abschnitt section 8.5.2 Mit InnoDB anfangen - Optionen empfohlenen anzugeben.
InnoDB wird unter der GNU-GPL-Lizenz Version 2 (vom Juni 1991) vertrieben.
In den Quelldistributionen von MySQL erscheint InnoDB als Unterverzeichnis.
Um InnoDB-Tabellen in MySQL-Max-3.23 zu benutzen, MÜSSEN Sie
Konfigurationsparameter im [mysqld]-Abschnitt der
MySQL-Konfigurationsdatei `my.cnf' angeben. See section 5.1.2 my.cnf-Optionsdateien.
Der einzige erforderliche Parameter, um InnoDB in MySQL-Max-3.23 benutzen
zu können, ist innodb_data_file_path.
In MySQL-4.0 müssen Sie nicht einmal innodb_data_file_path angeben.
Vorgabemäßig wird eine 64 MB große Daten-Datei `ibdata1' im
datadir von MySQL erzeugt.
Um jedoch eine gute Performance zu erzielen, MÜSSEN Sie explizit die unten
in Beispielen aufgeführten InnoDB-Parameter setzen.
Der Vorgabewert für innodb_data_home_dir ist das datadir von
MySQL. Wenn Sie innodb_data_home_dir nicht angeben, können Sie in
innodb_data_file_path keine absoluten Pfade benutzen.
Nehmen wir an, Sie haben eine Windows-NT-Maschine mit 128 MB RAM und einer
einzelnen 10 GB großen Festplatte. Unten steht ein Beispiel von möglichen
Konfigurationsparametern in `my.cnf' für InnoDB:
[mysqld]
# Hier können Ihre sonstigen MySQL-Serveroptionen stehen
# ...
#
innodb_data_home_dir = c:\ibdata
# Die Daten-Dateien müssen in der Lage sein,
# Ihre Daten und Indexe aufzunehmen
innodb_data_file_path = ibdata1:2000M;ibdata2:2000M
# Puffer-Poolgröße auf 50% bis 80%
# des Arbeitsspeichers Ihres Computers setzen
set-variable = innodb_buffer_pool_size=70M
set-variable = innodb_additional_mem_pool_size=10M
innodb_log_group_home_dir = c:\iblogs
# .._log_arch_dir muss dasselbe sein wie
# .._log_group_home_dir
innodb_log_arch_dir = c:\iblogs
innodb_log_archive=0
set-variable = innodb_log_files_in_group=3
# Die Log-Dateigröße auf ungefähr 15%
# der Puffer-Poolgröße setzen
set-variable = innodb_log_file_size=10M
set-variable = innodb_log_buffer_size=8M
# ..flush_log_at_trx_commit auf 0 setzen,
# wenn Sie es sich leisten können,
# ein paar der letzten Transaktionen zu verlieren
innodb_flush_log_at_trx_commit=1
set-variable = innodb_file_io_threads=4
set-variable = innodb_lock_wait_timeout=50
Beachten Sie, dass die Daten-Dateien bei einigen Betriebssystemen kleiner
als 2 GB sein müssen! Die Gesamtgröße von Daten-Dateien muss größer oder
gleich 10 MB sein. Die Gesamtgröße der Log-Dateien MUSS auf
32-Bit-Computern kleiner als 4 GB sein.
InnoDB legt keine Verzeichnisse an. Diese müssen Sie selbst
erzeugen!
Stellen Sie auch sicher, dass der MySQL-Server Rechte hat, Dateien in den
Verzeichnissen anzulegen, die Sie angeben.
Wenn Sie zum ersten Mal eine InnoDB-Datenbank erzeugen, sollten Sie den
MySQL-Server am besten von der Kommandozeilen-Eingabeaufforderung starten.
InnoDB gibt dann Informationen über die Datenbank-Erzeugung auf dem
Bildschirm aus und Sie sehen, was passiert. Unten in Abschnitt 3 sehen Sie,
wie die Ausgaben aussehen sollten.
Unter Windows können Sie `mysqld-max.exe' so starten:
ihr-pfad-zu-mysqld>mysqld-max --standalone --console
Nehmen wir an, Sie haben einen Linux-Computer mit 512 MB RAM und drei
Festplatten mit jeweils 20 GB (in Verzeichnispfaden `/', `/dr2'
and `/dr3'). Unten ist ein Beispiel möglicher Konfigurationsparameter
in `my.cnf' für InnoDB:
[mysqld]
# Hier können Ihre sonstigen MySQL-Serveroptionen stehen
# ...
#
innodb_data_home_dir = /
# Die Daten-Dateien müssen in der Lage sein,
# Ihre Daten und Indexe aufzunehmen
innodb_data_file_path = ibdata/ibdata1:2000M;dr2/ibdata/ibdata2:2000M
# Puffer-Poolgröße auf 50% bis 80%
# des Arbeitsspeichers Ihres Computers setzen
set-variable = innodb_buffer_pool_size=350M
set-variable = innodb_additional_mem_pool_size=20M
innodb_log_group_home_dir = /dr3/iblogs
# .._log_arch_dir muss dasselbe sein wie
# .._log_group_home_dir
innodb_log_arch_dir = /dr3/iblogs
innodb_log_archive=0
set-variable = innodb_log_files_in_group=3
# Die Log-Dateigröße auf ungefähr 15%
# der Puffer-Poolgröße setzen
set-variable = innodb_log_file_size=50M
set-variable = innodb_log_buffer_size=8M
# ..flush_log_at_trx_commit auf 0 setzen,
# wenn Sie es sich leisten können,
# ein paar der letzten Transaktionen zu verlieren
innodb_flush_log_at_trx_commit=1
set-variable = innodb_file_io_threads=4
set-variable = innodb_lock_wait_timeout=50
#innodb_flush_method=fdatasync
#innodb_fast_shutdown=1
#set-variable = innodb_thread_concurrency=5
Beachten Sie, dass die beiden Daten-Dateien auf unterschiedliche Platten
platziert wurden. Der Grund für den Namen innodb_data_file_path
ist, dass Sie auch Pfade zu Ihren Daten-Dateien angeben können und dass
innodb_data_home_dir nur textlich mit Ihren Daten-Datei-Pfaden
verkettet wird, wobei ein möglicher Schrägstrich oder Backslash dazwischen
hinzugefügt wird. InnoDB füllt den Tabellenplatz (Tablespace), der durch
die Daten-Dateien gebildet wird, von unten nach oben. In manchen Fällen
verbessert es die Performance der Datenbank, wenn nicht alle Daten auf
derselben physikalischen Festplatte platziert sind. Es verbessert häufig
die Performance, Log-Dateien auf anderen Platten als die Daten zu
platzieren.
Die Bedeutung der Konfigurationsparameter ist wie folgt:
| Option | Beschreibung
|
innodb_data_home_dir |
Der allgemeine Teil des Verzeichnispfads für alle InnoDB-Daten-Dateien. Die
Vorgabe für diesen Parameter ist das datadir von MySQL.
|
innodb_data_file_path |
Pfade zu individuellen Daten-Dateien und ihre Größen. Der volle
Verzeichnispfad zu jeder Daten-Datei wird durch Verkettung von
innodb_data_home_dir mit den hier angegebenen Pfaden hergestellt. Die
Dateigrößen werden in Megabytes angegeben, daher das 'M' nach der obigen
Angabe. InnoDB versteht auch die Abkürzung 'G', 1G bedeutet 1024M. Ab
3.23.44 können Sie die Dateigröße auf mehr als 4 GB setzen, wenn das
Betriebssystem große Dateien unterstützt. Auf einige Betriebssystemen
müssen Dateien kleiner als 2 GB sein. Die Summe der Dateigrößen muss
mindestens 10 MB betragen.
|
innodb_mirrored_log_groups |
Anzahl identischer Kopien von Log-Gruppen, die für die Datenbank gehalten
werden. Momentan sollte dieser Parameter auf 1 gesetzt werden.
|
innodb_log_group_home_dir |
Verzeichnispfad zu den InnoDB-Log-Dateien.
|
innodb_log_files_in_group |
Anzahl von Log-Dateien in der Log-Gruppe. InnoDB schreibt in zirkulärer
Weise in die Dateien. Hier wird ein Wert 3 empfohlen.
|
innodb_log_file_size |
Größe jeder Log-Datei in einer Log-Gruppe in Megabytes. Sinnvolle Werte
reichen von 1 MB bis 1/n-tel der Größe des Puffer-Pools, die unten
angegeben wird, wobei n die Anzahl der Log-Dateien in der Gruppe ist. Je
größer der Wert, desto weniger Checkpoint-Flush-Aktivität wird im Puffer
benötigt, was Festplatten-Ein- und -Ausgaben erspart. Größere Log-Dateien
bedeutet jedoch auch, dass die Wiederherstellung im Fall eines Absturzes
langsamer ist. Die Gesamtgröße aller Log-Dateien muss auf 32-Bit-Computern
kleiner als 4 GB sein.
|
innodb_log_buffer_size |
Die Größe des Puffers, den InnoDB benutzt, um in die Log-Dateien auf
Platte zu schreiben. Sinnvolle Werte liegen im Bereich von 1 MB bis zur
Hälfte der Gesamtgröße der Log-Dateien. Ein großer Log-Puffer erlaubt,
dass große Transaktionen laufen können, ohne dass die Notwendigkeit
besteht, das Log auf Platte zu schreiben, bis die Transaktion abgeschickt
(commit) wird. Wenn Sie daher große Transaktionen haben, sparen Sie
Festplatten-Ein- und Ausgaben, wenn Sie den Log-Puffer Groß machen.
|
innodb_flush_log_at_trx_commit |
Normalerweise wird dieser Parameter auf 1 gesetzt, was bedeutet, dass beim
Abschicken (commit) einer Transaktion das Log auf Platte geschrieben wird
(flush) und die durch die Transaktion gemachten Änderungen permanent werden
und einen Datenbankabsturz überleben. Wenn Sie willens sind, in Bezug auf
diese Sicherheit Kompromisse einzugeben und eher kleine Transaktionen
laufen lassen, können Sie diesen Wert auf 0 setzen, um Festplatten-Ein- und
-Ausgaben in Bezug auf die Log-Dateien zu verringern.
|
innodb_log_arch_dir |
Das Verzeichnis, in dem komplett geschriebene Log-Dateien archiviert
werden, wenn Archivierung benutzt wird. Der Wert dieses Parameters sollte
momentan derselbe sein wie innodb_log_group_home_dir.
|
innodb_log_archive |
Dieser Wert sollte momentan auf 0 gesetzt werden. Weil MySQL die
Wiederherstellung aus einer Datensicherung unter Benutzung seiner eigenen
Log-Dateien durchführt, gibt es momentan keine Notwendigkeit,
InnoDB-Log-Dateien zu archivieren.
|
innodb_buffer_pool_size |
Die Größe des Speicherpuffers, den InnoDB benutzt, um Daten und Indexe
seiner Tabellen zu cachen. Je größer Sie diesen Wert setzen, desto weniger
Festplatten-Ein- und -Ausgaben werden für den Zugriff auf Daten in Tabellen
benötigt. Auf einem dedizierten Datenbank-Server können Sie diesen
Parameter auf bis zu 80% des physikalischen Arbeitsspeichers der Maschine
setzen. Setzen Sie ihn allerdings nicht zu hoch, weil bei manchen
Betriebssystemen der Wettbewerb um Arbeitsspeicher zu Paging führt.
|
innodb_additional_mem_pool_size |
Die Größe des Speicher-Pools, den InnoDB für die Speicherung von
Daten-Wörterbuchinformationen und anderen internen Datenstrukturen benutzt.
Ein sinnvoller Wert hierfür könnte 2 MB sein. Je mehr Tabellen Sie jedoch
in Ihrer Applikation haben, desto mehr müssen Sie hier zuweisen. Wenn
InnoDB in diesem Pool keinen Speicherplatz mehr hat, läßt es sich
Speicherplatz vom Betriebssystem zuweisen und schreibt Warnmeldungen in die
MySQL-Fehler-Log-Datei.
|
innodb_file_io_threads |
Die Anzahl der Datei-Ein- und -Ausgabe-Threads in InnoDB. Normalerweise
sollte dieser Wert 4 sein, aber Windows-Festplatten könnten von einer
höheren Zahl profitieren.
|
innodb_lock_wait_timeout |
Timeout in Sekunden. Solange wartet eine InnoDB-Transaktion auf eine
Sperre, bevor sie abgebrochen (Rollback) wird. InnoDB erkennt automatisch
Transaktionsblockierungen in seiner eigenen Sperr-Tabelle und bricht die
Transaktion ab (Rollback). Wenn Sie den LOCK TABLES-Befehl oder
andere transaktionssichere Tabellen-Handler als InnoDB in derselben
Transaktion benutzen, kann eine Blockierung auftreten, die InnoDB nicht
erkennen kann. In solchen Fällen ist ein Timeout nützlich, um die Situation
zu bereinigen.
|
innodb_flush_method |
(Verfügbar ab Version 3.23.40.)
Der Vorgabewert hierfür ist fdatasync.
Ein andere Option ist O_DSYNC.
|
Angenommen, Sie haben MySQL installiert und `my.cnf' so editiert, dass
sie die notwendigen InnoDB Konfigurationsparameter enthält. Bevor Sie MySQL
starten, sollten Sie überprüfen, dass die für InnoDB-Daten- und Log-Dateien
angegebenen Verzeichnisse existieren und dass Sie auf diese Zugriffsrechte
haben. InnoDB kann keine Verzeichnisse anlegen, nur Dateien. Überprüfen Sie
auch, ob Sie auf der Festplatte genug Platz für Daten- und Log-Dateien
haben.
Wenn Sie jetzt MySQL starten, fängt InnoDB an, Ihre Daten- und Log-Dateien
zu erzeugen. InnoDB gibt dabei etwas wie das folgende aus:
~/mysqlm/sql > mysqld
InnoDB: The first specified data file /home/stefan/data/ibdata1 did not exist:
InnoDB: a new database to be created!
InnoDB: Setting file /home/stefan/data/ibdata1 size to 134217728
InnoDB: Database physically writes the file full: wait...
InnoDB: Data file /home/stefan/data/ibdata2 did not exist: new to be created
InnoDB: Setting file /home/stefan/data/ibdata2 size to 262144000
InnoDB: Database physically writes the file full: wait...
InnoDB: Log file /home/stefan/data/logs/ib_logfile0 did not exist: new to be created
InnoDB: Setting log file /home/stefan/data/logs/ib_logfile0 size to 5242880
InnoDB: Log file /home/stefan/data/logs/ib_logfile1 did not exist: new to be created
InnoDB: Setting log file /home/stefan/data/logs/ib_logfile1 size to 5242880
InnoDB: Log file /home/stefan/data/logs/ib_logfile2 did not exist: new to be created
InnoDB: Setting log file /home/stefan/data/logs/ib_logfile2 size to 5242880
InnoDB: Started
mysqld: ready for connections
Jetzt wurde eine neue InnoDB-Datenbank erzeugt. Sie können sich mit den
üblichen MySQL-Client-Programmen wie mysql mit dem MySQL-Server
verbinden. Wenn Sie den MySQL-Server mit `mysqladmin shutdown'
herunter fahren, gibt InnoDB etwa wie das folgende aus:
010321 18:33:34 mysqld: Normal shutdown
010321 18:33:34 mysqld: Shutdown Complete
InnoDB: Starting shutdown...
InnoDB: Shutdown completed
Wenn Sie jetzt einen Blick auf die Daten-Dateien und Log-Verzeichnisse
werfen, sehen Sie die erzeugten Dateien. Das Log-Verzeichnis enthält auch
eine kleine Datei namens `ib_arch_log_0000000000'. Diese Datei
resultiert aus der Datenbank-Erzeugung, nach der InnoDB die
Log-Archivierung ausgeschaltet hat. Wenn MySQL noch einmal gestartet wird,
sieht die Ausgabe etwa wie folgt aus:
~/mysqlm/sql > mysqld
InnoDB: Started
mysqld: ready for connections
Falls etwas bei der Datenbank-Erzeugung schiefgeht, sollten Sie alle durch
InnoDB erzeugten Dateien löschen. Das heißt alle Daten-Dateien, alle
Log-Dateien, die kleine archivierte Log-Datei und - falls Sie bereits
InnoDB-Tabellen erzeugt haben, auch die entsprechenden `.frm'-Dateien
für diese Tabellen in den MySQL-Datenbankverzeichnissen. Danach können Sie
die InnoDB-Datenbankerzeugung erneut versuchen.
Angenommen, Sie haben den MySQL-Client mit dem Befehl mysql test
gestartet. Um eine Tabelle im InnoDB-Format zu erzeugen, müssen Sie im
SQL-Befehl zur Tabellenerzeugung TYPE = InnoDB angeben:
CREATE TABLE kunde (A INT, B CHAR (20), INDEX (A)) TYPE = InnoDB;
Dieser SQL-Befehl erzeugt eine Tabelle und einen Index auf die Spalte
A im InnoDB-Tabellenplatz (Tablespace), der aus den Daten-Dateien
besteht, die Sie in `my.cnf' angegeben haben. MySQL erzeugt zusätzlich
eine Datei `kunde.frm' im MySQL-Datenbankverzeichnis `test'.
Intern fügt InnoDB seinem eigenen Datenwörterbuch einen Eintrag für die
Tabelle 'test/kunde' hinzu. Wenn Sie daher eine Tabelle namens
kunde in einer anderen Datenbank von MySQL erzeugen, kollidieren die
Tabellennamen innerhalb InnoDB nicht.
Sie können den freien Speicherplatz im InnoDB-Tabellenplatz (Tablespace)
mit dem Tabellen-Status-Befehl von MySQL für jede Tabelle, die Sie mit
TYPE = InnoDB erzeugt haben, abfragen. Die Menge freien Platzes im
Tabellenplatz (Tablespace) erscheint im Kommentar-Abschnitt der Tabelle in
der Ausgabe von SHOW. Beispiel:
SHOW TABLE STATUS FROM test LIKE 'kunde'
Beachten Sie, dass die Statistiken, die SHOW über InnoDB-Tabellen
ausgibt, nur Näherungswerte sind: Sie werden für die SQL-Optimierung
benutzt. Die für Tabelle und Indexe reservierten Größen in Bytes sind
allerdings genau.
InnoDB hat keine spezielle Optimierung für separate Index-Erzeugung. Daher
lohnt es sich nicht, die Tabelle zu exportieren und importieren und die
Indexe danach zu erzeugen. Die schnellste Art, eine Tabelle in InnoDB zu
ändern, ist, die Einfügungen direkt in eine InnoDB-Tabelle vorzunehmen,
das heißt, ALTER TABLE ... TYPE=INNODB zu benutzen oder eine leere
InnoDB-Tabelle mit identischen Definitionen zu nehmen und die Zeilen mit
INSERT INTO ... SELECT * FROM ... einzufügen.
Um eine bessere Kontrolle über den Einfügeprozess zu erhalten, kann es
besser sein, große Tabellen in Teilstücken einzufügen:
INSERT INTO neue_tabelle SELECT * FROM alte_tabelle WHERE schluessel > etwas
AND schluessel <= etwas_anderes;
Nachdem alle Daten eingefügt wurden, können Sie die Tabellen umbenennen.
Während der Umwandlung großer Tabellen sollten Sie den InnoDB-Puffer-Pool
hoch setzen, um Festplatten-Ein- und -Ausgaben zu verringern, allerdings
nicht höher als 80% des physikalischen Arbeitsspeichers. Sie sollten die
InnoDB-Log-Dateien Groß machen und auch den Log-Puffer.
Stellen Sie sicher, dass Sie genug Tabellenplatz (Tablespace) haben!
InnoDB-Tabellen benötigen viel mehr Platz als MyISAM-Tabellen. Wenn ein
ALTER TABLE nicht mehr genug Platz hat, wird ein Rollback gestartet,
das Stunden dauern kann, wenn es auf der Festplatte stattfindet. Bei
Einfügeoperationen verwendet InnoDB den Einfügepuffer, um sekundäre
Index-Datensätze mit Indexen in Stapeln zu vermischen. Das spart eine Menge
an Festplatten-Ein- und -Ausgaben. Beim Rollback wird kein solcher
Mechanismus benutzt, weshalb das Rollback bis zu 30 mal länger als das
Einfügen dauern kann.
Falls Sie keine wertvollen Daten in Ihren InnoDB-Dateien haben, ist es im
Fall eines 'festgefahrenen' Rollback besser, den Datenbank-Prozess zu
killen und alle InnoDB-Daten- und Log-Dateien sowie alle InnoDB-Tabellen
(`.frm'-Dateien) zu löschen und noch einmal anzufangen, statt darauf
zu warten, dass Millionen von Festplatten-Ein- und -Ausgaben beendet
werden.
InnoDB-Version 3.23.44 hat Fremdschlüssel-(Foreign Key)-Beschränkungen.
InnoDB ist der erste MySQL-Tabellentyp, der die Definition von
Fremdschlüssel-Beschränkungen zuläßt, um die Integrität Ihrer Daten zu
überwachen.
Die Syntax einer Fremdschlüsseldefinition in InnoDB:
FOREIGN KEY (index_spalten_name, ...) REFERENCES tabellen_name (index_spalten_name, ...)
Beispiel:
CREATE TABLE eltern(id INT NOT NULL, PRIMARY KEY (id)) TYPE=INNODB;
CREATE TABLE kind(id INT, eltern_id INT, INDEX par_ind (eltern_id),
FOREIGN KEY (eltern_id) REFERENCES eltern(id)) TYPE=INNODB;
Beide Tabellen müssen vom Typ InnoDB sein und es muss einen Index geben,
bei dem der Fremdschlüssel und der referenzierte Schlüssel als erste
Spalten aufgeführt sind. Jegliches ALTER TABLE entfernt momentan
alle Fremdschlüsselbeschränkungen, die für die Tabelle definiert wurden,
aber nicht die Beschränkungen, die die Tabelle referenzieren.
Korrespondierende Spalten im Fremdschlüssel und dem referenzierten
Schlüssel müssen ähnliche interne Datentypen innerhalb InnoDB sein, so dass
sie ohne Typumwandlung verglichen werden können. Die Längen von
Zeichenkettentypen müssen nicht dieselben sein. Die Größe und Vorzeichen /
kein Vorzeichen von Ganzzahltypen müssen dieselben sein.
Beim Prüfen von Fremdschlüsseln setzt InnoDB gemeinsame Sperren auf
Zeilenebene auf kind- und eltern-Datensätze, die es betrachten muss. InnoDB
prüft Fremdschlüssel-(Foreign Key)-Beschränkungen sofort: Die Prüfung wird
nicht bis zu einem Transaktions-Commit verschoben.
InnoDB läßt zu, dass jegliche Tabelle gelöscht wird, selbst wenn das die
Fremdschlüssel-(Foreign Key)-Beschränkungen durchbrechen würde, die die
Tabelle referenzieren. Wenn Sie eine Tabelle löschen, werden die
Beschränkungen, die in ihrem CREATE-Statement definiert wurden, ebenfalls
gelöscht.
Wenn Sie eine gelöschte Tabelle neu erzeugen, muss sie eine Definition
haben, die mit den Fremdschlüssel-(Foreign Key)-Beschränkungen konform ist,
die sie referenzieren. Sie muss die richten Spaltennamen und -typen haben,
und sie muss - wie oben angegeben - Indexe auf die referenzierten Schlüssel
haben.
Sie können die Fremdschlüssel-(Foreign Key)-Beschränkungen für eine Tabelle
wie folgt auflisten:
T with
SHOW TABLE STATUS FROM ihr_datenbank_name LIKE 'T';
Die Fremdschlüssel-(Foreign Key)-Beschränkungen werden im
Tabellen-Kommentar der Ausgabe aufgelistet.
InnoDB unterstützt noch kein CASCADE ON DELETE oder andere spezielle
Optionen für diese Beschränkungen.
Sie können die Größe einer InnoDB-Daten-Datei nicht vergrößern. Um Ihrem
Tabellenplatz (Tablespace) mehr hinzuzufügen, müssen Sie eine neue
Daten-Datei hinzufügen. Um das zu tun, müssen Sie Ihre MySQL-Datenbank
herunter fahren, die `my.cnf'-Datei editieren und eine neue Datei zu
innodb_data_file_path hinzufügen. Dann starten Sie MySQL erneut.
Momentan können Sie keine Daten-Datei aus InnoDB entfernen. Um die Größe
Ihrer Datenbank zu verringern, müssen Sie `mysqldump' benutzen, um
alle Ihre Tabellen zu dumpen, eine neue Datenbank erzeugen und Ihre
Tabellen in die neue Datenbank importieren.
Wenn Sie die Anzahl oder die Größe Ihrer InnoDB-Log-Dateien ändern wollen,
müssen Sie MySQL herunter fahren und sicher stellen, dass er ohne Fehler
herunter fuhr. Dann kopieren Sie die alten Log-Dateien an eine sichere
Stelle, falls etwas beim Herunterfahren schiefging und Sie die Datenbank
wiederherstellen müssen. Löschen Sie die alten Log-Dateien aus dem
Log-Datei-Verzeichnis, editieren Sie `my.cnf' und starten Sie MySQL
noch einmal. InnoDB meldet beim Starten, dass es neue Log-Dateien anlegt.
Der Schlüssel zur sicheren Datenbankverwaltung sind regelmäßige
Datensicherungen. Im eine 'binäre' Sicherung Ihrer Datenbank zu machen, tun
Sie folgendes:
-
Fahren Sie Ihre MySQL-Datenbank herunter und stellen Sie sicher, dass dabei
keine Fehler auftraten.
-
Kopieren Sie Ihre Daten-Dateien an eine sichere Stelle.
-
Kopieren Sie alle InnoDB-Log-Dateien an eine sichere Stelle.
-
Kopieren Sie Ihre `my.cnf' Konfigurationsdatei(en) an eine sichere
Stelle.
-
Kopieren Sie alle `.frm'-Dateien für Ihre InnoDB-Tabellen an eine
sichere Stelle.
Momentan gibt es kein Online- oder inkrementelles Datensicherungsprogramm
für InnoDB, obwohl diese auf der TODO-Liste sind.
Zusätzlich zu den beschriebenen Binär-Datensicherungen sollten Sie
ausserdem regelmäßig Dumps Ihrer Tabellen mit `mysqldump' machen. Der
Grund ist, dass eine Binärdatei beschädigt sein kann, ohne dass Sie das
bemerken. Gedumpte Tabellen werden in Textdateien gespeichert, die
Menschen-lesbar und viel einfacher als binäre Datenbankdateien sind. Aus
gedumpten Dateien läßt sich Tabellenbeschädigung leichter erkennen und da
ihr Format einfacher ist, ist das Risiko ernsthafter Datenbeschädigung in
ihnen geringer.
Es ist eine gute Idee, Dumps zur gleichen Zeit zu machen wie die binäre
Datensicherung Ihrer Datenbank. Sie müssen alle Clients aus Ihrer Datenbank
ausschließen, um konsistente Schnappschüsse aller Ihrer Tabellen im Dump
zu bekommen. Danach können Sie die binäre Datensicherung machen, so dass
Sie einen konsistenten Schnappschuss Ihrer Datenbank in zwei Formaten
haben.
Um in der Lage zu sein, Ihre InnoDB-Datenbank aus den beschriebenen binären
Datensicherungen wiederherzustellen, müssen Sie Ihre MySQL-Datenbank mit
allgemeinem Loggen und angeschalteter Log-Archivierung von MySQL laufen
lassen. Mit allgemeinem Loggen ist hier der Log-Mechanismus des
MySQL-Servers gemeint, der unabhängig von den InnoDB-Logs ist.
Zum Wiederherstellen nach einem Absturz des MySQL-Serverprozesses ist es
lediglich nötig, diesen erneut zu starten. InnoDB prüft automatisch die
Log-Dateien und führt ein Roll-Forward der Datenbank bis zum aktuellen
Stand durch. InnoDB macht ein automatisches Rollback nicht abgeschlossener
(committed) Transaktionen, die zur Zeit des Absturzes anhängig waren.
Während der Wiederherstellung gibt InnoDB etwa folgendes aus:
~/mysqlm/sql > mysqld
InnoDB: Database was not shut down normally.
InnoDB: Starting recovery from log files...
InnoDB: Starting log scan based on checkpoint at
InnoDB: log sequence number 0 13674004
InnoDB: Doing recovery: scanned up to log sequence number 0 13739520
InnoDB: Doing recovery: scanned up to log sequence number 0 13805056
InnoDB: Doing recovery: scanned up to log sequence number 0 13870592
InnoDB: Doing recovery: scanned up to log sequence number 0 13936128
...
InnoDB: Doing recovery: scanned up to log sequence number 0 20555264
InnoDB: Doing recovery: scanned up to log sequence number 0 20620800
InnoDB: Doing recovery: scanned up to log sequence number 0 20664692
InnoDB: 1 uncommitted transaction(s) which must be rolled back
InnoDB: Starting rollback of uncommitted transactions
InnoDB: Rolling back trx no 16745
InnoDB: Rolling back of trx no 16745 completed
InnoDB: Rollback of uncommitted transactions completed
InnoDB: Starting an apply batch of log records to the database...
InnoDB: Apply batch completed
InnoDB: Started
mysqld: ready for connections
Wenn Ihre Datenbank beschädigt wird oder Ihre Festplatte Fehler hat, müssen
Sie eine Wiederherstellung aus einer Datensicherung durchführen. Im Falle
der Beschädigung sollten Sie zunächst eine Datensicherung finden, die nicht
beschädigt ist. Machen Sie aus der Datensicherung eine Wiederherstellung
aus den allgemeinen Log-Dateien von MySQL unter Beachtung der Anleitungen
im MySQL-Handbuch.
InnoDB hat einen Checkpoint-Mechanismus implementiert, der sich Fuzzy
Checkpoint nennt. InnoDB schreibt veränderten Datenbankseiten aus dem
Puffer-Pool in kleinen Stapeln (Batch) auf Platte (flush), daher besteht
keine Notwendigkeit, den Puffer-Pool in einem einzelnen Stapel
zurückzuschreiben, was in der Praxis dazu führen würde, dass SQL-Statements
von Benutzern für eine Weile angehalten würden.
Bei der Reparatur nach Abstürzen sucht InnoDB nach einem Checkpoint-Label in
den Log-Dateien. Es weiß, dass alle Änderungen an der Datenbank vor dem
Label bereits im Platten-Image der Datenbank enthalten sind. InnoDB scannt
anschließend die Log-Dateien ab dem Checkpoint vorwärts und wendet die
geloggten Änderungen auf die Datenbank an.
InnoDB schreibt in zirkulärer Art in die Log-Dateien. Alle abgeschickten
(committed) Änderungen, die dazu führen, dass sich die Datenbankseiten im
Puffer-Pool vom Image auf der Platte unterscheiden, müssen in den
Log-Dateien verfügbar sein, für den Fall, dass InnoDB eine
Wiederherstellung durchführen muss. Das heißt, wenn InnoDB anfängt, eine
Log-Datei auf zirkuläre Weise wieder zu benutzen, muss es sicherstellen,
dass die Datenbankseiten-Images auf der Festplatte bereits die Änderungen
enthalten, die in der Log-Datei mitgeschrieben sind, die InnoDB benutzen
wird. Mit anderen Worten muss InnoDB einen Checkpoint machen, was oft das
Zurückschreiben auf Platte (flush) geänderter Datenbankseiten beinhaltet.
Das erklärt, warum es Festplatten-Ein- und -Ausgaben sparen kann, wenn man
die Log-Dateien sehr Groß macht. Es kann sinnvoll sein, die Gesamtgröße
der Log-Dateien so Groß wie den Puffer-Pool oder sogar noch größer zu
machen. Der Nachteil großer Log-Dateien ist, dass eine Reparatur nach
Absturz länger dauern kann, weil mehr Log-Einträge auf die Datenbank
angewendet werden müssen.
InnoDB-Daten- und Log-Dateien sind auf allen Plattformen binärkompatibel,
wenn das Fließkommazahlenformat auf den Maschinen dasselbe ist. Sie können
eine InnoDB-Datenbank einfach verschieben, indem Sie alle relevanten
Dateien kopieren, die im vorherigen Abschnitt über Datensicherung erwähnt
wurden. Wenn sich das Fließkommaformat auf den Maschinen unterscheidet,
sie aber keine FLOAT- oder DOUBLE-Datentypen in Ihren
Tabellen benutzt haben, ist die Prozedur dieselbe: Kopieren Sie einfach die
relevanten Dateien. Wenn die Formate unterschiedlich sind und Ihre Tabellen
Fließkomma-Daten enthalten, müssen Sie `mysqldump' und
`mysqlimport' benutzen, um diese Tabellen zu verschieben.
Ein Tipp zur Performance: Schalten Sie Auto-Commit aus, wenn Sie Daten in
Ihre Datenbank importieren (unter der Annahme, dass Ihr Tabellenplatz
(Tablespace) genug Platz für das große Rollback-Segment enthält, den die
große Import-Transaktion erzeugen wird). Machen Sie das Commit erst nach
dem Import einer ganzen Tabelle oder eines Segments einer Tabelle.
Im InnoDB-Transaktionsmodell war das Ziel, die besten Eigenschaften einer
multiversionsfähigen Datenbank mit dem traditionellen Zwei-Phasen-Sperren
zu verbinden. InnoDB führt Sperren auf Zeilenebene durch und läßt Anfragen
vorgabemäßig als nicht sperrende konsistente Leseoperationen laufen, im
Stil von Oracle. Das Tabellensperren ist in InnoDB so platzsparend
gespeichert, dass keine Sperr-Eskalation benötigt wird: Typischerweise
dürfen mehrere Benutzer jede Zeile in der Datenbank oder eine beliebige
Teilmenge der Zeilen sperren, ohne dass InnoDB keinen Speicher mehr hat.
Bei InnoDB findet jede Benutzeraktivität innerhalb von Transaktionen statt.
Wenn der Auto-Commit-Modus in MySQL benutzt wird, stellt jedes
SQL-Statement eine einzelne Transaktion dar. Wenn der Auto-Commit-Modus
ausgeschaltet wird, kann man sich vorstellen, dass ein Benutzer stets eine
Transaktion offen hat. Wenn er das SQL-COMMIT- oder
ROLLBACK-Statement absetzt, beendet das die aktuelle Transaktion und
eine neue beginnt. Beide Statements heben alle InnoDB-Sperren auf, die
während der aktuellen Transaktion gesetzt wurden. Ein COMMIT
bedeutet, dass die in der aktuellen Transaktion gemachten Änderungen
permanent und sichtbar für andere Benutzer gemacht werden. Auf der anderen
Seite bricht ein ROLLBACK alle Änderungen ab, die in der aktuellen
Transaktion gemacht wurden.
Konsistentes Lesen bedeutet, dass InnoDB seine Multiversionsfähigkeiten
nutzt, um einer Anfrage einen Schnappschuss der Datenbank zu einem
bestimmten Zeitpunkt zu zeigen. Die Anfrage sieht genau die Änderungen, die
von Transaktionen durchgeführt wurden, die bis zu diesem Zeitpunkt
abgeschlossen wurden (committed), und keine Änderungen, die später gemacht
wurden oder die noch nicht abgeschlossen sind. Die Ausnahme von der Regel
ist, dass die Anfrage die Änderungen sieht, die durch die Transaktion
selbst durchgeführt wurde, die die Anfrage absetzt.
Wenn eine Transaktion ihr erstes Konsistentes Lesen durchführt, weist
InnoDB den Schnappschuss oder Zeitpunkt zu, den jedes Konsistente Lesen
in derselben Transaktion benutzen wird. Im Schnappschuss sind alle
Transaktionen enthalten, die vor der Zuweisung zum Schnappschuss
abgeschlossen (committed) wurden. Daher ist Konsistentes Lesens innerhalb
derselben Transaktion auch untereinander konsistent. Sie können einen
frischeren Schnappschuss für Ihre Anfragen erhalten, indem Sie die aktuelle
Transaktion beenden (commit) und danach neue Anfragen absetzen.
Konsistentes Lesen ist der vorgabemäßige Modus, in dem InnoDB
SELECT-Statements abarbeitet. Konsistentes Lesen setzt keinerlei
Sperren auf die Tabellen, auf die es zugreift. Daher können andere Benutzer
zur selben Zeit, wie Konsistentes Lesen auf die Tabelle durchgeführt wird,
diese verändern.
Unter manchen Umständen ist Konsistentes Lesen nicht wünschenswert.
Angenommen, Sie wollen eine neue Zeile in die Tabelle kind einfügen
und dabei sicherstellen, dass das Kind bereits Eltern in der Tabelle
eltern hat.
Wenn Sie Konsistentes Lesen benutzen, um die Tabelle eltern zu lesen
und in der Tat die Eltern des Kindes in der Tabelle sehen, können Sie dann
sicher die Kind-Zeile zur Tabelle kind hinzufügen? Nein, denn es
kann sein, dass zwischenzeitlich jemand anderes die Eltern-Zeile aus der
Tabelle eltern gelöscht hat und Sie das nicht sehen.
Die Lösung besteht darin, das SELECT im Sperrmodus durchzuführen.
LOCK IN SHARE MODE.
SELECT * FROM eltern WHERE NAME = 'Hinz' LOCK IN SHARE MODE;
Wenn Sie ein Lesen im Share-Modus durchführen, heißt das, dass die letzten
verfügbaren Daten gelesen werden und eine Shared-Modus-Sperre auf die Zeile
gesetzt wird, die gelesen wird. Wenn die letzten Daten zu einer noch nicht
abgeschlossenen Transaktion eines anderen Benutzers gehören, wird gewartet,
bis die Transaktion abgeschlossen (committed) ist. Eine Shared-Modus-Sperre
verhindert, dass andere die Zeile aktualisieren oder löschen, die gerade
gelesen wurde. Nachdem festgestellt wurde, dass die obige Anfrage die
Eltern 'Hinr' zurückgibt, kann das Kind sicher zur Tabelle
kind hinzugefügt und die Transaktion abgeschlossen werden. Dieses
Beispiel zeigt, wie Sie in Ihren Applikations-Code referentielle Integrität
integrieren können.
Sehen wir uns ein weiteres Beispiel an. Wir haben ein ganzzahliges
Zählerfeld in einer Tabelle kind_codes, was benutzt wird, um jedem
Kinde, das wir der Tabelle kind hinzufügen, eine eindeutige Kennung
zuzuweisen. Es ist offensichtlich, dass Konsistentes Lesen oder
Shared-Modus-Lesen kein geeignetes Mittel ist, um den aktuellen Wert des
Zählers zu ermitteln, weil nämlich zwei Benutzer der Datenbank denselben
Wert des Zählers sehen können und wir daher einen Fehler wegen doppelter
Schlüsseleinträge erhalten, wenn wir zwei Kinder mit derselben Kennung in
die Tabelle einfügen.
In diesem Fall gibt es zwei geeignete Möglichkeiten, das Lesen und
Heraufzählen des Zählers zu implementieren:
(1) Zuerst den Zähler um eins erhöhen und erst danach lesen.
(2) Zuerst den Zähler im Sperr-Modus FOR UPDATE lesen und danach
heraufzählen:
SELECT COUNTER_FIELD FROM kind_codes FOR UPDATE;
UPDATE kind_codes SET COUNTER_FIELD = COUNTER_FIELD + 1;
SELECT ... FOR UPDATE liest die letzten verfügbaren Daten und setzt
exklusive Sperren auf jede Zeile, die es liest. Daher setzt es dieselben
Sperren, die ein gesuchtes SQL-UPDATE auf die Zeilen setzen würde.
Beim Sperren auf Zeilenebene benutzt InnoDB einen Algorithmus, der
Nächsten-Schlüssel-Sperren genannt wird. InnoDB führt das Sperren auf
Zeilenebene so durch, dass es beim Suchen oder Scannen eines Indexes auf
eine Tabelle gemeinsam genutzte (shared) oder exklusive Sperren auf die
Index-Datensätze setzt, die es findet. Daher werden die Sperren auf
Zeilenebene genauer Index-Datensatz-Sperren genannt.
Die Sperren, die InnoDB auf Index-Datensätze setzt, betreffen auch die
'Lücke' vor diesem Index-Datensatz. Wenn ein Benutzer eine gemeinsam
benutzte (shared) oder exklusive Sperre auf den Datensatz R in einem Index
hat, kann ein anderen Benutzer keinen Datensatz direkt vor R (in der
Index-Reihenfolge) einfügen. Dieses Sperren von Lücken wird durchgeführt,
um das so genannte Phantom-Problem zu vermeiden. Angenommen, man will alle
Kinder aus der Tabelle kind lesen und sperren, die eine Kennung
größer 100 haben, und irgend ein Feld in der ausgewählten Zeile
aktualisieren:
SELECT * FROM kind WHERE ID > 100 FOR UPDATE;
Angenommen, es gibt einen Index auf der Tabelle kind auf der Spalte
ID. Unsere Anfrage scannt diesen Index ab dem ersten Datensatz, bei
dem ID größer als 100 ist. Wenn jetzt die auf den Index-Datensatz
gesetzten Sperren nicht Einfügeoperationen sperren würden, die in die
Lücken ausgeführt würden, könnte zwischenzeitlich ein neues Kind in die
Tabelle eingefügt werden. Wenn jetzt unsere Transaktion noch einmal
folgendes ausführen würde:
SELECT * FROM kind WHERE ID > 100 FOR UPDATE;
Sehen wir ein neues Kind in der Ergebnismenge, die die Anfrage zurückgibt.
Das verstößt gegen das Isolationsprinzip von Transaktionen: Eine
Transaktion sollte in der Lage sein, so abzulaufen, dass die Daten, die sie
gelesen hat, sich nicht während der Transaktion ändern. Wenn wir einen Satz
von Zeilen als Daten-Posten betrachten, würde das neue 'Phantom'-Kind
dieses Isolationsprinzip durchbrechen.
Wenn InnoDB einen Index scannt, kann es auch die Lücke nach dem letzten
Datensatz im Index sperren. Genau das passiert im vorherigen Beispiel: Die
Sperren, die von InnoDB gesetzt werden, verhindert jedes Einfügen in die
Tabelle an Stellen, wo ID größer als 100 ist.
Sie können Nächsten-Schlüssel-Sperren dazu benutzen, eine
Eindeutigkeitsprüfung in Ihre Applikation zu implementieren: Wenn Sie Ihre
Daten im Share-Modus lesen und kein Duplikat für eine Zeile sehen, die Sie
einfügen werden, können Sie Ihre Zeile sicher einfügen und wissen, dass das
Nächsten-Schlüssel-Sperren verhindern wird, dass zwischenzeitlich jemand
eine Duplikatzeile Ihrer Zeile einfügt. Daher gestattet Ihnen das
Nächsten-Schlüssel-Sperren, die Nicht-Existenz von irgend etwas in Ihrer
Tabelle zu 'sperren'.
-
SELECT ... FROM ... : Das ist Konsistentes Lesen, es wird ein
Schnappschuss einer Datenbank gelesen und es werden keine Sperren gesetzt.
-
SELECT ... FROM ... LOCK IN SHARE MODE : setzt gemeinsam genutztes
(shared) Nächsten-Schlüssel-Sperren auf alle Index-Datensätze, die beim
Lesen gefunden werden.
-
SELECT ... FROM ... FOR UPDATE : setzt exklusives
Nächsten-Schlüssel-Sperren auf alle Index-Datensätze, die beim Lesen
gefunden werden.
-
INSERT INTO ... VALUES (...) : setzt eine exklusive Sperre auf die
eingefügte Zeile. Beachten Sie, dass diese Sperre kein
Nächsten-Schlüssel-Sperren ist und andere Benutzer nicht davon abhält,
etwas in die Lücke vor der eingefügten Zeile einzufügen. Wenn ein Fehler
wegen doppelter Schlüsseleinträge auftritt, setzt dieser Befehl eine
gemeinsam genutzte (shared) Sperre auf den doppelten (Duplikat)
Index-Datensatz.
-
INSERT INTO T SELECT ... FROM S WHERE ... setzt eine exklusive
Sperre (kein Nächsten-Schlüssel-Sperren) auf jede Zeile, die in T
eingefügt wurde. Sucht nach S in Form von Konsistentem Lesen, aber
setzt Nächsten-Schlüssel-Sperren auf S, wenn bei MySQL das Loggen
angeschaltet ist. InnoDB muss in letzterem Fall Sperren setzen, weil bei
einer Roll-Forward-Wiederherstellung aus einer Datensicherung jedes
SQL-Statement auf genau dieselbe Weise ausgeführt werden muss, wie es
ursprünglich ausgeführt wurde.
-
CREATE TABLE ... SELECT ... führt SELECT als Konsistentes
Lesen oder mit gemeinsam genutzten (shared) Sperren aus, wie im vorherigen
Punkt.
-
REPLACE wird wie Einfügen ausgeführt, wenn es keine Kollision auf
einem eindeutigen Schlüssel gibt. Ansonsten wird ein exklusives
Nächsten-Schlüssel-Sperren auf die Reihe gesetzt, die aktualisiert werden
muss.
-
UPDATE ... SET ... WHERE ... setzt ein exklusives
Nächsten-Schlüssel-Sperren auf jeden Datensatz, der beim Suchen gefunden
wird.
-
DELETE FROM ... WHERE ... setzt ein exklusives
Nächsten-Schlüssel-Sperren auf jeden Datensatz, der beim Suchen gefunden
wird.
-
Wenn auf der Tabelle eine
FOREIGN KEY-Beschränkung definiert ist,
setzt jedes Einfügen, Aktualisieren oder Löschen, was die Überprüfung der
Beschränkungsbedingung erfordert, gemeinsam genutzte (shared) Sperren auf
Datensatzebene auf die Datensätze, die bei der Überprüfung der Beschränkung
betrachtet werden. Auch im Falle, dass die Beschränkung fehlschlägt, setzt
InnoDB diese Sperren.
-
LOCK TABLES ... : setzt Tabellensperren. In der Implementation
setzt die MySQL-Ebene des Codes diese Sperren. Die automatische
Blockierungserkennung von InnoDB kann keine Blockierungen bemerken, bei
denen solche Tabellensperren involviert sind, siehe nächster Abschnitt
weiter unten. Sehen Sie auch im Abschnitt 13 ('InnoDB-Einschränkungen')
wegen folgendem nach: Weil MySQL keine Sperren auf Zeilenebene erkennt, ist
es möglich, dass Sie eine Sperre auf eine Tabelle erhalten, auf der ein
anderer Benutzer momentan Sperren auf Zeilenebene hat. Das gefährdet
allerdings nicht die Transaktionsintegrität.
InnoDB erkennt automatisch eine Blockierung von Transaktionen und rollt die
Transaktion zurück, deren Sperranforderung diejenige war, die die
Blockierung aufbaute, also einen Kreis im Warte-Diagramm von Transaktionen.
InnoDB kann keine Blockierungen erkennen, bei denen eine Sperre im Spiel
ist, die durch ein MySQL-LOCK TABLES-Statement verursacht wurde,
oder wenn eine Sperre durch einen anderen Tabellen-Handler als InnoDB
gesetzt wurde. Solche Situationen müssen Sie mit
innodb_lock_wait_timeout, das in `my.cnf' gesetzt wird.
Wenn InnoDB ein komplettes Rollback einer Transaktion durchführt, werden
alle Sperren der Transaktion aufgehoben. Wenn jedoch nur ein einzelnes
SQL-Statement als Ergebnis eines Fehlers zurückgerollt wird, können einige
der Sperren, die durch das SQL-Statement gesetzt wurde, verbleiben. Das
liegt daran, dass InnoDB Zeilensperren in einem Format speichert, die ihm
unmöglich machen, im Nachhinein zu erkennen, welche Sperre durch welches
SQL-Statement gesetzt wurde.
Wenn Sie ein Konsistentes Lesen ausführen, also ein gewöhnliches
SELECT-Statement, gibt InnoDB Ihrer Transaktion einen Zeitpunkt
(Timepoint), gemäß dem Ihre Anfrage die Datenbank sieht. Wenn daher
Transaktion B eine Zeile löscht und das wirksam wird (commit), nachdem Ihr
Zeitpunkt zugewiesen wurde, werden Sie die Zeile nicht als gelöscht sehen.
Gleiches gilt für Einfüge- und Aktualisierungsoperationen.
Sie können Ihren Zeitpunkt 'vorstellen', indem Sie Ihre Transaktion
abschicken (commit) und dann ein weiteres SELECT ausführen.
Das nennt sich Multiversioned Concurrency Control (multiversionierte
Gleichzeitigkeitskontrolle):
Benutzer A Benutzer B
set autocommit=0; set autocommit=0;
zeit
| SELECT * FROM t;
| empty set
| INSERT INTO t VALUES (1, 2);
|
v SELECT * FROM t;
empty set
COMMIT;
SELECT * FROM t;
empty set;
COMMIT;
SELECT * FROM t;
---------------------
| 1 | 2 |
---------------------
Daher sieht Benutzer A die durch B eingefügte Zeile erst, wenn B das
Einfügen und A seine eigene Transaktion abgeschickt hat (commit), so dass
der Zeitpunkt hinter das Commit von B 'vorgestellt' ist.
Wenn Sie den 'frischsten' Zustand der Datenbank sehen wollen, sollten Sie
ein sperrendes Lesen (Locking Read) benutzen:
SELECT * FROM t LOCK IN SHARE MODE;
1.
Wenn das Unix-`top' oder der Windows-`Task-Manager' zeigen, dass
die CPU-Auslastung weniger als 70% beträgt, ist Ihre Auslastung
wahrscheinlich Platten-gebunden. Das kann daran liegen, dass Sie zu viele
Transaktionen abschicken (commit) oder dass der Puffer-Pool zu klein ist.
Dann kann es helfen, den Puffer-Pool zu vergrößern. Setzen Sie ihn aber
nicht höher als 80% des physikalischen Arbeitsspeichers.
2.
Packen Sie mehrere Änderungen in eine Transaktion. InnoDB muss das Log
jedes Mal auf Platte zurückschreiben (flush), wenn eine Transaktion
abgeschickt wird (commit), wenn diese Transaktion irgend welche Änderungen
an der Datenbank vorgenommen hat. Weil die Rotationsgeschwindigkeit einer
Platte typischerweise höchsten 167 Umdrehungen pro Sekunde beträgt,
beschränkt das die Anzahl von Commits auf eben diese Zahl pro Sekunde, wenn
die Festplatte nicht das Betriebssystem täuscht.
3.
Wenn Sie es sich leisten können, einige der zuletzt abgeschickten
(committed) Transaktionen zu verlieren, können Sie den
`my.cnf'-Parameter innodb_flush_log_at_trx_commit auf 0 setzen.
InnoDB versucht dann trotzdem, das Log einmal pro Sekunde auf Platte
zurückzuschreiben (flush), doch dieses Zurückschreiben ist nicht
garantiert.
4.
Machen Sie Ihre Log-Dateien Groß, selbst so Groß wie den Puffer-Pool.
Wenn InnoDB seine Log-Dateien vollgeschrieben hat, muss es die veränderten
Inhalte des Puffer-Pools in einem Checkpoint auf Platte schreiben. Kleine
Log-Dateien verursachen daher unnötige Festplatten-Schreibzugriffe. Der
Nachteil großer Log-Dateien liegt darin, dass die Wiederherstellungszeit
länger wird.
5.
Ausserdem sollte der Log-Puffer recht Groß sein, sagen wir 8 MB.
6. (Relevant from 3.23.39 up.)
In einigen Versionen von Linux und Unix ist das Zurückschreiben von Dateien
auf Platte (flush) mit dem Unix-fdatasync und anderen ähnlichen
Methoden überraschend langsam. InnoDB benutzt vorgabemäßig die
fdatasync-Funktion. Wenn Sie mit der Datenbank-Schreib-Performance
nicht zufrieden sind, können Sie versuchen, die innodb_flush_method
in `my.cnf' auf O_DSYNC zu setzen, obwohl O_DSYNC auf den
meisten Systemen langsamer zu sein scheint.
7. Wenn Sie Daten in InnoDB importieren, stellen Sie sicher, dass
MySQL autocommit=1 nicht angeschaltet hat, denn dann benötigt jedes
Einfügen ein Zurückschreiben des Logs auf Platte (flush). Setzen Sie vor
Ihre SQL-Importdatei die Zeile
set autocommit=0;
und danach
commit;
Wenn Sie die `mysqldump'-Option --opt benutzen, erhalten Sie
Dump-Dateien, die sich sehr schnell auch in eine InnoDB-Tabelle importieren
lassen, selbst ohne sie in die oben erwähnten set autocommit=0; ...
commit;-Wrapper zu verpacken.
8.
Hüten Sie sich vor großen Rollbacks beim Einfügen von Massendaten: InnoDB
benutzt den Einfüge-Puffer, um beim Einfügen Festplatten-Ein- und -Ausgaben
zu sparen, doch beim entsprechenden Rollback wird kein solcher Mechanismus
benutzt. Ein Festplatten-gebundenes Rollback kann die 30-fache Zeit des
entsprechenden Einfügevorgangs in Anspruch nehmen. Es hilft nicht, den
Datenbankprozess zu killen, weil der Rollback erneut starten wird, wenn die
Datenbank hochfährt. Die einzige Möglichkeit, ein aus dem Ruder gelaufenes
Rollback loszuwerden, besteht darin, den Puffer-Pool zu erhöhen, so dass
das Rollback CPU-gebunden wird und damit schnell läuft, oder indem die
gesamte InnoDB-Datenbank gelöscht wird.
9.
Seien Sie auch vor anderen großen Festplatten-gebundenen Operationen auf
der Hut. Benutzen Sie DROP TABLE oder TRUNCATE (ab
MySQL-4.0), um eine Tabelle zu löschen, nicht DELETE FROM tabelle.
10.
Benutzen Sie das mehrzeilige INSERT, um den Kommunikations-Overhead
zwischen Client und Server zu verringern, wenn Sie viele Zeilen einfügen
müssen:
INSERT INTO tabelle VALUES (1, 2), (5, 5);
Dieser Tipp gilt natürlich für jeden Tabellentyp, nicht nur für InnoDB.
Ab Version 3.23.41 beinhaltet InnoDB den InnoDB-Monitor, der Informationen
über den internen Zustand von InnoDB ausgibt. Wenn er angeschaltet ist,
veranlasst der InnoDB-Monitor den MySQL-Server `mysqld', etwa alle 15
Sekunden Daten an die Standardausgabe auszugeben (Hinweis: der MySQL-Client
gibt nichts aus). Diese Daten sind nützlich, um die Performance zu tunen.
Unter Windows müssen Sie mysqld-max von einer DOS-Kommandozeile aus
mit --standalone --console starten, um die Ausgabe auf das
DOS-Fenster umzuleiten.
Es gibt einen separaten innodb_lock_monitor, der dieselben
Informationen ausgibt wie innodb_monitor, aber zusätzlich
Informationen über Sperren, die durch jede Transaktion gesetzt werden.
Die ausgegebene Information enthält Daten über:
-
Sperren, die auf eine Transaktion warten,
-
Semaphore, die auf Threads warten,
-
anhängige Datei-Ein- und -Ausgabeanforderungen,
-
Puffer-Pool-Statistiken und
-
Bereinigungs- (purge) und Einfüge-Puffer-Vermengungs- (merge) Aktivität des
Haupt-Threads von InnoDB.
Sie können den InnoDB-Monitor mit folgendem SQL-Befehl starten:
CREATE TABLE innodb_monitor(a int) type = innodb;
Und ihn mit folgendem Befehl anhalten:
DROP TABLE innodb_monitor;
Die CREATE TABLE-Syntax ist nur eine Möglichkeit, einen Befehl durch
den MySQL-SQL-Parser an die InnoDB-Engine durchzureichen. Wenn Sie die
Datenbank herunter fahren, während der Monitor läuft, und Sie den Monitor
erneut starten wollen, müssen Sie die Tabelle löschen, bevor Sie ein
erneutes CREATE TABLE absetzen können, um den Monitor zu starten.
Diese Syntax wird sich in zukünftigen Releases möglicherweise ändern.
Beispiel für die Ausgabe des InnoDB-Monitors:
================================
010809 18:45:06 INNODB MONITOR OUTPUT
================================
--------------------------
LOCKS HELD BY transactions
--------------------------
LOCK INFO:
Number of locks in the record hash table 1294
LOCKS FOR TRANSACTION ID 0 579342744
TABLE LOCK table test/tabelle trx id 0 582333343 lock_mode IX
RECORD LOCKS space id 0 page no 12758 n bits 104 table test/tabelle index
PRIMARY trx id 0 582333343 lock_mode X
Record lock, heap no 2 PHYSICAL RECORD: n_fields 74; 1-byte offs FALSE;
info bits 0
0: len 4; hex 0001a801; asc ;; 1: len 6; hex 000022b5b39f; asc ";; 2: len 7;
hex 000002001e03ec; asc ;; 3: len 4; hex 00000001;
...
-----------------------------------------------
CURRENT SEMAPHORES RESERVED AND SEMAPHORE WAITS
-----------------------------------------------
SYNC INFO:
Sorry, cannot give mutex list info in non-debug version!
Sorry, cannot give rw-lock list info in non-debug version!
-----------------------------------------------------
SYNC ARRAY INFO: reservation count 6041054, signal count 2913432
4a239430 waited for by thread 49627477 op. S-LOCK file NOT KNOWN line 0
Mut ex 0 sp 5530989 r 62038708 sys 2155035; rws 0 8257574 8025336; rwx 0 1121090 1848344
-----------------------------------------------------
CURRENT PENDING FILE I/O'S
--------------------------
Pending normal aio reads:
Reserved slot, messages 40157658 4a4a40b8
Reserved slot, messages 40157658 4a477e28
...
Reserved slot, messages 40157658 4a4424a8
Reserved slot, messages 40157658 4a39ea38
Total of 36 reserved aio slots
Pending aio writes:
Total of 0 reserved aio slots
Pending insert buffer aio reads:
Total of 0 reserved aio slots
Pending log writes or reads:
Reserved slot, messages 40158c98 40157f98
Total of 1 reserved aio slots
Pending synchronous reads or writes:
Total of 0 reserved aio slots
-----------
BUFFER POOL
-----------
LRU list length 8034
Free list length 0
Flush list length 999
Buffer pool size in pages 8192
Pending reads 39
Pending writes: LRU 0, flush list 0, single page 0
Pages read 31383918, created 51310, written 2985115
----------------------------
END OF INNODB MONITOR OUTPUT
============================
010809 18:45:22 InnoDB starts purge
010809 18:45:22 InnoDB purged 0 pages
Einige Anmerkungen zur Ausgabe:
-
Wenn der Abschnitt
LOCKS HELD BY transactions warten auf Sperren
berichtet, kann es sein, dass Ihre Applikation Sperr-Konflikte hat. Die
Ausgabe kann auch helfen, Gründe für Transaktions-Blockierungen
aufzuspüren.
-
Der Abschnitt
SYNC INFO berichtet reservierte Semaphore, wenn Sie
InnoDB mit UNIV_SYNC_DEBUG kompilieren, definiert in `univ.i'.
-
Der Abschnitt
SYNC ARRAY INFO berichtet Threads, die auf ein
Semaphor warten, und Statistiken, wie viele Male Threads ein Spin oder ein
Warten auf einem Mutex oder einem Lese-/Schreibe-Sperr-Semaphor benötigten.
Eine große Anzahl auf Semaphore wartender Threads kann ein Ergebnis von
Festplatten-Ein- und -Ausgaben oder Konfliktproblemen innerhalb von InnoDB
sein. Konflikte können durch starke Parallelen von Anfragen oder durch
Probleme des Betriebssystems beim Thread Scheduling hervorgerufen werden.
-
Der Abschnitt
CURRENT PENDING FILE I/O'S listet anhängige Datei-Ein-
und -Ausgabeanforderungen auf. Eine große Anzahl davon zeigt an, dass die
Auslastung Festplatten-Ein- und -Ausgabe-gebunden ist.
-
Der Abschnitt
BUFFER POOL gibt statistische Informationen über
gelesene und geschriebene Seiten. Aus diesen Zahlen können Sie errechnen,
wie viele Daten-Datei-Ein- und Ausgaben Ihre Anfragen aktuell durchführen.
Weil InnoDB eine multiversionierte Datenbank ist, muss es Informationen
über alte Versionen von Zeilen im Tabellenplatz (Tablespace) aufbewahren.
Diese Informationen werden in einer Datenstruktur gespeichert, die wir in
Anlehnung an eine analoge Struktur in Oracle Rollback-Segment nennen.
InnoDB fügt jeder Zeile, die in der Datenbank gespeichert wird, intern zwei
Felder hinzu. Ein 6 Byte großes Feld enthält den
Transaktions-Identifikator der letzten Transaktion, die die Zeile eingefügt
oder aktualisiert hat. Ein Löschen wir intern als eine Aktualisierung
behandelt, wobei ein spezielles Bit in die Zeile eingefügt wird, um sie als
gelöscht zu markieren. Jede Zeile enthält ausserdem ein 7 Byte großes
Feld, das Roll-Zeiger genannt wird. Der Roll-Zeiger zeigt auf einen
Rückgängig-Log-Datensatz, der in das Rollback-Segment geschrieben wird.
Wenn die Zeile aktualisiert wurde, enthält der Rückgängig-Log-Datensatz die
Informationen, die notwendig sind, um den Inhalt der Zeile wieder
herzustellen, bevor sie aktualisiert wurde.
InnoDB benutzt die Informationen im Rollback-Segment, um die
Rückgängig-Operationen durchzuführen, die bei einem Transaktions-Rollback
notwendig sind. Diese Informationen benutzt es auch dafür, um frühere
Informationen einer Zeile beim Konsistenten Lesen aufzubauen.
Rückgängig-Logs im Rollback-Segment lassen sich in Logs für Einfügen und
für Aktualisieren unterteilen. Einfüge-Rückgängig-Logs werden nur für
Transaktions-Rollbacks benötigt und können verworfen werden, sobald die
Transaktion abgeschickt ist (commit). Aktualisierungs-Rückgängig-Logs
werden auch für Konsistentes Lesens benutzt und können daher erst verworfen
werden, wenn keine Transaktion mehr vorhanden ist, für die InnoDB einen
Schnappschuss zugewiesen hat, dessen Informationen beim Konsistenten Lesen
benötigt werden könnten, um daraus eine frühere Version der Datenbank-Zeile
aufzubauen.
Sie müssen daran denken, Ihre Transaktionen regelmäßig abzuschicken
(commit), auch die Transaktionen, die nur Konsistentes Lesens ausführen.
Ansonsten kann InnoDB Daten aus dem Aktualisierungs-Rückgängig-Log nicht
verwerfen und das Rollback-Segment könnte zu Groß werden und Ihren
Tabellenplatz (Tablespace) komplett füllen.
Die physikalische Größe eines Rückgängig-Log-Datensatzes im
Rollback-Segment ist typischerweise kleiner als die entsprechende
eingefügte oder aktualisierte Zeile. Sie können diese Informationen
benutzen, um den Platzbedarf für Ihr Rollback-Segment zu berechnen.
In diesem multiversionierten Schema wird eine Zeile nicht unmittelbar
physikalisch aus der Datenbank entfernt, wenn Sie sie mit einem
SQL-Statement löschen. Erst wenn InnoDB den Datensatz des
Aktualisierungs-Rückgängig-Logs löschen kann, der für das Löschen
geschrieben wurde, kann es die entsprechende Zeile und ihre
Index-Datensätze auch physikalisch aus der Datenbank entfernen. Diese
Entfernungsoperation wird Purge genannt und ist recht schnell, wobei sie
überschlägig dieselbe Zeit benötigt wie das SQL-Statement, das das Löschen
ausführte.
MySQL speichert seine Daten-Wörterbuch-Informationen über Tabellen in
`.frm'-Dateien in den Datenbank-Verzeichnissen. Jedoch hat auch jede
Tabelle vom Typ InnoDB ihren eigenen Eintrag, in InnoDB-internen
Daten-Wörterbüchern innerhalb des Tabellenplatzes (Tablespace). Wenn MySQL
eine Tabelle oder Datenbank löscht, muss er sowohl eine oder mehrere
`.frm'-Datei(en) als auch die entsprechenden Einträge im
InnoDB-Daten-Wörterbuch löschen. Das ist der Grund, warum Sie
InnoDB-Tabellen nicht einfach zwischen Datenbanken verschieben können,
indem Sie die `.frm'-Dateien verschieben und warum DROP
DATABASE bei InnoDB-Tabellen in MySQL-Versionen bis 3.23.43 nicht
funktionierte.
Jede InnoDB-Tabelle hat einen speziellen Index, der Cluster-Index genannt
wird, in dem die Daten der Zeilen gespeichert sind. Wenn Sie auf Ihre
Tabelle einen PRIMARY KEY definieren, ist der Index des
Primärschlüssels der Cluster-Index.
Wenn Sie für Ihre Tabelle keinen Primärschlüssel definieren, erzeugt InnoDB
intern einen Cluster-Index, bei dem die Zeilen nach der Zeilen-Kennung (ID)
geordnet sind, die InnoDB Zeilen in einer solchen Tabelle zuweist. Die
Zeilen-Kennung ist ein 6 Byte großes Feld, das monoton erhöht wird, wenn
neue Zeilen eingefügt werden. Daher liegen nach der Zeilen-Kennung
geordnete Zeile physikalisch in der Einfüge-Reihenfolge vor.
Der Zugriff auf eine Zeile über den Cluster-Index ist schnell, weil die
Zeilendaten auf derselben Seite sind, auf die die Index-Suche führt. In
vielen Datenbanken werden die Daten traditionell auf einer anderen Seite
als derjenigen, wo sich der Index-Datensatz befindet, gespeichert. Wenn die
Tabelle Groß ist, spart die Cluster-Index-Architektur im Vergleich zur
traditionellen Lösung auf Festplatten-Ein- und -Ausgaben.
In InnoDB enthalten die Datensätze in Nicht-Cluster-Indexen (die wir auch
sekundäre Indexe nennen) den Primärschlüsselwert für die Zeile. InnoDB
benutzt diesen Primärschlüsselwert, um vom Cluster-Index aus nach der Zeile
zu suchen. Beachten Sie, dass die sekundären Indexe mehr Platz benötigen,
wenn der Primärschlüssel lang ist.
Alle Indexe in InnoDB sind B-Bäume, in denen die Index-Datensätze in den
Blätter-Seiten des Baums gespeichert sind. Die vorgabemäßige Größe einer
Index-Seite ist 16 KB. Wenn neue Datensätze eingefügt werden, versucht
InnoDB, 1/16 der Seite für zukünftige Einfügungen und Aktualisierungen des
Index-Datensatzes freizuhalten.
Wenn Index-Datensätze in sequentieller (aufsteigender oder absteigender)
Reihenfolge eingefügt werden, sind die resultierenden Index-Seiten ungefähr
zu 15/16 gefüllt. Wenn der Füllfaktor einer Index-Seite unter 1/12 fällt,
versucht InnoDB, den Index-Baum zusammenzuziehen, um die Seite
freizugeben.
Häufig wird der Primärschlüssel in Datenbank-Applikationen als eindeutiger
Identifizierer benutzt und neue Zeilen in aufsteigender Reihenfolge des
Primärschlüssels eingefügt. Daher erfordern Einfügungen in den
Cluster-Index keine wahlfreien (random) Lesezugriffe auf die Platte.
Sekundäre Indexe auf der anderen Seite sind üblicherweise nicht eindeutig
und Einfügungen in sekundäre Indexe erfolgen in einer relativ wahlfreien
Reihenfolge. Wenn InnoDB keinen speziellen Mechanismus hierfür benutzen
würde, würden diese viele wahlfreie Festplatten-Ein- und -Ausgaben
verursachen.
Wenn ein Index-Datensatz in einen nicht eindeutigen sekundären Index
eingefügt werden soll, prüft InnoDB, ob die sekundäre Index-Seite bereits
im Puffer-Pool ist. Wenn das der Fall ist, führt InnoDB das Einfügen direkt
in die Index-Seite durch. Wenn die Index-Seite aber nicht im Puffer-Pool
gefunden wird, fügt InnoDB den Datensatz in eine spezielle
Einfüge-Puffer-Struktur ein. Der Einfüge-Puffer wird so klein gehalten,
dass er komplett in den Puffer-Pool passt, so dass Einfügungen sehr schnell
durchgeführt werden können.
Der Einfüge-Puffer wird periodisch mit den sekundären Index-Bäumen in der
Datenbank vermengt. Oft können mehrere Einfügeoperationen auf derselben
Seite im Index-Baum zusammengefasst werden, so dass Festplatten-Ein- und
-Ausgaben eingespart werden. Messungen ergaben, dass der Einfüge-Puffer
Einfügungen in eine Tabelle bis zu 15 mal schneller machen kann.
Wenn eine Datenbank fast komplette in den Hauptspeicher passt, können
Anfragen am schnellsten unter Verwendung von Hash-Indexen ausgeführt
werden. InnoDB hat einen automatischen Mechanismus, der Index-Suchen
beobachtet, die auf den Indexen durchgeführt werden, die für eine Tabelle
definiert wurden. Wenn InnoDB bemerkt, dass Anfragen vom Aufbauen eines
Hash-Indexes profitieren könnten, wird ein solcher Index automatisch
aufgebaut.
Beachten Sie aber, dass der Hash-Index immer auf der Grundlage eines
bestehenden B-Baum-Indexes auf die Tabelle aufgebaut wird. InnoDB kann
einen Hash-Index auf einem Präfix beliebiger Länge des Schlüssels aufbauen,
der für den B-Baum definiert wurde, abhängig vom Suchmuster, das InnoDB auf
dem Index-Baum beobachtet. Ein Hash-Index kann partiell sein: Es ist nicht
erforderlich, dass der gesamte Index-Baum im Puffer-Pool
zwischengespeichert ist. InnoDB baut Hash-Indexe bei Bedarf automatisch für
die Index-Seiten auf, auf die oft zugegriffen wird.
In gewisser Hinsicht kommt InnoDB durch den anpassungsfähigen
Hash-Index-Mechanismus (wobei sich InnoDB üppig verfügbarem Hauptspeicher
anpasst) der Architektur von Hauptspeicher-Datenbanken nahe.
-
Jeder Index-Datensatz in InnoDB enthält einen Header von 6 Bytes. Der
Header wird benutzt, um nachfolgende Datensätze zu verknüpfen, sowie beim
Sperren auf Zeilenebene.
-
Datensätze im Cluster-Index enthalten Felder für alle benutzerdefinierten
Spalten. Zusätzlich gibt es ein 6 Byte großes Feld für die
Transaktions-Kennung und ein 7 Byte großes Feld für den Roll-Zeiger.
-
Wenn der Benutzer keinen Primärschlüssel für eine Tabelle definiert hat,
enthält jeder Cluster-Index-Datensatz zusätzlich ein 6 Byte großes
Zeilenkennungsfeld.
-
Jeder sekundäre Index-Datensatz enthält auch alle Felder, die für den
Cluster-Index-Schlüssel definiert wurden.
-
Ein Datensatz enthält auch einen Zeiger zu jedem Feld des Datensatzes. Wenn
die Gesamtlänge des Feldes in einem Datensatz kleiner als 128 Bytes ist,
ist der Zeiger 1 Byte lang, ansonsten 2 Bytes.
Wenn der Benutzer nach einem Datenbankstart zuerst einen Datensatz in eine
Tabelle T einfügt, in der eine Auto-Increment-Spalte definiert
wurde, und er keinen expliziten Wert für die Spalte angibt, führt InnoDB
SELECT MAX(auto-inc-column) FROM T aus und weist den um 1
hochgezählten Wert der Spalte und dem Auto-Increment-Zähler der Tabelle zu.
Wir sagen dazu, dass der Auto-Increment-Zähler für Tabelle T
initialisiert wurde.
InnoDB führt dieselbe Prozedur der Initialisierung des
Auto-Increment-Zählers für eine frisch erzeugte Tabelle durch.
Wenn Sie für die Auto-Increment-Spalte einen Wert von 0 angeben, beachten
Sie, dass InnoDB die Zeile so behandelt, als hätten Sie den Wert nicht
angegeben.
Wenn nach der Initialisierung des Auto-Increment-Zählers der Benutzer eine
Zeile eingibt, in der er explizit den Spaltenwert angibt, und dieser
größer als der aktuelle Zählerwert ist, wird der Zähler auf den
angegebenen Spaltenwert gesetzt. Wenn der Benutzer nicht explizit einen
Wert angibt, zählt InnoDB den Zähler um 1 hoch und weist der Spalte diesen
neuen Wert zu.
Der Auto-Increment-Mechanismus umgeht beim Zuweisen von Werten vom Zähler
Sperren und Transaktionshandhabung. Daher können Lücken in der
Nummernfolge entstehen, wenn Sie Transaktionen zurückrollen (Rollback), die
Nummern vom Zähler erhalten haben.
Das Verhalten von Auto-Increment ist für die Fälle undefiniert, in denen
ein Benutzer der Spalte einen negativen Wert gibt oder wenn der Wert
größer als die größte Ganzzahl wird, die im festgelegten Ganzzahl-Typ
gespeichert werden kann.
Bei Festplatten-Ein- und -Ausgaben benutzt InnoDB asynchrone Ein- und
Ausgaben. Unter Windows NT benutzt es die nativen Ein- und Ausgaben, die
vom Betriebssystem zur Verfügung gestellt werden. Unter Unix benutzt InnoDB
simulierte asynchrone Ein- und Ausgaben, die in InnoDB eingebaut sind:
InnoDB erzeugt eine Reihe von Ein-/Ausgabe-Threads, die sich um Ein- und
Ausgabeoperationen kümmern, zum Beispiel Vorwärts-Lesen (Read-Ahead).
Zukünftig werden wir auch für Windows NT simulierte Ein-/Ausgaben
unterstützen sowie für die Unix-Versionen, die so etwas besitzen, native
Ein-/Ausgaben.
Unter Windows NT benutzt InnoDB ungepufferte Ein- und Ausgaben. Das heißt,
dass die Festplatten-Seiten, die InnoDB liest oder schreibt, nicht im
Datei-Cache des Betriebssystems gepuffert werden. Das spart einiges an
Arbeitsspeicher-Bandbreite.
Ab Version 3.23.41 benutzt InnoDB eine neuartige Datei-Flush-Technik, die
Doublewrite heißt. Sie erhöht die Sicherheit bei Reparaturen nach Absturz,
wenn ein Betriebssystemabsturz oder ein Stromausfall aufgetreten sind, und
verbessert auf den meisten Unix-Versionen die Performance, indem die
Notwendigkeit von Fsync-Operationen verringert wird.
Doublewrite bedeutet, dass InnoDB zuerst in einen zusammenhängenden
Tabellenplatz (Tablespace) namens Doublewrite-Puffer schreibt, bevor Seiten
in eine Daten-Datei geschrieben werden. Erst nachdem das Schreiben und
Zurückschreiben (Flush) in den Doublewrite-Puffer fertig sind, schreibt
InnoDB die Seiten an ihre korrekten Positionen in der Daten-Datei. Wenn das
Betriebssystem mitten in einem Seiten-Schreiben abstürzt, findet InnoDB bei
der Wiederherstellung eine gute Kopie der Seite im Doublewrite-Puffer.
Ab Version 3.23.41 können Sie auch eine Raw-Disk-Partition als Daten-Datei
benutzen, obwohl das bisher noch nicht getestet wurde. Wenn Sie eine neue
Daten-Datei erzeugen, müssen Sie das Schlüsselwort newraw
unmittelbar nach der Daten-Datei-Größe in innodb_data_file_path
angeben. Die Partition muss größer oder gleich der Größe sein, die Sie
angeben. Beachten Sie, dass in InnoDB 1 MB 1024 x 1024 Bytes ist, während 1
MB in Festplatten-Spezifikationen üblicherweise 1.000.000 Bytes bedeutet.
innodb_data_file_path=hdd1:5Gnewraw;hdd2:2Gnewraw
Wenn Sie die Datenbank wieder starten, müssen -sue das
Schlüsselwort in raw ändern. Ansonsten schreibt InnoDB über Ihre
Partition!
innodb_data_file_path=hdd1:5Graw;hdd2:2Graw
Wenn Sie Raw-Disk benutzen, können Sie unter einigen Unixen ungepufferte
Ein- und Ausgaben ausführen.
Es gibt zwei Vorwärts-Lesen-(Read-Ahead-)Heuristiken in InnoDB:
sequentielles Vorwärts-Lesen und wahlfreies (random) Vorwärts-Lesen. Beim
sequentiellen Vorwärts-Lesen bemerkt InnoDB, dass das Zugriffsschema auf
ein Segment im Tabellenplatz (Tablespace) sequentiell ist. InnoDB schickt
dann vorab einen Stapel von Lesevorgängen von Datenbankseiten an das
Ein-/Ausgabesystem. Beim wahlfreien Vorwärts-Lesen bemerkt InnoDB, dass ein
bestimmter Bereich im Tabellenplatz (Tablespace) im Zustand des vollständig
Eingelesenwerdens in den Puffer-Pool zu sein scheint. Dann schickt InnoDB
die verbleibenden Lesevorgänge an das Ein-/Ausgabesystem.
Die Daten-Dateien, die Sie in der Konfigurationsdatei definieren, formen
den Tabellenplatz (Tablespace) von InnoDB. Die Dateien werden einfach
verkettet, um den Tabellenplatz (Tablespace) zu formen, es wird kein
Striping benutzt. Momentan können Sie nicht direkt angeben, wo der Platz
für Ihre Tabellen zugewiesen werden soll, ausser wenn Sie folgende Tatsache
benutzen: InnoDB weist Speicherplatz von einem neu erzeugten Tabellenplatz
(Tablespace) vom niedrigen Ende ausgehend zu.
Der Tabellenplatz (Tablespace) besteht aus Datenbankseiten, deren
vorgabemäßige Größe 16 KB beträgt. Diese Seiten werden bis zu einer
Ausdehnung von 64 aufeinander folgenden Seiten gruppiert. Die 'Dateien'
innerhalb eines Tabellenplatzes (Tablespace) werden in InnoDB Segmente
genannt. Der Name des Rollback-Segments ist in gewisser Hinsicht
irreführend, weil dieses tatsächlich viele Segmente im Tabellenplatz
enthält.
Für jeden Index in InnoDB werden zwei Segmente zugewiesen: eins für die
Nicht-Blätter-Knoten (Non-Leaf-Nodes) des B-Baum, das andere für die
Blätter-Knoten. Die Idee dahinter ist, für die Blätter-Knoten, die die
Daten enthalten, bessere Sequentialität zu erzielen.
Wenn ein Segment innerhalb des Tabellenplatzes anwächst, weist ihm InnoDB
die ersten 32 Seiten individuell zu. Danach fängt InnoDB an, dem Segment
ganze Ausdehnungen zuzuweisen. InnoDB kann einem großen Segment bis zu
vier Ausdehnungen auf einmal hinzufügen, um gute Sequentialität für die
Daten sicherzustellen.
Einige Seiten im Tabellenplatz enthalten Bitmaps anderer Seiten. Daher
können einige Ausdehnungen in einem InnoDB-Tabellenplatz (Tablespace) nicht
Segmenten als Ganzes zugewiesen werden, sondern nur als individuelle
Seiten.
Wenn Sie eine Anfrage SHOW TABLE STATUS FROM ... LIKE ... ausführen,
um den verfügbaren freien Platz im Tabellenplatz festzustellen, berichtet
InnoDB den Platz, der in völlig freien Ausdehnungen im Tabellenplatz sicher
benutzt werden kann. InnoDB reserviert immer einige Ausdehnungen für
Säuberungs- und interne Zwecke. Diese Ausdehnungen werden nicht in den
freien Platz einbezogen.
Wenn Sie Daten aus einer Tabelle löschen, zieht InnoDB die entsprechenden
B-Baum-Indexe zusammen. Es hängt vom Schema der Löschvorgänge ab, ob das
individuelle Seiten oder Ausdehnungen im Tabellenplatz freigibt, so dass
der freigegebene Platz anderen Benutzern zur Verfügung steht. Wenn eine
Tabelle gelöscht wird oder alle Zeilen aus ihr gelöscht werden, gibt das
garantiert Platz frei für andere Benutzer, aber denken Sie daran, dass
gelöschte Zeile physikalisch nur durch eine Purge-Operation entfernt werden
können, nachdem Sie nicht mehr für ein Transaktions-Rollback oder für
Konsistentes Lesen benötigt werden.
Wenn es wahlfreie (random) Einfüge- oder Löschvorgänge in die Indexe einer
Tabelle gibt, können die Indexe fragmentiert werden. Unter Fragmentierung
verstehen wird, dass die physikalische Reihenfolge der Index-Seiten auf der
Platte der alphabetischen Reihenfolge der Datensätze auf den Seiten nicht
nahe kommt oder dass es viele unbenutzte Seiten in den 64-Seiten-Blöcken
gibt, die dem Index zugewiesen wurden.
Index-Scans können beschleunigt werden, wenn Sie von Zeit zu Zeit
mysqldump benutzen, um die Tabelle in eine Textdatei zu dumpen, dann
die Tabelle zu löschen und sie aus dem Dump neu aufzubauen. Eine weitere
Möglichkeit zur Defragmentierung besteht darin, den Tabellentyp in
MyISAM zu ändern (ALTER) und danach wieder in InnoDB
zurück. Beachten Sie, dass die MyISAM-Tabelle auf Ihrem
Betriebssystem in eine einzige Datei passen muss.
Wenn die Einfügungen in einen Index immer aufsteigend sind und Datensätze
nur vom Ende gelöscht werden, garantiert der
Speicherplatzverwaltungs-Algorithmus von InnoDB, dass keine Fragmentierung
im Index auftritt.
Die Fehlerbehandlung in InnoDB ist nicht immer so, wie es die
ANSI-SQL-Standards festlegen. Nach ANSI-Standard sollte jeder Fehler
während eines SQL-Statements ein Rollback des Statements verursachen.
InnoDB rollt manchmal nur Teile des Statements oder auch die gesamte
Transaktion zurück. Folgende Liste gibt die Fehlerbehandlung von InnoDB an:
-
Wenn es keinen Speicherplatz mehr im Tabellenplatz (Tablespace) gibt,
bekommen Sie den MySQL-Fehler
'Table is full' und InnoDB rollt das
SQL-Statement zurück.
-
Eine Transaktions-Blockierung oder eine Zeitüberschreitung beim Warten auf
eine Sperre führen dazu, dass InnoDB die gesamte Transaktion zurückrollt.
-
Ein Fehler wegen doppelter Schlüsseleinträge rollt das Einfügen dieser
Zeile zurück, selbst in einem Statement wie
INSERT INTO ... SELECT
.... Das wird sich voraussichtlich ändern, so dass das SQL-Statement
zurückgerollt wird, wenn Sie die IGNORE-Option in Ihrem Statement
nicht angegeben haben.
-
Ein Fehler 'row too long' rollt das SQL-Statement zurück.
-
Andere Fehler werden zumeist durch die MySQL-Code-Ebene entdeckt und rollen
das entsprechende SQL-Statement zurück.
-
ACHTUNG: Konvertieren Sie KEINE MySQL-Systemtabellen von
MyISAM in InnoDB-Tabellen! Das wird nicht unterstützt. Wenn Sie es dennoch
tun, startet MySQL nicht mehr, bis Sie die alten Systemtabellen aus einer
Datensicherung wiederhergestellt haben oder sie mit dem
mysql_install_db-Skript neu erzeugen.
-
SHOW TABLE STATUS gibt keine genauen Statistiken über
InnoDB-Tabellen, ausser über die physikalische Größe, die durch die
Tabelle reserviert wird. Der Zeilenzähler ist nur eine grobe Schätzung, die
bei der SQL-Optimierung benutzt wird.
-
Wenn Sie versuchen, einen eindeutigen Index auf ein Präfix einer Spalte zu
erzeugen, erhalten Sie einen Fehler:
CREATE TABLE T (A CHAR(20), B INT, UNIQUE (A(5))) TYPE = InnoDB;
Wenn Sie einen nicht eindeutigen Index auf ein Spaltenpräfix erzeugen,
erzeugt InnoDB einen Index über die gesamte Spalte.
-
INSERT DELAYED wird für InnoDB-Tabellen nicht unterstützt.
-
Die MySQL-
LOCK TABLES-Operation weiß nichts von InnoDB-Sperren auf
Zeilenebene, die in bereits fertigen SQL-Statements gesetzt sind. Das
bedeutet, dass Sie eine Tabellensperre auf eine Tabelle selbst dann
erhalten können, wenn es noch Transaktionen anderer Benutzer gibt, die
Sperren auf Zeilenebene auf dieselbe Tabelle haben. Daher kann es sein,
dass Ihre Operationen auf die Tabelle warten müssen, wenn sie mit diesen
Sperren anderer Benutzer kollidieren. Auch eine Blockierung ist möglich.
Dennoch gefährdet das nicht die Transaktionsintegrität, weil sich die
Sperren auf Zeilenebene, die InnoDB setzt, um die Integrität kümmern.
Zusätzlich hindert eine Tabellensperren andere Transaktionen daran, weitere
Sperren auf Zeilenebene (in einem konfliktbehafteten Sperrmodus) auf die
Tabelle zu erlangen.
-
Sie können keinen Schlüssel auf eine
BLOB- oder TEXT-Spalte
setzen.
-
Eine Tabelle kann nicht mehr als 1.000 Spalten enthalten.
-
DELETE FROM TABLE erzeugt die Tabelle nicht neu, sondern löscht
statt dessen alle Zeilen, eine nach der anderen, was nicht sehr schnell
ist. In zukünftigen MySQL-Versionen können Sie TRUNCATE benutzen,
was schnell ist.
-
Die vorgabemäßige Datenbank-Seitengröße in InnoDB beträgt 16 KB. Indem
Sie den Code neu kompilieren, können Sie sie auf Werte zwischen 8 KB und 64
KB setzen. Die maximale Zeilenlänge beträgt etwas weniger als die Hälfte
der Datenbank-Seite in den InnoDB-Versionen kleiner oder gleich 3.23.40. Ab
Quelldistribution 3.23.41 dürfen BLOB- und TEXT-Spalten bis zu 4 GB Groß
sein, die gesamte Zeilenlänge kann auch < 4 GB betragen. InnoDB speichert
Felder, deren Größe kleiner oder gleich 128 Bytes beträgt, nicht auf
separaten Seiten. Nachdem InnoDB die Zeile geändert hat, indem lange Felder
auf separaten Seiten gespeichert werden, muss die restliche Zeilenlänge
weniger als die Hälfte einer Datenbank-Seite betragen. Die maximale
Schlüssellänge beträgt 7.000 Bytes.
-
Auf einigen Betriebssystemen müssen Daten-Dateien kleiner als 2 GB sein.
Die Gesamtgröße der Log-Dateien muss auf 32-Bit-Computern kleiner als 4 GB
sein.
-
Die maximale Größe des Tabellenplatzes (Tablespace) beträgt 4 Milliarden
Datenbank-Seiten. Das ist auch die maximale Größe für eine Tabelle. Die
minimale Größe des Tabellenplatzes (Tablespace) beträgt 10 MB.
Kontaktinformationen von Innobase Oy, Hersteller der InnoDB-Engine:
Website: http://www.innodb.com/.
E-Mail: Heikki.Tuuri@innodb.com
Telefon: 358-9-6969 3250 (Büro) 358-40-5617367 (mobil)
Innobase Oy Inc.
World Trade Center Helsinki
Aleksanterinkatu 17
P.O.Box 800
00101 Helsinki
Finnland
Unterstützung für BDB-Tabellen ist in der MySQL-Quelldistribution seit
Version 3.23.34 enthalten und in der MySQL-Max-Binärdistribution aktiviert.
BerkeleyDB, erhältlich unter http://www.sleepycat.com/, stattet
MySQL mit einem transaktionalen Tabellen-Handler aus. Wenn Sie
BerkeleyDB-Tabellen benutzen, haben Ihre Tabellen eine höhere Chance,
Abstürze zu überleben. Zusätzlich stehen COMMIT und ROLLBACK
für Transaktionen zur Verfügung. Die MySQL-Quelldistribution enthält eine
BDB-Distribution, die eine Reihe kleiner Patches hat, damit sie glatter mit
MySQL zusammen arbeitet. Sie können keine nicht gepatchte
BDB-Version für MySQL verwenden.
Wir bei MySQL AB arbeiten in enger Kooperation mit Sleepycat, um die hohe
Qualität der MySQL-/BDB-Schnittstelle zu halten.
Was den Support für BDB-Tabellen angeht, sehen wir uns in der Pflicht,
unseren Benutzern zu helfen, Probleme zu lokalisieren und Ihnen zu helfen,
einen reproduzierbaren Testfall für jegliche Probleme mit BDB-Tabellen zu
erstellen. Solche ein Fall wird an Sleepycat weiter geleitet, die sich dann
an uns wenden, um uns zu helfen, das Problem zu finden und zu beheben. Weil
das also in zwei Schritten abläuft, kann es bei jeglichen Problemen mit
BDB-Tabellen etwas länger dauern, diese zu lösen, als das bei anderen
Tabellen-Handlern der Fall ist. Weil jedoch der BerkeleyDB-Code selbst auch
von vielen sonstigen Applikationen benutzt wird, sind hierbei keine großen
Probleme zu erwarten. See section 2.4.1 Support den MySQL AB anbietet.
Wenn Sie eine Binärdistribution von MySQL herunter geladen haben, die
Unterstützung für BerkeleyDB enthält, folgen Sie einfach den Anweisungen
zur Installation einer Binärversion von MySQL. See section 3.2.6 MySQL-Binärdistributionen, die von MySQL AB kompiliert wurden. See section 5.7.5 mysqld-max, ein erweiterter mysqld-Server.
Um MySQL mit BerkeleyDB-Unterstützung zu kompilieren, laden Sie
MySQL-Version 3.23.34 oder neuer herunter und konfigurieren Sie
MySQL mit der --with-berkeley-db-Option.
See section 3.3 Installation der Quelldistribution.
cd /pfad/zur/quelle/von/mysql-3.23.34
./configure --with-berkeley-db
Bitte sehen Sie wegen aktuellerer Informationen im Handbuch nach, das mit
der BDB-Distribution mitgeliefert wird.
Obwohl BerkeleyDB selbst sehr gut getestet und zuverlässig ist, wird die
MySQL-Schnittstelle noch als Beta-Qualität erachtet. Wir verbessern diese
aktiv und optimieren sie, um sie sehr bald stabil zu bekommen.
Wenn Sie mit AUTOCOMMIT=0 fahren, werden Ihre Änderungen in
BDB-Tabellen erst aktualisiert, wenn Sie COMMIT ausführen.
Statt dessen können Sie ROLLBACK ausführen, um Ihre Änderungen zu
verwerfen. See section 7.7.1 BEGIN/COMMIT/ROLLBACK-Syntax.
Wenn Sie mit AUTOCOMMIT=1 fahren (der Vorgabe), werden Ihre
Änderungen sofort abgeschickt. Sie können eine ausgedehnte Transaktion mit
dem SQL-Befehl BEGIN WORK starten. Danach werden Ihre Änderungen
solange nicht abgeschickt, bis Sie COMMIT ausführen (oder sich für
ROLLBACK entscheiden, um Ihre Änderungen zu verwerfen).
Folgende Optionen für mysqld können benutzt werden, um das Verhalten
von BDB-Tabellen zu ändern:
| Option | Beschreibung
|
--bdb-home=directory
| Base Verzeichnis für BDB-Tabellen. Das sollte dasselbe Verzeichnis sein, das Sie für --datadir benutzen.
|
--bdb-lock-detect=#
| Berkeley-Sperr-Erkennung. # steht für DEFAULT, OLDEST, RANDOM oder YOUNGEST.
|
--bdb-logdir=Verzeichnis
| BerkeleyDB-Log-Datei-Verzeichnis.
|
--bdb-no-sync
| Flush-Logs nicht synchronisieren.
|
--bdb-no-recover
| BerkeleyDB nicht im Wiederherstellungsmodus starten.
|
--bdb-shared-data
| BerkeleyDB im Multi-Prozess-Modus starten (DB_PRIVATE bei der Initialisierung von BerkeleyDB nicht verwenden).
|
--bdb-tmpdir=verzeichnis
| Name der temporären Datei von BerkeleyDB.
|
--skip-bdb
| BerkeleyDB nicht benutzen.
|
-O bdb_max_lock=1000
| Setzt die höchste Anzahl möglicher Sperren. See section 5.5.5.4 SHOW VARIABLES.
|
Wenn Sie --skip-bdb benutzen, initialisiert MySQL nicht die
BerkeleyDB-Bibliothek und spart deshalb viel Speicher. Natürlich können Sie
BDB-Tabellen nicht benutzen, wenn Sie diese Option verwenden.
Normalerweise sollten Sie mysqld ohne --bdb-no-recover
starten, wenn Sie vorhaben, BDB-Tabellen zu verwenden. Das kann allerdings
zu Problemen führen, wenn Sie mysqld starten und die BDB-Log-Dateien
beschädigt sind. See section 3.4.2 Probleme mit dem Start des MySQL-Servers.
Mit bdb_max_lock können Sie die maximale Anzahl von Sperren
festlegen (vorgabemäßig 10.000), die auf einer BDB-Tabelle aktiv sein
können. Sie sollten diesen Wert herauf setzen, wenn Sie Fehler vom Typ
bdb: Lock table is out of available locks oder Got error 12
from ... erhalten, wenn Sie lange Transaktionen ausführen oder wenn
mysqld viele Zeilen untersuchen muss, um die Anfrage zu berechnen.
Sie könnten auch binlog_cache_size und max_binlog_cache_size
ändern, wenn Sie große, vielzeilige Transaktionen benutzen. See section 7.7.1 BEGIN/COMMIT/ROLLBACK-Syntax.
-
Um Transaktionen zurückrollen zu können, unterhält BDB Log-Dateien. Um
maximale Performance zu erzielen, sollten Sie diese auf andere Festplatten
platzieren als Ihre Datenbanken, indem Sie die
--bdb_log_dir-Option
benutzen.
-
MySQL macht jedes Mal, wenn eine neue BDB-Log-Datei gestartet wird, einen
Checkpoint und entfernt alle Log-Dateien, die nicht für aktuelle
Transaktionen benötigt werden. Sie können auch jederzeit
FLUSH LOGS
laufen lassen, um einen Checkpoint für die BerkeleyDB-Tabellen anzulegen.
Für die Wiederherstellung nach Abstürzen sollten Sie Datensicherungen der
Tabellen plus das Binär-Log von MySQL benutzen. See section 5.4.1 Datenbank-Datensicherungen.
Achtung: Wenn Sie alte Log-Dateien löschen, die in Benutzung sind,
ist BDB nicht in der Lage, Wiederherstellungen durchzuführen, und Sie
könnten Daten verlieren, wenn etwas schief geht.
-
MySQL erfordert einen
PRIMARY KEY in jeder BDB-Tabelle, um auf
vorher gelesene Zeilen verweisen zu können. Wenn Sie keine Primärschlüssel
anlegen, erzeugt MySQL einen versteckten PRIMARY KEY. Der versteckte
Schlüssel hat eine Länge von 5 Bytes und wird bei jedem Einfügeversuch um 1
hochgezählt.
-
Wenn alle Spalten, auf die Sie in einer
BDB-Tabelle zugreifen, Teil
desselben Indexes oder Teil des Primärschlüssels sind, kann MySQL die
Anfrage ausführen, ohne auf die tatsächliche Zeile zugreifen zu müssen. Bei
einer MyISAM-Tabelle gilt das nur, wenn die Spalten Teil desselben
Indexes sind.
-
Der
PRIMARY KEY ist schneller als jeder andere Schlüssel, weil
PRIMARY KEY zusammen mit den Zeilendaten gespeichert wird. Weil die
anderen Schlüssel als Schlüsseldaten plus PRIMARY KEY gespeichert
werden, ist es wichtig, den PRIMARY KEY so kurz wie möglich zu
halten, um Plattenplatz zu sparen und bessere Geschwindigkeit zu erzielen.
-
LOCK TABLES funktioniert bei BDB-Tabellen wie bei anderen
Tabellen. Wenn Sie LOCK TABLE nicht benutzen, führt MySQL einer
interne mehrfache Schreibsperre auf die Tabelle aus, um sicherzustellen,
dass die Tabelle korrekt gesperrt ist, wenn ein anderer Thread eine
Tabellensperre ausführt.
-
Internes Sperren in
BDB-Tabellen wird auf Seitenebene durchgeführt.
-
SELECT COUNT(*) FROM tabelle ist langsam, weil BDB-Tabellen
keinen Zähler für die Anzahl der Zeilen in der Tabelle unterhalten.
-
Scannen ist langsamer als bei
MyISAM-Tabellen, weil Daten in
BDB-Tabellen in B-Bäumen und nicht in separaten Daten-Dateien gespeichert
werden.
-
Die Applikation muss stets darauf vorbereitet sein, Fälle zu handhaben, bei
denen jegliche Änderung einer
BDB-Tabelle zu einem automatischen
Rollback führen kann und jegliches Lesen fehlschlagen kann, weil ein
Blockierungsfehler auftritt.
-
Schlüssel werden nicht auf vorherige Schlüssel komprimiert, wie das bei
ISAM- und MyISAM-Tabellen der Fall ist. Mit anderen Worten benötigt die
Schlüsselinformation etwas mehr Platz bei
BDB-Tabellen im Vergleich
zu MyISAM-Tabellen, die nicht PACK_KEYS=0 benutzen.
-
Oft gibt es Löcher in der BDB-Tabelle, damit Sie neue Zeilen in der Mitte
des Schlüsselbaums einfügen können. Das macht BDB-Tabellen etwas größer
als MyISAM-Tabellen.
-
Der Optimierer muss näherungsweise die Anzahl von Zeilen in der Tabelle
kennen. MySQL löst dieses Problem, indem Einfügeoperationen gezählt werden,
und unterhält diese in einem separaten Segment in jeder BDB-Tabelle. Wenn
Sie nicht viele
DELETE oder ROLLBACK ausführen, sollte diese
Zahl ausreichend genau für den MySQL-Optimierer sein. Weil MySQL die Zahl
nur beim Schließen speichert, kann sie falsch sein, wenn MySQL unerwartet
stirbt. Das sollte kein schwerer Fehler sein, selbst wenn die Zahl nicht
100% korrekt ist. Man kann die Anzahl von Zeilen aktualisieren, indem man
ANALYZE TABLE oder OPTIMIZE TABLE ausführt.
See section 5.5.2 ANALYZE TABLE-Syntax. See section 5.5.1 OPTIMIZE TABLE-Syntax.
-
Wenn die Platte bei einer
BDB-Tabelle voll wird, erhalten Sie einen
Fehler (wahrscheinlich Fehler 28) und die Transaktion sollte zurückgerollt
werden. Das steht im Gegensatz zu MyISAM- and ISAM-Tabellen,
bei denen mysqld wartet, bis genug Plattenplatz frei ist, bevor
weiter gemacht wird.
-
Viele BDB-Tabellen zur gleichen Zeit öffnen ist sehr langsam. Wenn Sie
BDB-Tabellen benutzen wollen, sollten Sie einen sehr großen Tabellen-Cache
haben (evtl. größer als 256) und beim
mysql-Client
--no-auto-rehash benutzen. Das soll partiell in Version 4.0 behoben
werden.
-
SHOW TABLE STATUS gibt momentan noch nicht viele Informationen über
BDB-Tabellen aus.
-
Performance optimieren.
-
Es sollten überhaupt keine Seitensperren mehr benutzt werden, wenn Tabellen
gescannt werden.
Wenn Sie MySQL mit Unterstützung für BDB-Tabellen gebaut haben und
folgenden Fehler in der Log-Datei sehen, wenn Sie mysqld starten:
bdb: architecture lacks fast mutexes: applications cannot be threaded
Can't init databases
Bedeutet das, dass BDB-Tabellen für Ihre Architektur nicht
unterstützt werden. In diesem Fall müssen Sie MySQL erneut bauen, ohne
Unterstützung für BDB-Tabellen.
HINWEIS: Folgende Liste ist nicht komplett. Sie wird aktualisiert, sobald
wir mehr Informationen darüber haben.
Momentan wissen wir, dass BDB-Tabellen auf folgenden Betriebssystemen
laufen:
-
Linux 2.x intel
-
Solaris sparc
-
Caldera (SCO) OpenServer
-
Caldera (SCO) UnixWare 7.0.1
Auf folgenden Betriebssystemen läuft BDB nicht:
-
Wenn Sie folgenden Fehler in der
hostname.err-Log-Datei beim Start
von mysqld erhalten:
bdb: Ignoring log file: .../log.XXXXXXXXXX: unsupported log version #
Bedeutet das, dass die neue BDB-Version das alte Log-Dateiformat
nicht unterstützt. In diesem Fall müssen Sie alle BDB-Log-Dateien
aus Ihrem Datenbankverzeichnis löschen (die Dateien haben das Format
log.XXXXXXXXXX) und mysqld neu starten. Wir empfehlen
ausserdem, dass Sie mysqldump --opt auf Ihre alten
BDB-Tabellen ausführen, die alten Tabellen löschen und aus dem Dump
wiederherstellen.
-
Wenn Sie im
auto_commit-Modus fahren und eine Tabelle löschen, die
durch einen anderen Thread benutzt wird, erhalten Sie womöglich folgende
Fehlermeldungen in der MySQL-Fehlerdatei:
001119 23:43:56 bdb: Missing log fileid entry
001119 23:43:56 bdb: txn_abort: Log undo failed for LSN: 1 3644744: Invalid
Das ist kein schwerer Fehler, aber wir empfehlen, alle Tabellen zu löschen,
wenn Sie nicht im auto_commit-Modus sind, bis dieses Problem behoben
ist (die Behebung ist nicht trivial).
Go to the first, previous, next, last section, table of contents.
|