Dies ist eine Übersetzung des MySQL-Referenzhandbuchs, das sich auf dev.mysql.com befindet. Das ursprüngliche Referenzhandbuch ist auf Englisch, und diese Übersetzung ist nicht notwendigerweise so aktuell wie die englische Ausgabe. Das vorliegende deutschsprachige Handbuch behandelt MySQL bis zur Version 5.1.
Copyright 1997-2006 MySQL AB
Diese Dokumentation wird NICHT unter der GPL-Lizenz vertrieben. Die Benutzung dieser Dokumentation unterliegt folgenden Bedingungen: Sie dürfen diese Dokumentation ausschließich für private Zwecke ausdrucken. Eine Umwandlung in andere Formate ist gestattet, solange die ursprünglichen Inhalte nicht verändert oder in sonstiger Weise editiert werden. Sie dürfen diese Dokumentation weder veröffentlichen noch in sonstiger Form auf irgendeinem Medium vertreiben, außer wenn Sie die Dokumentation in ähnlicher Form wie MySQL selbst verteilen (das heißt elektronisch zum Download auf einer Website zusammen mit der Software) oder auf einer CD-ROM oder einem ähnlichen Medium, vorausgesetzt, dass die Dokumentation zusammen mit der Software auf diesem Medium verteilt wird. Jeder sonstige Gebrauch, beispielsweise die Verteilung gedruckter Exemplare, oder die Verwendung dieser Dokumentation in Gänze oder in Teilen in irgendeiner anderen Publikation bedarf der vorherigen schriftlichen Zustimmung eines dazu berechtigten Vertreters von MySQL AB. MySQL AB behält sich sämtliche Rechte an dieser Dokumentation vor, die nicht weiter oben ausdrücklich eingeräumt wurden.
Wenn Sie an weiteren Informationen interessiert sind oder eine
Übersetzung durchführen wollen, schreiben Sie bitte an
<docs@mysql.com>
.
Zusammenfassung
Das ist das MySQL-Referenzhandbuch. Es dokumentiert MySQL 5.1 bis 5.1.5-alpha.
Dokument erzeugt am: 2006-10-11 (revision: 349)
Inhaltsverzeichnis
mysql
im StapelbetriebAUTO_INCREMENT
Access denied
-FehlerSELECT
-Anweisungen und andere Anfragen optimierenEXPLAIN
-Syntax (Informationen über ein
SELECT
erhalten)SELECT
-AnweisungenWHERE
-KlauselIS NULL
-OptimierungDISTINCT
LEFT JOIN
und RIGHT
JOIN
ORDER BY
-OptimierungGROUP BY
-OptimierungLIMIT
-OptimierungINSERT
-AnweisungenUPDATE
-AnweisungenDELETE
-AnfragenMyISAM
-Schlüssel-CacheMyISAM
-IndexstatistikenCOLLATE
in SQL-AnweisungenCOLLATE
-KlauselnBINARY
-OperatorSELECT
- und
WHERE
-KlauselnGROUP
BY
-KlauselnCREATE
, DROP
,
ALTER
SELECT
, INSERT
,
UPDATE
, DELETE
MyISAM
-Speicher-EngineInnoDB
-TabellenInnoDB
: Startoptionen und SystemvariablenInnoDB
-Tabellen erzeugenInnoDB
-DatenbankInnoDB
-FehlerbehandlungInnoDB
-TabellenInnoDB
-TroubleshootingMERGE
-Speicher-EngineMEMORY
-Speicher-EngineBDB
-Speicher-EngineEXAMPLE
-Speicher-EngineFEDERATED
-Speicher-EngineARCHIVE
-Speicher-EngineCSV
-Speicher-EngineBLACKHOLE
-Speicher-EngineHandlerton
INSERT
-Unterstützung für Speicher-EnginesUPDATE
-Unterstützung für Speicher-EnginesDELETE
-Unterstützung für Speicher-EnginesCREATE TABLE
-Operationen
erhaltenindex_init()
index_end()
index_read()
index_read_idx()
index_next()
index_prev()
index_first()
index_last()
Geometry
Point
Curve
LineString
Surface
Polygon
GeometryCollection
MultiPoint
MultiCurve
MultiLineString
MultiSurface
MultiPolygon
Geometry
-FunktionenCREATE PROCEDURE
und CREATE
FUNCTION
ALTER PROCEDURE
und ALTER FUNCTION
DROP PROCEDURE
und DROP FUNCTION
CALL
-AnweisungBEGIN ... END
-Syntax für komplexe AnweisungenDECLARE
-AnweisungINFORMATION_SCHEMA
INFORMATION_SCHEMA SCHEMATA
INFORMATION_SCHEMA TABLES
INFORMATION_SCHEMA COLUMNS
INFORMATION_SCHEMA STATISTICS
INFORMATION_SCHEMA USER_PRIVILEGES
INFORMATION_SCHEMA SCHEMA_PRIVILEGES
INFORMATION_SCHEMA TABLE_PRIVILEGES
INFORMATION_SCHEMA COLUMN_PRIVILEGES
INFORMATION_SCHEMA CHARACTER_SETS
INFORMATION_SCHEMA COLLATIONS
INFORMATION_SCHEMA
COLLATION_CHARACTER_SET_APPLICABILITY
INFORMATION_SCHEMA TABLE_CONSTRAINTS
INFORMATION_SCHEMA KEY_COLUMN_USAGE
INFORMATION_SCHEMA ROUTINES
INFORMATION_SCHEMA VIEWS
INFORMATION_SCHEMA TRIGGERS
INFORMATION_SCHEMA PLUGINS
INFORMATION_SCHEMA ENGINES
INFORMATION_SCHEMA PARTITIONS
INFORMATION_SCHEMA EVENTS
INFORMATION_SCHEMA
-TabellenSHOW
-Anweisungenlibmysqld
kompilierenAccess denied
-FehlerCan't connect to [local] MySQL server
-FehlerClient does not support authentication protocol
Host '...' is blocked
-FehlerToo many connections
-FehlerNo free memory
-FehlerMySQL server has gone away
-FehlerPacket too large
-FehlerThe table is full
-FehlerCan't create/write to file
-FehlerCommand out of sync
-Fehler in ClientUser ignored
-FehlerTable 'xxx' doesn't exist
-FehlerCan't initialize charset xxx
-Fehler/tmp/mysql.sock
schützen oder ändernDATE
-SpaltenNULL
-Wertenalias
Abbildungsverzeichnis
Beispiele
DriverManager
erhaltenSELECT
-Anfrage ausführenConnection.prepareCall()
CallableStatement
-EingabeparameternAUTO_INCREMENT
-Spaltenwerte mit
Statement.getGeneratedKeys()
abrufenAUTO_INCREMENT
-Spaltenwerten mit
SELECT LAST_INSERT_ID()
AUTO_INCREMENT
column values in
Updatable ResultSets
Dieses Referenzhandbuch für das MySQL-Datenbanksystem behandelt die MySQL-Serie 5.1 bis Version 5.1.5-alpha. Wegen vieler funktionaler und sonstiger Unterschiede ist es nicht explizit für ältere (oder neuere) Versionen von MySQL-Software vorgesehen. Wenn Sie eine solche Version verwenden, schauen Sie bitte nach, ob es eine ältere oder neuere Übersetzung des Referenzhandbuchs gibt. Sollte das nicht der Fall sein, verwenden Sie bitte die englischsprachige Originalversion.
Die Namen beteiligter Personen sind unverändert aus dem englischen
Original entnommen. Bei Namen, die ursprünglich in kyrillischer
Schrift geschrieben sind, wurde ebenfalls die englische
Transkription verwendet. Der Grund für einen Verzicht auf deutsche
Transkription besteht darin, dass die Namen solcher Personen häufig
in Changeset-Kommentaren oder im Quelltext auftauchen. (Es gibt auch
ein „Osterei“, SHOW AUTHORS
, das die
Namen der MySQL-Entwickler auflistet.) Eine Übertragung in die
deutsche Schreibweise hätte die Nachvollziehbarkeit in dieser
Hinsicht erschwert.
Inhaltsverzeichnis
Die MySQL®-Software ist ein sehr schneller und robuster SQL-Datenbankserver (Structured Query Language, strukturierte Abfragesprache), der Multi-Threading und Mehrbenutzerbetrieb unterstützt. MySQL Server ist für unternehmenskritische Produktionssysteme mit hoher Beanspruchung ebenso vorgesehen wie für die Einbettung in Software, die flächendeckend eingesetzt wird. MySQL ist ein eingetragenes Warenzeichen von MySQL AB.
Die MySQL-Software ist dual lizenziert: Der Benutzer kann wählen, ob er die MySQL-Software als Open-Source-Produkt gemäß der GNU General Public License (http://www.fsf.org/licenses/) verwenden oder eine kommerzielle Standardlizenz bei MySQL AB erwerben will. Weitere Informationen zu unseren Lizenzierungsrichtlinien erhalten Sie unter http://www.mysql.com/company/legal/licensing/.
Die folgende Liste beschreibt einige wesentliche Abschnitte dieses Handbuchs:
Eine Beschreibung des Funktionsumfangs des MySQL-Datenbankservers finden Sie unter Abschnitt 1.4.2, „Die wichtigsten Features von MySQL“.
Informationen zur Installation finden Sie in Kapitel 2, Installation von MySQL.
Tipps zur Portierung der MySQL-Datenbanksoftware auf andere Architekturen oder Betriebssysteme finden Sie in Anhang E, Anmerkungen zur Portierung auf andere Systeme.
Informationen zur Aktualisierung von MySQL 5.0 auf MySQL 5.1 sind in Abschnitt 2.10.1, „Upgrade von MySQL 5.0“, beschrieben.
Ein einführendes Tutorial zum MySQL-Datenbankserver finden Sie in Kapitel 3, Einführung in MySQL: ein MySQL-Tutorial.
Informationen zu Benchmarks finden Sie im Benchmark-Verzeichnis
sql-bench
Ihrer MySQL-Distribution.
Eine Übersicht über neue Funktionen und Fehlerbehebungen (Bugfixes) finden Sie in Anhang D, MySQL-Änderungsverlauf (Change History).
Bekannte Fehler und Funktionsprobleme werden in Abschnitt A.8, „Bekannte Fehler und konzeptionelle Unzulänglichkeiten in MySQL“, beschrieben.
Abschnitt 1.6, „MySQL-Roadmap“, enthält eine Übersicht über zukünftige Vorhaben.
Eine Liste aller an diesem Projekt Mitwirkenden finden Sie in Anhang C, Danksagungen.
Wichtig:
Um Fehler (häufig auch als „Bugs“ bezeichnet) zu melden, besuchen Sie die Seite http://bugs.mysql.com. Siehe auch Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“.
Wenn Sie einen kritischen Sicherheitsfehler in MySQL Server
festgestellt haben, teilen Sie uns dies bitte umgehend via E-Mail an
<security@mysql.com>
mit.
Dies ist das Referenzhandbuch zum MySQL-Datenbanksystem, Version
5.1 bis einschließlich Release 5.1.5-alpha.
Aufgrund der zahlreichen funktionalen und auch sonstigen
Unterschiede zwischen MySQL 5.1 und vorherigen
Versionen ist dieses Handbuch nicht für die Verwendung mit
älteren Versionen der MySQL-Software vorgesehen. Wenn Sie ein
älteres Release der MySQL-Software verwenden, finden Sie weitere
Informationen im MySQL 5.0 Reference Manual,
wo die 5.0-Serie der MySQL-Releases behandelt wird,
oder im MySQL-Referenzhandbuch für die Versionen 3.23,
4.0 und 4.1, wo die Serien 3.23, 4.0 und 4.1 der
MySQL-Software beschrieben werden. Unterschiede zwischen den
Unterversionen von MySQL 5.1 sind unter Angabe der
Release-Nummern (5.1.x
) im
vorliegenden Text enthalten.
Da dieses Handbuch als Referenzhandbuch dient, finden Sie hier keine allgemeinen Hinweise zu SQL oder zu Konzepten relationaler Datenbanken. Ebenso wenig wird beschrieben, wie Sie Ihr Betriebssystem oder einen Befehlszeilen-Interpreter verwenden.
Die MySQL-Datenbanksoftware wird fortlaufend weiterentwickelt. Auch das Referenzhandbuch wird häufig aktualisiert. Die aktuelle Version des Handbuchs ist in durchsuchbarer Form online unter http://dev.mysql.com/doc/ verfügbar. Weitere Formate wie HTML, PDF oder CHM (Windows-Hilfeformat) sind ebenfalls erhältlich.
Die Quelldateien des Referenzhandbuchs sind im Format DocBook XML verfasst. Die HTML-Version und weitere Versionen werden automatisch erzeugt. Dabei kommen in erster Linie die DocBook XSL-Stylesheets zum Einsatz. Informationen zu DocBook finden Sie unter http://docbook.org/.
Haben Sie Anmerkungen zu Ergänzungen oder Fehlerkorrekturen in
diesem Handbuch, dann senden Sie bitte eine E-Mail an das
Dokumentationsteam (<docs@mysql.com>
).
Dieses Handbuch wurde ursprünglich verfasst von David Axmark und Michael „Monty“ Widenius. Es wird vom MySQL-Dokumentationsteam gepflegt, zu dem Paul DuBois, Stefan Hinz, Mike Hillyer und Jon Stephens gehören. Die Namen zahlreicher weiterer Mitwirkender finden Sie unter Anhang C, Danksagungen.
Die Urheberrechte für dieses Handbuch liegen bei dem schwedischen Unternehmen MySQL AB. MySQL® und das MySQL-Logo sind eingetragene Warenzeichen von MySQL AB. Weitere in diesem Handbuch verwendete Warenzeichen und eingetragene Warenzeichen sind Eigentum der jeweiligen Besitzer und dienen lediglich erläuternden Zwecken.
Dieses Handbuch verwendet folgende typografische Konventionen:
Text in diesem Stil
wird für
SQL-Anweisungen sowie für Datenbank-, Tabellen- und
Spaltennamen verwendet, darüber hinaus für Listings,
Quellcode und Umgebungsvariablen. Beispiel: „Um
die Berechtigungstabellen neu einzuladen, benutzen Sie
die Anweisung FLUSH PRIVILEGES
.“
Text in diesem Stil
bezeichnet
Eingaben, die Sie in Beispielen eintippen.
Text in diesem Stil bezeichnet die Namen ausführbarer Programme und Skripte, beispielsweise mysql (das MySQL-Befehlszeilen-Clientprogramm) und mysqld (die ausführbare MySQL Server-Datei).
Text in diesem Stil
wird für
variable Eingaben verwendet, bei denen Sie einen Wert
Ihrer Wahl eingeben.
Datei- und Verzeichnisnamen werden wie folgt geschrieben:
„Die globale Optionsdatei my.cnf
befindet sich im Verzeichnis /etc
.“
Zeichenfolgen werden so geschrieben:
„Um einen Platzhalter anzugeben, verwenden Sie das
Zeichen ‘%
’.“
Text in diesem Stil wird für Hervorhebungen verwendet.
Text in diesem Stil wird für Tabellenüberschriften und für besonders starke Hervorhebung verwendet.
Wenn Befehle dargestellt werden, die innerhalb eines
bestimmten Programms eingegeben werden sollen, gibt die
Eingabeaufforderung am Zeilenbeginn das zu verwendende
Programm an. Beispielsweise gibt shell>
einen Befehl an, der von einer Login-Shell ausgeführt werden
soll. mysql>
gibt eine Anweisung an,
die innerhalb des Clientprogramms mysql ausgeführt wird.
shell>geben Sie hier einen Shell-Befehl ein
mysql>geben Sie hier eine MySQL-Anweisung ein
Die „Shell“ ist Ihr Befehlszeilen-Interpreter. Unter Unix ist das typischerweise ein Programm wie sh, csh oder bash. Unter Windows ist das entsprechende Programm command.com oder cmd.exe, die typischerweise in einem Eingabefenster ausgeführt werden.
Wenn Sie einen Befehl oder eine Anweisung aus einem Beispiel eingeben, geben Sie bitte nicht die Eingabeaufforderung (den Prompt) ein, die in dem Beispiel angegeben ist.
Innerhalb von Anweisungen müssen Datenbank-, Tabellen- und
Spaltennamen oftmals ersetzt werden. Das Handbuch verwendet
zum Kenntlichmachen, dass eine Ersetzung notwendig ist,
db_name
,
tbl_name
und
col_name
. Beispielsweise könnten Sie
folgende Anweisung finden:
mysql> SELECT col_name
FROM db_name
.tbl_name
;
Das bedeutet, dass Sie bei Eingabe einer ähnlichen Anweisung Ihre eigenen Namen für Datenbank, Tabelle und Spalten angeben sollen, beispielsweise so:
mysql> SELECT author_name FROM biblio_db.author_list;
SQL-Schlüsselwörter sind unabhängig von der verwendeten Groß- und Kleinschreibung. Dieses Handbuch verwendet ausschließlich zur besseren Kenntlichmachung Großschreibung.
In Syntaxbeschreibungen geben eckige Klammern
(‘[
’ und
‘]
’) optionale Wörter oder
Klauseln an. In folgender Anweisung beispielsweise ist
IF EXISTS
optional:
DROP TABLE [IF EXISTS] tbl_name
Wenn ein Syntaxelement eine Anzahl von Alternativen hat,
werden diese durch vertikale Striche
(‘|
’) getrennt.
Wenn ein Element ausgewählt werden kann, aber nicht muss,
werden die Alternativen in eckigen Klammern
(‘[
’
und ‘]
’) angegeben:
TRIM([[BOTH | LEADING | TRAILING] [remstr
] FROM]str
)
Wenn ein Element ausgewählt werden muss,
werden die Alternativen in geschweiften Klammern
(‘{
’ und
‘}
’) angegeben:
{DESCRIBE | DESC}tbl_name
[col_name
|wild
]
Eine Auslassung (…
) gibt an, dass
ein Abschnitt einer Anweisung weggelassen wurde, normalerweise,
um eine kürzere Version einer komplexeren Syntax darzustellen.
Beispielsweise ist INSERT …
SELECT
die Abkürzung der Form der
INSERT
-Anweisung, bei der eine
SELECT
-Anweisung folgt.
Eine Auslassung kann darüber hinaus angeben, dass das
vorhergehende Syntaxelement einer Anweisung wiederholt
werden kann. Im folgenden Beispiel können mehrere
reset_option
-Werte angegeben werden,
wobei jedem Wert nach dem ersten ein Komma vorangestellt
wird:
RESETreset_option
[,reset_option
] ...
Befehle zum Setzen von Shell-Variablen werden in der Syntax
der Bourne-Shell dargestellt, wie beispielsweise die Folge
zum Setzen der Umgebungsvariablen CC
und
der Ausführung des Befehls configure:
shell> CC=gcc ./configure
Wenn Sie csh oder tcsh verwenden, müssen Sie die Befehle etwas anders eingeben:
shell>setenv CC gcc
shell>./configure
MySQL AB ist das Unternehmen der Gründer und Hauptentwickler von MySQL. MySQL AB wurde ursprünglich in Schweden von David Axmark, Allan Larsson und Michael „Monty“ Widenius gegründet.
Wir entwickeln die MySQL-Datenbanksoftware mit viel Engagement und machen sie unseren Benutzern bekannt. MySQL AB gehört das Copyright am MySQL-Quellcode, das MySQL-Logo und (eingetragene) Warenzeichen und dieses Handbuch. Siehe auch Abschnitt 1.4, „Was ist MySQL?“.
Die Kernwerte von MySQL zeugen von unserem Engagement für MySQL und Open Source.
Diese Kernwerte bestimmen, wie MySQL AB mit der MySQL Server-Software verfährt:
Sie soll die beste und meistgenutzte Datenbank der Welt sein,
allen verfügbar und für alle erschwinglich,
leicht zu benutzen,
ständig in Verbesserung begriffen, jedoch stets schnell und sicher,
frei von Bugs und
es soll Spaß machen, sie zu benutzen.
Die Kernwerte des Unternehmens MySQL AB und seiner Angestellten sind:
Wir sind der Open-Source-Philosophie verpflichtet und unterstützen die Open-Source-Gemeinschaft,
versuchen, stets gute Bürger zu sein,
arbeiten vorzugsweise mit Partnern zusammen, die unsere Werte und Geisteshaltung teilen,
beantworten E-Mails und stellen Support zur Verfügung,
sind ein virtuelles Unternehmen, das mit anderen Netzwerkverbunde bildet, und
arbeiten gegen Softwarepatente.
Die MySQL-Website (http://www.mysql.com/) enthält stets die neuesten Informationen über MySQL und MySQL AB.
Nebenbei bemerkt ist das „AB“ im Firmennamen die Abkürzung für das schwedische Wort „aktiebolag“, was „Aktiengesellschaft“ bedeutet. In anderen Ländern verwenden wir stattdessen „MySQL, Inc.“ oder „MySQL GmbH“ (für regionale Niederlassungen). Diese befinden sich in den USA beziehungsweise in Deutschland.
MySQL, das populärste quelloffene SQL-Datenbankmanagementsystem der Welt, wird von MySQL AB entwickelt, vertrieben und supportet. MySQL AB ist ein kommerzielles, von den MySQL-Entwicklern gegründetes Unternehmen. Es ist ein Open-Source-Unternehmen der zweiten Generation, das die Werte und Methodik von Open Source mit einem erfolgreichen Geschäftsmodell verbindet.
Die MySQL-Website (http://www.mysql.com/) enthält die neuesten Informationen über MySQL-Software und MySQL AB.
MySQL ist ein Datenbankmanagementsystem.
Eine Datenbank ist eine strukturierte Sammlung von Daten. Das kann alles von einer einfachen Einkaufsliste über eine Bildergalerie bis zu riesigen Informationsmengen in einem Firmennetzwerk sein. Um Daten in einer Computerdatenbank hinzuzufügen, auf sie zuzugreifen oder um sie zu verarbeiten, wird ein Datenbankmanagementsystem wie der MySQL Server benötigt. Weil Computer in der Handhabung großer Datenmengen sehr gut sind, spielen Datenbankmanagementsysteme eine zentrale Rolle beim Einsatz von Computern, sowohl als selbstständige Hilfsprogramme als auch als Teile anderer Anwendungen.
MySQL ist ein relationales Datenbankmanagementsystem.
Eine relationale Datenbank speichert Daten in separaten Tabellen, statt alle Daten in einem einzigen großen Speicherraum abzulegen. Das sorgt für Vorteile hinsichtlich Geschwindigkeit und Flexibilität. Das „SQL“ in „MySQL“ steht für „Structured Query Language“ (strukturierte Abfragesprache). SQL ist die gebräuchlichste standardisierte Sprache, die für den Zugriff auf Datenbanken eingesetzt wird. Sie ist im ANSI/ISO-SQL-Standard festgelegt. Dieser, kurz SQL-Standard genannt, hat sich seit 1986 entwickelt. Es existieren verschiedene Versionen. In diesem Handbuch bezieht sich „SQL-92“ auf den im Jahre 1992 veröffentlichten Standard, „SQL:1999“ auf den 1999 veröffentlichten und „SQL:2003“ auf die aktuelle Version des Standards. Wir benutzen die Bezeichnung „der SQL-Standard“ für die aktuelle Version des SQL-Standards.
MySQL-Software ist quelloffene (Open Source) Software.
Open Source bedeutet, dass es für jeden möglich ist, die Software zu benutzen und zu verändern. Jeder kann sie vom Internet herunterladen und ohne Bezahlung verwenden. Wenn man will, kann man sich den Quellcode ansehen und diesen nach den eigenen Wünschen abwandeln. MySQL verwendet die Lizenz GPL (GNU General Public License), http://www.fsf.org/licenses/. Diese legt fest, was man in unterschiedlichen Fällen mit der Software machen darf und was nicht. Wenn Ihnen ein Gebrauch unter der GPL nicht zusagt oder Sie MySQL in eine kommerzielle Applikation einbetten wollen, können Sie von uns eine kommerzielle Version erwerben. Weitere Informationen zur Lizenz finden Sie auf unserer Website (http://www.mysql.com/company/legal/licensing/).
Der MySQL-Datenbankserver ist sehr schnell, zuverlässig und einfach zu benutzen.
Wenn es das ist, wonach Sie suchen, sollten Sie MySQL ausprobieren. MySQL Server hat darüber hinaus viele praktische Features, die in enger Zusammenarbeit mit unseren Benutzern entwickelt wurden. Einen Leistungsvergleich zwischen MySQL Server und anderen Datenbanksystemen finden Sie auf unserer Benchmark-Seite unter Abschnitt 7.1.4, „Die MySQL-Benchmark-Reihe“.
MySQL Server wurde ursprünglich für den Zweck entwickelt, große Datenbanken sehr viel schneller als bestehende Lösungen zu handhaben. Er ist seit Jahren in äußerst anspruchsvollen Produktionsumgebungen im Einsatz. Obwohl er ständig weiterentwickelt wird, bietet MySQL Server schon heute ein reiches Set von Funktionen. Flexible Anbindungsmöglichkeiten, Geschwindigkeit und Sicherheit machen MySQL Server äußerst geeignet für den Zugriff auf Datenbanken im Internet.
MySQL Server arbeitet als Client-Server-Version und in eingebetteten Systemen.
Die MySQL-Datenbanksoftware ist ein Client-Server-System, das aus einem Mehr-Thread-SQL-Server besteht, der verschiedene Backends sowie diverse Clientprogramme und -bibliotheken und Verwaltungswerkzeuge unterstützt und mittels vieler verschiedener Programmierschnittstellen (API) angesprochen werden kann.
MySQL Server ist auch als eingebettete Mehr-Thread-Bibliothek verfügbar, die Sie in Ihre Applikationen einlinken können, um ein schnelles, kleines und leicht zu verwaltendes Einzelprodukt zu erhalten.
Es gibt eine große Zahl von Dritten beigesteuerter Software.
Es ist recht wahrscheinlich, dass Ihre Lieblingsapplikation oder -sprache bereits den MySQL-Datenbankserver unterstützt.
Die offizielle Aussprache von „MySQL“ ist „Mai Es Ku Ell“ (nicht „Mai Sie Quell“).
Unsere Absicht war ursprünglich, den
mSQL
-Code zu benutzen, um unsere eigenen
Tabellen anzusprechen, wobei wir unsere eigenen schnellen
Low-Level-Routinen (ISAM) benutzten. Nach einigem Testen gelangten
wir allerdings zu der Überzeugung, dass mSQL
weder schnell noch flexibel genug wäre, um unsere Anforderungen
abzudecken. Dies resultierte in einer neuen SQL-Schnittstelle zu
unserer Datenbank, allerdings mit fast derselben
API-Schnittstelle, wie sie mSQL
benutzt. Diese
API wurde gewählt, weil sie es erlaubte, Code von Drittanbietern
einfach zu portieren.
Die Entstehung des Namens MySQL ist nicht völlig geklärt. Unser Basisverzeichnis und eine große Anzahl unserer Bibliotheken und Werkzeuge hatten immer schon das Präfix „my“ während mehr als 10 Jahren. Wie auch immer, auch die Tochter von Monty Widenius, einem der Gründer von MySQL, heißt My. Welcher der beiden Umstände MySQL den Namen gab, ist immer noch ein Rätsel, sogar für uns.
Der Name des MySQL-Delphins (unseres Logos) ist „Sakila“. Er wurde von den Gründern von MySQL AB aus einer riesigen Liste mit Vorschlägen unserer Benutzer im Rahmen des „Name the Dolphin“-Wettbewerbs gewählt. Der Name wurde von Ambrose Twebaze, einem Open-Source-Software-Entwickler aus Swasiland, Afrika, eingereicht. Nach Ambrose hat der weibliche Vorname Sakila seine Wurzeln in Siswati, der Sprache von Swasiland. Sakila ist darüber hinaus der Name einer Stadt in Arusha, Tansania, die in der Nähe von Ambroses Herkunftsland, Uganda, liegt.
Die folgende Liste beschreibt einige wichtige Charakteristika von MySQL. Weitere Informationen sind unter Abschnitt 1.6, „MySQL-Roadmap“, zu finden.
Interna und Portabilität:
Geschrieben in C und C++.
Getestet mit einer großen Anzahl unterschiedlicher Compiler.
Läuft auf vielen Plattformen, siehe Abschnitt 2.1.1, „Betriebssysteme, die von MySQL unterstützt werden“.
Benutzt aus Gründen der Portabilität GNU Automake, Autoconf und Libtool.
APIs für C, C++, Eiffel, Java, Perl, PHP, Python, Ruby und Tcl stehen zur Verfügung, siehe Kapitel 24, APIs und Bibliotheken.
Voll multithread-fähig unter Benutzung von Kernel-Threads. Das bedeutet, dass Sie sehr einfach mehrere Prozessoren benutzen können, falls verfügbar.
Enthält transaktionale und nichttransaktionale Speicher-Engines.
Verwendet sehr schnelle B-Baum-Festplatten-Tabellen
(MyISAM
) mit Indexkompression.
Es ist verhältnismäßig einfach, neue Speicher-Engines hinzuzufügen. Das ist praktisch, wenn man beispielsweise einer Inhouse-Datenbank eine SQL-Schnittstelle hinzufügen möchte.
Ein sehr schnelles thread-basiertes Speicherzuordnungssystem.
Sehr schnelle Joins durch Benutzung eines optimierten Multi-Joins in einem Durchgang.
Im Arbeitsspeicher gehaltene Hash-Tabellen, die als temporäre Tabellen benutzt werden.
SQL-Funktionen sind durch eine hochoptimierte Klassenbibliothek implementiert und sollten so schnell sein, wie es überhaupt geht. Üblicherweise gibt es keinerlei Speicherzuordnung nach der Initialisierung von Anfragen.
Keine Speicherlecks (memory leaks). MySQL wird mit Purify getestet, einem kommerziellen Werkzeug zur Entdeckung von Speicherlecks, und mit Valgrind, einem GPL-Werkzeug (http://developer.kde.org/~sewardj/).
Der Server ist als separates Programm verfügbar, das in einer vernetzten Client-Server-Umgebung arbeitet. Es ist auch als Bibliothek erhältlich, die in Einzelanwendungen eingebettet werden kann. Solche Applikationen können isoliert oder in Umgebungen eingesetzt werden, in denen kein Netzwerk zur Verfügung steht.
Datentypen:
Viele Datentypen: vorzeichenbehaftete und vorzeichenlose
Integers, die 1, 2, 3, 4 und 8 Byte lang sein können,
FLOAT
, DOUBLE
,
CHAR
, VARCHAR
,
TEXT
, BLOB
,
DATE
, TIME
,
DATETIME
, TIMESTAMP
,
YEAR
, SET
,
ENUM
und OpenGIS-Typen (raumbezogene
Daten). Siehe Kapitel 11, Datentypen.
Datensätze fester und variabler Länge.
Anweisungen und Funktionen:
Volle Operator- und Funktionsunterstützung in
SELECT
- und
WHERE
-Klauseln von Abfragen. Beispiel:
mysql>SELECT CONCAT(first_name, ' ', last_name)
->FROM citizen
->WHERE income/dependents > 10000 AND age > 30;
Volle Unterstützung der SQL-Klauseln GROUP
BY
und ORDER BY
. Unterstützung
von Gruppierungsfunktionen (COUNT()
,
COUNT(DISTINCT ...)
,
AVG()
, STD()
,
SUM()
, MAX()
,
MIN()
und
GROUP_CONCAT()
).
Unterstützung von LEFT OUTER JOIN
und
RIGHT OUTER JOIN
sowohl mit Standard-SQL-
als auch mit ODBC-Syntax.
Unterstützung für Aliase auf Tabellen und Spalten, wie im SQL-Standard verlangt.
DELETE
, INSERT
,
REPLACE
und UPDATE
geben
die Anzahl der geänderten (betroffenen) Zeilen zurück. Durch
Setzen eines Flags beim Verbinden mit dem Server lässt sich
stattdessen die Anzahl der übereinstimmenden Zeilen
zurückgeben.
Die MySQL-spezifische Anweisung SHOW
kann
zum Abruf von Informationen über Datenbanken,
Speicher-Engines, Tabellen und Indizes verwendet werden.
Mit der Anweisung EXPLAIN
lässt sich
feststellen, wie der Optimierer eine Abfrage auflöst.
Funktionsnamen vertragen sich mit Tabellen- und Spaltennamen.
Beispielsweise ist ABS
ein gültiger
Spaltenname. Als einzige Einschränkung dürfen bei einem
Funktionsaufruf dem Funktionsnamen keine Leerzeichen folgen,
siehe Abschnitt 9.5, „Ist MySQL pingelig hinsichtlich reservierter Wörter?“.
Ab MySQL 3.22 können Tabellen in unterschiedlichen Datenbanken in einer Abfrage verwendet werden.
Sicherheit:
MySQL besitzt ein sehr flexibles und sicheres Berechtigungs- und Kennwortsystem, das Host-basierte Überprüfung unterstützt. Kennwörter sind sicher, weil jegliche Übermittlung beim Verbinden mit dem Server verschlüsselt erfolgt.
Skalierbarkeit und Grenzen:
Handhabt große Datenbanken. Wir selbst benutzen Datenbanken mit mehr als 50 Millionen Datensätzen und kennen Benutzer, die MySQL Server mit 60.000 Tabellen und über 5 Milliarden Zeilen benutzen.
Pro Tabelle sind bis zu 64 Indizes erlaubt (32 vor MySQL
4.1.2). Jeder Index kann aus 1 bis 16 Spalten oder
Spaltenteilen bestehen. Die größte Indexweite beträgt 1.000
Byte (500 vor MySQL 4.1.2). Indizes können Präfixe einer
Spalte bei folgenden Spaltentypen verwenden:
CHAR
, VARCHAR
,
BLOB
und TEXT
.
Konnektivität:
Clients können sich mit dem MySQL Server über TCP/IP-Sockets verbinden. Das ist auf jeder Plattform möglich. Auf Windows-Systemen der NT-Serie (NT, 2000, XP, 2003, Vista) können sich Clients mittels Named Pipes verbinden. Auf Unix-ähnlichen Systemen können Clients Unix-Domain-Socketdateien verwenden.
Ab MySQL 4.1 werden unter Windows auch
Shared-Memory-Verbindungen unterstützt, wenn der Server mit
der Option --shared-memory
gestartet wurde.
Clients können sich über Shared Memory mit der Option
--protocol=memory
verbinden.
Die Schnittstelle Connector/ODBC (MyODBC) stellt MySQL-Unterstützung für Clientprogramme zur Verfügung, die ODBC (Open Database Connectivity) benutzen. Beispielsweise können sie damit von MS Access auf MySQL Server zugreifen. Clients können unter Windows und Unix laufen. Der Quellcode von MyODBC ist offen. Alle Funktionen von ODBC 2.5 werden unterstützt sowie darüber hinaus viele weitere, siehe Kapitel 25, Connectors.
Die Schnittstelle Connector/J stellt MySQL-Unterstützung für Java-Clientprogramme zur Verfügung, die JDBC-Verbindungen benutzen. Clients können unter Windows und Unix laufen. Der Quellcode von Connector/J ist offen. Siehe Kapitel 25, Connectors.
Mit MySQL Connector/NET können Entwickler auf einfache Art .NET-Applikationen entwickeln, die sichere, hochperformante Datenverbindungen mit MySQL benötigen. Es enthält die erforderlichen ADO.NET-Schnittstellen und lässt sich in Werkzeuge einbinden, die ADO.NET-kompatibel sind. Entwickler können Applikationen mit der .NET-Sprache ihrer Wahl herstellen. MySQL Connector/NET ist ein voll verwalteter ADO.NET-Treiber, der zu 100 % in C# geschrieben wurde, siehe Kapitel 25, Connectors.
Lokalisierung:
Der Server kann Clients Fehlermeldungen in vielen Sprachen ausgeben, siehe Abschnitt 5.11.2, „Nicht englische Fehlermeldungen“.
Volle Unterstützung für diverse Zeichensätze,
beispielsweise latin1
(cp1252),
german
, big5
,
ujis
. In Tabellen- und Spaltennamen sind
beispielsweise die Zeichen
‘å
’,
‘ä
’ und
‘ö
’ zulässig. Ab MySQL 4.1
wird Unicode unterstützt.
Alle Daten werden mit dem ausgewählten Zeichensatz gespeichert. Alle Vergleiche für normale String-Spalten unterscheiden nicht nach Groß- und Kleinschreibung.
Sortierungen werden mit dem ausgewählten Zeichensatz durchgeführt, wobei die schwedische Sortierfolge als Vorgabe ausgewählt ist. Das lässt sich beim Start des MySQL Servers ändern. Schauen Sie sich als Beispiel einer fortgeschrittenen Sortierfolge den tschechischen Sortiercode an. MySQL Server unterstützt viele verschiedene Zeichensätze, die beim Kompilieren von MySQL sowie zur Laufzeit angegeben werden können.
Clients und Werkzeuge:
MySQL Server hat eingebaute SQL-Anweisungen zum Prüfen,
Optimieren und Reparieren von Tabellen. Diese Anweisungen sind
auch von der Befehlszeile aus zugänglich, über das
Clientprogramm mysqlcheck. Darüber hinaus
enthält MySQL myisamchk, ein sehr
schnelles Hilfsprogramm zum Durchführen dieser Operationen
auf MyISAM
-Tabellen, siehe
Kapitel 5, Datenbankverwaltung.
Alle MySQL-Programme können mit den Optionen
--help
und -?
aufgerufen
werden, die direkte Hilfestellungen anzeigen.
Dieser Abschnitt beschäftigt sich mit den Fragen „Wie stabil ist MySQL?“ und „Kann ich mich auf MySQL bei diesem Projekt verlassen?“. Wir werden versuchen, einige Dinge klarzustellen und einige der wichtigeren Fragen zu beantworten, die offensichtlich viele Leute beschäftigen. Dieser Abschnitt wurde aus Informationen zusammengestellt, die aus den Mailinglisten gesammelt wurden, die sehr aktiv beim Berichten von Problemen und Nutzungsbeispielen sind.
Der ursprüngliche Code stammt aus den frühen 1980er Jahren. Er
stellt eine stabile Codebasis zur Verfügung, und das
Tabllenformat ISAM
, das von der ursprünglichen
Speicher-Engine verwendet wurde, ist immer noch
abwärtskompatibel. Bei TcX funktioniert MySQL ohne jegliche
Probleme in unseren Projekten seit Mitte 1996. Als MySQL einer
breiteren Öffentlichkeit zugänglich gemacht wurde, fiel uns auf,
dass es einige Teile von ungetestetem Code gab, die schnell von
neuen Benutzern gefunden wurden, die Anfragen machten, die von
unseren eigenen abwichen. Seitdem hat jedes neue Release weniger
Portabilitätsprobleme als das vorhergehende, obwohl jedes viele
neue Features hat.
Jedes Release von MySQL war benutzbar. Probleme gab es nur, wenn Benutzer anfingen, Code aus den „Grauzonen“ zu benutzen. Natürlich wissen Benutzer von außerhalb nicht, was diese Grauzonen sind, daher versucht dieser Abschnitt, die momentan bekannten aufzuzeigen. Die Beschreibungen hier beziehen sich auf Version 3.23 von MySQL. Alle bekannten und berichteten Bugs werden in der letzten Version behoben, mit Ausnahme der Bugs, die im Bugs-Abschnitt aufgelistet sind und auf das Design zurückzuführen sind. Siehe Abschnitt A.8, „Bekannte Fehler und konzeptionelle Unzulänglichkeiten in MySQL“.
MySQL ist in mehreren Ebenen mit unabhängigen Modulen geschrieben. Diese Module sind im Folgenden aufgeführt, wobei angezeigt wird, wie gut getestet jedes von ihnen ist:
Replikation (stabil)
Große Gruppen von Servern, die Replikation verwenden, sind im Produktionseinsatz, mit guten Ergebnissen. Die Entwicklung erweiterter Replikationsfeatures wird fortgesetzt.
InnoDB
-Tabellen (stabil)
Die transaktionale Speicher-Engine InnoDB
ist seit Version 3.23.49 stabil. InnoDB
wird in großen Hochlast-Produktionssystemen eingesetzt.
Volltextsuche (stabil)
Die Volltextsuche wird viel verwendet. Wichtige Detailverbesserungen wurden in MySQL 4.0 und 4.1 hinzugefügt.
MyODBC
3.51 (stabil)
MyODBC
3.51 verwendet ODBC SDK 3.51 und ist
im breiten Produktionseinsatz. Einige Probleme scheinen
applikationsbedingt zu sein und unabhängig vom ODBC-Treiber
oder den zugrunde liegenden Datenbanken.
MySQL Version 3.22 hatte eine Begrenzung auf 4 Gbyte bei der
Tabellengröße. Mit der Speicher-Engine MyISAM
in MySQL Version 3.23 wurde die maximale Tabellengröße auf 65.536
Terabyte (2567 – 1 Byte)
erhöht. Das bedeutet, dass die maximale effektive Tabellengröße
von MySQL-Datenbanken normalerweise durch Beschränkungen des
Betriebssystems hinsichtlich Dateigrößen festgelegt ist, nicht
durch MySQL-interne Grenzen.
Die Speicher-Engine InnoDB
hält
InnoDB
-Tabellen in einem Tablespace, der aus
mehreren Dateien bestehen kann. Hierdurch ist es möglich, dass
eine Tabelle die maximale Größe einer einzelnen Datei
überschreitet. Der Tablespace kann auch rohe
Festplattenpartitionen beinhalten, wodurch extrem große Tabellen
möglich werden. Die maximale Größe des Tablespaces beträgt 64
Terabyte.
Im Folgenden sind einige Beispiele für Dateigrößen aufgeführt, die durch Betriebssysteme veranlasst sind. Die Tabelle soll nur als Anhaltspunkt dienen. Sie ist in keiner Weise auf Vollständigkeit bedacht. Die aktuellsten Informationen erhalten Sie in der Dokumentation Ihres Betriebssystems.
Betriebssystem | Maximale Dateigröße |
Linux 2.2-Intel 32-bit | 2 Gbyte (LFS: 4 Gbyte) |
Linux 2.4+ | (mit Dateisystem ext3) 4 Tbyte |
Solaris 9/10 | 16 Tbyte |
NetWare w/NSS Dateisystem | 8 Tbyte |
Win32 w/ FAT/FAT32 | 2 Gbyte/4 Gbyte |
Win32 w/ NTFS | 2 Tbyte (möglicherweise mehr) |
Mac OS X w/ HFS+ | 2 Tbyte |
Unter Linux 2.2 können Sie MyISAM
-Tabellen mit
mehr als 2 Gbyte erzeugen, indem Sie den Large File Support(LFS)-Patch
für das Dateisystem ext2 einspielen. Unter Linux 2.4
bestehen Patches für ReiserFS, die Unterstützung für große
Dateien bieten (bis zu 2 Tbyte). Die meisten aktuellen
Linux-Distributionen basieren auf Kernel 2.4 oder höher und
enthalten sämtliche erforderlichen LFS-Patches. Mit JFS und XFS
sind unter Linux Dateien im Petabytebereich und darüber hinaus
möglich. Die maximal erreichbare Dateigröße hängt jedoch immer
noch von mehreren Faktoren ab, unter anderem vom Dateisystem, auf
dem MySQL-Tabellen gespeichert werden.
Einen detaillierten Überblick über LFS unter Linux bietet die Seite Large File Support in Linux von Andreas Jäger, die Sie hier finden: http://www.suse.de/~aj/linux_lfs.html.
Wichtiger Hinweis für Windows-Benutzer: FAT und VFAT (FAT32) sind nicht für den Produktionseinsatz von MySQL geeignet. Benutzen Sie stattdessen NTFS.
Standardmäßig erzeugt MySQL MyISAM
-Tabellen
mit einer internen Struktur, die eine maximale Größe von 4 Gbyte
erlaubt. Sie können die maximale Tabellengröße einer
MyISAM
-Tabelle mit der Anweisung SHOW
TABLE STATUS
oder mittels myisamchk -dv
tbl_name
feststellen. Siehe
Abschnitt 13.5.4, „SHOW
“.
Wenn Sie eine MyISAM
-Tabelle brauchen, die
größer als 4 Gbyte ist, und Ihr Betriebssystem große Dateien
unterstützt, können Sie in der CREATE
TABLE
-Anweisung die Optionen
AVG_ROW_LENGTH
und MAX_ROWS
verwenden, siehe Abschnitt 13.1.5, „CREATE TABLE
“. Sie können diese
Optionen auch mit ALTER TABLE
ändern, um die
maximale Tabellengröße zu verändern, nachdem die Tabelle
erzeugt wurde, siehe Abschnitt 13.1.2, „ALTER TABLE
“.
Darüber hinaus gibt es weitere Möglichkeiten, die
Dateigrößenbeschränkung von MyISAM
-Tabellen
zu umgehen:
Für schreibgeschützte Tabellen kann man myisampack verwenden, das diese komprimiert. myisampack komprimiert eine Tabelle normalerweise um mindestens 50 %, wodurch Sie im Endeffekt wesentlich größere Tabellen verwalten können. myisampack kann darüber hinaus mehrere Tabellen in einer einzigen Tabelle zusammenfassen, siehe Abschnitt 8.4, „myisampack — Erzeugung komprimierter, schreibgeschützter MyISAM Tabellen“.
MySQL enthält eine MERGE
-Bibliothek, die
es erlaubt, eine Sammlung von
MyISAM
-Tabellen mit identischer Struktur
als einzelne MERGE
-Tabelle anzusprechen,
siehe Abschnitt 14.3, „Die MERGE
-Speicher-Engine“.
Der MySQL Server selbst hat keine Probleme mit der Jahr-2000-Konformität:
MySQL benutzt Unix-Zeitfunktionen und hat keine Probleme mit
Datumsangaben bis 2069
. Alle zweistelligen
Jahresangaben werden als Angaben zwischen
1970
und 2069
,
betrachtet, was bedeutet, dass, wenn Sie 01
in einer Spalte speichern, MySQL dies als
2001
behandelt.
Alle MySQL-Datumsfunktionen sind in einer Datei
sql/time.cc
gespeichert und sehr
sorgfältig kodiert, um Jahr-2000-sicher zu sein.
AB MySQL Version 3.22 kann der Spaltentyp
YEAR
das Jahr 0
und den
Bereich von 1901
bis
2155
in einem Byte speichern und sie mit 2
oder 4 Ziffern anzeigen.
Das folgende einfache Beispiel demonstriert, dass MySQL Server
keine Probleme mit DATE
- oder
DATETIME
-Werten bis zum Jahr 9999 und
keine Probleme mit TIMESTAMP
-Werten bis ins
Jahr 2030 hat:
mysql>DROP TABLE IF EXISTS y2k;
Query OK, 0 rows affected (0.00 sec) mysql>CREATE TABLE y2k (date DATE,
->date_time DATETIME,
->time_stamp TIMESTAMP);
Query OK, 0 rows affected (0.01 sec) mysql>INSERT INTO y2k VALUES
->('1998-12-31','1998-12-31 23:59:59','1998-12-31 23:59:59'),
->('1999-01-01','1999-01-01 00:00:00','1999-01-01 00:00:00'),
->('1999-09-09','1999-09-09 23:59:59','1999-09-09 23:59:59'),
->('2000-01-01','2000-01-01 00:00:00','2000-01-01 00:00:00'),
->('2000-02-28','2000-02-28 00:00:00','2000-02-28 00:00:00'),
->('2000-02-29','2000-02-29 00:00:00','2000-02-29 00:00:00'),
->('2000-03-01','2000-03-01 00:00:00','2000-03-01 00:00:00'),
->('2000-12-31','2000-12-31 23:59:59','2000-12-31 23:59:59'),
->('2001-01-01','2001-01-01 00:00:00','2001-01-01 00:00:00'),
->('2004-12-31','2004-12-31 23:59:59','2004-12-31 23:59:59'),
->('2005-01-01','2005-01-01 00:00:00','2005-01-01 00:00:00'),
->('2030-01-01','2030-01-01 00:00:00','2030-01-01 00:00:00'),
->('2040-01-01','2040-01-01 00:00:00','2040-01-01 00:00:00'),
->('9999-12-31','9999-12-31 23:59:59','9999-12-31 23:59:59');
Query OK, 14 rows affected, 2 warnings (0.00 sec) Records: 14 Duplicates: 0 Warnings: 2 mysql>SELECT * FROM y2k;
+------------+---------------------+---------------------+ | date | date_time | time_stamp | +------------+---------------------+---------------------+ | 1998-12-31 | 1998-12-31 23:59:59 | 1998-12-31 23:59:59 | | 1999-01-01 | 1999-01-01 00:00:00 | 1999-01-01 00:00:00 | | 1999-09-09 | 1999-09-09 23:59:59 | 1999-09-09 23:59:59 | | 2000-01-01 | 2000-01-01 00:00:00 | 2000-01-01 00:00:00 | | 2000-02-28 | 2000-02-28 00:00:00 | 2000-02-28 00:00:00 | | 2000-02-29 | 2000-02-29 00:00:00 | 2000-02-29 00:00:00 | | 2000-03-01 | 2000-03-01 00:00:00 | 2000-03-01 00:00:00 | | 2000-12-31 | 2000-12-31 23:59:59 | 2000-12-31 23:59:59 | | 2001-01-01 | 2001-01-01 00:00:00 | 2001-01-01 00:00:00 | | 2004-12-31 | 2004-12-31 23:59:59 | 2004-12-31 23:59:59 | | 2005-01-01 | 2005-01-01 00:00:00 | 2005-01-01 00:00:00 | | 2030-01-01 | 2030-01-01 00:00:00 | 2030-01-01 00:00:00 | | 2040-01-01 | 2040-01-01 00:00:00 | 0000-00-00 00:00:00 | | 9999-12-31 | 9999-12-31 23:59:59 | 0000-00-00 00:00:00 | +------------+---------------------+---------------------+ 14 rows in set (0.00 sec)
Die letzten beiden TIMESTAMP
-Spaltenwerte sind
null, weil die Jahreswerte (2040
,
9999
) das Maximum für
TIMESTAMP
überschreiten. Der Datentyp
TIMESTAMP
, der zur Speicherung der aktuellen
Zeit verwendet wird, unterstützt Werte im Bereich zwischen
'1970-01-01 00:00:00'
und '2030-01-01
00:00:00'
(auf 32-Bit-Maschinen; vorzeichenbehafteter
Wert). Auf 64-Bit-Maschinen kann TIMESTAMP
Werte bis zum Jahr 2106
(vorzeichenloser Wert)
handhaben.
Obgleich MySQL Server selbst Jahr-2000-sicher ist, kann es
Probleme mit Applikationen geben, die nicht Jahr-2000-konform
sind. Beispielsweise speichern oder behandeln viele alte
Applikationen Jahreswerte als zweistellige Zahlen (was uneindeutig
ist). Dieses Problem wird durch Applikationen verschlimmert, die
Werte wie 00
oder 99
als
„fehlende“ Wertangaben betrachten. Solcherlei
Probleme können schwer zu beheben sein.
Obwohl also MySQL Server keine Jahr-2000-Probleme aufweist, ist es die Aufgabe der Applikation, eindeutige Werte einzugeben. Siehe Abschnitt 11.3.4, „Jahr-2000-Probleme und Datumstypen“, hier sind die Regeln aufgeführt, die MySQL Server zur Handhabung uneindeutiger Datumseingaben mit zweistelligen Jahreswerten verwendet.
MaxDB ist eine Hochlast-Datenbank für den Unternehmenseinsatz. Das System ist SAP-zertifiziert.
MaxDB ist der neue Name des Datenbankverwaltungssystems, das vormals SAP DB hieß. Im Jahr 2003 schlossen sich SAP AG und MySQL AB zu einer Partnerschaft zusammen und gaben das Datenbanksystem unter dem neuen Markennamen MaxDB heraus. Die Entwicklung von MaxDB wurde seitdem wie gehabt durch das SAP-Entwicklungsteam fortgesetzt.
MySQL AB arbeitet eng mit dem MaxDB-Team bei SAP zusammen, um Verbesserungen in das Produkt MaxDB einzubringen. Beispielsweise werden zusammen neue native Treiber entwickelt, die eine effizientere Nutzung von MaxDB in der Open-Source-Community erlauben. Die Dokumentation wurde auf den MaxDB-Seiten verfügbar gemacht. Als gleichermaßen wichtig werden Features für das Zusammenspiel zwischen MySQL und MaxDB erachtet. Der neu entwickelte Synchronisationsmanager von MaxDB beispielsweise unterstützt die Synchronisation von Daten zwischen MaxDB und MySQL.
Das MaxDB-Datenbankverwaltungssystem hat eine andere Codebasis als das MySQL-Datenbankverwaltungssystem. MaxDB und MySQL sind voneinander unabhängige Produkte, die beide von MySQL AB angeboten werden.
MySQL AB bietet eine Vielzahl professioneller Dienstleistungen für MaxDB an.
MaxDB ist ein zu ANSI SQL-92 (entry level) konformes relationales Datenbankverwaltungssystem (RDBMS) der SAP AG, das auch von MySQL AB vertrieben wird. MaxDB erfüllt alle Ansprüche an den Gebrauch im Unternehmen: Sicherheit, Skalierbarkeit, Nichtsequenzialität (Gleichzeitigkeit von Zugriffen) und Performanz. Es läuft auf allen größeren Betriebssystemen. Im Laufe der Jahre hat es unter Beweis gestellt, dass es in der Lage ist, SAP R/3 und Terabytes von Daten im Rund-um-die-Uhr-Betrieb zu unterstützen.
Die Datenbankentwicklung begann 1977 als Forschungsprojekt an der Technischen Universität Berlin. In den frühen 1980er Jahren wurde es zu einem Datenbankprodukt, das nacheinander Nixdort, Siemens Nixdorf, der Software AG und dann (bis heute) der SAP AG gehörte. Im Verlauf dieser Zeit wurde es VDN, Reflex, Supra 2, DDB/4, Entire SQL-DB-Server sowie ADABAS D genannt. 1997 übernahm SAP die Software von der Software AG und benannte sie in SAP DB um. Seit Oktober 2000 sind die SAP DB-Quellcodes unter der GNU General Public-Lizenz (siehe Anhang J, GNU General Public License) veröffentlicht.
Im Jahre 2003 gründeten die SAP AG und MySQL AB eine Partnerschaft und benannten das Datenbanksystem in MaxDB um.
Die Geschichte von MaxDB geht zurück auf SAP DB, das Datenbanksystem der SAP AG. MaxDB ist also die umbenannte und erweiterte Version von SAP DB. Seit vielen Jahren wird MaxDB in kleinen, mittleren und großen Installationen der mySAP-Business-Suite und anderen anspruchsvollen SQL-Anwendungen verwendet, die ein unternehmenstaugliches Datenbanksystem hinsichtlich Anzahl der Benutzer, transaktionaler Arbeitslast und Größe der Datenbank benötigen.
SAP DB war als Alternative zu Datenbanken von Drittanbietern wie Oracle oder Microsoft SQL Server sowie DB2 von IBM gedacht. Im Oktober 2000 veröffentlichte die SAP AG SAP DB unter der Lizenz GNU GPL (siehe Anhang J, GNU General Public License) und machte es damit zu quelloffener (Open Source) Software.
Heute kommt MaxDB in über 3500 SAP-Kundeninstallationen auf der ganzen Welt zum Einsatz. Darüber hinaus setzt die Mehrzahl aller Datenbankinstallationen unter Unix und Linux innerhalb der IT-Abteilung von SAP auf MaxDB auf. MaxDB ist optimiert auf Hochlast-Online-Transaction-Processing (OLTP) mit mehreren Tausend Benutzern und Datenbankgrößen zwischen mehreren hundert Gbytes und mehreren Tbytes.
Im Jahre 2003 begründeten SAP und MySQL eine Partnerschaft und eine Entwicklungskooperation. Im Rahmen dieser Zusammenarbeit wurde das System SAP DB der SAP AG unter dem Namen MaxDB by MySQL veröffentlicht. Das erste Release unter diesem Namen war 7.5 (November 2003).
Version 7.5 von MaxDB ist eine direkte Weiterentwicklung auf der Codebasis von SAP DB 7.4. Daher kann MaxDB 7.5 direkt als Upgrade von früheren SAP DB-Versionen ab 7.2.04 verwendet werden.
Das bestehende SAP-DB-Entwicklungsteam bei der SAP AG ist nach wie vor verantwortlich für die Entwicklung und den Support von MaxDB. MySQL AB und das MaxDB-Team bei SAP arbeiten an Verbesserungen am Produkt MaxDB eng zusammen; siehe Abschnitt 1.5, „Überblick über das Datenbanksystem MaxDB“. Sowohl die SAP AG als auch MySQL AB wickeln Verkauf und Auslieferung von MaxDB ab. Die Weiterentwicklung von MaxDB und MySQL Server setzt Synergien frei, die beiden Produktlinien zugute kommen.
MaxDB unterliegt dem kompletten Qualitätssicherungsprozess der SAP AB, bevor das Produkt mit SAP-Lösungen ausgeliefert oder zum Download auf der MySQL-Website zur Verfügung gestellt wird.
MaxDB ist eine SAP-zertifizierte, quelloffene Hochlast-Datenbank für OLTP- und OLAP-Einsatzzwecke, die hohe Zuverlässigkeit und Verfügbarkeit sowie Skalierbarkeit und ein sehr umfangreiches Set von Features bietet. MaxDB ist auf große mySAP-Business-Suite-Umgebungen und sonstige Applikationen, die höchste Unternehmensfunktionalität benötigen, zugeschnitten und ergänzt somit den MySQL-Datenbankserver.
MaxDB arbeitet als Client-Server-Produkt. Es wurde hinsichtlich der Anforderungen von OLTP und Data Warehouse/OLAP/Entscheidungsunterstützung entwickelt und bietet folgende Vorteile:
Einfache Konfiguration und Verwaltung: Ein grafischer Installationsmanager sowie ein Datenbankmanager als einziges Verwaltungswerkzeug für sämtliche DBMS-Operationen
Rund-um-die-Uhr-Betrieb, keine geplanten Stillstandszeiten, keine ständige Beobachtung erforderlich: Automatische Verwaltung des Speicherplatzes ohne Notwendigkeit von Neuorganisationen
Ausgefeilte Sicherungs- und Wiederherstellungsoptionen: Online-Backups und inkrementelle Sicherungen sowie Wiederherstellungsassistenten, die Sie durch das Recovery-Szenario führen
Unterstützt eine große Zahl gleichzeitiger Benutzer, Datenbankgrößen im Terabytebereich und anspruchsvolle Arbeitslasten: Ausgereifte Zuverlässigkeit, Performanz und Skalierbarkeit
Hochverfügbarkeit: Clusterunterstützung, Standby-Konfiguration, Hot-Standby-Konfiguration
MaxDB kann unter denselben Lizenzen benutzt werden, die für andere von MySQL AB vertriebene Produkte gelten. Es ist daher unter der Lizenz GNU General Public License sowie einer kommerziellen Lizenz erhältlich. Weitere Informationen zur Lizenzierung finden Sie unter http://www.mysql.com/company/legal/licensing/.
MySQL AB bietet technischen Support für Nicht-SAP-Kunden. Der Support ist in verschiedenen Stufen erhältlich (Basic, Silver, Gold), die vom unbegrenzten E-Mail- und Web-Support bis hin zum 24×7-Telefon-Support für geschäftskritische Anwendungen reichen.
MySQL AB bietet auch Lizenzen und Support für MaxDB an, wenn es mit SAP-Applikationen wie SAP NetWeaver und der mySAP-Business-Suite eingesetzt wird. Für weitere Informationen zu Lizenzen und Support gemäß Ihren Anforderungen setzen Sie sich bitte mit MySQL AB in Verbindung (http://www.mysql.com/company/contact/).
Consulting und Schulungen sind ebenfalls erhältlich. MySQL gibt in regelmäßigen Abständen Kurse. Eine Liste finden Sie unter http://www.mysql.com/training/.
MaxDB ist die SAP-zertifizierte Datenbank von MySQL AB. Der MaxDB-Datenbankserver ergänzt das Produktport von MySQL AB. Einige Features von MaxDB sind bei MySQL Server nicht erhältlich und umgekehrt.
Folgende Liste fasst die Hauptunterschiede zwischen MaxDB und MySQL zusammen, wobei kein Anspruch auf Vollständigkeit besteht:
MaxDB läuft als Client-Server-System, während MySQL darüber hinaus auch als eingebettetes System laufen kann.
MaxDB läuft nicht auf allen von MySQL unterstützten Plattformen.
MaxDB verwendet ein proprietäres Netzwerkprotokoll für die Client-Server-Kommunikation. MySQL benutzt entweder TCP/IP (mit oder ohne SSL-Verschlüsselung), Sockets (unter Unix-ähnlichen Systemen) oder Named Pipes und Shared Memory (unter Systemen der Windows-NT-Familie).
MaxDB unterstützt gespeicherte Prozeduren und Funktionen. MySQL unterstützt diese ab Version 5.0 ebenfalls. MaxDB unterstützt die Programmierung von Triggern über eine SQL-Erweiterung. MySQL unterstützt Trigger ab Version 5.0. MaxDB enthält einen Debugger für Stored-Procedure-Sprachen, kann Trigger verschachteln und unterstützt mehrere Trigger pro Aktion und Zeile.
MaxDB wird mit textbasierten, grafischen und webbasierten Benutzerschnittstellen ausgeliefert. MySQL wird nur mit textbasierten Schnittstellen ausgeliefert, während grafische Benutzerwerkzeuge wie MySQL Query Browser und MySQL Administrator getrennt von den Hauptdistributionen zur Verfügung stehen. Webbasierte Schnittstellen für MySQL werden von Drittanbietern zur Verfügung gestellt.
MaxDB unterstützt eine Reihe von Programmierschnittstellen, die auch von MySQL unterstützt werden. Zur Entwicklung mit MaxDB stehen folgende Schnittstellen zur Verfügung: Der MaxDB ODBC-Treiber, SQL Database Connectivity (SQLDBC), JDBC-Treiber, Perl- und Python-Module und eine MaxDB PHP-Extension, die den Zugriff auf MaxDB mittels PHP erlaubt. Schnittstellen von Drittanbietern: Unterstützung für OLE DB, ADO, DAO, RDO und .NET über ODBC. MaxDB unterstützt eingebettetes SQL mit C/C++.
MaxDB enthält Verwaltungsfeatures, die MySQL nicht hat: Auftragsplanung nach Zeit (in MySQL ab Version 5.1 enthalten), Ereignis und Alarm sowie das Senden von Nachrichten an einen Datenbankverwalter, geregelt durch Alarmschwellen (Thresholds).
MaxDB und MySQL sind unabhängige Datenbankverwaltungssysteme. Beide Systeme können über Datenaustausch interagieren. Um Daten zwischen MaxDB und MySQL auszutauschen, können Sie entweder die jeweiligen Export- und Importwerkzeuge der Systeme oder den Synchronisationsmanager von MaxDB verwenden. Die Verwendung der Import- und Exportwerkzeuge ist für gelegentlichen, manuell durchgeführten Datenabgleich gedacht. Der Synchronisationsmanager von MaxDB dagegen bietet schnelle, automatische Datentransfer-Möglichkeiten.
Der MaxDB Loader kann zum Export von Daten und Objektdefinitionen
verwendet werden. Der Loader kann Daten im MaxDB-internen, im
binären oder im Textformat (CSV) exportieren. Ins Textformat
exportierte Daten können in MySQL mittels des Clientprogramms
mysqlimport importiert werden. Um Daten aus
MySQL zu exportieren, können Sie entweder
mysqldump verwenden, um
INSERT
-Anweisungen zu erzeugen, oder
SELECT ... INTO OUTFILE
, um eine Textdatei
(CSV) zu schreiben. Diese Daten können dann mit dem MaxDB Loader
importiert werden.
Objektdefinitionen können zwischen den Systemen mittels MaxDB
Loader und dem MySQL-Werzeug mysqldump
ausgetauscht werden. Weil die SQL-Dialekte beider Systeme sich
leicht unterscheiden und MaxDB Features aufweist, die momentan von
MySQL nicht unterstützt werden (beispielsweise SQL-Constraints),
empfehlen wir, Definitionsdateien per Hand abzugleichen. Das
Werkzeug mysqldump stellt die Option
--compatible=maxdb
zur Verfügung, die Ausgaben
erzeugt, die sich leichter nach MaxDB portieren lassen.
Der Synchronisationsmanager von MaxDB steht ab Version 7.6 zur Verfügung. Er unterstützt das Erzeugen von asynchronen Replikationsszenarien zwischen mehreren MaxDB-Instanzen. Es sind jedoch auch darüber hinausgehende Features zur Interoperabilität geplant, die es dem Synchronisationsmanager erlauben sollen, zu und von einem MySQL Server zu replizieren.
Die Hauptseite für Informationen zu MaxDB ist http://www.mysql.com/products/maxdb. Hier finden Sie detaillierte Informationen zu den Features des MaxDB- Datenbanksystems und Links zur verfügbaren Dokumentation.
Das MySQL Referenzhandbuch enthält keinerlei MaxDB-Dokumentation mit Ausnahmen der in diesem Abschnitt gegebenen Einführung. MaxDB hat seine eigene Dokumentation, genannt MaxDB-Bibliothek, die sich hier befindet: http://dev.mysql.com/doc/maxdb/index.html.
MySQL AB unterhält eine Community-Mailingliste zu MaxDB: http://lists.mysql.com/maxdb, auf der sich neben lebhaften Beiträgen der Community auch Postings der Kernentwickler finden. Produktankündigungen werden ebenfalls an diese Liste geschickt.
Ein Webforum zu MaxDB ist verfügbar unter http://forums.mysql.com/. Im Forum werden vorrangig Fragen zu MaxDB angesprochen, die sich nicht auf SAP-Applikationen beziehen.
Dieser Abschnitt enthält eine Momentaufnahme des MySQL-Entwicklungsfahrplans einschließlich verschiedener wichtiger Funktionen, die in diversen MySQL-Releases implementiert wurden bzw. für diese vorgesehen sind. Nachfolgend finden Sie Informationen zu allen Release-Serien.
Die aktuelle Release-Serie ist MySQL 5.0. Die für den Einsatz in Produktionsumgebungen erforderliche Stabilität wurde für MySQL 5.0.15 (Freigabe im Oktober 2005) festgestellt. Die vorherige Release-Serie war MySQL 4.1. Die für den Einsatz in Produktionsumgebungen erforderliche Stabilität wurde für MySQL 4.1.7 (Freigabe im Oktober 2004) festgestellt. „Produktionsstatus“ bedeutet, dass die Entwicklung bei den Versionen 5.0 und 4.1 zukünftig auf die Fehlerbereinigung beschränkt ist. Bei den älteren MySQL-Serien 4.0 und 3.23 werden nur noch kritische Fehler behoben.
Die aktive MySQL-Entwicklung betrifft derzeit die MySQL-Release-Serien 5.0 und 5.1. Neue Funktionen werden lediglich bei Version 5.1 implementiert.
Bevor Sie von einer Release-Serie auf die nächste aktualisieren, beachten Sie die Hinweise in Abschnitt 2.10, „MySQL aktualisieren (Upgrade/Downgrade)“.
Die meistgewünschten Funktionen und die Versionen, in denen sie implementiert werden bzw. für die ihre Implementierung vorgesehen ist, werden in folgender Tabelle zusammengefasst.
Funktion | MySQL-Serie |
Fremdschlüssel | 3.23 (für die InnoDB -Speicher-Engine) |
Unions | 4.0 |
Unterabfragen | 4.1 |
R-Trees | 4.1 (für die MyISAM -Speicher-Engine) |
Gespeicherte Prozeduren | 5.0 |
Sichten | 5.0 |
Cursor | 5.0 |
XA-Transaktionen | 5.0 |
Fremdschlüssel | 5.2 (implementiert in 3.23 für InnoDB ) |
Trigger | 5.0 und 5.1 |
Partitionierung | 5.1 |
Pluggable Storage Engine-API | 5.1 |
Datensatzbasierte Replikation | 5.1 |
Die folgenden Funktionen wurden in MySQL 5.1 implementiert. Weitere Detailinformationen werden wir im Zuge der Weiterentwicklung von MySQL 5.1 ergänzen.
Partitionierung: Diese Funktionalität erlaubt die Verteilung von Teilen einzelner Tabellen über ein Dateisystem. Die entsprechenden Regeln können bei Erstellung der Tabelle konfiguriert werden. Verschiedene Teile einer Tabelle werden also als separate Tabellen an verschiedenen Positionen abgelegt, die partitionierte Tabelle präsentiert sich dem Benutzer jedoch weiterhin als eine einzige Tabelle. Weitere Informationen zu dieser Funktionalität finden Sie in Kapitel 17, Partitionierung (Autor: Mikael Ronström).
Plug-In-API: MySQL 5.1 unterstützt eine sehr flexible Plug-In-API, die das Laden und Entladen verschiedener Komponenten während der Laufzeit gestattet, ohne dass der Server neu gestartet werden müsste. Zwar sind die Arbeiten daran noch nicht abgeschlossen, aber die Plug-In-Volltext-Parser sind ein erster Schritt in diese Richtung. Hiermit können Benutzer eigene Eingabefilter für indizierten Text implementieren und so eine Volltextsuche für beliebige Daten (z. B. PDF-Dateien oder andere Dokumentformate) ermöglichen. Ein dem Parser vorgeschaltetes Volltext-Plug-In führt die eigentliche Verarbeitung und Extraktion des Texts durch und übergibt diesen dann an die in MySQL integrierte Volltextsuche (Autor: Sergey Vojtovich).
Der Instanzen-Manager (IM) bietet nun einige neue Funktionen:
SHOW
listet alle von der Instanz
verwendeten Logdateien auf (Autor: Petr Chardin).
instance_name
LOG FILES
SHOW
ruft einen
Teil der angegebenen Logdatei ab (Autor: Petr Chardin).
instance_name
LOG {ERROR | SLOW | GENERAL}
size
SET
setzt eine Option auf den angegebenen Wert und schreibt
sie in die Konfigurationsdatei. Weitere Informationen zu
diesen neuen Befehlen finden Sie unter
Abschnitt 5.5, „mysqlmanager — Der MySQL Instance Manager“ (Autor: Petr
Chardin).
instance_name
.option_name
=option_value
Dieser Abschnitt listet zusätzliche Informationsquellen auf, die für Sie hilfreich sein können. Dies sind etwa die MySQL-Mailinglisten und Benutzerforen sowie IRC-Kanäle.
Dieser Abschnitt stellt die MySQL-Mailinglisten vor und enthält Hinweise zur Benutzung dieser Listen. Wenn Sie eine Mailingliste bestellen, erhalten Sie alle Beiträge zu dieser Liste als E-Mails. Sie können auch eigene Fragen (und Antworten) an die Liste schicken.
Um eine der in diesem Abschnitt aufgeführten Listen zu bestellen bzw. zu kündigen, besuchen Sie die Seite http://lists.mysql.com/. Bei den meisten Listen können Sie die reguläre Version, bei der jeder Beitrag einzeln als Mail gesendet wird, oder eine Digest-Version auswählen, wobei Sie einmal täglich eine lange Mail mit allen Beiträgen des Tages erhalten.
Bitte senden Sie bei Fragen zu Bestellung oder Kündigung einer Liste keine Mitteilungen an die Liste selbst, denn auch diese werden automatisch an tausende anderer Benutzer weitergeschickt.
An Ihrem Standort haben vielleicht schon viele Benutzer eine
MySQL-Mailingliste abonniert. Sollte dies der Fall sein, dann wird
am Standort womöglich eine lokale Mailingliste betrieben, sodass
Mitteilungen, die von lists.mysql.com
an Ihren
Standort geschickt werden, an diese lokale Liste weitergeleitet
werden. Wenden Sie sich in diesem Fall an Ihren
Systemadministrator, damit dieser Sie zur lokalen MySQL-Liste
hinzufügt bzw. aus dieser entfernt.
Wenn Sie wollen, dass die Daten einer Mailingliste in Ihrem
E-Mail-Programm in ein anderes Postfach geleitet werden, erstellen
Sie einen Filter, der eingehende Mails nach den Kopfdaten
(Headern) sortiert. Sie können die Header
List-ID:
oder Delivered-To:
zur Identifizierung von Mitteilungen einer MySQL-Liste verwenden.
Die folgenden MySQL-Mailinglisten sind vorhanden:
announce
Diese Liste ist für Ankündigungen neuer MySQL-Versionen und zugehöriger Programme vorgesehen. Das Aufkommen ist bei dieser Liste gering. Sie sollte von allen MySQL-Benutzern abonniert werden.
mysql
Dies ist die wichtigste Liste für allgemeine Diskussionen zu MySQL. Bitte beachten Sie, dass einige Themen besser in den spezialisierteren Listen behandelt werden. Wenn Sie eine Mitteilung an die falsche Liste schicken, erhalten Sie unter Umständen keine Antwort.
bugs
Diese Liste ist für Benutzer vorgesehen, die bezüglich aller Probleme, die seit dem letzten MySQL-Release gemeldet wurden, auf dem neuesten Stand bleiben oder sich aktiv an der Suche und Behebung von Bugs beteiligen wollen. Siehe auch Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“.
internals
Diese Liste ist für Benutzer vorgesehen, die am MySQL-Code arbeiten. Sie ist auch das Forum für Diskussionen zur MySQL-Entwicklung und zur Verbreitung von Patches.
mysqldoc
Diese Liste ist für Benutzer vorgesehen, die an der MySQL-Dokumentation arbeiten. Dies sind beispielsweise Mitarbeiter von MySQL AB oder Übersetzer.
benchmarks
Diese Liste ist für jeden gedacht, der sich für Fragen der Leistungsfähigkeit interessiert. Die Diskussionen drehen sich in erster Linie um die Leistung von Datenbanken (wobei man sich nicht auf MySQL beschränkt), aber auch andere Kategorien – z. B. die Leistungsfähigkeit von Kerneln, Datei- oder Festplattensystemen usw. – werden hier behandelt.
packagers
Diese Liste ist für Diskussionen gedacht, bei denen es um das Packen und Vertreiben von MySQL geht. Dies ist das Forum, in dem für die Distribution Zuständige Ideen zum Packen von MySQL und zu der Frage austauschen können, wie man gewährleistet, dass „Look and Feel“ von MySQL auf allen unterstützten Plattformen und Betriebssystemen so ähnlich wie möglich sind.
java
Diese Liste ist für Diskussionen über den MySQL Server und Java vorgesehen. Hier werden meistens JDBC-Treiber wie etwa MySQL Connector/J diskutiert.
win32
Diese Liste ist für alle Themen reserviert, die den Betrieb der MySQL-Software auf Microsoft-Betriebssystemen wie Windows 9x, Me, NT, 2000, XP und 2003 betreffen.
myodbc
Diese Liste behandelt Themen im Zusammenhang mit der Verbindungsherstellung zum MySQL Server über ODBC.
gui-tools
Diese Liste ist für alle Themen vorgesehen, die GUI-Tools
(grafische Oberflächen) für MySQL bereitstellen, z. B.
MySQL Administrator
und MySQL
Query Browser
.
cluster
Bei dieser Liste dreht sich alles um MySQL Cluster.
dotnet
Diese Liste ist für Diskussionen über den MySQL Server und die .NET-Plattform vorgesehen. Es geht dabei in erster Linie um MySQL Connector/Net.
plusplus
Diese Liste behandelt alle Themen in Zusammenhang mit der Programmierung unter Verwendung der C++-API für MySQL.
perl
Dies ist eine Liste, bei der Themen zum Bereich der
Perl-Unterstützung für MySQL mit
DBD::mysql
diskutiert werden.
Wenn Sie über eine MySQL-Mailingliste oder ein Forum keine befriedigende Antwort auf Ihre Frage erhalten, besteht eine weitere Option im kostenpflichtigen Support durch MySQL AB. Auf diese Weise erhalten Sie direkten Kontakt zu den MySQL-Entwicklern.
Die folgende Tabelle enthält einige MySQL-Mailinglisten in anderen Sprachen als Englisch. Diese Listen werden jedoch nicht von MySQL AB betrieben.
<mysql-france-subscribe@yahoogroups.com>
Eine französischsprachige Mailingliste.
Eine koreanischsprachige Mailingliste. Sie bestellen sie,
indem Sie den Befehl subscribe mysql
ihre@email.adresse
in einer Mail an die Liste
schicken.
<mysql-de-request@lists.4t2.com>
Eine deutschsprachige Mailingliste. Sie bestellen sie, indem
Sie den Befehl subscribe mysql-de
ihre@email.adresse
in einer Mail an die Liste
schicken. Weitere Informationen zu dieser Mailingliste finden
Sie unter http://www.4t2.com/mysql/.
<mysql-br-request@listas.linkway.com.br>
Eine portugiesischsprachige Mailingliste. Sie bestellen sie,
indem Sie den Befehl subscribe mysql-br
ihre@email.adresse
in einer Mail an die Liste
schicken.
Eine spanischsprachige Mailingliste. Sie bestellen sie, indem
Sie den Befehl subscribe mysql
ihre@email.adresse
in einer Mail an die Liste
schicken.
Bitte senden Sie keine Mails mit aktiviertem HTML-Modus aus Ihrem Browser. Viele Benutzer lesen ihre Mails nicht mit einem Browser.
Wenn Sie eine Frage beantworten, die an die Mailingliste gesendet wurde, und der Ansicht sind, dass die Antwort von allgemeinem Interesse ist, dann sollten Sie sie an die Liste schicken, statt dem Fragesteller direkt zu schreiben. Formulieren Sie Ihre Antwort allgemein genug, sodass auch andere Benutzer als der Fragesteller davon profitieren können. Bevor Sie einen Beitrag an die Liste schicken, vergewissern Sie sich, dass es sich nicht um eine Wiederholung einer bereits vorhandenen Antwort handelt.
Versuchen Sie, die wesentlichen Aspekte der Frage in der Antwort zusammenzufassen. Sie sind nicht verpflichtet, die gesamte Frage in ihrer ursprünglichen Form zu zitieren.
Wenn Antworten direkt an Sie und nicht an die Mailingliste geschrieben werden, gilt es als lobenswert, die Antworten in zusammengefasster Form an die Liste zu schicken, sodass auch andere Benutzer von den Antworten profitieren können, mit deren Hilfe Sie das Problem beheben konnten.
Die Foren unter http://forums.mysql.com sind eine wichtige Quelle für die Benutzergemeinschaft. Es gibt eine ganze Reihe von Foren, die in die folgenden Kategorien fallen:
Migration
MySQL verwenden
MySQL Connectors
Programmiersprachen
Tools
Anwendungen von Drittanbietern
Speicher-Engines
MySQL-Technologie
SQL-Standards
Business
Neben den verschiedenen MySQL-Mailinglisten und -Foren finden Sie erfahrene Mitglieder der Gemeinschaft im Internet Relay Chat (IRC). Die folgenden Netzwerke und Kanäle sind die besten, die wir derzeit kennen:
freenode (Serverinformationen unter http://www.freenode.net/)
#mysql
ist in erster Linie für
MySQL-spezifische Fragen gedacht, aber auch allgemeine Fragen
zum SQL-Komplex sind willkommen. Auch Fragen zu PHP, Perl oder
C in Verbindung mit MySQL sind hier häufig zu finden.
Wenn Sie nach einer IRC-Clientsoftware suchen, um eine Verbindung
mit einem IRC-Netzwerk herzustellen, dann werfen Sie einen Blick
auf xChat
(http://www.xchat.org/). X-Chat (unter GPL-Lizenz)
ist für Unix und für Windows-Plattformen erhältlich. (Einen
kostenlosen Build von X-Chat finden Sie unter
http://www.silverex.org/download/.)
Bevor Sie einen Bugreport zu einem Problem einreichen, stellen Sie zunächst sicher, dass es sich wirklich um einen Bug handelt und dass dieser nicht bereits gemeldet wurde:
Beginnen Sie mit der Suche im MySQL-Online-Manual unter http://dev.mysql.com/doc/. Wir versuchen, das Manual aktuell zu halten, indem wir es häufig mit Lösungen zu neu gefundenen Problemen aktualisieren. Die Änderungshistorie (http://dev.mysql.com/doc/mysql/en/news.html) kann besonders nützlich sein, da es durchaus möglich ist, dass eine neuere Version eine Lösung zu Ihrem Problem enthält.
Wenn beim Parsen einer SQL-Anweisung ein Fehler auftritt,
überprüfen Sie Ihre Syntax bitte sorgfältig. Wenn Sie keinen
Fehler erkennen können, ist es sehr wahrscheinlich, dass Ihre
gegenwärtige Version von MySQL Server die verwendete Syntax
nicht unterstützt. Wenn Sie die aktuelle Version verwenden und
das Manual die von Ihnen verwendete Syntax nicht behandelt, dann
unterstützt MySQL Server Ihre Anweisung nicht. In diesem Fall
bestehen Ihre Möglichkeiten darin, die Syntax selbst zu
implementieren oder eine E-Mail an
<licensing@mysql.com>
zu senden und darin um ein
Angebot für eine Implementierung zu bitten.
Wenn das Manual die von Ihnen verwendete Syntax behandelt, aber Sie mit einer älteren Version von MySQL Server arbeiten, überprüfen Sie in der MySQL-Änderungshistorie, wann die Syntax implementiert wurde. In diesem Fall können Sie auf eine neuere Version von MySQL Server aktualisieren.
Informationen zur Lösung einiger häufiger Probleme finden Sie unter Anhang A, Probleme und häufig auftretende Fehler.
Durchsuchen Sie die Bugdatenbank unter http://bugs.mysql.com/ und überprüfen Sie, ob der Bug gemeldet und ggf. behoben wurde.
Durchsuchen Sie die Archive der MySQL-Mailinglisten unter http://lists.mysql.com/. Siehe auch Abschnitt 1.7.1, „Die MySQL-Mailinglisten“.
Sie können auch über http://www.mysql.com/search/ alle Webseiten (einschließlich des Manuals) durchsuchen, die sich auf der Website von MySQL AB befinden.
Wenn Sie im Manual, der Bugdatenbank oder den Archiven der Mailinglisten keine Antwort finden, wenden Sie sich an Ihren lokalen MySQL-Fachmann. Erhalten Sie auch dort keine Antwort auf Ihre Frage, dann melden Sie den Bug bitte unter Beachtung der folgenden Verhaltensregeln.
Die normale Vorgehensweise zur Meldung von Bugs besteht in einem Besuch auf http://bugs.mysql.com/. Dies ist die Adresse unserer Bugdatenbank. Diese Datenbank ist öffentlich und kann von jedem gelesen und durchsucht werden. Wenn Sie sich am System anmelden, können Sie neue Meldungen eingeben. Haben Sie keinen Webzugang, dann können Sie mit dem Skript mysqlbug einen Bugreport erstellen. Das Skript ist am Ende dieses Abschnitts beschrieben.
Bugs, die in die Bugdatenbank unter http://bugs.mysql.com/ eingetragen sind und in einem gegebenen Release behoben wurden, sind in der Änderungshistorie vermerkt.
Wenn Sie einen sensiblen Sicherheitsbug in MySQL gefunden haben,
können Sie eine E-Mail an <security@mysql.com>
schicken.
Wenn Sie Probleme mit anderen Benutzern diskutieren wollen, können Sie zu diesem Zweck eine der MySQL-Mailinglisten verwenden. Abschnitt 1.7.1, „Die MySQL-Mailinglisten“.
Das Verfassen eines Bugreports erfordert Geduld. Wenn Sie dies aber zuallererst tun, sparen Sie sowohl sich selbst als auch uns Zeit. Ein guter Bugreport enthält einen vollständigen Testfall für den Bug, welcher es uns mit hoher Wahrscheinlichkeit ermöglichen wird, ihn bereits im nächsten Release zu beheben. Dieser Abschnitt soll Ihnen dabei helfen, Ihren Bugreport korrekt zu formulieren, sodass Sie keine Zeit mit Dingen verschwenden, die uns nur wenig oder gar nicht helfen. Bitte lesen Sie diesen Abschnitt aufmerksam durch und stellen Sie sicher, dass alle hier beschriebenen Angaben in Ihrem Report enthalten sind.
Sie sollten das Problem bevorzugt mit der aktuellen Produktions-
oder Entwicklungsversion von MySQL Server überprüfen, bevor Sie
den Report absenden. Der Bug sollte sich problemlos reproduzieren
lassen, indem einfach der Befehl mysql test <
script_file
für Ihren Testfall ausgeführt oder das
Shell- oder Perl-Skript gestartet wird, das Sie dem Bugreport
hinzufügen. Für jeden Bug, den wir reproduzieren können, stehen
die Chancen einer Behebung im nächsten MySQL-Release gut.
Am hilfreichsten ist es, wenn eine gute Beschreibung des Problems dem Bugreport beiliegt. Das bedeutet: Geben Sie ein gutes Beispiel für alles an, was Sie taten, als das Problem auftrat, und beschreiben Sie möglichst detailliert das Problem selbst. Die besten Reports sind diejenigen, die eine vollständige Beschreibung enthalten, wie der Bug oder das Problem reproduziert werden können. Siehe auch Abschnitt E.1.6, „Erzeugen eines Testfalls, wenn Sie Tabellenbeschädigung feststellen“.
Bedenken Sie, dass wir zwar einen Report bearbeiten können, der zu viele Angaben enthält, nicht aber einen solchen, der zu wenig Informationen umfasst. Es kommt häufig vor, dass Tatsachen weggelassen werden, weil der Einreicher annimmt, dass wir das Problem kennen und die Details keine Rolle spielen. Eine Faustregel, der Sie folgen können, lautet: Wenn Sie im Zweifel sind, ob Sie etwas angeben wollen, dann geben Sie es lieber an. Es geht schneller und ist weniger mühsam, ein paar Zeilen mehr in Ihren Report zu schreiben, als länger auf die Antwort warten zu müssen, weil wir bei Ihnen Angaben erfragen müssen, die im eingereichten Bugreport nicht enthalten waren.
Die meistgemachten Fehler in Bugreports bestehen darin, dass (a) die Versionsnummer der verwendeten MySQL-Distribution nicht enthalten und (b) die Plattform, auf der der MySQL Server installiert ist, nicht vollständig (einschließlich der Angaben zu Typ und Versionsnummer der Plattform) beschrieben ist. Dies sind extrem wichtige Informationen, und in 99 von 100 Fällen ist der Bugreport ohne sie wertlos. Sehr oft erhalten wir Fragen wie „Warum funktioniert das bei mir nicht?“. Dann stellen wir fest, dass die angeforderte Funktionalität in der betreffenden MySQL-Version gar nicht implementiert war oder dass ein in einem Report beschriebener Bug in einer neueren MySQL-Version bereits behoben ist. Fehler sind häufig plattformspezifisch. In solchen Fällen ist es praktisch unmöglich für uns, irgendetwas zu beheben, wenn wir weder das Betriebssystem noch die Versionsnummer der Plattform kennen.
Wenn Sie MySQL aus dem Quellcode kompiliert haben, denken Sie bitte auch daran, Angaben zu Ihrem Compiler hinzuzufügen, sofern dies für das Problem relevant ist. Häufig finden Benutzer Bugs in Compilern und glauben dann, dass das Problem MySQL-spezifisch ist. Die meisten Compiler werden fortlaufend weiterentwickelt und von Version zu Version besser. Um zu ermitteln, ob Ihr Problem von Ihrem Compiler abhängt, müssen wir wissen, welchen Compiler Sie verwendet haben. Beachten Sie, dass jedes Kompilierungsproblem als Bug betrachtet und entsprechend gemeldet werden sollte.
Wenn ein Programm eine Fehlermeldung erzeugt, ist es sehr wichtig, auch diese Meldung in Ihrem Report zu erwähnen. Wenn wir versuchen, Erkundigungen in den Archiven einzuziehen, dann ist es am besten, wenn Sie die Fehlermeldung exakt so angeben, wie das Programm sie erzeugt hat. (Beachten Sie im Zweifelsfall auch die Groß-/Kleinschreibung.) Am besten kopieren Sie die gesamte Fehlermeldung über die Zwischenablage in Ihren Report. Versuchen Sie bitte nicht, die Fehlermeldung aus dem Gedächtnis zu rekonstruieren.
Wenn Sie ein Problem in Zusammenhang mit Connector/ODBC (MyODBC) haben, versuchen Sie bitte, eine Trace-Datei zu erzeugen, und schicken diese mit Ihrem Report. Siehe auch Abschnitt 25.1.7.2, „Melden von MyODBC-Problemen und -Fehlern“.
Wenn Ihr Report lange Abfrageausgabezeilen aus Testfällen enthält,
die Sie mit dem Befehlszeilen-Tool mysql
ausgeführt haben, dann können Sie die Leserlichkeit der Ausgabe
mit der Option --vertical
oder dem Abschlusszeichen
\G
erhöhen. Das weiter unten folgende Beispiel
für EXPLAIN SELECT
demonstriert die Verwendung
von \G
.
Bitte legen Sie Ihrem Report die folgenden Angaben bei:
Die Versionsnummer der von Ihnen verwendeten MySQL-Distribution
(z. B. MySQL 5.0.19). Die Versionsnummer ermitteln Sie durch
Ausführen von mysqladmin version. Das
Programm mysqladmin finden Sie im Verzeichnis
bin
im MySQL-Installationsverzeichnis.
Den Hersteller und das Modell des Computers, auf dem das Problem aufgetreten ist.
Name und Version des Betriebssystems. Wenn Sie mit Windows
arbeiten, erhalten Sie Namen und Versionsnummer, indem Sie auf
das Arbeitsplatz-Symbol doppelklicken und dann den Eintrag
„Hilfe/Über Windows“ auswählen. Bei den meisten
UNIX-Derivaten gelangen Sie an diese Angaben, indem Sie den
Befehl uname -a
ausführen.
In bestimmten Fällen ist die Menge des (physischen und virtuellen) Speichers relevant. Geben Sie diese Werte im Zweifelsfall auch an.
Wenn Sie eine Quelldistribution der MySQL-Software verwenden, geben Sie Namen und Versionsnummer des verwendeten Compilers an. Im Falle einer Binärdistribution nennen Sie den Distributionsnamen.
Tritt das Problem während der Kompilierung auf, dann fügen Sie die exakten Fehlermeldungen sowie ein paar Zeilen Kontext im Bereich des problematischen Codes in der Datei hinzu, in dem der Fehler auftritt.
Wenn mysqld abstürzt, sollten Sie auch die Anweisung angeben, mit der mysqld zum Absturz gebracht wurde. Diese Information erhalten Sie normalerweise, wenn Sie mysqld mit aktiviertem Abfragelog starten und die Logdatei überprüfen, nachdem mysqld abgestürzt ist. Siehe auch Abschnitt E.1.5, „Logdateien benutzen, um Ursachen für Fehler in mysqld zu finden“.
Wenn eine Datenbanktabelle mit dem Problem in Zusammenhang
steht, geben Sie die Ausgabe der Anweisung SHOW CREATE
TABLE
im Bugreport an. Dies stellt eine sehr einfache Möglichkeit
dar, die Definition einer beliebigen Tabelle in der Datenbank zu
ermitteln. Mithilfe dieser Information können wir die
Situation, in der das Problem bei Ihnen auftrat, auf unseren
Systemen nachstellen.
db_name
.tbl_name
Bei leistungsspezifischen Bugs oder Problemen mit
SELECT
-Anweisungen sollten Sie außerdem die
Ausgabe von EXPLAIN SELECT ...
und zumindest
die Anzahl der Datensätze angeben, die die
SELECT
-Anweisung erzeugt. Ferner hinzufügen
sollten Sie die Ausgabe von SHOW CREATE TABLE
für jede
betroffene Tabelle. Je mehr Angaben Sie über die Umstände
machen, desto größer ist die Wahrscheinlichkeit, dass wir
Ihnen helfen können.
tbl_name
Nachfolgend finden Sie ein Beispiel für einen sehr guten
Bugreport. Die Anweisungen werden mit dem Befehlszeilen-Tool
mysql ausgeführt. Beachten Sie die
Verwendung des Abschlusszeichens \G
bei
Anweisungen, die andernfalls sehr lange, schwierig zu lesende
Ausgabezeilen erzeugen würden.
mysql>SHOW VARIABLES;
mysql>SHOW COLUMNS FROM ...\G
<output from SHOW COLUMNS>
mysql>EXPLAIN SELECT ...\G
<output from EXPLAIN>
mysql>FLUSH STATUS;
mysql>SELECT ...;
<A short version of the output from SELECT, including the time taken to run the query>
mysql>SHOW STATUS;
<output from SHOW STATUS>
Wenn während der Ausführung von mysqld ein Bug oder Problem auftritt, dann versuchen Sie, ein Eingabeskript hinzuzufügen, welches die Anomalie reproduziert. Dieses Skript sollte alle erforderlichen Quellcodedateien enthalten. Je exakter das Skript die betreffende Situation reproduzieren kann, umso besser. Wenn Sie einen reproduzierbaren Test erstellen können, sollten Sie diesen als Anhang an den Bugreport anhängen.
Können Sie kein Skript erstellen, dann sollten Sie Ihrem Report zumindest die Ausgabe von mysqladmin variables extended-status processlist hinzufügen, damit wir einige Anhaltspunkte dazu erhalten, wie Ihr System arbeitet.
Können Sie keinen Testfall mit nur wenigen Datensätzen
erstellen oder ist die Testtabelle zu groß, um in den
Bugreport eingefügt werden zu können (d. h., sie umfasst mehr
als zehn Datensätze), dann sollten Sie Ihre Tabellen mit
mysqldump speichern und eine
README
-Datei erstellen, die Ihr Problem
beschreibt. Erstellen Sie ein komprimiertes Archiv Ihrer Dateien
mithilfe von tar und gzip
oder zip und übertragen Sie das Archiv dann
via FTP an ftp://ftp.mysql.com/pub/mysql/upload/.
Tragen Sie das Problem danach in unsere Bugdatenbank unter
http://bugs.mysql.com/ ein.
Wenn Sie der Ansicht sind, dass der MySQL Server ein merkwürdiges Ergebnis für die Anweisung erzeugt, fügen Sie nicht nur dieses, sondern auch Ihre Ansicht bezüglich des von Ihnen erwarteten Ergebnisses und eine Beschreibung der Grundlage dieser Ansicht hinzu.
Wenn Sie ein Beispiel des Problems angeben, sollten Sie am besten Tabellennamen, Variablennamen usw. verwenden, die in Ihrer tatsächlichen Situation zum Einsatz kommen, statt neue Namen einzuführen. Das Problem könnte auch mit dem Namen einer Tabelle oder Variablen zusammenhängen. Solche Fälle mögen selten sein, aber besser ist es, auf der sicheren Seite zu stehen. Schließlich sollte es für Sie einfacher sein, ein Beispiel anzugeben, das Ihre tatsächlichen Umstände verwendet, und für uns ist dies in jedem Fall besser. Wenn Sie wollen, dass bestimmte Daten im Bugreport für Dritte unsichtbar bleiben, können Sie ihn via FTP an ftp://ftp.mysql.com/pub/mysql/upload/ übertragen. Sind die Daten wirklich derart geheim, dass Sie sie noch nicht einmal uns zeigen wollen, dann können Sie auch ein Beispiel unter Verwendung anderer Namen erstellen; dies stellt allerdings nur den letzten Ausweg dar.
Fügen Sie, sofern möglich, alle Optionen an, die Sie für die
betreffenden Programme angegeben hatten. Geben Sie etwa die
Optionen an, die Sie beim Start des Servers
mysqld verwenden, sowie auch solche, die Sie
bei der Ausführung von MySQL-Clientprogrammen verwendet haben.
Die Optionen für Programme wie mysqld und
mysql sowie für das Skript
configure sind für die Behebung von
Problemen häufig unentbehrlich, und es kann nie schaden, sie
hinzuzufügen. Wenn Ihr Problem in Zusammenhang mit einem
Programm steht, das in einer Sprache wie Perl oder PHP
geschrieben ist, fügen Sie bitte die Versionsnummer des
Sprachprozessors sowie die Versionen aller Module an, die das
Programm verwendet. Setzen Sie beispielsweise ein Perl-Skript
ein, das die Module DBI
und
DBD::mysql
benutzt, dann müssen Sie die
Versionsnummern von Perl, DBI
und
DBD::mysql
angeben.
Bezieht sich Ihre Frage auf das Berechtigungssystem, dann
führen Sie bitte die Ausgaben von
mysqlaccess und mysqladmin
reload sowie alle Fehlermeldungen an, die Sie beim
Verbindungsversuch erhalten. Wenn Sie Ihre Berechtigungen
testen, sollten Sie zunächst mysqlaccess
ausführen. Nachfolgend starten Sie mysqladmin reload
version und versuchen, eine Verbindung mit dem
problematischen Programm herzustellen. Das Programm
mysqlaccess finden Sie im Verzeichnis
bin
im MySQL-Installationsverzeichnis.
Wenn Sie einen Patch für einen Bug haben, fügen Sie ihn hinzu. Gehen Sie aber nicht davon aus, dass wir lediglich diesen Patch benötigen oder dass wir ihn verwenden können, wenn Sie bestimmte Angaben wie etwa Testfälle weglassen, die den Bug demonstrieren, den Sie mit Ihrem Patch beheben. Unter Umständen stellen wir Probleme bei Ihrem Patch fest oder verstehen ihn überhaupt nicht. In diesem Fall können wir ihn natürlich nicht verwenden.
Wenn wir den Zweck des Patches nicht exakt verifizieren können, verwenden wir ihn auch nicht. In diesem Fall sind Testfälle sehr hilfreich. Zeigen Sie, dass der Patch das Problem in allen Situationen behebt, die auftreten können. Können wir einen (ggf. auch seltenen) Fall ermitteln, in dem der Patch nicht funktioniert, dann ist er möglicherweise nutzlos.
Mutmaßungen bezüglich des Wesens, der Ursache oder der Abhängigkeiten eines Bugs sind in der Regel falsch. Sogar das MySQL-Team kann solche Dinge nicht erraten, sondern muss zunächst einmal mit einem Debugger die wirkliche Ursache des Bugs ermitteln.
Geben Sie in Ihrem Bugreport an, dass Sie das Referenzmaterial und das Mailarchiv überprüft haben, damit andere wissen, dass Sie zunächst versucht haben, das Problem selbst zu lösen.
Wenn das Problem darin besteht, dass Ihre Daten beschädigt zu
sein scheinen oder Sie Fehler erhalten, wenn Sie auf eine
bestimmte Tabelle zugreifen, dann sollten Sie Ihre Tabellen
zuerst überprüfen und dann versuchen, sie zu reparieren.
Hierzu verwenden Sie CHECK TABLE
und
REPAIR TABLE
oder aber
myisamchk. Siehe auch
Kapitel 5, Datenbankverwaltung.
Wenn Sie Windows verwenden, überprüfen Sie bitte den Wert von
lower_case_table_names
mit dem Befehl
SHOW VARIABLES LIKE 'lower_case_table_names'
.
Diese Variable beeinflusst, wie der Server die
Groß-/Kleinschreibung von Datenbank- und Tabellennamen
behandelt. Die Auswirkung auf einen gegebenen Wert sollte so
sein wie in Abschnitt 9.2.2, „Groß-/Kleinschreibung in Namen“,
beschrieben.
Wenn Fälle beschädigter Tabellen bei Ihnen häufig auftreten,
sollten Sie herausfinden, wann und warum dies passiert. In
diesem Fall enthält das Fehlerlog im MySQL-Datenverzeichnis
unter Umständen Informationen dazu, was geschehen ist. (Es
handelt sich um die Datei mit dem Suffix
.err
im Dateinamen.) Siehe auch
Abschnitt 5.12.1, „Die Fehler-Logdatei“. Bitte fügen Sie alle relevanten
Angaben aus dieser Datei in Ihrem Bugreport an. Normalerweise
sollte mysqld eine Tabelle
niemals zum Absturz bringen, sofern es
nicht während eines laufenden Updates terminiert wurde. Wenn
Sie erkennen können, warum mysqld terminiert
wird, dann ist es für uns viel einfacher, Ihnen einen Fix für
dieses Problem zur Verfügung zu stellen. Siehe auch
Abschnitt A.1, „Wie man feststellt, was Probleme verursacht“.
Laden Sie, sofern möglich, die aktuellste Version von MySQL Server herunter und installieren Sie sie. Überprüfen Sie dann, ob Ihr Problem auf diese Weise gelöst wird. Alle Versionen der MySQL-Software wurden umfassend getestet und sollten problemlos funktionieren. Wir achten bei unseren Entwicklungen auf größtmögliche Abwärtskompatibilität, d. h., Sie sollten problemlos zwischen verschiedenen MySQL-Versionen wechseln können. Siehe auch Abschnitt 2.1.2, „Welche MySQL-Version Sie benutzen sollten“.
Wenn Sie keinen Webzugang haben und einen Bug nicht auf
http://bugs.mysql.com/ melden können, erzeugen Sie
mit dem Skript mysqlbug einen Bugreport (oder
einen Report zu einem beliebigen anderen Problem).
mysqlbug unterstützt Sie bei der Erzeugung eines
Reports, denn ein Großteil der erforderlichen Informationen wird
automatisch ermittelt. Sollte jedoch etwas fehlen, dann fügen Sie
es Ihrer Meldung bitte hinzu. mysqlbug finden Sie
im Verzeichnis scripts
(Quelldistribution) bzw.
im Verzeichnis bin
unter Ihrem
MySQL-Installationsverzeichnis (Binärdistribution).
Dieser Abschnitt beschreibt das Verhältnis von MySQL zu den SQL-Standards von ANSI und ISO. MySQL weist eine Reihe von Erweiterungen gegenüber dem SQL-Standard auf; hier finden Sie Informationen darüber, welche Erweiterungen dies sind und wie Sie sie benutzen. Ferner sind Informationen zu den Funktionalitäten, die in MySQL fehlen, und dazu enthalten, wie Sie einige dieser Unterschiede umgehen können.
Der SQL-Standard wird seit 1986 fortlaufend entwickelt, und es existieren verschiedene Versionen. In diesem Handbuch bezeichnet „SQL-92“ den im Jahr 1992 veröffentlichten Standard, „SQL:1999“ die 1999 veröffentlichte Version und„SQL:2003“ die aktuelle Variante des Standards. Wendungen wie „der SQL-Standard“ oder „Standard-SQL“ werden generell zur Bezeichnung der aktuellen Version des SQL-Standards verwendet.
Eines unserer wichtigsten Anliegen in Bezug auf das Produkt
besteht darin, die Kompatibilität mit dem SQL-Standard zu
optimieren, ohne dabei Geschwindigkeit oder Zuverlässigkeit von
MySQL zu opfern. Wir scheuen nicht davor zurück, SQL mit
Erweiterungen zu ergänzen oder Nicht-SQL-Funktionalitäten zu
unterstützen, wenn dies den Nutzen von MySQL Server für einen
Großteil unserer Benutzer erheblich steigert. Die
HANDLER
-Schnittstelle ist ein Beispiel für
diese Strategie. Siehe auch Abschnitt 13.2.3, „HANDLER
“.
Wir werden auch weiterhin sowohl transaktionale als auch nichttransaktionale Datenbanken unterstützen, damit der unternehmenskritische Einsatz rund um die Uhr wie auch eine hohe Beanspruchung im Web- oder Protokollierungseinsatz möglich sind.
MySQL Server wurde ursprünglich für die Arbeit mit mittelgroßen Datenbanken (10 bis 100 Millionen Datensätze bzw. 100 Mbyte pro Tabelle) auf Kleincomputern entwickelt. Heute hingegen werden mit MySQL Server terabytegroße Datenbanken verarbeitet. Der Code kann aber auch in einer reduzierten Version kompiliert werden, die für mobile oder integrierte Geräte geeignet ist. Die kompakte Struktur des MySQL Servers ermöglicht Weiterentwicklungen in beiden Richtungen, ohne dass es im Source-Tree zu Konflikten kommt.
Derzeit streben wir keine Echtzeitunterstützung an, obwohl die Replikationsmerkmale von MySQL die wesentlichen Funktionalitäten bieten.
MySQL unterstützt Clustering für Hochverfügbarkeitsdatenbanken
mithilfe der NDBCluster
-Speicher-Engine. Siehe
auch Kapitel 16, MySQL Cluster.
Die XML-Funktionalität wird ab MySQL 5.1 implementiert. Diese Version unterstützt den W3C XPath-Standard bereits weitgehend. Im Zuge der Fortentwicklung von MySQL planen wir, die XML-Unterstützung weiter zu optimieren.
Unser Ziel ist es, die SQL-Standards von ANSI und ISO vollständig zu unterstützen, ohne Zugeständnisse bezüglich der Geschwindigkeit oder der Qualität des Codes zu machen.
Der MySQL Server kann in verschiedenen SQL-Modi betrieben werden und diese Modi auf unterschiedliche Weise für verschiedene Clients anwenden. Diese Funktionalität erlaubt es jeder Anwendung, den Betriebsmodus des Servers an die eigenen Anforderungen anzupassen.
Die SQL-Modi steuern Aspekte des Serverbetriebs, z. B. welche SQL-Syntax MySQL unterstützen soll und welche Art der Datengültigkeitsprüfungen durchzuführen ist. Dies erleichtert die Verwendung von MySQL in verschiedenen Umgebungen und in Verbindung mit anderen Datenbankservern.
Sie können den SQL-Standardmodus einstellen, indem Sie
mysqld mit der Option
--sql-mode="
starten. Ab MySQL 4.1 können Sie den Modus auch während der
Laufzeit ändern, indem Sie die Systemvariable
mode_value
"sql_mode
mit der Anweisung SET
[SESSION|GLOBAL]
sql_mode='
einstellen.
mode_value
'
Weitere Informationen zur Einstellung des SQL-Modus finden Sie in Abschnitt 5.2.5, „Der SQL-Modus des Servers“.
Sie können mysqld mithilfe der Startoption
--ansi
zur Ausführung im ANSI-Modus anweisen.
Die Ausführung des Servers im ANSI-Modus entspricht dem
Serverstart mit den folgenden Optionen:
--transaction-isolation=SERIALIZABLE --sql-mode=ANSI
Ab MySQL 4.1.1 können Sie den gleichen Effekt während der Laufzeit erzielen, indem Sie die folgenden beiden Anweisungen ausführen:
SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE; SET GLOBAL sql_mode = 'ANSI';
Sie können wie folgt überprüfen, dass das Einstellen der
Systemvariablen sql_mode
auf
'ANSI'
alle für den ANSI-Modus
relevanten SQL-Modusoptionen aktiviert:
mysql>SET GLOBAL sql_mode='ANSI';
mysql>SELECT @@global.sql_mode;
-> 'REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI'
Beachten Sie, dass die Ausführung des Servers im ANSI-Modus
mithilfe der Option --ansi
nicht ganz zum
gleichen Ergebnis führt wie die Einstellung
'ANSI'
für den SQL-Modus. Die
Option --ansi
betrifft den SQL-Modus und stellt
ferner die Stufe der Transaktionsisolierung ein. Vom Einstellen
des SQL-Modus auf 'ANSI'
hingegen
ist die Isolierungsstufe nicht betroffen.
Siehe auch Abschnitt 5.2.1, „Befehlsoptionen für mysqld“, und Abschnitt 1.9.2, „Auswahl der SQL-Modi“.
MySQL Server unterstützt einige Erweiterungen, die Sie in anderen Datenbankmanagementsystemen wahrscheinlich nicht finden werden. Beachten Sie in jedem Fall, dass, wenn Sie diese Erweiterungen verwenden, Ihr Code nicht auf andere SQL-Server portierbar ist. In manchen Fällen können Sie Code schreiben, der MySQL-Erweiterungen enthält, aber trotzdem portierbar ist; Sie müssen dann Kommentare in der folgenden Form verwenden:
/*! MySQL-specific code
*/
In diesem Fall verarbeitet MySQL Server den Code innerhalb des
Kommentars wie normale SQL-Anweisungen; andere SQL-Server
hingegen ignorieren die Erweiterungen. So erkennt MySQL Server
beispielsweise anders als andere Server das Schlüsselwort
STRAIGHT_JOIN
in der folgenden Anweisung:
SELECT /*! STRAIGHT_JOIN */ col1 FROM table1,table2 WHERE ...
Wenn Sie nach dem Zeichen ‘!
’ die
Versionsnummer angeben, wird die Syntax nur ausgeführt, wenn
die betreffende oder eine neuere MySQL-Version verwendet wird.
Das Schlüsselwort TEMPORARY
im folgenden
Kommentar wird nur von Servern ausgeführt, auf denen MySQL
3.23.02 oder höher läuft:
CREATE /*!32302 TEMPORARY */ TABLE t (a INT);
Die folgenden Beschreibungen listen MySQL-Erweiterungen nach Kategorie sortiert auf.
Organisation der Daten auf der Festplatte
MySQL Server ordnet jede Datenbank einem Unterverzeichnis des MySQL-Datenverzeichnisses zu. Tabellen innerhalb einer Datenbank entsprechen den Dateinamen im Datenbankverzeichnis. Dies hat einige Auswirkungen:
Die Groß-/Kleinschreibung bei Datenbank- und Tabellennamen in MySQL Server wird bei solchen Betriebssystemen unterschieden, die auch eine Unterscheidung der Groß-/Kleinschreibung bei den Dateinamen vornehmen (also etwa die Mehrzahl der Unix-Systeme). Siehe auch Abschnitt 9.2.2, „Groß-/Kleinschreibung in Namen“.
Sie können Standardsystembefehle zum Sichern,
Umbenennen, Verschieben, Löschen und Kopieren von
Tabellen verwenden, die von der
MyISAM
-Speicher-Engine verwaltet
werden. So können Sie eine
MyISAM
-Tabelle etwa umbenennen, indem
Sie die Namen der .MYD
-,
.MYI
- und
.frm
-Dateien ändern, denen die
Tabelle entspricht. (Nichtsdestoweniger ist die
Verwendung von RENAME TABLE
bzw.
ALTER TABLE ... RENAME
und die
Umbenennung der Dateien durch den Server vorzuziehen.)
Datenbank- und Tabellennamen dürfen keine Pfadtrennzeichen
(‘/
’,
‘\
’) enthalten.
Allgemeine Sprachsyntax
Standardmäßig dürfen Strings von den Zeichen
‘"
’ oder
‘'
’ umschlossen sein
und nicht nur von
‘'
’. (Wenn der
SQL-Modus ANSI_QUOTES
aktiviert ist,
dürfen die Strings nur vom Zeichen
‘'
’ umfasst sein;
Strings, die von ‘"
’
umfasst sind, interpretiert der Server als Bezeichner.)
Verwendung von ‘\
’ als
Escape-Zeichen in Strings.
In SQL-Anweisungen können Sie mithilfe der Syntax
db_name.tbl_name
auf Tabellen
aus anderen Datenbanken zugreifen. Einige SQL-Server
bieten die gleiche Funktionalität, nennen dies aber
User-Space
. MySQL Server unterstützt
Tabellenräume, wie sie etwa in der folgenden Anweisung
verwendet werden, nicht: CREATE TABLE
ralph.my_table...IN my_tablespace
.
SQL-Anweisungssyntax
Die Anweisungen ANALYZE TABLE
,
CHECK TABLE
, OPTIMIZE
TABLE
und REPAIR TABLE
.
Die Anweisungen CREATE DATABASE
,
DROP DATABASE
und ALTER
DATABASE
. Siehe auch
Abschnitt 13.1.3, „CREATE DATABASE
“,
Abschnitt 13.1.6, „DROP DATABASE
“, und
Abschnitt 13.1.1, „ALTER DATABASE
“.
Die Anweisung DO
.
EXPLAIN SELECT
ruft eine Beschreibung
dazu auf, wie Tabellen durch die Abfrageoptimierung
verarbeitet werden.
Die Anweisungen FLUSH
und
RESET
.
Die Anweisung SET
. Siehe auch
Abschnitt 13.5.3, „SET
“.
Die Anweisung SHOW
. Siehe auch
Abschnitt 13.5.4, „SHOW
“. Ab MySQL 5.0 lassen sich die
Angaben, die von vielen der MySQL-spezifischen
SHOW
-Anweisungen erzeugt werden, auf
standardkonformere Weise durch Verwendung von
SELECT
zur Abfrage von
INFORMATION_SCHEMA
erhalten. Siehe
auch Kapitel 22, Die Datenbank INFORMATION_SCHEMA
.
Verwenden von LOAD DATA INFILE
. In
vielen Fällen ist die Syntax kompatibel mit Oracles
LOAD DATA INFILE
. Siehe auch
Abschnitt 13.2.5, „LOAD DATA INFILE
“.
Verwendung von RENAME TABLE
. Siehe
auch Abschnitt 13.1.9, „RENAME TABLE
“.
Verwendung von REPLACE
anstelle der
Kombination DELETE
und
INSERT
. Siehe auch
Abschnitt 13.2.6, „REPLACE
“.
Verwendung von CHANGE
,
col_name
DROP
oder
col_name
DROP INDEX
, IGNORE
oder RENAME
in ALTER
TABLE
-Anweisungen. Verwendung mehrerer
ADD
-, ALTER
-,
DROP
- oder
CHANGE
-Klauseln in einer
ALTER TABLE
-Anweisung. Siehe auch
Abschnitt 13.1.2, „ALTER TABLE
“.
Verwendung von Indexnamen, Indizes für das Präfix
einer Spalte und Verwendung von INDEX
oder KEY
in CREATE
TABLE
-Anweisungen. Siehe auch
Abschnitt 13.1.5, „CREATE TABLE
“.
Verwendung von TEMPORARY
oder
IF NOT EXISTS
mit CREATE
TABLE
.
Verwendung von IF EXISTS
mit
DROP TABLE
und DROP
DATABASE
.
Die Möglichkeit, mehrere Tabellen mit einer einzigen
DROP TABLE
-Anweisung zu löschen.
Die Klauseln ORDER BY
und
LIMIT
der Anweisungen
UPDATE
und DELETE
.
Die Syntax INSERT INTO ... SET
.
col_name
= ...
Die Klausel DELAYED
der Anweisungen
INSERT
und
REPLACE
.
Die Klausel LOW_PRIORITY
der
Anweisungen INSERT
,
REPLACE
, DELETE
und UPDATE
.
Verwendung von INTO OUTFILE
oder
INTO DUMPFILE
in
SELECT
-Anweisungen. Siehe auch
Abschnitt 13.2.7, „SELECT
“.
Optionen wie STRAIGHT_JOIN
oder
SQL_SMALL_RESULT
in
SELECT
-Anweisungen.
In der Klausel GROUP BY
müssen Sie
nicht alle gewählten Spalten benennen. Hierdurch
erhalten Sie eine bessere Leistung bei einigen sehr
speziellen, aber trotzdem recht häufig auftretenden
Abfragen. Siehe auch
Abschnitt 12.11, „Funktionen und Modifizierer für die Verwendung in GROUP
BY
-Klauseln“.
Sie können ASC
und
DESC
mit GROUP BY
und nicht nur mit ORDER BY
festlegen.
Die Möglichkeit, Variablen in einer Anweisung mit dem
Zuweisungsoperator :=
festzulegen:
mysql>SELECT @a:=SUM(total),@b=COUNT(*),@a/@b AS avg
->FROM test_table;
mysql>SELECT @t1:=(@t2:=1)+@t3:=4,@t1,@t2,@t3;
Datentypen
Die Datentypen MEDIUMINT
,
SET
und ENUM
sowie
die verschiedenen BLOB
- und
TEXT
-Datentypen.
Die Datentypattribute AUTO_INCREMENT
,
BINARY
, NULL
,
UNSIGNED
und
ZEROFILL
.
Funktionen und Operatoren
Um Benutzern anderer SQL-Umgebungen den Umstieg auf MySQL zu erleichtern, unterstützt MySQL Server Aliase für eine Reihe von Funktionen. So unterstützen etwa alle String-Funktionen sowohl die Standard-SQL- als auch die ODBC-Syntax.
MySQL Server fasst die Operatoren ||
und &&
als logisches ODER
bzw. UND auf, wie man es von der Programmiersprache C
her kennt. In MySQL Server sind ||
und OR
Synonyme; Gleiches gilt für
&&
und
AND
. Aufgrund dieser praktischen
syntaktischen Eigenschaften unterstützt MySQL Server
den Standard-SQL-Operator ||
für die
String-Verkettung nicht; verwenden Sie stattdessen
CONCAT()
. Da
CONCAT()
eine beliebige Anzahl von
Argumenten entgegennimmt, ist es ganz einfach, die
Verwendung des Operators ||
in MySQL
Server nachzubilden.
Verwendung von COUNT(DISTINCT
, wobei
value_list
)value_list
mehr als ein
Element aufweist.
Standardmäßig wird bei String-Vergleichen die
Groß-/Kleinschreibung unterschieden, wobei die
Sortierreihenfolge vom aktuellen Zeichensatz bestimmt
wird; dieser ist vorgabeseitig latin1
(cp1252 West European). Wenn Sie das nicht wollen,
sollten Sie Ihre Spalten mit dem Attribut
BINARY
deklarieren oder
BINARY
zur Umwandlung verwenden, was
Vergleiche auf der Basis des zugrunde liegenden
Zeichensatzes (statt der lexikalischen Anordnung)
ermöglicht.
Der Operator %
ist ein Synonym zu
MOD()
. Infolgedessen ist
gleichbedeutend
mit
N
%
M
MOD(
.
N
,M
)%
wird für C-Programmierer und aus
Gründen der Kompatibilität mit PostgreSQL
unterstützt.
Die Operatoren =
,
<>
,
<=
,<
,
>=
,>
,
<<
,
>>
,
<=>
, AND
,
OR
und LIKE
können in Ausdrücken in der Ausgabespaltenliste (links
von FROM
) in
SELECT
-Anweisungen verwendet werden.
Ein Beispiel:
mysql> SELECT col1=1 AND col2=2 FROM my_table;
Die Funktion LAST_INSERT_ID()
gibt
den aktuellen AUTO_INCREMENT
-Wert
zurück. Siehe auch
Abschnitt 12.10.3, „Informationsfunktionen“.
LIKE
ist für numerische Werte
zulässig.
Die Operatoren REGEXP
and
NOT REGEXP
für erweiterte reguläre
Ausdrücke.
CONCAT()
oder
CHAR()
mit einem oder mehr als zwei
Argumenten. (In MySQL Server können diese Funktionen
eine variable Anzahl von Argumenten entgegennehmen.)
Die Funktionen BIT_COUNT()
,
CASE
, ELT()
,
FROM_DAYS()
,
FORMAT()
, IF()
,
PASSWORD()
,
ENCRYPT()
, MD5()
,
ENCODE()
,
DECODE()
,
PERIOD_ADD()
,
PERIOD_DIFF()
,
TO_DAYS()
und
WEEKDAY()
.
Verwendung von TRIM()
zum
Zurechtschneiden von Teil-Strings. Standard-SQL
unterstützt nur die Entfernung einzelner Zeichen.
Die GROUP BY
-Funktionen
STD()
, BIT_OR()
,
BIT_AND()
,
BIT_XOR()
und
GROUP_CONCAT()
. Siehe auch
Abschnitt 12.11, „Funktionen und Modifizierer für die Verwendung in GROUP
BY
-Klauseln“.
Eine priorisierte Liste mit Angaben dazu, wann MySQL Server durch neue Erweiterungen ergänzt wird, finden Sie im MySQL-Entwicklungsfahrplan unter http://dev.mysql.com/doc/mysql/en/roadmap.html.
Wir versuchen, MySQL Server möglichst nah an die ANSI-SQL- und ODBC-SQL-Standards zu halten. Allerdings führt MySQL Server manche Operationen in bestimmten Fällen anders aus:
Bei VARCHAR
-Spalten werden führende
Leerzeichen beim Speichern des Werts entfernt (dies wurde in
MySQL 5.0.3 behoben). Siehe auch Abschnitt A.8, „Bekannte Fehler und konzeptionelle Unzulänglichkeiten in MySQL“.
In manchen Fällen werden CHAR
-Spalten
stillschweigend in VARCHAR
-Spalten
konvertiert, wenn Sie eine Tabelle definieren oder ihre
Struktur ändern (dies wurde in MySQL 5.0.3 behoben).
Es gibt eine Reihe von Unterschieden zwischen den
Berechtigungssystemen von MySQL und Standard-SQL.
Beispielsweise werden in MySQL Berechtigungen für eine
Tabelle nicht automatisch widerrufen, wenn Sie die Tabelle
löschen. Um die Berechtigungen für die Tabelle zu
widerrufen, müssen Sie explizit eine
REVOKE
-Anweisung absetzen. Weitere
Informationen finden Sie unter Abschnitt 13.5.1.5, „REVOKE
“.
Die Funktion CAST()
unterstützt die
Umwandlung in REAL
oder
BIGINT
nicht. Siehe auch
Abschnitt 12.8, „Cast-Funktionen und Operatoren“.
Standard-SQL setzt voraus, dass eine
HAVING
-Klausel in einer
SELECT
-Anweisung auf Spalten in der
GROUP BY
-Klausel verweist. Dies ist erst
ab MySQL 5.0.2 möglich.
MySQL 4.1 und höher unterstützen Unterabfragen und
abgeleitete Tabellen. Eine „Unterabfrage“ ist
eine SELECT
-Anweisung, die mit einer
anderen Anweisung verschachtelt ist. Eine „abgeleitete
Tabelle“ (eine unbenannte Sicht) ist eine Unterabfrage
in der FROM
-Klausel einer anderen
Anweisung. Siehe auch Abschnitt 13.2.8, „Syntax von Unterabfragen“.
Bei MySQL-Versionen vor 4.1 können die meisten Unterabfragen mithilfe von Joins oder anderer Methoden umformuliert werden. Beispiele zu dieser Vorgehensweise finden Sie unter Abschnitt 13.2.8.11, „Umschreiben von Unterabfragen in Joins für frühere MySQL-Versionen“.
MySQL Server unterstützt die Sybase SQL-Erweiterung
SELECT ... INTO TABLE
nicht. Stattdessen
verwendet MySQL Server die Standard-SQL-Syntax INSERT
INTO ... SELECT
, mit der im Wesentlichen das Gleiche
erreicht werden kann. Siehe auch
Abschnitt 13.2.4.1, „INSERT ... SELECT
“. Ein Beispiel:
INSERT INTO tbl_temp2 (fld_id) SELECT tbl_temp1.fld_order_id FROM tbl_temp1 WHERE tbl_temp1.fld_order_id > 100;
Alternativ können Sie auch SELECT ... INTO
OUTFILE
oder CREATE TABLE ...
SELECT
verwenden.
Ab MySQL 5.0 können Sie SELECT ... INTO
mit benutzerdefinierten Variablen verwenden. Die gleiche
Syntax kann ebenfalls in gespeicherten Routinen mithilfe von
Cursorn und lokalen Variablen eingesetzt werden. Siehe auch
Abschnitt 19.2.7.3, „SELECT ... INTO
-Anweisung“.
Die Versionen 3.23-max und alle Versionen ab 4.0 von MySQL
Server unterstützen Transaktionen mit transaktionalen
InnoDB
- und
BDB
-Speicher-Engines.
InnoDB
bietet
vollständige
ACID
-Konformität. Siehe auch
Kapitel 14, Speicher-Engines und Tabellentypen. Informationen zu
InnoDB
-spezifischen Unterschieden zu
Standard-SQL bezüglich der Behandlung von Transaktionsfehlern
finden Sie in Abschnitt 14.2.15, „InnoDB
-Fehlerbehandlung“.
Die anderen nichttransaktionalen Speicher-Engines in MySQL
Server (wie etwa MyISAM
) folgen einem
anderen Muster der Datenintegrität, welches „atomare
Operationen“ genannt wird. Aus transaktionaler Sicht
arbeiten MyISAM
-Tabellen quasi immer im
Modus AUTOCOMMIT=1
. Atomare Operationen
bieten häufig vergleichbare Integrität bei besserer
Leistung.
Da MySQL Server beide Muster unterstützt, können Sie selbst entscheiden, ob Ihre Anwendungen besser mit der Geschwindigkeit atomarer Operationen oder der Verwendung der Transaktionsfunktionalität bedient sind. Diese Auswahl lässt sich pro Tabelle treffen.
Wie bereits angemerkt, fällt die Entscheidung zwischen
transaktionalen und nichttransaktionalen Speicher-Engines in
erster Linie aufgrund von Leistungsanforderungen.
Transaktionale Tabellen haben einen wesentlich höheren Bedarf
an Speicher- und Festplattenkapazität und benötigen zudem
mehr Prozessorleistung. Andererseits bieten transaktionale
Speicher-Engines wie InnoDB
auch viele
wesentliche Vorteile. Der modulare Aufbau von MySQL Server
erlaubt die gleichzeitige Nutzung verschiedener
Speicher-Engines zur Erfüllung unterschiedlicher Bedürfnisse
und für optimale Leistung in allen Situationen.
Wie aber nutzen Sie nun die Funktionen von MySQL Server zur
Aufrechterhaltung einer strikten Integrität auch bei
nichttransaktionalen MyISAM
-Tabellen, und
wie stehen diese Funktionen im Vergleich mit transaktionalen
Speicher-Engines da?
Wenn Ihre Anwendungen so geschrieben sind, dass sie in
kritischen Situationen von der Fähigkeit zum Aufruf von
ROLLBACK
anstelle von
COMMIT
abhängen, dann sind
Transaktionen praktischer. Mit Transaktionen lässt sich
auch sicherstellen, dass nicht abgeschlossene Updates oder
beschädigende Aktionen nicht in die Datenbank übertragen
werden; der Server hat die Möglichkeit, einen
automatischen Rollback durchzuführen, und Ihre Datenbank
ist gerettet.
Wenn Sie nichttransaktionale Tabellen verwenden, gestattet Ihnen MySQL Server in fast allen Fällen die Lösung potenzieller Probleme durch Integrierung einfacher Prüfungen vor Updates und Ausführung simpler Skripten, die die Datenbank auf Inkonsistenzen untersuchen und diese ggf. automatisch reparieren bzw. Warnmeldungen anzeigen. Beachten Sie, dass Sie Tabellen normalerweise mithilfe der MySQL-Logdatei oder einer zusätzlichen Logdatei reparieren, ohne dass die Datenintegrität hiervon beeinträchtigt würde.
In der Mehrzahl der Fälle lassen sich kritische
transaktionale Updates so umformulieren, dass sie atomar
sind. Allgemein gesprochen lassen sich alle
Integritätsprobleme, die sich mit Transaktionen lösen
lassen, mit LOCK TABLES
oder atomaren
Updates beseitigen. Hierdurch ist sichergestellt, dass ein
Vorgang serverseitig nicht abgebrochen wird – ein
Problem, welches bei transaktionalen Datenbanksystemen
häufig auftritt.
Um unabhängig davon, ob Sie transaktionale Tabellen verwenden, mit MySQL Server sicher arbeiten zu können, müssen Sie nur über Backups verfügen und die binäre Protokollierung aktiviert haben. Sind diese Voraussetzungen erfüllt, dann können Sie wie bei anderen transaktionalen Datenbanksystemen einen fehlerlosen Zustand jederzeit wiederherstellen. Sicherungskopien sollten immer vorhanden sein – egal, welches Datenbanksystem Sie verwenden.
Das transaktionale Muster hat Vor- und Nachteile. Viele Benutzer und Anwendungsentwickler wissen die Einfachheit zu schätzen, sich um Probleme „herumzuprogrammieren“, bei denen ein Abbruch erforderlich ist oder erforderlich zu sein scheint. Doch sogar dann, wenn Sie mit dem atomaren Operationsmuster noch nicht oder mit Transaktionen recht gut vertraut sind, sollten Sie den Geschwindigkeitsvorteil berücksichtigen, den nicht transaktionale Tabellen bieten; immerhin liegt die Verarbeitungsgeschwindigkeit drei- bis fünfmal höher als bei optimal programmierten transaktionalen Tabellen.
In Situationen, in denen die Integrität eine entscheidende
Rolle spielt, bietet MySQL Server die Zuverlässigkeit und
Integrität transaktionaler Tabellen auch für
nichttransaktionale Tabellen. Wenn Sie Tabellen mit
LOCK TABLES
sperren, werden alle Updates so
lange angehalten, bis die Integritätsprüfungen durchgeführt
wurden. Wenn Sie eine READ LOCAL
-Sperre (im
Gegensatz zur Schreibsperre) für eine Tabelle setzen, die
gleichzeitiges Einfügen am Tabellenende gestattet, ist das
Lesen ebenso möglich wie das Einfügen durch andere Clients.
Der Client, für den die Lesesperre gesetzt ist, sieht die neu
hinzugefügten Datensätze erst, wenn die Sperre aufgehoben
wird. Mit INSERT DELAYED
können Sie
Einfügungen schreiben, die in eine lokale Warteschlange
aufgenommen werden, bis die Sperren aufgehoben wurden. In
diesem Fall muss der Client nicht warten, bis der
Einfügevorgang abgeschlossen ist. Siehe auch
Abschnitt 7.3.3, „Gleichzeitige Einfügevorgänge“, und
Abschnitt 13.2.4.2, „INSERT DELAYED
“.
„Atomar“, wie wir es hier verstehen, hat nichts mit Zauberei zu tun. Damit ist lediglich gemeint, dass gewährleistet ist, dass, solange ein bestimmtes Update durchgeführt wird, dieses von keinem anderen Benutzer unterbrochen werden kann und dass es keinen automatischen Rollback gibt (was bei transaktionalen Tabellen immer möglich ist, wenn Sie nicht mit extremer Sorgfalt vorgehen). MySQL Server garantiert außerdem, dass es nicht zur Dirty Reads kommt.
Die folgende Liste erläutert ein paar Methoden für die Arbeit mit nichttransaktionalen Tabellen:
Schleifen, die Transaktionen erfordern, lassen sich
normalerweise mithilfe von LOCK TABLES
kopieren. Sie benötigen keine Cursor, um Datensätze
direkt zu aktualisieren.
Um die Verwendung von ROLLBACK
zu
umgehen, können Sie die folgende Strategie verwenden:
Sperren Sie alle Tabellen, auf die Sie zugreifen
wollen, mit LOCK TABLES
.
Prüfen Sie die Bedingungen, die wahr sein müssen, bevor Sie das Update durchführen.
Sind alle Bedingungen erfüllt, dann führen Sie das Update durch.
Heben Sie die Sperrungen Ihrer Tabellen mit
UNLOCK TABLES
auf.
Wenn auch nicht immer, so funktioniert dies in der Regel doch wesentlich schneller als die Verwendung von Transaktionen mit möglichen Rollbacks. Die einzige Situation, die mit dieser Lösung nicht bereinigt werden kann, liegt vor, wenn jemand die Threads während eines Updates beendet. In diesem Fall werden alle Sperren aufgehoben, aber unter Umständen wurden manche Updates nicht ausgeführt.
Sie können auch Funktionen zur Aktualisierung von Datensätzen in einer einzigen Operation verwenden. Mithilfe der folgenden Methode erhalten Sie eine sehr effiziente Anwendung:
Ändern Sie die Spalten relativ zum aktuellen Wert.
Aktualisieren Sie nur solche Spalten, die tatsächlich geändert wurden.
Wenn wir beispielsweise Kundendaten aktualisieren, dann
aktualisieren wir nur diejenigen Kundendaten, die sich
auch geändert haben, und überprüfen nachfolgend
lediglich, ob sich geänderte Daten oder Daten, die von
den geänderten Daten abhängen, verglichen mit dem
ursprünglichen Datensatz geändert haben. Die
Überprüfung auf geänderte Daten erfolgt mit der
WHERE
-Klausel in der
UPDATE
-Anweisung. Wurde der Datensatz
nicht aktualisiert, dann erhält der Client folgende
Mitteilung: „Some of the data you have changed has
been changed by another user.“ („Einige
Daten, die Sie geändert haben, wurden von einem anderen
Benutzer geändert.“) Dann werden der alte und der
neue Datensatz in einem Fenster zu Vergleichszwecken
angezeigt, damit der Benutzer entscheiden kann, welche
Version des Kundendatensatzes zukünftig verwendet werden
soll.
Auf diese Weise erhalten wir etwas, dass der Sperrung
einer Spalte ähnelt, tatsächlich aber noch besser ist,
da nur einige Spalten mithilfe von Werten aktualisiert
werden, die relativ zu den aktuellen Werten sind. Dies
wiederum bedeutet, dass eine typische
UPDATE
-Anweisung etwa so aussieht:
UPDATE tablename SET pay_back=pay_back+125; UPDATE customer SET customer_date='current_date', address='new address', phone='new phone', money_owed_to_us=money_owed_to_us-125 WHERE customer_id=id AND address='old address' AND phone='old phone';
Dies ist sehr effizient und funktioniert auch dann, wenn
ein anderer Client die Werte in den Spalten
pay_back
oder
money_owed_to_us
geändert hat.
In vielen Fällen wünschten sich Benutzer LOCK
TABLES
oder ROLLBACK
, um
eindeutige Bezeichner verwalten zu können. Dies lässt
sich jedoch weitaus effizienter ohne Sperrung oder
Rollback realisieren, indem man eine
AUTO_INCREMENT
-Spalte und entweder die
SQL-Funktion LAST_INSERT_ID()
oder die
C-API-Funktion mysql_insert_id()
verwendet. Siehe auch
Abschnitt 12.10.3, „Informationsfunktionen“, und
Abschnitt 24.2.3.36, „mysql_insert_id()
“.
Sie können die Notwendigkeit, eine Sperrung auf
Datensatzebene vorzunehmen, im Allgemeinen durch
entsprechende Programmierung umgehen. In manchen
Situationen jedoch ist diese Sperrung erforderlich, und
InnoDB
-Tabellen unterstützen sie auch.
Andernfalls können Sie bei
MyISAM
-Tabellen eine Flag-Spalte
verwenden und etwa Folgendes machen:
UPDATE tbl_name
SET row_flag=1 WHERE id=ID;
MySQL gibt 1
als Anzahl der betroffenen
Datensätze zurück, wenn der Datensatz gefunden wurde und
row_flag
im ursprünglichen Datensatz
nicht 1
war. Sie können sich das so
vorstellen, als ob MySQL Server die obige Anweisung wie
folgt geändert hätte:
UPDATE tbl_name
SET row_flag=1 WHERE id=ID AND row_flag <> 1;
Gespeicherte Prozeduren und Funktionen sind ab MySQL 5.0 implementiert. Siehe auch Kapitel 19, Gespeicherte Prozeduren und Funktionen.
Die grundlegende Trigger-Funktionalität ist ab MySQL 5.0.2 implementiert. Die Weiterentwicklung ist für MySQL 5.1 vorgesehen. Siehe auch Kapitel 20, Trigger.
Ab MySQL Server 3.23.44 unterstützt die
InnoDB
-Speicher-Engine die Überprüfung
von Fremdschlüsselbeschränkungen einschließlich
CASCADE
, ON DELETE
und
ON UPDATE
. Siehe auch
Abschnitt 14.2.6.4, „Fremdschlüssel-Beschränkungen“.
Bei anderen Speicher-Engines als InnoDB
verarbeitet MySQL Server zwar die FOREIGN
KEY
-Syntax in CREATE
TABLE
-Anweisungen, verwendet oder speichert sie aber
nicht. Zukünftig wird die Implementierung auf die Speicherung
dieser Information in der Tabellenspezifikationsdatei
erweitert, sodass sie mit mysqldump und
ODBC abgerufen werden kann. Zu einem späteren Zeitpunkt
werden Fremdschlüsselbeschränkungen auch für
MyISAM
-Tabellen implementiert werden.
Die Durchsetzung von Fremdschlüsseln bietet Datenbankentwicklern verschiedene Vorteile:
Setzt man einen guten Entwurf der Beziehungen voraus, dann erschweren Fremdschlüsselbeschränkungen es dem Programmierer, Inkonsistenzen in die Datenbank einzubringen.
Die zentralisierte Überprüfung der Beschränkungen durch den Datenbankserver macht eine Durchführung dieser Überprüfungen auf Anwendungsseite unnötig. Auf diese Weise wird die Möglichkeit beseitigt, dass verschiedene Anwendungen unter Umständen nicht alle Beschränkungen auf gleiche Weise überprüfen.
Dank der Verwendung kaskadierender Updates und Löschungen kann der Anwendungscode vereinfacht werden.
Korrekt entworfene Fremdschlüsselregeln unterstützen Sie bei der Dokumentation von Beziehungen zwischen Tabellen.
Denken Sie in jedem Fall daran, dass diese Vorteile auf Kosten einer zusätzlichen Belastung des Datenbankservers entstehen, da dieser die erforderlichen Überprüfungen durchführen muss. Weitere Überprüfungen durch den Server beeinträchtigen die Leistungsfähigkeit in so hohem Maße, dass sie für bestimmte Anwendungen vermieden werden sollten, sofern dies möglich ist. (Aus diesem Grund ist die Fremdschlüssellogik bei einigen größeren kommerziellen Anwendungen auch auf Anwendungsebene programmiert.)
MySQL stellt Datenbankprogrammierern die Auswahl des zu
verwendenden Ansatzes frei. Wenn Sie keine Fremdschlüssel
benötigen und die Mehrbelastung des Servers bei der
Durchsetzung der referenziellen Integrität vermeiden wollen,
können Sie stattdessen eine andere Speicher-Engine wie etwa
MyISAM
auswählen. (Die
MyISAM
-Engine bietet eine sehr gute
Performance für Anwendungen, die nur
INSERT
- und
SELECT
-Operationen durchführen. In solchen
Fällen weist die Tabelle keine Löcher in der Mitte auf, und
das Einfügen und Abrufen von Daten kann gleichzeitig
erfolgen. Siehe auch Abschnitt 7.3.2, „Themen, die Tabellensperren betreffen“.)
Wenn Sie sich dafür entscheiden, die Vorteile der Überprüfung der referenziellen Integrität nicht zu nutzen, dann sollten Sie die folgenden Gesichtspunkte in Ihre Überlegungen mit einbeziehen:
Fehlt die serverseitige Überprüfung der Fremdschlüsselbeziehung, dann muss die Anwendung sich selbst um die Aspekte der Beziehung kümmern. Sie muss beispielsweise dafür sorgen, dass Datensätze in der korrekten Reihenfolge in Tabellen eingetragen werden und dass keine verwaisten Unterdatensätze erstellt werden. Ferner muss sie in der Lage sein, Fehler, die bei Einfügevorgängen für mehrere Datensätze auftreten, beheben zu können.
Wenn ON DELETE
die einzige
referenzielle Integritätsfunktion ist, die eine Anwendung
benötigt, dann können Sie ab MySQL Server 4.0 einen
ähnlichen Effekt erzielen, indem Sie
DELETE
-Anweisungen über mehrere
Tabellen verwenden; so können Sie Datensätze aus
mehreren Tabellen mit nur einer Anweisung löschen. Siehe
auch Abschnitt 13.2.1, „DELETE
“.
Ein Workaround für das Fehlen von ON
DELETE
besteht darin, die passenden
DELETE
-Anweisungen in Ihrer Anwendung
hinzuzufügen, wenn Sie Datensätze aus einer Tabelle
löschen, die einen Fremdschlüssel beinhaltet. In der
Praxis kann dies häufig ebenso schnell sein wie die
Verwendung von Fremdschlüsseln – und ist zudem besser
portierbar.
Denken Sie daran, dass der Einsatz von Fremdschlüsseln unter Umständen zu Problemen führen kann:
Die Unterstützung von Fremdschlüsseln beseitigt eine Reihe von Schwierigkeiten bei der referenziellen Integrität, aber es ist nach wie vor erforderlich, Schlüsselbeziehungen mit Sorgfalt zu erstellen, damit zirkulare Regeln oder falsche Kombinationen kaskadierender Löschungen ausgeschlossen werden.
Es kommt häufig vor, dass ein Datenbankadministrator eine Beziehungstopologie erstellt, die die Wiederherstellung einzelner Tabellen aus einem Backup erschwert. (MySQL schwächt dieses Problem ab, indem es Ihnen die temporäre Deaktivierung von Fremdschlüsselüberprüfungen gestattet, wenn Sie eine Tabelle neu laden, die von anderen Tabellen abhängt. Siehe auch Abschnitt 14.2.6.4, „Fremdschlüssel-Beschränkungen“. Ab MySQL 4.1.1 erzeugt mysqldump Speicherauszugsdateien, die diesen Vorteil automatisch nutzen, wenn sie neu geladen werden.)
Beachten Sie, dass Fremdschlüssel in SQL zur Überprüfung
und Durchsetzung der referenziellen Integrität verwendet
werden, nicht jedoch zur Verknüpfung von Tabellen. Wenn Sie
mit einer SELECT
-Abfrage Ergebnisse aus
mehreren Tabellen abrufen wollen, tun Sie dies mithilfe eines
Joins dieser Tabellen:
SELECT * FROM t1, t2 WHERE t1.id = t2.id;
Siehe auch Abschnitt 13.2.7.1, „JOIN
“, und
Abschnitt 3.6.6, „Wie Fremdschlüssel verwendet werden“.
Die FOREIGN KEY
-Syntax ohne ON
DELETE ...
wird von ODBC-Anwendungen häufig zur
Erzeugung automatischer WHERE
-Klauseln
verwendet.
Views (einschließlich aktualisierbarer Views) sind ab MySQL Server 5.0.1 implementiert. Siehe auch Kapitel 21, Views.
Views sind praktisch, wenn es darum geht, Benutzern den Zugriff auf einen Satz von Beziehungen (Tabellen) so zu gestatten, als ob es sich nur um eine einzige Tabelle handeln würde, und ihren Zugriff auf diesen Satz zu beschränken. Views können auch zur Beschränkung des Zugriffs auf Datensätze (d. h. auf eine Teilmenge einer bestimmten Tabelle) verwendet werden. Für die Steuerung des Spaltenzugriffs können Sie auch das pfiffige Berechtigungssystem in MySQL Server benutzen. Siehe auch Abschnitt 5.8, „Allgemeine Sicherheitsaspekte und das MySQL-Zugriffsberechtigungssystem“.
Bei der Entwicklung der Views-Implementierung war und ist es unser ehrgeiziges Ziel, in den Grenzen von SQL eine möglichst vollständige Konformität mit „Codds Regel Nr. 6“ für relationale Datenbanksysteme zu erzielen, die da besagt: „Alle Views, die theoretisch aktualisierbar sind, sollten auch in der Praxis aktualisierbar sein“.
Standard-SQL verwendet die C-Syntax /* This is a
Comment */
für Kommentare, und auch MySQL Server
unterstützt diese Syntax. Ferner unterstützt MySQL
Erweiterungen dieser Syntax, die die Einbettung
MySQL-spezifischen SQL-Codes in den Kommentar gestatten. Siehe
auch Abschnitt 9.4, „Kommentar“.
Als Startkommentarsequenz benutzt Standard-SQL
‘--
’. MySQL Server setzt hingegen
‘#
’ als Startkommentarzeichen.
MySQL Server 3.23.3 und höher unterstützen zudem eine
Variante des Kommentarstils
‘--
’. Das bedeutet, dass der
Startkommentarsequenz ‘--
’ ein
Leerzeichen (oder ein Steuerzeichen wie etwa der
Zeilenwechsel) folgen muss. Das Leerzeichen ist erforderlich,
um Probleme mit automatisch erzeugten SQL-Abfragen zu
vermeiden, die Konstrukte wie das folgende verwenden, in dem
wir in !payment!
automatisch eine
Rechnungssumme einsetzen:
UPDATE account SET credit=credit-!payment!
Überlegen Sie einmal, was passieren würde, wenn
payment
einen negativen Wert wie etwa
-1
hätte:
UPDATE account SET credit=credit--1
credit--1
ist in SQL ein zulässiger
Ausdruck, aber ‘--
’ wird als
Start eines Kommentars interpretiert – ein Teil des
Ausdrucks wird also verworfen! Das Ergebnis ist eine
Anweisung, die eine vollständig andere Bedeutung hat als
ursprünglich vorgesehen:
UPDATE account SET credit=credit
Diese Anweisung erzeugt überhaupt keine Werteänderung! So
lässt sich veranschaulichen, dass es erhebliche Folgen haben
könnte, wenn man ‘--
’ als
Startkommentarsequenz zulassen würde.
Wenn man unsere in MySQL 3.23.3 und höher vorhandene
Implementierung verwendet, bei der auf
‘--
’ zwingend ein Leerzeichen
folgen muss, damit die Startkommentarsequenz als solche
erkannt wird, ist credit--1
tatsächlich
sicher.
Eine weiteres Sicherheitsmerkmal besteht darin, dass der
Befehlszeilenclient mysql Zeilen ignoriert,
die mit ‘--
’ beginnen.
Die nachfolgenden Informationen sind nur von Bedeutung, wenn Sie eine MySQL-Version vor 3.23.3 verwenden:
Wenn Sie ein SQL-Skript, das Kommentare des Typs
‘--
’ enthält, als Textdatei
gespeichert haben, dann sollten Sie das Utility
replace wie folgt verwenden, um die
Kommentare so umzuwandeln, dass Sie das Zeichen
‘#
’ verwenden, bevor Sie das
Skript ausführen:
shell>replace " --" " #" < text-file-with-funny-comments.sql \
| mysql
db_name
Dies ist sicherer, als das Skript auf übliche Weise auszuführen:
shell> mysql db_name
< text-file-with-funny-comments.sql
Sie können die Skriptdatei auch „an Ort und
Stelle“ bearbeiten, damit die Kommentare des Typs
‘--
’ in
‘#
’-Kommentare umgewandelt
werden:
shell> replace " --" " #" -- text-file-with-funny-comments.sql
Mit folgendem Befehl machen Sie die Änderung rückgängig:
shell> replace " #" " --" -- text-file-with-funny-comments.sql
Siehe auch Abschnitt 8.17, „replace — Hilfsprogramm für String-Ersetzungen“.
MySQL erlaubt Ihnen die Verwendung sowohl von transaktionalen Tabellen, die Rollbacks unterstützen, als auch von nichttransaktionalen Tabellen ohne Rollback. Aus diesem Grund unterscheidet sich der Umgang mit Constraints in MySQL ein wenig von dem in anderen Datenbanksystemen. Wir müssen den Fall beschreiben, der vorliegt, wenn Sie eine große Menge von Datensätzen in einer nichttransaktionalen Tabelle, bei der im Fehlerfall kein Rollback möglich ist, eingefügt oder aktualisiert haben.
Die Grundphilosophie besteht darin, dass MySQL Server versucht, einen Fehler für alle Probleme zu generieren, die während der Verarbeitung einer auszuführenden Anweisung erkannt wurden; gleichzeitig wird versucht, den fehlerfreien Status in Bezug auf alle Fehler wiederherzustellen, die während der Ausführung der Anweisung auftreten. Das lässt sich in den meisten, jedoch nicht in allen Fällen realisieren.
Wenn ein Fehler auftritt, hat MySQL zwei Optionen: Es kann die Ausführung der Anweisung abbrechen oder das Problem bestmöglich beheben und dann fortfahren. Standardmäßig verfolgt der Server die zweite Option. Dies bedeutet beispielsweise, dass der Server unzulässige Werte automatisch auf die nächstgelegenen zulässigen Werte verschiebt.
Es gibt mehrere SQL-Modusoptionen, die eine bessere Kontrolle der Handhabung unzulässiger Datenwerte und der Frage gestatten, ob die Ausführung einer Anweisung im Fehlerfall fortgeführt oder abgebrochen werden soll. Mithilfe dieser Optionen können Sie MySQL Server so konfigurieren, dass es auf eine traditionellere Weise agiert, die anderen Datenbanksystemen ähnelt, bei denen unzulässige Eingaben nicht angenommen werden. Der SQL-Modus kann global beim Serverstart eingestellt werden und betrifft dann alle Clients. Einzelne Clients können den SQL-Modus während der Laufzeit einstellen; auf diese Weise kann jeder Client das Verhalten auswählen, welches für seine speziellen Anforderungen am geeignetsten ist. Siehe auch Abschnitt 5.2.5, „Der SQL-Modus des Servers“.
Die folgenden Abschnitte beschreiben, wie MySQL Server verschiedene Arten von Constraints handhabt.
Normalerweise tritt ein Fehler auf, wenn Sie versuchen, einen
Datensatz mit INSERT
bzw.
UPDATE
einzufügen oder zu aktualisieren,
und dadurch eine Unvereinbarkeit bezüglich eines
Primärschlüssels, eines eindeutigen Schlüssels oder eines
Fremdschlüssels erfolgen würde. Verwenden Sie eine
transaktionale Speicher-Engine wie InnoDB
,
dann macht MySQL die Anweisung automatisch rückgängig.
Nutzen Sie hingegen eine nichttransaktionale Speicher-Engine,
dann beendet MySQL die Verarbeitung der Anweisung bei dem
Datensatz, an dem der Fehler aufgetreten ist, und lässt alle
nachfolgenden Datensätze unverändert.
Für den Fall, dass Sie solche Unvereinbarkeiten ignorieren
wollen, unterstützt MySQL das Schlüsselwort
IGNORE
für INSERT
und
UPDATE
. In diesem Fall ignoriert MySQL
sämtliche Schlüsselunvereinbarkeiten und fährt mit der
Verarbeitung des nächsten Datensatzes fort. Siehe auch
Abschnitt 13.2.4, „INSERT
“, und Abschnitt 13.2.10, „UPDATE
“.
Informationen zur Anzahl der tatsächlich eingefügten oder
aktualisierten Datensätze erhalten Sie über die
C-API-Funktion mysql_info()
. Ab MySQL 4.1
können Sie auch die Anweisung SHOW
WARNINGS
verwenden. Siehe auch
Abschnitt 24.2.3.34, „mysql_info()
“, und
Abschnitt 13.5.4.25, „SHOW WARNINGS
“.
Derzeit unterstützen nur InnoDB
-Tabellen
Fremdschlüssel. Siehe auch
Abschnitt 14.2.6.4, „Fremdschlüssel-Beschränkungen“. Die
Fremdschlüsselunterstützung in
MyISAM
-Tabellen ist zur Implementierung in
MySQL 5.2 vorgesehen. Siehe auch Abschnitt 1.6, „MySQL-Roadmap“.
Vor MySQL 5.0.2 verzeiht MySQL unzulässige oder unzutreffende Dateneingaben und setzt diese nach der Eingabe auf zulässige Werte. Bei MySQL 5.0.2 und höher bleibt dies zwar auch das Standardverhalten, aber Sie können den SQL-Modus des Servers so ändern, dass ein traditionellerer Umgang mit solchen Daten gewählt wird: Der Server kann sie dann auch abweisen und die Anweisung abbrechen, in der sie auftreten. Abschnitt 5.2.5, „Der SQL-Modus des Servers“.
Dieser Abschnitt beschreibt das (nachsichtige) Standardverhalten von MySQL und den neueren strikten SQL-Modus sowie die Unterschiede zwischen diesen Modi.
Wenn Sie den strikten Modus nicht verwenden, dann wird, wann
immer Sie einen „falschen“ Wert in eine Spalte
einsetzen (z. B. eine NULL
in eine
NOT NULL
-Spalte oder einen zu großen
numerischen Wert in eine numerische Spalte), MySQL die Spalte
auf den „bestmöglichen“ Wert setzen, statt einen
Fehler zu erzeugen. Die folgenden Regeln beschreiben genauer,
wie dies funktioniert:
Wenn Sie versuchen, einen Wert außerhalb des zulässigen Bereichs in einer numerischen Spalte zu speichern, dann speichert MySQL Server stattdessen null, den kleinstmöglichen oder den größtmöglichen Wert – abhängig davon, welcher gültige Wert am nächsten liegt.
Bei Strings speichert MySQL entweder den Leer-String oder den Teil des Strings, der sich in der Spalte speichern lässt.
Wenn Sie in einer numerischen Spalte einen String speichern wollen, der nicht mit einer Zahl beginnt, dann speichert MySQL Server 0.
Mit ungültigen Werten für ENUM
- und
SET
-Spalten wird wie in
Abschnitt 1.9.6.3, „ENUM
- und SET
-Constraints“, beschrieben verfahren.
MySQL gestattet die Speicherung bestimmter unzulässiger
Werte in DATE
- und
DATETIME
-Spalten (z. B.
'2000-02-31'
oder
'2000-02-00'
). Der
Grundgedanke dahinter ist der, dass es nicht Aufgabe des
SQL-Servers sein kann, Datumsangaben auszuwerten. Wenn
MySQL einen Datumswert speichern und den exakt gleichen
Wert wieder abrufen kann, dann speichert MySQL ihn auch
wie eingegeben. Ist das Datum jedoch völlig falsch
(d. h., es kann nicht vom Server gespeichert werden),
dann wird stattdessen der spezielle
„Nulldatumswert“
'0000-00-00'
in der Spalte
abgelegt.
Wenn Sie NULL
in einer Spalte speichern
wollen, die keine NULL
-Werte
akzeptiert, dann erscheint bei
INSERT
-Anweisungen für einzelne
Datensätze ein Fehler. Bei
INSERT
-Anweisungen für mehrere
Datensätze oder INSERT INTO ...
SELECT
-Anweisungen hingegen speichert MySQL
Server den impliziten Vorgabewert für den Datentyp der
Spalte. In der Regel ist dies 0
bei
numerischen Typen, der Leer-String
(''
) bei String-Typen und der
„Nullwert“ für Datums- und Uhrzeittypen.
Implizite Vorgabewerte werden in
Abschnitt 11.1.4, „Vorgabewerte von Datentypen“, behandelt.
Wenn eine INSERT
-Anweisung keinen Wert
für eine Spalte angibt, fügt MySQL den Vorgabewert ein,
sofern die Spaltendefinition eine explizite
DEFAULT
-Klausel enthält. Ist eine
solche DEFAULT
-Klausel nicht in der
Definition enthalten, dann fügt MySQL den impliziten
Vorgabewert für den Datentyp der Spalte ein.
Der Grund für die Verwendung obiger Regeln im nicht strikten Modus ist, dass wir diese Bedingungen erst nach Beginn der Ausführung der betreffenden Anweisung überprüfen können. Tritt nach der Aktualisierung einiger Datensätze ein Problem auf, dann können wir nicht einfach einen Rollback durchführen, da die Speicher-Engine Rollbacks unter Umständen nicht unterstützt. Die Option, die Anweisung einfach zu beenden, wäre nachteilig; in diesem Fall wäre die Aktualisierung nämlich nur „zur Hälfte“ erfolgt, was das wohl schlimmste vorstellbare Szenario wäre. In einem solchen Fall ist es besser, das „Bestmögliche“ zu tun und dann fortzufahren, so als ob nichts gewesen wäre.
In MySQL 5.0.2 und höher können Sie eine strengere
Behandlung der Eingabewerte mithilfe der SQL-Modi
STRICT_TRANS_TABLES
oder
STRICT_ALL_TABLES
auswählen:
SET sql_mode = 'STRICT_TRANS_TABLES'; SET sql_mode = 'STRICT_ALL_TABLES';
STRICT_TRANS_TABLES
aktiviert den strikten
Modus für transaktionale Speicher-Engines und bis zu einem
gewissen Grad auch für nichttransaktionale Engines. Das
funktioniert wie folgt:
Bei transaktionalen Speicher-Engines wird bei Auftreten unzulässiger Werte in einer Anweisung die Ausführung dieser Anweisung abgebrochen und ein Rollback durchgeführt.
Bei nichttransaktionalen Speicher-Engines wird die
Anweisung abgebrochen, wenn der Fehler beim ersten
einzufügenden bzw. zu aktualisierenden Datensatz
auftritt. (Tritt der Fehler beim ersten Datensatz auf,
dann kann die Anweisung wie bei transaktionalen Tabellen
abgebrochen werden, ohne dass Änderungen in der Tabelle
erfolgt wären.) Fehler in nachfolgenden Datensätzen
brechen die Anweisung nicht ab, denn in der Tabelle wurden
bereits Änderungen vorgenommen. Stattdessen werden
unzulässige Datensätze korrigiert und Warnungen
(anstelle von Fehlern) erzeugt. Mit anderen Worten: Bei
STRICT_TRANS_TABLES
hat ein falscher
Wert zur Folge, dass MySQL einen Rollback aller bereits
durchgeführten Aktualisierungen vornimmt, sofern dies
ohne Änderungen in der Tabelle möglich ist. Wurde die
Tabelle jedoch bereits geändert, dann führen weitere
Fehler zu Korrekturen und Warnungen.
Für eine noch striktere Prüfung aktivieren Sie
STRICT_ALL_TABLES
. Dies entspricht
weitgehend STRICT_TRANS_TABLES
, nur führen
Fehler bei nichttransaktionalen Speicher-Engines hier dazu,
dass die Anweisung auch bei unzulässigen Daten im zweiten
oder allen folgenden Datensätzen abgebrochen wird. Das
bedeutet, dass, wenn bei einer nichttransaktionalen Tabelle im
Verlauf einer Einfüge- oder Aktualisierungsoperation für
mehrere Datensätze ein Fehler auftritt, nur eine
Teilaktualisierung erfolgt. Datensätze vor Auftreten des
Fehlers werden eingefügt bzw. aktualisiert, Datensätze nach
dem Fehler jedoch nicht. Um dieses Verhalten bei nicht
transaktionalen Tabellen zu vermeiden, verwenden Sie entweder
Anweisungen für einzelne Datensätze oder aber
STRICT_TRANS_TABLES
, sofern
Konvertierungswarnungen (statt Fehlern) akzeptabel sind. Um
Probleme bereits im Vorfeld zu vermeiden, sollten Sie zur
Überprüfung des Spalteninhalts nicht MySQL verwenden. Es ist
sicherer (und oft auch schneller), wenn die Anwendung
sicherstellt, dass sie nur zulässige Werte an die Datenbank
übermittelt.
Bei Auswahl eines strikten Modus können Sie die Behandlung
von Fehlern als Warnungen vorsehen, indem Sie INSERT
IGNORE
bzw. UPDATE IGNORE
statt
INSERT
oder UPDATE
ohne
IGNORE
verwenden.
ENUM
- und SET
-Spalten
stellen eine effiziente Möglickeit dar, Spalten zu
definieren, die nur eine festgelegte Wertemenge aufnehmen
können. Siehe auch Abschnitt 11.4.4, „Der Spaltentyp ENUM
“, und
Abschnitt 11.4.5, „Der Spaltentyp SET
“. Allerdings ermöglichen
ENUM
- und SET
-Spalten
vor MySQL 5.0.2 keine echten Constraints bei der Eingabe
ungültiger Daten:
ENUM
-Spalten haben immer einen
Vorgabewert. Wenn Sie keinen Vorgabewert angeben, dann ist
er NULL
für Spalten, die
NULL
unterstützen, andernfalls der
erste Aufzählungswert in der Spaltendefinition.
Fügen Sie einen falschen Wert in eine
ENUM
-Spalte ein oder erzwingen einen
Wert in einer ENUM
-Spalte mithilfe von
IGNORE
, dann wird dieser auf den
reservierten Aufzählungswert 0
gesetzt, der als Leer-String im String-Kontext angezeigt
wird.
Wenn Sie einen falschen Wert in eine
SET
-Spalte einfügen, wird dieser
falsche Wert ignoriert. Kann die Spalte beispielsweise die
Werte 'a'
,
'b'
und
'c'
enthalten, dann würde
der Versuch, 'a,x,b,y'
zuzuweisen, den Wert 'a,b'
zur Folge haben.
Ab MySQL 5.0.2 können Sie den Server so konfigurieren, dass
er den strikten SQL-Modus verwendet. Siehe auch
Abschnitt 5.2.5, „Der SQL-Modus des Servers“. Ist der strikte Modus
aktiviert, dann fungiert die Definition einer
ENUM
- oder SET
-Spalte
als Beschränkung für Werte, die in die Spalte eingegeben
werden. Bei Werten, die die folgenden Bedingungen nicht
erfüllen, tritt ein Fehler auf:
Ein ENUM
-Wert muss zu der Wertemenge
gehören, die in der Spaltendefinition aufgelistet ist,
oder ein internes numerisches Äquivalent eines Werts in
der Wertemenge sein. Der Wert darf nicht der Fehlerwert
(also 0 oder der Leer-String) sein. Bei einer Spalte, die
als
ENUM('a','b','c')
definiert ist, sind Werte wie etwa
''
,
'd'
oder
'ax'
unzulässig und werden
abgewiesen.
Ein SET
-Wert muss der Leer-String oder
ein Wert sein, der nur aus den in der Spaltendefinition
aufgeführten Werten besteht, die durch Kommata getrennt
sind. Bei einer Spalte, die als
SET('a','b','c')
definiert ist, sind Werte wie etwa
'd'
oder
'a,b,c,d'
unzulässig und
werden abgewiesen.
Fehler aufgrund ungültiger Werte können im strikten Modus
unterdrückt werden, indem Sie INSERT
IGNORE
bzw. UPDATE IGNORE
verwenden. In diesem Fall wird statt eines Fehlers eine
Warnung erzeugt. Bei ENUM
wird der Wert als
Fehlermitglied (0
) eingefügt. Bei
SET
wird der Wert wie vorgegeben
eingefügt, sofern nicht vorhandene ungültige Teil-Strings
gelöscht werden. So führt etwa
'a,x,b,y'
zum Wert
'a,b'
.
Inhaltsverzeichnis
Dieses Kapitel beschreibt, wie Sie sich MySQL beschaffen und installieren. Zunächst folgt eine Zusammenfassung der Vorgehensweise; die Details werden dann im weiteren Verlauf beschrieben. Wenn Sie MySQL nicht zum ersten Mal installieren, sondern eine vorhandene MySQL-Version auf eine neuere Version aktualisieren wollen, dann finden Sie weitere Informationen zur Vorgehensweise und zu Gesichtspunkten, die vor dem Upgrade beachtet werden müssen, in Abschnitt 2.10, „MySQL aktualisieren (Upgrade/Downgrade)“.
Ermitteln Sie, ob Ihre Plattform unterstützt wird. Bitte beachten Sie, dass nicht alle unterstützten Systeme gleichermaßen zur Ausführung von MySQL geeignet sind. Auf manchen Plattformen arbeitet MySQL robuster und effizienter als auf anderen. Weitere Informationen finden Sie in Abschnitt 2.1.1, „Betriebssysteme, die von MySQL unterstützt werden“.
Wählen Sie die zu installierende Distribution. Es sind verschiedene MySQL-Versionen verfügbar, die meisten davon in unterschiedlichen Distributionsformaten. Sie können zwischen fertig gepackten Distributionen mit binären (vorkompilierten) Programmen und dem Quellcode wählen. Entscheiden Sie sich im Zweifelsfall für eine binäre Distribution. Für Benutzer, die unsere aktuellsten Entwicklungen sehen und uns beim Testen des neuesten Codes helfen wollen, bieten wir auch einen öffentlichen Zugang zum aktuellen Source-Tree. Wie Sie bestimmen, welche Version und welchen Distributionstyp Sie verwenden sollten, erfahren Sie in Abschnitt 2.1.2, „Welche MySQL-Version Sie benutzen sollten“.
Laden Sie die Distribution herunter, die
Sie installieren wollen. Informationen zur
Vorgehensweise finden Sie in Abschnitt 2.1.3, „Woher man MySQL bekommt“. Um
die Integrität der Distribution zu überprüfen, gehen Sie vor
wie in Abschnitt 2.1.4, „Bestätigen der Paketintegrität mittels MD5-Prüfsummen oder
GnuPG
“,
beschrieben.
Installieren Sie die Distribution. Um MySQL aus einer binären Distribution zu installieren, gehen Sie vor wie in Abschnitt 2.2, „Schnelle Standardinstallation von MySQL“, beschrieben. Wenn Sie MySQL hingegen aus einer Quelldistribution oder aus dem aktuellen Entwicklungs-Source-Tree installieren, gehen Sie vor wie in Abschnitt 2.8, „Installation der Quelldistribution“, beschrieben.
Wenn Sie bei der Installation Probleme haben, finden Sie plattformspezifische Hinweise zu deren Beseitigung in Abschnitt 2.12, „Betriebssystemspezifische Anmerkungen“.
Führen Sie die nach der Installation erforderlichen Konfigurationsarbeiten durch. Lesen Sie nach der Installation von MySQL Abschnitt 2.9, „Einstellungen und Tests nach der Installation“. Dieser Abschnitt enthält wichtige Informationen dazu, wie Sie den einwandfreien Betrieb des MySQL Servers sicherstellen. Ferner ist dort beschrieben, wie Sie die bei der Installation erstellten MySQL-Benutzerkonten, die anfangs keine Passwörter aufweisen, bis zur Konfiguration von Passwörtern sichern. Die in diesem Abschnitt enthaltenen Informationen gelten unabhängig davon, ob Sie MySQL mithilfe einer Binär- oder einer Quelldistribution installieren.
Wenn Sie die MySQL-Benchmark-Skripten ausführen wollen, muss der Perl-Support für MySQL eingerichtet sein. Siehe auch Abschnitt 2.13, „Anmerkungen zur Perl-Installation“.
Vor der Installation von MySQL müssen Sie Folgendes tun:
Ermitteln Sie, ob MySQL auf Ihrer Plattform läuft.
Wählen Sie die zu installierende Distribution aus.
Laden Sie die Distribution herunter und überprüfen Sie die Integrität.
Dieser Abschnitt enthält Informationen, die für die Ausführung dieser Schritte erforderlich sind. Danach können Sie die Anweisungen in den nachfolgenden Abschnitten des Kapitels zur Installation der von Ihnen gewählten Distribution verwenden.
Dieser Abschnitt listet die Betriebssysteme auf, auf denen MySQL ausgeführt können werden sollte.
Wir verwenden GNU Autoconf, weswegen eine Portierung von MySQL auf alle modernen Systeme möglich ist, die einen C++-Compiler und eine funktionsfähige Implementierung von POSIX-Threads enthalten. (Die Thread-Unterstützung wird für den Server benötigt. Wenn Sie nur den Clientcode kompilieren wollen, benötigen Sie lediglich den C++-Compiler.) Wir selbst verwenden und entwickeln die Software in erster Linie auf Systemen unter Linux (SuSE und Red Hat), FreeBSD und Sun Solaris (Versionen 8 und 9).
Berichten zufolge lässt sich MySQL erfolgreich auf den nachfolgend aufgeführten Kombinationen aus Betriebssystem und Thread-Paket kompilieren. Beachten Sie, dass die native Thread-Unterstützung bei vielen Betriebssystemen nur in den jeweils aktuellsten Versionen funktioniert.
AIX 4.x, 5.x mit nativen Threads. Siehe auch Abschnitt 2.12.5.3, „Anmerkungen zu IBM-AIX“.
Amiga.
BSDI 2.x mit dem MIT-pthreads-Paket. Siehe auch Abschnitt 2.12.4.4, „Anmerkungen zu BSD/OS“.
BSDI 3.0, 3.1 und 4.x mit nativen Threads. Siehe auch Abschnitt 2.12.4.4, „Anmerkungen zu BSD/OS“.
Digital Unix 4.x mit nativen Threads. Siehe auch Abschnitt 2.12.5.5, „Anmerkungen zu Alpha-DEC-UNIX (Tru64)“.
FreeBSD 2.x mit dem MIT-pthreads-Paket. Siehe auch Abschnitt 2.12.4.1, „Anmerkungen zu FreeBSD“.
FreeBSD 3.x und 4.x mit nativen Threads. Siehe auch Abschnitt 2.12.4.1, „Anmerkungen zu FreeBSD“.
FreeBSD 4.x mit LinuxThreads. Siehe auch Abschnitt 2.12.4.1, „Anmerkungen zu FreeBSD“.
HP-UX 10.20 mit den DCE-Threads oder dem MIT-pthreads-Paket. Siehe auch Abschnitt 2.12.5.1, „Anmerkungen zu HP-UX Version 10.20“.
HP-UX 11.x mit den nativen Threads. Siehe auch Abschnitt 2.12.5.2, „Anmerkungen zu HP-UX Version 11.x“.
Linux 2.0+ mit LinuxThreads 0.7.1+ oder
glibc
2.0.7+ für verschiedene
CPU-Architekturen. Siehe auch Abschnitt 2.12.1, „Linux (alle Linux-Versionen)“.
Mac OS X. Siehe auch Abschnitt 2.12.2, „Anmerkungen zu Mac OS X“.
NetBSD 1.3/1.4 Intel und NetBSD 1.3 Alpha (erfordert GNU make). Siehe auch Abschnitt 2.12.4.2, „Anmerkungen zu NetBSD“.
Novell NetWare 6.0 und 6.5. Siehe auch Abschnitt 2.6, „Installation von MySQL unter NetWare“.
OpenBSD 2.5 mit nativen Threads. OpenBSD vor Version 2.5.x mit dem MIT-pthreads-Paket. Siehe auch Abschnitt 2.12.4.3, „Anmerkungen zu OpenBSD“.
OS/2 Warp 3, FixPack 29, und OS/2 Warp 4, FixPack 4. Siehe auch Abschnitt 2.12.6, „Anmerkungen zu OS/2“.
SCO OpenServer 5.0.X mit einer aktuellen Portierung des FSU-Pthreads-Pakets. Siehe auch Abschnitt 2.12.5.8, „Anmerkungen zu SCO UNIX und OpenServer 5.0.x“.
SCO OpenServer 6.0.x. Siehe auch Abschnitt 2.12.5.9, „Anmerkungen zu SCO OpenServer 6.0.x“.
SCO UnixWare 7.1.x. Siehe auch Abschnitt 2.12.5.10, „Anmerkungen zu SCO UnixWare 7.1.x und OpenUNIX 8.0.0“.
SGI Irix 6.x mit nativen Threads. Siehe auch Abschnitt 2.12.5.7, „Anmerkungen zu SGI Irix“.
Solaris 2.5 und höher mit nativen Threads auf SPARC und x86. Siehe auch Abschnitt 2.12.3, „Anmerkungen zu Solaris“.
SunOS 4.x mit dem MIT-pthreads-Paket. Siehe auch Abschnitt 2.12.3, „Anmerkungen zu Solaris“.
Tru64 Unix. Siehe auch Abschnitt 2.12.5.5, „Anmerkungen zu Alpha-DEC-UNIX (Tru64)“.
Windows 9x, Me, NT, 2000, XP und Windows Server 2003. Siehe auch Abschnitt 2.3, „Installation von MySQL unter Windows“.
Nicht alle Plattformen sind für die Ausführung von MySQL gleichermaßen geeignet. Die Eignung einer Plattform für einen unternehmenskritischen, stark beanspruchten MySQL Server wird von den folgenden Faktoren bestimmt:
Allgemeine Stabilität der Thread-Bibliothek. Auch auf Plattformen, die ansonsten einen exzellenten Ruf genießen, ist MySQL nur so stabil wie die aufgerufene Thread-Bibliothek – und zwar auch dann, wenn alles andere perfekt ist.
Die Funktionalität des Kernels und der Thread-Bibliothek bezüglich der optimalen Nutzung von SMP-Systemen (symmetrischen Multiprozessorsystemen). Mit anderen Worten: Wenn ein Prozess einen Thread erstellt, sollte dieser auf einem anderen Prozessor laufen können als der ursprüngliche Prozess.
Die Fähigkeit von Kernel und Thread-Bibliothek, mehrere
Threads auszuführen, die häufig ein Mutex für einen
kurzen kritischen Bereich ohne umfassende Kontextschalter
setzen, und aufzuheben. Wenn die Implementierung von
pthread_mutex_lock()
zu zurückhaltend
bei der Bereitstellung von Prozessorzeit ist, wird MySQL
hierdurch empfindlich gestört. Wird dieser Aspekt nicht
berücksichtigt, dann macht das Ergänzen zusätzlicher
Prozessoren MySQL tatsächlich langsamer.
Allgemeine Stabilität und Leistungsfähigkeit des Dateisystems.
Wenn Ihre Tabellen sehr groß werden, steht und fällt die Leistung mit der Fähigkeit des Dateisystems, mit großen Dateien nicht nur überhaupt, sondern sogar effizient umgehen zu können.
Unser eigenes Fachwissen hier bei MySQL AB bezüglich des jeweiligen Betriebssystems. Kennen wir eine Plattform gut, dann können wir plattformspezifische Optimierungen und Fehlerbehebungen bei der Kompilierung aktivieren. Außerdem können wir Informationen zur optimalen Konfiguration Ihres Systems für MySQL vermitteln.
Der Umfang der Tests, die wir intern für ähnliche Konfigurationen durchgeführt haben.
Die Anzahl der Benutzer, die MySQL erfolgreich auf Plattformen mit ähnlichen Konfigurationen verwenden. Ist diese Zahl groß, dann ist die Wahrscheinlichkeit plattformspezifischer Überraschungen eher gering.
Basierend auf diesen Kriterien sind die derzeit am besten für
die Ausführung von MySQL geeigneten Plattformen x86 mit SuSE
Linux (Kernel 2.4 oder 2.6) und ReiserFS (oder jede ähnliche
Linux-Distribution) und SPARC mit Solaris (2.7 bis 2.9). An
dritter Stelle kommt FreeBSD; wir hoffen aber, es in den Kreis
der Favoriten aufnehmen zu können, sobald die Thread-Bibliothek
optimiert wurde. Außerdem sind wir natürlich zuversichtlich,
irgendwann alle anderen Plattformen, auf denen MySQL derzeit
kompiliert und ausgeführt werden kann, aber noch nicht mit
derselben hohen Stabilität und Leistungsfähigkeit läuft, in
diese Runde aufnehmen zu können. Dies erfordert einigen Aufwand
unsererseits in Zusammenarbeit mit den Entwicklern der
Betriebssysteme und Bibliothekskomponenten, auf die MySQL
angewiesen ist. Wenn Sie an der Optimierung einer dieser
Komponenten interessiert sind, Einfluss auf deren Entwicklung
ausüben können und detailliertere Angaben dazu benötigen, was
MySQL für eine bessere Ausführung benötigt, dann senden Sie
eine E-Mail an die MySQL-Mailingliste
internals
. Siehe auch
Abschnitt 1.7.1, „Die MySQL-Mailinglisten“.
Bitte beachten Sie, dass es nicht Zweck des obigen Vergleichs ist, festzustellen, dass ein Betriebssystem generell besser oder schlechter ist als ein anderes. Die Rede ist hier ausschließlich von der Auswahl eines Betriebssystems für den ganz speziellen Zweck, MySQL auszuführen. Wenn man andere Schwerpunkte setzen würde, würde das Ergebnis des Vergleichs sicher auch anders ausfallen. In bestimmten Fällen besteht der Grund dafür, dass ein Betriebssystem für die Ausführung von MySQL besser geeignet ist als ein anderes, schlicht und einfach darin, dass wir mehr Aufwand in Tests und Optimierung einer bestimmten Plattform gesteckt haben. Wir geben hier unsere Beobachtungen wieder, um Ihnen bei der Entscheidung zu helfen, eine geeignete Plattform für MySQL auszuwählen.
Wenn Sie die Installation von MySQL vorbereiten, sollten Sie entscheiden, welche Version Sie benutzen. Die Entwicklung von MySQL erfolgt in mehreren Release-Serien, von denen Sie sich die für Ihre Zwecke geeignetste auswählen können. Wenn Sie sich für eine Version entschieden haben, können Sie ein Distributionsformat auswählen. Releases sind im Binär- und im Quellformat verfügbar.
Die erste zu treffende Entscheidung ist die, ob Sie einen (stabilen) Produktions-Release oder aber einen Entwicklungs-Release verwenden wollen. Im MySQL-Entwicklungsprozess koexistieren mehrere Release-Serien miteinander, die sich alle durch ihren Grad der Ausgereiftheit voneinander unterscheiden:
MySQL 5.1 ist die nächste Entwicklungs-Release-Serie. In ihr werden neue Funktionen implementiert. Alpha-Releases sind derzeit verfügbar und erlauben umfassende Tests durch interessierte Benutzer.
MySQL 5.0 ist die aktuelle Release-Serie für Produktionsumgebungen. Neue Releases erscheinen nur bei Vorhandensein von Bugfixes; neue Funktionalitäten werden nicht ergänzt, da sie die Stabilität beeinträchtigen könnten.
MySQL 4.1 ist die vorherige Release-Serie für Produktionsumgebungen. Neue Releases erscheinen hier, wenn kritische Bugs und Sicherheitslücken behoben werden. Bei dieser Serie werden keine wesentlichen neuen Funktionen mehr hinzugefügt.
MySQL 4.0 und 3.23 sind die alten stabilen Release-Serien für Produktionsumgebungen. Diese Versionen sind nun stillgelegt, d. h., neue Releases erscheinen nur, wenn extrem kritische, vorzugsweise sicherheitsrelevante Bugs behoben werden.
Wir halten ein endgültiges Einfrieren von Codes nicht für machbar, da dies Bugfixes und andere Fehlerbereinigungen, die erforderlich sind, unmöglich machen würde. Das von uns bevorzugte „Teileinfrieren“ erlaubt uns das Ergänzen von Kleinigkeiten, die sich nicht auf die Einsatzfähigkeit eines Produktions-Releases auswirken sollten. Natürlich pflanzen sich wesentliche Bugfixes in früheren Serien auch auf ihre jeweiligen Nachfolger fort.
Wenn Sie MySQL zum ersten Mal verwenden oder es auf ein System portieren wollen, für das keine binäre Distribution verfügbar ist, empfehlen wir Ihnen normalerweise, die Produktions-Release-Serie zu verwenden. Derzeit ist dies MySQL 5.0. Alle MySQL-Releases – auch die der Entwicklungsserie – werden vor der Veröffentlichung mit den MySQL-Benchmarks und der umfangreichen Testsuite überprüft.
Wenn Sie ein älteres System verwenden und ein Upgrade durchzuführen beabsichtigen, gleichzeitig aber verhindern wollen, dass es während der Aktualisierung zu Problemen kommt, dann sollten Sie auf die aktuelle Version derselben Release-Serie aktualisieren, die Sie bereits verwenden (hierbei ist nur der letzte Teil der Versionsnummer höher als bei der von Ihnen verwendeten Version). Wir haben lediglich versucht, kritische Bugs zu beheben und kleine, relativ „sichere“ Änderungen an dieser Version vorzunehmen.
Wenn Sie neue Funktionen verwenden wollen, die nicht in der Produktions-Release-Serie vorhanden sind, können Sie sich auch für eine Version aus der Entwicklungsserie entscheiden. Beachten Sie, dass die Entwicklungs-Releases nicht so stabil sind wie die Produktions-Releases.
Wollen Sie die allerneuesten Quellcodes mit allen aktuellen Patches und Bugfixes einsetzen, dann können Sie eines unserer BitKeeper-Repositorys verwenden. Dies sind nicht „Releases“ im eigentlichen Sinne, sondern Vorabversionen des Codes, auf dem zukünftige Releases basieren werden.
Das MySQL-Benennungsschema verwendet Release-Namen, die aus drei Zahlen und einem Suffix bestehen. Dies kann etwa so aussehen: mysql-5.0.12-beta. Die Zahlen im Release-Namen sind wie folgt zu interpretieren:
Die erste Zahl (5) ist die Hauptversion und beschreibt das Dateiformat. Alle MySQL 5-Releases haben das gleiche Dateiformat.
Die zweite Zahl (0) ist der Release-Level. Zusammengefasst bilden Hauptversion und Release-Level die Nummer der Release-Serie.
Die dritte Zahl (12) ist die Versionsnummer innerhalb der Release-Serie. Diese wird bei jedem neuen Release um den Wert 1 erhöht. In der Regel sollten Sie immer die neueste Version in der von Ihnen gewählten Serie verwenden.
Bei kleineren Updates wird jeweils die letzte Zahl im Versions-String hochgezählt. Liegen wesentliche Neuerungen bei den Merkmalen oder kleinere Inkompatibilitäten mit vorherigen Versionen vor, dann wird die zweite Zahl im Versions-String hochgezählt. Ändert sich schließlich das Dateiformat, dann wird die erste Zahl erhöht.
Release-Namen enthalten auch ein Suffix, welches die Stabilitätsstufe für den Release angibt. Releases innerhalb einer Serie durchschritten eine bestimmte Abfolge von Suffixen, die jeweils anzeigen, wie sich die Stabilität erhöht. Mögliche Suffixe sind die folgenden:
alpha zeigt an, dass der Release neue Funktionen enthält, die noch nicht umfassend getestet wurden. Bekannte Bugs sollten im Abschnitt „News“ dokumentiert sein. Siehe auch Anhang D, MySQL-Änderungsverlauf (Change History). Die meisten Alpha-Releases implementieren neue Befehle und Erweiterungen. Die aktive Entwicklung, die auch umfassende Änderungen am Code beinhalten kann, erfolgt in der Alphaphase. Allerdings werden vor der Veröffentlichung eines Releases Tests durchgeführt.
beta bedeutet, dass der Release funktionsseitig abgeschlossen ist und der gesamte neue Code getestet wurde. Es werden keine wesentlichen neuen Funktionen und Merkmale mehr hinzugefügt. Es sollten auch keine kritischen Bugs mehr vorhanden sein. Eine Version wechselt vom Alpha- in den Betastatus, wenn mindestens einen Monat lang keine schweren Bugs mehr für die Alphaversion gemeldet wurden und wir nicht beabsichtigen, neue Merkmale hinzuzufügen, die die Zuverlässigkeit der zuvor implementierten Funktionen beeinträchtigen könnten.
Bei zukünftigen Beta-, Release-Candidate- oder Produktions-Releases erfolgen keine Änderungen mehr an APIs, extern sichtbaren Strukturen und Spalten für SQL-Anweisungen.
rc ist ein Release-Candidate, d. h. eine Betaversion, die bereits seit einiger Zeit verfügbar ist und offensichtlich stabil arbeitet. Es werden nur noch kleinere Fehlerkorrekturen vorgenommen (deswegen entspricht der Release-Candidate auch dem, was man früher als Gamma-Release bezeichnete).
Ist kein Suffix vorhanden, dann bedeutet dies, dass die Version bereits seit einiger Zeit an vielen verschiedenen Standorten läuft, ohne dass kritische nachvollziehbare Bugs gemeldet wurden (Ausnahme: plattformspezifische Bugs). Bei solchen Releases werden nur kritische Bugfixes implementiert. Eine solche Version nennen wir Produktions-Release (stabilen Release) oder auch „GA-Release“ (General Availability, allgemeine Verfügbarkeit).
MySQL verwendet ein Benennungsschema, welches sich geringfügig von dem anderer Produkte unterscheidet. In der Regel können Sie problemlos jede Version einsetzen, die bereits seit ein paar Wochen verfügbar ist, ohne durch eine neue Version innerhalb derselben Release-Serie ersetzt worden zu sein.
Alle MySQL-Releases werden mit unseren Standardtests und Benchmarks überprüft, damit gewährleistet ist, dass ihr Einsatz relativ sicher ist. Da die Standardtests im Laufe der Zeit so erweitert werden, dass alle zuvor gefundenen Bugs berücksichtigt werden, wird unsere Testsuite immer besser.
Alle Releases wurden zumindest mit den folgenden Tools getestet:
Einer internen Testsuite.
Das Verzeichnis mysql-test
enthält
ein umfangreiches Set mit Testfällen. Wir führen diese
Tests an praktisch jeder Serverbinärdatei durch. Weitere
Informationen zur Testsuite finden Sie in
Abschnitt 26.1.2, „MySQL-Testsystem“.
MySQL-Benchmarks.
Diese Reihe führt eine Anzahl gängiger Abfragen aus. Ferner ermöglicht sie zu bestimmen, ob der letzte Optimierungsstapel den Code tatsächlich beschleunigt hat. Siehe auch Abschnitt 7.1.4, „Die MySQL-Benchmark-Reihe“.
Crash-Me
-Test.
Dieser Test versucht zu ermitteln, welche Funktionen die Datenbank unterstützt und welche Fähigkeiten und Einschränkungen vorhanden sind. Siehe auch Abschnitt 7.1.4, „Die MySQL-Benchmark-Reihe“.
Wir testen außerdem die neueste MySQL-Version immer auf zumindest einem System in unserer internen Produktionsumgebung. Dabei stehen uns mehr als 100 Gbyte Daten zum Arbeiten zur Verfügung.
Nachdem Sie die zu installierende MySQL-Version gewählt haben, müssen Sie noch festlegen, ob eine binäre oder eine Quelldistribution für die Installation verwendet werden soll. In den meisten Fällen werden Sie sich wahrscheinlich für die Binärdistribution entscheiden, sofern es für Ihre Plattform eine solche gibt. Binärdistributionen sind für viele Plattformen im nativen Format verfügbar, z. B. RPM-Dateien für Linux oder DMG-Pakete für Mac OS X. Distributionen sind außerdem als ZIP-Archive oder komprimierte tar-Dateien erhältlich.
Die folgenden Gründe sprechen für die Verwendung einer Binärdistribution:
Binärdistributionen sind in der Regel einfacher zu installieren als Quelldistributionen.
Um unterschiedliche Benutzeranforderungen zu erfüllen, bieten wir zwei verschiedene Binärversionen an: eine kompilierte Fassung mit der Kernfunktionalität und eine weitere (MySQL-Max) mit einem erweiterten Feature-Set. Beide Versionen werden aus derselben Quelldistribution kompiliert. Alle nativen MySQL-Clients können mit Servern aus beiden MySQL-Versionen Verbindungen herstellen.
Die erweiterte MySQL-Binärdistribution ist am Suffix
-max
zu erkennen und mit den gleichen
Optionen konfiguriert wie mysqld-max.
Siehe auch Abschnitt 5.3, „mysqld-max, ein erweiterter mysqld-Server“.
Wenn Sie bei RPM-Distributionen die RPM-Datei
MySQL-Max
verwenden wollen, müssen Sie
zuerst das Standard-RPM MySQL-server
installieren.
Unter bestimmten Umständen kann es auch von Vorteil sein, MySQL aus einer Quelldistribution heraus zu installieren:
Sie wollen MySQL an einer expliziten Position installieren. Die Standardbinärdistributionen lassen sich an jeder Installationsposition ausführen, aber unter Umständen benötigen Sie noch mehr Flexibilität, um MySQL-Komponenten an jeder beliebigen Stelle abzulegen.
Sie wollen mysqld konfigurieren, um sicherzustellen, dass Funktionen, die unter Umständen nicht in den Standardbinärdistributionen enthalten sind, in jedem Fall vorhanden sind. Es folgt eine Liste der meistbenötigten Zusatzoptionen, die Sie verwenden können, um die Verfügbarkeit von Funktionen zu gewährleisten:
--with-innodb
--with-berkeley-db
(nicht auf allen
Plattformen verfügbar)
--with-libwrap
--with-named-z-libs
(erfolgt für
einige der Binärdistributionen)
--with-debug[=full]
Sie wollen mysqld ohne bestimmte Funktionen konfigurieren, die in den Standardbinärdistributionen enthalten sind. So werden Distributionen beispielsweise mit der Unterstützung für alle Zeichensätze kompiliert. Wenn Sie einen kleineren MySQL Server wünschen, können Sie diesen so kompilieren, dass nur die erforderlichen Zeichensätze unterstützt werden.
Sie haben einen speziellen Compiler (z. B.
pgcc
) oder wollen Compiler-Optionen
nutzen, die für Ihren Prozessor besser optimiert sind.
Binärdistributionen werden mit Optionen kompiliert, die
auf einer Vielzahl von Prozessoren derselben
Prozessorfamilie funktionieren sollten.
Sie wollen die aktuellsten Quelltexte aus einem der BitKeeper-Repositorys verwenden, um Zugang zu allen aktuellen Bugfixes zu haben. Wenn Sie beispielsweise einen Bug gefunden und diesen dem MySQL-Entwicklerteam gemeldet haben, dann wird der Bugfix in das Quellcode-Repository geschrieben, und Sie können dann dort darauf zugreifen. Der Bugfix erscheint in einem Release erst, wenn dieser tatsächlich veröffentlicht wird.
Sie wollen den C- oder C++-Code lesen (oder ändern), aus dem MySQL besteht. Zu diesem Zweck sollten Sie sich eine Quelldistribution besorgen, denn der Quellcode ist immer das ultimative Handbuch.
Quelldistributionen enthalten mehr Tests und Beispiele als Binärdistributionen.
MySQL entwickelt sich ziemlich schnell, und neue Entwicklungen wollen wir anderen MySQL-Benutzern möglichst umgehend bereitstellen. Deswegen erstellen wir immer dann einen neuen Release, wenn wir neue und nützliche Funktionen integriert haben, die auch für andere Benutzer nützlich oder notwendig sein könnten.
Außerdem versuchen wir Benutzern zu helfen, die nach Funktionen fragen, welche leicht zu implementieren sind. Wir achten darauf, was unsere lizenzierten Benutzer – und insbesondere die Kunden unseres Supports – wollen, und versuchen ihnen in dieser Hinsicht zu helfen.
Niemand ist gezwungen, einen neuen Release herunterzuladen. Der Abschnitt „News“ soll Ihnen dabei helfen zu ermitteln, ob im neuen Release etwas dabei ist, was Sie wirklich brauchen. Siehe auch Anhang D, MySQL-Änderungsverlauf (Change History).
Bei der Aktualisierung von MySQL halten wir uns an die folgenden Richtlinien:
Releases werden innerhalb jeder Serie veröffentlicht. Bei jedem Release ist die letzte Zahl in der Versionsnummer um 1 höher als beim vorherigen Release in der Serie.
Stabile Produktions-Releases erscheinen in der Regel ein- bis zweimal jährlich. Werden jedoch kleine Bugs gefunden, dann wird ein Release nur mit Bugfixes veröffentlicht.
Arbeits-Releases und Bugfixes für ältere Releases erscheinen normalerweise alle vier bis acht Wochen.
Binärdistributionen für bestimmte Plattformen werden von uns für Haupt-Releases erstellt. Binärdistributionen für andere Systeme werden von Dritten angefertigt, dies aber wahrscheinlich weniger häufig.
Bugfixes werden bereitgestellt, sobald kleine oder unkritische, aber ärgerliche Bugs erkannt und korrigiert wurden. Dieses Fixes sind in den BitKeeper-Repositorys sofort verfügbar und außerdem Bestandteil des nächsten Releases.
Wird durch Zufall ein schwerwiegender Bug in einem Release gefunden, dann ist es unser Grundsatz, diesen in einem neuen Release schnellstmöglich zu beheben. (Wir wünschten uns, andere Unternehmen würden das auch so handhaben!)
Wir verwenden viel Zeit und Mühe darauf, unsere Releases fehlerfrei zu machen. Bislang haben wir nicht eine einzige MySQL-Version veröffentlicht, die einen bekannten nachvollziehbaren schweren Bug aufwies (ein „schwerer“ Bug ist ein Umstand, der dazu führt, dass MySQL bei normaler Verwendung abstürzt, falsche Antworten für normale Abfragen erzeugt oder ein Sicherheitsproblem aufweist).
Wir haben alle offenen Probleme, Bugs und Streitfragen dokumentiert, die von strukturellen Entscheidungen abhängen. Siehe auch Abschnitt A.8, „Bekannte Fehler und konzeptionelle Unzulänglichkeiten in MySQL“.
Unser Ziel ist es, alle Bugs zu beheben, die behebbar sind, ohne eine stabile MySQL-Version weniger stabil machen zu müssen. In bestimmten Fällen bedeutet dies, dass wir ein Problem in den Entwicklungsversionen, nicht aber in der stabilen Produktionsversion beheben können. Natürlich dokumentieren wir solche Probleme, damit sie den Benutzern bekannt sind.
Es folgt eine Beschreibung unserer Vorgehensweise:
Wir überwachen das Auftreten von Bugs mithilfe unserer Kundensupportliste, der Bugdatenbank unter http://bugs.mysql.com/ und der externen MySQL-Mailinglisten.
Alle gemeldeten Bugs für die aktiven Versionen werden in die Bugdatenbank eingegeben.
Wenn wir einen Bug beheben, dann versuchen wir immer, einen Testfall dafür zu erstellen und diesen in unser Testsystem einzufügen, damit gewährleistet ist, dass der Bug nie wieder auftreten kann, ohne sofort erkannt zu werden. (Solche Testfälle gibt es für ca. 90 Prozent aller behobenen Bugs.)
Wir erstellen Testfälle für alle neuen Funktionen, die wir in MySQL ergänzen.
Bevor wir mit der Erstellung eines neuen MySQL-Releases beginnen, stellen wir sicher, dass alle gemeldeten nachvollziehbaren Bugs der betreffenden MySQL-Version (3.23.x, 4.0.x, 4.1.x, 5.0.x, 5.1.x usw.) behoben sind. Wenn ein Fehler aufgrund interner Strukturentscheidungen in MySQL nicht behoben werden kann, wird dies im Handbuch dokumentiert. Siehe auch Abschnitt A.8, „Bekannte Fehler und konzeptionelle Unzulänglichkeiten in MySQL“.
Wir erstellen einen Build für alle Plattformen, für die Binärdistributionen unterstützt werden, und verarbeiten alle mit unserer Testsuite und der Benchmark-Reihe.
Schlagen Testsuite oder Benchmark-Reihe bei einer Plattform fehl, dann wird hierfür keine Binärdistribution veröffentlicht. Ist das Problem in einem allgemeinen Fehler im Quellcode begründet, dann beheben wir es und erstellen den Build einschließlich aller Tests auf allen Systemen von Grund auf neu.
Erstellungs- und Testvorgänge benötigen etwa eine Woche. Erhalten wir während dieses Zeitraums eine Meldung zu einem schweren Bug (z. B. einem Bug, der einen Speicherauszug verursacht), dann beheben wir das Problem und starten die Erstellung von Neuem.
Wenn die Binärdistributionen auf
http://dev.mysql.com/
veröffentlicht wurden, senden wir eine Bekanntmachung an
die Mailinglisten mysql
und
announce
. Siehe auch
Abschnitt 1.7.1, „Die MySQL-Mailinglisten“. Die
Bekanntmachung enthält eine Liste aller Änderungen am
und aller bekannten Probleme mit dem Release. Der
Abschnitt Known
Problems (Bekannte Probleme) in den
Versionshinweisen wurde bislang nur bei einer Hand voll
Releases benötigt.
Damit unsere Benutzer möglichst umgehend auf die aktuellsten MySQL-Funktionen zugreifen können, versuchen wir, alle vier bis acht Wochen einen neuen MySQL-Release anzufertigen. Momentaufnahmen des Quellcodes werden täglich erstellt und sind unter http://downloads.mysql.com/snapshots.php verfügbar.
Wenn wir trotz aller Bemühungen nach der Freigabe eines
Releases die Meldung erhalten, dass ein kritisches Problem
für den Build einer bestimmten Plattform vorliegt, dann
beheben wir dieses sofort und erstellen einen neuen
'a'
-Release für die
betreffende Plattform. Weil so viele Leute MySQL benutzen,
sind Probleme schnell gefunden und behoben.
Unsere Leistungen bei der Erstellung stabiler Releases
sind recht gut. Unter den letzten 150 Releases waren es
weniger als zehn, für die wir einen neuen Build erstellen
mussten. In drei dieser Fälle wurde der Bug von einer
fehlerhaften glibc
-Bibliothek auf einem
unserer Erstellungssysteme verursacht, die ausfindig zu
machen uns recht viel Zeit gekostet hat.
Eine der Dienstleistungen von MySQL AB besteht in der Bereitstellung von MySQL-Binärdistributionen, die entweder auf unseren eigenen Systemen oder aber auf Systemen kompiliert wurden, bei denen uns Unterstützer von MySQL freundlicherweise Zugang zu ihren Computern gewährt haben.
Neben den Binärdateien in den plattformspezifischen
Paketformaten bieten wir für eine Anzahl von Plattformen auch
Binärdistributionen in Form komprimierter
tar-Dateien
(.tar.gz
-Dateien) an. Siehe auch
Abschnitt 2.2, „Schnelle Standardinstallation von MySQL“.
Die RPM-Distributionen für MySQL 5.1-Releases, die wir über die Website bereitstellen, werden von MySQL AB angefertigt.
Informationen zu Windows-Distributionen finden Sie in Abschnitt 2.3, „Installation von MySQL unter Windows“.
Diese Distributionen werden mithilfe des Skripts
Build-tools/Do-compile
erzeugt, das den
Quellcode kompiliert und das Binärarchiv
tar.gz
mithilfe von
scripts/make_binary_distribution erstellt.
Diese Binärdateien werden mit den folgenden Compilern und
Optionen konfiguriert und erstellt. Diese Informationen
können Sie auch abrufen, indem Sie die Variablen
COMP_ENV_INFO
und
CONFIGURE_LINE
im Skript
bin/mysqlbug jeder
tar-Binärdistributionsdatei abfragen.
Sollten Sie optimalere Optionen für einen der folgenden
configure
-Befehle haben, dann schicken Sie
diese an die MySQL-Mailingliste internals
.
Siehe auch Abschnitt 1.7.1, „Die MySQL-Mailinglisten“.
Wollen Sie eine Debugversion von MySQL kompilieren, dann
sollten Sie die Option--with-debug
oder
--with-debug=full
zu den folgenden
configure-Befehlen hinzufügen und ggf.
vorhandene -fomit-frame-pointer
-Optionen
entfernen.
Die folgenden Binärdateien werden auf den Entwicklungssystemen von MySQL AB erstellt:
Linux 2.4.xx x86 mit gcc 2.95.3:
CFLAGS="-O2 -mcpu=pentiumpro" CXX=gcc CXXFLAGS="-O2 -mcpu=pentiumpro -felide-constructors" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --enable-assembler --disable-shared --with-client-ldflags=-all-static --with-mysqld-ldflags=-all-static
Linux 2.4.x x86 mit icc (Intel C++ Compiler 8.1 oder höhere Releases):
CC=icc CXX=icpc CFLAGS="-O3 -unroll2 -ip -mp -no-gcc -restrict" CXXFLAGS="-O3 -unroll2 -ip -mp -no-gcc -restrict" ./configure --prefix=/usr/local/mysql --localstatedir=/usr/local/mysql/data --libexecdir=/usr/local/mysql/bin --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --enable-assembler --disable-shared --with-client-ldflags=-all-static --with-mysqld-ldflags=-all-static --with-embedded-server --with-innodb
Beachten Sie, dass Version 8.1 und höher des
Intel-Compilers separate Treiber für
„reines“ C (icc
) und C++
(icpc
) aufweisen; wenn Sie
icc Version 8.0 oder älter zur
Erstellung von MySQL verwenden, müssen Sie die
Einstellung CXX=icc
vornehmen.
Linux 2.4.xx Intel Itanium 2 mit ecc (Intel C++ Itanium Compiler 7.0):
CC=ecc CFLAGS="-O2 -tpp2 -ip -nolib_inline" CXX=ecc CXXFLAGS="-O2 -tpp2 -ip -nolib_inline" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile
Linux 2.4.xx Intel Itanium mit ecc (Intel C++ Itanium Compiler 7.0):
CC=ecc CFLAGS=-tpp1 CXX=ecc CXXFLAGS=-tpp1 ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile
Linux 2.4.xx alpha mit ccc
(Compaq C
V6.2-505/Compaq C++ V6.3-006):
CC=ccc CFLAGS="-fast -arch generic" CXX=cxx CXXFLAGS="-fast -arch generic -noexceptions -nortti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --with-mysqld-ldflags=-non_shared --with-client-ldflags=-non_shared --disable-shared
Linux 2.x.xx ppc mit gcc 2.95.4:
CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --localstatedir=/usr/local/mysql/data --libexecdir=/usr/local/mysql/bin --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared --with-embedded-server --with-innodb
Linux 2.4.xx s390 mit gcc 2.95.3:
CFLAGS="-O2" CXX=gcc CXXFLAGS="-O2 -felide-constructors" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared --with-client-ldflags=-all-static --with-mysqld-ldflags=-all-static
Linux 2.4.xx x86_64 (AMD64) mit gcc 3.2.1:
CXX=gcc ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared
Sun Solaris 8 x86 mit gcc 3.2.3:
CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --localstatedir=/usr/local/mysql/data --libexecdir=/usr/local/mysql/bin --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared --with-innodb
Sun Solaris 8 SPARC mit gcc 3.2:
CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --enable-assembler --with-named-z-libs=no --with-named-curses-libs=-lcurses --disable-shared
Sun Solaris 8 SPARC (64-Bit) mit gcc 3.2:
CC=gcc CFLAGS="-O3 -m64 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -m64 -fno-omit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --with-named-z-libs=no --with-named-curses-libs=-lcurses --disable-shared
Sun Solaris 9 SPARC mit gcc 2.95.3:
CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --enable-assembler --with-named-curses-libs=-lcurses --disable-shared
Sun Solaris 9 SPARC mit cc-5.0
(Sun
Forte 5.0):
CC=cc-5.0 CXX=CC ASFLAGS="-xarch=v9" CFLAGS="-Xa -xstrconst -mt -D_FORTEC_ -xarch=v9" CXXFLAGS="-noex -mt -D_FORTEC_ -xarch=v9" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --enable-assembler --with-named-z-libs=no --enable-thread-safe-client --disable-shared
IBM AIX 4.3.2 ppc mit gcc 3.2.3:
CFLAGS="-O2 -mcpu=powerpc -Wa,-many " CXX=gcc CXXFLAGS="-O2 -mcpu=powerpc -Wa,-many -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --with-named-z-libs=no --disable-shared
IBM AIX 4.3.3 ppc mit xlC_r
(IBM Visual
Age C/C++ 6.0):
CC=xlc_r CFLAGS="-ma -O2 -qstrict -qoptimize=2 -qmaxmem=8192" CXX=xlC_r CXXFLAGS ="-ma -O2 -qstrict -qoptimize=2 -qmaxmem=8192" ./configure --prefix=/usr/local/mysql --localstatedir=/usr/local/mysql/data --libexecdir=/usr/local/mysql/bin --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --with-named-z-libs=no --disable-shared --with-innodb
IBM AIX 5.1.0 ppc mit gcc 3.3:
CFLAGS="-O2 -mcpu=powerpc -Wa,-many" CXX=gcc CXXFLAGS="-O2 -mcpu=powerpc -Wa,-many -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --with-named-z-libs=no --disable-shared
IBM AIX 5.2.0 ppc mit xlC_r
(IBM Visual
Age C/C++ 6.0):
CC=xlc_r CFLAGS="-ma -O2 -qstrict -qoptimize=2 -qmaxmem=8192" CXX=xlC_r CXXFLAGS="-ma -O2 -qstrict -qoptimize=2 -qmaxmem=8192" ./configure --prefix=/usr/local/mysql --localstatedir=/usr/local/mysql/data --libexecdir=/usr/local/mysql/bin --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --with-named-z-libs=no --disable-shared --with-embedded-server --with-innodb
HP-UX 10.20 pa-risc1.1 mit gcc 3.1:
CFLAGS="-DHPUX -I/opt/dce/include -O3 -fPIC" CXX=gcc CXXFLAGS="-DHPUX -I/opt/dce /include -felide-constructors -fno-exceptions -fno-rtti -O3 -fPIC" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --with-pthread --with-named-thread-libs=-ldce --with-lib-ccflags=-fPIC --disable-shared
HP-UX 11.00 pa-risc mit aCC
(HP ANSI
C++ B3910B A.03.50):
CC=cc CXX=aCC CFLAGS=+DAportable CXXFLAGS=+DAportable ./configure --prefix=/usr/local/mysql --localstatedir=/usr/local/mysql/data --libexecdir=/usr/local/mysql/bin --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared --with-embedded-server --with-innodb
HP-UX 11.11 pa-risc2.0 64-Bit mit aCC
(HP ANSI C++ B3910B A.03.33):
CC=cc CXX=aCC CFLAGS=+DD64 CXXFLAGS=+DD64 ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared
HP-UX 11.11 pa-risc2.0 32-Bit mit aCC
(HP ANSI C++ B3910B A.03.33):
CC=cc CXX=aCC CFLAGS="+DAportable" CXXFLAGS="+DAportable" ./configure --prefix=/usr/local/mysql --localstatedir=/usr/local/mysql/data --libexecdir=/usr/local/mysql/bin --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared --with-innodb
HP-UX 11.22 ia64 64-Bit mit aCC
(HP
aC++/ANSI C B3910B A.05.50):
CC=cc CXX=aCC CFLAGS="+DD64 +DSitanium2" CXXFLAGS="+DD64 +DSitanium2" ./configure --prefix=/usr/local/mysql --localstatedir=/usr/local/mysql/data --libexecdir=/usr/local/mysql/bin --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared --with-embedded-server --with-innodb
Apple Mac OS X 10.2 powerpc mit gcc 3.1:
CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared
FreeBSD 4.7 i386 mit gcc 2.95.4:
CFLAGS=-DHAVE_BROKEN_REALPATH ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --enable-assembler --with-named-z-libs=not-used --disable-shared
FreeBSD 4.7 i386 mit LinuxThreads mit gcc 2.95.4:
CFLAGS="-DHAVE_BROKEN_REALPATH -D__USE_UNIX98 -D_REENTRANT -D_THREAD_SAFE -I/usr/local/include/pthread/linuxthreads" CXXFLAGS="-DHAVE_BROKEN_REALPATH -D__USE_UNIX98 -D_REENTRANT -D_THREAD_SAFE -I/usr/local/include/pthread/linuxthreads" ./configure --prefix=/usr/local/mysql --localstatedir=/usr/local/mysql/data --libexecdir=/usr/local/mysql/bin --enable-thread-safe-client --enable-local-infile --enable-assembler --with-named-thread-libs="-DHAVE_GLIBC2_STYLE_GETHOSTBYNAME_R -D_THREAD_SAFE -I /usr/local/include/pthread/linuxthreads -L/usr/local/lib -llthread -llgcc_r" --disable-shared --with-embedded-server --with-innodb
QNX Neutrino 6.2.1 i386 mit gcc 2.95.3qnx-nto 20010315:
CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared
Die folgenden Binärdistributionen wurden auf Systemen von Dritten erstellt, die MySQL AB freundlicherweise von anderen Benutzern zur Verfügung gestellt wurden. Diese werden aus Gefälligkeit bereitgestellt; MySQL AB hat keine vollständige Kontrolle über diese Systeme, weswegen wir für Binärdistributionen, die auf ihnen erstellt wurden, nur eingeschränkten Support bieten können.
SCO Unix 3.2v5.0.7 i386 mit gcc 2.95.3:
CFLAGS="-O3 -mpentium" LDFLAGS=-static CXX=gcc CXXFLAGS="-O3 -mpentium -felide-constructors" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --with-named-z-libs=no --enable-thread-safe-client --disable-shared
SCO UnixWare 7.1.4 i386 mit CC 3.2:
CC=cc CFLAGS="-O" CXX=CC ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --with-named-z-libs=no --enable-thread-safe-client --disable-shared --with-readline
SCO OpenServer 6.0.0 i386 mit CC 3.2:
CC=cc CFLAGS="-O" CXX=CC ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --with-named-z-libs=no --enable-thread-safe-client --disable-shared --with-readline
Compaq Tru64 OSF/1 V5.1 732 alpha mit
cc/cxx
(Compaq C V6.3-029i/DIGITAL C++
V6.1-027):
CC="cc -pthread" CFLAGS="-O4 -ansi_alias -ansi_args -fast -inline speed -speculate all" CXX="cxx -pthread" CXXFLAGS="-O4 -ansi_alias -fast -inline speed -speculate all -noexceptions -nortti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --with-named-thread-libs="-lpthread -lmach -lexc -lc" --disable-shared --with-mysqld-ldflags=-all-static
SGI Irix 6.5 IP32 mit gcc 3.0.1:
CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared
FreeBSD/sparc64 5.0 mit gcc 3.2.1:
CFLAGS=-DHAVE_BROKEN_REALPATH ./configure --prefix=/usr/local/mysql --localstatedir=/usr/local/mysql/data --libexecdir=/usr/local/mysql/bin --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared --with-innodb
Die folgenden Kompilierungsoptionen wurden für Binärpakete verwendet, die MySQL AB in der Vergangenheit bereitgestellt hat. Diese Binärdistributionen werden nicht mehr aktualisiert. Die Kompilierungsoptionen werden zu Referenzzwecken an diese Stelle aufgelistet.
Linux 2.2.xx SPARC mit egcs 1.1.2:
CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --enable-assembler --disable-shared
Linux 2.2.x mit x686 mit gcc 2.95.2:
CFLAGS="-O3 -mpentiumpro" CXX=gcc CXXFLAGS="-O3 -mpentiumpro -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --enable-assembler --with-mysqld-ldflags=-all-static --disable-shared --with-extra-charsets=complex
SunOS 4.1.4 2 sun4c mit gcc 2.7.2.1:
CC=gcc CXX=gcc CXXFLAGS="-O3 -felide-constructors" ./configure --prefix=/usr/local/mysql --disable-shared --with-extra-charsets=complex --enable-assembler
SunOS 5.5.1 (und höher) sun4u mit egcs 1.0.3a oder 2.90.27 oder gcc 2.95.2 und höher:
CC=gcc CFLAGS="-O3" CXX=gcc CXXFLAGS="-O3 -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-low-memory --with-extra-charsets=complex --enable-assembler
SunOS 5.6 i86pc mit gcc 2.8.1:
CC=gcc CXX=gcc CXXFLAGS=-O3 ./configure --prefix=/usr/local/mysql --with-low-memory --with-extra-charsets=complex
BSDI BSD/OS 3.1 i386 mit gcc 2.7.2.1:
CC=gcc CXX=gcc CXXFLAGS=-O ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex
BSDI BSD/OS 2.1 i386 mit gcc 2.7.2:
CC=gcc CXX=gcc CXXFLAGS=-O3 ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex
AIX 4.2 mit gcc 2.7.2.2:
CC=gcc CXX=gcc CXXFLAGS=-O3 ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex
Informationen zur aktuellen MySQL-Version und Hinweise zum Download finden Sie auf unserer Downloadseite unter http://dev.mysql.com/downloads/. Eine vollständige und aktuelle Liste der Spiegelserver für den MySQL-Download finden Sie unter http://dev.mysql.com/downloads/mirrors.html. Dort erhalten Sie auch Hinweise dazu, wie Sie selbst einen MySQL-Spiegelserver anbieten können und wie Sie ausgefallene oder veraltete Spiegelserver melden.
Der Hauptspiegelserver ist über http://mirrors.sunsite.dk/mysql/ erreichbar.
Wenn Sie das für Ihre Zwecke geeignete MySQL-Paket heruntergeladen haben, sollten Sie, bevor Sie die Installation starten, sicherstellen, dass es intakt ist und nicht verändert wurde. Für diese Integritätsprüfung bietet MySQL drei Methoden an:
MD5-Prüfsummen
Kryptografiesignaturen unter Verwendung von
GnuPG
(GNU Privacy Guard)
die eingebaute RPM-Integritätsprüfmethode für RPM-Pakete
Die folgenden Abschnitte beschreiben, wie diese Methoden verwendet werden.
Wenn Sie feststellen, dass MD5-Prüfsumme oder GPG-Signaturen
nicht übereinstimmen, probieren Sie zunächst, das betreffende
Paket noch einmal von einem anderen Spiegelserver
herunterzuladen. Wenn Sie die Integrität des Pakets mehrfach
nicht erfolgreich verifizieren können, teilen Sie uns dies
unter Angabe des vollständigen Paketnamens und des verwendeten
Downloadservers via E-Mail an die Adresse
<webmaster@mysql.com>
oder
<build@mysql.com>
mit. Bitte melden Sie Probleme
mit dem Download nicht über das Bugmeldesystem.
Wenn Sie ein MySQL-Paket heruntergeladen haben, sollten Sie
sicherstellen, dass die zugehörige MD5-Prüfsumme mit der auf
den MySQL-Downloadseiten angegebenen Prüfsumme
übereinstimmt. Jedes Paket weist eine individuelle Prüfsumme
auf, die Sie mithilfe des folgenden Befehls abfragen können
(hierbei ist package_name
der Name
des heruntergeladenen Pakets):
shell> md5sum package_name
Beispiel:
shell> md5sum mysql-standard-5.1.5-alpha-linux-i686.tar.gz
aaab65abbec64d5e907dcd41b8699945 mysql-standard-5.1.5-alpha-linux-i686.tar.gz
Vergewissern Sie sich, dass die resultierende Prüfsumme (der angezeigte Hexadezimal-String) mit der Angabe übereinstimmt, die auf der Downloadseite unmittelbar unter dem betreffenden Paket angegeben ist.
Hinweis: Sie müssen die
Prüfsumme der Archivdatei (d. h. der
.zip
- oder
.tar.gz
-Datei) verifizieren, nicht die
Prüfsumme der Dateien, die im Archiv gespeichert sind.
Beachten Sie, dass nicht alle Betriebssysteme den Befehl
md5sum unterstützen. Bei manchen heißt er
einfach md5, bei anderen ist er überhaupt
nicht enthalten. Bei Linux ist er Teil des Pakets
GNU Text
Utilities, das für eine Vielzahl von Plattformen
verfügbar ist. Sie können den Quellcode auch unter
http://www.gnu.org/software/textutils/
herunterladen. Wenn Sie OpenSSL installiert haben, können Sie
stattdessen den Befehl openssl md5
package_name
verwenden.
Eine Windows-Implementierung des Befehls
md5 ist unter
http://www.fourmilab.ch/md5/
verfügbar. winMd5Sum ist ein grafisches
MD5-Prüfwerkzeug, das Sie sich unter
http://www.nullriver.com/index/products/winmd5sum
beschaffen können.
Eine andere Methode zur Überprüfung der Integrität und Authentizität eines Pakets besteht in der Verwendung kryptografischer Signaturen. Diese sind zuverlässiger, aber arbeitsaufwändiger als MD5-Prüfsummen.
Wir von MySQL AB signieren MySQL-Pakete für den Download mit GnuPG (GNU Privacy Guard). GnuPG ist eine Open-Source-Alternative zum bekannten Pretty Good Privacy (PGP) von Phil Zimmermann. Weitere Informationen zu GnuPG sowie zu dessen Download und Installation auf Ihrem System finden Sie unter http://www.gnupg.org/. Die meisten Linux-Distributionen werden mit standardmäßig installiertem GnuPG ausgeliefert. Weitere Informationen zu GnuPG finden Sie unter http://www.openpgp.org/.
Um die Signatur für ein bestimmtes Paket zu überprüfen,
müssen Sie sich zunächst eine Kopie des
GPG-Build-Schlüssels von MySQL AB beschaffen. Diese können
Sie unter http://www.keyserver.net/
herunterladen. Der erforderliche Schlüssel heißt
build@mysql.com
. Alternativ können Sie den
Schlüssel aus dem folgenden Text kopieren und direkt
einfügen:
Key ID: pub 1024D/5072E1F5 2003-02-03 MySQL Package signing key (www.mysql.com) <build@mysql.com> Fingerprint: A4A9 4068 76FC BD3C 4567 70C8 8C71 8D3B 5072 E1F5 Public Key (ASCII-armored): -----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1.0.6 (GNU/Linux) Comment: For info see http://www.gnupg.org mQGiBD4+owwRBAC14GIfUfCyEDSIePvEW3SAFUdJBtoQHH/nJKZyQT7h9bPlUWC3 RODjQReyCITRrdwyrKUGku2FmeVGwn2u2WmDMNABLnpprWPkBdCk96+OmSLN9brZ fw2vOUgCmYv2hW0hyDHuvYlQA/BThQoADgj8AW6/0Lo7V1W9/8VuHP0gQwCgvzV3 BqOxRznNCRCRxAuAuVztHRcEAJooQK1+iSiunZMYD1WufeXfshc57S/+yeJkegNW hxwR9pRWVArNYJdDRT+rf2RUe3vpquKNQU/hnEIUHJRQqYHo8gTxvxXNQc7fJYLV K2HtkrPbP72vwsEKMYhhr0eKCbtLGfls9krjJ6sBgACyP/Vb7hiPwxh6rDZ7ITnE kYpXBACmWpP8NJTkamEnPCia2ZoOHODANwpUkP43I7jsDmgtobZX9qnrAXw+uNDI QJEXM6FSbi0LLtZciNlYsafwAPEOMDKpMqAK6IyisNtPvaLd8lH0bPAnWqcyefep rv0sxxqUEMcM3o7wwgfN83POkDasDbs3pjwPhxvhz6//62zQJ7Q7TXlTUUwgUGFj a2FnZSBzaWduaW5nIGtleSAod3d3Lm15c3FsLmNvbSkgPGJ1aWxkQG15c3FsLmNv bT6IXQQTEQIAHQUCPj6jDAUJCWYBgAULBwoDBAMVAwIDFgIBAheAAAoJEIxxjTtQ cuH1cY4AnilUwTXn8MatQOiG0a/bPxrvK/gCAJ4oinSNZRYTnblChwFaazt7PF3q zIhMBBMRAgAMBQI+PqPRBYMJZgC7AAoJEElQ4SqycpHyJOEAn1mxHijft00bKXvu cSo/pECUmppiAJ41M9MRVj5VcdH/KN/KjRtW6tHFPYhMBBMRAgAMBQI+QoIDBYMJ YiKJAAoJELb1zU3GuiQ/lpEAoIhpp6BozKI8p6eaabzF5MlJH58pAKCu/ROofK8J Eg2aLos+5zEYrB/LsrkCDQQ+PqMdEAgA7+GJfxbMdY4wslPnjH9rF4N2qfWsEN/l xaZoJYc3a6M02WCnHl6ahT2/tBK2w1QI4YFteR47gCvtgb6O1JHffOo2HfLmRDRi Rjd1DTCHqeyX7CHhcghj/dNRlW2Z0l5QFEcmV9U0Vhp3aFfWC4Ujfs3LU+hkAWzE 7zaD5cH9J7yv/6xuZVw411x0h4UqsTcWMu0iM1BzELqX1DY7LwoPEb/O9Rkbf4fm Le11EzIaCa4PqARXQZc4dhSinMt6K3X4BrRsKTfozBu74F47D8Ilbf5vSYHbuE5p /1oIDznkg/p8kW+3FxuWrycciqFTcNz215yyX39LXFnlLzKUb/F5GwADBQf+Lwqq a8CGrRfsOAJxim63CHfty5mUc5rUSnTslGYEIOCR1BeQauyPZbPDsDD9MZ1ZaSaf anFvwFG6Llx9xkU7tzq+vKLoWkm4u5xf3vn55VjnSd1aQ9eQnUcXiL4cnBGoTbOW I39EcyzgslzBdC++MPjcQTcA7p6JUVsP6oAB3FQWg54tuUo0Ec8bsM8b3Ev42Lmu QT5NdKHGwHsXTPtl0klk4bQk4OajHsiy1BMahpT27jWjJlMiJc+IWJ0mghkKHt92 6s/ymfdf5HkdQ1cyvsz5tryVI3Fx78XeSYfQvuuwqp2H139pXGEkg0n6KdUOetdZ Whe70YGNPw1yjWJT1IhMBBgRAgAMBQI+PqMdBQkJZgGAAAoJEIxxjTtQcuH17p4A n3r1QpVC9yhnW2cSAjq+kr72GX0eAJ4295kl6NxYEuFApmr1+0uUq/SlsQ== =YJkx -----END PGP PUBLIC KEY BLOCK-----
Um den Schlüssel in Ihren eigenen öffentlichen
GPG-Schlüsselbund zu importieren, verwenden Sie gpg
--import. Haben Sie den Schlüssel beispielsweise
unter dem Dateinamen mysql_pubkey.asc
gespeichert, dann sieht der Importbefehl wie folgt aus:
shell> gpg --import mysql_pubkey.asc
Nachdem Sie den öffentlichen Schlüssel heruntergeladen und
importiert haben, laden Sie das gewünschte MySQL-Paket und
die entsprechende Signatur herunter (diese steht ebenfalls auf
der Downloadseite zur Verfügung). Die Signaturdatei hat den
gleichen Namen wie die Distributionsdatei und trägt die
Erweiterung .asc
. Ein Beispiel:
Distributionsdatei | mysql-standard-5.1.5-alpha-linux-i686.tar.gz |
Signaturdatei | mysql-standard-5.1.5-alpha-linux-i686.tar.gz.asc |
Stellen Sie sicher, dass beide Dateien im gleichen Verzeichnis gespeichert sind, und führen Sie dann den folgenden Befehl aus, um die Signatur der Distributionsdatei zu verifizieren:
shell> gpg --verify package_name
.asc
Beispiel:
shell> gpg --verify mysql-standard-5.1.5-alpha-linux-i686.tar.gz.asc gpg: Signature made Tue 12 Jul 2005 23:35:41 EST using DSA key ID 5072E1F5 gpg: Good signature from "MySQL Package signing key (www.mysql.com) <build@mysql.com>"
Die Meldung Good signature
(Signatur
korrekt) zeigt an, dass alles in Ordnung ist. Sie können alle
Warnungen vom Typ insecure memory
ignorieren, die unter Umständen angezeigt werden.
Weitere Informationen zum Umgang mit öffentlichen Schlüsseln finden Sie in der GPG-Dokumentation.
Bei RPM-Paketen ist keine separate Signatur vorhanden. RPM-Pakete enthalten vielmehr eine integrierte GPG-Signatur und eine MD5-Prüfsumme. Sie können ein Paket durch Ausführen des folgenden Befehls verifizieren:
shell> rpm --checksig package_name
.rpm
Beispiel:
shell> rpm --checksig MySQL-server-5.1.5-alpha-0.i386.rpm
MySQL-server-5.1.5-alpha-0.i386.rpm: md5 gpg OK
Hinweis: Wenn Sie RPM 4.1
verwenden und die Meldung (GPG) NOT OK (MISSING KEYS:
GPG#5072e1f5)
erhalten, obwohl Sie den öffentlichen
MySQL-Schlüssel zuerst in Ihren eigenen GPG-Schlüsselbund
importiert haben, dann müssen Sie den Schlüssel zuerst in
Ihren RPM-Schlüsselbund importieren. RPM 4.1 verwendet nicht
länger den GPG-Schlüsselbund (oder GPG selbst). Stattdessen
arbeitet es mit einem eigenen Schlüsselbund, da es eine
systemweite Anwendung ist, während der öffentliche
GPG-Schlüsselbund eine benutzerspezifische Datei ist. Um den
öffentlichen MySQL-Schlüssel in den RPM-Schlüsselbund zu
importieren, besorgen Sie sich den Schlüssel zunächst wie in
Abschnitt 2.1.4.2, „Signaturüberprüfung mit GnuPG
“,
beschrieben. Nachfolgend verwenden Sie den Befehl rpm
--import für den Schlüsselimport. Haben Sie den
öffentlichen Schlüssel beispielsweise unter dem Dateinamen
mysql_pubkey.asc
gespeichert, dann sieht
der Importbefehl wie folgt aus:
shell> rpm --import mysql_pubkey.asc
Wie Sie sich den öffentlichen MySQL-Schlüssel beschaffen,
lesen Sie in Abschnitt 2.1.4.2, „Signaturüberprüfung mit GnuPG
“.
Dieser Abschnitt beschreibt die standardmäßige Struktur der Verzeichnisse, die bei der Installation der von MySQL AB bereitgestellten Binär- oder Quelldistributionen erstellt werden. Distributionen anderer Anbieter verwenden unter Umständen andere Strukturen als die hier beschriebenen.
Bei MySQL 5.1 unter Windows heißt das
Standardinstallationsverzeichnis
C:\Programme\MySQL\MySQL Server
5.1
. (Manche Windows-Benutzer ziehen
eine Installation in C:\mysql
vor, da
dieses Verzeichnis früher einmal der Standardpfad war.
Allerdings bleibt auch in diesem Fall die Struktur der
Unterverzeichnisse dieselbe.) Das Installationsverzeichnis hat
die folgenden Unterverzeichnisse:
Verzeichnis | Verzeichnisinhalt |
bin | Clientprogramme und der mysqld-Server |
data | Logdateien, Datenbanken |
Docs | Dokumentation |
examples | Beispielprogramme und -skripten |
include | Include-Dateien (Header-Dateien) |
lib | Bibliotheken |
scripts | Hilfsprogrammskripten |
share | Fehlermeldungsdateien |
Installationen, die mit den Linux-RPM-Dateien von MySQL AB erstellt werden, erzeugen Dateien in den folgenden Systemverzeichnissen:
Verzeichnis | Verzeichnisinhalt |
/usr/bin | Clientprogramme und -skripten |
/usr/sbin | Der mysqld-Server |
/var/lib/mysql | Logdateien, Datenbanken |
/usr/share/doc/packages | Dokumentation |
/usr/include/mysql | Include-Dateien (Header-Dateien) |
/usr/lib/mysql | Bibliotheken |
/usr/share/mysql | Fehlermeldungs- und Zeichensatzdateien |
/usr/share/sql-bench | Benchmarks |
Unter Unix wird eine
tar-Binärdistributionsdatei installiert,
indem sie an der gewählten Installationsposition (meist
/usr/local/mysql
) entpackt wird. Dabei
werden die folgenden Unterverzeichnisse erstellt:
Verzeichnis | Verzeichnisinhalt |
bin | Clientprogramme und der mysqld-Server |
data | Logdateien, Datenbanken |
docs | Dokumentation, ChangeLog |
include | Include-Dateien (Header-Dateien) |
lib | Bibliotheken |
scripts | mysql_install_db |
share/mysql | Fehlermeldungsdateien |
sql-bench | Benchmarks |
Eine Quelldistribution wird installiert, nachdem Sie sie
konfiguriert und kompiliert haben. Standardmäßig werden bei
der Installation Dateien in den folgenden Unterverzeichnissen
von /usr/local
erstellt:
Verzeichnis | Verzeichnisinhalt |
bin | Clientprogramme und -skripten |
include/mysql | Include-Dateien (Header-Dateien) |
info | Dokumentation im Info-Format |
lib/mysql | Bibliotheken |
libexec | Der mysqld-Server |
share/mysql | Fehlermeldungsdateien |
sql-bench | Benchmarks und der Crash-Me -Test |
var | Datenbanken und Logdateien |
Innerhalb des Installationsverzeichnisses unterscheidet sich die Struktur einer Quelldistribution wie folgt von der einer Binärdistribution:
Der mysqld-Server wird im Verzeichnis
libexec
statt im Verzeichnis
bin
installiert.
Das Datenverzeichnis ist var
und nicht
data
.
mysql_install_db wird im Verzeichnis
bin
installiert, nicht im Verzeichnis
scripts
.
Die Header-Datei- und Bibliotheksverzeichnisse sind
include/mysql
und
lib/mysql
statt
include
und lib
.
Sie können Ihre eigene Binärdistribution aus einer
kompilierten Quelldistribution erstellen, indem Sie das Skript
scripts/make_binary_distribution
aus dem
Stammverzeichnis der Quelldistribution ausführen.
Die nachfolgenden Abschnitte behandeln die Installation von MySQL auf Plattformen, für die wir Pakete im nativen Paketformat der jeweiligen Plattform anbieten. (Dies wird auch als Durchführung einer „Binärinstallation“ bezeichnet.) Binärdistributionen von MySQL sind allerdings auch für viele andere Plattformen verfügbar. In Abschnitt 2.7, „Installation von MySQL auf anderen Unix-ähnlichen Systemen“, finden Sie allgemeine Installationsanweisungen für diese Pakete, die für alle Plattformen gelten.
In Abschnitt 2.1, „Allgemeines zur Installation“, finden Sie weitere Informationen dazu, welche anderen Binärdistributionen verfügbar sind und wie Sie diese erhalten.
Eine native Windows-Distribution von MySQL wird von MySQL AB seit Version 3.21 angeboten. Der Anteil dieser Distributionen an den täglichen MySQL-Downloads ist beträchtlich. In diesem Abschnitt beschreiben wir die Vorgehensweise bei der MySQL-Installation unter Windows.
Das Installationsprogramm der Windows-Version von MySQL installiert in Verbindung mit einem grafischen Konfigurations-Assistenten automatisch MySQL, erstellt eine Optionsdatei, startet den Server und sichert die voreingestellten Benutzerkonten ab.
Wenn Sie eine vorhandene Installation von MySQL aktualisieren, die älter als MySQL 4.1.5 ist, dann müssen Sie die folgenden Schritte durchführen:
Besorgen Sie sich die Distribution und installieren Sie sie.
Konfigurieren Sie, sofern erforderlich, eine Optionsdatei.
Wählen Sie den zu verwendenden Server aus.
Starten Sie den Server.
Konfigurieren Sie Passwörter für die vorgabeseitigen MySQL-Konten.
Diese Vorgehensweise muss auch bei neueren MySQL-Installationen beachtet werden, wenn Sie ein Installationspaket verwenden, das kein Installationsprogramm enthält.
MySQL für Windows ist in verschiedenen Distributionsformaten erhältlich:
Es sind Binärdistributionen verfügbar, die ein Setup-Programm enthalten, das alles Erforderliche installiert, sodass Sie den Server sofort starten können. Ein anderes Binärdistributionsformat enthält ein Archiv, das Sie einfach an der Installationsposition entpacken und dann selbst konfigurieren. Detaillierte Informationen finden Sie in Abschnitt 2.3.2, „Auswahl eines Installationspakets“.
Die Quelldistribution enthält den gesamten Code und alle Supportdateien zur Erstellung der ausführbaren Dateien mithilfe des Compiler-Systems Visual Studio 2003.
Im Allgemeinen sollten Sie die Binärdistribution verwenden. Sie ist einfacher zu verwenden als die übrigen, und Sie benötigen keine zusätzlichen Tools, um MySQL zum Laufen zu bringen.
Im folgenden Abschnitt wird beschrieben, wie MySQL unter Windows mithilfe einer Binärdistribution installiert wird. Informationen zur Installation einer Quelldistribution finden Sie in Abschnitt 2.8.6, „Windows-Quelldistribution“.
Um MySQL unter Windows auszuführen, benötigen Sie Folgendes:
Ein 32-Bit-Windows-Betriebssystem wie Windows 9x, Me, NT, 2000, XP oder Windows Server 2003.
Windows NT-basierte Betriebssysteme (NT, 2000, XP, 2003) gestatten Ihnen die Ausführung des MySQL Servers als Dienst. Die Verwendung eines Windows NT-basierten Betriebssystems wird dringend empfohlen. Siehe auch Abschnitt 2.3.12, „Starten von MySQL als Windows-Dienst“.
Sie sollten MySQL unter Windows generell mithilfe eines
Kontos erstellen, das über Administratorrechte verfügt.
Andernfalls kann es bei bestimmten Operationen wie der
Bearbeitung der Umgebungsvariablen PATH
oder dem Zugriff auf den Service Control
Manager zu Problemen kommen.
TCP/IP-Protokollunterstützung.
Eine Kopie der MySQL-Binärdistribution für Windows. Diese kann unter http://dev.mysql.com/downloads/ heruntergeladen werden. Siehe auch Abschnitt 2.1.3, „Woher man MySQL bekommt“.
Hinweis: Wenn Sie die Distribution via FTP herunterladen, empfehlen wir Ihnen die Verwendung eines geeigneten FTP-Clients mit Wiederaufnahmefunktion für den Download, um eine Dateibeschädigung während des Downloads auszuschließen.
Zum Entpacken der Distributionsdatei ein Programm, das
.zip
-Dateien lesen kann.
Ausreichend viel Speicherplatz auf Ihrer Festplatte, um MySQL entpacken und installieren und die Datenbanken entsprechend Ihren Anforderungen erstellen zu können (mindestens 200 Mbyte empfohlen).
Je nachdem, wie Sie MySQL einsetzen wollen, können auch weitere Anforderungen vorliegen:
Wenn Sie die Verbindung zum MySQL Server via ODBC herstellen wollen, benötigen Sie einen Connector/ODBC-Treiber. Siehe auch Abschnitt 25.1, „MySQL Connector/ODBC“.
Wenn Sie Tabellen benötigen, die größer als 4 Gbyte sind,
installieren Sie MySQL auf NTFS oder einem neueren
Dateisystem. Vergessen Sie nicht, bei der Erstellung von
Tabellen MAX_ROWS
und
AVG_ROW_LENGTH
zu verwenden. Siehe auch
Abschnitt 13.1.5, „CREATE TABLE
“.
Bei MySQL 5.1 können Sie zwischen drei Installationspaketen für MySQL unter Windows auswählen. Die folgenden Pakete sind verfügbar:
Das Essentials-Paket:
Dieses Paket erkennen Sie am Dateinamen mit dem Aufbau
mysql-essential-5.1.5-alpha-win32.msi
.
Es enthält die für die Installation von MySQL unter
Windows mindestens erforderlichen Dateien einschließlich
des Konfigurations-Assistenten. Nicht enthalten sind
optionale Komponenten wie der eingebettete Server und die
Benchmark-Reihe.
Das Complete-Paket: Dieses
Paket erkennen Sie am Dateinamen mit dem Aufbau
mysql-5.1.5-alpha-win32.zip
. Es
enthält alle Dateien, die für eine vollständige
Windows-Installation erforderlich sind, einschließlich des
Konfigurations-Assistenten. Ferner enthalten sind optionale
Komponenten wie der eingebettete Server und die
Benchmark-Reihe.
Das Noinstall-Archiv:
Dieses Paket erkennen Sie am Dateinamen mit dem Aufbau
mysql-noinstall-5.1.5-alpha-win32.zip
.
Es enthält alle im Complete-Paket enthaltenen Dateien mit
Ausnahme des Konfigurations-Assistenten. Das Paket umfasst
kein automatisiertes Installationsprogramm, muss also
manuell installiert und konfiguriert werden.
Für die meisten Benutzer wird das Essentials-Paket empfohlen.
Welches Paket Sie auswählen, wirkt sich auf den nachfolgenden Installationsvorgang aus. Entscheiden Sie sich für das Essentials- oder Complete-Paket, dann finden Sie weitere Informationen in Abschnitt 2.3.3, „Installation von MySQL mit dem automatischen Installer“. Wollen Sie MySQL hingegen aus dem Noinstall-Archiv installieren, dann fahren Sie fort mit Abschnitt 2.3.6, „Installation von MySQL aus einem Noinstall-Zip-Archiv“.
Neue MySQL-Benutzer können den MySQL-Installations-Assistenten und den MySQL-Konfigurations-Assistenten zur Installation von MySQL unter Windows verwenden. Diese Assistenten sind so aufgebaut, dass die MySQL-Installation und -Konfiguration neuen Benutzern den sofortigen Einsatz von MySQL ermöglicht.
Die MySQL-Installations- und MySQL-Konfigurations-Assistenten sind Bestandteil des Essentials- und des Complete-Pakets von MySQL. Sie werden für die meisten MySQL-Standardinstallationen empfohlen. Ausnahmen betreffen Benutzer, die mehrere MySQL-Instanzen auf demselben Serverhost installieren wollen, und fortgeschrittene Benutzer, die volle Kontrolle über die Serverkonfiguration wünschen.
Der MySQL-Installations-Assistent ist ein Installationsprogramm für den MySQL Server, das die aktuellen Installer-Technologien von Microsoft Windows nutzt. In Verbindung mit dem MySQL-Konfigurations-Assistenten ermöglicht der MySQL-Installations-Assistent einem Benutzer die Installation und Konfiguration eines MySQL Servers, der direkt nach der Installation einsatzbereit ist.
Der MySQL-Installations-Assistent ist das Standardinstallationsprogramm für alle MySQL Server-Distributionen ab Version 4.1.5. Benutzer vorheriger MySQL-Versionen müssen ihre vorhandenen MySQL-Installationen manuell herunterfahren und entfernen, bevor sie MySQL mit dem MySQL-Installations-Assistenten installieren. In Abschnitt 2.3.4.7, „Upgrade von MySQL mit dem Installations-Assistenten“, finden Sie weitere Informationen zur Aktualisierung einer früheren Version.
In den aktuellen Windows-Versionen hat Microsoft eine verbesserte Version von MSI (Microsoft Windows Installer) implementiert. In Windows 2000, Windows XP und Windows Server 2003 ist MSI der De-facto-Standard für die Anwendungsinstallation. Der MySQL-Installations-Assistent nutzt diese Technologie, um den Installationsprozess reibungsloser und flexibler zu gestalten.
Die MSI-Engine wurde mit der Veröffentlichung von Windows XP aktualisiert. Wenn Sie eine vorherige Windows-Version einsetzen, finden Sie in dem Microsoft Knowledge Base-Artikel unter der Adresse http://support.microsoft.com/default.aspx?scid=kb;EN-US;292539 Informationen zum Upgrade auf die aktuelle Version der MSI-Engine.
Ferner hat Microsoft kürzlich das WiX-Toolkit (Windows Installer XML) vorgestellt. Hierbei handelt es sich um das erste offizielle Open-Source-Projekt von Microsoft. Wir verwenden WiX nun auch, denn erstens ist es ein Open-Source-Projekt, und zweitens gestattet es die Handhabung des gesamten Windows-Installationsvorgangs auf flexible Weise unter Verwendung von Skripten.
Die Optimierung des MySQL-Installations-Assistenten steht und fällt mit der Unterstützung und dem Feedback solcher Benutzer wie Ihnen. Wenn Sie feststellen, dass im MySQL-Installations-Assistenten etwas fehlt, das für Sie sehr wichtig wäre, oder einen Bug entdecken, melden Sie dies bitte in unserer Bugdatenbank. Hinweise hierzu finden Sie in Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“.
Die MySQL-Installationspakete können unter http://dev.mysql.com/downloads/ heruntergeladen werden. Wenn das von Ihnen heruntergeladene Paket in einem ZIP-Archiv gespeichert ist, müssen Sie dieses zunächst entpacken.
Der Vorgang zum Starten des Assistenten hängt vom Inhalt des
heruntergeladenen Installationspakets ab. Enthält dieses eine
Datei namens setup.exe
, dann
doppelklicken Sie darauf, um den Installationsvorgang zu
starten. Enthält das Paket hingegen eine
.msi
-Datei, dann doppelklicken Sie
darauf, um den Installationsvorgang zu starten.
Es sind drei Installationstypen vorhanden: Typical (Standard), Complete (Vollständig) und Custom (Benutzerdefiniert).
Bei der Installationsmethode Typical werden der MySQL Server, der Befehlszeilenclient mysql und die befehlszeilenbasierten Hilfsprogramme installiert. Zu den Befehlszeilenclients und Hilfsprogrammen gehören mysqldump, myisamchk und verschiedene weitere Programme zur Verwaltung des MySQL Servers.
Die Installationsmethode Complete installiert alle Komponenten, die im Installationspaket enthalten sind. Das vollständige Installationspaket umfasst Komponenten wie die eingebettete Serverbibliothek, die Benchmark-Reihe, Support-Skripten und die Dokumentation.
Bei der Installationsmethode Custom haben Sie vollständige Kontrolle darüber, welche Pakete installiert werden und wie der Installationspfad aussieht. Weitere Informationen zur benutzerdefinierten Installation finden Sie unter Abschnitt 2.3.4.4, „Der Dialog zur benutzerspezifischen Installation“.
Wenn Sie sich für die Installationsmethode Typical oder Complete entschieden haben und auf die Schaltfläche klicken, wird ein Fenster angezeigt, in dem Sie die gewählten Optionen überprüfen und die Installation dann starten können. Wenn Sie hingegen die Methode Custom auswählen und dann auf die Schaltfläche klicken, wird nachfolgend das Dialogfeld für die benutzerdefinierte Installation aufgerufen, welches in Abschnitt 2.3.4.4, „Der Dialog zur benutzerspezifischen Installation“, beschrieben wird.
Wenn Sie den Installationspfad oder bestimmte Komponenten ändern wollen, die vom MySQL-Installations-Assistenten installiert werden, wählen Sie die Installationsmethode Custom.
Alle verfügbaren Komponenten werden dann in einer Baumstruktur links im Installationsdialog angezeigt. Komponenten, die nicht installiert werden, sind durch ein rotes X gekennzeichnet, während für die Installation gewählten Komponenten ein graues Symbol aufweisen. Um den Installationsstatus einer Komponente umzuschalten, klicken Sie auf das Symbol der betreffenden Komponente und wählen die gewünschte Option aus der erscheinenden Dropdown-Liste.
Sie können den vorgegebenen Installationspfad ändern, indem Sie auf die Schaltfläche
rechts neben dem angezeigten Installationspfad klicken.Wenn Sie die zu installierenden Komponenten und den Pfad gewählt haben, klicken Sie auf die Schaltfläche
, um den Bestätigungsdialog anzuzeigen.Wenn Sie eine Installationsmethode und ggf. die zu installierenden Komponenten gewählt haben, schreiten Sie fort zum Bestätigungsdialog. Installationsmethode und Pfad werden nun zur Bestätigung angezeigt.
Wenn die angezeigten Einstellungen korrekt sind, klicken Sie auf die Schaltfläche
, um MySQL zu installieren. Wenn Sie Ihre Einstellungen noch einmal ändern wollen, klicken Sie auf die Schaltfläche . Um den MySQL-Installations-Assistenten zu verlassen, ohne MySQL zu installieren, klicken Sie auf die Schaltfläche .Wenn die Installation abgeschlossen ist, können Sie sich auf der MySQL-Website registrieren. Wenn Sie registriert sind, können Sie Mitteilungen an die MySQL-Foren unter forums.mysql.com schicken, Bugs unter bugs.mysql.com melden und unseren Newsletter abonnieren. Der Abschlussbildschirm des Installationsprogramms zeigt eine Zusammenfassung der Installation und erlaubt Ihnen den Aufruf des MySQL-Konfigurations-Assistenten, mit dem Sie eine Konfigurationsdatei erstellen, den MySQL-Dienst installieren und die Sicherheitseinstellungen konfigurieren können.
Wenn Sie auf die Schaltfläche
klicken, startet der MySQL-Installations-Assistent den Installationsvorgang und nimmt bestimmte Änderungen an Ihrem System vor, die in den nachfolgenden Abschnitten beschrieben sind.Änderungen in der Registrierung
Der MySQL-Installations-Assistent erstellt bei Auswahl der
Standardinstallation einen Schlüssel in der
Windows-Registrierung. Dieser befindet sich unter
HKEY_LOCAL_MACHINE\SOFTWARE\MySQL AB
.
Der MySQL-Installations-Assistent richtet einen Schlüssel
ein, der nach der Hauptversion des installierten Servers
benannt ist (z. B. MySQL Server
5.1
). Dieser enthält zwei
Zeichenfolgenwerte namens Location
und
Version
. Die Zeichenfolge
Location
enthält den Pfad zum
Installationsverzeichnis. Bei einer Standardinstallation
heißt der Wert C:\Programme\MySQL\MySQL Server
5.1\
. Die Zeichenfolge
Version
enthält die Release-Nummer. Wird
etwa MySQL Server 5.1.5-alpha installiert, dann enthält
der Schlüssel den Wert 5.1.5-alpha
.
Diese Registrierungsschlüssel ermöglichen es externen Programmen, das Installationsverzeichnis des MySQL Servers zu ermitteln; hierdurch wird eine zeitaufwändige vollständige Durchsuchung der Festplatte zur Ermittlung des Installationspfads des MySQL Servers unnötig. Die Registrierungsschlüssel sind für die Ausführung des Servers nicht erforderlich und werden, wenn Sie MySQL aus dem Noinstall-Archiv installieren, auch nicht erstellt.
Änderungen im Startmenü
Der MySQL-Installations-Assistent erstellt im Windows-Menü
einen neuen Eintrag in einem MySQL-Menü, welches nach der installierten MySQL-Hauptversion benannt ist. Installieren Sie beispielsweise MySQL 5.1, dann erstellt der Installations-Assistent einen Abschnitt namens im Menü .In diesem neuen Abschnitt im Menü
werden die folgenden Einträge eingerichtet:
mysql, die so konfiguriert ist, dass
eine Verbindung als Benutzer root
hergestellt wird. Beim Aufruf fordert die Verknüpfung die
Eingabe eines root
-Benutzerpassworts
an, wenn Sie eine Verbindung herstellen.
: Dies ist eine Verknüpfung zum MySQL-Konfigurations-Assistenten. Verwenden Sie diese Verknüpfung zur Konfiguration eines neu installierten oder zur Neukonfiguration eines vorhandenen Servers.
: Dies ist eine Verknüpfung zur Dokumentation zum MySQL Server, die lokal im Installationsverzeichnis des MySQL Servers gespeichert ist. Die Option ist nicht verfügbar, wenn der MySQL Server aus dem Essentials-Paket installiert wurde.
Änderungen am Dateisystem
Der MySQL-Installations-Assistent installiert den MySQL
5.1 Server standardmäßig im Verzeichnis
C:\
.
Hierbei ist Programme
\MySQL\MySQL
Server 5.1
Programme
das
Standardverzeichnis für Anwendungen auf Ihrem System und
5.1
die Hauptversion
Ihres MySQL Servers. Dies ist das empfohlene Verzeichnis für
den MySQL Server. Es ersetzt die vormalige Standardposition
C:\mysql
.
Standardmäßig werden alle MySQL-Anwendungen in einem
gemeinsamen Verzeichnis in
C:\
gespeichert. Hierbei ist Programme
\MySQLProgramme
in Ihrer Windows-Installation das Standardverzeichnis für
Anwendungen. Bei einer typischen MySQL-Installation auf einem
Entwicklersystem könnte dies wie folgt aussehen:
C:\Programme\MySQL\MySQL Server 5.1 C:\Programme\MySQL\MySQL Administrator 1.0 C:\Programme\MySQL\MySQL Query Browser 1.0
Dieser Ansatz erleichtert Verwaltung und Pflege aller auf einem System installierten MySQL-Anwendungen.
Der MySQL-Installations-Assistent kann Server-Upgrades automatisch mithilfe der MSI-Aktualisierungsfunktionen durchführen. Das bedeutet, dass Sie eine vorhandene Installation nicht mehr manuell entfernen müssen, bevor Sie einen neuen Release installieren. Das Installationsprogramm beendet und entfernt den vorhandenen MySQL-Dienst selbsttätig, bevor die neue Version installiert wird.
Automatische Upgrades sind nur dann verfügbar, wenn Sie Aktualisierungen zwischen Installationen durchführen, die die gleiche Haupt- und Unterversionsnummern aufweisen. So kann etwa ein automatisches Upgrade von MySQL 4.1.5 auf MySQL 4.1.6 erfolgen, nicht jedoch von MySQL 5.0 auf MySQL 5.1.
Siehe auch Abschnitt 2.3.15, „Upgrade von MySQL unter Windows“.
my.ini
my.ini
Der MySQL-Konfigurations-Assistent hilft Ihnen bei der
Automatisierung der Serverkonfiguration unter Windows. Der
Konfigurations-Assistent erstellt eine benutzerdefinierte
Datei my.ini
. Hierzu stellt er Ihnen eine
Reihe von Fragen und verknüpft Ihre Antworten dann mit einer
Vorlage, um eine Datei my.ini
zu
erzeugen, die für Ihre Installation maßgeschneidert ist.
Der MySQL-Konfigurations-Assistent ist Bestandteil des MySQL 5.1-Servers und derzeit nur für Windows-Benutzer verfügbar.
Der MySQL-Konfigurations-Assistent ist zu einem Großteil Ergebnis des Feedbacks, das MySQL AB über viele Jahre hinweg von Benutzern erhalten hat. Sollten Sie feststellen, dass eine für Sie wesentliche Funktionalität fehlt, dann melden Sie dies bitte in unserer Bugdatenbank. Hinweise zur Vorgehensweise finden Sie in Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“.
Der MySQL-Konfigurations-Assistent wird normalerweise über den MySQL-Installations-Assistenten gestartet, wenn dieser beendet wird. Sie können den Konfigurations-Assistenten aber auch durch Auswahl des Eintrags
im Abschnitt des Windows-Menüs aufrufen.
Alternativ navigieren Sie zum Verzeichnis
bin
Ihrer MySQL-Installation und rufen
die Datei MySQLInstanceConfig.exe
direkt
auf.
Wenn der MySQL-Konfigurations-Assistent eine vorhandene Datei
my.ini
erkennt, können Sie wahlweise den
vorhandenen Server umkonfigurieren oder die Serverinstanz
durch Löschen von my.ini
entfernen und
den MySQL-Dienst beenden und entfernen.
Wenn Sie den vorhandenen Server umkonfigurieren wollen,
wählen Sie die Option my.ini
wird nun in
my
umbenannt, wobei timestamp
.ini.baktimestamp
ein
Zeitstempel mit dem Datum und der Uhrzeit des Zeitpunkts ist,
an dem die vorhandene my.ini
erstellt
worden ist. Wenn Sie die vorhandene Serverinstanz entfernen
wollen, wählen Sie die Option und klicken dann auf die Schaltfläche
.
Wählen Sie die Option my.ini
. Die Serverinstallation und ihr
Ordner data
werden nicht entfernt.
Wenn Sie die Option
auswählen, wird das Dialogfeld angezeigt. Hier können Sie den Installationstyp auswählen, den Sie konfigurieren wollen.Wenn Sie den MySQL-Konfigurations-Assistenten für eine neue MySQL-Installation aufrufen oder die Option
für eine vorhandene Installation auswählen, wird das Dialogfeld aufgerufen.Es stehen zwei Konfigurationsmethoden zur Verfügung:
und . Die Option ist für Neubenutzer vorgesehen, die direkt mit MySQL arbeiten wollen, ohne sich vorher Gedanken zur Serverkonfiguration machen zu müssen. Die Option ist hingegen für fortgeschrittene Benutzer gedacht, die eine exaktere Kontrolle über die Serverkonfiguration wünschen.Wenn Sie noch nicht mit MySQL gearbeitet haben und einen Server benötigen, der als Entwicklersystem für genau einen Benutzer vorgesehen ist, dann ist
die richtige Wahl für Ihre Bedürfnisse. Wenn Sie die Option wählen, stellt der MySQL-Konfigurations-Assistent alle Konfigurationsoptionen mit Ausnahme von (Dienstoptionen) und (Sicherheitsoptionen) automatisch ein.Unter Umständen werden bei Auswahl von
Optionseinstellungen vorgenommen, die mit Systemen, auf denen bereits MySQL-Installationen vorhanden sind, nicht kompatibel sind. Ist auf dem System, auf dem Sie eine MySQL-Installation konfigurieren wollen, bereits eine andere MySQL-Installation vorhanden, dann wird die Auswahl empfohlen.Um die Auswahl Abschnitt 2.3.5.11, „Der Dialog zu Dienstoptionen“, bzw. Abschnitt 2.3.5.12, „Der Dialog zu Sicherheitsoptionen“.
fertig zu stellen, lesen Sie bitte die Abschnitte zu und inSie können zwischen drei verschiedenen Servertypen wählen. Welchen Servertyp Sie wählen, wirkt sich auf die Entscheidungen aus, die der MySQL-Konfigurations-Assistent in den Bereichen Speicher-, Festplatten- und Prozessornutzung trifft.
: Diese Option ist die beste Wahl für eine normale Desktop-Workstation, auf der MySQL nur für den privaten Einsatz vorgesehen ist. Es wird vorausgesetzt, dass viele andere Desktopanwendungen ausgeführt werden. Der MySQL Server wird deswegen für eine minimale Nutzung der Systemressourcen konfiguriert.
: Wählen Sie diese Option für ein Serversystem, bei dem der MySQL Server gemeinsam mit anderen Serveranwendungen wie FTP-, Mail- oder Webservern ausgeführt wird. Der MySQL Server wird in diesem Fall für eine moderate Nutzung der Systemressourcen konfiguriert.
: Die Option wählen Sie bei einem Serversystem, auf dem ausschließlich der MySQL Server läuft. Es wird vorausgesetzt, dass keine anderen Anwendungen ausgeführt werden. Der MySQL Server wird deswegen für die Nutzung aller Systemressourcen konfiguriert.
Das Dialogfeld InnoDB
-Speicher-Engine verfügbar ist und
welcher Anteil der Serverressourcen für
InnoDB
bereitgestellt wird.
InnoDB
- als
auch die MyISAM
-Speicher-Engine und
teilt die verfügbaren Ressourcen gleichmäßig zwischen
diesen beiden auf. Die Option ist für Benutzer
empfehlenswert, die beide Speicher-Engines regelmäßig
verwenden.
InnoDB
- als auch die
MyISAM
-Speicher-Engine, reserviert den
überwiegenden Teil der Serverressourcen jedoch für die
InnoDB
-Engine. Diese Option ist für
Benutzer gedacht, die InnoDB
fast
ausschließlich verwenden und MyISAM
nur in sehr seltenen Fällen einsetzen.
InnoDB
-Speicher-Engine vollständig und
weist die gesamten Serverressourcen der
MyISAM
-Engine zu. Sie wird Benutzern
empfohlen, die InnoDB
überhaupt nicht
verwenden.
Manche Benutzer wollen die
InnoDB
-Tablespace-Dateien an einer anderen
Position als im MySQL Serverdatenverzeichnis speichern. Dies
kann wünschenswert sein, wenn Ihr System über ein
Speichergerät mit höherer Kapazität oder mehr Leistung
verfügt (z. B. ein RAID-Speichersystem).
Um die Standardposition der
InnoDB
-Tablespace-Dateien zu ändern,
wählen Sie ein anderes Laufwerk aus der Dropdown-Liste mit
den Laufwerksbuchstaben aus und stellen dann in der
Dropdown-Liste mit den Pfaden einen anderen Pfad ein. Um einen
benutzerdefinierten Pfad zu erstellen, klicken Sie auf die
Schaltfläche .
Wenn Sie die Konfiguration eines vorhandenen Servers modifizieren, müssen Sie auf die Schaltfläche
klicken, bevor Sie den Pfad ändern. In dieser Situation müssen Sie die vorhandenen Tablespace-Dateien manuell an die neue Position verschieben, bevor Sie den Server starten.Um zu verhindern, dass der Server keine Ressourcen mehr zugewiesen bekommt, ist es wichtig, die Anzahl gleichzeitiger Verbindungen zum MySQL Server zu begrenzen. Das Dialogfeld
ermöglicht Ihnen die Angabe der erwarteten Auslastung Ihres Servers und stellt die Anzahl gleichzeitiger Verbindungen entsprechend ein. Es ist ferner möglich, die Anzahl gleichzeitiger Verbindungen manuell zu ändern.: Wählen Sie diese Option, wenn Ihr Server keine hohe Anzahl gleichzeitiger Verbindungen unterstützen muss. Die maximale Anzahl von Verbindungen wird in diesem Fall auf 100 gesetzt, wobei ein Durchschnitt von 20 Verbindungen erwartet wird.
: Wählen Sie diese Option, wenn Ihr Server eine große Zahl gleichzeitiger Verbindungen unterstützen muss. Die maximale Anzahl der Verbindungen wird hier auf 500 festgelegt.
: Wählen Sie diese Option, wenn Sie die maximale Anzahl gleichzeitiger Verbindungen zum Server manuell einstellen wollen. Wählen Sie die Anzahl gleichzeitiger Verbindungen über die Dropdown-Liste aus oder geben Sie den gewünschten Wert direkt in das Dropdown-Feld ein, sofern er nicht in der Liste enthalten ist.
Im Dialogfeld
aktivieren oder deaktivieren Sie die TCP/IP-Netzwerkunterstützung und konfigurieren die Portnummer, die zur Verbindung mit dem MySQL Server verwendet wird.Standardmäßig ist die TCP/IP-Netzwerkunterstützung aktiviert. Um sie zu deaktivieren, entfernen Sie die Markierung des Kontrollkästchen
.Standardmäßig ist Port 3306 gewählt. Um den für den MySQL-Zugriff verwendeten Port zu ändern, wählen Sie im Dropdown-Feld eine neue Portnummer aus und geben die gewünschte Nummer direkt in das Dropdown-Feld ein. Wird die eingetragene Portnummer bereits verwendet, dann werden Sie aufgefordert, Ihre Eingabe zu bestätigen.
Über Wenn Sie Anwendungen ausführen, die auf das vorherige „nachsichtige“ Verhalten von MySQL angewiesen sind, müssen Sie diese Anwendungen entweder anpassen oder den strikten Modus deaktivieren. Weitere Informationen finden Sie in Abschnitt 5.2.5, „Der SQL-Modus des Servers“.
können Sie den strikten SQL-Servermodus aktivieren oder deaktivieren. Bei aktiviertem striktem Modus (Standard) verhält sich MySQL ähnlich wie andere Datenbankmanagementsysteme.Der MySQL Server unterstützt mehrere Zeichensätze. In diesem Zusammenhang ist es möglich, einen Standardzeichensatz einzustellen, der für alle Tabellen, Spalten und Datenbanken verwendet wird, soweit nichts anderes explizit festgelegt ist. Im Dialogfeld
können Sie den Standardzeichensatz des MySQL Servers ändern.
latin1
als
Standardzeichensatz verwenden wollen.
latin1
wird für Englisch und viele
westeuropäische Sprachen verwendet.
utf8
als Standardzeichensatz
verwenden wollen. Dies ist ein Unicode-Zeichensatz, der
Zeichen vieler verschiedener Sprachen enthält.
: Wählen Sie diese Option, wenn Sie den Standardzeichensatz des Servers manuell einstellen wollen. Wählen Sie den gewünschten Zeichensatz aus der angezeigten Dropdown-Liste.
Auf Windows NT-basierten Plattformen kann der MySQL Server als Windows-Dienst installiert werden. Wenn der Server auf diese Weise installiert wird, kann er beim Systemstart automatisch gestartet werden. Zudem ist auch ein automatischer Neustart des Dienstes durch Windows nach einem Ausfall möglich.
Der MySQL-Konfigurations-Assistent installiert den MySQL
Server standardmäßig als Dienst mit dem Dienstnamen
MySQL
. Wollen Sie den Dienst nicht
installieren, dann deaktivieren Sie das Kontrollkästchen
. Sie
können den Namen des Dienstes ändern, indem Sie einen
anderen Namen im vorhandenen Dropdown-Feld auswählen oder
einen neuen Dienstnamen direkt in das Feld eintragen.
Um den MySQL Server als Dienst zu installieren, der aber beim Systemstart nicht automatisch gestartet wird, deaktivieren Sie das Kontrollkästchen
.
Es wird dringend empfohlen, ein
root
-Passwort für Ihren MySQL Server
einzurichten. Der MySQL-Konfigurations-Assistent
fordert Sie standardmäßig dazu auf. Wollen Sie kein
root
-Passwort erstellen, dann deaktivieren
Sie das Kontrollkästchen .
Um das root
-Passwort einzurichten, geben
Sie das gewünschte Passwort in die Felder und
ein. Wenn Sie einen
vorhandenen Server umkonfigurieren, müssen Sie das vorhandene
root
-Passwort in das Feld
eingeben.
Um root
-Anmeldungen über das Netzwerk zu
verhindern, markieren Sie das Kontrollkästchen
. Dies erhöht die Sicherheit Ihres
root
-Kontos.
Um ein anonymes Benutzerkonto einzurichten, markieren Sie das Kontrollkästchen
. Die Erstellung eines solchen Kontos kann die Serversicherheit verringern und Probleme mit der Anmeldung und mit Berechtigungen verursachen. Aus diesem Grund wird davon abgeraten.Das letzte Dialogfeld im MySQL-Konfigurations-Assistent ist
. Um den Konfigurationsvorgang zu starten, klicken Sie auf die Schaltfläche . Wenn Sie zu einem der vorherigen Dialogfelder zurückkehren wollen, klicken Sie auf die Schaltfläche . Um den MySQL-Konfigurations-Assistenten zu verlassen, ohne MySQL zu konfigurieren, klicken Sie auf die Schaltfläche .Wenn Sie auf die Schaltfläche
geklickt haben, führt der MySQL-Konfigurations-Assistent eine Reihe von Aufgaben aus, deren Fortschritt auf dem Bildschirm angezeigt wird.
Der MySQL-Konfigurations-Assistent ermittelt zunächst die
Konfigurationsdateioptionen basierend auf Ihren Einstellungen.
Hierzu verwendet er eine Vorlage, die von Entwicklern und
Technikern bei MySQL AB erstellt wurde. Diese Vorlage heißt
my-template.ini
und befindet sich in
Ihrem Serverinstallationsverzeichnis.
Der Konfigurations-Assistent schreibt diese Optionen dann in
eine Datei namens my.ini
. Die endgültige
Position von my.ini
wird neben der
Aufgabe Write configuration file
angezeigt.
Wenn Sie angegeben haben, dass ein Dienst für den MySQL Server eingerichtet werden soll, erstellt und startet der MySQL-Konfigurations-Assistent diesen Dienst. Konfigurieren Sie einen vorhandenen Dienst um, dann startet der MySQL-Konfigurations-Assistent den Dienst neu, um Ihre Konfigurationsänderungen anzuwenden.
Haben Sie angegeben, dass ein root
-Passwort
eingerichtet werden soll, dann stellt der
MySQL-Konfigurations-Assistent eine Verbindung mit dem Server
her, richtet Ihr neues root
-Passwort ein
und übernimmt ggf. weitere von Ihnen gewählte
Sicherheitseinstellungen.
Wenn der MySQL-Konfigurations-Assistent seine Aufgaben abgeschlossen hat, wird eine Zusammenfassung angezeigt. Klicken Sie auf die Schaltfläche
, um den MySQL-Konfigurations-Assistenten zu beenden.
Der MySQL-Konfigurations-Assistent legt die Datei
my.ini
im Installationsverzeichnis des
MySQL Servers ab. Dies erleichtert die Zuordnung von
Konfigurationsdateien zu bestimmten Serverinstanzen.
Um sicherzustellen, dass der MySQL Server weiß, wo er nach
der Datei my.ini
suchen muss, wird im
Zuge der Dienstinstallation ein Argument ähnlich dem
folgenden an den MySQL Server übergeben:
--defaults-file="
.
Hierbei wird C:\Programme\MySQL\MySQL
Server 5.1
\my.ini"C:\Programme\MySQL\MySQL Server
5.1
durch den Installationspfad des
MySQL Servers ersetzt.
Die Option --defaults-file
weist den MySQL
Server an, beim Start die Konfigurationsoptionen aus der
angegebenen Datei auszulesen.
Um die Datei my.ini
zu ändern, öffnen
Sie sie mit einem Texteditor und nehmen die erforderlichen
Änderungen vor. Sie können die Serverkonfiguration auch mit
dem Hilfsprogramm
MySQL
Administrator bearbeiten.
MySQL-Clients und Hilfsprogramme wie die Befehlszeilenclients
mysql und mysqldump
können die Datei my.ini
im
Serverinstallationsverzeichnis nicht lokalisieren. Um die
Client- und Hilfsanwendungen zu konfigurieren, erstellen Sie
eine neue Datei my.ini
im Verzeichnis
C:\WINDOWS
bzw.
C:\WINNT
(je nachdem, welches Verzeichnis
für Ihre Windows-Version gültig ist).
Benutzer, die eine Installation aus dem Noinstall-Paket vornehmen, können die Anweisungen in diesem Abschnitt zur manuellen Installation von MySQL verwenden. Die Installation von MySQL aus einem ZIP-Archiv erfolgt mit den nachfolgenden Schritten:
Extrahieren Sie das Archiv in das gewünschte Installationsverzeichnis.
Erstellen Sie die Optionsdatei.
Wählen Sie den MySQL Server-Typ aus.
Starten Sie den MySQL Server.
Schützen Sie die standardmäßig eingerichteten Benutzerkonten.
Die Abläufe werden in den nachfolgenden Abschnitten beschrieben.
So installieren Sie MySQL manuell:
Wenn Sie ein Upgrade von einer vorherigen Version durchführen wollen, lesen Sie bitte Abschnitt 2.3.15, „Upgrade von MySQL unter Windows“, bevor Sie den Upgradevorgang beginnen.
Verwenden Sie ein Windows NT-basiertes Betriebssystem (z. B. Windows NT, Windows 2000, Windows XP oder Windows Server 2003), dann stellen Sie sicher, dass Sie als Benutzer mit Administratorrechten angemeldet sind.
Wählen Sie ein Installationsverzeichnis aus. Traditionell
wird der MySQL Server im Verzeichnis
C:\mysql
installiert. Der
MySQL-Installations-Assistent installiert MySQL hingegen in
C:\Programme\MySQL
. Wenn Sie MySQL
nicht in C:\mysql
installieren, müssen
Sie den Pfad zum Installationsverzeichnis während des
Systemstarts oder in einer Optionsdatei angeben. Siehe auch
Abschnitt 2.3.8, „Anlegen einer Optionsdatei“.
Verwenden Sie ein ZIP-kompatibles Programm, um das Installationsarchiv in das gewählte Verzeichnis zu extrahieren. Bei Verwendung bestimmter Programme wird das Archiv in einen Ordner im Installationsverzeichnis extrahiert. Sollte dies bei Ihrem Programm der Fall sein, dann verschieben Sie den gesamten Inhalt des Unterordners in das gewählte Installationsverzeichnis.
Wenn Sie für die Ausführung des Servers bestimmte Startoptionen angeben wollen, können Sie dies über die Befehlszeile tun oder sie in einer Optionsdatei ablegen. Sollen die Optionen bei jedem Serverstart verwendet werden, dann ist die Verwendung einer Optionsdatei zur Angabe Ihrer MySQL-Konfiguration praktischer. Dies gilt insbesondere unter den folgenden Umständen:
Die Positionen von Installations- oder Datenverzeichnis
unterscheiden sich von den Standardvorgaben
(C:\Programme\MySQL\MySQL Server
5.1
und
C:\Programme\MySQL\MySQL Server
5.1\data
).
Sie müssen die Servereinstellungen optimieren.
Wenn der MySQL Server unter Windows gestartet wird, sucht er in
zwei Dateien nach Optionseinstellungen: in der Datei
my.ini
im Windows-Verzeichnis und der Datei
C:\my.cnf
. Das Windows-Verzeichnis heißt
normalerweise C:\WINDOWS
,
C:\WINNT
o. ä. Sie können die exakte
Position der Umgebungsvariable WINDIR
entnehmen. Hierzu geben Sie den folgenden Befehl ein:
C:\> echo %WINDIR%
MySQL sucht zunächst in der Datei my.ini
und nachfolgend in my.cnf
nach
Optionseinstellungen. Allerdings sollten Sie, um Verwirrung zu
vermeiden, am besten nur eine Datei verwenden. Verwendet Ihr PC
einen Boot-Loader, bei dem C:
nicht das
Startlaufwerk ist, dann können Sie ohnehin nur die Datei
my.ini
benutzen. Unabhängig von der
gewählten Option muss es sich in jedem Fall um eine
unverschlüsselte Textdatei handeln.
Sie können auch die Beispieloptionsdateien verwenden, die zum
Umfang Ihrer MySQL-Distribution gehören. Suchen Sie im
Installationsverzeichnis nach Dateien wie
my-small.cnf
,
my-medium.cnf
,
my-large.cnf
und
my-huge.cnf
, die Sie umbenennen und als
Grundlage für Ihre Konfigurationsdatei in das passende
Verzeichnis kopieren können.
Eine Optionsdatei kann mit jedem Texteditor (z. B. dem
Windows-Editor) erstellt und bearbeitet werden. Ist MySQL
beispielsweise in E:\mysql
installiert und
befindet sich das Datenverzeichnis in
E:\mydata\data
, dann können Sie eine
Optionsdatei erstellen, die einen Abschnitt
[mysqld]
enthält. In diesem geben Sie die
folgenden Werte für die Parameter basedir
und datadir
an:
[mysqld] # set basedir to your installation path basedir=E:/mysql # set datadir to the location of your data directory datadir=E:/mydata/data
Beachten Sie, dass Windows-Pfadnamen in Optionsdateien nicht mit Backslashs, sondern mit normalen Schrägstrichen angegeben werden. Wenn Sie Backslashs (umgekehrte Schrägstriche) verwenden, müssen Sie sie doppelt angeben:
[mysqld] # set basedir to your installation path basedir=E:\\mysql # set datadir to the location of your data directory datadir=E:\\mydata\\data
Unter Windows legt das MySQL-Installationsprogramm das
Datenverzeichnis direkt im Installationsverzeichnis von MySQL
ab. Wenn Sie das Datenverzeichnis an eine andere Position
verschieben wollen, sollten Sie den gesamten Inhalt des
Verzeichnisses data
an die neue Position
kopieren. Befindet sich MySQL etwa in
C:\Programme\MySQL\MySQL Server
5.1
, dann ist das Datenverzeichnis
standardmäßig C:\Programme\MySQL\MySQL Server
5.1\data
. Wollen Sie stattdessen
E:\mydata
als Datenverzeichnis verwenden,
dann müssen Sie zweierlei tun:
Sie verschieben das gesamte Verzeichnis
data
und alle darin enthaltenen Daten
von C:\Programme\MySQL\MySQL Server
5.1\data
nach
E:\mydata
.
Sie verwenden die Option --datadir
, um die
neue Position des Datenverzeichnisses bei jedem Serverstart
anzugeben.
Die folgende Tabelle zeigt die in MySQL 5.1 für Windows verfügbaren Server:
Binärdatei | Beschreibung |
mysqld-debug | Mit allen Debugging-Funktionen und automatischer Überprüfung der
Speicherzuordnung kompiliert. Unterstützt auch
InnoDB - und
BDB -Tabellen. |
mysqld | Optimierte Binärdatei mit InnoDB -Unterstützung. |
mysqld-nt | Optimierte Binärdatei für Windows NT/2000/XP mit Unterstützung von Named Pipes. |
mysqld-max | Optimierte Binärdatei mit Unterstützung für
InnoDB - und
BDB -Tabellen. |
mysqld-max-nt | Wie mysqld-max, aber mit Unterstützung für Named Pipes kompiliert. |
Alle genannten Binärdateien sind für moderne Intel-Prozessoren optimiert, sollten aber auf allen Intel i386-Prozessoren oder höher funktionieren.
Alle Windows-MySQL 5.1 Server unterstützen symbolische Verknüpfungen von Datenbankverzeichnissen.
MySQL unterstützt TCP/IP auf allen Windows-Plattformen. Die
Server mysqld-nt und
mysql-max-nt
unterstützen Named Pipes unter
Windows NT, 2000, XP und 2003. Allerdings wird TCP/IP
standardmäßig unabhängig von der Plattform verwendet. (Named
Pipes sind in vielen Windows-Konfigurationen langsamer als
TCP/IP.)
Die Verwendung von Named Pipes hängt von folgenden Bedingungen ab:
Named Pipes werden nur aktiviert, wenn Sie den Server mit
der Option --enable-named-pipe
starten.
Diese Option muss explizit angegeben werden, da einige
Benutzer Schwierigkeiten mit dem Herunterfahren des MySQL
Servers hatten, wenn Named Pipes verwendet wurden.
Named-Pipe-Verbindungen sind nur bei den Servern mysqld-nt und mysqld-max-nt und nur dann zulässig, wenn der Server unter einer Windows-Version läuft, die Named Pipes auch unterstützt (NT, 2000, XP, 2003).
Diese Server können auch auf Computern unter Windows 98 oder ME laufen, aber dann muss TCP/IP installiert sein; Named-Pipe-Verbindungen sind in diesem Fall nicht möglich.
Unter Windows 95 laufen die Server nicht.
Hinweis: Die meisten Beispiele in diesem Handbuch verwenden mysqld als Servername. Wenn Sie einen anderen Server (z. B. mysqld-nt) auswählen, nehmen Sie bei den in den Beispielen gezeigten Befehlen die erforderlichen Änderungen vor.
In diesem Abschnitt finden Sie einen allgemeinen Überblick zum Start des MySQL Servers. Die nachfolgenden Abschnitte enthalten spezielle Informationen zum Starten des MySQL Servers von der Befehlszeile oder als Windows-Dienst.
Die hier enthaltenen Informationen gelten in erster Linie, wenn
Sie MySQL aus dem Noinstall
-Paket heraus
installiert haben oder MySQL manuell (statt unter Verwendung der
grafischen Oberflächen) konfigurieren und testen wollen.
Die Beispiele in diesem und den folgenden Abschnitten setzen
voraus, dass MySQL im Standardverzeichnis
C:\Programme\MySQL\MySQL Server
5.1
installiert wurde. Haben Sie MySQL
an anderer Stelle installiert, dann müssen Sie die in den
Beispielen gezeigten Pfadnamen entsprechend abändern.
Auf NT-basierten Systemen wie Windows NT, 2000, XP oder 2003 haben Clients zwei Optionen: Sie können entweder TCP/IP verwenden oder eine Named Pipe nutzen, sofern der Server Named-Pipe-Verbindungen unterstützt. Damit MySQL TCP/IP unter Windows NT 4.0 nutzen kann, muss das Service Pack 3 (oder höher) installiert sein.
Unter Windows 95/98/ME müssen MySQL-Clients die Serververbindung immer über TCP/IP herstellen. (Auf diese Weise kann jeder Rechner in Ihrem Netzwerk eine Verbindung zum MySQL Server herstellen.) Aus diesem Grund müssen Sie sicherstellen, dass die TCP/IP-Unterstützung auf Ihrem Computer installiert ist, bevor Sie MySQL starten. Sie finden TCP/IP auf Ihrer Windows-CD-ROM.
Beachten Sie, dass Sie, wenn Sie einen frühen Windows 95-Release (z. B. OSR2) verwenden, wahrscheinlich ein veraltetes Winsock-Paket verwenden; MySQL erfordert jedoch Winsock 2. Sie finden die aktuelle Winsock-Version auf der Website http://www.microsoft.com/. Windows 98 enthält die neue Winsock 2-Bibliothek bereits, d. h., diese muss nicht aktualisiert werden.
MySQL für Windows unterstützt auch Verbindungen mit gemeinsam
genutztem Speicher, sofern beim Start die Option
--shared-memory
angegeben wurde. Clients
können durch Verwendung der Option
--protocol=memory
eine Verbindung über
gemeinsamen Speicher herstellen.
Informationen zur zu startenden Serverbinärdatei finden Sie in Abschnitt 2.3.9, „Auswahl des MySQL Server-Typs“.
Tests führen Sie am besten über die Eingabeaufforderung in einem Konsolenfenster (oder „DOS-Fenster“) aus. So kann der Server Statusmeldungen im Fenster anzeigen, wo sie leicht zu sehen sind. Funktioniert bei der Konfiguration etwas nicht einwandfrei, dann können Sie Probleme mithilfe dieser Meldungen erkennen und beheben.
Um den Server zu starten, geben Sie folgenden Befehl ein:
C:\> "C:\Programme\MySQL\MySQL Server 5.1\bin\mysqld" --console
Bei Servern, die die InnoDB
-Unterstützung
enthalten, sollten Sie folgende Mitteilungen beim Serverstart
sehen:
InnoDB: The first specified datafile c:\ibdata\ibdata1 did not exist: InnoDB: a new database to be created! InnoDB: Setting file c:\ibdata\ibdata1 size to 209715200 InnoDB: Database physically writes the file full: wait... InnoDB: Log file c:\iblogs\ib_logfile0 did not exist: new to be created InnoDB: Setting log file c:\iblogs\ib_logfile0 size to 31457280 InnoDB: Log file c:\iblogs\ib_logfile1 did not exist: new to be created InnoDB: Setting log file c:\iblogs\ib_logfile1 size to 31457280 InnoDB: Log file c:\iblogs\ib_logfile2 did not exist: new to be created InnoDB: Setting log file c:\iblogs\ib_logfile2 size to 31457280 InnoDB: Doublewrite buffer not found: creating new InnoDB: Doublewrite buffer created InnoDB: creating foreign key constraint system tables InnoDB: foreign key constraint system tables created 011024 10:58:25 InnoDB: Started
Wenn der Server seine Startsequenz beendet, sollten Sie eine Meldung in der Art der folgenden sehen (hierdurch wird angezeigt, dass der Server nun zur Annahme von Clientverbindungen bereit ist):
mysqld: ready for connections Version: '5.1.5-alpha' socket: '' port: 3306
Nachfolgend schreibt der Server weiterhin alle erzeugten Diagnoseausgaben in die Konsole. Sie können ein neues Konsolenfenster öffnen, in dem Clientprogramme ausgeführt werden.
Wenn Sie die Option --console
weglassen,
schreibt der Server die gesamte Diagnoseausgabe in das Fehlerlog
im Datenverzeichnis (standardmäßig
C:\Programme\MySQL\MySQL Server
5.1\data
). Das Fehlerlog ist die Datei
mit der Erweiterung .err
.
Hinweis: Für die in den MySQL-Grant-Tabellen aufgeführten Konten gibt es zunächst noch keine Passwörter. Wenn Sie den Server gestartet haben, sollten Sie entsprechend der in Abschnitt 2.9, „Einstellungen und Tests nach der Installation“, beschriebenen Verfahrensweise Passwörter für diese Konten einrichten.
Der MySQL Server kann manuell über die Befehlszeile gestartet werden. Dies ist bei jeder Windows-Version möglich.
Um dem Server mysqld von der Befehlszeile zu starten, öffnen Sie ein Konsolenfenster („Eingabeaufforderung“) und geben folgenden Befehl ein:
C:\> "C:\Programme\MySQL\MySQL Server 5.1\bin\mysqld"
Der in obigem Beispiel verwendete Pfad kann abhängig vom MySQL-Installationsverzeichnis auf Ihrem System anders aussehen.
Bei Nicht-NT-Versionen von Windows wird hierdurch mysqld im Hintergrund gestartet. Das bedeutet, dass nach dem Serverstart eine andere Eingabeaufforderung angezeigt wird. Wenn Sie den Server auf diese Weise unter Windows NT, 2000, XP oder 2003 starten, läuft der Server im Vordergrund; bis zur Beendigung des Servers erscheint keine Eingabeaufforderung. Aus diesem Grund müssen Sie ein anderes Konsolenfenster öffnen, um Clientprogramme ausführen zu können, während der Server läuft.
Sie können den MySQL Server mit folgendem Befehl beenden:
C:\> "C:\Programme\MySQL\MySQL Server 5.1\bin\mysqladmin" -u root shutdown
Hinweis: Wenn das
MySQL-Benutzerkonto root
ein Passwort
aufweist, müssen Sie mysqladmin mit der
Option -p
aufrufen und das Passwort auf
Aufforderung angeben.
Mit diesem Befehl rufen Sie das
MySQL-Administrationshilfsprogramm mysqladmin
auf, welches eine Verbindung zum Server herstellt und das
Herunterfahren auslöst. Der Befehl stellt die Verbindung als
MySQL-Benutzer root
her. Dies ist das
standardmäßige Administratorenkonto im MySQL-Grant-System.
Beachten Sie, dass Benutzer im MySQL-Grant-System nichts mit den
Benutzerkonten zu tun haben, über die man sich am
Windows-System anmeldet.
Wenn mysqld nicht startet, kontrollieren Sie,
ob der Server im Fehlerlog Meldungen eingetragen hat, die auf
die Ursache des Problems schließen lassen. Das Fehlerlog
befindet sich im Verzeichnis C:\Programme\MySQL\MySQL
Server 5.1\data
. Es handelt sich um die
Datei mit der Erweiterung .err
. Sie können
auch versuchen, den Server als mysqld
--console zu starten; in diesem Fall erhalten Sie
unter Umständen über den Bildschirm einige nützliche
Informationen, die bei der Beseitigung des Problems helfen
können.
Die letzte Option ist der Start von mysqld
mit den Optionen --standalone
und
--debug
. In diesem Fall schreibt
mysqld eine Logdatei namens
C:\mysqld.trace
, die die Ursache dafür
angeben sollte, dass mysqld nicht gestartet
wird. Siehe auch Abschnitt E.1.2, „Trace-Dateien erzeugen“.
Verwenden Sie mysqld --verbose --help, um alle Optionen anzuzeigen, die mysqld versteht.
Bei der Windows NT-Familie (Windows NT, 2000, XP, 2003) besteht die empfohlene Methode zur Ausführung von MySQL in der Installation als Dienst, wobei MySQL automatisch mit Windows gestartet und beendet wird. Ein MySQL Server, der als Dienst installiert ist, lässt sich mithilfe von NET über die Befehlszeile oder über das grafische Hilfsprogramm Dienste steuern.
Das Hilfsprogramm Dienste (der Service Control Manager von Windows) lässt sich über die Windows-Systemsteuerung aufrufen (Abschnitt bei Windows 2000, XP und Server 2003). Um Konflikte zu vermeiden, ist es ratsam, das Hilfsprogramm Dienste während der Serverinstallation oder Löschaktionen über die Befehlszeile zu schließen.
Bevor Sie MySQL als Windows-Dienst installieren, sollten Sie zunächst mit dem folgenden Befehl den aktuellen Server beenden, sofern dieser ausgeführt wird:
C:\> "C:\Programme\MySQL\MySQL Server 5.1\bin\mysqladmin" -u root shutdown
Hinweis: Wenn das
MySQL-Benutzerkonto root
ein Passwort
aufweist, müssen Sie mysqladmin mit der
Option -p
aufrufen und das Passwort auf
Aufforderung angeben.
Mit diesem Befehl rufen Sie das
MySQL-Administrationshilfsprogramm mysqladmin
auf, welches eine Verbindung zum Server herstellt und das
Herunterfahren auslöst. Der Befehl stellt die Verbindung als
MySQL-Benutzer root
her. Dies ist das
standardmäßige Administratorenkonto im MySQL-Grant-System.
Beachten Sie, dass Benutzer im MySQL-Grant-System nichts mit den
Benutzerkonten zu tun haben, über die man sich am
Windows-System anmeldet.
Installieren Sie den Server mit dem folgenden Befehl als Dienst:
C:\> "C:\Programme\MySQL\MySQL Server 5.1\bin\mysqld" --install
Mit dem Befehl zur Dienstinstallation wird der Server nicht gestartet. Hinweise zum Start finden Sie in einem späteren Abschnitt.
Um den Aufruf von MySQL-Programmen zu erleichtern, können Sie
den Pfadnamen des MySQL-Verzeichnisses bin
zur Umgebungsvariable PATH
Ihres
Windows-Systems hinzufügen:
Klicken Sie auf dem Windows-Desktop mit der rechten Maustaste auf das Symbol Arbeitsplatz und wählen Sie .
Wählen Sie nun im angezeigten Fenster
die Registerkarte und klicken Sie auf die Schaltfläche .Unter Systemvariablen wählen Sie und klicken dann auf die Schaltfläche . Das Dialogfeld erscheint.
Setzen Sie den Cursor an das Ende des im Feld Wert
der Variablen gezeigten Texts (betätigen Sie die
Taste Ende, um sicherzustellen, dass der
Cursor tatsächlich ans Ende des Textes in diesem Textfeld
gesetzt wird). Geben Sie nun den vollständigen Pfadnamen
Ihres MySQL-Verzeichnisses bin
ein
(beispielsweise C:\Programme\MySQL\MySQL Server
5.1\bin
). Achten Sie dabei darauf,
dass dieser Pfad durch ein Semikolon von den übrigen Werten
in diesem Feld abgetrennt ist. Bestätigen Sie nun alle
angezeigten Dialogfelder nacheinander durch Anklicken der
jeweiligen Schaltflächen , bis
keine offenen Dialogfelder mehr angezeigt werden. Sie
sollten jetzt aus jedem beliebigen Verzeichnis heraus jedes
ausführbare MySQL-Programm durch Eingabe seines Namens an
der DOS-Eingabeaufforderung starten können, ohne den
vollständigen Pfad angeben zu müssen. Dies betrifft die
Server, den mysql-Client und alle
befehlszeilenbasierten MySQL-Hilfsprogramme wie
mysqladmin und
mysqldump.
Wenn Sie mehrere MySQL Server auf Ihrem System betreiben,
sollten Sie das MySQL-Verzeichnis bin
nicht der Windows-Umgebungsvariablen PATH
hinzufügen.
Warnung: Bei der manuellen
Editierung der Umgebungsvariablen PATH
müssen Sie größte Vorsicht walten lassen: Wenn Sie einen Teil
des Werts von PATH
versehentlich löschen
oder ändern, kann das System instabil oder sogar unbrauchbar
werden.
Bei der Installation des Dienstes können die folgenden zusätzlichen Argumente in MySQL 5.1 verwendet werden:
Sie können unmittelbar auf die Option
--install
einen Dienstnamen angeben. Der
Standardname für den Dienst lautet
MySQL
.
Wird ein Name für den Dienst angegeben, so kann genau eine
weitere Option folgen. Konventionsgemäß ist dies
--defaults-file=
;
hierdurch wird der Name einer Optionsdatei angegeben, die
der Server beim Start auslesen soll.
file_name
Sie können statt --defaults-file
auch eine
beliebige andere Option angeben, doch dies wird nicht
empfohlen. --defaults-file
ist flexibler,
da es Ihnen die Festlegung einer Vielzahl von Startoptionen
für den Server gestattet, die einfach in der spezifizierten
Optionsdatei abgelegt werden.
Sie können auch eine Option
--local-service
gefolgt vom Dienstnamen
angeben. In diesem Fall wird der Server über das
Windows-Konto LocalService
ausgeführt,
welches über eingeschränkte Systemberechtigungen verfügt.
Dieses Konto ist nur unter Windows XP oder höher
vorhanden. Werden beide Optionen
--defaults-file
und
--local-service
auf den Dienstnamen folgend
angegeben, dann ist die Reihenfolge unerheblich.
Bei einem MySQL Server, der als Windows-Dienst installiert ist, bestimmen die folgenden Grundsätze den Dienstnamen und die vom Server verwendeten Optionsdateien:
Wenn der Dienstinstallationsbefehl keinen Dienstnamen oder
den Vorgabenamen (MySQL
) gefolgt von der
Option --install
angibt, dann verwendet der
Server den Dienstnamen MySQL
und liest
seine Optionen aus dem Abschnitt [mysqld]
der Standardoptionsdateien aus.
Wurde im Dienstinstallationsbefehl ein anderer Dienstname
als MySQL
gefolgt von der Option
--install
angegeben, dann verwendet der
Server diesen anderen Namen. Die Optionen werden dann aus
dem Abschnitt in den Standardoptionsdateien ausgelesen, der
den gleichen Namen hat wie der Dienst selbst.
Außerdem liest der Server auch den Abschnitt
[mysqld]
in den Standardoptionsdateien
aus. Sie können den Abschnitt [mysqld]
also für diejenigen Optionen verwenden, die allen
MySQL-Diensten gemeinsam sind, und zusätzlich einen
Abschnitt mit dem Namen eines bestimmten Dienstes
konfigurieren, der dann von dem Server benutzt wird, der mit
diesem Dienstnamen installiert wurde.
Wenn im Dienstinstallationsbefehl die Option
--defaults-file
auf den Dienstnamen folgend
angegeben wird, liest der Server nur die Optionen im
Abschnitt [mysqld]
der angegebenen Datei
aus und ignoriert die Standardoptionsdateien.
Nehmen wir einmal den folgenden Befehl als ein etwas komplexeres Beispiel:
C:\>"C:\Programme\MySQL\MySQL Server 5.1\bin\mysqld"
--install MySQL --defaults-file=C:\my-opts.cnf
Hier wird der Standarddienstname (MySQL
) auf
die Option --install
folgend angegeben. Wäre
keine Option --defaults-file
vorhanden, dann
würde dieser Befehl dafür sorgen, dass der Server den
Abschnitt [mysqld]
in den
Standardoptionsdateien ausliest. Da allerdings die Option
--defaults-file
angegeben ist, liest der Server
die Optionen im Abschnitt [mysqld]
der
spezifizierten Datei.
Sie können Optionen auch als Startparameter im Windows-Hilfsprogramm Dienste festlegen, bevor Sie den MySQL-Dienst starten.
Wurde ein MySQL Server als Dienst installiert, dann startet Windows den Dienst automatisch beim Systemstart. Der Dienst lässt sich auch direkt aus dem Hilfsprogramm Dienste oder mithilfe des Befehls NET START MySQL starten. Der NET-Befehl unterscheidet hierbei keine Groß-/Kleinschreibung.
Wenn mysqld als Dienst ausgeführt wird, hat
es keinen Zugriff auf ein Konsolenfenster; insofern werden keine
Meldungen angezeigt. Wenn mysqld nicht
startet, kontrollieren Sie, ob der Server im Fehlerlog Meldungen
eingetragen hat, die auf die Ursache des Problems schließen
lassen. Das Fehlerlog befindet sich im MySQL-Datenverzeichnis
(z. B. C:\Programme\MySQL\MySQL Server
5.1\data
). Es handelt sich um die Datei
mit der Erweiterung .err
.
Wenn ein MySQL Server als Dienst installiert wurde und dieser
Dienst ausgeführt wird, beendet Windows ihn automatisch beim
Herunterfahren. Der Server kann auch manuell im Hilfsprogramm
Dienste
, mit dem Befehl NET STOP
MySQL oder dem Befehl mysqladmin
shutdown beendet werden.
Außerdem haben Sie die Möglichkeit, den Server als manuellen
Dienst zu installieren, wenn Sie nicht wollen, dass der Dienst
beim Hochfahren automatisch gestartet wird. Verwenden Sie zu
diesem Zweck die Option --install-manual
statt
--install
:
C:\> "C:\Programme\MySQL\MySQL Server 5.1\bin\mysqld" --install-manual
Um einen Server zu entfernen, der als Dienst installiert ist,
beenden Sie ihn zunächst, sofern er noch ausgeführt wird;
hierzu verwenden Sie den Befehl NET STOP
MYSQL. Danach entfernen Sie ihn mit der Option
--remove
:
C:\> "C:\Programme\MySQL\MySQL Server 5.1\bin\mysqld" --remove
Wenn mysqld nicht als Dienst ausgeführt wird, können Sie ihn über die Befehlszeile starten. Informationen zur Vorgehensweise finden Sie in Abschnitt 2.3.11, „Starten von MySQL von der Windows-Befehlszeile“.
Bitte schlagen Sie in Abschnitt 2.3.14, „Troubleshooting einer MySQL-Installation unter Windows“, nach, wenn Sie bei der Installation Probleme haben sollten.
Ob der MySQL Server funktioniert, können Sie durch Ausführen eines der folgenden Befehle leicht überprüfen:
C:\>"C:\Programme\MySQL\MySQL Server 5.1\bin\mysqlshow"
C:\>"C:\Programme\MySQL\MySQL Server 5.1\bin\mysqlshow" -u root mysql
C:\>"C:\Programme\MySQL\MySQL Server 5.1\bin\mysqladmin" version status proc
C:\>"C:\Programme\MySQL\MySQL Server 5.1\bin\mysql" test
Wenn mysqld nur langsam auf
TCP/IP-Verbindungen von Clientprogrammen reagiert, liegt
wahrscheinlich ein DNS-Problem vor. Starten Sie in einem solchen
Fall mysqld mit der Option
--skip-name-resolve
und verwenden Sie nur
localhost
und IP-Nummern in der Spalte
Host
der MySQL-Grant-Tabellen.
Sie können die Verwendung einer Named-Pipe-Verbindung (statt
einer TCP/IP-Verbindung) erzwingen, indem Sie die Optionen
--pipe
oder --protocol=PIPE
verwenden oder den Punkt .
als Hostnamen
angeben. Verwenden Sie die Option --socket
, um
den Namen der Pipe anzugeben, sofern Sie nicht den Namen der
Standard-Pipe verwenden wollen.
Wenn Sie MySQL zum ersten Mal installieren und ausführen, können bestimmte Fehler auftreten, die verhindern, dass der MySQL Server gestartet wird. Dieser Abschnitt soll Ihnen dabei helfen, einige dieser Fehler zu diagnostizieren und zu beheben.
Ihre erste Ressource bei der Fehlersuche ist das Fehlerlog. Der
MySQL Server verwendet das Fehlerlog zur Aufzeichnung von Daten
zu dem Fehler, der verhindert, dass der Server gestartet werden
kann. Das Fehlerlog befindet sich im Datenverzeichnis, das in
Ihrer Datei my.ini
angegeben ist. Die
Standardposition des Datenverzeichnisses ist
C:\Programme\MySQL\MySQL Server
5.1\data
. Siehe auch
Abschnitt 5.12.1, „Die Fehler-Logdatei“.
Eine andere Informationsquelle zu möglichen Fehlern sind die Konsolenmeldungen, die beim Starten des MySQL-Dienstes angezeigt werden. Verwenden Sie den Befehl NET START mysql an der Befehlszeile, nachdem Sie mysqld als Dienst installiert haben, um Fehlermeldungen anzuzeigen, die beim Start des MySQL Servers als Dienst erzeugt werden. Siehe auch Abschnitt 2.3.12, „Starten von MySQL als Windows-Dienst“.
Die folgenden Beispiele zeigen weitere häufig auftretende Fehlermeldungen, die bei der Installation von MySQL und dem ersten Start des Servers angezeigt werden können:
Wenn der MySQL Server die
mysql
-Berechtigungsdatenbank oder andere
kritische Dateien nicht finden kann, erscheinen Meldungen
folgenden Typs:
System error 1067 has occurred. Fatal error: Can't open privilege tables: Table 'mysql.host' doesn't exist
Solche Meldungen treten häufig auf, wenn das
MySQL-Datenbank- oder das MySQL-Datenverzeichnis nicht an
der Standardposition (C:\Programme\MySQL\MySQL
Server 5.1
bzw.
C:\Programme\MySQL\MySQL Server
5.1\data
) installiert wurde.
Die Situation entsteht, wenn MySQL aktualisiert und in einem neuen Verzeichnis installiert, aber die Konfigurationsdatei nicht an die geänderte Umgebung angepasst wurde. Außerdem kann es zu Konflikten zwischen alten und neuen Konfigurationsdateien kommen. Benennen Sie alte Konfigurationsdateien in jedem Fall um oder löschen Sie sie, bevor Sie MySQL aktualisieren.
Wenn Sie MySQL in ein anderes Verzeichnis als
C:\Programme\MySQL\MySQL Server
5.1
installiert haben, müssen Sie
sicherstellen, dass dies dem MySQL Server bekannt ist.
Hierzu verwenden Sie die Konfigurationsdatei
my.ini
. Die Datei mit dem Namen
my.ini
muss in Ihrem
Windows-Verzeichnis gespeichert sein (normalerweise
C:\WINDOWS
oder
C:\WINNT
). Sie können die exakte
Position der Umgebungsvariable WINDIR
entnehmen. Hierzu geben Sie den folgenden Befehl an der
Befehlszeile ein:
C:\> echo %WINDIR%
Eine Optionsdatei kann mit jedem Texteditor (z. B. dem
Windows-Editor) erstellt und bearbeitet werden. Ist MySQL
beispielsweise in E:\mysql
installiert
und befindet sich das Datenverzeichnis in
D:\MySQLdata
, dann können Sie eine
Optionsdatei erstellen, die einen Abschnitt
[mysqld]
enthält. In diesem geben Sie
die folgenden Werte für die Parameter
basedir
und datadir
an:
[mysqld] # set basedir to your installation path basedir=E:/mysql # set datadir to the location of your data directory datadir=D:/MySQLdata
Beachten Sie, dass Windows-Pfadnamen in Optionsdateien nicht mit Backslashs, sondern mit normalen Schrägstrichen angegeben werden. Wenn Sie Backslashs (umgekehrte Schrägstriche) verwenden, müssen Sie sie doppelt angeben:
[mysqld] # set basedir to your installation path basedir=C:\\Program Files\\MySQL\\MySQL Server 5.1 # set datadir to the location of your data directory datadir=D:\\MySQLdata
Wenn Sie den Wert datadir
in Ihrer
MySQL-Konfigurationsdatei ändern, müssen Sie den Inhalt
des vorhandenen MySQL-Datenverzeichnisses verschieben, bevor
Sie den MySQL Server neu starten.
Siehe auch Abschnitt 2.3.8, „Anlegen einer Optionsdatei“.
Wenn Sie MySQL neu installieren oder aktualisieren, ohne den vorhandenen MySQL-Dienst zu beenden und zu entfernen, und zur Installation den MySQL-Konfigurations-Assistenten verwenden, dann wird unter Umständen folgende Fehlermeldung angezeigt:
Error: Cannot create Windows service for MySql. Error: 0
Dies passiert, wenn der Konfigurations-Assistent einen Dienst zu installieren versucht und einen anderen Dienst gleichen Namens vorfindet.
Eine Lösung dieses Problems besteht darin, bei Verwendung
des Konfigurations-Assistenten einen anderen Dienstnamen als
mysql
auszuwählen. Hierdurch wird der
neue Dienst korrekt installiert. Allerdings bleibt dann ein
veralteter Dienst zurück. Dies ist an sich zwar
unproblematisch, aber trotzdem sollten alte Dienste, die
nicht mehr erforderlich sind, korrekt entfernt werden.
Um den alten mysql
-Dienst permanent zu
entfernen, führen Sie den folgenden Befehl als Benutzer mit
Administratorrechten an der Befehlszeile aus:
C:\> sc delete mysql
[SC] DeleteService SUCCESS
Wenn das Hilfsprogramm sc
bei Ihrer
Windows-Version nicht vorhanden ist, laden Sie das
Hilfsprogramm delsrv
unter
http://www.microsoft.com/windows2000/techinfo/reskit/tools/existing/delsrv-o.asp
herunter und verwenden Sie die Syntax delsrv
mysql
.
Dieser Abschnitt listet einige der Schritte auf, die bei der Aktualisierung von MySQL unter Windows erforderlich sind.
Lesen Sie Abschnitt 2.10, „MySQL aktualisieren (Upgrade/Downgrade)“. Sie finden dort weitere, nicht Windows-spezifische Informationen zum Upgrade von MySQL.
Fertigen Sie immer eine Sicherung Ihrer aktuellen MySQL-Installation an, bevor Sie ein Upgrade durchführen. Siehe auch Abschnitt 5.10.1, „Datenbank-Datensicherungen“.
Laden Sie die aktuelle Windows-Distribution von MySQL unter http://dev.mysql.com/downloads/ herunter.
Vor Durchführung des Upgrades müssen Sie den Server beenden. Ist der Server als Dienst installiert, dann beenden Sie ihn durch Eingabe des folgenden Befehls an der Befehlszeile:
C:\> NET STOP MYSQL
Wird der MySQL Server nicht als Dienst ausgeführt, dann beenden Sie ihn mit dem folgenden Befehl:
C:\> "C:\Programme\MySQL\MySQL Server 5.1\bin\mysqladmin" -u root shutdown
Hinweis: Wenn das
MySQL-Benutzerkonto root
ein Passwort
aufweist, müssen Sie mysqladmin mit der
Option -p
aufrufen und das Passwort auf
Aufforderung angeben.
Wenn Sie von einer MySQL-Version vor 4.1.5 auf MySQL 5.1 aktualisieren oder ein Upgrade von einer MySQL-Version, die aus einem ZIP-Archiv installiert wurde, auf eine mit dem MySQL-Installations-Assistenten zu installierende Version durchführen, dann müssen Sie die vorherige Installation und den MySQL-Dienst (sofern der Server als Dienst installiert ist) manuell entfernen.
Verwenden Sie den folgenden Befehl, um den MySQL-Dienst zu entfernen:
C:\> C:\mysql\bin\mysqld --remove
Wenn Sie den vorhandenen Dienst nicht entfernen, kann der MySQL-Installations-Assistent den neuen MySQL-Dienst unter Umständen nicht korrekt installieren.
Wenn Sie den MySQL-Installations-Assistenten verwenden, starten Sie den Assistenten wie in Abschnitt 2.3.4, „Verwendung des MySQL-Installations-Assistenten“, beschrieben.
Wenn Sie MySQL aus einem ZIP-Archiv installieren,
extrahieren Sie das Archiv. Sie können die vorhandene
MySQL-Installation entweder überschreiben (diese befindet
sich normalerweise im Verzeichnis
C:\mysql
) oder es in ein anderes
Verzeichnis (z. B. C:\mysql4
)
installieren. Wir empfehlen das Überschreiben der
vorhandenen Installation.
Wenn Sie MySQL als Windows-Dienst ausführen und Sie den Dienst zu einem früheren Zeitpunkt dieses Vorgangs deinstallieren mussten, installieren Sie ihn jetzt neu. (Siehe auch Abschnitt 2.3.12, „Starten von MySQL als Windows-Dienst“.)
Starten Sie den Server neu. Verwenden Sie beispielsweise NET START MySQL, wenn Sie MySQL als Dienst ausführen, oder rufen Sie mysqld auf andere Weise direkt auf.
Wenn Fehler auftreten, finden Sie weitere Informationen in Abschnitt 2.3.14, „Troubleshooting einer MySQL-Installation unter Windows“.
MySQL für Windows hat sich als sehr stabil erwiesen. Die Windows-Version von MySQL hat dieselben Merkmale wie die entsprechende Unix-Version. Es gibt jedoch folgende Ausnahmen:
Windows 95 und Threads
Pro erstelltem Thread verliert Windows 95 durch ein Speicherleck etwa 200 Byte Hauptspeicher. Jede Verbindung in MySQL erstellt einen neuen Thread, weswegen man mysqld nicht für längere Zeit unter Windows 95 ausführen sollte, wenn Ihr Server mehrere Verbindungen verwaltet! Neuere Windows-Versionen weisen diesen Bug nicht auf.
Eingeschränkte Anzahl von Ports
Windows-Systeme stellen für Clientverbindungen etwa 4000 Ports bereit. Wird eine Verbindung über einen Port beendet, dann dauert es zwei bis vier Minuten, bis der Port wieder verwendet werden kann. In Situationen, in denen Clients sehr schnell Verbindungen mit dem Server herstellen und diese wieder trennen, ist es unter Umständen möglich, dass alle verfügbaren Ports verbraucht sind, bevor bereits geschlossene Ports wieder verfügbar werden. In diesem Fall scheint der MySQL Server stehen geblieben zu sein, obwohl er tatsächlich nach wie vor ausgeführt wird. Beachten Sie, dass unter Umständen auch andere auf dem System laufenden Anwendungen Ports beanspruchen; in diesem Fall ist die Anzahl der für MySQL verfügbaren Ports noch geringer.
Weitere Informationen zu diesem Problem finden Sie unter http://support.microsoft.com/default.aspx?scid=kb;en-us;196271.
Gleichzeitige Leseoperationen
MySQL ist auf die Systemaufrufe pread()
und pwrite()
angewiesen, um
INSERT
und SELECT
miteinander kombinieren zu können. Zurzeit verwenden wir
Mutexe zur Emulation von pread()
und
pwrite()
. Wir beabsichtigen, diese
Schnittstelle auf Dateiebene in der Zukunft durch eine
virtuelle Schnittstelle zu ersetzen, damit wir die
Schnittstellen
readfile()
/writefile()
unter Windows NT, Windows 2000 und Windows XP verwenden
und so eine höhere Geschwindigkeit erzielen können. Die
aktuelle Implementierung beschränkt die Anzahl der von
MySQL 5.1 verwendbaren offenen Dateien auf
2048, d. h., Sie können unter Windows NT/2000/XP/Server
2003 nicht so viele gleichzeitige Threads ausführen wie
unter Unix.
Sperrleseoperationen
MySQL verwendet für jede Verbindung eine Sperrleseoperation. Dies hat die folgenden Auswirkungen, wenn Named-Pipe-Verbindungen aktiviert sind:
Eine Verbindung wird – anders als bei MySQL für Unix – nicht automatisch nach acht Stunden getrennt.
Hängt eine Verbindung, dann ist es nicht möglich, diese zu unterbrechen, ohne MySQL zu terminieren.
mysqladmin kill funktioniert bei hängenden Verbindungen nicht.
mysqladmin shutdown kann MySQL nicht herunterfahren, solange eine Verbindung hängt.
Wir beabsichtigen, dieses Problem in der Zukunft zu lösen.
ALTER TABLE
Während Sie eine ALTER TABLE
-Anweisung
ausführen, ist die betreffende Tabelle für die Benutzung
durch andere Threads gesperrt. Dies hängt mit der Tatsache
zusammen, dass Sie eine Datei unter Windows nicht löschen
können, solange sie von einem anderen Thread verwendet
wird. Wir hoffen, für dieses Problem in der Zukunft einen
Workaround zu finden.
DROP TABLE
Die Ausführung von DROP TABLE
für eine
Tabelle, die von einer MERGE
-Tabelle
verwendet wird, funktioniert unter Windows nicht, da der
MERGE
-Handler die Tabellenzuordnung vor
der übergeordneten Schicht von MySQL verborgen vornimmt. Da
Windows das Löschen geöffneter Dateien nicht gestattet,
müssen Sie zunächst alle MERGE
-Tabellen
(mit FLUSH TABLES
) neu laden oder die
MERGE
-Tabelle löschen, bevor Sie die
gewünschte Tabelle tatsächlich löschen können.
DATA DIRECTORY
und
INDEX DIRECTORY
Die Optionen DATA DIRECTORY
und
INDEX DIRECTORY
für CREATE
TABLE
werden unter Windows ignoriert, da Windows
keine symbolischen Verknüpfungen unterstützt. Außerdem
werden diese Optionen auf Systemen ignoriert, bei denen der
Aufruf realpath()
nicht funktioniert.
DROP DATABASE
Sie können eine Datenbank, die gerade von einem Thread verwendet wird, nicht löschen.
MySQL aus dem Task-Manager heraus terminieren
Unter Windows 95 können Sie MySQL nicht aus dem Task-Manager heraus oder mit dem Ausschalt-Utility terminieren. Sie müssen MySQL vielmehr mit dem Befehl mysqladmin shutdown beenden.
Irrelevante Groß-/Kleinschreibung bei Namen
Da die Groß-/Kleinschreibung bei Dateinamen unter Windows nicht unterschieden wird, ist auch die Schreibweise der Namen von MySQL-Datenbanken und -Tabellen unter Windows irrelevant. Die einzige Einschränkung besteht darin, dass die Datenbank- und Tabellennamen unter Verwendung derselben Schreibweise (Groß- oder Kleinschreibung) in einer gegebenen Anweisung festgelegt werden müssen. Siehe auch Abschnitt 9.2.2, „Groß-/Kleinschreibung in Namen“.
Das Pfadtrennzeichen
‘\
’
Unter Windows werden die Bestandteile von Pfaden durch das
Zeichen ‘\
’ voneinander
getrennt, welches gleichzeitig das Escape-Zeichen von MySQL
ist. Wenn Sie LOAD DATA INFILE
oder
SELECT ... INTO OUTFILE
verwenden,
verwenden Sie Dateinamen im Unix-Stil mit
‘/
’-Zeichen:
mysql>LOAD DATA INFILE 'C:/tmp/skr.txt' INTO TABLE skr;
mysql>SELECT * INTO OUTFILE 'C:/tmp/skr.txt' FROM skr;
Alternativ müssen Sie das Zeichen
‘\
’ doppelt verwenden:
mysql>LOAD DATA INFILE 'C:\\tmp\\skr.txt' INTO TABLE skr;
mysql>SELECT * INTO OUTFILE 'C:\\tmp\\skr.txt' FROM skr;
Probleme mit Pipes
An der Windows-Eingabeaufforderung funktionieren Pipes nicht
zuverlässig. Wenn eine Pipe das Zeichen
^Z
/CHAR(24)
enthält,
meint Windows ein Dateiende zu erkennen und bricht das
Programm ab.
Dies ist in erster Linie ein Problem, wenn Sie wie folgt eine binäre Logdatei anzuwenden versuchen:
C:\> mysqlbinlog binary_log_file
| mysql --user=root
Wenn Sie bei der Anwendung des Logs Probleme haben und das
Zeichen ^Z
/CHAR(24)
für die Ursache halten, dann können Sie den folgenden
Workaround verwenden:
C:\>mysqlbinlog
C:\>binary_log_file
--result-file=/tmp/bin.sqlmysql --user=root --execute "source /tmp/bin.sql"
Der untere Befehl kann auch verwendet werden, um zuverlässig in einer beliebigen SQL-Datei zu lesen, die unter Umständen Binärdateien enthält.
Fehler Access denied for
user
Wenn MySQL Ihren Hostnamen nicht korrekt auflösen kann, erhalten Sie unter Umständen folgende Fehlermeldung, sobald Sie versuchen, ein MySQL-Clientprogramm auszuführen, um eine Verbindung mit dem auf dem gleichen Computer laufenden Server herzustellen:
Access denied for user 'some_user
'@'unknown'
to database 'mysql'
Um dieses Problem zu beheben, sollten Sie eine Datei namens
\windows\hosts
erstellen, die die
folgenden Informationen enthält:
127.0.0.1 localhost
Die empfohlene Vorgehensweise zur Installation von MySQL unter
Linux besteht in der Verwendung von RPM-Paketen. Die MySQL-RPMs
werden derzeit auf einem SuSE Linux 7.3-System erstellt, sollten
aber unter den meisten Linux-Versionen funktionieren, die
rpm unterstützen und glibc
verwenden. Wie Sie sich die RPM-Pakete beschaffen, lesen Sie in
Abschnitt 2.1.3, „Woher man MySQL bekommt“.
MySQL AB bietet eine Reihe plattformspezifischer RPMs an. Der Unterschied zwischen einem plattformspezifischen und einem generischen RPM besteht darin, dass ein plattformspezifisches RPM auf der Zielplattform erstellt und dynamisch verknüpft wurde, wohingegen ein generisches RPM statisch mit LinuxThreads verknüpft ist.
Hinweis: RPM-Distributionen von MySQL werden häufig von anderen Anbietern bereitgestellt. Beachten Sie, dass Merkmale und Funktionsumfang sich von den Versionen unterscheiden können, die von MySQL AB angeboten werden, und dass die Angaben in diesem Handbuch nicht unbedingt für deren Installation gelten. Ziehen Sie im Zweifelsfall die Dokumentation des Anbieters zu Rate.
Wenn Sie Probleme mit einer RPM-Datei haben (also etwa, wenn die
Fehlermeldung Sorry, the host
'
angezeigt wird), finden Sie weitere Informationen in
Abschnitt 2.12.1.2, „Anmerkungen zur Binärdistribution (Linux)“.
xxxx
' could not be looked
up
In den meisten Fällen müssen Sie nur die Pakete
MySQL-server
und
MySQL-client
installieren, um eine lauffähige
MySQL-Installation zu erhalten. Die übrigen Pakete sind für eine
Standardinstallation nicht erforderlich. Wenn Sie einen
MySQL-Max-Server mit Zusatzfunktionen verwenden wollen, sollten
Sie auch das RPM MySQL-Max
installieren.
Allerdings sollten Sie dies erst nach der
Installation des MySQL-server
-RPM durchführen.
Siehe auch Abschnitt 5.3, „mysqld-max, ein erweiterter mysqld-Server“.
Wenn Sie bei dem Versuch, MySQL-Pakete zu installieren, einen
Abhängigkeitsfehler erhalten (z. B. error: removing
these packages would break dependencies: libmysqlclient.so.10 is
needed by ...
), dann sollten Sie auch das Paket
MySQL-shared-compat
installieren, denn dieses
enthält die beiden gemeinsamen Bibliotheken für die
Abwärtskompatibilität (libmysqlclient.so.12
für MySQL 4.0 und libmysqlclient.so.10
für
MySQL 3.23) .
Einige Linux-Distributionen werden immer noch mit MySQL 3.23
ausgeliefert und verknüpfen Anwendungen gewöhnlich dynamisch, um
Festplattenkapazität zu sparen. Befinden sich diese gemeinsamen
Bibliotheken in einem separaten Paket (z. B.
MySQL-shared
), dann reicht es aus, dieses Paket
einfach installiert zu lassen und nur die MySQL Server- und
-Clientpakete zu aktualisieren (diese sind statisch verknüpft und
hängen nicht von den gemeinsamen Bibliotheken ab). Bei
Distributionen, in denen die gemeinsamen Bibliotheken im selben
Paket enthalten sind wie der MySQL Server (z. B. Red Hat Linux),
können Sie entweder unser MySQL-shared
-RPM
für Version 3.23 installieren oder stattdessen das Paket
MySQL-shared-compat
verwenden.
Die folgenden RPM-Pakete sind verfügbar:
MySQL-server-
VERSION
.i386.rpm
Das ist der MySQL Server. Sie benötigen ihn in jedem Fall,
sofern Sie nicht lediglich eine Verbindung mit einem MySQL
Server herstellen wollen, der auf einem anderen Computer
ausgeführt wird. Hinweis:
Server-RPM-Dateien hießen vor MySQL 4.0.10
MySQL-
(d. h., der Zusatz VERSION
.i386.rpm-server
war im Namen
nicht enthalten).
MySQL-Max-
VERSION
.i386.rpm
Das ist der MySQL Max-Server. Dieser Server verfügt über
zusätzliche Fähigkeiten, die der Server im RPM
MySQL-server
nicht aufweist. Sie müssen
das RPM MySQL-server
jedoch zuerst
installieren, da es für MySQL-Max
erforderlich ist.
MySQL-client-
VERSION
.i386.rpm
Die MySQL-Standardclientprogramme. Dieses Paket sollten Sie immer installieren.
MySQL-bench-
VERSION
.i386.rpm
Tests und Benchmarks. Erfordert Perl und das Modul
DBD::mysql
.
MySQL-devel-
VERSION
.i386.rpm
Die Bibliotheken und Include-Dateien, die erforderlich sind, wenn Sie andere MySQL-Clients (z. B. die Perl-Module) kompilieren wollen.
MySQL-shared-
VERSION
.i386.rpm
Dieses Paket enthält die gemeinsamen Bibliotheken
(libmysqlclient.so*
), die bestimmte
Sprachen und Anwendungen benötigen, um MySQL dynamisch laden
und verwenden zu können.
MySQL-shared-compat-
VERSION
.i386.rpm
Dieses Paket enthält die gemeinsamen Bibliotheken für MySQL
3.23 und MySQL 4.0. Installieren Sie es statt
MySQL-shared
, wenn Sie Anwendungen haben,
die dynamisch mit MySQL 3.23 verknüpft sind, Sie aber auf
MySQL 4.0 aktualisieren wollen, ohne die
Bibliotheksabhängigkeiten zu durchbrechen. Das Paket ist ab
MySQL 4.0.13 verfügbar.
MySQL-embedded-
VERSION
.i386.rpm
Dies ist die eingebettete MySQL Server-Bibliothek (verfügbar ab MySQL 4.0).
MySQL-
VERSION
.src.rpm
Dieses Paket enthält den Quellcode aller zuvor aufgeführten Pakete. Es kann auch zur Neuerstellung der RPMs auf anderen Architekturen (z. B. Alpha oder SPARC) verwendet werden.
Um alle in einem RPM-Paket (z. B. einem
MySQL-server
-RPM) enthaltenen Dateien
anzuzeigen, führen Sie den folgenden Befehl aus:
shell> rpm -qpl MySQL-server-VERSION
.i386.rpm
Wollen Sie eine minimale Standardinstallation durchführen, dann installieren Sie die Server- und Client-RPMs:
shell>rpm -i MySQL-server-
shell>VERSION
.i386.rpmrpm -i MySQL-client-
VERSION
.i386.rpm
Wenn Sie nur die Clientprogramme benötigen, dann installieren Sie lediglich das Client-RPM:
shell> rpm -i MySQL-client-VERSION
.i386.rpm
Das RPM-Format bietet eine Funktion zur Überprüfung der
Integrität und Authentifizierung von Paketen vor der
Installation. Wenn Sie mehr zu dieser Funktion erfahren wollen,
lesen Sie Abschnitt 2.1.4, „Bestätigen der Paketintegrität mittels MD5-Prüfsummen oder
GnuPG
“.
Das Server-RPM legt Daten im Verzeichnis
/var/lib/mysql
ab. Außerdem richtet das RPM
ein Anmeldekonto für einen Benutzer namens
mysql
(sofern nicht bereits vorhanden) ein,
über das der MySQL Server ausgeführt wird, und erstellt die
entsprechenden Einträge in /etc/init.d/
, um
den Server automatisch mit dem System zu starten. (Dies bedeutet,
dass Sie, wenn Sie zuvor bereits eine Installation durchgeführt
und Änderungen an deren Startskript vorgenommen haben, eine Kopie
des Skripts erstellen sollten, damit es bei der Installation eines
neueren RPM nicht verloren geht.) Weitere Informationen dazu, wie
MySQL automatisch mit dem System gestartet werden kann, finden Sie
in Abschnitt 2.9.2.2, „MySQL automatisch starten und anhalten“.
Wenn Sie das MySQL-RPM auf älteren Linux-Distributionen
installieren wollen, die Initialisierungsskripten in
/etc/init.d
noch nicht (direkt oder über
eine symbolische Verknüpfung) unterstützen, dann sollten Sie
eine symbolische Verknüpfung erstellen, die auf die Position
verweist, an der Ihre Initialisierungsskripten tatsächlich
installiert sind. Heißt die Position etwa
/etc/rc.d/init.d
, dann geben Sie vor der
Installation des RPM die folgenden Befehle ein, um
/etc/init.d
als symbolische Verknüpfung zu
erstellen, die darauf verweist:
shell>cd /etc
shell>ln -s rc.d/init.d .
Allerdings sollten die aktuellen Versionen aller wichtigen
Linux-Distributionen das neue Verzeichnislayout unterstützen, das
/etc/init.d
verwendet, da es für die
LSB-Kompatibilität (Linux Standard Base) erforderlich ist.
Wenn zu den RPM-Dateien, die Sie installieren,
MySQL-server
gehört, dann sollte der Server
mysqld nach der Installation einwandfrei
funktionieren. Sie sollten ihn mithilfe von MySQL starten können.
Klappt etwas nicht, dann erhalten Sie weitere Informationen im Abschnitt zur Installation von Binärdistributionen. Siehe auch Abschnitt 2.7, „Installation von MySQL auf anderen Unix-ähnlichen Systemen“.
Hinweis: Für die in den MySQL-Grant-Tabellen aufgeführten Konten gibt es zunächst noch keine Passwörter. Wenn Sie den Server gestartet haben, sollten Sie entsprechend der in Abschnitt 2.9, „Einstellungen und Tests nach der Installation“, beschriebenen Verfahrensweise Passwörter für diese Konten einrichten.
Sie können MySQL unter Mac OS X 10.2.x („Jaguar“) oder höher mithilfe eines Mac OS X-Binärpakets im PKG-Format anstelle der binären Tar-Distribution installieren. Bitte beachten Sie, dass ältere Mac OS X-Versionen (z. B. 10.1.x) nicht durch dieses Paket unterstützt werden.
Das Paket befindet sich in einer Festplattenimagedatei
(.dmg
), die Sie zunächst einbinden müssen.
Doppelklicken Sie im Finder auf das zugehörige Symbol. Danach
binden Sie das Image ein und zeigen seinen Inhalt an.
Wie Sie sich MySQL beschaffen, lesen Sie in Abschnitt 2.1.3, „Woher man MySQL bekommt“.
Hinweis: Bevor Sie mit der Installation fortfahren, müssen Sie alle laufenden MySQL Server-Instanzen herunterfahren. Dies tun Sie entweder mit der MySQL-Manager-Anwendung (unter Mac OS X Server) oder mithilfe von mysqladmin shutdown an der Befehlszeile.
Um nun die MySQL-PGK-Datei zu installieren, doppelklicken Sie auf das Paketsymbol. Nun wird das Installationsprogramm für das Mac OS X-Paket gestartet. Dieses Programm geleitet Sie durch die Installation von MySQL.
Aufgrund eines Bugs im Mac OS X-Paketinstallationsprogramm wird bei Anzeige des Dialogfelds zur Auswahl des Ziellaufwerks unter Umständen die folgende Fehlermeldung angezeigt:
You cannot install this software on this disk. (null)
Klicken Sie in diesem Fall einmal auf die Schaltfläche
Go Back
, um zum vorherigen Bildschirm
zurückzukehren. Klicken Sie dann auf Continue
,
um das Dialogfeld zur Auswahl des Ziellaufwerks erneut aufzurufen.
Nun sollten Sie das Ziellaufwerk problemlos auswählen können.
Wir haben diesen Bug Apple bereits gemeldet. Das Problem wird dort
untersucht.
Das Mac OS X-PKG von MySQL installiert sich im Verzeichnis
/usr/local/mysql-
.
Ferner wird eine symbolische Verknüpfung
VERSION
/usr/local/mysql
eingerichtet, die ebenfalls
auf die neue Position verweist. Ist ein Verzeichnis namens
/usr/local/mysql
bereits vorhanden, dann wird
dieses zunächst in /usr/local/mysql.bak
umbenannt. Außerdem erstellt das Installationsprogramm die
Grant-Tabellen in der mysql
-Datenbank. Hierzu
führt es den Befehl mysql_install_db aus.
Das Installationslayout ähnelt dem einer
tar-Binärdistribution: Alle
MySQL-Binärdateien befinden sich im Verzeichnis
/usr/local/mysql/bin
. Die MySQL-Socketdatei
wird standardmäßig als /tmp/mysql.sock
erstellt. Siehe auch Abschnitt 2.1.5, „Installationslayouts“.
Für die MySQL-Installation ist ein Mac OS X-Benutzerkonto mit dem
Namen mysql
erforderlich. Unter Mac OS X 10.2
und höher sollte ein solches Konto standardmäßig vorhanden
sein.
Wenn Sie Mac OS X Server ausführen, sollte eine MySQL-Version bereits installiert sein. Die folgende Tabelle zeigt die MySQL-Versionen, die mit den verschiedenen Versionen von Mac OS X Server ausgeliefert werden.
Mac OS X Server-Version | MySQL-Version |
10.2–10.2.2 | 3.23.51 |
10.2.3–10.2.6 | 3.23.53 |
10.3 | 4.0.14 |
10.3.2 | 4.0.16 |
10.4.0 | 4.1.10a |
Dieses Handbuch behandelt nur die Installation des offiziellen MySQL-PKG für Mac OS X. Lesen Sie in jedem Fall Apples Hilfeinformationen zur Installation von MySQL: Starten Sie die Anwendung „Hilfeanzeige“ und wählen Sie die Hilfe für „Mac OS X-Server“. Suchen Sie dann nach dem Begriff „MySQL“ und lesen Sie das Thema „MySQL installieren“.
Beachten Sie bei vorinstallierten MySQL-Versionen auf Mac OS X Server insbesondere, dass Sie mysqld mit dem Befehl safe_mysqld statt mysqld_safe starten müssen, wenn die betreffende MySQL-Version älter ist als 4.0.
Haben Sie zuvor MySQL-Pakete für Mac OS X von Marc Liyanage verwendet (http://www.entropy.ch), dann können Sie die auf den dortigen Seiten beschriebenen Aktualisierungsanweisungen für Pakete einfach unter Verwendung der dort bezeichneten Installationsstruktur für Binärdistributionen befolgen.
Aktualisieren Sie von Marcs Versionen 3.23.xx oder von der Mac OS X Server-Version von MySQL auf das offizielle MySQL-PKG, dann müssen Sie die vorhandenen MySQL-Berechtigungstabellen ebenfalls in das aktuelle Format konvertieren, da einige neue Sicherheitsberechtigungen hinzugefügt worden sind. Siehe auch Abschnitt 5.6, „mysql_fix_privilege_tables — Upgrade von MySQL-Systemtabellen“.
Wenn Sie wollen, dass MySQL während des Systemstarts automatisch gestartet wird, müssen Sie auch das MySQL-Startobjekt installieren. Es ist auf dem Mac OS X-Installationsmedium als separates Installationspaket enthalten. Doppelklicken Sie einfach auf das Symbol MySQLStartupItem.pkg und folgen Sie dann den Anweisungen am Bildschirm.
Beachten Sie, dass das Startobjekt nur einmal installiert werden darf! Es ist nicht notwendig, das Startobjekt bei jeder späteren Aktualisierung des MySQL-Pakets vorzunehmen.
Das Startobjekt für MySQL wird in
/Library/Startobjekte/MySQLCOM
installiert.
(Vor MySQL 4.1.2 hieß das Verzeichnis
/Library/StartupItems/MySQL
, aber dies führt
zu einem Konflikt mit dem MySQL-Startobjekt, das von Mac OS X
Server installiert wurde.) Bei der Startobjektinstallation wird
eine Variable MYSQLCOM=-YES-
in der
Systemkonfigurationsdatei /etc/hostconfig
ergänzt. Wenn Sie den automatischen Start von MySQL deaktivieren
wollen, ändern Sie einfach den Wert der Variablen wie folgt:
MYSQLCOM=-NO-
.
Unter Mac OS X Server verwendet die MySQL-Standardinstallation die
Variable MYSQL
in der Datei
/etc/hostconfig
. Das
Startobjekt-Installationsprogramm von MySQL AB deaktiviert diese
Variable (MYSQL=-NO-
). Hierdurch werden beim
Systemstart Konflikte mit der Variablen
MYSQLCOM
vermieden, die vom MySQL
AB-Startobjekt verwendet wird. Allerdings wird dabei ein laufender
MySQL Server nicht heruntergefahren. Dies müssen Sie selbst
erledigen.
Nach der Installation können Sie MySQL mithilfe der folgenden Befehle in einem Terminal-Fenster ausführen. Um diesen Vorgang durchzuführen, benötigen Sie Administratorrechte.
Wenn Sie das Startobjekt installiert haben, verwenden Sie folgenden Befehl:
shell>sudo /Library/StartupItems/MySQLCOM/MySQLCOM start
(Enter your password, if necessary)
(Press Control-D or enter "exit" to exit the shell)
Wenn Sie das Startobjekt hingegen nicht installiert haben, geben Sie diese Befehlsfolge ein:
shell>cd /usr/local/mysql
shell>sudo ./bin/mysqld_safe
(Enter your password, if necessary)
(Press Control-Z)
shell>bg
(Press Control-D or enter "exit" to exit the shell)
Sie sollten nun in der Lage sein, eine Verbindung zum MySQL Server
herzustellen. Hierzu können Sie etwa
/usr/local/mysql/bin/mysql
ausführen.
Hinweis: Für die in den MySQL-Grant-Tabellen aufgeführten Konten gibt es zunächst noch keine Passwörter. Wenn Sie den Server gestartet haben, sollten Sie entsprechend der in Abschnitt 2.9, „Einstellungen und Tests nach der Installation“, beschriebenen Verfahrensweise Passwörter für diese Konten einrichten.
Sie sollten in der Ressourcendatei Ihrer Shell Aliase ergänzen, um den Zugriff auf häufig verwendete Programme wie mysql und mysqladmin über die Befehlszeile zu erleichtern. Die Syntax für bash lautet:
alias mysql=/usr/local/mysql/bin/mysql alias mysqladmin=/usr/local/mysql/bin/mysqladmin
Für tcsh verwenden Sie Folgendes:
alias mysql /usr/local/mysql/bin/mysql alias mysqladmin /usr/local/mysql/bin/mysqladmin
Noch vorteilhafter ist es, /usr/local/mysql/bin
zur Umgebungsvariablen PATH
hinzuzufügen.
Fügen Sie beispielsweise die folgende Zeile zu Ihrer Datei
$HOME/.bashrc
hinzu, wenn Sie
bash als Shell verwenden:
PATH=${PATH}:/usr/local/mysql/bin
Fügen Sie folgende Zeile zu Ihrer Datei
$HOME/.tcshrc
hinzu, wenn Sie
tcsh als Shell verwenden:
setenv PATH ${PATH}:/usr/local/mysql/bin
Wenn weder .bashrc
noch
.tcshrc
in Ihrem Homeverzeichnis vorhanden
sind, erstellen Sie die Datei mit einem Texteditor.
Aktualisieren Sie eine vorhandene Installation, dann beachten Sie, dass, wenn Sie ein neues MySQL-PKG installieren, das Verzeichnis der alten Installation nicht entfernt wird. Leider bietet das Mac OS X-Installationsprogramm noch nicht die Funktionalität, die zur korrekten Aktualisierung zuvor installierter Pakete erforderlich ist.
Um Ihre vorhandenen Datenbanken mit der neuen Installation
verwenden zu können, müssen Sie den Inhalt des alten
Datenverzeichnisses in das neue Datenverzeichnis kopieren. Stellen
Sie sicher, dass weder der alte noch der neue Server laufen,
während Sie diesen Kopiervorgang durchführen. Haben Sie die
MySQL-Datenbankdateien der alten Installation kopiert und den
neuen Server erfolgreich gestartet, dann können Sie die alten
Installationsdateien entfernen, um Festplattenspeicher zu sparen.
Ebenfalls entfernen sollten Sie ältere Versionen der
Package-Receipt-Verzeichnisse in
/Library/Receipts/mysql-
.
VERSION
.pkg
Die Portierung von MySQL auf NetWare wurde von Novell gezielt unterstützt. Kunden von Novell werden erfreut sein zu erfahren, dass NetWare 6.5 im Bündel mit MySQL-Binärdateien ausgeliefert wird – komplett mit einer automatischen Lizenz zur kommerziellen Nutzung, gültig für alle Server, auf denen diese NetWare-Version läuft.
MySQL für NetWare wird mithilfe einer Kombination aus Metrowerks CodeWarrior for NetWare und speziellen Versionen der GNU-Autotools zur Cross-Kompilierung kompiliert.
Die aktuellen Binärpakete für NetWare erhalten Sie unter http://dev.mysql.com/downloads/. Siehe auch Abschnitt 2.1.3, „Woher man MySQL bekommt“.
Ein NetWare-Server, auf dem MySQL laufen soll, muss die folgenden Anforderungen erfüllen:
Das aktuelle Support Pack für NetWare 6.5 muss installiert sein.
Das System muss die Mindestanforderungen erfüllen, die Novell für die Ausführung der betreffenden NetWare-Version stellt.
MySQL-Daten und die Programmbinärdateien müssen auf einem NSS-Volume installiert sein (traditionelle Volumes werden nicht unterstützt).
Gehen Sie wie folgt vor, um MySQL für NetWare zu installieren:
Wenn Sie eine vorhandene Installation aktualisieren, beenden Sie den MySQL Server. Hierzu geben Sie den folgenden Befehl an der Serverkonsole ein:
SERVER: mysqladmin -u root shutdown
Hinweis: Wenn das
MySQL-Benutzerkonto root
ein Passwort
aufweist, müssen Sie mysqladmin mit der
Option -p
aufrufen und das Passwort auf
Aufforderung angeben.
Melden Sie sich am Zielserver über einen Clientcomputer an, der Zugriff auf das Verzeichnis hat, in dem Sie MySQL installieren wollen.
Extrahieren Sie die ZIP-Datei mit dem Binärpaket auf den
Server. Stellen Sie dabei sicher, dass die in der ZIP-Datei
gespeicherten Pfade verwendet werden. Am sichersten ist das
einfache Entpacken nach SYS:\
.
Wenn Sie eine vorhandene Installation aktualisieren, müssen
Sie unter Umständen das Datenverzeichnis (beispielsweise
SYS:MYSQL\DATA
) kopieren. Gleiches gilt
für die Datei my.cnf
, sofern Sie diese
an Ihre Bedürfnisse angepasst haben. Danach können Sie die
alte Kopie von MySQL löschen.
Sie sollten dem Verzeichnis einen anderen, konsistenteren und
einfacher zu handhabenden Namen geben. In den Beispielen
dieses Handbuchs verwenden wir SYS:MYSQL
als Bezeichnung für das Installationsverzeichnis.
Beachten Sie, dass die MySQL-Installation unter NetWare nicht
erkennt, ob eine MySQL-Version außerhalb des NetWare-Releases
bereits vorhanden ist. Haben Sie also etwa die aktuelle
MySQL-Version (ab MySQL 4.1 oder höher) aus dem Web in
SYS:\MYSQL
installiert, dann müssen Sie
den Ordner umbenennen, bevor Sie den NetWare-Server
aktualisieren; andernfalls werden in
SYS:\MySQL
vorhandene Dateien, die im
NetWare Support Pack abgelegt sind, mit der MySQL-Version
überschrieben.
Fügen Sie an der Serverkonsole einen Suchpfad für das Verzeichnis hinzu, welches die MySQL-NLMs enthält. Ein Beispiel:
SERVER: SEARCH ADD SYS:MYSQL\BIN
Initialisieren Sie ggf. das Datenverzeichnis und die Grant-Tabellen, indem Sie mysql_install_db an der Serverkonsole ausführen.
Starten Sie den MySQL Server mit mysqld_safe an der Serverkonsole.
Um die Installation abzuschließen, sollten Sie auch die
folgenden Befehle in der Datei
autoexec.ncf
ergänzen. Wenn Ihre
MySQL-Installation beispielsweise in
SYS:MYSQL
abgelegt ist und Sie MySQL
automatisch starten wollen, fügen Sie folgende Befehle hinzu:
#Starts the MySQL 5.1.x database server SEARCH ADD SYS:MYSQL\BIN MYSQLD_SAFE
Führen Sie MySQL unter NetWare 6.0 aus, dann empfehlen wir
Ihnen dringend die Verwendung der Option
--skip-external-locking
in der Befehlszeile:
#Starts the MySQL 5.1.x database server SEARCH ADD SYS:MYSQL\BIN MYSQLD_SAFE --skip-external-locking
Ferner ist es notwendig, CHECK TABLE
und
REPAIR TABLE
anstelle von
myisamchk zu verwenden, da
myisamchk externe Sperren verwendet. Die
externe Sperrung bereitet bei NetWare 6.0 bekanntermaßen
Probleme. Diese wurden jedoch in NetWare 6.5 beseitigt.
mysqld_safe stellt unter NetWare eine Bildschirmpräsenz bereit. Wenn Sie das NLM mysqld_safe entladen (herunterfahren), verschwindet der Bildschirm standardmäßig nicht. Stattdessen wird eine Benutzereingabe angefordert:
*<NLM has terminated; Press any key to close the screen>*
Wenn Sie hingegen wollen, dass NetWare den Bildschirm
automatisch schließt, dann verwenden Sie die Option
--autoclose
für
mysqld_safe. Ein Beispiel:
#Starts the MySQL 5.1.x database server SEARCH ADD SYS:MYSQL\BIN MYSQLD_SAFE --autoclose
Wenn Sie MySQL installieren – sei es zum ersten Mal oder im Zuge der Aktualisierung von einer vorherigen Version –, dann müssen Sie das aktuellste passende Perl-Modul und die geeigneten PHP-Erweiterungen für NetWare herunterladen:
Perl: http://forge.novell.com/modules/xfcontent/downloads.php/perl/Modules/
PHP: http://forge.novell.com/modules/xfcontent/downloads.php/php/Modules/
(Die PHP 5-Erweiterung für MySQL 4.1 sollte auch mit MySQL 5.1 funktionieren.)
Das Verhalten von mysqld_safe unter NetWare wird in Abschnitt 5.4.1, „mysqld_safe — Startskript für den MySQL-Server“, detailliert beschrieben.
War auf dem NetWare-Server bereits eine MySQL-Installation
vorhanden, dann müssen Sie in jedem Fall in der Datei
autoexec.ncf
nach MySQL-Startbefehlen suchen
und diese nach Bedarf bearbeiten oder löschen.
Hinweis: Für die in den MySQL-Grant-Tabellen aufgeführten Konten gibt es zunächst noch keine Passwörter. Wenn Sie den Server gestartet haben, sollten Sie entsprechend der in Abschnitt 2.9, „Einstellungen und Tests nach der Installation“, beschriebenen Verfahrensweise Passwörter für diese Konten einrichten.
Dieser Abschnitt behandelt die Installation der
MySQL-Binärdistributionen, die für die verschiedenen Plattformen
in Form komprimierter tar-Dateien (d. h.
Dateien mit der Erweiterung .tar.gz
) vorliegen.
Eine detaillierte Liste finden Sie in
Abschnitt 2.1.2.5, „MySQL-Binärdistributionen, die von MySQL AB kompiliert wurden“.
Wie Sie sich MySQL beschaffen, lesen Sie in Abschnitt 2.1.3, „Woher man MySQL bekommt“.
Eine tar-Datei mit einer Binärdistribution
weist einen Namen mit dem Aufbau
mysql-
auf. Hierbei ist VERSION
-OS
.tar.gz
eine Zahl (z. B.
VERSION
5.1.5-alpha
), während
OS
das Betriebssystem bezeichnet, für
das die Distribution vorgesehen ist (beispielsweise
pc-linux-i686
).
Neben diesen Universalpaketen bieten wir für ausgewählte Plattformen auch Binärdateien in plattformspezifischen Paketformaten an. Weitere Informationen zur Installation dieser Pakete finden Sie in Abschnitt 2.2, „Schnelle Standardinstallation von MySQL“.
Um eine MySQL-Binärdistribution in einer tar-Datei zu installieren, benötigen Sie die folgenden Tools:
GNU gunzip
zum Dekomprimieren der
Distribution.
Ein anständiges tar zum Entpacken der Distribution. GNU tar funktioniert bekanntermaßen. Bestimmte Betriebssysteme enthalten eine vorinstallierte Version von tar, die aber offenbar problematisch ist. Beispielsweise haben die tar-Varianten von Mac OS X und Sun Probleme mit langen Dateinamen. Unter Mac OS X können Sie das vorinstallierte Programm gnutar verwenden. Auf anderen Systemen mit fehlerhaften tar-Anwendungen sollten Sie zunächst GNU tar installieren.
Sollten Sie auf Probleme stoßen und einen Fehlerbericht speichern wollen, dann gehen Sie vor wie in Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“, beschrieben.
Die wichtigsten Befehle, die bei der Installation und Verwendung einer MySQL-Binärdistribution ausgeführt werden müssen, sind die folgenden:
shell>groupadd mysql
shell>useradd -g mysql mysql
shell>cd /usr/local
shell>gunzip <
shell>/path/to/mysql-VERSION-OS
.tar.gz | tar xvf -ln -s
shell>full-path-to-mysql-VERSION-OS
mysqlcd mysql
shell>scripts/mysql_install_db --user=mysql
shell>chown -R root .
shell>chown -R mysql data
shell>chgrp -R mysql .
shell>bin/mysqld_safe --user=mysql &
Hinweis: Beim folgenden Vorgang werden keine Passwörter für MySQL-Konten eingerichtet. Wenn Sie den Vorgang abgeschlossen haben, fahren Sie fort bei Abschnitt 2.9, „Einstellungen und Tests nach der Installation“.
Hier nun eine detailliertere Version der vorangegangenen Beschreibung zur Installation einer Binärdistribution:
Fügen Sie einen Anmeldebenutzer und eine Gruppe hinzu, unter denen mysqld ausgeführt wird:
shell>groupadd mysql
shell>useradd -g mysql mysql
Diese Befehle fügen die Gruppe mysql
und
den Benutzer mysql
hinzu. Die Syntax für
useradd und groupadd
kann bei den verschiedenen Unix-Varianten etwas anders
aussehen. Auch können die Befehlsnamen selbst variieren
(z. B. adduser und
addgroup).
Unter Umständen wollen Sie dem Benutzer und der Gruppe einen
anderen Namen als mysql
zuweisen. In diesem
Fall müssen Sie in den folgenden Schritten den entsprechenden
Namen einsetzen.
Wählen Sie das Verzeichnis aus, in das Sie die Distribution
entpacken wollen, und rufen Sie dieses auf. Im folgenden
Beispiel entpacken wir die Distribution in
/usr/local
. (Die folgenden Anweisungen
setzen deswegen auch voraus, dass Sie Berechtigungen zum
Erstellen von Dateien und Verzeichnissen in
/usr/local
haben. Ist das Verzeichnis
geschützt, dann müssen Sie die Installation als
root
durchführen.)
shell> cd /usr/local
Beschaffen Sie sich wie in Abschnitt 2.1.3, „Woher man MySQL bekommt“, beschrieben eine Distributionsdatei. Die Binärdistributionen für alle Plattformen werden innerhalb eines Releases aus derselben MySQL-Quelldistribution erstellt.
Entpacken Sie die Distribution. Hierdurch wird das Installationsverzeichnis erstellt. Erstellen Sie dann eine symbolische Verknüpfung zu diesem Verzeichnis:
shell>gunzip <
shell>/path/to/mysql-VERSION-OS
.tar.gz | tar xvf -ln -s
full-path-to-mysql-VERSION-OS
mysql
Der Befehl tar erstellt ein Verzeichnis
namens
mysql-
.
Der Befehl VERSION
-OS
ln
legt eine symbolische
Verknüpfung zu diesem Verzeichnis an. Auf diese Weise können
Sie das Installationsverzeichnis einfacher aufrufen als über
/usr/local/mysql
.
Bei GNU tar ist kein separater Aufruf von
gunzip
erforderlich. Sie können die erste
Zeile mit dem folgenden Alternativbefehl ersetzen, um die
Distribution zu dekomprimieren und zu entpacken:
shell> tar zxvf /path/to/mysql-VERSION-OS
.tar.gz
Wechseln Sie nun in das Installationsverzeichnis:
shell> cd mysql
Sie werden im Verzeichnis mysql
verschiedene Dateien und Unterverzeichnisse vorfinden. Die
für die Installation wichtigsten Elemente sind die
Unterverzeichnisse bin
und
scripts
:
Das Verzeichnis bin
enthält
Clientprogramme und den Server. Sie sollten den
vollständigen Pfadnamen dieses Verzeichnisses zu Ihrer
Umgebungsvariablen PATH
hinzufügen,
damit Ihre Shell die MySQL-Programme korrekt findet. Siehe
auch Anhang F, Umgebungsvariablen.
Das Verzeichnis scripts
enthält das
Skript mysql_install_db, welches zur
Initialisierung der mysql
-Datenbank mit
den Grant-Tabellen verwendet wird, in denen die
Serverzugriffsberechtigungen gespeichert sind.
Wenn Sie MySQL vorher noch nicht installiert hatten, müssen Sie die MySQL-Grant-Tabellen erstellen:
shell> scripts/mysql_install_db --user=mysql
Wenn Sie den Befehl als root
ausführen,
müssen Sie wie gezeigt die Option --user
verwenden. Als Wert der Option sollte der Name des
Anmeldekontos eingetragen werden, das Sie im ersten Schritt
zur Verwendung für die Ausführung des Servers angegeben
haben. Wenn Sie den Befehl ausführen, während Sie als dieser
Benutzer angemeldet sind, können Sie die Option
--user
weglassen.
Nach Erstellung oder Aktualisierung der Grant-Tabellen müssen Sie den Server manuell neu starten.
Weisen Sie als neuen Besitzer der Programmbinärdateien
root
und als neuen Besitzer des
Datenverzeichnisses den Benutzer zu, unter dessen Konto Sie
mysqld ausführen. Wenn Sie sich etwa im
Installationsverzeichnis
(/usr/local/mysql
) befinden, sieht der
Befehl wie folgt aus:
shell>chown -R root .
shell>chown -R mysql data
shell>chgrp -R mysql .
Der erste Befehl setzt das Besitzerattribut der Dateien auf
den Benutzer root
. Der zweite setzt das
Besitzerattribut des Datenverzeichnisses auf den Benutzer
mysql
. Der dritte schließlich setzt das
Gruppenattribut auf die Gruppe mysql
.
Wenn Sie wollen, dass MySQL beim Starten des Computers
automatisch startet, können Sie
support-files/mysql.server
in das
Verzeichnis kopieren, in dem sich die Startdateien Ihres
Systems befinden. Weitere Informationen finden Sie im Skript
support-files/mysql.server
selbst und in
Abschnitt 2.9.2.2, „MySQL automatisch starten und anhalten“.
Neue Konten können Sie mit dem Skript
bin/mysql_setpermission einrichten, wenn
Sie die Perl-Module DBI
und
DBD::mysql
installieren. Informationen zur
Vorgehensweise finden Sie in
Abschnitt 2.13, „Anmerkungen zur Perl-Installation“.
Wenn Sie mysqlaccess verwenden wollen und
Ihre MySQL-Distribution in einem anderen als dem
Standardverzeichnis abgelegt ist, müssen Sie die Position
ändern, an der mysqlaccess den
mysql-Client vorzufinden erwartet.
Bearbeiten Sie das Skript bin/mysqlaccess
im Bereich von Zeile 18. Suchen Sie nach einer Zeile ähnlich
der folgenden:
$MYSQL = '/usr/local/bin/mysql'; # path to mysql executable
Ändern Sie den Pfad so ab, dass er die Position wiedergibt,
an der mysql tatsächlich auf Ihrem System
gespeichert ist. Andernfalls wird die Fehlermeldung
Broken Pipe
angezeigt, wenn Sie
mysqlaccess ausführen.
Nachdem alles entpackt und installiert wurde, sollten Sie Ihre Distribution testen. Verwenden Sie den folgenden Befehl, um den MySQL Server zu starten:
shell> bin/mysqld_safe --user=mysql &
Wenn der Befehl sofort fehlschlägt und die Meldung
mysqld ended
ausgibt, finden Sie unter
Umständen hilfreiche Informationen in der Datei
im
Datenverzeichnis.
host_name
.err
Weitere Informationen zu mysqld_safe können Sie Abschnitt 5.4.1, „mysqld_safe — Startskript für den MySQL-Server“, entnehmen.
Hinweis: Für die in den MySQL-Grant-Tabellen aufgeführten Konten gibt es zunächst noch keine Passwörter. Wenn Sie den Server gestartet haben, sollten Sie entsprechend der in Abschnitt 2.9, „Einstellungen und Tests nach der Installation“, beschriebenen Verfahrensweise Passwörter für diese Konten einrichten.
Bevor Sie mit einer Installation aus einer Quelldistribution fortfahren, überprüfen Sie zunächst, ob nicht für Ihre Plattform eine Binärdatei von uns angeboten wird, die für Ihre Belange geeignet sein könnte. Wir haben viel Aufwand betrieben, um zu gewährleisten, dass unsere Binärdateien mit den optimalen Optionen erstellt werden.
Wie Sie sich eine MySQL-Quelldistribution beschaffen, erfahren Sie in Abschnitt 2.1.3, „Woher man MySQL bekommt“.
MySQL-Quelldistributionen werden als komprimierte
tar-Archive bereitgestellt. Der Dateiname hat
den folgenden Aufbau:
mysql-
.
Hierbei ist VERSION
.tar.gzVERSION
eine Zahl wie
beispielsweise 5.1.5-alpha
.
Zur Installation von MySQL aus einer Quelldistribution benötigen Sie die folgenden Tools:
GNU gunzip
zum Dekomprimieren der
Distribution.
Ein anständiges tar zum Entpacken der Distribution. GNU tar funktioniert bekanntermaßen. Bestimmte Betriebssysteme enthalten eine vorinstallierte Version von tar, die aber offenbar problematisch ist. Beispielsweise haben die tar-Varianten von Mac OS X und Sun Probleme mit langen Dateinamen. Unter Mac OS X können Sie das vorinstallierte Programm gnutar verwenden. Auf anderen Systemen mit fehlerhaften tar-Anwendungen sollten Sie zunächst GNU tar installieren.
Einen funktionsfähigen ANSI C++-Compiler.
gcc 2.95.2 oder höher,
egcs 1.0.2 oder höher oder egcs
2.91.66, SGI C++ und SunPro C++ sind Compiler, die
offensichtlich problemlos funktionieren.
libg++
wird bei der Verwendung von
gcc nicht benötigt. gcc
2.7.x weist einen Fehler auf, der die Kompilierung bestimmter,
hundertprozentig zulässiger C++-Dateien wie etwa
sql/sql_base.cc
unmöglich macht. Wenn
Sie nur gcc 2.7.x haben, müssen Sie Ihr
gcc so aktualisieren, dass es MySQL
kompilieren kann. Auch gcc 2.8.1 weist
bekanntermaßen Probleme auf bestimmten Plattformen auf,
sollte also ebenfalls außen vor gelassen werden, sofern auf
der betreffenden Plattform ein neuerer Compiler verfügbar
ist.
gcc 2.95.2 oder höher wird zur Kompilierung von MySQL 3.23.x empfohlen.
Ein gutes make-Programm. GNU make wird immer empfohlen und ist unter Umständen sogar erforderlich. Wenn Sie Probleme haben, dann empfehlen wir GNU make 3.75 oder höher.
Benutzen Sie eine Version von gcc, die neu
genug ist, um die Option -fno-exceptions
zu
kennen, dann ist es extrem wichtig, diese
Option auch zu verwenden. Andernfalls kompilieren Sie unter
Umständen eine Binärdatei, die zu unvorhersagbaren Zeitpunkten
abstürzt. Ferner empfehlen wir die Verwendung von
-felide-constructors
und
-fno-rtti
mit -fno-exceptions
.
Im Zweifelsfall tun Sie Folgendes:
CFLAGS="-O3" CXX=gcc CXXFLAGS="-O3 -felide-constructors \ -fno-exceptions -fno-rtti" ./configure \ --prefix=/usr/local/mysql --enable-assembler \ --with-mysqld-ldflags=-all-static
Auf den meisten Systemen erhalten Sie so eine schnelle und stabile Binärdatei.
Sollten Sie auf Probleme stoßen und einen Fehlerbericht speichern wollen, dann gehen Sie vor wie in Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“, beschrieben.
Die wichtigsten Befehle, die bei der Installation und Verwendung einer MySQL-Quelldistribution ausgeführt werden müssen, sind die folgenden:
shell>groupadd mysql
shell>useradd -g mysql mysql
shell>gunzip < mysql-
shell>VERSION
.tar.gz | tar -xvf -cd mysql-
shell>VERSION
./configure --prefix=/usr/local/mysql
shell>make
shell>make install
shell>cp support-files/my-medium.cnf /etc/my.cnf
shell>cd /usr/local/mysql
shell>bin/mysql_install_db --user=mysql
shell>chown -R root .
shell>chown -R mysql var
shell>chgrp -R mysql .
shell>bin/mysqld_safe --user=mysql &
Wenn Sie von einem Quell-RPM ausgehen, tun Sie Folgendes:
shell> rpmbuild --rebuild --clean MySQL-VERSION
.src.rpm
Auf diese Weise wird ein Binär-RPM erstellt, das Sie installieren können. Bei älteren RPM-Versionen müssen Sie unter Umständen den Befehl rpmbuild durch rpm ersetzen.
Hinweis: Beim folgenden Vorgang werden keine Passwörter für MySQL-Konten eingerichtet. Wenn Sie den Vorgang abgeschlossen haben, fahren Sie fort mit Abschnitt 2.9, „Einstellungen und Tests nach der Installation“, wo Konfiguration und Tests nach der Installation beschrieben sind.
Hier nun eine detailliertere Version der vorangegangenen Beschreibung zur MySQL-Installation aus einer Quelldistribution:
Fügen Sie einen Anmeldebenutzer und eine Gruppe hinzu, unter denen mysqld ausgeführt wird:
shell>groupadd mysql
shell>useradd -g mysql mysql
Diese Befehle fügen die Gruppe mysql
und
den Benutzer mysql
hinzu. Die Syntax für
useradd und groupadd
kann bei den verschiedenen Unix-Varianten etwas anders
aussehen. Auch können die Befehlsnamen selbst variieren
(z. B. adduser und
addgroup).
Unter Umständen wollen Sie dem Benutzer und der Gruppe
einen anderen Namen als mysql
zuweisen.
In diesem Fall müssen Sie in den folgenden Schritten den
entsprechenden Namen einsetzen.
Wählen Sie das Verzeichnis aus, in das Sie die Distribution entpacken wollen, und rufen Sie dieses auf.
Beschaffen Sie sich wie in Abschnitt 2.1.3, „Woher man MySQL bekommt“, beschrieben eine Distributionsdatei.
Entpacken Sie die Distribution in das aktuelle Verzeichnis:
shell> gunzip < /path/to/mysql-VERSION
.tar.gz | tar xvf -
Dieser Befehl erstellt ein Verzeichnis namens
mysql-
.
VERSION
Bei GNU tar ist kein separater Aufruf von
gunzip
erforderlich. Alternativ verwenden
Sie den folgenden Befehl zum Dekomprimieren und Entpacken
der Distribution:
shell> tar zxvf /path/to/mysql-VERSION-OS
.tar.gz
Wechseln Sie nun in das Stammverzeichnis der entpackten Distribution:
shell> cd mysql-VERSION
Beachten Sie, dass Sie MySQL derzeit nur von diesem Stammverzeichnis aus installieren können. Sie können es nicht in einem anderen Verzeichnis erstellen.
Konfigurieren Sie den Release und kompilieren Sie alles:
shell>./configure --prefix=/usr/local/mysql
shell>make
Wenn Sie configure ausführen, sollten Sie weitere Optionen festlegen. Führen Sie ./configure --help aus, um eine Liste der Optionen anzuzeigen. Abschnitt 2.8.2, „Typische configure-Optionen“, beschreibt einige der nützlicheren Optionen.
Wenn Sie eine E-Mail an eine MySQL-Mailingliste senden, weil
configure fehlgeschlagen ist und Sie
Hilfe benötigen, fügen Sie bitte alle ggf. in der Datei
config.log
vorhandenen Zeilen hinzu,
von denen Sie annehmen, dass sie zur Problembehebung
beitragen können. Ferner sollten Sie die letzten paar
Zeilen der Ausgabe von configure
aufführen. Verwenden Sie zum Übermitteln eines
Fehlerberichts die in Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“,
beschriebenen Anweisungen.
Schlägt die Kompilierung fehl, dann finden Sie hilfreiche Informationen in Abschnitt 2.8.4, „Probleme beim Kompilieren?“.
Installieren Sie die Distribution:
shell> make install
Wenn Sie eine Optionsdatei konfigurieren wollen, verwenden
Sie eine der im Verzeichnis
support-files
vorhandenen Dateien als
Vorlage. Ein Beispiel:
shell> cp support-files/my-medium.cnf /etc/my.cnf
Sie müssen diese Befehle unter Umständen als
root
ausführen.
Wenn Sie die Unterstützung für
InnoDB
-Tabellen konfigurieren wollen,
sollten Sie die Datei /etc/my.cnf
bearbeiten, das Zeichen #
vor den
Optionszeilen entfernen, die mit
innodb_...
beginnen, und die Optionswerte
nach Bedarf ändern. Siehe auch
Abschnitt 4.3.2, „my.cnf-Optionsdateien“, und
Abschnitt 14.2.3, „Konfiguration“.
Wechseln Sie nun in das Installationsverzeichnis:
shell> cd /usr/local/mysql
Wenn Sie MySQL vorher noch nicht installiert hatten, müssen Sie die MySQL-Grant-Tabellen erstellen:
shell> bin/mysql_install_db --user=mysql
Wenn Sie den Befehl als root
ausführen,
sollten Sie wie gezeigt die Option --user
verwenden. Als Wert der Option sollte der Name des
Anmeldekontos eingetragen werden, das Sie im ersten Schritt
zur Verwendung für die Ausführung des Servers angegeben
haben. Wenn Sie den Befehl ausführen, während Sie als
dieser Benutzer angemeldet sind, können Sie die Option
--user
weglassen.
Wenn Sie die Grant-Tabellen mit mysql_install_db erstellt haben, müssen Sie den Server manuell neu starten. Wie dies mit dem Befehl mysqld_safe geht, wird in einem späteren Schritt erläutert.
Weisen Sie als neuen Besitzer der Programmbinärdateien
root
und als neuen Besitzer des
Datenverzeichnisses den Benutzer zu, unter dessen Konto Sie
mysqld ausführen. Wenn Sie sich etwa im
Installationsverzeichnis
(/usr/local/mysql
) befinden, sieht der
Befehl wie folgt aus:
shell>chown -R root .
shell>chown -R mysql var
shell>chgrp -R mysql .
Der erste Befehl setzt das Besitzerattribut der Dateien auf
den Benutzer root
. Der zweite setzt das
Besitzerattribut des Datenverzeichnisses auf den Benutzer
mysql
. Der dritte schließlich setzt das
Gruppenattribut auf die Gruppe mysql
.
Wenn Sie wollen, dass MySQL beim Starten des Computers
automatisch startet, können Sie
support-files/mysql.server
in das
Verzeichnis kopieren, in dem sich die Startdateien Ihres
Systems befinden. Weitere Informationen finden Sie im Skript
support-files/mysql.server
selbst und
in Abschnitt 2.9.2.2, „MySQL automatisch starten und anhalten“.
Neue Konten können Sie mit dem Skript
bin/mysql_setpermission einrichten, wenn
Sie die Perl-Module DBI
und
DBD::mysql
installieren. Informationen
zur Vorgehensweise finden Sie in
Abschnitt 2.13, „Anmerkungen zur Perl-Installation“.
Nachdem alles installiert wurde, sollten Sie Ihre Distribution testen. Verwenden Sie den folgenden Befehl, um den MySQL Server zu starten:
shell> /usr/local/mysql/bin/mysqld_safe --user=mysql &
Wenn der Befehl sofort fehlschlägt und die Meldung
mysqld ended
ausgibt, finden Sie unter
Umständen hilfreiche Informationen in der Datei
im
Datenverzeichnis.
host_name
.err
Weitere Informationen zu mysqld_safe können Sie Abschnitt 5.4.1, „mysqld_safe — Startskript für den MySQL-Server“, entnehmen.
Hinweis: Für die in den MySQL-Grant-Tabellen aufgeführten Konten gibt es zunächst noch keine Passwörter. Wenn Sie den Server gestartet haben, sollten Sie entsprechend der in Abschnitt 2.9, „Einstellungen und Tests nach der Installation“, beschriebenen Verfahrensweise Passwörter für diese Konten einrichten.
Das Skript configure bietet Ihnen umfassende Kontrolle darüber, wie Sie Ihre MySQL-Quelldistribution konfigurieren. Normalerweise werden Sie dies mithilfe der Optionen von configure an der Befehlszeile tun. Sie können configure auch über bestimmte Umgebungsvariablen beeinflussen. Siehe auch Anhang F, Umgebungsvariablen. Eine Liste der Optionen, die von configure unterstützt werden, erhalten Sie nach Ausführen des folgenden Befehls:
shell> ./configure --help
In der Folge wollen wir einige der häufiger verwendeten Optionen von configure beschreiben:
Um nur die Clientbibliotheken und -programme von MySQL (und
nicht den Server) zu kompilieren, verwenden Sie die Option
--without-server
:
shell> ./configure --without-server
Wenn Sie keinen C++-Compiler haben, kann
mysql nicht kompiliert werden (dies ist
das einzige Clientprogramm, das C++ erfordert). In diesem
Fall können Sie den Code, der das Vorhandensein des
C++-Compilers prüft, aus configure
entfernen und dann ./configure mit der
Option --without-server
ausführen. In
diesem Fall wird bei der Kompilierung zwar versucht,
mysql zu erstellen, aber Sie können alle
Warnungen bezüglich mysql.cc
ignorieren. (Wenn make stehen bleibt,
geben Sie make -k ein, um das System
anzuweisen, die Erstellung auch bei Auftreten von Fehlern
abzuschließen.)
Wenn Sie die eingebettete MySQL-Bibliothek
(libmysqld.a
) erstellen wollen, verwenden
Sie die Option --with-embedded-server
.
Wenn Sie nicht wollen, dass Ihre Logdateien und die
Datenbankverzeichnisse in
/usr/local/var
abgelegt werden,
verwenden Sie configure in der Art wie
folgt:
shell>./configure --prefix=/usr/local/mysql
shell>./configure --prefix=/usr/local \
--localstatedir=/usr/local/mysql/data
Der erste Befehl ändert das Installationspräfix, sodass
alles in /usr/local/mysql
(statt wie
standardmäßig vorgesehen in
/usr/local
) installiert wird. Der
zweite Befehl belässt das Installationsstandardpräfix
zwar, ersetzt aber die Standardposition der
Datenbankverzeichnisse (normalerweise
/usr/local/var
) durch
/usr/local/mysql/data
.
Sie können die Positionen auch zum Zeitpunkt des Serverstarts angeben, indem Sie sie in die MySQL-Optionsdatei eintragen. Siehe auch Abschnitt 4.3.2, „my.cnf-Optionsdateien“.
Wenn Sie Unix verwenden und die MySQL-Socketdatei an einer
anderen Position als im Standardverzeichnis (normalerweise
/tmp
oder
/var/run
) ablegen wollen, verwenden Sie
den configure-Befehl wie folgt:
shell>./configure \
--with-unix-socket-path=/usr/local/mysql/tmp/mysql.sock
Der Socketdateiname muss ein absoluter Pfadname sein. Sie
können die Position von mysql.sock
mithilfe einer Optionsdatei auch zum Zeitpunkt des
Serverstarts einstellen. Siehe auch
Abschnitt A.4.5, „Wie Sie die MySQL-Socketdatei /tmp/mysql.sock
schützen oder ändern“.
Wenn Sie statisch verknüpfte Programme kompilieren wollen, um etwa eine Binärdistribution zu erstellen, die Leistung zu optimieren oder Probleme mit bestimmten Red Hat Linux-Distributionen zu umgehen, dann führen Sie configure wie folgt aus:
shell>./configure --with-client-ldflags=-all-static \
--with-mysqld-ldflags=-all-static
Wenn Sie gcc einsetzen und
libg++
oder libstdc++
nicht installiert haben, können Sie
configure anweisen,
gcc als C++-Compiler zu verwenden:
shell> CC=gcc CXX=gcc ./configure
Verwenden Sie gcc als C++-Compiler, dann
wird keine Verknüpfung mit libg++
oder
libstdc++
probiert. Dies kann auch dann
von Vorteil sein, wenn Sie die betreffenden Bibliotheken
installiert haben. In Verbindung mit einigen Versionen
dieser Bibliotheken sind bei MySQL-Benutzern in der
Vergangenheit nicht nachvollziehbare Probleme aufgetreten.
Die folgende Liste führt einige Compiler auf. Ferner aufgelistet sind die zugehörigen Einstellungen für Umgebungsvariablen.
gcc 2.7.2:
CC=gcc CXX=gcc CXXFLAGS="-O3 -felide-constructors"
egcs 1.0.3a:
CC=gcc CXX=gcc CXXFLAGS="-O3 -felide-constructors \ -fno-exceptions -fno-rtti"
gcc 2.95.2:
CFLAGS="-O3 -mpentiumpro" CXX=gcc CXXFLAGS="-O3 -mpentiumpro \ -felide-constructors -fno-exceptions -fno-rtti"
pgcc
2.90.29 oder höher:
CFLAGS="-O3 -mpentiumpro -mstack-align-double" CXX=gcc \ CXXFLAGS="-O3 -mpentiumpro -mstack-align-double \ -felide-constructors -fno-exceptions -fno-rtti"
In den meisten Fällen erhalten Sie eine vernünftig optimierte MySQL-Binärdatei, wenn Sie die Optionen der vorangegangenen Tabelle verwenden und die folgenden Optionen in der configure-Befehlszeile hinzufügen:
--prefix=/usr/local/mysql --enable-assembler \ --with-mysqld-ldflags=-all-static
Mit anderen Worten: Die vollständige configure-Zeile würde bei allen aktuellen gcc-Versionen ungefähr wie folgt aussehen:
CFLAGS="-O3 -mpentiumpro" CXX=gcc CXXFLAGS="-O3 -mpentiumpro \ -felide-constructors -fno-exceptions -fno-rtti" ./configure \ --prefix=/usr/local/mysql --enable-assembler \ --with-mysqld-ldflags=-all-static
Alle von uns auf der MySQL-Website unter http://dev.mysql.com/downloads/ bereitgestellten Binärdateien wurden mit optimalen Einstellungen kompiliert und sollten für die meisten Benutzer perfekt geeignet sein. Siehe auch Abschnitt 2.1.2.5, „MySQL-Binärdistributionen, die von MySQL AB kompiliert wurden“. Es gibt einige Konfigurationseinstellungen, durch deren Optimierung Sie eine noch schnellere Binärdatei erstellen können. Diese Einstellungen sind jedoch nur für fortgeschrittene Benutzer geeignet. Siehe auch Abschnitt 7.5.4, „Wie Kompilieren und Linken die Geschwindigkeit von MySQL beeinflusst“.
Schlägt die Erstellung fehl und werden Fehlermeldungen
erzeugt, weil Ihr Compiler oder Linker die gemeinsame
Bibliothek
libmysqlclient.so.
nicht erstellen konnte (wobei N
N
eine Versionsnummer ist), dann können Sie dieses Problem
umgehen, indem Sie die Option
--disable-shared
für
configure ergänzen. In diesem Fall
erstellt configure die gemeinsame
Bibliothek
libmysqlclient.so.
nicht.
N
Standardmäßig verwendet MySQL den Zeichensatz
latin1
(cp1252 West European). Um den
Standardzeichensatz zu ändern, verwenden Sie die Option
--with-charset
:
shell> ./configure --with-charset=CHARSET
CHARSET
kann einen der folgenden
Werte annehmen: big5
,
cp1251
, cp1257
,
czech
, danish
,
dec8
, dos
,
euc_kr
, gb2312
,
gbk
, german1
,
hebrew
, hp8
,
hungarian
, koi8_ru
,
koi8_ukr
, latin1
,
latin2
, sjis
,
swe7
, tis620
,
ujis
, usa7
oder
win1251ukr
. Siehe auch
Abschnitt 5.11.1, „Der für Daten und zum Sortieren benutzte Zeichensatz“.
Die Standardsortierung kann ebenfalls angegeben werden.
Standardmäßig verwendet MySQL die Sortierung
latin1_swedish_ci
. Um diese Sortierung zu
ändern, verwenden Sie die Option
--with-collation
:
shell> ./configure --with-collation=COLLATION
Wollen Sie Zeichensatz und Sortierung gleichzeitig ändern,
dann verwenden Sie einfach beide Optionen
--with-charset
und
--with-collation
. Die Sortierung muss für
den gewählten Zeichensatz zulässig sein. (Mit der
Anweisung SHOW COLLATION
können Sie die
für den jeweiligen Zeichensatz zulässige Sortierung
ermitteln.)
Wenn Sie Zeichen zwischen Server und Client konvertieren
wollen, dann sollten Sie einen Blick auf die Anweisung
SET NAMES
werfen. Siehe auch
Abschnitt 13.5.3, „SET
“, und
Abschnitt 10.4, „Verbindungszeichensatz und -sortierfolge“.
Warnung: Wenn Sie den
Zeichensatz ändern, nachdem Sie bereits Tabellen erstellt
haben, müssen Sie myisamchk -r -q
--set-collation=collation_name
für jede Tabelle ausführen.
Andernfalls werden Ihre Indizes unter Umständen falsch
sortiert. Dies kann passieren, wenn Sie MySQL installieren,
einige Tabellen erstellen und nachfolgend MySQL so
umkonfigurieren, dass ein anderer Zeichensatz verwendet
wird, und dann neu installieren.
Mit der configure-Option
--with-extra-charsets=
können Sie definieren, welche zusätzlichen Zeichensätze
in den Server einkompiliert werden sollen.
LIST
LIST
hat dabei einen der
folgenden Werte:
eine Liste von Zeichensatznamen, die durch Leerzeichen getrennt sind
complex
, wenn alle Zeichensätze
enthalten sein sollen, die sich nicht dynamisch laden
lassen
all
, wenn grundsätzlich alle
Zeichensätze in den Binärdateien enthalten sein sollen
Um MySQL mit Debugging-Code zu konfigurieren, verwenden Sie
die Option --with-debug
:
shell> ./configure --with-debug
Auf diese Weise wird eine sichere Speicherzuweisung in die Konfiguration integriert, die in der Lage ist, bestimmte Fehler zu finden und Informationen zu den Abläufen zu vermitteln. Siehe auch Abschnitt E.1, „Einen MySQL-Server debuggen“.
Wenn Ihre Clientprogramme Threads verwenden, müssen Sie
eine Thread-sichere Version der MySQL-Clientbibliothek mit
der Konfigurationsoption
--enable-thread-safe-client
erstellen. Auf
diese Weise wird eine Bibliothek
libmysqlclient_r
angelegt, mit der Sie
Ihre Thread-basierten Anwendungen verknüpfen sollten. Siehe
auch Abschnitt 24.2.15, „Wie man einen Thread-Client herstellt“.
Es ist möglich, MySQL mit Unterstützung für große
Tabellen zu erstellen. Hierzu verwenden Sie die Option
--with-big-tables
.
Diese Option sorgt dafür, dass die Variablen, die die
Ergebnisse der Datensatzzählungen enthalten, als
unsigned long long
statt als
unsigned long
gespeichert werden. Sie
erlaubt Tabellen die Aufnahme von ca. 1,844E+19
((232)2)
Datensätzen statt 232 (ca.
4,295E+09) Datensätzen. Zuvor war es notwendig gewesen,
-DBIG_TABLES
manuell an den Compiler zu
übergeben, um diese Funktion zu aktivieren.
Optionen, die spezifisch für bestimmte Betriebssysteme sind, finden Sie in den jeweiligen Abschnitten dieses Handbuchs. Siehe auch Abschnitt 2.12, „Betriebssystemspezifische Anmerkungen“.
Vorsicht: Sie sollten diesen Abschnitt nur lesen, wenn Sie Interesse daran haben, uns beim Testen unseres neuen Codes behilflich zu sein. Wenn Sie MySQL lediglich in funktionsfähiger Form auf Ihrem System einrichten wollen, sollten Sie einen Standard-Release (entweder als Binär- oder als Quelldistribution) verwenden.
Um unseren aktuellsten Entwicklungs-Source-Tree zu bekommen, laden Sie zunächst den kostenlosen BitKeeper-Client herunter, sofern Sie ihn noch nicht haben, und installieren ihn. Sie erhalten den Client unter http://www.bitmover.com/bk-client.shar.
Zur Installation des BitKeeper-Clients unter Unix verwenden Sie die folgenden Befehle:
shell>sh bk-client.shar
shell>cd bk_client-1.1
shell>make all
shell>PATH=$PWD:$PATH
Zur Installation des BitKeeper-Clients unter Windows gehen Sie wie folgt vor:
Laden Sie Cygwin von http://cygwin.com herunter und installieren Sie es.
Vergewissern Sie sich, dass gcc und make unter Cygwin installiert wurden. Sie können dies überprüfen, indem Sie die Befehle which gcc und which make absetzen. Ist eines der Programme nicht installiert, dann führen Sie den Paket-Manager von Cygwin aus, wählen gcc und/oder make und führen die Installation aus.
Führen Sie dann unter Cygwin die folgenden Befehle aus:
shell>sh bk-client.shar
shell>cd bk_client-1.1
Nachfolgend bearbeiten Sie das Makefile
und ändern die Zeile $(CC) $(CFLAGS) -o sfio -lz
sfio.c
wie folgt:
$(CC) $(CFLAGS) -o sfio sfio.c -lz
Nun führen Sie den Befehl make aus und stellen den Pfad ein:
shell>make all
shell>PATH=$PWD:$PATH
Der kostenlose BitKeeper-Client wird mit seinem Quellcode ausgeliefert. Dieser Quellcode ist auch die einzige Dokumentation, die für den kostenlosen Client verfügbar ist.
Nachdem Sie den BitKeeper-Client installiert haben, können Sie auf den MySQL-Entwicklungs-Source-Tree zugreifen:
Wechseln Sie in das Verzeichnis, das als Arbeitsverzeichnis vorgesehen ist, und erstellen Sie mit dem folgenden Befehl eine lokale Kopie des Zweigs von MySQL 5.1:
shell> sfioball -r+ bk://mysql.bkbits.net/mysql-5.1-new mysql-5.1
In obigem Beispiel wird der Source-Tree im Unterverzeichnis
mysql-5.1/
Ihres aktuellen
Verzeichnisses eingerichtet.
Der erste Download des Source-Trees kann je nach Geschwindigkeit Ihrer Verbindung eine Weile dauern. Haben Sie bitte Geduld.
Sie benötigen GNU make, autoconf 2.58 (oder höher), automake 1.8, libtool 1.5 und m4, um die nächste Befehlsgruppe auszuführen. Zwar werden viele Betriebssysteme mit eigener Implementierung von make ausgeliefert, aber die Wahrscheinlichkeit, dass der Kompilierungsvorgang mit merkwürdigen Fehlermeldungen abbricht, ist doch recht hoch. Aus diesem Grund wird dringend empfohlen, stattdessen GNU make (das manchmal auch als gmake bezeichnet wird) zu verwenden.
Glücklicherweise wird eine große Anzahl von Betriebssystemen mit vorinstallierten GNU-Tools ausgeliefert oder enthält deren Installationspakete. In jedem Fall können Sie sie auch unter den folgenden Adressen herunterladen:
Um MySQL 5.1 zu konfigurieren, benötigen Sie ferner GNU bison 1.75 oder höher. Ältere Versionen von bison zeigen unter Umständen folgenden Fehler an:
sql_yacc.yy:#####: fatal error: maximum table size (32767) exceeded
Hinweis: Die maximale Tabellengröße wurde mitnichten überschritten; vielmehr wird der Fehler von Bugs in älteren bison-Versionen ausgelöst.
Das folgende Beispiel zeigt die typischen Befehle, die zur
Konfiguration eines Source-Trees erforderlich sind. Der
erste Befehl cd
wechselt in das oberste
Verzeichnis des Trees. Hierbei ist
mysql-5.1
durch den
korrekten Verzeichnisnamen zu ersetzen.
shell>cd mysql-5.1
shell>aclocal; autoheader
shell>libtoolize --automake --force
shell>automake --force --add-missing; autoconf
shell>(cd storage/innobase; aclocal; autoheader; autoconf; automake)
shell>(cd storage/bdb/dist; sh s_all)
shell>./configure # Add your favorite options here
shell>make
Alternativ verwenden Sie BUILD/autorun.sh als Abkürzung für die folgende Befehlssequenz:
shell>aclocal; autoheader
shell>libtoolize --automake --force
shell>automake --force --add-missing; autoconf
shell>(cd storage/innobase; aclocal; autoheader; autoconf; automake)
shell>(cd storage/bdb/dist; sh s_all)
Die Befehlszeilen, die in die Verzeichnisse
storage/innobase
bzw.
storage/bdb/dist
wechseln, dienen der
Konfiguration der InnoDB
- und Berkeley
DB(BDB
)-Speicher-Engines. Sie können
diese Befehlszeilen weglassen, wenn Sie Unterstützung für
InnoDB
bzw. BDB
nicht
benötigen.
Hinweis: Ab MySQL 5.1 wird
Code, der spezifisch für bestimmte Speicher-Engines ist, in
ein storage
-Verzeichnis verschoben. So
liegt beispielsweise InnoDB
-Code jetzt in
storage/innobase
und
NDBCluster
-Code in
storage/ndb
.
Wenn Ihnen in dieser Phase seltsame Fehler angezeigt werden, dann vergewissern Sie sich, dass libtool wirklich installiert wurde.
Eine Sammlung unserer Standardkonfigurationsskripten
befindet sich im Unterverzeichnis
BUILD/
. Unter Umständen finden Sie es
praktischer, statt der vorangegangenen Gruppe von
Shell-Befehlen das Skript
BUILD/compile-pentium-debug
zu
verwenden. Um auf einer anderen Architektur zu kompilieren,
ändern Sie das Skript ab, indem Sie Pentium-spezifische
Flags entfernen.
Wenn die Erstellung abgeschlossen ist, führen Sie
make install aus. Auf einem
Produktionssystem sollten Sie dies allerdings mit Vorsicht
tun: Es besteht die Möglichkeit, dass der Befehl die
aktuelle Release-Installation überschreibt. Wenn bereits
eine MySQL-Installation vorhanden ist, empfehlen wir die
Ausführung von ./configure unter
Zuweisung anderer als der für den Produktionsserver
verwendeten Werte für die Optionen
--prefix
, --with-tcp-port
und --unix-socket-path
.
Prüfen Sie Ihre neue Installation auf Herz und Nieren und versuchen Sie, die neuen Funktionen zum Absturz zu bringen. Führen Sie zunächst make test aus. Siehe auch Abschnitt 26.1.2, „MySQL-Testsystem“.
Wenn Sie es bis zur make-Phase geschafft
haben, aber die Distribution sich nicht kompilieren lässt,
dann geben Sie das Problem in unsere Fehlerdatenbank ein.
Beachten Sie hierzu die Anweisungen in
Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“. Haben Sie die aktuellen
Versionen der erforderlichen GNU-Tools installiert und
stürzen diese bei der Verarbeitung unserer
Konfigurationsdateien ebenfalls ab, dann teilen Sie uns
bitte auch dies mit. Wenn Sie allerdings
aclocal
ausführen und die Fehlermeldung
command not found
o. ä. erhalten,
melden Sie dies bitte nicht. Überprüfen Sie stattdessen,
ob alle notwendigen Tools installiert sind und Ihre Variable
PATH
korrekt eingestellt ist, damit Ihre
Shell sie finden kann.
Wenn Sie das Repository mit sfioball kopiert haben, um den Source-Tree zu erhalten, sollten Sie regelmäßig update ausführen, um Ihre lokale Kopie zu aktualisieren. Zu diesem Zweck können Sie nach der Konfiguration des Repositorys jederzeit den folgenden Befehl verwenden:
shell> update bk://mysql.bkbits.net/mysql-5.1-new
Sie können die Änderungshistorie des Trees mit allen Diffs
überprüfen, indem Sie die Datei
BK/ChangeLog
im Source-Tree anzeigen
und nach den dort aufgelisteten
ChangeSet
-Beschreibungen suchen. Um ein
bestimmtes Changeset zu untersuchen, müssten Sie mit dem
Befehl sfioball zwei bestimmte Revisionen
des Source-Trees extrahieren und dann einen externen
diff-Befehl aufrufen, um den Vergleich
durchzuführen. Wenn Sie über ein paar spaßige Diffs oder
über Code stolpern, zu dem Sie Fragen haben, schicken Sie
einfach eine E-Mail an die MySQL-Mailingliste
internals
. Siehe auch
Abschnitt 1.7.1, „Die MySQL-Mailinglisten“. Auch wenn Sie
eine gute Idee haben, wie man etwas vielleicht besser lösen
könnte, schicken Sie ruhig eine E-Mail mit einem Patch an
die Liste.
Changesets, Anmerkungen und Quellcode können Sie auch online durchsuchen. Um die entsprechenden Informationen für MySQL 5.1 anzuzeigen, besuchen Sie http://mysql.bkbits.net:8080/mysql-5.1.
Alle MySQL-Programme lassen sich bei uns mit gcc sauber und ohne Warnungen unter Solaris oder Linux kompilieren. Auf anderen Systemen werden aufgrund von Unterschieden in den systemspezifischen Include-Dateien unter Umständen Warnungen angezeigt. Informationen dazu, welche Warnungen bei der Verwendung von MIT-pthreads angezeigt werden können, finden Sie in Abschnitt 2.8.5, „Anmerkungen zu MIT-pthreads“. Informationen zu anderen Problemen entnehmen Sie der folgenden Liste.
Die Lösung zahlreicher Probleme erfordert eine Umkonfiguration. Wenn Sie eine Umkonfiguration durchführen müssen, beachten Sie bitte die folgenden Hinweise:
Wird configure nach einem vorherigen
Aufruf erneut ausgeführt, dann werden unter Umständen
Daten zugrunde gelegt, die während des vorherigen Aufrufs
ermittelt worden waren. Diese Informationen sind in der
Datei config.cache
abgelegt. Nach dem
Start prüft configure auf das
Vorhandensein dieser Datei und liest ihren Inhalt ggf. aus
– davon ausgehend, dass die Daten nach wie vor korrekt
sind. Dies ist allerdings bei einer Umkonfigurierung nicht
mehr der Fall.
Jedes Mal, wenn Sie configure ausführen, müssen Sie zur Neukompilierung auch make erneut ausführen. Allerdings sollten Sie alte Objektdateien aus vorherigen Builds entfernen, da diese mit abweichenden Konfigurationsoptionen erstellt wurden.
Um die Verwendung veralteter Konfigurationsdaten oder Objektdateien zu verhindern, führen Sie die folgenden Befehle aus, bevor Sie configure erneut aufrufen:
shell>rm config.cache
shell>make clean
Alternativ können Sie auch make distclean ausführen.
Die folgende Liste enthält die bei der Kompilierung von MySQL am häufigsten auftretenden Probleme:
Wenn Sie bei der Kompilierung von
sql_yacc.cc
Fehler wie die hier
aufgeführten erhalten, ist offensichtlich nicht genug
Arbeits- oder Auslagerungsspeicher vorhanden.
Internal compiler error: program cc1plus got fatal signal 11 Out of virtual memory Virtual memory exhausted
Das Problem besteht darin, dass gcc zur
Kompilierung von sql_yacc.cc
mit
Inline-Funktionen eine gewaltige Menge Speicher benötigt.
Versuchen Sie in diesem Fall, configure
mit der Option --with-low-memory
auszuführen:
shell> ./configure --with-low-memory
Diese Option ergänzt die Kompilierungszeile um den Eintrag
-fno-inline
, wenn Sie
gcc verwenden, bzw. um
-O0
bei Verwendung eines anderen Tools. Sie
sollten die Option --with-low-memory
auch
dann verwenden, wenn Sie der Ansicht sind, dass so viel
Arbeits- und Auslagerungsspeicher vorhanden ist, dass ein
Speichermangel nicht wahrscheinlich ist. Dieses Problem
wurde sogar schon auf Systemen mit wirklich großzügigen
Hardwarekonfigurationen beobachtet und konnte stets mit der
Option --with-low-memory
behoben werden.
Standardmäßig wählt configure
c++ als Compiler-Namen aus, und GNU
c++ verknüpft sich mit
-lg++
. Wenn Sie gcc
verwenden, dann kann dieses Verhalten während der
Konfiguration zu Problemen wie dem folgenden führen:
configure: error: installation or configuration problem: C++ compiler cannot create executables.
Ferner könnten Sie während der Kompilierung Probleme in
Bezug auf g++, libg++
oder libstdc++
beobachten.
Eine Ursache dieser Probleme besteht darin, dass Sie
g++ entweder nicht haben oder dass Sie
g++, nicht jedoch
libg++
oder libstdc++
haben. Werfen Sie einen Blick in die Datei
config.log
. Sie sollten den Grund
dafür, dass Ihr C++-Compiler nicht funktioniert, exakt
angeben. Um derartige Probleme zu vermeiden, können Sie
gcc als C++-Compiler verwenden. Setzen
Sie die Umgebungsvariable CXX
versuchsweise auf "gcc -O3"
.
Ein Beispiel:
shell> CXX="gcc -O3" ./configure
Dies funktioniert, weil gcc
C++-Quelldateien ebenso kompiliert, wie es
g++ tut, jedoch standardmäßig keine
Verknüpfung mit libg++
oder
libstdc++
herstellt.
Eine andere Möglichkeit, diese Probleme zu beheben, besteht
in der Installation von g++,
libg++
und libstdc++
.
Allerdings raten wir von der Verwendung von
libg++
oder libstdc++
mit MySQL ab, da hierdurch nur die
mysqld-Binärdatei vergrößert wird –
Vorteile ergeben sich ansonsten keine. In Verbindung mit
einigen Versionen dieser Bibliotheken sind bei
MySQL-Benutzern in der Vergangenheit nicht nachvollziehbare
Probleme aufgetreten.
Bricht Ihre Kompilierung mit Fehlern wie dem folgenden ab, dann müssen Sie Ihre make-Version auf GNU make aktualisieren:
making all in mit-pthreads make: Fatal error in reader: Makefile, line 18: Badly formed macro assignment
Oder:
make: file `Makefile' line 18: Must be a separator (:
Oder:
pthread.h: No such file or directory
Es ist bekannt, dass Solaris und FreeBSD problematische make-Programme umfassen.
GNU make 3.75 funktioniert erfahrungsgemäß.
Wenn Sie Flags für die Verwendung durch Ihre C- oder
C++-Compiler definieren wollen, sollten Sie dies tun, indem
Sie die Flags den Umgebungsvariablen
CFLAGS
und CXXFLAGS
hinzufügen. Sie können auf diese Weise auch die
Compiler-Namen über CC
und
CXX
angeben. Ein Beispiel:
shell>CC=gcc
shell>CFLAGS=-O3
shell>CXX=gcc
shell>CXXFLAGS=-O3
shell>export CC CFLAGS CXX CXXFLAGS
In Abschnitt 2.1.2.5, „MySQL-Binärdistributionen, die von MySQL AB kompiliert wurden“, finden Sie eine Liste der Flag-Definitionen, die sich bei verschiedenen Systemen als nützlich erwiesen haben.
Wenn Sie bei der Kompilierung von mysqld
Fehlermeldungen wie die nachfolgend gezeigte erhalten, hat
configure den Typ des letzten Arguments
von accept()
,
getsockname()
oder
getpeername()
nicht korrekt erkannt:
cxx: Error: mysqld.cc, line 645: In this statement, the referenced type of the pointer value ''length'' is ''unsigned long'', which is not compatible with ''int''. new_sock = accept(sock, (struct sockaddr *)&cAddr, &length);
Um dieses Problem zu beheben, bearbeiten Sie die Datei
config.h
(diese wird durch
configure erzeugt). Suchen Sie dort nach
den folgenden Zeilen:
/* Define as the base type of the last arg to accept */ #define SOCKET_SIZE_TYPE XXX
Setzen Sie XXX
je nach Betriebssystem auf
size_t
oder int
. (Sie
müssen dies bei jeder Ausführung von
configure tun, da
configure config.h
immer neu erstellt.)
Die Datei sql_yacc.cc
wird aus
sql_yacc.yy
erstellt. Normalerweise
muss bei der Erstellung keine Datei
sql_yacc.cc
erzeugt werden, da MySQL
bereits eine vorab generierte Kopie enthält. Sofern Sie sie
aber trotzdem neu erstellen müssen, könnte unter
Umständen folgende Fehlermeldung angezeigt werden:
"sql_yacc.yy", line xxx
fatal: default action causes potential ...
Dies weist darauf hin, dass Ihre Version von yacc fehlerhaft ist. Sie müssen stattdessen wahrscheinlich bison (die GNU-Variante von yacc) installieren und verwenden.
Unter Debian Linux 3.0 müssen Sie gawk
anstelle des standardmäßigen mawk
installieren, wenn Sie MySQL mit Berkeley DB-Unterstützung
kompilieren wollen.
Wenn Sie mysqld oder einen MySQL-Client
debuggen müssen, führen Sie configure
mit der Option --with-debug
aus.
Kompilieren Sie Ihre Clients dann neu und verknüpfen Sie
sie mit der neuen Clientbibliothek. Siehe auch
Abschnitt E.2, „Einen MySQL-Client debuggen“.
Unter Umständen erhalten Sie unter Linux (z. B. bei SuSE Linux 8.1 oder Red Hat Linux 7.3) einen Kompilierungsfehler ähnlich dem folgenden:
libmysql.c:1329: warning: passing arg 5 of `gethostbyname_r' from incompatible pointer type libmysql.c:1329: too few arguments to function `gethostbyname_r' libmysql.c:1329: warning: assignment makes pointer from integer without a cast make[2]: *** [libmysql.lo] Error 1
Standardmäßig versucht das configure-Skript, die korrekte Anzahl der Argumente mithilfe des GNU C++-Compilers g++ zu ermitteln. Dieser Test führt zu falschen Ergebnissen, wenn g++ nicht installiert ist. Es gibt zwei Möglichkeiten, dieses Problem zu umgehen:
Stellen Sie sicher, dass der GNU-C++-Compiler
g++ installiert ist. Bei manchen
Linux-Distributionen heißt das erforderliche Paket
gpp
, bei anderen
gcc-c++.
Verwenden Sie gcc als C++-Compiler,
indem Sie die Umgebungsvariable CXX
auf gcc setzen:
export CXX="gcc"
Welche Änderungen Sie auch immer durchgeführt haben, nachfolgend müssen Sie configure erneut ausführen.
In diesem Abschnitt werden einige Probleme in Zusammenhang mit MIT-pthreads angesprochen.
Unter Linux sollten Sie MIT-pthreads nicht verwenden. Benutzen Sie stattdessen die installierte LinuxThreads-Implementierung. Siehe auch Abschnitt 2.12.1, „Linux (alle Linux-Versionen)“.
Wenn Ihr System keine native Thread-Unterstützung bietet, sollten Sie MySQL mithilfe des MIT-pthreads-Pakets erstellen. Dies gilt für ältere FreeBSD-Systeme, SunOS 4.x, Solaris 2.4 und früher sowie einige andere. Siehe auch Abschnitt 2.1.1, „Betriebssysteme, die von MySQL unterstützt werden“.
MIT-pthreads ist nicht in der Quelldistribution von MySQL 5.1 enthalten. Wenn Sie dieses Paket benötigen, müssen Sie es unter http://dev.mysql.com/Downloads/Contrib/pthreads-1_60_beta6-mysql.tar.gz separat herunterladen.
Extrahieren Sie das Quellarchiv nach dem Download in das oberste
MySQL-Quellverzeichnis. Hierdurch wird ein neues
Unterverzeichnis namens mit-pthreads
erstellt.
Auf den meisten Systemen können Sie die Verwendung von
MIT-pthreads erzwingen, indem Sie
configure mit der Option
--with-mit-threads
ausführen:
shell> ./configure --with-mit-threads
Die Erstellung eines Nichtquellverzeichnisses wird bei der Verwendung von MIT-pthreads nicht unterstützt, da wir unsere Änderungen an diesem Code minimieren wollen.
Die Tests, mit denen ermittelt wird, ob MIT-pthreads
verwendet werden soll, finden nur während derjenigen Phase
des Konfigurationsvorgangs statt, in der der Servercode
bearbeitet wird. Haben Sie die Distribution mit der Option
--without-server
konfiguriert, um nur den
Clientcode zu erstellen, dann wissen die Clients nicht, ob
MIT-pthreads verwendet wird oder nicht; deswegen verwenden
sie standardmäßig die Unix-Socketdatei. Da
Unix-Socketdateien jedoch auf bestimmten Plattformen unter
MIT-pthreads nicht funktionieren, bedeutet dies, dass Sie
-h
oder --host
mit einem
anderen Wert als localhost
verwenden
müssen, wenn Sie Clientprogramme ausführen.
Wird MySQL mit MIT-pthreads kompiliert, dann wird die
Systemsperrung zum Zweck der Leistungsoptimierung
standardmäßig deaktiviert. Mit der Option
--external-locking
können Sie den Server
anweisen, die Systemsperre zu verwenden. Dies ist aber nur
erforderlich, wenn Sie zwei MySQL Server ausführen, die auf
die gleichen Datendateien zugreifen (hiervon sei aber
ohnehin abgeraten).
Manchmal schlägt beim pthread-Befehl
bind()
der Versuch fehl, eine Bindung an
den Server vorzunehmen – und dies, ohne dass (zumindest
bei Solaris) eine Fehlermeldung erzeugt wird. Nachfolgend
schlagen alle Verbindungen zu diesem Server fehl. Ein
Beispiel:
shell> mysqladmin version
mysqladmin: connect to server at '' failed;
error: 'Can't connect to mysql server on localhost (146)'
Die Lösung dieses Problems besteht in Terminierung und Neustart des Servers mysqld. Dies ist bei uns nur aufgetreten, wenn wir den Server zwangsweise beendet und unmittelbar darauf neu gestartet haben.
Bei MIT-pthreads ist der Systemaufruf
sleep()
nicht durch
SIGINT
(Pause) zu unterbrechen. Dies
macht sich nur bemerkbar, wenn Sie mysqladmin
--sleep ausführen. Sie müssen warten, bis der
Aufruf sleep()
abgeschlossen ist, bevor
der Interrupt bedient und der Prozess angehalten wird.
Beim Verknüpfen erhalten Sie (wiederum zumindest unter Solaris) unter Umständen Warnmeldungen wie die folgende, die Sie aber getrost ignorieren können:
ld: warning: symbol `_iob' has differing sizes: (file /my/local/pthreads/lib/libpthread.a(findfp.o) value=0x4; file /usr/lib/libc.so value=0x140); /my/local/pthreads/lib/libpthread.a(findfp.o) definition taken ld: warning: symbol `__iob' has differing sizes: (file /my/local/pthreads/lib/libpthread.a(findfp.o) value=0x4; file /usr/lib/libc.so value=0x140); /my/local/pthreads/lib/libpthread.a(findfp.o) definition taken
Bestimmte andere Warnungen können ebenfalls ignoriert werden:
implicit declaration of function `int strtoll(...)' implicit declaration of function `int strtoul(...)'
Wir haben es nicht geschafft, die Verwendung von
readline
mit MIT-pthreads zu
ermöglichen. (Das ist zwar auch nicht notwendig, mag für
manchen aber von Interesse sein.)
Diese Anweisungen beschreiben, wie man unter Windows Binärdateien aus dem Quellcode von MySQL 5.1 erstellt. Die Anweisungen beziehen sich auf die Erstellung von Binärdateien aus einer Standardquelldistribution oder aus dem BitKeeper-Tree, der den aktuellen Entwicklungsquellcode enthält.
Hinweis: Die Angaben in diesem Abschnitt sind ausschließlich für Benutzer vorgesehen, die ein der aktuellen Quelldistribution oder dem BitKeeper-Tree entstammendes MySQL unter Windows testen wollen. Von der Verwendung eines aus dem Quellcode selbsterstellten MySQL Servers in Produktionsumgebungen rät MySQL AB ausdrücklich ab. In der Regel ist es am besten, vorkompilierte MySQL-Binärdistributionen zu verwenden, die von MySQL AB gezielt für optimale Leistung unter Windows erstellt wurden. Anweisungen zur Installation einer Binärdistribution finden Sie in Abschnitt 2.3, „Installation von MySQL unter Windows“.
Um MySQL unter Windows aus dem Quellcode zu erstellen, benötigen Sie die folgenden Compiler und Ressourcen auf Ihrem Windows-System:
Visual Studio 2003-Compilersystem (VC++ 7.0)
Zwischen 3 und 5 Gbyte Festplattenspeicher
Windows 2000 oder höher
Die exakten Systemvoraussetzungen finden Sie hier: http://msdn.microsoft.com/vstudio/productinfo/sysreqs/default.aspx
Außerdem brauchen Sie eine MySQL-Quelldistribution für Windows. Es gibt zwei Möglichkeiten, eine Quelldistribution zu erhalten:
Besorgen Sie sich eine von MySQL AB gepackte Quelldistribution. Diese finden Sie unter http://dev.mysql.com/downloads/.
Sie können sich auch selbst eine Quelldistribution aus dem aktuellen BitKeeper-Entwicklungs-Source-Tree packen. In diesem Fall müssen Sie das Paket auf einem Unix-System erstellen und dann auf Ihr Windows-System übertragen. (Das liegt daran, dass einige Konfigurations- und Erstellungsschritte Tools erfordern, die nur unter Unix funktionieren.) Insofern benötigen Sie für die BitKeeper-Variante Folgendes:
Ein System unter Unix oder einem Unix-Derivat (z. B. Linux).
Ein auf dem System installiertes BitKeeper 3.0. Informationen zu Download und Installation von BitKeeper finden Sie in Abschnitt 2.8.3, „Installation vom Entwicklungs-Source-Tree“.
Wenn Sie eine Windows-Quelldistribution verwenden, können Sie direkt bei Abschnitt 2.8.6.1, „Bauen von MySQL mit VC++“, fortfahren. Um die Distribution aus dem BitKeeper-Tree zu erstellen, fahren Sie fort bei Abschnitt 2.8.6.2, „Erzeugen eines Windows-Quellpakets aus dem neusten Entwicklungsbaum“.
Wenn Sie feststellen, dass etwas nicht erwartungsgemäß
funktioniert, oder Vorschläge zur Verbesserung des derzeitigen
Erstellungsvorgangs unter Windows haben, senden Sie bitte eine
Mitteilung an die Mailingliste win32
. Siehe
auch Abschnitt 1.7.1, „Die MySQL-Mailinglisten“.
Hinweis: VC++-Arbeitsbereichsdateien für MySQL 4.1 und höher sind kompatibel mit den Microsoft Visual Studio 2003-Editionen und wurden von MySQL AB-Mitarbeitern vor der Freigabe getestet.
Gehen Sie wie folgt vor, um MySQL zu erstellen:
Erstellen Sie ein Arbeitsverzeichnis (z. B.
C:\workdir
).
Entpacken Sie die Quelldistribution mit
WinZip oder einem anderen Windows-Tool,
das .zip
-Dateien lesen kann, in das
gerade erstellte Verzeichnis.
Starten Sie Visual Studio.
Wählen Sie im Menü
den Eintrag .
Öffnen Sie den Arbeitsbereich
mysql.dsw
, den Sie im
Arbeitsverzeichnis finden.
Wählen Sie im Menü
den Eintrag .Klicken Sie auf der anderen Seite des Bildschirms auf
und dann auf die Schaltfläche .Betätigen Sie F7, um die Erstellung des Debugservers, der Bibliotheken und einiger Clientanwendungen zu starten.
Kompilieren Sie die Release-Version auf gleiche Weise.
Debugversionen der Programme und Bibliotheken befinden
sich in den Verzeichnissen
client_debug
und
lib_debug
. Release-Versionen der
Programme und Bibliotheken befinden sich in den
Verzeichnissen client_release
und
lib_release
. Beachten Sie, dass Sie,
wenn Sie sowohl Debug- als auch Release-Versionen
erstellen wollen, die Option im Menü
auswählen können.
Testen Sie den Server. Der Server, den Sie gerade erstellt
haben, erwartet die Standardwerte für das
MySQL-Basisverzeichnis und das Datenverzeichnis
(C:\mysql
bzw.
C:\mysql\data
). Wenn Sie Ihren Server
unter Verwendung des Source-Tree-Stammverzeichnisses und
-Datenverzeichnisses als Stamm- bzw. Datenverzeichnis
testen wollen, müssen Sie dem Server die entsprechenden
Pfadnamen mitteilen. Sie können dies entweder über die
Befehlszeile mit den Optionen --basedir
und --datadir
tun, oder indem Sie die
entsprechenden Optionen in einer Optionsdatei ablegen.
(Siehe auch Abschnitt 4.3.2, „my.cnf-Optionsdateien“.) Wenn Sie ein
anderes, bereits an anderer Stelle vorhandenes
Datenverzeichnis verwenden sollen, können Sie stattdessen
auch diesen Pfadnamen angeben.
Starten Sie Ihren Server aus dem Verzeichnis
client_release
oder
client_debug
(dies hängt vom zu
verwendenden Server ab). Die allgemeinen Anweisungen zum
Starten des Servers finden Sie in
Abschnitt 2.3, „Installation von MySQL unter Windows“.
Sie müssen die Anweisung entsprechend anpassen, wenn Sie
ein anderes Basis- oder Datenverzeichnis verwenden wollen.
Wenn der Server je nach Ihrer Konfiguration als Anwendung
oder Dienst ausgeführt wird, versuchen Sie, mit ihm über
das interaktive Befehlszeilen-Hilfsprogramm
mysql eine Verbindung herzustellen. Sie
finden es in Ihrem Verzeichnis
client_release
oder
client_debug
.
Wenn Sie zu der Ansicht gekommen sind, dass die von Ihnen erstellten Programme korrekt laufen, beenden Sie den Server. Installieren Sie nun wie folgt MySQL:
Erstellen Sie die Verzeichnisse, in die Sie MySQL
installieren wollen. Um etwa MySQL im Verzeichnis
C:\mysql
zu installieren, verwenden
Sie die folgenden Befehle:
C:\>mkdir C:\mysql
C:\>mkdir C:\mysql\bin
C:\>mkdir C:\mysql\data
C:\>mkdir C:\mysql\share
C:\>mkdir C:\mysql\scripts
Wenn Sie andere Clients kompilieren und diese mit MySQL verknüpfen wollen, sollten Sie mehrere zusätzliche Verzeichnisse erstellen:
C:\>mkdir C:\mysql\include
C:\>mkdir C:\mysql\lib
C:\>mkdir C:\mysql\lib\debug
C:\>mkdir C:\mysql\lib\opt
Wenn Sie Benchmarks für MySQL erstellen wollen, legen Sie das folgende Verzeichnis an:
C:\> mkdir C:\mysql\sql-bench
Für Benchmark-Tests benötigen Sie die Perl-Unterstützung. Siehe auch Abschnitt 2.13, „Anmerkungen zur Perl-Installation“.
Kopieren Sie die folgenden Verzeichnisse aus dem
Verzeichnis workdir
in das
Verzeichnis C:\mysql
:
C:\>cd \workdir
C:\workdir>copy client_release\*.exe C:\mysql\bin
C:\workdir>copy client_debug\mysqld.exe C:\mysql\bin\mysqld-debug.exe
C:\workdir>xcopy scripts\*.* C:\mysql\scripts /E
C:\workdir>xcopy share\*.* C:\mysql\share /E
Wenn Sie andere Clients kompilieren und diese mit MySQL verknüpfen wollen, sollten Sie außerdem verschiedene Bibliotheken und Header-Dateien erstellen:
C:\workdir>copy lib_debug\mysqlclient.lib C:\mysql\lib\debug
C:\workdir>copy lib_debug\libmysql.* C:\mysql\lib\debug
C:\workdir>copy lib_debug\zlib.* C:\mysql\lib\debug
C:\workdir>copy lib_release\mysqlclient.lib C:\mysql\lib\opt
C:\workdir>copy lib_release\libmysql.* C:\mysql\lib\opt
C:\workdir>copy lib_release\zlib.* C:\mysql\lib\opt
C:\workdir>copy include\*.h C:\mysql\include
C:\workdir>copy libmysql\libmysql.def C:\mysql\include
Wenn Sie Benchmarks für MySQL erstellen wollen, sollten Sie auch Folgendes tun:
C:\workdir> xcopy sql-bench\*.* C:\mysql\bench /E
Konfigurieren und starten Sie den Server auf die gleiche Weise wie bei einer Windows-Distribution. Siehe auch Abschnitt 2.3, „Installation von MySQL unter Windows“.
Um ein Windows-Quellcodepaket aus dem BitKeeper-Source-Tree zu erstellen, verwenden Sie die nachfolgenden Anweisungen. Dieser Vorgang muss auf einem System unter Unix oder einem Unix-Derivat durchgeführt werden, da einige der Konfigurations- und Erstellungsschritte das Vorhandensein von Tools voraussetzen, die nur unter Unix laufen. Die folgende Vorgehensweise funktioniert etwa unter Linux einwandfrei.
Kopieren Sie den BitKeeper-Source-Tree für MySQL 5.1. Hinweise hierzu finden Sie in Abschnitt 2.8.3, „Installation vom Entwicklungs-Source-Tree“.
Konfigurieren und erstellen Sie die Distribution, um eine Serverbinärdatei zu erhalten, mit der Sie arbeiten können. Eine Möglichkeit hierzu besteht im Ausführen des folgenden Befehls im obersten Verzeichnis Ihres Source-Trees:
shell> ./BUILD/compile-pentium-max
Wenn Sie sich davon überzeugt haben, dass der Erstellungsprozess erfolgreich abgeschlossen wurde, führen Sie das folgende Hilfsskript im obersten Verzeichnis Ihres Source-Trees aus:
shell> ./scripts/make_win_src_distribution
Das Skript erstellt ein Windows-Quellpaket zur Verwendung auf Ihrem Windows-System. Sie können je nach Bedarf unterschiedliche Optionen für das Skript angeben. Die folgenden Optionen werden akzeptiert:
--help
Zeigt eine Hilfemeldung an.
--debug
Druckt Informationen zu Skriptoperationen (das Paket wird nicht erstellt).
--tmp
Gibt das Temporärverzeichnis an.
--suffix
Suffixname des Pakets.
--dirname
Name des Verzeichnisses, in das die Dateien temporär kopiert werden.
--silent
Die Liste der verarbeiteten Dateien wird nicht ausgegeben.
--tar
Erstellt ein tar.gz
- statt eines
.zip
-Pakets.
Standardmäßig legt
make_win_src_distribution ein Archiv im
ZIP-Format mit dem Namen
mysql-
an. Hierbei steht VERSION
-win-src.zipVERSION
für
die Version Ihres MySQL-Source-Trees.
Kopieren Sie das soeben erstellte Windows-Quellpaket auf Ihren Windows-Computer bzw. laden Sie es hoch. Verwenden Sie zur Kompilierung die Anweisungen in Abschnitt 2.8.6.1, „Bauen von MySQL mit VC++“.
In Ihren Quelldateien sollten Sie
my_global.h
vor
mysql.h
einsetzen:
#include <my_global.h> #include <mysql.h>
my_global.h
enthält alle Dateien, die für
die Windows-Kompatibilität erforderlich sind (z. B.
windows.h
), wenn Sie Ihr Programm unter
Windows kompilieren.
Sie können Ihren Code entweder mit der dynamischen Bibliothek
libmysql.lib
, die nichts anderes als ein
Wrapper zum Einladen bei Bedarf in
libmysql.dll
ist, oder mit der statischen
Bibliothek mysqlclient.lib
verknüpfen.
Die MySQL-Clientbibliotheken werden als Bibliotheken mit Threads kompiliert, d. h., Sie sollten Ihren Code mit Multithread-Unterstützung kompilieren.
Nach der Installation von MySQL gibt es einige Aspekte, die beachtet werden sollten. So sollten Sie etwa unter Unix das Datenverzeichnis initialisieren und die MySQL-Grant-Tabellen erstellen. Bei allen Plattformen besteht ein erhebliches Sicherheitsrisiko darin, dass die bei der Installation in den Grant-Tabellen eingerichteten Konten keine Passwörter aufweisen. Sie sollten Passwörter zuweisen, um unautorisierten Zugriff auf den MySQL Server zu verhindern. Optional können Sie Zeitzonentabellen erstellen, um die Erkennung benannter Zeitzonen zu ermöglichen.
Die folgenden Abschnitte erhalten Angaben zu Maßnahmen nach Abschluss der Installation, die speziell auf Windows- bzw. Unix-Systeme zugeschnitten sind. In Abschnitt 2.9.2.3, „Probleme mit dem Start des MySQL Servers“, finden Sie zudem Informationen, die für alle Plattformen gelten. Dort wird beschrieben, was Sie tun können, wenn Sie Probleme mit dem Starten des Servers haben. Auch Abschnitt 2.9.3, „Einrichtung der anfänglichen MySQL-Berechtigungen“, betrifft alle Plattformen. Sie sollten den Anweisungen folgen, um zu gewährleisten, dass Ihre MySQL-Konten durch Konfiguration von Passwörtern angemessen geschützt sind.
Wenn Sie so weit sind, dass Sie weitere Benutzerkonten erstellen wollen oder müssen, finden Sie Informationen zum MySQL-Zugriffssteuerungssystem und zur Kontenverwaltung in Abschnitt 5.8, „Allgemeine Sicherheitsaspekte und das MySQL-Zugriffsberechtigungssystem“, und Abschnitt 5.9, „MySQL-Benutzerkontenverwaltung“.
Unter Windows müssen Datenverzeichnis und Grant-Tabellen nicht
erstellt werden. Windows-Distributionen von MySQL enthalten
bereits Grant-Tabellen mit vorinitialisierten Konten in der
mysql
-Datenbank im Datenverzeichnis. Insofern
ist es nicht notwendig, das Skript
mysql_install_db auszuführen, das unter Unix
obligatorisch ist. Was Passwörter betrifft, so haben Sie diese
unter Umständen bereits für die Konten vergeben, sofern Sie
MySQL mit dem Windows-Installations-Assistenten installiert
haben. (Siehe auch Abschnitt 2.3.4, „Verwendung des MySQL-Installations-Assistenten“.)
Andernfalls müssen Sie die in
Abschnitt 2.9.3, „Einrichtung der anfänglichen MySQL-Berechtigungen“, beschriebene
Vorgehensweise zur Vergabe von Passwörtern befolgen.
Bevor Sie Passwörter konfigurieren, sollten Sie einige Clientprogramme ausführen, um sicherzustellen, dass sich Serververbindungen herstellen lassen und einwandfrei arbeiten. Vergewissern Sie sich, dass der Server läuft (siehe Abschnitt 2.3.10, „Erstmaliges Starten des Servers“), und geben Sie dann die folgenden Befehle ein, um nachzuprüfen, ob Sie Daten vom Server abrufen können. Die Ausgabe sollte ähnlich wie nachfolgend aufgeführt aussehen:
C:\>C:\mysql\bin\mysqlshow
+-----------+ | Databases | +-----------+ | mysql | | test | +-----------+ C:\>C:\mysql\bin\mysqlshow mysql
Database: mysql +---------------------------+ | Tables | +---------------------------+ | columns_priv | | db | | func | | help_category | | help_keyword | | help_relation | | help_topic | | host | | proc | | procs_priv | | tables_priv | | time_zone | | time_zone_leap_second | | time_zone_name | | time_zone_transition | | time_zone_transition_type | | user | +---------------------------+ C:\>C:\mysql\bin\mysql -e "SELECT Host,Db,User FROM db" mysql
+------+-------+------+ | host | db | user | +------+-------+------+ | % | test% | | +------+-------+------+
Wenn Sie eine Windows-Version verwenden, die Dienste unterstützt, und Sie wollen, dass der MySQL Server beim Start von Windows automatisch gestartet wird, finden Sie Informationen in Abschnitt 2.3.12, „Starten von MySQL als Windows-Dienst“.
Nachdem Sie MySQL unter Unix installiert haben, müssen Sie die Grant-Tabellen initialisieren, den Server starten und sicherstellen, dass dieser korrekt arbeitet. Ferner sollten Sie das automatische Starten und Beenden des Servers beim Starten bzw. Herunterfahren des Systems konfigurieren. Zudem sind Passwörter für die Konten in den Grant-Tabellen zu erstellen.
Unter Unix werden die Grant-Tabellen durch das Programm mysql_install_db eingerichtet. Bei einigen Installationsmethoden wird dieses Programm für Sie automatisch ausgeführt:
Wenn Sie MySQL unter Linux mithilfe von RPM-Distributionen installieren, startet das Server-RPM mysql_install_db.
Wenn Sie MySQL unter Mac OS X mithilfe einer PKG-Distribution installieren, startet das Installationsprogramm mysql_install_db.
In allen anderen Fällen müssen Sie mysql_install_db selbst ausführen.
Die nachfolgende Vorgehensweise beschreibt, wie man die Grant-Tabellen initialisiert (soweit dies noch nicht geschehen ist) und dann den Server startet. Ferner werden einige Befehle vorgeschlagen, mit denen Sie testen können, ob der Server zugänglich ist und korrekt arbeitet. Informationen zum automatischen Starten und Beenden des Servers finden Sie in Abschnitt 2.9.2.2, „MySQL automatisch starten und anhalten“.
Wenn Sie den Vorgang abgeschlossen haben und der Server läuft, sollten Sie für die von mysql_install_db erstellten Konten Passwörter erstellen. Eine Anleitung hierzu finden Sie in Abschnitt 2.9.3, „Einrichtung der anfänglichen MySQL-Berechtigungen“.
In den nachfolgenden Beispielen läuft der Server unter der
Benutzer-ID des Anmeldekontos mysql
. Dies
setzt natürlich voraus, dass dieses Konto auch existiert. Ist
dies nicht der Fall, dann müssen Sie das Konto entweder
erstellen oder den Namen eines anderen vorhandenen Anmeldekontos
ersetzen, das Sie für die Ausführung des Servers verwenden
wollen.
Wechseln Sie in das oberste Verzeichnis Ihrer
MySQL-Installation (dieses wird hier als
BASEDIR
dargestellt):
shell> cd BASEDIR
BASEDIR
ist dabei so etwas wie
/usr/local/mysql
oder
/usr/local
. Die folgenden Schritte
setzen voraus, dass Sie in dieses Verzeichnis gewechselt
sind.
Sofern notwendig, führen Sie mysql_install_db aus, um die vorgabeseitigen MySQL-Grant-Tabellen mit den Berechtigungen einzurichten, die bestimmen, wie Benutzer mit dem Server Verbindungen herstellen können. Sie müssen das tun, wenn Sie einen Distributionstyp verwendet haben, bei dessen Installation das Programm nicht automatisch ausgeführt wird.
Normalerweise muss mysql_install_db nur bei der Erstinstallation von MySQL ausgeführt werden; Sie können diesen Schritt also überspringen, wenn Sie eine vorhandene Installation aktualisieren. Allerdings überschreibt mysql_install_db keine vorhandenen Berechtigungstabellen, kann also in allen Situationen problemlos ausgeführt werden.
Um die Grant-Tabellen zu initialisieren, verwenden Sie einen
der folgenden Befehle (je nachdem, ob sich
mysql_install_db im Verzeichnis
bin
oder scripts
befindet):
shell>bin/mysql_install_db --user=mysql
shell>scripts/mysql_install_db --user=mysql
Das Skript mysql_install_db erstellt das
Datenverzeichnis des Servers. In diesem Datenverzeichnis
werden Verzeichnisse für die
mysql
-Datenbank, die alle
Datenbankberechtigungen enthält, und die
test
-Datenbank erstellt, die Sie zum
Testen von MySQL verwenden können. Das Skript erstellt
außerdem Einträge für root
-Konten und
Konten für anonyme Benutzer in den Berechtigungstabellen.
Diese Konten haben anfangs kein Passwort. Eine Beschreibung
ihrer Ausgangsberechtigungen finden Sie in
Abschnitt 2.9.3, „Einrichtung der anfänglichen MySQL-Berechtigungen“. Kurz
gesagt, ermöglichen diese Berechtigungen dem
MySQL-root
-Benutzer alles und erlauben
jedem Benutzer zudem die Erstellung und Verwendung von
Datenbanken mit dem Namen test
oder einem
Namen, der mit test_
beginnt.
Es ist wichtig sicherzustellen, dass die
Datenbankverzeichnisse und -dateien im Besitz des Kontos
mysql
sind, damit der Server bei der
späteren Ausführung Lese- und Schreibzugriff darauf hat.
Um dies zu gewährleisten, sollte die Option
--user
wie nachfolgend gezeigt verwendet
werden, wenn Sie mysql_install_db als
root
ausführen. Andernfalls sollten Sie
das Skript ausführen, während Sie als
mysql
angemeldet sind; in diesem Fall
können Sie die Option --user
in dem Befehl
weglassen.
mysql_install_db erstellt eine Reihe von
Tabellen in der mysql
-Datenbank, darunter
u. a. user
, db
,
host
, tables_priv
,
columns_priv
und func
.
Eine vollständige Auflistung und Beschreibung dieser
Tabellen finden Sie in
Abschnitt 5.8, „Allgemeine Sicherheitsaspekte und das MySQL-Zugriffsberechtigungssystem“.
Wenn Sie die test
-Datenbank nicht
brauchen, können Sie sie nach dem Starten des Servers mit
dem Befehl mysqladmin -u root drop test
entfernen.
Sollten Sie an dieser Stelle Probleme mit
mysql_install_db haben, dann finden Sie
weitere Informationen in Abschnitt 2.9.2.1, „Probleme mit mysql_install_db
“.
Starten Sie den MySQL Server:
shell> bin/mysqld_safe --user=mysql &
Es ist wichtig, dass der MySQL Server über ein
berechtigungsloses Anmeldekonto (d. h. kein
root
-Konto) ausgeführt wird. Um dies zu
gewährleisten, sollte die Option --user
wie nachfolgend gezeigt verwendet werden, wenn Sie
mysql_safe
als root
ausführen. Andernfalls sollten Sie das Skript ausführen,
während Sie als mysql
am System
angemeldet sind; in diesem Fall können Sie die Option
--user
in dem Befehl weglassen.
Weitere Anweisungen zur Ausführung von MySQL als berechtigungsloser Benutzer finden Sie in Abschnitt 5.7.5, „Wie man MySQL als normaler Benutzer laufen läßt“.
Wenn Sie vor Durchführung dieses Schritts vergessen haben, die Grant-Tabellen zu erstellen, dann erscheint die folgende Meldung im Fehlerlog, wenn Sie den Server starten:
mysqld: Can't find file: 'host.frm'
Bei Auftreten anderer Probleme während des Serverstarts finden Sie Informationen in Abschnitt 2.9.2.3, „Probleme mit dem Start des MySQL Servers“.
Stellen Sie mit mysqladmin sicher, dass der Server ausgeführt wird. Die folgenden Befehle ermöglichen einfache Tests, um zu prüfen, ob der Server aktiv ist und auf Verbindungen reagiert:
shell>bin/mysqladmin version
shell>bin/mysqladmin variables
Die Ausgabe von mysqladmin version kann je nach Plattform und MySQL-Version variieren, sollte aber der nachfolgend abgebildeten ähneln:
shell> bin/mysqladmin version
mysqladmin Ver 14.12 Distrib 5.1.5-alpha, for pc-linux-gnu on i686
Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
This software comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to modify and redistribute it under the GPL license
Server version 5.1.5-alpha-Max
Protocol version 10
Connection Localhost via UNIX socket
UNIX socket /var/lib/mysql/mysql.sock
Uptime: 14 days 5 hours 5 min 21 sec
Threads: 1 Questions: 366 Slow queries: 0
Opens: 0 Flush tables: 1 Open tables: 19
Queries per second avg: 0.000
Wenn Sie wissen wollen, was Sie mit
mysqladmin noch machen können, rufen Sie
es mit der Option --help
auf.
Überprüfen Sie nun, ob Sie den Server herunterfahren können:
shell> bin/mysqladmin -u root shutdown
Als Nächstes prüfen Sie, ob Sie den Server neu starten können. Hierzu verwenden Sie mysqld_safe oder rufen mysqld direkt auf. Ein Beispiel:
shell> bin/mysqld_safe --user=mysql --log &
Schlägt mysqld_safe fehl, dann lesen Sie Abschnitt 2.9.2.3, „Probleme mit dem Start des MySQL Servers“.
Führen Sie einige einfache Tests durch, um sicherzustellen, dass Sie Daten am Server abrufen können. Die Ausgabe sollte ähnlich wie nachfolgend aufgeführt aussehen:
shell>bin/mysqlshow
+-----------+ | Databases | +-----------+ | mysql | | test | +-----------+ shell>bin/mysqlshow mysql
Database: mysql +---------------------------+ | Tables | +---------------------------+ | columns_priv | | db | | func | | help_category | | help_keyword | | help_relation | | help_topic | | host | | proc | | procs_priv | | tables_priv | | time_zone | | time_zone_leap_second | | time_zone_name | | time_zone_transition | | time_zone_transition_type | | user | +---------------------------+ shell>bin/mysql -e "SELECT Host,Db,User FROM db" mysql
+------+--------+------+ | host | db | user | +------+--------+------+ | % | test | | | % | test_% | | +------+--------+------+
Im Verzeichnis sql-bench
(dieses
befindet sich im MySQL-Installationsverzeichnis) befindet
sich eine Benchmark-Reihe, die Sie verwenden können, um die
Leistungsfähigkeit von MySQL auf verschiedenen Plattformen
zu vergleichen. Diese Benchmark-Reihe ist in Perl
geschrieben. Sie erfordert das Perl-DBI-Modul, welches eine
datenbankunabhängige Schnittstelle zu verschiedenen
Datenbanken bereitstellt, sowie einige weitere Perl-Module:
DBI DBD::mysql Data::Dumper Data::ShowTable
Diese Module erhalten Sie bei CPAN (http://www.cpan.org/). Siehe auch Abschnitt 2.13.1, „Installation von Perl unter Unix“.
Das Verzeichnis sql-bench/Results
enthält die Ergebnisse vieler Testläufe mit
unterschiedlichen Datenbanken und Plattformen. Um alle Tests
durchzuführen, setzen Sie die folgenden Befehle ab:
shell>cd sql-bench
shell>perl run-all-tests
Wenn das Verzeichnis sql-bench
bei
Ihnen nicht vorhanden ist, haben Sie MySQL wahrscheinlich
aus anderen RPM-Dateien als dem Quell-RPM installiert. (Das
Quell-RPM enthält das Benchmark-Verzeichnis
sql-bench
.) In diesem Fall müssen Sie
die Benchmark-Reihe zunächst installieren, bevor Sie sie
verwenden können. Es gibt separate Benchmark-RPMs namens
mysql-bench-
,
die den Benchmark-Code und die Daten enthalten.
VERSION
-i386.rpm
Wenn Sie mit einer Quelldistribution arbeiten, finden Sie in
deren Unterverzeichnis tests
weitere
Tests, die Sie ausführen können. Um etwa
auto_increment.tst
auszuführen, setzen
Sie den folgenden Befehl im obersten Verzeichnis Ihrer
Quelldistribution ab:
shell> mysql -vvf test < ./tests/auto_increment.tst
Die erwarteten Testergebnisse finden Sie in der Datei
./tests/auto_increment.res
.
An dieser Stelle sollte der Server bereits laufen. Allerdings verfügt keines der vorgabeseitigen MySQL-Konten über ein Passwort. Weisen Sie deswegen Passwörter zu wie in Abschnitt 2.9.3, „Einrichtung der anfänglichen MySQL-Berechtigungen“, beschrieben.
Der Installationsvorgang für MySQL 5.1 erstellt
Zeitzonentabellen in der Datenbank mysql
. Sie
müssen die Tabellen allerdings manuell ausfüllen; wie das
geht, steht in Abschnitt 5.11.8, „Zeitzonen-Unterstützung des MySQL-Servers“.
Der Zweck des Skripts mysql_install_db besteht in der Generierung neuer MySQL-Berechtigungstabellen. Hierbei werden vorhandene MySQL-Berechtigungstabellen nicht überschrieben, und auch andere Daten werden nicht beeinträchtigt.
Wollen Sie Ihre Berechtigungstabellen neu erstellen, dann
beenden Sie zunächst den mysqld-Server,
sofern dieser läuft. Benennen Sie das Verzeichnis
mysql
im Datenverzeichnis dann um, um es
zu speichern, und führen Sie nachfolgend
mysql_install_db aus. Nehmen wir an, Ihr
aktuelles Verzeichnis ist das MySQL-Installationsverzeichnis,
mysql_install_db befindet sich im
Verzeichnis bin
und das Datenverzeichnis
heißt data
. Um die
mysql
-Datenbank umzubenennen und
mysql_install_db erneut auszuführen,
verwenden Sie die folgenden Befehle:
shell>mv data/mysql data/mysql.old
shell>bin/mysql_install_db --user=mysql
Wenn Sie mysql_install_db ausführen, können die folgenden Probleme auftreten:
mysql_install_db kann die Grant-Tabellen nicht installieren.
Unter Umständen stellen Sie fest, dass mysql_install_db die Grant-Tabellen nicht installieren kann und nach Anzeige der folgenden Meldungen beendet wird:
Starting mysqld daemon with databases from XXXXXX mysqld ended
In diesem Fall sollten Sie die Fehlerlogdatei sehr
aufmerksam lesen. Das Fehlerlog sollte sich im Verzeichnis
XXXXXX
befinden (dieses ist nach der
Fehlermeldung benannt) und angeben, warum
mysqld nicht gestartet wurde. Wenn Sie
nicht verstehen, was geschehen ist, hängen Sie das Log
an, wenn Sie einen Bugreport einsenden. Siehe auch
Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“.
Ein mysqld-Prozess wird ausgeführt.
Dies weist darauf hin, dass der Server läuft und die Grant-Tabellen wahrscheinlich bereits erstellt wurden. In diesem Fall müssen Sie mysql_install_db überhaupt nicht ausführen, da es nur einmal gestartet werden muss (nämlich dann, wenn Sie MySQL zum ersten Mal installieren).
Die Installation eines zweiten mysqld-Servers schlägt fehl, wenn ein Server bereits läuft.
Dies kann passieren, wenn eine MySQL-Installation bereits vorhanden ist, Sie aber eine neue Installation an einer anderen Position ablegen wollen. So haben Sie vielleicht eine Produktionsinstallation, wollen aber eine zweite Installation zu Testzwecken einrichten. Meist tritt dieses Problem auf, wenn Sie einen zweiten Server ausführen wollen, der auf eine Netzwerkschnittstelle zuzugreifen versucht, die bereits vom ersten Server verwendet wird. In diesem Fall werden Sie eine der folgenden Fehlermeldungen sehen:
Can't start server: Bind on TCP/IP port: Address already in use Can't start server: Bind on unix socket ...
Anweisungen zur Einrichtung mehrerer Server finden Sie in Abschnitt 5.13, „Mehrere MySQL-Server auf derselben Maschine laufen lassen“.
Sie haben keinen Schreibzugriff auf
das Verzeichnis /tmp
.
Wenn Sie keinen Schreibzugriff erhalten, um
Temporärdateien oder eine Unix-Socketdatei im
Standardverzeichnis (/tmp
) zu
erstellen, dann tritt ein Fehler auf, wenn Sie
mysql_install_db oder den
mysqld-Server ausführen wollen.
Sie können verschiedene Positionen für das
Temporärverzeichnis und die Unix-Socketdatei angeben,
indem Sie die folgenden Befehle vor dem Starten von
mysql_install_db oder
mysqld ausführen (hierbei ist
some_tmp_dir
der vollständige
Pfadname eines Verzeichnisses, für das Sie Schreibzugriff
haben):
shell>TMPDIR=/
shell>some_tmp_dir
/MYSQL_UNIX_PORT=/
shell>some_tmp_dir
/mysql.sockexport TMPDIR MYSQL_UNIX_PORT
Danach sollten Sie in der Lage sein, mysql_install_db mit den folgenden Befehlen auszuführen und den Server zu starten:
shell>bin/mysql_install_db --user=mysql
shell>bin/mysqld_safe --user=mysql &
Wenn sich mysql_install_db im
Verzeichnis scripts
befindet, ändern
Sie den ersten Befehl zu
scripts/mysql_install_db
.
Siehe auch
Abschnitt A.4.5, „Wie Sie die MySQL-Socketdatei /tmp/mysql.sock
schützen oder ändern“,
und Anhang F, Umgebungsvariablen.
Es gibt einige Alternativen zur Ausführung des Skripts mysql_install_db, welches Bestandteil der MySQL-Distribution ist:
Wenn Sie wollen, dass die Ausgangsberechtigungen sich von
den Standardwerten unterscheiden, können Sie
mysql_install_db vor der Ausführung
bearbeiten. Allerdings bietet es sich eher an, mit
GRANT
und REVOKE
die
Berechtigungen zu ändern, nachdem
die Grant-Tabellen eingerichtet wurden. Mit anderen
Worten, Sie können mysql_install_db
ausführen und dann mithilfe von mysql -u root
mysql
eine Verbindung zum Server als
MySQL-root
-Benutzer herstellen, damit
Sie die erforderlichen GRANT
- und
REVOKE
-Anweisungen absetzen können.
Wenn Sie MySQL auf mehreren Computern mit denselben
Berechtigungen installieren wollen, können Sie die
GRANT
- und
REVOKE
-Anweisungen auch in einer Datei
ablegen und diese Datei mithilfe von
mysql
als Skript ausführen, nachdem
Sie mysql_install_db gestartet haben.
Ein Beispiel:
shell>bin/mysql_install_db --user=mysql
shell>bin/mysql -u root < your_script_file
Auf diese Weise müssen Sie die Anweisungen nicht manuell auf jedem einzelnen Computer eingeben.
Es ist möglich, die Grant-Tabellen nach ihrer Erstellung
vollständig neu zu erstellen. Dies müssen Sie unter
Umständen tun, wenn Sie gerade erst lernen, wie man
GRANT
und REVOKE
verwendet, und nach der Ausführung von
mysql_install_db derart viele
Änderungen vorgenommen haben, dass Sie die Tabellen
komplett löschen und von vorn beginnen wollen.
Um die Grant-Tabellen neu zu erstellen, entfernen Sie alle
.frm
-, .MYI
- und
.MYD
-Dateien im Datenbankverzeichnis
mysql
. Danach führen Sie das Skript
mysql_install_db erneut aus.
Sie können mysqld manuell mithilfe der
Option --skip-grant-tables
starten und
die Berechtigungsdaten selbst unter Verwendung von
mysql hinzufügen:
shell>bin/mysqld_safe --user=mysql --skip-grant-tables &
shell>bin/mysql mysql
Von mysql führen Sie die in mysql_install_db enthaltenen SQL-Befehle manuell aus. In jedem Fall müssen Sie danach mysqladmin flush-privileges oder mysqladmin reload ausführen, um dem Server mitzuteilen, dass er die Grant-Tabellen neu laden muss.
Beachten Sie, dass Sie, wenn Sie mysql_install_db nicht benutzen, die Grant-Tabellen nicht nur manuell ausfüllen, sondern sie zuvor auch noch erstellen müssen.
Normalerweise starten Sie den mysqld-Server unter Verwendung einer der folgenden Möglichkeiten:
Durch direkten Aufruf von mysqld. Das funktioniert auf allen Plattformen.
Durch Ausführung des MySQL Servers als Windows-Dienst. Dies ist unter Windows-Versionen möglich, die Dienste unterstützen (also NT, 2000, XP und 2003). Der Dienst kann entweder so konfiguriert werden, dass der Server automatisch mit Windows startet, oder als manueller Dienst, den Sie manuell starten müssen. Informationen zur Vorgehensweise finden Sie in Abschnitt 2.3.12, „Starten von MySQL als Windows-Dienst“.
Durch Aufruf von mysqld_safe. Hierbei wird versucht, die passenden Optionen für mysqld zu ermitteln und es dann mit diesen Optionen zu starten. Dieses Skript wird unter Unix und Unix-ähnlichen Systemen verwendet. Siehe auch Abschnitt 5.4.1, „mysqld_safe — Startskript für den MySQL-Server“.
Durch den Aufruf von mysql.server.
Dieses Skript wird in erster Linie beim Starten und
Beenden von Systemen verwendet, die
Ausführungsverzeichnisse im System V-Stil verwenden, wo
es normalerweise unter dem Namen mysql
installiert ist. Das Skript
mysql.server startet den Server, indem
es mysqld_safe aufruft. Siehe auch
Abschnitt 5.4.2, „mysql.server — Startskript für den MySQL-Server“.
Unter Mac OS X können Sie ein separates MySQL-Startobjektpaket installieren, um den automatischen Start von MySQL beim Systemstart zu aktivieren. Das Startobjekt startet den Server durch Aufruf von mysql.server. Weitere Informationen finden Sie in Abschnitt 2.5, „Installation von MySQL unter Mac OS X“.
Die Skripten mysqld_safe und mysql.server und das Mac OS X-Startobjekt können für den manuellen Start des Servers oder für seinen automatischen Start beim Systemstart verwendet werden. mysql.server und das Startobjekt erlauben zudem das Beenden des Servers.
Um den Server mit mysql.server manuell zu
starten oder zu beenden, rufen Sie es mit dem Argument
start
bzw. stop
auf:
shell>mysql.server start
shell>mysql.server stop
Bevor mysql.server den Server startet,
wechselt es in das MySQL-Installationsverzeichnis und ruft
dann mysqld_safe auf. Wenn Sie wollen, dass
der Server als ein bestimmter Benutzer ausgeführt wird,
fügen Sie die entsprechende Option user
im
Abschnitt [mysqld]
der Optionsdatei
/etc/my.cnf
hinzu. Eine Erklärung
erhalten Sie im weiteren Verlauf dieses Abschnitts. (Unter
Umständen müssen Sie mysql.server
bearbeiten, wenn Sie eine Binärdistribution von MySQL in
einem anderen als dem Standardverzeichnis installiert haben.
Ändern Sie es so, dass es via cd
in das
korrekte Verzeichnis wechselt, bevor es
mysqld_safe ausführt. Beachten Sie
allerdings, dass Ihre geänderte Version von
mysql.server bei einem zukünftigen
MySQL-Upgrade überschrieben werden könnte; deswegen sollten
Sie eine Kopie der editierten Version erstellen, die Sie bei
Bedarf neu installieren können.)
mysql.server stop beendet den Server, indem es ein Signal an ihn schickt. Sie können den Server auch manuell beenden, indem Sie mysqladmin shutdown ausführen.
Um MySQL automatisch auf Ihrem Server zu starten und zu
beenden, müssen Sie Start- und Stoppbefehle an den
entsprechenden Stellen Ihrer
/etc/rc*
-Dateien einfügen.
Wenn Sie das Linux-Server-RPM-Paket
(MySQL-server-
)
verwenden, wird das Skript mysql.server im
Verzeichnis VERSION
.rpm/etc/init.d
unter dem Namen
mysql
installiert. Sie müssen die
Installation also nicht manuell vornehmen. Weitere
Informationen zu Linux-RPM-Paketen finden Sie in
Abschnitt 2.4, „MySQL unter Linux installieren“.
Manche Anbieter stellen RPM-Pakete bereit, die ein Startskript unter einem anderen Namen wie etwa mysqld installieren.
Wenn Sie MySQL aus einer Quelldistribution installieren oder
ein Binärdistributionsformat verwenden, das
mysql.server nicht automatisch installiert,
können Sie es manuell installieren. Sie finden das Skript im
Verzeichnis support-files
, das sich im
MySQL-Installationsverzeichnis befindet, oder in einem
MySQL-Source-Tree.
Um mysql.server manuell zu installieren,
kopieren Sie es unter dem Namen mysql in
das Verzeichnis /etc/init.d
und machen es
dann ausführbar. Dies tun Sie, indem Sie in das entsprechende
Verzeichnis wechseln, in dem sich
mysql.server befindet, und dann die
folgenden Befehle ausführen:
shell>cp mysql.server /etc/init.d/mysql
shell>chmod +x /etc/init.d/mysql
Ältere Red Hat-Systeme verwenden das Verzeichnis
/etc/rc.d/init.d
statt
/etc/init.d
. In diesem Fall müssen Sie
die obigen Befehle entsprechend ändern. Alternativ erstellen
Sie zunächst /etc/init.d
als symbolische
Verknüpfung, die auf /etc/rc.d/init.d
verweist:
shell>cd /etc
shell>ln -s rc.d/init.d .
Nach der Installation des Skripts hängt der Befehl, der zur
Aktivierung der Ausführung beim Systemstart erforderlich ist,
von Ihrem Betriebssystem ab. Unter Linux können Sie
chkconfig
verwenden:
shell> chkconfig --add mysql
Unter manchen Linux-Systemen scheint auch der folgende Befehl notwendig zu sein, um das Skript mysql vollständig zu aktivieren:
shell> chkconfig --level 345 mysql on
Unter FreeBSD sollten Startskripten generell in
/usr/local/etc/rc.d/
abgelegt werden. Die
Manpage rc(8)
gibt an, dass Skripten in
diesem Verzeichnis nur dann ausgeführt werden, wenn ihr
Basisname dem Shell-Muster für Dateinamen
*.sh
entspricht. Alle anderen Dateien oder
Verzeichnisse, die in diesem Verzeichnis vorhanden sind,
werden stillschweigend ignoriert. Mit anderen Worten: Unter
FreeBSD müssen Sie das Skript
mysql.server
als
/usr/local/etc/rc.d/mysql.server.sh
installieren, um den automatischen Start zu aktivieren.
Als Alternative zur obigen Konfiguration verwenden manche
Betriebssysteme auch /etc/rc.local
oder
/etc/init.d/boot.local
, um zusätzliche
Dienste beim Systemstart zu starten. Um MySQL auf diese Weise
zu starten, könnten Sie einen Befehl wie den folgenden an die
entsprechende Startdatei anhängen:
/bin/sh -c 'cd /usr/local/mysql; ./bin/mysqld_safe --user=mysql &'
Bei anderen Systemen lesen Sie in der Dokumentation zu Ihrem Betriebssystem nach, um zu erfahren, wie Startskripten installiert werden.
Sie können Optionen für mysql.server in
einer globalen Datei /etc/my.cnf
ablegen.
Eine /etc/my.cnf
-Datei sieht
normalerweise so aus:
[mysqld] datadir=/usr/local/mysql/var socket=/var/tmp/mysql.sock port=3306 user=mysql [mysql.server] basedir=/usr/local/mysql
Das Skript mysql.server versteht die
folgenden Optionen: basedir
,
datadir
und pid-file
.
Sofern angegeben, müssen diese in einer
Optionsdatei und nicht an der Befehlszeile abgelegt sein.
mysql.server versteht nur
start
und stop
als
Befehlszeilenargumente.
Die folgende Tabelle zeigt, welche Optionsgruppen der Server und die jeweiligen Startskripten aus den Optionsdateien auslesen:
Skript | Abschnitte in der Optionsdatei |
mysqld | [mysqld] , [server] ,
[mysqld- |
mysqld_safe | [mysqld] , [server] ,
[mysqld_safe] |
mysql.server | [mysqld] , [mysql.server] ,
[server] |
[mysqld-
bedeutet, dass Abschnitte mit Namen wie
major_version
][mysqld-5.0]
und
[mysqld-5.1]
von Servern der
Versionen 5.0.x, 5.1.x usw.
ausgelesen werden. Diese Funktion kann verwendet werden, um
Optionen anzugeben, die nur von Servern einer bestimmten
Release-Serie ausgelesen werden können.
Zwecks Abwärtskompatibilität liest
mysql.server auch den Abschnitt
[mysql_server]
und
mysqld_safe den Abschnitt
[safe_mysqld]
aus. Allerdings sollten Sie
Ihre Optionsdateien so aktualisieren, dass sie stattdessen die
Abschnitte [mysql.server]
und
[mysqld_safe]
auslesen, wenn Sie MySQL
5.1 verwenden.
Siehe auch Abschnitt 4.3.2, „my.cnf-Optionsdateien“.
Dieser Abschnitt enthält Vorschläge zur Fehlersuche, wenn unter Unix Probleme beim Start des Servers auftreten. Wenn Sie Windows verwenden, finden Sie Informationen in Abschnitt 2.3.14, „Troubleshooting einer MySQL-Installation unter Windows“.
Haben Sie Probleme beim Starten des Servers, dann probieren Sie folgende Schritte:
Suchen Sie im Fehlerlog nach Ursachen dafür, dass der Server nicht startet.
Geben Sie alle Sonderoptionen an, die von den von Ihnen verwendeten Speicher-Engines benötigt werden.
Stellen Sie sicher, dass der Server die Position des Datenverzeichnisses kennt.
Stellen Sie auch sicher, dass der Server auf das Datenverzeichnis zugreifen kann. Besitzrechte und Berechtigungen für das Datenverzeichnis und seine Inhalte müssen so konfiguriert sein, dass der Server sie lesen und ändern kann.
Überprüfen Sie, ob die Netzwerkschnittstellen, die der Server verwenden will, vorhanden sind.
Einige Speicher-Engines haben Optionen, die ihr Verhalten
steuern. Sie können eine Datei my.cnf
erstellen und darin die Startoptionen der Engines angeben, die
Sie zu verwenden beabsichtigen. Wenn Sie Speicher-Engines
verwenden wollen, die transaktionssichere Tabellen
(InnoDB
, BDB
,
NDB
) unterstützen, dann vergewissern Sie
sich, dass diese wie gewünscht konfiguriert sind, bevor Sie
den Server starten:
Wenn Sie InnoDB
-Tabellen verwenden,
finden Sie Informationen in
Abschnitt 14.2.3, „Konfiguration“.
Setzen Sie BDB
-Tabellen
(BerkeleyDB-Tabellen) ein, dann finden Sie Informationen
in Abschnitt 14.5.3, „BDB-Startoptionen“.
Wenn Sie MySQL-Cluster verwenden, finden Sie Informationen in Abschnitt 16.4, „MySQL Cluster: Konfiguration“.
Speicher-Engines verwenden, sofern keine Optionswerte definiert sind, die Vorgabewerte. Wir empfehlen deswegen, die verfügbaren Optionen zu prüfen und explizite Werte für diejenigen Optionen anzugeben, bei denen die Vorgabewerte nicht für Ihre Installation geeignet sind.
Wenn der mysqld-Server startet, wechselt er in das Datenverzeichnis. In diesem Verzeichnis erwartet er das Vorhandensein der Datenbanken, und hier wird er auch seine Logdateien speichern. Auch die PID-Datei (Process ID, Prozesskennung) wird im Datenverzeichnis abgelegt.
Das Datenverzeichnis wird bei der Kompilierung des Servers
fest zugeordnet. Standardmäßig sucht der Server deswegen an
der angegebenen Position nach diesem Verzeichnis. Befindet
sich das Datenverzeichnis in Ihrem System an anderer Stelle,
dann funktioniert der Server nicht einwandfrei. Durch Aufruf
des Befehls mysqld mit den Optionen
--verbose
und --help
können
Sie die Vorgaben für die Pfadeinstellungen ermitteln.
Wenn die Standardpositionen dem MySQL-Installationslayout auf Ihrem System nicht entsprechen, können Sie sie durch Angabe von Optionen für mysqld oder mysqld_safe auf der Befehlszeile oder in einer Optionsdatei außer Kraft setzen.
Um die Position des Datenverzeichnisses explizit anzugeben,
verwenden Sie die Option --datadir
.
Allerdings können Sie mysqld die Position
des Basisverzeichnisses angeben, in dem MySQL installiert ist;
mysqld wird dann in diesem Verzeichnis nach
dem Datenverzeichnis suchen. Die Angabe erfolgt mit der Option
--basedir
.
Um die Auswirkungen der Optionen zur Pfadangabe zu
überprüfen, rufen Sie mysqld mit diesen
Optionen auf, gefolgt von den Optionen
--verbose
und --help
. Wenn
Sie beispielsweise in das Verzeichnis wechseln, in dem
mysqld installiert ist, und dann den
folgenden Befehl ausführen, werden die Auswirkung des
Serverstarts bei einem Basisverzeichnis
/usr/local
angezeigt:
shell> ./mysqld --basedir=/usr/local --verbose --help
Sie können auch andere Optionen wie
--datadir
spezifizieren; beachten Sie aber,
dass --verbose
und --help
jeweils als letzte Optionen aufzuführen sind.
Wenn Sie die gewünschten Pfadeinstellungen ermittelt haben,
starten Sie den Server ohne --verbose
und
--help
.
Wird mysqld gerade ausgeführt, dann können Sie die verwendeten Pfadeinstellungen durch Absetzen des folgenden Befehls ermitteln:
shell> mysqladmin variables
Oder:
shell> mysqladmin -h host_name
variables
host_name
ist der Name des MySQL
Server-Hosts.
Erhalten Sie beim Starten von mysqld die
Fehlermeldung Errcode 13
(Permission denied
, Berechtigung
verweigert), dann gestatten die Berechtigungen des
Datenverzeichnisses oder seiner Inhalte keinen Serverzugriff.
In diesem Fall ändern Sie die Berechtigungen für die
betreffenden Dateien und Verzeichnisse so, dass der Server das
Recht hat, sie zu verwenden. Sie können den Server auch als
root
starten, wovon aus
sicherheitstechnischer Sicht jedoch dringend abgeraten wird.
Wechseln Sie unter Unix in das Datenverzeichnis und
überprüfen Sie die Besitzrechte für das Datenverzeichnis
und seinen Inhalt, um den Serverzugriff zu gewährleisten.
Verwenden Sie etwa folgenden Befehl, wenn das Datenverzeichnis
/usr/local/mysql/var
ist:
shell> ls -la /usr/local/mysql/var
Wenn die Besitzrechte für das Datenverzeichnis oder seine
Unterverzeichnisse nicht bei dem Anmeldekonto liegen, das Sie
zur Ausführung des Servers verwenden, dann müssen Sie die
Besitzrechte für diese Ressourcen dem Konto zuweisen. Heißt
das Konto mysql
, dann verwenden Sie
folgende Befehle:
shell>chown -R mysql /usr/local/mysql/var
shell>chgrp -R mysql /usr/local/mysql/var
Wenn der Server nicht korrekt startet, prüfen Sie das
Fehlerlog. Logdateien befinden sich im Datenverzeichnis (unter
Windows normalerweise C:\Programme\MySQL\MySQL
Server 5.1\data
, bei
Unix-Binärdistributionen in
/usr/local/mysql/data
und bei
Unix-Quelldistributionen in
/usr/local/var
). Suchen Sie im
Datenverzeichnis nach Dateien mit Namen des Typs
und
host_name
.err
,
wobei host_name
.loghost_name
der Name des
Serverhosts ist. Überprüfen Sie nun die letzten paar Zeilen
dieser Dateien. Unter Unix können Sie sie mit
tail
anzeigen:
shell>tail
shell>host_name
.errtail
host_name
.log
Das Fehlerlog sollte Informationen dazu enthalten, warum der Server nicht starten konnte. Beispielsweise könnte das Log etwa Folgendes enthalten:
000729 14:50:10 bdb: Recovery function for LSN 1 27595 failed 000729 14:50:10 bdb: warning: ./test/t1.db: No such file or directory 000729 14:50:10 Can't init databases
Das bedeutet, dass Sie mysqld nicht mit der
Option --bdb-no-recover
gestartet haben;
Berkeley DB hat dann, als es versuchte, Ihre Datenbanken
wiederherzustellen, Ungereimtheiten in Bezug auf die eigenen
Logdateien erkannt. Um fortzufahren, sollten Sie die alten
Berkeley DB-Logdateien aus dem Datenbankverzeichnis an einen
anderen Ort verschieben, wo Sie sie später untersuchen
können. Die BDB
-Logdateien werden in
chronologischer Reihenfolge beginnend mit
log.0000000001
benannt; die Zahl im Namen
wird dabei stets erhöht.
Wenn Sie mysqld mit Unterstützung für
BDB
-Tabellen ausführen und beim Start von
mysqld ein Speicherauszug auftritt, könnte
dies auf Probleme in Verbindung mit dem
BDB
-Wiederherstellungslog hinweisen. In
diesem Fall können Sie versuchen, mysqld
mit der Option --bdb-no-recover
zu starten.
Wenn das klappt, sollten Sie alle
BDB
-Logdateien aus dem Datenverzeichnis
entfernen und dann versuchen, mysqld ohne
die Option --bdb-no-recover
neu zu starten.
Tritt einer der folgenden Fehler auf, dann bedeutet dies, dass ein anderes Programm (vielleicht ein anderer mysqld-Server) den TCP/IP-Port bzw. die Unix-Socketdatei verwendet, die mysqld für sich beansprucht:
Can't start server: Bind on TCP/IP port: Address already in use Can't start server: Bind on unix socket ...
Ermitteln Sie mit dem Befehl ps, ob ein anderer mysqld-Server ausgeführt wird. Ist dies der Fall, dann fahren Sie den Server herunter, bevor Sie mysqld erneut starten. (Wenn ein anderer Server ausgeführt wird und Sie tatsächlich mehrere Server gleichzeitig betreiben wollen, finden Sie Informationen zur Vorgehensweise in Abschnitt 5.13, „Mehrere MySQL-Server auf derselben Maschine laufen lassen“.)
Läuft kein anderer Server, dann führen Sie den Befehl
telnet
aus.
(Die Standardportnummer von MySQL ist 3306.) Betätigen Sie
dann mehrfach die Eingabetaste. Erhalten Sie keine
Fehlermeldung in der Art von your_host_name
tcp_ip_port_number
telnet: Unable to
connect to remote host: Connection refused
, dann
verwendet ein anderes Programm den TCP/IP-Port, den
mysqld nutzen will. Sie müssen dann ermitteln,
welches Programm dies ist, und es deaktivieren; alternativ
können Sie mysqld mit der Option
--port
auch anweisen, an einem anderen Port
zu lauschen. In diesem Fall müssen Sie auch die Portnummer
für Clientprogramme angeben, die über TCP/IP eine Verbindung
mit dem Server herstellen wollen.
Ein anderer Grund, warum kein Zugriff auf den Port möglich ist, könnte eine laufende Firewall sein, die Verbindungen zu diesem Port unterbindet. In diesem Fall müssen Sie die Firewall-Einstellungen so abändern, dass ein Zugriff möglich ist.
Wenn der Server startet, Sie aber keine Verbindung zu ihm
herstellen können, dann sollten Sie sicherstellen, dass ein
Eintrag wie der folgende in /etc/hosts
vorhanden ist:
127.0.0.1 localhost
Dieses Problem tritt nur bei Systemen auf, die über keine funktionierende Thread-Bibliothek verfügen und für die MySQL zur Verwendung von MIT-pthreads konfiguriert sein muss.
Wenn Sie mysqld nicht zum Laufen bringen,
können Sie versuchen, unter Verwendung der Option
--debug
eine Trace-Datei zu erstellen, um das
Problem zu ermitteln. Siehe auch
Abschnitt E.1.2, „Trace-Dateien erzeugen“.
Eine wesentliche Komponente des MySQL-Installationsprozesses ist
die Einrichtung der mysql
-Datenbank, die die
Grant-Tabellen enthält:
Windows-Distributionen enthalten vorinitialisierte Grant-Tabellen, die automatisch installiert werden.
Unter Unix werden die Grant-Tabellen durch das Programm mysql_install_db ausgefüllt. Einige Installationsmethoden führen dieses Programm für Sie aus. Andere wiederum erfordern eine manuelle Ausführung. Detaillierte Informationen finden Sie in Abschnitt 2.9.2, „Schritte nach der Installation unter Unix“.
Die Grant-Tabellen definieren die vorgabeseitigen MySQL-Benutzerkonten und deren Zugriffsberechtigungen. Diese Konten werden wie folgt eingerichtet:
Es werden Konten mit dem Benutzernamen
root
erstellt. Dies sind
Superuser-Konten, die alles dürfen. Anfänglich sind die
Passwörter der root
-Konten leer, d. h.,
jeder kann als root
—
ohne Passwort — eine Verbindung
mit dem MySQL Server herstellen und erhält alle
Berechtigungen.
Unter Windows wird genau ein
root
-Konto erstellt. Dieses erlaubt
nur eine Verbindung über den lokalen Host. Das
Windows-Installationsprogramm erstellt optional ein
Konto, welches Verbindung von beliebigen Hosts
ermöglicht. Dieses Konto wird jedoch nur dann angelegt,
wenn die Option Enable root access from remote
machines während der Installation gewählt
wurde.
Unter Unix sind beide root
-Konten
für Verbindungen vom lokalen Host vorgesehen.
Verbindungen vom lokalen Host müssen unter Angabe von
localhost
für das eine Konto bzw.
des tatsächlichen Hostnamens oder der IP-Nummer für
das andere Konto hergestellt werden.
Es werden zwei Konten für anonyme Benutzer erstellt; bei beiden ist der Benutzername leer. Die anonymen Konten haben kein Passwort, d. h., jeder kann über sie eine Verbindung zum MySQL Server herstellen.
Unter Windows wird ein anonymes Konto für Verbindungen
vom lokalen Host eingerichtet. Es hat ebenso wie die
root
-Konten alle Berechtigungen. Das
andere Konto ist für Verbindungen von beliebigen Hosts
vorgesehen und hat alle Berechtigungen für die
test
-Datenbank und für alle
Datenbanken, deren Name auf test
beginnt.
Unter Unix sind beide anonymen Konten für Verbindungen
vom lokalen Host vorgesehen. Verbindungen vom lokalen
Host müssen unter Angabe von
localhost
für das eine Konto bzw.
des tatsächlichen Hostnamens oder der IP-Nummer für
das andere Konto hergestellt werden. Diese Konten haben
alle Berechtigungen für die Datenbank
test
und für alle Datenbanken, deren
Name mit test_
beginnt.
Wie bereits angemerkt, hat keines der Vorgabekonten ein Passwort. Das bedeutet, dass Ihre MySQL-Installation nicht geschützt ist, bis Sie etwas Entsprechendes unternehmen:
Wenn Sie verhindern wollen, dass Clients sich ohne Angabe eines Passworts als anonyme Benutzer anmelden können, sollten Sie entweder für jedes anonyme Konto ein Passwort einrichten oder die Konten ganz entfernen.
Allen MySQL-root
-Konten sollten Sie
Passwörter zuweisen.
Die folgenden Angaben erläutern, wie Sie Passwörter für die
vorgegebenen MySQL-Konten erstellen – erst für die anonymen
Konten und dann für die root
-Konten.
Ersetzen Sie „ newpwd
“
in den Beispielen durch das Passwort, welches Sie verwenden
wollen. Die Erläuterungen behandeln auch die Frage, wie Sie die
anonymen Konten entfernen können, wenn Sie anonymen Zugriff
überhaupt nicht gestatten wollen.
Sie sollten die Einstellung der Passwörter auf einen späteren Zeitpunkt verschieben, damit Sie sie nicht angeben müssen, wenn Sie weitere Konfigurations- oder Testschritte durchführen. Achten Sie allerdings darauf, sie einzurichten, bevor Sie Ihre Installation für Produktionszwecke einsetzen.
Um Passwörter für anonyme Konten zu konfigurieren, stellen Sie
als root
eine Verbindung zum Server her und
stellen das Passwort entweder mit SET
PASSWORD
ein oder führen eine
UPDATE
-Anweisung aus. In beiden Fällen
müssen Sie das Passwort mit der
PASSWORD()
-Funktion verschlüsseln.
SET PASSWORD
verwenden Sie unter Windows wie
folgt:
shell>mysql -u root
mysql>SET PASSWORD FOR ''@'localhost' = PASSWORD('
mysql>newpwd
');SET PASSWORD FOR ''@'%' = PASSWORD('
newpwd
');
SET PASSWORD
verwenden Sie unter Unix wie
folgt:
shell>mysql -u root
mysql>SET PASSWORD FOR ''@'localhost' = PASSWORD('
mysql>newpwd
');SET PASSWORD FOR ''@'
host_name
' = PASSWORD('newpwd
');
In der zweiten SET PASSWORD
-Anweisung
ersetzen Sie host_name
durch den
Namen des Serverhosts. Es handelt sich dabei um den Namen, den
Sie in der Spalte Host
desjenigen
root
-Datensatzes in der Tabelle
user
angegeben haben, der nicht mit
localhost
verknüpft wird. Wenn Sie diesen
Hostnamen nicht kennen, setzen Sie die folgende Anweisung vor
der Verwendung von SET PASSWORD
ab:
mysql> SELECT Host, User FROM mysql.user;
Suchen Sie nach dem Datensatz, bei dem root
in der Spalte User
und etwas anderes als
localhost
in der Spalte
Host
steht. Verwenden Sie dann diesen
Host
-Wert in der zweiten SET
PASSWORD
-Anweisung.
Die andere Möglichkeit, Passwörter für anonyme Konten
zuzuweisen, ist die Verwendung von UPDATE
zur
direkten Modifizierung der Tabelle user
.
Stellen Sie als root
eine Verbindung zum
Server her und setzen Sie eine
UPDATE
-Anweisung ab, die in der Spalte
Password
der betreffenden Datensätze in der
Tabelle user
einen Wert hinzufügt. Der
Vorgang ist bei Windows und Unix identisch. Die folgende
UPDATE
-Anweisung weist beiden anonymen Konten
gleichzeitig ein Passwort zu:
shell>mysql -u root
mysql>UPDATE mysql.user SET Password = PASSWORD('
->newpwd
')WHERE User = '';
mysql>FLUSH PRIVILEGES;
Wenn Sie die Passwörter in der Tabelle user
mit UPDATE
direkt aktualisieren, müssen Sie
den Server mit FLUSH PRIVILEGES
anweisen, die
Grant-Tabellen neu einzulesen. Andernfalls werden Ihre
Änderungen erst umgesetzt, wenn Sie den Server neu starten.
Wenn Sie die anonymen Konten stattdessen ganz entfernen wollen, gehen Sie wie folgt vor:
shell>mysql -u root
mysql>DELETE FROM mysql.user WHERE User = '';
mysql>FLUSH PRIVILEGES;
Die DELETE
-Anweisung gilt für Windows und
Unix gleichermaßen. Wenn Sie unter Windows nur das anonyme
Konto entfernen wollen, das die gleichen Berechtigungen wie
root
hat, geben Sie stattdessen Folgendes
ein:
shell>mysql -u root
mysql>DELETE FROM mysql.user WHERE Host='localhost' AND User='';
mysql>FLUSH PRIVILEGES;
Dieses Konto gewährt anonymen Zugriff, verfügt aber über Vollzugriff; insofern verbessern Sie die Sicherheit, wenn Sie es entfernen.
Sie können den root
-Konten Passwörter auf
mehreren unterschiedlichen Wegen zuweisen. Im Folgenden wollen
wir drei Methoden demonstrieren:
Verwenden der SET PASSWORD
-Anweisung
Verwenden des befehlszeilenbasierten Clientprogramms mysqladmin
Verwenden der UPDATE
-Anweisung
Um Passwörter mit SET PASSWORD
zuzuweisen,
stellen Sie als root
eine Verbindung zum
Server her und setzen zwei SET
PASSWORD
-Anweisungen ab. Beachten Sie dabei, dass Sie
das Passwort mit der PASSWORD()
-Funktion
verschlüsseln müssen.
Unter Windows geben Sie Folgendes ein:
shell>mysql -u root
mysql>SET PASSWORD FOR 'root'@'localhost' = PASSWORD('
mysql>newpwd
');SET PASSWORD FOR 'root'@'%' = PASSWORD('
newpwd
');
Unter Unix geben Sie Folgendes ein:
shell>mysql -u root
mysql>SET PASSWORD FOR 'root'@'localhost' = PASSWORD('
mysql>newpwd
');SET PASSWORD FOR 'root'@'
host_name
' = PASSWORD('newpwd
');
In der zweiten SET PASSWORD
-Anweisung
ersetzen Sie host_name
durch den
Namen des Serverhosts. Dies ist derselbe Hostname, den Sie bei
der Zuweisung der Passwörter für die anonymen Konten verwendet
haben.
Um für die root
-Konten Passwörter mit
mysqladmin zu konfigurieren, führen Sie
folgende Befehle aus:
shell>mysqladmin -u root password "
shell>newpwd
"mysqladmin -u root -h
host_name
password "newpwd
"
Diese Befehle gelten für Windows und Unix gleichermaßen. Im
zweiten Befehl ersetzen Sie host_name
durch den Namen des Serverhosts. Die doppelten
Anführungszeichen, die das Passwort umgeben, sind nicht immer
erforderlich; Sie sollten sie aber verwenden, wenn das Passwort
Leerzeichen oder andere Zeichen enthält, die Ihr
Befehls-Interpreter als Sonderzeichen interpretiert.
Sie können auch mithilfe von UPDATE
die
Tabelle user
direkt bearbeiten. Die folgende
UPDATE
-Anweisung weist beiden
root
-Konten gleichzeitig ein Passwort zu:
shell>mysql -u root
mysql>UPDATE mysql.user SET Password = PASSWORD('
->newpwd
')WHERE User = 'root';
mysql>FLUSH PRIVILEGES;
Die UPDATE
-Anweisung gilt für Windows und
Unix gleichermaßen.
Nachdem die Passwörter konfiguriert wurden, müssen Sie immer, wenn Sie eine Serververbindung herstellen, das Passwort angeben. Wollen Sie also etwa mysqladmin zum Herunterfahren des Servers verwenden, dann tun Sie das mit folgendem Befehl:
shell>mysqladmin -u root -p shutdown
Enter password:(enter root password here)
Hinweis: Wenn Sie Ihr
root
-Passwort nach der Konfiguration
vergessen haben, finden Sie in
Abschnitt A.4.1, „Wie ein vergessenes Kennwort zurückgesetzt wird“, Informationen
dazu, wie Sie das Passwort zurücksetzen.
Um weitere Konten einzurichten, können Sie die Anweisung
GRANT
verwenden. Informationen zur
Vorgehensweise finden Sie in Abschnitt 5.9.2, „Hinzufügen neuer MySQL-Benutzer“.
Generell empfehlen wir, Upgrades nur von einer Release-Serie zur nächsten durchzuführen und keine Serien auszulassen. Wenn Sie beispielsweise derzeit MySQL 4.0 verwenden und dann auf eine neuere Serie aktualisieren wollen, führen Sie ein Upgrade auf MySQL 4.1 und nicht auf 5.0 oder 5.1 durch.
Die folgende Checkliste sollten Sie immer überprüfen, wenn Sie ein Upgrade durchführen:
Vor der Aktualisierung von MySQL 5.0 auf 5.1 lesen Sie Abschnitt 2.10.1, „Upgrade von MySQL 5.0“, und Anhang D, MySQL-Änderungsverlauf (Change History). Dort finden Sie Informationen zu Funktionen, die bei MySQL 5.1 neu sind oder sich von jenen in MySQL 5.0 unterscheiden. Wenn Sie von einer Release-Serie vor MySQL 5.0 aus ein Upgrade durchführen wollen, sollten Sie nacheinander von Release-Serie zu Release-Serie aktualisieren, bis Sie MySQL 5.0 erreicht haben; danach können Sie auf MySQL 5.1 aktualisieren. Informationen zu Upgrades von MySQL 5.0 finden Sie im MySQL 5.0 Reference Manual. MySQL-Referenzhandbuch für die Versionen 3.23, 4.0 und 4.1 enthält die entsprechenden Angaben zu früheren Releases.
Bevor Sie das Upgrade durchführen, sichern Sie Ihre
Datenbanken einschließlich der
mysql
-Datenbank, die Ihre Grant-Tabellen
enthält.
Einige Releases von MySQL enthalten Änderungen an der Struktur der Grant-Tabellen, damit neue Berechtigungen oder Funktionen hinzugefügt werden können. Wenn Sie ein Upgrade auf eine neue MySQL-Version durchführen, sollten Sie Ihre Grant-Tabellen aktualisieren, damit sichergestellt ist, dass diese auf der aktuellen Struktur basieren und auf diese Weise neue Funktionalitäten nutzen können. Siehe auch Abschnitt 5.6, „mysql_fix_privilege_tables — Upgrade von MySQL-Systemtabellen“.
Wenn Sie MySQL Server unter Windows betreiben, lesen Sie Abschnitt 2.3.15, „Upgrade von MySQL unter Windows“.
Wenn Sie die Replikation nutzen, finden Sie in Abschnitt 6.7, „Upgrade eines Replikationssetups“, weitere Informationen zur Aktualisierung Ihrer Replikationskonfiguration.
Haben Sie zuvor bereits eine MySQL-Max-Distribution installiert, die einen Server namens mysqld-max enthält, und wollen nun auf eine Nicht-Max-Version von MySQL aktualisieren, dann beachten Sie, dass mysqld_safe nach wie vor versucht, den alten Server mysqld-max auszuführen. Wenn Sie ein Upgrade durchführen, sollten Sie den alten mysqld-max-Server manuell entfernen, um sicherzustellen, dass mysqld_safe den neuen Server mysqld ausführt.
Sie können die Format- und Datendateien von MySQL jederzeit
zwischen verschiedenen Versionen derselben Architektur hin- und
herschieben, solange Sie die Release-Serie nicht wechseln. Wenn
Sie den Zeichensatz bei der Ausführung von MySQL ändern, dann
müssen Sie myisamchk -r -q
--set-collation=collation_name
für alle MyISAM
-Tabellen ausführen.
Andernfalls werden Ihre Indizes unter Umständen nicht korrekt
sortiert, weil sich bei einer Änderung des Zeichensatzes auch die
Sortierreihenfolge ändern kann.
Wenn Sie in Bezug auf neue Versionen eher vorsichtig sind, können Sie Ihr vorhandenes mysqld immer umbenennen, bevor Sie eine neue Version installieren. Verwenden Sie beispielsweise MySQL 5.0.13 und wollen auf 5.1.10 aktualisieren, dann benennen Sie Ihren aktuellen Server von mysqld zu mysqld-5.0.13 um. Tut Ihr neuer Server mysqld dann etwas Unerwartetes, dann können Sie ihn einfach herunterfahren und mit Ihrem alten mysqld neu starten.
Wenn Sie nach Durchführung eines Upgrades auf Probleme in
Zusammenhang mit neu kompilierten Clientprogrammen (z. B. die
Fehlermeldung Commands out of sync
) stoßen
oder unerwartete Speicherauszüge auftreten, dann haben Sie bei
der Kompilierung Ihrer Programme wahrscheinlich alte Header- oder
Bibliotheksdateien angegeben. In diesem Fall sollten Sie das Datum
Ihrer Datei mysql.h
und der Bibliothek
libmysqlclient.a
überprüfen, um
sicherzustellen, dass diese der aktuellen MySQL-Distribution
entstammen. Andernfalls müssen Sie Ihre Programme mit den neuen
Headern und Bibliotheken neu kompilieren.
Wenn Probleme in der Art auftreten, dass der neue
mysqld-Server nicht startet oder Sie ohne
Passwort keine Verbindung herstellen können, dann schauen Sie
nach, ob Sie nicht noch eine alte
my.cnf
-Datei von Ihrer vorherigen
Installation verwenden. Diese Überprüfung können Sie mithilfe
der Option --print-defaults
vornehmen (z. B.
mysqld --print-defaults). Wenn dieser Befehl
etwas anderes als den Programmnamen anzeigt, dann beeinträchtigt
eine aktive my.cnf
den Server- oder
Clientbetrieb.
Wenn Sie einen neuen MySQL-Release installieren, bietet es sich
immer an, das Perl-Modul DBD::mysql
neu zu
erstellen und zu installieren. Gleiches gilt auch für die anderen
MySQL-Schnittstellen wie die PHP-Erweiterung
mysql
und das Python-Modul
MySQLdb
.
Wenn Sie von einer 5.0-Installation auf 5.0.10 oder höher aktualisieren, beachten Sie, dass es unumgänglich ist, Ihre Grant-Tabellen zu aktualisieren. Andernfalls wird die Erstellung gespeicherter Prozeduren und Funktionen unter Umständen nicht funktionieren. Die entsprechende Vorgehensweise ist in Abschnitt 5.6, „mysql_fix_privilege_tables — Upgrade von MySQL-Systemtabellen“, beschrieben.
Hinweis: Es ist gängige Praxis, Ihre Daten vor der Installation einer neuen Softwareversion zu sichern. Auch wenn MySQL mit Eifer daran arbeitet, ein möglichst hohes Qualitätsniveau zu erzielen, sollten Sie Ihre Daten immer schützen, indem Sie eine Sicherungskopie erstellen. MySQL empfiehlt in der Regel, dass Sie Ihre Tabellen aus vorherigen Versionen speichern und dann neu laden, um auf 5.1 zu aktualisieren.
Generell sollten Sie beim Upgrade von MySQL 5.0 auf 5.1 Folgendes tun:
Überprüfen Sie die Einträge in den weiter unten in diesem Abschnitt vorhandenen Änderungslisten darauf, ob Ihre Anwendungen hierdurch auf irgendeine Weise betroffen sein könnten. Achten Sie dabei insbesondere auf solche Änderungen, die mit dem Vermerk Inkompatible Änderung versehen sind. Diese führen zu Inkompatibilitäten mit früheren MySQL-Versionen und können Ihre Aufmerksamkeit bereits vor Durchführung des Upgrades erfordern.
Lesen Sie die Änderungshistorie von MySQL 5.1 im Hinblick auf die wesentlichen neuen Funktionen, die Sie in Version 5.1 verwenden können. Siehe auch Abschnitt D.1, „Änderungen in Release 5.1.x (Entwicklung)“.
Wenn Sie MySQL Server unter Windows betreiben, lesen Sie Abschnitt 2.3.15, „Upgrade von MySQL unter Windows“.
Wenn Sie die Replikation nutzen, finden Sie in Abschnitt 6.7, „Upgrade eines Replikationssetups“, weitere Informationen zur Aktualisierung Ihrer Replikationskonfiguration.
Die nachfolgenden Listen beschreiben Änderungen, die unter Umständen Anwendungen betreffen können und die Sie beachten sollten, wenn Sie auf Version 5.1 aktualisieren.
Änderungen beim Server:
Inkompatible Änderung:
MySQL 5.1 implementiert die Unterstützung
einer sehr flexiblen Plug-In-API, die das Laden und Entladen
verschiedener Komponenten während der Laufzeit gestattet,
ohne dass der Server neu gestartet werden müsste. Siehe
auch Abschnitt 26.2, „Die MySQL-Plug-In-Schnittstelle“. Die Plug-In-API benötigt
die Tabelle mysql.plugin
. Wenn Sie von
einer älteren MySQL-Version aktualisieren, sollten Sie den
Befehl mysql_fix_privilege_tables
ausführen, um diese Tabelle zu erstellen. Siehe auch
Abschnitt 5.6, „mysql_fix_privilege_tables — Upgrade von MySQL-Systemtabellen“.
Plug-Ins werden in das Verzeichnis installiert, welches in
der Systemvariablen plugin_dir
spezifiziert ist. Diese Variable steuert auch die Position,
von der der Server benutzerdefinierte Funktionen
(User-Defined Functions, UDFs) lädt; dies stellt eine
Änderung zu früheren Versionen von MySQL dar. Mithin
müssen alle UDF-Bibliotheksdateien von jetzt an in das
Plug-In-Verzeichnis installiert werden. Wenn Sie von einer
älteren MySQL-Version aktualisieren, müssen Sie Ihre
UDF-Dateien in das Plug-In-Verzeichnis migrieren.
Die Systemvariable table_cache
wurde
umbenannt in table_open_cache
. Skripten,
die table_cache
verwenden, sollten so
angepasst werden, dass sie den neuen Namen benutzen.
Inkompatible Änderung: Die
Struktur der FULLTEXT
-Indizes wurde in
MySQL 5.1.6 geändert. Nach der Aktualisierung auf MySQL
5.1.6 oder höher müssen Sie die REPAIR
TABLE
-Anweisung für jede Tabelle aufrufen, die
FULLTEXT
-Indizes enthält.
SQL-Änderungen
Inkompatible Änderung: Der
Namespace für Trigger wurde in MySQL 5.0.10 geändert.
Vorher mussten Trigger-Namen je Tabelle eindeutig sein. Nun
muss eine Eindeutigkeit innerhalb des Schemas (Datenbank)
gegeben sein. Eine Auswirkung dieser Änderung besteht
darin, dass die Syntax DROP TRIGGER
nun
statt eines Tabellennamens einen Schemanamen verwendet
(wobei dieser Schemaname optional ist; wird er weggelassen,
dann wird das aktuelle Schema verwendet).
Wenn Sie von einer vorherigen Version von MySQL 5 auf MySQL
5.0.10 oder höher aktualisieren, müssen Sie alle Trigger
löschen und sie neu erstellen; andernfalls wird
DROP TRIGGER
nach dem Upgrade nicht
funktionieren. Gehen Sie am besten wie folgt vor:
Aktualisieren Sie auf MySQL 5.0.10 oder höher, um auf
die Trigger-Daten in der Tabelle
INFORMATION_SCHEMA.TRIGGERS
zugreifen
zu können. (Dies sollte auch für Trigger aus Versionen
vor 5.0.10 funktionieren.)
Speichern Sie alle Trigger-Definitionen mithilfe der
folgenden SELECT
-Anweisung:
SELECT CONCAT('CREATE TRIGGER ', t.TRIGGER_SCHEMA, '.', t.TRIGGER_NAME, ' ', t.ACTION_TIMING, ' ', t.EVENT_MANIPULATION, ' ON ', t.EVENT_OBJECT_SCHEMA, '.', t.EVENT_OBJECT_TABLE, ' FOR EACH ROW ', t.ACTION_STATEMENT, '//' ) INTO OUTFILE '/tmp/triggers.sql' FROM INFORMATION_SCHEMA.TRIGGERS AS t;
Die Anweisung verwendet INTO OUTFILE
,
d. h., Sie müssen die Berechtigung
FILE
haben. Die Datei wird auf dem
Serverhost erstellt; wenn Sie wollen, können Sie einen
anderen Dateinamen verwenden. Um hundertprozentig sicher
zu sein, überprüfen Sie die Trigger-Definitionen in
der Datei triggers.sql
und fertigen
unter Umständen eine Sicherung der Datei an.
Beenden Sie den Server und löschen Sie alle Trigger,
indem Sie sämtliche .TRG
-Dateien
in Ihren Datenbankverzeichnissen entfernen. Wechseln Sie
dann in Ihr Datenverzeichnis und setzen Sie folgenden
Befehl ab:
shell> rm */*.TRG
Starten Sie den Server und erstellen Sie alle Trigger
mithilfe der triggers.sql
-Datei
neu: In meinem Fall sah dies beispielsweise so aus:
mysql>delimiter // ;
mysql>source /tmp/triggers.sql //
Vergewissern Sie sich, dass alle Trigger mit der
SHOW TRIGGERS
-Anweisung erfolgreich
erstellt wurden.
Inkompatible Änderung:
MySQL 5.1.6 hat die Berechtigung TRIGGER
neu eingeführt. Zuvor benötigte man die Berechtigung
SUPER
zum Erstellen oder Löschen von
Triggern. Jetzt ist für derartige Vorgänge die
Berechtigung TRIGGER
erforderlich. Dies
ist eine Sicherheitsoptimierung, da Sie Benutzern nun nicht
länger die Berechtigung SUPER
gewähren
müssen, damit diese Trigger erstellen können. Allerdings
wurde die Anforderung, dass das Konto, welches in der
DEFINER
-Klausel eines Triggers genannt
wird, die Berechtigung SUPER
haben muss,
dadurch ersetzt, dass das Konto nun die Berechtigung
TRIGGER
erfordert. Wenn Sie von einer
früheren MySQL 5-Version auf MySQL 5.1.6 oder höher
aktualisieren, sollten Sie überprüfen, welche Konten in
der DEFINER
-Klausel vorhandener Trigger
aufgeführt sind, und sicherstellen, dass diese Konten die
Berechtigung TRIGGER
haben. Andernfalls
werden sie bei Aktivierung fehlschlagen. Mit der folgenden
Anweisung können Sie ermitteln, welche Konten in den
DEFINER
-Klauseln aufgeführt sind:
SELECT DISTINCT DEFINER FROM INFORMATION_SCHEMA.TRIGGERS;
Wenn Sie diesen Konten die Berechtigung
TRIGGER
gewährt haben, können Sie die
Berechtigung SUPER
für diejenigen Konten
widerrufen, die Sie nicht anderweitig benötigen.
Einige Schlüsselwörter sind in MySQL 5.1 reserviert, bei denen dies in MySQL 5.0 nicht der Fall war. Siehe auch Abschnitt 9.5, „Ist MySQL pingelig hinsichtlich reservierter Wörter?“.
Die Anweisungen INSTALL PLUGIN
und
UNINSTALL PLUGIN
, die für die
Plug-In-API verwendet werden, sind neu. Gleiches gilt für
die Klausel WITH PARSER
der
FULLTEXT
-Indexerstellung, die ein
Parser-Plug-In mit einem Volltextindex verknüpft.
Abschnitt 26.2, „Die MySQL-Plug-In-Schnittstelle“.
Sie können die .frm
-,
.MYI
- und .MYD
-Dateien
für MyISAM
-Tabellen zwischen verschiedenen
Architekturen kopieren, die dasselbe Fließkommaformat
unterstützen. (MySQL sorgt automatisch für das erforderliche
Austauschen von Bytes.) Siehe auch
Abschnitt 14.1, „Die MyISAM
-Speicher-Engine“.
In Fällen, in denen Sie Datenbanken zwischen verschiedenen Architekturen transferieren müssen, können Sie mit mysqldump eine Datei mit SQL-Anweisungen erstellen. Danach übertragen Sie die Datei auf das andere System und verwenden es dort als Eingabe für den mysql-Client.
Mit mysqldump --help erfahren Sie, welche Optionen vorhanden sind. Wenn Sie die Daten auf eine neuere Version von MySQL verschieben, sollten Sie mysqldump --opt verwenden, denn so profitieren Sie von allen Optimierungen, die zu einer kleineren Speicherdatei führen, welche sich auch schneller verarbeiten lässt.
Die einfachste (wenn auch nicht schnellste) Möglichkeit, eine Datenbank zwischen zwei Computern zu verschieben, besteht darin, die folgenden Befehle auf dem Rechner auszuführen, auf dem die Datenbank sich befindet:
shell>mysqladmin -h '
shell>other_hostname
' createdb_name
mysqldump --opt
db_name
| mysql -h 'other_hostname
'db_name
Wollen Sie eine Datenbank von einem entfernten Computer über ein langsames Netzwerk kopieren, dann können Sie die folgenden Befehle verwenden:
shell>mysqladmin create
shell>db_name
mysqldump -h '
other_hostname
' --opt --compressdb_name
| mysqldb_name
Sie können die Daten auch in einer Datei ablegen, diese auf den Zielcomputer übertragen und dann dort in die Datenbank einladen. So können Sie etwa eine Datenbank wie folgt in einer komprimierten Datei auf dem Quellcomputer speichern:
shell> mysqldump --quick db_name
| gzip > db_name
.gz
Übertragen Sie die Datei mit den Datenbankinhalten auf den Zielcomputer und führen Sie dort folgende Befehle aus:
shell>mysqladmin create
shell>db_name
gunzip <
db_name
.gz | mysqldb_name
Sie können auch mysqldump und
mysqlimport zur Übertragung der Datenbank
verwenden. Bei großen Tabellen ist das wesentlich schneller als
die einfache Verwendung von mysqldump. Bei
den folgenden Befehlen steht DUMPDIR
für den vollständigen Pfadnamen des Verzeichnisses, in dem Sie
die Ausgabe von mysqldump speichern.
Zunächst erstellen Sie das Verzeichnis für die Ausgabedateien und speichern dann die Datenbank:
shell>mkdir
shell>DUMPDIR
mysqldump --tab=
DUMPDIR
db_name
Danach übertragen Sie die Dateien im Verzeichnis
DUMPDIR
in das entsprechende
Verzeichnis auf dem Zielcomputer und laden die Dateien dann dort
in MySQL ein:
shell>mysqladmin create
shell>db_name
# create databasecat
shell>DUMPDIR
/*.sql | mysqldb_name
# create tables in databasemysqlimport
db_name
DUMPDIR
/*.txt # load data into tables
Vergessen Sie nicht, die mysql
-Datenbank zu
kopieren, da darin die Grant-Tabellen gespeichert sind. Unter
Umständen müssen Sie die Befehle auf dem neuen Computer als
MySQL-root
-Benutzer ausführen, bis Ihre
mysql
-Datenbank vor Ort ist.
Nachdem Sie die mysql
-Datenbank auf dem neuen
System importiert haben, führen Sie mysqladmin
flush-privileges aus, damit der Server die
Grant-Tabelle-Daten neu lädt.
Dieser Abschnitt erläutert, was Sie tun sollten, um in dem unwahrscheinlichen Fall, dass eine ältere MySQL-Version besser funktionierte als eine neue Version, ein Downgrade durchzuführen.
Führen Sie das Downgrade innerhalb derselben Release-Serie durch (z. B. von 5.0.13 auf 5.0.12), dann müssen Sie in der Regel nur die neuen Binärdateien über die alten installieren. Mit den Datenbanken müssen Sie nichts machen. Allerdings empfiehlt es sich wie immer auch hier, ein Backup zu erstellen.
Die folgende Checkliste sollten Sie immer überprüfen, wenn Sie ein Downgrade durchführen:
Lesen Sie den Abschnitt zur Aktualisierung auf die Release-Serie, von der aus Sie das Downgrade durchführen, um sicherzustellen, dass diese nicht bestimmte Funktionen enthält, die Sie doch benötigen. Siehe Abschnitt 2.10, „MySQL aktualisieren (Upgrade/Downgrade)“.
Wenn für die betreffende Version ein Abschnitt zum Downgrade vorhanden ist, sollten Sie diesen ebenfalls sorgfältig lesen.
In den meisten Fällen können Sie die Format- und Datendateien von MySQL zwischen verschiedenen Versionen derselben Architektur hin- und herschieben, solange Sie die Release-Serie nicht wechseln.
Wenn Sie das Downgrade von einer Release-Serie auf eine andere
durchführen, kann es bei den Speicherformaten der Tabellen zu
Inkompatibilitäten kommen. In diesem Fall können Sie Ihre
Tabellen vor dem Downgrade mithilfe von
mysqldump speichern. Laden Sie nach Abschluss
des Downgrades die Speicherauszugsdatei mit
mysql oder mysqlimport
, um
die Tabellen neu zu erstellen. Beispiele finden Sie in
Abschnitt 2.10.2, „Upgrade auf eine andere Architektur“.
Das offensichtlichste Symptom bei Downgrade-Inkompatibilitäten des Tabellenformats besteht darin, dass Sie Tabellen nicht öffnen können. Gehen Sie in diesem Fall wie folgt vor:
Beenden Sie den älteren MySQL Server, auf den Sie das Downgrade durchführen.
Starten Sie den neueren MySQL Server, von dem aus Sie das Downgrade durchführen.
Speichern Sie alle Tabellen, auf die der ältere Server nicht zugreifen konnte, mithilfe von mysqldump, um eine Speicherauszugsdatei zu erstellen.
Beenden Sie den neueren MySQL Server und starten Sie den älteren neu.
Laden Sie die Speicherauszugsdatei in den älteren Server. Nun sollten Sie auf Ihre Tabellen zugreifen können.
Dieser Abschnitt beschreibt Probleme, die unter Linux aufgetreten sind. Die ersten Teilabschnitte schildern dabei betriebssystemspezifische Probleme allgemeiner Art, Probleme in Bezug auf die Verwendung von Binär- oder Quelldistributionen und Probleme nach Abschluss der Installation. Im Weiteren werden Probleme erläutert, die unter Linux auf bestimmten Plattformen auftreten.
Beachten Sie, dass die meisten dieser Probleme unter älteren Linux-Versionen auftreten. Wenn Sie eine neuere Version verwenden, werden Sie wahrscheinlich gar nichts bemerken.
MySQL setzt die Linux-Version 2.0 oder höher voraus.
Warnung: Auf SMP-Systemen sind merkwürdige Probleme bei der Kombination Linux 2.2.14 und MySQL aufgetreten. Ferner haben uns einige MySQL-Benutzer mitgeteilt, dass sie schwerwiegende Stabilitätsprobleme bei der Verwendung von MySQL mit dem Kernel 2.2.14 hatten. Wenn Sie diesen Kernel verwenden, sollten Sie auf die Kernel-Version 2.2.19 (oder höher) oder auf Version 2.4 aktualisieren. Bei Multiprozessorsystemen sollten Sie die Verwendung der Kernel-Version 2.4 in jedem Fall in Betracht ziehen, da Sie dadurch einen erheblichen Geschwindigkeitszuwachs erfahren werden. Außerdem wird sich so die Stabilität Ihres Systems erhöhen.
Wenn Sie LinuxThreads verwenden, sollten mindestens drei laufende mysqld-Prozesse angezeigt werden. Das sind tatsächlich Threads. Ein Thread ist für den LinuxThreads-Manager, ein weiterer zur Verwaltung der Verbindungen und der dritte zur Verwaltung von Alarmmeldungen und Signalen.
Die MySQL-Binär- und -RPM-Releases für die Linux-Intel-Kombination sind für optimale Geschwindigkeit konfiguriert. Wir versuchen immer, den schnellsten stabilen Compiler zu finden, der verfügbar ist.
Der Binär-Release wird mit -static
verknüpft, d. h., Sie müssen sich in der Regel keine
Gedanken darüber machen, welche Version der
Systembibliotheken Sie haben. Sie müssen auch LinuxThreads
nicht installieren. Ein mit -static
verknüpftes Programm ist ein wenig größer als ein dynamisch
verknüpftes Programm, aber auch ein bisschen schneller (ca. 3
bis 5 Prozent). Allerdings besteht ein Problem bei statisch
verknüpften Programmen darin, dass Sie keine UDFs
(User-Defined Functions, benutzerdefinierte Funktionen)
verwenden können. Wenn Sie UDFs schreiben oder verwenden
wollen (dies ist nur etwas für C- oder C++-Programmierer),
dann müssen Sie MySQL selbst mit dynamischer Verknüpfung
kompilieren.
Ein bekanntes Problem bei Binärdistributionen besteht darin,
dass auf älteren Linux-Systemen, die libc
verwenden (also z. B. Red Hat 4.x oder Slackware),
gelegentlich Schwierigkeiten in Verbindung mit der Auflösung
der Hostnamen auftreten (diese sind jedoch nicht
schwerwiegend). Verwendet Ihr System libc
statt glibc2
, dann werden Sie
wahrscheinlich Probleme in Verbindung mit der
Hostnamensauflösung und getpwnam()
haben.
Diese treten auf, weil glibc
(leider) auf
einige externe Bibliotheken angewiesen ist, um die
Namensauflösung und getpwent()
implementieren zu können – und zwar auch dann, wenn mit der
Option -static
kompiliert wurde. Diese
Probleme äußern sich auf zweierlei Weise:
Bei der Ausführung von mysql_install_db erhalten Sie die folgende Fehlermeldung:
Sorry, the host 'xxxx
' could not be looked up
Sie können dieses Problem beheben, indem Sie
mysql_install_db --force ausführen,
was dazu führt, dass der Test
resolveip in
mysql_install_db nicht ausgeführt
wird. Der Nachteil besteht darin, dass Sie Hostnamen nicht
in Grant-Tabellen verwenden können; mit Ausnahme von
localhost
müssen Sie dann immer die
entsprechenden IP-Adressen angeben. Wenn Sie eine alte
MySQL-Version verwenden, die --force
nicht unterstützt, dann müssen Sie den Test
resolveip
in
mysql_install
manuell mit einem
Texteditor entfernen.
Unter Umständen erhalten Sie auch die folgende
Fehlermeldung, wenn Sie versuchen,
mysqld mit der Option
--user
auszuführen:
getpwnam: No such file or directory
Um dieses Problem zu umgehen, starten Sie
mysqld mit dem Befehl
su
statt durch Angabe der Option
--user
. Auf diese Weise ändert das
System die Benutzerkennung des
mysqld-Prozesses selbst, d. h.
mysqld muss dies nicht erledigen.
Eine andere Lösung, die beide Probleme behebt, besteht darin,
keine Binärdistribution zu verwenden. Beschaffen Sie sich
eine MySQL-Quelldistribution (im RPM- oder
tar.gz
-Format) und installieren Sie diese
stattdessen.
Bei manchen Linux 2.2-Versionen erhalten Sie unter Umständen
die Fehlermeldung Resource temporarily
unavailable
, wenn Clients über TCP/IP sehr schnell
viele neue Verbindungen mit einem
mysqld-Server herstellen. Das Problem
besteht darin, dass bei Linux zwischen dem Moment, zu dem ein
TCP/IP-Socket von Ihnen geschlossen wird, und dem Zeitpunkt
der tatsächlichen Freigabe des Sockets eine Verzögerung
auftritt. Es ist nur für eine endliche Anzahl von
TCP/IP-Slots Platz vorhanden; deswegen sind zu wenig
Ressourcen vorhanden, wenn Clients innerhalb kurzer Zeit zu
viele neue TCP/IP-Verbindungen anfordern. Beispielsweise tritt
dieser Fehler auf, wenn Sie den MySQL-Benchmark
test-connect
über TCP/IP ausführen.
Wir haben dieses Problem einige Male auf verschiedenen Linux-Mailinglisten beschrieben, konnten aber niemals eine geeignete Lösung finden. Der einzige bekannte „Fix“ besteht darin, dass Clients Permanentverbindungen verwenden oder Sie, wenn Sie den Datenbankserver und die Clients auf demselben Rechner ausführen, Verbindungen via Unix-Socketdatei statt TCP/IP-Verbindungen einsetzen.
Die folgenden Anmerkungen zu glibc
betreffen Sie nur, wenn Sie MySQL selbst erstellen. Wenn Sie
Linux auf einem x86-Computer ausführen, sollten Sie in den
meisten Fällen besser unsere Binärdistribution verwenden.
Wir verknüpfen unsere Binärdateien zur jeweils am besten
gepatchten Version von glibc
, die wir
finden können, und mit den bestmöglichen
Compiler-Einstellungen, um sie so für hochbeanspruchte Server
zu optimieren. Für normale Benutzer ist unsere
Binärdistribution auch in Setups mit vielen gleichzeitigen
Verbindungen oder Tabellen, die die 2-Gbyte-Grenze sprengen,
in den meisten Fällen erste Wahl. Wenn Sie nach der Lektüre
des folgenden Texts nicht genau wissen, wie Sie vorgehen
sollen, probieren Sie zunächst unsere Binärdatei aus, um zu
ermitteln, ob diese für Ihre Anforderungen geeignet ist.
Sollten Sie feststellen, dass dies nicht der Fall ist, dann
sollten Sie eine selbsterstellte Version erproben. In diesem
Fall würden wir uns freuen, wenn Sie uns dies mitteilen
würden, damit wir beim nächsten Mal eine bessere
Binärdistribution erstellen können.
MySQL verwendet LinuxThreads unter Linux. Wenn Sie eine alte
Linux-Version verwenden, die glibc2
nicht
enthält, dann müssen Sie LinuxThreads installieren, bevor
Sie MySQL zu kompilieren versuchen. Sie bekommen LinuxThreads
unter
http://dev.mysql.com/downloads/os-linux.html.
Beachten Sie, dass glibc
-Versionen bis
einschließlich 2.1.1 beim Umgang mit
pthread_mutex_timedwait()
, welches beim
Absetzen von INSERT DELAYED
-Anweisungen
verwendet wird, einen schweren Bug aufweisen. Wir empfehlen
Ihnen, INSERT DELAYED
erst nach der
Aktualisierung von glibc
zu verwenden.
Beachten Sie, dass der Linux-Kernel und die LinuxThread-Bibliothek standardmäßig maximal 1024 Threads verwalten können. Wenn Sie mehr als 1000 gleichzeitige Verbindungen vorsehen, dann müssen Sie wie folgt ein paar Änderungen an LinuxThreads vornehmen:
Erhöhen Sie den Wert
PTHREAD_THREADS_MAX
in
sysdeps/unix/sysv/linux/bits/local_lim.h
auf 4096 und verringern Sie STACK_SIZE
in linuxthreads/internals.h
auf 256
Kbyte. Die Pfade sind relativ zum Stammverzeichnis von
glibc
. (Beachten Sie, dass MySQL bei
600 bis 1000 Verbindungen nicht stabil läuft, wenn
STACK_SIZE
auf der Vorgabe von 2 Mbyte
belassen wird.)
Kompilieren Sie LinuxThreads erneut, um eine neue
libpthread.a
-Bibliothek zu erzeugen,
und verknüpfen Sie MySQL dann wieder damit.
Weitere Informationen dazu, wie Sie Thread-Beschränkungen in LinuxThreads umgehen, finden Sie unter http://www.volano.com/linuxnotes.html.
Es gibt noch ein weiteres Problem, dass die Performance von
MySQL insbesondere auf SMP-Systemen erheblich beeinträchtigt.
glibc
2.1 weist eine sehr schwache
Mutex-Implementierung in LinuxThreads für Programme mit
vielen Threads auf, die das Mutex nur für eine kurze Zeit
halten. Die Folgen sind paradox: Wenn Sie MySQL mit einer
nicht modifizierten LinuxThreads-Version verbinden, können
Sie die Leistungsfähigkeit von MySQL in vielen Fällen
verbessern, indem Sie Prozessoren aus dem SMP entfernen! Wir
haben für glibc
2.1.3 unter
http://dev.mysql.com/Downloads/Linux/linuxthreads-2.1-patch
einen Patch bereitgestellt, um dieses Verhalten zu
korrigieren.
Bei glibc
2.2.2 verwendet MySQL das
adaptive Mutex, welches wesentlich besser ist als bei
glibc
2.1.3 (auch in der gepatchten
Version). Wir wollen aber darauf hinweisen, dass der aktuelle
Mutex-Code in glibc
2.2.2 gelegentlich zu
viel des Guten tut, wodurch die MySQL-Performance wieder
beeinträchtigt wird. Die Wahrscheinlichkeit, dass ein solches
Verhalten auftritt, kann dadurch verringert werden, dass man
dem Prozess mysqld die höchste Priorität
zuweist. Wir konnten das Problem zudem ebenfalls mit einem
Patch beheben, den Sie unter
http://dev.mysql.com/Downloads/Linux/linuxthreads-2.2.2.patch
finden. Dieser Patch korrigiert alle drei hier beschriebenen
Probleme: das STACK_SIZE
-Problem, das
Problem der Thread-Beschränkung und das Mutex-Problem. Er
muss im Verzeichnis linuxthreads
mit
patch -p0 </tmp/linuxthreads-2.2.2.patch
angewendet werden. Wir hoffen, dass er in irgendeiner Form in
zukünftigen Releases von glibc
2.2
enthalten sein wird. In jedem Fall müssen Sie bei der
Verknüpfung mit glibc
2.2.2
STACK_SIZE
und
PTHREAD_THREADS_MAX
korrigieren. Wir
hoffen, dass die Standardeinstellungen in Zukunft auf Werte
korrigiert werden, die für hochbeanspruchte MySQL Server
geeigneter sind; in diesem Fall ließen sich die Befehle zur
Erstellung eines eigenen Builds auf ./configure;
make; make install beschränken.
Wir empfehlen Ihnen, diese Patches zur Erstellung einer
speziellen statischen Version von
libpthread.a
zu verwenden und diese dann
nur für die statische Verknüpfung mit MySQL zu verwenden.
Wir wissen, dass diese Patches in Verbindung mit MySQL
einwandfrei funktionieren und die Leistungsfähigkeit
erheblich verbessern, können jedoch nichts zu ihren
Auswirkungen auf andere Anwendungen sagen. Wenn Sie andere
Anwendungen verknüpfen, die LinuxThreads mit einer anderen
als der gepatchten statischen Version der Bibliothek
benötigen, oder eine gepatchte gemeinsame Version erstellen
und diese auf Ihrem System installieren, dann tun Sie dies auf
eigenes Risiko.
Sollten während der Installation von MySQL merkwürdige Probleme auftreten oder bestimmte gängige Hilfsprogramme stehen bleiben, dann ist dies mit hoher Wahrscheinlichkeit durch die Bibliothek oder den Compiler verursacht. Wenn dies der Fall ist, dann können Sie diese Probleme mithilfe unserer Binärdistribution lösen.
Wenn Sie eigene MySQL-Clientprogramme verknüpfen, dann wird unter Umständen die folgende Fehlermeldung zur Laufzeit angezeigt:
ld.so.1: fatal: libmysqlclient.so.#: open failed: No such file or directory
Dieses Problem lässt sich auf eine der folgenden Weisen lösen:
Wenn Sie den Fujitsu-Compiler (fcc/FCC
)
verwenden, treten unter Umständen Probleme bei der
Kompilierung von MySQL auf, weil die Linux-Header-Dateien sehr
stark auf gcc ausgerichtet sind. Der
folgende configure-Befehl sollte auch für
fcc/FCC funktionieren:
CC=fcc CFLAGS="-O -K fast -K lib -K omitfp -Kpreex -D_GNU_SOURCE \ -DCONST=const -DNO_STRTOLL_PROTO" \ CXX=FCC CXXFLAGS="-O -K fast -K lib \ -K omitfp -K preex --no_exceptions --no_rtti -D_GNU_SOURCE \ -DCONST=const -Dalloca=__builtin_alloca -DNO_STRTOLL_PROTO \ '-D_EXTERN_INLINE=static __inline'" \ ./configure \ --prefix=/usr/local/mysql --enable-assembler \ --with-mysqld-ldflags=-all-static --disable-shared \ --with-low-memory
mysql.server finden Sie im Verzeichnis
support-files
, das sich im
MySQL-Installationsverzeichnis befindet, oder in einem
MySQL-Source-Tree. Sie können es als
/etc/init.d/mysql
installieren, um MySQL
automatisch zu starten und zu beenden. Siehe auch
Abschnitt 2.9.2.2, „MySQL automatisch starten und anhalten“.
Wenn MySQL nicht genügend Dateien oder Verbindungen öffnen kann, haben Sie Linux möglicherweise nicht so konfiguriert, dass es genug Dateien verwalten kann.
Unter Linux 2.2 und höher können Sie die Anzahl zugewiesener Datei-Handles wie folgt überprüfen:
shell>cat /proc/sys/fs/file-max
shell>cat /proc/sys/fs/dquot-max
shell>cat /proc/sys/fs/super-max
Wenn Sie mehr als 16 Mbyte Speicher haben, sollten Sie Ihre
Skripten durch einen Zusatz in der Art des folgenden ergänzen
(z. B. /etc/init.d/boot.local
unter SuSE
Linux):
echo 65536 > /proc/sys/fs/file-max echo 8192 > /proc/sys/fs/dquot-max echo 1024 > /proc/sys/fs/super-max
Sie können die echo
-Befehle auf der
Befehlszeile auch als root
ausführen, aber
diese Einstellungen gehen beim nächsten Neustart Ihres
Computers verloren.
Alternativ stellen Sie diese Parameter für den Start mithilfe
des Tools sysctl
ein, welches von vielen
Linux-Distributionen (einschließlich SuSE Linux 8.0 und
höher) verwendet wird. Tragen Sie die folgenden Werte in eine
Datei namens /etc/sysctl.conf
ein:
# Increase some values for MySQL fs.file-max = 65536 fs.dquot-max = 8192 fs.super-max = 1024
Außerdem sollten Sie Folgendes in
/etc/my.cnf
ergänzen:
[mysqld_safe] open-files-limit=8192
Auf diese Weise konfigurieren Sie für den Server eine Gesamtbeschränkung der Verbindungen und offenen Dateien auf 8192.
Die Konstante STACK_SIZE
in LinuxThreads
steuert das Spacing von Thread-Stapeln im Adressraum. Dieses
muss groß genug sein, um genügend Raum für jeden einzelnen
Thread-Stapel bereitzustellen, aber auch klein genug, um zu
verhindern, dass der Stapel bestimmter Threads mit den
globalen mysqld-Daten kollidiert. Leider
trennt, wie wir durch Experimentieren festgestellt haben, die
Linux-Implementierung von mmap()
einen
bereits zugeordneten Bereich wieder auf, wenn Sie sie
anweisen, die Zuordnung einer derzeit verwendeten Adresse
aufzulösen: Es wird kein Fehler zurückgegeben, sondern alle
Daten auf der gesamten Seite werden auf null gesetzt. Insofern
hängt die Sicherheit von mysqld und allen
anderen Thread-basierten Anwendungen vom
„wohlwollenden“ Verhalten des Codes ab, der die
Threads erstellt. Der Benutzer muss Maßnahmen ergreifen, um
sicherzustellen, dass die Anzahl laufender Threads jederzeit
so niedrig ist, dass es nicht zum Konflikt zwischen den
Thread-Stapeln und dem globalen Bereich kommt. Bei
mysqld sollten Sie dieses Verhalten
erzwingen, indem Sie der Variablen
max_connections
einen sinnvollen Wert
zuweisen.
Wenn Sie MySQL selbst erstellen, können Sie LinuxThreads für
eine bessere Stapelnutzung patchen. Siehe auch
Abschnitt 2.12.1.3, „Anmerkungen zur Linux-Quelldistribution“. Wenn Sie
LinuxThreads aber nicht patchen wollen, sollten Sie
max_connections
auf einen Wert von maximal
500 setzen. Arbeiten Sie mit einem großen Schlüsselpuffer,
großen Heap-Tabellen oder anderen Materialien, die zu einer
umfassenden Speicherzuweisung durch mysqld
führen, oder verwenden Sie die Kernel-Version 2.2 mit einem
2-Gbyte-Patch, dann sollte der Wert noch kleiner sein. Wenn
Sie unsere Binär- oder RPM-Version verwenden, können Sie
max_connections
beruhigt auf 1500 setzen,
sofern Sie weder große Schlüsselpuffer noch datenintensive
Heap-Tabellen benutzen. Je stärker Sie
STACK_SIZE
in LinuxThreads verringern,
desto mehr Threads können Sie gefahrlos erstellen. Wir
empfehlen Werte zwischen 128 und 256 Kbyte.
Wenn Sie zahlreiche nebenläufige Verbindungen verwenden, können Sie einem „Feature“ im Kernel 2.2 zum Opfer fallen, das Fork-Bomb-Angriffe verhindern soll, indem Prozesse, die untergeordnete Prozesse aufspalten oder klonen, eine Strafe erhalten. Hierdurch wird die Skalierbarkeit zunehmend beeinträchtigt, je größer die Anzahl nebenläufiger Clients ist. Auf Systemen mit nur einem Prozessor manifestiert sich dies unseren Beobachtungen zufolge in einer sehr langsamen Thread-Erstellung: Die Verbindungsherstellung mit MySQL kann sehr lange (bis zu einer Minute) dauern; Gleiches gilt für das Abbauen der Verbindung. Auf Multiprozessorsystemen haben wir bei steigender Clientanzahl eine allmähliche Abnahme der Abfragegeschwindigkeit feststellen können. Im Zuge der Lösung dieses Problems haben wir von einem unserer Benutzer einen Kernel-Patch erhalten, der seinen Angaben zufolge auf seiner Site geholfen haben soll. Dieser Patch ist unter http://dev.mysql.com/Downloads/Patches/linux-fork.patch verfügbar. Wir haben den Patch sowohl in Entwicklungs- als auch in Produktionssystemen umfassend getestet und festgestellt, dass sich die MySQL-Performance hierdurch erheblich verbessert, ohne dass es zu Problemen kommt. Deswegen empfehlen wir Benutzern, die hochbeanspruchte Server mit Kernel-Version 2.2 betreiben, seine Anwendung.
In der Kernel-Version 2.4 wurde das Problem behoben; wenn Sie also nicht mit der aktuellen Leistungsfähigkeit Ihres Systems zufrieden sind, ist es unter Umständen einfacher, ein Upgrade auf Version 2.4 durchzuführen, statt Ihren 2.2-Kernel zu patchen. Auf SMP-Systemen erhalten Sie neben der Problembehandlung zusätzlich noch eine beträchtliche SMP-Steigerung.
Wir haben MySQL mit dem Kernel 2.4 auf einem System mit zwei Prozessoren getestet und festgestellt, dass sich MySQL wesentlich besser skalieren lässt. Es gab im gesamten Testbereich bis 1000 Clients praktisch keine Verringerung des Abfragedurchsatzes, und der MySQL-Skalierungsfaktor (berechnet als Verhältnis des maximalen Durchsatzes zum Durchsatz pro Client) lag bei 180 %. Ähnliche Ergebnisse konnten wir auf einem System mit vier CPUs beobachten: praktisch keine Verlangsamung, während die Anzahl der Clients auf 1000 erhöht wurde, und dazu ein Skalierungsfaktor von 300 %. Basierend auf diesen Ergebnissen empfehlen wir für hochbeanspruchte SMP-Server mit dem Kernel 2.2 derzeit in jedem Fall eine Aktualisierung auf Kernel 2.4.
Unseren Beobachtungen zufolge ist es unumgänglich, den
Prozess mysqld unter dem Kernel 2.4 mit
höchstmöglicher Priorität auszuführen, um maximale
Leistung zu erzielen. Dies ist möglich, indem der Befehl
renice -20 $$
zu
mysqld_safe hinzugefügt wird. Bei unseren
Tests mit einem 4-CPU-Rechner haben wir eine 60-prozentige
Durchsatzsteigerung bei 400 Clients erzielt.
Ferner versuchen wir derzeit auch, weitere Informationen dazu
zu sammeln, wie gut MySQL mit dem Kernel 2.4 auf 4-Wege- und
8-Wege-Systemen funktioniert. Wenn Sie Zugang zu einem solchen
System haben und einige Benchmarks erstellt haben, möchten
wir Sie bitten, eine E-Mail mit den Ergebnissen an
<benchmarks@mysql.com>
zu senden. Wir werden
diese prüfen und ggf. in das Handbuch aufnehmen.
Wenn Sie einen abgestürzten mysqld-Serverprozess mit ps erkennen, dann weist dies normalerweise darauf hin, dass Sie einen Bug in MySQL entdeckt haben oder eine Tabelle beschädigt ist. Siehe auch Abschnitt A.4.2, „Was zu tun ist, wenn MySQL andauernd abstürzt“.
Um, wenn mysqld mit einem
SIGSEGV
-Signal abstürzt, unter Linux einen
Speicherauszug zu erhalten, können Sie
mysqld mit der Option
--core-file
starten. Beachten Sie, dass Sie
wahrscheinlich auch die Größe der Speicherauszugsdatei
erhöhen müssen, indem Sie ulimit -c
1000000 zu mysqld_safe
hinzufügen oder mysqld_safe mit
--core-file-size=1000000
starten. Siehe auch
Abschnitt 5.4.1, „mysqld_safe — Startskript für den MySQL-Server“.
MySQL erfordert libc
5.4.12 oder höher.
Bekanntermaßen funktioniert es mit libc
5.4.46. glibc
2.0.6 und höher sollten
ebenfalls keine Probleme bereiten. Es hat in der Vergangenheit
einige Probleme mit den glibc
-RPMs von Red
Hat gegeben. Prüfen Sie also bei Auftreten von Problemen, ob
Updates vorhanden sind. Die glibc
-RPMs
2.0.7-19 und 2.0.7-29 RPMs funktionieren ebenfalls
einwandfrei.
Wenn Sie Red Hat 8.0 oder eine neue glibc
2.2.x-Bibliothek verwenden, werden Sie unter Umständen
feststellen, dass sich mysqld in
gethostbyaddr()
aufhängt. Dies geschieht,
weil die neue glibc
-Bibliothek eine
Stapelgröße von mehr als 128 Kbyte für diesen Aufruf
benötigt. Um das Problem zu beheben, starten Sie
mysqld mit der Option
--thread-stack=192K
. (Verwenden Sie
-O thread_stack=192K
bei MySQL vor Version
4.) Diese Stapelgröße ist bei MySQL 4.0.10 und höher
voreingestellt, weswegen das Problem bei diesen Versionen
nicht auftreten sollte.
Wenn Sie zur Kompilierung von MySQL gcc 3.0
und höher verwenden, müssen Sie die Bibliothek
libstdc++v3
vor der MySQL-Kompilierung
installieren, da Sie andernfalls bei der Verknüpfung eine
Fehlermeldung zu einem fehlenden
__cxa_pure_virtual
-Symbol erhalten.
Bei einigen älteren Linux-Distributionen erzeugt configure unter Umständen einen Fehler wie den folgenden:
Syntax error in sched.h. Change _P to __P in the /usr/include/sched.h file. See the Installation chapter in the Reference Manual.
Tun Sie einfach, was die Fehlermeldung vorschlägt: Ergänzen
Sie den Makronamen _P
, der nur einen
Unterstrich aufweist, um einen weiteren Unterstrich und
probieren Sie es dann erneut.
Bei der Kompilierung werden unter Umständen Warnungen angezeigt. Die folgenden können dabei ignoriert werden:
mysqld.cc -o objs-thread/mysqld.o mysqld.cc: In function `void init_signals()': mysqld.cc:315: warning: assignment of negative value `-1' to `long unsigned int' mysqld.cc: In function `void * signal_hand(void *)': mysqld.cc:346: warning: assignment of negative value `-1' to `long unsigned int'
Wenn mysqld beim Start immer einen
Speicherauszug erzeugt, kann dies möglicherweise durch eine
veraltete /lib/libc.a
verursacht worden
sein. Versuchen Sie sie umzubenennen, entfernen Sie
sql/mysqld
, führen Sie ein neues
make install durch und probieren Sie es
dann erneut. Dieses Problem wurde für einige
Slackware-Installationen gemeldet.
Wenn Sie die folgende Fehlermeldung beim Verknüpfen von
mysqld erhalten, ist Ihre
libg++.a
nicht korrekt installiert:
/usr/lib/libc.a(putc.o): In function `_IO_putc': putc.o(.text+0x0): multiple definition of `_IO_putc'
Sie können die Verwendung von libg++.a
vermeiden, indem Sie configure wie folgt
ausführen:
shell> CXX=gcc ./configure
Bei einigen Implementierungen ist
readdir_r()
fehlerhaft. Das Symptom besteht
darin, dass die SHOW DATABASES
-Anweisung
immer eine leere Menge zurückgibt. Dies lässt sich durch
Entfernen von HAVE_READDIR_R
aus der Datei
config.h
nach der Konfiguration, aber vor
der Kompilierung durchführen.
Wir haben MySQL 5.1 unter Linux Alpha mit unseren Benchmarks und unserer Testsuite getestet, und es scheint gut zu funktionieren.
Derzeit erstellen wir die MySQL-Binärpakete unter SuSE Linux 7.0 für AXP, Kernel 2.4.4-SMP, Compaq C-Compiler (V6.2-505) und Compaq C++-Compiler (V6.3-006) auf einem Compaq DS20-Computer mit einem Alpha EV6-Prozessor.
Sie finden die genannten Compiler unter http://www.support.compaq.com/alpha-tools/. Durch Verwendung dieser Compiler anstelle von gcc erhalten wir eine um ca. 9 bis 14 Prozent bessere MySQL-Performance.
Bei MySQL unter Alpha verwenden wir das Flag -arch
generic
für unsere Kompilierungsoptionen. Hierdurch
ist sichergestellt, dass die Binärdatei auf allen
Alpha-Prozessoren läuft. Wir kompilieren auch statisch, um
Probleme mit Bibliotheken zu vermeiden. Der
configure-Befehl sieht wie folgt aus:
CC=ccc CFLAGS="-fast -arch generic" CXX=cxx \ CXXFLAGS="-fast -arch generic -noexceptions -nortti" \ ./configure --prefix=/usr/local/mysql --disable-shared \ --with-extra-charsets=complex --enable-thread-safe-client \ --with-mysqld-ldflags=-non_shared --with-client-ldflags=-non_shared
Wenn Sie egcs benutzen wollen, funktioniert unserer Erfahrung nach folgende configure-Zeile:
CFLAGS="-O3 -fomit-frame-pointer" CXX=gcc \ CXXFLAGS="-O3 -fomit-frame-pointer -felide-constructors \ -fno-exceptions -fno-rtti" \ ./configure --prefix=/usr/local/mysql --disable-shared
Es gibt ein paar bekannte Probleme bei der Ausführung von MySQL unter Linux-Alpha:
Das Debugging von Thread-basierten Anwendungen wie MySQL
funktioniert mit gdb 4.18
nicht.
Verwenden Sie stattdessen gdb 5.1.
Wenn Sie versuchen, mysqld bei der
Verwendung von gcc statisch zu
verknüpfen, dann tritt beim Start des resultierenden
Images ein Speicherauszug auf. Anders gesagt: Verwenden
Sie keinesfalls
--with-mysqld-ldflags=-all-static
mit
gcc.
MySQL sollte auf MkLinux mit dem neuesten
glibc
-Paket funktionieren (getestet mit
glibc
2.0.7).
Um MySQL auf Qube2 (Linux Mips) zum Laufen zu bringen,
benötigen Sie die neuesten
glibc
-Bibliotheken.
glibc-2.0.7-29C2
funktioniert
bekanntermaßen. Sie müssen ferner den C++-Compiler
egcs verwenden (egcs
1.0.2-9, gcc 2.95.2 oder höher).
Um MySQL unter Linux IA-64 kompilieren zu können, verwenden wir den folgenden configure-Befehl zur Erstellung mit gcc 2.96:
CC=gcc \ CFLAGS="-O3 -fno-omit-frame-pointer" \ CXX=gcc \ CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors \ -fno-exceptions -fno-rtti" \ ./configure --prefix=/usr/local/mysql \ "--with-comment=Official MySQL binary" \ --with-extra-charsets=complex
Unter IA-64 verwenden die MySQL-Clientbinärdateien gemeinsame
Bibliotheken. Das bedeutet, dass Sie, wenn Sie unsere
Binärdistribution in einem anderen Verzeichnis als
/usr/local/mysql
installieren, den Pfad
des Verzeichnisses, in dem
libmysqlclient.so
installiert ist,
entweder der Datei /etc/ld.so.conf
oder
dem Wert der Umgebungsvariablen
LD_LIBRARY_PATH
hinzufügen müssen.
Siehe auch Abschnitt A.3.1, „Probleme beim Linken mit der MySQL-Clientbibliothek“.
Unter Mac OS X kann tar lange Dateinamen
nicht verarbeiten. Wenn Sie eine
.tar.gz
-Distribution entpacken müssen,
verwenden Sie stattdessen gnutar.
MySQL sollte unter Mac OS X 10.x (Darwin) ohne größere Probleme funktionieren.
Die folgenden Probleme sind bekannt:
Die Verbindungszeiten (wait_timeout
,
interactive_timeout
und
net_read_timeout
) werden nicht
beachtet.
Dies ist wahrscheinlich ein Signalverwaltungsproblem in der Thread-Bibliothek, wo das Signal eine anhängige Leseoperation nicht unterbricht. Wir hoffen, dass ein künftiges Update der Thread-Bibliotheken dieses Problem beheben wird.
Unsere Binärdatei für Mac OS X wird unter Darwin 6.3 mit der folgenden configure-Zeile kompiliert:
CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc \ CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors \ -fno-exceptions -fno-rtti" \ ./configure --prefix=/usr/local/mysql \ --with-extra-charsets=complex --enable-thread-safe-client \ --enable-local-infile --disable-shared
Siehe auch Abschnitt 2.5, „Installation von MySQL unter Mac OS X“.
Bei aktuellen Versionen von Mac OS X Server sind vor der Kompilierung keine Betriebssystemänderungen erforderlich. Die Kompilierung für die Serverplattform ist mit der für die Clientversion von Mac OS X identisch.
Bei älteren Versionen (Mac OS X Server 1.2, auch bekannt als „Rhapsody“) müssen Sie zunächst ein pthread-Paket installieren, bevor Sie MySQL konfigurieren können.
Siehe auch Abschnitt 2.5, „Installation von MySQL unter Mac OS X“.
Unter Solaris haben Sie möglicherweise schon die ersten Probleme, bevor Sie die MySQL-Distribution überhaupt entpacken können, denn tar unter Solaris kann mit langen Dateinamen nicht umgehen. Dies bedeutet, dass Ihnen unter Umständen Fehler angezeigt werden, wenn Sie MySQL entpacken.
In diesem Fall müssen Sie GNU tar (gtar) zum Entpacken der Distribution verwenden. Sie finden eine vorkompilierte Kopie für Solaris unter http://dev.mysql.com/downloads/os-solaris.html.
Native Sun-Threads funktionieren erst ab Solaris 2.5. Bis Solaris 2.4 verwendet MySQL automatisch MIT-pthreads. Siehe auch Abschnitt 2.8.5, „Anmerkungen zu MIT-pthreads“.
Wenn die folgende Fehlermeldung bei Ausführung von configure angezeigt wird, stimmt etwas mit Ihrer Compiler-Installation nicht:
checking for restartable system calls... configure: error can not run test programs while cross compiling
In diesem Fall sollten Sie den Compiler auf eine neuere Version
aktualisieren. Sie können das Problem möglicherweise auch
beheben, indem Sie die folgende Zeile in die Datei
config.cache
einfügen:
ac_cv_sys_restartable_syscalls=${ac_cv_sys_restartable_syscalls='no'}
Wenn Sie Solaris auf einem SPARC-System verwenden, wird gcc 2.95.2 oder 3.2 als Compiler empfohlen. Sie finden ihn unter http://gcc.gnu.org/. Beachten Sie, dass egcs 1.1.1 und gcc 2.8.1 auf SPARC nicht zuverlässig arbeiten.
Die empfohlene configure-Zeile sieht bei Verwendung von gcc 2.95.2 wie folgt aus:
CC=gcc CFLAGS="-O3" \ CXX=gcc CXXFLAGS="-O3 -felide-constructors -fno-exceptions -fno-rtti" \ ./configure --prefix=/usr/local/mysql --with-low-memory \ --enable-assembler
Bei Verwendung eines UltraSPARC-Systems erhalten Sie eine um 4
Prozent bessere Performance, wenn Sie -mcpu=v8
-Wa,-xarch=v8plusa
zu den Umgebungsvariablen
CFLAGS
und CXXFLAGS
hinzufügen.
Wenn Sie den Forte-Compiler 5.0 oder höher von Sun einsetzen, können Sie configure wie folgt ausführen:
CC=cc CFLAGS="-Xa -fast -native -xstrconst -mt" \ CXX=CC CXXFLAGS="-noex -mt" \ ./configure --prefix=/usr/local/mysql --enable-assembler
Um eine 64-Bit-Binärdatei mit Sun Forte zu erstellen, verwenden Sie die folgenden Konfigurationsoptionen:
CC=cc CFLAGS="-Xa -fast -native -xstrconst -mt -xarch=v9" \ CXX=CC CXXFLAGS="-noex -mt -xarch=v9" ASFLAGS="-xarch=v9" \ ./configure --prefix=/usr/local/mysql --enable-assembler
Wenn Sie eine 64-Bit-Solaris-Binärdatei mit
gcc erstellen wollen, ergänzen Sie
-m64
in CFLAGS
und
CXXFLAGS
und entfernen Sie
--enable-assembler
aus der
configure-Zeile.
In den MySQL-Benchmarks erhielten wir auf UltraSPARC bei der
Verwendung von Forte 5.0 im 32-Bit-Modus im Vergleich zu
gcc 3.2 mit dem Flag -mcpu
einen Geschwindigkeitszuwachs von 4 Prozent.
Wenn Sie eine 64-Bit-mysqld-Binärdatei erstellen, ist diese um 4 Prozent langsamer als die 32-Bit-Binärdatei, kann aber mehr Threads und Speicher verwalten.
Wenn Sie Solaris 10 für x86_64 einsetzen, sollten Sie alle
Dateisysteme einbinden, auf denen Sie
InnoDB
-Dateien mit der Option
forcedirectio
speichern wollen.
(Standardmäßig erfolgt die Einbindung ohne diese Option.)
Andernfalls entsteht ein erheblicher Leistungseinbruch, wenn die
InnoDB
-Speicher-Engine auf dieser Plattform
verwendet wird.
Wenn Sie auf ein Problem mit fdatasync
oder
sched_yield
stoßen, können Sie es beheben,
indem Sie LIBS=-lrt
zur
configure-Zeile hinzufügen.
Bei Versionen des WorkShop-Compilers vor 5.3 müssen Sie eventuell das Skript configure bearbeiten. Die Zeile
#if !defined(__STDC__) || __STDC__ != 1
ändern Sie wie folgt:
#if !defined(__STDC__)
Wenn Sie __STDC__
mit der Option
-Xc
aktivieren, kann der Sun-Compiler keine
Kompilierung mit der pthread.h
-Header-Datei
von Solaris durchführen. Dies ist ein Sun-spezifischer Bug
(beschädigter Compiler oder beschädigte Include-Datei).
Wenn mysqld die folgende Fehlermeldung bei
der Ausführung ausgibt, haben Sie versucht, MySQL mit dem
Sun-Compiler zu kompilieren, ohne die Multithread-Option
-mt
zu aktivieren:
libc internal error: _rmutex_unlock: rmutex not held
Fügen Sie -mt
zu CFLAGS
und
CXXFLAGS
hinzu und kompilieren Sie neu.
Wenn Sie die SFW-Version von gcc verwenden
(in Solaris 8 enthalten), dann müssen Sie
/opt/sfw/lib
zur Umgebungsvariablen
LD_LIBRARY_PATH
hinzufügen, bevor Sie
configure ausführen.
Verwenden Sie das auf sunfreeware.com
verfügbare gcc, dann werden Sie eine Menge
Probleme haben. Um dies zu vermeiden, sollten Sie
gcc und GNU binutils
auf
dem Computer kompilieren, auf dem sie auch ausgeführt werden
sollen.
Wenn Sie bei der Kompilierung von MySQL mit gcc folgende Fehlermeldung erhalten, ist Ihr gcc nicht für Ihre Solaris-Version konfiguriert:
shell> gcc -O3 -g -O2 -DDBUG_OFF -o thr_alarm ...
./thr_alarm.c: In function `signal_hand':
./thr_alarm.c:556: too many arguments to function `sigwait'
In diesem Fall besteht die richtige Lösung einzig und allein darin, sich die neueste Version von gcc zu besorgen und sie mit Ihrem aktuellen gcc-Compiler zu kompilieren. Zumindest bei Solaris 2.5 enthalten praktisch alle Binärversionen von gcc alte, unbrauchbare Include-Dateien, die Thread-basierte (und wohl auch weitere) Programme beschädigen.
Solaris bietet keine statischen Versionen aller
Systembibliotheken (libpthreads
und
libdl
) an, d. h., Sie können MySQL nicht
mit --static
kompilieren. Wenn Sie es dennoch
versuchen, erhalten Sie eine der folgenden Fehlermeldungen:
ld: fatal: library -ldl: not found undefined reference to `dlopen' cannot find -lrt
Wenn Sie eigene MySQL-Clientprogramme verknüpfen, dann wird unter Umständen die folgende Fehlermeldung zur Laufzeit angezeigt:
ld.so.1: fatal: libmysqlclient.so.#: open failed: No such file or directory
Dieses Problem lässt sich auf eine der folgenden Weisen lösen:
Wenn Sie Probleme haben, configure mit
-lz
zu verknüpfen, weil
zlib
nicht installiert ist, dann haben Sie
zwei Möglichkeiten:
Wenn Sie das komprimierte Kommunikationsprotokoll einsetzen
können wollen, müssen Sie zlib
bei
ftp.gnu.org
herunterladen und
installieren.
Sie führen configure mit der Option
--with-named-z-libs=no
aus, wenn Sie MySQL
erstellen.
Wenn Sie gcc verwenden und Probleme beim
Einladen von UDFs (User-Defined Functions, benutzerdefinierte
Funktionen) in MySQL haben, ergänzen Sie die Verknüpfungszeile
für die UDF um -lgcc
.
Wollen Sie, dass MySQL automatisch startet, dann können Sie
support-files/mysql.server
in das
Verzeichnis /etc/init.d
kopieren und eine
symbolische Verknüpfung namens
/etc/rc3.d/S99mysql.server
zu ihr
erstellen.
Wenn zu viele Prozesse innerhalb kurzer Zeit eine Verbindung mit mysqld herstellen wollen, werden Sie die folgende Fehlermeldung im MySQL-Log finden:
Error in accept: Protocol error
Dieses Problem können Sie unter Umständen beheben, indem Sie
den Server mit der Option --back_log=50
starten. (Bei MySQL vor Version 4 verwenden Sie -O
back_log=50
.)
Solaris unterstützt Core-Dateien für
setuid()
-Anwendungen nicht, d. h., Sie
können keine Core-Datei von mysqld erhalten,
wenn Sie die Option --user
verwenden.
Normalerweise können Sie eine Binärdatei für Solaris 2.6 auch unter Solaris 2.7 oder 2.8 verwenden. Auch betreffen Probleme, die für Solaris 2.6 gelistet sind, meist ebenfalls Solaris 2.7 und 2.8.
MySQL sollte neue Versionen von Solaris automatisch erkennen können und für die im Folgenden beschriebenen Probleme Workarounds aktivieren.
Solaris 2.7 und 2.8 haben einige Bugs bei den Include-Dateien. Bei Verwendung von gcc erhalten Sie unter Umständen folgende Fehlermeldung:
/usr/include/widec.h:42: warning: `getwc' redefined /usr/include/wchar.h:326: warning: this is the location of the previous definition
In diesem Fall können Sie das Problem beheben, indem Sie
/usr/include/widec.h
nach
.../lib/gcc-lib/os/gcc-version/include
kopieren. Die Zeile 41
#if !defined(lint) && !defined(__lint)
ändern Sie wie folgt:
#if !defined(lint) && !defined(__lint) && !defined(getwc)
Alternativ können Sie
/usr/include/widec.h
auch direkt
editieren. Wenn Sie das Problem auf eine der beschriebenen
Weisen behoben haben, sollten Sie
config.cache
entfernen und
configure erneut ausführen.
Wenn Sie bei der Ausführung von make die
folgenden Fehlermeldungen erhalten, liegt das daran, dass
configure die Datei
curses.h
nicht erkannt hat
(wahrscheinlich aufgrund des Fehlers in
/usr/include/widec.h
):
In file included from mysql.cc:50: /usr/include/term.h:1060: syntax error before `,' /usr/include/term.h:1081: syntax error before `;'
Dieses Problem lässt sich auf mehreren Wegen lösen:
Konfigurieren Sie mit CFLAGS=-DHAVE_CURSES_H
CXXFLAGS=-DHAVE_CURSES_H ./configure
.
Bearbeiten Sie /usr/include/widec.h
wie im vorherigen Abschnitt beschrieben und führen Sie
configure erneut aus.
Entfernen Sie die Zeile #define
HAVE_TERM
aus der Datei
config.h
und führen Sie
make erneut aus.
Wenn Ihr Linker beim Verknüpfen von Clientprogrammen
-lz
nicht finden kann, besteht das Problem
wahrscheinlich darin, dass Ihre Datei
libz.so
in
/usr/local/lib
installiert ist. Dieses
Problem lässt sich auf eine der folgenden Weisen lösen:
Fügen Sie /usr/local/lib
zu
LD_LIBRARY_PATH
hinzu.
Fügen Sie von /lib
aus eine
Verknüpfung zu libz.so
hinzu.
Wenn Sie Solaris 8 verwenden, können Sie die optionale
zlib
von Ihrer Solaris
8-Distributions-CD installieren.
Sie führen configure mit der Option
--with-named-z-libs=no
aus, wenn Sie
MySQL erstellen.
Unter Solaris 8 auf x86 erzeugt mysqld
einen Speicherauszug, wenn Sie die Debugsymbole mithilfe von
strip
entfernen.
Wenn Sie gcc oder egcs unter Solaris x86 verwenden und bei hoher Belastung Probleme mit Speicherauszügen haben, sollten Sie folgenden configure-Befehl verwenden:
CC=gcc CFLAGS="-O3 -fomit-frame-pointer -DHAVE_CURSES_H" \ CXX=gcc \ CXXFLAGS="-O3 -fomit-frame-pointer -felide-constructors \ -fno-exceptions -fno-rtti -DHAVE_CURSES_H" \ ./configure --prefix=/usr/local/mysql
Hierdurch vermeiden Sie Probleme mit der Bibliothek
libstdc++
und mit C++-Ausnahmefehlern.
Sollte dies nicht helfen, dann sollten Sie eine Debugversion kompilieren und diese mit einer Trace-Datei oder unter gdb ausführen. Siehe auch Abschnitt E.1.3, „mysqld unter gdb debuggen“.
In diesem Abschnitt erhalten Sie Informationen zur Verwendung von MySQL unter Varianten von BSD Unix.
FreeBSD 4.x oder neuer wird für die Ausführung von MySQL
empfohlen, da das Thread-Paket wesentlich besser integriert
ist. Um ein sicheres und stabiles System zu erhalten, sollten
Sie nur FreeBSD-Kernels verwenden, die mit
-RELEASE
gekennzeichnet sind.
Die einfachste (und deswegen empfohlene) Vorgehensweise zur
Installation von MySQL besteht in der Verwendung der
mysql-server- und
mysql-client
-Ports, die unter
http://www.freebsd.org/ verfügbar
sind. Die Verwendung dieser Ports hat die folgenden Vorteile:
Sie erhalten ein funktionsfähiges MySQL, bei dem alle Optimierungen, die unter Ihrer FreeBSD-Version bekanntermaßen funktionieren, bereits aktiviert sind.
Konfiguration und Erstellung werden automatisch durchgeführt.
Startskripten sind in
/usr/local/etc/rc.d
installiert.
Sie können mit pkg_info -L
überprüfen, welche Dateien installiert sind.
Sie können ferner mit pkg_delete
MySQL
entfernen, wenn Sie es auf Ihrem Rechner nicht mehr
benötigen.
Wir empfehlen die Verwendung von MIT-pthreads unter FreeBSD 2.x und von nativen Threads unter FreeBSD 3 und höher. Zwar können auch spätere Versionen von Release 2.2.x mit nativen Threads betrieben werden, aber dann kann es zu Problemen beim Herunterfahren von mysqld kommen.
Leider sind bestimmte Funktionsaufrufe unter FreeBSD noch
nicht vollständig Thread-sicher. Dies betrifft vor allem die
Funktion gethostbyname()
, die von MySQL zur
Umwandlung von Hostnamen in IP-Adressen verwendet wird. Unter
bestimmten Umständen verursacht der Prozess
mysqld unvermittelt eine
Prozessorauslastung von 100 Prozent und reagiert nicht mehr.
Wenn dieses Problem auftritt, versuchen Sie MySQL mit der
Option --skip-name-resolve
zu starten.
Alternativ können Sie MySQL unter FreeBSD 4.x mit der LinuxThreads-Bibliothek verknüpfen, wodurch einige der Probleme vermieden werden, die die native Thread-Implementierung von FreeBSD hat. Einen sehr guten Vergleich von LinuxThreads und nativen Threads finden Sie in Jeremy Zawodnys Artikel FreeBSD or Linux for your MySQL Server? unter http://jeremy.zawodny.com/blog/archives/000697.html.
Es gibt ein bekanntes Problem bei der Verwendung von LinuxThreads unter FreeBSD:
Die Verbindungszeiten (wait_timeout
,
interactive_timeout
und
net_read_timeout
) werden nicht
beachtet. Auffälliges Symptom ist, dass
Permanentverbindungen für eine sehr lange Zeit hängen,
ohne abgebaut zu werden, und dass eine Terminierung des
Threads erst Erfolg hat, wenn der Thread einem neuen
Befehl zugeordnet wird.
Dies ist wahrscheinlich ein Signalverwaltungsproblem in der Thread-Bibliothek, wo das Signal eine anhängige Leseoperation nicht unterbricht. Das Problem wird voraussichtlich in FreeBSD 5.0 behoben.
Damit der MySQL-Erstellungsprozess funktioniert, ist GNU make (gmake) erforderlich. Wenn GNU make nicht vorhanden ist, müssen Sie es vor der Kompilierung von MySQL installieren.
Die empfohlene Vorgehensweise zur Kompilierung und Installation von MySQL unter FreeBSD mit gcc (2.95.2 und höher) ist die folgende:
CC=gcc CFLAGS="-O2 -fno-strength-reduce" \ CXX=gcc CXXFLAGS="-O2 -fno-rtti -fno-exceptions \ -felide-constructors -fno-strength-reduce" \ ./configure --prefix=/usr/local/mysql --enable-assembler gmake gmake install cd /usr/local/mysql bin/mysql_install_db --user=mysql bin/mysqld_safe &
Wenn Sie feststellen, dass configure MIT-pthreads verwendet, lesen Sie die Anmerkungen zu MIT-pthreads. Siehe auch Abschnitt 2.8.5, „Anmerkungen zu MIT-pthreads“.
Wenn make install die Fehlermeldung
ausgibt, dass es /usr/include/pthreads
nicht finden kann, dann hat configure nicht
erkannt, dass Sie MIT-pthreads benötigen. Um dieses Problem
zu beheben, entfernen Sie config.cache
und führen configure dann erneut mit der
Option --with-mit-threads
aus.
Achten Sie darauf, dass Ihre Namensauflösung korrekt ist.
Andernfalls werden Verzögerungen oder Fehler bei der
Auflösung auftreten, wenn Sie die Verbindung mit
mysqld herzustellen versuchen. Ferner
müssen Sie sicherstellen, dass der Eintrag
localhost
in der Datei
/etc/hosts
korrekt ist. Am Anfang der
Datei sollte eine Zeile ähnlich der folgenden stehen:
127.0.0.1 localhost localhost.your.domain
FreeBSD hat bekanntermaßen einen sehr niedrigen Standardwert
für Datei-Handles. Siehe auch
Abschnitt A.2.17, „Datei nicht gefunden“. Starten
Sie den Server unter Verwendung der Option
--open-files-limit
für
mysqld_safe oder heben Sie den Wert für
den Benutzer mysqld in
/etc/login.conf
an und erstellen Sie die
Datei dann mit cap_mkdb /etc/login.conf
neu. Achten Sie außerdem darauf, die passende Klasse für
diesen Benutzer in der Passwortdatei zu konfigurieren, sofern
Sie die Vorgabe nicht verwenden (benutzen Sie chpass
mysqld-user-name
). Siehe auch
Abschnitt 5.4.1, „mysqld_safe — Startskript für den MySQL-Server“.
FreeBSD beschränkt die Größe eines Prozesses auch dann auf 512 Mbyte, wenn auf Ihrem System wesentlich mehr Arbeitsspeicher vorhanden ist. Insofern kann ein Fehler wie der folgende auftreten:
Out of memory (Needed 16391 bytes)
Bei den aktuellen Versionen von FreeBSD (mindestens seit 4.x)
können Sie den Grenzwert auch anheben, indem Sie die
folgenden Einträge in der Datei
/boot/loader.conf
hinzufügen und den
Computer neu starten (diese Einstellungen lassen sich nicht
zur Laufzeit mit dem Befehl sysctl
ändern):
kern.maxdsiz="1073741824" # 1GB kern.dfldsiz="1073741824" # 1GB kern.maxssiz="134217728" # 128MB
Bei älteren FreeBSD-Versionen müssen Sie Ihren Kernel neu
kompilieren, um die maximale Datensegmentgröße für einen
Prozess zu ändern. In diesem Fall sollten Sie sich die Option
MAXDSIZ
in der Konfigurationsdatei
LINT
näher ansehen, um weitere
Informationen zu erhalten.
Wenn es Probleme mit dem aktuellen Daten in MySQL gibt, sollte
eine Einstellung der Variablen TZ
Abhilfe
leisten können. Siehe auch
Anhang F, Umgebungsvariablen.
Zur Kompilierung unter NetBSD benötigen Sie GNU
make. Andernfalls schlägt der
Erstellungsprozess fehl, wenn make
versucht, lint
für C++-Dateien
auszuführen.
Unter OpenBSD 2.5 können Sie MySQL mit nativen Threads kompilieren. Hierzu verwenden Sie die folgenden Optionen:
CFLAGS=-pthread CXXFLAGS=-pthread ./configure --with-mit-threads=no
Wenn Sie die folgende Fehlermeldung bei der Kompilierung von MySQL erhalten, ist der Wert ulimit für den virtuellen Speicher auf Ihrem System zu niedrig:
item_func.h: In method `Item_func_ge::Item_func_ge(const Item_func_ge &)': item_func.h:28: virtual memory exhausted make[2]: *** [item_func.o] Error 1
Verwenden Sie beispielsweise ulimit -v 80000 und führen Sie make erneut aus. Funktioniert dies nicht und Sie verwenden bash, dann probieren Sie stattdessen csh oder sh aus. Einige BSDI-Benutzer haben Probleme mit bash und ulimit gemeldet.
Wenn Sie gcc einsetzen, müssen Sie unter
Umständen auch das Flag --with-low-memory
verwenden, damit configure
sql_yacc.cc
kompilieren kann.
Wenn es Probleme mit den aktuellen Daten in MySQL gibt, sollte
eine Einstellung der Variablen TZ
Abhilfe
leisten können. Siehe auch
Anhang F, Umgebungsvariablen.
Aktualisieren Sie auf BSD/OS 3.1. Sollte dies nicht möglich sein, dann installieren Sie BSDIpatch M300-038.
Verwenden Sie den folgenden Befehl zur Konfiguration von MySQL:
env CXX=shlicc++ CC=shlicc2 \ ./configure \ --prefix=/usr/local/mysql \ --localstatedir=/var/mysql \ --without-perl \ --with-unix-socket-path=/var/mysql/mysql.sock
Auch die folgende Variante funktioniert bekanntermaßen:
env CC=gcc CXX=gcc CXXFLAGS=-O3 \ ./configure \ --prefix=/usr/local/mysql \ --with-unix-socket-path=/var/mysql/mysql.sock
Sie können die Verzeichnispositionen auf Wunsch ändern oder die Voreinstellungen übernehmen (hierzu geben Sie einfach keine Positionen an).
Sollten Leistungsprobleme unter starker Belastung auftreten,
dann probieren Sie die Option
--skip-thread-priority
für
mysqld. Hierdurch werden alle Threads mit
derselben Priorität ausgeführt. Unter BSDI 3.1 können Sie
auf diese Weise die Performance verbessern – zumindest so
lange, bis BSDI den Thread-Scheduler in Ordnung bringt.
Wird bei der Kompilierung die Fehlermeldung virtual
memory exhausted
angezeigt, dann sollten Sie
ulimit -v 80000 ausprobieren und
make erneut ausführen. Funktioniert dies
nicht und Sie verwenden bash, dann
probieren Sie stattdessen csh oder
sh aus. Einige BSDI-Benutzer haben Probleme
mit bash und ulimit
gemeldet.
BSDI 4.x weist einige Bugs in Bezug auf Threads auf. Wenn Sie MySQL hierunter verwenden wollen, sollten Sie alle Thread-spezifischen Patches installieren. Dis gilt zumindest für M400-023.
Auf einigen BSDI 4.x-Systemen treten Probleme mit gemeinsamen
Bibliotheken auf. Sie erkennen dies daran, dass Sie keine
Clientprogramme wie etwa mysqladmin
ausführen können. In diesem Fall müssen Sie das System so
umkonfigurieren, dass es keine gemeinsamen Bibliotheken
verwendet; dies tun Sie mit der Option
--disable-shared
für
configure.
Ferner haben Kunden Probleme unter BSDI 4.0.1 damit gehabt, dass die Binärdatei mysqld nach einer Weile keine Tabellen mehr öffnen konnte. Ursache hierfür ist ein bibliotheks- oder systembezogener Bug, aufgrund dessen mysqld das aktuelle Verzeichnis wechselt, ohne hierfür zuvor eine Bestätigung angefordert zu haben.
Sie beseitigen das Problem, indem Sie entweder MySQL auf
Version 3.23.34 oder höher aktualisieren oder nach der
Ausführung von configure die Zeile
#define HAVE_REALPATH
aus der Datei
config.h
entfernen, bevor Sie
make starten.
Beachten Sie, dass dies bedeutet, dass Sie in diesem Fall unter BSDI keine symbolischen Verknüpfungen zwischen Datenbankverzeichnissen oder von einer Tabelle zu einer anderen Datenbank erstellen können. (Symbolische Verknüpfungen zu anderen Festplatten hingegen sind unproblematisch.)
Wenn Sie MySQL unter HP-UX kompilieren, gibt es ein paar kleinere Probleme. Wir empfehlen die Verwendung von gcc anstelle des nativen Compilers von HP-UX, da gcc einen besseren Code erzeugt.
Verwenden Sie unter HP-UX am besten gcc
2.95. Verwenden Sie keine Hochoptimierungsflags (wie etwa
-O6
), da dies unter Umständen unter HP-UX
nicht sicher ist.
Der folgende configure-Befehl sollte für gcc 2.95 funktionieren:
CFLAGS="-I/opt/dce/include -fpic" \ CXXFLAGS="-I/opt/dce/include -felide-constructors -fno-exceptions \ -fno-rtti" \ CXX=gcc \ ./configure --with-pthread \ --with-named-thread-libs='-ldce' \ --prefix=/usr/local/mysql --disable-shared
Der folgende configure-Befehl sollte für gcc 3.1 funktionieren:
CFLAGS="-DHPUX -I/opt/dce/include -O3 -fPIC" CXX=gcc \ CXXFLAGS="-DHPUX -I/opt/dce/include -felide-constructors \ -fno-exceptions -fno-rtti -O3 -fPIC" \ ./configure --prefix=/usr/local/mysql \ --with-extra-charsets=complex --enable-thread-safe-client \ --enable-local-infile --with-pthread \ --with-named-thread-libs=-ldce --with-lib-ccflags=-fPIC --disable-shared
Aufgrund einiger kritischer Bugs in den HP-UX-Standardbibliotheken sollten Sie die folgenden Patches installieren, bevor Sie MySQL unter HP-UX 11.0 ausführen:
PHKL_22840 Streams cumulative PHNE_22397 ARPA cumulative
Hierdurch können Sie das Problem beheben,
EWOULDBLOCK
aus recv()
und EBADF
aus accept()
in Thread-basierten Anwendungen zu erhalten.
Wenn Sie gcc 2.95.1 auf einem nicht gepatchten HP-UX 11.x-System einsetzen, wird unter Umständen die folgende Fehlermeldung angezeigt:
In file included from /usr/include/unistd.h:11, from ../include/global.h:125, from mysql_priv.h:15, from item.cc:19: /usr/include/sys/unistd.h:184: declaration of C function ... /usr/include/sys/pthread.h:440: previous declaration ... In file included from item.h:306, from mysql_priv.h:158, from item.cc:19:
Das Problem besteht darin, dass HP-UX
pthreads_atfork()
nicht konsistent
definiert. Es liegt ein Prototypkonflikt in
/usr/include/sys/unistd.h
:184 und
/usr/include/sys/pthread.h
:440 vor.
Eine Lösung besteht darin,
/usr/include/sys/unistd.h
nach
mysql/include
zu kopieren und
unistd.h
so zu editieren, dass es zur
Definition in pthread.h
passt. Suchen Sie
nach der folgenden Zeile:
extern int pthread_atfork(void (*prepare)(), void (*parent)(), void (*child)());
Ändern Sie sie wie folgt ab:
extern int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void));
Wenn Sie die Änderung vorgenommen haben, sollte die folgende configure-Zeile funktionieren:
CFLAGS="-fomit-frame-pointer -O3 -fpic" CXX=gcc \ CXXFLAGS="-felide-constructors -fno-exceptions -fno-rtti -O3" \ ./configure --prefix=/usr/local/mysql --disable-shared
Verwenden Sie den HP-UX-Compiler, dann können Sie den folgenden Befehl verwenden (dieser wurde mit cc B.11.11.04 getestet):
CC=cc CXX=aCC CFLAGS=+DD64 CXXFLAGS=+DD64 ./configure \ --with-extra-character-set=complex
Sie können alle Fehler des folgenden Typs ignorieren:
aCC: warning 901: unknown option: `-3': use +help for online documentation
Wenn die folgende Fehlermeldung von configure ausgegeben wird, dann stellen Sie sicher, dass der Pfad zum K&R-Compiler nicht vor dem Pfad zum HP-UX-C- und C++-Compiler steht:
checking for cc option to accept ANSI C... no configure: error: MySQL requires an ANSI C compiler (and a C++ compiler). Try gcc. See the Installation chapter in the Reference Manual.
Ein anderer Grund dafür, dass eine Kompilierung nicht
möglich ist, besteht darin, dass Sie die
+DD64
-Flags nicht wie eben beschrieben
definiert haben.
Eine andere Möglichkeit für HP-UX 11 besteht darin, die unter http://dev.mysql.com/downloads/ verfügbaren MySQL-Binärdateien zu verwenden, die wir selbst erstellt und getestet haben. Ferner wurde uns mitgeteilt, dass die von MySQL angebotenen Binärdateien für HP-UX 10.20 auch unter HP-UX 11 erfolgreich ausgeführt werden können. Wenn Sie hierbei auf Probleme treffen, sollten Sie überprüfen, ob HP-UX-Patches verfügbar sind.
Die automatische Erkennung von xlC
fehlt
bei Autoconf. Aus diesem Grund muss eine Reihe von Variablen
eingestellt werden, bevor configure
ausgeführt wird. Das folgende Beispiel verwendet den
IBM-Compiler:
export CC="xlc_r -ma -O3 -qstrict -qoptimize=3 -qmaxmem=8192 " export CXX="xlC_r -ma -O3 -qstrict -qoptimize=3 -qmaxmem=8192" export CFLAGS="-I /usr/local/include" export LDFLAGS="-L /usr/local/lib" export CPPFLAGS=$CFLAGS export CXXFLAGS=$CFLAGS ./configure --prefix=/usr/local \ --localstatedir=/var/mysql \ --sbindir='/usr/local/bin' \ --libexecdir='/usr/local/bin' \ --enable-thread-safe-client \ --enable-large-files
Obige Optionen werden zur Kompilierung der MySQL-Distribution verwendet, die unter http://www-frec.bull.com/ verfügbar ist.
Wenn Sie in obiger configure-Zeile die
Option -O3
auf -O2
setzen,
müssen Sie auch die Option -qstrict
entfernen. Dies ist eine Einschränkung des C-Compilers von
IBM.
Wenn Sie gcc oder egcs
zur Kompilierung von MySQL verwenden,
müssen Sie das Flag
-fno-exceptions
benutzen, weil die
Fehlerbehandlung in
gcc/egcs nicht
Thread-sicher ist! (Dies wurde mit egcs 1.1
getestet.) Es gibt ferner einige bekannte Probleme mit dem
IBM-Assembler, die in Verbindung mit gcc zu
fehlerhaftem Code führen können.
Wir empfehlen die folgende configure-Zeile bei egcs und gcc 2.95 unter AIX:
CC="gcc -pipe -mcpu=power -Wa,-many" \ CXX="gcc -pipe -mcpu=power -Wa,-many" \ CXXFLAGS="-felide-constructors -fno-exceptions -fno-rtti" \ ./configure --prefix=/usr/local/mysql --with-low-memory
Die Option -Wa,-many
ist erforderlich, damit
die Kompilierung erfolgreich verläuft. Bei IBM ist dieses
Problem bekannt, man sieht sich aber mit der Behebung nicht
unter Zeitdruck, da ein Workaround verfügbar ist. Wir wissen
nicht, ob -fno-exceptions
bei
gcc 2.95 erforderlich ist, aber weil MySQL
keine Ausnahmen verwendet und die Option einen schnelleren
Code erzeugt, empfehlen wir ihre generelle Verwendung bei
egcs und gcc.
Wenn ein Problem mit dem Assemblercode auftritt, versuchen Sie
die Option
-mcpu=
so zu
ändern, dass sie zu Ihrer CPU passt. Normalerweise müssen
xxx
power2
, power
oder
powerpc
verwendet werden. Möglicherweise
müssen Sie aber auch 604
oder
604e
einsetzen. Wir wissen es nicht genau,
nehmen aber an, dass power
mit hoher
Wahrscheinlichkeit in den meisten Fällen sicher ist (und zwar
auch auf power2-Systemen).
Wenn Sie nicht wissen, welchen Prozessor Sie haben, führen
Sie den Befehl uname -m
aus. Er erzeugt
einen String, der etwa so aussieht:
000514676700
. Das Format ist
xxyyyyyymmss
, wobei xx
und ss
immer 00
,
yyyyyy
eine eindeutige Systemkennung und
mm
die Kennung des CPU-Planars sind. Eine
Übersicht über diese Werte finden Sie unter
http://www16.boulder.ibm.com/pseries/en_US/cmds/aixcmds5/uname.htm.
Dort erhalten Sie Angaben zu Rechnertyp und -modell, auf deren Basis Sie die CPU in Ihrem Rechner ermitteln können.
Wenn Sie Probleme mit Signalen haben (weil sich MySQL unter hoher Belastung unerwartet aufhängt), haben Sie unter Umständen einen Betriebssystembug bei den Threads oder Signalen gefunden. In diesem Fall können Sie MySQL wie folgt anweisen, Signale nicht zu verwenden:
CFLAGS=-DDONT_USE_THR_ALARM CXX=gcc \ CXXFLAGS="-felide-constructors -fno-exceptions -fno-rtti \ -DDONT_USE_THR_ALARM" \ ./configure --prefix=/usr/local/mysql --with-debug \ --with-low-memory
Hierdurch wird die Leistungsfähigkeit von MySQL nicht beeinträchtigt; ein Nebeneffekt besteht aber darin, dass Sie Clients, die an einer Verbindung „schlafen“, mit mysqladmin kill oder mysqladmin shutdown nicht terminieren können. Stattdessen hängt sich der Client auf, wenn er den nächsten Befehl absetzt.
Bei einigen Versionen von AIX führt eine Verknüpfung mit
libbind.a
bei
getservbyname()
zu einem Speicherauszug.
Dies ist ein AIX-Bug, der IBM gemeldet werden sollte.
Bei AIX 4.2.1 und gcc müssen Sie die folgenden Änderungen vornehmen.
Bearbeiten Sie nach der Konfiguration
config.h
und
include/my_config.h
. Die Zeile
#define HAVE_SNPRINTF 1
ändern Sie wie folgt:
#undef HAVE_SNPRINTF
Schließlich müssen Sie in mysqld.cc
noch einen Prototyp für initgroups()
hinzufügen.
#ifdef _AIX41 extern "C" int initgroups(const char *,int); #endif
Wenn Sie dem Prozess mysqld viel Speicher zuweisen müssen, reicht es nicht aus, einfach ulimit -d unlimited zu verwenden. Sie müssen vielmehr auch mysqld_safe mit einer Zeile wie der folgenden ergänzen:
export LDR_CNTRL='MAXDATA=0x80000000'
Weitere Informationen zur Verwendung einer großen Menge Speicher finden Sie unter http://publib16.boulder.ibm.com/pseries/en_US/aixprggd/genprogc/lrg_prg_support.htm.
Benutzer von AIX 4.3 sollten gmake statt des in AIX enthaltenen make-Hilfsprogramms verwenden.
Unter SunOS 4 ist MIT-pthreads zur Kompilierung von MySQL erforderlich. Das wiederum bedeutet, dass Sie GNU make benötigen.
Einige SunOS 4-Systeme haben Probleme mit dynamischen Bibliotheken und libtool. Dieses Problem können Sie mit der folgenden configure-Zeile beheben:
./configure --disable-shared --with-mysqld-ldflags=-all-static
Wenn Sie readline
kompilieren, erhalten Sie
unter Umständen Warnungen zu Doppeldefinitionen. Diese
können Sie getrost ignorieren.
Wenn Sie mysqld kompilieren, erscheinen
einige Warnungen des Typs implicit declaration of
function
. Diese können Sie getrost ignorieren.
Wenn Sie egcs 1.1.2 unter Digital Unix verwenden, sollten Sie auf gcc 2.95.2 aktualisieren, weil egcs unter DEC einige schwerwiegende Bugs aufweist!
Wenn Sie Thread-basierte Programme unter Digital Unix
kompilieren, empfiehlt die Dokumentation die Verwendung der
Option -pthread
für cc
und cxx und die -lmach
-lexc
-Bibliotheken (zusätzlich zu
-lpthread
). Sie sollten
configure etwa wie folgt ausführen:
CC="cc -pthread" CXX="cxx -pthread -O" \ ./configure --with-named-thread-libs="-lpthread -lmach -lexc -lc"
Wenn Sie mysqld kompilieren, werden unter Umständen einige Warnungen wie die folgenden angezeigt:
mysqld.cc: In function void handle_connections()': mysqld.cc:626: passing long unsigned int *' as argument 3 of accept(int,sockadddr *, int *)'
Diese können Sie getrost ignorieren. Sie erscheinen, weil configure nur Fehler, nicht jedoch Warnungen erkennen kann.
Wenn Sie den Server direkt über die Befehlszeile starten,
kann es bei der Abmeldung zu Abstürzen kommen. (Wenn Sie sich
abmelden, erhalten Ihre ausstehenden Prozesse ein
SIGHUP
-Signal.) Versuchen Sie, den Server
wie folgt zu starten:
nohup mysqld [options
] &
nohup
sorgt dafür, dass der Befehl, der
darauf folgt, alle ggf. vom Terminal gesendeten
SIGHUP
-Signale ignoriert. Alternativ
starten Sie den Server durch Ausführung von
mysqld_safe. Hierdurch wird
mysqld unter Verwendung von
nohup für Sie aufgerufen. Siehe auch
Abschnitt 5.4.1, „mysqld_safe — Startskript für den MySQL-Server“.
Wenn ein Problem bei der Kompilierung von
mysys/get_opt.c
auftritt, entfernen Sie
einfach die Zeile #define _NO_PROTO
am
Anfang dieser Datei.
Wenn Sie den CC-Compiler von Compaq einsetzen, sollte die folgende configure-Zeile problemlos funktionieren:
CC="cc -pthread" CFLAGS="-O4 -ansi_alias -ansi_args -fast -inline speed all -arch host" CXX="cxx -pthread" CXXFLAGS="-O4 -ansi_alias -ansi_args -fast -inline speed all \ -arch host -noexceptions -nortti" export CC CFLAGS CXX CXXFLAGS ./configure \ --prefix=/usr/local/mysql \ --with-low-memory \ --enable-large-files \ --enable-shared=yes \ --with-named-thread-libs="-lpthread -lmach -lexc -lc" gnumake
Tritt ein Problem mit libtool auf, wenn Sie wie gerade gezeigt mit gemeinsamen Bibliotheken kompilieren und mysql verknüpfen, sollten Sie dieses durch Absetzen der folgenden Befehle umgehen können:
cd mysql /bin/sh ../libtool --mode=link cxx -pthread -O3 -DDBUG_OFF \ -O4 -ansi_alias -ansi_args -fast -inline speed \ -speculate all \ -arch host -DUNDEF_HAVE_GETHOSTBYNAME_R \ -o mysql mysql.o readline.o sql_string.o completion_hash.o \ ../readline/libreadline.a -lcurses \ ../libmysql/.libs/libmysqlclient.so -lm cd .. gnumake gnumake install scripts/mysql_install_db
Wenn Sie Probleme beim Kompilieren haben und DEC CC und gcc installiert sind, probieren Sie einmal, configure wie folgt auszuführen:
CC=cc CFLAGS=-O CXX=gcc CXXFLAGS=-O3 \ ./configure --prefix=/usr/local/mysql
Treten Probleme in Verbindung mit der Datei
c_asm.h
auf, dann können Sie wie folgt
eine Dummyversion von c_asm.h
erstellen:
touch include/c_asm.h CC=gcc CFLAGS=-I./include \ CXX=gcc CXXFLAGS=-O3 \ ./configure --prefix=/usr/local/mysql
Beachten Sie, dass die folgenden Probleme beim Programm ld sich durch den Download des aktuellen DEC-(Compaq-)Patch-Kits beheben lassen. Dieses finden Sie unter http://ftp.support.compaq.com/public/unix/.
Unter OSF/1 V4.0D tritt bei Verwendung des Compilers "DEC
C V5.6-071 on Digital Unix V4.0 (Rev. 878)" ein seltsames
Verhalten auf (undefinierte asm
-Symbole).
/bin/ld
scheint ebenfalls beschädigt zu
sein (Probleme mit _exit undefined
-Fehlern,
die beim Verknüpfen von mysqld auftreten).
Es ist uns gelungen, MySQL auf diesem System mit der folgenden
configure-Zeile zu kompilieren, nachdem wir
/bin/ld
durch die Version aus OSF 4.0C
ersetzt haben:
CC=gcc CXX=gcc CXXFLAGS=-O3 ./configure --prefix=/usr/local/mysql
Beim Digital-Compiler "C++ V6.1-029" sollte Folgendes funktionieren:
CC=cc -pthread CFLAGS=-O4 -ansi_alias -ansi_args -fast -inline speed \ -speculate all -arch host CXX=cxx -pthread CXXFLAGS=-O4 -ansi_alias -ansi_args -fast -inline speed \ -speculate all -arch host -noexceptions -nortti export CC CFLAGS CXX CXXFLAGS ./configure --prefix=/usr/mysql/mysql \ --with-mysqld-ldflags=-all-static --disable-shared \ --with-named-thread-libs="-lmach -lexc -lc"
Bei einigen Versionen von OSF/1 ist die Funktion
alloca()
beschädigt. Dieses Problem
können Sie beheben, indem Sie die Zeile in
config.h
entfernen, die
'HAVE_ALLOCA'
definiert.
Die Funktion alloca()
weist unter
Umständen auch einen falschen Prototyp in
/usr/include/alloca.h
auf. Sich hierauf
beziehende Warnmeldungen können Sie ignorieren.
configure verwendet die folgenden
Thread-Bibliotheken automatisch:
--with-named-thread-libs="-lpthread -lmach -lexc
-lc"
.
Wenn Sie gcc verwenden, können Sie auch versuchen, configure wie folgt auszuführen:
CFLAGS=-D_PTHREAD_USE_D4 CXX=gcc CXXFLAGS=-O3 ./configure ...
Wenn Sie Probleme mit Signalen haben (weil sich MySQL unter hoher Belastung unerwartet aufhängt), haben Sie unter Umständen einen Betriebssystembug bei den Threads oder Signalen gefunden. In diesem Fall können Sie MySQL wie folgt anweisen, Signale nicht zu verwenden:
CFLAGS=-DDONT_USE_THR_ALARM \ CXXFLAGS=-DDONT_USE_THR_ALARM \ ./configure ...
Hierdurch wird die Leistungsfähigkeit von MySQL nicht beeinträchtigt; ein Nebeneffekt besteht aber darin, dass Sie Clients, die an einer Verbindung „schlafen“, mit mysqladmin kill oder mysqladmin shutdown nicht terminieren können. Stattdessen hängt sich der Client auf, wenn er den nächsten Befehl absetzt.
Bei gcc 2.95.2 erhalten Sie möglicherweise den folgenden Kompilierungsfehler:
sql_acl.cc:1456: Internal compiler error in `scan_region', at except.c:2566 Please submit a full bug report.
Um dies zu beheben, sollten Sie in das Verzeichnis
sql
wechseln und dort die letzte
gcc-Zeile ausschneiden und einfügen, die
Option -O3
dabei jedoch zu
-O0
ändern (oder -O0
direkt
nach gcc hinzufügen, wenn Ihre
compile-Zeile gar keine -O
-Option enthält).
Danach können Sie wieder zum obersten Verzeichnis wechseln
und make erneut ausführen.
Wenn Sie Irix 6.5.3 oder höher verwenden, kann
mysqld Threads nur dann erstellen, wenn Sie
es als Benutzer mit
CAP_SCHED_MGT
-Berechtigungen (z. B. als
root
) ausführen oder dem Server
mysqld diese Berechtigung mit dem folgenden
Shell-Befehl zuweisen:
chcap "CAP_SCHED_MGT+epi" /opt/mysql/libexec/mysqld
Unter Umständen müssen Sie die Definitionen einiger Symbole
in config.h
nach der Ausführung von
configure, aber vor der Kompilierung
aufheben.
Bei einigen Irix-Implementierungen ist die Funktion
alloca()
beschädigt. Wenn der
mysqld-Server sich bei einigen
SELECT
-Anweisungen aufhängt, entfernen Sie
die Zeilen aus config.h
, die
HAVE_ALLOC
und
HAVE_ALLOCA_H
definieren. Funktioniert
mysqladmin create nicht, dann entfernen Sie
die Zeile aus config.h
, die
HAVE_READDIR_R
definiert. Möglicherweise
müssen Sie auch die Zeile HAVE_TERM_H
entfernen.
SGI empfiehlt, alle Patches auf der folgenden Seite auf einmal zu installieren: http://support.sgi.com/surfzone/patches/patchset/6.2_indigo.rps.html.
Sie sollten zumindest das jeweils letzte Kernel-,
rld
- und libc
-Rollup
installieren.
Für die pthreads-Unterstützung benötigen Sie in jedem Fall alle POSIX-Patches auf der folgenden Seite:
http://support.sgi.com/surfzone/patches/patchset/6.2_posix.rps.html
Möglicherweise erhalten Sie bei der Kompilierung von
mysql.cc
eine Fehlermeldung ähnlich der
folgenden:
"/usr/include/curses.h", line 82: error(1084): invalid combination of type
Geben Sie in diesem Fall Folgendes im obersten Verzeichnis Ihres MySQL-Source-Trees ein:
extra/replace bool curses_bool < /usr/include/curses.h > include/curses.h make
Gemeldet wurden ferner Zeitplanungsprobleme. Wird nur ein Thread ausgeführt, dann ist die Performance schwach. Dies können Sie vermeiden, indem Sie einen anderen Client starten. Dies hat unter Umständen eine zwei- bis zehnfache Steigerung der Ausführungsgeschwindigkeit für den anderen Thread zur Folge. Dieses Problem mit Irix-Threads ist schlecht nachvollziehbar: Bis es behoben ist, müssen Sie wohl improvisieren, um geeignete Lösungen zu finden.
Wenn Sie mit gcc kompilieren, können Sie den folgenden configure-Befehl verwenden:
CC=gcc CXX=gcc CXXFLAGS=-O3 \ ./configure --prefix=/usr/local/mysql --enable-thread-safe-client \ --with-named-thread-libs=-lpthread
Unter Irix 6.5.11 mit nativen Irix-C- und -C++-Compilern der Version 7.3.1.2 funktioniert Angaben zufolge auch Folgendes:
CC=cc CXX=CC CFLAGS='-O3 -n32 -TARG:platform=IP22 -I/usr/local/include \ -L/usr/local/lib' CXXFLAGS='-O3 -n32 -TARG:platform=IP22 \ -I/usr/local/include -L/usr/local/lib' \ ./configure --prefix=/usr/local/mysql --with-innodb --with-berkeley-db \ --with-libwrap=/usr/local \ --with-named-curses-libs=/usr/local/lib/libncurses.a
Die aktuelle Portierung wird nur auf Systemen unter sco3.2v5.0.5, sco3.2v5.0.6 und sco3.2v5.0.7 getestet. Die Portierung auf sco3.2v4.2 ist ebenfalls weit fortgeschritten. Open Server 5.0.8 (Legend) bietet native Threads und unterstützt Dateien, die größer sind als 2 Gbyte. Das aktuelle Limit bei der Dateigröße liegt bei 2 Gbyte.
Wir konnten MySQL mit dem folgenden configure-Befehl unter OpenServer mit gcc 2.95.3 kompilieren.
CC=gcc CXX=gcc ./configure --prefix=/usr/local/mysql \ --enable-thread-safe-client --with-innodb \ --with-openssl --with-vio --with-extra-charsets=complex
gcc erhalten Sie unter ftp://ftp.sco.com/pub/openserver5/opensrc/gnutools-5.0.7Kj.
Dieses Entwicklungssystem erfordert das OpenServer Execution
Environment Supplement oss646B unter OpenServer 5.0.6 und
oss656B und die in gwxlibs enthaltenen
OpenSource-Bibliotheken. Alle OpenSource-Tools befinden sich
im Verzeichnis opensrc
. Sie finden sie
unter
ftp://ftp.sco.com/pub/openserver5/opensrc/.
Wir empfehlen die Verwendung des aktuellen Produktions-Releases von MySQL.
SCO stellt Betriebssystem-Patches unter ftp://ftp.sco.com/pub/openserver5 für OpenServer 5.0.[0-6] und unter ftp://ftp.sco.com/pub/openserverv5/507 für OpenServer 5.0.7 bereit.
Informationen zu behobenen Sicherheitslücken bietet SCO unter ftp://ftp.sco.com/pub/security/OpenServer für OpenServer 5.0.x an.
Die maximale Dateigröße auf einem OpenServer 5.0.x-System beträgt 2 Gbyte.
Die Gesamtmenge an Speicher, der für Stream-Puffer, CLISTs und Sperrdatensätze zugewiesen wird, darf unter OpenServer 5.0.x einen Wert von 60 Mbyte nicht überschreiten.
Stream-Puffer werden in Einheiten von 4096 Byte großen Seiten zugewiesen, CLISTs haben jeweils 70 Byte, und Sperrdatensätze sind je 64 Byte groß. Hieraus ergibt sich:
(NSTRPAGES * 4096) + (NCLIST * 70) + (MAX_FLCKREC * 64) <= 62914560
Gehen Sie wie folgt vor, um die Option Database
Services
zu konfigurieren. Wenn Sie nicht genau
wissen, ob eine Anwendung dies erfordert, schlagen Sie in der
Dokumentation dieser Anwendung nach.
Melden Sie sich als root
an.
Aktivieren Sie den SUDS-Treiber, indem Sie die Datei
/etc/conf/sdevice.d/suds
bearbeiten.
Ändern Sie das N
im zweiten Feld zu
Y
.
Aktivieren Sie mithilfe von mkdev aio
oder des Hardware/Kernel-Managers die Unterstützung für
asynchrone Eingabe/Ausgabe und verknüpfen Sie den Kernel
neu. Damit Benutzer Speicher für die Verwendung mit
diesem E/A-Typ verriegeln können, aktualisieren Sie die
Datei aiomemlock(F)
. Diese Datei
sollte mit den Namen der Benutzer, die AIO verwenden
dürfen, und der maximalen Speichermenge aktualisiert
werden, die diese Benutzer sperren dürfen.
Viele Anwendungen verwenden setuid-Binärdateien, d. h., Sie müssen nur einen Benutzer angeben. Konsultieren Sie die Dokumentation zur fraglichen Anwendung, um zu ermitteln, ob dies bei dieser Anwendung der Fall ist.
Nachdem Sie den Vorgang abgeschlossen haben, starten Sie das System neu, um einen neuen Kernel zu erstellen, der diese Änderungen beinhaltet.
Standardmäßig haben die Einträge in
/etc/conf/cf.d/mtune
folgende
Einstellungen:
Value Default Min Max ----- ------- --- --- NBUF 0 24 450000 NHBUF 0 32 524288 NMPBUF 0 12 512 MAX_INODE 0 100 64000 MAX_FILE 0 100 64000 CTBUFSIZE 128 0 256 MAX_PROC 0 50 16000 MAX_REGION 0 500 160000 NCLIST 170 120 16640 MAXUP 100 15 16000 NOFILES 110 60 11000 NHINODE 128 64 8192 NAUTOUP 10 0 60 NGROUPS 8 0 128 BDFLUSHR 30 1 300 MAX_FLCKREC 0 50 16000 PUTBUFSZ 8000 2000 20000 MAXSLICE 100 25 100 ULIMIT 4194303 2048 4194303 * Streams Parameters NSTREAM 64 1 32768 NSTRPUSH 9 9 9 NMUXLINK 192 1 4096 STRMSGSZ 16384 4096 524288 STRCTLSZ 1024 1024 1024 STRMAXBLK 524288 4096 524288 NSTRPAGES 500 0 8000 STRSPLITFRAC 80 50 100 NLOG 3 3 3 NUMSP 64 1 256 NUMTIM 16 1 8192 NUMTRW 16 1 8192 * Semaphore Parameters SEMMAP 10 10 8192 SEMMNI 10 10 8192 SEMMNS 60 60 8192 SEMMNU 30 10 8192 SEMMSL 25 25 150 SEMOPM 10 10 1024 SEMUME 10 10 25 SEMVMX 32767 32767 32767 SEMAEM 16384 16384 16384 * Shared Memory Parameters SHMMAX 524288 131072 2147483647 SHMMIN 1 1 1 SHMMNI 100 100 2000 FILE 0 100 64000 NMOUNT 0 4 256 NPROC 0 50 16000 NREGION 0 500 160000
Wir empfehlen die Einstellung folgender Werte:
NOFILES
sollte 4096 oder 2048 sein.
MAXUP
sollte 2048 sein.
Um Änderungen am Kernel vorzunehmen, wechseln Sie in das
Verzeichnis /etc/conf/bin
und nehmen die
erforderlichen Änderungen mit ./idtune
name parameter
vor. Um
beispielsweise SEMMS
auf
200
zu setzen, führen Sie folgende Befehle
als root
aus:
# cd /etc/conf/bin # ./idtune SEMMNS 200
Wir empfehlen eine Optimierung des Systems. Welche
Parameterwerte allerdings hierzu geeignet sind, hängt von der
Anzahl der Benutzer, die auf die Anwendung oder Datenbank
zugreifen, und von der Größe der Datenbank selbst (d. h.
dem verwendeten Pufferpool) ab. Das Folgende betrifft die
Kernel-Parameter, die in
/etc/conf/cf.d/stune
definiert sind:
SHMMAX
(Einstellempfehlung: 128 Mbyte) und
SHMSEG
(Einstellempfehlung: 15). Diese
Parameter beeinflussen die MySQL-Datenbank-Engine bei der
Erstellung der Benutzerpufferpools.
NOFILES
und MAXUP
sollten auf mindestens 2048 gesetzt werden.
MAXPROC
sollte (abhängig von der Anzahl
der Benutzer) auf mindestens 3000/4000 gesetzt werden.
Ferner wird die Verwendung der folgenden Formel zur Berechnung
der Werte für SEMMSL
,
SEMMNS
und SEMMNU
empfohlen:
SEMMSL = 13
13 hat sich als optimaler Wert sowohl für Progress als auch für MySQL erwiesen.
SEMMNS
= SEMMSL
×
Anzahl der auf dem System ausgeführten Server
Setzen Sie SEMMNS
auf den Wert von
SEMMSL
multipliziert mit der maximalen
Anzahl der Datenbankserver, die gleichzeitig auf Ihrem System
ausgeführt werden.
SEMMNU = SEMMNS
SEMMNU
setzen Sie dann auf den gleichen
Wert wie SEMMNS
. Wahrscheinlich würde hier
auch ein Wert von 75 Prozent von SEMMNS
ausreichen, aber dies ist eine konservative Schätzung.
Sie müssen zumindest die "SCO OpenServer Linker and Application Development Libraries" oder das OpenServer Development System installieren, um gcc verwenden zu können. Das GCC Dev-System können Sie nicht nutzen, ohne mindestens eine dieser Komponenten zu installieren.
Zunächst sollten Sie sich jedoch das FSU-Pthreads-Paket beschaffen und es installieren. Sie finden es unter http://moss.csc.ncsu.edu/~mueller/ftp/pub/PART/pthreads.tar.gz. Eine vorkompilierte Fassung finden Sie unter ftp://ftp.zenez.com/pub/zenez/prgms/FSU-threads-3.14.tar.gz.
FSU-Pthreads kann mit SCO Unix 4.2 mit tcpip oder aber
mithilfe von OpenServer 3.0 oder Open Desktop 3.0 (OS 3.0 ODT
3.0) mit installiertem SCO Development System kompiliert
werden, wobei eine gute Portierung von GCC 2.5.x zum Einsatz
kommen sollte. Für ODT oder OS 3.0 benötigen Sie eine gute
Portierung von GCC 2.5.x. Ohne eine solche gute Portierung
können eine Menge Probleme entstehen. Die Portierung für
dieses Produkt erfordert das SCO Unix Development-System. Ohne
dieses fehlen Ihnen die Bibliotheken und der erforderliche
Linker. Ferner benötigen Sie
SCO-3.2v4.2-includes.tar.gz
. Diese Datei
enthält die Änderungen an den Include-Dateien des SCO
Development Systems, die für die Erstellung von MySQL
benötigt werden. Sie müssen die vorhandenen
System-Include-Dateien durch diese modifizierten
Header-Dateien ersetzen. Sie erhalten sie unter
ftp://ftp.zenez.com/pub/zenez/prgms/SCO-3.2v4.2-includes.tar.gz.
Um FSU-Pthreads auf Ihrem System zu erstellen, sollten Sie
nichts weiteres tun müssen, als GNU make
auszuführen. Das Makefile
in
FSU-threads-3.14.tar.gz ist so konfiguriert, dass es
FSU-threads erstellt.
Sie können ./configure im Verzeichnis
threads/src
ausführen und die Option SCO
OpenServer auswählen. Dieser Befehl kopiert
Makefile.SCO5
nach
Makefile
. Danach führen Sie
make aus.
Zur Installation in das Standardverzeichnis
/usr/include
melden Sie sich als
root
und wechseln dann in das Verzeichnis
thread/src
. Dort führen Sie
make install aus.
Denken Sie daran, GNU make zur Erstellung von MySQL zu verwenden.
Hinweis: Wenn Sie
mysqld_safe nicht als
root
starten, erhalten Sie nur die
standardmäßig vorgesehenen 110 offenen Dateien pro Prozess.
mysqld schreibt eine entsprechende
Anmerkung in die Logdatei.
Bei SCO 3.2V4.2 sollten Sie FSU-Pthreads Version 3.14 oder höher verwenden. Der folgende configure-Befehl sollte funktionieren:
CFLAGS="-D_XOPEN_XPG4" CXX=gcc CXXFLAGS="-D_XOPEN_XPG4" \ ./configure \ --prefix=/usr/local/mysql \ --with-named-thread-libs="-lgthreads -lsocket -lgen -lgthreads" \ --with-named-curses-libs="-lcurses"
Unter Umständen treten Probleme mit einigen Include-Dateien auf. In diesem Fall finden Sie neue SCO-spezifische Include-Dateien unter ftp://ftp.zenez.com/pub/zenez/prgms/SCO-3.2v4.2-includes.tar.gz.
Sie sollten diese Datei in das Verzeichnis
include
Ihres MySQL-Source-Trees
entpacken.
Anmerkungen zur SCO-Entwicklung:
MySQL sollte FSU-Pthreads automatisch erkennen und
mysqld mit -lgthreads -lsocket
-lgthreads
verknüpfen.
Die SCO-Entwicklungsbibliotheken sind in FSU-Pthreads mehrfach aufrufbar. SCO behauptet, dass seine Bibliothek mehrfach aufrufbar ist, mithin muss sie also auch bei FSU-Pthreads mehrfach aufrufbar sein. FSU-Pthreads unter OpenServer versucht, mithilfe des SCO-Schemas mehrfach aufrufbare Bibliotheken zu erstellen.
FSU-Pthreads wird mit GNU malloc
verknüpft ausgeliefert (zumindest gilt dies für die
Version unter ftp::/ftp.zenez.com). Wenn
Probleme mit der Speichernutzung auftreten, vergewissern
Sie sich, dass gmalloc.o
in
libgthreads.a
und
libgthreads.so
enthalten ist.
In FSU-Pthreads erkennen die folgenden Systemaufrufe das
Vorhandensein von pthreads: read()
,
write()
, getmsg()
,
connect()
, accept(),
select()
und wait()
.
Der Patch CSSA-2001-SCO.35.2, der üblicherweise als Sicherheits-Patch erg711905-dscr_remap (version 2.0.0) gelistet ist, beschädigt FSU-Threads und macht mysqld instabil. Wenn Sie mysqld auf einem System unter OpenServer 5.0.6 verwenden wollen, müssen Sie diesen Patch entfernen.
Setzen Sie SCO OpenServer 5 ein, dann müssen Sie unter
Umständen FSU-Pthreads mit -DDRAFT7
in
CFLAGS
neu kompilieren. Andernfalls
hängt sich InnoDB
beim Start von
mysqld auf.
SCO bietet Betriebssystem-Patches unter ftp://ftp.sco.com/pub/openserver5 für OpenServer 5.0.x.
Fehlerbehebungen für Sicherheitslücken und
libsocket.so.2
bietet SCO unter
ftp://ftp.sco.com/pub/security/OpenServer
und ftp://ftp.sco.com/pub/security/sse für
OpenServer 5.0.x an.
Sicherheitsrelevante Fehlerbehebungen für OpenServer vor
OSR506 und den Bugfix für telnetd
finden Sie unter
ftp://stage.caldera.com/pub/security/openserver/
oder
ftp://stage.caldera.com/pub/security/openserver/CSSA-2001-SCO.10/
als libsocket.so.2
und
libresolv.so.1
mit Anweisungen zur
Installation auf Systemen vor OSR506.
Es empfiehlt sich wohl, diese Patches vor der Kompilierung und Verwendung von MySQL zu installieren.
Ab Legend/OpenServer 6.0.0 gibt es native Threads, und die Beschränkung der Dateigröße auf 2 Gbyte entfällt.
OpenServer 6 enthält die folgenden wesentlichen Verbesserungen:
Unterstützung für Dateien bis zu 1 Tbyte
Multiprozessorunterstützung für bis zu 32 Prozessoren
verbesserte Speicherunterstützung für bis zu 64 Gbyte
Leistungserweiterung von UnixWare auf OpenServer 6
drastische Leistungssteigerungen
OpenServer 6.0.0-Befehle sind wie folgt organisiert:
/bin
ist für Befehle vorgesehen, die
sich exakt so verhalten wie unter OpenServer 5.0.x.
/u95/bin
ist für Befehle vorgesehen,
die eine erhöhte Standardkonformität aufweisen. Hierzu
gehört z. B. die LFS-Unterstützung (Large File System).
/udk/bin
ist für Befehle vorgesehen,
die sich exakt so verhalten wie unter UnixWare 7.1.4.
Standardmäßig wird LFS unterstützt.
Nachfolgend erhalten Sie eine Anleitung zur Einstellung von
PATH unter OpenServer 6. Wenn der Benutzer das traditionelle
Verhalten von OpenServer 5.0.x wünscht, sollte
PATH
zunächst /bin
sein. Wünscht der Benutzer LFS-Unterstützung, dann sollte
der Pfad /u95/bin:/bin
sein. Benötigt
der Benutzer zunächst UnixWare 7-Unterstützung, dann wäre
der korrekte Pfad
/udk/bin:/u95/bin:/bin:
.
Wir empfehlen die Verwendung des aktuellen Produktions-Releases von MySQL.
Wir konnten MySQL mit dem folgenden configure-Befehl unter OpenServer 6.0.x kompilieren.
CC="cc" CFLAGS="-I/usr/local/include" \ CXX="CC" CXXFLAGS="-I/usr/local/include" \ ./configure --prefix=/usr/local/mysql \ --enable-thread-safe-client --with-berkeley-db=./bdb \ --with-innodb --with-openssl --with-extra-charsets=complex \ --enable-readline
Wenn Sie gcc verwenden wollen, müssen Sie gcc 2.95.3 oder höher einsetzen.
CC=gcc CXX=g++ ./configure --prefix=/usr/local/mysql
Die Version von Berkeley DB, die Bestandteil von UnixWare
7.1.4 wie auch von OpenServer 6.0.0 ist, wird bei der
Erstellung von MySQL nicht eingesetzt. Stattdessen verwendet
MySQL seine eigene Version von Berkeley DB. Der Befehl
configure muss sowohl eine statische als
auch eine dynamische Bibliothek in
erstellen, aber dies nicht mit MySQLs eigener
src_directory
/bdb/build_unix/BDB
-Version. Der Workaround sieht wie folgt
aus:
Führen Sie die normalen für MySQL erforderlichen Konfigurationsarbeiten durch.
cd bdb/build_unix/
cp -p Makefile to Makefile.sav
Führen Sie unter Verwendung derselben Optionen ../dist/configure aus.
Führen Sie gmake aus.
cp -p Makefile.sav Makefile
Wechseln Sie in das oberste Quellverzeichnis und führen Sie gmake aus.
Auf diese Weise lassen sich sowohl die statischen als auch die
dynamischen Bibliotheken erstellen und zum Laufen bringen.
OpenServer 6.0.0 erfordert auch, dass Patches für den
MySQL-Source-Tree und der Patch für
config.guess
auf
bdb/dist/config.guess
angewendet werden.
Sie können die Patches unter
ftp://ftp.zenez.com/pub/zenez/prgms/mysql-4.1.12-osr6-patches.tar.gz
bzw.
ftp://ftp.zenez.com/pub/zenez/prgms/mysql-4.x.x-osr6-patches herunterladen.
Lesen Sie die beigefügte Datei README
,
um Hilfe zu erhalten.
SCO stellt Betriebssystem-Patches für OpenServer 6 unter ftp://ftp.sco.com/pub/openserver6 bereit.
Informationen zu behobenen Sicherheitslücken bietet SCO unter ftp://ftp.sco.com/pub/security/OpenServer.
Standardmäßig beträgt die maximale Dateigröße auf einem OpenServer 6.0.0-System 1 Tbyte. Einige Betriebssystem-Hilfsprogramme weisen eine Beschränkung auf 2 Gbyte auf. Die maximale Dateigröße unter UnixWare 7 beträgt 1 Tbyte mit VXFS oder HTFS.
Standardmäßig haben die Einträge in
/etc/conf/cf.d/mtune
folgende
Einstellungen:
Value Default Min Max ----- ------- --- --- SVMMLIM 0x9000000 0x1000000 0x7FFFFFFF HVMMLIM 0x9000000 0x1000000 0x7FFFFFFF SSTKLIM 0x1000000 0x2000 0x7FFFFFFF HSTKLIM 0x1000000 0x2000 0x7FFFFFFF
Wir empfehlen die Einstellung folgender Werte:
SDATLIM 0x7FFFFFFF HDATLIM 0x7FFFFFFF SSTKLIM 0x7FFFFFFF HSTKLIM 0x7FFFFFFF SVMMLIM 0x7FFFFFFF HVMMLIM 0x7FFFFFFF SFNOLIM 2048 HFNOLIM 2048
Wir empfehlen eine Optimierung des Systems. Welche
Parameterwerte allerdings hierzu geeignet sind, hängt von der
Anzahl der Benutzer, die auf die Anwendung oder Datenbank
zugreifen, und von der Größe der Datenbank selbst (d. h.
dem verwendeten Pufferpool) ab. Das Folgende betrifft die
Kernel-Parameter, die in
/etc/conf/cf.d/stune
definiert sind:
SHMMAX
(Einstellempfehlung: 128 Mbyte) und
SHMSEG
(Einstellempfehlung: 15). Diese
Parameter beeinflussen die MySQL-Datenbank-Engine bei der
Erstellung der Benutzerpufferpools.
SFNOLIM
und HFNOLIM
sollten auf maximal 2048 gesetzt werden.
NPROC
sollte (abhängig von der Anzahl der
Benutzer) auf mindestens 3000/4000 gesetzt werden.
Ferner wird die Verwendung der folgenden Formel zur Berechnung
der Werte für SEMMSL
,
SEMMNS
und SEMMNU
empfohlen:
SEMMSL = 13
13 hat sich als optimaler Wert sowohl für Progress als auch für MySQL erwiesen.
SEMMNS
= SEMMSL
×
Anzahl der auf dem System ausgeführten Server
Setzen Sie SEMMNS
auf den Wert von
SEMMSL
multipliziert mit der maximalen
Anzahl der Datenbankserver, die gleichzeitig auf Ihrem System
ausgeführt werden.
SEMMNU
= SEMMNS
SEMMNU
setzen Sie dann auf den gleichen
Wert wie SEMMNS
. Wahrscheinlich würde hier
auch ein Wert von 75 Prozent von SEMMNS
ausreichen, aber dies ist eine konservative Schätzung.
Wir empfehlen die Verwendung des aktuellen Produktions-Releases von MySQL.
Wir konnten MySQL mit dem folgenden configure-Befehl unter UnixWare 7.1.x kompilieren.
CC="cc" CFLAGS="-I/usr/local/include" \ CXX="CC" CXXFLAGS="-I/usr/local/include" \ ./configure --prefix=/usr/local/mysql \ --enable-thread-safe-client --with-berkeley-db=./bdb \ --with-innodb --with-openssl --with-extra-charsets=complex
Wenn Sie gcc verwenden wollen, müssen Sie gcc 2.95.3 oder höher einsetzen.
CC=gcc CXX=g++ ./configure --prefix=/usr/local/mysql
Die Version von Berkeley DB, die Bestandteil von UnixWare
7.1.4 wie auch von OpenServer 6.0.0 ist, wird bei der
Erstellung von MySQL nicht eingesetzt. Stattdessen verwendet
MySQL seine eigene Version von Berkeley DB. Der Befehl
configure muss sowohl eine statische als
auch eine dynamische Bibliothek in
erstellen, aber dies nicht mit MySQLs eigener
src_directory
/bdb/build_unix/BDB
-Version. Der Workaround sieht wie folgt
aus:
Führen Sie die normalen für MySQL erforderlichen Konfigurationsarbeiten durch.
cd bdb/build_unix/
cp -p Makefile to Makefile.sav
Führen Sie unter Verwendung derselben Optionen ../dist/configure aus.
Führen Sie gmake aus.
cp -p Makefile.sav Makefile
Wechseln Sie in das oberste Quellverzeichnis und führen Sie gmake aus.
Auf diese Weise lassen sich sowohl die statischen als auch die dynamischen Bibliotheken erstellen und zum Laufen bringen.
SCO bietet Betriebssystem-Patches unter ftp://ftp.sco.com/pub/unixware7 für UnixWare 7.1.1, unter ftp://ftp.sco.com/pub/unixware7/713/ für UnixWare 7.1.3, unter ftp://ftp.sco.com/pub/unixware7/714/ für UnixWare 7.1.4 und unter ftp://ftp.sco.com/pub/openunix8 für OpenUNIX 8.0.0 an.
Informationen zu behobenen Sicherheitslücken bietet SCO unter ftp://ftp.sco.com/pub/security/OpenUNIX für OpenUNIX und unter ftp://ftp.sco.com/pub/security/UnixWare für UnixWare an.
Standardmäßig beträgt die maximale Dateigröße auf einem UnixWare 7.1.1-System 1 Gbyte, bei UnixWare 7.1.4 ist die Größe hingegen auf 1 Tbyte mit VXFS beschränkt. Einige Betriebssystem-Hilfsprogramme weisen eine Beschränkung auf 2 Gbyte auf. Die maximal mögliche Dateigröße unter UnixWare 7 beträgt 1 Tbyte mit VXFS.
Unter UnixWare 7.1.4 müssen Sie nichts tun, um in den Genuss
der Unterstützung großer Dateien zu kommen. Bei Versionen
vor UnixWare 7.1.x müssen Sie zu diesem Zweck
fsadm
ausführen.
# fsadm -Fvxfs -o largefiles / # fsadm / * Note # ulimit unlimited # cd /etc/conf/bin # ./idtune SFSZLIM 0x7FFFFFFF ** Note # ./idtune HFSZLIM 0x7FFFFFFF ** Note # ./idbuild -B * This should report "largefiles". ** 0x7FFFFFFF represents infinity for these values.
Starten Sie das System mit shutdown
neu.
Standardmäßig haben die Einträge in
/etc/conf/cf.d/mtune
folgende
Einstellungen:
Value Default Min Max ----- ------- --- --- SVMMLIM 0x9000000 0x1000000 0x7FFFFFFF HVMMLIM 0x9000000 0x1000000 0x7FFFFFFF SSTKLIM 0x1000000 0x2000 0x7FFFFFFF HSTKLIM 0x1000000 0x2000 0x7FFFFFFF
Wir empfehlen die Einstellung folgender Werte:
SDATLIM 0x7FFFFFFF HDATLIM 0x7FFFFFFF SSTKLIM 0x7FFFFFFF HSTKLIM 0x7FFFFFFF SVMMLIM 0x7FFFFFFF HVMMLIM 0x7FFFFFFF SFNOLIM 2048 HFNOLIM 2048
Wir empfehlen eine Optimierung des Systems. Welche
Parameterwerte allerdings hierzu geeignet sind, hängt von der
Anzahl der Benutzer, die auf die Anwendung oder Datenbank
zugreifen, und von der Größe der Datenbank selbst (d. h.
dem verwendeten Pufferpool) ab. Das Folgende betrifft die
Kernel-Parameter, die in
/etc/conf/cf.d/stune
definiert sind:
SHMMAX
(Einstellempfehlung: 128 Mbyte) und
SHMSEG
(Einstellempfehlung: 15). Diese
Parameter beeinflussen die MySQL-Datenbank-Engine bei der
Erstellung der Benutzerpufferpools.
SFNOLIM
und HFNOLIM
sollten auf maximal 2048 gesetzt werden.
NPROC
sollte (abhängig von der Anzahl der
Benutzer) auf mindestens 3000/4000 gesetzt werden.
Ferner wird die Verwendung der folgenden Formel zur Berechnung
der Werte für SEMMSL
,
SEMMNS
und SEMMNU
empfohlen:
SEMMSL = 13
13 hat sich als optimaler Wert sowohl für Progress als auch für MySQL erwiesen.
SEMMNS
= SEMMSL
×
Anzahl der auf dem System ausgeführten Server
Setzen Sie SEMMNS
auf den Wert von
SEMMSL
multipliziert mit der maximalen
Anzahl der Datenbankserver, die gleichzeitig auf Ihrem System
ausgeführt werden.
SEMMNU
= SEMMNS
SEMMNU
setzen Sie dann auf den gleichen
Wert wie SEMMNS
. Wahrscheinlich würde hier
auch ein Wert von 75 Prozent von SEMMNS
ausreichen, aber dies ist eine konservative Schätzung.
MySQL verwendet eine ganze Menge offener Dateien. Aus diesem
Grund sollten Sie Ihre Datei CONFIG.SYS
um
etwas in der Art des Folgenden ergänzen:
SET EMXOPT=-c -n -h1024
Andernfalls könnte der folgende Fehler auftreten:
File 'xxxx
' not found (Errcode: 24)
Wenn Sie MySQL mit OS/2 Warp 3 verwenden, benötigen Sie FixPack 29 oder höher. Bei OS/2 Warp 4 ist FixPack 4 oder höher erforderlich. Dies ist eine Anforderung der Pthreads-Bibliothek. MySQL muss auf einer Partition eines Typs installiert sein, der lange Dateinamen benutzt (also etwa HPFS, FAT32 usw.).
Das Skript INSTALL.CMD
muss aus der
OS/2-eigenen CMD.EXE
ausgeführt werden und
funktioniert unter Ersatz-Shells wie
4OS2.EXE
unter Umständen nicht.
Das Skript scripts/mysql-install-db
wurde
umbenannt. Es heißt install.cmd
und ist
ein REXX-Skript, das die Standardsicherheitseinstellungen von
MySQL einrichtet und die WorkPlace-Shell-Symbole für MySQL
erstellt.
Dynamische Module sind einkompiliert, wurden aber nicht vollständig getestet. Dynamische Module sollten mit der Pthreads-Laufzeitbibliothek kompiliert werden.
gcc -Zdll -Zmt -Zcrtdll=pthrdrtl -I../include -I../regex -I.. \ -o example udf_example.cc -L../lib -lmysqlclient udf_example.def mv example.dll example.udf
Hinweis: Aufgrund der
Beschränkungen in OS/2 dürfen UDF-Modulnamenstämme nicht
länger als acht Zeichen sein. Module werden im Verzeichnis
/mysql2/udf
gespeichert, welches vom Skript
safe-mysqld.cmd
in der Umgebungsvariablen
BEGINLIBPATH
abgelegt wird. Wenn Sie
UDF-Module verwenden, werden die angegebenen Erweiterungen
ignoriert (es wird davon ausgegangen, dass diese ohnehin immer
.udf
lauten). Beispielsweise kann das
gemeinsame Modul unter Unix example.so
heißen; eine Funktion daraus würden Sie dann wie folgt laden:
mysql> CREATE FUNCTION metaphon RETURNS STRING SONAME 'example.so';
Bei OS/2 hieße das Modul example.udf
, aber
Sie würden die Modulerweiterung nicht angeben:
mysql> CREATE FUNCTION metaphon RETURNS STRING SONAME 'example';
Die Perl-Unterstützung für MySQL erfolgt mithilfe der
DBI
-/DBD
-Clientschnittstelle.
Die Schnittstelle erfordert Perl 5.6.1 oder höher. Sie
funktioniert nicht, wenn Sie eine ältere
Perl-Version einsetzen.
Wenn Sie Transaktionen mit Perl DBI verwenden wollen, brauchen Sie
DBD::mysql
in der Version 1.2216 oder höher.
Empfohlen wird DBD::mysql
2.9003 oder höher.
Sofern Sie MySQL 4.1 oder eine neuere Clientbibliothek verwenden,
müssen Sie DBD::mysql
2.9003 oder höher in
jedem Fall einsetzen.
Die Perl-Unterstützung ist nicht in den MySQL-Distributionen enthalten. Die erforderlichen Module für Unix erhalten Sie unter http://search.cpan.org bzw. für Windows durch Verwendung des ActiveState-Programms ppm. Die folgenden Abschnitte beschreiben die erforderlichen Abläufe.
Wenn Sie die MySQL-Benchmark-Skripten ausführen wollen, muss der Perl-Support für MySQL installiert sein. Siehe auch Abschnitt 7.1.4, „Die MySQL-Benchmark-Reihe“.
Die Perl-Unterstützung durch MySQL setzt voraus, dass Sie die Unterstützung für die MySQL-Clientprogrammierung (Bibliotheken und Header-Dateien) installiert haben. Bei den meisten Installationsmethoden werden die notwendigen Dateien installiert. Haben Sie MySQL allerdings aus RPM-Dateien für Linux installiert, dann vergewissern Sie sich, dass Sie das Entwickler-RPM zur Installation verwendet haben. Die Clientprogramme befinden sich im Client-RPM, die Unterstützung für die Clientprogrammierung jedoch im Entwickler-RPM.
Wenn Sie die Perl-Unterstützung installieren wollen, erhalten Sie die erforderlichen Dateien beim CPAN (Comprehensive Perl Archive Network) unter http://search.cpan.org.
Die einfachste Möglichkeit, Perl-Module unter Unix zu
installieren, besteht in der Verwendung des
CPAN
-Moduls. Ein Beispiel:
shell> perl -MCPAN -e shell
cpan> install DBI
cpan> install DBD::mysql
Die DBD::mysql
-Installation führt eine
Anzahl von Tests durch. Bei diesen Tests wird versucht, unter
Angabe der Standardwerte für Benutzername und Passwort eine
Verbindung zum lokalen MySQL Server herzustellen. (Der
Standardbenutzername ist unter Unix Ihr Anmeldename und unter
Windows ODBC
. Das Standardpasswort heißt
„no password“.) Wenn Sie mit diesen Einstellungen
keine Verbindung zum Server herstellen können, weil
beispielsweise Ihr Konto ein Passwort hat, dann schlagen die
Tests fehl. Sie können force install
DBD::mysql
verwenden, um fehlgeschlagene Tests zu
ignorieren.
DBI
benötigt das Modul
Data::Dumper
. Dieses ist unter Umständen
bereits installiert, andernfalls sollten Sie es vor der
Installation von DBI
installieren.
Es ist auch möglich, die Moduldistributionen in Form komprimierter tar-Archive herunterzuladen und die Module manuell zu erstellen. Um beispielsweise eine DBI-Distribution zu entpacken und zu erstellen, verwenden Sie folgende Vorgehensweise:
Entpacken Sie die Distribution in das aktuelle Verzeichnis:
shell> gunzip < DBI-VERSION
.tar.gz | tar xvf -
Dieser Befehl erstellt ein Verzeichnis namens
DBI-
.
VERSION
Wechseln Sie nun in das Stammverzeichnis der entpackten Distribution:
shell> cd DBI-VERSION
Erstellen Sie die Distribution und kompilieren Sie alles:
shell>perl Makefile.PL
shell>make
shell>make test
shell>make install
Der Befehl make test ist wichtig, da mit ihm
die Funktionsfähigkeit des Moduls verifiziert wird. Beachten
Sie, dass der MySQL Server laufen muss, wenn Sie diesen Befehl
während der DBD::mysql
-Installation
absetzen, um den Schnittstellencode auszuführen; andernfalls
schlägt der Test fehl.
Sie sollten die DBD::mysql
-Distribution bei
jeder Installation eines neuen MySQL-Releases neu erstellen und
installieren. Dies gilt insbesondere, wenn Sie beispielsweise
feststellen, dass all Ihre DBI
-Skripten nach
der Aktualisierung von MySQL nicht mehr funktionieren.
Wenn Sie nicht die erforderlichen Berechtigungen zur Installation von Perl-Modulen im Systemverzeichnis haben oder lokale Perl-Module installieren wollen, ist die folgende Referenz für Ihre Belange vielleicht recht nützlich: http://servers.digitaldaze.com/extensions/perl/modules.html#modules
Lesen Sie dort das Kapitel „Installing New Modules that Require Locally Installed Modules“.
Unter Windows müssen Sie Folgendes tun, um das
DBD
-Modul mit ActiveState-Perl zu
installieren:
Beschaffen Sie sich ActiveState Perl unter http://www.activestate.com/Products/ActivePerl/ und installieren Sie es.
Öffnen Sie ein Konsolenfenster („Eingabeaufforderung“).
Stellen Sie ggf. die Variable HTTP_proxy
ein. So kann etwa folgende Einstellung erforderlich sein:
set HTTP_proxy=my.proxy.com:3128
Starten Sie das PPM-Programm:
C:\> C:\perl\bin\ppm.pl
Installieren Sie DBI
, sofern Sie dies
nicht bereits getan haben:
ppm> install DBI
Führen Sie, wenn alles geklappt hat, folgenden Befehl aus:
install \ ftp://ftp.de.uu.net/pub/CPAN/authors/id/JWIED/DBD-mysql-1.2212.x86.ppd
Diese Vorgehensweise sollte bei ActiveState Perl 5.6 oder höher funktionieren.
Klappt dies nicht, dann sollten Sie stattdessen den MyODBC-Treiber installieren und über ODBC eine Verbindung zum MySQL Server herstellen:
use DBI; $dbh= DBI->connect("DBI:ODBC:$dsn",$user,$password) || die "Got error $DBI::errstr when connecting to $dsn\n";
Wenn Perl meldet, dass das Modul
../mysql/mysql.so
nicht gefunden werden
kann, dann liegt das wahrscheinlich daran, dass Perl die
gemeinsame Bibliothek libmysqlclient.so
nicht findet. Sie sollten dieses Problem auf eine der folgenden
Weisen lösen können:
Kompilieren Sie die Distribution
DBD::mysql
mit perl Makefile.PL
-static -config
statt mit perl
Makefile.PL
.
Kopieren Sie libmysqlclient.so
in das
Verzeichnis, in dem sich Ihre anderen gemeinsamen
Bibliotheken befinden (dies ist wahrscheinlich
/usr/lib
oder
/lib
).
Ändern Sie die -L
-Optionen zur
Kompilierung von DBD::mysql
so ab, dass
die tatsächliche Position von
libmysqlclient.so
berücksichtigt wird.
Unter Linux können Sie den Pfadnamen des Verzeichnisses, in
dem sich libmysqlclient.so
befindet,
zur Datei /etc/ld.so.conf
hinzufügen.
Fügen Sie den Pfadnamen des Verzeichnisses, in dem sich
libmysqlclient.so
befindet, der
Umgebungsvariablen LD_RUN_PATH
hinzu.
Einige Systeme verwenden stattdessen
LD_LIBRARY_PATH
.
Beachten Sie, dass Sie möglicherweise auch die
-L
-Optionen ändern müssen, wenn auch andere
Bibliotheken vom Linker nicht gefunden werden. Kann der Linker
beispielsweise libc
nicht finden, weil sich
die Datei in /lib
befindet, der
Verknüpfungsbefehl aber -L/usr/lib
angibt,
dann ändern Sie die Option -L
zu
-L/lib
oder fügen -L/lib
zum
vorhandenen Verknüpfungsbefehl hinzu.
Wenn Sie die folgenden Fehler von DBD::mysql
erhalten, verwenden Sie wahrscheinlich gcc
(oder eine alte Binärdatei, die mit gcc
kompiliert wurde):
/usr/bin/perl: can't resolve symbol '__moddi3' /usr/bin/perl: can't resolve symbol '__divdi3'
Fügen Sie -L/usr/lib/gcc-lib/... -lgcc
zum
Verknüpfungsbefehl hinzu, wenn die Bibliothek
mysql.so
erstellt wird (überprüfen Sie
die Ausgabe von make bezüglich
mysql.so
, wenn Sie den Perl-Client
kompilieren). Die -L
-Option sollte den
Pfadnamen des Verzeichnisses angeben, in dem
libgcc.a
auf Ihrem System gespeichert ist.
Eine andere Ursache dieses Problems könnte sein, dass nicht sowohl Perl als auch MySQL mit gcc kompiliert wurden. In diesem Fall können Sie die Nichtübereinstimmung beheben, indem Sie beide mit gcc kompilieren.
Wenn Sie die Tests ausführen, gibt
DBD::mysql
unter Umständen die folgende
Fehlermeldung aus:
t/00base............install_driver(mysql) failed: Can't load '../blib/arch/auto/DBD/mysql/mysql.so' for module DBD::mysql: ../blib/arch/auto/DBD/mysql/mysql.so: undefined symbol: uncompress at /usr/lib/perl5/5.00503/i586-linux/DynaLoader.pm line 169.
Dies bedeutet, dass Sie die Komprimierungsbibliothek
-lz
in der Verknüpfungszeile hinzufügen
müssen. Dies können Sie tun, indem Sie in der Datei
lib/DBD/mysql/Install.pm
die Zeile
$sysliblist .= " -lm";
wie folgt ändern:
$sysliblist .= " -lm -lz";
Danach müssen Sie make realclean ausführen und nachfolgend von vorne mit der Installation beginnen.
Wenn Sie DBI unter SCO installieren wollen, müssen Sie
Makefile
in
DBI-xxx
und allen Unterverzeichnissen
bearbeiten. Beachten Sie, dass das Folgende
gcc 2.95.2 oder höher voraussetzt:
OLD: NEW: CC = cc CC = gcc CCCDLFLAGS = -KPIC -W1,-Bexport CCCDLFLAGS = -fpic CCDLFLAGS = -wl,-Bexport CCDLFLAGS = LD = ld LD = gcc -G -fpic LDDLFLAGS = -G -L/usr/local/lib LDDLFLAGS = -L/usr/local/lib LDFLAGS = -belf -L/usr/local/lib LDFLAGS = -L/usr/local/lib LD = ld LD = gcc -G -fpic OPTIMISE = -Od OPTIMISE = -O1 OLD: CCCFLAGS = -belf -dy -w0 -U M_XENIX -DPERL_SCO5 -I/usr/local/include NEW: CCFLAGS = -U M_XENIX -DPERL_SCO5 -I/usr/local/include
Diese Änderungen sind erforderlich, weil der Perl-Dynaloader
die DBI
-Module nicht lädt, wenn diese mit
icc oder cc kompiliert
wurden.
Wollen Sie das Perl-Modul auf einem System verwenden, das keine
dynamischen Verknüpfungen unterstützt (wie z. B. SCO), dann
können Sie eine statische Perl-Version erzeugen, die
DBI
und DBD::mysql
enthält. Dies funktioniert so, dass Sie eine Perl-Version mit
verknüpftem DBI
-Code erzeugen und diese
über Ihre aktuelle Perl-Installation installieren. Dieses
verwenden Sie dann zur Erstellung einer Perl-Version, die
zusätzlich den verknüpften DBD
-Code
beinhaltet und die Sie dann installieren.
Unter SCO müssen Sie zuvor die folgenden Umgebungsvariablen einstellen:
LD_LIBRARY_PATH=/lib:/usr/lib:/usr/local/lib:/usr/progressive/lib
Oder:
LD_LIBRARY_PATH=/usr/lib:/lib:/usr/local/lib:/usr/ccs/lib:\ /usr/progressive/lib:/usr/skunk/lib LIBPATH=/usr/lib:/lib:/usr/local/lib:/usr/ccs/lib:\ /usr/progressive/lib:/usr/skunk/lib MANPATH=scohelp:/usr/man:/usr/local1/man:/usr/local/man:\ /usr/skunk/man:
Sie erstellen zunächst eine Perl-Version, die ein statisch
verknüpftes DBI
-Modul enthält. Dies tun Sie
durch Ausführen der folgenden Befehle in dem Verzeichnis, in
dem Ihre DBI
-Distribution gespeichert ist:
shell>perl Makefile.PL -static -config
shell>make
shell>make install
shell>make perl
Danach müssen Sie das neue Perl installieren. Die Ausgabe von make perl gibt den exakten make-Befehl an, den Sie ausführen müssen, um die Installation durchzuführen. Unter SCO heißt der Befehl make -f Makefile.aperl inst_perl MAP_TARGET=perl.
Als Nächstes verwenden Sie das gerade erstellte Perl zur
Erstellung eines anderen Perl, welches auch ein statisch
verknüpftes DBD::mysql
enthält. Hierzu
führen Sie die folgenden Befehle in dem Verzeichnis aus, in dem
sich Ihre DBD::mysql
-Distribution befindet:
shell>perl Makefile.PL -static -config
shell>make
shell>make install
shell>make perl
Abschließend sollten Sie dieses neue Perl installieren. Auch hier zeigt die Ausgabe von make perl den zu verwendenden Befehl an.
Inhaltsverzeichnis
mysql
im StapelbetriebAUTO_INCREMENT
Dieses Kapitel enthält eine Einführung in MySQL. Hier wird erläutert, wie mithilfe des mysql-Clientprogramms eine einfache Datenbank erstellt und verwendet wird. mysql (das manchmal auch als „Terminalmonitor“ oder einfach als „Monitor“ bezeichnet wird) ist ein interaktives Programm, das es Ihnen ermöglicht, Verbindungen mit einem MySQL Server herzustellen, Abfragen auszuführen und die Ergebnisse anzuzeigen. mysql kann auch im Stapelbetrieb verwendet werden: Sie legen Ihre Abfragen im Voraus in einer Datei ab und weisen mysql dann an, den Inhalt dieser Datei auszuführen. Wir werden hier beide Methoden der Verwendung von mysql behandeln.
Um eine Liste der Optionen anzuzeigen, die mysql
bietet, rufen Sie es mit der Option --help
auf:
shell> mysql --help
Dieses Kapitel setzt voraus, dass mysql auf Ihrem Computer installiert ist und dass ein MySQL Server verfügbar ist, mit dem Sie eine Verbindung herstellen können. Sollte dies nicht der Fall sein, dann wenden Sie sich an Ihren MySQL-Administrator. (Wenn Sie selbst der Administrator sind, lesen Sie die erforderlichen Abschnitte dieses Handbuchs, z. B. Kapitel 5, Datenbankverwaltung.)
Dieses Kapitel beschreibt den gesamten Vorgang der Einrichtung und Verwendung einer Datenbank. Wenn Sie nur am Zugriff auf eine vorhandene Datenbank interessiert sind, können Sie die Abschnitte überspringen, die beschreiben, wie Datenbanken und die darin enthaltenen Tabellen erstellt werden.
Da dieses Kapitel lediglich ein Tutorial ist, werden natürlich viele Detailangaben weggelassen. Um mehr zu den hier behandelten Themen zu erfahren, lesen Sie die einschlägigen Abschnitte dieses Handbuchs.
Um eine Verbindung mit dem Server herzustellen, müssen Sie beim Aufruf von mysql normalerweise einen MySQL-Benutzernamen und in aller Regel auch ein Passwort angeben. Wird der Server auf einem anderen System als demjenigen ausgeführt, an dem Sie sich anmelden, dann müssen Sie auch einen Hostnamen angeben. Wenden Sie sich an Ihrem Administrator, um zu erfahren, welche Parameter (Host- und Benutzernamen sowie Passwort) Sie für die Verbindung angeben müssen. Wenn Sie die korrekten Anmeldeinformationen kennen, sollten Sie wie folgt eine Verbindung herstellen können:
shell>mysql -h
Enter password:host
-uuser
-p********
host
und user
stehen für
den Namen des Hosts, auf dem Ihr MySQL Server ausgeführt wird,
bzw. den Benutzernamen Ihres MySQL-Kontos. Ersetzen Sie die Werte
wie für Ihre Konfiguration erforderlich. Hierbei repräsentiert
********
Ihr Passwort; geben Sie dieses ein,
wenn mysql die Aufforderung Enter
password:
anzeigt.
Funktioniert alles wie erwartet, dann werden ein paar einleitende
Informationen gefolgt von der Eingabeaufforderung
mysql>
angezeigt:
shell>mysql -h
Enter password:host
-uuser
-p********
Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 25338 to server version: 5.1.5-alpha-standard Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql>
Die Eingabeaufforderung mysql>
zeigt an,
dass mysql nun zur Entgegennahme von Befehlen
bereit ist.
Wenn Sie sich an dem Computer angemeldet haben, auf dem auch MySQL ausgeführt wird, dann können Sie den Hostnamen weglassen und einfach Folgendes eingeben:
shell< mysql -u user
-p
Wenn Sie beim Anmeldeversuch eine Fehlermeldung wie etwa ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) erhalten, bedeutet dies, dass der MySQL Server-Daemon (unter Unix) bzw. der MySQL Server-Dienst (unter Windows) nicht ausgeführt wird. Wenden Sie sich an den Administrator oder lesen Sie den für Ihr Betriebssystem vorgesehenen Abschnitt in Kapitel 2, Installation von MySQL.
Hilfe bei anderen Problemen, die beim Anmelden häufig auftreten, finden Sie in Abschnitt A.2, „Einige häufige Fehler bei der Benutzung von MySQL“.
Einige MySQL-Installationen gestatten Benutzern die Herstellung einer Verbindung zum auf dem lokalen Host laufenden Server als anonymer (d. h. nicht benannter) Benutzer. Sollte dies bei Ihrem System der Fall sein, dann sollten Sie eine Verbindung herstellen können, indem Sie mysql einfach ohne weitere Optionen aufrufen:
shell> mysql
Wenn Sie erfolgreich eine Verbindung hergestellt haben, können
Sie diese jederzeit trennen, indem Sie QUIT
(oder
einfach \q
) an der Eingabeaufforderung
mysql>
eingeben:
mysql> QUIT
Bye
Unter Unix können Sie die Trennung auch mit der Tastenkombination Strg+D durchführen.
Die meisten Beispiele in den nachfolgenden Abschnitten setzen
voraus, dass Sie mit dem Server verbunden sind. Dieses wird durch
die Eingabeaufforderung mysql>
angezeigt.
Stellen Sie zunächst wie im vorhergehenden Abschnitt beschrieben eine Verbindung zum Server her. Durch diesen Vorgang wird noch keine Datenbank ausgewählt, was aber noch nicht problematisch ist. Wir wollen erst einmal sehen, wie man Abfragen absetzt, statt gleich mit den eigentlichen Datenbankfunktionen – dem Erstellen von Tabellen und dem Einladen von Daten in bzw. Abrufen dieser Daten aus den Tabellen – anzufangen. Dieser Abschnitt erläutert die Grundprinzipien der Befehlseingabe mithilfe verschiedener Abfragen, die Sie ausprobieren können, um sich mit der Funktionsweise von mysql vertraut zu machen.
Hier zunächst ein einfacher Befehl, der den Server bittet, seine
Versionsnummer und das aktuelle Datum anzugeben. Geben Sie den
Befehl wie hier gezeigt an der Eingabeaufforderung
mysql>
ein und betätigen Sie dann die
Eingabetaste:
mysql> SELECT VERSION(), CURRENT_DATE;
+-----------------+--------------+
| VERSION() | CURRENT_DATE |
+-----------------+--------------+
| 5.1.2-alpha-log | 2005-10-11 |
+-----------------+--------------+
1 row in set (0.01 sec)
mysql>
Diese Abfrage veranschaulicht mehrere Aspekte von mysql:
Ein Befehl besteht normalerweise aus einer SQL-Anweisung
gefolgt von einem Semikolon. (Es gibt eine Reihe von
Ausnahmen, bei denen das Semikolon weggelassen werden kann.
Ein Beispiel ist das bereits weiter oben erwähnte
QUIT
; weitere werden folgen.)
Wenn Sie einen Befehl absetzen, sendet mysql
ihn zur Ausführung an den Server und zeigt die Ergebnisse an.
Darauf folgt wieder eine neue Eingabeaufforderung
mysql>
, mit der angezeigt wird, dass nun
ein neuer Befehl eingegeben werden kann.
mysql zeigt die Abfrageausgabe in Tabellenform (d. h. als Zeilen und Spalten) an. Die erste Zeile enthält die Spaltenüberschriften. Alle nachfolgenden Zeilen sind Abfrageergebnisse. Normalerweise sind Spaltenüberschriften die Namen der Spalten, die aus den Datenbanktabellen abgerufen werden. Wenn Sie den Wert eines Ausdrucks statt einer Tabellenspalte (wie im obigen Beispiel) abrufen, beschriftet mysql die Spalte mit dem Ausdruck selbst.
mysql zeigt an, wie viele Datensätze (Zeilen) zurückgegeben wurden und wie lange die Ausführung der Abfrage dauerte; hierdurch können Sie grob auf die Serverleistung schließen. Die Werte sind allerdings nicht sehr genau, denn sie geben nur eine normale Zeit statt der Prozessor- oder Systemzeit an, die zudem durch Faktoren wie der Serverauslastung und der Netzwerklatenz beeinflusst wird. (Aus Gründen der Übersichtlichkeit haben wir die Zeile „rows in set“ in einigen der in diesem Kapitel aufgeführten Beispiele weggelassen.)
Schlüsselwörter können in beliebiger Groß-/Kleinschreibung angegeben werden. Die folgenden Abfragen sind gleichwertig:
mysql>SELECT VERSION(), CURRENT_DATE;
mysql>select version(), current_datum;
mysql>SeLeCt vErSiOn(), current_DATE;
Es folgt eine weitere Abfrage. Sie veranschaulicht, wie man mysql als einfachen Taschenrechner verwenden kann:
mysql> SELECT SIN(PI()/4), (4+1)*5;
+------------------+---------+
| SIN(PI()/4) | (4+1)*5 |
+------------------+---------+
| 0.70710678118655 | 25 |
+------------------+---------+
1 row in set (0.02 sec)
Die bislang gezeigten Abfragen waren vergleichsweise kurze, einzeilige Anweisungen. Sie können aber auch mehrere Anweisungen in eine Zeile schreiben. Schließen Sie sie jeweils mit einem Semikolon ab:
mysql> SELECT VERSION(); SELECT NOW();
+-----------------+
| VERSION() |
+-----------------+
| 5.1.2-alpha-log |
+-----------------+
1 row in set (0.00 sec)
+---------------------+
| NOW() |
+---------------------+
| 2005-10-11 15:15:00 |
+---------------------+
1 row in set (0.00 sec)
Ein Befehl muss nicht vollständig innerhalb einer einzelnen Zeile angegeben werden; insofern stellen auch längere Befehle über mehrere Zeilen kein Problem dar. mysql ermittelt das Ende Ihrer Anweisung anhand des schließenden Semikolons und nicht auf der Basis der Eingabezeile. (Anders gesagt, akzeptiert mysql frei formatierte Eingaben: Alle Eingabezeilen werden gesammelt, die Ausführung erfolgt aber erst, nachdem das Semikolon erkannt wurde.)
Hier ist eine einfache mehrzeilige Anweisung:
mysql>SELECT
->USER()
->,
->CURRENT_DATE;
+---------------+--------------+ | USER() | CURRENT_DATE | +---------------+--------------+ | jon@localhost | 2005-10-11 | +---------------+--------------+
Beachten Sie in diesem Beispiel, wie die Eingabeaufforderung von
mysql>
auf ->
umschaltet, nachdem Sie die erste Zeile einer mehrzeiligen Abfrage
eingegeben haben. Auf diese Weise zeigt mysql
an, dass noch keine vollständige Anweisung erkannt wurde und
weitere Eingaben erwartet werden. Diese Form der
Eingabeaufforderung ist sehr praktisch, denn sie erlaubt
Rückschlüsse auf erforderliche Eingaben. Sie wissen also immer,
worauf mysql gerade wartet.
Wenn Sie einen Befehl, den Sie gerade eingeben, doch nicht
ausführen wollen, können Sie ihn durch Eingabe von
\c
abbrechen:
mysql>SELECT
->USER()
->\c
mysql>
Beachten Sie auch hier die Eingabeaufforderung. Sie schaltet
zurück auf mysql>
, nachdem Sie
\c
eingegeben haben. So wird angezeigt, dass
mysql auf einen neuen Befehl wartet.
Die folgende Tabelle zeigt alle Eingabeaufforderungen, auf die Sie treffen können, und fasst ferner zusammen, welche Rückschlüsse sie jeweils bezüglich des Zustandes von mysql erlauben.
Eingabeaufforderung | Bedeutung |
mysql> | Bereit für einen neuen Befehl. |
-> | Erwartet die nächste Zeile einer mehrzeiligen Befehlseingabe. |
'> | Erwartet die nächste Zeile und die Vervollständigung eines Strings,
der mit einem einfachen Anführungszeichen
(‘' ’) begonnen wurde. |
"> | Erwartet die nächste Zeile und die Vervollständigung eines Strings,
der mit einem doppelten Anführungszeichen
(‘" ’) begonnen wurde. |
`> | Erwartet die nächste Zeile und die Vervollständigung eines
Bezeichners, der mit einem Backtick
(‘` ’) begonnen wurde. |
/*> | Erwartet die nächste Zeile und die Vervollständigung eines Kommentars,
der mit /* begonnen wurde. |
Mehrzeilige Anweisungen treten häufig ungewollt auf, wenn Sie eigentlich nur einen einzeiligen Befehl absetzen wollen, aber das abschließende Semikolon vergessen. In diesem Fall erwartet mysql eine weitere Eingabe:
mysql> SELECT USER()
->
Wenn das geschieht (d. h., wenn Sie glauben, dass Sie einen
vollständigen Befehl eingegeben haben, aber die
Eingabeaufforderung ->
erscheint), dann
wartet mysql in aller Regel auf das Semikolon.
Bemerken Sie nicht sofort, welche Eingabeaufforderung hier
angezeigt wird, dann sitzen Sie womöglich eine Zeit lang vor dem
Computer, bevor Sie feststellen, was passiert ist. Geben Sie
einfach ein Semikolon ein, um die Anweisung abzuschließen – sie
wird dann von mysql ausgeführt:
mysql>SELECT USER()
->;
+---------------+ | USER() | +---------------+ | jon@localhost | +---------------+
Die Eingabeaufforderungen '>
und
">
erscheinen bei der Erfassung von Strings
(MySQL erwartet also die Vervollständigung eines Strings). In
MySQL können Sie Strings entweder in
‘'
’ oder
‘"
’ setzen (z. B.
'hello'
oder "goodbye"
).
mysql erlaubt die Eingabe von Strings, die sich
über mehrere Zeilen erstrecken. Wenn Sie die Eingabeaufforderung
'>
oder ">
sehen,
bedeutet dies, dass Sie eine Zeile mit einem String eingegeben
haben, der mit dem Anführungszeichen
‘'
’ oder
‘"
’ beginnt, diesen String aber
noch nicht mit dem zugehörigen schließenden Anführungszeichen
beendet haben. Hierdurch ist häufig erkennbar, dass Sie ein
Anführungszeichen einzugeben vergessen haben. Ein Beispiel:
mysql> SELECT * FROM my_table WHERE name = 'Smith AND alter < 30;
'>
Wenn Sie diese SELECT
-Anweisung eingeben und
dann die Eingabetaste betätigen, werden Sie eine Zeit lang warten,
ohne dass etwas passiert. Wenn Sie sich wundern, warum die
Verarbeitung der Abfrage so lange dauert, werden Sie bald
feststellen, dass die Eingabeaufforderung '>
angezeigt wird. Sie besagt, dass mysql den Rest
eines nicht abgeschlossenen Strings erwartet. (Erkennen Sie den
Fehler in der Anweisung? Beim String 'Smith
fehlt das zweite einzelne Anführungszeichen.)
Was können Sie nun tun? Die einfachste Möglichkeit besteht
darin, den Befehl abzubrechen. Sie können in diesem Fall aber
nicht einfach \c
eingeben, da
mysql dies als Teil des Strings interpretieren
würde, den Sie vermeintlich eingeben. Geben Sie stattdessen
zuerst das schließende Anführungszeichen (damit
mysql weiß, dass der String abgeschlossen ist)
und erst dann \c
ein:
mysql>SELECT * FROM my_table WHERE name = 'Smith AND alter < 30;
'>'\c
mysql>
Die Eingabeaufforderung schaltet nun auf
mysql>
zurück und zeigt so an, dass
mysql für einen neuen Befehl bereit ist.
Die Eingabeaufforderung `>
ähnelt
'>
und ">
, gibt aber
an, dass Sie mit einem Backtick einen Bezeichner begonnen, aber
noch nicht beendet haben.
Zu wissen, was die Eingabeaufforderungen '>
,
">
und `>
bedeuten,
ist wichtig, denn wenn Sie versehentlich einen nicht
abgeschlossenen String eingeben, werden alle nachfolgend
eingegebenen Zeilen von mysql ignoriert –
einschließlich der Zeile mit dem Befehl QUIT
.
Dies kann insbesondere dann recht verwirrend sein, wenn Sie nicht
wissen, dass Sie ein schließendes Anführungszeichen eingeben
müssen, bevor Sie den aktuellen Befehl abbrechen können.
Nachdem Sie nun wissen, wie Sie Befehle eingeben, sind Sie so weit, dass Sie auf eine Datenbank zugreifen können.
Angenommen, Sie halten bei sich zu Hause mehrere Haustiere (Ihre kleine „Menagerie“) und wollen nun verschiedene Informationen zu diesen Tieren verwalten. Dies können Sie tun, indem Sie Tabellen erstellen, die die gewünschten Informationen aufnehmen sollen, und diese Tabellen dann mit den erforderlichen Daten bestücken. Danach können Sie zu Ihren Tieren verschiedene Arten von Fragen beantworten, indem Sie Daten aus den Tabellen abrufen. In diesem Abschnitt erläutern wir, wie man
eine Datenbank erstellt,
eine Tabelle erstellt,
Daten in eine Tabelle lädt,
Daten auf verschiedene Weisen aus der Tabelle abruft,
mehrere Tabellen verwendet.
Die Menageriedatenbank ist (bewusst) einfach gehalten, aber es ist auch nicht schwierig, sich Situationen aus dem täglichen Leben vorzustellen, in denen eine ähnliche Art von Datenbank zum Einsatz kommen könnte. Eine solche Datenbank könnte etwa von einem Landwirt, der seinen Tierbestand organisieren möchte, oder von einem Tierarzt zur Patientenverwaltung verwendet werden. Eine Menageriedistribution mit einigen der in den folgenden Abschnitten verwendeten Abfragen und Beispieldaten finden Sie auf der MySQL-Website. Sie ist in komprimierter Form als tar- (http://www.mysql.com/Downloads/Contrib/Examples/menagerie.tar.gz) und Zip-Archiv (http://www.mysql.com/Downloads/Contrib/Examples/menagerie.zip) verfügbar.
Verwenden Sie die SHOW
-Anweisung, um zu
ermitteln, welche Datenbanken derzeit auf dem Server vorhanden
sind:
mysql> SHOW DATABASES;
+----------+
| Database |
+----------+
| mysql |
| test |
| tmp |
+----------+
Die Liste der Datenbanken sieht auf Ihrem Computer wahrscheinlich
etwas anders aus, aber die Datenbanken mysql
und test
sind höchstwahrscheinlich vorhanden.
Die Datenbank mysql
ist erforderlich, da sie
die Benutzerberechtigungen beschreibt. Die Datenbank
test
hingegen wird häufig als Spielplatz für
Benutzer verwendet, die Dinge ausprobieren möchten.
Beachten Sie, dass Ihnen unter Umständen nicht alle Datenbanken
angezeigt werden, wenn Ihnen die Berechtigung SHOW
DATABASES
fehlt. Siehe auch Abschnitt 13.5.1.3, „GRANT
und REVOKE
“.
Wenn die Datenbank test
vorhanden ist,
versuchen Sie sie aufzurufen:
mysql> USE test
Database changed
Beachten Sie, dass USE
ebenso wie
QUIT
kein Semikolon braucht. (Sie können
solche Anweisungen aber nichtsdestoweniger mit einem Semikolon
abschließen – hierdurch wird kein Schaden angerichtet.) Die
USE
-Anweisung ist auch auf andere Weise
besonders: Sie muss in einer einzigen Zeile angegeben werden.
Sie können die Datenbank test
für die
folgenden Beispiele verwenden (vorausgesetzt, Sie haben Zugriff
darauf); beachten Sie aber, dass alles, was Sie in dieser
Datenbank erstellen, von allen anderen Benutzern, die darauf
zugreifen dürfen, entfernt werden kann. Aus diesem Grund sollten
Sie Ihren MySQL-Administrator besser bitten, eine eigene Datenbank
verwenden zu dürfen. Wenn Sie Ihre Datenbank
menagerie
nennen wollen, dann muss der
Administrator folgenden Befehl ausführen:
mysql> GRANT ALL ON menagerie.* TO 'your_mysql_name'@'your_client_host';
Hierbei ist your_mysql_name
der Ihnen
zugewiesene MySQL-Benutzername und
your_client_host
der Name des Hosts, von dem
aus Sie die Verbindung zum Server herstellen.
Wenn Ihr Administrator beim Konfigurieren der Berechtigungen eine Datenbank für Sie erstellt hat, können Sie diese sofort nutzen. Andernfalls müssen Sie sie selbst einrichten:
mysql> CREATE DATABASE menagerie;
Unter Unix wird bei Datenbanknamen – anders als bei
SQL-Schlüsselwörtern – die Groß-/Kleinschreibung
unterschieden. Deswegen muss der Datenbankname immer als
menagerie
und nicht als
Menagerie
, MENAGERIE
oder
in einer anderen Variante angegeben werden. Gleiches gilt für
Tabellennamen. (Unter Windows gilt diese Einschränkung nicht;
allerdings müssen Sie innerhalb einer Abfrage eine Datenbank
oder Tabelle konsistent mit derselben Schreibung bezeichnen. Wir
empfehlen jedoch aus verschiedenen Gründen, immer dieselbe
Schreibweise zu nutzen, die beim Einrichten der Datenbank
verwendet wurde.)
Hinweis: Wenn Sie beim Erstellen einer Datenbank eine Fehlermeldung wie etwa ERROR 1044 (42000): Access denied for user 'monty'@'localhost' to database 'menagerie' erhalten, bedeutet dies, dass Ihr Benutzerkonto nicht die zur Datenbankerstellung erforderlichen Berechtigungen hat. Besprechen Sie dies mit Ihrem Administrator oder lesen Sie Abschnitt 5.8, „Allgemeine Sicherheitsaspekte und das MySQL-Zugriffsberechtigungssystem“.
Wenn Sie eine Datenbank erstellen, wird diese nicht automatisch
für die Verwendung ausgewählt; Sie müssen dies ausdrücklich
tun. Um menagerie
also zur aktuellen
Datenbank zu machen, verwenden Sie folgenden Befehl:
mysql> USE menagerie
Database changed
Ihre Datenbank muss nur einmal erstellt werden, sie muss aber
jedes Mal, wenn Sie eine mysql-Sitzung
beginnen, zur Verwendung ausgewählt werden. Dies tun Sie durch
Absetzen einer USE
-Anweisung wie im Beispiel
gezeigt. Alternativ können Sie die Datenbank auch auf der
Befehlszeile auswählen, wenn Sie mysql
aufrufen. Geben Sie auf alle ggf. erforderlichen
Verbindungsparameter folgend einfach den Datenbanknamen ein. Ein
Beispiel:
shell>mysql -h
Enter password:host
-uuser
-p menagerie********
Beachten Sie, dass menagerie
im gerade
gezeigten Befehl nicht Ihr
Passwort ist. Wenn Sie Ihr Passwort auf der Befehlszeile nach
der Option -p
angeben wollen, müssen Sie
dies ohne zwischengeschaltetes Leerzeichen tun (z. B. als
-pmypassword
, nicht jedoch als -p
mypassword
). Allerdings wird von der Übermittlung des
Passworts auf der Befehlszeile ohnehin abgeraten, weil es so
anderen Benutzern offenbart werden könnte, die an Ihrem
Computer angemeldet sind.
Das Erstellen einer Datenbank ist ganz einfach. Noch aber ist
die Datenbank leer, wie Sie mit SHOW TABLES
nachprüfen können:
mysql> SHOW TABLES;
Empty set (0.00 sec)
Schwieriger zu entscheiden ist hingegen, wie die Struktur der Datenbank aussehen soll: Welche Tabellen brauchen Sie? Und welche Spalten sollen in diesen Tabellen enthalten sein?
Sie brauchen eine Tabelle, die einen Datensatz für jedes Ihrer
Haustiere enthält. Diese Tabelle könnte man
haustier
nennen; sie sollte zumindest den
Namen jedes Tieres enthalten. Da der Name an sich aber nicht
besonders interessant ist, sollte die Tabelle auch weitere
Informationen enthalten. Wenn beispielsweise mehrere Personen in
Ihrer Familie Haustiere halten, würde es sich anbieten, die
Besitzer der einzelnen Tiere aufzuführen. Ferner könnten
einige grundlegende Beschreibungen eingetragen werden, z. B. die
Tierart und das Geschlecht.
Und das Alter der Tiere? Das könnte zwar interessant sein, die Speicherung in einer Datenbank ist jedoch problematisch. Da sich das Alter im Laufe der Zeit ändert, müssten Sie Ihre Datensätze regelmäßig aktualisieren. Stattdessen ist es besser, einen festen Wert wie etwa das Geburtsdatum zu speichern. Wann immer Sie dann das Alter eines Tieres in Erfahrung bringen wollten, müssten Sie nur die Differenz zwischen dem aktuellen Datum und dem Geburtsdatum errechnen. MySQL bietet Funktionen, die derartige Rechenaufgaben erledigen können, sodass dies nicht weiter schwierig ist. Das Speichern des Geburtsdatums statt des Alters hat aber auch weitere Vorteile:
Sie können die Datenbank für Aufgaben wie das automatische Erinnern an anstehende Tiergeburtstage verwenden. (Wenn Sie der Ansicht sind, dass eine solche Abfrage etwas albern ist, dann beachten Sie, dass Sie dieselbe Frage im Kontext einer Unternehmensdatenbank verwenden könnten, um Kunden zu ermitteln, denen Sie demnächst Geburtstagsgrüße senden wollen – die persönliche Note mit freundlicher Unterstützung Ihrer Datenbank.)
Sie können das Alter auch in Relation zu anderen als dem aktuellen Datum berechnen. Wenn Sie etwa das Sterbedatum eines Tieres in der Datenbank ablegen, können Sie ganz leicht berechnen, wie alt es bei seinem Tod war.
Sie können sich wahrscheinlich eine Reihe andere
Informationstypen vorstellen, die in der Tabelle
haustier
von Nutzen sein könnten, aber die
bisher genannten sollen fürs Erste ausreichen: Name, Besitzer,
Tierart, Geschlecht, Geburts- und Sterbedatum.
Das Layout Ihrer Tabelle legen Sie mit einer CREATE
TABLE
-Anweisung fest:
mysql>CREATE TABLE haustier (name VARCHAR(20), besitzer VARCHAR(20),
->gattung VARCHAR(20), geschlecht CHAR(1), geburtstag DATE, todestag DATE);
VARCHAR
ist eine geeignete Wahl für die
Spalten name
, besitzer
und
gattung
, denn die Werte dieser Spalten
können in der Länge variieren. Die Längen in diesen
Spaltendefinitionen müssen weder identisch sein noch alle den
Wert 20
haben. Sie können eine beliebige
Länge zwischen 1
und
65535
eingeben – je nachdem, was Ihnen am
sinnvollsten erscheint. Haben Sie jedoch eine falsche
Entscheidung getroffen und es stellt sich später heraus, dass
Sie ein längeres Feld benötigen, dann bietet MySQL hierfür
die ALTER TABLE
-Anweisung an.
Zur Auswahl des Geschlechts Ihrer Tiere bieten sich mehrere
Wertetypen an, z. B. 'm'
und
'w'
oder auch 'männlich'
und 'weiblich'
. Am einfachsten ist die
Verwendung der Einzelzeichen 'm'
und
'w'
.
Der Datentyp DATE
ist offensichtlich am
geeignetsten für die Spalten geburtstag
und
todestag
.
Wenn Sie eine Tabelle erstellt haben, sollte die Anweisung
SHOW TABLES
eine entsprechende Ausgabe
erzeugen:
mysql> SHOW TABLES;
+---------------------+
| Tables in menagerie |
+---------------------+
| haustier |
+---------------------+
Um zu überprüfen, dass Ihre Tabelle wie gewünscht erstellt
worden ist, verwenden Sie eine
DESCRIBE
-Anweisung:
mysql> DESCRIBE haustier;
+------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| name | varchar(20) | YES | | NULL | |
| besitzer | varchar(20) | YES | | NULL | |
| gattung | varchar(20) | YES | | NULL | |
| geschlecht | char(1) | YES | | NULL | |
| geburtstag | date | YES | | NULL | |
| todestag | date | YES | | NULL | |
+------------+-------------+------+-----+---------+-------+
Sie können DESCRIBE
auch jederzeit aufrufen,
wenn Sie die Spaltennamen Ihrer Tabelle oder die verwendeten
Datentypen vergessen haben.
Weitere Informationen zu MySQL-Datentypen finden Sie in Kapitel 11, Datentypen.
Nachdem Sie Ihre Tabelle erstellt haben, müssen Sie sie mit
Daten füllen. Zu diesem Zweck sind die Anweisungen
LOAD DATA
und INSERT
vorhanden.
Nehmen wir einmal an, dass sich die Angaben zu Ihren Haustieren
wie in der folgenden Tabelle gezeigt zusammenfassen lassen
(beachten Sie dabei, dass MySQL Datumsangaben im Format
'YYYY-MM-DD'
erwartet; dies unterscheidet
sich unter Umständen von dem Format, mit dem Sie vertraut
sind).
name | besitzer | gattung | geschlecht | geburtstag | todestag |
Fluffy | Harold | Katze | w | 1993-02-04 | |
Claws | Gwen | Katze | m | 1994-03-17 | |
Buffy | Harold | Hund | w | 1989-05-13 | |
Fang | Benny | Hund | m | 1990-08-27 | |
Bowser | Diane | Hund | m | 1979-08-31 | 1995-07-29 |
Chirpy | Gwen | Vogel | w | 1998-09-11 | |
Whistler | Gwen | Vogel | 1997-12-09 | ||
Slim | Benny | Schlange | m | 1996-04-29 |
Da wir anfangs eine leere Tabelle haben, können Sie diese zunächst ganz einfach ausfüllen, indem Sie eine Textdatei erstellen, die jeweils eine Zeile pro Tier enthält. Die Inhalte der Datei können Sie dann mit einer einzigen Anweisung in die Tabelle einladen.
Erstellen Sie also eine Textdatei namens
haustier.txt
mit einem Datensatz pro Zeile,
bei dem die einzelnen Werte durch Tabulatorzeichen voneinander
getrennt sind; die Werte müssen dabei in der Reihenfolge
eingegeben werden, in der Sie in der CREATE
TABLE
-Anweisung aufgeführt wurden. Bei fehlenden
Werten (z. B. wenn das Geschlecht nicht bekannt oder das Ableben
des Tieres noch nicht erfolgt ist) können Sie
NULL
-Werte eingeben. Diese geben Sie als
\N
(Backslash, großes N) in Ihre Textdatei
ein. So würde der Datensatz für Whistler, den Vogel, wie folgt
aussehen (der Whitespace zwischen den Werten ist ein
Tabulatorzeichen):
name | besitzer | gattung | geschlecht | geburtstag | todestag |
Whistler | Gwen | Vogel | \N | 1997-12-09 | \N |
Um die Textdatei haustier.txt
in die
Tabelle haustier
zu laden, genügt die
folgende Anweisung:
mysql> LOAD DATA LOCAL INFILE '/path/haustier.txt' INTO TABLE haustier;
Beachten Sie, dass Sie, wenn Sie die Datei unter Windows mit
einem Editor erstellt haben, der \r\n
als
Zeilenbegrenzer verwendet, Folgendes verwenden:
mysql>LOAD DATA LOCAL INFILE '/path/haustier.txt' INTO TABLE haustier
->LINES TERMINATED BY '\r\n';
(Auf einem Apple Macintosh unter Mac OS X würden Sie hingegen
eher LINES TERMINATED BY '\r'
benutzen.)
Sie können das Trennzeichen für Spaltenwerte und den
Zeilenbegrenzer bei Bedarf auch ausdrücklich in der
LOAD DATA
-Anweisung angeben, die
Standardeinstellungen sind jedoch das Tabulator- bzw. das
Zeilenvorschubzeichen. Diese Einstellungen sind zum Einlesen
unserer Datei haustier.txt
geeignet.
Schlägt die Anweisung fehl, dann liegt das wahrscheinlich
daran, dass bei der MySQL-Installation standardmäßig nicht die
Funktionalität für lokale Dateien aktiviert ist. Wie Sie dies
ändern, erfahren Sie in Abschnitt 5.7.4, „Sicherheitsprobleme mit LOAD DATA LOCAL
“.
Zum sukzessiven Einfügen neuer Datensätze ist die
INSERT
-Anweisung am praktischsten. In ihrer
einfachsten Form geben Sie Werte für jede Spalte in der
Reihenfolge an, in der die Spalten in der CREATE
TABLE
-Anweisung aufgeführt waren. Nehmen wir etwa an,
Diane bekommt einen neuen Hamster namens
„Puffball“. Nun könnten Sie den erforderlichen
neuen Datensatz wie folgt mithilfe einer
INSERT
-Anweisung angeben:
mysql>INSERT INTO haustier
->VALUES ('Puffball','Diane','Hamster','w','1999-03-30',NULL);
Beachten Sie, dass die String- und Datenwerte hier in
Anführungszeichen gesetzt werden. Mit der
INSERT
-Anweisung können Sie
NULL
auch direkt eingeben, um einen fehlenden
Wert darzustellen. \N
würden Sie hier –
anders als bei LOAD DATA
– nicht verwenden.
Aus diesem Beispiel sollte klar werden, dass die Erstellung der
Basisdatensätze mithilfe einzelner
INSERT
-Anweisungen erheblich mehr Tipparbeit
bedeuten würde als die Verwendung einer einzelnen LOAD
DATA
-Anweisung.
Mit der SELECT
-Anweisung können Sie Daten
aus einer Tabelle abrufen. Die allgemeine Form dieser Anweisung
sieht wie folgt aus:
SELECTwhat_to_select
FROMwhich_table
WHEREconditions_to_satisfy
;
what_to_select
gibt hierbei an, was
Sie sehen wollen. Dies kann eine Liste mit Spalten oder
alternativ *
sein, wenn Sie alle Spalten
anzeigen wollen. which_table
gibt die
Tabelle an, aus der Sie Daten abrufen wollen. Die
WHERE
-Klausel ist optional. Ist sie
vorhanden, dann gibt
conditions_to_satisfy
eine oder
mehrere Bedingungen an, die Datensätze erfüllen müssen, um
abgerufen zu werden.
Die einfachste Form von SELECT
ruft alle in
der Tabelle vorhandenen Daten ab:
mysql> SELECT * FROM haustier;
+----------+----------+----------+------------+------------+------------+
| name | besitzer | gattung | geschlecht | geburtstag | todestag |
+----------+----------+----------+------------+------------+------------+
| Fluffy | Harold | Katze | w | 1993-02-04 | NULL |
| Claws | Gwen | Katze | m | 1994-03-17 | NULL |
| Buffy | Harold | Hund | w | 1989-05-13 | NULL |
| Fang | Benny | Hund | m | 1990-08-27 | NULL |
| Bowser | Diane | Hund | m | 1979-08-31 | 1995-07-29 |
| Chirpy | Gwen | Vogel | w | 1998-09-11 | NULL |
| Whistler | Gwen | Vogel | NULL | 1997-12-09 | NULL |
| Slim | Benny | Schlange | m | 1996-04-29 | NULL |
| Puffball | Diane | Hamster | w | 1999-03-30 | NULL |
+----------+----------+----------+------------+------------+------------+
Diese Verwendung von SELECT
ist nützlich,
wenn Sie beispielsweise Ihre Tabelle überprüfen wollen,
nachdem Sie gerade die ersten Daten eingeladen haben. Nehmen
wir etwa an, dass Sie nicht ganz sicher sind, ob Sie für
Bowser das richtige Geburtsdatum eingegeben haben. Dem
Stammbaum entnehmen Sie, dass das korrekte Geburtsjahr nicht
1979, sondern 1989 lautet.
Nun gibt es zwei Möglichkeiten, den Fehler zu beheben:
Sie korrigieren den Datensatz in der Datei
haustier.txt
, leeren die Tabelle mit
DELETE
und laden die Daten dann mit
LOAD DATA
neu ein:
mysql>DELETE FROM haustier;
mysql>LOAD DATA LOCAL INFILE 'haustier.txt' INTO TABLE haustier;
Allerdings müssen Sie bei dieser Vorgehensweise auch die Daten für Puffball neu eingeben.
Sie ändern nur den fehlerhaften Datensatz. Hierzu
verwenden Sie eine UPDATE
-Anweisung:
mysql> UPDATE haustier SET geburtstag = '1989-08-31' WHERE name = 'Bowser';
Mit UPDATE
ändern Sie nur den
fraglichen Datensatz – Sie müssen die Tabellendaten in
diesem Fall nicht neu laden.
Wie im vorherigen Abschnitt gezeigt, ist das Abrufen der Daten
einer ganzen Tabelle recht einfach. Sie lassen einfach die
WHERE
-Klausel in der
SELECT
-Anweisung weg. In der Regel wollen
Sie aber nicht die gesamte Tabelle anzeigen – insbesondere
dann nicht, wenn diese sehr groß ist. Stattdessen werden Sie
meist an der Beantwortung einer bestimmten Frage interessiert
sein. In diesem Fall müssen Sie Beschränkungen für die
gewünschten Daten definieren. Betrachten wir einmal einige
Auswahlabfragen dahingehend, welche Fragen diese zu Ihren
Haustieren beantworten.
Sie können die Auswahl in Ihrer Tabelle auch auf bestimmte Datensätze beschränken. Wollen Sie z. B. die Änderungen am Geburtsdatum von Bowser überprüfen, dann wählen Sie den entsprechenden Datensatz wie folgt aus:
mysql> SELECT * FROM haustier WHERE name = 'Bowser';
+--------+----------+----------+------------+------------+------------+
| name | besitzer | gattung | geschlecht | geburtstag | todestag |
+--------+----------+----------+------------+------------+------------+
| Bowser | Diane | Hund | m | 1989-08-31 | 1995-07-29 |
+--------+----------+----------+------------+------------+------------+
Die Ausgabe bestätigt die korrekte Änderung der Jahresangabe von 1979 auf 1989.
Bei String-Vergleichen wird die Groß-/Kleinschreibung
normalerweise ignoriert, weswegen Sie den Namen als
'bowser'
, 'BOWSER'
usw.
angeben können. Das Abfrageergebnis ist stets gleich.
Sie können Bedingungen aber nicht nur für
name
, sondern für jede beliebige Spalte
angeben. Wenn Sie beispielsweise wissen wollen, welche Tiere
im Jahre 1998 oder danach geboren wurden, testen Sie die
Spalte geburtstag
:
mysql> SELECT * FROM haustier WHERE geburtstag >= '1998-1-1';
+----------+----------+---------+-------------+------------+----------+
| name | besitzer | gattung | geschlecht | geburtstag | todestag |
+----------+----------+---------+-------------+------------+----------+
| Chirpy | Gwen | Vogel | w | 1998-09-11 | NULL |
| Puffball | Diane | Hamster | w | 1999-03-30 | NULL |
+----------+----------+---------+-------------+------------+----------+
Sie können auch Bedingungen kombinieren, um etwa nach weiblichen Hunden zu suchen:
mysql> SELECT * FROM haustier WHERE gattung = 'Hund' AND geschlecht = 'w';
+-------+-----------+---------+-------------+------------+----------+
| name | besitzer | gattung | geschlecht | geburtstag | todestag |
+-------+-----------+---------+-------------+------------+----------+
| Buffy | Harold | Hund | w | 1989-05-13 | NULL |
+-------+-----------+---------+-------------+------------+----------+
Obige Abfrage verwendet den Operator AND
(logisches Und). Es gibt analog auch einen Operator
OR
(logisches Oder):
mysql> SELECT * FROM haustier WHERE gattung = 'Schlange' OR gattung = 'Vogel';
+----------+----------+----------+-------------+------------+----------+
| name | besitzer | gattung | geschlecht | geburtstag | todestag |
+----------+----------+----------+-------------+------------+----------+
| Chirpy | Gwen | Vogel | w | 1998-09-11 | NULL |
| Whistler | Gwen | Vogel | NULL | 1997-12-09 | NULL |
| Slim | Benny | Schlange | m | 1996-04-29 | NULL |
+----------+----------+----------+-------------+------------+----------+
AND
und OR
können auch
gemischt verwendet werden, wobei AND
jedoch
Vorrang vor OR
hat. Wenn Sie beide
Operatoren verwenden, bietet sich die Verwendung von Klammern
an, um exakt anzugeben, wie die Bedingungen gruppiert werden
sollen:
mysql>SELECT * FROM haustier WHERE (gattung = 'Katze' AND geschlecht = 'm')
->OR (gattung = 'Hund' AND geschlecht = 'w');
+-------+-----------+---------+-------------+------------+----------+ | name | besitzer | gattung | geschlecht | geburtstag | todestag | +-------+-----------+---------+-------------+------------+----------+ | Claws | Gwen | Katze | m | 1994-03-17 | NULL | | Buffy | Harold | Hund | w | 1989-05-13 | NULL | +-------+-----------+---------+-------------+------------+----------+
Wenn Sie nicht die gesamten Datensätze aus Ihrer Tabelle
sehen wollen, dann führen Sie in der jeweiligen Abfrage die
gewünschten Spalten durch Kommata getrennt auf. Wollen Sie
also etwa wissen, wann Ihre Tiere geboren wurden, dann wählen
Sie die Spalten name
und
geburtstag
:
mysql> SELECT name, geburtstag FROM haustier;
+----------+------------+
| name | geburtstag |
+----------+------------+
| Fluffy | 1993-02-04 |
| Claws | 1994-03-17 |
| Buffy | 1989-05-13 |
| Fang | 1990-08-27 |
| Bowser | 1989-08-31 |
| Chirpy | 1998-09-11 |
| Whistler | 1997-12-09 |
| Slim | 1996-04-29 |
| Puffball | 1999-03-30 |
+----------+------------+
Um herauszufinden, wem welches Tier gehört, setzen Sie folgende Abfrage ab:
mysql> SELECT besitzer FROM haustier;
+----------+
| besitzer |
+----------+
| Harold |
| Gwen |
| Harold |
| Benny |
| Diane |
| Gwen |
| Gwen |
| Benny |
| Diane |
+----------+
Beachten Sie, dass diese einfache Abfrage die Spalte
besitzer
jedes Datensatzes abruft; einige
davon tauchen mehrfach auf. Um die Ausgabe zu optimieren,
können Sie jeden eindeutigen Ergebnisdatensatz genau einmal
ausgeben, indem Sie einfach das Schlüsselwort
DISTINCT
hinzufügen:
mysql> SELECT DISTINCT besitzer FROM haustier;
+----------+
| besitzer |
+----------+
| Benny |
| Diane |
| Gwen |
| Harold |
+----------+
Mithilfe einer WHERE
-Klausel können Sie
Datensatz- und Spaltenauswahl kombinieren. Um z. B. die
Geburtsdaten von Hunden und Katzen anzuzeigen, verwenden Sie
folgende Abfrage:
mysql>SELECT name, gattung, geburtstag FROM haustier
->WHERE gattung = 'Hund' OR gattung = 'Katze';
+--------+---------+------------+ | name | gattung | geburtstag | +--------+---------+------------+ | Fluffy | Katze | 1993-02-04 | | Claws | Katze | 1994-03-17 | | Buffy | Hund | 1989-05-13 | | Fang | Hund | 1990-08-27 | | Bowser | Hund | 1989-08-31 | +--------+---------+------------+
Sie haben in den vorangegangenen Beispielen vielleicht bereits
festgestellt, dass die Ergebnisdatensätze nicht in einer
bestimmten Reihenfolge angezeigt werden. Häufig ist es jedoch
einfacher, das Abfrageergebnis zu durchsuchen, wenn die
Datensätze sinnvoll sortiert werden. Um ein Ergebnis zu
sortieren, verwenden Sie die ORDER
BY
-Klausel.
Nachfolgend sind die Geburtstage der Tiere nach Datum sortiert aufgelistet:
mysql> SELECT name, geburtstag FROM haustier ORDER BY geburtstag;
+----------+------------+
| name | geburtstag |
+----------+------------+
| Buffy | 1989-05-13 |
| Bowser | 1989-08-31 |
| Fang | 1990-08-27 |
| Fluffy | 1993-02-04 |
| Claws | 1994-03-17 |
| Slim | 1996-04-29 |
| Whistler | 1997-12-09 |
| Chirpy | 1998-09-11 |
| Puffball | 1999-03-30 |
+----------+------------+
Bei zeichenbasierten Spalten erfolgt die Sortierung –
wie bei allen anderen Vergleichsoperationen auch –
normalerweise ohne Berücksichtigung der
Groß-/Kleinschreibung. Das bedeutet, dass die Reihenfolge bei
Spalten, die bis auf die Groß-/Kleinschreibung identisch
sind, nicht definiert ist. Sie können die Sortierung einer
Spalte unter Berücksichtigung der Groß-/Kleinschreibung
durch Verwendung von BINARY
wie folgt
erzwingen: ORDER BY BINARY
.
col_name
Die Standardreihenfolge bei der Sortierung ist aufsteigend, d.
h., die kleinsten Werte werden zuerst aufgeführt. Um in
umgekehrter (absteigender) Reihenfolge zu sortieren, fügen
Sie das Schlüsselwort DESC
zum Namen der
Spalte zu, nach der die Sortierung erfolgt:
mysql> SELECT name, geburtstag FROM haustier ORDER BY geburtstag DESC;
+----------+------------+
| name | geburtstag |
+----------+------------+
| Puffball | 1999-03-30 |
| Chirpy | 1998-09-11 |
| Whistler | 1997-12-09 |
| Slim | 1996-04-29 |
| Claws | 1994-03-17 |
| Fluffy | 1993-02-04 |
| Fang | 1990-08-27 |
| Bowser | 1989-08-31 |
| Buffy | 1989-05-13 |
+----------+------------+
Sie können auch nach mehreren Spalten und diese jeweils mit eigener Reihenfolge sortieren. Um beispielsweise nach der Tierart in aufsteigender, dann dem Geburtsdatum innerhalb der Tierart in absteigender Reihenfolge (d. h. das jüngste Tier zuerst nennend) zu sortieren, verwenden Sie die folgende Abfrage:
mysql>SELECT name, gattung, geburtstag FROM haustier
->ORDER BY gattung, geburtstag DESC;
+----------+----------+------------+ | name | gattung | geburtstag | +----------+----------+------------+ | Chirpy | Vogel | 1998-09-11 | | Whistler | Vogel | 1997-12-09 | | Claws | Katze | 1994-03-17 | | Fluffy | Katze | 1993-02-04 | | Fang | Hund | 1990-08-27 | | Bowser | Hund | 1989-08-31 | | Buffy | Hund | 1989-05-13 | | Puffball | Hamster | 1999-03-30 | | Slim | Schlange | 1996-04-29 | +----------+----------+------------+
Beachten Sie, dass das Schlüsselwort DESC
nur für den Spaltennamen gilt, dem es direkt vorangestellt
ist (geburtstag
); die Sortierreihenfolge
der Spalte gattung
wird hiervon nicht
berührt.
MySQL bietet eine Anzahl von Funktionen, mit denen Sie datumsbezogene Berechnungen durchführen können, um etwa Altersangaben zu ermitteln oder Teile aus Datumsangaben zu extrahieren.
Um zu bestimmen, wie alt Ihre Haustiere jeweils sind,
berechnen Sie die Differenz im Jahresbestandteil des aktuellen
und des Geburtsdatums und ziehen den Wert 1
ab, sofern das aktuelle Datum im Kalenderjahr vor dem
Geburtsdatum liegt. Die folgende Abfrage zeigt für jedes
Haustier das Geburtsdatum, das aktuelle Datum und das Alter in
Jahren an.
mysql>SELECT name, geburtstag, CURDATE(),
->(YEAR(CURDATE())-YEAR(geburtstag))
->- (RIGHT(CURDATE(),5)<RIGHT(geburtstag,5))
->AS alter
->FROM haustier;
+----------+------------+------------+-------+ | name | geburtstag | CURDATE() | alter | +----------+------------+------------+-------+ | Fluffy | 1993-02-04 | 2003-08-19 | 10 | | Claws | 1994-03-17 | 2003-08-19 | 9 | | Buffy | 1989-05-13 | 2003-08-19 | 14 | | Fang | 1990-08-27 | 2003-08-19 | 12 | | Bowser | 1989-08-31 | 2003-08-19 | 13 | | Chirpy | 1998-09-11 | 2003-08-19 | 4 | | Whistler | 1997-12-09 | 2003-08-19 | 5 | | Slim | 1996-04-29 | 2003-08-19 | 7 | | Puffball | 1999-03-30 | 2003-08-19 | 4 | +----------+------------+------------+-------+
Hierbei extrahiert YEAR()
die Jahreszahl
aus dem Datum, während mit RIGHT()
die
fünf Zeichen ganz rechts im Datum (MM-DD
,
also der Monat und der Tag) ermittelt werden. Der Teil des
Ausdrucks, der die Werte MM-DD
vergleicht,
ist entweder 1
oder 0
.
Hiermit wird von der Jahresdifferenz ggf. ein Jahr abgezogen,
sofern CURDATE()
(das aktuelle Datum) im
Kalenderjahr vor geburtstag
liegt. Der
gesamte Ausdruck wirkt ein wenig unübersichtlich, weswegen
ein Alias (alter
)
verwendet wird, um die Beschriftung der Ausgabespalte
sinnvoller zu gestalten.
Die Abfrage funktioniert zwar, aber das Ergebnis ließe sich
einfacher erfassen, wenn die Datensätze in einer bestimmten
Reihenfolge angezeigt würden. Dies ist durch Ergänzen der
Klausel ORDER BY name
möglich, die die
Ausgaben dem Namen nach sortiert:
mysql>SELECT name, geburtstag, CURDATE(),
->(YEAR(CURDATE())-YEAR(geburtstag))
->- (RIGHT(CURDATE(),5)<RIGHT(geburtstag,5))
->AS alter
->FROM haustier ORDER BY name;
+----------+------------+------------+-------+ | name | geburtstag | CURDATE() | alter | +----------+------------+------------+-------+ | Bowser | 1989-08-31 | 2003-08-19 | 13 | | Buffy | 1989-05-13 | 2003-08-19 | 14 | | Chirpy | 1998-09-11 | 2003-08-19 | 4 | | Claws | 1994-03-17 | 2003-08-19 | 9 | | Fang | 1990-08-27 | 2003-08-19 | 12 | | Fluffy | 1993-02-04 | 2003-08-19 | 10 | | Puffball | 1999-03-30 | 2003-08-19 | 4 | | Slim | 1996-04-29 | 2003-08-19 | 7 | | Whistler | 1997-12-09 | 2003-08-19 | 5 | +----------+------------+------------+-------+
Um die Ausgabe nach dem Alter statt dem Namen zu sortieren,
verwenden Sie einfach eine andere ORDER
BY
-Klausel:
mysql>SELECT name, geburtstag, CURDATE(),
->(YEAR(CURDATE())-YEAR(geburtstag))
->- (RIGHT(CURDATE(),5)<RIGHT(geburtstag,5))
->AS alter
->FROM haustier ORDER BY alter;
+----------+------------+------------+-------+ | name | geburtstag | CURDATE() | alter | +----------+------------+------------+-------+ | Chirpy | 1998-09-11 | 2003-08-19 | 4 | | Puffball | 1999-03-30 | 2003-08-19 | 4 | | Whistler | 1997-12-09 | 2003-08-19 | 5 | | Slim | 1996-04-29 | 2003-08-19 | 7 | | Claws | 1994-03-17 | 2003-08-19 | 9 | | Fluffy | 1993-02-04 | 2003-08-19 | 10 | | Fang | 1990-08-27 | 2003-08-19 | 12 | | Bowser | 1989-08-31 | 2003-08-19 | 13 | | Buffy | 1989-05-13 | 2003-08-19 | 14 | +----------+------------+------------+-------+
Eine ähnliche Abfrage kann verwendet werden, um das erreichte
Alter bereits verstorbener Tiere zu bestimmen. Welche Tiere
dies sind, ermitteln Sie durch die Überprüfung, ob für
todestag
der Wert NULL
lautet. Bei denjenigen Datensätzen, bei denen der Wert nicht
NULL
ist, berechnen Sie die Differenz
zwischen den Werten todestag
und
geburtstag
:
mysql>SELECT name, geburtstag, todestag,
->(YEAR(todestag)-YEAR(geburtstag)) - (RIGHT(todestag,5)<RIGHT(geburtstag,5))
->AS alter
->FROM haustier WHERE todestag IS NOT NULL ORDER BY alter;
+--------+------------+------------+-------+ | name | geburtstag | todestag | alter | +--------+------------+------------+-------+ | Bowser | 1989-08-31 | 1995-07-29 | 5 | +--------+------------+------------+-------+
Die Abfrage verwendet todestag IS NOT NULL
statt todestag <> NULL
, da
NULL
ein Sonderwert ist, der nicht mithilfe
der üblichen Vergleichsoperatoren verglichen werden kann. Wir
werden später noch darauf eingehen. Siehe auch
Abschnitt 3.3.4.6, „Mit NULL
-Werten arbeiten“.
Was aber, wenn Sie nun wissen wollen, welche Tiere im
nächsten Monat Geburtstag haben? Für diese Art der
Berechnung sind Jahr und Tag irrelevant: Sie müssen lediglich
den Monat aus der Spalte geburtstag
extrahieren. MySQL bietet mehrere Funktionen zur Extraktion
von Datumsbestandteilen, z. B. YEAR()
,
MONTH()
und
DAYOFMONTH()
. MONTH()
ist für unsere Belange die passende Funktion. Um zu sehen,
wie sie funktioniert, führen Sie eine einfache Abfrage aus,
die den Wert von geburtstag
und
MONTH(geburtstag)
anzeigt:
mysql> SELECT name, geburtstag, MONTH(geburtstag) FROM haustier;
+----------+------------+-------------------+
| name | geburtstag | MONTH(geburtstag) |
+----------+------------+-------------------+
| Fluffy | 1993-02-04 | 2 |
| Claws | 1994-03-17 | 3 |
| Buffy | 1989-05-13 | 5 |
| Fang | 1990-08-27 | 8 |
| Bowser | 1989-08-31 | 8 |
| Chirpy | 1998-09-11 | 9 |
| Whistler | 1997-12-09 | 12 |
| Slim | 1996-04-29 | 4 |
| Puffball | 1999-03-30 | 3 |
+----------+------------+-------------------+
Das Suchen von Tieren, die nächsten Monat Geburtstag haben,
ist ebenfalls ganz einfach. Nehmen wir einmal an, es wäre
April. In diesem Fall ist der Monatswert 4
– Sie suchen also nach Tieren, die im Mai (d. h. im Monat
5
) geboren sind. Das geht wie folgt:
mysql> SELECT name, geburtstag FROM haustier WHERE MONTH(geburtstag) = 5;
+-------+------------+
| name | geburtstag |
+-------+------------+
| Buffy | 1989-05-13 |
+-------+------------+
Wenn der aktuelle Monat Dezember ist, gibt es eine kleine
Komplikation. Sie können nämlich nicht einfach die
Monatsnummer (12
) um den Wert
1
erhöhen – die Suche nach im Monat
13
geborenen Tieren brächte kein Ergebnis,
weil es diesen Monat nicht gibt. Schließlich suchen Sie nach
Tieren, die im Januar (Monat 1
) geboren
sind.
Sie können die Abfrage so verfassen, dass sie unabhängig vom
aktuellen Monat funktioniert, sodass Sie die Nummer eines
bestimmten Monats gar nicht verwenden müssen.
DATE_ADD()
erlaubt Ihnen das Addieren eines
bestimmten Zeitintervalls für ein gegebenes Datum. Wenn Sie
einen Monat zum aktuellen Wert von
CURDATE()
hinzuaddieren wollen, extrahieren
Sie den Monatsbestandteil mit MONTH()
. Das
Ergebnis ist der Monat, in dem Sie nach Geburtstagen suchen
müssen:
mysql>SELECT name, geburtstag FROM haustier
->WHERE MONTH(geburtstag) = MONTH(DATE_ADD(CURDATE(),INTERVAL 1 MONTH));
Eine andere Möglichkeit, diese Aufgabe zu lösen, besteht
darin, 1
hinzuzuaddieren und dann den auf
den aktuellen Monat folgenden Monat zu ermitteln, wobei
mithilfe der Modulofunktion (MOD
) der
Monatswert auf 0
gesetzt wird, wenn er
derzeit 12
beträgt:
mysql>SELECT name, geburtstag FROM haustier
->WHERE MONTH(geburtstag) = MOD(MONTH(CURDATE()), 12) + 1;
Beachten Sie, dass MONTH
eine Zahl zwischen
1
und 12
zurückgibt.
Ferner gibt MOD(something,12)
eine Zahl
zwischen 0
und 11
zurück. Insofern muss die Addition nach
MOD()
erfolgen, andernfalls würden wir von
November (11
) direkt zu Januar
(1
) springen.
Wenn Sie mit dem Wert NULL
noch keine
Erfahrung haben, kann Ihnen manche Überraschung bevorstehen.
Vom Konzept her bezeichnet NULL
einen
„fehlenden unbekannten Wert“ und wird etwas
anders behandelt als andere Werte. Um auf
NULL
zu prüfen, können Sie arithmetische
Vergleichsoperatoren wie =
,
<
oder <>
nicht
verwenden. Um dies zu demonstrieren, geben Sie einmal
Folgendes ein:
mysql> SELECT 1 = NULL, 1 <> NULL, 1 < NULL, 1 > NULL;
+----------+-----------+----------+----------+
| 1 = NULL | 1 <> NULL | 1 < NULL | 1 > NULL |
+----------+-----------+----------+----------+
| NULL | NULL | NULL | NULL |
+----------+-----------+----------+----------+
Offensichtlich lassen sich aus diesen Vergleichen keine
sinngebenden Ergebnisse ziehen. Verwenden Sie stattdessen die
Operatoren IS NULL
und IS NOT
NULL
:
mysql> SELECT 1 IS NULL, 1 IS NOT NULL;
+-----------+---------------+
| 1 IS NULL | 1 IS NOT NULL |
+-----------+---------------+
| 0 | 1 |
+-----------+---------------+
Beachten Sie, dass 0
oder
NULL
in MySQL „falsch“
entspricht, während alles andere wahr ist. Der
standardmäßig „wahr“ entsprechende Wert aus
einer booleschen Operation ist 1
.
Die Sonderbehandlung für NULL
ist der
Grund dafür, warum im vorherigen Abschnitt die Frage, welche
Tiere nicht mehr leben, mit todestag IS NOT
NULL
statt mit todestag <>
NULL
ermittelt werden musste.
Zwei NULL
in einer GROUP
BY
-Klausel werden als gleichberechtigt betrachtet.
Wenn Sie eine ORDER BY
-Klausel verwenden,
werden NULL
-Werte zuerst angezeigt, sofern
Sie ORDER BY ... ASC
angeben; im
umgekehrten Fall ORDER BY ... DESC
erscheinen sie hingegen am Ende der Ergebnislisten.
Ein häufiger Fehler beim Umgang mit NULL
besteht in der Annahme, dass es nicht möglich ist, eine Null
oder einen Leer-String in eine Spalte einzufügen, die als
NOT NULL
definiert ist. Das stimmt nicht.
Es handelt sich dabei vielmehr um echte Werte, während
NULL
die Bedeutung „kein Wert“
hat. Sie können dies ganz einfach wie folgt durch Verwendung
von IS
[NOT
]
NULL
testen:
mysql> SELECT 0 IS NULL, 0 IS NOT NULL, '' IS NULL, '' IS NOT NULL;
+-----------+---------------+------------+----------------+
| 0 IS NULL | 0 IS NOT NULL | '' IS NULL | '' IS NOT NULL |
+-----------+---------------+------------+----------------+
| 0 | 1 | 0 | 1 |
+-----------+---------------+------------+----------------+
Es ist also durchaus möglich, eine Null oder einen
Leer-String in eine NOT NULL
-Spalte
einzusetzen, denn diese Werte sind in der Tat NOT
NULL
. Siehe auch
Abschnitt A.5.3, „Probleme mit NULL
-Werten“.
MySQL ermöglicht einen Mustervergleich sowohl nach SQL-Standard als auch basierend auf erweiterten regulären Ausdrücken, wie man es von Unix-Hilfsprogrammen wie vi, grep und sed her kennt.
Beim SQL-Mustervergleich können Sie
‘_
’ für eine Übereinstimmung
mit einzelnen Zeichen sowie ‘%
’
für eine Übereinstimmung mit einer beliebigen Anzahl von
Zeichen (einschließlich 0 Zeichen) verwenden. In MySQL wird
bei SQL-Mustern standardmäßig keine Unterscheidung der
Groß-/Kleinschreibung vorgenommen. Einige Beispiele sind hier
aufgeführt. Achten Sie darauf, in Verbindung mit SQL-Mustern
nicht =
oder <>
zu
verwenden, sondern die Vergleichsoperatoren
LIKE
bzw. NOT LIKE
.
Namen, die mit ‘b
’ beginnen,
finden Sie so:
mysql> SELECT * FROM haustier WHERE name LIKE 'b%';
+--------+----------+---------+------------+------------+------------+
| name | besitzer | gattung | geschlecht | geburtstag | todestag |
+--------+----------+---------+------------+------------+------------+
| Buffy | Harold | Hund | w | 1989-05-13 | NULL |
| Bowser | Diane | Hund | m | 1989-08-31 | 1995-07-29 |
+--------+----------+---------+------------+------------+------------+
Namen, die auf ‘fy
’ enden,
finden Sie so:
mysql> SELECT * FROM haustier WHERE name LIKE '%fy';
+--------+----------+---------+------------+------------+----------+
| name | besitzer | gattung | geschlecht | geburtstag | todestag |
+--------+----------+---------+------------+------------+----------+
| Fluffy | Harold | Katze | w | 1993-02-04 | NULL |
| Buffy | Harold | Hund | w | 1989-05-13 | NULL |
+--------+----------+---------+------------+------------+----------+
Und Namen, die ‘w
’ enthalten,
finden Sie so:
mysql> SELECT * FROM haustier WHERE name LIKE '%w%';
+----------+----------+---------+------------+------------+------------+
| name | besitzer | gattung | geschlecht | geburtstag | todestag |
+----------+----------+---------+------------+------------+------------+
| Claws | Gwen | Katze | m | 1994-03-17 | NULL |
| Bowser | Diane | Hund | m | 1989-08-31 | 1995-07-29 |
| Whistler | Gwen | Vogel | NULL | 1997-12-09 | NULL |
+----------+----------+---------+------------+------------+------------+
Um Namen zu ermitteln, die aus genau fünf Zeichen bestehen,
verwenden Sie fünf Instanzen des Musterzeichens
‘_
’:
mysql> SELECT * FROM haustier WHERE name LIKE '_____';
+-------+----------+---------+------------+------------+----------+
| name | besitzer | gattung | geschlecht | geburtstag | todestag |
+-------+----------+---------+------------+------------+----------+
| Claws | Gwen | Katze | m | 1994-03-17 | NULL |
| Buffy | Harold | Hund | w | 1989-05-13 | NULL |
+-------+----------+---------+------------+------------+----------+
Der andere von MySQL unterstützte Mustervergleichstyp nutzt
erweiterte reguläre Ausdrücke. Wenn Sie bei diesem Mustertyp
auf Übereinstimmung testen, verwenden Sie die Operatoren
REGEXP
und NOT REGEXP
(bzw. deren Synonyme RLIKE
und NOT
RLIKE
).
Erweiterte reguläre Ausdrücke weisen u. a. die folgenden Merkmale auf:
‘.
’ stimmt mit genau einem
beliebigen Zeichen überein.
Eine Zeichenklasse ‘[...]
’
führt zur Übereinstimmung bei jedem Zeichen in den
Klammern. Beispielsweise liegt bei
‘[abc]
’ eine
Übereinstimmung mit ‘a
’,
‘b
’ oder
‘c
’ vor. Um einen
Zeichenbereich anzugeben, verwenden Sie einen Bindestrich.
‘[a-z]
’ führt zur
Übereinstimmung mit einem beliebigen Buchstaben,
wohingegen ‘[0-9]
’ einer
Übereinstimmung mit jeder Ziffer entspricht.
‘*
’ stimmt mit null oder
mehr Instanzen des Elements überein, das ihm vorangeht.
Beispielsweise liegt bei
‘x*
’ eine Übereinstimmung
mit einer beliebigen Anzahl von
‘x
’-Zeichen vor. Gleiches
gilt bei ‘[0-9]*
’ für eine
beliebige Anzahl von Ziffern und bei
‘.*
’ für eine beliebige
Anzahl eines beliebigen Elements.
Ein REGEXP
-Mustervergleich ist
erfolgreich, wenn eine Übereinstimmung des Musters an
beliebiger Stelle im getesteten Wert vorliegt. (Hier liegt
ein Unterschied zum
LIKE
-Mustervergleich, der nur
erfolgreich ist, wenn das Muster mit dem gesamten Wert
übereinstimmt.)
Um einen Anker im Muster zu setzen, sodass es mit dem
Anfang oder Ende des getesteten Wertes übereinstimmen
muss, verwenden Sie ‘^
’ am
Anfang bzw. ‘$
’ am Ende des
Musters.
Um zu demonstrieren, wie erweiterte reguläre Ausdrücke
funktionieren, haben wir die oben gezeigten
LIKE
-Abfragen so umgeschrieben, dass sie
REGEXP
verwenden.
Um Namen zu finden, die mit ‘b
’
beginnen, verwenden Sie ‘^
’
für eine Übereinstimmung mit dem Namensanfang:
mysql> SELECT * FROM haustier WHERE name REGEXP '^b';
+--------+----------+---------+------------+------------+------------+
| name | besitzer | gattung | geschlecht | geburtstag | todestag |
+--------+----------+---------+------------+------------+------------+
| Buffy | Harold | Hund | w | 1989-05-13 | NULL |
| Bowser | Diane | Hund | m | 1989-08-31 | 1995-07-29 |
+--------+----------+---------+------------+------------+------------+
Wenn Sie einen REGEXP
-Vergleich mit
Unterscheidung der Groß-/Kleinschreibung wirklich erzwingen
wollen, verwenden Sie das Schlüsselwort
BINARY
, um aus einem der Strings einen
Binär-String zu machen. Bei folgender Abfrage liegt eine
Übereinstimmung nur bei einem kleinen
‘b
’ am Anfang des Namens vor:
mysql> SELECT * FROM haustier WHERE name REGEXP BINARY '^b';
Um Namen zu finden, die auf
‘fy
’ enden, verwenden Sie
‘$
’ für eine Übereinstimmung
mit dem Namensende:
mysql> SELECT * FROM haustier WHERE name REGEXP 'fy$';
+--------+----------+---------+------------+------------+----------+
| name | besitzer | gattung | geschlecht | geburtstag | todestag |
+--------+----------+---------+------------+------------+----------+
| Fluffy | Harold | Katze | w | 1993-02-04 | NULL |
| Buffy | Harold | Hund | w | 1989-05-13 | NULL |
+--------+----------+---------+------------+------------+----------+
Namen schließlich, die ‘w
’
enthalten, finden Sie mit folgender Abfrage:
mysql> SELECT * FROM haustier WHERE name REGEXP 'w';
+----------+----------+---------+------------+------------+------------+
| name | besitzer | gattung | geschlecht | geburtstag | todestag |
+----------+----------+---------+------------+------------+------------+
| Claws | Gwen | Katze | m | 1994-03-17 | NULL |
| Bowser | Diane | Hund | m | 1989-08-31 | 1995-07-29 |
| Whistler | Gwen | Vogel | NULL | 1997-12-09 | NULL |
+----------+----------+---------+------------+------------+------------+
Da ein auf einem regulären Ausdruck basierendes Muster eine Übereinstimmung liefert, wenn es an beliebiger Stelle im Wert auftaucht, ist es in dieser Abfrage nicht notwendig, ein Jokerzeichen an den beiden Seiten des Musters zu setzen (bei einem SQL-Muster wäre dies hingegen erforderlich, um eine Übereinstimmung zu erzielen).
Um Namen zu ermitteln, die aus genau fünf Zeichen bestehen,
verwenden Sie ‘^
’ und
‘$
’ für Übereinstimmungen
für Anfang und Ende des Namens und fünf Instanzen von
‘.
’ dazwischen:
mysql> SELECT * FROM haustier WHERE name REGEXP '^.....$';
+-------+----------+---------+------------+------------+----------+
| name | besitzer | gattung | geschlecht | geburtstag | todestag |
+-------+----------+---------+------------+------------+----------+
| Claws | Gwen | Katze | m | 1994-03-17 | NULL |
| Buffy | Harold | Hund | w | 1989-05-13 | NULL |
+-------+----------+---------+------------+------------+----------+
Sie könnten diese Abfrage auch mithilfe des Operators
{
(„n
}n
-mal wiederholen“)
schreiben:
mysql> SELECT * FROM haustier WHERE name REGEXP '^.{5}$';
+-------+----------+---------+------------+------------+----------+
| name | besitzer | gattung | geschlecht | geburtstag | todestag |
+-------+----------+---------+------------+------------+----------+
| Claws | Gwen | Katze | m | 1994-03-17 | NULL |
| Buffy | Harold | Hund | w | 1989-05-13 | NULL |
+-------+----------+---------+------------+------------+----------+
In Anhang G, Beschreibung der MySQL-Syntax für reguläre Ausdrücke, finden Sie weitere Informationen zur Syntax regulärer Ausdrücke.
Datenbanken werden häufig zur Beantwortung der Frage „Wie häufig taucht ein bestimmter Datentyp in einer Tabelle auf?“ verwendet. So möchten Sie vielleicht wissen, wie viele Tiere Sie oder ein anderer Besitzer haben, oder verschiedene statistische Erhebungen zu Ihren Tieren machen.
Das Zählen aller vorhandenen Tiere entspricht der Frage
„Wie viele Datensätze sind in der Tabelle
haustier
vorhanden?“, denn es gibt
genau einen Datensatz pro Tier. COUNT(*)
zählt die Anzahl der Datensätze, d. h., die Abfrage zur
Zählung Ihrer Tiere sieht wie folgt aus:
mysql> SELECT COUNT(*) FROM haustier;
+----------+
| COUNT(*) |
+----------+
| 9 |
+----------+
Weiter oben haben Sie die Namen der Leute abgerufen, die Tiere
besitzen. Mit COUNT()
können Sie etwa
ermitteln, wie viele Tiere jeder Besitzer hat:
mysql> SELECT besitzer, COUNT(*) FROM haustier GROUP BY besitzer;
+----------+----------+
| besitzer | COUNT(*) |
+----------+----------+
| Benny | 2 |
| Diane | 2 |
| Gwen | 3 |
| Harold | 2 |
+----------+----------+
Beachten Sie, dass GROUP BY
zur Gruppierung
aller Datensätze für jeden Besitzer
besitzer
verwendet wird. Ohne diese Klausel
erhalten Sie lediglich eine Fehlermeldung:
mysql> SELECT besitzer, COUNT(*) FROM haustier;
ERROR 1140 (42000): Mixing of GROUP columns (MIN(),MAX(),COUNT(),...)
with no GROUP columns is illegal if there is no GROUP BY clause
COUNT()
und GROUP BY
sind praktisch, wenn Sie Ihre Daten auf verschiedene Arten
charakterisieren wollen. Die folgenden Beispiele zeigen
verschiedene Wege, statistische Daten zu den Tieren zu
erheben.
Anzahl der Exemplare je Tierart:
mysql> SELECT gattung, COUNT(*) FROM haustier GROUP BY gattung;
+----------+----------+
| gattung | COUNT(*) |
+----------+----------+
| Vogel | 2 |
| Katze | 2 |
| Hund | 3 |
| Hamster | 1 |
| Schlange | 1 |
+----------+----------+
Anzahl der Tiere je Geschlecht:
mysql> SELECT geschlecht, COUNT(*) FROM haustier GROUP BY geschlecht;
+------------+----------+
| geschlecht | COUNT(*) |
+------------+----------+
| NULL | 1 |
| w | 4 |
| m | 4 |
+------------+----------+
(In dieser Ausgabe gibt NULL
an, dass das
Geschlecht unbekannt ist.)
Anzahl der Tiere je Kombination von Tierart und Geschlecht:
mysql> SELECT gattung, geschlecht, COUNT(*) FROM haustier GROUP BY gattung, geschlecht;
+----------+------------+----------+
| gattung | geschlecht | COUNT(*) |
+----------+------------+----------+
| Vogel | NULL | 1 |
| Vogel | w | 1 |
| Katze | w | 1 |
| Katze | m | 1 |
| Hund | w | 1 |
| Hund | m | 2 |
| Hamster | w | 1 |
| Schlange | m | 1 |
+----------+------------+----------+
Wenn Sie COUNT()
verwenden, müssen Sie
nicht die gesamte Tabelle abrufen. Die obige Abfrage
beispielsweise sieht wie folgt aus, wenn Sie nur für Hunde
und Katzen durchgeführt wird:
mysql>SELECT gattung, geschlecht, COUNT(*) FROM haustier
->WHERE gattung = 'Hund' OR gattung = 'Katze'
->GROUP BY gattung, geschlecht;
+---------+------------+----------+ | gattung | geschlecht | COUNT(*) | +---------+------------+----------+ | Katze | w | 1 | | Katze | m | 1 | | Hund | w | 1 | | Hund | m | 2 | +---------+------------+----------+
Oder, wenn Sie die Anzahl der Tiere je Geschlecht nur für diejenigen Tiere anzeigen wollen, deren Geschlecht auch bekannt ist:
mysql>SELECT gattung, geschlecht, COUNT(*) FROM haustier
->WHERE geschlecht IS NOT NULL
->GROUP BY gattung, geschlecht;
+----------+------------+----------+ | gattung | geschlecht | COUNT(*) | +----------+------------+----------+ | Vogel | w | 1 | | Katze | w | 1 | | Katze | m | 1 | | Hund | w | 1 | | Hund | m | 2 | | Hamster | w | 1 | | Schlange | m | 1 | +----------+------------+----------+
Die Tabelle haustier
enthält Daten zu den
Tieren, die Sie besitzen. Wollen Sie andere Informationen zu
diesen aufzeichnen – z. B. Ereignisse wie Tierarztbesuche
oder die Ankunft von Nachwuchs –, dann benötigen Sie eine
zweite Tabelle. Wie sollte diese Tabelle aussehen? Folgende
Angaben müssen enthalten sein:
Der Name des Tieres, damit Sie wissen, welches Ereignis zu welchem Tier gehört.
Das Ereignisdatum.
Ein Feld, welches das Ereignis beschreibt.
Ein Ereignistypfeld, das Sie zum Kategorisieren der Ereignisse benötigen.
Unter Berücksichtigung dieser Aspekte könnte die
CREATE TABLE
-Anweisung für die Tabelle
ereignis
wie folgt aussehen:
mysql>CREATE TABLE ereignis (name VARCHAR(20), datum DATE,
->typ VARCHAR(15), bemerkung VARCHAR(255));
Wie bei der Tabelle haustier
ist es auch
hier am einfachsten, die bereits bekannten Daten über eine
tabulatorgetrennte Textdatei in die Tabelle einzuladen. Diese
Datei soll die folgenden Informationen enthalten:
name | datum | typ | bemerkung |
Fluffy | 1995-05-15 | Nachwuchs | 4 Kätzchen, 3 weiblich, 1 männlich |
Buffy | 1993-06-23 | Nachwuchs | 5 Welpen, 2 weiblich, 3 männlich |
Buffy | 1994-06-19 | Nachwuchs | 3 Welpen, 3 weiblich |
Chirpy | 1999-03-21 | Tierarzt | Schnabel begradigt |
Slim | 1997-08-03 | Tierarzt | gebrochene Rippe |
Bowser | 1991-10-12 | Hundepension | |
Fang | 1991-10-12 | Hundepension | |
Fang | 1998-08-28 | Geburtstag | neues Kauspielzeug |
Claws | 1998-03-17 | Geburtstag | neues Flohhalsband |
Whistler | 1998-12-09 | Geburtstag | erster Geburtstag |
Laden Sie die Datensätze wie folgt:
mysql> LOAD DATA LOCAL INFILE 'ereignis.txt' INTO TABLE ereignis;
Mit dem, was Sie bereits aus den Abfragen erlernt haben, die
Sie zur Tabelle haustier
abgesetzt haben,
sollten Sie auch Daten aus der Tabelle
ereignis
abrufen können; die Prinzipien
sind dieselben. Was aber, wenn Sie die Fragen, die Sie
stellen, mit der Tabelle ereignis
allein nicht
beantworten können?
Nehmen wir an, Sie wollen herausfinden, in welchem Alter die
jeweiligen Tiere Nachwuchs bekommen haben. Wir haben bereits
weiter oben gesehen, wie Sie das Alter auf der Grundlage
zweiter Datumsangaben berechnen. Das Datum, an dem die Mutter
ihren Nachwuchs auf die Welt gebracht hat, ist in der Tabelle
ereignis
gespeichert, aber um das Alter der
Mutter am Tag der Niederkunft zu ermitteln, benötigen Sie das
Geburtsdatum, welches wiederum in der Tabelle
haustier
abgelegt ist. Das bedeutet, dass
wir zwei Tabellen benötigen:
mysql>SELECT haustier.name,
->(YEAR(datum)-YEAR(geburtstag)) - (RIGHT(datum,5)<RIGHT(geburtstag,5)) AS alter,
->bemerkung
->FROM haustier, ereignis
->WHERE haustier.name = ereignis.name AND ereignis.typ = 'Nachwuchs';
+--------+-------+-------------------------------------+ | name | alter | bemerkung | +--------+-------+-------------------------------------+ | Fluffy | 2 | 4 Kätzchen, 3 weiblich, 1 männlich | | Buffy | 4 | 5 Welpen, 2 weiblich, 3 männlich | | Buffy | 5 | 3 Welpen, 3 weiblich | +--------+-------+-------------------------------------+
Bei dieser Abfrage fällt Verschiedenes auf:
Die FROM
-Klausel listet zwei Tabellen
auf, da die Abfrage Informationen aus beiden Tabellen
abrufen muss.
Wenn Sie Daten aus mehreren Tabellen kombinieren
(verknüpfen), dann müssen Sie angeben, wie die
Datensätze der einen Tabelle denen der anderen Tabelle
zugeordnet werden können. Dies ist recht einfach, da
beide Tabellen eine Spalte name
haben.
Die Abfrage verwendet eine
WHERE
-Klausel zur Zuordnung von
Datensätzen der beiden Tabellen basierend auf den Werten
in der Spalte name
.
Da die Spalte name
in beiden Tabellen
auftritt, müssen Sie bei Bezugnahme auf diese Spalte
angeben, welche der beiden Tabellen Sie meinen. Dies
erfolgt durch Voranstellung des Tabellennamens vor den
Spaltennamen.
Um eine solche Verknüpfung – einen Join – durchzuführen,
brauchen Sie keine zwei Tabellen. Manchmal ist es nützlich,
eine Tabelle mit sich selbst zu verknüpfen, wenn man etwa
Datensätze in einer Tabelle mit anderen Datensätzen in
derselben Tabelle vergleichen will. Um beispielsweise
Zuchtmöglichkeiten unter Ihren Tieren auszuloten, kann eine
Verknüpfung der Tabelle haustier
mit sich
selbst praktisch sein, um passende Männchen und Weibchen
einer Tierart zu ermitteln:
mysql>SELECT p1.name, p1.geschlecht, p2.name, p2.geschlecht, p1.gattung
->FROM haustier AS p1, haustier AS p2
->WHERE p1.gattung = p2.gattung AND p1.geschlecht = 'w' AND p2.geschlecht = 'm';
+--------+------------+--------+------------+---------+ | name | geschlecht | name | geschlecht | gattung | +--------+------------+--------+------------+---------+ | Fluffy | w | Claws | m | Katze | | Buffy | w | Fang | m | Hund | | Buffy | w | Bowser | m | Hund | +--------+------------+--------+------------+---------+
In dieser Abfrage geben Sie Aliase für den Tabellennamen an, um auf die Spalten Bezug zu nehmen und klar zu machen, welcher Tabelleninstanz die Bezugnahme auf eine Spalte zuzuordnen ist.
Was können Sie tun, wenn Sie den Namen einer Datenbank oder Tabelle vergessen haben oder nicht mehr wissen, wie die Struktur einer gegebenen Tabelle aussieht (d. h., wie beispielsweise die Spalten heißen)? MySQL bietet zur Lösung dieses Problems eine Reihe von Anweisungen an, die Informationen zu unterstützten Datenbanken und Tabellen vermitteln.
Die Anweisung SHOW DATABASES
, die die vom
Server verwalteten Datenbanken auflistet, haben Sie bereits
gesehen. Um herauszufinden, welche Datenbank gerade gewählt ist,
verwenden Sie die Funktion DATABASE()
:
mysql> SELECT DATABASE();
+------------+
| DATABASE() |
+------------+
| menagerie |
+------------+
Haben Sie noch keine Datenbank ausgewählt, dann lautet das
Ergebnis NULL
.
Um herauszufinden, welche Tabellen die Standarddatenbank enthält (wenn Sie etwa den Namen einer Tabelle nicht mehr genau wissen), verwenden Sie diesen Befehl:
mysql> SHOW TABLES;
+---------------------+
| Tables in menagerie |
+---------------------+
| ereignis |
| haustier |
+---------------------+
Wollen Sie die Struktur einer Tabelle ermitteln, dann ist der
Befehl DESCRIBE
praktisch, denn er zeigt
Informationen zu allen Spalten einer Tabelle an:
mysql> DESCRIBE haustier;
+------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| name | varchar(20) | YES | | NULL | |
| besitzer | varchar(20) | YES | | NULL | |
| gattung | varchar(20) | YES | | NULL | |
| geschlecht | char(1) | YES | | NULL | |
| geburtstag | date | YES | | NULL | |
| todestag | date | YES | | NULL | |
+------------+-------------+------+-----+---------+-------+
Field
ist dabei der Spaltenname,
Type
der Datentyp der Spalte,
NULL
zeigt an, ob die Spalte
NULL
-Werte enthalten kann,
Key
, ob die Spalte indiziert ist, und
Default
bezeichnet den Standardwert der Spalte.
Wenn Sie Indizes in einer Tabelle verwenden, generiert
SHOW INDEX FROM
Informationen zu
diesen.
tbl_name
In obigen Abschnitten haben Sie mysql interaktiv zur Eingabe von Abfragen und zur Anzeige der Ergebnisse verwendet. Sie können mysql aber auch im Stapelbetrieb (Batch-Modus) ausführen. Zu diesem Zweck legen Sie die gewünschten Befehle in einer Datei ab und weisen mysql dann an, diese Datei auszulesen und die Befehle zu verarbeiten:
shell> mysql < batch-file
Wenn Sie mysql unter Windows ausführen und gewisse Sonderzeichen in der Datei Probleme verursachen, dann können Sie Folgendes tun:
C:\> mysql -e "source batch-file
"
Müssen Sie die Verbindungsparameter auf der Befehlszeile angeben, dann könnte der Befehl so aussehen:
shell>mysql -h
Enter password:host
-uuser
-p <batch-file
********
Wenn Sie mysql auf diese Weise verwenden, erstellen Sie eine Skriptdatei und führen das Skript dann aus.
Soll das Skript auch dann vollständig abgearbeitet werden, wenn
enthaltene Anweisungen Fehler erzeugen, dann sollten Sie die
Befehlszeilenoption --force
verwenden.
Warum sollte man Skripten verwenden? Dafür gibt es ein paar gute Gründe:
Führen Sie eine Abfrage häufiger aus (beispielsweise einmal in der Woche), dann können Sie ein Skript erstellen und sich so die Tipparbeit sparen, die bei jeder Neueingabe der Abfrage anfallen würde.
Sie können neue Abfragen aus bereits vorhandenen ähnlichen erstellen, indem Sie Skriptdateien kopieren und bearbeiten.
Der Stapelbetrieb kann auch nützlich sein, wenn Sie eine Abfrage entwickeln; dies gilt insbesondere für mehrzeilige Befehle oder aus mehreren Anweisungen bestehende Befehlsabfolgen. Wenn Sie einen Fehler machen, brauchen Sie nicht alles neu einzugeben. Beheben Sie den Fehler einfach in Ihrem Skript und weisen Sie mysql dann an, es erneut auszuführen.
Wenn Ihre Abfrage eine umfangreiche Ausgabe erzeugt, dann können Sie diese seitenweise anzeigen lassen, statt sie am oberen Bildschirmrand verschwinden zu sehen:
shell> mysql < batch-file
| more
Zur weiteren Verarbeitung können Sie die Ausgabe auch in eine Datei leiten:
shell> mysql < batch-file
> mysql.out
Sie können Ihr Skript auch an andere Benutzer weitergeben, damit diese ebenfalls die entsprechenden Befehle ausführen können.
Manche Situationen erlauben keine interaktive Vorgehensweise. Dies ist etwa der Fall, wenn eine Abfrage aus einem cron-Job heraus erfolgt. In diesem Fall müssen Sie den Stapelbetrieb verwenden.
Wenn Sie mysql im Stapelbetrieb verwenden, ist
das Standardausgabeformat anders (genauer gesagt, knapper) als im
interaktiven Modus. Die Ausgabe von SELECT DISTINCT
gattung FROM haustier
etwa sieht wie folgt aus, wenn
mysql interaktiv läuft:
+----------+ | gattung | +----------+ | Vogel | | Katze | | Hund | | Hamster | | Schlange | +----------+
Im Stapelbetrieb hingegen sieht die Ausgabe so aus:
gattung Vogel Katze Hund Hamster Schlange
Wenn Sie das interaktive Ausgabeformat auch im Stapelbetrieb
wünschen, verwenden Sie zum Aufruf mysql -t
.
Damit die Ausgabe der ausgeführten Befehle angezeigt wird,
verwenden Sie mysql -vvv
.
Sie können auch Skripten an der
mysql-Eingabeaufforderung verwenden. Hierzu
dient der Befehl source
bzw.
\.
:
mysql>source filename;
mysql>\. filename
AUTO_INCREMENT
Es folgen einige Beispiele dafür, wie man häufige Probleme mit MySQL löst.
Einige dieser Beispiele verwenden die Tabelle
shop
, in der die Preise jedes Artikels (bzw.
Artikelnummer) für bestimmte Händler aufgeführt sind. Wenn man
davon ausgeht, dass jeder Händler genau einen bestimmten
Festpreis für einen Artikel hat, dann ist
(artikel
, haendler
) ein
Primärschlüssel für die Datensätze.
Starten Sie das Befehlszeilen-Tool mysql und wählen Sie eine Datenbank aus:
shell> mysql your-database-name
(Bei den meisten MySQL-Installationen können Sie die Datenbank
test
verwenden.)
Erstellung der Beispieltabelle und Ausfüllen mit Daten erfolgen mit den folgenden Anweisungen:
mysql>CREATE TABLE shop (
->artikel INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL,
->haendler CHAR(20) DEFAULT '' NOT NULL,
->preis DOUBLE(16,2) DEFAULT '0.00' NOT NULL,
->PRIMARY KEY(artikel, haendler));
mysql>INSERT INTO shop VALUES
->(1,'A',3.45),(1,'B',3.99),(2,'A',10.99),(3,'B',1.45),
->(3,'C',1.69),(3,'D',1.25),(4,'D',19.95);
Nachdem Sie die Anweisungen abgesetzt haben, weist die Tabelle den folgenden Inhalt auf:
mysql> SELECT * FROM shop;
+---------+----------+-------+
| artikel | haendler | preis |
+---------+----------+-------+
| 0001 | A | 3.45 |
| 0001 | B | 3.99 |
| 0002 | A | 10.99 |
| 0003 | B | 1.45 |
| 0003 | C | 1.69 |
| 0003 | D | 1.25 |
| 0004 | D | 19.95 |
+---------+----------+-------+
„Welches ist die höchste Artikelnummer?“
SELECT MAX(artikel) AS artikel FROM shop; +---------+ | artikel | +---------+ | 4 | +---------+
Aufgabe: Ermitteln Sie Nummer, Händler und Preis des teuersten Artikels.
Dies lässt sich recht einfach mit einer Unterabfrage bewerkstelligen:
SELECT artikel, haendler, preis FROM shop WHERE preis=(SELECT MAX(preis) FROM shop);
Eine andere Lösung besteht darin, alle Datensätze nach Preis
aufsteigend zu sortieren und nur den ersten Datensatz mithilfe
der MySQL-spezifischen LIMIT
-Klausel
abzurufen:
SELECT artikel, haendler, preis FROM shop ORDER BY preis DESC LIMIT 1;
Hinweis: Wenn mehrere teuerste
Artikel zum gleichen Preis vorhanden sind, dann zeigt die
LIMIT
-Lösung nur einen davon an.
Aufgabe: Ermitteln Sie den höchsten Preis je Artikel.
SELECT artikel, MAX(preis) AS preis FROM shop GROUP BY artikel +---------+-------+ | artikel | preis | +---------+-------+ | 0001 | 3.99 | | 0002 | 10.99 | | 0003 | 1.69 | | 0004 | 19.95 | +---------+-------+
Aufgabe: Ermitteln Sie für jeden Artikel den oder die Händler mit dem höchsten Preis.
Dieses Problem lässt sich mit einer Unterabfrage wie der folgenden lösen:
SELECT artikel, haendler, preis FROM shop s1 WHERE preis=(SELECT MAX(s2.preis) FROM shop s2 WHERE s1.artikel = s2.artikel);
Sie können MySQL-Benutzervariablen verwenden, um die Ergebnisse zu vermerken, ohne sie in Temporärvariablen auf dem Client speichern zu müssen. (Siehe auch Abschnitt 9.3, „Benutzerdefinierte Variablen“.)
Um beispielsweise die Artikel mit dem höchsten und dem niedrigsten Preis zu ermitteln, können Sie Folgendes tun:
mysql>SELECT @min_preis:=MIN(preis),@max_preis:=MAX(preis) FROM shop;
mysql>SELECT * FROM shop WHERE preis=@min_preis OR preis=@max_preis;
+---------+----------+-------+ | artikel | haendler | preis | +---------+----------+-------+ | 0003 | D | 1.25 | | 0004 | D | 19.95 | +---------+----------+-------+
Bei MySQL unterstützen InnoDB
-Tabellen die
Überprüfung von Fremdschlüsselbeschränkungen. Siehe auch
Abschnitt 14.2, „InnoDB
-Tabellen“, und
Abschnitt 1.9.5.5, „Fremdschlüssel“.
Eine Fremdschlüsselbeschränkung ist nicht erforderlich, wenn
Sie lediglich zwei Tabellen miteinander verknüpfen wollen. Bei
anderen Speicher-Engines als InnoDB
ist dies
möglich, indem eine Spalte zur Verwendung einer
REFERENCES
-Klausel
definiert wird; diese hat keine eigentliche Wirkung und
dient Ihnen lediglich als Erinnerung oder Anmerkung,
damit Sie daran denken, dass die derzeit definierte Spalte auf
eine Spalte in einer anderen Tabelle verweisen soll.
Es ist bei Verwendung dieser Syntax extrem wichtig, sich zu
vergegenwärtigen, dass
tbl_name
(col_name
)
MySQL keinerlei Überprüfung durchführt, um
sicherzustellen, dass col_name
tatsächlich in tbl_name
vorhanden ist (bzw. dass tbl_name
selbst existiert),
MySQL keine Aktionen an tbl_name
– wie etwa das Löschen von Datensätzen – als Reaktion
auf Aktionen ausführt, die an Datensätzen in der von Ihnen
gerade definierten Tabelle vorgenommen werden (mit anderen
Worten, diese Syntax enthält keine Funktionalität wie etwa
ON DELETE
oder ON
UPDATE
; Sie können zwar eine ON
DELETE
- oder ON UPDATE
-Klausel
als Bestandteil der REFERENCES
-Klausel
schreiben, aber diese wird ebenfalls ignoriert),
diese Syntax eine Spalte erstellt (und keinerlei Index oder Schlüssel),
diese Syntax einen Fehler erzeugt, wenn damit eine
InnoDB
-Tabelle zu erzeugen versucht wird.
Sie können eine Spalte, die als Join-Spalte erstellt wurde, wie nachfolgend gezeigt verwenden:
CREATE TABLE person ( id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT, name CHAR(60) NOT NULL, PRIMARY KEY (id) ); CREATE TABLE shirt ( id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT, style ENUM('t-shirt', 'polo', 'dress') NOT NULL, color ENUM('red', 'blue', 'orange', 'white', 'black') NOT NULL, owner SMALLINT UNSIGNED NOT NULL REFERENCES person(id), PRIMARY KEY (id) ); INSERT INTO person VALUES (NULL, 'Antonio Paz'); SELECT @last := LAST_INSERT_ID(); INSERT INTO shirt VALUES (NULL, 'polo', 'blue', @last), (NULL, 'dress', 'white', @last), (NULL, 't-shirt', 'blue', @last); INSERT INTO person VALUES (NULL, 'Lilliana Angelovska'); SELECT @last := LAST_INSERT_ID(); INSERT INTO shirt VALUES (NULL, 'dress', 'orange', @last), (NULL, 'polo', 'red', @last), (NULL, 'dress', 'blue', @last), (NULL, 't-shirt', 'white', @last); SELECT * FROM person; +----+---------------------+ | id | name | +----+---------------------+ | 1 | Antonio Paz | | 2 | Lilliana Angelovska | +----+---------------------+ SELECT * FROM shirt; +----+---------+--------+-------+ | id | style | color | owner | +----+---------+--------+-------+ | 1 | polo | blue | 1 | | 2 | dress | white | 1 | | 3 | t-shirt | blue | 1 | | 4 | dress | orange | 2 | | 5 | polo | red | 2 | | 6 | dress | blue | 2 | | 7 | t-shirt | white | 2 | +----+---------+--------+-------+ SELECT s.* FROM person p, shirt s WHERE p.name LIKE 'Lilliana%' AND s.owner = p.id AND s.color <> 'white'; +----+-------+--------+-------+ | id | style | color | owner | +----+-------+--------+-------+ | 4 | dress | orange | 2 | | 5 | polo | red | 2 | | 6 | dress | blue | 2 | +----+-------+--------+-------+
Wenn sie auf diese Weise eingesetzt wird, wird die
REFERENCES
-Klausel in der Ausgabe von
SHOW CREATE TABLE
oder
DESCRIBE
nicht angezeigt:
SHOW CREATE TABLE shirt\G *************************** 1. row *************************** Table: shirt Create Table: CREATE TABLE `shirt` ( `id` smallint(5) unsigned NOT NULL auto_increment, `style` enum('t-shirt','polo','dress') NOT NULL, `color` enum('red','blue','orange','white','black') NOT NULL, `owner` smallint(5) unsigned NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1
Die Verwendung von REFERENCES
als derartigen
Kommentar oder „Erinnerung“ in einer
Spaltendefinition funktioniert sowohl mit
MyISAM
- als auch mit
BerkeleyDB
-Tabellen.
Eine Suche mit OR
über einen Schlüssel ist
in MySQL ebenso optimal gelöst wie die Verwendung von
AND
.
Der einzige etwas heikle Fall ist die Suche über zwei
verschiedene Schlüssel, die durch OR
kombiniert sind:
SELECT field1_index, field2_index FROM test_table WHERE field1_index = '1' OR field2_index = '1'
Dieser Fall ist optimiert. Siehe auch Abschnitt 7.2.6, „Optimierung durch Indexverschmelzung“.
Sie können das Problem auch effizient mithilfe einer Union
lösen, die die Ausgabe zweier getrennter
SELECT
-Anweisungen zusammenfasst. Siehe auch
Abschnitt 13.2.7.2, „UNION
“.
Jede SELECT
-Anweisung sucht nur über einen
Schlüssel und kann optimiert werden:
SELECT field1_index, field2_index FROM test_table WHERE field1_index = '1' UNION SELECT field1_index, field2_index FROM test_table WHERE field2_index = '1';
Das folgende Beispiel zeigt, wie Sie die Bitgruppenfunktionen zur Berechnung der Anzahl von Tagen im Monat verwenden können, an denen ein Benutzer eine bestimmte Webseite besucht hat.
CREATE TABLE t1 (year YEAR(4), month INT(2) UNSIGNED ZEROFILL, day INT(2) UNSIGNED ZEROFILL); INSERT INTO t1 VALUES(2000,1,1),(2000,1,20),(2000,1,30),(2000,2,2), (2000,2,23),(2000,2,23);
Die Beispieltabelle enthält Jahr/Monat/Tag-Werte, die die Besuche von Benutzern auf der Seite repräsentieren. Um zu ermitteln, an wie vielen verschiedenen Tagen in den einzelnen Monaten diese Besuche stattfanden, verwenden Sie folgende Abfrage:
SELECT year,month,BIT_COUNT(BIT_OR(1<<day)) AS days FROM t1 GROUP BY year,month;
Das Ergebnis sieht wie folgt aus:
+------+-------+------+ | year | month | days | +------+-------+------+ | 2000 | 01 | 3 | | 2000 | 02 | 2 | +------+-------+------+
Die Abfrage berechnet, wie viele verschiedene Tage in der Tabelle für jede Jahr/Monat/Tag-Kombination erscheinen, und entfernt doppelte Einträge dabei automatisch.
Das Attribut AUTO_INCREMENT
kann zur
Erzeugung einer eindeutigen Kennung für neue Datensätze
verwendet werden:
CREATE TABLE animals ( id MEDIUMINT NOT NULL AUTO_INCREMENT, name CHAR(30) NOT NULL, PRIMARY KEY (id) ); INSERT INTO animals (name) VALUES ('dog'),('cat'),('penguin'), ('lax'),('whale'),('ostrich'); SELECT * FROM animals;
Das Ergebnis sieht wie folgt aus:
+----+---------+ | id | name | +----+---------+ | 1 | dog | | 2 | cat | | 3 | penguin | | 4 | lax | | 5 | whale | | 6 | ostrich | +----+---------+
Sie können den aktuellen AUTO_INCREMENT
-Wert
mit der SQL-Funktion LAST_INSERT_ID()
oder
der C-API-Funktion mysql_insert_id()
abrufen.
Diese Funktionen sind verbindungsspezifisch, d. h., ihre
Rückgabewerte werden nicht durch eine andere Verbindung
beeinträchtigt, die ebenfalls Einfügeoperationen durchführt.
Hinweis: Bei mehrzeiligen
Einfügeoperationen geben LAST_INSERT_ID()
und mysql_insert_id()
den
AUTO_INCREMENT
-Schlüssel des
ersten eingefügten Datensatzes zurück.
Auf diese Weise lassen sich mehrzeilige Einfügeoperationen auch
von anderen Servern in einer Replikationskonfiguration korrekt
nachvollziehen.
Bei MyISAM
- und
BDB
-Tabellen können Sie
AUTO_INCREMENT
in einer Sekundärspalte eines
mehrspaltigen Indexes angeben. In diesem Fall wird der erzeugte
Wert der AUTO_INCREMENT
-Spalte als
MAX(
berechnet. Dies ist praktisch, wenn Sie Daten in sortierte
Gruppen eingeben wollen.
auto_increment_column
) +
1 WHERE prefix=given-prefix
CREATE TABLE animals ( grp ENUM('fish','mammal','bird') NOT NULL, id MEDIUMINT NOT NULL AUTO_INCREMENT, name CHAR(30) NOT NULL, PRIMARY KEY (grp,id) ); INSERT INTO animals (grp,name) VALUES ('mammal','dog'),('mammal','cat'), ('Vogel','penguin'),('fish','lax'),('mammal','whale'), ('Vogel','ostrich'); SELECT * FROM animals ORDER BY grp,id;
Das Ergebnis sieht wie folgt aus:
+--------+----+---------+ | grp | id | name | +--------+----+---------+ | fish | 1 | lax | | mammal | 1 | dog | | mammal | 2 | cat | | mammal | 3 | whale | | bird | 1 | penguin | | bird | 2 | ostrich | +--------+----+---------+
Beachten Sie, dass in diesem Fall (wenn die
AUTO_INCREMENT
-Spalte Teil eines
mehrspaltigen Index ist) AUTO_INCREMENT
-Werte
neu verwendet werden, wenn Sie den Datensatz mit dem höchsten
AUTO_INCREMENT
-Wert in einer beliebigen
Gruppe löschen. Dies gilt auch für
MyISAM
-Tabellen, bei denen
AUTO_INCREMENT
-Werte normalerweise nicht
wiederverwendet werden.
Wenn die AUTO_INCREMENT
-Spalte Bestandteil
mehrerer Indizes ist, erzeugt MySQL Folgewerte auf der Basis des
Indexes, der mit der AUTO_INCREMENT
-Spalte
beginnt (sofern er vorhanden ist). Wenn also die Tabelle
animals
die Indizes PRIMARY KEY
(grp, id)
und INDEX (id)
enthielte,
würde MySQL den Index PRIMARY KEY
bei der
Erstellung von Folgewerten ignorieren. Das Ergebnis wäre eine
Tabelle, die eine einzelne Folge (und nicht eine Folge pro
grp
-Wert) enthalten würde.
Wenn Sie bei einem anderen
AUTO_INCREMENT
-Wert als 1 beginnen wollen,
können Sie diesen Wert mit CREATE TABLE
oder
ALTER TABLE
wie folgt festlegen:
mysql> ALTER TABLE tbl AUTO_INCREMENT = 100;
Weitere Informationen zu AUTO_INCREMENT
finden Sie hier:
Wie Sie das AUTO_INCREMENT
-Attribut
einer Spalte zuweisen: Abschnitt 13.1.5, „CREATE TABLE
“, und
Abschnitt 13.1.2, „ALTER TABLE
“.
Wie sich AUTO_INCREMENT
je nach
SQL-Modus verhält: Abschnitt 5.2.5, „Der SQL-Modus des Servers“.
Wie man den Datensatz mit dem aktuellsten
AUTO_INCREMENT
-Wert findet:
Abschnitt 12.1.3, „Vergleichsoperatoren“.
Wie man den zu verwendenden
AUTO_INCREMENT
-Wert einstellt:
Abschnitt 13.5.3, „SET
“.
AUTO_INCREMENT
und Replikation:
Abschnitt 6.8, „Replikation: Features und bekannte Probleme“.
Wie die auf AUTO_INCREMENT
bezogenen
Serversystemvariablen
(auto_increment_increment
und
auto_increment_offset
) zur Replikation
verwendet werden können:
Abschnitt 5.2.2, „Server-Systemvariablen“.
Bei Analytikerna und Lentus haben wir die System- und Feldarbeiten für ein umfangreiches Forschungsprojekt durchgeführt. Dieses Projekt ist eine Zusammenarbeit zwischen dem Institut für Umweltmedizin am Karolinska Institutet in Stockholm und der Abteilung für klinische Forschung bei Altersprozessen und Psychologie an der University of Southern California.
Das Projekt umfasste u. a. ein Screening, bei dem alle in Schweden lebenden Zwillinge, die über 65 Jahre alt waren, telefonisch befragt wurden. Zwillinge, die bestimmte Kriterien erfüllten, wurden dann in eine zweite Untersuchungsphase überführt. In dieser zweiten Phase konnten sich die teilnehmenden Zwillinge auf freiwilliger Basis einer ärztlichen Untersuchung unterziehen. Zu dieser Untersuchung gehörten körperliche und neuropsychologische Tests, Labortests, Neuro-Imaging, eine Bewertung des psychologischen Zustandes und eine Erfassung der Familiengeschichte. Ferner wurden Daten zu medizinischen und umweltbedingten Risikofaktoren ermittelt.
Weitere Informationen zum Zwillingsprojekt finden Sie unter folgender Adresse: http://www.mep.ki.se/twinreg/index_en.html
Im Verlauf des Projekts kam zu Verwaltungszwecken eine Weboberfläche zum Einsatz, die in Perl und MySQL geschrieben war.
Am Ende jedes Tages wurden die Daten der Befragungen in eine MySQL-Datenbank eingetragen.
Mit der folgenden Abfrage wurde ermittelt, wer für die zweite Phase des Projekts geeignet war:
SELECT CONCAT(p1.id, p1.tvab) + 0 AS tvid, CONCAT(p1.christian_name, ' ', p1.surname) AS Name, p1.postal_code AS Code, p1.city AS City, pg.abrev AS Area, IF(td.participation = 'Aborted', 'A', ' ') AS A, p1.dead AS dead1, l.ereignis AS event1, td.suspect AS tsuspect1, id.suspect AS isuspect1, td.severe AS tsevere1, id.severe AS isevere1, p2.dead AS dead2, l2.ereignis AS event2, h2.nurse AS nurse2, h2.doctor AS doctor2, td2.suspect AS tsuspect2, id2.suspect AS isuspect2, td2.severe AS tsevere2, id2.severe AS isevere2, l.finish_datum FROM twin_project AS tp /* For Twin 1 */ LEFT JOIN twin_data AS td ON tp.id = td.id AND tp.tvab = td.tvab LEFT JOIN informant_data AS id ON tp.id = id.id AND tp.tvab = id.tvab LEFT JOIN harmony AS h ON tp.id = h.id AND tp.tvab = h.tvab LEFT JOIN lentus AS l ON tp.id = l.id AND tp.tvab = l.tvab /* For Twin 2 */ LEFT JOIN twin_data AS td2 ON p2.id = td2.id AND p2.tvab = td2.tvab LEFT JOIN informant_data AS id2 ON p2.id = id2.id AND p2.tvab = id2.tvab LEFT JOIN harmony AS h2 ON p2.id = h2.id AND p2.tvab = h2.tvab LEFT JOIN lentus AS l2 ON p2.id = l2.id AND p2.tvab = l2.tvab, person_data AS p1, person_data AS p2, postal_groups AS pg WHERE /* p1 gets main twin and p2 gets his/her twin. */ /* ptvab is a field inverted from tvab */ p1.id = tp.id AND p1.tvab = tp.tvab AND p2.id = p1.id AND p2.ptvab = p1.tvab AND /* Just the screening survey */ tp.survey_no = 5 AND /* Skip if partner died before 65 but allow emigration (dead=9) */ (p2.dead = 0 OR p2.dead = 9 OR (p2.dead = 1 AND (p2.todestag_datum = 0 OR (((TO_DAYS(p2.todestag_datum) - TO_DAYS(p2.Geburtstag)) / 365) >= 65)))) AND ( /* Twin is suspect */ (td.future_contact = 'Yes' AND td.suspect = 2) OR /* Twin is suspect - Informant is Blessed */ (td.future_contact = 'Yes' AND td.suspect = 1 AND id.suspect = 1) OR /* No twin - Informant is Blessed */ (ISNULL(td.suspect) AND id.suspect = 1 AND id.future_contact = 'Yes') OR /* Twin broken off - Informant is Blessed */ (td.participation = 'Aborted' AND id.suspect = 1 AND id.future_contact = 'Yes') OR /* Twin broken off - No inform - Have partner */ (td.participation = 'Aborted' AND ISNULL(id.suspect) AND p2.dead = 0)) AND l.ereignis = 'Finished' /* Get at area code */ AND SUBSTRING(p1.postal_code, 1, 2) = pg.code /* Not already distributed */ AND (h.nurse IS NULL OR h.nurse=00 OR h.doctor=00) /* Has not refused or been aborted */ AND NOT (h.status = 'Refused' OR h.status = 'Aborted' OR h.status = 'Died' OR h.status = 'Other') ORDER BY tvid;
Hierzu ein paar Anmerkungen:
CONCAT(p1.id, p1.tvab) + 0 AS tvid
Die verketteten Werte id
und
tvab
sollen in numerischer Reihenfolge
sortiert werden. Durch Hinzufügen von 0
zum Ergebnis wird MySQL dazu veranlasst, dieses Ergebnis als
Zahl zu betrachten.
Spalte id
Bezeichnet ein Zwillingspaar. Die Spalte wird als Schlüssel in allen Tabellen verwendet.
Spalte tvab
Bezeichnet einen Zwilling in einem Paar. Der Wert ist
entweder 1
oder 2
.
Spalte ptvab
Dies ist das Gegenstück zu tvab
. Wenn
tvab
1
ist, dann ist
dieser Wert 2
und umgekehrt. Zweck ist
die Einsparung von Tipparbeit und eine vereinfachte
Optimierung der Abfrage durch MySQL.
Diese Abfrage veranschaulicht unter anderem, wie man Daten in
einer Tabelle mithilfe eines Joins von derselben Tabelle aus
durchführt (p1
und p2
).
In diesem Beispiel wird diese Methode verwendet, um zu
ermitteln, ob einer von zwei Zwillingen eines Paares vor dem 65.
Lebensjahr starb. Ist dies der Fall, dann wird der Datensatz
nicht zurückgegeben.
Alle genannten Elemente sind in allen Tabellen mit Informationen
zu den Zwillingen vorhanden. Um Abfragen zu beschleunigen, wurde
ein Schlüssel sowohl auf id,tvab
(alle
Tabellen) als auch auf id,ptvab
(person_data
) erstellt.
Auf unserem Produktionssystem (UltraSPARC, 200 MHz) gibt diese Abfrage etwa 150 bis 200 Datensätze zurück und benötigt dafür weniger als eine Sekunde.
Die aktuelle Anzahl der Datensätze in den in dieser Abfrage verwendeten Tabellen sieht wie folgt aus:
Tabelle | Datensätze |
person_data | 71074 |
lentus | 5291 |
twin_project | 5286 |
twin_data | 2012 |
informant_data | 663 |
harmony | 381 |
postal_groups | 100 |
Jede Befragung resultiert in einem Statuscode, der
ereignis
heißt. Die nachfolgend gezeigte
Abfrage wird zur Anzeige einer Tabelle über alle Zwillingspaare
mit zugeordnetem Statuscode verwendet. Sie zeigt an, bei wie
vielen Paaren beide Zwillinge zugelassen wurden, bei wie vielen
Paaren nur ein Zwilling zugelassen (und der andere abgelehnt)
wurde usw.
SELECT t1.ereignis, t2.ereignis, COUNT(*) FROM lentus AS t1, lentus AS t2, twin_project AS tp WHERE /* We are looking at one pair at a time */ t1.id = tp.id AND t1.tvab=tp.tvab AND t1.id = t2.id /* Just the screening survey */ AND tp.survey_no = 5 /* This makes each pair only appear once */ AND t1.tvab='1' AND t2.tvab='2' GROUP BY t1.ereignis, t2.ereignis;
Es gibt Programme, die Ihnen die Authentifizierung Ihrer Benutzer aus einer MySQL-Datenbank gestatten und gleichzeitig das Schreiben der Logdateien in eine MySQL-Tabelle ermöglichen.
Sie können das Apache-Logformat so ändern, dass es leichter von MySQL gelesen werden kann. Hierzu fügen Sie Folgendes in Ihre Apache-Konfigurationsdatei ein:
LogFormat \ "\"%h\",%{%Y%m%d%H%M%S}t,%>s,\"%b\",\"%{Content-Type}o\", \ \"%U\",\"%{Referer}i\",\"%{User-Agent}i\""
Um eine Logdatei in diesem Format in MySQL einzuladen, können Sie etwa folgende Anweisung verwenden:
LOAD DATA INFILE '/local/access_log
' INTO TABLEtbl_name
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' ESCAPED BY '\\'
Die benannte Tabelle sollte so erstellt sein, dass sie Spalten
aufweist, die denen entsprechen, welche die Zeile
LogFormat
in die Logdatei schreibt.
Inhaltsverzeichnis
Dieses Kapitel vermittelt einen kurzen Überblick über die Befehlszeilenprogramme, die von MySQL AB angeboten werden, und beschreibt die allgemeine Syntax zur Angabe von Optionen bei der Ausführung dieser Programme. Die meisten Programme bieten zwar programmspezifische Optionen, aber die Optionssyntax ist bei allen Programmen ähnlich. Die nachfolgenden Kapitel enthalten detailliertere Beschreibungen einzelner Programme und der jeweiligen Optionen.
MySQL AB bietet auch drei grafikbasierte Clientprogramme zur Verwendung mit MySQL Server an:
MySQL Administrator: Dieses Tool dient der Administration von MySQL Servern, Datenbanken, Tabellen und Benutzerkonten.
MySQL Query Browser: Dieses grafische Tool von MySQL AB erlaubt das Erstellen, Ausführen und Optimieren von Abfragen über MySQL-Datenbanken.
MySQL Migration Toolkit: Dieses Tool erleichtert Ihnen die Migration von Schemata und Daten aus anderen Datenbanksystemen zur Verwendung mit MySQL.
Diese GUI-Programme haben jeweils eigene Handbücher, die unter http://dev.mysql.com/doc/ erhältlich sind.
MySQL AB bietet mehrere Programmtypen an:
Den MySQL Server und die Serverstartskripten:
mysqld ist der MySQL Server.
mysqld_safe, mysql.server und mysqld_multi sind Serverstartskripten.
mysql_install_db initialisiert das Datenverzeichnis und die Ausgangsdatenbanken.
Der MySQL Instance Manager überwacht und verwaltet MySQL Server-Instanzen.
In Kapitel 5, Datenbankverwaltung, werden diese Programme eingehender behandelt.
Clientprogramme, die auf den Server zugreifen:
mysql ist ein Befehlszeilenclient zur Ausführung von SQL-Anweisungen im interaktiven Modus oder im Stapelbetrieb.
mysqladmin ist ein Administrationsclient.
mysqlcheck führt Wartungsarbeiten an den Tabellen aus.
mysqldump und mysqlhotcopy erstellen Datenbank-Backups.
mysqlimport importiert Datendateien.
mysqlshow zeigt Informationen zu Datenbanken und Tabellen an.
In Kapitel 8, Client- und Hilfsprogramme, werden diese Programme eingehender behandelt.
Hilfsprogramme, die unabhängig vom Server laufen:
myisamchk führt Wartungsarbeiten an den Tabellen aus.
myisampack erzeugt komprimierte, schreibgeschützte Dateien.
mysqlbinlog ist ein Tool zur Verarbeitung binärer Logdateien.
perror zeigt Erläuterungen zu Fehlercodes an.
Kapitel 5, Datenbankverwaltung, beschreibt myisamchk. Die übrigen Programme werden in Kapitel 8, Client- und Hilfsprogramme, erklärt.
Die meisten MySQL-Distributionen enthalten alle diese Programme abgesehen von denjenigen, die plattformspezifisch sind (dies gilt beispielsweise für die Serverstartskripten, die unter Windows nicht verwendet werden). Ausgenommen hiervon sind die RPM-Distributionen, denn sie sind spezialisierter: Es gibt ein RPM für den Server, ein anderes für Clientprogramme usw. Wenn Sie feststellen, dass Ihnen ein oder mehrere Programme fehlen, finden Sie in Kapitel 2, Installation von MySQL, Informationen zu Distributionstypen und deren Inhalten. Unter Umständen haben Sie eine Distribution, die nicht alle Programme enthält; Sie müssen dann möglicherweise noch andere Komponenten installieren.
Um ein MySQL-Programm über die Befehlszeile (d. h. von Ihrer
Shell bzw. an der Eingabeaufforderung) aufzurufen, geben Sie den
Programmnamen gefolgt von allen erforderlichen Optionen oder
anderen Argumenten ein, mit denen Sie dem Programm mitteilen, was
es tun soll. Die folgenden Befehle zeigen einige beispielhafte
Programmaufrufe. „shell>
“
stellt dabei die Eingabeaufforderung für Ihren
Befehls-Interpreter dar, ist also nicht Bestandteil der Eingabe.
Welche Eingabeaufforderung angezeigt wird, hängt vom verwendeten
Befehls-Interpreter ab. Typische Eingabeaufforderungen sind
$
bei sh oder
bash, %
bei
csh oder tcsh und
C:\>
bei den Windows-Interpretern
command.com oder cmd.exe.
shell>mysql -u root test
shell>mysqladmin extended-status variables
shell>mysqlshow --help
shell>mysqldump --user=root personnel
Argumente, die mit einem einzelnen oder doppelten Bindestrich
(‘-
’,
‘--
’) beginnen, sind
Optionsargumente. Optionen geben in der Regel die Art der
Verbindung an, die ein Programm zum Server herstellen soll, oder
betreffen den Betriebsmodus. Die Optionssyntax ist in
Abschnitt 4.3, „Angabe von Programmoptionen“, beschrieben.
Nichtoptionsargumente (d. h. Argumente ohne führenden
Bindestrich) übergeben zusätzliche Informationen an das
Programm. So interpretiert etwa das Programm
mysql das erste Nichtoptionsargument als
Datenbanknamen; der Befehl mysql -u root test
gibt also an, dass Sie die Datenbank test
verwenden wollen.
Die nachfolgenden programmspezifischen Abschnitte geben auch an, welche Optionen das betreffende Programm versteht, und beschreiben die Bedeutung aller weiteren Nichtoptionsargumente.
Einige Optionen sind zahlreichen Programmen gemeinsam. Die
häufigsten hiervon sind --host
(oder
-h
), --user
(oder
-u
) und --password
(oder
-p
); sie alle dienen der Angabe von
Verbindungsparametern. Angegeben werden auf diese Weise der Host,
auf dem der MySQL Server ausgeführt wird, sowie der Benutzername
und das Passwort Ihres MySQL-Kontos. Alle MySQL-Clientprogramme
verstehen diese Optionen; sie gestatten Ihnen, festzulegen, mit
welchem Server eine Verbindung hergestellt werden soll und welches
Konto auf dem Server zu verwenden ist.
Sie werden möglicherweise feststellen, dass Sie beim Aufruf von
MySQL-Programmen den Pfadnamen zum Verzeichnis
bin
angeben müssen, in dem sie installiert
sind. Dies ist wahrscheinlich der Fall, wenn Sie beim Versuch, ein
MySQL-Programm aus einem anderen als diesem Verzeichnis
aufzurufen, die Fehlermeldung „Program not found“
erhalten. Um die Verwendung von MySQL praktischer zu gestalten,
können Sie den Pfadnamen des Verzeichnisses
bin
zu Ihrer Umgebungsvariablen
PATH
hinzufügen. Danach können Sie ein
Programm durch Eingabe des Programmnamens aufrufen und müssen den
Pfadnamen nicht mehr angeben. Wenn Sie beispielsweise
mysql in
/usr/local/mysql/bin
installiert haben,
können Sie es nachfolgend über die Eingabe
mysql; aufrufen; das Eingeben von
/usr/local/mysql/bin/mysql ist dann nicht mehr
notwendig.
Informationen zur Einstellung Ihrer Umgebungsvariable
PATH
finden Sie in der Dokumentation zu Ihrem
Befehls-Interpreter. Die Syntax zur Einstellung von
Umgebungsvariablen ist Interpreter-spezifisch.
Es gibt mehrere Möglichkeiten, Optionen für MySQL-Programme anzugeben:
Sie listen die Optionen auf den Programmnamen folgend auf der Befehlszeile auf. Dies ist die meistverwendete Methode bei Optionen, die für eine bestimmte Art des Programmaufrufs verwendet werden.
Sie listen die Optionen in einer Optionsdatei auf, die das Programm beim Start ausliest. Dies bietet sich für Optionen an, die Sie bei jedem Programmstart verwenden wollen.
Sie listen die Optionen in Umgebungsvariablen auf. Auch diese Methode ist nützlich, wenn Sie bestimmte Optionen bei jeder Programmausführung verwenden wollen. In der Praxis werden für diesen Zweck allerdings meistens Optionsdateien verwendet. Abschnitt 5.13.2, „Mehrere MySQL-Server unter Unix laufen lassen“, beschreibt jedoch eine Situation, in der Umgebungsvariablen sehr hilfreich sein können. Dort wird eine praktische Methode erläutert, die solche Variablen zur Angabe der TCP/IP-Portnummer und der Unix-Socketdatei für Server- und Clientprogramme verwendet.
Bei der Ermittlung der angegebenen Optionen fragen MySQL-Programme zunächst die Umgebungsvariablen ab, lesen dann die Optionsdateien aus und überprüfen schließlich die Eingabe auf der Befehlszeile. Wird eine Option mehrfach angegeben, so hat das jeweils letzte Auftreten Vorrang. Das bedeutet, dass Angaben in Umgebungsvariablen die niedrigste und Befehlszeileneingaben die höchste Priorität genießen.
Sie können diese Art der Verarbeitung von Optionen durch MySQL-Programme nutzen, indem Sie Vorgabewerte in einer Optionsdatei angeben. Auf diese Weise müssen Sie sie nicht bei jeder Ausführung des Programms neu eingeben, können die Vorgabewerte bei Bedarf aber mithilfe von Optionseingaben auf der Befehlszeile außer Kraft setzen.
Auf der Befehlszeile angegebene Programmoptionen unterliegen den folgenden Regeln:
Optionen werden auf den Befehlsnamen folgend angegeben.
Ein Optionsargument beginnt abhängig davon, ob es sich um
einen kurzen oder langen Optionsnamen handelt, mit einem
oder zwei Bindestrichen. Für viele Optionen sind sowohl ein
Kurz- als auch ein Langname vorhanden. Beispielsweise sind
-?
und --help
die Kurz-
und die Langform der Option, die ein MySQL-Programm anweist,
eine Hilfemeldung anzuzeigen.
Bei Optionsnamen wird die Groß-/Kleinschreibung
unterschieden. Das bedeutet, dass sowohl -v
als auch -V
zulässig sind und auch
unterschiedliche Bedeutungen haben. (Es handelt sich hierbei
um die Kurzformen der Optionen --verbose
bzw. --version
.)
Einige Optionen nehmen einen Wert entgegen, der auf den
Optionsnamen folgt. So bezeichnet -h
localhost
bzw. --host=localhost
den MySQL Server für ein Clientprogramm. Der Optionswert
nennt dem Programm den Namen des Hosts, auf dem der
MySQL Server ausgeführt wird.
Bei einer Option mit einem Langnamen, die einen Wert
entgegennimmt, trennen Sie den Optionsnamen und den Wert
durch das Zeichen ‘=
’. Bei
Verwendung einer Kurzform, die einen Wert entgegennimmt,
kann dieser entweder direkt oder durch ein Leerzeichen
getrennt auf den Optionsbuchstaben folgen:
-hlocalhost
und -h
localhost
sind gleichbedeutend. Eine Ausnahme
dieser Regel ist die Option zur Angabe Ihres
MySQL-Passworts. Diese Option kann in der Langform entweder
als
--password=
oder als pass_val
--password
angegeben werden. Im
zweiten Fall (in dem kein Passwort übergeben wird) fordert
das Programm Sie danach zur Eingabe des Passworts auf. Die
Passwortoption kann auch in Kurzform als
-p
oder
als pass_val
-p
angegeben werden. Allerdings muss
die Eingabe des Passwortwerts bei der Kurzform unmittelbar
auf den Optionsbuchstaben folgend, d. h. ohne
trennendes Leerzeichen, erfolgen. Der Grund
hierfür ist, dass, wenn ein Leerzeichen auf den
Optionsbuchstaben folgt, das Programm keine Möglichkeit
hat, festzustellen, ob das nachfolgende Argument der
Passwortwert oder ein anderes Argument sein soll. Hieraus
ergibt sich, dass die folgenden beiden Befehle zwei völlig
unterschiedliche Bedeutungen haben:
shell>mysql -ptest
shell>mysql -p test
Der erste Befehl weist mysql an, den
Passwortwert test
zu verwenden, gibt aber
keine Standarddatenbank an. Der zweite Befehl hingegen weist
mysql an, zur Eingabe des Passworts
aufzufordern und test
als
Standarddatenbank zu verwenden.
Einige Optionen steuern Verhaltensweisen, die sich aktivieren
oder deaktivieren lassen. So unterstützt der Client
mysql etwa eine Option
--column-names
, die bestimmt, ob zu Beginn der
Abfrageergebnisse eine Zeile mit Spaltennamen angezeigt wird
oder nicht. Standardmäßig ist diese Option aktiviert. Unter
Umständen kann es jedoch sinnvoll sein, sie zu deaktivieren,
wenn Sie beispielsweise die Ausgabe von mysql
an ein anderes Programm übergeben, das nur die Daten und keine
Kopfzeile erwartet.
Sie können die Spaltennamen mit jeder der folgenden Optionen deaktivieren:
--disable-column-names --skip-column-names --column-names=0
Die Präfixe --disable
und
--skip
und das Suffix =0
haben den jeweils gleichen Effekt: Sie schalten die Option ab.
Um die „einschaltende“ Form der Option anzugeben, gibt es die folgenden Möglichkeiten:
--column-names --enable-column-names --column-names=1
Wenn einer Option das Präfix --loose
vorangestellt wird, bricht ein Programm, dass die Option nicht
erkennt, nicht mit einer Fehlermeldung ab, sondern setzt
lediglich eine Warnung ab:
shell> mysql --loose-no-such-option
mysql: WARNING: unknown option '--no-such-option'
Das Präfix --loose
kann nützlich sein, wenn
Sie Programme unter mehreren MySQL-Installationen auf demselben
Computer ausführen und die Optionen in einer Optionsdatei
auflisten. Eine Option, die unter Umständen nicht von allen
Versionen eines Programms erkannt wird, kann mithilfe des
Präfixes --loose
(bzw.
loose
in einer Optionsdatei) angegeben
werden. Versionen des Programms, die die Option erkennen, werden
sie dann in der Regel auch verarbeiten, während
Programmversionen, die sie nicht erkennen, eine Warnung absetzen
und sie ansonsten ignorieren.
Eine andere Option, die in Verbindung mit
mysql gelegentlich nützlich sein kann, ist
--execute
oder -e
. Hiermit
können Sie SQL-Anweisungen an den Server übergeben. Die
Anweisungen müssen in einfache oder doppelte Anführungszeichen
gesetzt sein. Wenn Sie Werte in Anführungszeichen innerhalb
einer Anweisung angeben wollen, sollten Sie doppelte
Anführungszeichen für die Anweisung selbst und einfache
Anführungszeichen für Werte innerhalb der Anweisung benutzen.
Wenn Sie diese Option verwenden, führt mysql
die Anweisung aus und wird dann beendet.
So können Sie beispielsweise mithilfe des folgenden Befehls eine Liste der Benutzerkonten aufrufen:
shell>mysql -u root -p --execute="SELECT User, Host FROM user" mysql
Enter password:******
+------+-----------+ | User | Host | +------+-----------+ | | gigan | | root | gigan | | | localhost | | jon | localhost | | root | localhost | +------+-----------+ shell>
Beachten Sie, dass auf die Langform (--execute
)
das Gleichheitszeichen (=
) folgen muss.
In obigem Beispiel wurde der Name der Datenbank
mysql
als separates Argument übergeben.
Dieselbe Anweisung hätte auch mit dem folgenden Befehl
ausgeführt werden können, der keine Standarddatenbank angibt:
mysql> mysql -u root -p --execute="SELECT User, Host FROM mysql.user"
Über die Befehlszeile lassen sich mehrere SQL-Anweisungen durch Semikola getrennt angeben:
shell>mysql -u root -p -e "SELECT VERSION();SELECT NOW()"
Enter password:******
+-----------------+ | VERSION() | +-----------------+ | 5.1.5-alpha-log | +-----------------+ +---------------------+ | NOW() | +---------------------+ | 2006-01-05 21:19:04 | +---------------------+
Die Option --execute
oder -e
kann auch verwendet werden, um Befehle in analoger Form an
ndb_mgm, den Verwaltungsclient für MySQL
Cluster, zu übergeben. Ein Beispiel finden Sie in
Abschnitt 16.3.6, „Sicheres Herunterfahren und Neustarten“.
Die meisten MySQL-Programme können Startoptionen aus Optionsdateien (die manchmal auch Konfigurationsdateien genannt werden) auslesen. Optionsdateien stellen eine praktische Möglichkeit dar, häufig verwendete Optionen anzugeben, damit sie nicht mehr bei jeder Ausführung eines Programms explizit eingegeben werden müssen.
Um zu ermitteln, ob ein Programm Optionsdateien ausliest, rufen
Sie es mit der Option --help
auf
(--verbose
und --help
bei
mysqld). Wenn das Programm Optionsdateien
ausliest, zeigt die Hilfemeldung an, nach welchen Dateien sie
sucht und welche Optionsabschnitte (Gruppen) sie erkennt.
Hinweis: Optionsdateien, die für MySQL Cluster-Dateien verwendet werden, werden in Abschnitt 16.4, „MySQL Cluster: Konfiguration“, behandelt.
Unter Windows lesen MySQL-Programme Startoptionen aus den folgenden Dateien aus:
Dateiname | Zweck |
| globale Optionen |
C:\my.cnf | globale Optionen |
| globale Optionen |
defaults-extra-file | die ggf. mit
--defaults-extra-file=
angegebene Datei |
WINDIR
steht dabei für die Position
Ihres Windows-Verzeichnisses. Dies ist in der Regel
C:\WINDOWS
oder
C:\WINNT
. Sie können die exakte Position
der Umgebungsvariablen WINDIR
entnehmen.
Hierzu geben Sie den folgenden Befehl ein:
C:\> echo %WINDIR%
INSTALLDIR
steht für das
MySQL-Installationsverzeichnis. Dies ist normalerweise
C:\
, wobei
PROGRAMDIR
\MySQL\MySQL
5.1 ServerPROGRAMDIR
das Programmverzeichnis
(bei deutschsprachigen Windows-Versionen üblicherweise
Programme
) ist, wenn MySQL 5.1
mithilfe der Installations- und Konfigurations-Assistenten
eingerichtet wurde. Siehe auch
Abschnitt 2.3.5.14, „Speicherort der Datei my.ini
“.
Unter Unix lesen MySQL-Programme Startoptionen aus den folgenden Dateien aus:
Dateiname | Zweck |
/etc/my.cnf | globale Optionen |
$MYSQL_HOME/my.cnf | serverspezifische Optionen |
defaults-extra-file | die ggf. mit
--defaults-extra-file=
angegebene Datei |
~/.my.cnf | benutzerspezifische Optionen |
MYSQL_HOME
ist eine Umgebungsvariable, die
den Pfad angibt, in dem die serverspezifische Datei
my.cnf
abgelegt ist.
Wenn MYSQL_HOME
nicht eingestellt ist und Sie
den Server mit dem Programm mysqld_safe
starten, versucht mysqld_safe,
MYSQL_HOME
wie folgt einzustellen:
Dabei stehen BASEDIR
und
DATADIR
für die Pfadnamen zum
MySQL-Basis- bzw. Datenverzeichnis.
Ist eine Datei my.cnf
in
DATADIR
, aber nicht in
BASEDIR
vorhanden, so setzt
mysqld_safe MYSQL_HOME
auf DATADIR
.
Andernfalls – also wenn MYSQL_HOME
nicht gesetzt und keine Datei my.cnf
in
DATADIR
vorhanden ist – setzt
mysqld_safe MYSQL_HOME
auf BASEDIR
.
Normalerweise ist DATADIR
/usr/local/mysql/data
in einer
Binärinstallation bzw. /usr/local/var
in
einer Quellinstallation. Beachten Sie, dass dies jeweils die
Position des Datenverzeichnisses ist, die zum Zeitpunkt der
Konfiguration angegeben wurde, und nicht die mit der Option
--datadir
beim Start von
mysqld spezifizierte Position. Die Verwendung
von --datadir
während der Laufzeit hat keinen
Einfluss darauf, wo der Server nach Optionsdateien sucht, denn
die Suche erfolgt vor der Verarbeitung ggf. angegebener
Optionen.
MySQL sucht in der gerade beschriebenen Reihenfolge nach Optionsdateien und liest diese aus, sofern sie vorhanden sind. Ist eine Optionsdatei, die Sie verwenden wollen, nicht vorhanden, dann können Sie sie mit einem Texteditor erstellen.
Werden mehrere Instanzen einer gegebenen Option gefunden, dann
hat die jeweils zuletzt gefundene Instanz immer Vorrang. Es gibt
allerdings eine Ausnahme: Bei mysqld wird aus
Sicherheitsgründen immer die erste Instanz
der Option --user
verarbeitet, damit verhindert
wird, dass eine Benutzerangabe in einer Optionsdatei über die
Befehlszeile außer Kraft gesetzt werden kann.
Hinweis: Auf Unix-Plattformen ignoriert MySQL Konfigurationsdateien, die für alle schreibbar („world-writable“) sind. Dies ist beabsichtigt und dient der Erhöhung der Sicherheit.
Jede Langformoption, die beim Start eines MySQL-Programms über
die Befehlszeile angegeben wird, kann ebenso gut auch in einer
Optionsdatei spezifiziert werden. Um eine Liste der für ein
Programm verfügbaren Optionen zu erhalten, führen Sie es mit
der Option --help
aus.
Die Syntax zur Angabe von Optionen in einer Optionsdatei ähnelt
der Befehlszeilensyntax, nur können Sie die beiden Bindestriche
am Anfang weglassen. So werden etwa die Befehlszeilenoptionen
--quick
oder --host=localhost
in einer Optionsdatei als quick
bzw.
host=localhost
angegeben. Um eine Option des
Typs
--loose-
in
einer Optionsdatei anzugeben, schreiben Sie sie als
opt_name
loose-
.
opt_name
Leerzeilen in Optionsdateien werden ignoriert. Nichtleere Zeilen können die folgenden Formen annehmen:
#
,
comment
;
comment
Kommentarzeilen starten mit
‘#
’ oder
‘;
’. Ein Kommentar des Typs
‘#
’ kann auch in der Mitte
einer Zeile verwendet werden.
[
group
]
group
ist der Name des Programms
oder Abschnitts, für den Sie die Optionen einstellen
wollen. Alle auf eine Abschnittszeile folgenden Zeilen mit
Optionseinstellungen gelten für den betreffenden Abschnitt,
bis eine andere Abschnittszeile angegeben oder das Ende der
Optionsdatei erreicht wird.
opt_name
Entspricht
--
auf
der Befehlszeile.
opt_name
opt_name
=value
Entspricht
--
auf der Befehlszeile. In einer Optionsdatei können Sie –
anders als auf der Befehlszeile – Leerzeichen um das
Gleichheitszeichen ‘opt_name
=value
=
’
setzen. Sie können den Wert in einzelne oder doppelte
Anführungszeichen setzen, was nützlich bei Werten ist, die
das Kommentarzeichen ‘#
’ oder
Whitespace enthalten.
Bei Optionen, die numerische Werte annehmen, kann dieser mit den
Suffixen K
, M
oder
G
(in Groß- oder Kleinschreibung) angegeben
werden, um einen Multiplikator von 1024,
10242 oder
10243 anzuzeigen. Der folgende Befehl
beispielsweise weist mysqladmin an, 1024
Ping-Befehle im Abstand von jeweils zehn Sekunden an den Server
zu senden:
mysql> mysqladmin --count=1K --sleep=10 ping
Bei Optionsnamen oder -werten werden Leerzeichen am Anfang oder
Ende automatisch gelöscht. Sie können die Escape-Sequenzen
‘\b
’,
‘\t
’,
‘\n
’,
‘\r
’,
‘\\
’ und
‘\s
’ in Optionswerten zur
Darstellung von Rückschritt-, Tabulator-, Zeilenwechsel-,
Absatzschaltungs- und Leerzeichen verwenden.
Da die Escape-Sequenz ‘\\
’ genau
einen Backslash darstellt, müssen Sie jeden Backslash als
‘\\
’ schreiben. Alternativ geben
Sie den Wert unter Einsatz von
‘/
’ statt
‘\
’ als Trennzeichen in Pfadnamen
an.
Wenn der Name eines Optionsabschnitts mit dem eines Programms
identisch ist, gelten die Optionen in diesem Abschnitt speziell
für dieses Programm. So betreffen beispielsweise die Abschnitte
[mysqld]
und [mysql]
den
Server mysqld bzw. das Clientprogramm
mysql.
Der Optionsabschnitt [client]
wird von allen
Clientprogrammen (aber nicht von
mysqld) ausgelesen. Auf diese Weise können
Sie Optionen angeben, die für alle Clients gelten.
Beispielsweise ist [client]
der optimale
Abschnitt zur Angabe des Passworts, mit dem Sie die
Serververbindung herstellen. (Hierbei müssen Sie natürlich
sicherstellen, dass nur Sie die Optionsdatei lesen und in sie
schreiben können, damit Dritte Ihr Passwort nicht ermitteln
können.) Beachten Sie, dass Sie eine Option nicht im Abschnitt
[client]
ablegen dürfen, wenn nicht
gewährleistet ist, dass alle von Ihnen
verwendeten Clientprogramme sie erkennen. Wenn Sie Programme
starten, die eine bestimmte Option nicht verstehen, dann zeigen
diese eine Fehlermeldung an und werden nachfolgend beendet.
Eine typische Datei mit globalen Optionen sieht so aus:
[client] port=3306 socket=/tmp/mysql.sock [mysqld] port=3306 socket=/tmp/mysql.sock key_buffer_size=16M max_allowed_packet=8M [mysqldump] quick
Diese Optionsdatei verwendet die Syntax
für Zeilen, die die Variablen
var_name
=value
key_buffer_size
und
max_allowed_packet
einstellen.
Eine typische Datei mit Benutzeroptionen sieht so aus:
[client] # The following password will be sent to all standard MySQL clients password="my_password" [mysql] no-auto-rehash connect_timeout=2 [mysqlhotcopy] interactive-timeout
Wenn Sie Optionsabschnitte erstellen wollen, die nur von
mysqld-Servern einer bestimmten
MySQL-Release-Serie ausgelesen werden sollen, dann sollten Sie
Abschnittsnamen in der Form
[mysqld-5.0]
,
[mysqld-5.1]
usw. verwenden. Der
folgende Abschnitt gibt an, dass die Option
--new
nur von MySQL Servern der Versionsnummern
5.1.x verwendet werden soll:
[mysqld-5.1] new
Seit MySQL 5.0.4 ist es möglich,
!include
-Direktiven in Optionsdateien zu
verwenden, um andere Optionsdateien zu integrieren. Ebenfalls
nutzbar ist !includedir
; hiermit wird das
Durchsuchen bestimmter Verzeichnisse nach Optionsdateien
veranlasst. Um beispielsweise die Datei
/home/mydir/myopt.cnf
zu integrieren,
können Sie die folgende Direktive verwenden:
!include /home/me/myopt.cnf
Wenn Sie das Verzeichnis /home/mydir
durchsuchen und die darin vorhandenen Optionsdateien auslesen
wollen, würde die Direktive wie folgt aussehen:
!includedir /home/mydir
Hinweis: Zurzeit
müssen alle Dateien, die auf
Unix-Betriebssystemen mithilfe der Direktive
!includedir
gesucht und integriert werden
sollen, Dateinamen mit der Erweiterung .cnf
aufweisen. Unter Windows prüft die Direktive auf Dateien mit
den Erweiterungen .ini
oder
.cnf
.
Beachten Sie, dass Optionen, die aus integrierten Dateien
ausgelesen werden, im Kontext des aktuellen Optionsabschnitts
angewendet werden. Nehmen wir einmal an, Sie würden die
folgenden Zeilen in my.cnf
ablegen:
[mysqld] !include /home/mydir/myopt.cnf
In diesem Fall wird die Datei myopt.cnf
nur
für den Server verarbeitet; die Direktive
!include
wird von allen Clientanwendungen
ignoriert. Würden Sie jedoch wie folgt formulieren, dann würde
das Verzeichnis /home/mydir/my-dump-options
nur von mysqldump auf Optionsdateien
geprüft, nicht jedoch vom Server oder anderen
Clientanwendungen:
[mysqldump] !includedir /home/mydir/my-dump-options
Wenn Sie eine Quelldistribution verwenden, finden Sie
Beispieloptionsdateien mit dem Namen
my-
im
Verzeichnis xxxx
.cnfsupport-files
. Im Falle einer
Binärdistribution schauen Sie im Verzeichnis
support-files
nach, welches sich im
MySQL-Installationsverzeichnis befindet. Unter Windows sind die
Beispieloptionsdateien unter Umständen im
MySQL-Installationsverzeichnis selbst abgelegt (siehe auch
weiter oben in diesem Abschnitt oder in
Kapitel 2, Installation von MySQL, wenn Sie nicht wissen, wo sich
dieses befindet). Derzeit sind Beispieloptionsdateien für
kleine, mittelgroße, große und sehr große Systeme vorhanden.
Um mit einer dieser Dateien zu experimentieren, kopieren Sie sie
unter Windows als C:\my.cnf
bzw. unter Unix
als .my.cnf
in Ihr Homeverzeichnis.
Hinweis: Unter Windows wird die
Dateierweiterung .cnf
unter Umständen
nicht angezeigt.
Alle MySQL-Programme, die Optionsdateien unterstützen,
verarbeiten die folgenden Optionen. Diese betreffen den Umgang
mit Optionsdateien, müssen also über die Befehlszeile (und
nicht in einer Optionsdatei) angegeben werden. Damit sie
einwandfrei funktionieren, müssen die Optionen jeweils
unmittelbar auf den Befehlsnamen folgen. Ausgenommen ist
--print-defaults
, das unmittelbar auf
--defaults-file
oder
--defaults-extra-file
angegeben werden muss.
--no-defaults
Optionsdateien nicht auslesen.
--print-defaults
Programmnamen und alle aus den Optionsdateien ausgelesenen Optionen anzeigen.
--defaults-file=
file_name
Nur die angegebene Optionsdatei verwenden. Dabei ist
file_name
der vollständige
Pfadname zur betreffenden Datei.
--defaults-extra-file=
file_name
Diese Optionsdatei nach der globalen Optionsdatei, aber
(unter Unix) vor der Benutzeroptionsdatei auslesen. Dabei
ist file_name
der vollständige
Pfadname zur betreffenden Datei.
In Shell-Skripten können Sie mit dem Programm
my_print_defaults die Optionsdateien
durchsuchen und überprüfen, welche Optionen für ein gegebenes
Programm verwendet würden. Das folgende Beispiel zeigt eine
Ausgabe, die my_print_defaults erzeugen
könnte, wenn es die in den Abschnitten
[client]
und [mysql]
gefundenen Optionen anzeigen sollte:
shell> my_print_defaults client mysql
--port=3306
--socket=/tmp/mysql.sock
--no-auto-rehash
Hinweis für Entwickler: Die Verarbeitung von Optionsdateien wird in der C-Clientbibliothek implementiert, indem einfach alle Optionen in dem oder den entsprechenden Abschnitten vor den Befehlszeilenargumenten ausgelesen werden. Dies funktioniert bei Programmen, die das letzte Auftreten einer mehrfach angegebenen Option verwenden, einwandfrei. Wenn Sie jedoch ein C- oder C++-Programm haben, das zwar mehrfach angegebene Optionen verarbeitet, aber die Optionsdateien nicht ausliest, müssen Sie lediglich zwei Zeilen hinzufügen, um diese Funktionalität zu implementieren. Studieren Sie den Quellcode eines beliebigen MySQL-Standardclients, um zu erfahren, wie es gemacht wird.
Mehrere andere Sprachschnittstellen zu MySQL basieren auf der C-Clientbibliothek, und eine davon ermöglicht den Zugriff auf die Inhalte von Optionsdateien. Dies betrifft Perl und Python. Details entnehmen Sie der Dokumentation Ihrer bevorzugten Schnittstelle.
Um eine Option in einer Umgebungsvariablen anzugeben, stellen Sie
die Variable unter Verwendung der für Ihren Befehls-Interpreter
passenden Syntax ein. Unter Windows oder NetWare etwa können
Sie die Variable USER
zur Angabe Ihres
MySQL-Kontennamens verwenden. Benutzen Sie zu diesem Zweck
folgende Syntax:
SET USER=your_name
Die Unix-Syntax hängt von der verwendeten Shell ab. Nehmen wir
an, Sie wollen die TCP/IP-Portnummer über die Variable
MYSQL_TCP_PORT
festlegen. Die typische Syntax
(etwa bei sh, bash
,
zsh usw.) sieht so aus:
MYSQL_TCP_PORT=3306 export MYSQL_TCP_PORT
Der erste Befehl stellt die Variable ein, und der Befehl
export
exportiert diese dann in die
Shell-Umgebung, sodass ihr Wert für MySQL und andere Prozesse
verfügbar wird.
Bei csh und tcsh machen Sie die Shell-Variable mithilfe von setenv für die Umgebung verfügbar:
setenv MYSQL_TCP_PORT 3306
Die Befehle zur Einstellung von Umgebungsvariablen können Sie
an der Eingabeaufforderung ausführen; sie werden dann sofort
gültig, bleiben es aber nur, bis Sie sich abmelden. Damit die
Einstellungen bei jeder Anmeldung übernommen werden, legen Sie
den oder die entsprechenden Befehle in einer Autostartdatei ab,
die Ihr Befehls-Interpreter bei jedem Start ausliest. Typische
Autostartdateien sind AUTOEXEC.BAT
unter
Windows, .bash_profile
unter
bash oder .tcshrc
unter
tcsh. Weitere Informationen entnehmen Sie der
Dokumentation zu Ihrem Befehls-Interpreter.
Anhang F, Umgebungsvariablen, listet alle Umgebungsvariablen auf, die den Betrieb von MySQL-Programmen beeinflussen.
Viele MySQL-Programme haben interne Variablen, die zur Laufzeit
eingestellt werden können. Programmvariablen werden auf die
gleiche Weise eingestellt wie andere Langformoptionen, die einen
Wert entgegennehmen. Beispielsweise hat mysql
eine Variable max_allowed_packet
, mit der die
maximale Größe des Kommunikationspuffers eingestellt wird. Um
die Variable max_allowed_packet
für
mysql auf einen Wert von 16 Mbyte
einzustellen, können Sie einen der folgenden Befehle verwenden:
shell>mysql --max_allowed_packet=16777216
shell>mysql --max_allowed_packet=16M
Der erste Befehl gibt den Wert in Byte an, der zweite den Wert
in Mbyte. Bei Variablen, die numerische Werte annehmen, kann
dieser mit den Suffixen K
,
M
oder G
(in Groß- oder
Kleinschreibung) angegeben werden, um einen Multiplikator von
1024, 10242 oder
10243 anzuzeigen. (Bei der
Einstellung von max_allowed_packet
etwa
würden hiermit die Werte als Kbyte, Mbyte oder Gbyte
angegeben.)
In einer Optionsdatei werden die Variableneinstellungen ohne führende Bindestriche angegeben:
[mysql] max_allowed_packet=16777216
Oder:
[mysql] max_allowed_packet=16M
Wenn Sie wollen, können Sie Unterstriche in einem Variablennamen als Bindestriche angeben. Die folgenden Optionsabschnitte sind gleichwertig. Beide setzen die Größe des Schlüsselpuffers am Server auf 512 Mbyte:
[mysqld] key_buffer_size=512M [mysqld] key-buffer-size=512M
Hinweis: Vor MySQL 4.0.2 lautet
die einzige verfügbare Syntax zur Einstellung von
Programmvariablen
--set-variable=
(bzw.
option
=value
set-variable=
in Optionsdateien). Diese Syntax wird zwar nach wie vor erkannt,
findet aber seit MySQL 4.0.2 keine Akzeptanz mehr.
option
=value
Viele Serversystemvariablen können auch zur Laufzeit angegeben werden. Detaillierte Informationen finden Sie in Abschnitt 5.2.3.2, „Dynamische Systemvariablen“.
Inhaltsverzeichnis
Access denied
-FehlerDieses Kapitel behandelt Themen im Zusammenhang mit der Administration einer MySQL-Installation:
Server konfigurieren
Benutzerkonten verwalten
Sicherungen durchführen
Serverlogdateien
Abfrage-Cache
Der MySQL-Server mysqld ist das Hauptprogramm, welches in einer MySQL-Installation die meiste Arbeit leistet. Der Server wird von mehreren zugehörigen Skripten begleitet, die bei der Einrichtung von MySQL Konfigurationsarbeiten durchführen oder Ihnen beim Starten und Beenden des Servers behilflich sind. Dieser Abschnitt vermittelt einen Überblick über den Server und zugehörige Programme. Die nachfolgenden Abschnitte beschreiben dann alle diese Programme im Detail.
Jedes MySQL-Programm akzeptiert viele verschiedene Optionen. Die meisten Programme enthalten eine Option --help
, über die Sie eine Beschreibung der verschiedenen Programmoptionen erhalten können. Probieren Sie z. B. mysqld --help aus.
Sie können die Standardoptionswerte bei MySQL-Programmen außer Kraft setzen, indem Sie Optionen auf der Befehlszeile oder in einer Optionsdatei angeben. Abschnitt 4.3, „Angabe von Programmoptionen“.
Die folgende Liste stellt eine kurze Beschreibung des MySQL-Servers und der serverbezogenen Programme dar:
Dies ist der SQL-Daemon (d. h. der eigentliche MySQL-Server). Damit Sie Clientprogramme verwenden können, muss mysqld ausgeführt werden, denn die Clients greifen über eine Verbindung zum Server auf die Datenbanken zu. Siehe auch Abschnitt 5.2, „mysqld — Der MySQL-Server“.
Dies ist eine Serverversion, die zusätzliche Funktionen enthält. Siehe auch Abschnitt 5.3, „mysqld-max, ein erweiterter mysqld-Server“.
Dies ist ein Serverstartskript. mysqld_safe versucht mysqld-max zu starten, sofern es vorhanden ist; andernfalls wird mysqld gestartet. Siehe auch Abschnitt 5.4.1, „mysqld_safe — Startskript für den MySQL-Server“.
Dies ist ein Serverstartskript. Es wird auf Systemen eingesetzt, die Ausführungsverzeichnisse im System V-Stil verwenden. Diese Verzeichnisse enthalten Skripten, die Systemstartdienste für bestimmte Ausführungsebenen enthalten. Das Skript ruft mysqld_safe auf, um den MySQL-Server zu starten. Siehe auch Abschnitt 5.4.2, „mysql.server — Startskript für den MySQL-Server“.
Ein Serverstartskript, welches mehrere auf dem System installierte Server starten oder beenden kann. Siehe auch Abschnitt 5.4.3, „mysqld_multi — Verwalten mehrerer MySQL-Server“. Eine Alternative zu mysqld_multi ist mysqlmanager
, der MySQL Instance Manager. Siehe auch Abschnitt 5.5, „mysqlmanager — Der MySQL Instance Manager“.
Dieses Skript erstellt die MySQL-Datenbank und initialisiert die Grant-Tabellen mit Standardberechtigungen. Es wird normalerweise nur einmal ausgeführt, nämlich dann, wenn Sie MySQL zum ersten Mal auf einem System installieren. Siehe auch Abschnitt 2.9.2, „Schritte nach der Installation unter Unix“.
Dieses Skript wird nach Durchführung eines MySQL-Upgrades verwendet. Es aktualisiert die Grant-Tabellen mit allen Änderungen, die in der neueren MySQL-Version vorgenommen wurden. Siehe auch Abschnitt 5.6, „mysql_fix_privilege_tables — Upgrade von MySQL-Systemtabellen“.
Der MySQL Instance Manager, ein Programm zur Überwachung und Verwaltung von MySQL-Servern. Siehe auch Abschnitt 5.5, „mysqlmanager — Der MySQL Instance Manager“.
Es gibt noch einige andere Programme, die auf dem Serverhost ausgeführt werden.
mysqld ist der MySQL-Server. Nachfolgend werden wir folgende Themen in Zusammenhang mit der Konfiguration dieses MySQL-Servers behandeln:
Startoptionen, die vom Server unterstützt werden
Serversystemvariablen
Serverstatusvariablen
Einstellen des SQL-Modus des Servers
Herunterfahren des Servers
Wenn Sie den Server mysqld starten, können Sie Programmoptionen mithilfe aller in Abschnitt 4.3, „Angabe von Programmoptionen“, beschriebenen Methoden festlegen. Die meistverwendeten Methoden sind die Angabe von Optionen in einer Optionsdatei oder über die Befehlszeile. In den meisten Fällen ist es wünschenswert, dass der Server stets die gleichen Optionen verwendet. Dies lässt sich am einfachsten gewährleisten, indem man die Optionen in einer Optionsdatei auflistet. Siehe auch Abschnitt 4.3.2, „my.cnf-Optionsdateien“.
mysqld liest Optionen aus den Abschnitten [mysqld]
und [server]
aus. mysqld_safe liest Optionen aus den Abschnitten [mysqld]
, [server]
, [mysqld_safe]
und [safe_mysqld]
aus. mysql.server schließlich liest Optionen aus den Abschnitten [mysqld]
und [mysql.server]
aus.
Ein eingebetteter MySQL-Server entnimmt seine Optionen den Abschnitten [server]
, [embedded]
und [
, wobei xxxxx
_SERVER]xxxxx
der Name der Anwendung ist, in die der Server eingebettet ist.
mysqld akzeptiert viele Befehlsoptionen. Eine kurze Liste erhalten Sie, wenn Sie mysqld --help ausführen. Die vollständige Liste rufen Sie über mysqld --verbose --help auf.
Die folgende Liste zeigt einige der häufigsten Serveroptionen (weitere Optionen sind an anderer Stelle beschrieben):
Sicherheitsspezifische Optionen: Siehe auch Abschnitt 5.7.3, „Startoptionen für mysqld
in Bezug auf Sicherheit“.
SSL-spezifische Optionen: Siehe auch Abschnitt 5.9.7.5, „SSL-Befehlsoptionen“.
Optionen zur Steuerung von Binärlogs: Siehe auch Abschnitt 5.12.3, „Die binäre Update-Logdatei“.
Optionen zur Replikation: Siehe auch Abschnitt 6.9, „Replikationsoptionen in my.cnf“.
Optionen für bestimmte Speicher-Engines: Siehe auch Abschnitt 14.1.1, „MyISAM
-Startoptionen“, Abschnitt 14.5.3, „BDB-Startoptionen“, Abschnitt 14.2.4, „InnoDB
: Startoptionen und Systemvariablen“, und Abschnitt 16.5.5.1, „MySQL Cluster-spezifische Befehlsoptionen für mysqld“.
Sie können die Werte der Serversystemvariablen auch mithilfe von Variablennamen als Optionen zuweisen. Dies wird im weiteren Verlauf dieses Abschnitts beschrieben.
--help
, -?
Zeigt eine kurze Hilfemeldung an und wird dann beendet. Verwenden Sie die Optionen --verbose
und --help
, um die vollständige Meldung zu sehen.
--allow-suspicious-udfs
Diese Option bestimmt, ob UDFs (User-Defined Functions, benutzerdefinierte Funktionen), die nur ein xxx
-Symbol für die Hauptfunktion aufweisen, geladen werden dürfen. Standardmäßig ist die Option deaktiviert, und es dürfen nur UDFs geladen werden, die mindestens ein Hilfssymbol aufweisen. Hierdurch soll das Laden von Funktionen aus solchen freigegebenen Objektdateien verhindert werden, die keine zulässigen UDFs enthalten. Siehe auch Abschnitt 26.3.4.6, „Vorsichtsmaßnahmen bei benutzerdefinierten Funktionen (UDF)“.
--ansi
Verwendet die ANSI-konforme SQL-Standardsyntax (statt der MySQL-Syntax). Für eine genauere Steuerung des SQL-Modus des Servers verwenden Sie stattdessen die Option --sql-mode
. Siehe auch Abschnitt 1.9.3, „MySQL im ANSI-Modus laufen lassen“, und Abschnitt 5.2.5, „Der SQL-Modus des Servers“.
--basedir=
path
, -b
path
Der Pfad zum MySQL-Installationsverzeichnis. Normalerweise werden alle Pfad relativ zu diesem Verzeichnis aufgelöst.
--bind-address=
IP
Die IP-Adresse, zu der eine Bindung hergestellt wird.
--binlog-format={row|statement}
Gibt an, ob die datensatz- oder die anweisungsbasierte Replikation verwendet werden soll (die anweisungsbasierte Replikation ist die Vorgabe). Siehe auch Abschnitt 6.3, „Zeilenbasierte Replikation“. Diese Option wurde in MySQL 5.1.5 hinzugefügt.
--binlog-row-event-max-size=
N
Gibt die maximale Größe eines datensatzbasierten Binärlogereignisses in Byte an. Datensätze werden zu Ereignissen zusammengefasst, die – sofern möglich – kleiner sind als die hier angegebene Größe. Der Wert sollte ein Vielfaches von 256 sein, Standard ist 1.024. Siehe auch Abschnitt 6.3, „Zeilenbasierte Replikation“. Diese Option wurde in MySQL 5.1.5 hinzugefügt.
--both-log-formats
Aktiviert alte und neue Logformate (Logdateien und Logtabellen). Diese Option wurde in MySQL 5.1.6 hinzugefügt.
--bootstrap
Diese Option wird vom Skript mysql_install_db verwendet, um die MySQL-Berechtigungstabellen zu erstellen, ohne einen vollständigen MySQL-Server starten zu müssen.
--character-sets-dir=
path
Das Verzeichnis, in dem Zeichensätze installiert sind. Siehe auch Abschnitt 5.11.1, „Der für Daten und zum Sortieren benutzte Zeichensatz“.
--character-set-client-handshake
Zeichensatzinformationen, die vom Client übermittelt wurden, sollten nicht ignoriert werden. Um die Clientangaben zu ignorieren und den Standardzeichensatz des Servers zu benutzen, verwenden Sie --skip-character-set-client-handshake
. In diesem Fall verhält sich MySQL wie MySQL 4.0.
--character-set-filesystem=
charset_name
Der Zeichensatz des Dateisystems. Diese Option wurde in MySQL 5.1.6 hinzugefügt.
--character-set-server=
, charset_name
-C
charset_name
Verwendet charset_name
als Standardzeichensatz am Server. Siehe auch Abschnitt 5.11.1, „Der für Daten und zum Sortieren benutzte Zeichensatz“.
--chroot=
path
Versetzt den Server mysqld während des Starts mithilfe des Systemaufrufs chroot()
in eine geschlossene Umgebung. Dies ist eine empfohlene Sicherheitsmaßnahme. Beachten Sie, dass durch Verwendung dieser Option LOAD DATA INFILE
und SELECT ... INTO OUTFILE
in geringem Maße eingeschränkt werden.
--collation-server=
collation_name
Verwendet collation_name
als Standardsortierung auf dem Server. Siehe auch Abschnitt 5.11.1, „Der für Daten und zum Sortieren benutzte Zeichensatz“.
--console
(Nur für Windows.) Schreibt Fehlerlogmeldungen auch dann in stderr
und stdout
, wenn --log-error
angegeben ist. Wenn diese Option verwendet wird, schließt mysqld das Konsolenfenster nicht.
--core-file
Schreibt eine Speicherauszugsdatei, wenn mysqld sich aufhängt. Bei einigen Systemen müssen Sie zusätzlich die Option --core-file-size
für mysqld_safe angeben. Siehe auch Abschnitt 5.4.1, „mysqld_safe — Startskript für den MySQL-Server“. Beachten Sie, dass auf manchen Systemen (z. B. Solaris) keine Speicherauszugsdateien geschrieben werden, wenn gleichzeitig die Option --user
verwendet wird.
--datadir=
path
, -h
path
Der Pfad zum Datenverzeichnis.
--debug[=
, debug_options
]-#
[
debug_options
]
Wird MySQL mit der Option --with-debug
konfiguriert, dann können Sie mithilfe dieser Option eine Trace-Datei mit Angaben dazu erstellen, was mysqld tut. Der String debug_options
heißt häufig 'd:t:o,
. Standardwert ist file_name
''d:t:i:o,mysqld.trace'
. Siehe auch Abschnitt E.1.2, „Trace-Dateien erzeugen“.
--default-character-set=
(AUSLAUFEND)
charset_name
Verwendet charset_name
als Standardzeichensatz. Diese Option läuft zugunsten von --character-set-server
aus. Siehe auch Abschnitt 5.11.1, „Der für Daten und zum Sortieren benutzte Zeichensatz“.
--default-collation=
collation_name
Verwendet collation_name
als Standardsortierung. Diese Option läuft zugunsten von --collation-server
aus. Siehe auch Abschnitt 5.11.1, „Der für Daten und zum Sortieren benutzte Zeichensatz“.
--default-storage-engine=
type
Stellt die standardmäßige Speicher-Engine für Tabellen ein. Siehe auch Kapitel 14, Speicher-Engines und Tabellentypen.
--default-table-type=
type
Diese Option ist synonym zu --default-storage-engine
.
--default-time-zone=
timezone
Stellt die Standardzeitzone des Servers ein. Diese Option stellt die globale Systemvariable time_zone
ein. Wird die Option nicht angegeben, dann ist die Standardzeitzone mit der Systemzeitzone identisch (diese wird durch den Wert der Systemvariablen system_time_zone
bestimmt).
--delay-key-write[= OFF | ON | ALL]
Legt fest, wie verzögerte Schlüsselschreiboperationen gehandhabt werden. Das verzögerte Schreiben von Schlüsseln sorgt dafür, dass Schlüsselpuffer zwischen einzelnen Schreibvorgängen für MyISAM
-Tabellen neu geladen werden. OFF
deaktiviert das verzögerte Schreiben von Schlüsseln, während ON
es für jene Tabellen aktiviert, die mit der Option DELAY_KEY_WRITE
erstellt worden sind. ALL
schließlich verzögert das Schreiben der Schlüssel für alle MyISAM
-Tabellen. Siehe auch Abschnitt 7.5.2, „Serverparameter feineinstellen“, und Abschnitt 14.1.1, „MyISAM
-Startoptionen“.
Hinweis: Wenn Sie diese Variable auf ALL
setzen, sollten Sie MyISAM
-Tabellen nicht aus einem anderen Programm (z. B. einem anderen MySQL-Server oder myisamchk) heraus verwenden, wenn diese Tabellen bereits in Benutzung sind. Andernfalls können Indizes beschädigt werden.
--des-key-file=
file_name
Liest den DES-Standardschlüssel aus der angegebenen Datei aus. Diese Schlüssel werden von den Funktionen DES_ENCRYPT()
und DES_DECRYPT()
verwendet.
--enable-named-pipe
Aktiviert die Unterstützung für Named Pipes. Diese Option betrifft nur Systeme unter Windows NT/2000/XP/2003 und kann nur für die Server mysqld-nt und mysqld-max-nt benutzt werden, die Named-Pipe-Verbindungen benutzen.
--event-scheduler
Aktiviert den Ereignisplaner. Diese Option wurde in MySQL 5.1.6 hinzugefügt.
--exit-info[=
, flags
]-T [
flags
]
Dies ist eine Bitmaske mit verschiedenen Flags, die Sie zum Debugging des Servers mysqld verwenden können. Verwenden Sie diese Option nur, wenn Sie genau wissen, was sie tut!
Aktiviert die externe Sperrung (Systemsperrung). Diese ist seit MySQL 4.0 standardmäßig deaktiviert. Beachten Sie, dass, wenn Sie diese Option auf einem System verwenden, auf dem lockd
nicht vollständig funktioniert (z. B. unter Linux), mysqld vollständig gesperrt werden kann. Diese Option hieß früher --enable-locking
.
Hinweis: Wenn Sie diese Option verwenden, um das Aktualisieren von MyISAM
-Tabellen durch mehrere MySQL-Prozesse zu ermöglichen, dann müssen Sie sicherstellen, dass die folgenden Bedingungen erfüllt sind:
Sie sollten den Abfrage-Cache nicht für Abfragen benutzen, die Tabellen verwenden, welche durch einen anderen Prozess aktualisiert werden.
Sie sollten --delay-key-write=ALL
oder DELAY_KEY_WRITE=1
nicht bei gemeinsam genutzten Tabellen einsetzen.
Die einfachste Möglichkeit, dies zu gewährleisten, besteht darin, --external-locking
immer zusammen mit --delay-key-write=OFF
und --query-cache-size=0
zu benutzen. (Dies wird standardmäßig nicht gemacht, weil es in vielen Konfigurationen nützlich ist, eine Mischung der vorangegangenen Optionen einzusetzen.)
--flush
Schreibt nach jeder SQL-Anweisung alle Änderungen neu auf die Festplatte (Synchronisierung). Normalerweise schreibt MySQL alle Änderungen erst nach der jeweiligen SQL-Anweisung auf die Festplatte und überlässt dem Betriebssystem die Festplattensynchronisierung. Siehe auch Abschnitt A.4.2, „Was zu tun ist, wenn MySQL andauernd abstürzt“.
--init-file=
file
Liest beim Start SQL-Anweisungen aus der angegebenen Datei aus. Jede Anweisung muss in einer eigenen Zeile stehen und darf keine Kommentare enthalten.
--innodb-
xxx
Die InnoDB
-Optionen sind in Abschnitt 14.2.4, „InnoDB
: Startoptionen und Systemvariablen“, beschrieben.
--language=
lang_name
,
-L lang_name
Gibt Clientfehlermeldungen in der angegebenen Sprache zurück. lang_name
kann als Sprachname oder als vollständiger Pfadname zu dem Verzeichnis angegeben werden, in dem die Sprachdateien installiert sind. Siehe auch Abschnitt 5.11.2, „Nicht englische Fehlermeldungen“.
--large-pages
Einige Hardware- und Betriebssystemarchitekturen unterstützen Speicherseiten, die größer als der Standardwert (normalerweise 4 Kbyte) sind. Die eigentliche Implementierung dieser Unterstützung hängt von der zugrundeliegenden Hardware und dem Betriebssystem ab. Anwendungen, die häufig auf den Speicher zugreifen, können leistungsseitig von der Verwendung großer Seiten profitieren, da die Anzahl von TLB-Fehlschlägen (Translation Lookaside Buffer, Übersetzungspuffer) verringert wird.
Zurzeit unterstützt MySQL nur die Linux-Implementierung der Unterstützung für große Seiten (diese heißt in Linux HugeTLB). Wir beabsichtigen, diese Unterstützung auf FreeBSD, Solaris und möglicherweise auch andere Plattformen auszudehnen.
Bevor unter Linux große Seiten verwendet werden können, ist es notwendig, den HugeTLB-Speicherpool zu konfigurieren. Hinweise hierzu entnehmen Sie der Datei hugetlbpage.txt
im Linux-Kernel-Quellcode.
Die Option ist standardmäßig deaktiviert.
--log[=
, file_name
]-l [
file_name
]
Verbindungen und SQL-Anweisungen, die von Clients empfangen werden, werden in dieser Datei protokolliert. Siehe auch Abschnitt 5.12.2, „Die allgemeine Anfragen-Logdatei“. Wenn Sie den Dateinamen weglassen, verwendet MySQL
als Dateinamen.
host_name
.log
--log-bin=[
base_name
]
Aktiviert das binäre Loggen. Der Server loggt alle datenändernden Anweisungen in das Binärlog, welches für Sicherungs- und Replikationszwecke verwendet wird. Siehe auch Abschnitt 5.12.3, „Die binäre Update-Logdatei“.
Sofern angegeben, ist der Optionswert der Basisname der Logabfolge. Der Server erstellt Binärlogs in einer Abfolge und fügt dabei an den Basisnamen jeweils ein numerisches Suffix an. Die Angabe eines Basisnamens wird empfohlen (siehe Abschnitt A.8.1, „Offene Probleme in MySQL“ zu den Gründen). Andernfalls verwendet MySQL
als Basisnamen.
host_name
-bin
--log-bin-index[=
file_name
]
Dies ist die Indexdatei für Dateinamen von Binärlogs. Siehe auch Abschnitt 5.12.3, „Die binäre Update-Logdatei“. Wenn Sie den Dateinamen weglassen und auch mit --log-bin
keinen Namen festgelegt haben, verwendet MySQL
als Dateinamen.
host_name
-bin.index
--log-bin-trust-function-creators[={0|1}]
Ohne Argument oder mit dem Argument 1 setzt diese Option die Systemvariable log_bin_trust_function_creators
auf 1. Wird als Argument 0 übergeben, dann wird die Systemvariable auf 0 gesetzt. log_bin_trust_function_creators
beeinflusst, wie MySQL Beschränkungen für die Erstellung gespeicherter Funktionen durchsetzt. Siehe auch Abschnitt 19.4, „Binärloggen gespeicherter Routinen und Trigger“.
--log-error[=
file_name
]
Fehler- und Startmeldungen werden in der genannten Datei protokolliert. Siehe auch Abschnitt 5.12.1, „Die Fehler-Logdatei“. Wenn Sie den Dateinamen weglassen, verwendet MySQL
. Hat der Dateiname keine Erweiterung, dann fügt der Server die Erweiterung host_name
.err.err
hinzu.
--log-isam[=
file_name
]
Protokolliert alle MyISAM
-Änderungen an dieser Datei (wird nur zum MyISAM
-Debugging verwendet).
--log-long-format
(AUSLAUFEND)
Schreibt Zusatzinformationen in das Update-Log, das Binärlog und das Log für langsame Abfragen, sofern diese aktiviert sind. So werden etwa der Benutzername und ein Zeitstempel für alle Abfragen protokolliert. Diese Option läuft aus, da sie mittlerweile das Standardverhalten beim Loggen darstellt. (Siehe Beschreibung zu --log-short-format
.) Die Option --log-queries-not-using-indexes
dient dem Loggen von Abfragen, die keine Indizes verwenden, in das Log für langsame Abfragen.
--log-queries-not-using-indexes
Wenn Sie diese Option in Verbindung mit --log-slow-queries
verwenden, werden Abfragen, die keine Indizes verwenden, in das Log für langsame Abfragen geschrieben. Siehe auch Abschnitt 5.12.4, „Die Logdatei für langsame Anfragen“.
--log-short-format
Protokolliert weniger Informationen in das Update-Log, das Binärlog und das Log für langsame Abfragen, sofern diese aktiviert sind. So werden etwa weder Benutzername noch ein Zeitstempel für Abfragen protokolliert.
--log-slow-admin-statements
Protokolliert administrative Anweisungen wie OPTIMIZE TABLE
, ANALYZE TABLE
und ALTER TABLE
in das Log für langsame Abfragen.
--log-slow-queries[=
file_name
]
Protokolliert alle Abfragen, deren Ausführung mehr als long_query_time
Sekunden gedauert hat, in die angegebene Datei. Siehe auch Abschnitt 5.12.4, „Die Logdatei für langsame Anfragen“. Details finden Sie in den Beschreibungen zu den Optionen --log-long-format
und --log-short-format
.
--log-warnings
, -W
Schreibt Warnungen wie Aborted connection...
in das Fehlerlog. Die Aktivierung dieser Option wird beispielsweise empfohlen, wenn Sie die Replikation verwenden. (Sie erhalten dann mehr Informationen zu den ablaufenden Vorgängen, z. B. Netzwerkausfälle und Neuverbindungen.) Die Option ist standardmäßig aktiviert. Sie können sie mithilfe von --skip-log-warnings
deaktivieren. Unterbrochene Verbindungen werden nicht in das Fehlerlog protokolliert, sofern der Wert größer als 1 ist. Siehe auch Abschnitt A.2.10, „Kommunikationsfehler/abgebrochene Verbindung“.
--low-priority-updates
Gibt tabellenändernden Operationen (INSERT
, REPLACE
, DELETE
, UPDATE
) eine niedrigere Priorität als Auswahloperationen. Dies kann auch via {INSERT | REPLACE | DELETE | UPDATE} LOW_PRIORITY ...
erfolgen, um die Priorität nur einer Abfrage zu verringern. Die Priorität eines Threads können Sie mit SET LOW_PRIORITY_UPDATES=1
verringern. Siehe auch Abschnitt 7.3.2, „Themen, die Tabellensperren betreffen“.
--memlock
Sperrt den mysqld-Prozess im Speicher. Dies funktioniert auf Systemen wie Solaris, die den Systemaufruf mlockall()
unterstützen. Die Option kann hilfreich sein, wenn ein Problem auftritt, bei dem das Betriebssystem eine Auslagerung von mysqld auf die Festplatte verursacht. Beachten Sie, dass die Verwendung dieser Option eine Ausführung des Servers als root
erfordert, wovon in der Regel aus Sicherheitsgründen abzuraten ist. Siehe auch Abschnitt 5.7.5, „Wie man MySQL als normaler Benutzer laufen läßt“.
--myisam-recover
[=
option
[,option
]...]]
Stellt den Wiederherstellungsmodus der MyISAM
-Speicher-Engine ein. Der Optionswert ist eine beliebige Kombination der Werte DEFAULT
, BACKUP
, FORCE
oder QUICK
. Wenn Sie mehrere Werte angeben, trennen Sie sie durch Kommata. Sie können auch den Wert ""
angeben, um die Option zu deaktivieren. Wird die Option verwendet, dann prüft mysqld bei jedem Öffnen einer MyISAM
-Tabelle, ob diese als abgestürzt gekennzeichnet ist oder beim letzten Mal nicht korrekt geschlossen wurde. (Die zweite Option funktioniert nur, wenn die Ausführung mit deaktivierter externer Sperrung erfolgt.) In diesem Fall führt mysqld eine Überprüfung der Tabelle durch. Ist die Tabelle tatsächlich beschädigt, dann versucht mysqld sie zu reparieren.
Die folgenden Optionen beeinflussen die Ausführung der Reparatur:
Option | Beschreibung |
DEFAULT | Ist identisch mit der Nichtangabe von Optionen für --myisam-recover . |
BACKUP | Speichert, wenn die Datendatei während der Wiederherstellung geändert wurde, eine Sicherungskopie der Datei als . |
FORCE | Führt die Wiederherstellung auch dann durch, wenn dadurch mehr als nur ein Datensatz in der .MYD -Datei verloren geht. |
QUICK | Überprüft die Datensätze in der Tabelle nicht, wenn keine Löschblöcke vorhanden sind. |
Bevor der Server eine Tabelle automatisch repariert, schreibt er einen Hinweis zur Reparatur in das Fehlerlog. Wollen Sie die meisten Probleme durch eine Wiederherstellung ohne Benutzereingriff beseitigen, dann sollten Sie die Optionen BACKUP,FORCE
angeben. Hierdurch wird die Reparatur der Tabelle auch dann erzwungen, wenn mehrere Datensätze gelöscht würden; gleichzeitig wird aber die alte Datendatei als Sicherungskopie vorgehalten, sodass Sie später untersuchen können, was passiert ist.
Siehe auch Abschnitt 14.1.1, „MyISAM
-Startoptionen“.
--ndb-connectstring=
connect_string
Wenn Sie die NDB
-Speicher-Engine verwenden, können Sie den Managementserver angeben, der die Clusterkonfiguration verteilt. Dies tun Sie durch Einstellung der Option --ndb-connectstring
. Informationen zur Syntax finden Sie in Abschnitt 16.4.4.2, „MySQL Cluster: connectstring
“.
--ndbcluster
Wenn die Binärdatei eine Unterstützung der NDB Cluster
-Speicher-Engine enthält, aktiviert diese Option die Engine (diese ist standardmäßig deaktiviert). Siehe auch Kapitel 16, MySQL Cluster.
--old-log-format
Aktiviert nur das alte Logformat. Hierdurch werden Logtabellen und die SELECT
-Funktionalität für Loginhalte deaktiviert. Diese Option wurde in MySQL 5.1.6 hinzugefügt.
--old-passwords
Erzwingt die Erzeugung kurzer Passwort-Hashes (wie vor Version 4.1) auch für neue Passwörter. Dies kann zu Kompatibilitätszwecken erforderlich sein, wenn der Server ältere Clientprogramme unterstützen muss. Siehe auch Abschnitt 5.8.9, „Kennwort-Hashing ab MySQL 4.1“.
--one-thread
Verwendet nur einen Thread (zum Debuggen unter Linux). Diese Option ist nur verfügbar, wenn der Server mit aktiviertem Debugging erstellt wurde. Siehe auch Abschnitt E.1, „Einen MySQL-Server debuggen“.
--open-files-limit=
count
Ändert die Anzahl der für mysqld verfügbaren Dateideskriptoren. Wenn diese Option nicht oder auf 0 gesetzt ist, verwendet mysqld den Wert, um Dateideskriptoren mit setrlimit()
zu reservieren. Ist der Wert hingegen 0, dann reserviert mysqld max_connections×5
oder max_connections +
table_open_cache×2
Dateien (je nachdem, welcher Wert höher ist). Versuchen Sie, diesen Wert zu erhöhen, wenn mysqld die Fehlermeldung Too many open files
ausgibt.
--pid-file=
path
Der Pfadname der Prozesskennungsdatei. Diese Datei wird von anderen Programmen wie mysqld_safe verwendet, um die Prozesskennung des Servers zu bestimmen.
--port=
port_num
, -P
port_num
Die Portnummer, die beim Horchen auf TCP/IP-Verbindungen verwendet wird. Die Portnummer muss 1024 oder höher sein, sofern der Server nicht vom Systembenutzer root
gestartet wird.
--port-open-timeout=
num
Bei manchen Systemen wird, wenn der Server beendet wird, der TCP/IP-Port unter Umständen nicht mehr verfügbar gemacht. Wenn der Server kurz darauf neu gestartet wird, kann der Versuch fehlschlagen, den Port neu zu öffnen. Diese Option gibt an, wie viele Sekunden der Server warten soll, bis der TCP/IP-Port wieder frei wird, sofern er nicht geöffnet werden kann. Standardmäßig gibt es keine Wartezeit. Diese Option wurde in MySQL 5.1.5 hinzugefügt.
--safe-mode
Überspringt einige Optimierungsstufen.
--safe-show-database
(AUSLAUFEND)
Siehe auch Abschnitt 5.8.3, „Von MySQL zur Verfügung gestellte Berechtigungen“.
--safe-user-create
Wenn diese Option aktiviert ist, kann ein Benutzer mit der GRANT
-Anweisung keine neuen MySQL-Benutzer erstellen, wenn er für die Tabelle mysql.user
oder eine der Spalten in dieser Tabelle nicht die Berechtigung INSERT
hat.
--secure-auth
Unterbindet die Authentifizierung von Clients, die Konten mit alten Passwörtern (vor Version 4.1) zu verwenden versuchen.
--shared-memory
Aktiviert Verbindungen mit gemeinsamem Speicher durch lokale Clients. Diese Option ist nur unter Windows verfügbar.
--shared-memory-base-name=
name
Der Name des gemeinsamen Speichers, der für Verbindungen mit gemeinsamem Speicher verwendet werden soll. Diese Option ist nur unter Windows verfügbar. Der Standardname ist MYSQL
. Beim Namen wird die Groß-/Kleinschreibung unterschieden.
--skip-bdb
Deaktiviert die BDB
-Speicher-Engine. Hierdurch wird Speicher gespart, ferner werden einige Operationen beschleunigt. Verwenden Sie die Option nicht, wenn Sie BDB
-Tabellen benötigen.
--skip-concurrent-insert
Schaltet die Möglichkeit ab, bei MyISAM
-Tabellen gleichzeitig auszuwählen und einzufügen. (Diese Option sollte nur verwendet werden, wenn Sie das Gefühl haben, einen Bug in dieser Funktion gefunden zu haben.)
Eine externe Sperrung (Systemsperrung) wird nicht verwendet. Bei deaktivierter externer Sperrung müssen Sie den Server herunterfahren, um myisamchk verwenden zu können. (Siehe auch Abschnitt 1.4.3, „Wie stabil ist MySQL?“.) Um diese Anforderung zu umgehen, verwenden Sie die Anweisungen CHECK TABLE
und REPAIR TABLE
zur Überprüfung und Reparatur von MyISAM
-Tabellen.
Die externe Sperrung wird seit MySQL 4.0 standardmäßig deaktiviert.
--skip-grant-tables
Diese Option sorgt dafür, dass der Server das Berechtigungssystem überhaupt nicht verwendet. Hierdurch erhalten alle Benutzer, die auf den Server zugreifen können, uneingeschränkten Zugang zu allen Datenbanken. Sie können einen laufenden Server dazu bringen, die Grant-Tabellen wieder zu verwenden, indem Sie mysqladmin flush-privileges oder mysqladmin reload über die System-Shell ausführen oder die MySQL-Anweisung FLUSH PRIVILEGES
nach Herstellen einer Verbindung zum Server absetzen. Diese Option unterbindet auch das Laden von Plug-Ins und benutzerdefinierten Funktionen (UDFs).
--skip-host-cache
Der interne Hostnamencache wird nicht zur schnelleren Namensauflösung verwendet. Stattdessen wird bei jeder Verbindungsherstellung durch einen Client der DNS-Server abgefragt. Siehe auch Abschnitt 7.5.6, „Wie MySQL DNS benutzt“.
--skip-innodb
Deaktiviert die InnoDB
-Speicher-Engine. Hierdurch wird Speicher und Festplattenkapazität gespart, ferner werden einige Operationen beschleunigt. Verwenden Sie die Option nicht, wenn Sie InnoDB
-Tabellen benötigen.
--skip-name-resolve
Bei der Überprüfung von Clientverbindungen werden Hostnamen nicht aufgelöst. Es werden ausschließlich IP-Nummern verwendet. Wenn Sie diese Option verwenden, müssen alle Werte in der Spalte Host
der Grant-Tabellen IP-Nummern oder localhost
sein. Siehe auch Abschnitt 7.5.6, „Wie MySQL DNS benutzt“.
--skip-ndbcluster
Deaktiviert die NDB Cluster
-Speicher-Engine. Dies ist die Standardeinstellung bei Binärdistributionen, die mit Unterstützung für die NDB Cluster
-Speicher-Engine erstellt wurden. Der Server reserviert dieser Speicher-Engine nur dann Speicher und andere Ressourcen, wenn die Option --ndbcluster
explizit angegeben wird. Ein Anwendungsbeispiel finden Sie in Abschnitt 16.4.3, „Schnelle Testeinrichtung von MySQL Cluster“.
--skip-networking
Unterbindet das Horchen auf TCP/IP-Verbindungen ganz. Die gesamte Interaktion mit mysqld muss über Named Pipes oder gemeinsamen Speicher (unter Windows) bzw. Unix-Socketdateien (unter Unix) erfolgen. Diese Option ist für Systeme, bei denen nur lokale Clients zulässig sind, sehr empfehlenswert. Siehe auch Abschnitt 7.5.6, „Wie MySQL DNS benutzt“.
--standalone
Nur unter Windows NT-basierten Systemen vorhanden. Die Option weist den MySQL-Server an, nicht als Dienst ausgeführt zu werden.
--symbolic-links
, --skip-symbolic-links
Aktiviert bzw. deaktiviert die Unterstützung für symbolische Verknüpfungen. Die Option hat unter Windows und Unix unterschiedliche Auswirkungen:
Unter Windows erlaubt Ihnen die Aktivierung symbolischer Verknüpfungen die Einrichtung einer solchen Verknüpfung zu einem Datenbankverzeichnis durch Erstellen einer Datei
, die den Pfad zum echten Verzeichnis enthält. Siehe auch Abschnitt 7.6.1.3, „Daten unter Windows auf verschiedene Platten aufteilen“.
db_name
.sym
Unter Unix hat die Aktivierung symbolischer Verknüpfungen zur Folge, dass Sie eine MyISAM
-Index- oder -Datendatei mit einem anderen Verzeichnis verknüpfen können. Diese Verknüpfung erfolgt mit den Optionen INDEX
DIRECTORY
oder DATA DIRECTORY
der CREATE TABLE
-Anweisung. Wenn Sie die Tabelle löschen oder umbenennen, werden die Dateien, auf die die symbolischen Verknüpfungen verweisen, ebenfalls gelöscht bzw. umbenannt. Siehe auch Abschnitt 7.6.1.2, „Benutzung symbolischer Links für Tabellen“.
--skip-safemalloc
Wenn MySQL mit der Option --with-debug=full
konfiguriert wird, prüfen alle MySQL-Programme bei jedem Speicherzuweisungs- und -freigabevorgang auf Speicherüberläufe. Diese Überprüfung erfolgt recht langsam, weswegen Sie sie für den Server mithilfe der Option --skip-safemalloc
umgehen sollten, wenn Sie sie nicht brauchen.
--skip-show-database
Bei dieser Option darf die SHOW DATABASES
-Anweisung nur von Benutzern verwendet werden, die die Berechtigung SHOW DATABASES
haben. Die Anweisung zeigt dann alle Datenbanknamen an. Ohne diese Option dürfen alle Benutzer SHOW DATABASES
verwenden, aber die Datenbanknamen werden nur angezeigt, wenn der Benutzer die Berechtigung SHOW DATABASES
oder spezifische Berechtigungen für eine Datenbank hat. Beachten Sie, dass jede globale Berechtigung als Berechtigung für die Datenbank betrachtet wird.
--skip-stack-trace
Stapel-Trace-Dateien werden nicht geschrieben. Diese Option ist praktisch, wenn Sie mysqld unter einem Debugger ausführen. Bei manchen Systemen müssen Sie die Option auch verwenden, um eine Speicherauszugsdatei zu erhalten. Siehe auch Abschnitt E.1, „Einen MySQL-Server debuggen“.
--skip-thread-priority
Deaktiviert die Verwendung von Thread-Prioritäten für eine schnellere Antwortzeit.
--socket=
path
Unter Unix gibt diese Option die Unix-Socketdatei an, die beim Horchen nach lokalen Verbindungen verwendet werden soll. Der Vorgabewert ist /tmp/mysql.sock
. Unter Windows legt die Option den Pipe-Namen fest, der beim Horchen nach lokalen Verbindungen verwendet werden soll, die eine Named Pipe nutzen. Der Vorgabewert ist MySQL
(keine Unterscheidung der Groß-/Kleinschreibung).
--sql-mode=
value
[,value
[,value
...]]
Stellt den SQL-Modus ein. Siehe auch Abschnitt 5.2.5, „Der SQL-Modus des Servers“.
--temp-pool
Diese Option sorgt dafür, dass die meisten vom Server erstellten Temporärdateien eine kleine Menge von Namen nutzt (statt dass ein eindeutiger Name für jede neue Datei erstellt wird). Hierdurch wird ein Problem umgangen, dass der Linux-Kernel mit der Erstellung vieler neuer Dateien mit unterschiedlichen Namen hat. Beim ursprünglichen Verhalten scheint Linux ein „Speicherleck“ aufzuweisen, da der Speicher nicht dem Festplattencache, sondern dem Verzeichniseintragscache zugewiesen wird.
--transaction-isolation=
level
Stellt die Standardstufe für die Transaktionsisolierung ein. Der Wert level
kann READ-UNCOMMITTED
, READ-COMMITTED
, REPEATABLE-READ
oder SERIALIZABLE
sein. Siehe auch Abschnitt 13.4.6, „SET TRANSACTION
“.
--tmpdir=
path
, -t
path
Der Pfad des Verzeichnisses, in dem Temporärdateien erstellt werden. Die Option kann nützlich sein, wenn Ihr /tmp
-Standardverzeichnis auf einer Partition liegt, die zu klein für die Aufnahme temporärer Tabellen ist. Die Option akzeptiert mehrere Pfade, die zyklisch abwechselnd verwendet werden. Pfade sollten unter Unix durch Doppelpunkte (‘:
’) und unter Windows, NetWare und OS/2 durch Semikola (‘;
’) getrennt werden. Wenn der MySQL-Server als Replikations-Slave agiert, sollten Sie die Option --tmpdir
nicht auf ein Verzeichnis auf einem speicherbasierten Dateisystem oder aber ein Verzeichnis verweisen lassen, welches gelöscht wird, wenn der Serverhost neu gestartet wird. Weitere Informationen zur Speicherposition temporärer Dateien finden Sie in Abschnitt A.4.4, „Wohin MySQL temporäre Dateien speichert“. Ein Replikations-Slave benötigt einen Teil seiner Temporärdateien, um einen Systemneustart so zu überstehen, dass er Temporärtabellen oder LOAD DATA INFILE
-Operationen replizieren kann. Wenn Dateien in im Verzeichnis für Temporärdateien beim Serverneustart verloren gehen, schlägt die Replikation fehl.
--user={
user_name
|
user_id
}, -u
{user_name
|
user_id
}
Führt den Server mysqld als Benutzer mit dem spezifizierten Benutzernamen (user_name
) oder der numerischen Benutzerkennung (user_id
) aus. („Benutzer“ bezeichnet in diesem Kontext ein Systemanmeldekonto und keinen in den Grant-Tabellen aufgeführten MySQL-Benutzer.)
Diese Option zwingend erforderlich, wenn Sie mysqld als root
starten. Der Server wechselt seine Benutzerkennung während der Startsequenz und wird dann als der angegebene Benutzer statt als root
ausgeführt. Siehe auch Abschnitt 5.7.1, „Allgemeine Sicherheitsrichtlinien“.
Um eine potenzielle Sicherheitslücke zu vermeiden, wenn ein Benutzer die Option --user=root
in einer Datei my.cnf
hinzufügt (und auf diese Weise eine Ausführung des Servers als root
veranlasst), verwendet mysqld nur die erste angegebene Option --user
und erzeugt eine Warnung, wenn mehrere --user
-Optionen vorhanden sind. Optionen in /etc/my.cnf
und $MYSQL_HOME/my.cnf
werden vor eventuellen Befehlszeilenoptionen verarbeitet, weswegen empfohlen wird, eine Option --user
in /etc/my.cnf
einzufügen und dort einen anderen Wert als root
anzugeben. Die Option in /etc/my.cnf
wird vor allen anderen --user
-Optionen gefunden; hierdurch ist sichergestellt, dass der Server als ein anderer Benutzer als root
ausgeführt und eine Warnung erzeugt wird, wenn eine andere --user
- Option gefunden wird.
--version
, -V
Zeigt die Versionsinformation an und wird dann beendet.
Sie können einer Serversystemvariablen einen Wert zuweisen, indem Sie eine Option der Form --
verwenden. So setzt beispielsweise var_name
=value
--key_buffer_size=32M
die Variable key_buffer_size
auf einen Wert von 32 Mbyte.
Beachten Sie, dass, wenn Sie einer Variablen einen Wert zuweisen, MySQL diesen ggf. automatisch so korrigiert, dass er innerhalb eines gegebenen Bereichs bleibt, oder den Wert auf den nächstgelegenen zulässigen Wert setzt, sofern nur bestimmte Werte gestattet sind.
Wenn Sie den Höchstwert, auf den eine Variable zur Laufzeit mit SET
gesetzt werden kann, beschränken wollen, definieren Sie dies unter Verwendung der Befehlszeileoption --maximum-
.
var_name
Es ist ferner möglich, Variablen über die Syntax --set-variable=
oder var_name
=value
-O
einzustellen. Diese Syntax läuft jedoch aus.
var_name
=value
Sie können die Werte der meisten Systemvariablen für einen laufenden Server mit der Anweisung SET
ändern. Siehe auch Abschnitt 13.5.3, „SET
“.
Abschnitt 5.2.2, „Server-Systemvariablen“, bietet eine vollständige Beschreibung aller Variablen sowie weitere Informationen zu deren Einstellung beim Serverstart und zur Laufzeit. Abschnitt 7.5.2, „Serverparameter feineinstellen“, enthält Informationen zur Optimierung des Servers durch gezielte Einstellung der Systemvariablen.
Der Server mysql verwaltet eine ganze Reihe von Systemvariablen, die angeben, wie er konfiguriert ist. Für alle diese Variablen gibt es Vorgabewerte. Diese können beim Serverstart über Optionen auf der Befehlszeile oder in Optionsdateien eingestellt werden. Die meisten Variablen lassen sich zur Laufzeit des Servers dynamisch mithilfe der SET
-Anweisung ändern; auf diese Weise können Sie den Betrieb des Servers beeinflussen, ohne ihn beenden und neu starten zu müssen. Ferner können Sie die Werte auch in Ausdrücken verwenden.
Durch Absetzen der SHOW VARIABLES
-Anweisung können Sie die Namen und Werte der Systemvariablen auflisten lassen.
Die meisten Systemvariablen werden an dieser Stelle beschrieben. Variablen, bei denen keine Version angegeben ist, sind in allen Releases von MySQL 5.1 vorhanden. Historische Informationen zu ihrer Implementierung finden Sie im MySQL 5.0 Reference Manual und im MySQL-Referenzhandbuch für die Versionen 3.23, 4.0 und 4.1.
Hinweise zur Syntax bei der Einstellung und Anzeige von Werten von Systemvariablen finden Sie in Abschnitt 5.2.3, „Verwendung von Server-Systemvariablen“. Abschnitt 5.2.3.2, „Dynamische Systemvariablen“, listet die Variablen auf, die zur Laufzeit eingestellt werden können. Abschnitt 14.2.4, „InnoDB
: Startoptionen und Systemvariablen“, listet InnoDB
-Systemvariablen auf. Informationen zur Optimierung der Systemvariablen sind in Abschnitt 7.5.2, „Serverparameter feineinstellen“, enthalten.
Hinweis: Verschiedene Systemvariablen lassen sich mit der Anweisung SET
aktivieren, indem sie auf ON
bzw. 1
gesetzt werden. Ähnlich können Sie sie mit SET
deaktivieren, indem Sie sie auf OFF
bzw. 0
setzen. Um solche Variablen über die Befehlszeile oder in Optionsdateien einstellen zu können, müssen Sie sie auf 1
oder 0
setzen (d. h. die Einstellungen ON
und OFF
funktionieren nicht). So führt beispielsweise auf der Befehlszeile die Option --delay_key_write=1
zum gewünschten Ergebnis – anders als --delay_key_write=ON
.
Werte für Puffergrößen, Längen und Stapelgrößen sind in Byte angegeben, sofern nichts anderes festgelegt ist.
auto_increment_increment
auto_increment_increment
und auto_increment_offset
sind zur Verwendung bei der Master-to-Master-Replikation vorgesehen und können zur Steuerung des Betriebs von AUTO_INCREMENT
-Spalten eingesetzt werden. Beide Variablen können global oder lokal eingestellt werden und jeweils einen Integer-Wert zwischen 1 und 65.535 einnehmen. Wenn eine dieser Variablen auf 0 gesetzt wird, wird der Wert automatisch auf 1 umgestellt. Der Versuch, ihnen einen ganzzahligen Wert größer 65.535 oder kleiner 0 zuzuweisen, führt hingegen zur automatischen Zuweisung des Wertes 65.535. Sollten Sie versuchen, auto_increment_increment
oder auto_increment_offset
auf einen nicht ganzzahligen Wert zu stellen, dann wird eine Fehlermeldung ausgegeben, und der Wert der Variable bleibt unverändert.
Diese beiden Variablen beeinflussen das Verhalten von AUTO_INCREMENT
-Spalten wie folgt:
auto_increment_increment
steuert das Intervall zwischen aufeinanderfolgenden Spaltenwerten. Zum Beispiel:
mysql>SHOW VARIABLES LIKE 'auto_inc%';
+--------------------------+-------+ | Variable_name | Value | +--------------------------+-------+ | auto_increment_increment | 1 | | auto_increment_offset | 1 | +--------------------------+-------+ 2 rows in set (0.00 sec) mysql>CREATE TABLE autoinc1
->(col INT NOT NULL AUTO_INCREMENT PRIMARY KEY);
Query OK, 0 rows affected (0.04 sec) mysql>SET @@auto_increment_increment=10;
Query OK, 0 rows affected (0.00 sec) mysql>SHOW VARIABLES LIKE 'auto_inc%';
+--------------------------+-------+ | Variable_name | Value | +--------------------------+-------+ | auto_increment_increment | 10 | | auto_increment_offset | 1 | +--------------------------+-------+ 2 rows in set (0.01 sec) mysql>INSERT INTO autoinc1 VALUES (NULL), (NULL), (NULL), (NULL);
Query OK, 4 rows affected (0.00 sec) Records: 4 Duplicates: 0 Warnings: 0 mysql>SELECT col FROM autoinc1;
+-----+ | col | +-----+ | 1 | | 11 | | 21 | | 31 | +-----+ 4 rows in set (0.00 sec)
(Beachten Sie, wie hier mithilfe von SHOW VARIABLES
die aktuellen Werte dieser Variablen ermittelt werden.)
auto_increment_offset
bestimmt den Startwert der Spalte AUTO_INCREMENT
. Betrachten Sie folgendes Beispiel (hier wird davon ausgegangen, dass diese Anweisungen während derselben Sitzung ausgeführt werden, bei der auch obiges Beispiel für auto_increment_increment
erstellt wurde):
mysql>SET @@auto_increment_offset=5;
Query OK, 0 rows affected (0.00 sec) mysql>SHOW VARIABLES LIKE 'auto_inc%';
+--------------------------+-------+ | Variable_name | Value | +--------------------------+-------+ | auto_increment_increment | 10 | | auto_increment_offset | 5 | +--------------------------+-------+ 2 rows in set (0.00 sec) mysql>CREATE TABLE autoinc2
->(col INT NOT NULL AUTO_INCREMENT PRIMARY KEY);
Query OK, 0 rows affected (0.06 sec) mysql>INSERT INTO autoinc2 VALUES (NULL), (NULL), (NULL), (NULL);
Query OK, 4 rows affected (0.00 sec) Records: 4 Duplicates: 0 Warnings: 0 mysql>SELECT col FROM autoinc2;
+-----+ | col | +-----+ | 5 | | 15 | | 25 | | 35 | +-----+ 4 rows in set (0.02 sec)
Wenn der Wert von auto_increment_offset
größer ist als der von auto_increment_increment
, dann wird der Wert von auto_increment_offset
ignoriert.
Sollte eine dieser Variablen (oder beide) geändert werden und dann neue Datensätze in eine Tabelle mit einer AUTO_INCREMENT
-Spalte eingefügt werden, dann könnten die Ergebnisse unlogisch erscheinen, da die Berechnung der AUTO_INCREMENT
-Wertereihe ohne Berücksichtigung ggf. bereits in der Spalte vorhandener Werte erfolgt und der nächste eingefügte Wert der kleinste Wert in der Reihe ist, der größer ist als der größte vorhandene Wert in der AUTO_INCREMENT
-Spalte. Mit anderen Worten wird die Reihe so berechnet:
auto_increment_offset +
N
×
auto_increment_increment
Hierbei ist N
ist ein positiver Integer-Wert in der Reihe [1, 2, 3, ...]. Zum Beispiel:
mysql>SHOW VARIABLES LIKE 'auto_inc%';
+--------------------------+-------+ | Variable_name | Value | +--------------------------+-------+ | auto_increment_increment | 10 | | auto_increment_offset | 5 | +--------------------------+-------+ 2 rows in set (0.00 sec) mysql>SELECT col FROM autoinc1;
+-----+ | col | +-----+ | 1 | | 11 | | 21 | | 31 | +-----+ 4 rows in set (0.00 sec) mysql>INSERT INTO autoinc1 VALUES (NULL), (NULL), (NULL), (NULL);
Query OK, 4 rows affected (0.00 sec) Records: 4 Duplicates: 0 Warnings: 0 mysql>SELECT col FROM autoinc1;
+-----+ | col | +-----+ | 1 | | 11 | | 21 | | 31 | | 35 | | 45 | | 55 | | 65 | +-----+ 8 rows in set (0.00 sec)
Die für auto_increment_increment
und auto_increment_offset
angezeigten Werte erzeugen die Reihe 5 + N
× 10, also [5, 15, 25, 35, 45, ...]. Der größte Wert, der vor der INSERT
-Anweisung in der col
-Spalte vorhanden ist, ist 31. Der nächste verfügbare Wert in der AUTO_INCREMENT
-Reihe ist 35, d. h. die eingefügten Werte für col
beginnen bei diesem Punkt; die Ergebnisse der SELECT
-Abfrage sehen also so aus wie angezeigt.
Es ist wichtig, sich zu vergegenwärtigen, dass es nicht möglich ist, die Wirkungen dieser zwei Variablen auf eine einzige Tabelle zu beschränken, weswegen sie nicht die Funktion von Folgen wahrnehmen, die einige andere Datenbanksysteme anbieten; die Variablen steuern vielmehr das Verhalten aller AUTO_INCREMENT
-Spalten in allen Tabellen auf dem MySQL-Server. Wird eine dieser Variablen global eingestellt, dann wird die Wirkung aufrechterhalten, bis der globale Wert geändert oder durch eine lokale Einstellung außer Kraft gesetzt oder mysqld neu gestartet wird. Bei einer lokalen Einstellung wirkt sich der neue Wert auf die AUTO_INCREMENT
in allen Tabellen aus, in die vom aktuellen Benutzer während der laufenden Sitzung neue Datensätze eingefügt werden, sofern die Werte nicht während dieser Sitzung geändert werden.
Der Standardwert von auto_increment_increment
ist 1. Siehe auch Abschnitt 6.15, „Auto-Increment in der Multi-Master-Replikation“.
auto_increment_offset
Diese Variable hat den Vorgabewert 1. Besonderheiten entnehmen Sie der Beschreibung von auto_increment_increment
.
back_log
Dies ist die Anzahl der ausstehenden Verbindungsanforderungen, die bei MySQL zulässig sind. Die Option wird wichtig, wenn der MySQL-Haupt-Thread sehr viele Verbindungsanforderungen innerhalb kürzester Zeit erhält. Es dauert dann eine (wenn auch sehr kurze) Zeit, bis der Haupt-Thread die Verbindung geprüft und einen neuen Thread gestartet hat. Der Wert back_log
gibt an, wie viele Anforderungen während dieser kurzen Zeit gestapelt werden können, bevor MySQL neue Anforderungen vorübergehend nicht mehr beantwortet. Sie müssen diesen Wert nur dann erhöhen, wenn Sie eine hohe Anzahl von Verbindungen innerhalb kurzer Zeit erwarten.
Anders gesagt bestimmt der Wert die Größe der Horchwarteschlange für eingehende TCP/IP-Verbindungen. Ihr Betriebssystem hat eine eigene Begrenzung dieser Warteschlangengröße. Weitere Informationen hierzu sollten Sie auf der Manpage zum Unix-Systemaufruf listen()
finden. Überprüfen Sie Ihre Betriebssystemdokumentation zu Angaben für den Maximalwert dieser Variablen. back_log
darf nicht höher gesetzt sein als für das jeweilige Betriebssystem zulässig.
basedir
Gibt das Basisverzeichnis der MySQL-Installation an. Die Variable kann mit der Option --basedir
eingestellt werden.
bdb_cache_parts
Die Anzahl der Teile, die für den BDB
-Cache verwendet werden sollen. Wurde in MySQL 5.1.2 hinzugefügt.
bdb_cache_size
Die Größe des Puffers, der für das Caching von Indizes und Datensätzen für BDB
-Tabellen reserviert wird. Einige Systeme erlauben eine Einstellung dieser Variablen auf einen Wert von mehr als 4 Gbyte. Wenn Sie keine BDB
-Tabellen verwenden, sollten Sie mysqld mit --skip-bdb
starten, damit für diesen Cache kein Speicher reserviert wird.
bdb_home
Dies ist das Basisverzeichnis für BDB
-Tabellen. Hier sollte der gleiche Wert stehen wie bei der Variablen datadir
.
bdb_log_buffer_size
Gibt die Größe des Puffers an, der für das Caching von Indizes und Datensätzen für BDB
-Tabellen reserviert wird. Wenn Sie keine BDB
-Tabellen verwenden, sollten Sie hier 0 zuweisen oder mysqld mit --skip-bdb
, damit für diesen Cache kein Speicher reserviert wird.
bdb_logdir
Gibt das Verzeichnis an, in das die BDB
-Speicher-Engine ihre Logdateien schreibt. Die Variable kann mit der Option --bdb-logdir
eingestellt werden.
bdb_max_lock
Die maximale Anzahl von Sperren, die für eine BDB
-Tabelle aktiv sein können (standardmäßig 10.000). Sie sollten diesen Wert erhöhen, wenn bei der Durchführung langer Transaktionen oder dann, wenn mysqld viele Datensätze zur Berechnung einer Abfrage untersuchen muss, die folgende Fehlermeldung auftritt:
bdb: Lock table is out of available locks Got error 12 from ...
bdb_region_size
Die Größe des zugrundeliegenden Logbereichs der BDB
-Umgebung. Dies ist die Größe des Speicherpools, der zur Aufzeichnung der in einer Transaktion verwendeten Dateinamen verwendet wird. Wurde in MySQL 5.1.2 hinzugefügt.
bdb_shared_data
Ist ON
, wenn Sie Berkeley DB mithilfe von --bdb-shared-data
im Multiprozessmodus starten. (Verwenden Sie DB_PRIVATE
nicht bei der Initialisierung von Berkeley DB.)
bdb_tmpdir
Gibt das Verzeichnis für BDB
-Temporärdateien an.
binlog_cache_size
Gibt die Größe des Caches an, der die SQL-Anweisungen für das Binärlog während einer Transaktion aufnimmt. Ein Binärlog-Cache wird jedem Client zugewiesen, wenn der Server transaktionssichere Speicher-Engines unterstützt und an ihm das Binärlog aktiviert ist (Option --log-bin
). Wenn Sie häufig umfangreiche, aus mehreren Anweisungen bestehende Transaktionen verwenden, können Sie diese Cachegröße erhöhen, um mehr Leistung zu erzielen. Die Statusvariablen Binlog_cache_use
und Binlog_cache_disk_use
können für die Optimierung dieser Variable nützlich sein. Siehe auch Abschnitt 5.12.3, „Die binäre Update-Logdatei“.
binlog_format
Das Binärlogformat (entweder STATEMENT
oder ROW
). Diese Variable wird von der Option --binlog-format
eingestellt. Siehe auch Abschnitt 6.3, „Zeilenbasierte Replikation“.
bulk_insert_buffer_size
MyISAM
verwendet einen speziellen Cache mit Baumstruktur, um Masseneinfügeoperation für INSERT ... SELECT
, INSERT ... VALUES (...), (...), ...
und LOAD DATA INFILE
beim Hinzufügen von Daten in nicht leere Tabellen zu beschleunigen. Diese Variable beschränkt die Größe der Cachebaumstruktur und ist in Byte pro Thread angegeben. Die Einstellung 0 deaktiviert diese Optimierung. Der Vorgabewert ist 8 Mbyte.
character_set_client
Der Zeichensatz für Anweisungen, die vom Client kommend eintreffen.
character_set_connection
Der Zeichensatz für Literale, die keine Zeichensatzeinführung aufweisen, und für die Umwandlung von Zahlen in Strings.
character_set_database
Der von der Standarddatenbank verwendete Zeichensatz. Der Server stellt diese Variable immer dann ein, wenn die Standarddatenbank sich ändert. Ist keine Standarddatenbank vorhanden, dann hat die Variable denselben Wert wie character_set_server
.
character_set_filesystem
Der Zeichensatz des Dateisystems. Der Vorgabewert ist binary
. Diese Variable wurde in MySQL 5.1.6 hinzugefügt.
character_set_results
Der zur Rückgabe von Abfrageergebnissen an den Client verwendete Zeichensatz.
character_set_server
Der Standardzeichensatz des Servers.
character_set_system
Der vom Server zur Speicherung von Bezeichnern verwendete Zeichensatz. Der Wert ist immer utf8
.
character_sets_dir
Das Verzeichnis, in dem Zeichensätze installiert sind.
collation_connection
Die Sortierung des Verbindungszeichensatzes.
collation_database
Die von der Standarddatenbank verwendete Sortierung. Der Server stellt diese Variable immer dann ein, wenn die Standarddatenbank sich ändert. Ist keine Standarddatenbank vorhanden, dann hat die Variable denselben Wert wie collation_server
.
collation_server
Die Standardsortierung des Servers.
completion_type
Der Transaktionsabschlusstyp:
Wenn der Wert 0 ist (Standardeinstellung), werden COMMIT
und ROLLBACK
nicht beeinflusst.
Ist der Wert 1, dann sind COMMIT
und ROLLBACK
äquivalent zu COMMIT AND CHAIN
bzw. ROLLBACK AND CHAIN
. (Eine neue Transaktion wird mit derselben Isolierungsstufe gestartet wie die unmittelbar zuvor beendete Transaktion.)
Ist der Wert 2, dann sind COMMIT
und ROLLBACK
äquivalent zu COMMIT RELEASE
bzw. ROLLBACK RELEASE
. (Der Server trennt die Verbindung nach Abschluss der Transaktion.)
concurrent_insert
Wenn die Variable den Wert ON
hat (Standardeinstellung), gestattet MySQL die nebenläufige Ausführung von INSERT
- und SELECT
-Anweisungen für MyISAM
-Tabellen, die in der Mitte keine freien Blöcke aufweisen. Sie können diese Option deaktivieren, indem Sie mysqld mit --safe
oder --skip-new
starten.
Diese Variable kann drei ganzzahlige Werte annehmen:
Wert | Beschreibung |
0 | Die Funktion ist deaktiviert. |
1 | Dies ist die Standardeinstellung. Sie aktiviert nebenläufige Einfügeoperationen für MyISAM -Tabellen, die keine Lücken aufweisen. |
2 | Dieser Wert aktiviert nebenläufige Einfügeoperationen für alle MyISAM -Tabellen. Wenn eine Tabelle eine Lücke aufweist und gerade von einem anderen Thread verwendet wird, wird der neue Datensatz am Tabellenende eingefügt. Wird die Tabelle gerade nicht verwendet, dann setzt MySQL eine normale Lesesperre und fügt den neuen Datensatz in die Lücke ein. |
Siehe auch Abschnitt 7.3.3, „Gleichzeitige Einfügevorgänge“.
Zeit in Sekunden, während der der mysqld-Server auf ein Verbindungspaket wartet, bevor er mit der Meldung Bad handshake
antwortet.
datadir
Das MySQL-Datenverzeichnis. Die Variable kann mit der Option --datadir
eingestellt werden.
date_format
Diese Variable ist nicht implementiert.
datetime_format
Diese Variable ist nicht implementiert.
default_week_format
Standardmoduswert für die Funktion WEEK()
. Siehe auch Abschnitt 12.5, „Datums- und Zeitfunktionen“.
delay_key_write
Diese Option gilt nur für MyISAM
-Tabellen. Sie kann einen der folgenden Werte annehmen und beeinflusst hierdurch die Wirkung der Tabellenoption DELAY_KEY_WRITE
, die in CREATE TABLE
-Anweisungen verwendet werden kann.
Option | Beschreibung |
OFF | DELAY_KEY_WRITE wird ignoriert. |
ON | MySQL beachtet alle DELAY_KEY_WRITE -Optionen, die in CREATE TABLE -Anweisungen angegeben sind. Dies ist der Standardwert. |
ALL | Alle neu geöffneten Tabellen werden so behandelt, als ob sie mit aktivierter Option DELAY_KEY_WRITE erstellt worden wären. |
Wenn DELAY_KEY_WRITE
für eine Tabelle aktiviert ist, wird der Schlüsselpuffer der Tabelle nicht bei jeder Indexaktualisierung, sondern nur dann neu geschrieben, wenn die Tabelle geschlossen wird. Hierdurch werden Schreiboperationen für Schlüssel erheblich beschleunigt. Wenn Sie diese Funktion nutzen, sollten Sie jedoch eine automatische Überprüfung aller MyISAM
-Tabellen ergänzen, indem Sie den Server mit der Option --myisam-recover
starten (beispielsweise --myisam-recover=BACKUP,FORCE
). Siehe auch Abschnitt 5.2.1, „Befehlsoptionen für mysqld“, und Abschnitt 14.1.1, „MyISAM
-Startoptionen“.
Beachten Sie, dass die Aktivierung der externen Sperrung mit --external-locking
keinen Schutz gegen die Beschädigung von Indizes gewährleistet, deren Tabellen das verzögerte Schreiben von Schlüsseln verwenden.
delayed_insert_limit
Nach dem Einfügen von mit delayed_insert_limit
verzögerten Datensätzen überprüft der Handler INSERT DELAYED
, ob noch SELECT
-Anweisungen ausstehen. Ist dies der Fall, dann gestattet er deren Ausführung, bevor er mit dem Einfügen verzögerter Datensätze fortfährt.
delayed_insert_timeout
Gibt an, wie viele Sekunden ein INSERT DELAYED
-Handler auf INSERT
-Anweisungen warten soll, bevor er beendet wird.
delayed_queue_size
Dies ist eine tabellenspezifische Beschränkung der Anzahl von Datensätze, die bei der Verarbeitung von INSERT DELAYED
-Anweisungen in der Warteschlange stehen dürfen. Wenn die Warteschlange voll wird, wartet jeder Client mit dem Absetzen einer INSERT DELAYED
-Anweisung, bis wieder Platz in der Warteschlange ist.
div_precision_increment
Diese Variable gibt die Anzahl der Präzisionsstellen an, um die das Ergebnis von Divisionsoperationen mit dem Operator /
erweitert werden soll. Der Standardwert ist 4, der Mindestwert 0 und der Höchstwert 30. Das folgende Beispiel veranschaulicht die Wirkung einer Erhöhung des Standardwertes.
mysql>SELECT 1/7;
+--------+ | 1/7 | +--------+ | 0.1429 | +--------+ mysql>SET div_precision_increment = 12;
mysql>SELECT 1/7;
+----------------+ | 1/7 | +----------------+ | 0.142857142857 | +----------------+
event_scheduler
Gibt an, ob der Ereignisplaner aktiviert oder deaktiviert ist. Standardmäßig ist der Planer deaktiviert. Diese Variable wurde in MySQL 5.1.6 hinzugefügt.
engine_condition_pushdown
Diese Variable betrifft NDB. Der Standardwert ist 0 (deaktiviert): Wenn Sie eine Abfrage wie SELECT * FROM t WHERE mycol = 42
ausführen, wobei mycol
eine nicht indizierte Spalte ist, dann wird die Abfrage als vollständiger Tabellenscan an jedem NDB-Knoten durchgeführt. Jeder Knoten sendet jeden Datensatz an den MySQL-Server, auf dem dann die WHERE
-Bedingung angewendet wird. Ist engine_condition_pushdown
auf 1 gesetzt (aktiviert), dann wird die Bedingung an die Speicher-Engine „zurückverwiesen“ und an die NDB-Knoten gesendet. Jeder Knoten führt dann den Scan unter Anwendung der Bedingung durch und sendet nur diejenigen Datensätze an den MySQL-Server zurück, bei denen eine Übereinstimmung vorliegt.
expire_logs_days
Die Anzahl der Tage, nach denen Binärlogs automatisch entfernt werden. Der Standardwert ist 0, d. h. es erfolgt keine automatische Entfernung. Sofern Logs entfernt werden, erfolgt dies beim Start sowie bei der Binärlogrotation.
flush
Wenn aktiviert, schreibt der Server nach jeder SQL-Anweisung alle Änderungen neu auf die Festplatte (Synchronisierung). Normalerweise schreibt MySQL alle Änderungen erst nach der jeweiligen SQL-Anweisung auf die Festplatte und überlässt dem Betriebssystem die Festplattensynchronisierung. Siehe auch Abschnitt A.4.2, „Was zu tun ist, wenn MySQL andauernd abstürzt“. Diese Variable ist aktiviert, wenn Sie mysqld mit der Option --flush
starten.
flush_time
Hat diese Variable einen Wert ungleich Null, dann werden alle Tabellen nach Verstreichen des durch flush_time
(in Sekunden) angegebenen Zeitraums geschlossen, um Ressourcen freizugeben und nicht geschriebene Daten auf die Festplatte zu synchronisieren. Wir empfehlen die Verwendung dieser Option lediglich unter Windows 9x/Me und auf Systemen mit nur minimalen Ressourcen.
ft_boolean_syntax
Die Liste der Operatoren, die bei mit der Option IN BOOLEAN MODE
durchgeführter Volltextsuche unterstützt werden. Siehe auch Abschnitt 12.7.1, „Boolesche Volltextsuche“.
Vorgabe ist '+
-><()~*:""&|'
. Es gelten folgende Regeln zur Änderung des Wertes:
Die Operatorfunktion wird durch die Position innerhalb des Strings bestimmt.
Der Ersetzungswert muss 14 Zeichen umfassen.
Jedes Zeichen muss ein ASCII-konformes, nicht alphanumerisches Zeichen sein.
Das erste oder zweite Zeichen muss ein Leerzeichen sein.
Mit Ausnahme der Anführungszeichen für Phrasen an den Positionen 11 und 12 sind Duplikate unzulässig. Die beiden Anführungszeichen müssen nicht identisch sein, dürfen es jedoch als einzige.
Die Positionen 10, 13 und 14 (Standardeinstellungen: ‘:
’, ‘&
’ und ‘|
’) sind für zukünftige Erweiterungen vorgesehen.
ft_max_word_len
Die maximale Länge des Wortes, das in einem FULLTEXT
-Index enthalten sein darf.
Hinweis: Wenn Sie diese Variable ändern, müssen Sie FULLTEXT
-Indizes neu erstellen. Verwenden Sie REPAIR TABLE
.
tbl_name
QUICK
ft_min_word_len
Die minimale Länge des Wortes, das in einem FULLTEXT
-Index enthalten sein darf.
Hinweis: Wenn Sie diese Variable ändern, müssen Sie FULLTEXT
-Indizes neu erstellen. Verwenden Sie REPAIR TABLE
.
tbl_name
QUICK
ft_query_expansion_limit
Die Anzahl der obersten zu verwendenden Übereinstimmungen, die bei einer mit WITH QUERY EXPANSION
ausgeführten Volltextsuche verwendet werden.
ft_stopword_file
Datei, aus der die Liste der Stoppwörter für die Volltextsuche ausgelesen wird. Es werden alle Wörter aus der Datei verwendet; Kommentare hingegen werden nicht berücksichtigt. Standardmäßig wird eine eingebaute Liste mit Stoppwörtern (wie in der Datei myisam/ft_static.c
definiert) verwendet. Wenn Sie die Variable auf den Leer-String setzen (''
), wird die Ausfilterung von Stoppwörtern deaktiviert.
Hinweis: Wenn Sie diese Variable ändern oder den Inhalt der Stoppwortdatei ändern, müssen die FULLTEXT
-Indizes neu erstellt werden. Verwenden Sie REPAIR TABLE
.
tbl_name
QUICK
group_concat_max_len
Die maximal zulässige Ergebnislänge der Funktion GROUP_CONCAT()
. Der Standardwert ist 1.024.
have_archive
YES
, wenn mysqld ARCHIVE
-Tabellen unterstützt, andernfalls NO
.
have_bdb
YES
, wenn mysqld BDB
-Tabellen unterstützt. DISABLED
, wenn --skip-bdb
verwendet wird.
have_blackhole_engine
YES
, wenn mysqld BLACKHOLE
-Tabellen unterstützt, andernfalls NO
.
have_compress
YES
, wenn die Komprimierungsbibliothek zlib
auf dem Server verfügbar ist, andernfalls NO
. In diesem Fall können die Funktionen COMPRESS()
und UNCOMPRESS()
nicht verwendet werden.
have_crypt
YES
, wenn der Systemaufruf crypt()
auf dem Server verfügbar ist, andernfalls NO
. In diesem Fall kann die Funktion ENCRYPT()
nicht verwendet werden.
have_csv
YES
, wenn mysqld ARCHIVE
-Tabellen unterstützt, andernfalls NO
.
have_example_engine
YES
, wenn mysqld EXAMPLE
-Tabellen unterstützt, andernfalls NO
.
have_federated_engine
YES
, wenn mysqld FEDERATED
-Tabellen unterstützt, andernfalls NO
.
have_geometry
YES
, wenn der Server raumbezogene Datentypen unterstützt, andernfalls NO
.
have_innodb
YES
, wenn mysqld InnoDB
-Tabellen unterstützt. DISABLED
, wenn --skip-innodb
verwendet wird.
have_isam
In MySQL 5.1 ist diese Variable nur aus Gründen der Abwärtskompatibilität vorhanden. Sie hat immer den Wert NO
, da ISAM
nicht mehr unterstützt werden.
have_ndbcluster
YES
, wenn mysqld NDB Cluster
-Tabellen unterstützt. DISABLED
, wenn --skip-ndbcluster
verwendet wird.
have_partitioning
YES
, wenn mysqld die Partitionierung unterstützt. Wurde in MySQL 5.1.1 als have_partition_engine
hinzugefügt und in 5.1.6 in have_partioning
umbenannt.
have_openssl
YES
, wenn mysqld eine SSL-Verschlüsselung des Client/Server-Protokolls unterstützt, andernfalls NO
.
have_query_cache
YES
, wenn mysqld den Abfrage-Cache unterstützt, andernfalls NO
.
have_raid
YES
, wenn mysqld die Option RAID
unterstützt, andernfalls NO
.
have_row_based_replication
YES
, wenn der Server die Replikation unter Verwendung datensatzbasierten Binärloggens durchführen kann. Wenn der Wert NO
ist, kann der Server nur anweisungsbasiertes Loggen durchführen. Siehe auch Abschnitt 6.3, „Zeilenbasierte Replikation“. Diese Variable wurde in MySQL 5.1.5 hinzugefügt.
have_rtree_keys
YES
, wenn RTREE
-Indizes verfügbar sind, andernfalls NO
. (Diese werden für raumbezogene Indizes in MyISAM
-Tabellen verwendet.)
have_symlink
YES
, wenn die Unterstützung für symbolische Verknüpfungen aktiviert ist, andernfalls NO
. Diese ist unter Unix für die Unterstützung der Tabellenoptionen DATA DIRECTORY
und INDEX DIRECTORY
und unter Windows für die Unterstützung von symbolischen Verknüpfungen mit Datenverzeichnissen erforderlich.
init_connect
Ein String, der vom Server immer dann ausgeführt wird, wenn ein Client eine Verbindung herstellt. Der String besteht aus einer oder mehreren SQL-Anweisungen. Wenn Sie mehrere Anweisungen angeben wollen, trennen Sie sie durch Semikola. So beginnt beispielsweise jeder Client bei einer Verbindung mit aktiviertem Autocommit-Modus. Es gibt keine globale Systemvariable, mit der festgelegt werden kann, dass Autocommit standardmäßig deaktiviert werden soll; mithilfe von init_connect
aber können Sie genau dies realisieren:
SET GLOBAL init_connect='SET AUTOCOMMIT=0';
Diese Variable können Sie sowohl über die Befehlszeile als auch in einer Optionsdatei einstellen. Wenn Sie die Variable wie gezeigt in einer Optionsdatei einstellen wollen, ergänzen Sie die folgenden Zeilen:
[mysqld] init_connect='SET AUTOCOMMIT=0'
Beachten Sie, dass der Inhalt von init_connect
nicht für Benutzer ausgeführt wird, die die Berechtigung SUPER
haben. Zweck dieser Maßnahme ist es zu verhindern, dass ein fehlerhafter Wert für init_connect
eine Verbindung zum System für alle Benutzer unmöglich macht. Wenn der Wert etwa eine Anweisung mit einem Syntaxfehler enthält, dann könnte dieser dazu führen, dass sich die Clients nicht mehr anmelden können. Da init_connect
für Benutzer mit der Berechtigung SUPER
nicht ausgeführt wird, können diese eine Verbindung herstellen und den Wert von init_connect
korrigieren.
init_file
Der Name der beim Serverstart mit der Option --init-file
angegebenen Datei. Es sollte sich hierbei um eine Datei mit SQL-Anweisungen handeln, die der Server beim Start ausführen soll. Jede Anweisung muss in einer eigenen Zeile stehen und darf keine Kommentare enthalten.
init_slave
Diese Variable ähnelt init_connect
, es handelt sich hierbei aber um einen String, der von einem Slave-Server jedes Mal dann ausgeführt wird, wenn der SQL-Thread startet. Das Format des Strings ist identisch mit dem der Variable init_connect
.
innodb_
xxx
InnoDB
-Systemvariablen werden in Abschnitt 14.2.4, „InnoDB
: Startoptionen und Systemvariablen“ beschrieben.
interactive_timeout
Zeit in Sekunden, während der der Server bei einer interaktiven Verbindung auf Aktivitäten wartet, bevor er sie schließt. Ein interaktiver Client ist als Client definiert, der die Option CLIENT_INTERACTIVE
für mysql_real_connect()
verwendet. Siehe auch wait_timeout
.
join_buffer_size
Die Größe des Puffers, der für Joins benutzt wird, die keine Indizes verwenden und deswegen vollständige Tabellenscans durchführen. Normalerweise besteht die beste Möglichkeit der Realisierung schneller Joins darin, Indizes hinzuzufügen. Erhöhen Sie den Wert von join_buffer_size
, um einen schnelleren vollständigen Join zu implementieren, wenn das Hinzufügen von Indizes nicht möglich ist. Für jeden vollständigen Join zwischen zwei Tabellen wird ein Join-Puffer hinzugefügt. Für einen komplexen Join zwischen mehreren Tabellen, für den Indizes nicht verwendet werden, sind unter Umständen mehrere Join-Puffer erforderlich.
Indexblöcke für MyISAM
-Tabellen werden gepuffert und von allen Threads gemeinsam verwendet. key_buffer_size
ist die Größe des für die Indexblöcke verwendeten Puffers. Der Schlüsselpuffer heißt auch Schlüssel-Cache.
Die maximal zulässige Größe für key_buffer_size
beträgt 4 Gbyte. Das effektive Limit kann abhängig davon, wie viel physisches RAM vorhanden ist und welche RAM-spezifischen Grenzwerte je Prozess unter Ihrem Betriebssystem bzw. auf Ihrer Hardwareplattform gelten, niedriger liegen.
Wenn Sie die Indexverwaltung (für Lese- und mehrfachen Schreiboperationen) optimieren wollen, erhöhen Sie diesen Wert so weit wie möglich. Ein Wert von 25 Prozent des gesamten Speichers auf einem System, auf dem hauptsächlich MySQL läuft, ist durchaus normal. Wenn Sie den Wert jedoch zu hoch (beispielsweise auf mehr als 50 Prozent Ihres gesamten Speichers) setzen, wird Ihr System Daten auslagern und so extrem langsam werden. Zur Durchführung des Dateisystem-Cachings für Datenleseoperationen ist MySQL auf das Betriebssystem angewiesen, d. h. Sie müssen ein wenig Platz für den Dateisystem-Cache lassen. Außerdem müssen Sie die Speicheranforderungen anderer Speicher-Engines berücksichtigen.
Um eine noch höhere Geschwindigkeit beim Schreiben vieler Datensätze zur gleichen Zeit zu erzielen, verwenden Sie LOCK TABLES
. Siehe auch Abschnitt 7.2.16, „Geschwindigkeit von INSERT
-Anweisungen“.
Sie können die Leistung des Schlüsselpuffers durch Absetzen einer SHOW STATUS
-Anweisung und Überprüfung der Statusvariablen Key_read_requests
, Key_reads
, Key_write_requests
und Key_writes
verifizieren. (Siehe auch Abschnitt 13.5.4, „SHOW
“.) Das Verhältnis von Key_reads
zu Key_read_requests
sollte möglichst kleiner als 0,01 sein. Das Key_writes/Key_write_requests
-Verhältnis hat normalerweise einen Wert von knapp 1, wenn Sie in erster Linie Aktualisierungs- und Löschvorgänge durchführen, kann aber wesentlich kleiner sein, wenn Sie entweder häufig Updates ausführen, die zahlreiche Datensätze gleichzeitig betreffen, oder die Tabellenoption DELAY_KEY_WRITE
verwenden.
Der Anteil des verwendeten Schlüsselpuffers kann mithilfe von key_buffer_size
in Verbindung mit der Statusvariablen Key_blocks_unused
und der Pufferblockgröße bestimmt werden, die über die Systemvariable key_cache_block_size
verfügbar ist:
1 - ((Key_blocks_unused × key_cache_block_size) / key_buffer_size)
Dies ist lediglich ein Näherungswert, weil ein Teil des Schlüsselpuffers möglicherweise intern für Verwaltungsstrukturen reserviert ist.
Sie können mehrere MyISAM
-Schlüssel-Caches erstellen. Die Größenbeschränkung von 4 Gbyte gilt für jeden einzelnen Cache, nicht für die Summe aller Caches. Siehe auch Abschnitt 7.4.6, „Der MyISAM
-Schlüssel-Cache“.
key_cache_age_threshold
Dieser Wert steuert die Herabstufung von Puffern aus der heißen Unterkette eines Schlüssel-Caches in eine warme Unterkette. Niedrige Werte führen dazu, dass diese Herabstufung schneller erfolgt. Der minimale Wert ist 100, der Vorgabewert 300. Siehe auch Abschnitt 7.4.6, „Der MyISAM
-Schlüssel-Cache“.
key_cache_block_size
Größe der Blocks im Schlüssel-Cache in Byte. Der Standardwert ist 1.024. Siehe auch Abschnitt 7.4.6, „Der MyISAM
-Schlüssel-Cache“.
key_cache_division_limit
Der Trennpunkt zwischen heißen und warmen Unterketten der Schlüssel-Cache-Pufferkette. Der Wert gibt den Anteil der Pufferkette, die für die warme Unterkette benutzt wird, prozentual an. Der zulässige Wertebereich liegt zwischen 1 und 100, Vorgabewert ist 100. Siehe auch Abschnitt 7.4.6, „Der MyISAM
-Schlüssel-Cache“.
language
Sprache, in der Fehlermeldungen ausgegeben werden.
large_file_support
Gibt an, ob mysqld mit Optionen zur Unterstützung großer Dateien kompiliert wurde.
large_pages
Gibt an, ob die Unterstützung großer Seiten aktiviert wurde.
license
Der Lizenztyp des Servers.
local_infile
Gibt an, ob LOCAL
für LOAD DATA INFILE
-Anweisungen unterstützt wird. Siehe auch Abschnitt 5.7.4, „Sicherheitsprobleme mit LOAD DATA LOCAL
“.
locked_in_memory
Gibt an, ob mysqld mit der Option --memlock
im Speicher gesperrt wurde.
log
Gibt an, ob das Loggen aller Anweisungen im allgemeinen Abfragelog aktiviert wurde Siehe auch Abschnitt 5.12.2, „Die allgemeine Anfragen-Logdatei“.
log_bin
Gibt an, ob das Binärlog aktiviert wurde. Siehe auch Abschnitt 5.12.3, „Die binäre Update-Logdatei“.
log_bin_trust_function_creators
Diese Variable wird angewendet, wenn das binäre Loggen aktiviert ist. Sie steuert, ob die Ersteller gespeicherter Funktionen vertrauenswürdig sind, keine gespeicherten Funktionen zu erstellen, die das Schreiben unsicherer Ereignisse in das Binärlog bewirken könnten. Wenn die Variable den Wert 0 hat (Standardeinstellung), dann dürfen Benutzer gespeicherte Routinen nur dann erstellen oder ändern, wenn sie zusätzlich zu den Berechtigungen CREATE ROUTINE
oder ALTER ROUTINE
die Berechtigung SUPER
haben. Die Einstellung 0 implementiert auch eine Beschränkung, dass eine Funktion mit der Eigenschaft DETERMINISTIC
, der Eigenschaft READS SQL DATA
oder der Eigenschaft NO SQL
deklariert werden muss. Hat die Variable den Wert 1, dann setzt MySQL diese Beschränkungen bei der Erstellung gespeicherter Funktionen nicht durch. Siehe auch Abschnitt 19.4, „Binärloggen gespeicherter Routinen und Trigger“.
log_error
Die Position des Fehlerlogs.
log_slave_updates
Gibt an, ob Updates, die ein Slave-Server von einem Master-Server empfängt, im eigenen Binärlog des Slave-Servers aufgezeichnet werden sollen. Damit diese Variable Wirkung zeigt, muss das binäre Loggen am Slave aktiviert sein. Siehe auch Abschnitt 6.9, „Replikationsoptionen in my.cnf“.
log_slow_queries
Gibt an, ob langsame Abfragen protokolliert werden sollen. „Langsam“ wird hierbei durch den Wert der Variable long_query_time
bestimmt. Siehe auch Abschnitt 5.12.4, „Die Logdatei für langsame Anfragen“.
log_warnings
Gibt an, ob zusätzliche Warnmeldungen erzeugt werden sollen. Die Funktion ist standardmäßig aktiviert. Unterbrochene Verbindungen werden nicht in das Fehlerlog protokolliert, sofern der Wert größer als 1 ist.
long_query_time
Wenn eine Abfrage länger dauert als durch diese Variable (in Sekunden) angegeben, erhöht der Server die Statusvariable Slow_queries
entsprechend. Wenn Sie die Option --log-slow-queries
verwenden, wird die Abfrage in der Logdatei für langsame Abfragen protokolliert. Dieser Wert wird als Echtzeit (nicht als Prozessorzeit) gemessen, d. h. eine Abfrage, die bei einem System mit geringer Belastung den Schwellwert unterschreitet, kann bei einem stark belasteten System bereits darüber liegen. Der Mindestwert ist 1. Siehe auch Abschnitt 5.12.4, „Die Logdatei für langsame Anfragen“.
low_priority_updates
Wenn diese Variable den Wert 1
hat, warten alle INSERT
-, UPDATE
-, DELETE
- und LOCK TABLE WRITE
-Anweisungen, bis keine SELECT
- oder LOCK TABLE READ
-Anweisungen für die betreffende Tabelle mehr anhängig sind. Diese Variable hieß früher sql_low_priority_updates
.
lower_case_file_system
Diese Variable beschreibt die Auswirkungen der Groß-/Kleinschreibung auf dem Dateisystem, auf dem sich das Datenverzeichnis befindet. OFF
bedeutet, dass die Groß-/Kleinschreibung bei Dateinamen unterschieden wird, bei ON
ist dies nicht der Fall.
lower_case_table_names
Hat die Variable den Wert 1, dann werden Tabellennamen in Kleinschreibung auf der Festplatte gespeichert. Vergleiche von Tabellennamen werden dann nicht durch unterschiedliche Groß-/Kleinschreibung beeinträchtigt. Der Wert 2 führt zu einer Speicherung der Tabellennamen in der eingegebenen Form, Vergleiche erfolgen aber stets in Kleinschreibung. Diese Option gilt auch für Datenbanknamen und Tabellenaliase. Siehe auch Abschnitt 9.2.2, „Groß-/Kleinschreibung in Namen“.
Wenn Sie InnoDB
-Tabellen verwenden, sollten Sie diese Variable auf allen Plattformen auf 1 setzen. Hiermit wird die Konvertierung von Namen in die Kleinschreibung erzwungen.
Sie sollten diese Variable keinesfalls auf 0 setzen, wenn Sie MySQL auf einem System ausführen, bei dem die Groß-/Kleinschreibung von Dateinamen nicht unterschieden wird (dies betrifft etwa Windows oder Mac OS X). Wird diese Variable beim Start nicht eingestellt und unterscheidet das Dateisystem, auf dem sich das Datenverzeichnis befindet, keine Groß-/Kleinschreibung bei Dateinamen, dann stellt MySQL lower_case_table_names
automatisch auf 2.
max_allowed_packet
Die maximale Größe eines Pakets oder eines erzeugten oder temporären Strings.
Der Paketmeldungspuffer wird mit net_buffer_length
Bytes initialisiert, kann aber bei Bedarf auf bis zu max_allowed_packet
Bytes anwachsen. Dieser Wert ist standardmäßig niedrig, damit große (und möglicherweise falsche) Pakete abgefangen werden.
Wenn Sie große BLOB
-Spalten oder lange Strings verwenden, müssen Sie ihn erhöhen. Es sollte so groß sein wie das größte BLOB
, das Sie verwenden wollen. Das Protokolllimit für max_allowed_packet
beträgt 1Gbyte.
max_binlog_cache_size
Wenn eine Transaktion mit mehreren Anweisungen mehr Speicher benötigt als hier angegeben, dann erzeugt der Server die Fehlermeldung Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage
.
max_binlog_size
Wenn eine Schreiboperation in das Binärlog bewirkt, dass die aktuelle Größe der Logdatei den Wert dieser Variable überschreitet, dann führt der Server eine Rotation der Binärlogs durch (d. h. er schließt die aktuelle Datei und öffnet die nächste). Sie können diese Variable nur auf einen Wert im Bereich zwischen 4096 Bytes und 1 Gbyte setzen. Der Vorgabewert ist 1 Gbyte.
Eine Transaktion wird am Stück in das Binärlog geschrieben, kann also niemals auf mehrere Binärlogs verteilt werden. Deswegen kann es vorkommen, dass, wenn Transaktionen sehr groß sind, Binärlogs am Ende größer sind als mit max_binlog_size
angegeben.
Wenn max_relay_log_size
0 ist, gilt der Wert von max_binlog_size
auch für Relay-Logdateien.
max_connect_errors
Wenn die Anzahl unterbrochener Verbindungen zu einem Host höher liegt als durch diese Variable angegeben, dann werden weitere Verbindungen für diesen Host gesperrt. Diese Sperrung von Hosts können Sie mit FLUSH HOSTS
aufheben.
max_connections
Die zulässige Anzahl nebenläufiger Clientverbindungen. Wenn Sie diesen Wert erhöhen, erhöht sich auch die Anzahl der Dateideskriptoren, die mysqld benötigt. Anmerkungen zu Grenzwerten für Dateideskriptoren finden Sie in Abschnitt 7.4.8, „Nachteile der Erzeugung großer Mengen von Tabellen in derselben
Datenbank“. Siehe auch Abschnitt A.2.6, „Too many connections
-Fehler“.
max_delayed_threads
Maximale Anzahl von Threads, die zur Verarbeitung von INSERT DELAYED
-Anweisungen gestartet werden dürfen. Wenn Sie versuchen, Daten in eine neue Tabelle einzufügen, während alle INSERT DELAYED
-Threads gerade verwendet werden, dann wird der Datensatz so eingefügt, als ob das Attribut DELAYED
nicht angegeben worden wäre. Wenn Sie hier den Wert 0 angeben, erstellt MySQL in keinem Fall einen Thread zur Verarbeitung von DELAYED
-Datensätzen; im Endeffekt bedeutet dies eine vollständige Deaktivierung von DELAYED
.
max_error_count
Die maximale Anzahl von Fehlermeldungen, Warnungen und Hinweisen, die mit SHOW ERRORS
- und SHOW WARNINGS
-Anweisungen zur Anzeige gespeichert werden.
max_heap_table_size
Diese Variable bestimmt die maximale Größe, auf die MEMORY
-Tabellen anwachsen dürfen. Der Wert der Variable wird zur Berechnung von MAX_ROWS
-Werte für MEMORY
-Tabellen verwendet. Die Einstellung der Variable hat keine Auswirkungen auf bereits vorhandene MEMORY
-Tabellen, sofern diese nicht mit einer Anweisung wie CREATE TABLE
neu erstellt oder mit ALTER TABLE
oder TRUNCATE TABLE
modifiziert werden.
max_insert_delayed_threads
Diese Variable ist synonym zu max_delayed_threads
.
max_join_size
Ermöglicht das Unterbinden von SELECT
-Anweisungen, die unter Umständen eine größere Anzahl von Datensätzen (bei Anweisungen für eine Tabelle) oder Datensatzkombinationen (bei Anweisungen für mehrere Tabellen) untersuchen müssen als durch max_join_size
angegeben. Ebenfalls unterbunden werden SELECT
-Anweisungen, bei denen mehr Festplattenzugriffe erfolgen würden als durch max_join_size
angegeben. Durch Einstellen dieses Wertes können Sie SELECT
-Anweisungen abfangen, bei denen Schlüssel nicht korrekt verwendet wurden und deren Verarbeitung wahrscheinlich sehr lange dauern würde. Nehmen Sie diese Einstellung vor, wenn Ihre Benutzer dazu neigen, Joins durchzuführen, bei denen entweder eine WHERE
-Klausel fehlt oder die sehr lange dauern oder mehrere Millionen Datensätze zurückgeben könnten.
Wenn Sie die Variable auf einen anderen Wert als DEFAULT
setzen, wird der Wert von SQL_BIG_SELECTS
auf 0
zurückgesetzt. Stellen Sie den Wert von SQL_BIG_SELECTS
erneut ein, dann wird die Variable max_join_size
ignoriert.
Befindet sich ein Abfrageergebnis im Abfrage-Cache, dann wird keine Überprüfung der Ergebnisgröße durchgeführt, weil das Ergebnis zuvor bereits berechnet wurde und der Server durch den Versand des Ergebnisses nicht belastet würde.
Diese Variable hieß früher sql_max_join_size
.
max_length_for_sort_data
Die Teilungsgröße bei Indexwerten. Sie bestimmt, welcher filesort
-Algorithmus verwendet werden soll. Siehe auch Abschnitt 7.2.12, „ORDER BY
-Optimierung“.
max_relay_log_size
Wenn eine Schreiboperation durch einen Replikations-Slave in seine Relay-Logdatei bewirkt, dass die aktuelle Größe der Logdatei den Wert dieser Variable überschreitet, dann führt der Slave eine Rotation der Relay-Logs durch (d. h. er schließt die aktuelle Datei und öffnet die nächste). Wenn max_relay_log_size
0 ist, verwendet der Server max_binlog_size
sowohl für das Binär- als auch für das Relay-Log. Ist max_relay_log_size
größer als 0, dann wird hierdurch die Größe des Relay-Logs beschränkt. Dies ermöglicht Ihnen die Konfiguration unterschiedlicher Größen für die beiden Logdateien. Sie müssen max_relay_log_size
auf einen Wert zwischen 4.096 Bytes und 1 Gbyte (jeweils einschließlich) oder auf 0 setzen. Der Standardwert ist 0. Siehe auch Abschnitt 6.4, „Replikation: Implementationsdetails“.
max_seeks_for_key
Beschränkt die voraussichtliche Anzahl von Festplattenzugriffen beim schlüsselbasierten Suchen nach Datensätzen. Der MySQL-Optimierer geht davon aus, dass nicht mehr als die hier angegebene Anzahl von Schlüsselsuchvorgängen bei der Suche nach passenden Datensätzen in einer Tabelle durch einen Indexscan erforderlich ist (und zwar unabhängig von der tatsächlichen Kardinalität des Index; siehe auch Abschnitt 13.5.4.12, „SHOW INDEX
“). Durch Einstellen eines niedrigen Wertes (z. B. 100) können Sie MySQL dazu zwingen, Indizes statt Tabellenscans zu bevorzugen.
max_sort_length
Die bei der Sortierung von BLOB
- oder TEXT
-Werten zu verwendende Anzahl von Bytes. Nur die ersten max_sort_length
Bytes jedes Wertes werden berücksichtigt; der Rest wird ignoriert.
max_tmp_tables
Die maximale Anzahl temporärer Tabellen, die ein Client zur selben Zeit offen halten darf. (Diese Option hat derzeit noch keine Auswirkungen.)
max_user_connections
Die maximale Anzahl gleichzeitiger Verbindungen zu einem gegebenen MySQL-Konto. Der Wert 0 hat die Bedeutung „unbeschränkt“.
Diese Variable hat sowohl einen globalen als auch einen (schreibgeschützten) sitzungsbezogenen Geltungsbereich. Die Sitzungsvariable hat denselben Wert wie die globale Variable, sofern das aktuelle Konto nicht eine MAX_USER_CONNECTIONS
-Ressourcenbeschränkung ungleich Null hat. In diesem Fall beschreibt der Sitzungswert die kontenbezogene Beschränkung.
max_write_lock_count
Nach Verstreichen der hier angegebenen Anzahl von Schreibsperren muss zunächst einmal eine Anzahl anhängiger Anforderungen für Lesesperren verarbeitet werden.
myisam_data_pointer_size
Die Standardgröße (in Byte) des Zeigers, der von CREATE TABLE
für MyISAM
-Tabellen verwendet wird, wenn die Option MAX_ROWS
nicht angegeben ist. Der Variablenwert muss zwischen 2 und 7 liegen, der Standardwert ist 6. Siehe auch Abschnitt A.2.11, „The table is full
-Fehler“.
myisam_max_extra_sort_file_size
(AUSLAUFEND)
Hinweis: Diese Variable wird in MySQL 5.1 nicht unterstützt. Weitere Informationen finden Sie im MySQL 5.0 Reference Manual.
myisam_max_sort_file_size
Die maximale Größe der Temporärdatei, die MySQL bei der Neuerstellung eines MyISAM
-Indexes (bei REPAIR TABLE
, ALTER TABLE
oder LOAD DATA INFILE
) verwenden darf. Ist die Datei größer als durch diesen Wert angegeben, dann wird der Index stattdessen unter Verwendung des Schlüssel-Caches erstellt (was allerdings langsamer ist). Der Wert wird in Byte angegeben.
myisam_recover_options
Der Wert der Option --myisam-recover
. Siehe auch Abschnitt 5.2.1, „Befehlsoptionen für mysqld“.
myisam_repair_threads
Wenn dieser Wert größer als 1 ist, werden Indizes von MyISAM
-Tabellen parallel (d. h. jeder Index mit einem eigenen Thread) während des Prozesses Repair by sorting
erstellt. Der Standardwert ist 1. Hinweis: Der Code für die Multithread-Reparatur befindet sich noch im Betastadium.
myisam_sort_buffer_size
Die Größe des Puffers, der bei der Sortierung von MyISAM
-Indizes bei Ausführung von REPAIR TABLE
oder bei der Erstellung von Indizes mit CREATE INDEX
oder ALTER TABLE
zugewiesen wird.
myisam_stats_method
Bestimmt, wie der Server NULL
-Werte bei der Ermittlung von Statistiken zur Verteilung von Indexwerten bei MyISAM
-Tabellen behandelt. Für die Variable gibt es zwei mögliche Werte: nulls_equal
und nulls_unequal
. Bei nulls_equal
werden alle NULL
-Indexwerte als gleichwertig betrachtet und bilden eine einzelne Wertegruppe, deren Größe der Anzahl der NULL
-Werte entspricht. Bei nulls_unequal
hingegen werden NULL
-Werte nicht als gleichwertig betrachtet, und jeder NULL
-Wert bildet eine eigene Wertegruppe der Größe 1.
Die Methode, mit der Tabellenstatistiken erzeugt werden, wirkt sich darauf aus, wie der Optimierer Indizes zur Abfrageausführung auswählt. Eine Beschreibung finden Sie in Abschnitt 7.4.7, „Sammlung von MyISAM
-Indexstatistiken“.
myisam_use_mmap
Sorgt für die Verwendung der Speicherzuordnung zum Lesen und Schreiben von MyISAM
-Tabellen. Diese Variable wurde in MySQL 5.1.4 hinzugefügt.
multi_read_range
Gibt die maximale Anzahl von Bereichen an, die bei der Bereichsauswahl an eine Speicher-Engine gesendet werden. Der Standardwert beträgt 256. Das Senden mehrerer Bereiche an eine Engine ist eine Funktion, die die Leistung bestimmter Auswahloperationen drastisch optimieren kann. Dies gilt insbesondere für NDBCLUSTER
: Diese Engine muss Bereichsanforderungen an alle Knoten senden, und das gleichzeitige Senden vieler derartiger Anforderungen verringert die Kommunikationskosten erheblich.
named_pipe
(Nur für Windows.) Gibt an, ob der Server Verbindungen über Named Pipes unterstützt.
ndb_extra_logging
Diese Variable kann auf einen Wert ungleich Null gesetzt werden, um das zusätzliche NDB-Loggen zu aktivieren. Diese Variable wurde in MySQL 5.1.6 hinzugefügt.
net_buffer_length
Der Kommunikationspuffer wird zwischen SQL-Anweisungen auf diese Größe zurücksetzt. Der Wert dieser Variable sollte normalerweise nicht geändert werden. Wenn Sie aber sehr wenig Speicher haben, können Sie ihn auf die voraussichtliche Länge der von Clients gesendeten Anweisungen setzen. Überschreiten Anweisungen diese Länge, dann wird der Puffer automatisch auf bis zu max_allowed_packet
Bytes vergrößert.
net_read_timeout
Gibt an (in Sekunden), wie lange auf weitere Daten über eine Verbindung gewartet wird, bevor die Leseoperation abgebrochen wird. Dieser Grenzwert gilt nur für TCP/IP-Verbindungen, nicht jedoch für Verbindungen, die über Unix-Socketdateien, Named Pipes oder gemeinsamen Speicher erfolgen. Wenn der Server vom Client liest, gibt net_read_timeout
den Zeitwert an, mit dem der Zeitpunkt des Abbruchs gesteuert wird. Wenn der Server hingegen auf den Client schreibt, gibt net_write_timeout
den Zeitwert an, mit dem der Zeitpunkt des Abbruchs gesteuert wird. Siehe auch slave_net_timeout
.
net_retry_count
Wenn eine Leseoperation an einem Kommunikationsport unterbrochen wird, erfolgt die hier angegebene Anzahl von Wiederverbindungsversuchen, bevor der Vorgang endgültig abgebrochen wird. Bei FreeBSD sollte dieser Wert ziemlich hoch sein, weil interne Interrupts an alle Threads gesendet werden.
net_write_timeout
Gibt an (in Sekunden), wie lange auf das Schreiben eines Blocks über eine Verbindung gewartet wird, bis die Schreiboperation abgebrochen wird. Dieser Grenzwert gilt nur für TCP/IP-Verbindungen, nicht jedoch für Verbindungen, die über Unix-Socketdateien, Named Pipes oder gemeinsamen Speicher erfolgen. Siehe auch net_read_timeout
.
new
Diese Variable wurde in MySQL 4.0 verwendet, um bestimmte Verhaltensweisen von Version 4.1 zu aktivieren. Sie ist aus Gründen der Abwärtskompatibilität noch vorhanden. In MySQL 5.1 ist der Wert immer OFF
.
old_passwords
Gibt an, ob der Server Passwörter im vor Version 4.1 verwendeten Stil benutzen soll. Siehe auch Abschnitt A.2.3, „Client does not support authentication protocol
“.
one_shot
Dies ist keine Variable, kann aber zur Einstellung einiger Variablen verwendet werden. Eine Beschreibung finden Sie in Abschnitt 13.5.3, „SET
“.
open_files_limit
Die Anzahl der Dateien, die mysqld nach Maßgabe des Betriebssystems öffnen darf. Dies ist der wirkliche, vom System gestattete Wert; er kann sich von dem Wert unterscheiden, den Sie mithilfe der Option --open-files-limit
an mysqld bzw. mysqld_safe übergeben haben. Auf Systemen, bei denen MySQL die Anzahl offener Dateien nicht ändern kann, ist der Wert 0.
optimizer_prune_level
Steuert die bei der Abfrageoptimierung angewendete Heuristik, um den Suchraum des Optimierers von wenig vielversprechenden Teilplänen zu säubern. Der Wert 0 deaktiviert die Heuristik, d. h. der Optimierer führt eine erschöpfende Suche durch. Der Wert 1 hingegen sorgt dafür, dass der Optimierer Pläne basierend auf der Anzahl der von temporären Plänen abgerufenen Datensätze entfernt.
optimizer_search_depth
Die maximale Tiefe der vom Abfrageoptimierer durchgeführten Suche. Werte, die größer sind als die Anzahl der Beziehungen in einer Abfrage, führen zu besseren Abfrageplänen, benötigen aber mehr Zeit zur Erzeugung eines Ausführungsplans für eine Abfrage. Bei Werten hingegen, die kleiner sind als die Anzahl der Beziehungen in einer Abfrage, wird der Ausführungsplan schneller zurückgegeben; allerdings ist der zurückgegebene Plan unter Umständen weit davon entfernt, optimal zu sein. Wenn der Wert 0 gewählt wird, wählt das System automatisch einen sinnvollen Wert aus. Wird ein Wert zugewiesen, der der maximalen Anzahl der in einer Abfrage verwendeten Tabelle plus 2 entspricht, dann verwendet der Optimierer zur Durchführung von Suchvorgängen den in MySQL 5.0.0 (und vorher) verwendeten Algorithmus.
pid_file
Der Pfadname der Prozesskennungsdatei. Die Variable kann mit der Option --pid-file
eingestellt werden.
plugin_dir
Der Pfadname des Plug-In-Verzeichnisses. Diese Variable wurde in MySQL 5.1.2 hinzugefügt.
port
Die Nummer des Ports, auf dem der Server nach TCP/IP-Verbindungen horcht. Die Variable kann mit der Option --port
eingestellt werden.
preload_buffer_size
Die Größe des Puffers, der beim Vorabladen von Indizes reserviert wird.
protocol_version
Die Version des vom MySQL-Server verwendeten Client/Server-Protokolls.
query_alloc_block_size
Die Zuweisungsgröße von Speicherblöcken, die für Objekte reserviert sind, welche während der Verarbeitung und Ausführung von Anweisungen erstellt werden. Wenn Sie Probleme mit der Speicherfragmentierung haben, kann es hilfreich sein, diesen Wert ein wenig zu erhöhen.
query_cache_limit
Es werden nur Ergebnisse zwischengespeichert, die nicht größer sind als die hier angegebene Anzahl von Bytes. Der Vorgabewert ist 1 Mbyte.
query_cache_min_res_unit
Die Mindestgröße (in Byte) für Blöcke, die vom Abfrage-Cache reserviert wurden. Der Vorgabewert ist 4.096 (4 Kbyte). Informationen zur Optimierung dieser Variable finden Sie in Abschnitt 5.14.3, „Konfiguration des Anfragen-Cache“.
query_cache_size
Die Menge des Speichers, der zur Zwischenspeicherung von Abfrageergebnissen reserviert wird. Der Standardwert ist 0, d. h. der Abfrage-Cache ist deaktiviert. Beachten Sie, dass die hier angegebene Speichermenge auch dann reserviert wird, wenn query_cache_type
den Wert 0 hat. Weitere Informationen finden Sie in Abschnitt 5.14.3, „Konfiguration des Anfragen-Cache“.
query_cache_type
Bestimmt den Typ des Abfrage-Caches. Die Einstellung des GLOBAL
-Wertes legt den Typ für alle Clients fest, die sich nachfolgend anmelden. Einzelne Clients können den SESSION
-Wert einstellen, um die eigene Verwendung des Abfrage-Caches zu beeinflussen. Die zulässigen Werte entnehmen Sie folgender Tabelle:
Option | Beschreibung |
0 oder OFF | Ergebnisse werden nicht zwischengespeichert oder abgerufen. Beachten Sie, dass die Reservierung des Puffers für den Abfrage-Cache hierdurch nicht aufgehoben wird. Zu diesem Zweck müssen Sie query_cache_size auf 0 setzen. |
1 oder ON | Legt alle Abfrageergebnisse mit Ausnahme derjenigen, die mit SELECT SQL_NO_CACHE beginnen, im Cache ab. |
2 oder DEMAND | Zwischengespeichert werden nur die Ergebnisse der Abfragen, die mit SELECT SQL_CACHE beginnen. |
Diese Variable hat den Standardwert ON
.
query_cache_wlock_invalidate
Wenn ein Client eine Schreibsperre auf eine MyISAM
-Tabelle erwirkt, dann wird das Absetzen von Anweisungen anderer Clients, die aus dieser Tabelle lesen, normalerweise nicht unterbunden, wenn die Abfrageergebnisse im Abfrage-Cache vorhanden sind. Wenn Sie diese Variable auf 1 setzen, werden bei vorhandener Schreibsperre für eine Tabelle alle Abfragen im Abfrage-Cache, die auf diese Tabelle verweisen, ungültig. Hierdurch sind andere Clients, die auf diese Tabelle zugreifen wollen, zum Warten gezwungen, bis die Sperre aufgehoben wird.
query_prealloc_size
Die Größe des Permanentpuffers, der zur Abarbeitung und Ausführung von Anweisungen verwendet wird. Dieser Puffer wird zwischen den Anweisungen nicht geleert. Wenn Sie komplexe Abfragen ausführen, kann ein höherer Wert für query_prealloc_size
die Leistung optimieren, weil er dafür sorgt, dass der Server während der Abfrageausführung weniger Speicherreservierungen vornehmen muss.
range_alloc_block_size
Die Größe der Blöcke, die bei der Bereichsoptimierung reserviert werden.
read_buffer_size
Jeder Thread, der einen sequenziellen Scan durchführt, reserviert einen Puffer dieser Größe (in Byte) pro gescannter Tabelle. Wenn Sie mehrere sequenzielle Scans durchführen, sollten Sie den Wert erhöhen. Standardmäßig steht er bei 131.072.
read_only
Wenn die Variable für einen Replikations-Slave-Server auf ON
gesetzt ist, gestattet der Slave Updates lediglich von Slave-Threads oder von Benutzern, die die Berechtigung SUPER
haben. Dies kann sinnvoll sein, um sicherzustellen, dass ein Slave-Server Updates nur von seinem Master-Server und nicht von Clients akzeptiert. Diese Variable gilt nicht für TEMPORARY
-Tabellen.
relay_log_purge
Aktiviert oder deaktiviert das automatische Säubern von Relay-Logdateien, sobald diese nicht mehr benötigt werden. Der Vorgabewert ist 1 (ON
).
read_rnd_buffer_size
Beim Lesen von Datensätzen in sortierter Reihenfolge (auf einen Schlüsselsortiervorgang folgend) werden die Datensätze über diesen Puffer gelesen, um Festplattenzugriffe zu vermeiden. Das Setzen dieser Variable auf einen hohen Wert kann die Leistung von ORDER BY
erheblich verbessern. Allerdings ist dies ein Puffer, der je Client zugewiesen wird. Deswegen sollten Sie die globale Variable nicht auf einen hohen Wert setzen. Ändern Sie stattdessen die Sitzungsvariablen nur bei den Clients, die große Abfragen ausführen müssen.
secure_auth
Wenn der MySQL-Server mit der Option --secure-auth
gestartet wurde, sperrt er Verbindungen aller Konten, deren Passwörter im alten (d. h. vor Version 4.1 gültigen) Format gespeichert sind. In diesem Fall ist der Wert dieser Variable ON
, andernfalls OFF
.
Sie sollten diese Option aktivieren, wenn Sie die Verwendung von Passwörtern im alten Format (und damit eine unsichere Kommunikation über das Netzwerk) generell unterbinden wollen.
Der Serverstart schlägt mit einer Fehlermeldung fehl, wenn diese Option aktiviert ist, die Berechtigungstabellen jedoch das alte Format verwenden. Siehe auch Abschnitt A.2.3, „Client does not support authentication protocol
“.
server_id
Die Serverkennung. Der Wert wird mit der Option --server-id
eingestellt. Er erlaubt im Rahmen der Replikation die eindeutige Identifizierung von Master- und Slave-Servern.
shared_memory
(Nur für Windows.) Gibt an, ob der Server Verbindungen mit gemeinsamem Speicher gestattet.
shared_memory_base_name
(Nur für Windows.) Der Name des gemeinsamen Speichers, der für Verbindungen mit gemeinsamem Speicher verwendet werden soll. Dies ist praktisch, wenn Sie mehrere MySQL-Instanzen auf einem einzelnen physischen Computer ausführen. Der Standardname ist MYSQL
. Beim Namen wird die Groß-/Kleinschreibung unterschieden.
Hat den Wert OFF
, wenn mysqld die externe Sperrung verwendet, bzw. ON
, wenn die externe Sperrung deaktiviert ist.
skip_networking
Diese Variable hat den Wert ON
, wenn der Server nur lokale Verbindungen (Nicht-TCP/IP-Verbindungen) zulässt. Unter Unix verwenden lokale Verbindungen eine Unix-Socketdatei. Unter Windows nutzen lokale Verbindungen eine Named Pipe oder gemeinsamen Speicher. Unter NetWare werden nur TCP/IP-Verbindungen unterstützt; hier dürfen Sie diese Variable nicht auf ON
setzen. Die Variable kann mit der Option --skip-networking
auf ON
gesetzt werden.
skip_show_database
Diese Variable verhindert, dass Benutzer die Anweisung SHOW DATABASES
verwenden, wenn sie die Berechtigung SHOW DATABASES
nicht haben. Dies kann die Sicherheit erhöhen, wenn Sie es für unerwünscht halten, dass Benutzer Datenbanken sehen können, die anderen Benutzern gehören. Die Wirkung der Variable hängt von der Berechtigung SHOW DATABASES
ab: Wenn der Variablenwert ON
ist, darf die SHOW DATABASES
-Anweisung nur von Benutzern verwendet werden, die die Berechtigung SHOW DATABASES
haben. Die Anweisung zeigt dann alle Datenbanknamen an. Ist der Wert hingegen OFF
, dann dürfen alle Benutzer SHOW DATABASES
absetzen; angezeigt werden in diesem Fall aber nur diejenigen Datenbanken, für die der jeweilige Benutzer die Berechtigung SHOW DATABASES
oder eine ähnliche Berechtigung hat.
slave_compressed_protocol
Gibt an, ob eine Komprimierung des Slave/Master-Protokolls verwendet werden soll, wenn sowohl Slave als auch Master diese unterstützen.
slave_load_tmpdir
Der Name des Verzeichnisses, in dem der Slave Temporärdateien zur Replikation von LOAD DATA INFILE
-Anweisungen erstellt.
slave_net_timeout
Gibt an (in Sekunden), wie lange auf weitere Daten über eine Master/Slave-Verbindung gewartet wird, bevor die Leseoperation abgebrochen wird. Dieser Grenzwert gilt nur für TCP/IP-Verbindungen, nicht jedoch für Verbindungen, die über Unix-Socketdateien, Named Pipes oder gemeinsamen Speicher erfolgen.
slave_skip_errors
Anzahl der Replikationsfehler, die der Slave übergehen (d. h. ignorieren) soll.
slave_transaction_retries
Wenn ein SQL-Thread auf einem Replikations-Slave eine Transaktion nicht ausführen kann, weil eine InnoDB
-Blockade aufgetreten ist oder die Werte innodb_lock_wait_timeout
von InnoDB
bzw. TransactionDeadlockDetectionTimeout
oder TransactionInactiveTimeout
von NDBCluster überschritten wurden, erfolgt die durch slave_transaction_retries
angegebene Anzahl von Neuversuchen, bevor der Vorgang mit einer Fehlermeldung beendet wird. Der Vorgabewert ist 10.
slow_launch_time
Wenn die Erstellung eines Threads länger dauert als durch diese Variable (in Sekunden) angegeben, dann erhöht der Server den Wert der Statusvariablen Slow_launch_threads
entsprechend.
socket
Auf Unix-Plattformen bezeichnet diese Variable den Namen der Socketdatei, die für lokale Clientverbindungen verwendet wird. Der Vorgabewert ist /tmp/mysql.sock
. (Bei einigen Distributionsformaten kann das Verzeichnis anders aussehen, z. B. /var/lib/mysql
bei RPMs.)
Unter Windows bezeichnet diese Variable den Namen der Named Pipe, die für lokale Clientverbindungen verwendet wird. Der Vorgabewert ist MySQL
(keine Unterscheidung der Groß-/Kleinschreibung).
sort_buffer_size
Jeder Thread, der eine Sortierung durchführen muss, reserviert einen Puffer dieser Größe. Erhöhen Sie den Wert, um ORDER BY
- oder GROUP BY
-Operationen zu beschleunigen. Siehe auch Abschnitt A.4.4, „Wohin MySQL temporäre Dateien speichert“.
sql_mode
Der aktuelle SQL-Modus des Servers. Dieser kann dynamisch eingestellt werden. Siehe auch Abschnitt 5.2.5, „Der SQL-Modus des Servers“.
sql_slave_skip_counter
Die Anzahl der vom Master kommenden Ereignisse, die ein Slave-Server übergehen soll. Siehe auch Abschnitt 13.6.2.6, „SET GLOBAL SQL_SLAVE_SKIP_COUNTER
“.
storage_engine
Die vorgabeseitige Speicher-Engine (Tabellentyp). Um die Speicher-Engine beim Serverstart einzustellen, verwenden Sie die Option --default-storage-engine
. Siehe auch Abschnitt 5.2.1, „Befehlsoptionen für mysqld“.
sync_binlog
Ist der Wert dieser Variable positiv, dann synchronisiert der MySQL-Server sein Binärlog jedes Mal auf die Festplatte (unter Verwendung von fdatasync()
), wenn sync_binlog
in das Binärlog geschrieben wird. Beachten Sie, dass, wenn der Autocommit-Modus aktiviert ist, eine Schreiboperation pro Anweisung im Binärlog gespeichert wird; andernfalls handelt es sich um eine Schreiboperation je Transaktion. Der Standardwert ist 0, d. h. es wird keine Synchronisierung auf Festplatte durchgeführt. Der Wert 1 ist die sicherste Variante, denn im Falle eines Absturzes verlieren Sie maximal eine Anweisung bzw. eine Transaktion aus dem Binärlog. Allerdings ist diese Methode auch die langsamste (sofern die Festplatte nicht über einen batteriegestützten Cache verfügt, der die Synchronisierung extrem beschleunigt).
Ist der Wert von sync_binlog
0 (Standardeinstellung), dann erfolgt kein zusätzliches Schreiben auf die Festplatte. Der Server ist wie bei jeder anderen Datei auch auf das Betriebssystem angewiesen, um den Dateiinhalt regelmäßig auf die Festplatte schreiben zu können.
sync_frm
Wenn diese Variable auf 1 gesetzt ist, wird, wenn eine nichttemporäre Tabelle erstellt wird, deren .frm
-Datei auf Festplatte synchronisiert (dies geschieht mithilfe von fdatasync()
). Dies ist zwar langsamer, im Falle eines Absturzes aber sicherer. Der Standardwert ist 1.
system_time_zone
Die Systemzeitzone des Servers. Wenn die Serverausführung startet, erbt sie eine Zeitzoneneinstellung von den Standardwerten des Computers, welche unter Umständen von der Umgebung des Kontos modifiziert wird, welches zur Ausführung des Servers oder Startskripts verwendet wird. Der Wert wird verwendet, um system_time_zone
einzustellen. Normalerweise wird die Zeitzone durch die Umgebungsvariable TZ
festgelegt. Eine Definition kann aber auch mithilfe der Option --timezone
des Skripts mysqld_safe erfolgen.
Die Variable system_time_zone
unterscheidet sich von time_zone
. Zwar können diese beiden Variablen denselben Wert haben, letztere wird aber zur Initialisierung der Zeitzone für die Clients verwendet, die eine Verbindung herstellen. Siehe auch Abschnitt 5.11.8, „Zeitzonen-Unterstützung des MySQL-Servers“.
table_cache
Dies ist der alte Name von table_open_cache
, der vor MySQL 5.1.3 verwendet wurde. Verwenden Sie ab MySQL 5.1.3 stattdessen table_open_cache
.
table_definition_cache
Die Anzahl der Tabellendefinitionen, die im Definitions-Cache gespeichert werden können. Wenn Sie eine hohe Anzahl von Tabellen verwenden, können Sie einen großen Tabellendefinitions-Cache erstellen, um das Öffnen von Tabellen zu beschleunigen. Der Tabellendefinitions-Cache benötigt weniger Platz als der normale Tabellen-Cache und verwendet anders als jener keine Dateideskriptoren. Diese Variable wurde in MySQL 5.1.3 hinzugefügt.
table_open_cache
Die Anzahl offener Tabellen für alle Threads. Wenn Sie diesen Wert erhöhen, erhöht sich auch die Anzahl der Dateideskriptoren, die mysqld benötigt. Wenn Sie überprüfen wollen, ob Sie den Tabellen-Cache vergrößern müssen, kontrollieren Sie die Statusvariable Opened_tables
. Siehe auch Abschnitt 5.2.4, „Server-Statusvariablen“. Wenn der Wert von Opened_tables
sehr groß ist und Sie FLUSH TABLES
nicht sehr häufig verwenden (was nichts anderes tut, als alle Tabellen zu schließen und neu zu öffnen), dann sollten Sie den Wert von table_open_cache
erhöhen. Weitere Informationen zum Tabellen-Cache finden Sie unter Abschnitt 7.4.8, „Nachteile der Erzeugung großer Mengen von Tabellen in derselben
Datenbank“. Vor MySQL 5.1.3 hieß diese Variable table_cache
.
table_type
Diese Variable ist synonym zu storage_engine
. Bei MySQL 5.1 ist storage_engine
der bevorzugte Name.
thread_cache_size
Gibt an, wie viele Threads der Server zur Neuverwendung zwischenspeichern soll. Wenn ein Client seine Verbindung trennt, dann werden die Threads dieses Clients im Cache abgelegt, sofern die Anzahl der dort vorhandenen Threads geringer als thread_cache_size
ist. Thread-Anforderungen werden erfüllt, indem, sofern möglich, Threads aus dem Cache neu verwendet werden; neue Threads werden nur erstellt, wenn der Cache leer ist. Der Wert dieser Variablen kann erhöht werden, um die Leistung zu optimieren, wenn viele neue Verbindungen auftreten. (Bei einer guten Thread-Implementierung werden Sie normalerweise jedoch keine spürbare Leistungsverbesserung bemerken.) Durch Überprüfung der Differenz zwischen den Statusvariablen Connections
und Threads_created
können Sie die Wirksamkeit des Thread-Caches kontrollieren. Detaillierte Informationen finden Sie in Abschnitt 5.2.4, „Server-Statusvariablen“.
thread_concurrency
Unter Solaris ruft mysqld thr_setconcurrency()
mit diesem Wert auf. Diese Funktionen erlaubt es Anwendungen, dem Thread-System Hinweise zur gewünschten Anzahl der gleichzeitig ausgeführten Threads zukommen zu lassen.
thread_stack
Die Stapelgröße für jeden Thread. Viele der vom crash-me
-Test erkannten Einschränkungen hängen von diesem Wert ab. Der Standardwert ist für den normalen Betrieb ausreichend groß. Siehe auch Abschnitt 7.1.4, „Die MySQL-Benchmark-Reihe“. Standardwert ist 192 Kbyte.
time_format
Diese Variable ist nicht implementiert.
time_zone
Die aktuelle Zeitzone. Diese Variable wird zur Initialisierung der Zeitzone für die Clients verwendet, die eine Verbindung herstellen. Standardmäßig ist der Ausgangswert 'SYSTEM'
(mit der Bedeutung „Den Wert von system_time_zone
verwenden“). Der Wert kann beim Serverstart mit der Option --default-time-zone
explizit angegeben werden. Siehe auch Abschnitt 5.11.8, „Zeitzonen-Unterstützung des MySQL-Servers“.
tmp_table_size
Wenn eine temporäre Tabelle im Arbeitsspeicher diese Größe überschreitet, wandelt MySQL sie automatisch in eine MyISAM
-Tabelle auf der Festplatte um. Erhöhen Sie den Wert von tmp_table_size
, wenn Sie viele erweiterte GROUP BY
-Abfragen ausführen und viel Speicher haben.
tmpdir
Das für Temporärdateien und Temporärtabellen verwendete Verzeichnis. Dieser Variable kann eine Liste mit mehreren verschiedenen Pfaden zugewiesen werden, die zyklisch abwechselnd verwendet werden. Die Pfade sollten unter Unix mit Doppelpunkten (‘:
’) und unter Windows, NetWare und OS/2 mit Semikola (‘;
’) voneinander getrennt werden.
Diese Multiverzeichnisfunktion kann verwendet werden, um die Last auf mehrere physische Festplatten zu verteilen. Wenn der MySQL-Server als Replikations-Slave agiert, sollten Sie tmpdir
nicht auf ein Verzeichnis auf einem speicherbasierten Dateisystem oder ein Verzeichnis verweisen lassen, das gelöscht wird, wenn der Server neu startet. Ein Replikations-Slave benötigt einen Teil seiner Temporärdateien, um einen Systemneustart so zu überstehen, dass er Temporärtabellen oder LOAD DATA INFILE
-Operationen replizieren kann. Wenn Dateien im Verzeichnis für Temporärdateien beim Serverneustart verloren gehen, schlägt die Replikation fehl. Wenn Sie allerdings MySQL 4.0.0 oder höher verwenden, können Sie das Temporärverzeichnis des Slaves mithilfe der Variable slave_load_tmpdir
einstellen. In diesem Fall wird der Slave den globalen Wert von tmpdir
nicht verwenden, und Sie können tmpdir
auch auf eine nichtpermanente Position verweisen lassen.
transaction_alloc_block_size
Die Menge an Bytes, um die ein Speicherpool für eine Transaktion erhöht wird, für die Speicher benötigt wird. Siehe auch die Beschreibung zu transaction_prealloc_size
.
transaction_prealloc_size
Es gibt für jede Transaktion einen Speicherpool, aus dem verschiedene transaktionsbezogene Reservierungen Speicher entnehmen. Die Ausgangsgröße dieses Pools entspricht der Anzahl von Bytes, die durch transaction_prealloc_size
angegeben ist. Für jede Reservierung, die aus dem Pool nicht erfüllt werden kann, da zu wenig Speicher verfügbar ist, wird der Pool um die Anzahl von Bytes erhöht, die durch transaction_alloc_block_size
angegeben ist. Sobald die Transaktion endet, wird der Pool wieder um die durch transaction_prealloc_size
angegebene Anzahl von Bytes verringert.
Wenn Sie dafür Sorge tragen, dass transaction_prealloc_size
groß genug ist, um alle Anweisungen einer einzelnen Transaktion aufzunehmen, können Sie viele malloc()
-Aufrufe vermeiden.
tx_isolation
Die Standardstufe für die Transaktionsisolierung. Der Vorgabewert ist REPEATABLE-READ
.
Diese Variable wird durch die SET TRANSACTION ISOLATION LEVEL
-Anweisung eingestellt. Siehe auch Abschnitt 13.4.6, „SET TRANSACTION
“. Wenn Sie tx_isolation
direkt auf einen Isolierungsstufennamen setzen, der ein Leerzeichen enthält, dann sollte der Name in Anführungszeichen gesetzt und das Leerzeichen durch einen Bindestrich ersetzt werden. Zum Beispiel:
SET tx_isolation = 'READ-COMMITTED';
updatable_views_with_limit
Diese Variable steuert, ob Updates unter Verwendung einer View vorgenommen werden können, die keinen Primärschlüssel in der zugrundeliegenden Tabelle enthält, wenn das Update eine LIMIT
-Klausel enthält. (Derartige Updates werden häufig von GUI-Tools erzeugt.) Ein Update ist eine UPDATE
- oder DELETE
-Anweisung. Unter dem Primärschlüssel versteht man hier einen PRIMARY KEY
- oder einen UNIQUE
-Index, bei dem keine Spalte NULL
enthalten kann.
Die Variable kann zwei Werte haben:
1
oder YES
: Es wird nur eine Warnung (d. h. keine Fehlermeldung) ausgegeben. Dies ist der Standardwert.
0
oder NO
: Das Update wird untersagt.
version
Die Versionsnummer des Servers.
version_bdb
Die Version der BDB
-Speicher-Engine.
version_comment
Das Skript configure umfasst eine Option --with-comment
, die die Angabe eines Kommentars bei der Erstellung von MySQL erlaubt. Diese Variable enthält den Wert dieses Kommentars.
version_compile_machine
Der Typ des Computers oder der Architektur, auf der MySQL erstellt wurde.
version_compile_os
Der Typ des Betriebssystem, auf der MySQL erstellt wurde.
wait_timeout
Zeit (in Sekunden), während der der Server bei einer nichtinteraktiven Verbindung auf Aktivitäten wartet, bevor er sie schließt. Dieser Grenzwert gilt nur für TCP/IP-Verbindungen, nicht jedoch für Verbindungen, die über Unix-Socketdateien, Named Pipes oder gemeinsamen Speicher erfolgen.
Beim Thread-Start wird der Sitzungswert wait_timeout
auf der Basis des globalen Wertes wait_timeout
oder des globalen Wertes interactive_timeout
initialisiert. Welcher Wert verwendet wird, hängt vom Clienttyp (entsprechend der Definition durch die Verbindungsoption CLIENT_INTERACTIVE
von mysql_real_connect()
) ab. Siehe auch interactive_timeout
.
Der Server mysqld arbeitet mit einer ganzen Reihe von Systemvariablen, die angeben, wie er konfiguriert ist. Für alle diese Variablen gibt es Vorgabewerte. Diese können beim Serverstart über Optionen auf der Befehlszeile oder in Optionsdateien eingestellt werden. Die meisten Variablen lassen sich zur Laufzeit des Servers dynamisch mithilfe der SET
-Anweisung ändern; auf diese Weise können Sie den Betrieb des Servers beeinflussen, ohne ihn beenden und neu starten zu müssen. Ferner können Sie die Werte auch in Ausdrücken verwenden.
Hinweis: Verschiedene Systemvariablen lassen sich mit der Anweisung SET
aktivieren, indem sie auf ON
bzw. 1
gesetzt werden. Ähnlich können Sie sie mit SET
deaktivieren, indem Sie sie auf OFF
bzw. 0
setzen. Um solche Variablen über die Befehlszeile oder in Optionsdateien einstellen zu können, müssen Sie sie auf 1
oder 0
setzen (d. h. die Einstellungen ON
und OFF
funktionieren nicht). So führt beispielsweise auf der Befehlszeile die Option --delay_key_write=1
zum gewünschten Ergebnis – anders als --delay_key_write=ON
.
Der Server verwendet zwei Arten von Systemvariablen. Globale Variablen beeinflussen den Gesamtbetrieb des Servers. Sitzungsvariablen hingegen wirken sich auf seinen Betrieb bezogen auf jeweils individuelle Clientverbindungen aus. Eine gegebene Systemvariable kann sowohl einen globalen als auch einen sitzungsbezogenen Wert haben.
Wenn der Server startet, setzt er alle globalen Variablen auf ihr jeweiligen Standardwerte. Diese Vorgaben können mithilfe von Optionen geändert werden, die in Optionsdateien oder über die Befehlszeile angegeben werden.
Wenn Sie eine Variable, die einen numerischen Wert annimmt, über eine Startoption konfigurieren, dann kann dieser Wert mit den Suffixen K
, M
oder G
(in Groß- oder Kleinschreibung) angegeben werden, um einen Multiplikator von 1.024, 1.0242 oder 1.0243 anzuzeigen. Bei der Einstellung von key_buffer_size
etwa würden hiermit die Werte als Kbyte, Mbyte oder Gbyte angegeben. Der folgende Befehl startet den Server also mit einem Abfrage-Cache, der eine Größe von 16 Mbyte hat.
mysqld --query_cache_size=16M
Die Groß-/Kleinschreibung der Suffixbuchstaben ist irrelevant: 16M
und 16m
sind gleichwertig.
Wenn Sie den Maximalwert, auf den eine Systemvariable zur Laufzeit mit der SET
-Anweisung gesetzt werden kann, beschränken wollen, können Sie das gewünschte Maximum mithilfe einer Option des Typs --maximum-
beim Serverstart festlegen. Um beispielsweise eine Erhöhung des Wertes von var_name
query_cache_size
auf mehr als 32 Mbyte zu verhindern, benutzen Sie die Option --maximum-query_cache_size=32M
.
Wenn der Server gestartet wurde, können diejenigen Variablen, die dynamisch sind, geändert werden, indem Sie eine Verbindung mit dem Server herstellen und eine SET GLOBAL
-Anweisung absetzen. Um eine globale Variable ändern zu können, benötigen Sie die Berechtigung var_name
= value
SUPER
.
Der Server verwendet zudem einen Satz von Sitzungsvariablen für jeden Client, der eine Verbindung herstellt. Die Sitzungsvariablen des Clients werden zum Zeitpunkt der Verbindungsherstellung unter Verwendung der aktuellen Werte der entsprechenden globalen Variablen initialisiert. So wird z. B. der SQL-Modus des Clients von der Sitzungsvariable sql_mode
gesteuert, die, wenn der Client die Verbindung herstellt, mit dem Wert der globalen Variable sql_mode
initialisiert wird.
Sitzungsvariablen, die dynamisch sind, kann der Client durch Absetzen einer SET SESSION
-Anweisung ändern. Das Einstellen einer Sitzungsvariable erfordert keine speziellen Berechtigungen, aber ein Client kann nur seine eigenen Sitzungsvariablen einstellen, nicht jedoch die anderer Clients.
var_name
= value
Eine Änderung einer globalen Variable ist für alle Clients sichtbar, die auf diese globale Variable zugreifen. Allerdings wirkt sich diese Änderung nur auf die entsprechenden Sitzungsvariablen derjenigen Clients aus, die nach ihrer Durchführung eine Verbindung herstellen. Änderungen an globalen Variablen haben hingegen keinen Einfluss auf die betreffende Sitzungsvariable derjenigen Clients, die bereits eine Verbindung hergestellt haben (dies gilt sogar für Clients, die die SET GLOBAL
-Anweisung absetzen).
Es gibt unterschiedliche Möglichkeiten, globale und Sitzungsvariablen zur Laufzeit einzustellen. Die folgenden Beispiele verwenden sort_buffer_size
als Beispiel für einen Variablennamen.
Um den Wert einer GLOBAL
-Variable einzustellen, verwenden Sie eine der folgenden Syntaxen:
SET GLOBAL sort_buffer_size =value
; SET @@global.sort_buffer_size =value
;
Um den Wert einer SESSION
-Variable einzustellen, verwenden Sie eine der folgenden Syntaxen:
SET SESSION sort_buffer_size =value
; SET @@session.sort_buffer_size =value
; SET sort_buffer_size =value
;
LOCAL
ist ein Synonym für SESSION
, und @@local.
ist ein Synonym für @@session.
.
Wenn Sie beim Einstellen einer Variable keinen GLOBAL
- oder SESSION
-Modifikator angeben, stellt die Anweisung den Sitzungswert ein.
Um eine falsche Verwendung zu verhindern, erzeugt MySQL einen Fehler, wenn Sie SET GLOBAL
für eine Variable verwenden, für die nur SET SESSION
zulässig ist, oder GLOBAL
(bzw. @@global.
) beim Einstellen einer globalen Variable nicht angeben.
Wenn Sie einer Systemvariablen mit SET
einen Wert zuweisen, dann können Sie in diesem Wert keine Suffixbuchstaben verwenden. Allerdings kann der Wert die Form eines Ausdrucks annehmen:
SET sort_buffer_size = 10 * 1024 * 1024;
Um explizit anzugeben, ob Sie die globale oder die Sitzungsvariable einstellen wollen, verwenden Sie die Modifikatoren GLOBAL
oder SESSION
:
SET GLOBAL sort_buffer_size = 10 * 1024 * 1024; SET SESSION sort_buffer_size = 10 * 1024 * 1024;
Systemvariablen und ihre Werte zeigen Sie mit der SHOW VARIABLES
-Anweisung an.
mysql> SHOW VARIABLES;
+---------------------------------+--------------------------------------+
| Variable_name | Value |
+---------------------------------+--------------------------------------+
| auto_increment_increment | 1 |
| auto_increment_offset | 1 |
| automatic_sp_privileges | ON |
| back_log | 50 |
| basedir | /home/jon/bin/mysql/ |
| binlog_cache_size | 32768 |
| bulk_insert_buffer_size | 8388608 |
| character_set_client | latin1 |
| character_set_connection | latin1 |
| character_set_database | latin1 |
| character_set_results | latin1 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | /usr/bin/mysql/share/mysql/charsets/ |
| collation_connection | latin1_swedish_ci |
| collation_database | latin1_swedish_ci |
| collation_server | latin1_swedish_ci |
...
| innodb_additional_mem_pool_size | 1048576 |
| innodb_autoextend_increment | 8 |
| innodb_buffer_pool_awe_mem_mb | 0 |
| innodb_buffer_pool_size | 8388608 |
| innodb_checksums | ON |
| innodb_commit_concurrency | 0 |
| innodb_concurrency_tickets | 500 |
| innodb_data_file_path | ibdata1:10M:autoextend |
| innodb_data_home_dir | |
...
| version | 5.1.6-alpha-log |
| version_comment | Source distribution |
| version_compile_machine | i686 |
| version_compile_os | suse-linux |
| wait_timeout | 28800 |
+---------------------------------+--------------------------------------+
Um den Wert einer bestimmten GLOBAL
-Variable abzurufen, geben Sie eine der folgenden Anweisungen ein:
SELECT @@global.sort_buffer_size; SHOW GLOBAL VARIABLES like 'sort_buffer_size';
Um den Wert einer SESSION
-Variable abzurufen, geben Sie eine der folgenden Anweisungen ein:
SELECT @@sort_buffer_size; SELECT @@session.sort_buffer_size; SHOW SESSION VARIABLES like 'sort_buffer_size';
Wenn Sie eine Variable mit SELECT @@
abrufen (d. h. var_name
global.
oder session.
nicht angeben), gibt MySQL den SESSION
-Wert zurück, sofern dieser vorhanden ist, ansonsten den GLOBAL
-Wert.
Wenn Sie bei SHOW VARIABLES
weder GLOBAL
noch SESSION
angeben, gibt MySQL die SESSION
-Werte zurück.
Der Grund dafür, warum das Schlüsselwort GLOBAL
bei der Einstellung von Variablen angegeben werden muss, die ohnehin nur global verfügbar sind, nicht jedoch bei deren Abrufen, besteht darin, zukünftige Probleme von vornherein auszuschließen. Wenn wir in Zukunft eine SESSION
-Variable entfernen müssten, die denselben Namen wie eine GLOBAL
-Variable hat, würde ein Client mit der Berechtigung SUPER
möglicherweise ungewollt die GLOBAL
-Variable ändern – und nicht die SESSION
-Variable für die eigene Verbindung. Würden wir ein SESSION
-Variable mit demselben Namen hinzufügen, den auch eine GLOBAL
-Variable hat, dann könnte ein Client, der eigentlich die GLOBAL
-Variable ändern sollte, am Ende seine eigene SESSION
-Variable modifizieren.
Eine Strukturvariable unterscheidet sich in zweierlei Hinsicht von einer regulären Systemvariablen:
Ihr Wert ist eine Struktur mit Komponenten, die Serverparameter angeben, welche als zusammengehörig zu betrachten sind.
Es kann mehrere Instanzen eines gegebenen Strukturvariablentyps geben. Jede Instanz hat einen anderen Namen und verweist auf eine andere Ressource, die vom Server verwaltet wird.
MySQL 5.1 unterstützt genau einen Typ von Strukturvariablen. Dieser gibt Parameter an, die den Betrieb von Schlüssel-Caches regeln. Eine Strukturvariable für Schlüssel-Caches hat die folgenden Komponenten:
key_buffer_size
key_cache_block_size
key_cache_division_limit
key_cache_age_threshold
In diesem Abschnitt beschreiben wir die Syntax, mit der Strukturvariablen referenziert werden. Schlüssel-Cache-Variablen werden zwar für Syntaxbeispiele verwendet; die einzelnen Details dazu, wie Schlüssel-Caches funktionieren, finden Sie jedoch an anderer Stelle in Abschnitt 7.4.6, „Der MyISAM
-Schlüssel-Cache“.
Um eine Komponente einer Strukturvariableninstanz zu referenzieren, können Sie einen zusammengesetzten Namen des Formats instance_name.component_name
verwenden. Ein paar Beispiele:
hot_cache.key_buffer_size hot_cache.key_cache_block_size cold_cache.key_cache_block_size
Für jede strukturierte Systemvariable ist immer eine Instanz mit dem Namen default
vordefiniert. Wenn Sie eine Komponente einer Strukturvariable ohne einen Instanznamen referenzieren, wird die Instanz default
verwendet. Auf diese Weise referenzieren default.key_buffer_size
und key_buffer_size
dieselbe Systemvariable.
Strukturvariableninstanzen und Komponenten gehorchen den folgenden Benennungsregeln:
Für einen gegebenen Strukturvariablentyp muss jede Instanz einen Namen haben, der innerhalb der Variablen dieses Typs eindeutig ist. Typenübergreifend hingegen müssen die Instanznamen nicht eindeutig sein. So gibt es für jede Strukturvariable eine Instanz namens default
– der Name default
ist also keineswegs typübergreifend eindeutig.
Die Namen der Komponenten jedes Strukturvariablentyps muss über alle Systemvariablennamen hinweg eindeutig sein. Wäre dies nicht der Fall (d. h. könnten zwei verschiedene Strukturvariablentypen die gleichen Mitgliedsnamen für Komponenten aufweisen), dann wäre nicht eindeutig, welche Standardstrukturvariable zur Referenzierung von Mitgliedsnamen verwendet werden sollte, die nicht durch einen Instanznamen qualifiziert wären.
Wenn der Namen einer Strukturvariableninstanz als Bezeichner ohne Anführungszeichen nicht zulässig ist, setzen Sie sie ihn in Backticks. So ist etwa hot-cache
unzulässig – anders als `hot-cache`
.
global
, session
und local
sind unzulässige Instanznamen. Hierdurch wird ein Konflikt umgangen, der bei der Referenzierung nichtstrukturierter Systemvariablen auftreten kann, bei denen die Schreibung @@global.
zulässig ist.
var_name
Zurzeit besteht die Möglichkeit des Verstoßes gegen die ersten beiden Regeln nicht, weil der einzige Strukturvariablentyp der für die Schlüssel-Caches ist. Die Bedeutung dieser Regeln wird jedoch zunehmen, wenn zukünftig andere Typen strukturierter Variablen eingeführt werden.
Mit einer Ausnahme können Sie Komponenten von Strukturvariablen über zusammengesetzte Namen in jedem Kontext referenzieren, in dem einfache Variablennamen auftauchen können. So können Sie einer Strukturvariablen beispielsweise über eine Befehlszeilenoption einen Wert zuweisen:
shell> mysqld --hot_cache.key_buffer_size=64K
In einer Optionsdatei verwenden Sie folgende Syntax:
[mysqld] hot_cache.key_buffer_size=64K
Wenn Sie den Server mit dieser Option starten, erstellt er einen Schlüssel-Cache namens hot_cache
mit einer Größe von 64 Kbyte zusätzlich zum vorgabeseitigen Schlüssel-Cache mit der Standardgröße von 8 Mbyte.
Nehmen wir an, Sie starten den Server wie folgt:
shell>mysqld --key_buffer_size=256K \
--extra_cache.key_buffer_size=128K \
--extra_cache.key_cache_block_size=2048
In diesem Fall setzt der Server die Größe des vorgabeseitigen Caches auf 256 Kbyte. (Sie hätten auch --default.key_buffer_size=256K
schreiben können.) Ferner erstellt der Server einen zweiten Schlüssel-Cache namens extra_cache
mit einer Größe von 128 Kbyte. Bei diesem ist die Größe der Blockpuffer für die Zwischenspeicherung von Tabellenindexblöcken auf 2.048 Bytes gesetzt.
Das folgende Beispiel startet den Server mit drei verschiedenen Schlüssel-Caches, deren Größen das Verhältnis 3:1:1 aufweisen:
shell>mysqld --key_buffer_size=6M \
--hot_cache.key_buffer_size=2M \
--cold_cache.key_buffer_size=2M
Strukturvariablen können auch zur Laufzeit eingestellt und abgefragt werden. Um beispielsweise einen Schlüssel-Cache namens hot_cache
auf eine Größe von 10 Mbyte zu setzen, verwenden Sie eine der folgenden Anweisungen:
mysql>SET GLOBAL hot_cache.key_buffer_size = 10*1024*1024;
mysql>SET @@global.hot_cache.key_buffer_size = 10*1024*1024;
Um die Cache-Größe abzufragen, tun Sie Folgendes:
mysql> SELECT @@global.hot_cache.key_buffer_size;
Die folgende Anweisung wird hingegen nicht funktionieren. Die Variable wird nicht als zusammengesetzter Name, sondern als einfacher String für einen LIKE
-Mustervergleich aufgefasst:
mysql> SHOW GLOBAL VARIABLES LIKE 'hot_cache.key_buffer_size';
Dies ist die oben erwähnte Ausnahme bei der Verwendung von Strukturvariablennamen in allen Kontexten, in denen einfache Variablennamen auftreten können.
Viele Serversystemvariablen sind dynamisch und lassen sich mit SET GLOBAL
oder SET SESSION
zur Laufzeit einstellen. Sie können ihre Werte auch mit SELECT
abrufen. Siehe auch Abschnitt 5.2.3, „Verwendung von Server-Systemvariablen“.
Die folgende Tabelle zeigt eine vollständige Liste aller Systemvariablen. Dabei gibt die letzte Spalte für jede Variable an, ob GLOBAL
oder SESSION
(oder beide) gültig sind. Die Tabelle listet auch Sitzungsoptionen auf, die sich mit der SET
-Anweisung einstellen lassen. Abschnitt 13.5.3, „SET
“, beschreibt diese Optionen.
Variablen, die vom Typ „String“ sind, nehmen einen String-Wert entgegen. Variablen, die vom Typ „numerisch“ sind, nehmen einen Zahlenwert entgegen. Variablen vom Typ „boolesch“ können die Werte 0, 1, ON
und OFF
annehmen. (Wenn Sie sie über die Befehlszeile oder in einer Optionsdatei einstellen, verwenden Sie die numerischen Werte.) Variablen, die als „Aufzählung“ gekennzeichnet sind, sollten normalerweise einen der für die Variable verfügbaren Werte enthalten; solche Variablen können aber auch auf die Zahl gesetzt werden, die der Stelle des gewünschten Wertes in der Aufzählung entspricht. Bei Aufzählungssystemvariablen ist der erste Aufzählungswert 0. Hier liegt ein Unterschied zu ENUM
-Spalten vor, bei denen der erste Aufzählungswert der 1 entspricht.
Variablenname | Werttyp | Typ |
autocommit | boolesch | SESSION |
big_tables | boolesch | SESSION |
binlog_cache_size | numerisch | GLOBAL |
bulk_insert_buffer_size | numerisch | GLOBAL | SESSION |
character_set_client | String | GLOBAL | SESSION |
character_set_connection | String | GLOBAL | SESSION
|
character_set_results | String | GLOBAL | SESSION |
character_set_server | String | GLOBAL | SESSION |
collation_connection | String | GLOBAL | SESSION |
collation_server | String | GLOBAL | SESSION |
completion_type | numerisch | GLOBAL | SESSION |
concurrent_insert | boolesch | GLOBAL |
connect_timeout | numerisch | GLOBAL |
convert_character_set | String | GLOBAL | SESSION |
default_week_format | numerisch | GLOBAL | SESSION |
delay_key_write | OFF | ON | ALL | GLOBAL |
delayed_insert_limit | numerisch | GLOBAL |
delayed_insert_timeout | numerisch | GLOBAL |
delayed_queue_size | numerisch | GLOBAL |
div_precision_increment | numerisch | GLOBAL | SESSION |
engine_condition_pushdown | boolesch | GLOBAL | SESSION |
error_count | numerisch | SESSION |
event_scheduler | boolesch | GLOBAL |
expire_logs_days | numerisch | GLOBAL |
flush | boolesch | GLOBAL |
flush_time | numerisch | GLOBAL |
foreign_key_checks | boolesch | SESSION |
ft_boolean_syntax | numerisch | GLOBAL |
group_concat_max_len | numerisch | GLOBAL | SESSION |
identity | numerisch | SESSION |
innodb_autoextend_increment | numerisch | GLOBAL |
innodb_commit_concurrency | numerisch | GLOBAL |
innodb_concurrency_tickets | numerisch | GLOBAL |
innodb_max_dirty_pages_pct | numerisch | GLOBAL |
innodb_max_purge_lag | numerisch | GLOBAL |
innodb_support_xa | boolesch | GLOBAL | SESSION |
innodb_sync_spin_loops | numerisch | GLOBAL |
innodb_table_locks | boolesch | GLOBAL | SESSION |
innodb_thread_concurrency | numerisch | GLOBAL |
innodb_thread_sleep_delay | numerisch | GLOBAL |
insert_id | boolesch | SESSION |
interactive_timeout | numerisch | GLOBAL | SESSION |
join_buffer_size | numerisch | GLOBAL | SESSION |
key_buffer_size | numerisch | GLOBAL |
last_insert_id | numerisch | SESSION |
local_infile | boolesch | GLOBAL |
log_warnings | numerisch | GLOBAL |
long_query_time | numerisch | GLOBAL | SESSION |
low_priority_updates | boolesch | GLOBAL | SESSION |
max_allowed_packet | numerisch | GLOBAL | SESSION |
max_binlog_cache_size | numerisch | GLOBAL |
max_binlog_size | numerisch | GLOBAL |
max_connect_errors | numerisch | GLOBAL |
max_connections | numerisch | GLOBAL |
max_delayed_threads | numerisch | GLOBAL |
max_error_count | numerisch | GLOBAL | SESSION |
max_heap_table_size | numerisch | GLOBAL | SESSION |
max_insert_delayed_threads | numerisch | GLOBAL |
max_join_size | numerisch | GLOBAL | SESSION |
max_relay_log_size | numerisch | GLOBAL |
max_seeks_for_key | numerisch | GLOBAL | SESSION |
max_sort_length | numerisch | GLOBAL | SESSION |
max_tmp_tables | numerisch | GLOBAL | SESSION |
max_user_connections | numerisch | GLOBAL |
max_write_lock_count | numerisch | GLOBAL |
myisam_stats_method | Aufzählung | GLOBAL | SESSION |
multi_read_range | numerisch | GLOBAL | SESSION |
myisam_data_pointer_size | numerisch | GLOBAL |
log_bin_trust_function_creators | boolesch | GLOBAL |
myisam_max_sort_file_size | numerisch | GLOBAL | SESSION |
myisam_repair_threads | numerisch | GLOBAL | SESSION |
myisam_sort_buffer_size | numerisch | GLOBAL | SESSION |
myisam_use_mmap | boolesch | GLOBAL |
ndb_extra_logging | numerisch | GLOBAL |
net_buffer_length | numerisch | GLOBAL | SESSION |
net_read_timeout | numerisch | GLOBAL | SESSION |
net_retry_count | numerisch | GLOBAL | SESSION |
net_write_timeout | numerisch | GLOBAL | SESSION |
old_passwords | numerisch | GLOBAL | SESSION |
optimizer_prune_level | numerisch | GLOBAL | SESSION |
optimizer_search_depth | numerisch | GLOBAL | SESSION |
preload_buffer_size | numerisch | GLOBAL | SESSION |
query_alloc_block_size | numerisch | GLOBAL | SESSION |
query_cache_limit | numerisch | GLOBAL |
query_cache_size | numerisch | GLOBAL |
query_cache_type | Aufzählung | GLOBAL | SESSION |
query_cache_wlock_invalidate | boolesch | GLOBAL | SESSION |
query_prealloc_size | numerisch | GLOBAL | SESSION |
range_alloc_block_size | numerisch | GLOBAL | SESSION |
read_buffer_size | numerisch | GLOBAL | SESSION |
read_only | numerisch | GLOBAL |
read_rnd_buffer_size | numerisch | GLOBAL | SESSION |
rpl_recovery_rank | numerisch | GLOBAL |
safe_show_database | boolesch | GLOBAL |
secure_auth | boolesch | GLOBAL |
server_id | numerisch | GLOBAL |
slave_compressed_protocol | boolesch | GLOBAL |
slave_net_timeout | numerisch | GLOBAL |
slave_transaction_retries | numerisch | GLOBAL |
slow_launch_time | numerisch | GLOBAL |
sort_buffer_size | numerisch | GLOBAL | SESSION |
sql_auto_is_null | boolesch | SESSION |
sql_big_selects | boolesch | SESSION |
sql_big_tables | boolesch | SESSION |
sql_buffer_result | boolesch | SESSION |
sql_log_bin | boolesch | SESSION |
sql_log_off | boolesch | SESSION |
sql_log_update | boolesch | SESSION |
sql_low_priority_updates | boolesch | GLOBAL | SESSION |
sql_max_join_size | numerisch | GLOBAL | SESSION |
sql_mode | Aufzählung | GLOBAL | SESSION |
sql_notes | boolesch | SESSION |
sql_quote_show_create | boolesch | SESSION |
sql_safe_updates | boolesch | SESSION |
sql_select_limit | numerisch | SESSION |
sql_slave_skip_counter | numerisch | GLOBAL |
updatable_views_with_limit | Aufzählung | GLOBAL | SESSION |
sql_warnings | boolesch | SESSION |
sync_binlog | numerisch | GLOBAL |
sync_frm | boolesch | GLOBAL |
storage_engine | Aufzählung | GLOBAL | SESSION |
table_definition_cache | numerisch | GLOBAL |
table_open_cache | numerisch | GLOBAL |
table_type | Aufzählung | GLOBAL | SESSION |
thread_cache_size | numerisch | GLOBAL |
time_zone | String | GLOBAL | SESSION |
timestamp | boolesch | SESSION |
tmp_table_size | Aufzählung | GLOBAL | SESSION |
transaction_alloc_block_size | numerisch | GLOBAL | SESSION |
transaction_prealloc_size | numerisch | GLOBAL | SESSION |
tx_isolation | Aufzählung | GLOBAL | SESSION |
unique_checks | boolesch | SESSION |
wait_timeout | numerisch | GLOBAL | SESSION |
warning_count | numerisch | SESSION |
Der Server verwaltet eine Vielzahl von Statusvariablen, die Daten zu seinem Betrieb enthalten. Sie können sich diese Variablen und die zugehörigen Werte mit der Anweisung SHOW STATUS
anzeigen lassen:
mysql> SHOW STATUS;
+-----------------------------------+------------+
| Variable_name | Value |
+-----------------------------------+------------+
| Aborted_clients | 0 |
| Aborted_connects | 0 |
| Bytes_received | 155372598 |
| Bytes_sent | 1176560426 |
...
| Connections | 30023 |
| Created_tmp_disk_tables | 0 |
| Created_tmp_files | 3 |
| Created_tmp_tables | 2 |
...
| Threads_created | 217 |
| Threads_running | 88 |
| Uptime | 1389872 |
+-----------------------------------+------------+
Viele Statusvariablen werden durch die Anweisung FLUSH STATUS
auf 0 zurückgesetzt.
Die Statusvariablen haben die nachfolgend beschriebenen Bedeutungen. Variablen ohne Versionsangabe waren bereits vor MySQL 5.1 vorhanden. Informationen zur Implementierungshistorie finden Sie im MySQL 5.0 Reference Manual.
Aborted_clients
Anzahl der Verbindungen, die abgebrochen wurden, weil der Client beendet wurde, ohne die Verbindung ordnungsgemäß zu schließen. Siehe auch Abschnitt A.2.10, „Kommunikationsfehler/abgebrochene Verbindung“.
Aborted_connects
Anzahl der fehlgeschlagenen Versuche, eine Verbindung mit dem MySQL-Server herzustellen. Siehe auch Abschnitt A.2.10, „Kommunikationsfehler/abgebrochene Verbindung“.
Binlog_cache_disk_use
Anzahl der Transaktionen, die den temporären Binärlog-Cache verwendeten, aber den Wert von binlog_cache_size
überstiegen, weswegen eine Temporärdatei zur Speicherung von Anweisungen aus der Transaktion benutzt wurde.
Binlog_cache_use
Anzahl der Transaktionen, die den Binärlog-Cache verwendet haben.
Bytes_received
Anzahl der Bytes, die von allen Clients empfangen wurden.
Bytes_sent
Anzahl der Bytes, die an alle Clients gesendet wurden.
Com_
xxx
Die Com_
-Variablen zum Zählen von Anweisungen geben die Häufigkeit an, mit der die Anweisung xxx
xxx
ausgeführt wurde. Für jeden Anweisungstyp gibt es eine Statusvariable. So zählen etwa Com_delete
und Com_insert
die DELETE
- bzw. INSERT
-Anweisungen.
Die folgenden Com_stmt_
-Statusvariablen sind vorhanden:
xxx
Com_stmt_prepare
Com_stmt_execute
Com_stmt_fetch
Com_stmt_send_long_data
Com_stmt_reset
Com_stmt_close
Diese Variablen stehen für vorbereitete Anweisungsbefehle. Ihre Namen beziehen sich auf den COM_
-Befehlssatz, der in der Vermittlungsschicht zum Einsatz kommt. Mit anderen Worten erhöhen sich ihre Werte immer dann, wenn vorbereitete Anweisungs-API-Aufrufe wie mysql_stmt_prepare(), mysql_stmt_execute() usw. ausgeführt werden. Allerdings erhöhen sich xxx
Com_stmt_prepare
, Com_stmt_execute
und Com_stmt_close
auch bei PREPARE
, EXECUTE
bzw. DEALLOCATE PREPARE
. Ferner erhöhen sich die Werte der älteren (d. h. seit MySQL 4.1.3 vorhandenen) Anweisungszählvariablen Com_prepare_sql
, Com_execute_sql
und Com_dealloc_sql
bei den Anweisungen PREPARE
, EXECUTE
und DEALLOCATE PREPARE
. Com_stmt_fetch
steht für die Gesamtanzahl der beim Holen von Cursorn abgesetzten Netzwerkrundreisen.
Alle Com_stmt_
-Variablen werden auch dann erhöht, wenn ein Argument einer vorbereiteten Anweisung unbekannt ist oder während der Ausführung ein Fehler aufgetreten ist. Mit anderen Worten entsprechen ihre Werte der Anzahl der abgesetzten (und nicht der erfolgreich verarbeiteten) Anfragen.
xxx
Compression
Gibt an, ob die Clientverbindung eine Komprimierung im Client/Server-Protokoll verwendet. Wurde in MySQL 5.1.2 hinzugefügt.
Connections
Anzahl der Versuche, eine Verbindung mit dem MySQL-Server herzustellen (unabhängig davon, ob diese erfolgreich waren oder nicht).
Created_tmp_disk_tables
Anzahl der vom Server bei der Ausführung von Anweisungen automatisch auf der Festplatte erstellten Temporärtabellen.
Created_tmp_files
Gibt an, wie viele Temporärdateien mysqld erstellt hat.
Created_tmp_tables
Anzahl der vom Server bei der Ausführung von Anweisungen automatisch im Speicher erstellten Temporärtabellen. Wenn Created_tmp_disk_tables
einen hohen Wert hat, sollten Sie den Wert von tmp_table_size
erhöhen, damit Temporärtabellen im Speicher statt auf Festplatte erstellt werden.
Delayed_errors
Anzahl der mit INSERT DELAYED
geschriebenen Datensätze, bei denen ein Fehler aufgetreten ist (wahrscheinlich duplicate key
).
Delayed_insert_threads
Anzahl der verzögerten INSERT DELAYED
-Threads, die in Verwendung sind.
Delayed_writes
Anzahl der geschriebenen INSERT DELAYED
-Datensätze.
Flush_commands
Anzahl der ausgeführten FLUSH
-Anweisungen.
Handler_commit
Anzahl der internen COMMIT
-Anweisungen.
Handler_discover
Der MySQL-Server kann bei der NDB Cluster
-Speicher-Engine fragen, ob sie eine Tabelle mit einem gegebenen Namen kennt. Dies bezeichnet man als Entdeckung. Handler_discover
gibt die Häufigkeit ein, mit der Tabellen mithilfe dieser Methode entdeckt wurden.
Handler_delete
Häufigkeit, mit der Datensätze aus Tabellen gelöscht wurden.
Handler_read_first
Häufigkeit, mit der der erste Eintrag aus einem Index gelesen wurde. Wenn dieser Wert hoch ist, kann man davon ausgehen, dass der Server eine große Zahl vollständiger Indexscans ausführt (z. B. für die Spalte SELECT col1 FROM foo
, vorausgesetzt, col1
ist indiziert).
Handler_read_key
Anzahl der Anforderungen zum Auslesen eines Datensatzes basierend auf einem Schlüssel. Wenn der Wert hoch ist, können Sie davon ausgehen, dass Ihre Tabellen passend für Ihre Abfragen indiziert sind.
Handler_read_next
Anzahl der Anforderungen zum Auslesen des nächsten Datensatzes in der Schlüsselreihenfolge. Dieser Wert wird hochgezählt, wenn Sie eine Indexspalte mit einer Bereichsbeschränkung abfragen oder einen Indexscan ausführen.
Handler_read_prev
Anzahl der Anforderungen zum Auslesen des vorherigen Datensatzes in der Schlüsselreihenfolge. Diese Lesemethode wird in erster Linie zur Optimierung von ORDER BY ... DESC
verwendet.
Handler_read_rnd
Anzahl der Anforderungen zum Auslesen eines Datensatzes basierend auf einer festen Position. Dieser Wert ist hoch, wenn Sie viele Abfragen ausführen, die eine Sortierung des Ergebnisses erfordern. Sie setzen dann wahrscheinlich viele Abfragen ab, die für MySQL das Scannen ganzer Tabellen erforderlich machen, oder verwenden Joins, die die Schlüssel nicht optimal nutzen.
Handler_read_rnd_next
Anzahl der Anforderungen zum Auslesen des nächsten Datensatzes in der Datendatei. Dieser Wert ist hoch, wenn Sie viele Tabellenscans ausführen. Im Allgemeinen lässt dies darauf schließen, dass Ihre Tabellen nicht korrekt indiziert sind oder Ihre Abfragen nicht so geschrieben sind, dass sie die vorhandenen Indizes nutzen können.
Handler_rollback
Anzahl der internen ROLLBACK
-Anweisungen.
Handler_update
Anzahl der Anforderungen zur Aktualisierung eines Datensatzes in einer Tabelle.
Handler_write
Anzahl der Anforderungen zum Einfügen eines Datensatzes in eine Tabelle.
Innodb_buffer_pool_pages_data
Anzahl der Seiten, die (schmutzige wie auch saubere) Daten enthalten.
Innodb_buffer_pool_pages_dirty
Anzahl der derzeit schmutzigen Seiten.
Innodb_buffer_pool_pages_flushed
Anzahl der Anforderungen nach einem Neuladen der Pufferpoolseiten.
Innodb_buffer_pool_pages_free
Anzahl der freien Seiten.
Innodb_buffer_pool_pages_latched
Anzahl der verriegelten Seiten im InnoDB
-Pufferpool. Dies sind die Seiten, die derzeit gelesen oder geschrieben oder aus einem anderen Grund nicht auf Festplatte synchronisiert werden können.
Innodb_buffer_pool_pages_misc
Anzahl der Seiten, die in Verwendung sind, weil sie aufgrund administrativer Mehrbelastung (z. B. Datensatzsperren oder eines adaptiven Hash-Index) zugewiesen wurden. Dieser Wert kann auch als Innodb_buffer_pool_pages_total
– Innodb_buffer_pool_pages_free
– Innodb_buffer_pool_pages_data
berechnet werden.
Innodb_buffer_pool_pages_total
Gesamtgröße des Pufferpools in Seiten.
Innodb_buffer_pool_read_ahead_rnd
Anzahl der vorab durchgeführten „zufälligen“ Leseoperationen, die durch InnoDB
eingeleitet wurden. Dies geschieht, wenn eine Abfrage einen Großteil einer Tabelle in zufälliger Reihenfolge scannt.
Innodb_buffer_pool_read_ahead_seq
Anzahl der vorab durchgeführten sequenziellen Leseoperationen, die durch InnoDB
eingeleitet wurden. Dies geschieht, wenn InnoDB
einen vollständigen sequenziellen Tabellenscan durchführt.
Innodb_buffer_pool_read_requests
Anzahl der Anforderungen logischer Leseoperationen durch InnoDB
.
Innodb_buffer_pool_reads
Anzahl der Anforderungen logischer Leseoperationen, die InnoDB
nicht aus dem Pufferpool erfüllen konnte, weswegen eine Leseoperationen für eine einzelne Seite ausgeführt werden musste.
Innodb_buffer_pool_wait_free
Normalerweise erfolgen Schreiboperationen in den InnoDB
-Pufferpool im Hintergrund. Wenn es allerdings notwendig ist, eine Seite zu lesen oder zu erstellen, und keine sauberen Seiten verfügbar sind, ist es auch erforderlich zu warten, bis die Seiten neu geschrieben wurden. Dieser Zähler enthält die Anzahl der Instanzen dieser Wartevorgänge. Wenn die Größe des Pufferpools korrekt eingestellt wurde, sollte dieser Wert niedrig sein.
Innodb_buffer_pool_write_requests
Anzahl der Schreiboperationen in den InnoDB
-Pufferpool.
Innodb_data_fsyncs
Anzahl der bislang aufgetretenen fsync()
-Operationen.
Innodb_data_pending_fsyncs
Aktuelle Anzahl anhängiger fsync()
-Operationen.
Innodb_data_pending_reads
Aktuelle Anzahl anhängiger Leseoperationen.
Innodb_data_pending_writes
Aktuelle Anzahl anhängiger Schreiboperationen.
Innodb_data_read
Menge der bislang gelesenen Daten (in Byte).
Innodb_data_reads
Gesamtanzahl der Datenleseoperationen.
Innodb_data_writes
Gesamtanzahl der Datenschreiboperationen.
Innodb_data_written
Menge der bislang geschriebenen Daten (in Byte).
Innodb_dblwr_writes
, Innodb_dblwr_pages_written
Anzahl der durchgeführten doppelten Schreiboperationen und Anzahl der Seiten, die zu diesem Zweck geschrieben wurden. Siehe auch Abschnitt 14.2.14.1, „Festplattenein- und -ausgaben“.
Innodb_log_waits
Häufigkeit, mit der der Logpuffer zu klein und ein Wartevorgang erforderlich war, bis der Vorgang nach dem Neuschreiben fortgesetzt werden konnte.
Innodb_log_write_requests
Anzahl der Logschreibeanforderungen.
Innodb_log_writes
Anzahl der physischen Schreiboperationen in die Logdatei.
Innodb_os_log_fsyncs
Anzahl der abgeschlossenen fsync()
-Schreiboperationen in die Logdatei.
Innodb_os_log_pending_fsyncs
Anzahl der anhängigen fsync()
-Operationen für die Logdatei.
Innodb_os_log_pending_writes
Anzahl der anhängigen Schreiboperationen für die Logdatei.
Innodb_os_log_written
Anzahl der in die Logdatei geschriebenen Bytes.
Innodb_page_size
Die einkompilierte InnoDB
-Seitengröße (standardmäßig 16 Kbyte). Viele Werte werden in Seiten gezählt. Die Angabe der Seitengröße erlaubt eine einfache Konvertierung in Bytes.
Innodb_pages_created
Anzahl der erstellten Seiten.
Innodb_pages_read
Anzahl der gelesenen Seiten.
Innodb_pages_written
Anzahl der geschriebenen Seiten.
Innodb_row_lock_current_waits
Anzahl der Datensatzsperren, auf die derzeit gewartet wird.
Innodb_row_lock_time
Die mit dem Erwirken von Datensatzsperren verbrachte Zeit (in Millisekunden).
Innodb_row_lock_time_avg
Die durchschnittliche Zeit zum Erwirken einer Datensatzsperre (in Millisekunden).
Innodb_row_lock_time_max
Die maximale Zeit zum Erwirken einer Datensatzsperre (in Millisekunden).
Innodb_row_lock_waits
Häufigkeit, mit der auf eine Datensatzsperre gewartet werden musste.
Innodb_rows_deleted
Anzahl der Datensätze, die aus InnoDB
-Tabellen gelöscht wurden.
Innodb_rows_inserted
Anzahl der Datensätze, die in InnoDB
-Tabellen eingefügt wurden.
Innodb_rows_read
Anzahl der Datensätze, die aus InnoDB
-Tabellen gelesen wurden.
Innodb_rows_updated
Anzahl der Datensätze, die in InnoDB
-Tabellen aktualisiert wurden.
Key_blocks_not_flushed
Anzahl der Schlüsselblöcke im Schlüssel-Cache, die geändert, aber noch nicht neu auf Festplatte geschrieben wurden.
Key_blocks_unused
Anzahl der unbenutzten Blöcke im Schlüssel-Cache. Sie können anhand dieses Wertes bestimmen, wie groß der verwendete Anteil des Schlüssel-Caches ist. Lesen Sie auch die Beschreibung zu key_buffer_size
in Abschnitt 5.2.2, „Server-Systemvariablen“.
Key_blocks_used
Anzahl der benutzten Blöcke im Schlüssel-Cache. Dieser Wert ist eine Art Hochwassermarke, die die maximale Anzahl von Blöcken angibt, die jemals gleichzeitig verwendet wurden.
Key_read_requests
Anzahl der Anforderungen zum Auslesen eines Schlüsselblocks aus dem Cache.
Key_reads
Die Anzahl physischer Lesezugriffe eines Schlüsselblocks von der Festplatte. Wenn der Wert von Key_reads
hoch ist, dann ist Ihr Wert für key_buffer_size
wahrscheinlich zu niedrig. Die Cache-Fehlrate kann berechnet werden als Key_reads
÷ Key_read_requests
.
Key_write_requests
Die Anzahl der Anforderungen zum Schreiben eines Schlüsselblocks in den Cache.
Key_writes
Anzahl physischer Schreibvorgänge eines Schlüsselblocks auf die Festplatte.
Last_query_cost
Gesamtkosten der letzten kompilierten Abfrage nach Berechnung durch den Abfrageoptimierer. Dieser Wert ist praktisch, um die Kosten verschiedener Abfragepläne für dieselbe Abfrage zu vergleichen. Der Vorgabewert 0 bedeutet, dass noch keine Abfrage kompiliert wurde. Last_query_cost
hat sitzungsbezogen Geltung.
Max_used_connections
Maximale Anzahl von Verbindungen, die seit dem Start des Servers gleichzeitig in Verwendung waren.
Not_flushed_delayed_rows
Anzahl der Datensätze, die darauf warten, in INSERT DELAY
-Warteschlangen geschrieben zu werden.
Open_files
Anzahl der offenen Dateien.
Open_streams
Anzahl der offenen Streams (hauptsächlich zum Loggen verwendet).
Open_tables
Anzahl der offenen Tabellen.
Opened_tables
Anzahl der Tabellen, die geöffnet wurden. Wenn der Wert von Opened_tables
hoch ist, dann ist Ihr Wert für table_open_cache
wahrscheinlich zu niedrig.
Qcache_free_blocks
Anzahl freier Speicherblöcke im Abfrage-Cache.
Qcache_free_memory
Menge des freien Speichers für den Abfrage-Cache.
Qcache_hits
Anzahl der Treffer im Abfrage-Cache.
Qcache_inserts
Anzahl der Abfragen, die zum Abfrage-Cache hinzugefügt wurden.
Qcache_lowmem_prunes
Anzahl der Abfragen, die wegen Speichermangels aus dem Abfrage-Cache gelöscht wurden.
Qcache_not_cached
Anzahl der nicht im Cache abgelegten Abfragen (weil diese entweder nicht speicherbar waren oder aufgrund der query_cache_type
-Einstellung nicht abgelegt wurden).
Qcache_queries_in_cache
Anzahl der im Abfrage-Cache registrierten Abfragen.
Qcache_total_blocks
Gesamtzahl von Blöcken im Abfrage-Cache.
Questions
Anzahl der Anweisungen, die Clients an den Server gesendet haben.
Rpl_status
Status der ausfallsicheren Replikation (noch nicht implementiert).
Select_full_join
Anzahl der Joins, die Tabellenscans durchführen, weil sie keine Indizes verwenden. Wenn der Wert nicht 0 ist, sollten Sie die Indizes Ihrer Tabellen sorgfältig prüfen.
Select_full_range_join
Anzahl der Joins, die eine Bereichssuche in einer Referenztabelle verwendet haben.
Select_range
Anzahl der Joins, die Bereiche in der ersten Tabelle verwendet haben. Dies ist normalerweise auch dann kein kritisches Problem, wenn der Wert zu groß ist.
Select_range_check
Anzahl der Joins ohne Schlüssel, die nach jedem Datensatz auf Schlüsselverwendung prüfen. Wenn der Wert nicht 0 ist, sollten Sie die Indizes Ihrer Tabellen sorgfältig prüfen.
Select_scan
Anzahl der Joins, die einen vollständigen Scan der ersten Tabelle durchgeführt haben.
Slave_open_temp_tables
Anzahl der Temporärtabellen, die der Slave-SQL-Thread derzeit geöffnet hält.
Slave_running
Ist ON
, wenn dieser Server ein Slave ist, der mit einem Master verbunden ist.
Slave_retried_transactions
Gesamthäufigkeit seit dem Serverstart, mit der der Replikations-Slave-SQL-Thread Transaktionen erneut versucht hat.
Slow_launch_threads
Anzahl der Threads, deren Erzeugung länger als die durch slow_launch_time
angegebene Anzahl von Sekunden dauerte.
Slow_queries
Anzahl der Abfragen, die länger als die durch long_query_time
angegebene Anzahl von Sekunden dauerten. Siehe auch Abschnitt 5.12.4, „Die Logdatei für langsame Anfragen“.
Sort_merge_passes
Anzahl der Merge-Durchgänge, die der Sortieralgorithmus durchführen musste. Wenn dieser Wert hoch ist, sollten Sie unter Umständen den Wert der Systemvariable sort_buffer_size
erhöhen.
Sort_range
Anzahl der Sortiervorgänge, die mit Bereichen durchgeführt wurden.
Sort_rows
Anzahl der sortierten Datensätze.
Sort_scan
Anzahl der Sortiervorgänge, die durchgeführt wurden, indem die Tabelle gescannt wurde.
Ssl_
xxx
Für SSL-Verbindungen verwendete Variablen.
Table_locks_immediate
Häufigkeit, mit der eine Tabellensperre sofort erwirkt werden konnte.
Table_locks_waited
Häufigkeit, mit der eine Tabellensperre nicht sofort erwirkt werden konnte und ein Wartevorgang erforderlich wurde. Wenn dieser Wert hoch und die Leistung problematisch niedrig ist, sollten Sie zunächst Ihre Abfragen optimieren und dann Ihre Tabelle(n) entweder unterteilen oder die Replikation verwenden.
Threads_cached
Anzahl der Threads im Thread-Cache.
Threads_connected
Anzahl der momentan offenen Verbindungen.
Threads_created
Anzahl der Threads, die zur Verwaltung von Verbindungen erstellt wurden. Wenn der Wert von Threads_created
hoch ist, sollten Sie den Wert von thread_cache_size
erhöhen. Die Cache-Trefferrate kann berechnet werden als Threads_created
÷ Connections
.
Threads_running
Anzahl nicht schlafender Threads.
Uptime
Dauer seit dem Serverstart (in Sekunden).
Der MySQL-Server kann in verschiedenen SQL-Modi betrieben werden und diese Modi auf unterschiedliche Weise für verschiedene Clients anwenden. Diese Funktionalität erlaubt es jeder Anwendung, den Betriebsmodus des Servers an die eigenen Anforderungen anzupassen.
Modi definieren, welche SQL-Syntax MySQL unterstützen soll und welche Art von Gültigkeitsprüfungen in Bezug auf die Daten durchgeführt werden sollen. Dies erleichtert die Verwendung von MySQL in verschiedenen Umgebungen und in Verbindung mit anderen Datenbankservern.
Sie stellen den SQL-Standardmodus ein, indem Sie mysqld mit der Option --sql-mode="
starten. modes
"modes
ist hierbei eine Liste verschiedener Modi, die durch Kommata (‘,
’) voneinander getrennt sind. Der Standardwert ist leer (d. h. es sind keine Modi ausgewählt). Der Wert modes
kann ebenfalls als leer angegeben werden (--sql-mode=""
), wenn Sie ihn explizit löschen wollen.
Sie können den SQL-Modus zur Laufzeit mithilfe der Anweisung SET [GLOBAL|SESSION] sql_mode='
zur Einstellung des Systemwertes modes
'sql_mode
ändern. Die Einstellung der GLOBAL
-Variable erfordert die Berechtigung SUPER
und wirkt sich auf den Betrieb aller Clients aus, die nachfolgend eine Verbindung herstellen. Von der Änderung der SESSION
-Variable ist nur der aktuelle Client betroffen. Jeder Client kann jederzeit seinen eigenen sql_mode
-Sitzungswert ändern.
Sie können den globalen oder sitzungsspezifischen sql_mode
-Wert mit den folgenden Anweisungen ändern:
SELECT @@global.sql_mode; SELECT @@session.sql_mode;
Die wahrscheinlich wichtigsten sql_mode
-Werte sind die folgenden:
Ändert Syntax und Verhalten so, dass eine höhere Kompatibilität mit Standard-SQL erzielt wird.
Wenn ein Wert nicht wie eingegeben in eine transaktionssichere Tabelle eingefügt werden konnte, wird die Anweisung abgebrochen. Bei nicht transaktionssicheren Tabellen wird die Anweisung abgebrochen, wenn der Wert in einer Anweisung für genau einen Datensatz oder im ersten Datensatz einer Anweisung für mehrere Datensätze erscheint. Weitere Informationen erhalten Sie im Verlauf dieses Abschnitts.
Hierbei verhält sich MySQL wie ein „traditionelles“ SQL-Datenbanksystem. Eine einfache Beschreibung dieses Modus wäre: „Gib eine Fehlermeldung anstelle einer Warnung aus, wenn ein falscher Wert in eine Spalte eingefügt wird“. Hinweis: Die Anweisung INSERT
/UPDATE
wird abgebrochen, sobald der Fehler bemerkt wird. Wenn Sie eine nicht transaktionssichere Speicher-Engine verwenden, ist dies ein unter Umständen unerwünschtes Verhalten, weil Datenänderungen, die vor dem Fehler ausgeführt wurden, nicht rückgängig gemacht werden, was zu einer „unvollständigen“ Aktualisierung führt.
Wenn in diesem Handbuch vom „strikten Modus“ die Rede ist, bezeichnet dies einen Modus, in dem zumindest STRICT_TRANS_TABLES
oder STRICT_ALL_TABLES
aktiviert ist.
Die folgende Liste beschreibt alle unterstützten Modi:
Führt keine vollständige Datumsüberprüfung durch. Geprüft wird nur, ob die Monatsangabe zwischen 1 und 12 und die Tagesangabe zwischen 1 und 31 liegt. Dies ist sehr praktisch für Webanwendungen, bei denen man die Jahres-, Monats- und Tagesangabe drei verschiedenen Feldern entnimmt und diese Angaben dann genau so gespeichert werden sollen, wie der Benutzer sie eingegeben hat (d. h. ohne Plausibilitätsprüfung). Dieser Modus betrifft DATE
- und DATETIME
-Spalten. Für TIMESTAMP
-Spalten gilt er hingegen nicht, da diese immer ein gültiges Datum erfordern.
Für den Server ist es erforderlich, dass Monats- und Tagesangaben gültig sind und sich nicht einfach nur in den Bereichen 1 bis 12 bzw. 1 bis 31 bewegen. Wenn der strikte Modus deaktiviert ist, werden ungültige Daten wie '2004-04-31'
in '0000-00-00'
umgewandelt, und es wird eine Warnung erzeugt. Ist der strikte Modus hingegen aktiviert, dann erzeugen ungültige Datumsangaben einen Fehler. Um derartige Daten zuzulassen, aktivieren Sie ALLOW_INVALID_DATES
.
Hierbei wird ‘"
’ als Anführungszeichen für Bezeichner (wie ‘`
’) und nicht als String-Anführungszeichen behandelt. Auch wenn dieser Modus aktiviert ist, können Sie ‘`
’ als Anführungszeichen für Bezeichner verwenden. Ist ANSI_QUOTES
aktiviert, dann dürfen Sie doppelte Anführungszeichen für einen literalen String verwenden, da dieser andernfalls als Bezeichner erkannt würde.
Erzeugt im strikten Modus einen Fehler (sonst eine Warnung), wenn bei INSERT
- oder UPDATE
-Anweisungen eine Division durch Null (oder MOD(X,0)
) auftritt. Wenn dieser Modus nicht aktiviert ist, gibt MySQL stattdessen NULL
als Ergebnis einer Division durch Null zurück. Bei INSERT IGNORE
oder UPDATE IGNORE
erzeugt MySQL eine Warnung bezüglich einer Division durch Null, das Ergebnis des Vorgangs ist aber NULL
.
Die Vorrangstellung des Operators NOT
besteht darin, dass Ausdrücke wie NOT a BETWEEN b AND c
als NOT (a BETWEEN b AND c)
verarbeitet werden. Bei einigen älteren Versionen von MySQL wurde der Ausdruck hingegen als (NOT a) BETWEEN b AND c
aufgefasst. Dieses ältere Vorrangsverhalten kann verwendet werden, indem man den SQL-Modus HIGH_NOT_PRECEDENCE
aktiviert.
mysql>SET sql_mode = '';
mysql>SELECT NOT 1 BETWEEN -5 AND 5;
-> 0 mysql>SET sql_mode = 'broken_not';
mysql>SELECT NOT 1 BETWEEN -5 AND 5;
-> 1
Gestattet Leerzeichen zwischen einem Funktionsnamen und dem Zeichen ‘(
’. Hierdurch wird die Behandlung aller Funktionsnamen als reservierte Wörter erzwungen. Dies wiederum bedingt, dass Sie Datenbank-, Tabellen- oder Spaltennamen, die Sie verwenden wollen, als referenzierte Wörter in Anführungszeichen setzen müssen. Weil es beispielsweise eine Funktion USER()
gibt, sind die Namen der Tabelle user
in der mysql
-Datenbank und der Spalte User
in dieser Tabelle reservierte Wörter, müssen also in Anführungszeichen gesetzt werden:
SELECT "User" FROM mysql."user";
Der SQL-Modus IGNORE_SPACE
gilt für integrierte Funktionen, nicht aber für gespeicherte Routinen. Nach einem Routinennamen müssen unabhängig davon, ob IGNORE_SPACE
aktiviert ist oder nicht, immer Leerzeichen stehen dürfen.
Verhindert, dass GRANT
automatisch neue Benutzer erstellt, sofern es dies tun würde (es sei denn, es wird ein nicht leeres Passwort angegeben).
NO_AUTO_VALUE_ON_ZERO
wirkt sich auf die Verarbeitung von AUTO_INCREMENT
-Spalten aus. Normalerweise erzeugen Sie die nächste Sequenznummer für die Spalte, indem Sie entweder NULL
oder 0
einfügen. NO_AUTO_VALUE_ON_ZERO
unterdrückt dieses Verhalten für 0
, sodass nur NULL
die nächste Sequenznummer erzeugt.
Dieser Modus kann nützlich sein, wenn 0
in einer AUTO_INCREMENT
-Spalte einer Tabelle gespeichert wurde. (Nebenbei gesagt: Das Speichern von 0
ist keine empfehlenswerte Vorgehensweise.) Wenn Sie beispielsweise die Tabelle mit mysqldump speichern und sie dann neu laden, erzeugt MySQL normalerweise neue Sequenznummern, sobald die 0
-Werte gefunden werden; das Ergebnis ist also eine Tabelle, deren Inhalt sich von dem ursprünglich gespeicherten unterscheidet. Die Aktivierung von NO_AUTO_VALUE_ON_ZERO
vor dem Neuladen der Speicherauszugsdatei löst dieses Problem. mysqldump schließt nun automatisch eine Anweisung in seine Ausgabe mit ein, die NO_AUTO_VALUE_ON_ZERO
aktiviert, um das Problem zu vermeiden.
Deaktiviert die Verwendung des Backslashs (‘\
’) als Escape-Zeichen innerhalb von Strings. Wenn dieser Modus aktiviert ist, wird der Backslash zu einem ganz gewöhnlichen Zeichen.
Wenn Sie eine Tabelle erstellen, werden in diesem Modus alle INDEX DIRECTORY
- und DATA DIRECTORY
-Direktiven ignoriert. Diese Option ist praktisch bei Slave-Replikationsservern.
NO_ENGINE_SUBSTITUTION
Verhindert die automatische Ersetzung der vorgabeseitigen Speicher-Engine, wenn eine Anweisung wie CREATE TABLE
eine Speicher-Engine angibt, die deaktiviert oder nicht einkompiliert ist.
Sorgt dafür, dass MySQL-spezifische Spaltenoptionen in der Ausgabe von SHOW CREATE TABLE
nicht angegeben werden. Dieser Modus wird von mysqldump im Portabilitätsmodus verwendet.
Sorgt dafür, dass MySQL-spezifische Indexoptionen in der Ausgabe von SHOW CREATE TABLE
nicht angegeben werden. Dieser Modus wird von mysqldump im Portabilitätsmodus verwendet.
Sorgt dafür, dass MySQL-spezifische Tabellenoptionen (wie ENGINE
) in der Ausgabe von SHOW CREATE TABLE
nicht angegeben werden. Dieser Modus wird von mysqldump im Portabilitätsmodus verwendet.
Bei Subtraktionsoperationen wird das Ergebnis nicht als UNSIGNED
gekennzeichnet, wenn einer der Operanden ohne Vorzeichen ist. Beachten Sie, dass hiermit BIGINT UNSIGNED
nicht mehr in allen Kontexten hundertprozentig einsetzbar ist. Siehe auch Abschnitt 12.8, „Cast-Funktionen und Operatoren“.
Im strikten Modus wird '0000-00-00'
nicht als gültiges Datum zugelassen. Mit der Option IGNORE
können Sie trotzdem Nulldatumsangaben einfügen. Außerhalb des strikten Modus wird das Datum zwar akzeptiert, aber es wird eine Warnung erzeugt.
Im strikten Modus werden Daten nicht akzeptiert, wenn die Monats- oder Tagesangabe 0 ist. Wenn der Modus mit der Option IGNORE
verwendet wird, fügt MySQL das Datum '0000-00-00'
für derartige Datumsangaben ein. Außerhalb des strikten Modus wird das Datum zwar akzeptiert, aber es wird eine Warnung erzeugt.
Erlaubt keine Abfragen, bei denen die GROUP BY
-Klausel auf eine Spalte verweist, die in der Ausgabespaltenliste nicht vorhanden ist.
Behandelt ||
als Operator zur String-Verkettung (also identisch mit CONCAT()
) statt als Synonym von OR
.
Behandelt REAL
als Synonym von FLOAT
. Standardmäßig behandelt MySQL REAL
als Synonym von DOUBLE
.
Aktiviert den strikten Modus für alle Speicher-Engines. Ungültige Datenwerte werden abgewiesen. Zusätzliche Informationen folgen.
Aktiviert den strikten Modus für transaktionssichere Speicher-Engines sowie – sofern möglich – für nicht transaktionssichere Speicher-Engines. Zusätzliche Informationen folgen.
Der strikte Modus steuert, wie MySQL Eingabewerte behandelt, die ungültig sind oder fehlen. Ein Wert kann aus mehreren Gründen ungültig sein. So kann er den falschen Datentyp für die Spalte aufweisen oder außerhalb des zulässigen Bereichs liegen. Ein Wert fehlt, wenn ein neuer Datensatz, der eingefügt werden soll, keinen Wert für eine Spalte enthält, für die keine explizite DEFAULT
-Klausel definiert ist.
Bei transaktionssicheren Tabellen tritt bei ungültigen oder fehlenden Werten in einer Anweisung ein Fehler auf, wenn einer der Modi STRICT_ALL_TABLES
oder STRICT_TRANS_TABLES
aktiviert ist. Die Anweisung wird abgebrochen, und es erfolgt ein Rollback.
Bei nicht transaktionssicheren Tabellen ist das Verhalten in beiden Modi gleich, wenn der betreffende Wert im ersten einzufügenden oder zu aktualisierenden Datensatz auftritt. Die Anweisung wird abgebrochen, und die Tabelle bleibt unverändert. Wenn die Anweisung mehrere Datensätze einfügt oder ändert und der unpassende Wert im zweiten oder einem nachfolgenden Datensatz auftritt, dann hängt das Ergebnis davon ab, welche Option aktiviert ist:
Bei STRICT_ALL_TABLES
gibt MySQL einen Fehler zurück und ignoriert die verbleibenden Datensätze. Allerdings bleiben die zuvor durch Einfügung oder Aktualisierung an Datensätzen vorgenommenen Änderung erhalten. Das bedeutet, dass unter Umständen eine Teilaktualisierung erfolgt, was vielleicht nicht wünschenswert ist. Um dies zu vermeiden, sollten Sie am besten Anweisungen nur für jeweils einen Datensatz verwenden, da diese abgebrochen werden können, ohne die Tabelle zu verändern.
Bei STRICT_TRANS_TABLES
wandelt MySQL einen ungültigen Wert in den nächstgelegenen für die Spalte gültigen Wert um und fügt diesen umgewandelten Wert dann ein. Fehlt ein Wert, dann fügt MySQL den impliziten Vorgabewert für den Spaltendatentyp ein. In beiden Fällen erzeugt MySQL zudem eine Warnung (statt eines Fehlers) und fährt dann mit der Verarbeitung der Anweisung fort. Implizite Vorgabewerte sind in Abschnitt 11.1.4, „Vorgabewerte von Datentypen“, beschrieben.
Der strikte Modus untersagt ungültige Datumswerte wie '2004-04-31'
. Nicht verboten sind hingegen Datumsangaben mit Nullbestandteilen wie etwa '2004-04-00'
oder „Nulldaten“. Um auch diese zu unterbinden, aktivieren Sie die SQL-Modi NO_ZERO_IN_DATE
und NO_ZERO_DATE
zusätzlich zum strikten Modus.
Wenn Sie den strikten Modus nicht verwenden (d. h. weder STRICT_TRANS_TABLES
noch STRICT_ALL_TABLES
sind aktiviert), dann fügt MySQL korrigierte Werte für ungültige oder fehlende Angaben ein und erzeugt Warnungen. Im strikten Modus können Sie dieses Verhalten erzeugen, indem Sie INSERT IGNORE
bzw. UPDATE IGNORE
verwenden. Siehe auch Abschnitt 13.5.4.25, „SHOW WARNINGS
“.
Die folgenden Spezialmodi sind als Abkürzungen für Kombinationen von Moduswerten aus obiger Liste aufzufassen.
Die Beschreibungen enthalten alle Moduswerte, die in der aktuellen MySQL-Version vorhanden sind. Bei älteren Versionen enthalten die Kombinationsmodi keine einzelnen Moduswerte, die erst in neueren Versionen verfügbar sind.
Entspricht REAL_AS_FLOAT
, PIPES_AS_CONCAT
, ANSI_QUOTES
, IGNORE_SPACE
. Siehe auch Abschnitt 1.9.3, „MySQL im ANSI-Modus laufen lassen“.
Entspricht PIPES_AS_CONCAT
, ANSI_QUOTES
, IGNORE_SPACE
, NO_KEY_OPTIONS
, NO_TABLE_OPTIONS
, NO_FIELD_OPTIONS
.
Entspricht PIPES_AS_CONCAT
, ANSI_QUOTES
, IGNORE_SPACE
, NO_KEY_OPTIONS
, NO_TABLE_OPTIONS
, NO_FIELD_OPTIONS
, NO_AUTO_CREATE_USER
.
Entspricht PIPES_AS_CONCAT
, ANSI_QUOTES
, IGNORE_SPACE
, NO_KEY_OPTIONS
, NO_TABLE_OPTIONS
, NO_FIELD_OPTIONS
.
Entspricht NO_FIELD_OPTIONS
, HIGH_NOT_PRECEDENCE
.
Entspricht NO_FIELD_OPTIONS
, HIGH_NOT_PRECEDENCE
.
Entspricht PIPES_AS_CONCAT
, ANSI_QUOTES
, IGNORE_SPACE
, NO_KEY_OPTIONS
, NO_TABLE_OPTIONS
, NO_FIELD_OPTIONS
, NO_AUTO_CREATE_USER
.
Entspricht PIPES_AS_CONCAT
, ANSI_QUOTES
, IGNORE_SPACE
, NO_KEY_OPTIONS
, NO_TABLE_OPTIONS
, NO_FIELD_OPTIONS
.
Entspricht STRICT_TRANS_TABLES
, STRICT_ALL_TABLES
, NO_ZERO_IN_DATE
, NO_ZERO_DATE
, ERROR_FOR_DIVISION_BY_ZERO
, NO_AUTO_CREATE_USER
.
Beim Herunterfahren des Servers laufen die folgenden Vorgänge ab:
Das Herunterfahren wird eingeleitet.
Das Herunterfahren des Servers kann auf mehreren Wegen veranlasst werden. So kann etwa ein Benutzer mit der Berechtigung SHUTDOWN
den Befehl mysqladmin shutdown ausführen. mysqladmin kann auf jeder von MySQL unterstützen Plattform benutzt werden. Auch andere betriebssystemspezifische Methoden sind möglich, um das Herunterfahren einzuleiten: Unter Unix wird der Server heruntergefahren, wenn er ein SIGTERM
-Signal empfängt. Unter Windows wird ein Server, der als Dienst ausgeführt wird, beendet, wenn der Dienste-Manager ihn dazu anweist.
Bei Bedarf erstellt der Server einen Abschaltungs-Thread.
Je nachdem, wie das Herunterfahren eingeleitet wurde, erstellt der Server unter Umständen einen Thread, um den Abschaltvorgang zu verwalten. Wurde das Herunterfahren von einem Client angefordert, dann wird ein Abschaltungs-Thread erstellt. Ist das Herunterfahren Folge eines empfangenen SIGTERM
-Signals, dann erledigt der Signal-Thread die Abschaltung entweder selbst oder erstellt zu diesem Zweck einen separaten Thread. Versucht der Server vergeblich einen Abschaltungs-Thread zu erstellen (etwa weil nicht genügend Speicher zur Verfügung steht), dann gibt er eine Diagnosemeldung aus, die im Fehlerlog erscheint:
Error: Can't create thread to kill server
Der Server nimmt keine neuen Verbindungen mehr an.
Um die Initialisierung neuer Aktivitäten während des Herunterfahrens zu vermeiden, beendet der Server die Annahme neuer Clientverbindungen. Er tut dies, indem er die Netzwerkverbindungen schließt, auf denen er normalerweise auf Verbindungen horcht: den TCP/IP-Port, die Unix-Socketdatei und die Named Pipe und den gemeinsamen Speicher unter Windows.
Der Server beendet alle aktuellen Aktivitäten.
Für jeden Thread, der mit einer Clientverbindung verknüpft ist, wird die Verbindung zum Client abgebrochen, und der Thread wird als terminiert gekennzeichnet. Wenn ein Thread diese Kennzeichnung erkennt, beendet er sich. Threads leer laufender Verbindungen beenden sich sehr schnell. Threads hingegen, die zum betreffenden Zeitpunkt Anweisungen verarbeiten, überprüfen ihren Status regelmäßig und benötigen insofern länger, um sich zu beenden. Weitere Informationen zur Thread-Terminierung finden Sie in Abschnitt 13.5.5.3, „KILL
“. Beachten Sie dort insbesondere die Erläuterungen zu terminierten REPAIR TABLE
- und OPTIMIZE TABLE
-Operationen an MyISAM
-Tabellen.
Wenn bei Threads eine Transaktion offen ist, wird diese via Rollback rückgängig gemacht. Beachten Sie, dass, wenn ein Thread eine nicht transaktionssichere Tabelle aktualisiert, Anweisungen für mehrere Datensätze wie UPDATE
oder INSERT
eine teilaktualisierte Tabelle entstehen lassen können, weil der Vorgang vor seinem Abschluss terminiert werden kann.
Wenn der Server ein Master-Replikationsserver ist, werden Threads, die derzeit angeschlossenen Slaves zugeordnet sind, wie andere Client-Threads behandelt. Das bedeutet, dass jeder dieser Threads als terminiert gekennzeichnet wird und sich beendet, sobald er zum nächsten Mal seinen Status überprüft.
Ist der Server ein Slave-Replikationsserver, dann werden die E/A- und SQL-Threads – sofern aktiv – beendet, bevor Client-Threads als terminiert gekennzeichnet werden. Der SQL-Thread darf seine aktuelle Anweisung abschließen, um Replikationsprobleme zu vermeiden, und wird dann beendet. Befand sich der SQL-Thread zu diesem Zeitpunkt mitten in einer Transaktion, dann wird diese Transaktion rückgängig gemacht.
Speicher-Engines werden heruntergefahren oder geschlossen.
An dieser Stelle wird der Tabellen-Cache auf die Festplatte geschrieben, und alle offenen Tabellen werden geschlossen.
Alle Speicher-Engines führen ggf. Vorgänge aus, die für die jeweils verwalteten Tabellen erforderlich sind. So synchronisiert MyISAM
beispielsweise alle anhängigen Indexschreiboperationen für eine Tabelle. InnoDB
schreibt seinen Pufferpool auf die Festplatte (sofern innodb_fast_shutdown
nicht 2 ist), speichert die aktuelle LSN in den Tablespace und beendet seine eigenen internen Threads.
Der Server wird beendet.
Ein MySQL-Max-Server ist eine Version des MySQL-Servers mysqld, in die zusätzliche Funktionen integriert sind. Welche MySQL-Max-Distribution verwendet werden kann, hängt von Ihrer Plattform ab:
Unter Windows enthalten MySQL-Binärdistributionen sowohl den Standardserver (mysqld.exe
) als auch den MySQL-Max-Server (mysqld-max.exe), d. h. es ist keine gesonderte Distribution erforderlich; Sie verwenden einfach eine normale Windows-Distribution. Siehe auch Abschnitt 2.3, „Installation von MySQL unter Windows“.
Wenn Sie MySQL unter Linux mithilfe von RPM-Distributionen installieren, setzt das MySQL-Max
-RPM voraus, dass Sie das reguläre Server-RPM bereits installiert haben. Sie installieren also zunächst mithilfe des MySQL-server
-RPM einen Standardserver namens mysqld und nachfolgend mit dem MySQL-Max
-RPM einen Server namens mysqld-max. Weitere Informationen zu Linux-RPM-Paketen finden Sie in Abschnitt 2.4, „MySQL unter Linux installieren“.
Alle anderen MySQL-Max-Distributionen enthalten einen einzelnen Server namens mysqld, der jedoch die Zusatzfunktionen enthält.
Sie finden die MySQL-Max-Binärdateien auf der MySQL AB-Website unter http://dev.mysql.com/downloads/.
MySQL AB erstellt MySQL-Max-Server unter Verwendung der folgenden configure-Optionen:
--with-server-suffix=-max
Diese Option fügt dem Versions-String mysqld das Suffix -max
hinzu.
--with-innodb
Diese Option aktiviert die Unterstützung für die InnoDB
-Speicher-Engine. MySQL-Max-Server enthalten die InnoDB
-Unterstützung generell. Seit MySQL 4.0 ist InnoDB
standardmäßig in allen Binärdistributionen enthalten, d. h. Sie benötigen zur InnoDB
-Unterstützung keinen MySQL-Max-Server.
--with-bdb
Diese Option aktiviert die Unterstützung der BDB
-Speicher-Engine (Berkeley DB) auf denjenigen Plattformen, für die BDB
verfügbar ist. (Beachten Sie die nachfolgenden Hinweise.)
--with-blackhole-storage-engine
Diese Option aktiviert die Unterstützung für die BLACKHOLE
-Speicher-Engine.
--with-csv-storage-engine
Diese Option aktiviert die Unterstützung für die CSV
-Speicher-Engine.
--with-example-storage-engine
Diese Option aktiviert die Unterstützung für die EXAMPLE
-Speicher-Engine.
--with-federated-storage-engine
Diese Option aktiviert die Unterstützung für die FEDERATED
-Speicher-Engine.
--with-ndbcluster
Diese Option aktiviert die Unterstützung der NDB Cluster
-Speicher-Engine auf denjenigen Plattformen, für die Cluster verfügbar sind. (Beachten Sie die nachfolgenden Hinweise.)
USE_SYMDIR
Diese Definition wird aktiviert, um die Unterstützung symbolischer Datenbankverknüpfungen unter Windows zu aktivieren. Seit MySQL 4.0 ist die Unterstützung symbolischer Verknüpfungen für alle Windows-Server aktiviert, d. h. Sie benötigen hierfür keinen MySQL-Max-Server.
MySQL-Max-Binärdistributionen sind praktisch für Benutzer, die vorkompilierte Programme installieren wollen. Wenn Sie MySQL unter Verwendung einer Quelldistribution erstellen, können Sie Ihren eigenen Max-Server erstellen, indem Sie zum Zeitpunkt der Konfiguration genau diejenigen Funktionen aktivieren, mit denen die MySQL-Max-Binärdistributionen erstellt werden.
Sofern möglich, enthalten MySQL-Max-Server die BDB
-Speicher-Engine; diese wird jedoch nicht von allen Plattformen unterstützt.
Zurzeit werden MySQL-Cluster nur von Linux (auf den meisten Plattformen), Solaris und Mac OS X unterstützt. Einige Benutzer haben berichtet, dass sie einen aus einer Quelldistribution erstellten MySQL-Cluster erfolgreich unter BSD-Betriebssystemen zum Laufen bekommen haben; hierfür gibt es aber derzeit keinen offiziellen Support. Beachten Sie, dass auch dann, wenn die Server mit Cluster-Unterstützung kompiliert werden, die NDB Cluster
-Speicher-Engine standardmäßig nicht aktiviert wird. Sie müssen den Server mit der Option --ndbcluster
starten, um ihn als Teil eines MySQL-Clusters verwenden zu können. (Detaillierte Informationen finden Sie in Abschnitt 16.4, „MySQL Cluster: Konfiguration“.)
Die folgende Tabelle listet die Plattformen auf, deren MySQL-Max-Binärdateien Unterstützung für BDB
und NDB-Cluster enthalten.
System | BDB-Unterstützung | NDB-Unterstützung |
AIX 4.3 | Nein | Nein |
HP-UX 11.0 | Nein | Nein |
Linux-Alpha | Nein | Ja |
Linux-IA-64 | Nein | Nein |
Linux-Intel | Ja | Ja |
Mac OS X | Nein | Ja |
NetWare | Nein | Nein |
SCO OSR5 | Ja | Nein |
Solaris-SPARC | Ja | Ja |
Solaris-Intel | Nein | Ja |
UnixWare | Ja | Nein |
Windows NT/2000/XP | Ja | Nein |
Um herauszufinden, welche Speicher-Engines Ihr Server unterstützt, verwenden Sie die SHOW ENGINES
-Anweisung. (Siehe auch Abschnitt 13.5.4.9, „SHOW ENGINES
“.) Zum Beispiel:
mysql> SHOW ENGINES\G
*************************** 1. row ***************************
Engine: MEMORY
Support: YES
Comment: Hash based, stored in memory, useful for temporary tables
Transactions: NO
XA: NO
Savepoints: NO
*************************** 2. row ***************************
Engine: CSV
Support: YES
Comment: CSV storage engine
Transactions: NO
XA: NO
Savepoints: NO
*************************** 3. row ***************************
Engine: MRG_MYISAM
Support: YES
Comment: Collection of identical MyISAM tables
Transactions: NO
XA: NO
Savepoints: NO
*************************** 4. row ***************************
Engine: MyISAM
Support: DEFAULT
Comment: Default engine as of MySQL 3.23 with great performance
Transactions: NO
XA: NO
Savepoints: NO
...
Die exakte Ausgabe von SHOW ENGINES
kann je nach verwendeter MySQL-Version (und aktivierten Funktionen) variieren. Die Support
-Werte in der Ausgabe geben den Umfang der Unterstützung für die jeweilige Funktion entsprechend nachfolgender Tabelle an:
Wert | Bedeutung |
YES | Diese Funktion wird unterstützt und ist aktiv. |
NO | Die Funktion wird nicht unterstützt. |
DISABLED | Die Funktion wird unterstützt, wurde aber deaktiviert. |
Der Wert NO
bedeutet, dass der Server ohne Unterstützung für die Funktion kompiliert wurde; sie kann also zur Laufzeit nicht aktiviert werden.
Der Wert DISABLED
tritt entweder auf, weil der Server mit einer Option gestartet wurde, die die Funktion deaktiviert, oder weil nicht alle Optionen angegeben wurden, die für die Aktivierung der Funktion erforderlich sind. Im zweiten Fall sollte im Fehlerlog ein Eintrag vorhanden sein, der angibt, warum die Option deaktiviert ist. Siehe auch Abschnitt 5.12.1, „Die Fehler-Logdatei“.
DISABLED
wird unter Umständen auch für eine Speicher-Engine angezeigt, wenn der Server zwar mit Unterstützung für diese Engine kompiliert, aber mit der Option --skip-
gestartet wurde. So deaktiviert beispielsweise engine
--skip-innodb
die InnoDB
-Engine. Bei der NDB Cluster
-Speicher-Engine bedeutet DISABLED
, dass der Server mit Unterstützung für MySQL-Cluster kompiliert, aber nicht mit der Option --ndb-cluster
gestartet wurde.
Alle MySQL-Server unterstützen MyISAM
-Tabellen, weil MyISAM
die vorgabeseitige Speicher-Engine ist.
Dieser Abschnitt beschreibt verschiedene Programme, die zum Starten des MySQL-Servers mysqld verwendet werden.
mysqld_safe ist die empfohlene Methode zum Starten eines mysqld-Servers unter Unix und NetWare. mysqld_safe fügt einige Sicherheitsfunktionen hin zu, so etwa das Neustarten des Servers bei Auftreten eines Fehlers und das Loggen von Laufzeitinformationen in eine Fehlerlogdatei. Das NetWare-spezifische Verhalten wird im weiteren Verlauf dieses Abschnitts beschrieben.
Hinweis: Um die Abwärtskompatibilität mit älteren Versionen von MySQL aufrechtzuerhalten, enthalten MySQL-Binärdistributionen auch weiterhin safe_mysqld als symbolische Verknüpfung mit mysqld_safe. Allerdings sollten Sie sich nicht fest darauf verlassen, da dieses Feature mit an Sicherheit grenzender Wahrscheinlichkeit in Zukunft entfernt werden wird.
Standardmäßig versucht mysqld_safe eine ausführbare Datei namens mysqld-max zu starten, sofern diese vorhanden ist; andernfalls wird mysqld gestartet. Beachten Sie die Auswirkungen dieses Verhaltens:
Unter Linux ist das MySQL-Max
-RPM auf dieses Verhalten von mysqld_safe angewiesen. Das RPM installiert eine ausführbare Datei namens mysqld-max; aufgrund dessen verwendet mysqld_safe ab sofort automatisch diese Datei anstelle von mysqld.
Wenn Sie eine MySQL-Max-Distribution installieren, die einen Server namens mysqld-max enthält, und nachfolgend auf eine Nicht-Max-Version von MySQL aktualisieren wollen, dann beachten Sie, dass mysqld_safe nach wie vor versuchen wird, den alten Server mysqld-max auszuführen. Führen Sie ein solches Upgrade durch, dann sollten Sie den alten mysqld-max-Server manuell entfernen, um sicherzustellen, dass mysqld_safe den neuen Server mysqld ausführt.
Um dieses Standardverhalten außer Kraft zu setzen und den Namen des auszuführenden Servers explizit anzugeben, müssen Sie eine der Optionen --mysqld
oder --mysqld-version
für mysqld_safe angeben. Sie können auch --ledir
verwenden, um das Verzeichnis anzugeben, in dem mysqld_safe nach dem Server suchen soll.
Viele der Optionen für mysqld_safe sind identisch mit den Optionen für mysqld. Siehe auch Abschnitt 5.2.1, „Befehlsoptionen für mysqld“.
Alle für mysqld_safe auf der Befehlszeile angegebenen Optionen werden an mysqld übergeben. Wenn Sie Optionen verwenden wollen, die für mysqld_safe spezifisch sind und von mysqld nicht unterstützt werden, dann geben Sie sie nicht über die Befehlszeile an. Stattdessen sollten Sie sie im Abschnitt [mysqld_safe]
einer Optionsdatei auflisten. Siehe auch Abschnitt 4.3.2, „my.cnf-Optionsdateien“.
mysqld_safe liest alle Optionen aus den Abschnitten [mysqld]
, [server]
und [mysqld_safe]
in Optionsdateien aus. Aus Gründen der Abwärtskompatibilität werden auch [safe_mysqld]
-Abschnitte ausgelesen, aber Sie sollten diese Abschnitte bei MySQL 5.1-Installationen in [mysqld_safe]
umbenennen.
mysqld_safe unterstützt die folgenden Optionen:
--help
Zeigt eine Hilfsmeldung an und wird dann beendet.
--autoclose
(Nur NetWare.) mysqld_safe stellt unter NetWare eine Bildschirmpräsenz bereit. Wenn Sie das NLM mysqld_safe entladen (herunterfahren), verschwindet der Bildschirm standardmäßig nicht. Stattdessen wird eine Benutzereingabe angefordert:
*<NLM has terminated; Press any key to close the screen>*
Wenn Sie hingegen wollen, dass NetWare den Bildschirm automatisch schließt, dann verwenden Sie die Option --autoclose
für mysqld_safe.
--basedir=
path
Der Pfad zum MySQL-Installationsverzeichnis.
--core-file-size=
size
Größe der Speicherauszugsdatei, die mysqld erstellen können soll. Der Optionswert wird an ulimit -c übergeben.
--datadir=
path
Der Pfad zum Datenverzeichnis.
--defaults-extra-file=
path
Der Name einer Optionsdatei, die zusätzlich zu den normalen Optionsdateien ausgelesen wird. Wenn diese Option verwendet wird, muss Sie auf der Befehlszeile die erste angegebene Option sein.
--defaults-file=
file_name
Der Name einer Optionsdatei, die anstelle der normalen Optionsdateien ausgelesen wird. Wenn diese Option verwendet wird, muss Sie auf der Befehlszeile die erste angegebene Option sein.
--ledir=
path
Wenn mysqld_safe den Server nicht finden kann, können Sie diese Option verwenden, um einen Pfadnamen zu dem Verzeichnis anzugeben, in dem sich der Server befindet.
--log-error=
file_name
Schreibt das Fehlerlog in die angegebene Datei. Siehe auch Abschnitt 5.12.1, „Die Fehler-Logdatei“.
--mysqld=
prog_name
Name des Serverprogramms (im Verzeichnis ledir
), das Sie starten wollen. Diese Option ist erforderlich, wenn Sie die MySQL-Binärdistribution verwenden, aber das Datenverzeichnis sich außerhalb der Binärdistribution befindet. Wenn mysqld_safe den Server nicht finden kann, können Sie die Option --ledir
verwenden, um einen Pfadnamen zu dem Verzeichnis anzugeben, in dem sich der Server befindet.
--mysqld-version=
suffix
Diese Option ähnelt --mysqld
, Sie geben aber nur das Suffix für den Serverprogrammnamen an. Als Basisname wird mysqld vorausgesetzt. Wenn Sie beispielsweise --mysqld-version=max
verwenden, startet mysqld_safe das Programm mysqld-max im Verzeichnis ledir
. Wenn das Argument für --mysqld-version
leer ist, verwendet mysqld_safe mysqld im Verzeichnis ledir
.
--nice=
priority
Stellt die Zeitplanungspriorität mit dem Programm nice
auf den angegebenen Wert.
--no-defaults
Optionsdateien werden nicht auslesen. Wenn diese Option verwendet wird, muss Sie auf der Befehlszeile die erste angegebene Option sein.
--open-files-limit=
count
Anzahl der Dateien, die mysqld öffnen können sollte. Der Optionswert wird an ulimit -n übergeben. Beachten Sie, dass Sie mysqld_safe als root
starten müssen, damit dies einwandfrei funktioniert!
--pid-file=
file_name
Der Pfadname der Prozesskennungsdatei.
--port=
port_num
Portnummer, die der Server beim Horchen auf TCP/IP-Verbindungen verwenden soll. Die Portnummer muss 1.024 oder höher sein, sofern der Server nicht vom Systembenutzer root
gestartet wird.
--socket=
path
Unix-Socketdatei, die der Server bei Horchen auf lokale Verbindungen verwenden soll.
--timezone=
timezone
Weist der Zeitzonen-Umgebungsvariablen TZ
den angegebenen Optionswert zu. Informationen zu zulässigen Formaten für Zeitzonenangaben finden Sie in der Dokumentation zu Ihrem Betriebssystem.
--user={
user_name
|
user_id
}
Führt den Server mysqld als Benutzer mit dem spezifizierten Benutzernamen (user_name
) oder der numerischen Benutzerkennung (user_id
) aus. („Benutzer“ bezeichnet in diesem Kontext ein Systemanmeldekonto und keinen in den Grant-Tabellen aufgeführten MySQL-Benutzer.)
Wenn Sie mysqld_safe mit den Optionen --defaults-file
oder --defaults-extra-option
ausführen, um eine Optionsdatei zu benennen, dann muss diese Option als erste auf der Befehlszeile angegeben werden, da die Optionsdatei andernfalls nicht benutzt wird. So wird die Optionsdatei etwa bei folgendem Befehl nicht verarbeitet:
mysql> mysqld_safe --port=port_num
--defaults-file=file_name
Verwenden Sie stattdessen den folgenden Befehl:
mysql> mysqld_safe --defaults-file=file_name
--port=port_num
Das Skript mysqld_safe ist so abgefasst, dass es normalerweise einen Server starten kann, der aus einer Quell- oder eine Binärdistribution von MySQL installiert wurde, auch wenn diese Distributionstypen den Server normalerweise an etwas anderen Positionen installieren. (Siehe auch Abschnitt 2.1.5, „Installationslayouts“.) mysqld_safe setzt voraus, dass eine der folgenden Bedingungen erfüllt ist:
Server und Datenbanken befinden sich relativ zum Arbeitsverzeichnis (d. h. zu dem Verzeichnis, aus dem heraus mysqld_safe aufgerufen wurde). Bei Binärdistributionen sucht mysqld_safe in seinem Arbeitsverzeichnis nach den Verzeichnissen bin
und data
. Bei Quelldistributionen hingegen wird nach den Verzeichnissen libexec
und var
gesucht. Diese Bedingung sollte erfüllt sein, wenn Sie mysqld_safe aus Ihrem MySQL-Installationsverzeichnis heraus aufrufen (z. B. /usr/local/mysql
bei einer Binärdistribution).
Wenn der Server und die Datenbanken relativ zum Arbeitsverzeichnis nicht vorgefunden werden, versucht mysqld_safe sie anhand absoluter Pfadnamen zu ermitteln. Typische Positionen sind /usr/local/libexec
und /usr/local/var
. Die tatsächlichen Verzeichnisse werden den Werten entnommen, die bei der Erstellung in die Distribution einkonfiguriert wurden. Sie sollten korrekt sein, wenn MySQL im während der Konfiguration angegebenen Verzeichnis installiert ist.
Da mysqld_safe den Server und die Datenbanken relativ zum eigenen Arbeitsverzeichnis zu finden versucht, können Sie eine MySQL-Binärdistribution an beliebiger Stelle installieren, solange Sie mysqld_safe aus dem MySQL-Installationsverzeichnis heraus aufrufen:
shell>cd
shell>mysql_installation_directory
bin/mysqld_safe &
Wenn mysqld_safe fehlschlägt, obwohl es aus dem MySQL-Installationsverzeichnis heraus aufgerufen wurde, können Sie die Optionen --ledir
und --datadir
angeben, um die Verzeichnisse anzuzeigen, in denen der Server und die Datenbanken auf Ihrem System vorhanden sind.
Normalerweise sollten Sie das Skript mysqld_safe nicht bearbeiten. Konfigurieren Sie stattdessen mysqld_safe über Befehlszeilenoptionen oder Optionen im Abschnitt [mysqld_safe]
einer Optionsdatei my.cnf
. In seltenen Fällen kann es unter Umständen erforderlich sein, mysqld_safe zu modifizieren, damit der Server korrekt startet. Beachten Sie allerdings, dass Ihre geänderte Version von mysqld_safe bei einem zukünftigen MySQL-Upgrade überschrieben werden könnte; deswegen sollten Sie eine Kopie der editierten Version erstellen, die Sie bei Bedarf neu installieren können.
Unter NetWare ist mysqld_safe ein NLM, das aus dem ursprünglichen Unix-Shell-Skript portiert wurde. Es startet den Server wie folgt:
Eine Reihe von System- und Optionstest wird ausgeführt.
Die MyISAM
-Tabellen werden überprüft.
Es wird eine Bildschirmpräsenz für den MySQL-Server bereitgestellt.
mysqld wird gestartet und überwacht. Wird es mit einem Fehler beendet, so erfolgt ein Neustart.
Fehlermeldungen von mysqld werden in die Datei
im Datenverzeichnis geschrieben.
host_name
.err
Bildschirmausgaben von mysqld_safe werden in die Datei
im Datenverzeichnis geschrieben.
host_name
.safe
MySQL-Distributionen unter Unix enthalten ein Skript namens mysql.server. Dieses kann auf Systemen wie Linux oder Solaris verwendet werden, die Ausführungsverzeichnisse im System V-Stil verwenden. Ferner wird es vom Mac OS X-Startobjekt für MySQL benutzt.
Sie finden mysql.server im Verzeichnis support-files
, das sich im MySQL-Installationsverzeichnis befindet, oder in einer MySQL-Quelldistribution.
Wenn Sie das Linux-Server-RPM-Paket (MySQL-server-
) einsetzen, wird das Skript mysql.server im Verzeichnis VERSION
.rpm/etc/init.d
unter dem Namen mysql
installiert. Sie müssen die Installation also nicht manuell vornehmen. Weitere Informationen zu Linux-RPM-Paketen finden Sie in Abschnitt 2.4, „MySQL unter Linux installieren“.
Manche Anbieter stellen RPM-Pakete bereit, die ein Startskript unter einem anderen Namen wie etwa mysqld installieren.
Wenn Sie MySQL aus einer Quelldistribution installieren oder ein Binärdistributionsformat verwenden, das mysql.server nicht automatisch installiert, können Sie es manuell installieren. Eine Anleitung finden Sie in Abschnitt 2.9.2.2, „MySQL automatisch starten und anhalten“.
mysql.server liest Optionen aus den Abschnitten [mysql.server]
und [mysqld]
der Optionsdateien aus. Aus Gründen der Abwärtskompatibilität werden auch [mysql_server]
-Abschnitte ausgelesen, aber Sie sollten diese Abschnitte bei MySQL 5.1-Installationen in [mysql.server]
umbenennen.
mysqld_multi wurde entwickelt, um mehrere mysqld-Prozesse zu verwalten, die auf Verbindungen über verschiedene Unix-Socketdateien oder TCP/IP-Ports horchen. Das Skript kann Server starten und beenden und den aktuellen Status melden. Eine Alternative zur Verwaltung mehrerer Server ist der MySQL Instance Manager (siehe auch Abschnitt 5.5, „mysqlmanager — Der MySQL Instance Manager“).
mysqld_multi sucht nach Abschnitten namens [mysqld
in N
]my.cnf
(bzw. in der Datei, die mit der Option --config-file
angegeben wurde). N
kann eine beliebige positive Ganzzahl sein. Diese Zahl wird in der folgenden Abhandlung als Abschnittsnummer bzw. als GNR
(vom Englischen „Group Number“) bezeichnet. Abschnittsnummern trennen Abschnitte in Optionsdateien voneinander und werden als Argumente für mysqld_multi verwendet. Sie geben an, welche Server Sie starten oder beenden bzw. zu welchen Servern Sie einen Statusbericht anfordern wollen. Die Optionen, die in diesen Abschnitten aufgelistet sind, sind identisch mit denen, die Sie im Abschnitt [mysqld]
angeben würden, der zum Starten von mysqld verwendet wird. (Siehe z. B. Abschnitt 2.9.2.2, „MySQL automatisch starten und anhalten“.) Wenn Sie allerdings mehrere Server verwenden, ist es erforderlich, dass jeder dieser Server seinen eigenen Optionswert (z. B. die Unix-Socketdatei oder die TCP/IP-Portnummer) verwendet. Weitere Informationen dazu, welche Optionen in einer Multiserverumgebung für jeden Server eindeutig sein müssen, finden Sie in Abschnitt 5.13, „Mehrere MySQL-Server auf derselben Maschine laufen lassen“.
Um mysqld_multi aufzurufen, verwenden Sie folgende Syntax:
shell> mysqld_multi [options
] {start|stop|report} [GNR
[,GNR
] ...]
start
, stop
und report
geben die jeweilig durchzuführende Operation an. Sie können die angegebene Operation für einen oder mehrere Server abhängig davon durchführen lassen, welche GNR
-Liste auf die Option folgt. Ist keine Liste vorhanden, dann führt mysqld_multi den Vorgang für alle Server in der Optionsdatei aus.
Jeder GNR
-Wert stellt eine Abschnittsnummer bzw. einen Abschnittsnummernbereich für Optionsdateien dar. Der Wert sollte die Zahl am Ende des Abschnittsnamens in der Optionsdatei sein. So lautet die GNR
für einen Abschnitt namens [mysqld17]
etwa 17
. Um einen Zahlenbereich anzugeben, trennen Sie die erste und die letzte Zahl durch einen Bindestrich. Der GNR
-Wert 10-13
bezeichnet also die Abschnitte [mysqld10]
bis [mysqld13]
. Mehrere Abschnitte oder Abschnittsbereiche lassen sich – getrennt durch Kommata – auf der Befehlszeile angeben. Es dürfen keine Whitespace-Zeichen (d. h. Leerzeichen oder Tabulatoren) in der GNR
-Liste erscheinen, da alle auf ein solches Zeichen folgenden Angaben ignoriert werden.
Der folgende Befehl startet einen einzelnen Server unter Verwendung des Optionsabschnitts [mysqld17]
:
shell> mysqld_multi start 17
Der folgende Befehl beendet mehrere Server unter Verwendung der Abschnittsgruppen [mysqld8]
sowie [mysqld10]
bis [mysqld13]
:
shell> mysqld_multi stop 8,10-13
Ein Beispiel, wie man eine Optionsdatei konfigurieren kann, bietet der folgende Befehl:
shell> mysqld_multi --example
mysqld_multi unterstützt die folgenden Optionen:
Zeigt eine Hilfsmeldung an und wird dann beendet.
Gibt den Namen einer alternativen Optionsdatei an. Die Option bestimmt, wo mysqld_multi nach [mysqld
-Optionsabschnitten sucht. Ohne Angabe dieser Option werden alle Optionen aus der normalen Optionsdatei N
]my.cnf
ausgelesen. Die Option beeinflusst nicht, wo mysqld_multi seine eigenen Optionen ausliest (diese werden immer dem Abschnitt [mysqld_multi]
in der normalen Datei my.cnf
entnommen).
Zeigt eine Beispieloptionsdatei an.
Gibt den Namen der Logdatei an. Wenn die Datei vorhanden ist, werden geloggte Einträge angehängt.
Gibt die mysqladmin-Binärdatei an, die zum Beenden von Servern verwendet wird.
Die zu verwendende mysqld-Binärdatei. Beachten Sie, dass Sie auch mysqld_safe als Wert angeben können. Wenn Sie den Server mit mysqld_safe starten, können Sie die Optionen mysqld
oder ledir
im entsprechenden Abschnitt [mysqld
angeben. Diese Optionen bezeichnen den Namen des Servers, den mysqld_safe starten soll, und den Pfadnamen des Verzeichnisses, in dem der Server sich befindet. (Beschreibungen zu diesen Optionen finden Sie in Abschnitt 5.4.1, „mysqld_safe — Startskript für den MySQL-Server“.) Beispiel:
N
]
[mysqld38] mysqld = mysqld-max ledir = /opt/local/mysql/libexec
Schreibt Loginformationen in stdout
statt in die Logdatei. (Standardmäßig erfolgt die Ausgabe in die Logdatei.)
Passwort des MySQL-Kontos, das für den Aufruf von mysqladmin verwendet wird. Beachten Sie, dass der Passwortwert – anders als bei anderen MySQL-Programmen – bei dieser Option nicht optional ist.
Stummer Modus (Warnungen werden deaktiviert).
Alle betreffenden MySQL-Server werden statt über die Unix-Socketdatei über den TCP/IP-Port angebunden. (Wenn eine Socketdatei fehlt, kann der Server zwar unter Umständen noch laufen, ist aber nur über den TCP/IP-Port erreichbar.) Standardmäßig werden Verbindungen unter Verwendung der Unix-Socketdatei hergestellt. Diese Option wirkt sich auf alle stop
- und report
Operationen aus.
Benutzername des MySQL-Kontos, das für den Aufruf von mysqladmin verwendet wird.
Zeigt mehr Informationen an.
Zeigt die Versionsinformation an und wird dann beendet.
Einige Anmerkungen zu mysqld_multi:
Extrem wichtig: Bevor Sie mysqld_multi verwenden, müssen Sie die Bedeutung der Optionen, die an die mysqld-Server übergeben werden, verstanden haben und genau wissen, warum Sie separate mysqld-Prozesse benutzen wollen. Die Verwendung mehrerer mysqld-Server mit demselben Datenverzeichnis ist extrem gefährlich. Sofern Sie nicht genauestens wissen, was Sie tun, verwenden Sie in jedem Fall getrennte Datenverzeichnisse. Das Starten mehrerer Server mit demselben Datenverzeichnis steigert die Leistungsfähigkeit eines Thread-basierten Systems nicht! Siehe auch Abschnitt 5.13, „Mehrere MySQL-Server auf derselben Maschine laufen lassen“.
Wichtig: Vergewissern Sie sich, dass das Datenverzeichnis jedes Servers für das Unix-Konto, unter dem der jeweilige mysqld-Prozess gestartet wurde, uneingeschränkt zugänglich ist. Verwenden Sie hierfür keinesfalls das Unix-Konto root
, sofern Sie nicht genauestens wissen, was Sie tun. Siehe auch Abschnitt 5.7.5, „Wie man MySQL als normaler Benutzer laufen läßt“.
Vergewissern Sie sich, dass das MySQL-Konto, welches zum Beenden der mysqld-Server (mit dem Programm mysqladmin) verwendet wird, für jeden Server den gleichen Benutzernamen und das gleiche Passwort hat. Außerdem müssen Sie sicherstellen, dass das Konto über die Berechtigung SHUTDOWN
verfügt. Wenn die Server, die Sie verwalten wollen, unterschiedliche Benutzernamen oder Passwörter für die Administrationskonten aufweisen, sollten Sie auf jedem Server ein Konto mit jeweils demselben Benutzernamen und Passwort einrichten. Sie könnten etwa ein gemeinsames Konto multi_admin
erstellen, indem Sie auf jedem Server die folgenden Befehle ausführen:
shell>mysql -u root -S /tmp/mysql.sock -p
Enter password: mysql>GRANT SHUTDOWN ON *.*
->TO 'multi_admin'@'localhost' IDENTIFIED BY 'multipass';
Siehe auch Abschnitt 5.8.2, „Wie das Berechtigungssystem funktioniert“. Sie müssen diesen Schritt für jeden mysqld-Server durchführen. Ändern Sie die Verbindungsparameter entsprechend, wenn Sie mit den einzelnen Servern Verbindungen herstellen. Beachten Sie, dass der Hostnamensteil des Kontonamens die Herstellung einer Verbindung als multi_admin
von dem Host aus ermöglichen muss, auf dem sie mysqld_multi ausführen wollen.
Die Unix-Socketdatei und die TCP/IP-Portnummer müssen für jeden mysqld-Server unterschiedlich sein.
Die Option --pid-file
ist sehr wichtig, wenn Sie mysqld_safe zum Starten von mysqld verwenden (z. B. --mysqld=mysqld_safe
). Jeder mysqld-Server sollte seine eigene Prozesskennungsdatei haben. Der Vorteil der Verwendung von mysqld_safe anstelle von mysqld besteht darin, dass mysqld_safe seinen mysqld-Prozess überwacht und ihn neu startet, wenn der Prozess aufgrund eines Signals, welches mit kill -9
gesendet wurde, oder aus einem anderen Grund (z. B. wegen eines Segmentierungsfehlers) terminiert wurde. Bitte beachten Sie, dass das Skript mysqld_safe unter Umständen erfordert, dass Sie es von einer bestimmten Position aus starten. Das bedeutet, dass Sie möglicherweise in ein bestimmtes Verzeichnis wechseln müssen, bevor Sie mysqld_multi ausführen. Wenn Sie Probleme mit dem Starten haben, rufen Sie das Skript mysqld_safe zur Anzeige auf. Suchen Sie dort die folgenden Zeilen:
---------------------------------------------------------------- MY_PWD=`pwd` # Check if we are starting this relative (for the binary release) if test -d $MY_PWD/data/mysql -a -f ./share/mysql/english/errmsg.sys -a \ -x ./bin/mysqld ----------------------------------------------------------------
Der mit diesen Zeilen durchgeführte Test sollte erfolgreich sein, andernfalls könnten Probleme auftreten. Siehe auch Abschnitt 5.4.1, „mysqld_safe — Startskript für den MySQL-Server“.
Sie sollten die Option --user
für mysqld verwenden. Zu diesem Zweck müssen Sie das Skript mysqld_multi jedoch als Unix-Benutzer root
ausführen. Das Einfügen der Option in die Optionsdatei ist irrelevant: Wenn Sie nicht der Superuser sind und die mysqld-Prozesse unter Ihrem eigenen Unix-Konto gestartet werden, erhalten Sie lediglich eine Warnung.
Das folgende Beispiel zeigt, wie Sie eine Optionsdatei zur Verwendung mit mysqld_multi einrichten könnten. Die Reihenfolge, in der die mysqld-Programme gestartet oder beendet werden, hängt von der Reihenfolge ab, in der sie in der Optionsdatei aufgeführt sind. Abschnittsnummern müssen keine durchgehende Folge bilden. Der erste und der fünfte [mysqld
-Abschnitt wurden im Beispiel absichtlich weggelassen, um zu veranschaulichen, dass es „Lücken“ in der Optionsdatei geben darf. Dies erhöht die Flexibilität.
N
]
# This file should probably be in your home dir (~/.my.cnf) # or /etc/my.cnf # Version 2.1 by Jani Tolonen [mysqld_multi] mysqld = /usr/local/bin/mysqld_safe mysqladmin = /usr/local/bin/mysqladmin user = multi_admin password = multipass [mysqld2] socket = /tmp/mysql.sock2 port = 3307 pid-file = /usr/local/mysql/var2/hostname.pid2 datadir = /usr/local/mysql/var2 language = /usr/local/share/mysql/english user = john [mysqld3] socket = /tmp/mysql.sock3 port = 3308 pid-file = /usr/local/mysql/var3/hostname.pid3 datadir = /usr/local/mysql/var3 language = /usr/local/share/mysql/swedish user = monty [mysqld4] socket = /tmp/mysql.sock4 port = 3309 pid-file = /usr/local/mysql/var4/hostname.pid4 datadir = /usr/local/mysql/var4 language = /usr/local/share/mysql/estonia user = tonu [mysqld6] socket = /tmp/mysql.sock6 port = 3311 pid-file = /usr/local/mysql/var6/hostname.pid6 datadir = /usr/local/mysql/var6 language = /usr/local/share/mysql/japanese user = jani
Siehe auch Abschnitt 4.3.2, „my.cnf-Optionsdateien“.
mysqlmanager ist der MySQL Instance Manager (IM). Es handelt sich bei diesem Programm um einen über einen TCP/IP-Port ausgeführten Daemon, der die Überwachung und Verwaltung von MySQL-Datenbankserverinstanzen ermöglicht. Der MySQL Instance Manager ist für Unix und verwandte Betriebssysteme sowie für Windows verfügbar.
Der MySQL Instance Manager kann anstelle des Skripts mysqld_safe
verwendet werden, um den MySQL-Server sogar von einem Remotehost aus zu starten. Der MySQL Instance Manager implementiert ferner die Funktionalität (sowie beinahe die vollständige Syntax) des Skripts mysqld_multi. Eine detaillierte Beschreibung des MySQL Instance Managers folgt.
In der Regel wird der MySQL-Datenbankserver mysqld mit dem Skript mysql.server gestartet, welches normalerweise im Ordner /etc/init.d/
abgelegt ist. Das Skript ruft standardmäßig das Skript mysqld_safe auf. Sie können die Variable use_mysqld_safe
im Skript aber auch auf 0
(Null) setzen, um mit dem MySQL Instance Manager einen Server zu starten.
In diesem Fall hängt das Verhalten des MySQL Instance Managers von den Optionen ab, die in der MySQL-Konfigurationsdatei angegeben sind. Wenn keine Konfigurationsdatei vorhanden ist, erstellt der MySQL Instance Manager eine Serverinstanz namens mysqld
und versucht diese mit den vorgabeseitigen (d. h. einkompilierten) Konfigurationswerten zu starten. Das bedeutet, dass der IM die Position eines nicht an der Standardposition installierten mysqld nicht erschließen kann. Wenn Sie den MySQL-Server an einer anderen als der Standardposition installiert haben, sollten Sie eine Konfigurationsdatei verwenden. Siehe auch Abschnitt 2.1.5, „Installationslayouts“.
Ist eine Konfigurationsdatei vorhanden, dann liest der IM deren [mysqld]
-Abschnitte (z. B. [mysqld]
, [mysqld1]
, [mysqld2]
usw.) aus. Jeder dieser Abschnitte gibt eine Instanz an. Wenn der MySQL Instance Manager gestartet wird, versucht er seinerseits alle Serverinstanzen zu starten, die er finden kann. Wird er beendet, dann beendet er selbst standardmäßig alle laufenden Serverinstanzen.
Beachten Sie, dass es eine Sonderoption --mysqld-path=
gibt, die nur vom IM erkannt wird. Mit dieser Variable können Sie dem IM mitteilen, wo die mysqld-Binärdatei abgelegt ist. Sie sollten ferner die Optionen path-to-mysqld-binary
basedir
und datadir
für den Server angeben.
Der typische Ablauf beim Starten und Beenden eines MySQL-Servers mit dem MySQL Instance Manager sieht wie folgt aus:
Der MySQL Instance Manager wird mit dem Skript /etc/init.d/mysql gestartet.
Der MySQL Instance Manager startet alle Instanzen und überwacht sie.
Wenn eine Serverinstanz fehlschlägt, startet der MySQL Instance Manager sie neu.
Wird der MySQL Instance Manager heruntergefahren (z. B. mit dem Befehl /etc/init.d/mysql stop), dann fährt er seinerseits zunächst alle Serverinstanzen herunter.
Die Kommunikation mit dem MySQL Instance Manager wird mithilfe des MySQL-Client/Server-Protokolls verwaltet. Insofern können Sie mithilfe des mysql-Standardclientprogramms wie auch mit der MySQL-C-API eine Verbindung mit dem IM herstellen. Der IM unterstützt die Version des MySQL-Client/Server-Protokolls, das von den Client-Tools und -Bibliotheken verwendet wird, die den Distributionen seit MySQL 4.1 beiliegen.
Der MySQL Instance Manager speichert die Benutzerdaten in einer Passwortdatei. Der Standardname dieser Passwortdatei lautet /etc/mysqlmanager.passwd
.
Passworteinträge haben das folgende Format:
petr:*35110DC9B4D8140F5DE667E28C72DD2597B5C848
Sind keine Einträge in der Datei /etc/mysqlmanager.passwd
vorhanden, dann können Sie keine Verbindung zum Instance Manager herstellen.
Um einen neuen Eintrag zu erzeugen, rufen Sie den Instance Manager mit der Option --passwd auf. Die Ausgabe kann nachfolgend an die Datei /etc/mysqlmanager.passwd
angehängt werden, um einen neuen Benutzer hinzuzufügen. Hier ein Beispiel:
shell>mysqlmanager --passwd >> /etc/mysqlmanager.passwd
Creating record for new user. Enter user name:mike
Enter password:password
Re-type password:password
Der vorangegangene Befehl bewirkt das Hinzufügen der folgenden Zeile zur Datei /etc/mysqlmanager.passwd
:
mike:*00A51F3F48415C7D4E8908980D443C29C69B60C9
Um den Serverstatus zu überwachen, versucht der MySQL Instance Manager in regelmäßigen Abständen eine Verbindung zur MySQL-Serverinstanz herzustellen. Hierzu verwendet er das Benutzerkonto MySQL_Instance_Manager@localhost
mit dem Passwort check_connection
.
Sie müssen kein Benutzerkonto MySQL_Instance_M@localhost
erstellen, damit der MySQL Instance Manager den Serverstatus überwacht, denn eine fehlgeschlagene Anmeldung ist bereits ausreichend, um sicherzustellen, dass der Server betriebsbereit ist. Wenn allerdings dieses Konto nicht vorhanden ist, werden fehlgeschlagene Anmeldeversuche vom Server im allgemeinen Anfragelog vermerkt (siehe auch Abschnitt 5.12.2, „Die allgemeine Anfragen-Logdatei“).
Der MySQL Instance Manager unterstützt eine Reihe von Befehlszeilenoptionen. Eine kurze Auflistung erhalten Sie, indem Sie mysqlmanager mit der Option --help
aufrufen.
mysqlmanager unterstützt die folgenden Optionen:
--help
, -?
Zeigt eine Hilfemeldung an und wird dann beendet.
--bind-address=
IP
Die IP-Adresse, zu der eine Bindung hergestellt wird.
--default-mysqld-path=
path
Unter Unix der Pfadname der MySQL-Serverbinärdatei, sofern kein Pfad im Instanzabschnitt angegeben ist. Beispiel: --default-mysqld-path=/usr/sbin/mysqld
--defaults-file=
file_name
Datei, aus der die Einstellungen für den Instance Manager und MySQL Server ausgelesen werden sollen. Alle Konfigurationsänderungen, die der Instance Manager durchführt, werden an dieser Datei vorgenommen. Wenn diese Option verwendet wird, muss Sie auf der Befehlszeile die erste angegebene Option sein.
--install
Gibt an, dass der Instance Manager unter Windows als Dienst installiert werden soll.
--log=
file_name
Der Pfad zur IM-Logdatei. Wird mit der Option --run-as-service verwendet.
--monitoring-interval=
seconds
Das Intervall zur Überwachung der Instanzen, angegeben in Sekunden. Der Vorgabewert beträgt 20 Sekunden. Der Instance Manager versucht mit jeder überwachten Instanz eine Verbindung herzustellen, um festzustellen, ob sie läuft bzw. nicht abgestürzt ist. Stellt der Instance Manager fest, dass die Instanz terminiert wurde, versucht er mehrfach, sie neu zu starten. Über die Option nonguarded
im Abschnitt der betreffenden Instanz kann man dieses Verhalten für eine bestimmte Instanz deaktivieren.
--passwd
, -P
Bereitet einen Eintrag für die Passwortdatei vor und beendet sich dann.
--password-file=
file_name
Datei, in der nach Instance Manager-Benutzern und -Passwörtern gesucht wird. Die Standarddatei ist /etc/mysqlmanager.passwd
.
--pid-file=
file_name
Die zu verwendende Prozesskennung. Standardmäßig heißt die Datei mysqlmanager.pid
.
--port=
port_num
Die TCP/IP-Portnummer, die für eingehende Verbindungen verwendet werden soll (der von der IANA vergebene Standardport ist 2273).
--print-defaults
Gibt die aktuellen Standardwerte an und beendet sich nachfolgend. Wenn diese Option verwendet wird, muss Sie auf der Befehlszeile die erste angegebene Option sein.
--remove
Gibt unter Windows an, dass der Instance Manager als Windows-Dienst entfernt wird. Dies setzt voraus, dass der Instance Manager zuvor mit der Option --install
ausgeführt wurde.
--run-as-service
Gibt an, dass eine Daemonisierung durchgeführt und nachfolgend der Engelsprozess gestartet werden soll. Der Engelsprozess ist einfach und stürzt mit hoher Wahrscheinlichkeit nicht ab. Im Falle eines Absturzes startet er den Instance Manager selbst neu.
--socket=
path
Unter Unix die Socketdatei, die für eingehende Verbindungen verwendet werden soll. Standardmäßig heißt die Datei /tmp/mysqlmanager.sock
.
--standalone
Führt den Instance Manager unter Windows im autarken Modus aus.
--user=
user_name
Benutzername, unter dem mysqlmanager gestartet und ausgeführt werden soll. Es wird empfohlen, mysqlmanager unter demselben Benutzerkonto auszuführen, unter dem auch der Server mysqld läuft. („Benutzer“ bezeichnet in diesem Kontext ein Systemanmeldekonto und keinen in den Grant-Tabellen aufgeführten MySQL-Benutzer.)
--version
, -V
Gibt die Versionsinformation aus und wird dann beendet.
Der Instance Manager verwendet die Standarddatei my.cnf
. Aus dem Abschnitt [manager]
liest er Optionen für sich selbst, aus den [mysqld]
-Abschnitten Optionen für die Erstellung von Instanzen aus. Der Abschnitt [manager]
enthält Optionen, die unter Abschnitt 5.5.3, „MySQL Instance Manager: Befehlsoptionen“ aufgeführt sind. Hier ein Beispiel für einen [manager]
-Abschnitt:
# MySQL Instance Manager options section [manager] default-mysqld-path = /usr/local/mysql/libexec/mysqld socket=/tmp/manager.sock pid-file=/tmp/manager.pid password-file = /home/cps/.mysqlmanager.passwd monitoring-interval = 2 port = 1999 bind-address = 192.168.1.5
Der MySQL Instance Manager liest und verwaltet die Datei /etc/my.cnf
nur unter Linux. Unter Windows liest der MySQL Instance Manager die Datei my.ini
in dem Verzeichnis aus, in dem der Instance Manager installiert ist. Die Standardposition der Optionsdatei kann mit der Option --defaults-file=
geändert werden.
file_name
Instanzabschnitte geben Optionen an, die für jede Instanz beim Start festgelegt werden. Es handelt sich hierbei in erster Linie um normale MySQL-Serveroptionen, allerdings sind auch ein paar IM-spezifische Optionen vorhanden:
mysqld-path =
path
Pfadname zur Binärdatei des mysqld-Servers.
shutdown-delay =
seconds
Dauer (in Sekunden), die der IM auf das Herunterfahren der Instanz warten soll. Der Vorgabewert beträgt 35 Sekunden. Wird dieses Intervall überschritten, dann geht der IM davon aus, dass die Instanz abgestürzt ist, und versucht sie zu terminieren. Wenn Sie InnoDB
mit großen Tabellen verwenden, sollten Sie diesen Wert erhöhen.
nonguarded
Diese Option sollte angegeben werden, wenn Sie die IM-Überwachungsfunktion für eine bestimmte Instanz deaktivieren wollen.
Es folgen einige Beispiele für Instanzabschnitte:
[mysqld] mysqld-path=/usr/local/mysql/libexec/mysqld socket=/tmp/mysql.sock port=3307 server_id=1 skip-stack-trace core-file skip-bdb log-bin log-error log=mylog log-slow-queries [mysqld2] nonguarded port=3308 server_id=2 mysqld-path= /home/cps/mysql/trees/mysql-5.1/sql/mysqld socket = /tmp/mysql.sock5 pid-file = /tmp/hostname.pid5 datadir= /home/cps/mysql_data/data_dir1 language=/home/cps/mysql/trees/mysql-5.1/sql/share/english log-bin log=/tmp/fordel.log
Wenn Sie eine Passwortdatei für den MySQL Instance Manager eingerichtet haben und dieser ausgeführt wird, können Sie mit ihm eine Verbindung herstellen. Sie können den Client mysql verwenden, um eine Verbindung über eine MySQL-Standard-API herzustellen. Die folgende Liste zeigt die vom Instance Manager derzeit verarbeiteten Befehle mit Beispielen.
START INSTANCE
instance_name
Dieser Befehl versucht eine Instanz zu starten.
mysql> START INSTANCE mysqld4;
Query OK, 0 rows affected (0,00 sec)
STOP INSTANCE
instance_name
Dieser Befehl versucht eine Instanz zu beenden.
mysql> STOP INSTANCE mysqld4;
Query OK, 0 rows affected (0,00 sec)
SHOW INSTANCES
Zeigt die Namen aller geladenen Instanzen an.
mysql> SHOW INSTANCES;
+---------------+---------+
| instance_name | status |
+---------------+---------+
| mysqld3 | offline |
| mysqld4 | online |
| mysqld2 | offline |
+---------------+---------+
3 rows in set (0,04 sec)
SHOW INSTANCE STATUS
instance_name
Zeigt den Status und die Versionsinformation für eine Instanz an.
mysql> SHOW INSTANCE STATUS mysqld3;
+---------------+--------+---------+
| instance_name | status | version |
+---------------+--------+---------+
| mysqld3 | online | unknown |
+---------------+--------+---------+
1 row in set (0.00 sec)
SHOW INSTANCE OPTIONS
instance_name
Zeigt die von der Instanz verwendeten Optionen an.
mysql> SHOW INSTANCE OPTIONS mysqld3;
+---------------+---------------------------------------------------+
| option_name | value |
+---------------+---------------------------------------------------+
| instance_name | mysqld3 |
| mysqld-path | /home/cps/mysql/trees/mysql-4.1/sql/mysqld |
| port | 3309 |
| socket | /tmp/mysql.sock3 |
| pid-file | hostname.pid3 |
| datadir | /home/cps/mysql_data/data_dir1/ |
| language | /home/cps/mysql/trees/mysql-4.1/sql/share/english |
+---------------+---------------------------------------------------+
7 rows in set (0.01 sec)
SHOW
instance_name
LOG
FILES
Dieser Befehl listet alle von der Instanz verwendeten Logdateien auf. Die Ergebnisliste enthält die Pfade und die Größe der Logdateien. Wird in der Konfigurationsdatei kein Logdateipfad (wie etwa log=/var/mysql.log
) angegeben, dann versucht der Instance Manager, die Position der Logdatei zu erschließen. Wenn der IM die Position jedoch nicht erraten kann, dann sollten Sie sie unter Verwendung der entsprechenden Logoption explizit im Instanzabschnitt der Konfigurationsdatei angeben.
mysql> SHOW mysqld LOG FILES;
+-------------+------------------------------------+----------+
| Logfile | Path | Filesize |
+-------------+------------------------------------+----------+
| ERROR LOG | /home/cps/var/mysql/owlet.err | 9186 |
| GENERAL LOG | /home/cps/var/mysql/owlet.log | 471503 |
| SLOW LOG | /home/cps/var/mysql/owlet-slow.log | 4463 |
+-------------+------------------------------------+----------+
3 rows in set (0.01 sec)
SHOW
instance_name
LOG
{ERROR | SLOW | GENERAL}
size
[,offset_from_end
]
Dieser Befehl ruft einen Teil der angegebenen Logdatei ab. Da die meisten Benutzer wohl an den neuesten Logmeldungen interessiert sein werden, können Sie mit dem Parameter size
die Anzahl der Bytes definieren, die Sie – rückwärts vom Ende der Logdatei ausgehend – abrufen wollen. Sie können Daten aber auch aus einem Bereich mitten in der Datei abrufen, indem Sie den optionalen Parameter offset_from_end
angeben. Das folgende Beispiel ruft 21 Datenbytes ab, beginnend 23 Bytes vor dem Ende der Logdatei und zwei Bytes vor ihrem Ende endend:
mysql> SHOW mysqld LOG GENERAL 21, 2;
+---------------------+
| Log |
+---------------------+
| using password: YES |
+---------------------+
1 row in set (0.00 sec)
SET
instance_name
.option_name
=option_value
Dieser Befehl bearbeitet die Konfigurationsdatei der angegebenen Instanz dahingehend, dass er Instanzoptionen ändert oder hinzufügt. Der IM geht dabei davon aus, dass die Konfigurationsdatei sich in /etc/my.cnf
befindet. Sie sollten sicherstellen, dass die Datei existiert und die passenden Berechtigungen hat.
mysql> SET mysqld2.port=3322;
Query OK, 0 rows affected (0.00 sec)
Änderungen, die an der Konfigurationsdatei vorgenommen werden, werden erst beim nächsten Start des MySQL-Servers umgesetzt. Außerdem werden diese Änderungen erst im lokalen Cache des Instance Managers für die Instanzeinstellungen gespeichert, wenn der Befehl FLUSH INSTANCES
ausgeführt wird.
UNSET
instance_name
.option_name
Dieser Befehl entfernt eine Option aus der Konfigurationsdatei einer Instanz.
mysql> UNSET mysqld2.port;
Query OK, 0 rows affected (0.00 sec)
Änderungen, die an der Konfigurationsdatei vorgenommen werden, werden erst beim nächsten Start des MySQL-Servers umgesetzt. Außerdem werden diese Änderungen erst im lokalen Cache des Instance Managers für die Instanzeinstellungen gespeichert, wenn der Befehl FLUSH INSTANCES
ausgeführt wird.
FLUSH INSTANCES
Dieser Befehl erzwingt das Neueinlesen der Konfigurationsdatei durch den IM und die Aktualisierung der internen Strukturen. Der Befehl sollte nach einer Bearbeitung der Konfigurationsdatei ausgeführt werden. Er startet Instanzen nicht neu.
mysql> FLUSH INSTANCES;
Query OK, 0 rows affected (0.04 sec)
Einige Releases von MySQL enthalten Änderungen an der Struktur der Systemtabellen in der mysql
-Datenbank, damit neue Berechtigungen oder Funktionen hinzugefügt werden können. Wenn Sie ein Update auf eine neue Version von MySQL durchführen, sollten Sie auch Ihre Systemtabellen aktualisieren, um sicherzustellen, dass ihre Struktur auf dem neuesten Stand ist. Andernfalls können Sie bestimmte Funktionen unter Umständen nicht nutzen. Erstellen Sie zunächst eine Sicherung der mysql
-Datenbank und gehen Sie dann wie nachfolgend beschrieben vor.
Unter Unix und verwandten Systemen aktualisieren Sie die Systemtabellen, indem Sie das Skript mysql_fix_privilege_tables ausführen:
shell> mysql_fix_privilege_tables
Sie müssen dieses Skript zur Laufzeit des Servers ausführen. Es versucht dann, eine Verbindung zu dem Server herzustellen, der auf dem lokalen Host als root
ausgeführt wird. Wenn Ihr root
-Konto ein Passwort erfordert, geben Sie dieses wie folgt auf der Befehlszeile an:
shell> mysql_fix_privilege_tables --password=root_password
Das Skript mysql_fix_privilege_tables führt alle Vorgänge aus, die notwendig sind, um Ihre Systemtabellen in das aktuelle Format zu konvertieren. Unter Umständen wird mehrmals die Warnung Duplicate column name
angezeigt, die Sie aber getrost ignorieren können.
Nach der Ausführung des Skripts beenden Sie den Server und starten ihn neu.
Auf Windows-Systemen enthalten MySQL-Distributionen ein SQL-Skript namens mysql_fix_privilege_tables.sql
, das Sie mithilfe des Clients mysql ausführen können. Wenn Ihre MySQL-Installation sich beispielsweise im Verzeichnis C:\Programme\MySQL\MySQL Server 5.1
befindet, sieht der Befehl wie folgt aus:
C:\>cd "C:\Program Files\MySQL\MySQL Server 5.1"
C:\>bin\mysql -u root -p mysql
mysql>SOURCE scripts/mysql_fix_privilege_tables.sql
Der Befehl mysql fordert Sie dann auf, das root
-Passwort einzugeben. Folgen Sie dieser Aufforderung.
Wenn Ihre Installation sich in einem anderen Verzeichnis befindet, geben Sie die entsprechenden Pfadnamen ein.
Wie bei der Vorgehensweise unter Unix können auch hier Warnungen vom Typ Duplicate column name
angezeigt werden, während mysql die Anweisungen im Skript mysql_fix_privilege_tables.sql
verarbeitet, und auch hier können Sie diese ignorieren.
Nach der Ausführung des Skripts beenden Sie den Server und starten ihn neu.
Dieser Abschnitt beschreibt einige allgemeine Sicherheitsfragen, die man beachten sollte, und erläutert, was Sie tun können, um Ihre MySQL-Installation besser gegen Angriffe und Missbrauch zu schützen. Informationen, die speziell das Zugriffssteuerungssystem betreffen, das MySQL zur Konfiguration von Benutzerkonten und zur Überprüfung des Datenbankzugriffs verwendet, finden Sie in Abschnitt 5.8, „Allgemeine Sicherheitsaspekte und das MySQL-Zugriffsberechtigungssystem“.
Jeder, der MySQL auf einem mit dem Internet verbundenen Computer betreibt, sollte diesen Abschnitt lesen, um die häufigsten sicherheitsspezifischen Fehler zu vermeiden.
In unserer Beschreibung zur Sicherheit wollen wir die Notwendigkeit betonen, den gesamten Serverhost (und nicht nur den MySQL-Server) gegen alle möglichen Angriffe zu schützen: Lauschangriffe, Modifikationen, Wiedergabe und DoS (Denial of Service, Dienstablehnung). Wir werden an dieser Stelle nicht alle Aspekte der Verfügbarkeit und Fehlertoleranz behandeln.
MySQL benutzt ein Sicherheitssystem, welches auf ACLs (Access Control Lists, Zugriffssteuerungslisten) basiert, für alle Verbindungen, Abfragen und anderen Operationen, die Benutzer durchzuführen versuchen können. Ferner unterstützt werden SSL-verschlüsselte Verbindungen zwischen MySQL-Clients und -Servern. Viele der hier beschriebenen Konzepte sind keineswegs MySQL-spezifisch, sondern gelten vielmehr für fast alle gängigen Anwendungen.
Wenn Sie MySQL ausführen, befolgen Sie, sofern irgendwie möglich, die folgenden Richtlinien:
Gewähren Sie niemals irgendjemandem (mit Ausnahme von MySQL-root
-Konten) Zugang zur Tabelle user
in der mysql
-Datenbank! Dies ist entscheidend. Das verschlüsselte Passwort ist das echte Passwort in MySQL. Jeder, der das Passwort kennt, welches in der Tabelle user
aufgeführt ist, und Zugang zu dem für das betreffende Konto gelisteten Host hat, kann sich problemlos als dieser Benutzer anmelden.
Machen Sie sich mit dem MySQL-Zugriffsberechtigungssystem vertraut. Die Anweisungen GRANT
und REVOKE
werden zur Steuerung des Zugriffs auf MySQL verwendet. Gewähren Sie nie mehr Berechtigungen als notwendig. Gewähren Sie Berechtigungen niemals allen Hosts.
Checkliste:
Geben Sie mysql -u root
ein. Wenn Sie mit dem Server erfolgreich eine Verbindung herstellen können, ohne nach einem Passwort gefragt worden zu sein, dann kann jede Person als MySQL-Benutzer root
eine solche Verbindung mit Ihrem MySQL-Server herstellen und hat nachfolgend alle Berechtigungen! Lesen Sie noch einmal die MySQL-Installationsanleitung und achten Sie dabei insbesondere auf Informationen zur Einstellung eines root
-Passworts. Siehe auch Abschnitt 2.9.3, „Einrichtung der anfänglichen MySQL-Berechtigungen“.
Überprüfen Sie mithilfe der Anweisung SHOW GRANTS
, welche Konten worauf zugreifen können. Entfernen Sie dann nicht erforderliche Berechtigungen mit der REVOKE
-Anweisung.
Speichern Sie Passwörter nicht unverschlüsselt in Ihrer Datenbank. Wenn der Computer in die Hände eines Angreifers fällt, kann dieser die Passwortliste lesen und die Passwörter verwenden. Verwenden Sie stattdessen MD5()
, SHA1()
oder eine andere unidirektionale Hashing-Funktion und speichern Sie den Hash-Wert.
Wählen Sie keine Passwörter aus Wörterbüchern aus. Es gibt Spezialprogramme zum Knacken von Passwörtern. Sogar Passwörter wie „fisch98“ sind ziemlich schlecht. Wesentlich besser ist „duaxg98“: Dieses Passwort enthält zwar auch das Wort „fisch“, jedoch wurde jeder Buchstabe auf einer QWERTZ-Standardtastatur durch die Taste zu seiner Linken ersetzt. Eine andere Methode, ein Passwort zu verwenden, besteht darin, die jeweils ersten Buchstaben jedes Wortes eines Satzes zu benutzen; so wird etwa aus „Hoch auf dem gelben Wagen“ ganz einfach das Passwort „HadgW“. Dieses Passwort ist vergleichsweise einfach zu merken und einzugeben, aber für jemanden, der den Satz gar nicht kennt, schwer zu erraten.
Schaffen Sie eine Firewall an. Diese schützt Sie vor mindestens 50 Prozent aller Sicherheitslücken in jeder beliebigen Software. Setzen Sie MySQL hinter die Firewall oder in eine DMZ (De-Militarized Zone, entmilitarisierte Zone).
Checkliste:
Scannen Sie Ihre Ports aus dem Internet heraus mithilfe eines Tools wie nmap
. MySQL verwendet standardmäßig Port 3306. Dieser Port sollte für nicht vertrauenswürdige Hosts nicht zugänglich sein. Eine weitere einfache Möglichkeit zu prüfen, ob Ihr MySQL-Port offen ist oder nicht, besteht darin, den folgenden Befehl an einem entfernten System einzugeben. Hierbei ist server_host
der Hostname oder die IP-Nummer des Hosts, auf dem Ihr MySQL-Server ausgeführt wird:
shell> telnet server_host
3306
Wenn Sie eine Verbindung erhalten und einige sinnlose Zeichen angezeigt werden, ist der Port geöffnet; Sie sollten ihn dann umgehend mit Ihrer Firewall oder Ihrem Router schließen, es sei denn, es gäbe einen guten Grund dafür, dass der Port offen ist. Wenn telnet hängt oder die Verbindung abgewiesen wird, dann ist der Port gesperrt – so soll es sein.
Schenken Sie Daten, die von Benutzern Ihrer Anwendungen eingegeben wurden, kein Vertrauen. Benutzer können Ihren Code überlisten, indem Sie Sonderzeichen oder Zeichenfolgen mit vorangestelltem Escape-Zeichen in Webformulare, URLs oder andere Eingabemöglichkeiten der von Ihnen erstellten Anwendungen eintragen. Sie müssen sicherstellen, dass Ihre Anwendung auch dann sicher bleibt, wenn ein Benutzer so etwas wie „; DROP DATABASE mysql;
“ eingibt. Dies ist natürlich ein Extrembeispiel, aber große Sicherheitslücken oder umfangreiche Datenverlust können die Folge sein, wenn Hacker ähnliche Methoden verwenden und Sie nicht darauf vorbereitet sind.
Ein häufiger Fehler besteht darin, nur String-Datenwerte zu schützen. Denken Sie daran, auch numerische Daten abzusichern. Wenn eine Anwendung eine Abfrage wie SELECT * FROM table WHERE ID=234
erzeugt, weil ein Benutzer den Wert 234
eingegeben hat, dann kann der Benutzer auch den Wert 234 OR 1=1
eingeben; hierauf generiert die Anwendung die Abfrage SELECT * FROM table WHERE ID=234 OR 1=1
. Folge ist, dass der Server jeden Datensatz in der Tabelle abruft. Mithin wird jeder Datensatz angezeigt, zudem wird der Server extrem belastet. Die einfachste Möglichkeit, sich vor diesem Angriffstyp zu schützen, besteht darin, numerische Konstanten in Anführungszeichen zu setzen: SELECT * FROM table WHERE ID='234'
. Gibt nämlich der Benutzer zusätzliche Daten an, so werden sie alle Teil des Strings. In einem numerischen Kontext wandelt MySQL diesen String automatisch in eine Zahl um und entfernt alle nachfolgenden nichtnumerischen Zeichen.
Manche Leute gehen davon aus, dass eine Datenbank, die nur öffentlich verfügbare Daten enthält, nicht geschützt werden muss. Das stimmt nicht. Auch wenn jeder Datensatz in der Datenbank angezeigt werden dürfte, sollten Sie sich trotzdem etwa gegen DoS-Angriffe schützen (z. B. jene, die auf der im vorigen Absatz beschriebenen Methode basieren und den Server dazu bringen, Ressourcen zu vergeuden). Andernfalls kann Ihr Server für legitime Benutzer unerreichbar werden.
Checkliste:
Geben Sie einfache und doppelte Anführungszeichen (‘'
’ bzw. ‘"
’) in all Ihre Webformulare ein. Wird irgendein MySQL-Fehler ausgegeben, dann untersuchen Sie das Problem umgehend.
Versuchen Sie, dynamische URLs durch Hinzufügen von %22
(‘"
’), %23
(‘#
’) und %27
(‘'
’) zu modifizieren.
Versuchen Sie, die Datentypen in dynamischen URLs von numerischen auf Zeichentypen umzustellen, indem Sie die in den obigen Beispielen verwendeten Zeichen eingeben. Ihre Anwendung sollte gegen solche und ähnliche Angriffe gewappnet sein.
Geben Sie Buchstaben, Leer- und Sonderzeichen statt Ziffern in numerische Felder ein. Ihre Anwendung sollte diese Zeichen entfernen, bevor Sie sie an MySQL übergibt, oder andernfalls einen Fehler erzeugen. Die Übergabe ungeprüfter Werte an MySQL ist extrem gefährlich!
Überprüfen Sie die Daten, bevor Sie sie an MySQL übergeben.
Lassen Sie Ihre Anwendung eine Verbindung mit der Datenbank unter Verwendung eines anderen Benutzernamens als desjenigen herstellen, den Sie für administrative Zwecke verwenden. Geben Sie Ihren Anwendungen nicht mehr Zugriffsberechtigungen als notwendig.
Viele APIs stellen eine Methode bereit, um Sonderzeichen in Datenwerten zu kennzeichnen. Richtig verwendet, verhindert dies, dass Anwendungsbenutzer Werte eingeben können, die eine Erzeugung von Anweisungen durch die Anwendung verursachen könnten, welche einen anderen Effekt als von Ihnen erwünscht hervorrufen:
MySQL-C-API: Verwenden Sie den API-Aufruf mysql_real_escape_string()
.
MySQL++: Verwenden Sie die Modifizierer escape
und quote
für Abfrage-Streams.
PHP: Verwenden Sie die Funktion mysql_escape_string()
, die auf der gleichnamigen Funktion in der MySQL-C-API basiert. (Bei PHP vor Version 4.0.3 benutzen Sie stattdessen addslashes()
.) In PHP 5 können Sie die Erweiterung mysqli
einsetzen, die das verbesserte MySQL-Authentifizierungsprotokoll und Passwörter ebenso unterstützt wie vorbereitete Anweisungen mit Platzhaltern.
Perl DBI: Verwenden Sie die Methode quote()
oder Platzhalter.
Ruby DBI: Verwenden Sie Platzhalter.
Java JDBC: Verwenden Sie ein PreparedStatement
-Objekt und Platzhalter.
Andere Programmierschnittstellen weisen möglicherweise ähnliche Funktionalitäten auf.
Übertragen Sie keine unverschlüsselten Daten über das Internet. Auf solche Daten kann jeder zugreifen, der die Zeit und die Fähigkeiten hat, sie abzufangen und für eigene Zwecke zu verwenden. Verwenden Sie stattdessen ein verschlüsseltes Protokoll wie SSL oder SSH. MySQL unterstützt interne SSL-Verbindungen ab Version 4.0. Eine andere Methode besteht in der Verwendung der SSH-Portweiterleitung, mit der man einen verschlüsselten (und komprimierten) Kommunikationstunnel einrichten kann.
Machen Sie sich mit den Hilfsprogrammen tcpdump und strings vertraut. In den meisten Fällen können Sie durch Absetzen eines Befehls wie des folgenden überprüfen, ob MySQL-Datenströme unverschlüsselt sind:
shell> tcpdump -l -i eth0 -w - src or dst port 3306 | strings
(Das funktioniert unter Linux und sollte mit kleinen Anpassungen auf unter anderen Betriebssystemen laufen.) Warnung: Wenn Sie keine Klartextdaten sehen, bedeutet dies nicht notwendigerweise, dass die Daten tatsächlich verschlüsselt sind. Sofern Sie ein hohes Maß an Sicherheit benötigen, sollten Sie sich an einen Sicherheitsexperten wenden.
Wenn Sie eine Verbindung mit einem MySQL-Server herstellen, sollten Sie ein Passwort verwenden. Dieses Passwort wird nicht unverschlüsselt über die Verbindung übertragen. Die Behandlung des Passworts während der Herstellung der Clientverbindung wurde in MySQL 4.1.1 so aktualisiert, dass sie nun sehr sicher ist. Wenn Sie immer noch Passwörter im alten Stil (d. h. vor MySQL 4.1.1) verwenden, beachten Sie, dass der Verschlüsselungsalgorithmus nicht so leistungsfähig ist wie der neuere Algorithmus. Mit ein wenig Aufwand kann ein cleverer Angreifer den Datenverkehr zwischen Client und Server abfangen und das Passwort knacken. (Eine Beschreibung der verschiedenen Methoden für den Umgang mit Passwörtern finden Sie in Abschnitt 5.8.9, „Kennwort-Hashing ab MySQL 4.1“.)
Alle übrigen Informationen werden unverschlüsselt übertragen und können von jedem gelesen werden, der die Verbindung überwachen kann. Wenn die Verbindung zwischen Client und Server durch ein nicht vertrauenswürdiges Netzwerk verläuft und Sie deswegen Bedenken haben, können Sie das komprimierte Protokoll verwenden, um die Entschlüsselung der Daten erheblich zu erschweren. Sie können auch den internen SSL-Support von MySQL verwenden, um die Sicherheit der Verbindung noch mehr zu erhöhen. Siehe auch Abschnitt 5.9.7, „Verwendung sicherer Verbindungen“. Alternativ stellen Sie mit SSH eine verschlüsselte TCP/IP-Verbindung zwischen einem MySQL-Server und einem MySQL-Client her. Einen Open-Source-SSH-Client finden Sie unter http://www.openssh.org/, eine kommerzielle Variante unter http://www.ssh.com/.
Um ein MySQL-System möglichst sicher zu machen, sollten Sie die folgenden Vorschläge dringend beachten:
Verlangen Sie für alle MySQL-Konten die Nutzung eines Passworts. Ein Clientprogramm kennt die Identität seines Benutzers nicht unbedingt. Bei Client/Server-Anwendungen ist es durchaus üblich, dass der Benutzer einen beliebigen Benutzernamen für das Clientprogramm angeben kann. So kann beispielsweise jede beliebige Person das Programm mysql verwenden, um eine Verbindung als eine andere Person herzustellen, indem sie mysql -u
aufruft, wenn für other_user
db_name
other_user
kein Passwort konfiguriert ist. Wenn alle Konten ein Passwort besitzen, wird das Herstellen einer Verbindung unter Verwendung des Kontos eines anderen Benutzers erheblich schwieriger.
Eine Beschreibung der Methoden zur Konfiguration von Passwörtern finden Sie in Abschnitt 5.9.5, „Kennwörter einrichten“.
Führen Sie den MySQL-Server niemals als Unix-Benutzer root
aus. Dies ist extrem gefährlich, weil jeder Benutzer mit der Berechtigung FILE
in der Lage ist, auf dem Server die Erstellung von Dateien als root
anzufordern (z. B. ~root/.bashrc
). Um dies zu verhindern, verweigert mysqld die Ausführung als root
, sofern dies nicht ausdrücklich mit der Option --user=root
festgelegt wurde.
mysqld kann (und sollte) stattdessen als gewöhnlicher, nichtberechtigter Benutzer ausgeführt werden. Sie können ein separates Unix-Konto namens mysql
einrichten, um die Sicherheit noch weiter zu erhöhen. Dieses Konto verwenden Sie dann nur zur Administration von MySQL. Um mysqld als ein anderer Unix-Benutzer zu starten, fügen Sie die Option user
hinzu, die den Benutzernamen im Abschnitt [mysqld]
der Optionsdatei my.cnf
angibt, in der Sie die Serveroptionen konfigurieren. Zum Beispiel:
[mysqld] user=mysql
Hierdurch wird der Server unabhängig davon, ob Sie ihn manuell oder mithilfe von mysqld_safe oder mysql.server starten, als der angegebene Benutzer gestartet. Weitere Informationen finden Sie unter Abschnitt 5.7.5, „Wie man MySQL als normaler Benutzer laufen läßt“.
Die Ausführung von mysqld als ein anderer Unix-Benutzer als root
hat nicht zur Folge, dass Sie den Benutzernamen root
in der Tabelle user
ändern müssen. Benutzernamen für MySQL-Konten haben nichts mit den Benutzernamen für Unix-Konten zu tun.
Unterbinden Sie die Verwendung von symbolischen Verknüpfungen mit Tabellen. (Diese Funktionalität kann mit der Option --skip-symbolic-links
deaktiviert werden.) Dies ist insbesondere dann wichtig, wenn Sie mysqld als root
ausführen, da jeder Benutzer, der Schreibzugriff auf das Datenverzeichnis des Servers hat, jede beliebige Datei im System löschen kann! Siehe auch Abschnitt 7.6.1.2, „Benutzung symbolischer Links für Tabellen“.
Vergewissern Sie sich, dass der einzige Unix-Benutzer mit Lese- und Schreibberechtigungen in den Datenbankverzeichnissen der Benutzer ist, als der mysqld ausgeführt wird.
Gewähren Sie die Berechtigungen PROCESS
und SUPER
ausschließlich Administratoren. Die Ausgabe von mysqladmin processlist und SHOW PROCESSLIST
zeigt den Text aller Anweisungen, die gerade ausgeführt werden. Insofern kann jeder Benutzer, der die Serverprozessliste anzeigen kann, unter Umständen Anweisungen sehen, die von anderen Benutzern abgesetzt werden – z. B. auch UPDATE user SET password=PASSWORD('not_secure')
.
mysqld reserviert eine zusätzliche Verbindung für Benutzer mit der Berechtigung SUPER
, sodass ein MySQL-Benutzer root
sich auch dann anmelden und die Serveraktivitäten überprüfen kann, wenn alle normalen Verbindungen gerade verwendet werden.
Die Berechtigung SUPER
kann zur Terminierung von Clientverbindungen, zur Änderung des Serverbetriebs durch Modifikation von Systemvariablen und zur Steuerung von Replikationsservern verwendet werden.
Gewähren Sie die Berechtigung FILE
ausschließlich Administratoren. Jeder Benutzer mit dieser Berechtigung kann eine Datei an beliebiger Stelle im Dateisystem mit den Berechtigungen des mysqld-Daemons speichern. Um dies ein wenig sicherer zu gestalten, überschreiben Dateien, die mit SELECT ... INTO OUTFILE
erzeugt wurden, keine vorhandenen Dateien und können von allen geschrieben werden.
Die Berechtigung FILE
kann auch eingesetzt werden, um jede Datei zu lesen, die von allen gelesen werden kann oder für den Unix-Benutzer, als der der Server ausgeführt wird, zugänglich ist. Mit dieser Berechtigung können Sie jede Datei in eine Datenbanktabelle einlesen. Dies könnte beispielsweise missbraucht werden, indem man mit LOAD DATA
die Datei /etc/passwd
in eine Tabelle einlädt, die dann mit SELECT
angezeigt werden könnte.
Wenn Sie Ihrem DNS nicht trauen, sollten Sie IP-Nummern statt Hostnamen in den Grant-Tabellen verwenden. In jedem Fall sollten Sie sehr vorsichtig mit der Erstellung von Einträgen in Grant-Tabellen unter Verwendung von Hostnamenswerten sein, die Jokerzeichen enthalten.
Wenn Sie die Anzahl der für ein Konto verwendbaren Verbindungen einschränken wollen, können Sie dies tun, indem Sie die Variable max_user_connections
in mysqld einstellen. Die GRANT
-Anweisung unterstützt auch Ressourcensteuerungsoptionen, mit denen die Servernutzung durch ein Konto beschränkt werden kann. Siehe auch Abschnitt 13.5.1.3, „GRANT
und REVOKE
“.
Die folgenden mysqld-Optionen sind sicherheitsrelevant:
--allow-suspicious-udfs
Diese Option bestimmt, ob UDFs (User-Defined Functions, benutzerdefinierte Funktionen), die nur ein xxx
-Symbol für die Hauptfunktion aufweisen, geladen werden dürfen. Standardmäßig ist die Option deaktiviert, und es dürfen nur UDFs geladen werden, die mindestens ein Hilfssymbol aufweisen. Hierdurch soll das Laden von Funktionen aus solchen freigegebenen Objektdateien verhindert werden, die keine zulässigen UDFs enthalten. Siehe auch Abschnitt 26.3.4.6, „Vorsichtsmaßnahmen bei benutzerdefinierten Funktionen (UDF)“.
--local-infile[={0|1}]
Wenn Sie den Server mit --local-infile=0
starten, können Clients LOCAL
in LOAD DATA
-Anweisungen nicht verwenden. Siehe auch Abschnitt 5.7.4, „Sicherheitsprobleme mit LOAD DATA LOCAL
“.
--old-passwords
Erzwingt die Erzeugung kurzer Passwort-Hashes (wie vor Version 4.1) auch für neue Passwörter. Dies kann zu Kompatibilitätszwecken erforderlich sein, wenn der Server ältere Clientprogramme unterstützen muss. Siehe auch Abschnitt 5.8.9, „Kennwort-Hashing ab MySQL 4.1“.
--safe-show-database
(AUSGELAUFEN)
In älteren MySQL-Versionen konnte mit dieser Option festgelegt werden, dass die SHOW DATABASES
-Anweisung die Namen nur derjenigen Datenbanken anzeigte, für die der Benutzer eine entsprechende Berechtigung hatte. In MySQL 5.1 steht diese Option nicht mehr zur Verfügung, da dies nun das Standardverhalten ist und es eine SHOW DATABASES
-Berechtigung gibt, die zur kontenspezifischen Steuerung des Zugriffs auf Datenbanknamen verwendet werden kann. Siehe auch Abschnitt 13.5.1.3, „GRANT
und REVOKE
“.
--safe-user-create
Wenn diese Option aktiviert ist, kann ein Benutzer nur dann neue Benutzer mit der GRANT
-Anweisung erstellen, wenn er die Berechtigung INSERT
für die Tabelle mysql.user
hat. Wenn Sie wollen, dass ein bestimmter Benutzer die Möglichkeit zur Einrichtung neuer Benutzer hat, die diejenigen Berechtigungen haben, die der erstellende Benutzer gewähren darf, dann sollten Sie dem Benutzer die folgende Berechtigung gewähren:
GRANT INSERT(user) ON mysql.user TO 'user_name
'@'host_name
';
Hierdurch ist gewährleistet, dass der Benutzer Berechtigungsspalten nicht direkt ändern kann, sondern die GRANT
-Anweisung zur Gewährung von Berechtigungen an andere Benutzer verwenden muss.
--secure-auth
Unterbindet die Authentifizierung für Konten, die alte Passwörter (d. h. solche im Stil vor MySQL 4.1) haben.
Der Client mysql verfügt ebenfalls über eine Option namens --secure-auth
, die Verbindungen mit einem Server verhindert, wenn dieser für das Clientkonto ein Passwort im alten Format anfordert.
--skip-grant-tables
Mit dieser Option verwendet der Server das Berechtigungssystem überhaupt nicht. Das bedeutet, dass jeder, der Zugriff auf den Server erhält, uneingeschränkten Zugang zu allen Datenbanken bekommt. Sie können einen laufenden Server dazu bringen, die Grant-Tabellen wieder zu verwenden, indem Sie mysqladmin flush-privileges oder mysqladmin reload über die System-Shell ausführen oder die MySQL-Anweisung FLUSH PRIVILEGES
absetzen. Diese Option unterbindet auch das Laden von Plug-Ins und benutzerdefinierten Funktionen (UDFs).
--skip-name-resolve
Hostnamen werden nicht aufgelöst. Alle Host
-Spaltenwerte in den Grant-Tabellen müssen IP-Nummern oder localhost
sein.
--skip-networking
TCP/IP-Verbindungen über das Netzwerk werden unterbunden. Alle Verbindungen zu mysqld müssen über Unix-Socketdateien erfolgen.
--skip-show-database
Bei dieser Option darf die SHOW DATABASES
-Anweisung nur von Benutzern verwendet werden, die die Berechtigung SHOW DATABASES
haben. Die Anweisung zeigt dann alle Datenbanknamen an. Ohne diese Option dürfen alle Benutzer SHOW DATABASES
verwenden, aber die Datenbanknamen werden nur angezeigt, wenn der Benutzer die Berechtigung SHOW DATABASES
oder spezifische Berechtigungen für eine Datenbank hat. Beachten Sie, dass jede globale Berechtigung als Berechtigung für die Datenbank betrachtet wird.
Die LOAD DATA
-Anweisung kann eine Datei, die sich auf dem Serverhost befindet, oder eine Datei laden, die auf dem Clienthost abgelegt ist, wenn das Schlüsselwort LOCAL
angegeben ist.
Es gibt bei der Unterstützung der LOCAL
-Version von LOAD DATA
zwei potenzielle Sicherheitsrisiken:
Die Übertragung der Datei vom Client- auf den Serverhost wird durch den MySQL-Server eingeleitet. Theoretisch ließe sich ein gepatchter Server erstellen, der das Clientprogramm anweisen könnte, eine Datei nach Maßgabe des Servers (statt der vom Client in der LOAD DATA
-Anweisung festgelegten Datei) zu übertragen. Ein solcher Server könnte dann auf jede Datei auf dem Clienthost zugreifen, auf die der Clientbenutzer Lesezugriff hat.
In einer Webumgebung, in der die Clients Verbindungen über einen Webserver herstellen, könnte ein Benutzer mit LOAD DATA LOCAL
beliebige Dateien lesen, auf die der Webserverprozess Lesezugriff hat (vorausgesetzt, der Benutzer kann einen beliebigen Befehl den SQL-Server betreffend ausführen). In dieser Umgebung ist der Client aus Sicht des MySQL-Servers eigentlich der Webserver und nicht das entfernte Programm, das von dem Benutzer ausgeführt wird, der die Verbindung zum Webserver hergestellt hat.
Um diese Probleme zu beheben, haben wir die Verfahrensweise für LOAD DATA LOCAL
beginnend mit MySQL 3.23.49 und MySQL 4.0.2 (4.0.13 unter Windows) wie folgt geändert:
Standardmäßig werden alle MySQL-Clients und -Bibliotheken mit der Option --enable-local-infile
kompiliert, um die Kompatibilität mit MySQL 3.23.48 und vorher aufrechtzuerhalten.
Wenn Sie MySQL aus der Quelldistribution erstellt, aber configure nicht mit der Option --enable-local-infile
aufgerufen haben, kann LOAD DATA LOCAL
nicht von beliebigen Clients verwendet werden, sofern nicht ausdrücklich der Aufruf von mysql_options(... MYSQL_OPT_LOCAL_INFILE, 0)
einkompiliert wurde. Siehe auch Abschnitt 24.2.3.48, „mysql_options()
“.
Sie können alle LOAD DATA LOCAL
-Befehle auf der Serverseite deaktivieren, indem Sie mysqld mit der Option --local-infile=0
starten.
Für den Befehlszeilenclient mysql kann LOAD DATA LOCAL
durch Angabe der Option --local-infile[=1]
aktiviert bzw. mit der Option --local-infile=0
deaktiviert werden. Ähnlich aktiviert die Option --local
bzw. -L
das Laden lokaler Dateien für mysqlimport. In jedem Fall setzt die erfolgreiche Verwendung einer lokalen Ladeoperation voraus, dass die Durchführung derartiger Operationen durch den Server zugelassen ist.
Wenn Sie LOAD DATA LOCAL
in Perl-Skripten oder anderen Programmen verwenden, die den Abschnitt [client]
aus Optionsdateien auslesen, können Sie die Option local-infile=1
in diesem Abschnitt hinzufügen. Allerdings sollten Sie sie mit dem Präfix loose-
versehen, um Probleme mit Programmen zu vermeiden, die local-infile
nicht verstehen:
[client] loose-local-infile=1
Wenn LOAD DATA LOCAL INFILE
deaktiviert ist – sei es am Server oder am Client –, dann erhält ein Client, der eine solche Anweisung abzusetzen versucht, die folgende Fehlermeldung:
ERROR 1148: The used command is not allowed with this MySQL version
Unter Windows können Sie den Server als Windows-Dienst über ein normales Benutzerkonto ausführen.
Unter Unix kann jeder Benutzer den MySQL-Server mysqld starten und ausführen. Allerdings sollten Sie aus Sicherheitsgründen eine Ausführung des Servers als Unix-Benutzer root
unterbinden. Gehen Sie wie folgt vor, um den Server mysqld so zu ändern, dass er als normaler Unix-Benutzer user_name
ohne spezielle Berechtigungen ausgeführt wird:
Beenden Sie mit mysqladmin shutdown den Server, sofern er ausgeführt wird.
Ändern Sie die Datenbankverzeichnisse und -dateien so ab, dass user_name
Berechtigungen zum Lesen und Schreiben von Dateien in diese Verzeichnisse hat (dies müssen Sie unter Umständen als Unix-Benutzer root
tun):
shell> chown -R user_name
/path/to/mysql/datadir
Wenn Sie dies versäumen, kann der Server, wenn er als user_name
ausgeführt wird, nicht auf Datenbanken oder Tabellen zugreifen.
Wenn Verzeichnisse oder Dateien im MySQL-Datenverzeichnis symbolische Verknüpfungen sind, müssen Sie diese Verknüpfungen nachverfolgen und die Verzeichnisse und Dateien ändern, auf die sie verweisen. chown -R
verfolgt die symbolischen Verknüpfungen möglicherweise nicht.
Starten Sie den Server als Benutzer user_name
. Wenn Sie MySQL 3.22 oder höher verwenden, besteht eine Alternative darin, mysqld als Unix-Benutzer root
zu starten und dabei die Option --user=
zu verwenden. mysqld wird gestartet und schaltet dann auf die Ausführung als Unix-Benutzer user_name
user_name
um, bevor Verbindungen akzeptiert werden.
Um den Server beim Systemstart automatisch als der betreffende Benutzer zu starten, geben Sie den Benutzernamen durch Hinzufügen einer Option user
im Abschnitt [mysqld]
der Optionsdateien /etc/my.cnf
oder my.cnf
im Datenverzeichnis des Servers an. Zum Beispiel:
[mysqld]
user=user_name
Wenn Ihr Unix-System selbst nicht geschützt ist, sollten Sie für die MySQL-root
-Konten Passwörter in den Grant-Tabellen konfigurieren. Andernfalls kann jeder Benutzer mit einem Anmeldekonto auf diesem Computer den Client mysql mit der Option --user=root
ausführen und beliebige Operationen durchführen. (Es empfiehlt sich generell, MySQL-Konten mit Passwörtern zu verknüpfen, ist aber absolut erforderlich, wenn andere Anmeldekonten auf dem Serverhost vorhanden sind.) Siehe auch Abschnitt 2.9, „Einstellungen und Tests nach der Installation“.
Access denied
-FehlerMySQL verfügt über ein fortschrittliches, aber nicht standardkonformes Sicherheits- und Berechtigungssystem. Im Folgenden wird beschrieben, wie dieses System funktioniert.
Die wesentliche Funktion des MySQL-Berechtigungssystems ist die Authentifizierung von Benutzern, die von einem gegebenen Host eine Verbindung herstellen, und die Zuweisung von Berechtigungen für eine Datenbank wie SELECT
, INSERT
, UPDATE
und DELETE
an diesen Benutzer.
Weitere Funktionalitäten umfassen die Möglichkeit zur Authentifizierung anonymer Benutzer und die Gewährung von Berechtigungen für MySQL-spezifische Funktionen wie LOAD DATA INFILE
und administrativen Operationen.
Das MySQL-Berechtigungssystem stellt sicher, dass alle Benutzer nur diejenigen Operationen ausführen können, die sie auch ausführen dürfen. Wenn Sie als Benutzer eine Verbindung mit einem MySQL-Server herstellen, dann wird Ihre Identität über den Host, von dem aus Sie die Verbindung herstellen, und den angegebenen Benutzernamen bestimmt. Wenn Sie nach Herstellung der Verbindung Abfragen absetzen, gewährt das System Berechtigungen entsprechend Ihrer Identität und dem, was Sie tun wollen.
MySQL berücksichtigt bei der Identifizierung sowohl Ihren Host- als auch Ihren Benutzernamen, da es wenig Grund zu der Annahme gibt, dass ein bestimmter Benutzername überall im Internet jeweils derselben Person zuzuordnen ist. So muss beispielsweise der Benutzer joe
, der eine Verbindung von office.example.com
aus herstellt, keineswegs mit dem Benutzer joe
identisch sein, der seine Verbindung von home.example.com
aus aufbaut. MySQL löst diese Diskrepanz, indem es Ihnen gestattet, zwischen Benutzern auf unterschiedlichen Hosts zu unterscheiden, die zufällig den gleichen Namen haben: Sie können einen Satz mit Berechtigungen für Verbindungen von joe
auf office.example.com
und einen anderen Berechtigungssatz für Verbindungen von joe
auf home.example.com
gewähren.
Die MySQL-Zugriffssteuerung umfasst zwei Stufen, wenn Sie ein Clientprogramm ausführen, das eine Verbindung mit dem Server herstellt:
Stufe 1: Der Server überprüft, ob er Ihnen die Verbindungsherstellung gestattet.
Stufe 2: Sofern Sie eine Verbindung herstellen konnten, überprüft der Server nun jede von Ihnen abgesetzte Anweisung, um zu ermitteln, ob Sie ausreichende Berechtigungen für deren Durchführung genießen. Versuchen Sie beispielsweise, Datensätze aus einer Tabelle in einer Datenbank auszuwählen oder eine Tabelle aus der Datenbank zu löschen, dann vergewissert sich der Server, dass Sie die Berechtigung SELECT
für die Tabelle bzw. die Berechtigung DROP
für die Datenbank haben.
Werden Ihre Berechtigungen (sei es von Ihnen selbst oder jemandem anderes) geändert, während Sie eine Verbindung haben, dann haben diese Änderungen nicht unbedingt sofort für die nächste abgesetzte Anweisung Gültigkeit. Weitere Informationen finden Sie in Abschnitt 5.8.7, „Wann Berechtigungsänderungen wirksam werden“.
Der Server speichert Berechtigungsinformationen in den Grant-Tabellen der mysql
-Datenbank (d. h. in der Datenbank namens mysql
). Der MySQL-Server liest die Inhalte dieser Tabellen beim Start in den Speicher ein. Unter den in Abschnitt 5.8.7, „Wann Berechtigungsänderungen wirksam werden“, beschriebenen Umständen erfolgt zudem ein Neueinlesen der Inhalte. Entscheidungen der Zugriffssteuerung basieren auf den im Arbeitsspeicher vorhandenen Kopien der Grant-Tabellen.
Normalerweise manipulieren Sie die Inhalte der Grant-Tabellen indirekt, indem Sie mit Anweisungen wie GRANT
oder REVOKE
Konten einrichten und die Berechtigungen für jedes einzelne Konto steuern. Siehe auch Abschnitt 13.5.1, „Anweisungen zur Benutzerkontenverwaltung“. Die nachfolgende Beschreibung erläutert die den Grant-Tabellen zugrundeliegende Struktur und die Frage, wie der Server die Inhalte dieser Tabellen für die Interaktion mit Clients verwendet.
Der Server benutzt die Tabellen user
, db
und host
in der Datenbank mysql
für beide Stufen der Zugriffssteuerung. Die Spalten in den Tabellen user
und db
sind nachfolgend aufgeführt. Die Tabelle host
ähnelt der Tabelle db
, weist aber einen speziellen Einsatzbereich auf, der in Abschnitt 5.8.6, „Zugriffskontrolle, Phase 2: Anfrageüberprüfung“, beschrieben wird.
Tabellenname | user | db |
Spalten für Gültigkeitsbereiche | Host | Host |
User | Db | |
Password | User | |
Berechtigungsspalten | Select_priv | Select_priv |
Insert_priv | Insert_priv | |
Update_priv | Update_priv | |
Delete_priv | Delete_priv | |
Index_priv | Index_priv | |
Alter_priv | Alter_priv | |
Create_priv | Create_priv | |
Drop_priv | Drop_priv | |
Grant_priv | Grant_priv | |
Create_view_priv | Create_view_priv | |
Show_view_priv | Show_view_priv | |
Create_routine_priv | Create_routine_priv | |
Alter_routine_priv | Alter_routine_priv | |
Execute_priv | Execute_priv | |
Trigger_priv | Trigger_priv | |
Event_priv | Event_priv | |
Create_tmp_table_priv | Create_tmp_table_priv | |
Lock_tables_priv | Lock_tables_priv | |
References_priv | References_priv | |
Reload_priv | ||
Shutdown_priv | ||
Process_priv | ||
File_priv | ||
Show_db_priv | ||
Super_priv | ||
Repl_slave_priv | ||
Repl_client_priv | ||
Sicherheitsspalten | ssl_type | |
ssl_cipher | ||
x509_issuer | ||
x509_subject | ||
Spalten zur Ressourcensteuerung | max_questions | |
max_updates | ||
max_connections | ||
max_user_connections |
Die Spalten Event_priv
und Trigger_priv
wurden in MySQL 5.1.6 hinzugefügt.
Während der zweiten Stufe der Zugriffssteuerung führt der Server eine Anforderungsverifizierung durch, um sicherzustellen, dass jeder Client über die erforderlichen Berechtigungen für jede abgesetzt Anforderung verfügt. Neben den Grant-Tabellen user
, db
und host
kann der Server auch die Tabellen tables_priv
und columns_priv
für Anforderungen abfragen, die Tabellen betreffen. Die Tabellen tables_priv
und columns_priv
ermöglichen eine feiner abgestufte Berechtigungssteuerung auf der Tabellen- und Spaltenebene. Die Tabellen haben die folgenden Spalten:
Tabellenname | tables_priv | columns_priv |
Spalten für Gültigkeitsbereiche | Host | Host |
Db | Db | |
User | User | |
Table_name | Table_name | |
Column_name | ||
Berechtigungsspalten | Table_priv | Column_priv |
Column_priv | ||
Weitere Spalten | Timestamp | Timestamp |
Grantor |
Die Spalten Timestamp
und Grantor
werden derzeit nicht benutzt und sollen deswegen an dieser Stelle nicht weiter behandelt werden.
Zur Verifizierung von Anforderungen, die gespeicherte Routinen betreffen, kann der Server auch die Tabelle procs_priv
abfragen. Diese Tabelle weist die folgenden Spalten auf:
Tabellenname | procs_priv |
Spalten für Gültigkeitsbereiche | Host |
Db | |
User | |
Routine_name | |
Routine_type | |
Berechtigungsspalten | Proc_priv |
Weitere Spalten | Timestamp |
Grantor |
Die Spalte Routine_type
ist eine ENUM
-Spalte, die mit den Werten 'FUNCTION'
bzw. 'PROCEDURE'
den Typ der Routine angibt, auf die sich der Datensatz bezieht. Diese Spalte gestattet die separate Gewährung von Berechtigungen für eine Funktion oder Prozedur gleichen Namens.
Die Spalten Timestamp
und Grantor
werden derzeit nicht benutzt und sollen deswegen an dieser Stelle nicht weiter behandelt werden.
Jede Grant-Tabelle enthält Gültigkeitsbereichs- und Berechtigungsspalten:
Bereichsspalten bestimmen den Gültigkeitsbereich aller Datensätze in den Tabellen, d. h. den Kontext, in dem der Datensatz gültig ist. So würde beispielsweise eine Tabelle user
mit den Host
- und User
-Werten 'thomas.loc.gov'
bzw. 'bob'
zur Authentifizierung von Verbindungen verwendet, die vom Host thomas.loc.gov
aus durch einen Client, der den Benutzernamen bob
angibt, hergestellt würden. Ähnlich würde ein Datensatz in der Tabelle db
mit den Werten 'thomas.loc.gov'
, 'bob'
und 'reports'
in den Spalten Host
, User
und Db
verwendet werden, wenn der Benutzer bob
vom Host thomas.loc.gov
aus auf die Datenbank reports
zuzugreifen versucht. Die Tabellen tables_priv
und columns_priv
enthalten Gültigkeitsbereichsspalten, die die Tabellen oder Tabellenkombinationen angeben, für die der jeweilige Datensatz gilt. Die Bereichsspalten in procs_priv
geben die jeweilige gespeicherte Routine an, für die der Datensatz gilt.
Berechtigungsspalten legen fest, welche Berechtigungen durch einen Datensatz gewährt werden, d. h. welche Operationen durchgeführt werden können. Der Server kombiniert die Daten in den verschiedenen Grant-Tabellen zu einer vollständigen Beschreibung der Berechtigungen eines Benutzers. Abschnitt 5.8.6, „Zugriffskontrolle, Phase 2: Anfrageüberprüfung“, beschreibt, welches Regeln hierbei zugrundegelegt werden.
Bereichsspalten enthalten Strings. Diese werden wie nachfolgend gezeigt deklariert, wobei der Vorgabewert jeweils der Leer-String ist:
Spaltenname | Typ |
Host | CHAR(60) |
User | CHAR(16) |
Password | CHAR(16) |
Db | CHAR(64) |
Table_name | CHAR(64) |
Column_name | CHAR(64) |
Routine_name | CHAR(64) |
Bei der Überprüfung der Host
-Werte im Zuge der Berechtigungsverifizierung wird keine Unterscheidung der Groß-/Kleinschreibung vorgenommen. Die User
-, Password
-, Db
- und Table_name
-Werte hingegen unterscheiden die Groß-/Kleinschreibung. Nicht unterschieden wird sie wiederum bei Column_name
- und Routine_name
-Werten.
In den Tabellen user
, db
und host
wird jede Berechtigung in einer separaten Spalte aufgeführt, die als ENUM('N','Y') DEFAULT 'N'
deklariert ist. Anders gesagt: Jede Berechtigung lässt sich aktivieren oder deaktivieren, wobei sie vorgabeseitig immer deaktiviert ist.
In den Tabellen tables_priv
, columns_priv
und procs_priv
sind die Berechtigungsspalten als SET
-Spalten deklariert. Werte in diesen Spalten können eine beliebige Kombination der Berechtigungen enthalten, die von der Tabelle gesteuert werden:
Tabellenname | Spaltenname | Mögliche Elemente des Satzes |
tables_priv | Table_priv | 'Select', 'Insert', 'Update', 'Delete', 'Create', 'Drop',
'Grant', 'References', 'Index', 'Alter', 'Create View',
'Show view', 'Trigger' |
tables_priv | Column_priv | 'Select', 'Insert', 'Update', 'References' |
columns_priv | Column_priv | 'Select', 'Insert', 'Update', 'References' |
procs_priv | Proc_priv | 'Execute', 'Alter Routine', 'Grant' |
Kurz gesagt verwendet der Server die Grant-Tabellen wie folgt:
Die Bereichsspalten in der Tabelle user
bestimmen, ob eingehende Verbindungen abgewiesen oder zugelassen werden. Bei zulässigen Verbindungen geben alle in der Tabelle user
gewährten Berechtigungen die globalen Berechtigungen (Superuser-Berechtigungen) des Benutzers an. Jede Berechtigung, die in dieser Tabelle gewährt wird, gilt für alle Datenbanken auf dem Server.
Hinweis: Da alle globalen Berechtigungen als Berechtigungen für alle Datenbanken zu betrachten sind, erlaubt das Vorhandensein einer beliebigen globalen Berechtigung für einen Benutzer diesem, alle Datenbanknamen mit SHOW DATABASES
oder durch Untersuchen der Tabelle SCHEMATA
von INFORMATION_SCHEMA
anzuzeigen.
Die Bereichsspalten der Tabelle db
bestimmen dabei, welche Benutzer von welchen Hosts aus auf welche Datenbanken zugreifen können. Die Berechtigungsspalten legen hingegen fest, welche Operationen zulässig sind. Eine auf der Datenbankebene gewährte Berechtigung gilt für die Datenbank und alle in ihr enthaltenen Tabellen.
Die Tabelle host
wird in Verbindung mit der Tabelle db
benutzt, wenn ein bestimmte Datensatz in der Tabelle db
für mehrere Hosts gelten soll. Wenn Sie beispielsweise einem Benutzer die Verwendung einer Datenbank von verschiedenen Hosts in Ihrem Netzwerk aus gestatten wollen, lassen Sie den Wert Host
im Datensatz des betreffenden Benutzers in der Tabelle db
frei und geben Sie dann einen Datensatz für jeden der betreffenden Hosts in die Tabelle host
ein. Diese Vorgehensweise wird in Abschnitt 5.8.6, „Zugriffskontrolle, Phase 2: Anfrageüberprüfung“, genauer beschrieben.
Hinweis: Die Tabelle host
muss mit Anweisungen wie INSERT
, UPDATE
und DELETE
direkt modifiziert werden. Anweisungen wie GRANT
und REVOKE
, die die Grant-Tabellen indirekt manipulieren, haben keine Auswirkungen auf diese Tabelle. Die meisten MySQL-Installationen verwenden die Tabelle ohnehin nicht.
Die Tabellen tables_priv
und columns_priv
ähneln der Tabelle db
, sind aber feiner abgestuft: Sie werden nicht auf Datenbankebene, sondern auf der Tabellen- und der Spaltenebene angewendet. Eine auf der Tabellenebene gewährte Berechtigung gilt für die Tabelle und alle in ihr enthaltenen Spalten. Eine auf der Spaltenebene gewährte Berechtigung gilt indes nur für eine bestimmte Spalte.
Die Tabelle procs_priv
gilt für gespeicherte Routinen. Eine auf der Routinenebene gewährte Berechtigung gilt nur für eine bestimmte Routine.
Administrative Berechtigungen (wie etwa RELOAD
oder SHUTDOWN
) werden nur in der Tabelle user
festgelegt. Der Grund hierfür besteht darin, dass administrative Operationen auf dem Server selbst erfolgen und nicht datenbankspezifisch sind, d. h. es gibt keinen Grund, diese Berechtigungen in anderen Grant-Tabellen aufzuführen. Tatsächlich muss der Server, um zu ermitteln, ob Sie eine administrative Operation durchführen dürfen, nur die Tabelle user
abfragen.
Die Berechtigung FILE
wird ebenfalls nur in der Tabelle user
festgelegt. Sie ist im Eigentlichen keine administrative Berechtigung, aber die Fähigkeit zum Lesen oder Schreiben von Dateien auf dem Serverhost hängt nicht von der Datenbank ab, auf die Sie zugreifen.
Der Server mysqld liest die Inhalte der Grant-Tabellen beim Start in den Speicher ein. Sie können ihn mit der Anweisung FLUSH PRIVILEGES
oder durch Ausführen der Befehle mysqladmin flush-privileges oder mysqladmin reload anweisen, die Tabellen neu einzulesen. Änderungen an den Grant-Tabellen werden umgesetzt wie in Abschnitt 5.8.7, „Wann Berechtigungsänderungen wirksam werden“, beschrieben.
Wenn Sie die Inhalte der Grant-Tabellen ändern, empfiehlt es sich sicherzustellen, dass Ihre Änderungen die Berechtigungen so konfigurieren, wie Sie es auch wünschen. Um die Berechtigungen eines gegebenen Kontos zu überprüfen, verwenden Sie die Anweisung SHOW GRANTS
. (Siehe auch Abschnitt 13.5.4.11, „SHOW GRANTS
“.) Um also etwa die Berechtigungen zu ermitteln, die einem Konto mit den Host
- und User
-Werten pc84.example.com
bzw. bob
gewährt werden, setzen Sie folgende Anweisung ab:
SHOW GRANTS FOR 'bob'@'pc84.example.com';
Weitere Hilfe zur Diagnose von Problemen in Zusammenhang mit Berechtigungen finden Sie in Abschnitt 5.8.8, „Gründe für Access denied
-Fehler“. Allgemeine Richtlinien zu Sicherheitsfragen finden Sie außerdem in Abschnitt 5.7, „Absichern von MySQL gegen Angreifer“.
Die Informationen zu Kontenberechtigungen sind in den Tabellen user
, db
, host
, tables_priv
, columns_priv
und procs_priv
in der mysql
-Datenbank abgelegt. Der MySQL-Server liest die Inhalte dieser Tabellen beim Start in den Speicher ein. Unter den in Abschnitt 5.8.7, „Wann Berechtigungsänderungen wirksam werden“, beschriebenen Umständen erfolgt zudem ein Neueinlesen der Inhalte. Entscheidungen der Zugriffssteuerung basieren auf den im Arbeitsspeicher vorhandenen Kopien der Grant-Tabellen.
Die in den Anweisungen GRANT
und REVOKE
zur Bezeichnung von Berechtigungen verwendeten Namen sind in der folgenden Tabelle aufgeführt. Diese enthält außerdem Angaben zu dem mit der jeweiligen Berechtigung in den Grant-Tabellen verknüpften Spaltennamen und zum Kontext, in dem die Berechtigung gültig ist. Weitere Informationen zur Bedeutung der einzelnen Berechtigungen können Sie Abschnitt 13.5.1.3, „GRANT
und REVOKE
“, entnehmen.
Berechtigung | Spalte | Kontext |
CREATE | Create_priv | Datenbanken, Tabellen oder Indizes |
DROP | Drop_priv | Datenbanken oder Tabellen |
GRANT OPTION | Grant_priv | Datenbanken, Tabellen oder gespeicherte Routinen |
REFERENCES | References_priv | Datenbanken oder Tabellen |
EVENT | Event_priv | Datenbanken |
ALTER | Alter_priv | Tabellen |
DELETE | Delete_priv | Tabellen |
INDEX | Index_priv | Tabellen |
INSERT | Insert_priv | Tabellen |
SELECT | Select_priv | Tabellen |
UPDATE | Update_priv | Tabellen |
TRIGGER | Trigger_priv | Tabellen |
CREATE VIEW | Create_view_priv | Views |
SHOW VIEW | Show_view_priv | Views |
ALTER ROUTINE | Alter_routine_priv | gespeicherte Routinen |
CREATE ROUTINE | Create_routine_priv | gespeicherte Routinen |
EXECUTE | Execute_priv | gespeicherte Routinen |
FILE | File_priv | Dateizugriff auf dem Serverhost |
CREATE TEMPORARY TABLES | Create_tmp_table_priv | Serveradministration |
LOCK TABLES | Lock_tables_priv | Serveradministration |
CREATE USER | Create_user_priv | Serveradministration |
PROCESS | Process_priv | Serveradministration |
RELOAD | Reload_priv | Serveradministration |
REPLICATION CLIENT | Repl_client_priv | Serveradministration |
REPLICATION SLAVE | Repl_slave_priv | Serveradministration |
SHOW DATABASES | Show_db_priv | Serveradministration |
SHUTDOWN | Shutdown_priv | Serveradministration |
SUPER | Super_priv | Serveradministration |
Einige Releases von MySQL enthalten Änderungen an der Struktur der Grant-Tabellen, damit neue Berechtigungen oder Funktionen hinzugefügt werden können. Wenn Sie ein Upgrade auf eine neue MySQL-Version durchführen, sollten Sie Ihre Grant-Tabellen aktualisieren, damit sichergestellt ist, dass diese auf der aktuellen Struktur basieren und auf diese Weise neue Funktionalitäten nutzen können. Siehe auch Abschnitt 5.6, „mysql_fix_privilege_tables — Upgrade von MySQL-Systemtabellen“.
Die Berechtigungen EVENT
und TRIGGER
wurden in MySQL 5.1.6 hinzugefügt.
Um gespeicherte Funktionen zu erstellen oder zu verändern, benötigen Sie bei aktiviertem binärem Loggen unter Umständen auch die Berechtigung SUPER
(siehe auch Beschreibung in Abschnitt 19.4, „Binärloggen gespeicherter Routinen und Trigger“).
Die Berechtigungen CREATE
und DROP
gestatten Ihnen die Erstellung neuer bzw. das Löschen vorhandener Datenbanken und Tabellen. Wenn Sie einem Benutzer die Berechtigung DROP
für die Datenbank mysql
gewähren, kann dieser Benutzer die Datenbank löschen, in der die MySQL-Zugriffsberechtigungen gespeichert sind.
Die Berechtigungen SELECT
, INSERT
, UPDATE
und DELETE
gestatten Ihnen die Durchführung der betreffenden Operationen an Datensätzen in vorhandenen Tabellen einer Datenbank.
SELECT
-Anweisungen erfordern die Berechtigung SELECT
nur dann, wenn Sie sie tatsächlich Datensätze aus eine Tabelle abrufen. Einige SELECT
-Anweisungen greifen nicht auf Tabellen zu und können deswegen ohne Berechtigung für eine bestimmte Datenbank ausgeführt werden. So können Sie etwa den Client mysql als einfachen Taschenrechner zur Auswertung von Ausdrücken verwenden, die keine Tabellen referenzieren:
SELECT 1+1; SELECT PI()*2;
Die Berechtigung INDEX
erlaubt Ihnen das Erstellen und Löschen von Indizes. INDEX
gilt für vorhandene Tabellen. Wenn Sie die Berechtigung CREATE
für eine Tabelle haben, können Sie Indexdefinitionen in die CREATE TABLE
-Anweisung einfügen.
Die Berechtigung ALTER
gestattet es Ihnen, mit ALTER TABLE
die Struktur einer Tabelle zu ändern oder die Tabelle umzubenennen.
Die Berechtigung CREATE ROUTINE
ist zur Erstellung gespeicherter Routinen (Funktionen und Prozeduren) erforderlich. Die Berechtigung ALTER ROUTINE
benötigen Sie zum Ändern oder Löschen gespeicherter Routinen und die Berechtigung EXECUTE
für deren Ausführung.
Die Berechtigung TRIGGER
erlaubt Ihnen das Erstellen und Löschen von Triggern. Sie benötigen diese Berechtigung für eine Tabelle, um Trigger für diese Tabelle erstellen oder löschen zu dürfen. (Vor MySQL 5.1.6 erforderten diese Operationen die Berechtigung SUPER
.)
Die Berechtigung EVENT
erlaubt Ihnen die Erstellung von Ereignissen im Ereignisplaner.
Mit der Berechtigung GRANT
können Sie anderen Benutzern die Berechtigungen gewähren, die Sie selbst besitzen. Sie kann für Datenbanken, Tabellen und gespeicherte Routinen verwendet werden.
Die Berechtigung FILE
gibt Ihnen die Erlaubnis, Dateien auf dem Serverhost mit den LOAD DATA INFILE
- und SELECT ... INTO OUTFILE
-Anweisungen zu lesen bzw. zu schreiben. Ein Benutzer mit der Berechtigung FILE
kann jede Datei auf dem Server lesen, die entweder von allen oder vom MySQL-Server gelesen werden kann. (Daraus folgt, dass der Benutzer jede Datei in jedem Datenbankverzeichnis lesen kann, da der Server auf all diese Dateien zugreifen darf.) Die Berechtigung FILE
erlaubt dem Benutzer auch die Erstellung neuer Dateien in allen Verzeichnissen, auf die der MySQL-Server Schreibzugriff hat. Der Server kann vorhandene Dateien jedoch nicht überschreiben (dies ist eine Sicherheitsmaßnahme).
Die verbleibenden Berechtigungen werden für administrative Operationen verwendet. Viele von ihnen können mit dem Programm mysqladmin oder durch Absetzen von SQL-Anweisungen ausgeführt werden. Die folgende Tabelle zeigt, die Ausführung welcher mysqladmin-Befehle mit den einzelnen administrativen Berechtigungen möglich ist:
Berechtigung | Für Berechtigte verfügbare Befehle |
RELOAD | flush-hosts , flush-logs , flush-privileges , flush-status , flush-tables , flush-threads , refresh , reload |
SHUTDOWN | shutdown |
PROCESS | processlist |
SUPER | kill |
Der Befehl reload
weist den Server an, die Grant-Tabellen erneut in den Speicher einzulesen. flush-privileges
ist ein Synonym für reload
. Der Befehl refresh
schließt die Logdateien und öffnet sie dann neu und schreibt zudem alle Tabellen neu auf Festplatte. Die übrigen flush-
-Befehle führen Funktionen aus, die xxx
refresh
ähneln, sind aber spezieller und in bestimmten Fällen vorzuziehen. Wenn Sie beispielsweise nur die Logdateien neu schreiben wollen, ist flush-logs
eine bessere Wahl als refresh
.
Der Befehl shutdown
fährt den Server herunter. Eine entsprechende SQL-Anweisung gibt es nicht.
Der Befehl processlist
zeigt Informationen zu den Threads an, die auf dem Server ausgeführt werden (und somit auch zu den Anweisungen, die von den Clients ausgeführt werden). Der Befehl kill
terminiert Server-Threads. Eigene Threads können Sie immer anzeigen oder terminieren; zum Anzeigen von Threads, die von anderen Benutzern gestartet wurden, benötigen Sie die Berechtigung PROCESS
und zum Terminieren solcher Threads die Berechtigung SUPER
. Siehe auch Abschnitt 13.5.5.3, „KILL
“.
Die Berechtigung CREATE TEMPORARY TABLES
ermöglicht die Verwendung des Schlüsselwortes TEMPORARY
in CREATE TABLE
-Anweisungen.
Die Berechtigung LOCK TABLES
gestattet die Verwendung expliziter LOCK TABLES
-Anweisungen zum Sperren von Tabellen, für die Sie die Berechtigung SELECT
haben. Dies umfasst auch das Setzen von Schreibsperren, wodurch das Lesen der Tabellen durch andere unterbunden wird.
Die Berechtigung REPLICATION CLIENT
ermöglicht die Verwendung von SHOW MASTER STATUS
und SHOW SLAVE STATUS
.
Die Berechtigung REPLICATION SLAVE
sollte Konten gewährt werden, die von Slave-Servern zum Herstellen einer Verbindung mit dem aktuellen Server als Master verwendet werden. Ohne diese Berechtigung kann der Slave keine Updates anfordern, die an den Datenbanken auf dem Master-Server vorgenommen wurden.
Die Berechtigung SHOW DATABASES
ermöglicht dem Konto die Anzeige von Datenbanknamen durch Absetzen einer SHOW DATABASE
-Anweisung. Konten, die diese Berechtigung nicht haben, sehen nur solche Datenbanken, für die sie Berechtigungen haben; wurde der Server mit der Option --skip-show-database
gestartet, dann kann die Anweisung überhaupt nicht verwendet werden. Beachten Sie, dass jede globale Berechtigung eine Berechtigung für die Datenbank ist.
Es empfiehlt sich deswegen, einem Konto nur diejenigen Berechtigungen zu gewähren, die es tatsächlich braucht. Besondere Vorsicht sollten Sie bei Gewährung der Berechtigung FILE
sowie administrativer Berechtigungen walten lassen:
Die Berechtigung FILE
kann missbraucht werden, um beliebige Dateien, die der MySQL-Server auf dem Serverhost lesen kann, in eine Datenbanktabelle einzulesen. Dies betrifft alle World-Readable-Dateien sowie Dateien im Datenverzeichnis des Servers. Die Tabelle kann dann mit SELECT
aufgerufen und ihr Inhalt an den Clienthost übertragen werden.
Die Berechtigung GRANT
gestattet Benutzern, ihre Berechtigungen an andere Benutzer weiterzugeben. Zwei Benutzer, die unterschiedliche Berechtigungen haben und beide über die Berechtigung GRANT
verfügen, können ihre Berechtigungen kombinieren.
Die Berechtigung ALTER
kann verwendet werden, um das Berechtigungssystem durch Umbenennen zu unterlaufen.
Die Berechtigung SHUTDOWN
kann verwendet werden, um durch Herunterfahren des Servers anderen Benutzern Dienste vollständig zu verweigern.
Mit der Berechtigung PROCESS
kann man aktuell ausgeführte Anweisungen einschließlich solcher, mit denen Passwörter eingestellt oder geändert werden, unverschlüsselt anzeigen.
Mit der Berechtigung SUPER
schließlich lassen sich andere Clients terminieren und die Betriebsweise des Servers ändern.
Berechtigungen, die für die mysql
-Datenbank selbst gewährt wurden, können zum Ändern von Passwörtern und anderen Daten benutzt werden, die für Zugriffsberechtigungen relevant sind. Passwörter werden verschlüsselt gespeichert, d. h. ein arglistiger Benutzer kann sie nicht einfach im Klartext auslesen. Allerdings kann ein Benutzer mit Schreibzugriff auf die Spalte Password
der Tabelle user
das Passwort eines Kontos ändern und dann unter Verwendung dieses Kontos eine Verbindung mit dem MySQL-Server herstellen.
Es gibt aber auch einige Dinge, die Sie mit dem MySQL-Berechtigungssystem nicht tun können:
Sie können nicht explizit angeben, dass einem bestimmten Benutzer der Zugriff verweigert werden soll. Anders gesagt ist es nicht möglich, einen Benutzervergleich durchzuführen und bei Übereinstimmung die Verbindung zu verweigern.
Sie können nicht festlegen, dass ein Benutzer Berechtigungen zum Erstellen oder Löschen von Tabellen in einer Datenbank hat, aber die Datenbank selbst nicht erstellen bzw. löschen darf.
Ein Passwort gilt immer global für ein Konto. Sie können kein Passwort für ein bestimmtes Objekt wie eine Datenbank, eine Tabelle oder eine Routine vergeben.
Wenn Sie auf einen MySQL-Server zugreifen wollen, erwarten MySQL-Clientprogramme im Allgemeinen die Angabe bestimmter Verbindungsparameter von Ihnen:
den Namen des Hosts, auf dem der MySQL-Server ausgeführt wird
Ihren Benutzernamen
Ihr Passwort
Der Client mysql kann beispielsweise wie folgt über die Befehlszeile gestartet werden (die Eingabeaufforderung wird durch shell>
repräsentiert):
shell> mysql -h host_name
-u user_name
-pyour_pass
Alternative Formen der Optionen -h
, -u
und -p
sind --host=
, host_name
--user=
und user_name
--password=
. Beachten Sie, dass zwischen your_pass
-p
oder --password=
und dem nachfolgenden Passwort kein Leerzeichen stehen darf.
Wenn Sie die Option -p
oder --password
verwenden, aber keinen Passwortwert angeben, fordert das Clientprogramm Sie zur Eingabe des Passworts auf. Das Passwort wird bei der Eingabe nicht angezeigt. Dies ist sicherer als die Angabe des Passworts über die Befehlszeile. Ein Benutzer auf Ihrem System kann ein über die Befehlszeile angegebenes Passwort unter Umständen anzeigen, indem er einen Befehl wie ps auxww ausführt. Siehe auch Abschnitt 5.9.6, „Wie Sie Ihre Kennwörter sicher halten“.
MySQL-Clientprogramme verwenden Standardwerte für alle Verbindungsparameteroptionen, die Sie nicht angeben:
Der Standardhostname ist localhost
.
Der vorgabeseitige Benutzername heißt unter Windows ODBC
, unter Unix ist es Ihr Anmeldename.
Wenn weder die Option -p
noch die Option --password
angegeben wird, wird kein Passwort übergeben.
Das bedeutet für einen Unix-Benutzer mit dem Anmeldenamen joe
, dass alle folgenden Befehle äquivalent sind:
shell>mysql -h localhost -u joe
shell>mysql -h localhost
shell>mysql -u joe
shell>mysql
Andere MySQL-Clients verhalten sich ähnlich.
Sie können andere Standardwerte festlegen, die zur Herstellung einer Verbindung verwendet werden sollen, damit Sie sie nicht jedes Mal auf der Befehlszeile angeben müssen, wenn Sie ein Clientprogramm aufrufen. Hierzu gibt es mehrere Möglichkeiten:
Sie können die Verbindungsparameter im Abschnitt [client]
einer Optionsdatei angeben. Der entsprechende Abschnitt der Datei kann etwa so aussehen:
[client] host=host_name
user=user_name
password=your_pass
Abschnitt 4.3.2, „my.cnf-Optionsdateien“, enthält eine eingehendere Beschreibung der Optionsdateien.
Sie können bestimmte Verbindungsparameter auch über Umgebungsvariablen angeben. Der Host kann für mysql mithilfe von MYSQL_HOST
festgelegt werden. Der MySQL-Benutzername kann über USER
angegeben werden (dies gilt nur für Windows und NetWare). Das Passwort kann über MYSQL_PWD
angegeben werden. Dies beeinträchtigt jedoch die Sicherheit (siehe auch Abschnitt 5.9.6, „Wie Sie Ihre Kennwörter sicher halten“). Eine Liste der Variablen finden Sie unter Anhang F, Umgebungsvariablen.
Wenn Sie eine Verbindung mit einem MySQL-Server herzustellen versuchen, kann dieser die Verbindungsanfrage basierend auf Ihrer Identität und darauf, ob Sie diese Identität durch Übermittlung nachgewiesen haben, annehmen oder abweisen. Im Falle der Abweisung verweigert Ihnen der Server jedweden Zugriff. Andernfalls akzeptiert der Server die Verbindung. Er schaltet dann auf Stufe 2 um und erwartet Ihre Anforderungen.
Ihre Identität basiert auf zwei Datenelementen:
dem Clienthost, von dem aus Sie die Verbindung herstellen
Ihrem MySQL-Benutzernamen
Die Identitätsprüfung wird mithilfe der drei Gültigkeitsbereichsspalten (Host
, User
und Password
) der Tabelle user
durchgeführt. Der Server akzeptiert die Verbindung nur dann, wenn die Werte in den Spalten Host
und User
eines Datensatzes in der Tabelle user
mit dem vom Client übermittelten Host- und Benutzernamen übereinstimmen und der Client nachfolgend das Passwort für diesen Datensatz sendet.
Die Host
-Werte in der Tabelle user
können wie folgt angegeben werden:
Ein Host
-Wert kann ein Hostname oder eine IP-Adresse oder aber 'localhost'
(zur Bezeichnung des lokalen Hosts) sein.
Sie können die Jokerzeichen ‘%
’ und ‘_
’ in Host
-Spaltenwerten benutzen. Sie haben die gleiche Bedeutung wie bei Mustervergleichsoperationen, die mit dem Operator LIKE
durchgeführt werden. So stimmt etwa der Host
-Wert '%'
mit allen Hostnamen überein, während der Wert '%.mysql.com'
eine Übereinstimmung mit allen Hosts der Domäne mysql.com
bedingt.
Bei Host
-Werten, die als IP-Nummern angegeben werden, können Sie ein Netzmaske angeben, die die Anzahl der Bits definiert, die für die Netzwerknummer verwendet werden. Zum Beispiel:
GRANT ALL PRIVILEGES ON db.* TO david@'192.58.197.0/255.255.255.0';
Hiermit kann david
von jedem Clienthost aus eine Verbindung herstellen, der die IP-Nummer client_ip
hat, sofern für diese die folgende Bedingung wahr ist:
client_ip & netmask = host_ip
Das bedeutet für die gerade gezeigte GRANT
-Anweisung:
client_ip & 255.255.255.0 = 192.58.197.0
IP-Nummern, die dieser Bedingung genügen und eine Verbindung mit dem MySQL-Server herstellen können, sind mithin diejenigen im Bereich zwischen 192.58.197.0
und 192.58.197.255
.
Hinweis: Die Netzmaske kann nur verwendet werden, um den Server anzuweisen, die ersten acht, 16, 24 oder alle 32 Bits der Adresse zu verwenden. Ein paar Beispiele:
192.0.0.0/255.0.0.0
: Alle Hosts im Klasse-A-Netzwerk 192.
192.168.0.0/255.255.0.0
: Alle Hosts im Klasse-B-Netzwerk 192.168.
192.168.1.0/255.255.255.0
: Alle Hosts im Klasse-C-Netzwerk 192.168.1.
192.168.1.1
: Nur die angegebene IP-Adresse.
Die folgende Netzmaske (28 Bits) wird hingegen nicht funktionieren:
192.168.0.1/255.255.255.240
Ein leerer Host
-Wert in einem Datensatz der Tabelle db
bedeutet, dass die Berechtigungen mit denen im Datensatz in der host
-Tabelle kombiniert werden sollen, der mit dem Hostnamen des Clients übereinstimmt. Diese Berechtigungen werden mithilfe des logischen UND (Schnittmenge), nicht des logischen ODER (Gesamtmenge) verknüpft. Abschnitt 5.8.6, „Zugriffskontrolle, Phase 2: Anfrageüberprüfung“, beschreibt die Verwendung der Tabelle host
im Detail.
Ein leerer Host
-Wert in den anderen Grant-Tabellen entspricht '%'
.
Da es möglich ist, Jokerwerte in den IP-Adressen der Host
-Spalte zu verwenden (z. B. '144.155.166.%'
, um eine Übereinstimmung mit jedem Host in einem bestimmten Subnetz zu erzielen), könnte jemand versuchen, diese Funktionalität auszunutzen, indem er einen Host 144.155.166.somewhere.com
nennt. Um derartige Versuche zu durchkreuzen, verbietet MySQL Mustervergleiche mit Hostnamen, die mit Ziffern und einem Punkt beginnen. Das bedeutet, dass ,wenn Sie einen Host mit dem Namen 1.2.foo.com
oder ähnlich haben, dieser Name niemals eine Übereinstimmung in der Host
-Spalte der Grant-Tabellen finden wird. Ein IP-Jokerwert kann nur mit IP-Adressen, nicht jedoch mit Hostnamen übereinstimmen.
In der Spalte User
sind Jokerzeichen nicht zulässig, Sie können jedoch einen leeren Wert angeben, der mit jedem Namen übereinstimmt. Wenn der Datensatz in der Tabelle user
, der mit einer eingehenden Verbindung übereinstimmt, einen leeren Benutzernamen aufweist, dann wird der Benutzer als anonymer Benutzer ohne Namen und nicht als Benutzer mit dem Namen betrachtet, der eigentlich vom Client übergeben wurde. Folglich wird ein leerer Benutzername für alle weiteren Zugriffsüberprüfungen während der gesamten Dauer der Verbindung (also während der zweiten Stufe) verwendet.
Die Spalte Password
darf leer sein. Dies ist kein Joker und bedeutet auch keine Übereinstimmung mit beliebigen Passwörtern. Vielmehr besagt dies, dass der Benutzer eine Verbindung ohne Angabe eines Passworts herstellen muss.
Nichtleere Password
-Werte in der Tabelle user
stehen für verschlüsselte Passwörter. MySQL speichert Passwörter nicht in unverschlüsselter, problemlos ersichtlicher Form. Stattdessen wird das von einem Benutzer, der eine Verbindung herstellen will, eingegebene Passwort verschlüsselt (und zwar mit der Funktion PASSWORD()
). Dieses verschlüsselte Passwort wird dann während des Verbindungsaufbaus verwendet, um zu überprüfen, ob das Passwort korrekt ist. (Dieser Vorgang läuft ab, ohne dass das verschlüsselte Passwort jemals über die Verbindung übermittelt wird.) Aus der Sicht von MySQL ist das verschlüsselte Passwort das echte Passwort, d. h. Sie sollten niemals jemandem den Zugriff darauf ermöglichen. Insbesondere sollten Sie Nichtadministratoren niemals Lesezugriff auf die Tabellen in der mysql
-Datenbank gewähren.
MySQL 5.1 verwendet eine stärkere, erstmals in MySQL 4.1 implementierte Authentifizierungsmethode, die während des Verbindungsvorgangs einen besseren Passwortschutz bietet als frühere Versionen. Sie ist auch dann sicher, wenn TCP/IP-Pakete abgefangen oder die mysql
-Datenbank aufgezeichnet wird. Abschnitt 5.8.9, „Kennwort-Hashing ab MySQL 4.1“, enthält eine eingehendere Beschreibung der Passwortverschlüsselung.
Die folgende Tabelle zeigt, wie verschiedene Kombinationen von Host
- und User
-Werten in der Tabelle user
auf eingehende Verbindungen angewendet werden.
Host Wert | User Wert | Zulässige Verbindungen |
'thomas.loc.gov' | 'fred' | fred , stellt Verbindung her über thomas.loc.gov |
'thomas.loc.gov' | '' | Beliebiger Benutzer, stellt Verbindung her über thomas.loc.gov |
'%' | 'fred' | fred , stellt Verbindung her über beliebigen Host |
'%' | '' | Beliebiger Benutzer, stellt Verbindung her über beliebigen Host |
'%.loc.gov' | 'fred' | fred , stellt Verbindung her über beliebigen Host in der Domäne loc.gov |
'x.y.%' | 'fred' | fred , stellt Verbindung her über x.y.net , x.y.com , x.y.edu und so weiter (dies ist wahrscheinlich nicht sehr sinnvoll) |
'144.155.166.177' | 'fred' | fred , stellt Verbindung her vom Host mit der IP-Adresse 144.155.166.177 |
'144.155.166.%' | 'fred' | fred , stellt Verbindung her über beliebigen Host im Klasse-C-Subnetz 144.155.166 |
'144.155.166.0/255.255.255.0' | 'fred' | wie oben |
Es kann durchaus vorkommen, dass für die Host- und Benutzernamen einer eingehenden Verbindung mehrere passende Datensätze in der Tabelle user
vorhanden sind. Die obigen Beispiele demonstrieren dies: Mehrere der angezeigten Einträge stimmen mit einer Verbindung von fred
über thomas.loc.gov
überein.
Wenn mehrere Übereinstimmungen möglich sind, muss der Server ermitteln, welche davon er verwenden soll. Dieses Problem löst er wie folgt:
Wenn der Server die Tabelle user
in den Speicher einliest, sortiert er die Datensätze.
Versucht nun ein Client eine Verbindung herzustellen, dann durchsucht der Server die Datensätze in der Sortierreihenfolge.
Der Server verwendet den ersten mit dem Host- und Benutzernamen des Clients übereinstimmenden Datensatz.
Um zu verstehen, wie dies funktioniert, nehmen wir einmal an, dass die Tabelle user
wie folgt aussieht:
+-----------+----------+- | Host | User | ... +-----------+----------+- | % | root | ... | % | jeffrey | ... | localhost | root | ... | localhost | | ... +-----------+----------+-
Wenn der Server die Tabelle in den Speicher einliest, sortiert er die Datensätze mit den spezifischsten Host
-Werten nach oben. Literale Hostnamen und IP-Nummern sind am spezifischsten. Das Muster '%'
bedeutet „jeder Host“ und ist am wenigsten spezifisch. Datensätze mit demselben Host
-Wert werden nach den spezifischsten User
-Werten sortiert (wobei ein leerer User
-Wert die Bedeutung „beliebiger Benutzer“ hat und am wenigsten spezifisch ist). Bei der oben gezeigten Tabelle user
sieht das Ergebnis nach der Sortierung wie folgt aus:
+-----------+----------+- | Host | User | ... +-----------+----------+- | localhost | root | ... | localhost | | ... | % | jeffrey | ... | % | root | ... +-----------+----------+-
Wenn ein Client eine Verbindung herzustellen versucht, durchsucht der Server die sortierten Datensätze und verwendet die erste gefundene Übereinstimmung. Stellt jeffrey
über localhost
eine Verbindung her, dann liegt bei zwei Datensätzen in der Tabelle eine Übereinstimmung vor: zum einen der Datensatz mit den Host
- und User
-Werten 'localhost'
und ''
, zum anderen der Datensatz mit den Werten '%'
und 'jeffrey'
. Der Datensatz 'localhost'
taucht jedoch in der sortierten Tabelle zuerst auf, wird also vom Server verwendet.
Es folgt ein weiteres Beispiel. Angenommen, die Tabelle user
sähe so aus:
+----------------+----------+- | Host | User | ... +----------------+----------+- | % | jeffrey | ... | thomas.loc.gov | | ... +----------------+----------+-
Die sortierte Tabelle hat dann folgendes Aussehen:
+----------------+----------+- | Host | User | ... +----------------+----------+- | thomas.loc.gov | | ... | % | jeffrey | ... +----------------+----------+-
Für eine Verbindung von jeffrey
an thomas.loc.gov
liegt eine Übereinstimmung gleich beim ersten Datensatz vor; bei einer Verbindung von jeffrey
an whitehouse.gov
trifft dies für den zweiten Datensatz zu.
Die Ansicht ist weitverbreitet, dass für einen gegebenen Benutzernamen alle Datensätze, die diesen Namen ausdrücklich angeben, zuerst verwendet werden, wenn der Server eine Übereinstimmung für die Verbindung sucht. Dies ist allerdings unzutreffend. Das obige Beispiel veranschaulicht dies: Eine Verbindung von jeffrey
an thomas.loc.gov
findet ihre erste Übereinstimmung nicht bei dem Datensatz, der 'jeffrey'
als Wert in der Spalte User
enthält, sondern beim Datensatz ohne Benutzernamen. Hieraus folgt, dass jeffrey
als anonymer Benutzer authentifiziert wird, obwohl er bei der Verbindungsherstellung einen Benutzernamen angegeben hat.
Wenn Sie eine Verbindung mit dem Server herstellen können, aber Ihre Berechtigungen nicht dem entsprechen, was Sie erwarten, dann wurden Sie wahrscheinlich über ein anderes Konto authentifiziert. Um zu ermitteln, welches Konto der Server für Ihre Authentifizierung verwendet hat, verwenden Sie die Funktion CURRENT_USER()
. (Siehe auch Abschnitt 12.10.3, „Informationsfunktionen“.) Sie gibt einen Wert im Format
zurück, der die Werte user_name
@host_name
User
und Host
des entsprechenden Datensatzes in der Tabelle user
angibt. Angenommen, jeffrey
hat eine Verbindung hergestellt und setzt die folgende Abfrage ab:
mysql> SELECT CURRENT_USER();
+----------------+
| CURRENT_USER() |
+----------------+
| @localhost |
+----------------+
Das hier gezeigte Ergebnis gibt an, dass der übereinstimmende Datensatz in der Tabelle user
einen leeren Wert in der Spalte User
aufweist. Mit anderen Worten behandelt der Server jeffrey
als anonymen Benutzer.
Ein anderer Schritt, den Sie zur Diagnose von Authentifizierungsproblemen anwenden können, besteht darin, die Tabelle user
auszudrucken und sie manuell zu sortieren, um zu ermitteln, wo die erste Übereinstimmung auftritt.
Nachdem Sie eine Verbindung hergestellt haben, wechselt der Server zu Stufe 2 der Zugriffssteuerung. Für jede Anforderung, die Sie über die Verbindung absetzen, ermittelt der Server, welche Operation Sie durchführen wollen, und überprüft dann, ob Sie die zu diesem Zweck erforderlichen Berechtigungen besitzen. Hier nun kommen die Berechtigungsspalten in den Grant-Tabellen ins Spiel. Diese Berechtigungen können aus den folgenden Tabellen stammen: user
, db
, host
, tables_priv
, columns_priv
oder procs_priv
. (An dieser Stelle kann es unter Umständen hilfreich sein, noch einmal Abschnitt 5.8.2, „Wie das Berechtigungssystem funktioniert“, zu lesen. Dort sind die Spalten aufgelistet, die in den verschiedenen Grant-Tabellen vorhanden sind.)
Die Tabelle user
gewährt Berechtigungen, die Ihnen auf globaler Basis zugewiesen werden und die unabhängig von der gewählten Standarddatenbank gelten. Wenn die Tabelle user
Ihnen beispielsweise die Berechtigung DELETE
gewährt, können Sie Datensätze aus allen Tabellen in allen Datenbanken auf dem Serverhost löschen! Anders gesagt sind Berechtigungen für die Tabelle user
Superuser-Berechtigungen. Es ist klug, Berechtigungen in der Tabelle user
nur Superusern wie beispielsweise Datenbankadministratoren zu gewähren. Bei allen anderen Benutzern sollten Sie die Berechtigungen in der Tabelle user
auf 'N'
stehen lassen und Berechtigungen nur auf spezifischeren Ebenen gewähren. Sie können Berechtigungen für bestimmte Datenbanken, Tabellen, Spalten und Routinen gewähren.
Die Tabellen db
und host
gewähren datenbankspezifische Berechtigungen. Werte in den Bereichsspalten dieser Tabellen können die folgende Form annehmen:
Die Jokerzeichen ‘%
’ und ‘_
’ können in den Spalten Host
und Db
dieser Tabellen verwendet werden. Sie haben die gleiche Bedeutung wie bei Mustervergleichsoperationen, die mit dem Operator LIKE
durchgeführt werden. Wenn Sie eines der Zeichen beim Gewähren von Berechtigungen literal verwenden wollen, müssen Sie es mit einem Backslash kennzeichnen. Um beispielsweise den Unterstrich (‘_
’) als Teil eines Datenbanknamens zu verwenden, geben Sie ihn als ‘\_
’ in der GRANT
-Anweisung an.
Der Wert '%'
in der Spalte Host
der Tabelle db
bedeutet „ein beliebiger Host“. Ein leerer Host
-Wert in der Tabelle db
hat die Bedeutung „Weitere Informationen der Tabelle host
entnehmen“ (dieser Vorgang wird im weiteren Verlauf dieses Abschnitts noch beschrieben).
Der Wert '%'
oder ein leerer Wert in der Spalte Host
der Tabelle host
bedeutet „ein beliebiger Host“.
Der Wert '%'
oder ein leerer Wert in der Spalte Db
in einer dieser Tabellen bedeutet „eine beliebige Datenbank“.
Ein leerer User
-Wert in einer der Tabellen führt zur Übereinstimmung mit dem anonymen Benutzer.
Der Server liest die Tabellen db
und host
in den Speicher ein und sortiert sie, während er gleichzeitig die Tabelle user
einliest. Der Server sortiert die Tabelle db
nach den Bereichsspalten Host
, Db
und User
und die Tabelle host
nach den Bereichsspalten Host
und Db
. Wie bei der Sortierung der Tabelle user
werden auch hier die spezifischeren Werte an den Anfang und die weniger spezifischen an das Ende der Tabelle gesetzt, und auch hier verwendet der Server bei der Suche nach Übereinstimmungen das erste passende Ergebnis.
Die Tabellen tables_priv
columns_priv
und proc_priv
gewähren tabellenspezifische, spaltenspezifische und routinenspezifische Berechtigungen. Werte in den Bereichsspalten dieser Tabellen können die folgende Form annehmen:
Die Jokerzeichen ‘%
’ und ‘_
’ können in der Spalte Host
verwendet werden. Sie haben die gleiche Bedeutung wie bei Mustervergleichsoperationen, die mit dem Operator LIKE
durchgeführt werden.
Der Wert '%'
oder ein leerer Wert in der Spalte Host
bedeutet „ein beliebiger Host“.
Die Spalten Db
, Table_name
und Column_name
dürfen weder Jokerzeichen enthalten noch leer sein.
Der Server sortiert die Tabellen tables_priv
, columns_priv
und procs_priv
nach den Spalten Host
, Db
und User
. Dies ähnelt der Sortierung der Tabelle db
, ist aber einfacher, da nur die Spalte Host
Jokerzeichen enthalten darf.
Der Server verwendet die sortierten Tabellen zur Verifizierung aller empfangenen Anforderungen. Bei Anforderungen, die administrative Berechtigungen voraussetzen (z. B. SHUTDOWN
oder RELOAD
), überprüft der Server nur den Datensatz in der Tabelle user
, weil dies die einzige Tabelle ist, die administrative Berechtigungen angibt. Der Server gewährt den Zugriff, wenn der Datensatz die angeforderte Operation gestattet; andernfalls wird der Zugriff abgewiesen. Wenn Sie also beispielsweise mysqladmin shutdown ausführen wollen, aber Ihr Datensatz in der Tabelle user
Ihnen die Berechtigung SHUTDOWN
nicht gewährt, dann verweigert der Server Ihnen den Zugriff, ohne die Tabellen db
oder host
auch nur abgefragt zu haben. (Da diese Tabellen keine Shutdown_priv
-Spalte enthalten, ist dies ohnehin unnötig.)
Bei datenbankbezogenen Anforderungen (INSERT
, UPDATE
usw.) überprüft der Server zuerst die globalen Berechtigungen (Superuser-Berechtigungen), indem er den Datensatz in der Tabelle user
abfragt. Gestattet der Datensatz die angeforderte Operation, dann wird der Zugriff gewährt. Wenn die globalen Berechtigungen in der Tabelle user
nicht ausreichend sind, ermittelt der Server die datenbankspezifischen Berechtigungen, indem er die Tabellen db
und host
überprüft:
Der Server sucht in der Tabelle db
nach einer Übereinstimmung der Spalten Host
, Db
und User
. Die Spalten Host
und User
werden auf Übereinstimmung mit dem Hostnamen und dem MySQL-Benutzernamen des Benutzers geprüft, der die Verbindung herstellen will. Die Spalte Db
wird mit der Datenbank verglichen, auf die der Benutzer zugreifen will. Kann kein Datensatz für Host
und User
gefunden werden, dann wird der Zugriff verweigert.
Ist ein übereinstimmender Datensatz in der Tabelle db
vorhanden und ist die Spalte Host
nicht leer, dann definiert der Datensatz die datenbankspezifischen Berechtigungen für den Benutzer.
Ist die Spalte Host
im übereinstimmenden Datensatz der Tabelle db
leer, dann bedeutet dies, dass die Tabelle host
auflistet, welche Hosts auf die Datenbank zugreifen dürfen. In diesem Fall wird in der Tabelle host
erneut eine Übereinstimmung mit den Spalten Host
und Db
gesucht. Wird kein passender Datensatz in der Tabelle host
gefunden, dann wird der Zugriff verweigert. Wird allerdings eine Übereinstimmung gefunden, dann werden die datenbankspezifischen Berechtigungen des Benutzers als Schnittmenge (nicht als Gesamtmenge!) der Berechtigungen in den Einträgen der Tabellen db
und host
berechnet, d. h. die Berechtigungen müssen in beiden Einträgen jeweils 'Y'
sein. (Auf diese Weise können Sie allgemeine Berechtigungen im Datensatz der Tabelle db
gewähren und diese dann über die Tabelle host
auf Hostbasis selektiv einschränken.)
Nachdem er die datenbankspezifischen Berechtigungen ermittelt hat, die durch die Einträge in den Tabellen db
und host
gewährt werden, fügt der Server diese den durch die Tabelle user
gewährten Berechtigungen hinzu. Gestattet das Ergebnis die angeforderte Operation, dann wird der Zugriff gewährt. Andernfalls überprüft der Server nachfolgend die Tabellen- und Spaltenberechtigungen des Benutzers in den Tabellen tables_priv
bzw. columns_priv
, fügt diese den Benutzerberechtigungen hinzu und gestattet oder verweigert auf der Basis des Ergebnisses den Zugriff. Bei Operationen in Zusammenhang mit gespeicherten Routinen verwendet der Server die Tabelle procs_priv
statt tables_priv
und columns_priv
.
Ausgedrückt in booleschen Termini, lässt sich die vorangegangene Beschreibung der Berechnung von Benutzerberechtigungen wie folgt zusammenfassen:
global privileges OR (database privileges AND host privileges) OR table privileges OR column privileges OR routine privileges
Es ist vielleicht nicht einleuchtend, warum der Server, wenn die globalen Berechtigungen im Datensatz der Tabelle user
zunächst nicht als ausreichend für die angeforderte Operation erachtet werden, diese Berechtigungen später zu den Berechtigungen für die Datenbanken, Tabellen und Spalten hinzufügt. Der Grund hierfür besteht darin, dass eine Anforderung mehrere Berechtigungstypen erfordern kann. Wenn Sie beispielsweise eine INSERT INTO ... SELECT
-Anweisung ausführen, benötigen Sie sowohl die Berechtigung INSERT
als auch die Berechtigung SELECT
. Ihre Berechtigungen sehen unter Umständen so aus, dass der Datensatz in der Tabelle user
eine dieser Berechtigungen und der Datensatz in der Tabelle db
die andere Berechtigung gewährt. In diesem Fall besitzen Sie die erforderlichen Berechtigungen, um die Anforderung durchzuführen, aber der Server kann dies nicht mithilfe nur einer Tabelle bestimmen; vielmehr müssen die von den Einträgen in beiden Tabellen gewährten Berechtigungen kombiniert werden.
Die Tabelle host
wird von GRANT
- und REVOKE
-Anweisungen nicht beeinflusst, liegt also in den meisten MySQL-Installationen brach. Wenn Sie sie jedoch manuell modifizieren, können Sie sie für bestimmte Spezialzwecke einsetzen, z. B. um eine Liste sicherer Server zu führen. Bei TcX beispielsweise enthält die Tabelle host
eine Liste aller Systeme im lokalen Netzwerk. Diesen sind alle Berechtigungen gewährt.
Sie können die Tabelle host
auch verwenden, um Hosts anzugeben, die nicht sicher sind. Nehmen wir an, dass Sie einen Computer namens public.your.domain
haben, der sich in einem öffentlichen Bereich befindet, den Sie als nicht sicher erachten. Sie können Zugriff auf alle Hosts in Ihrem Netzwerk mit Ausnahme dieses Computers gewähren, indem Sie die Einträge der Tabelle host
wie folgt verwenden:
+--------------------+----+- | Host | Db | ... +--------------------+----+- | public.your.domain | % | ... (all privileges set to 'N') | %.your.domain | % | ... (all privileges set to 'Y') +--------------------+----+-
Natürlich sollten Sie Ihre Änderungen an den Grant-Tabellen immer testen (z. B. mit SHOW GRANTS
), um sicherzustellen, dass Ihre Zugriffsberechtigungen tatsächlich so konfiguriert sind, wie Sie es wünschen.
Beim Start liest mysqld den gesamten Inhalt der Grant-Tabellen in den Speicher. Die Tabellen im Arbeitsspeicher werden zu diesem Zeitpunkt für die Zugriffssteuerung verbindlich.
Wenn der Server die Grant-Tabellen neu lädt, sind Berechtigungen für vorhandene Clientverbindungen hiervon wie folgt betroffen:
Änderungen an Berechtigungen für Tabellen und Spalten werden beginnend mit der nächsten Anforderung des Clients gültig.
Datenbankberechtigungen werden bei der nächsten USE
-Anweisung gültig.
db_name
Änderungen an globalen Berechtigungen und Passwörtern werden gültig, wenn der Client beim nächsten Mal eine Verbindung herstellen will.
Wenn Sie die Grant-Tabellen indirekt mit Anweisungen wie GRANT
, REVOKE
oder SET PASSWORD
modifizieren, bemerkt der Server diese Änderungen und lädt die Grant-Tabellen sofort wieder neu in den Speicher.
Ändern Sie die Grant-Tabellen hingegen direkt mit Anweisungen wie INSERT
, UPDATE
oder DELETE
, dann werden Ihre berechtigungsbezogenen Änderungen erst umgesetzt, wenn Sie den Server neu starten oder ihn zum Neuladen der Tabellen anweisen. Um die Grant-Tabellen manuell neu zu laden, setzen Sie eine FLUSH PRIVILEGES
-Anweisung ab oder führen den Befehl mysqladmin flush-privileges oder mysqladmin reload aus.
Wenn Sie die Grant-Tabellen ändern, aber vergessen, sie neu zu laden, dann werden Ihre Änderungen erst dann umgesetzt, wenn Sie den Server neu starten. Unter Umständen wundern Sie sich aus diesem Grund darüber, dass Ihre Änderungen überhaupt keinen Unterschied zu machen scheinen!
Wenn beim Versuch, eine Verbindung zum MySQL-Server herzustellen, Probleme auftreten, dann können Sie die in diesem Abschnitt beschriebenen Schritte ausführen, um diese Probleme zu beseitigen.
Vergewissern Sie sich zunächst, dass der Server auch ausgeführt wird. Läuft er nicht, dann können Sie auch keine Verbindung herstellen. Wenn Sie beispielsweise versuchen, eine Verbindung zum Server herzustellen, und eine Meldung wie die folgende angezeigt wird, dann kann Ursache hierfür auch sein, dass der Server schlichtweg nicht läuft:
shell>mysql
ERROR 2003: Can't connect to MySQL server on 'host_name
' (111) shell>mysql
ERROR 2002: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (111)
Ferner ist es möglich, dass der Server zwar ausgeführt wird, Sie aber eine Verbindung über einen TCP/IP-Port, eine Named Pipe oder eine Unix-Socketdatei herstellen wollen, die nicht mit der Ressource übereinstimmt, auf der der Server horcht. Um dieses Problem zu beheben, geben Sie beim Aufruf eines Clientprogramms eine Option --port
oder --socket
an, um die korrekte Portnummer bzw. Named Pipe oder Unix-Socketdatei anzugeben. Mithilfe des folgenden Befehls ermitteln Sie, wo die Socketdatei sich befindet:
shell> netstat -ln | grep mysql
Die Grant-Tabellen müssen korrekt konfiguriert sein, damit der Server sie zur Zugriffssteuerung verwenden kann. Bei einigen Distributionstypen (z. B. Binärdistributionen für Windows oder RPM-Distributionen für Linux) initialisiert der Installationsvorgang die mysql
-Datenbank, die die Grant-Tabellen enthält. Wenn Ihre Distribution dies nicht tut, dann müssen Sie die Grant-Tabellen manuell initialisieren, indem Sie das Skript mysql_install_db ausführen. Detaillierte Informationen finden Sie in Abschnitt 2.9.2, „Schritte nach der Installation unter Unix“.
Eine Möglichkeit, zu ermitteln, ob Sie die Grant-Tabellen initialisieren müssen, besteht darin, nach einem Verzeichnis mysql
zu suchen, das sich im Datenverzeichnis befindet. (Das Datenverzeichnis heißt normalerweise data
oder var
und befindet sich seinerseits im MySQL-Installationsverzeichnis.) Vergewissern Sie sich, dass eine Datei namens user.MYD
im Datenverzeichnis mysql
vorhanden ist. Sollte dies nicht der Fall sein, dann führen Sie das Skript mysql_install_db aus. Nach Ausführung des Skripts und dem Starten des Servers können Sie die anfänglich vorhandenen Berechtigungen durch Ausführung des folgenden Befehls überprüfen:
shell> mysql -u root test
Der Server sollte die Herstellung dieser Verbindung ohne Fehler gestatten.
Nach einer frischen Installation sollten Sie eine Verbindung mit dem Server herstellen und Ihre Benutzer und deren Zugriffsberechtigungen einrichten:
shell> mysql -u root mysql
Der Server sollte diese Verbindung gestatten, da der MySQL-Benutzer root
anfänglich kein Passwort hat. Dies ist natürlich auch ein Sicherheitsrisiko d. h. Sie sollten das Passwort für das root
-Konto einrichten, während Sie auch die übrigen MySQL-Konten konfigurieren. Anweisungen zur Einstellung der anfänglichen Passwörter finden Sie in Abschnitt 2.9.3, „Einrichtung der anfänglichen MySQL-Berechtigungen“.
Haben Sie, sofern Sie eine vorhandene MySQL-Installation auf eine neuere Version aktualisiert haben, das Skript mysql_fix_privilege_tables ausgeführt? Wenn nicht, holen Sie dies schleunigst nach. Die Struktur der Grant-Tabellen ändert sich ab und an, wenn neue Funktionalitäten hinzugefügt werden. Deswegen sollten Sie nach einem Upgrade immer sicherstellen, dass Ihre Tabellen die aktuell gültige Struktur aufweisen. Informationen zur Vorgehensweise finden Sie in Abschnitt 5.6, „mysql_fix_privilege_tables — Upgrade von MySQL-Systemtabellen“.
Wenn ein Clientprogramm beim Verbindungsversuch die folgende Fehlermeldung erhält, bedeutet dies, dass der Server Passwörter in einem neueren Format als dem erwartet, das der Client erzeugen kann:
shell> mysql
Client does not support authentication protocol requested
by server; consider upgrading MySQL client
Informationen dazu, wie Sie in diesem Fall verfahren, finden Sie in Abschnitt 5.8.9, „Kennwort-Hashing ab MySQL 4.1“, und Abschnitt A.2.3, „Client does not support authentication protocol
“.
Wenn Sie eine Verbindung als root
herstellen und die folgende Fehlermeldung erhalten, dann heißt das, dass kein Datensatz in der Tabelle user
gefunden wurde, der in der Spalte User
den Wert 'root'
aufweist – mysqld kann den Hostnamen Ihres Clients in diesem Fall nicht auflösen:
Access denied for user ''@'unknown' to database mysql
Sie müssen den Server in einem solchen Fall mit der Option --skip-grant-tables
neu starten und in Ihrer Datei /etc/hosts
bzw. \windows\hosts
einen Eintrag für den Host hinzufügen.
Zur Erinnerung: Clientprogramme verwenden Verbindungsparameter, die in Optionsdateien oder über Umgebungsvariablen angegeben sind. Wenn ein Clientprogramm offensichtlich unzutreffende Standardverbindungsparameter sendet, weil Sie auf der Befehlszeile keine entsprechenden Informationen angegeben haben, überprüfen Sie die Umgebung und alle relevanten Optionsdateien. Wenn Sie beispielsweise bei der Ausführung eines Clients ohne Optionen die Fehlermeldung Access denied
erhalten, vergewissern Sie sich, dass Sie in keiner Ihrer Optionsdateien ein altes Passwort angegeben haben!
Sie können die Verwendung von Optionsdateien durch ein Clientprogramm unterdrücken, indem Sie es mit der Option --no-defaults
aufrufen. Zum Beispiel:
shell> mysqladmin --no-defaults -u root version
Die von Clients verwendeten Optionsdateien sind in Abschnitt 4.3.2, „my.cnf-Optionsdateien“ aufgelistet. Umgebungsvariablen werden in Anhang F, Umgebungsvariablen beschrieben.
Wenn Sie die folgende Fehlermeldung erhalten, bedeutet dies, dass Sie das falsche root
-Passwort benutzen:
shell> mysqladmin -u root -pxxxx
ver
Access denied for user 'root'@'localhost' (using password: YES)
Wenn dieser Fehler auftritt, obwohl Sie gar kein Passwort angegeben haben, ergibt sich daraus, dass ein falsches Passwort in irgendeiner Optionsdatei aufgeführt sein muss. Probieren Sie in diesem Fall die Option --no-defaults
wie im vorhergehenden Abschnitt beschrieben aus.
Informationen zur Änderung von Passwörtern finden Sie in Abschnitt 5.9.5, „Kennwörter einrichten“.
Haben Sie das root
-Passwort verloren oder vergessen, dann können Sie mysqld mit --skip-grant-tables
neu starten, um das Passwort zu ändern. Siehe auch Abschnitt A.4.1, „Wie ein vergessenes Kennwort zurückgesetzt wird“.
Wenn Sie ein Passwort mit SET PASSWORD
, INSERT
oder UPDATE
ändern, müssen Sie es mit der Funktion PASSWORD()
verschlüsseln. Verwenden Sie PASSWORD()
für diese Anweisungen nicht, dann funktioniert das Passwort nicht. So wird mit der folgenden Anweisung ein Passwort zwar eingestellt, aber nicht verschlüsselt – und der Benutzer kann nachfolgend keine Verbindung herstellen:
SET PASSWORD FOR 'abe'@'host_name
' = 'eagle';
Stattdessen muss das Passwort wie folgt eingestellt werden:
SET PASSWORD FOR 'abe'@'host_name
' = PASSWORD('eagle');
Die Funktion PASSWORD()
ist entbehrlich, wenn Sie ein Passwort mit GRANT
- oder CREATE USER
-Anweisungen oder dem Befehl mysqladmin password festlegen. Sie alle verschlüsseln das Passwort automatisch mit PASSWORD()
. Siehe auch Abschnitt 5.9.5, „Kennwörter einrichten“, und Abschnitt 13.5.1.1, „CREATE USER
“.
localhost
ist ein Synonym für Ihren lokalen Hostnamen und zudem der standardmäßige Host, mit dem Clients eine Verbindung herzustellen versuchen, wenn Sie keinen Host explizit angeben.
Um dieses Problem auf solchen Systemen zu umgehen, können Sie die Option --host=127.0.0.1
verwenden, um den Serverhost explizit anzugeben. Hierdurch wird eine TCP/IP-Verbindung mit dem lokalen mysqld-Server hergestellt. Sie können TCP/IP auch verwenden, indem Sie eine Option --host
angeben, die den eigentlichen Hostnamen des lokalen Hosts verwendet. In diesem Fall muss der Hostname in einem Datensatz in der Tabelle user
auf dem Serverhost angegeben sein, auch wenn Sie das Clientprogramm auf demselben Host wie den Server ausführen.
Wenn Sie die Fehlermeldung Access denied
erhalten, wenn Sie mit mysql -u
eine Verbindung zur Datenbank herstellen, liegt unter Umständen ein Problem mit der Tabelle user_name
user
vor. Sie können dies überprüfen, indem Sie mysql -u root mysql
ausführen und die folgende SQL-Anweisung absetzen:
SELECT * FROM user;
Das Ergebnis sollte einen Datensatz mit Host
- und User
-Spaltenwerten enthalten, die mit dem Hostnamen Ihres Computers bzw. Ihrem MySQL-Benutzernamen übereinstimmen.
Die Fehlermeldung Access denied
sagt Ihnen, als wer Sie eine Verbindung herzustellen versuchen, von welchem Clienthost Sie diese Verbindung herzustellen versuchen und ob Sie ein Passwort angegeben haben. Normalerweise sollte genau ein Datensatz in der Tabelle user
vorhanden sein, für den eine Übereinstimmung mit dem Host- und dem Benutzernamen vorliegt, die in der Fehlermeldung angegeben werden. Erhalten Sie beispielsweise eine Fehlermeldung, die using password: NO
enthält, dann bedeutet dies, dass Sie versucht haben, sich ohne Passwort anzumelden.
Tritt der folgende Fehler auf, wenn Sie versuchen, eine Verbindung von einem anderen als dem Host herzustellen, auf dem der MySQL-Server ausgeführt wird, dann bedeutet dies, dass in der Tabelle user
kein Datensatz mit einem zum Clienthost passenden Host
-Wert gefunden wurde:
Host ... is not allowed to connect to this MySQL server
Sie können dieses Problem beheben, indem Sie ein Konto für die Kombination aus Clienthostname und Benutzername erstellen, die Sie zur Verbindungsherstellung verwenden.
Wenn Sie IP-Adresse oder Hostname des Computers, von dem aus Sie die Verbindung herstellen, nicht kennen, dann sollten Sie einen Datensatz mit dem Wert '%'
in die Spalte Host
der Tabelle user
einfügen. Nachdem Sie versucht haben, eine Verbindung vom Clientsystem herzustellen, ermitteln Sie mit einer SELECT USER()
-Abfrage, wie Sie die Verbindung tatsächlich hergestellt haben. (Ändern Sie nachfolgend den Eintrag '%'
im betreffenden Datensatz der Tabelle user
zu dem im Log angegebenen Hostnamen. Wenn Sie dies versäumen, bleibt Ihr System unsicher, da es dem angegebenen Benutzernamen Verbindungen von jedem Host aus gestattet.)
Unter Linux kann ein anderer Grund für diese Fehlermeldung darin bestehen, dass Sie eine aus einer Binärdistribution stammende MySQL-Version verwenden, die mit einer anderen Version der glibc
-Bibliothek als der von Ihnen verwendeten kompiliert wurde. In diesem Fall sollten Sie entweder Ihr Betriebssystem oder glibc
aktualisieren oder eine Quelldistribution der MySQL-Version herunterladen und selbst kompilieren. Dies ist kein Problem, da Kompilierung und Installation eines Quellcode-RPM in der Regel einfach und schnell erledigt sind.
Wenn Sie beim Verbindungsversuch einen Hostnamen angeben, aber eine Fehlermeldung erhalten, in der der Hostname nicht oder an seiner Stelle eine IP-Adresse angegeben ist, dann bedeutet dies, dass am MySQL-Server bei dem Versuch, die IP-Adresse des Clients in einen Namen aufzulösen, ein Fehler aufgetreten ist:
shell> mysqladmin -u root -pxxxx
-h some_hostname
ver
Access denied for user 'root'@'' (using password: YES)
Dies weist auf ein DNS-Problem hin. Um es zu beheben, setzen Sie den internen DNS-Hostnamens-Cache durch Ausführen von mysqladmin flush-hosts zurück. Siehe auch Abschnitt 7.5.6, „Wie MySQL DNS benutzt“.
Die folgenden Lösungen versprechen dauerhaften Erfolg:
Ermitteln Sie, was bei Ihrem DNS-Server nicht stimmt, und beheben Sie das Problem.
Geben Sie in den MySQL-Grant-Tabellen IP-Adressen statt Hostnamen an.
Fügen Sie für den Namen des Clientcomputers einen Eintrag in /etc/hosts
bzw. \windows\hosts
hinzu.
Starten Sie mysqld mit der Option --skip-name-resolve
.
Starten Sie mysqld mit der Option --skip-host-cache
.
Stellen Sie eine Verbindung mit localhost
her, wenn Sie unter Unix den Server und den Client auf demselben Computer ausführen. Für Verbindungen mit localhost
verwendet Unix statt TCP/IP eine Unix-Socketdatei.
Stellen Sie eine Verbindung mit dem Hostnamen .
(Punkt) her, wenn Sie unter Windows den Server und den Client auf demselben Computer ausführen und der Server Named Pipes unterstützt. Verbindungen mit .
verwenden statt TCP/IP eine Named Pipe.
Wenn mysql -u root test
funktioniert, aber mysql -h
zur Fehlermeldung your_hostname
-u root testAccess denied
führt (wobei your_hostname
der tatsächliche Hostname des lokalen Hosts ist), dann steht unter Umständen für Ihren Host nicht der korrekte Name in der Tabelle user
. Ein häufig auftretendes Problem besteht hier darin, dass der Host
-Wert des Datensatzes in der Tabelle user
einen unqualifizierten Hostnamen angibt, die Namensauflösungsroutinen Ihres Systems aber einen vollqualifizierten Domänennamen zurückgeben (oder umgekehrt). Wenn Sie also beispielsweise einen Eintrag mit dem Host 'tcx'
in der Tabelle user
haben, aber Ihr DNS MySQL meldet, dass Ihr Hostname 'tcx.subnet.se'
lautet, dann funktioniert der Eintrag nicht. Versuchen Sie, der Tabelle user
einen Eintrag hinzufügen, der die IP-Adresse Ihres Hosts als Host
-Spaltenwert enthält. (Alternativ können Sie einen Eintrag in der Tabelle user
mit einem Host
-Wert hinzufügen, der ein Jokerzeichen enthält – z. B. 'tcx.%'
. Allerdings ist die Verwendung von Hostnamen, die auf ‘%
’ enden, ein Sicherheitsrisiko. Wir raten dringend davon ab!)
Wenn mysql -u
funktioniert, user_name
testmysql -u
aber nicht, dann haben Sie dem betreffenden Benutzer keinen Datenbankzugriff auf user_name
other_db_name
other_db_name
gewährt.
Wenn mysql -u
bei einer Ausführung auf dem Serverhost funktioniert, user_name
mysql -h
jedoch bei der Ausführung auf dem Clienthost jedoch nicht, dann haben Sie für den betreffenden Benutzernamen den Zugriff vom entfernten Host auf den Server nicht aktiviert.
host_name
-u user_name
Wenn Sie nicht feststellen können, warum Sie den Fehler Access denied
erhalten, entfernen Sie aus der Tabelle user
alle Einträge, die Host
-Werte mit Jokerzeichen aufweisen (d. h. Einträge, die ‘%
’ oder ‘_
’ enthalten). Ein sehr häufiger Fehler besteht darin, einen neuen Eintrag mit Host
='%'
und User
='
einzufügen, weil man der Ansicht ist, dass dies die Angabe von some_user
'localhost
zur Verbindung von demselben Computer aus ermöglicht. Der Grund dafür, dass dies nicht funktioniert, ist, dass die Standardberechtigungen einen Eintrag mit Host
='localhost'
und User
=''
enthalten. Da dieser Eintrag einen Host
-Wert 'localhost'
aufweist, der spezifischer ist als '%'
, wird er anstelle des neuen Eintrags verwendet, wenn eine Verbindung von localhost
aus hergestellt wird! Die korrekte Vorgehensweise besteht darin, einen zweiten Eintrag mit Host
='localhost'
und User
='
einzufügen oder den Eintrag mit some_user
'Host
='localhost'
und User
=''
zu löschen. Nach dem Löschen des Eintrags dürfen Sie nicht vergessen, eine FLUSH PRIVILEGES
-Anweisung abzusetzen, um die Grant-Tabellen neu zu laden.
Wenn Sie den folgenden Fehler erhalten, liegt unter Umständen ein Problem mit den Tabellen db
oder host
vor:
Access to database denied
Wenn der in der Tabelle db
gewählte Eintrag einen leeren Wert in der Spalte Host
aufweist, müssen Sie sicherstellen, dass mindestens ein entsprechender Eintrag in der Tabelle host
vorhanden ist, der angibt, für welche Hosts der Eintrag in der Tabelle db
gilt.
Wenn Sie eine Verbindung mit dem MySQL-Server herstellen können, aber immer dann eine Fehlermeldung Access denied
erhalten, wenn Sie eine SELECT ... INTO OUTFILE
- oder LOAD DATA INFILE
-Anweisung absetzen, ist für Ihren Eintrag in der Tabelle user
die Berechtigung FILE
nicht aktiviert.
Ändern Sie die Grant-Tabellen direkt (z. B. mit INSERT
, UPDATE
oder DELETE
) und werden Ihre Änderungen offenbar ignoriert, dann dürfen Sie nicht vergessen, eine FLUSH PRIVILEGES
-Anweisung oder den Befehl mysqladmin flush-privileges auszuführen, damit der Server Ihre Berechtigungstabellen neu einliest. Andernfalls werden Ihre Änderungen erst beim nächsten Neustart des Servers umgesetzt. Denken Sie auch immer daran, dass Sie, wenn Sie das root
-Passwort mit einem UPDATE
-Befehl geändert haben, das neue Passwort erst nach dem Schreiben der Berechtigungen angeben müssen, da der Server vorher gar nicht weiß, dass Sie Ihr Passwort geändert haben!
Wenn Ihre Berechtigungen im Verlauf einer Sitzung offensichtlich geändert werden, besteht die Möglichkeit, dass ein MySQL-Administrator die Änderungen vorgenommen hat. Das Neuladen der Grant-Tabellen wirkt sich auf neue Clientverbindungen, aber auch auf vorhandene Verbindungen aus (siehe auch Abschnitt 5.8.7, „Wann Berechtigungsänderungen wirksam werden“).
Wenn Sie bei einem Perl-, PHP-, Python- oder ODBC-Programm Probleme mit dem Zugriff haben, sollten Sie versuchen, eine Serververbindung mit mysql -u
oder user_name
db_name
mysql -u
herzustellen. Wenn Sie eine Verbindung mit dem mysql-Client herstellen können, wird das Problem von Ihrem Programm und nicht von den Zugriffsberechtigungen verursacht. (Zwischen user_name
-pyour_pass
db_name
-p
und dem Passwort ist kein Leerzeichen vorhanden; Sie können auch die Syntax --password=
zur Angabe des Passworts verwenden. Wenn Sie die Option your_pass
-p
bzw. --password
ohne Passwortwert benutzen, fordert Sie MySQL zur Eingabe des Passworts auf.)
Zu Testzwecken starten Sie den mysqld-Server mit der Option --skip-grant-tables
. Sie können dann die MySQL-Grant-Tabellen ändern und das Skript mysqlaccess zur Überprüfung verwenden, ob Ihre Änderungen die gewünschte Wirkung hervorrufen. Wenn Sie mit den Änderungen zufrieden sind, führen Sie mysqladmin flush-privileges aus, um dem mysqld-Server anzuweisen, die neuen Grant-Tabellen ab sofort zu verwenden. (Das Neuladen der Grant-Tabellen hat Vorrang vor der Option --skip-grant-tables
. Dies ermöglicht Ihnen, den Server zur sofortigen Verwendung der neuen Grant-Tabellen anzuweisen, ohne dass ein Serverneustart erforderlich wäre.)
Wenn alles andere fehlschlägt, starten Sie den mysqld-Server mit einer Debug-Option (z. B. --debug=d,general,query
). Hierdurch werden Host- und Benutzerinformationen zu Verbindungsversuchen sowie Angaben zu allen abgesetzten Befehlen ausgegeben. Siehe auch Abschnitt E.1.2, „Trace-Dateien erzeugen“.
Wenn Sie andere Probleme mit den MySQL-Grant-Tabellen haben und diese der Mailingliste beschreiben wollen, fügen Sie auch immer einen Speicherauszug der MySQL-Grant-Tabellen bei. Diesen können Sie mit dem Befehl mysqldump mysql erstellen. Verwenden Sie zum Übermitteln eines Fehlerberichts die in Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“ beschriebenen Anweisungen. In manchem Fällen müssen Sie mysqld unter Umständen mit der Option --skip-grant-tables
neu starten, um mysqldump ausführen zu können.
MySQL-Benutzerkonten sind in der Tabelle user
der Datenbank mysql
aufgelistet. Jedem MySQL-Konto wird ein Passwort zugewiesen. Allerdings wird in der Spalte Password
der Tabelle user
nicht die unverschlüsselte Version des Passworts gespeichert, sondern ein auf dessen Basis berechneter Hash-Wert. Die Hash-Werte für Passwörter werden mit der Funktion PASSWORD()
berechnet.
MySQL verwendet die Passwörter in zwei Phasen der Client/Server-Kommunikation:
Wenn ein Client eine Verbindung zum Server herstellen will, gibt es einen ersten Authentifizierungsschritt, bei dem der Client ein Passwort mit einem Hash-Wert vorweisen muss, der mit dem Hash-Wert übereinstimmt, welcher in der Tabelle user
für das vom Client verwendete Konto gespeichert ist.
Wenn der Client die Verbindung hergestellt hat, kann er – sofern er über ausreichende Berechtigungen verfügt – die Passwort-Hashes für die in der Tabelle user
gelisteten Konten einstellen oder ändern. Der Client kann dies tun, indem er mithilfe der Funktion PASSWORD()
einen Passwort-Hash erzeugt oder die Anweisungen GRANT
oder SET PASSWORD
verwendet.
Mit anderen Worten benutzt der Server die Hash-Werte während der Authentifizierung, wenn der Client erstmals eine Verbindung herzustellen versucht. Dagegen erzeugt der Server Hash-Werte, wenn ein verbundener Client die Funktion PASSWORD()
aufruft oder eine GRANT
- oder SET PASSWORD
-Anweisung benutzt, um ein Passwort einzustellen oder zu ändern.
Die Methode für das Passwort-Hashing wurde in MySQL 4.1 geändert, um mehr Sicherheit zu bieten und das Risiko zu verringern, dass Passwörter abgefangen werden. Allerdings wird diese neue Methode nur von Servern und Clients unter MySQL 4.1 und höher verstanden, was Kompatibilitätsprobleme verursachen kann. Ein Client unter Version 4.1 oder höher kann mit einem Server unter einer Version vor 4.1 eine Verbindung herstellen, da der Client sowohl die alte als auch die neue Hashing-Methode versteht. Allerdings kann es zu Schwierigkeiten kommen, wenn ein Client unter einer alten Version mit einem Server unter Version 4.1 oder höher einen Verbindungsaufbau probiert. So kann eine Verbindung, die ein mysql-Client unter Version 3.23 mit einem Server unter 5.1 herzustellen versucht, mit der folgenden Fehlermeldung fehlschlagen:
shell> mysql -h localhost -u root
Client does not support authentication protocol requested
by server; consider upgrading MySQL client
Ein anderes häufiges Beispiel für dieses Phänomen tritt auf, wenn nach einem Upgrade auf MySQL 4.1 versucht wird, die ältere PHP-mysql
-Erweiterung zu verwenden. (Siehe auch Abschnitt 24.3.1, „Allgemeine Probleme mit MySQL und PHP“.)
Im Folgenden werden die Unterschiede zwischen der alten und der neuen Passwortmethode beschrieben. Ferner werden wir erläutern, was Sie tun müssen, wenn Sie Ihren Server unter Beibehaltung der Abwärtskompatibilität mit Clients unter Versionen vor 4.1 aktualisieren wollen. Zusätzliche Informationen finden Sie unter Abschnitt A.2.3, „Client does not support authentication protocol
“. Diese Hinweise sind besonders wichtig für PHP-Programmierer, die ihre MySQL-Datenbanken von einer Version vor 4.1 auf Version 4.1 oder höher migrieren.
Hinweis: In der Beschreibung wird das Verhalten von Version 4.1 und höher dem Verhalten älterer Versionen gegenübergestellt. Tatsächlich aber wurde das hier beschriebene Verhalten erst mit Version 4.1.1 implementiert. MySQL 4.1.0 ist eine „merkwürdige“ Version, denn sie weist eine etwas andere Methode auf als die Versionen 4.1.1 und folgende. Die Unterschiede zwischen 4.1.0 und den neueren Versionen sind im MySQL 5.0 Reference Manual ausführlicher beschrieben.
In MySQL vor Version 4.1 sind die Passwort-Hashes, die mit der Funktion PASSWORD()
berechnet werden, 16 Bytes lang. Solche Hashes sehen etwa so aus:
mysql> SELECT PASSWORD('mypass');
+--------------------+
| PASSWORD('mypass') |
+--------------------+
| 6f8c114b58f2ce9e |
+--------------------+
Die Spalte Password
in der Tabelle user
(in der diese Hashes gespeichert werden) ist bei MySQL vor Version 4.1 ebenfalls 16 Bytes lang.
Seit MySQL 4.1 erzeugt die geänderte PASSWORD()
-Funktion einen 41 Byte langen Hash-Wert:
mysql> SELECT PASSWORD('mypass');
+-------------------------------------------+
| PASSWORD('mypass') |
+-------------------------------------------+
| *6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4 |
+-------------------------------------------+
Entsprechend muss die Spalte Password
in der Tabelle user
ebenfalls 41 Byte lang sein, um diese Werte aufnehmen zu können:
Wenn Sie eine Neuinstallation von MySQL 5.1 durchführen, wird die Spalte Password
automatisch auf 41 Byte verlängert.
Die Aktualisierung von MySQL 4.1 (4.1.1 oder höher in der Serie 4.1) auf MySQL 5.1 sollte diesbezüglich unproblematisch zu sein, da beide Versionen dieselbe Hashing-Methode für Passwörter einsetzen. Wollen Sie hingegen von einem älteren MySQL-Release auf Version 5.1 aktualisieren, dann sollten Sie zunächst ein Upgrade auf 4.1 durchführen und diese 4.1-Installation dann auf 5.1 aktualisieren.
Die verbreiterte Password
-Spalte kann Passwort-Hashes im alten wie im neuen Format aufnehmen. Das Format eines gegebenen Hash-Wertes kann auf zweierlei Art und Weise bestimmt werden:
Der offensichtliche Unterschied ist die Länge (16 Bytes im Vergleich zu 41 Bytes).
Ein zweiter Unterschied besteht darin, dass Passwort-Hashes im neuen Format immer mit dem Zeichen ‘*
’ beginnen, was bei alten Passwörtern nie der Fall ist.
Das längere Format für Passwort-Hashes hat bessere kryptografische Eigenschaften, und die auf langen Hashes basierende Clientauthentifizierung ist sicherer als die alte, auf kurzen Hashes basierende Methode.
Die Unterschiede zwischen kurzen und langen Passwort-Hashes sind sowohl dafür, wie der Server Passwörter während der Authentifizierung verwendet, als auch dafür relevant, wie er Passwort-Hashes für verbundene Clients erzeugt, die Operationen zur Passwortänderung durchführen.
Die Breite der Password
-Spalte wirkt sich auf die Art und Weise aus, wie der Server Passwort-Hashes während der Authentifizierung benutzt:
Wenn die Spalte kurz ist, wird die Authentifizierung mit kurzen Hashes verwendet.
Ist die Spalte hingegen lang, dann kann sie kurze wie auch lange Hashes aufnehmen, und der Server kann beide Formate verwenden:
Clients unter einer Version vor 4.1 können zwar Verbindungen herstellen, aber sie können, weil sie nur die alte Hashing-Methode kennen, eine Authentifizierung nur für Konten mit kurzen Hashes durchführen.
Clients unter 4.1 und höher können sich mit Konten authentifizieren, die kurze oder lange Hashes haben.
Auch bei Konten mit kurzen Hashes ist der Authentifizierungsvorgang eigentlich ein bisschen sicherer für Clients unter 4.1 und höher als bei älteren Clients. Aus sicherheitstechnischer Sicht sieht der Übergang von der geringsten zur höchsten Sicherheit wie folgt aus:
Clients unter Versionen vor 4.1 mit kurzem Passwort-Hash
Clients unter Versionen ab 4.1 mit kurzem Passwort-Hash
Clients unter Versionen ab 4.1 mit langem Passwort-Hash
Die Art und Weise, wie der Server Passwort-Hashes für verbundene Clients erzeugt, wird von der Breite der Spalte Password
und von der Option --old-passwords
beeinflusst. Ein Server unter 4.1 oder höher erzeugt lange Hashes nur, wenn bestimmte Bedingungen erfüllt werden: Die Spalte Password
muss breit genug für lange Werte sein, und die Option --old-passwords
darf nicht angegeben worden sein. Diese Bedingungen gelten wie folgt:
Die Spalte Password
muss breit genug sein, um lange Hashes (41 Bytes) aufzunehmen. Wenn die Spalte nicht aktualisiert wurde und noch die Breite von 16 Bytes hat, stellt der Server fest, dass lange Hashes nicht in die Spalte passen. Insofern werden nur kurze Hashes erzeugt, wenn ein Client passwortändernde Operationen mit PASSWORD()
, GRANT
oder SET PASSWORD
durchführt. Dieses Verhalten tritt auf, wenn Sie auf Version 4.1 aktualisiert, aber das Skript mysql_fix_privilege_tables zur Verbreiterung der Spalte Password
noch nicht ausgeführt haben.
Ist die Spalte Password
breit, dann kann sie kurze und lange Passwort-Hashes speichern. In diesem Fall erzeugen PASSWORD()
, GRANT
und SET PASSWORD
lange Hashes, sofern der Server nicht mit der Option --old-passwords
gestartet wurde. Diese Option erzwingt am Server die Erzeugung kurzes Hashes.
Der Zweck der Option --old-passwords
besteht darin, Ihnen die Beibehaltung der Abwärtskompatibilität mit Clients unter Versionen vor 4.1 unter solchen Umständen zu ermöglichen, unter denen der Server andernfalls lange Passwort-Hashes erzeugen würde. Die Option beeinträchtigt die Authentifizierung nicht (denn Clients unter 4.1 und höher können weiterhin Konten mit langen Passwort-Hashes verwenden), verhindert aber die Erstellung eines langen Passwort-Hashes in der Tabelle user
als Folge einer passwortändernden Operation. Andernfalls könnte das Konto nicht länger von Clients unter einer alten MySQL-Version verwendet werden. Ohne die Option --old-passwords
wäre das folgende, nicht wünschenswerte Szenario möglich:
Ein alter Client stellt eine Verbindung zu einem Konto her, das einen kurzen Passwort-Hash hat.
Der Client ändert sein eigenes Passwort. Ohne die Option --old-passwords
führt dies dazu, dass das Konto einen langen Passwort-Hash erhält.
Beim nächsten Verbindungsversuch des alten Clients mit dem betreffenden Konto schlägt die Verbindung fehl, weil das Konto einen langen Passwort-Hash aufweist, der zur Authentifizierung die neue Hashing-Methode benötigt. (Sobald für ein Konto ein langer Passwort-Hash in der Tabelle user
gespeichert wird, können nur Clients unter Version 4.1 und höher eine Authentifizierung durchführen, weil ältere Clients die langen Hashes nicht verstehen.)
Dieses Szenario veranschaulicht, dass es, wenn Sie Clients unter Versionen vor 4.1 unterstützen müssen, gefährlich ist, einen Server unter 4.1 oder höher ohne die Option --old-passwords
zu verwenden. Bei Ausführung des Servers mit der Option --old-passwords
erzeugen passwortändernde Optionen keine langen Passwort-Hashes, d. h. Konten geraten für ältere Clients nicht außer Reichweite. (Diese Clients können sich nicht versehentlich selbst aussperren, indem sie ihr Passwort ändern und am Ende einen langen Passwort-Hash erhalten.)
Der Nachteil der Option --old-passwords
besteht darin, dass alle von Ihnen erstellten oder geänderten Passwörter kurze Hashes verwenden – auch die Clients unter Version 4.1 und höher. Auf diese Weise verlieren Sie die zusätzliche Sicherheit, die lange Passwort-Hashes bieten. Wenn Sie ein Konto erstellen wollen, das einen langen Hash hat (etwa zur Verwendung durch Clients unter 4.1), dann müssen Sie dies tun, während der Server ohne die Option --old-passwords
läuft.
Die folgenden Szenarios sind bei Ausführung eines Servers unter Version 4.1 möglich:
Szenario 1: Kurze Password
-Spalte in der Tabelle user
In der Spalte Password
können nur kurze Hashes gespeichert werden.
Der Server verwendet nur kurze Hashes zur Clientauthentifizierung.
Bei verbundenen Clients verwenden Operationen, die Passwort-Hashes mithilfe von PASSWORD()
, GRANT
oder SET PASSWORD
erzeugen, ausschließlich kurzes Hashes. Änderungen am Passwort eines Kontos führen dazu, dass dieses Konto einen kurzen Passwort-Hash erhält.
Die Option --old-passwords
kann verwendet werden, ist aber überflüssig, weil der Server bei einer kurzen Password
-Spalte ohnehin nur kurze Passwort-Hashes erzeugt.
Szenario 2: Lange Password
-Spalte, Server wurde nicht mit der Option --old-passwords
gestartet
In der Spalte Password
können kurze wie auch lange Hashes gespeichert werden.
Clients unter 4.1 und höher können sich mit Konten authentifizieren, die kurze oder lange Hashes haben.
Clients vor 4.1 können sich nur mithilfe von Konten authentifizieren, die kurze Hashes haben.
Bei verbundenen Clients verwenden Operationen, die Passwort-Hashes mithilfe von PASSWORD()
, GRANT
oder SET PASSWORD
erzeugen, ausschließlich lange Hashes. Änderungen am Passwort eines Kontos führen dazu, dass dieses Konto einen langen Passwort-Hash hat.
Wie weiter oben beschrieben, besteht die Gefahr bei diesem Szenario darin, dass Konten, die einen kurzen Passwort-Hash aufweisen, für Clients unter einer Version vor 4.1 unzugänglich werden. Eine Änderung am Passwort eines solchen Kontos, die mithilfe von GRANT
, PASSWORD()
oder SET PASSWORD
vorgenommen wird, führt dazu, dass das Konto einen langen Passwort-Hash erhält. Von diesem Punkt an kann ein Client unter einer Version vor 4.1 eine Authentifizierung über dieses Konto erst dann durchführen, wenn er seinerseits auf 4.1 oder höher aktualisiert wurde.
Um dieses Problem zu beseitigen, können Sie das Passwort auf eine spezielle Art und Weise ändern. So verwenden Sie etwa normalerweise SET PASSWORD
wie folgt, um ein Kontopasswort zu ändern:
SET PASSWORD FOR 'some_user
'@'some_host
' = PASSWORD('mypass');
Um das Passwort zu ändern, aber einen kurzen Hash zu erstellen, verwenden Sie stattdessen die Funktion OLD_PASSWORD()
:
SET PASSWORD FOR 'some_user
'@'some_host
' = OLD_PASSWORD('mypass');
OLD_PASSWORD()
ist in Situationen nützlich, in denen Sie ausdrücklich einen kurzen Hash erzeugen wollen.
Szenario 3: Lange Password
-Spalte, Server unter Version 4.1 oder höher wurde mit der Option --old-passwords
gestartet
In der Spalte Password
können kurze wie auch lange Hashes gespeichert werden.
Clients unter 4.1 oder höher können sich mit Konten authentifizieren, die kurze oder lange Hashes haben. (Beachten Sie aber, dass die Erzeugung langer Hashes nur dann möglich ist, wenn der Server ohne die Option --old-passwords
gestartet wurde.)
Clients vor 4.1 können sich nur mit Konten authentifizieren, die kurze Hashes haben.
Bei verbundenen Clients verwenden Operationen, die Passwort-Hashes mithilfe von PASSWORD()
, GRANT
oder SET PASSWORD
erzeugen, ausschließlich kurzes Hashes. Änderungen am Passwort eines Kontos führen dazu, dass dieses Konto einen kurzen Passwort-Hash erhält.
In diesem Szenario können Sie keine Konten mit langen Passwort-Hashes erstellen, weil die Option --old-passwords
deren Erzeugung verhindert. Ferner wird, wenn Sie ein Konto mit einem langem Hash vor Verwendung der Option --old-passwords
erstellen, eine Änderung dieses Passworts bei aktivierter Option --old-passwords
dazu führen, dass das Konto ein kurzes Passwort erhält, wodurch die sicherheitstechnischen Vorzüge eines langen Hashs verloren gehen.
Die Nachteile dieser Szenarien lassen sich wie folgt zusammenfassen:
In Szenario 1 müssen Sie auf die Vorteile langer Hashes verzichten, die eine sicherere Authentifizierung ermöglichen.
In Szenario 2 werden Konten mit kurzen Hashes für Clients unter einer Version vor 4.1 unzugänglich, wenn sie ihre Passwörter ändern, ohne die Option OLD_PASSWORD()
ausdrücklich zu verwenden.
In Szenario 3 verhindert --old-passwords
, dass Konten mit kurzen Hashes unzugänglich werden; passwortändernde Operationen setzen allerdings Konten mit langen Hashes auf kurze Hashes herunter, was Sie auch nicht ändern können, solange die Option --old-passwords
gültig bleibt.
Ein Upgrade auf MySQL 4.1 oder höher kann Kompatibilitätsprobleme für Anwendungen verursachen, die PASSWORD()
zur Erzeugung von Passwörter für eigene Zwecke verwenden. Anwendungen sollten dies möglichst nicht tun, weil PASSWORD()
einzig und allein zur Verwaltung von Passwörtern für MySQL-Konten eingesetzt werden sollten. Manche Anwendungen verwenden PASSWORD()
allerdings trotzdem für ihre eigenen Zwecke.
Wenn Sie von einer alten MySQL-Version auf 4.1 oder höher aktualisieren und den Server unter Bedingungen ausführen, bei denen er lange Passwort-Hashes erzeugt, wird eine Anwendung, die PASSWORD()
für eigene Passwörter verwendet, beschädigt. Die empfohlene Vorgehensweise besteht in solchen Fällen darin, die Anwendung so zu ändern, dass sie eine andere Funktion wie SHA1()
oder MD5()
zur Erzeugung von Hash-Werten verwendet. Sollte dies nicht möglich sei, dann können Sie die Funktion OLD_PASSWORD()
benutzen, die zur Erzeugung von Passwörtern im alten Format bereitsteht. Allerdings sollten Sie beachten, dass OLD_PASSWORD()
unter Umständen nicht auf Dauer unterstützt werden wird.
Läuft der Server unter Umständen, unter denen er kurze Hashes erzeugt, steht OLD_PASSWORD()
zwar zur Verfügung, ist aber äquivalent zu PASSWORD()
.
PHP-Programmierer, die ihre MySQL-Datenbanken von Version 4.0 oder älter auf 4.1 oder höher migrieren, sollten Abschnitt 24.3, „MySQLs PHP-API“, lesen.
Dieser Abschnitt beschreibt, wie Konten für Clients auf Ihrem MySQL-Server eingerichtet werden. Behandelt werden die folgenden Themen:
Bedeutung von Kontennamen und Passwörtern bei der Verwendung in MySQL im Vergleich zu den vom Betriebssystem verwendeten Namen und Passwörtern
Einrichtung neuer und Entfernung vorhandener Konten
Ändern von Passwörtern
Richtlinien zur sicheren Passwortverwendung
Verwenden sicherer Verbindungen mit SSL
Ein MySQL-Konto wird durch einen Benutzernamen und den oder die Clienthosts definiert, von denen aus der Benutzer eine Verbindung zum Server herstellen kann. Ein Konto hat auch ein Passwort. Es gibt mehrere Unterschiede zwischen der Verwendung von Benutzernamen und Passwörtern unter MySQL und der Verwendung durch Ihr Betriebssystem:
Benutzernamen, die MySQL zu Authentifizierungszwecken verwendet, haben nicht mit den von Windows oder Unix eingesetzten Benutzernamen (Anmeldenamen) zu tun. Unter Unix versuchen die meisten MySQL-Clients standardmäßig, eine Anmeldung unter Verwendung des aktuellen Unix-Benutzernamens als MySQL-Benutzername durchzuführen, aber dies dient lediglich der Bequemlichkeit. Diese Voreinstellung kann ganz einfach außer Kraft gesetzt werden, da Clientprogramme die Angabe beliebiger Benutzernamen mit der Option -u
bzw. --user
erlauben. Da dies impliziert, dass jeder versuchen kann, unter Verwendung eines beliebigen Benutzernamens eine Serververbindung herzustellen, können Sie eine Datenbank nur schützen, indem Sie für alle MySQL-Konten Passwörter konfigurieren. Jeder, der einen Benutzernamen für ein Konto angibt, welches über kein Passwort verfügt, kann erfolgreich eine Verbindung zum Server herstellen.
MySQL-Benutzernamen dürfen bis zu 16 Zeichen lang sein. Diese Beschränkung ist bei MySQL-Servern und -Clients fest vorgegeben; sie durch Änderung der Tabellendefinitionen in der mysql
-Datenbank zu umgehen, funktioniert nicht.
Hinweis: Sie sollten die Tabellen in der mysql
-Datenbank grundsätzlich nicht auf eine andere als die von MySQL AB vorgeschriebene, in Abschnitt 5.6, „mysql_fix_privilege_tables — Upgrade von MySQL-Systemtabellen“, geschilderte Weise ändern. Jeder Versuch, die Systemtabellen von MySQL auf eine andere Weise zu ändern, führt zu undefiniertem (und nicht unterstütztem!) Verhalten.
Die Benutzernamen des Betriebssystems haben überhaupt keine Beziehung zu den MySQL-Benutzernamen und können sogar eine ganz andere Maximallänge aufweisen. So sind etwa Unix-Benutzernamen normalerweise auf acht Zeichen beschränkt.
Auch haben MySQL-Passwörter nichts mit den Passwörtern zu tun, mit denen Sie sich an Ihrem Betriebssystem anmelden. Es gibt also keine notwendige Verbindung zwischen dem Passwort, mit dem Sie sich an einem Windows- oder Unix-Computer anmelden, und dem Passwort, das Sie für den Zugriff auf den MySQL-Server auf diesem Computer verwenden.
MySQL verschlüsselt Passwörter mit einem eigenen Algorithmus. Diese Verschlüsselung unterscheidet sich von der, die während des Anmeldevorgangs unter Unix eingesetzt wird. Die MySQL-Passwortverschlüsselung ist identisch mit der durch die SQL-Funktion PASSWORD()
implementierten. Die Unix-Passwortverschlüsselung hingegen ist identisch mit der durch die SQL-Funktion ENCRYPT()
implementierten. Details finden Sie in den Beschreibungen zu den Funktionen PASSWORD()
und ENCRYPT()
in Abschnitt 12.10.2, „Verschlüsselungs- und Kompressionsfunktionen“. Seit Version 4.1 verwendet MySQL eine stärkere Authentifizierungsmethode, die während des Anmeldevorgangs einen besseren Passwortschutz gewährleistet als frühere Versionen. Sie ist auch dann sicher, wenn TCP/IP-Pakete abgefangen oder die mysql
-Datenbank aufgezeichnet wird. (Bei den früheren Versionen wurden die Passwörter zwar in verschlüsselter Form in der Tabelle user
abgelegt, aber die Kenntnis des verschlüsselten Passwortwertes konnte zur Verbindung mit dem MySQL-Server bereits genügen.)
Wenn Sie MySQL installieren, werden einige Vorgabekonten in die Grant-Tabellen eingetragen. Die Namen und Zugriffsberechtigungen dieser Konten sind in Abschnitt 2.9.3, „Einrichtung der anfänglichen MySQL-Berechtigungen“, beschrieben. Dort finden Sie auch eine Erläuterung, wie Sie Passwörter für diese Konten konfigurieren. Nachfolgend werden MySQL-Konten normalerweise mit Anweisungen wie GRANT
oder REVOKE
eingerichtet, geändert und entfernt. Siehe auch Abschnitt 13.5.1, „Anweisungen zur Benutzerkontenverwaltung“.
Wenn Sie über einen Befehlszeilenclient eine Verbindung mit einem MySQL-Server herstellen, sollten Sie den Benutzernamen und das Passwort des zu verwendenden Kontos angeben:
shell> mysql --user=monty --password=guess
db_name
Verwenden Sie lieber kurze Optionen, dann sieht der Befehl wie folgt aus:
shell> mysql -u monty -pguess
db_name
Zwischen der Option -p
und dem nachfolgenden Passwortwert darf kein Leerzeichen vorhanden sein. Siehe auch Abschnitt 5.8.4, „Verbinden mit dem MySQL-Server“.
Obige Befehle enthalten den Passwortwert in der Befehlszeile. Dies kann ein Sicherheitsrisiko darstellen. Siehe auch Abschnitt 5.9.6, „Wie Sie Ihre Kennwörter sicher halten“. Um dieses Problem zu umgehen, geben Sie die Option --password
bzw. -p
ohne nachfolgenden Passwortwert an:
shell>mysql --user=monty --password
shell>db_name
mysql -u monty -p
db_name
Wenn die Passwortoption keinen Passwortwert enthält, zeigt das Clientprogramm eine Eingabeaufforderung an und wartet auf die Eingabe des Passworts. (In diesen Beispielen wird db_name
nicht als Passwort interpretiert, da es von der vorangegangenen Passwortoption durch ein Leerzeichen getrennt ist.)
Auf manchen Systemen beschränkt die von MySQL zur Passworteingabe verwendete Bibliotheksroutine die Eingabe auf acht Zeichen. Dies ist ein Problem der Systembibliothek und nicht von MySQL. Intern beschränkt MySQL die Länge des Passworts nicht. Um dieses Problem zu umgehen, setzen Sie das MySQL-Passwort entweder auf einen Wert, der maximal acht Zeichen umfasst, oder legen es in einer Optionsdatei ab.
Es gibt zwei Vorgehensweisen zum Hinzufügen von MySQL-Konten:
Verwenden von Anweisungen zur Erstellung von Konten (z. B. CREATE USER
oder GRANT
)
direktes Modifizieren der MySQL-Grant-Tabellen mit Anweisungen wie INSERT
, UPDATE
oder DELETE
Die zu bevorzugende Methode ist die Verwendung von Anweisungen zur Kontenerstellung, denn diese sind knapper und zudem weniger fehleranfällig. CREATE USER
und GRANT
sind in Abschnitt 13.5.1.1, „CREATE USER
“, und Abschnitt 13.5.1.3, „GRANT
und REVOKE
“, beschrieben.
Eine weitere Option zur Erstellung von Konten besteht in der Verwendung eines der vielen erhältlichen Drittanbieterprogramme, die Funktionen zur MySQL-Kontenverwaltung anbieten. phpMyAdmin
ist ein solches Programm.
Die folgenden Beispiele zeigen, wie man mit dem mysql-Client neue Benutzer einrichtet. Die Beispiele setzen voraus, dass die Berechtigungen entsprechend der Beschreibung in Abschnitt 2.9.3, „Einrichtung der anfänglichen MySQL-Berechtigungen“, auf die Vorgabewerte gesetzt sind. Das bedeutet, dass Sie, um Änderungen vornehmen zu können, eine Verbindung zum MySQL-Server als MySQL-Benutzer root
herstellen müssen und das root
-Konto die Berechtigung INSERT
für die mysql
-Datenbank sowie die administrative Berechtigung RELOAD
benötigt.
Verwenden Sie zunächst das Programm mysql, um als MySQL-Benutzer root
eine Verbindung zum Server herzustellen:
shell> mysql --user=root mysql
Wenn Sie für das Konto root
ein Passwort konfiguriert haben, müssen Sie auch eine Option --password
bzw. -p
für diesen und alle weiteren in diesem Abschnitt folgenden mysql-Befehle angeben.
Wenn Sie die Verbindung zum Server als root
hergestellt haben, können Sie neue Konten hinzufügen. Die folgenden Anweisungen richten mit GRANT
vier neue Benutzerkonten ein:
mysql>GRANT ALL PRIVILEGES ON *.* TO 'monty'@'localhost'
->IDENTIFIED BY 'some_pass' WITH GRANT OPTION;
mysql>GRANT ALL PRIVILEGES ON *.* TO 'monty'@'%'
->IDENTIFIED BY 'some_pass' WITH GRANT OPTION;
mysql>GRANT RELOAD,PROCESS ON *.* TO 'admin'@'localhost';
mysql>GRANT USAGE ON *.* TO 'dummy'@'localhost';
Die mit diesen GRANT
-Anweisungen erstellten Konten haben die folgenden Eigenschaften:
Zwei der Konten haben den Benutzernamen monty
und das Passwort some_pass
. Beide Konten sind Superuser-Konten mit allen Berechtigungen für beliebige Operationen. Eines der Konten ('monty'@'localhost'
) kann nur für eine Verbindung vom lokalen Host verwendet werden. Das andere Konto ('monty'@'%'
) erlaubt die Verbindung von einem beliebigen anderen Host. Beachten Sie, dass beide Konten erforderlich sind, damit monty
von einem beliebigen Host aus als monty
eine Verbindung herstellen kann. Würde das localhost
-Konto nicht eingerichtet, dann hätte das anonyme Benutzerkonto für localhost
, welches von mysql_install_db eingerichtet wird, Vorrang für die Anmeldung von monty
am lokalen Host. Die Folge wäre, dass monty
als anonymer Benutzer behandelt würde. Grund hierfür ist, dass das Konto für anonyme Benutzer einen spezifischeren Wert in der Host
-Spalte aufweist als das Konto 'monty'@'%'
und deswegen in der Tabelle user
weiter oben einsortiert wird. (Die Sortierung der Tabelle user
ist in Abschnitt 5.8.5, „Zugriffskontrolle, Phase 1: Verbindungsüberprüfung“, beschrieben.)
Ein Konto hat den Benutzernamen admin
und kein Passwort. Dieses Konto kann nur für eine Verbindung vom lokalen Host verwendet werden. Gewährt werden die administrativen Berechtigungen RELOAD
und PROCESS
. Diese Berechtigungen gestatten dem Benutzer admin
die Ausführung der Befehle mysqladmin reload, mysqladmin refresh und mysqladmin flush-xxx
sowie des Befehls mysqladmin processlist . Für den Zugriff auf Datenbanken werden keine Berechtigungen gewährt. Sie können solche Berechtigungen später durch Absetzen zusätzlicher GRANT
-Anweisungen hinzufügen.
Ein Konto hat den Benutzernamen dummy
und kein Passwort. Dieses Konto kann nur für eine Verbindung vom lokalen Host verwendet werden. Es werden keine Berechtigungen gewährt. Die Berechtigung USAGE
in der GRANT
-Anweisung erlaubt Ihnen die Erstellung eines Kontos ohne Gewährung von Berechtigungen. Es werden also alle globalen Berechtigungen auf 'N'
gesetzt. Es ist davon auszugehen, dass Sie diesem Konto später gewisse Berechtigungen gewähren werden.
Als Alternative zu GRANT
können Sie dieselben Konten auch direkt durch Absetzen von INSERT
-Anweisungen und ein nachfolgendes Neuladen der Grant-Tabellen durch den Server mithilfe von FLUSH PRIVILEGES
erstellen:
shell>mysql --user=root mysql
mysql>INSERT INTO user
->VALUES('localhost','monty',PASSWORD('some_pass'),
->'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');
mysql>INSERT INTO user
->VALUES('%','monty',PASSWORD('some_pass'),
->'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');
mysql>INSERT INTO user SET Host='localhost',User='admin',
->Reload_priv='Y', Process_priv='Y';
mysql>INSERT INTO user (Host,User,Password)
->VALUES('localhost','dummy','');
mysql>FLUSH PRIVILEGES;
Der Grund für die Verwendung von FLUSH PRIVILEGES
bei der Erstellung von Konten mit INSERT
besteht darin, dass der Server zum Neuladen der Grant-Tabellen angewiesen werden muss. Andernfalls wird Ihre Änderung erst umgesetzt, wenn Sie den Server neu starten. Bei GRANT
ist das Absetzen von FLUSH PRIVILEGES
nicht erforderlich.
Die Funktion PASSWORD()
wird bei INSERT
zur Verschlüsselung des Passwortes verwendet. Die Anweisung GRANT
verschlüsselt das Passwort direkt, d. h. PASSWORD()
ist hier nicht erforderlich.
Die 'Y'
-Werte aktivieren die Berechtigungen für die Konten. Je nach MySQL-Version müssen Sie unter Umständen eine unterschiedliche Anzahl von 'Y'
-Werten in den ersten beiden INSERT
-Anweisungen verwenden. Für das admin
-Konto sollten Sie vielleicht eher die besser lesbare erweiterte INSERT
-Syntax unter Verwendung von SET
benutzen.
In der INSERT
-Anweisung für das Konto dummy
sind nur die Spalten Host
, User
und Password
in der Tabelle user
zugewiesene Werte. Keine der Berechtigungsspalten wird explizit eingestellt, weswegen MySQL ihnen allen den Standardwert 'N'
zuweist. Dies entspricht dem, was auch GRANT USAGE
tut.
Beachten Sie, dass es zur Einrichtung eines Superuser-Kontos erforderlich ist, einen Eintrag in der Tabelle user
zu erstellen, bei dem die Berechtigungsspalten auf 'Y'
gesetzt sind. Berechtigungen in der Tabelle user
sind global, d. h. es sind keine anderen Einträge in einer anderen Grant-Tabelle erforderlich.
Die nächsten Beispiele erstellen drei Konten und gewähren ihnen Zugang zu bestimmten Datenbanken. Alle haben den Benutzernamen custom
und das Passwort obscure
.
Um die Konten mit GRANT
zu erstellen, verwenden Sie die folgenden Anweisungen:
shell>mysql --user=root mysql
mysql>GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
->ON bankaccount.*
->TO 'custom'@'localhost'
->IDENTIFIED BY 'obscure';
mysql>GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
->ON expenses.*
->TO 'custom'@'whitehouse.gov'
->IDENTIFIED BY 'obscure';
mysql>GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
->ON customer.*
->TO 'custom'@'server.domain'
->IDENTIFIED BY 'obscure';
Die drei Konten können wie folgt verwendet werden:
Das erste Konto kann auf die Datenbank bankaccount
zugreifen, dies allerdings nur vom lokalen Host aus.
Das zweite Konto kann auf die Datenbank expenses
zugreifen, dies allerdings nur vom Host whitehouse.gov
aus.
Das dritte Konto kann auf die Datenbank customer
zugreifen, dies allerdings nur vom Host server.domain
aus.
Um die custom
-Konten ohne GRANT
einrichten zu können, verwenden Sie wie folgt INSERT
-Anweisungen zur direkten Änderung der Grant-Tabellen:
shell>mysql --user=root mysql
mysql>INSERT INTO user (Host,User,Password)
->VALUES('localhost','custom',PASSWORD('obscure'));
mysql>INSERT INTO user (Host,User,Password)
->VALUES('whitehouse.gov','custom',PASSWORD('obscure'));
mysql>INSERT INTO user (Host,User,Password)
->VALUES('server.domain','custom',PASSWORD('obscure'));
mysql>INSERT INTO db
->(Host,Db,User,Select_priv,Insert_priv,
->Update_priv,Delete_priv,Create_priv,Drop_priv)
->VALUES('localhost','bankaccount','custom',
->'Y','Y','Y','Y','Y','Y');
mysql>INSERT INTO db
->(Host,Db,User,Select_priv,Insert_priv,
->Update_priv,Delete_priv,Create_priv,Drop_priv)
->VALUES('whitehouse.gov','expenses','custom',
->'Y','Y','Y','Y','Y','Y');
mysql>INSERT INTO db
->(Host,Db,User,Select_priv,Insert_priv,
->Update_priv,Delete_priv,Create_priv,Drop_priv)
->VALUES('server.domain','customer','custom',
->'Y','Y','Y','Y','Y','Y');
mysql>FLUSH PRIVILEGES;
Die ersten drei INSERT
-Anweisungen fügen Einträge in der Tabelle user
hinzu, die dem Benutzer custom
die Verbindungsherstellung an den verschiedenen Hosts unter Verwendung des betreffenden Passwortes gestatten, gewähren aber keine globale Berechtigungen (alle Berechtigungen erhalten den Standardwert 'N'
). Die nachfolgenden drei INSERT
-Anweisungen fügen Einträge in der Tabelle db
hinzu, die custom
Berechtigungen für die Datenbanken bankaccount
, expenses
und customer
unter der Voraussetzung gewähren, dass der Zugriff vom angegebenen Host aus erfolgt. Wie bei der direkten Änderung der Grant-Tabellen üblich, müssen Sie den Server auch hier mit FLUSH PRIVILEGES
zum Neuladen der Grant-Tabellen anweisen, damit die Änderungen an den Berechtigungen übernommen werden.
Wenn Sie einem bestimmten Benutzer den Zugriff von allen Computern in einer bestimmten Domäne (z. B. mydomain.com
) gestatten wollen, können Sie eine GRANT
-Anweisung absetzen, die das Jokerzeichen ‘%
’ im Hostpart des Kontennamens verwendet:
mysql>GRANT ...
->ON *.*
->TO 'myname'@'%.mydomain.com'
->IDENTIFIED BY 'mypass';
Um das gleiche Ergebnis durch direkte Modifikation der Grant-Tabellen zu erzielen, tun Sie folgendes:
mysql>INSERT INTO user (Host,User,Password,...)
->VALUES('%.mydomain.com','myname',PASSWORD('mypass'),...);
mysql>FLUSH PRIVILEGES;
Um ein Konto zu entfernen, verwenden Sie die Anweisung DROP USER
, die in Abschnitt 13.5.1.2, „DROP USER
“, beschrieben ist.
Eine Möglichkeit, die Nutzung der MySQL-Serverressourcen einzuschränken, besteht in der Einstellung der Systemvariablen max_user_connections
auf einen Wert ungleich Null. Allerdings arbeitet diese Methode streng global und ermöglicht keine Verwaltung einzelner Konten. Außerdem wird hierbei nur die Anzahl der Verbindungen beschränkt, die gleichzeitig über ein einzelnes Konto verwendet werden, nicht jedoch, was ein Client tun kann, sobald die Verbindung hergestellt ist. Diese beiden Steuerungsformen sind für viele MySQL-Administratoren interessant – insbesondere für solche, die für Internetprovider tätig sind.
In MySQL 5.1 können Sie die folgenden Serverressourcen für einzelne Konten einschränken:
Anzahl der Abfragen, die ein Konto pro Stunde absetzen kann
Anzahl der Updates, die ein Konto pro Stunde durchführen kann
Häufigkeit, mit der ein Konto pro Stunde Verbindungen herstellen kann
Jede Anweisung, die ein Client absetzen kann, erhöht den Zähler für das Abfragelimit. Der Updatezähler hingegen wird nur bei Anweisungen hochgezählt, die Datenbanken oder Tabellen ändern.
Es ist auch möglich, die Anzahl gleichzeitiger Verbindungen zum Server pro Konto zu beschränken.
In diesem Kontext ist unter einem Konto ein Datensatz in der Tabelle user
zu verstehen. Jedes Konto wird durch die User
- und Host
-Spaltenwerte eindeutig bezeichnet.
Voraussetzung für die Verwendung dieser Funktion ist, dass die Tabelle user
in der mysql
-Datenbank die ressourcenspezifischen Spalten enthält. Ressourcenbeschränkungen sind in den Spalten max_questions
, max_updates
, max_connections
und max_user_connections
abgelegt. Wenn Ihre Tabelle user
diese Spalten nicht aufweist, muss sie aktualisiert werden. Siehe auch Abschnitt 5.6, „mysql_fix_privilege_tables — Upgrade von MySQL-Systemtabellen“.
Um Ressourcenbeschränkungen mit einer GRANT
-Anweisung einzustellen, verwenden Sie eine WITH
-Klausel, die alle zu beschränkenden Ressourcen und einen stundenbezogenen Zähler benennt, der den jeweiligen Maximalwert angibt. Um also etwa ein neues Konto zu erstellen, das auf die Datenbank customer
in eingeschränkter Weise zugreifen kann, setzen Sie folgende Anweisung ab:
mysql>GRANT ALL ON customer.* TO 'francis'@'localhost'
->IDENTIFIED BY 'frank'
->WITH MAX_QUERIES_PER_HOUR 20
->MAX_UPDATES_PER_HOUR 10
->MAX_CONNECTIONS_PER_HOUR 5
->MAX_USER_CONNECTIONS 2;
Nicht alle Beschränkungstypen müssen in der WITH
-Klausel aufgeführt sein. Zudem ist die Reihenfolge der aufgeführten Typen beliebig. Der Wert des Stundenlimits sollte eine ganze Zahl sein, die den Wert pro Stunde angibt. Wird die GRANT
-Anweisung ohne WITH
-Klausel abgesetzt, dann werden alle Beschränkungen auf den Standardwert Null gesetzt (d. h. es gibt keine Beschränkungen). Bei MAX_USER_CONNECTIONS
ist der Höchstwert eine ganze Zahl, die die maximale Anzahl der Verbindungen angibt, die das Konto gleichzeitig halten kann. Wenn der Wert auf die Vorgabe Null gesetzt ist, bestimmt die Systemvariable max_user_connections
die maximale Anzahl gleichzeitiger Verbindungen für das Konto.
Um die Beschränkungen für ein vorhandenes Konto einzustellen oder zu ändern, verwenden Sie eine GRANT USAGE
-Anweisung auf der globalen Ebene (ON *.*
). Die folgende Anweisung setzt das Abfragelimit für francis
auf 100:
mysql>GRANT USAGE ON *.* TO 'francis'@'localhost'
->WITH MAX_QUERIES_PER_HOUR 100;
Diese Anweisung ändert nicht die vorhandenen Berechtigungen des Kontos, sondern nur die vorhandenen Maximalwerte.
Um eine vorhandene Beschränkung zu entfernen, setzen Sie den Wert auf Null. Um etwa die Beschränkung der Häufigkeit aufzuheben, mit der francis
eine Verbindung herstellen kann, verwenden Sie folgende Anweisung:
mysql>GRANT USAGE ON *.* TO 'francis'@'localhost'
->WITH MAX_CONNECTIONS_PER_HOUR 0;
Eine Zählung der Ressourcennutzung findet statt, wenn für ein Konto ein Wert ungleich Null für die Beschränkung einer bestimmten Ressource konfiguriert ist.
Wenn der Server läuft, ermittelt er, wie häufig jedes Konto welche Ressourcen verwendet. Wenn ein Konto die höchste Anzahl zulässiger Verbindungen innerhalb einer Stunde erreicht, werden weitere Verbindungsanfragen des Kontos abgewiesen, bis die Stunde verstrichen ist. Ähnlich werden weitere Abfragen oder Updates abgewiesen, wenn für diese der jeweilige Maximalwert durch ein Konto erreicht wird. In all diesen Fällen wird eine entsprechende Fehlermeldung angezeigt.
Die Zählung der Ressourcennutzungen erfolgt auf Konten- und nicht auf Clientbasis. Wenn Ihr Konto beispielsweise eine Beschränkung von 50 Abfragen pro Stunde hat, dann können Sie diese nicht verdoppeln, indem Sie gleichzeitig zwei Clientverbindungen zum Server herstellen. Die Abfragen, die über die beiden Verbindungen abgesetzt werden, werden zusammengezählt.
Die aktuellen Ressourcenzähler können global oder auch für einzelne Konten zurückgesetzt werden:
Um die aktuellen Zähler für alle Konten zu nullen, setzen Sie eine FLUSH USER_RESOURCES
-Anweisung ab. Die Werte können auch durch Neuladen der Grant-Tabellen (etwa mit einer FLUSH PRIVILEGES
-Anweisung oder dem Befehl mysqladmin reload) zurückgesetzt werden.
Zähler eines bestimmten Kontos können auf Null gesetzt werden, indem eine beliebige Beschränkung erneut definiert wird. Verwenden Sie zu diesem Zweck wie oben beschrieben die Anweisung GRANT USAGE
und geben Sie den Wert, der für das Konto bereits festgelegt ist, erneut an.
Das Zurücksetzen der Zähler wirkt sich nicht auf die Beschränkung MAX_USER_CONNECTIONS
aus.
Beim Serverstart beginnen alle Zähler bei Null zu zählen, d. h. vorhandene Werte lassen sich nicht über einen Neustart hinweg übertragen.
Passwörter können mit mysqladmin über die Befehlszeile zugewiesen werden:
shell> mysqladmin -u user_name
-h host_name
password "newpwd
"
Der Befehl setzt das Passwort des Kontos zurück, bei dessen Datensatz in der Tabelle user
eine Übereinstimmung mit user_name
in der Spalte User
und eine Übereinstimmung des Clienthosts, von dem aus Sie die Verbindung herstellen, in der Spalte Host
vorliegt.
Eine weitere Möglichkeit, einem Konto ein Passwort zuzuweisen, besteht im Absetzen einer SET PASSWORD
-Anweisung:
mysql> SET PASSWORD FOR 'jeffrey'@'%' = PASSWORD('biscuit');
Nur Benutzer wie root
, die die mysql
-Datenbank aktualisieren dürfen, können die Passwörter anderer Benutzer ändern. Sofern Sie nicht als anonymer Benutzer verbunden sind, können Sie Ihr eigenes Passwort durch Weglassen der FOR
-Klausel ändern:
mysql> SET PASSWORD = PASSWORD('biscuit');
Sie können auch eine GRANT USAGE
-Anweisung auf der globalen Ebene (ON *.*
) verwenden, um einem Konto ein Passwort zuzuweisen, ohne die aktuellen Berechtigungen dieses Kontos zu beeinträchtigen:
mysql> GRANT USAGE ON *.* TO 'jeffrey'@'%' IDENTIFIED BY 'biscuit';
Zwar ist die Zuweisung von Passwörtern unter Verwendung einer der zuvor beschriebenen Methoden generell vorzuziehen, aber Sie können die Tabelle user
auch direkt ändern:
Um bei Erstellung eines neuen Kontos ein Passwort zuzuweisen, setzen Sie einen Wert in die Spalte Password
:
shell>mysql -u root mysql
mysql>INSERT INTO user (Host,User,Password)
->VALUES('%','jeffrey',PASSWORD('biscuit'));
mysql>FLUSH PRIVILEGES;
Wollen Sie das Passwort eines vorhandenen Kontos ändern, dann weisen Sie mit UPDATE
den Password
-Spaltenwert zu:
shell>mysql -u root mysql
mysql>UPDATE user SET Password = PASSWORD('bagel')
->WHERE Host = '%' AND User = 'francis';
mysql>FLUSH PRIVILEGES;
Wenn Sie einem Konto mit SET PASSWORD
, INSERT
oder UPDATE
ein nichtleeres Passwort zuweisen, müssen Sie die Funktion PASSWORD()
zur Verschlüsselung verwenden. PASSWORD()
ist erforderlich, weil die Tabelle user
Passwörter nicht als Klartext, sondern in verschlüsselter Form speichert. Wenn Sie dies vergessen, werden Sie Passwörter wahrscheinlich so einstellen:
shell>mysql -u root mysql
mysql>INSERT INTO user (Host,User,Password)
->VALUES('%','jeffrey','biscuit');
mysql>FLUSH PRIVILEGES;
Die Folge ist, dass der literale Wert 'biscuit'
und nicht der verschlüsselte Wert als Passwort in der Tabelle user
gespeichert wird. Wenn jeffrey
dann unter Angabe dieses Passworts eine Verbindung zum Server herzustellen versucht, wird der Wert verschlüsselt und dann mit dem in der Tabelle user
gespeicherten Wert verglichen. Dieser gespeicherte Wert ist jedoch der literale String 'biscuit'
– der Vergleich schlägt fehl, und der Server weist die Verbindungsanfrage ab:
shell> mysql -u jeffrey -pbiscuit test
Access denied
Bei der Zuweisung von Passwörtern mit der Anweisung GRANT ... IDENTIFIED BY
oder dem Befehl mysqladmin password wird die Verschlüsselung des Passworts automatisch erledigt. In diesen Fällen ist die Verwendung der Funktion PASSWORD()
nicht erforderlich.
Hinweis: Die PASSWORD()
-Verschlüsselung unterscheidet sich von der Unix-Passwortverschlüsselung. Siehe auch Abschnitt 5.9.1, „MySQL-Benutzernamen und -Kennwörter“.
Auf der administrativen Ebene sollten Sie nichtadministrativen Konten niemals Zugriff auf die Grant-Tabelle user
gestatten.
Wenn Sie ein Clientprogramm ausführen, um eine Verbindung mit dem MySQL-Server herzustellen, ist es nicht ratsam, Ihr Passwort so einzugeben, dass es von anderen Benutzern erraten werden könnte. Die Methoden, die Sie zur Angabe Ihres Passworts bei Ausführung von Clientprogrammen verwenden können, sind einschließlich einer Risikoeinschätzung jeder Methode nachfolgend aufgeführt:
Sie verwenden die Option -p
bzw. your_pass
--password=
auf der Befehlszeile. Zum Beispiel:
your_pass
shell> mysql -u francis -pfrank db_name
Dies ist praktisch, aber unsicher, weil Ihr Passwort für Systemstatusprogramme wie ps sichtbar wird, die von anderen Benutzern zur Anzeige von Befehlszeilen aufgerufen werden können. MySQL-Clients überschreiben das befehlszeilenbasierte Passwortargument bei der Initialisierung normalerweise mit Nullen. Es gibt allerdings noch einen ganz kurzen Zeitraum, für den der Wert sichtbar ist. Auf einigen Systemen ist diese Strategie ohnehin ohne Wirkung, und die Passwörter bleiben für ps sichtbar. (Das Problem tritt etwa bei System V-Unix und unter Umständen auch bei anderen Systemen auf.)
Sie verwenden die Option -p
bzw. --password
ohne Passwortangabe. In diesem Fall fordert das Clientprogramm zur Eingabe des Passworts über das Terminal auf:
shell> mysql -u francis -p db_name
Enter password: ********
Die Zeichen ‘*
’ geben an, wo Sie Ihr Passwort eingegeben haben. Das Passwort wird bei der Eingabe nicht angezeigt.
Diese Methode zur Passworteingabe ist sicherer als die Angabe über die Befehlszeile, da das Passwort anderen Benutzern nicht angezeigt wird. Allerdings ist diese Eingabemethode nur für Programme geeignet, die Sie interaktiv ausführen. Wollen Sie einen Client aus einem Skript heraus aufrufen, das nicht interaktiv läuft, dann gibt es keine Möglichkeit, das Passwort über das Terminal einzugeben. Bei manchen Systemen werden Sie sogar feststellen, dass die erste Zeile Ihres Skript gelesen und irrtümlich als Passwort interpretiert wird.
Sie speichern Ihr Passwort in einer Optionsdatei. Unter Unix etwa können Sie Ihr Passwort im Abschnitt [client]
der Datei .my.cnf
im Stammverzeichnis auflisten:
[client] password=your_pass
Wenn Sie Ihr Passwort in .my.cnf
speichern, dann sollte diese Datei ausschließlich für Sie zugänglich sein. Um dies sicherzustellen, setzen Sie die Dateizugriffsmethode auf 400
oder 600
. Zum Beispiel:
shell> chmod 600 .my.cnf
Abschnitt 4.3.2, „my.cnf-Optionsdateien“, erläutert Optionsdateien im Detail.
Sie speichern Ihr Passwort in der Umgebungsvariable MYSQL_PWD
. Diese Methode der Angabe eines MySQL-Passworts muss als extrem unsicher betrachtet werden und sollte nicht verwendet werden. Einige Versionen von ps enthalten eine Option zur Anzeige der Umgebung laufender Prozesse. Wenn Sie MYSQL_PWD
einstellen, wird Ihr Passwort allen Benutzern zugänglich gemacht, die ps ausführen. Sogar auf Systemen ohne eine solche Version von ps ist es nicht ratsam, davon auszugehen, dass keine andere Methoden vorhanden sind, mit denen Benutzer Prozessumgebungen untersuchen können. Siehe auch Anhang F, Umgebungsvariablen.
Insgesamt betrachtet sind die sichersten Methoden die Aufforderung des Clientprogramms zur Eingabe des Passwortes oder die Angabe des Passwortes in einer angemessen geschützten Optionsdatei.
MySQL unterstützt sichere (verschlüsselte) Verbindungen zwischen MySQL-Clients und dem Server unter Verwendung des SSL-Protokolls (Secure Sockets Layer). Dieser Abschnitt beschreibt, wie man SSL-Verbindungen verwendet. Ferner wird eine Möglichkeit beschrieben, SSH unter Windows einzurichten. Informationen dazu, wie man die Verwendung von SSL-Verbindungen durch die Benutzer erzwingt, finden Sie in Abschnitt 13.5.1.3, „GRANT
und REVOKE
“.
Die Standardkonfiguration von MySQL ist auf Geschwindigkeit optimiert, weswegen verschlüsselte Verbindungen standardmäßig nicht verwendet werden. Andernfalls wäre das Client/Server-Protokoll erheblich langsamer. Die Verschlüsselung von Daten ist ein prozessorintensiver Vorgang, der zusätzliche Operationen seitens des Computers erfordert und andere MySQL-Aufgaben verzögern kann. Bei Anwendungen hingegen, die die Sicherheit verschlüsselter Verbindungen erfordern, ist der zusätzliche Rechenaufwand in jedem Fall gerechtfertigt.
MySQL gestattet die Aktivierung der Verschlüsselung auf der Basis einzelner Verbindungen. Sie können je nach Anforderungen einzelner Anwendungen zwischen einer normalen unverschlüsselten Verbindung oder einer sicheren verschlüsselten SSL-Verbindung wählen.
Um verstehen zu können, wie MySQL SSL verwendet, ist es notwendig, einige grundlegende Konzepte zu SSL und X509 zu kennen. Leser, die mit diesen Konzepten vertraut sind, können diesen Teil des Handbuchs überspringen.
Standardmäßig verwendet MySQL unverschlüsselte Verbindungen zwischen Client und Server. Das bedeutet, dass jemand, der Zugriff auf das Netzwerk hat, den gesamten Datenverkehr überwachen und die Daten bei Versand oder Empfang überprüfen könnte. Schlimmer noch: Selbst eine Modifikation der Daten während der Übertragung zwischen Client und Server ist möglich. Um die Sicherheit ein wenig zu erhöhen, können Sie den Client/Server-Datenverkehr durch Angabe der Option --compress
beim Aufruf des Clientprogramms komprimieren. Ein entschlossener Angreifer würde sich hiervon jedoch nicht abhalten lassen.
Wenn Sie Daten in sicherer Form über ein Netzwerk übertragen müssen, ist eine unverschlüsselte Verbindung nicht akzeptabel. Die Verschlüsselung stellt eine Möglichkeit dar, beliebige Daten unlesbar zu machen. Tatsächlich erfordert die moderne Praxis viele zusätzliche Sicherheitselemente von Verschlüsselungsalgorithmen. Sie sollten viele bekannte Angriffstypen abwehren können, z. B. eine Änderung der Reihenfolge verschlüsselter Daten oder die zweimalige Wiedergabe von Daten.
SSL ist ein Protokoll, welches mithilfe verschiedener Verschlüsselungsalgorithmen sicherstellen soll, dass Daten, die über ein öffentliches Netzwerk übertragen wurden, vertrauenswürdig sind. SSL verfügt über Methoden zur Erkennung von Änderungen, Verlusten oder Wiedergabe von Daten. Ferner enthalten sind Algorithmen, die eine Identitätsprüfung unter Verwendung des X509-Standards ermöglichen.
X509 erlaubt eine Identifizierung über das Internet. Der bevorzugte Anwendungsfall hierfür ist der E-Commerce. Einfach gesagt wird ein Unternehmen benötigt, welches als „Zertifizierungsstelle“ (Certificate Authority, CA) elektronische Zertifikate an Antragssteller vergibt. Zertifikate basieren auf asymmetrischen Verschlüsselungsalgorithmen mit zwei Schlüsseln: einem öffentlichen und einem Geheimschlüssel. Der Halter eines Zertifikats kann einem Gegenüber das Zertifikat als Identitätsnachweis vorlegen. Das Zertifikat besteht aus dem öffentlichen Schlüssel seines Besitzers. Daten, die mit diesem öffentlichen Schlüssel verschlüsselt wurden, können nur mit dem entsprechenden Geheimschlüssel wieder entschlüsselt werden. Dieser Geheimschlüssel befindet sich im Besitz des Zertifikatshalters.
Wenn Sie weitere Informationen zu SSL, X509 oder zum Thema Verschlüsselung suchen, geben Sie die entsprechenden Begriffe in die Internetsuchmaschine Ihrer Wahl ein.
Um SSL-Verbindungen zwischen dem MySQL-Server und den Clientprogrammen zu verwenden, muss Ihr System entweder OpenSSL oder yaSSL unterstützen. In diesem Abschnitt behandeln wir OpenSSL. Wenn sie yaSSL verwenden, lesen Sie stattdessen Abschnitt 5.9.7.3, „Verwendung von SSL-Verbindungen mit yaSSL“.
Gehen Sie wie folgt vor, um mithilfe von OpenSSL sichere Verbindungen für MySQL zu erstellen:
Installieren Sie, soweit nicht bereits vorhanden, die OpenSSL-Bibliothek. Wir haben MySQL mit OpenSSL 0.9.6 getestet. Wenn Sie OpenSSL benötigen, besuchen Sie die Site http://www.openssl.org.
Wenn Sie MySQL konfigurieren, rufen Sie das Skript configure mit den Optionen --with-vio
und --with-openssl
auf:
shell> ./configure --with-vio --with-openssl
Stellen Sie sicher, dass Sie Ihre Grant-Tabellen so aktualisiert haben, dass die SSL-spezifischen Spalten in der Tabelle mysql.user
enthalten sind. Dies ist erforderlich, wenn Ihre Grant-Tabellen aus einer Version vor MySQL 4.0.0 stammen. Der Aktualisierungsvorgang ist in Abschnitt 5.6, „mysql_fix_privilege_tables — Upgrade von MySQL-Systemtabellen“, beschrieben.
Um zu überprüfen, ob ein laufender mysqld-Server OpenSSL unterstützt, prüfen Sie den Wert der Systemvariable have_openssl
:
mysql> SHOW VARIABLES LIKE 'have_openssl';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| have_openssl | YES |
+---------------+-------+
Ist der Wert YES
, dann unterstützt der Server OpenSSL-Verbindungen.
Die in MySQL integrierte yaSSL-Unterstützung erleichtert die Verwendung sicherer Verbindungen. Sie müssen OpenSSL nicht installieren und auch die anderen in Abschnitt 5.9.7.2, „Verwendung von SSL-Verbindungen mit OpenSSL“, beschriebenen Schritte nicht durchführen. Außerdem verwenden MySQL und yaSSL dasselbe Lizenzmodell.
Zurzeit wird yaSSL auf den folgenden Plattformen unterstützt:
Linux/x86-64 Red Hat Enterprise 3.0
Linux RHAS21 Itanium-2 mit gcc, statisch verknüpft
Linux Itanium-2 mit gcc
Windows (alle Builds)
Um beim Erstellen von MySQL aus einer Quelldistribution yaSSL zu aktivieren, sollten Sie MySQL wie folgt konfigurieren:
shell> ./configure --with-yassl
Beachten Sie, dass die yaSSL-Unterstützung auf Unix-Plattformen die Installation von /dev/urandom
oder /dev/random
erfordert, damit echte Zufallszahlen abgerufen werden können. Weitere Informationen (insbesondere zu yaSSL auf Solaris-Versionen vor 2.8 und HP-UX) finden Sie im Bug Nr. 13164.
Um den MySQL-Server mit yaSSL-Unterstützung zu starten, verwenden Sie dieselben Optionen wie beim OpenSSL-Support und geben die zur Herstellung einer sicheren Verbindung erforderlichen Zertifikate an:
shell>mysqld --ssl-ca=
cacert.pem
\--ssl-cert=
server-cert.pem
\--ssl-key=
server-key.pem
--ssl-ca
benennt das CA-Zertifikat.
--ssl-cert
benennt das Serverzertifikat.
--ssl-key
benennt das Clientzertifikat.
Um eine sichere Verbindung zu einem MySQL-Server mit yaSSL-Unterstützung herzustellen, starten Sie Ihren Client wie folgt:
shell>mysql --ssl-ca=
cacert.pem
\--ssl-cert=
server-cert.pem
\--ssl-key=
server-key.pem
Mit anderen Worten sind die Optionen dieselben wie beim Server, und das Zertifikat der Zertifizierungsstelle muss das gleiche sein.
Wenn Sie eine sichere Verbindung von einem Anwendungsprogramm aus herstellen wollen, stellen Sie mit der mysql_ssl_set()
-API-Funktion die passenden Zertifikatsoptionen ein, bevor Sie mysql_real_connect()
aufrufen. Siehe auch Abschnitt 24.2.3.64, „mysql_ssl_set()
“.
An dieser Stelle folgt ein Beispiel zur Konfiguration von SSL-Zertifikaten für MySQL mit OpenSSL:
DIR=`pwd`/openssl PRIV=$DIR/private mkdir $DIR $PRIV $DIR/newcerts cp /usr/share/ssl/openssl.cnf $DIR replace ./demoCA $DIR -- $DIR/openssl.cnf # Create necessary files: $database, $serial and $new_certs_dir # directory (optional) touch $DIR/index.txt echo "01" > $DIR/serial # # Generation of Certificate Authority(CA) # openssl req -new -x509 -keyout $PRIV/cakey.pem -out $DIR/cacert.pem \ -config $DIR/openssl.cnf # Sample output: # Using configuration from /home/monty/openssl/openssl.cnf # Generating a 1024 bit RSA private key # ................++++++ # .........++++++ # writing new private key to '/home/monty/openssl/private/cakey.pem' # Enter PEM pass phrase: # Verifying password - Enter PEM pass phrase: # ----- # You are about to be asked to enter information that will be # incorporated into your certificate request. # What you are about to enter is what is called a Distinguished Name # or a DN. # There are quite a few fields but you can leave some blank # For some fields there will be a default value, # If you enter '.', the field will be left blank. # ----- # Country Name (2 letter code) [AU]:FI # State or Province Name (full name) [Some-State]:. # Locality Name (eg, city) []: # Organization Name (eg, company) [Internet Widgits Pty Ltd]:MySQL AB # Organizational Unit Name (eg, section) []: # Common Name (eg, YOUR name) []:MySQL admin # Email Address []: # # Create server request and key # openssl req -new -keyout $DIR/server-key.pem -out \ $DIR/server-req.pem -days 3600 -config $DIR/openssl.cnf # Sample output: # Using configuration from /home/monty/openssl/openssl.cnf # Generating a 1024 bit RSA private key # ..++++++ # ..........++++++ # writing new private key to '/home/monty/openssl/server-key.pem' # Enter PEM pass phrase: # Verifying password - Enter PEM pass phrase: # ----- # You are about to be asked to enter information that will be # incorporated into your certificate request. # What you are about to enter is what is called a Distinguished Name # or a DN. # There are quite a few fields but you can leave some blank # For some fields there will be a default value, # If you enter '.', the field will be left blank. # ----- # Country Name (2 letter code) [AU]:FI # State or Province Name (full name) [Some-State]:. # Locality Name (eg, city) []: # Organization Name (eg, company) [Internet Widgits Pty Ltd]:MySQL AB # Organizational Unit Name (eg, section) []: # Common Name (eg, YOUR name) []:MySQL server # Email Address []: # # Please enter the following 'extra' attributes # to be sent with your certificate request # A challenge password []: # An optional company name []: # # Remove the passphrase from the key (optional) # openssl rsa -in $DIR/server-key.pem -out $DIR/server-key.pem # # Sign server cert # openssl ca -policy policy_anything -out $DIR/server-cert.pem \ -config $DIR/openssl.cnf -infiles $DIR/server-req.pem # Sample output: # Using configuration from /home/monty/openssl/openssl.cnf # Enter PEM pass phrase: # Check that the request matches the signature # Signature ok # The Subjects Distinguished Name is as follows # countryName :PRINTABLE:'FI' # organizationName :PRINTABLE:'MySQL AB' # commonName :PRINTABLE:'MySQL admin' # Certificate is to be certified until Sep 13 14:22:46 2003 GMT # (365 days) # Sign the certificate? [y/n]:y # # # 1 out of 1 certificate requests certified, commit? [y/n]y # Write out database with 1 new entries # Data Base Updated # # Create client request and key # openssl req -new -keyout $DIR/client-key.pem -out \ $DIR/client-req.pem -days 3600 -config $DIR/openssl.cnf # Sample output: # Using configuration from /home/monty/openssl/openssl.cnf # Generating a 1024 bit RSA private key # .....................................++++++ # .............................................++++++ # writing new private key to '/home/monty/openssl/client-key.pem' # Enter PEM pass phrase: # Verifying password - Enter PEM pass phrase: # ----- # You are about to be asked to enter information that will be # incorporated into your certificate request. # What you are about to enter is what is called a Distinguished Name # or a DN. # There are quite a few fields but you can leave some blank # For some fields there will be a default value, # If you enter '.', the field will be left blank. # ----- # Country Name (2 letter code) [AU]:FI # State or Province Name (full name) [Some-State]:. # Locality Name (eg, city) []: # Organization Name (eg, company) [Internet Widgits Pty Ltd]:MySQL AB # Organizational Unit Name (eg, section) []: # Common Name (eg, YOUR name) []:MySQL user # Email Address []: # # Please enter the following 'extra' attributes # to be sent with your certificate request # A challenge password []: # An optional company name []: # # Remove a passphrase from the key (optional) # openssl rsa -in $DIR/client-key.pem -out $DIR/client-key.pem # # Sign client cert # openssl ca -policy policy_anything -out $DIR/client-cert.pem \ -config $DIR/openssl.cnf -infiles $DIR/client-req.pem # Sample output: # Using configuration from /home/monty/openssl/openssl.cnf # Enter PEM pass phrase: # Check that the request matches the signature # Signature ok # The Subjects Distinguished Name is as follows # countryName :PRINTABLE:'FI' # organizationName :PRINTABLE:'MySQL AB' # commonName :PRINTABLE:'MySQL user' # Certificate is to be certified until Sep 13 16:45:17 2003 GMT # (365 days) # Sign the certificate? [y/n]:y # # # 1 out of 1 certificate requests certified, commit? [y/n]y # Write out database with 1 new entries # Data Base Updated # # Create a my.cnf file that you can use to test the certificates # cnf="" cnf="$cnf [client]" cnf="$cnf ssl-ca=$DIR/cacert.pem" cnf="$cnf ssl-cert=$DIR/client-cert.pem" cnf="$cnf ssl-key=$DIR/client-key.pem" cnf="$cnf [mysqld]" cnf="$cnf ssl-ca=$DIR/cacert.pem" cnf="$cnf ssl-cert=$DIR/server-cert.pem" cnf="$cnf ssl-key=$DIR/server-key.pem" echo $cnf | replace " " ' ' > $DIR/my.cnf
Um SSL-Verbindungen zu testen, starten Sie den Server wie folgt, wobei $DIR
der Pfadname zu dem Verzeichnis ist, in dem sich die Beispieloptionsdatei my.cnf
befindet:
shell> mysqld --defaults-file=$DIR/my.cnf &
Danach rufen Sie ein Clientprogramm mit derselben Optionsdatei auf:
shell> mysql --defaults-file=$DIR/my.cnf
Wenn Sie eine MySQL-Quelldistribution haben, können Sie Ihre Konfiguration auch durch eine dahingehende Änderung der genannten Datei my.cnf
testen, dass diese auf das Demozertifikat und die Schlüsseldateien im Verzeichnis SSL
der Distribution verweist.
Die folgende Liste beschreibt Optionen, die zur Angabe der SSL-Nutzung, der Zertifikatsdateien und der Schlüsseldateien dienen. Diese Optionen können über die Befehlszeile oder in einer Optionsdatei angegeben werden.
--ssl
Am Server legt diese Option fest, dass der Server SSL-Verbindungen zulässt. Bei einem Clientprogramm gestattet sie dem Client die Herstellung einer Serververbindung unter Verwendung von SSL. Die Angabe der Option allein reicht nicht aus, um die Verwendung einer SSL-Verbindung zu bewirken. Sie müssen auch die Optionen --ssl-ca
, --ssl-cert
und --ssl-key
angeben.
Diese Option wird häufiger in ihrer negativen Form angegeben, um festzulegen, dass SSL nicht verwendet werden soll. Zu diesem Zweck geben Sie --skip-ssl
oder --ssl=0
an.
Beachten Sie, dass die Verwendung von --ssl
das Vorhandensein einer SSL-Verbindung nicht erfordert. Werden beispielsweise Server oder Client ohne SSL-Unterstützung kompiliert, dann wird eine normale unverschlüsselte Verbindung verwendet.
Die sichere Art, die Verwendung einer SSL-Verbindung zu gewährleisten, besteht in der Erstellung eines Kontos auf dem Server mit einer REQUIRE SSL
-Klausel in der GRANT
-Anweisung. Danach stellen Sie über dieses Konto eine Verbindung zum Server her, wobei die SSL-Unterstützung sowohl am Server als auch am Client aktiviert sein muss.
--ssl-ca=
file_name
Pfad zu einer Datei, die eine Liste vertrauenswürdiger SSL-CAs enthält.
--ssl-capath=
directory_name
Pfad zu einem Verzeichnis, welches Zertifikate vertrauenswürdiger SSL-CAs im PEM-Format enthält.
--ssl-cert=
file_name
Name der SSL-Zertifikatsdatei, die zur Herstellung einer sicheren Verbindung verwendet wird.
--ssl-cipher=
cipher_list
Eine Liste zulässiger Chiffren, die für die SSL-Verschlüsselung verwendet werden dürfen. cipher_list
hat das gleiche Format wie der Befehl openssl ciphers
.
Beispiel: --ssl-cipher=ALL:-AES:-EXP
--ssl-key=
file_name
Name der SSL-Schlüsseldatei, die zur Herstellung einer sicheren Verbindung verwendet wird.
Der folgende Hinweise beschreibt, wie man unter Verwendung von SSH eine sichere Verbindung mit einem entfernte MySQL-Server herstellt (von David Carlson, <dcarlson@mplcomm.com>
):
Installieren Sie einen SSH-Client auf Ihrem Windows-Computer. Für Benutzer ist der beste nicht kostenlose Client, den ich gefunden habe, SecureCRT
von http://www.vandyke.com/. Eine weitere Option ist f-secure
von http://www.f-secure.com/. Es gibt auch kostenlose Varianten, die Sie via Google finden können (http://directory.google.com/Top/Computers/Security/Products_and_Tools/Cryptography/SSH/Clients/Windows/).
Starten Sie Ihren Windows-SSH-Client. Nehmen Sie folgende Einstellung vor: Host_Name =
. Setzen Sie ferner yourmysqlserver_URL_or_IP
userid=
, um sich an Ihrem Server anzumelden. Dieser your_userid
userid
-Wert ist unter Umständen nicht mit dem Benutzernamen Ihres MySQL-Kontos identisch.
Konfigurieren Sie die Portweiterleitung. Sie können entweder eine Remote-Weiterleitung (via local_port: 3306
, remote_host:
, yourmysqlservername_or_ip
remote_port: 3306
) oder eine lokale Weiterleitung einstellen (über port: 3306
, host: localhost
, remote port: 3306
).
Speichern Sie alles (ansonsten müssen Sie die Schritte beim nächsten Mal wiederholen).
Melden Sie sich mit der gerade erstellten SSH-Sitzung an Ihrem Server an.
Starten Sie auf Ihrem Windows-Computer eine ODBC-Anwendung (z. B. Microsoft Access).
Erstellen Sie unter Windows eine neue Datei und stellen Sie mithilfe des ODBC-Treibers wie gewöhnlich die Verbindung zu MySQL her; der einzige Unterschied besteht darin, dass Sie localhost
statt yourmysqlservername
als MySQL-Hostserver angeben.
An diesem Punkt nun sollte eine ODBC-Verbindung zu MySQL vorhanden sein, die mit SSH verschlüsselt wird.
Dieser Abschnitt erläutert, wie man (vollständige und inkrementelle) Datenbanksicherungen durchführt und Tabellen pflegt. Die Syntax der hier beschriebenen SQL-Anweisungen wird in Kapitel 13, SQL-Anweisungssyntax, beschrieben. Ein Großteil der hier vermittelten Informationen bezieht sich in erster Linie auf MyISAM
-Tabellen. Weitere Informationen zu Sicherungsvorgängen für InnoDB
-Tabellen können Sie Abschnitt 14.2.8, „Sichern und Wiederherstellen einer InnoDB
-Datenbank“ entnehmen.
Da MySQL-Tabellen als Dateien gespeichert werden, ist die Durchführung einer Datensicherung recht einfach. Um ein konsistentes Backup zu erhalten, führen Sie für die gewünschten Tabellen nacheinander die Anweisungen LOCK TABLES
und FLUSH TABLES
aus. Siehe auch Abschnitt 13.4.5, „LOCK TABLES
und UNLOCK TABLES
“, und Abschnitt 13.5.5.2, „FLUSH
“. Sie benötigen lediglich eine Lesesperre, d. h. andere Clients können die Tabellen weiterhin abfragen, während Sie eine Kopie der Dateien im Datenbankverzeichnis erstellen. Die Anweisung FLUSH TABLES
ist erforderlich, um sicherzustellen, dass alle aktiven Indexseiten auf Festplatte geschrieben werden, bevor Sie die Sicherung starten.
Um eine Tabelle auf SQL-Ebene zu sichern, können Sie SELECT INTO ... OUTFILE
verwenden. Bei dieser Anweisung darf die Ausgabedatei nicht bereits vorhanden sein, da das Überschreiben vorhandener Dateien ein Sicherheitsrisiko darstellen würde. Siehe auch Abschnitt 13.2.7, „SELECT
“.
Eine weitere Methode zur Sicherung einer Datenbank besteht in der Verwendung des Programms mysqldump oder des Skripts mysqlhotcopy. Siehe auch Abschnitt 8.10, „mysqldump — Programm zur Datensicherung“, und Abschnitt 8.11, „mysqlhotcopy — Backup-Programm für Datenbanken“.
Erstellen Sie eine vollständige Sicherung Ihrer Datenbank:
shell> mysqldump --tab=/path/to/some/dir
--opt db_name
Oder:
shell> mysqlhotcopy db_name
/path/to/some/dir
Sie können auch eine binäre Sicherung erstellen, indem Sie einfach alle Tabellendateien (*.frm
, *.MYD
und *.MYI
) kopieren, während der Server keine Aktualisierungen vornimmt. Das Skript mysqlhotcopy verwendet diese Methode. (Beachten Sie aber, dass diese Methoden nicht funktionieren, wenn Ihre Datenbank InnoDB
-Tabellen enthält. InnoDB
speichert die Tabelleninhalte nicht in Datenbankverzeichnissen, und mysqlhotcopy funktioniert nur bei MyISAM
-Tabellen.)
Wenn mysqld läuft, beenden Sie es und starten Sie es dann mit der Option --log-bin[=
neu. Siehe auch Abschnitt 5.12.3, „Die binäre Update-Logdatei“. Die Binärlogdateien vermitteln Ihnen die Informationen, die Sie zur Replikation von Änderungen an der Datenbank benötigen, die nach dem Punkt, an dem Sie mysqldump ausgeführt haben, durchgeführt wurden.
file_name
]
Bei InnoDB
-Tabellen können Sie ein Onlinebackup durchführen, bei dem die Tabellen nicht gesperrt werden; siehe auch Abschnitt 8.10, „mysqldump — Programm zur Datensicherung“.
MySQL unterstützt inkrementelle Backups: Zu diesem Zweck müssen Sie den Server mit der Option --log-bin
starten (Abschnitt 5.12.3, „Die binäre Update-Logdatei“). Sobald Sie ein inkrementelles Backup erstellen wollen (d. h. eine Sicherung, die alle seit dem letzten vollständigen oder inkrementellen Backup vorgenommenen Änderungen enthält), dann sollten Sie das Binärlog mit FLUSH LOGS
rotieren. Danach müssen Sie alle Binärlogs, die aus dem Zeitraum zwischen dem letzten vollständigen oder inkrementellen Backup und dem vorletzten erstellten Log stammen, an die Sicherungsposition kopieren. Diese Binärlogs bilden die inkrementelle Sicherung; wenn eine Wiederherstellung erforderlich ist, wenden Sie sie wie weiter unten erläutert an. Wenn Sie beim nächsten Mal eine vollständige Sicherung durchführen, sollten Sie das Binärlog ebenfalls mit FLUSH LOGS
, mysqldump --flush-logs
oder mysqlhotcopy --flushlog
rotieren. Siehe auch Abschnitt 8.10, „mysqldump — Programm zur Datensicherung“, und Abschnitt 8.11, „mysqlhotcopy — Backup-Programm für Datenbanken“.
Wenn Ihr MySQL-Server ein Slave-Replikationsserver ist, dann sollten Sie unabhängig von der gewählten Sicherungsmethode auch die Dateien master.info
und relay-log.info
sichern, wenn Sie ein Backup der Daten auf Ihrem Slave durchführen. Diese Dateien werden immer benötigt, um die Replikation nach Wiederherstellung der Daten auf dem Slave fortzusetzen. Wenn Ihr Slave Gegenstand der Replikation von LOAD DATA INFILE
-Befehlen ist, sollten Sie auch alle SQL_LOAD-*
-Dateien sichern, die ggf. in dem mit der Option --slave-load-tmpdir
angegebenen Verzeichnis vorhanden sind. (Sofern die Option nicht angegeben wurde, ist die Position standardmäßig der Wert der Variable tmpdir
.) Der Slave benötigt diese Dateien, um die Replikation unterbrochener LOAD DATA INFILE
-Operationen fortzusetzen.
Wenn Sie MyISAM
-Tabellen wiederherstellen müssen, probieren Sie dies zunächst mit REPAIR TABLE
oder myisamchk -r. Dies sollte in 99,9 Prozent aller Fälle funktionieren. Schlägt der Befehl myisamchk fehl, dann probieren Sie die nachfolgend beschriebene Vorgehensweise aus. Beachten Sie, dass dies nur funktioniert, wenn Sie durch Starten von MySQL mit der Option --log-bin
das binäre Loggen aktiviert haben.
Stellen Sie das ursprüngliche mysqldump-Backup oder das binäre Backup wieder her.
Führen Sie den folgenden Befehl aus, um die Aktualisierungen in den Binärlogs erneut auszuführen:
shell> mysqlbinlog binlog.[0-9]* | mysql
In manchen Fällen wollen Sie unter Umständen nur bestimmte Binärlogs in bestimmten Verzeichnissen erneut ausführen (wobei Sie in der Regel alle Binärlogs ab dem Datum der wiedergestellten Sicherung wiederherstellen sollten – möglicherweise abgesehen von einigen falschen Anweisungen). Weitere Informationen zum Hilfsprogramm mysqlbinlog und seiner Verwendung finden Sie in Abschnitt 8.8, „mysqlbinlog — Hilfsprogramm für die Verarbeitung binärer Logdateien“.
Sie können auch selektive Sicherungen einzelner Dateien vornehmen:
Um einen Speicherauszug einer Tabelle zu erstellen, verwenden Sie SELECT * INTO OUTFILE '
.
file_name
' FROM tbl_name
Um die Tabelle wieder zu laden, verwenden Sie LOAD DATA INFILE '
. Um Datensatzdubletten zu verhindern, muss die Tabelle einen file_name
' REPLACE ...PRIMARY KEY
- oder einen UNIQUE
-Index aufweisen. Das Schlüsselwort REPLACE
sorgt dafür, dass alte Datensätze durch neue ersetzt werden, wenn ein eindeutiger Schlüsselwert in einem neuen Datensatz dem eines alten Datensatzes entspricht.
Wenn Sie bei der Durchführung von Sicherungen Probleme mit der Serverleistung haben, besteht eine mögliche Abhilfe darin, die Replikation zu konfigurieren und Backups auf dem Slave statt auf dem Master durchzuführen. Siehe auch Abschnitt 6.1, „Einführung in die Replikation“.
Wenn Sie ein Veritas-Dateisystem verwenden, können Sie das Backup wie folgt erstellen:
Führen Sie im Clientprogramm FLUSH TABLES WITH READ LOCK
aus.
Führen Sie unter einer anderen Shell mount vxfs snapshot
aus.
Führen Sie nun wiederum auf dem ersten Client UNLOCK TABLES
aus.
Kopieren Sie die Dateien aus dem Schnappschuss.
Trennen Sie den Schnappschuss ab.
Dieser Abschnitt erläutert eine Vorgehensweise zur Durchführung von Backups, die eine Wiederherstellung von Daten nach mehreren Arten von Abstürzen gestattet:
Absturz des Betriebssystems
Stromausfall
Absturz des Dateisystems
Hardwareproblem (Festplatte, Hauptplatine usw.)
Die Befehlsbeispiele enthalten keine Optionen wie --user
und --password
für die Programme mysqldump und mysql. Sie sollten diese Optionen nach Bedarf hinzufügen, sodass der MySQL-Server Ihnen das Herstellen einer Verbindung gestattet.
Wir setzen voraus, dass die Daten in der InnoDB
-Speicher-Engine gespeichert sind, die Transaktionen und automatische Wiederherstellung nach einem Absturz unterstützt. Ferner wird vorausgesetzt, dass der MySQL-Server zum Zeitpunkt des Absturzes Daten verarbeitet; wäre dies nicht der Fall, dann wäre keine Wiederherstellung erforderlich.
In Fällen von Betriebssystemabstürzen oder Stromausfällen können wir davon ausgehen, dass die Festplattendaten von MySQL nach einem Neustart wieder verfügbar sind. Die InnoDB
-Datendateien enthalten unter Umständen aufgrund des Absturzes keine konsistenten Daten, aber InnoDB
liest seine Logs aus und findet darin die Liste der anhängigen abgeschlossenen und nicht abgeschlossenen Transaktionen, die noch nicht in die Datendateien geschrieben wurden. InnoDB
führt für die nicht abgeschlossenen Transaktionen automatisch einen Rollback aus, die abgeschlossenen Transaktionen hingegen werden in die Datendateien geschrieben. Informationen zum Wiederherstellungsprozess erhält der Benutzer über das MySQL-Fehlerlog. Hier ein Beispielauszug aus einem Log:
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
In Fällen von Dateisystemabstürzen oder Hardwareproblemen können wir davon ausgehen, dass die MySQL-Festplattendaten nach einem Neustart nicht verfügbar sind. Das bedeutet wiederum, dass MySQL nicht erfolgreich gestartet werden kann, da einige Datenblöcke auf der Festplatte nicht mehr lesbar sind. In diesem Fall ist es erforderlich, die Festplatte neu zu formatieren, eine neue Festplatte zu installieren oder das zugrundeliegende Problem anderweitig zu beheben. Danach müssen wir unsere MySQL-Daten aus Backups wiederherstellen, d. h. es sollten bereits Backups vorhanden sein. Um dies sicherzustellen, sollten wir eine Sicherungsrichtlinie erstellen.
Wir alle wissen, dass die regelmäßige Durchführung von Sicherungen geplant werden muss. Ein vollständiges Backup (d. h. ein Schnappschuss der Daten zu einem gegebenen Zeitpunkt) kann in MySQL mit verschiedenen Tools erfolgen. So ermöglicht etwa InnoDB Hot Backup
eine online durchgeführte physische Sicherung der InnoDB
-Datendateien ohne Sperre, und mysqldump erlaubt ein online erstelltes logisches Backup. Wir werden an dieser Stelle mysqldump beschreiben.
Nehmen wir an, Sie erstellen am Sonntag um 13:00 Uhr ein Backup. Dies ist ein Zeitpunkt, an dem die Serverlast niedrig ist. Der folgende Befehl erstellt ein vollständiges Backup all Ihrer InnoDB
-Tabellen in allen Datenbanken:
shell> mysqldump --single-transaction --all-databases > backup_sunday_1_PM.sql
Dies ist eine online ausgeführte, nicht sperrende Sicherung, die Lese- und Schreibvorgänge in den Tabellen nicht beeinträchtigt. Wir haben bereits weiter oben gesagt, dass unsere Tabellen InnoDB
-Tabellen sind, d. h. --single-transaction
verwendet eine konsistente Leseoperation und gewährleistet, dass die von mysqldump erkannten Daten nicht geändert werden. (Änderungen, die von anderen Clients an den InnoDB
-Tabellen durchgeführt werden, werden vom mysqldump-Prozess nicht erkannt.) Wenn auch andere Tabellentypen vorhanden sind, müssen wir davon ausgehen, dass diese während des Sicherungsvorgangs nicht geändert werden. So müssen wir beispielsweise für die MyISAM
-Tabellen in der mysql
-Datenbank voraussetzen, dass während der Sicherung keine administrativen Änderungen an den MySQL-Konten vorgenommen werden.
Am Ende steht eine .sql
-Datei, die von mysqldump erzeugt wird. Sie enthält einen Satz von INSERT
-SQL-Anweisungen, die zum Neuladen der gespeicherten Tabellen zu einem späteren Zeitpunkt verwendet werden können.
Vollständige Backups sind erforderlich, aber manchmal unpraktisch. Sie erzeugen große Sicherungsdateien, und die Erstellung dauert recht lange. Außerdem sind sie nicht optimal in dem Sinn, dass alle aufeinanderfolgenden Sicherungen alle Daten enthalten – d. h. auch solche, die seit dem letzten vollständigen Backup nicht geändert wurden. Wenn wir also ein vollständiges Backup als Ausgangspunkt erstellt haben, ist es effektiver, nachfolgend inkrementelle Sicherungen zu erstellen. Diese sind kleiner, und ihre Erstellung verläuft schneller. Der Nachteil besteht darin, dass Sie im Fehlerfall nicht einfach ein einziges vollständiges Backup aufspielen können, um Ihre Daten wiederherzustellen. Sie müssen vielmehr auch die inkrementellen Sicherungen aufspielen, um die dort gespeicherten Änderungen wiederherzustellen.
Um inkrementelle Sicherungen zu erstellen, müssen wir die inkrementellen Änderungen speichern. Der MySQL-Server sollte immer mit der Option --log-bin
gestartet werden, damit er diese Änderungen beim Aktualisieren von Daten in einer Datei speichert. Diese Option aktiviert das binäre Loggen, d. h. der Server schreibt jede SQL-Anweisung, die Daten ändert, in eine Datei: das MySQL-Binärlog. Wenn man einen Blick in das Datenverzeichnis eines MySQL-Servers wirft, der mit der Option --log-bin
gestartet wurde und schon ein paar Tage läuft, dann findet man dort die folgenden MySQL-Binärlogdateien:
-rw-rw---- 1 guilhem guilhem 1277324 Nov 10 23:59 gbichot2-bin.000001 -rw-rw---- 1 guilhem guilhem 4 Nov 10 23:59 gbichot2-bin.000002 -rw-rw---- 1 guilhem guilhem 79 Nov 11 11:06 gbichot2-bin.000003 -rw-rw---- 1 guilhem guilhem 508 Nov 11 11:08 gbichot2-bin.000004 -rw-rw---- 1 guilhem guilhem 220047446 Nov 12 16:47 gbichot2-bin.000005 -rw-rw---- 1 guilhem guilhem 998412 Nov 14 10:08 gbichot2-bin.000006 -rw-rw---- 1 guilhem guilhem 361 Nov 14 10:07 gbichot2-bin.index
Bei jedem Neustart erstellt der MySQL-Server eine neue Binärlogdatei, für deren Benennung er die nächste Nummer in der Nummernfolge verwendet. Solange der Server ausgeführt wird, können Sie ihn auch manuell anweisen, die aktuelle Binärlogdatei zu schließen und eine neue zu erstellen. Hierzu verwenden Sie die SQL-Anweisung FLUSH LOGS
oder geben den Befehl mysqladmin flush-logs ein. Auch mysqldump bietet eine Option zum Schreiben der Logs auf die Festplatte. Die .index
-Datei im Datenverzeichnis enthält eine Liste aller MySQL-Binärlogs in diesem Verzeichnis. Die Datei wird zur Replikation verwendet.
Die MySQL-Binärlogs sind für die Wiederherstellung wichtig, denn sie bilden den Satz inkrementeller Backups. Wenn Sie die Logs beim Erstellen einer vollständigen Sicherung auf Festplatte schreiben, dann enthält ein ggf. nachfolgend erstelltes Backup alle Änderungen seit dem Backup. Wir wollen den obigen mysqldump-Befehl ein wenig abändern, damit er die MySQL-Binärlogs zum Zeitpunkt einer vollständigen Sicherung auf die Festplatte schreibt und die Speicherauszugsdatei den Namen des neuen aktuellen Binärlogs enthält:
shell>mysqldump --single-transaction --flush-logs --master-data=2 \
--all-databases > backup_sunday_1_PM.sql
Nach Ausführung dieses Befehls enthält das Datenverzeichnis eine neue Binärlogdatei namens gbichot2-bin.000007
. Die am Ende erstellte .sql
-Datei enthält die folgenden Zeilen:
-- Position to start replication or point-in-time recovery from -- CHANGE MASTER TO MASTER_LOG_FILE='gbichot2-bin.000007',MASTER_LOG_POS=4;
Weil der mysqldump-Befehl ein vollständiges Backup erstellt hat, bedeuten diese Zeilen zweierlei:
Die .sql
-Datei enthält alle Änderungen, die vorgenommen wurden, bevor Änderungen in die Binärlogdatei gbichot2-bin.000007
oder eine neuere Binärlogdatei geschrieben wurden.
Alle nach dem Backup geloggten Datenänderungen sind noch nicht in der .sql
-Datei, wohl aber in der Binärlogdatei gbichot2-bin.000007
oder einer neueren Binärlogdatei vorhanden.
Am Montag um 13:00 Uhr erstellen wir eine inkrementelle Sicherungsdatei, indem wir die Logdateien auf die Festplatte schreiben, um so eine neue Binärlogdatei zu erstellen. So erstellt beispielsweise der Befehl mysqladmin flush-logs die Datei gbichot2-bin.000008
. Alle Änderungen, die zwischen Sonntag, 13:00 Uhr (Erstellung des vollständigen Backups), und Montag, 13:00 Uhr, vorgenommen wurden, sind in der Datei gbichot2-bin.000007
enthalten. Diese inkrementelle Sicherung ist wichtig, weswegen sie an einen sicheren Ort kopiert werden sollte. (Sie können sie etwa auf Band oder DVD sichern oder auf einen anderen Computer kopieren.) Am Dienstag um 13:00 Uhr wird der Befehl mysqladmin flush-logs erneut ausgeführt. Alle Änderungen, die zwischen Montag, 13:00 Uhr, und Dienstag, 13:00 Uhr, angefallen sind, sind in der Datei gbichot2-bin.000008
vermerkt (auch diese sollten Sie an einen sicheren Ort kopieren).
Die MySQL-Binärlogs benötigen Festplattenspeicher. Um Speicher freizugeben, sollten Sie sie von Zeit zu Zeit bereinigen. Eine Möglichkeit, dies zu tun, besteht im Löschen von Binärlogs, die nicht mehr benötigt werden (beispielsweise nachdem ein vollständiges Backup erstellt wurde):
shell>mysqldump --single-transaction --flush-logs --master-data=2 \
--all-databases --delete-master-logs > backup_sunday_1_PM.sql
Hinweis: Das Löschen von MySQL-Binärlogs mit mysqldump --delete-master-logs kann gefährlich sein, wenn Ihr Server ein Replikations-Master ist, denn unter Umständen haben die Slave-Server den Inhalt des Binärlogs noch nicht vollständig verarbeitet. Die Beschreibung der PURGE MASTER LOGS
-Anweisung erläutert, was zu prüfen ist, bevor die MySQL-Binärlogs gelöscht werden. Siehe auch Abschnitt 13.6.1.1, „PURGE MASTER LOGS
“.
Nehmen wir nun an, dass es am Mittwoch um 8:00 Uhr zu einem folgenschweren Absturz kommt, der eine Wiederherstellung aus den Sicherungen erfordert. Zu diesem Zweck stellen wir zunächst das letzte vollständige Backup (von Sonntag, 13:00 Uhr) wieder her. Da die vollständige Sicherungsdatei nichts anderes als eine Sammlung von SQL-Anweisungen ist, ist die Wiederherstellung sehr einfach:
shell> mysql < backup_sunday_1_PM.sql
An dieser Stelle sind die Daten auf dem Stand von Sonntag, 13:00 Uhr. Um nun die seitdem vorgenommenen Änderungen wiederherzustellen, müssen wir die inkrementellen Sicherungen verwenden, d. h. die Binärlogdateien gbichot2-bin.000007
und gbichot2-bin.000008
. Besorgen Sie sich diese Dateien nun von dort, wo Sie sie gesichert hatten, und verarbeiten Sie ihren Inhalt wie folgt:
shell> mysqlbinlog gbichot2-bin.000007 gbichot2-bin.000008 | mysql
Wir haben nun die Daten auf dem Stand von Dienstag, 13:00 Uhr, wiederhergestellt. Noch aber fehlen die Daten zwischen diesem Zeitpunkt und dem des Absturzes. Um diese nicht zu verlieren, hätten wir den MySQL-Server so konfiguriert haben müssen, dass er seine MySQL-Binärlogs an einem sicheren Ort (RAID-Festplatten, SAN, usw.) speichert – nicht aber auf der Festplatte, wo er seine Datendateien speichert, damit die Logs sich im Schadensfalls nicht auf der zerstörten Festplatte befinden. (Zu diesem Zweck können wir den Server mit der Option --log-bin
starten, die eine Position auf einem anderen physischen Gerät als demjenigen angibt, auf dem das Datenverzeichnis liegt. Auf diese Weise gehen die Logs nicht verloren, wenn das Gerät mit dem Datenverzeichnis zerstört wird.) Hätten wir das gemacht, dann hätten wir jetzt die Datei gbichot2-bin.000009
zur Hand und könnten sie einfach mit mysqlbinlog und mysql aufspielen, um die letzten Datenänderungen bis zum Moment des Absturzes verlustfrei wiederherzustellen.
Bei einem Betriebssystemabsturz oder einem Stromausfall erledigt InnoDB
die gesamte Datenwiederherstellung automatisch. Um jedoch ruhig schlafen zu können, sollten Sie unbedingt folgende Richtlinien beachten:
Führen Sie den MySQL-Server immer mit der Option --log-bin
oder sogar --log-bin=
aus. Der angegebene Logdateiname befindet sich dabei auf einem anderen Medium als dem Laufwerk, auf dem das Datenverzeichnis gespeichert ist. Sofern Sie solche sicheren Medien haben, können Sie sie unter Umständen auch gut für eine Festplattenlastverteilung einsetzen (was sich positiv auf die Leistung auswirkt).
log_name
Erstellen Sie regelmäßig vollständige Backups. Verwenden Sie dazu den letzten der oben angegebenen mysqldump-Befehle, um ein Online-Backup ohne Sperren durchzuführen.
Erstellen Sie regelmäßig inkrementelle Backups, indem Sie die Logs mit FLUSH LOGS
oder mysqladmin flush-logs auf die Festplatte schreiben.
Wenn am MySQL-Server das binäre Loggen aktiviert ist, können Sie mit dem Hilfsprogramm mysqlbinlog Daten ab dem angegebenen Zeitpunkt („Point in Time“) bis zum aktuellen oder einem anderen angegebenen Zeitpunkt wiederherstellen. Informationen zur Aktivierung des Binärlogs und zur Verwendung von mysqlbinlog finden Sie in Abschnitt 5.12.3, „Die binäre Update-Logdatei“, und Abschnitt 8.8, „mysqlbinlog — Hilfsprogramm für die Verarbeitung binärer Logdateien“.
Um Daten aus einem Binärlog wiederherzustellen, müssen Sie den Pfad und den Namen der aktuellen Binärlogdatei kennen. Sie finden den Pfad normalerweise in der Optionsdatei (also je nach System my.cnf
oder my.ini
). Ist der Pfad nicht in der Optionsdatei enthalten, dann wurde er unter Umständen beim Serverstart als Option auf der Befehlszeile angegeben. Die Option zur Aktivierung des binären Loggens heißt --log-bin
. Den Namen der aktuellen Binärlogdatei ermitteln Sie mit der folgenden Anweisung:
mysql> SHOW BINLOG EVENTS \G
Sie können, wenn Sie dies vorziehen, auch folgenden Befehl über die Befehlszeile ausführen:
shell> mysql --user=root -p -E -e "SHOW BINLOG EVENTS"
Geben Sie das root
-Passwort für Ihren Server ein, wenn mysql Sie dazu auffordert.
Um die Start- und Endzeitpunkte für die Wiederherstellung festzulegen, geben Sie für mysqlbinlog die Optionen --start-date
und --stop-date
im DATETIME
an. Nehmen wir beispielsweise an, dass am 20. April 2005 um genau 10:00 Uhr eine SQL-Anweisung ausgeführt wurde, mit der eine große Tabelle gelöscht wurde. Um die Tabelle und ihre Daten wiederherzustellen, könnten Sie das Backup der vorhergehenden Nacht wiederherstellen und dann den folgenden Befehl ausführen:
shell>mysqlbinlog --stop-date="2005-04-20 9:59:59" \
/var/log/mysql/bin.123456 | mysql -u root -p
Dieser Befehl stellt alle Daten bis zum durch die Option --stop-date
angegebenen Zeitpunkt wieder her. Haben Sie die fehlerhafte SQL-Anweisung, die zum Löschen der Tabellen eingegeben wurde, erst Stunden später entdeckt, dann werden Sie wahrscheinlich auch die nachfolgenden durchgeführten Operationen wiederherstellen wollen. Davon ausgehend könnten Sie mysqlbinlog noch einmal unter Angabe eines Startzeitpunkts ausführen:
shell>mysqlbinlog --start-date="2005-04-20 10:01:00" \
/var/log/mysql/bin.123456 | mysql -u root -p
In diesem Befehl werden die SQL-Anweisungen, die ab 10:01 Uhr aufgezeichnet wurden, erneut aufgeführt. Die Kombination aus der Wiederherstellung der Speicherauszugsdatei der vorangegangenen Nacht und der Ausführung der beiden mysqlbinlog-Befehle stellt alle Aktionen mit Ausnahme derjenigen wieder her, die im Zeitraum zwischen 9:59:59 Uhr und 10:01:00 Uhr ausgeführt wurden. Überprüfen Sie die Logdatei, um die exakten Zeiten angeben zu können. Der nächste Abschnitt beschreibt die erforderlichen Abläufe.
Statt Datums- und Zeitangaben anzugeben, können Sie die Optionen --start-position
und --stop-position
für mysqlbinlog zur Angabe von Logpositionen verwenden. Diese Optionen arbeiten genauso wie die Optionen für Start- und Endzeitpunkt, nur werden Positionsangaben aus dem Log spezifiziert. Die Angabe dieser Logposition ist unter Umständen eine exaktere Wiederherstellungsmethode – insbesondere dann, wenn viele Transaktionen zur gleichen Zeit wie die schädliche SQL-Anweisung auftraten. Zur Bestimmung der Positionsnummer können Sie mysqlbinlog für einen Zeitbereich in der Umgebung des Zeitpunkts ausführen, an dem die unerwünschte Transaktion durchgeführt wurde, die Ergebnisse aber zur Überprüfung in einer Textdatei umleiten. Dies wird wie folgt gemacht:
shell>mysqlbinlog --start-date="2005-04-20 9:55:00" \
--stop-date="2005-04-20 10:05:00" \
/var/log/mysql/bin.123456 > /tmp/mysql_restore.sql
Dieser Befehl erstellt eine kleine Textdatei im Verzeichnis /tmp
, die die im zeitlichen Bereich der misslichen SQL-Anweisung abgesetzten Anweisungen enthält. Öffnen Sie diese Datei mit einem Texteditor und suchen Sie nach der Anweisung, die nicht wiederholt werden soll. Bestimmen Sie die Positionen im Binärlog für das Beenden und Wiederaufnehmen der Wiederherstellung und notieren Sie sich diese. Die Positionen sind gekennzeichnet mit log_pos
, gefolgt von einer Zahl. Nach der Wiederherstellung der vorherigen Sicherungsdatei verarbeiten Sie die Binärlogdatei unter Verwendung der Positionsnummern. So würden Sie z. B. Befehle in der Art der folgenden verwenden:
shell>mysqlbinlog --stop-position="368312" /var/log/mysql/bin.123456 \
| mysql -u root -p
shell>mysqlbinlog --start-position="368315" /var/log/mysql/bin.123456 \
| mysql -u root -p
Der erste Befehl stellt alle Transaktionen bis zur angegebenen Endposition wieder her. Der zweite Befehl führt die Wiederherstellung aller Transaktionen vom angegebenen Fortsetzungspunkt bis zum Ende des Binärlogs durch. Da die Ausgabe von mysqlbinlog vor jeder aufgezeichneten SQL-Anweisung SET TIMESTAMP
-Anweisungen enthält, finden sich in den wiederhergestellten Daten und den zugehörigen MySQL-Logs die ursprünglichen Ausführungszeitpunkte der Transaktionen wieder.
Dieser Abschnitt beschreibt, wie man mit myisamchk MyISAM
-Tabellen überprüft oder repariert (also Tabellen, für die .MYD
- und .MYI
-Dateien zur Speicherung von Daten und Indizes vorhanden sind). Allgemeine Hinweise zu myisamchk finden Sie in Abschnitt 8.2, „myisamchk — Hilfsprogramm für die Tabellenwartung von MyISAM“.
Sie können mit myisamchk Informationen zu Ihren Datenbanktabellen abrufen oder sie überprüfen, reparieren oder optimieren. Die folgenden Abschnitte erläutern, wie Sie diese Operationen durchführen und wie man einen Wartungsplan für Tabellen einrichtet.
Auch wenn die Tabellenreparatur mit myisamchk verhältnismäßig sicher ist, sollten Sie immer ein Backup erstellen, bevor Sie eine Reparatur oder Wartungsoperationen durchführen, bei denen viele Änderungen an einer Tabelle vorgenommen werden.
myisamchk-Operationen, die sich auf Indizes auswirken, können die Neuerstellung von FULLTEXT
-Indizes mit Volltextparametern auslösen, die nicht mit den vom MySQL-Server verwendeten Werten kompatibel sind. Um dieses Problem zu umgehen, beachten Sie die Hinweise in Abschnitt 8.2.1, „Allgemeine Optionen für myisamchk
“.
In vielen Fällen kann es auch einfacher sein, die Wartung einer MyISAM
-Tabelle mit SQL-Anweisungen durchzuführen, die Operationen ausführen, wie Sie auch von myisamchk unterstützt werden:
Um MyISAM
-Tabellen zu überprüfen oder zu reparieren, verwenden Sie CHECK TABLE
oder REPAIR TABLE
.
Um MyISAM
-Tabellen zu optimieren, benutzen Sie OPTIMIZE TABLE
.
Um MyISAM
-Tabellen zu analysieren, benutzen Sie ANALYZE TABLE
.
Diese Anweisungen können wahlweise direkt oder mithilfe des Clientprogramms mysqlcheck eingesetzt werden. Ein Vorteil dieser Anweisungen im Vergleich zu myisamchk besteht darin, dass der Server die gesamte Arbeit erledigt. Bei myisamchk müssen Sie sicherstellen, dass der Server die Tabellen nicht zur selben Zeit verwendet, damit es nicht zu unerwünschten Interaktionen zwischen myisamchk und dem Server kommt. Siehe auch Abschnitt 13.5.2.1, „ANALYZE TABLE
“, Abschnitt 13.5.2.3, „CHECK TABLE
“, Abschnitt 13.5.2.5, „OPTIMIZE TABLE
“, und Abschnitt 13.5.2.6, „REPAIR TABLE
“.
Dieser Abschnitt beschreibt, wie Sie MySQL-Datenbanken auf beschädigte Daten überprüfen und mit diesen ggf. verfahren können. Wenn Ihre Tabellen häufig beschädigt werden, sollten Sie die Ursache hierfür ermitteln. Siehe auch Abschnitt A.4.2, „Was zu tun ist, wenn MySQL andauernd abstürzt“.
Eine Erklärung, wie Schäden an MyISAM
-Tabellen auftreten können, finden Sie in Abschnitt 14.1.4, „MyISAM-Tabellenprobleme“.
Wenn Sie mysqld mit deaktivierter externer Sperre ausführen (was ab MySQL 4.0 das Standardverhalten ist), dann können Sie myisamchk nicht für das zuverlässige Überprüfen einer Tabelle verwenden, wenn mysqld genau diese Tabelle benutzt. Wenn Sie ganz sicher sind, dass niemand über mysqld auf die Tabellen zugreifen kann, während Sie myisamchk ausführen, müssen Sie lediglich mysqladmin flush-tables ausführen, bevor Sie die Überprüfung der Tabellen starten. Können Sie dies nicht gewährleisten, dann müssen Sie mysqld stoppen, solange Sie die Tabellen überprüfen. Führen Sie myisamchk zur Überprüfung von Tabellen aus, die gleichzeitig von mysqld aktualisiert werden, dann erhalten Sie unter Umständen eine Warnung, dass eine Tabelle beschädigt sei, obwohl dies gar nicht stimmt.
Wenn der Server mit aktivierter externer Sperrung ausgeführt wird, können Sie die Tabellen jederzeit mit myisamchk überprüfen. In diesem Fall muss der Server, wenn er eine Tabelle zu aktualisieren versucht, die myisamchk gerade verwendet, warten, bis myisamchk den Vorgang abgeschlossen hat, bevor er fortfährt.
Verwenden Sie myisamchk zur Reparatur oder Optimierung von Tabellen, dann müssen Sie immer sicherstellen, dass der Server mysqld die Tabelle nicht verwendet. (Dies gilt auch bei deaktivierter externer Sperrung.) Beenden Sie mysqld nicht, dann sollten Sie zumindest mysqladmin flush-tables ausführen, bevor Sie myisamchk starten. Wenn der Server und myisamchk gleichzeitig auf die Tabellen zugreifen, können Ihre Tabellen beschädigt werden.
Wenn Sie eine Wiederherstellung nach einem Absturz durchführen, müssen Sie beachten, dass zu jeder MyISAM
-Tabelle tbl_name
in einer Datenbank drei Dateien im Datenbankverzeichnis gehören:
Datei | Zweck |
| Definitionsdatei (Formatdatei) |
| Datendatei |
| Indexdatei |
Jeder dieser drei Dateitypen kann auf unterschiedliche Weise beschädigt werden, meistens treten Probleme aber in Zusammenhang mit Daten- und Indexdateien auf.
myisamchk erstellt datensatzweise eine Kopie der .MYD
-Datendatei. Die Reparatur wird beendet, indem die alte .MYD
-Datei entfernt und der neuen Daten dann der ursprüngliche Dateiname zugewiesen wird. Wenn Sie --quick
verwenden, erstellt myisamchk keine temporäre .MYD
-Datei, sondern setzt stattdessen voraus, dass die .MYD
-Datei korrekt ist, und erstellt nur eine neue Indexdatei – die vorhandene .MYD
-Datei wird nicht angerührt. Dies ist sicher, da myisamchk automatisch erkennt, ob die .MYD
-Datei beschädigt ist (in diesem Fall wird diese Reparatur abgebrochen). Sie können für myisamchk auch zweimal die Option --quick
angeben. In diesem Fall bricht myisamchk bei einigen Fehlern (z. B. Schlüsseldubletten) nicht ab, sondern versucht diese zu beheben, indem die .MYD
-Datei modifiziert wird. Normalerweise ist die Verwendung zweier --quick
-Optionen nur dann sinnvoll, wenn zu wenig freier Festplattenspeicher für eine normale Reparatur vorhanden ist. In diesem Fall sollten Sie zumindest ein Backup der Tabelle erstellen, bevor Sie myisamchk ausführen.
Verwenden Sie die folgenden Befehle, um eine MyISAM
-Tabelle auf Fehler zu prüfen:
myisamchk
tbl_name
Hierdurch werden 99,99 Prozent aller Fehler gefunden. Nicht gefunden werden lediglich Datenschäden, bei denen nur die Datendatei betroffen ist (dies kommt ausgesprochen selten vor). Wenn Sie eine Tabelle überprüfen wollen, sollten Sie normalerweise myisamchk ohne Optionen oder aber mit der Option -s
(stumm) ausführen.
myisamchk -m
tbl_name
Hierdurch werden 99,999 Prozent aller Fehler gefunden. Zunächst werden alle Indexeinträge auf Fehler geprüft, dann werden alle Datensätze gelesen. Für alle Schlüsselwerte in den Datensätzen wird eine Prüfsumme berechnet, die mit der Prüfsumme der Schlüssel im Indexbaum übereinstimmen muss.
myisamchk -e
tbl_name
Führt eine vollständige und umfassende Überprüfung aller Daten durch (-e
bedeutet „Extended Check“, also erweiterte Überprüfung). Jeder Schlüssel in jedem Datensatz wird prüfweise gelesen, um sicherzustellen, dass er tatsächlich auf den korrekten Datensatz verweist.Das kann bei umfangreichen Tabellen mit vielen Indizes recht lange dauern. Normalerweise wird myisamchk nach dem ersten gefundenen Fehler beendet. Wenn Sie weitere Informationen benötigen, können Sie die Option -v
(ausführlicher Modus) hinzufügen. In diesem Fall läuft myisamchk weiter, bis maximal 20 Fehler gefunden wurden.
myisamchk -e -i
tbl_name
Dies ähnelt dem vorherigen Befehl, aber die Option -i
weist myisamchk an, zusätzliche Statistikinformationen auszugeben.
In den meisten Fällen ist ein einfacher myisamchk-Befehl ohne andere Argumente als den Tabellennamen zum Überprüfen einer Tabelle ausreichend.
In diesem Abschnitt wird beschrieben, wie man myisamchk für MyISAM
-Tabellen (Erweiterungen .MYI
und .MYD
) verwendet.
Sie können (und sollten möglichst auch) MyISAM
-Tabellen mit CHECK TABLE
- und REPAIR TABLE
-Anweisungen überprüfen bzw. reparieren. Siehe auch Abschnitt 13.5.2.3, „CHECK TABLE
“, und Abschnitt 13.5.2.6, „REPAIR TABLE
“.
Zu den Symptomen beschädigter Tabellen gehören auch Abfragen, die unerwartet abgebrochen werden, und wahrnehmbare Fehler wie die folgenden:
ist gegen Änderungen gesperrt
tbl_name
.frm
Die Datei
kann nicht gefunden werden (Fehlercode: tbl_name
.MYInnn
)
Unerwartetes Ende der Datei
Aufzeichnungsdatei ist abgestürzt
Fehler nnn
vom Tabellen-Handler erhalten
Um weitere Informationen zum Fehler zu erhalten, führen Sie perror nnn
aus, wobei nnn
die Fehlernummer ist. Die folgenden Beispiele zeigen, wie man mit perror die Bedeutungen der häufigsten Fehlernummern ermittelt, die ein Problem mit einer Tabelle angeben:
shell> perror 126 127 132 134 135 136 141 144 145
126 = Index file is crashed / Wrong file format
127 = Record-file is crashed
132 = Old database file
134 = Record was already deleted (or record file crashed)
135 = No more room in record file
136 = No more room in index file
141 = Duplicate unique key or constraint on write or update
144 = Table is crashed and last repair failed
145 = Table was marked as crashed and should be repaired
Beachten Sie, dass die Fehler 135 („No more room in record file“) und 136 („No more room in index file“) nicht mit einer einfachen Tabellenreparatur behoben werden können. In diesem Fall müssen Sie mit ALTER TABLE
die Tabellenoptionswerte MAX_ROWS
und AVG_ROW_LENGTH
erhöhen:
ALTER TABLEtbl_name
MAX_ROWS=xxx
AVG_ROW_LENGTH=yyy
;
Wenn Sie die aktuellen Tabellenoptionswerte nicht kennen, verwenden Sie SHOW CREATE TABLE
.
Bei Auftreten anderer Fehler müssen Sie Ihre Tabellen reparieren. myisamchk erkennt und behebt normalerweise die meisten Probleme.
Der Reparaturvorgang umfasst die nachfolgend beschriebenen vier Stufen. Bevor Sie anfangen, sollten Sie in das Datenbankverzeichnis wechseln und die Berechtigungen für die Tabellendateien überprüfen. Unter Unix müssen Sie sicherstellen, dass diese von dem Benutzer gelesen werden können, als der mysqld ausgeführt wird (und von Ihnen natürlich auch, denn schließlich müssen Sie auf die Dateien zugreifen können, die Sie überprüfen wollen). Sollte sich herausstellen, dass Sie Dateien ändern müssen, dann sollten diese auch von Ihnen geschrieben werden können.
Dieser Abschnitt ist für Fälle vorgesehen, in denen die Überprüfung einer Tabelle fehlschlägt (siehe auch die Beschreibung in Abschnitt 5.10.4.2, „Wie Tabellen auf Fehler überprüft werden“) oder Sie die erweiterten Funktionen einsetzen wollen, die myisamchk bereitstellt.
Die Optionen, die Sie zur Wartung von Tabellen mit myisamchk verwenden können, sind in Abschnitt 8.2, „myisamchk — Hilfsprogramm für die Tabellenwartung von MyISAM“, beschrieben.
Wenn Sie eine Tabelle über die Befehlszeile reparieren wollen, müssen Sie den Server mysqld zunächst beenden. Beachten Sie, dass, wenn Sie mysqladmin shutdown auf einem entfernten Server ausführen, der Server mysqld auch nach der entsprechenden Meldung von mysqladmin noch eine Weile weiterläuft, bis die gesamte Anweisungsbearbeitung beendet wurde und alle Änderungen auf Festplatte geschrieben wurden.
Stufe 1: Tabellen überprüfen
Führen Sie myisamchk *.MYI oder – wenn genug Zeit vorhanden ist – myisamchk -e *.MYI aus. Verwenden Sie die Option -s
(stumm) zur Unterdrückung nicht benötigter Informationen.
Wenn der Server mysqld beendet ist, sollten Sie die Option --update-state
verwenden, um myisamchk anzuweisen, die Tabelle als „geprüft“ zu kennzeichnen.
Sie müssen nur diejenigen Tabellen reparieren, für die myisamchk einen Fehler meldet. Fahren Sie bei solchen Tabellen mit Stufe 2 fort.
Erhalten Sie bei der Überprüfung unerwartete Fehler (z. B. out of memory
) oder stürzt myisamchk ab, dann fahren Sie mit Stufe 3 fort.
Stufe 2: Einfache und sichere Reparatur
Probieren Sie zunächst myisamchk -r -q tbl_name
aus (-r -q
bedeutet „schneller Wiederherstellungsmodus“). Hierbei wird versucht, die Indexdatei zu reparieren, ohne die Datendatei anzurühren. Wenn die Datendatei alles Erforderliche enthält und die Löschverknüpfungen auf die korrekten Positionen innerhalb der Datendatei verweisen, sollte diese Vorgehensweise funktionieren, d. h. die Tabelle sollte nachfolgend repariert sein. Fahren Sie nun mit der Reparatur der nächsten Tabelle fort. Andernfalls wenden Sie folgende Vorgehensweise an:
Erstellen Sie ein Backup der Datendatei, bevor Sie fortfahren.
Verwenden Sie myisamchk -r tbl_name
(-r
bedeutet „Wiederherstellungsmodus“). Hierdurch werden falsche und gelöschte Datensätze aus der Datendatei entfernt, und die Indexdatei wird neu erstellt.
Schlägt der vorherige Schritt fehl, dann setzen Sie myisamchk --safe-recover tbl_name
ab. Der sichere Wiederherstellungsmodus verwendet eine alte Wiederherstellungsmethode, die ein paar Fälle behebt, die im normalen Wiederherstellungsmodus unberücksichtigt bleiben; sie ist aber langsamer.
Hinweis: Wenn Sie eine Reparaturoption erheblich beschleunigen wollen, sollten Sie die Werte der Variablen sort_buffer_size
und key_buffer_size
jeweils auf 25 Prozent Ihres verfügbaren Speichers setzen, wenn Sie myisamchk ausführen.
Erhalten Sie bei der Reparatur unerwartete Fehler (z. B. out of memory
) oder stürzt myisamchk ab, dann fahren Sie mit Stufe 3 fort.
Stufe 3: Schwierige Reparatur
Diese Stufe sollten Sie nur erreichen, wenn der erste 16-Kbyte-Block der Indexdatei zerstört ist oder falsche Daten enthält oder aber die Indexdatei ganz fehlt. In diesem Fall muss eine neue Indexdatei erstellt werden. Gehen Sie wie folgt vor:
Verschieben Sie die Datendatei an einen sicheren Ort.
Erstellen Sie unter Verwendung der Tabellenbeschreibungsdatei neue (leere) Daten- und Indexdateien:
shell>mysql
mysql>db_name
SET AUTOCOMMIT=1;
mysql>TRUNCATE TABLE
mysql>tbl_name
;quit
Kopieren Sie die alte Datendatei wieder auf die neu erstellte Datendatei. (Verschieben Sie die alte Datei nicht einfach auf die neue, sondern behalten Sie eine Kopie für den Fall, dass etwas fehlschlägt.)
Kehren Sie zurück zu Stufe 2. myisamchk -r -q sollte nun funktionieren. (Das heißt, die Stufen sollten sich nicht in endloser Abfolge wiederholen.)
Sie können auch die SQL-Anweisung REPAIR TABLE
verwenden, die den gesamten Vorgang automatisch ausführt. Es gibt außerdem nicht die Möglichkeit unerwünschter Interaktion zwischen einem Hilfsprogramm und dem Server, weil der Server gar nicht läuft, wenn Sie tbl_name
USE_FRMREPAIR TABLE
verwenden. Siehe auch Abschnitt 13.5.2.6, „REPAIR TABLE
“.
Stufe 4: Sehr schwierige Reparatur
Diese Stufe sollten Sie nur erreichen, wenn die .frm
-Beschreibungsdatei ebenfalls abgestürzt ist. Dies sollte eigentlich nie passieren, da die Beschreibungsdatei nach Erstellung der Tabelle nicht mehr geändert wird:
Stellen Sie die Beschreibungsdatei aus einer Sicherungskopie wieder her und kehren Sie zu Stufe 3 zurück. Sie können auch die Indexdatei wiederherstellen und dann bei Stufe 2 fortfahren; in diesem Fall sollten Sie allerdings mit myisamchk -r beginnen.
Wenn Sie über keine Sicherungskopie verfügen, aber genau wissen, wie die Tabelle erstellt worden war, erstellen Sie eine Kopie der Tabelle in einer andere Datenbank. Entfernen Sie die neue Datendatei und verschieben Sie die .frm
-Beschreibungsdatei und die .MYI
-Indexdatei aus der anderen Datenbank in die abgestürzte Datenbank. Auf diese Weise erhalten Sie eine neue Beschreibungs- und Indexdatei, während die .MYD
-Datendatei nicht angerührt wird. Kehren Sie zu Stufe 2 zurück und versuchen Sie, die Indexdatei neu zu erstellen.
Um fragmentierte Datensätze zu vereinigen und die infolge des Löschens und Aktualisierens von Datensätzen entstandene Platzvergeudung zu beseitigen, führen Sie myisamchk im Wiederherstellungsmodus aus:
shell> myisamchk -r tbl_name
Sie können eine Tabelle auf die gleiche Weise optimieren, indem Sie die SQL-Anweisung OPTIMIZE TABLE
verwenden. OPTIMIZE TABLE
führt eine Reparatur der Tabelle und eine Schlüsselanalyse durch und sortiert zudem den Indexbaum, sodass die Schlüsselsuche beschleunigt wird. Es gibt außerdem nicht die Möglichkeit unerwünschter Interaktion zwischen einem Hilfsprogramm und dem Server, weil der Server gar nicht läuft, wenn Sie OPTIMIZE TABLE
verwenden. Siehe auch Abschnitt 13.5.2.5, „OPTIMIZE TABLE
“.
myisamchk bietet eine Reihe weiterer Optionen, die Sie zur Optimierung der Leistungsfähigkeit einer Tabelle verwenden können:
--analyze
, -a
--sort-index
, -S
--sort-records=
, index_num
-R
index_num
Eine vollständige Beschreibung der verfügbaren Optionen finden Sie in Abschnitt 8.2, „myisamchk — Hilfsprogramm für die Tabellenwartung von MyISAM“.
Um die Beschreibung einer Tabelle oder Statistiken zu ihr zu erhalten, verwenden Sie die hier beschriebenen Befehle. Einige der Informationen werden wir im weiteren Verlauf näher erläutern.
myisamchk -d
tbl_name
Führt myisamchk im „Beschreibungsmodus“ aus, um eine Beschreibung Ihrer Tabelle zu erzeugen. Wenn Sie den MySQL-Server mit deaktivierter externer Sperrung starten, meldet myisamchk unter Umständen einen Fehler für eine Tabelle, die aktualisiert wird, während es ausgeführt wird. Da myisamchk die Tabelle im Beschreibungsmodus allerdings nicht ändert, besteht kein Risiko der Beschädigung von Daten.
myisamchk -d -v
tbl_name
Wenn Sie -v
hinzufügen, läuft myisamchk im ausführlichen Modus, d. h. es werden mehr Informationen zu den ablaufenden Vorgängen erzeugt.
myisamchk -eis
tbl_name
Zeigt nur die wichtigsten Informationen zu einer Tabelle an. Dieser Vorgang ist langsam, da die gesamte Tabelle gelesen werden muss.
myisamchk -eiv
tbl_name
Ähnlich wie -eis
, aber Sie erfahren jeweils, was gerade getan wird.
Eine Beispielausgabe für einige dieser Befehle folgt. Sie basieren auf einer Tabelle mit den folgenden Größen für die Daten- und die Indexdatei:
-rw-rw-r-- 1 monty tcx 317235748 Jan 12 17:30 company.MYD -rw-rw-r-- 1 davida tcx 96482304 Jan 12 18:35 company.MYI
Beispielausgabe von myisamchk -d:
MyISAM file: company.MYI Record format: Fixed length Data records: 1403698 Deleted blocks: 0 Recordlength: 226 table description: Key Start Len Index Type 1 2 8 unique double 2 15 10 multip. text packed stripped 3 219 8 multip. double 4 63 10 multip. text packed stripped 5 167 2 multip. unsigned short 6 177 4 multip. unsigned long 7 155 4 multip. text 8 138 4 multip. unsigned long 9 177 4 multip. unsigned long 193 1 text
Beispielausgabe von myisamchk -d -v:
MyISAM file: company Record format: Fixed length File-version: 1 Creation time: 1999-10-30 12:12:51 Recover time: 1999-10-31 19:13:01 Status: checked Data records: 1403698 Deleted blocks: 0 Datafile parts: 1403698 Deleted data: 0 Datafile pointer (bytes): 3 Keyfile pointer (bytes): 3 Max datafile length: 3791650815 Max keyfile length: 4294967294 Recordlength: 226 table description: Key Start Len Index Type Rec/key Root Blocksize 1 2 8 unique double 1 15845376 1024 2 15 10 multip. text packed stripped 2 25062400 1024 3 219 8 multip. double 73 40907776 1024 4 63 10 multip. text packed stripped 5 48097280 1024 5 167 2 multip. unsigned short 4840 55200768 1024 6 177 4 multip. unsigned long 1346 65145856 1024 7 155 4 multip. text 4995 75090944 1024 8 138 4 multip. unsigned long 87 85036032 1024 9 177 4 multip. unsigned long 178 96481280 1024 193 1 text
Beispielausgabe von myisamchk -eis:
Checking MyISAM file: company Key: 1: Keyblocks used: 97% Packed: 0% Max levels: 4 Key: 2: Keyblocks used: 98% Packed: 50% Max levels: 4 Key: 3: Keyblocks used: 97% Packed: 0% Max levels: 4 Key: 4: Keyblocks used: 99% Packed: 60% Max levels: 3 Key: 5: Keyblocks used: 99% Packed: 0% Max levels: 3 Key: 6: Keyblocks used: 99% Packed: 0% Max levels: 3 Key: 7: Keyblocks used: 99% Packed: 0% Max levels: 3 Key: 8: Keyblocks used: 99% Packed: 0% Max levels: 3 Key: 9: Keyblocks used: 98% Packed: 0% Max levels: 4 Total: Keyblocks used: 98% Packed: 17% Records: 1403698 M.recordlength: 226 Packed: 0% Recordspace used: 100% Empty space: 0% Blocks/Record: 1.00 Record blocks: 1403698 Delete blocks: 0 Recorddata: 317235748 Deleted data: 0 Lost space: 0 Linkdata: 0 User time 1626.51, System time 232.36 Maximum resident set size 0, Integral resident set size 0 Non physical pagefaults 0, Physical pagefaults 627, Swaps 0 Blocks in 0 out 0, Messages in 0 out 0, Signals 0 Voluntary context switches 639, Involuntary context switches 28966
Beispielausgabe von myisamchk -eiv:
Checking MyISAM file: company
Data records: 1403698 Deleted blocks: 0
- check file-size
- check delete-chain
block_size 1024:
index 1:
index 2:
index 3:
index 4:
index 5:
index 6:
index 7:
index 8:
index 9:
No recordlinks
- check index reference
- check data record references index: 1
Key: 1: Keyblocks used: 97% Packed: 0% Max levels: 4
- check data record references index: 2
Key: 2: Keyblocks used: 98% Packed: 50% Max levels: 4
- check data record references index: 3
Key: 3: Keyblocks used: 97% Packed: 0% Max levels: 4
- check data record references index: 4
Key: 4: Keyblocks used: 99% Packed: 60% Max levels: 3
- check data record references index: 5
Key: 5: Keyblocks used: 99% Packed: 0% Max levels: 3
- check data record references index: 6
Key: 6: Keyblocks used: 99% Packed: 0% Max levels: 3
- check data record references index: 7
Key: 7: Keyblocks used: 99% Packed: 0% Max levels: 3
- check data record references index: 8
Key: 8: Keyblocks used: 99% Packed: 0% Max levels: 3
- check data record references index: 9
Key: 9: Keyblocks used: 98% Packed: 0% Max levels: 4
Total: Keyblocks used: 9% Packed: 17%
- check records and index references
*** LOTS OF ROW NUMBERS DELETED ***
Records: 1403698 M.recordlength: 226 Packed: 0%
Recordspace used: 100% Empty space: 0% Blocks/Record: 1.00
Record blocks: 1403698 Delete blocks: 0
Recorddata: 317235748 Deleted data: 0
Lost space: 0 Linkdata: 0
User time 1639.63, System time 251.61
Maximum resident set size 0, Integral resident set size 0
Non physical pagefaults 0, Physical pagefaults 10580, Swaps 0
Blocks in 4 out 0, Messages in 0 out 0, Signals 0
Voluntary context switches 10604, Involuntary context switches 122798
Erläuterungen zu den Informationstypen, die myisamchk erzeugt, folgen an dieser Stelle. „Keyfile“ bezeichnet dabei die Indexdatei. „Eintrag“ und „Datensatz“ sind Synonyme.
MyISAM file
Name der MyISAM
-Datei (Indexdatei).
File-version
Version des MyISAM
-Formats. Ist derzeit immer 2.
Creation time
Zeitpunkt der Erstellung der Datendatei.
Recover time
Letzte Neuerstellung der Index- oder Datendatei.
Data records
Anzahl der Datensätze in der Tabelle.
Deleted blocks
Anzahl der gelöschten Blöcke, für die noch Speicher reserviert ist. Sie können Ihre Tabelle optimieren, um diesen Speicherbedarf zu minimieren. Siehe auch Abschnitt 5.10.4.4, „Tabellenoptimierung“.
Datafile parts
Beim dynamischen Datensatzformat die Anzahl der vorhandenen Datenblöcke. Bei einer optimierten Tabelle ohne fragmentierte Datensätze entspricht der Wert Data records
.
Deleted data
Anzahl der Bytes unbeanspruchter gelöschter Daten. Sie können Ihre Tabelle optimieren, um diesen Speicherbedarf zu minimieren. Siehe auch Abschnitt 5.10.4.4, „Tabellenoptimierung“.
Datafile pointer
Größe des Datendateizeigers in Byte. Beträgt normalerweise zwischen zwei und fünf Bytes. Den meisten Tabellen reichen zwei Bytes aus. Dies lässt sich allerdings von MySQL noch nicht steuern. Bei festen Tabellen ist dies eine Datensatzadresse. Bei dynamischen Tabellen ist es hingegen eine Byteadresse.
Keyfile pointer
Größe des Indexdateizeigers in Byte. Beträgt normalerweise zwischen ein und drei Bytes. Den meisten Tabellen reichen zwei Bytes aus, der Wert wird jedoch von MySQL automatisch berechnet. Es handelt sich immer um eine Blockadresse.
Max datafile length
Maximaler Umfang der Datendatei in Bytes.
Max keyfile length
Maximaler Umfang der Indexdatei in Bytes.
Recordlength
Maximaler Speicherbedarf je Datensatz in Bytes.
Record format
Format, in dem die Datensätze in den Tabellen gespeichert werden. Die obigen Beispiele verwenden Fixed length
. Weitere mögliche Werte sind Compressed
und Packed
.
table description
Eine Liste aller Schlüssel in der Tabelle. Für jeden Schlüssel zeigt myisamchk einige maschinennahe Informationen an:
Key
Die Schlüsselnummer.
Start
Startposition des Index im Datensatz.
Len
Länge des Indexbestandteils. Bei gepackten Zahlen sollte dies immer die Gesamtbreite der Spalte sein. Bei Strings hingegen kann der Wert kürzer sein als die volle Breite der indizierten Spalte, weil Sie das Präfix einer String-Spalte indizieren können.
Index
Gibt an, ob ein Schlüsselwert mehrfach im Index enthalten sein kann. Mögliche Werte sind unique
(eindeutig) oder multip.
(mehrfach).
Type
Gibt den Datentyp an, den dieser Indexbestandteil hat. Dies ist ein MyISAM
-Datentyp mit den möglichen Werten packed
, stripped
oder empty
.
Root
Adresse des Stammindexblocks.
Blocksize
Größe jedes Indexblocks. Ist standardmäßig 1024, der Wert kann aber bei der Kompilierung geändert werden, sofern MySQL aus einer Quelldistribution erstellt wird.
Rec/key
Diese ist ein statistischer Wert, der vom Optimierer verwendet wird. Er besagt, wie viele Datensätze pro Wert für diesen Index vorhanden sind. Bei einem eindeutigen Index ist der Wert immer 1. Dies kann aber geändert werden, nachdem eine Tabelle mit myisamchk -a geladen (oder erheblich verändert) wurde. Erfolgt überhaupt keine Änderung, dann wird ein Standardwert von 30 zugewiesen.
In der in den Beispielen gezeigten Tabelle gibt es zwei table description
-Zeilen für den neunten Index. Hierdurch wird signalisiert, dass es sich um einen mehrteiligen Index mit zwei Teilen handelt.
Keyblocks used
Prozentualer Anteil der verwendeten Schlüsselblöcke. Wenn eine Tabelle gerade erst mit myisamchk neu organisiert wurde (wie die Tabelle in den Beispielen), dann sind die Werte sehr hoch und reichen fast an das theoretische Maximum heran.
Packed
MySQL versucht, Schlüsselwerte mit gemeinsamem Suffix zu packen. Dies ist nur bei Indizes für CHAR
- und VARCHAR
-Spalten möglich. Bei langen indizierten Strings mit ähnlichen führenden Bestandteilen kann dies die Menge des verwendeten Speichers erheblich reduzieren. Im dritten der obigen Beispiele ist der vierte Schlüssel zehn Zeichen lang, und es wird eine Speicherersparnis in Höhe von 60 Prozent erzielt.
Max levels
Tiefe des B-Trees für diesen Schlüssel. Große Tabellen mit langen Schlüsselwerten erhalten hohe Werte.
Records
Anzahl der Datensätze in der Tabelle.
M.recordlength
Durchschnittliche Länge eines Datensatzes. Bei Tabellen mit Datensätzen fester Länge ist dies die exakte Länge des Datensatzes, da alle Datensätze die gleiche Länge haben.
Packed
MySQL schneidet Leerzeichen am Ende von Strings ab. Der Wert Packed
gibt den prozentualen Anteil der hierdurch erzielten Einsparungen an.
Recordspace used
Verwendeter Anteil der Datendatei in Prozent.
Empty space
Nicht verwendeter Anteil der Datendatei in Prozent.
Blocks/Record
Durchschnittliche Anzahl der Blöcke je Datensatz (d. h. aus wie vielen Verknüpfungen ein fragmentierter Datensatz besteht). Bei festen Tabellen ist dies immer 1.0. Der Wert sollte möglichst nah an 1,0 herankommen. Wird er zu groß, dann können Sie die Tabelle reorganisieren. Siehe auch Abschnitt 5.10.4.4, „Tabellenoptimierung“.
Recordblocks
Anzahl der verwendeten Blöcke (Verknüpfungen). Bei festen Tabellen ist dieser Wert identisch mit der Anzahl der Datensätze.
Deleteblocks
Anzahl der gelöschten Blöcke (Verknüpfungen).
Recorddata
Anzahl der verwendeten Bytes in der Datendatei.
Deleted data
Anzahl der gelöschten (d. h. nicht verwendeten) Bytes in der Datendatei.
Lost space
Wenn ein Datensatz aktualisiert wird und sich seine Länge verringert, geht Speicherplatz verloren. Dies ist die Summe dieser Verluste in Byte.
Linkdata
Wenn das dynamische Tabellenformat verwendet wird, werden die Datensatzfragmente durch Zeiger miteinander verknüpft. Die Zeiger haben eine Länge zwischen vier und sieben Bytes. Linkdata
gibt den gesamten von diesen Zeigern verwendeten Speicherplatz an.
Wurde eine Tabelle mit myisampack komprimiert, dann zeigt myisamchk -d zusätzliche Informationen zu allen Tabellenspalten an. In Abschnitt 8.4, „myisampack — Erzeugung komprimierter, schreibgeschützter MyISAM Tabellen“, finden Sie ein Beispiel für diese Informationen und eine Beschreibung ihrer Bedeutung.
Statt abzuwarten, bis Probleme auftreten, bietet es sich an, Tabellen regelmäßig zu überprüfen. Eine Möglichkeit, MyISAM
-Tabellen zu überprüfen und zu reparieren, besteht in der Verwendung der Anweisungen CHECK TABLE
und REPAIR TABLE
. Siehe auch Abschnitt 13.5.2.3, „CHECK TABLE
“, und Abschnitt 13.5.2.6, „REPAIR TABLE
“.
Eine weitere Methoden ist die Nutzung von myisamchk. Bei Wartungsproblemen können Sie myisamchk -s verwenden. Mit der Option -s
(--silent
) läuft myisamchk im stummen Modus, d. h. Meldungen werden nur ausgegeben, wenn Fehler auftreten.
Auch die Aktivierung der automatisierten Überprüfung von MyISAM
-Tabellen ist empfehlenswert. Wann immer ein Computer beispielsweise im Verlauf eines Updates einen Neustart durchführt, müssen Sie jede Tabelle, die hiervon betroffen sein könnte, überprüfen, bevor Sie sie weiter verwenden. (Man bezeichnet solche Tabellen auch als „voraussichtlich abgestürzte Tabellen“.) Um MyISAM
-Tabellen automatisch zu überprüfen, starten Sie den Server mit der Option --myisam-recover
. Siehe auch Abschnitt 5.2.1, „Befehlsoptionen für mysqld“.
Doch auch im normalen Systembetrieb sollten Sie die Tabellen regelmäßig überprüfen. Bei MySQL AB führen wir einmal wöchentlich einen cron-Job zur Überprüfung wichtiger Tabellen durch, wobei wir eine Zeile ähnlich der folgenden in einer Datei crontab
verwenden:
35 0 * * 0/path/to/myisamchk
--fast --silent/path/to/datadir
/*/*.MYI
Hierbei werden Informationen zu abgestürzten Tabellen ausgegeben, die wir untersuchen können, um ggf. erforderliche Reparaturen durchzuführen.
Da seit Jahren kein Fall unerwartet abgestürzter Tabellen aufgetreten ist (also Tabellen, die aus anderen Gründen als Problemen mit der Hardware beschädigt wurden), betrachten wir die wöchentliche Überprüfung als ausreichend.
Wir empfehlen, myisamchk -s anfangs in jeder Nacht für alle Tabellen auszuführen, die während der jeweils letzten 24 Stunden aktualisiert wurden, bis Sie MySQL so weit trauen, wie wir es tun.
Normalerweise erfordern MySQL-Tabellen recht wenig Pflege. Wenn Sie MyISAM
-Tabellen mit Datensätzen dynamischer Größe (also Tabellen mit VARCHAR
-, BLOB
- oder TEXT
-Spalten) oder Tabellen mit vielen gelöschten Datensätzen haben, dann sollten Sie diese Tabellen von Zeit zu Zeit defragmentieren, d. h. den unbenutzten Speicher wieder zur Benutzung freigeben. Dies können Sie tun, indem Sie die fraglichen Tabellen mit einer OPTIMIZE TABLE
-Anweisung verarbeiten. Alternativ können Sie, wenn Sie den mysqld-Server eine Zeitlang anhalten können, in das Datenverzeichnis wechseln und den folgenden Befehl bei angehaltenem Server ausführen:
shell> myisamchk -r -s --sort-index --sort_buffer_size=16M */*.MYI
Dieser Abschnitt beschreibt, wie Sie den Server für die Verwendung anderer Zeichensätze konfigurieren. Ferner werden wir erläutern, wie Sie die Zeitzone des Servers einstellen und die Unterstützung verbindungsspezifischer Zeitzonen aktivieren.
Standardmäßig verwendet MySQL den Zeichensatz latin1
(cp1252 West European) und die Sortierung latin1_swedish_ci
, die gemäß den in Schweden und Finnland gültigen Regeln sortiert. Diese Standardeinstellungen sind für die Vereinigten Staaten und die meisten Länder Westeuropas angemessen.
Alle MySQL-Binärdistributionen werden mit der Option --with-extra-charsets=complex
kompiliert. Hierdurch wird allen Standardprogrammen ein Code hinzugefügt, der es ihnen gestattet, latin1
und alle Multibyte-Zeichensätze in der Binärdatei zu verarbeiten. Andere Zeichensätze werden bei Bedarf aus einer Zeichensatzdefinitionsdatei geladen.
Der Zeichensatz bestimmt, welche Zeichen in Bezeichnern zulässig sind. Die Sortierung hingegen definiert die Art und Weise, wie Strings von den Klauseln ORDER BY
und GROUP BY
der SELECT
-Anweisung sortiert werden.
Sie können den Standardzeichensatz und die Standardsortierung auf dem Server mit den Optionen --character-set-server
bzw. --collation-server
beim Serverstart ändern. Die Sortierung muss für den gewählten Standardzeichensatz zulässig sein. (Mit der Anweisung SHOW COLLATION
können Sie die für den jeweiligen Zeichensatz zulässige Sortierung ermitteln.) Siehe auch Abschnitt 5.2.1, „Befehlsoptionen für mysqld“.
Welche Zeichensätze verfügbar sind, hängt von den Optionen --with-charset=
und charset_name
--with-extra-charsets=
des Befehls configure sowie von den in list-of-charsets
| complex | all | none
gelisteten Zeichensatz-Konfigurationsdateien ab. Siehe auch Abschnitt 2.8.2, „Typische configure-Optionen“.
SHAREDIR
/charsets/Index
Wenn Sie den Zeichensatz während der Ausführung von MySQL ändern, kann sich dies auch auf die Sortierreihenfolge auswirken. Das bedeutet, dass Sie myisamchk -r -q --set-collation=collation_name
für alle Tabellen ausführen müssen, da andernfalls Ihre Indizes nicht korrekt sortiert sind.
Wenn ein Client eine Verbindung mit einem MySQL-Server herstellt, gibt der Server dem Client seinen Standardzeichensatz an. Der Client schaltet dann für diese Verbindung auf den betreffenden Zeichensatz um.
Sie sollten mysql_real_escape_string()
verwenden, wenn Sie Strings für eine SQL-Abfrage kennzeichnen. mysql_real_escape_string()
ist identisch mit der alten Funktion mysql_escape_string()
, nur nimmt es den MYSQL
-Verbindungs-Handle als ersten Parameter entgegen, sodass der korrekte Zeichensatz bei der Kennzeichnung von Zeichen berücksichtigt werden kann.
Wird der Client mit anderen als den Pfaden kompiliert, unter denen der Server installiert ist, und hat der Benutzer, der MySQL konfiguriert hat, nicht alle Zeichensätze in die MySQL-Binärdatei eingefügt, dann müssen Sie dem Client angeben, wo er die zusätzlichen Zeichensätze finden kann, die er braucht, wenn der Server mit einem anderen Zeichensatz ausgeführt wird als der Client.
Dies können Sie durch Angabe der Option --character-sets-dir
tun, die den Pfad zu dem Verzeichnis angibt, in dem die dynamischen MySQL-Zeichensätze gespeichert sind. Sie können beispielsweise in einer Optionsdatei folgende Angaben machen:
[client] character-sets-dir=/usr/local/mysql/share/mysql/charsets
Die Verwendung eines bestimmten Zeichensatzes durch den Client erzwingen Sie wie folgt:
[client]
default-character-set=charset_name
Allerdings ist dies normalerweise nicht erforderlich.
In MySQL 5.1 werden Zeichensatz und Sortierung normalerweise getrennt angegeben. Wenn Sie also die deutsche Sortierreihenfolge verwenden wollen, sollten Sie den Zeichensatz latin1
und die Sortierung latin1_german1_ci
oder latin1_german2_ci
auswählen. Um den Server beispielsweise mit der Sortierung latin1_german1_ci
zu starten, verwenden Sie die Optionen --character-set-server=latin1
und --collation-server=latin1_german1_ci
.
Informationen zu den Unterschieden zwischen diesen beiden Sortierungen finden Sie in Abschnitt 10.9.2, „Westeuropäische Zeichensätze“.
Standardmäßig erzeugt mysqld seine Fehlermeldungen auf Englisch, die Anzeige kann aber auch in den folgenden Sprachen erfolgen: Dänisch, Deutsch, Estnisch, Französisch, Griechisch, Italienisch, Japanisch, Koreanisch, Niederländisch, Norwegisch und Neunorwegisch, Polnisch, Portugiesisch, Rumänisch, Russisch, Schwedisch, Slowakisch, Spanisch, Tschechisch und Ungarisch.
Um in mysqld Fehlermeldungen in einer bestimmten Sprache zu erhalten, starten Sie den Server mit der Option --language
bzw. -L
. Der Optionswert kann entweder ein Sprachenname oder der vollständige Pfad zu einer Fehlermeldungsdatei sein. Zum Beispiel:
shell> mysqld --language=swedish
Oder:
shell> mysqld --language=/usr/local/share/swedish
Der Sprachname sollte in Kleinbuchstaben angegeben werden.
Standardmäßig befinden sich die Sprachdateien im Unterverzeichnis share/
des MySQL-Basisverzeichnisses.
LANGUAGE
Sie können den Inhalt der vom Server erzeugten Fehlermeldungen auch ändern. Details hierzu finden Sie im Handbuch MySQL Internals unter http://dev.mysql.com/doc/. Wenn Sie Änderungen an den Fehlermeldungen vorgenommen haben und dann auf eine neuere Version von MySQL aktualisieren, müssen Sie diese Änderungen nach dem Upgrade erneut eintragen.
In diesem Abschnitt beschreiben wir den Vorgang des Hinzufügens eines neuen Zeichensatzes zu MySQL. Für die folgende Anleitung benötigen Sie eine MySQL-Quelldistribution. Um die korrekte Vorgehensweise zu bestimmen, ermitteln Sie zunächst, ob der gewünschte Zeichensatz einfach oder komplex ist:
Benötigt der Zeichensatz keine speziellen Routinen für die String-Sortierung und keine Multibyteunterstützung, dann handelt es sich um einen einfachen Zeichensatz.
Benötigt der Zeichensatz eine dieser Funktionen, dann ist er komplex.
Beispielsweise sind latin1
und danish
einfache Zeichensätze, big5
und czech
hingegen sind komplexe Zeichensätze.
In der folgenden Anleitung wird der Name des Zeichensatzes als MYSET
angegeben.
Bei einem einfachen Zeichensatz verfahren Sie wie folgt:
Fügen Sie MYSET
am Ende der Datei sql/share/charsets/Index
ein. Weisen Sie ihm eine eindeutige Nummer zu.
Erstellen Sie die Datei sql/share/charsets/
. (Sie können eine Kopie von MYSET
.confsql/share/charsets/latin1.conf
als Basis für diese Datei verwenden.)
Die Syntax für diese Datei ist sehr einfach:
Kommentare beginnen mit dem Rautenzeichen ‘#
’ und erstrecken sich bis zum Ende der Zeile.
Wörter werden durch eine beliebige Anzahl von Whitespace-Zeichen voneinander getrennt.
Bei der Definition des Zeichensatzes muss jedes Wort eine Zahl im Hexadezimalformat sein.
Das Array ctype
enthält die ersten 257 Wörter. Die Arrays to_lower[]
, to_upper[]
und sort_order[]
nehmen nachfolgend je 256 Wörter entgegen.
Siehe auch Abschnitt 5.11.4, „Die Zeichendefinitionsarrays“.
Fügen Sie den Namen des Zeichensatzes zu den Listen CHARSETS_AVAILABLE
und COMPILED_CHARSETS
in der Datei configure.in
hinzu.
Führen Sie Konfiguration und Kompilierung aus und testen Sie die Distribution.
Bei einem komplexen Zeichensatz verfahren Sie wie folgt:
Erstellen Sie die Datei strings/ctype-
in der MySQL-Quelldistribution.
MYSET
.c
Fügen Sie MYSET
am Ende der Datei sql/share/charsets/Index
ein. Weisen Sie ihm eine eindeutige Nummer zu.
Suchen Sie nach vorhandenen ctype-*.c
-Dateien (z. B. strings/ctype-big5.c
), um den Definitionsbedarf zu ermitteln Beachten Sie, dass die Arrays in Ihrer Datei Namen wie ctype_
, MYSET
to_lower_
usw. aufweisen müssen. Diese entsprechen den Arrays eines einfachen Zeichensatzes. Siehe auch Abschnitt 5.11.4, „Die Zeichendefinitionsarrays“.
MYSET
Fügen Sie weit oben in der Datei einen speziellen Kommentar wie den folgenden ein:
/* * This comment is parsed by configure to create ctype.c, * so don't change it unless you know what you are doing. * * .configure. number_MYSET
=MYNUMBER
* .configure. strxfrm_multiply_MYSET
=N
* .configure. mbmaxlen_MYSET
=N
*/
Das Programm configure verwendet diesen Kommentar, um den Zeichensatz automatisch in die MySQL-Bibliothek einzufügen.
Die Zeilen strxfrm_multiply
und mbmaxlen
werden in den folgenden Abschnitten erläutert. Sie müssen sie nur einfügen, wenn Sie die Funktionen für die String-Sortierung bzw. für Multibytezeichensätze benötigen.
Danach sollten Sie einige der folgenden Funktionen erstellen:
my_strncoll_
MYSET
()
my_strcoll_
MYSET
()
my_strxfrm_
MYSET
()
my_like_range_
MYSET
()
Siehe auch Abschnitt 5.11.5, „Unterstützung für String-Vergleiche“.
Fügen Sie den Namen des Zeichensatzes zu den Listen CHARSETS_AVAILABLE
und COMPILED_CHARSETS
in der Datei configure.in
hinzu.
Führen Sie Konfiguration und Kompilierung aus und testen Sie die Distribution.
Die Datei sql/share/charsets/README
enthält weitere Anweisungen.
Wenn der Zeichensatz in die MySQL-Distribution eingefügt werden soll, schicken Sie einen Patch an die MySQL-Mailingliste internals
. Siehe auch Abschnitt 1.7.1, „Die MySQL-Mailinglisten“.
to_lower[]
und to_upper[]
sind einfache Arrays, die die Klein- bzw. Großbuchstaben enthalten, die den einzelnen Mitgliedszeichen des Zeichensatzes entsprechen. Zum Beispiel:
to_lower['A'] should contain 'a' to_upper['a'] should contain 'A'
sort_order[]
bildet die Art und Weise ab, wie Zeichen zu Vergleichs- und Sortierzwecken anzuordnen sind. Recht häufig – aber nicht immer – ist dies identisch mit to_upper[]
, was bedeutet, dass bei der Sortierung die Groß-/Kleinschreibung unterschieden wird. MySQL sortiert Zeichen basierend auf den Werten von sort_order[]
-Elementen. Informationen zu komplexeren Sortierregeln entnehmen Sie der Beschreibung der String-Sortierung in Abschnitt 5.11.5, „Unterstützung für String-Vergleiche“.
ctype[]
ist ein Array mit Bitwerten, wobei jeweils ein Element für ein Zeichen vorhanden ist. (Beachten Sie, dass to_lower[]
, to_upper[]
und sort_order[]
über den Zeichenwert indiziert werden, ctype[]
hingegen über den Zeichenwert + 1. Dies ist eine Altkonvention zur Verarbeitung von EOF
.)
In m_ctype.h
finden Sie die folgenden Bitmaskendefinitionen:
#define _U 01 /* Uppercase */ #define _L 02 /* Lowercase */ #define _N 04 /* Numeral (digit) */ #define _S 010 /* Spacing character */ #define _P 020 /* Punctuation */ #define _C 040 /* Control character */ #define _B 0100 /* Blank */ #define _X 0200 /* heXadecimal digit */
Der Eintrag ctype[]
eines Zeichens sollte die Union der anwendbaren Bitmaskenwerte sein, die das Zeichen beschreiben. Beispielsweise ist 'A'
sowohl ein Großbuchstabe (_U
) als auch eine Hexadezimalziffer (_X
), d. h. ctype['A'+1]
sollte folgenden Wert enthalten:
_U + _X = 01 + 0200 = 0201
Wenn die Sortierregeln Ihrer Sprache zu komplex sind, um mit der einfachen sort_order[]
-Tabelle verarbeitet zu werden, dann müssen Sie die String-Sortierfunktionen verwenden.
Die beste Dokumentation hierfür sind die vorhandenen Zeichensätze. Sehen Sie sich beispielsweise die Zeichensätze big5
, czech
, gbk
, sjis
und tis160
einmal an.
Sie müssen den Wert strxfrm_multiply_
in dem speziellen Kommentar oben in der Datei angeben. MYSET
=N
N
sollte dabei auf das maximale Verhältnis gesetzt werden, auf das die Strings bei my_strxfrm_
anwachsen dürfen (es muss sich dabei um einen positiven Integer handeln).
MYSET
Wenn Sie Unterstützung für einen neuen Zeichensatz hinzufügen wollen, der Multibytezeichen enthält, dann müssen Sie die Multibytezeichenfunktionen verwenden.
Die beste Dokumentation hierfür sind die vorhandenen Zeichensätze. Sehen Sie sich beispielsweise die Zeichensätze euc_kr
, gb2312
, gbk
, sjis
und ujis
einmal an. Diese sind in den ctype-
-Dateien im Verzeichnis charset_name
.cstrings
implementiert.
Sie müssen den Wert mbmaxlen_
in dem speziellen Kommentar oben in der Quelldatei angeben. MYSET
=N
N
sollte auf die Größe (in Byte) des größten Zeichens im Zeichensatz gesetzt werden.
Wenn Sie einen Zeichensatz verwenden wollen, der nicht in Ihre Binärdatei einkompiliert ist, können die folgenden Probleme auftreten:
Ihr Programm verwendet einen falschen Pfad für die Speicherposition der Zeichensätze (Vorgabe ist /usr/local/mysql/share/mysql/charsets
). Dies kann mit der Option --character-sets-dir
behoben werden, wenn Sie das fragliche Programm ausführen.
Der Zeichensatz ist ein Multibytezeichensatz, der nicht dynamisch geladen werden kann. In diesem Fall müssen Sie das Programm mit Unterstützung für den Zeichensatz neu kompilieren.
Der Zeichensatz ist ein dynamischer Zeichensatz, aber Sie haben keine Konfigurationsdatei für ihn. In diesem Fall sollten Sie die Konfigurationsdatei für den Zeichensatz aus einer neuen MySQL-Distribution installieren.
Wenn Ihre Datei Index
den Namen für diesen Zeichensatz nicht enthält, zeigt Ihr Programm die folgende Fehlermeldung an:
ERROR 1105: File '/usr/local/share/mysql/charsets/?.conf' not found (Errcode: 2)
In diesem Fall sollten Sie sich entweder eine neue Datei Index
beschaffen oder die Namen fehlender Zeichensätze manuell in die aktuelle Datei eintragen.
Bei MyISAM
-Tabellen können Sie Name und Nummer des Zeichensatzes für eine Tabelle mit myisamchk -dvv tbl_name
überprüfen.
Beim MySQL-Server gibt es mehrere verschiedene Zeitzoneneinstellungen:
Die Systemzeitzone. Wenn der Server startet, versucht er die Zeitzone des Hostcomputers zu ermitteln und weist diesen Wert dann der Systemvariable system_time_zone
zu. Der Wert wird nachfolgend nicht mehr geändert.
Die aktuelle Zeitzone des Servers. Die globale Systemvariable time_zone
gibt die Zeitzone an, in der der Server derzeit läuft. Der Startwert für time_zone
ist 'SYSTEM'
, d. h. die Serverzeitzone ist mit der Systemzeitzone identisch. Der Ausgangswert lässt sich mit der Option --default-time-zone=
auch ausdrücklich festlegen. Wenn Sie die Berechtigung timezone
SUPER
haben, können Sie den globalen Wert mit folgender Anweisung zur Laufzeit ändern:
mysql> SET GLOBAL time_zone = timezone
;
Verbindungsspezifische Zeitzonen. Jeder Client, der eine Verbindung herstellt, hat eine eigene Zeitzoneneinstellung, die von der Sitzungsvariablen time_zone
vorgegeben wird. Standardmäßig erhält die Sitzungsvariable den Wert von der globalen Variable time_zone
, der Client kann seine Zeitzone aber mit folgender Anweisung ändern:
mysql> SET time_zone = timezone
;
Die aktuellen Werte der globalen und der clientspezifischen Zeitzone lassen sich wie folgt abrufen:
mysql> SELECT @@global.time_zone, @@session.time_zone;
timezone
-Werte können als Strings angegeben werden, die einen Offset zur UTC angeben (z. B. '+10:00'
oder '-6:00'
). Wenn die Zeitzonen-Informationstabellen in der mysql
-Datenbank erstellt und ausgefüllt wurden, können Sie auch benannte Zeitzonen wie etwa 'Europe/Helsinki'
, 'US/Eastern'
oder 'MET'
verwenden. Mit dem Wert 'SYSTEM'
kann angegeben werden, dass die Zeitzone denselben Wert haben sollte wie die Systemzeitzone. Bei den Zeitzonennamen wird die Groß-/Kleinschreibung nicht unterschieden.
Der MySQL-Installationsvorgang erzeugt Zeitzonentabellen in der mysql
-Datenbank, lädt diese aber nicht. Dies müssen Sie manuell tun. (Wenn Sie von einer früheren Version auf MySQL 4.1.3 oder höher aktualisieren, sollten Sie die Tabellen erstellen, indem Sie ein Upgrade Ihrer mysql
-Datenbank durchführen. Verwenden Sie hierzu die Anleitung in Abschnitt 5.6, „mysql_fix_privilege_tables — Upgrade von MySQL-Systemtabellen“.)
Wenn Ihr System eine eigene zoneinfo-Datenbank hat (dies ist ein Satz von Dateien, die die Zeitzonen beschreiben), dann sollten Sie das Programm mysql_tzinfo_to_sql zum Ausfüllen der Zeitzonentabellen verwenden. Beispiele für solche Systeme sind Linux, FreeBSD, Sun Solaris und Mac OS X. Eine wahrscheinliche Position für diese Dateien ist das Verzeichnis /usr/share/zoneinfo
. Verfügt Ihr System nicht über eine zoneinfo-Datenbank, dann können Sie das im weiteren Verlauf dieses Abschnitts genannte Paket herunterladen und verwenden.
Das Programm mysql_tzinfo_to_sql wird zum Laden der Zeitzonentabellen verwendet. Auf der Befehlszeile übergeben Sie den Pfadnamen des zoneinfo-Verzeichnisses an mysql_tzinfo_to_sql und leiten die Ausgabe in das Programm mysql. Zum Beispiel:
shell> mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql
mysql_tzinfo_to_sql liest die Zeitzonendateien Ihres Systems aus und erzeugt daraus SQL-Anweisungen. mysql verarbeitet diese Anweisungen, um die Zeitzonentabellen zu laden.
mysql_tzinfo_to_sql kann auch zum Laden einer einzelnen Zeitzonendatei und zur Erzeugung von Schaltsekunden verwendet werden:
Um eine einzelne Zeitzonendatei tz_file
zu laden, die einem Zeitzonennamen tz_name
entspricht, rufen Sie mysql_tzinfo_to_sql wie folgt auf:
shell> mysql_tzinfo_to_sql tz_file
tz_name
| mysql -u root mysql
Wenn Ihre Zeitzone Schaltsekunden berücksichtigen muss, initialisieren Sie die Schaltsekundeninformation wie folgt (hierbei ist tz_file
der Name der Zeitzonendatei):
shell> mysql_tzinfo_to_sql --leap tz_file
| mysql -u root mysql
Verfügt Ihr System über keine zoneinfo-Datenbank (dies gilt beispielsweise für Windows oder HP-UX), dann können Sie das Paket mit den vorerstellten Zeitzonentabellen verwenden, welches unter http://dev.mysql.com/downloads/timezones.html heruntergeladen werden kann. Dieses Paket enthält .frm
-, .MYD
- und .MYI
-Dateien für die MyISAM
-Zeitzonentabellen. Diese Tabellen sollten Teil der mysql
-Datenbank sein, d. h. Sie sollten Sie Dateien im Unterverzeichnis mysql
des Datenverzeichnisses Ihres MySQL-Servers ablegen. Währenddessen sollte der Server beendet sein.
Warnung: Verwenden Sie das herunterzuladende Paket nicht, wenn Ihr System über eine zoneinfo-Datenbank verfügt. Benutzen Sie stattdessen das Hilfsprogramm mysql_tzinfo_to_sql. Andernfalls kann es zu Diskrepanzen in der Verarbeitung von Datum und Uhrzeit zwischen MySQL und anderen Anwendungen auf Ihrem System kommen.
Informationen zu Zeitzoneneinstellungen in der Replikationskonfiguration finden Sie in Abschnitt 6.8, „Replikation: Features und bekannte Probleme“.
MySQL schreibt mehrere verschiedene Logdateien, mit deren Hilfe Sie ermitteln können, was in mysqld abläuft:
Logdatei | Geloggte Informationen |
Fehlerlog | Probleme beim Starten, Ausführen oder Beenden von mysqld |
Abfragelog | hergestellte Clientverbindungen, ausgeführte Anweisungen |
Binärlog | alle datenändernden Anweisungen (wird auch zur Replikation verwendet) |
Logdatei für langsame Abfragen | Abfragen, die länger als in long_query_time (in Sekunden) angegeben zur Ausführung benötigen oder keine Indizes verwendet haben |
Standardmäßig werden alle Logdateien im Datenverzeichnis mysqld erstellt. Sie können das Schließen und Neuöffnen der Logdateien (in manchen Fällen auch das Wechseln zu einer neuen Logdatei) erzwingen, indem Sie die Logdateien auf die Festplatte schreiben. Das Schreiben der Logdateien auf Festplatte erfolgt, wenn Sie eine FLUSH LOGS
-Anweisung absetzen oder mysqladmin flush-logs oder mysqladmin refresh ausführen. Siehe auch Abschnitt 13.5.5.2, „FLUSH
“.
Wenn Sie die Replikationsfunktionen von MySQL verwenden, erstellen die Slave-Replikationsserver weitere Logdateien, die Relay-Logs heißen. Diese werden in Kapitel 6, Replikation bei MySQL, beschrieben.
Die Fehlerlogdatei enthält Informationen, die angeben, wann mysqld gestartet und beendet wurde und welche kritischen Fehler während der Laufzeit des Servers ggf. aufgetreten sind. Wenn mysqld feststellt, dass eine Tabelle automatisch überprüft oder repariert werden muss, dann schreibt es eine Meldung in das Fehlerlog.
Bei einigen Betriebssystemen enthält das Fehlerlog einen Stapel-Trace, wenn mysqld abstürzt. Mit dem Trace kann bestimmt werden, wo mysqld abgestürzt ist. Siehe auch Abschnitt E.1.4, „Einen Stack-Trace benutzen“.
Wenn mysqld unerwartet abstürzt und mysqld_safe den Server neu starten muss, schreibt mysqld_safe die Meldung restarted mysqld
in das Fehlerlog.
Mit der Option --log-error[=
können Sie angeben, wo mysqld das Fehlerlog speichern soll. Wird für file_name
]file_name
kein Wert angegeben, dann verwendet mysqld den Namen
und schreibt die Datei in das Datenverzeichnis. Wenn Sie host_name
.errFLUSH LOGS
ausführen, wird das Fehlerlog durch Ergänzung des Suffixes -old
umbenannt, und mysqld erzeugt eine neue leere Logdatei. (Wenn die Option --log-error
nicht angegeben wird, erfolgt keine Umbenennung.)
Wenn Sie --log-error
nicht angeben oder (unter Windows) die Option --console
verwenden, werden Fehler in stderr
(Standardfehlerausgabe) geschrieben. Normalerweise ist dies Ihr Terminal.
Unter Windows wird die Fehlerausgabe in die .err
-Datei geschrieben, sofern --console
nicht angegeben ist.
Wenn Sie wissen wollen, was bei mysqld intern vor sich geht, sollten Sie es mit der Option --log[=
oder file_name
]-l [
starten. Wird keine Wert file_name
]file_name
angegeben, dann lautet der Vorgabename
. Aufgezeichnet werden alle Verbindungen und Anweisungen. Dieses Log kann sehr praktisch sein, wenn Sie einen Fehler bei einem Client vermuten und genau wissen wollen, was dieser Client an mysqld gesendet hat.
host_name
.log
mysqld schreibt die Anweisungen in der Reihenfolge in das Abfragelog, in der sie empfangen werden. Diese Reihenfolge kann sich von der Ausführungsreihenfolge unterscheiden. Dies steht im Gegensatz zum Binärlog, bei dem Anweisungen nach ihrer Ausführung, aber vor dem Aufheben von Sperren geschrieben werden. (Außerdem enthält das Abfragelog alle Anweisungen, wogegen das Binärlog keine Anweisungen enthält, die nur Daten auswählen.)
Bei Serverneustarts und beim Schreiben des Logs auf Festplatte wird keine neue allgemeine Abfragelogdatei erstellt (auch wenn sie beim Schreiben auf Festplatte geschlossen und neu geöffnet wird). Unter Unix können Sie die Datei mit den folgenden Befehlen umbenennen und eine neue Datei erstellen:
shell>mv
shell>host_name
.loghost_name
-old.logmysqladmin flush-logs
shell>cp
shell>host_name
-old.logbackup-directory
rm
host_name
-old.log
Unter Windows können Sie die Logdatei nicht umbenennen, solange sie vom Server geöffnet ist. Sie müssen zunächst den Server beenden, die Datei umbenennen und den Server dann neu starten, um eine neue Logdatei zu erstellen.
Das Binärlog enthält alle Anweisungen, die Daten aktualisieren oder hätten aktualisieren können (beispielsweise eine DELETE
-Anweisung ohne zutreffenden Datensatz). Die Anweisungen werden in Form von „Ereignissen“ gespeichert, die die Änderungen beschreiben. Ferner enthält das Binärlog auch Informationen dazu, wie lange die Ausführung datenverändernder Anweisungen jeweils gedauert hat.
Hinweis: Das Binärlog hat beginnend mit MySQL 5.0 das alte Update-Log ersetzt, welches nun nicht mehr vorhanden ist. Das Binärlog enthält alle Informationen, die bereits im Update-Log vorhanden waren, in einem effizienteren Format und ist zudem transaktionssicher. Wenn Sie Transaktionen verwenden, müssen Sie für Backups das MySQL-Binärlog statt des alten Update-Logs verwenden.
Das Binärlog enthält keine Anweisungen, die keine Daten ändern. Wenn Sie alle Anweisungen aufzeichnen wollen (um etwa eine problematische Abfrage zu ermitteln), dann verwenden Sie das allgemeine Abfragelog. Siehe auch Abschnitt 5.12.2, „Die allgemeine Anfragen-Logdatei“.
Der primäre Zweck des Binärlogs besteht darin, eine möglichst vollständige Aktualisierung von Datenbanken im Zuge eines Wiederherstellungsvorgangs zu ermöglichen, denn das Binärlog enthält alle Updates, die nach Erstellung einer Sicherung erfolgten. Außerdem wird das Binärlog auf Master-Replikationsservern zur Aufzeichnung von Anweisungen verwendet, die an Slave-Server gesendet werden. Siehe auch Kapitel 6, Replikation bei MySQL.
Die Ausführung des Servers mit aktiviertem Binärlog verringert die Leistungsfähigkeit um ca. 1 Prozent. Die vom Binärlog in Zusammenhang mit der Datenwiederherstellung und der Replikationskonfiguration gebotenen Vorteile machen diese vernachlässigbare Leistungseinbuße jedoch mehr als wett.
Wenn mysqld mit der Option --log-bin[=
gestartet wird, schreibt es eine Logdatei mit allen SQL-Befehlen, die Daten aktualisieren. Wird kein base_name
]base_name
-Wert angegeben, dann wird als Name der Datei standardmäßig der Name des Hostcomputers gefolgt von -bin
gewählt. Wenn der Basisname angegeben wird, jedoch nicht als absoluter Pfadname, dann schreibt der Server die Datei in das Datenverzeichnis. Die Angabe eines Basisnamens wird empfohlen (siehe Abschnitt A.8.1, „Offene Probleme in MySQL“ zu den Gründen).
Wenn Sie eine Erweiterung im Lognamen angeben (z. B. --log-bin=
), dann wird diese stillschweigend entfernt und ignoriert.
base_name.extension
mysqld hängt eine numerische Erweiterung an den Basisnamen des Binärlogs an. Diese Zahl wird jedes Mal erhöht, wenn der Server eine neue Logdatei erstellt. Hierdurch entsteht eine geordnete Abfolge von Dateien. Der Server erstellt bei jedem Neustart und beim Schreiben der Logs jedes Mal eine neue Logdatei. Ferner wird ein neues Binärlog automatisch erstellt, wenn die Größe der aktuellen Logdatei den Wert max_binlog_size
erreicht. Ein Binärlog kann, wenn Sie große Transaktionen verwenden, unter Umständen auch größer werden als durch max_binlog_size
angegeben. Das liegt daran, dass eine Transaktion vollständig in eine Datei geschrieben und niemals auf mehrere Dateien verteilt wird.
Um im Überblick zu behalten, welche Binärlogdateien bereits verwendet wurden, erstellt mysqld außerdem eine Indexdatei, die die Namen aller verwendeten Binärlogdateien enthält. Standardmäßig hat diese denselben Basisnamen wie die Binärlogdatei zuzüglich der Erweiterung '.index'
. Sie können den Namen der Indexdatei für Binärlogs mit der Option --log-bin-index[=
ändern. Solange mysqld ausgeführt wird, sollten Sie diese Datei nicht manuell bearbeiten, da dies mysqld durcheinander bringen könnte.
file_name
]
Schreibvorgänge in die Binärlogdatei und die Indexdatei für Binärlogs werden auf identische Weise verarbeitet, nämlich als Schreiboperationen in MyISAM
-Tabellen. Siehe auch Abschnitt A.4.3, „Wie MySQL mit vollen Festplatten umgeht“.
Mit der Anweisung RESET MASTER
können Sie alle Binärlogdateien löschen, mit der Anweisung PURGE MASTER LOGS
einen Teil davon. Siehe auch Abschnitt 13.5.5.5, „RESET
“, und Abschnitt 13.6.1, „SQL-Anweisungen für die Steuerung von Master-Servern“.
Das Binärlogformat hat einige bekannte Beschränkungen, die sich auf die Wiederherstellung aus Backups auswirken können. Siehe auch Abschnitt 6.8, „Replikation: Features und bekannte Probleme“.
Das binäre Loggen für gespeicherte Routinen und Trigger erfolgt wie in Abschnitt 19.4, „Binärloggen gespeicherter Routinen und Trigger“, beschrieben.
Sie können die folgenden Optionen für mysqld verwenden, um zu beeinflussen, was in der Binärlogdatei aufgezeichnet wird. Beachten Sie auch die auf die Liste folgenden Erläuterungen.
Wenn Sie die Replikation verwenden, beeinflussen die hier beschriebenen Optionen, welche Anweisungen vom Master-Server an die Slaves gesendet werden. Es gibt auch Optionen für Slave-Server, mit denen gesteuert wird, welche vom Master empfangenen Anweisungen ausgeführt und welche ignoriert werden. Detaillierte Informationen finden Sie in Abschnitt 6.9, „Replikationsoptionen in my.cnf“.
--binlog-do-db=
db_name
Weist den Server an, das binäre Loggen auf Updates zu beschränken, für die die Standarddatenbank db_name
heißt (d. h. die mit USE
gewählte Datenbank). Alle anderen nicht ausdrücklich erwähnten Datenbanken werden ignoriert. Wenn Sie diese Option verwenden, sollten Sie sicherstellen, dass Sie Aktualisierungen nur in der Standarddatenbank durchführen.
Hierzu gibt es eine Ausnahme für die Anweisungen CREATE DATABASE
, ALTER DATABASE
und DROP DATABASE
. Der Server entscheidet auf der Basis der in der Anweisung genannten Datenbank (nicht der Standarddatenbank), ob die Anweisungen protokolliert werden sollen oder nicht.
Hier ein Beispiel für etwas, das nicht so funktioniert, wie Sie es vielleicht erwarten: Wenn der Server mit binlog-do-db=sales
gestartet wird und Sie USE prices; UPDATE sales.january SET amount=amount+1000;
ausführen, wird diese Anweisung nicht in das Binärlog geschrieben.
Um mehrere Datenbanken zu loggen, verwenden Sie mehrere Optionen, wobei die Option einmal für jede Datenbank angegeben werden muss.
--binlog-ignore-db=
db_name
Weist den Server an, das binäre Loggen von Updates zu unterdrücken, für die die Standarddatenbank db_name
heißt (d. h. die mit USE
gewählte Datenbank). Wenn Sie diese Option verwenden, sollten Sie sicherstellen, dass Sie Aktualisierungen nur in der Standarddatenbank durchführen.
Wie bei der Option --binlog-do-db
gibt es auch hier eine Ausnahme für die Anweisungen CREATE DATABASE
, ALTER DATABASE
und DROP DATABASE
. Der Server entscheidet auf der Basis der in der Anweisung genannten Datenbank (nicht der Standarddatenbank), ob die Anweisungen protokolliert werden sollen oder nicht.
Hier ein Beispiel für etwas, das nicht so funktioniert, wie Sie es vielleicht erwarten: Wenn der Server mit binlog-ignore-db=sales
gestartet wird und Sie USE prices; UPDATE sales.january SET amount=amount+1000;
ausführen, wird diese Anweisung in das Binärlog geschrieben.
Um mehrere Datenbanken zu ignorieren, verwenden Sie mehrere Optionen, wobei die Option einmal für jede Datenbank angegeben werden muss.
Der Server wertet die Optionen zum Loggen von Updates im Binärlog oder zum Ignorieren der Updates entsprechend den folgenden Regeln aus. Wie bereits erwähnt, gibt es eine Ausnahme für die Anweisungen CREATE DATABASE
, ALTER DATABASE
und DROP DATABASE
. In solchen Fällen ersetzt die Datenbank, die erstellt, geändert oder gelöscht wird, in den folgenden Regeln die Standarddatenbank.
Sind --binlog-do-db
- oder --binlog-ignore-db
-Regeln vorhanden?
Nein: Anweisung in Binärlog schreiben und beenden.
Ja: Mit nächstem Schritt fortfahren.
Es sind Regeln vorhanden (--binlog-do-db
, --binlog-ignore-db
oder beide). Gibt es eine Standarddatenbank (d. h. wurde eine Datenbank mit USE
ausgewählt)?
Nein: Anweisung nicht schreiben, sondern beenden.
Ja: Mit nächstem Schritt fortfahren.
Es gibt eine Standarddatenbank. Gibt es --binlog-do-db
-Regeln?
Ja: Liegt eine Übereinstimmung der Standarddatenbank mit einer der --binlog-do-db
-Regeln vor?
Ja: Anweisung schreiben und beenden.
Nein: Anweisung nicht schreiben, sondern beenden.
Nein: Mit nächstem Schritt fortfahren.
Es gibt --binlog-ignore-db
-Regeln. Liegt eine Übereinstimmung der Standarddatenbank mit einer der --binlog-ignore-db
-Regeln vor?
Ja: Anweisung nicht schreiben, sondern beenden.
Nein: Abfrage schreiben und beenden.
So schreibt beispielsweise ein Slave, der nur mit --binlog-do-db=sales
ausgeführt wird, keine Anweisungen in das Binärlog, bei der sich die Standarddatenbank von sales
unterscheidet (anders gesagt kann --binlog-do-db
auch manchmal „andere Datenbanken ignorieren“ bedeuten).
Wenn Sie die Replikation verwenden, sollten Sie alte Binärlogdateien erst dann löschen, wenn Sie ganz sicher sind, dass kein Slave sie mehr benötigt. Laufen Ihre Slaves also etwa nie länger als drei Tage am Stück, dann können Sie einmal täglich mysqladmin flush-logs auf dem Master ausführen und dann alle Logs entfernen, die älter als drei Tage sind. Sie können die Dateien dabei zwar manuell entfernen, aber die Verwendung von PURGE MASTER LOGS
ist vorzuziehen, weil diese Anweisung gleichzeitig auch die Indexdatei für die Binärlogs sicher aktualisiert (und weil sie auch ein Datumsargument entgegennehmen kann). Siehe auch Abschnitt 13.6.1, „SQL-Anweisungen für die Steuerung von Master-Servern“.
Ein Client, der die Berechtigung SUPER
hat, kann das binäre Loggen seiner eigenen Anweisungen mithilfe einer SET SQL_LOG_BIN=0
-Anweisung deaktivieren. Siehe auch Abschnitt 13.5.3, „SET
“.
Sie können den Inhalt von Binärlogdateien mit dem Hilfsprogramm mysqlbinlog anzeigen. Die kann praktisch sein, wenn Sie die Anweisungen im Log neu verarbeiten wollen. So können Sie einen MySQL-Server beispielsweise aus dem Binärlog heraus wie folgt aktualisieren:
shell> mysqlbinlog log_file
| mysql -h server_name
Weitere Informationen zum Hilfsprogramm mysqlbinlog und seiner Verwendung finden Sie in Abschnitt 8.8, „mysqlbinlog — Hilfsprogramm für die Verarbeitung binärer Logdateien“. mysqlbinlog kann auch mit Relay-Logs verwendet werden, da diese im selben Format wie Binärlogdateien geschrieben sind.
Das binäre Loggen erfolgt unmittelbar nach Abschluss einer Anweisung, aber vor dem Aufheben ggf. vorhandener Sperren und dem Schreiben in die Datenbank. Auf diese Weise ist sichergestellt, dass die Anweisungen in der Reihenfolge ihrer Ausführung geloggt werden.
Aktualisierungen nicht transaktionssicherer Tabellen werden im Binärlog unmittelbar nach ihrer Ausführung gespeichert. Im Verlauf einer noch nicht geschriebenen Transaktion werden alle Änderungen (UPDATE
, DELETE
oder INSERT
), die transaktionssichere Tabellen wie etwa BDB
- oder InnoDB
-Tabellen betreffen, zwischengespeichert, bis vom Server eine COMMIT
-Anweisung empfangen wird. Dann schreibt mysqld die gesamte Transaktion in das Binärlog, bevor die COMMIT
-Anweisung ausgeführt wird. Wenn der Thread, der die Transaktion verarbeitet, startet, reserviert er zur Zwischenspeicherung von Anweisungen einen Puffer der mit binlog_cache_size
angegebenen Größe. Ist eine Anweisung größer, dann öffnet der Thread eine Temporärdatei, um die Transaktion zu speichern. Endet der Thread, dann wird auch die Temporärdatei wieder gelöscht.
Für Modifikationen an nicht transaktionssicheren Tabellen kann kein Rollback durchgeführt werden. Wenn eine Transaktion, für die ein Rollback erfolgt, Änderungen an nicht transaktionssicheren Tabellen enthält, dann wird die gesamte Transaktionen am Ende mit einer ROLLBACK
-Anweisung geloggt, um sicherzustellen, dass die Modifikationen an diesen Tabellen repliziert werden.
Die Statusvariable Binlog_cache_use
zeigt die Anzahl der Transaktionen an, die diesen Puffer (und möglicherweise auch eine Temporärdatei) zur Speicherung von Anweisungen verwendet haben. Die Statusvariable Binlog_cache_disk_use
gibt an, wie viele dieser Transaktionen tatsächlich eine Temporärdatei erstellen mussten. Mithilfe dieser beiden Variablen kann die Größe von binlog_cache_size
optimiert werden: Wählen Sie einen ausreichend hohen Wert, damit die Verwendung von Temporärdateien möglichst vermieden wird.
Die Systemvariable max_binlog_cache_size
kann benutzt werden, um die Gesamtspeicherkapazität zu begrenzen, die zur Zwischenspeicherung einer Transaktion mit mehreren Anweisungen verwendet wird (Standardwert: 4 Gbyte). Ist eine Transaktion größer als dieser Wert, dann schlägt sie fehl, und es wird ein Rollback durchgeführt.
Wenn Sie das Binärlog verwenden, werden nebenläufige in normale Einfügeoperationen für die Anweisungen CREATE ... SELECT
oder INSERT ... SELECT
umgewandelt. Hierdurch wird gewährleistet, dass Sie eine exakte Kopie Ihrer Tabellen neu erstellen können, indem Sie das Log während eines Sicherungsvorgangs anwenden.
Beachten Sie, dass sich das Binärlogformat in MySQL 5.1 von dem in vorherigen MySQL-Versionen unterscheidet. Grund hierfür sind Erweiterungen bei der Replikation. Siehe auch Abschnitt 6.6, „Replikation: Kompatibilität zwischen MySQL-Versionen“.
Standardmäßig wird das Binärlog nicht bei jeder Schreiboperation auf Festplatte synchronisiert. Wenn also das Betriebssystem oder der Computer selbst (d. h. nicht nur der MySQL-Server) abstürzen, dann sind die letzten Änderungen im Binärlog unter Umständen verloren gegangen. Um dies zu verhindern, können Sie mithilfe der Systemvariablen sync_binlog
die Synchronisierung des Binärlogs nach jeder N
-Schreiboperation erzwingen. Siehe auch Abschnitt 5.2.2, „Server-Systemvariablen“. Der sicherste – aber auch langsamste – Wert für sync_binlog
ist 1. Aber auch dann, wenn sync_binlog
auf 1 steht, besteht die Möglichkeit von Inkonsistenzen zwischen dem Tabelleninhalt und dem Inhalt des Binärlogs im Falle eines Absturzes. Wenn Sie beispielsweise InnoDB
-Tabellen benutzen und der MySQL-Server eine COMMIT
-Anweisung verarbeitet, dann schreibt er die gesamte Transaktion in das Binärlog und übergibt sie dann an InnoDB
. Stürzt der Server zwischen diesen beiden Vorgängen ab, dann erfolgt beim Neustart ein Rollback der Transaktion durch InnoDB
; sie ist aber weiterhin im Binärlog vorhanden. Dieses Problem lässt sich mit der Option --innodb-safe-binlog
beheben, die die Konsistenz zwischen InnoDB
-Tabellen und dem Binärlog herstellt. (Hinweis: --innodb-safe-binlog
wird ab MySQL 5.0 nicht mehr benötigt, weil die XA-Transaktionsunterstützung implementiert wurde.)
Damit diese Option ein höheres Maß an Sicherheit gewähren kann, sollte der MySQL-Server auch so konfiguriert werden, dass das Binär- und die InnoDB
-Logs bei jeder Transaktion synchronisiert werden. Die InnoDB
-Logs werden standardmäßig synchronisiert, und das Binärlog kann mit der Option sync_binlog=1
synchronisiert werden. Diese Option bewirkt, dass der MySQL-Server nach einem Absturz und dem beim folgenden Neustart ausgeführten Rollback die betreffenden Transaktionen aus dem Binärlog ausschneidet. Hierdurch ist sichergestellt, dass das Binärlog die exakten Daten der InnoDB
-Tabellen widerspiegelt und der Slave insofern immer synchron zum Master bleibt (d. h. keine Anweisung empfängt, für die ein Rollback durchgeführt wurde).
Beachten Sie, dass die Option --innodb-safe-binlog
auch dann verwendet werden kann, wenn der MySQL-Server andere Speicher-Engines als InnoDB
aktualisiert. Aus dem Binärlog entfernt werden durch die Wiederherstellungsfunktionen von InnoDB
nur Anweisungen und Transaktionen, die InnoDB
-Tabellen betreffen. Wenn der MySQL-Server bei der Wiederherstellung nach einem Absturz feststellt, dass das Binärlog kürzer als erwartet ist, dann fehlt ihm mindestens eine erfolgreich übermittelte InnoDB
-Transaktion. Dies sollte normalerweise nicht passieren, wenn die Synchronisierung gezielt über sync_binlog=1
und das Festplatten-/Dateisystem geregelt wurde (was nicht immer klappt); der Server gibt also die Fehlermeldung The binary log
<name> is shorter than its expected size.
aus. In diesem Fall ist das Binärlog nicht korrekt, und die Replikation sollte mit einem neuen Schnappschuss der Master-Daten neu gestartet werden.
Wenn mysqld mit der Option --log-slow-queries[=
gestartet wird, schreibt es eine Logdatei mit allen SQL-Befehlen, deren Ausführung länger gedauert hat als durch file_name
]long_query_time
(in Sekunden) angegeben. Die Zeit zum Erwirken der ersten Tabellensperren wird dabei nicht als Ausführungszeit berücksichtigt. Der Mindestwert von long_query_time
ist 1.
Wird kein file_name
-Wert angegeben, dann wird als Name der Datei standardmäßig der Name des Hostcomputers gefolgt von -slow.log
gewählt. Wenn ein Dateiname zwar angegeben ist, jedoch nicht als absoluter Pfadname, dann schreibt der Server die Datei in das Datenverzeichnis.
Eine Anweisung wird in das Log für langsame Abfragen geschrieben, nachdem sie abgeschlossen wurde und alle Sperren aufgehoben wurden. Die Reihenfolge, in der die Anweisungen ins Log geschrieben werden, kann sich mithin von der Ausführungsreihenfolge unterscheiden.
Das Log für langsame Abfragen kann zum Ermitteln von Abfragen verwendet werden, deren Ausführung sehr lange dauert und die deswegen für Optimierungen prädestiniert sind. Allerdings kann die Überprüfung dieses Logs eine recht schwierige Aufgabe sein. Um sie zu vereinfachen, können Sie das Log für langsame Abfragen mit dem Befehl mysqldumpslow verarbeiten, um Abfragen zusammenzufassen, die im Log erscheinen.
Bei MySQL 5.1 werden langsame Abfragen, die keine Indizes verwenden, ebenso im Log aufgezeichnet wie solche, die Indizes benutzen. Um zu verhindern, dass Abfragen ohne Indizes in das Log geschrieben werden, verwenden Sie die Option --log-queries-not-using-indexes
. Siehe auch Abschnitt 5.2.1, „Befehlsoptionen für mysqld“.
Bei MySQL 5.1 können Sie mit der Serveroption --log-slow-admin-statements
festlegen, dass langsame administrative Anweisungen wie OPTIMIZE TABLE
, ANALYZE TABLE
und ALTER TABLE
ebenfalls in das Log für langsame Abfragen geschrieben werden.
Abfragen, die vom Abfrage-Cache verarbeitet werden, werden im Log für langsame Abfragen nicht aufgezeichnet. Gleiches gilt für Abfragen, die vom Vorhandensein eines Index nicht profitieren würden, da die Tabellen keinen oder nur einen Datensatz umfasst.
MySQL Server erstellt eine Reihe verschiedener Logdateien, mit denen Sie ganz einfach feststellen können, was vor sich geht. Siehe auch Abschnitt 5.12, „Die MySQL-Logdateien“. Allerdings müssen Sie diese Dateien regelmäßig bereinigen, damit sichergestellt ist, dass die Logs nicht zu viel Festplattenspeicher belegen.
Wenn Sie MySQL mit aktiviertem Loggen verwenden, dann sollten Sie alte Logdateien von Zeit zu Zeit sichern und entfernen und MySQL anweisen, neue Logdateien zu erstellen. Siehe auch Abschnitt 5.10.1, „Datenbank-Datensicherungen“.
Auf einer Linux-Installation (Red Hat) können Sie hierfür das Skript mysql-log-rotate
verwenden. Wenn Sie MySQL aus einer RPM-Distribution installiert haben, sollte dieses Skript automatisch installiert worden sein. Allerdings sollten Sie mit dem Skript vorsichtig umgehen, wenn Sie das Binärlog zur Replikation verwenden. Entfernen Sie Binärlogs erst, wenn Sie sicher sind, dass die Inhalte von allen Slaves verarbeitet wurden.
Auf anderen Systemen müssen Sie selbst ein kurzes Skript installieren, welches Sie über cron (oder ein passendes Gegenstück) starten, um Logdateien zu verarbeiten.
Sie können die Einrichtung und Verwendung neuer Logdateien in MySQL mit mysqladmin flush-logs oder der SQL-Anweisung FLUSH LOGS
erzwingen.
Beim Schreiben einer Logdatei auf die Festplatte geschieht folgendes:
Wenn das Loggen allgemeiner Abfragen (--log
) oder langsamer Abfragen (--log-slow-queries
) verwendet wird, schließt der Server die entsprechende Logdatei und öffnet sie dann neu.
Beim binären Loggen (--log-bin
) schließt der Server die aktuelle Logdatei und öffnet eine neue Logdatei mit der nächsthöheren Sequenznummer.
Wenn die Logs auf Festplatte geschrieben werden, erstellt der Server eine neue Binärlogdatei. Die Logs für allgemeine und langsame Abfragen hingegen werden nur geschlossen und dann wieder geöffnet. Wenn Sie unter Unix neue Dateien erstellen wollen, benennen Sie die aktuellen Logs um, bevor Sie sie auf die Festplatte schreiben. Beim Schreiben auf Festplatte öffnet der Server dann neue Logdateien mit den ursprünglichen Namen. Wenn beispielsweise die Logdateien für allgemeine und langsame Abfragen die Namen mysql.log
bzw. mysql-slow.log
haben, können Sie folgende Befehlssequenz verwenden:
shell>cd
shell>mysql-data-directory
mv mysql.log mysql.old
shell>mv mysql-slow.log mysql-slow.old
shell>mysqladmin flush-logs
An dieser Stelle können Sie eine Sicherung von mysql.old
und mysql-slow.log
erstellen und diese dann von der Festplatte entfernen.
Unter Windows können Sie die Logdateien nicht umbenennen, solange sie vom Server geöffnet sind. Sie müssen zunächst den Server beenden, die Dateien umbenennen und den Server dann neu starten, um neue Logdateien zu erstellen.
In manchen Fällen kann es wünschenswert oder erforderlich sein, mehrere mysqld-Server auf demselben Computer auszuführen. Dies ist etwa der Fall, wenn Sie einen neuen MySQL-Release testen wollen, ohne die vorhandene Produktionskonfiguration anzurühren, oder wenn Sie verschiedenen Benutzern Zugang zu unterschiedlichen mysqld-Servern gestatten wollen, die dann von diesen Benutzern selbst verwaltet werden. (Ein solcher Fall läge bei einem Internetprovider vor, der separate MySQL-Installationen für verschiedene Kunden bereithält.)
Damit mehrere Server auf demselben Computer ausgeführt werden können, benötigt jeder Server eindeutige Werte für verschiedene Betriebsparameter. Diese können über die Befehlszeile oder in Optionsdateien angegeben werden. Siehe auch Abschnitt 4.3, „Angabe von Programmoptionen“.
Zumindest die folgenden Optionen müssen für jeden Server unterschiedlich sein:
--port=
port_num
--port
steuert die Portnummer für TCP/IP-Verbindungen.
--socket=
path
--socket
gibt unter Unix den Pfad zur Unix-Socketdatei und unter Windows den Namen der Named Pipe an. Unter Windows müssen separate Pipe-Namen nur für diejenigen Server angegeben werden, die Named-Pipe-Verbindungen unterstützen.
--shared-memory-base-name=
name
Diese Option wird derzeit nur unter Windows verwendet. Sie bezeichnet den Namen des gemeinsamen Speichers, mit dem ein Windows-Server Clients das Herstellen einer Verbindung über gemeinsamen Speicher gestattet. Die Angabe ist nur für Server erforderlich, die Verbindungen über gemeinsamen Speicher unterstützen.
--pid-file=
file_name
Diese Option wird nur unter Unix verwendet. Sie gibt den Pfadnamen der Datei an, in die der Server seine Prozesskennung schreibt.
Wenn Sie die folgenden Logdateioptionen verwenden, müssen diese für jeden Server anders sein:
--log=
file_name
--log-bin=
file_name
--log-update=
file_name
--log-error=
file_name
--bdb-logdir=
file_name
Weitere Informationen zu Logdateien finden Sie in Abschnitt 5.12.5, „Wartung und Pflege der Logdateien“.
Zur Leistungsoptimierung können Sie auch die folgenden Optionen für jeden Server individuell angeben, um so die Last auf mehrere physische Festplatten zu verteilen:
--tmpdir=
path
--bdb-tmpdir=
path
Auch die Verwendung verschiedener Temporärverzeichnisse wird empfohlen, um besser bestimmen zu können, welche MySQL-Server welche der vorhandenen Temporärdateien erstellt hat.
Mit sehr wenigen Ausnahmen sollte jeder Server ein eigenes Datenverzeichnis haben, das mit der Option --datadir=
angegeben wird.
path
Warnung: Normalerweise sollten Daten in denselben Datenbanken niemals von zwei Servern aktualisiert werden. Dies kann zu unliebsamen Überraschungen führen, wenn Ihr Betriebssystem keine fehlerfreie Systemsperrung unterstützt. Wenn Sie (ungeachtet dieser Warnung) mehrere Server betreiben, die dasselbe Datenverzeichnis verwenden, müssen Sie, wenn das Loggen aktiviert ist, die passenden Optionen zur Angabe der Logdateinamen festlegen, die für jeden Server eindeutig sein müssen. Andernfalls versuchen die Server nämlich, in die gleichen Logdateien zu schreiben. Beachten Sie, dass eine solche Konfiguration nur bei MyISAM
- und MERGE
-Tabellen funktioniert, nicht aber bei anderen Speicher-Engines.
Die Warnung vor der gemeinsamen Nutzung eines Datenverzeichnisses durch mehrere Server gilt auch in einer NFS-Umgebung. Mehreren MySQL-Servern den Zugriff auf ein gemeinsames Datenverzeichnis über NFS zu gestatten, ist eine ganz schlechte Idee.
Das Problem ist hierbei primär, dass NFS in punkto Geschwindigkeit einen Flaschenhals darstellt. NFS ist für einen solchen Einsatz schlichtweg ungeeignet.
Ein weiteres Risiko besteht bei NFS darin, dass Sie eine Möglichkeit finden müssen, sicherzustellen, dass zwei oder mehr Server einander nicht stören. Normalerweise wird die NFS-Dateisperrung vom Daemon lockd
verwaltet; es gibt aber derzeit keine Plattform, die die Sperrung in jeder Situation hundertprozentig zuverlässig ausführt.
Machen Sie es sich einfach: Lassen Sie die Freigabe eines Datenverzeichnisses für mehrere Server über NFS einfach bleiben. Eine bessere Lösung besteht in der Verwendung eines Computers, der mehrere Prozessoren enthält und ein Betriebssystem verwendet, das Threads effizient verwaltet.
Wenn Sie mehrere MySQL-Installationen in verschiedenen Verzeichnissen haben, können Sie das Basisinstallationsverzeichnis für jeden Server mit der Option --basedir=
angeben; in diesem Fall verwendet jeder Server ein anderes Datenverzeichnis, eigene Logdateien und eine eigene Prozesskennungsdatei. (Standardmäßig werden diese Werte relativ zum Basisverzeichnis gesetzt.) In diesem Fall müssen Sie als weitere Optionen nur path
--socket
und --port
angeben. Angenommen, Sie installieren verschiedene MySQL-Versionen aus einer tar
-Datei mit einer Binärdistribution. Diese Versionen werden an verschiedenen Positionen installiert, d. h. Sie können den Server für jede Installation mit dem Befehl bin/mysqld_safe in seinem jeweiligen Basisverzeichnis starten. mysqld_safe bestimmt die korrekte --basedir
-Option, die an mysqld übergeben werden muss; Sie müssen dann nur noch die Optionen --socket
und --port
für mysqld_safe angeben.
Wie in den vorangegangenen Abschnitten bereits erläutert, können zusätzliche Server durch Einstellen von Umgebungsvariablen oder durch Angabe passender Befehlszeilenoptionen gestartet werden. Wenn Sie allerdings auf Dauer mehrere Server ausführen wollen, ist es praktischer, die Optionswerte, die für jeden Server eindeutig sein müssen, mithilfe von Optionsdateien anzugeben. Die Option --defaults-file
ist für diese Zwecke praktisch.
Sie können mehrere Server unter Windows ausführen, indem Sie sie manuell über die Befehlszeile starten und die jeweils passenden Betriebsparameter angeben. Auf Windows NT-basierten Systemen können Sie mehrere Server auch als Windows-Dienste installieren und sie auf diese Weise ausführen. Eine allgemeine Anleitung zur Ausführung von MySQL-Servern über die Befehlszeile oder als Dienste finden Sie in Abschnitt 2.3, „Installation von MySQL unter Windows“. Dieser Abschnitt beschreibt, wie man sicherstellt, dass jeder Server mit unterschiedlichen Werten für diejenigen Optionen gestartet wird, die je Server eindeutig sein müssen (z. B. das Datenverzeichnis). Diese Optionen sind in Abschnitt 5.13, „Mehrere MySQL-Server auf derselben Maschine laufen lassen“, beschrieben.
Um mehrere Server manuell über die Befehlszeile zu starten, können Sie die erforderlichen Optionen ebenfalls über die Befehlszeile oder in einer Optionsdatei angeben. Die Verwendung einer Optionsdatei ist praktischer. Sie müssen aber in jedem Fall sicherstellen, dass jeder Server eigene Optionen zugeordnet bekommt. Zu diesem Zweck erstellen Sie für jeden Server eine Optionsdatei und übergeben dem Server beim Start den Dateinamen mit der Option --defaults-file
.
Angenommen, Sie wollen mysqld über Port 3307 mit dem Datenverzeichnis C:\mydata1
und mysqld-max über Port 3308 mit dem Datenverzeichnis C:\mydata2
ausführen. (Vergewissern Sie sich zu diesem Zweck vor dem Starten der Server, dass die Datenverzeichnisse vorhanden sind und jeweils eine eigene Kopie der mysql
-Datenbank mit den Grant-Tabellen enthalten.) Erstellen Sie nun zwei Optionsdateien. Legen Sie beispielsweise eine Datei namens C:\my-opts1.cnf
an, die wie folgt aussieht:
[mysqld] datadir = C:/mydata1 port = 3307
Legen Sie nun eine zweite Datei namens C:\my-opts2.cnf
an, die wie folgt aussieht:
[mysqld] datadir = C:/mydata2 port = 3308
Jetzt starten Sie die Server mit jeweils eigener Optionsdatei:
C:\>C:\mysql\bin\mysqld --defaults-file=C:\my-opts1.cnf
C:\>C:\mysql\bin\mysqld-max --defaults-file=C:\my-opts2.cnf
Unter NT starten beide Server in den Vordergrund (d. h. eine Eingabeaufforderung wird erst wieder angezeigt, wenn der Server später beendet wird); Sie müssen deswegen zwei Befehle in separaten Konsolenfenstern ausführen.
Um die Server herunterzufahren, müssen Sie mit jedem Server unter Angabe der entsprechenden Portnummer eine Verbindung herstellen:
C:\>C:\mysql\bin\mysqladmin --port=3307 shutdown
C:\>C:\mysql\bin\mysqladmin --port=3308 shutdown
Mit Servern, die auf die beschriebene Weise konfiguriert wurden, können Clients über TCP/IP Verbindungen herstellen. Wenn Ihre Windows-Version Named Pipes unterstützt und Sie Named-Pipe-Verbindungen auch zulassen wollen, dann verwenden Sie die Server mysqld-nt oder mysqld-max-nt und geben Sie Optionen an, die die Named Pipe aktivieren und den zugehörigen Namen definieren. Jeder Server, der Named-Pipe-Verbindungen unterstützt, muss einen eindeutigen Namen für die Pipe verwenden. Beispielsweise könnte die Datei C:\my-opts1.cnf
wie folgt aussehen:
[mysqld] datadir = C:/mydata1 port = 3307 enable-named-pipe socket = mypipe1
Starten Sie den Server in diesem Fall wie folgt:
C:\> C:\mysql\bin\mysqld-nt --defaults-file=C:\my-opts1.cnf
Ändern Sie C:\my-opts2.cnf
auf ähnliche Weise für die Verwendung durch den zweiten Server ab.
Eine ähnliche Vorgehensweise gilt für Server, die Verbindungen über gemeinsamen Speicher unterstützen sollen. Sie aktivieren solche Verbindungen mit der Option --shared-memory
und vergeben dann für jeden Server mit der Option --shared-memory-base-name
einen eindeutigen Namen für den freigegebenen Speicher.
Unter Windows NT-basierten Systemen kann ein MySQL-Server als Windows-Dienst ausgeführt werden. Die Vorgehensweise zum Installieren, Steuern und Entfernen eines einzelnen MySQL-Dienstes sind in Abschnitt 2.3.12, „Starten von MySQL als Windows-Dienst“, beschrieben.
Sie können auch mehrere MySQL-Server als Dienste installieren. In diesem Fall müssen Sie sicherstellen, dass jeder Server neben allen Parametern, die für jeden Server eindeutig sein müssen, auch einen eigenen Dienstnamen verwendet.
Bei der folgenden Anleitung wird davon ausgegangen, dass Sie den Server mysqld-nt aus zwei verschiedenen MySQL-Versionen ausführen wollen, die in C:\mysql-5.0.19
bzw. C:\mysql-5.1.5-alpha
installiert sind. (Dies kann etwa der Fall sein, wenn Sie Version 5.0.19 als Produktionsserver ausführen und gleichzeitig Tests mit Version 5.1.5-alpha durchführen wollen.)
Die folgenden Prinzipien finden Anwendung, wenn Sie einen MySQL-Dienst mit der Option --install
oder --install-manual
installieren:
Wenn Sie keinen Dienstnamen angeben, verwendet der Server den Standarddienstnamen MySQL
und liest seine Optionen aus dem Abschnitt [mysqld]
in den Standardoptionsdateien aus.
Geben Sie hingegen auf die Option --install
folgend einen Dienstnamen an, dann ignoriert der Server den Abschnitt [mysqld]
und liest stattdessen die Optionen aus dem Abschnitt aus, der den gleichen Namen wie der Dienst hat. Der Server liest Optionen aus den Standardoptionsdateien aus.
Wenn Sie eine Option --defaults-file
auf den Dienstnamen folgend angeben, ignoriert der Server die Standardoptionsdateien und liest seine Optionen aus dem Abschnitt [mysqld]
der benannten Datei aus.
Hinweis: Vor MySQL 4.0.17 wird der Abschnitt [mysqld]
in den Standardoptionsdateien nur dann vom Server gelesen, wenn dieser mit dem Standarddienstnamen (MySQL
) oder dem explizit angegebenen Dienstnamen mysqld installiert wurde. Ab Version 4.0.17 lesen alle Server, falls sie die Standardoptionsdateien auslesen, den Abschnitt [mysqld]
. Dies gilt auch für Server, die mit einem anderen Dienstnamen installiert wurden. Sie können den Abschnitt [mysqld]
also für diejenigen Optionen verwenden, die allen MySQL-Diensten gemeinsam sind, und zusätzlich einen Abschnitt mit dem Namen eines bestimmten Dienstes konfigurieren, der dann von dem Server benutzt wird, der mit diesem Dienstnamen installiert wurde.
Basierend auf diesen Informationen stehen Ihnen verschiedene Möglichkeiten zur Verfügung, mehrere Dienste einzurichten. Die folgende Anleitung beschreibt einige Beispiele. Bevor Sie jedoch eines davon ausprobieren, fahren Sie alle vorhandenen MySQL-Dienste herunter und entfernen Sie sie.
Methode 1: Geben Sie die Optionen für alle Dienste in einer der Standardoptionsdateien an. Verwenden Sie zu diesem Zweck einen anderen Dienstnamen für jeden Server. Angenommen, Sie wollen mysqld-nt aus Version 5.0.19 mit dem Dienstnamen mysqld1
und mysqld-nt aus Version 5.1.5-alpha mit dem Dienstnamen mysqld2
ausführen. In diesem Fall können Sie den Abschnitt [mysqld1]
für Version 5.0.19 und den Abschnitt [mysqld2]
für Version 5.1.5-alpha verwenden. Sie können C:\my.cnf
etwa wie folgt konfigurieren:
# options for mysqld1 service [mysqld1] basedir = C:/mysql-5.0.19 port = 3307 enable-named-pipe socket = mypipe1 # options for mysqld2 service [mysqld2] basedir = C:/mysql-5.1.5-alpha port = 3308 enable-named-pipe socket = mypipe2
Installieren Sie die Dienste wie folgt und verwenden Sie dabei die vollständigen Serverpfadnamen, um sicherzustellen, dass Windows für jeden Dienst die korrekte ausführbare Datei registriert:
C:\>C:\mysql-5.0.19\bin\mysqld-nt --install mysqld1
C:\>C:\mysql-5.1.5-alpha\bin\mysqld-nt --install mysqld2
Um die Dienste zu starten, verwenden Sie den Dienste-Manager oder NET START mit den entsprechenden Dienstnamen:
C:\>NET START mysqld1
C:\>NET START mysqld2
Um die Dienste zu beenden, verwenden Sie den Dienste-Manager oder NET STOP mit den entsprechenden Dienstnamen:
C:\>NET STOP mysqld1
C:\>NET STOP mysqld2
Methode 2: Sie geben Sie Optionen für jeden Server in einer separaten Datei an und geben bei der Installation --defaults-file
an, um den Servern die jeweils zu verwendende Datei mitzuteilen. In diesem Fall sollten die Optionen in jeder Datei in einem Abschnitt [mysqld]
aufgelistet sein.
Bei dieser Methode erstellen Sie zur Angabe der Optionen für mysqld-nt aus Version 5.0.19 eine Datei C:\my-opts1.cnf
, die wie folgt aussieht:
[mysqld] basedir = C:/mysql-5.0.19 port = 3307 enable-named-pipe socket = mypipe1
Legen Sie nun für mysqld-nt aus Version 5.1.5-alpha eine zweite Datei namens C:\my-opts2.cnf
an, die wie folgt aussieht:
[mysqld] basedir = C:/mysql-5.1.5-alpha port = 3308 enable-named-pipe socket = mypipe2
Installieren Sie die Dienste wie folgt (geben Sie jeden Befehl in eine eigene Zeile ein):
C:\>C:\mysql-5.0.19\bin\mysqld-nt --install mysqld1
--defaults-file=C:\my-opts1.cnf C:\>C:\mysql-5.1.5-alpha\bin\mysqld-nt --install mysqld2
--defaults-file=C:\my-opts2.cnf
Um bei der Installation eines MySQL-Servers als Dienst eine Option --defaults-file
anzugeben, müssen Sie der Option den Dienstnamen voranstellen.
Nach der Installation der Dienste starten und beenden Sie sie auf die gleiche Weise wie im vorherigen Beispiel.
Zum Entfernen mehrerer Dienste verwenden Sie für jeden einzelnen Dienst mysqld --remove und geben dabei auf die Option --remove
folgend einen Dienstnamen an. Wenn der Dienst den Standardnamen (MySQL
) hat, können Sie die Angabe auch weglassen.
Die einfachste Möglichkeit, mehrere Server unter Unix auszuführen, besteht darin, sie mit verschiedenen TCP/IP-Ports und Unix-Socketdateien zu kompilieren, sodass jeder Server auf eine andere Netzwerkschnittstelle horcht. Auch das Einkompilieren verschiedener Basisverzeichnisse für jede Installation hat automatisch ein dediziertes einkompiliertes Verzeichnis zur Folge, in dem Datenverzeichnis, Logdatei und Prozesskennungsdatei des betreffenden Servers abgelegt sind.
Nehmen wir einmal an, dass der vorhandene Server (Version 5.0.19) für den TCP/IP-Standardport (3306) und die Standardsocketdatei (/tmp/mysql.sock
) konfiguriert ist. Um nun einen neuen Server unter MySQL 5.1.5-alpha mit anderen Betriebsparametern zu konfigurieren, verwenden Sie den Befehl configure wie folgt:
shell>./configure --with-tcp-port=
port_number
\--with-unix-socket-path=
file_name
\--prefix=/usr/local/mysql-5.1.5-alpha
Hierbei müssen sich port_number
und file_name
von der TCP/IP-Standardportnummer bzw. dem Standardpfadnamen der Unix-Socketdatei unterscheiden. Ferner sollte die Option --prefix
ein anderes Installationsverzeichnis als jenes angeben, in dem sich die vorhandene MySQL-Installation befindet.
Wenn Ihr MySQL-Server auf eine gegebene Portnummer horcht, dann können Sie mit folgendem Befehl herausfinden, welche Betriebsparameter er für verschiedene wichtige konfigurierbare Variablen (einschließlich Basisverzeichnis und Unix-Socketdatei) verwendet:
shell> mysqladmin --host=host_name
--port=port_number
variables
Anhand der von diesem Befehl angezeigten Informationen können Sie festlegen, welche Optionswerte Sie nicht verwenden dürfen, wenn Sie einen zusätzlichen Server konfigurieren.
Beachten Sie, dass, wenn Sie localhost
als Hostnamen angeben, mysqladmin standardmäßig statt TCP/IP eine Verbindung über eine Unix-Socketdatei verwendet. Ab MySQL 4.1 können Sie das zu verwendende Verbindungsprotokoll mit der Option --protocol={TCP|SOCKET|PIPE|MEMORY}
explizit angeben.
Sie müssen keinen neuen MySQL-Server kompilieren, nur um neu mit einer anderen Unix-Socketdatei und TCP/IP-Portnummer zu starten. Sie können auch dieselbe Serverbinärdatei verwenden und diese mehrfach aufrufen – mit jeweils anderen Parameterwerten zur Laufzeit. Eine Möglichkeit hierzu besteht in der Verwendung von Befehlszeilenoptionen:
shell> mysqld_safe --socket=file_name
--port=port_number
Um einen zweiten Server zu starten, geben Sie andere Optionswerte für --socket
und --port
an und übergeben zudem eine Option --datadir=
an mysqld_safe, damit der Server ein anderes Datenverzeichnis benutzt.
path
Eine weitere Möglichkeit, mit der sich ein ähnlicher Effekt erzielen lässt, besteht darin, den Namen der Unix-Socketdatei und die TCP/IP-Portnummer mithilfe von Umgebungsvariablen anzugeben:
shell>MYSQL_UNIX_PORT=/tmp/mysqld-new.sock
shell>MYSQL_TCP_PORT=3307
shell>export MYSQL_UNIX_PORT MYSQL_TCP_PORT
shell>mysql_install_db --user=mysql
shell>mysqld_safe --datadir=/path/to/datadir &
Dies steht eine schnelle Möglichkeit dar, einen zweiten Server zu Testzwecken zu starten. Das Praktische an dieser Methode ist, dass die Einstellungen der Umgebungsvariablen für alle Clientprogramme gelten, die Sie von derselben Shell aufrufen. Auf diese Weise werden Verbindungen für diese Clients automatisch an den zweiten Server geleitet.
Anhang F, Umgebungsvariablen, enthält eine Liste aller anderen Umgebungsvariablen, die Sie zur Beeinflussung von mysqld verwenden können.
Für die automatische Ausführung des Servers sollte das Startskript, welches beim Systemstart ausgeführt wird, den folgenden Befehl jeweils einmal pro Server ausführen und dabei den jeweils passenden Optionsdateipfad angeben:
shell> mysqld_safe --defaults-file=file_name
Jede Optionsdatei sollte die Optionswerte für jeweils einen bestimmten Server angeben.
Eine andere Möglichkeit zum Starten mehrerer Server bietet unter Unix das Skript mysqld_multi. Siehe auch Abschnitt 5.4.3, „mysqld_multi — Verwalten mehrerer MySQL-Server“.
Um eine Verbindung von einem Clientprogramm mit einem MySQL-Server herzustellen, der auf anderen als den in Ihren Client einkompilierten Netzwerkschnittstellen lauscht, können Sie eine der folgenden Methoden benutzen:
Starten Sie den Client mit --host=
, host_name
--port=port_number
--host=127.0.0.1 --port=
bzw. port_number
--host=localhost --socket=
, um eine TCP/IP-Verbindung mit einem entfernten Server, eine TCP/IP-Verbindung mit dem lokalen Server oder eine Verbindung mit dem lokalen Server über eine Unix-Socketdatei oder eine Named Pipe unter Windows herzustellen.
file_name
Ab MySQL 4.1 starten Sie den Client mit --protocol=tcp
, --protocol=socket
, --protocol=pipe
bzw. --protocol=memory
, um eine Verbindung über TCP/IP, eine Unix-Socketdatei, eine Named Pipe oder gemeinsamen Speicher herzustellen. Bei TCP/IP-Verbindungen müssen Sie auch die Optionen --host
und --port
angeben. Bei den anderen Verbindungstypen können Sie eine Option --socket
zur Festlegung einer Unix-Socketdatei bzw. einer Named-Pipe-Datei oder eine Option --shared-memory-base-name
zur Bezeichnung des Namens des gemeinsamen Speichers angeben. Verbindungen über gemeinsamen Speicher werden nur unter Windows unterstützt.
Unter Unix stellen Sie, bevor Sie Ihre Clients starten, die Umgebungsvariablen MYSQL_UNIX_PORT
und MYSQL_TCP_PORT
so ein, dass sie die Unix-Socketdatei bzw. die TCP/IP-Portnummer angeben. Wenn Sie normalerweise eine bestimmte Socketdatei oder Portnummer verwenden, können Sie die Befehle, die die Werte der Umgebungsvariablen einstellen, in Ihrer Datei .login
ablegen, damit diese bei jeder Anmeldung automatisch konfiguriert werden. Siehe auch Anhang F, Umgebungsvariablen.
Geben Sie die Vorgaben für die Unix-Socketdatei und die TCP/IP-Portnummer im Abschnitt [client]
einer Optionsdatei an. Sie können beispielsweise C:\my.cnf
unter Windows oder .my.cnf
in Ihrem Stammverzeichnis unter Unix verwenden. Siehe auch Abschnitt 4.3.2, „my.cnf-Optionsdateien“.
In einem C-Programm können Sie die Socketdatei- oder Portnummerargumente im Aufruf mysql_real_connect()
angeben. Sie können das Programm auch die Optionsdateien auslesen lassen, indem Sie mysql_options()
aufrufen. Siehe auch Abschnitt 24.2.3, „C-API: Funktionsbeschreibungen“.
Wenn Sie das Perl-Modul DBD::mysql
verwenden, können Sie ebenfalls Optionen aus MySQL-Optionsdateien auslesen. Zum Beispiel:
$dsn = "DBI:mysql:test;mysql_read_default_group=client;" . "mysql_read_default_file=/usr/local/mysql/data/my.cnf"; $dbh = DBI->connect($dsn, $user, $password);
Siehe auch Abschnitt 24.4, „MySQLs Perl-API“.
Andere Programmierschnittstellen bieten unter Umständen ähnliche Funktionalitäten zum Auslesen von Optionsdateien.
Der Abfrage-Cache speichert den Text einer SELECT
-Anweisung gemeinsam mit dem zugehörigen Ergebnis, das an den Client gesendet wurde. Wenn später eine identische Anweisung empfangen wird, ruft der Server die Ergebnisse aus dem Abfrage-Cache ab, statt die Anweisung erneut zu verarbeiten und auszuführen.
Der Abfrage-Cache ist extrem nützlich in Umgebungen, in denen sich Tabellen nicht besonders häufig ändern und der Server häufig identische Abfragen empfängt. Dies ist eine typische Situation insbesondere für Webserver, die basierend auf den Datenbankinhalten viele dynamische Seiten erzeugen.
Hinweis: Der Abfrage-Cache gibt keine veralteten Daten zurück. Wenn Tabellen modifiziert werden, werden alle entsprechenden Einträge im Abfrage-Cache synchronisiert.
Hinweis: Der Abfrage-Cache funktioniert nicht in Umgebungen, in denen mehrere mysqld-Server dieselben MyISAM
-Tabellen aktualisieren.
Hinweis: Der Abfrage-Cache wird nicht bei serverseitig vorbereiteten Anweisungen benutzt. Wenn Sie serverseitig vorbereitete Anweisungen verwenden, müssen Sie berücksichtigen, dass diese Anweisungen nicht vom Abfrage-Cache profitieren. Siehe auch Abschnitt 24.2.4, „C-API: Prepared Statements“.
An dieser Stelle folgen ein paar Leistungsdaten für den Abfrage-Cache. Diese Ergebnisse wurden erzeugt, indem die MySQL-Benchmarks auf einem Linux-Alpha-System mit 2 × 500 MHz, 2 Gbyte RAM und einem Abfrage-Cache von 64 Mbyte ausgeführt wurden.
Wenn alle von Ihnen durchgeführten Abfragen einfacher Natur sind (z. B. das Auswählen eines Datensatzes aus einer Tabelle mit nur einem Datensatz), aber sich noch voneinander unterscheiden, sodass die Abfragen nicht im Cache abgelegt werden können, dann liegt die Mehrbelastung bei Nutzung eines aktiven Abfrage-Caches bei 13 Prozent. Dies sollte als ungünstigster Fall betrachtet werden. In der Praxis neigen Abfragen dazu, wesentlich komplizierter zu sein, d. h. die Mehrbelastung ist in der Regel deutlich niedriger.
Suchvorgänge nach einem einzelnen Datensatz in einer Tabelle mit nur einem Datensatz sind mit Abfrage-Cache um 238 Prozent schneller als ohne. Dieser Wert kann annähernd als zu erwartende Mindestbeschleunigung für im Cache abgelegte Abfragen betrachtet werden.
Um den Abfrage-Cache beim Serverstart zu deaktivieren, setzen Sie die Systemvariable query_cache_size
auf 0. Durch Deaktivierung des Codes für den Abfrage-Cache erhalten Sie keine merkliche Mehrbelastung. Wenn Sie MySQL aus der Quelldistribution erstellen, lässt sich die Abfrage-Cachefunktionalität auf dem Server vollständig abschalten, indem Sie configure mit der Option --without-query-cache
aufrufen.
Dieser Abschnitt beschreibt, wie der Abfrage-Cache funktioniert, wenn er betriebsbereit ist. Abschnitt 5.14.3, „Konfiguration des Anfragen-Cache“, erläutert, wie Sie ermitteln können, ob die Betriebsbereitschaft gegeben ist.
Eingehende Abfragen werden vor Ihrer Verarbeitung mit denen im Abfrage-Cache verglichen; die folgenden beiden Abfragen werden also aus der Sicht des Abfrage-Caches als unterschiedlich betrachtet:
SELECT * FROMtbl_name
Select * fromtbl_name
Abfragen müssen absolut (das heißt bytegenau) gleich sein, damit sie als identisch gelten. Außerdem können Abfrage-Strings, die identisch sind, auch aus anderen Gründen wie unterschiedliche Abfragen behandelt werden. Abfragen, die verschiedene Datenbanken, Protokollversionen oder Standardzeichensätze verwenden, gelten als unterschiedliche Abfragen und werden separate im Cache abgelegt.
Bevor ein Abfrageergebnis aus dem Abfrage-Cache abgerufen wird, prüft MySQL, ob der Benutzer die Berechtigung SELECT
für alle betreffenden Datenbanken und Tabellen hat. Ist dies nicht der Fall, dann wird das Ergebnis im Cache nicht verwendet.
Wird ein Abfrageergebnis aus dem Abfrage-Cache zurückgegeben, dann zählt der Server die Statusvariable Qcache_hits
hoch, nicht aber Com_select
. Siehe auch Abschnitt 5.14.4, „Anfragen-Cache-Status und -Wartung“.
Wenn eine Tabelle geändert wird, werden alle Abfragen, die die Tabelle verwenden, ungültig und insofern aus dem Cache entfernt. Dies betrifft auch Abfragen, die MERGE
-Tabellen verwenden, welche die geänderte Tabelle abbilden. Eine Tabelle kann von vielen Anweisungstypen geändert werden, so etwa INSERT
, UPDATE
, DELETE
, TRUNCATE
, ALTER TABLE
, DROP TABLE
oder DROP DATABASE
.
Transaktionssichere InnoDB
-Tabellen, die geändert wurden, werden ungültig, wenn eine COMMIT
-Anweisung ausgeführt wird.
Der Abfrage-Cache funktioniert auch innerhalb von Transaktionen, wenn Sie InnoDB
-Tabellen verwenden, denn anhand der Tabellenversionsnummer bestimmt er, ob seine Inhalte nach wie vor gültig sind.
In MySQL 5.1 werden Abfragen, die von Views erstellt werden, im Cache abgelegt.
Der Abfrage-Cache funktioniert bei Abfragen der Typen SELECT SQL_CALC_FOUND_ROWS ...
und SELECT FOUND_ROWS()
. FOUND_ROWS()
gibt den korrekten Wert auch dann zurück, wenn die vorherige Abfragen aus dem Cache geholt wurde, da die Anzahl der gefundenen Datensätze ebenfalls im Cache abgelegt ist.
Eine Abfrage landet nicht im Abfrage-Cache, wenn sie eine der Funktionen enthält, die in der folgenden Tabellen aufgeführt sind.
BENCHMARK() | CONNECTION_ID() | CURDATE() |
CURRENT_DATE() | CURRENT_TIME() | CURRENT_TIMESTAMP() |
CURTIME() | DATABASE() | ENCRYPT() mit genau einem Parameter |
FOUND_ROWS() | GET_LOCK() | LAST_INSERT_ID() |
LOAD_FILE() | MASTER_POS_WAIT() | NOW() |
RAND() | RELEASE_LOCK() | SYSDATE() |
UNIX_TIMESTAMP() ohne Parameter | USER() |
Auch unter den folgenden Bedingungen wird eine Abfrage nicht im Abfrage-Cache gespeichert:
Sie verweist auf benutzerdefinierte Funktionen (UDFs).
Sie verweist auf Benutzervariablen.
Sie verweist auf Tabellen in der mysql
-Systemdatenbank.
Sie hat eine der folgenden Formen:
SELECT ... IN SHARE MODE SELECT ... FOR UPDATE SELECT ... INTO OUTFILE ... SELECT ... INTO DUMPFILE ... SELECT * FROM ... WHERE autoincrement_col IS NULL
Die letzte Form wird nicht gespeichert, weil Sie als ODBC-Workaround zur Ermittlung des letzten Einfügekennungswertes eingesetzt wird. Siehe auch Abschnitt 25.1.6.1.1, „Abruf von Auto-Increment-Werten“.
Sie wurde als vorbereitete Anweisung abgesetzt, auch wenn keine Platzhalter verwendet wurden. So wird etwa folgende Abfrage nicht im Cache gespeichert:
char *my_sql_stmt = "SELECT a, b FROM table_c"; /* ... */ mysql_stmt_prepare(stmt, my_sql_stmt, strlen(my_sql_stmt));
Siehe auch Abschnitt 24.2.4, „C-API: Prepared Statements“.
Sie verwendet TEMPORARY
-Tabellen.
Sie verwendet überhaupt keine Tabellen.
Der Benutzer hat eine Berechtigung auf Spaltenebene für eine der betreffenden Tabellen.
In SELECT
-Anweisungen können zwei für den Abfrage-Cache spezifische Optionen angegeben werden:
Ein paar Beispiele:
SELECT SQL_CACHE id, name FROM customer; SELECT SQL_NO_CACHE id, name FROM customer;
Die Serversystemvariable have_query_cache
gibt an, ob der Abfrage-Cache verfügbar ist:
mysql> SHOW VARIABLES LIKE 'have_query_cache';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| have_query_cache | YES |
+------------------+-------+
Wenn Sie eine MySQL-Standardbinärdatei verwenden, ist der Wert immer YES
– und zwar auch dann, wenn die Zwischenspeicherung von Abfragen deaktiviert ist.
Mehrere andere Systemvariablen steuern den Betrieb des Abfrage-Caches. Diese können in einer Optionsdatei oder über die Befehlszeile beim Start von mysqld angegeben werden. Die Namen aller Systemvariablen für den Abfrage-Cache beginnen stets mit query_cache_
. Sie sind in Abschnitt 5.2.2, „Server-Systemvariablen“, kurz beschrieben. An dieser Stelle sollen zusätzliche Konfigurationsinformationen erläutert werden.
Die Größe des Abfrage-Caches stellen Sie mit der Systemvariable query_cache_size
ein. Die Einstellung 0 deaktiviert den Abfrage-Cache. Standardwert ist 0, d. h. der Abfrage-Cache ist vorgabeseitig deaktiviert.
Wenn Sie query_cache_size
auf einen Wert ungleich Null setzen, beachten Sie, dass der Abfrage-Cache eine Mindestgröße von ca. 40 Kbyte benötigt, um seine Strukturen zuzuweisen. (Der exakte Wert hängt von der Systemarchitektur ab.) Wenn Sie den Wert zu niedrig ansetzen, erhalten Sie eine Warnung wie im folgenden Beispiel:
mysql>SET GLOBAL query_cache_size = 40000;
Query OK, 0 rows affected, 1 warning (0.00 sec) mysql>SHOW WARNINGS\G
*************************** 1. row *************************** Level: Warning Code: 1282 Message: Query cache failed to set size 39936; new query cache size is 0 mysql>SET GLOBAL query_cache_size = 41984;
Query OK, 0 rows affected (0.00 sec) mysql>SHOW VARIABLES LIKE 'query_cache_size';
+------------------+-------+ | Variable_name | Value | +------------------+-------+ | query_cache_size | 41984 | +------------------+-------+
Ist die Größe des Abfrage-Caches größer als 0, dann beeinflusst die Variable query_cache_type
die Wirkungsweise. Die Variable kann auf die folgenden Werte gesetzt werden:
Der Wert 0
oder OFF
verhindert das Speichern von Abfragen im und das Abrufen aus dem Cache.
Der Wert 1
oder ON
gestattet das Speichern von Abfragen im Cache. Ausgenommen sind Anweisungen, die mit SELECT SQL_NO_CACHE
beginnen.
Der Wert 2
oder DEMAND
speichert nur diejenigen Anweisungen im Cache, die mit SELECT SQL_CACHE
beginnen.
Die Einstellung des GLOBAL
-Wertes query_cache_type
bestimmt das Verhalten des Abfrage-Caches für alle Clients, die nach Durchführung der Änderung eine Verbindung herstellen. Einzelne Clients können das Verhalten des Caches bezüglich ihrer eigenen Verbindung steuern, indem Sie den SESSION
-Wert query_cache_type
einstellen. So kann ein Client beispielsweise die Verwendung des Abfrage-Caches für eigene Abfragen wie folgt deaktivieren:
mysql> SET SESSION query_cache_type = OFF;
Um die maximale Größe einzelner Abfrageergebnisse zu steuern, die im Cache gespeichert werden können, stellen Sie die Systemvariable query_cache_limit
ein. Der Vorgabewert ist 1 Mbyte.
Wenn eine Abfrage im Cache abgelegt werden soll, wird ihr Ergebnis (d. h. die Daten, die an den Client gesendet werden) während des Abrufens des Ergebnisses im Abfrage-Cache abgelegt. Dies bedeutet, dass die Daten nicht am Stück verwaltet werden. Der Abfrage-Cache reserviert Blöcke zur Speicherung dieser Daten nach Bedarf, d. h. wenn ein Block voll ist, wird der nächste zugewiesen. Da der Speicherreservierungsvorgang (in zeitlicher Hinsicht) aufwändig ist, reserviert der Abfrage-Cache die Blöcke mit einer Mindestgröße, die durch die Systemvariable query_cache_min_res_unit
festgelegt wird. Wird eine Abfrage ausgeführt, dann wird der letzte Ergebnisblock auf die tatsächliche Datengröße zugeschnitten, sodass unbenutzter Speicher freigegeben wird. Je nach Typ der von Ihrem Server ausgeführten Abfragen kann es für Sie hilfreich sein, den Wert von query_cache_min_res_unit
zu optimieren:
Der Vorgabewert von query_cache_min_res_unit
beträgt 4 Kbyte. Dies sollte für die meisten Fälle ausreichend sein.
Wenn Sie viele Abfragen mit kleinen Ergebnissen haben, kann die standardmäßige Blockgröße zur Speicherfragmentierung führen, wie durch eine große Anzahl freier Blöcke zu erkennen ist. Die Fragmentierung wiederum kann das Entfernen (Löschen) von Abfragen aus dem Abfragen aufgrund von Speichermangel erforderlich machen. In diesem Fall sollten Sie den Wert von query_cache_min_res_unit
verringern. Die Anzahl freier Blöcke und entfernter Abfragen wird durch die Werte der Statusvariablen Qcache_free_blocks
bzw. Qcache_lowmem_prunes
angegeben.
Weist die Mehrzahl Ihrer Abfragen hingegen große Ergebnisse auf (dies können Sie mit den Statusvariablen Qcache_total_blocks
und Qcache_queries_in_cache
überprüfen), dann können sie die Leistung steigern, indem Sie query_cache_min_res_unit
erhöhen. Allerdings sollten Sie den Wert nicht zu groß wählen (siehe obige Beschreibung).
Sie können mit der folgenden Anweisung überprüfen, ob der Abfrage-Cache auf Ihrem MySQL-Server vorhanden ist:
mysql> SHOW VARIABLES LIKE 'have_query_cache';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| have_query_cache | YES |
+------------------+-------+
Um den Abfrage-Cache zu defragmentieren und den vorhandenen Speicher so besser zu nutzen, setzen Sie die Anweisung FLUSH QUERY CACHE
ab. Diese Anweisung entfernt keine Abfragen aus dem Cache.
Die Anweisung RESET QUERY CACHE
entfernt alle Abfrageergebnisse aus dem Abfrage-Cache. Auch die Anweisung FLUSH TABLES
tut dies.
Wenn Sie die Leistung des Abfrage-Caches überwachen wollen, können Sie mit SHOW STATUS
die Statusvariablen für den Cache anzeigen:
mysql> SHOW STATUS LIKE 'Qcache%';
+-------------------------+--------+
| Variable_name | Value |
+-------------------------+--------+
| Qcache_free_blocks | 36 |
| Qcache_free_memory | 138488 |
| Qcache_hits | 79570 |
| Qcache_inserts | 27087 |
| Qcache_lowmem_prunes | 3114 |
| Qcache_not_cached | 22989 |
| Qcache_queries_in_cache | 415 |
| Qcache_total_blocks | 912 |
+-------------------------+--------+
Beschreibungen dieser Variablen finden Sie in Abschnitt 5.2.4, „Server-Statusvariablen“. An dieser Stelle wollen wir einige Anwendungsmöglichkeiten für sie beschreiben.
Die Gesamtzahl der SELECT
-Anweisungen berechnen Sie mit folgender Formel:
Com_select + Qcache_hits + queries with errors found by parser
Den Wert Com_select
erhalten Sie über folgende Formel:
Qcache_inserts + Qcache_not_cached + queries with errors found during the column-privileges check
Der Abfrage-Cache verwendet Blöcke variabler Länge, d. h. Qcache_total_blocks
und Qcache_free_blocks
lassen Rückschlüsse auf die Speicherfragmentierung des Abfrage-Caches zu. Nach Absetzen von FLUSH QUERY CACHE
bleibt nur ein einziger freie Block übrig.
Alle im Cache gespeicherten Abfragen benötigen mindestens zwei Blöcke (einen für den Abfragetext und einen weiteren für die Ergebnisse). Ferner benötigt jede Tabelle, die von einer Abfrage verwendet wird, einen Block. Wenn jedoch zwei oder mehr Abfragen dieselbe Tabelle verwenden, muss nur ein Tabellenblock reserviert werden.
Mithilfe der in der Statusvariable Qcache_lowmem_prunes
gespeicherten Information können Sie die Größe des Abfrage-Cache optimieren. Diese Variable zählt die Anzahl der Abfragen, die aus dem Cache entfernt wurden, um Speicherplatz für die Aufnahme neuer Abfragen zu schaffen. Der Abfrage-Cache entscheidet auf der Basis der zuletzt verwendeten Abfragen, welche Abfragen aus dem Cache entfernt werden können. Hinweise zur Optimierung finden Sie in Abschnitt 5.14.3, „Konfiguration des Anfragen-Cache“.
Inhaltsverzeichnis
Dieses Kapitel beschreibt die verschiedenen Replikationsfunktionen in MySQL. Es stellt Replikationskonzepte vor, erläutert die Konfiguration von Replikationsservern und dient als Referenz der verfügbaren Replikationsoptionen. Ferner vorhanden ist eine Liste mit häufig gestellten Fragen (und den zugehörigen Antworten) sowie Hilfestellung zur Behebung von Replikationsproblemen.
Eine Beschreibung der Syntax replikationsspezifischer SQL-Anweisungen finden Sie in Abschnitt 13.6, „SQL-Befehle in Bezug auf Replikation“.
MySQL unterstützt die unidirektionale, asynchrone Replikation, bei der ein Server als Master agiert, während mehrere andere Server die Rolle der Slaves erfüllen. Dies steht im Gegensatz zur synchronen Replikation, die ein Kennzeichen von MySQL Cluster ist (siehe auch Kapitel 16, MySQL Cluster).
Bei der Single-Master-Replikation schreibt der Master-Server Updates in seine Binärlogdateien und führt zudem einen Index dieser Dateien, um den Überblick über die Logrotation zu behalten. Die Binärlogdateien dienen als Datenspeicher für Updates, die an alle Slave-Server gesendet werden. Wenn ein Slave eine Verbindung zu seinem Master herstellt, nennt er dem Master die Position, bis zu der er die Logdateien beim letzten erfolgreichen Update gelesen hat. Der Slave empfängt daraufhin alle Änderungen, die seit jenem Zeitpunkt durchgeführt wurden. Nachfolgend wechselt er in den Leerlauf und wartet darauf, dass der Master ihn über neue Aktualisierungen in Kenntnis setzt.
Ein Slave-Server kann seinerseits als Master agieren, um beispielsweise eine Verkettung von Replikationsservern realisieren zu können.
Die Multi-Master-Replikation ist zwar auch möglich, aber hierbei können Probleme auftreten, die bei der Single-Master-Replikation ausgeschlossen sind. Siehe auch Abschnitt 6.15, „Auto-Increment in der Multi-Master-Replikation“.
Sofern Sie die Replikation verwenden, sollten alle Änderungen an Tabellen, die repliziert werden, auf dem Master-Server durchgeführt werden. Andernfalls müssen Sie nämlich immer sorgfältig darauf achten, Konflikte zwischen von Benutzern vorgenommenen Änderungen an den Tabellen auf dem Master und solchen Änderungen zu vermeiden, die an Tabellen auf dem Slave vorgenommen werden. Beachten Sie ferner, dass Updates auf der Slave-Seite abhängig davon, ob Sie eine anweisungs- oder eine datensatzbasierte Replikation verwenden, unterschiedlich verarbeitet werden können. Betrachten Sie einmal das folgende Szenario, bei dem ein Datensatz auf dem Slave eingefügt wird, gefolgt von einer Anweisung auf Master-Seite, die die Tabelle leert:
slave>INSERT INTO tbl VALUES (1);
master>DELETE FROM tbl;
Der Master weiß nichts über die
INSERT
-Operation auf dem Slave-Server. Bei der
anweisungsbasierten Replikation wird tbl
auf
dem Master und dem Slave geleert, sobald der Slave auf den Stand
des Masters gebracht wird, weil der Master seine
DELETE
-Anweisung dann an den Slave sendet.
Infolgedessen hat tbl
nachfolgend auf beiden
Servern den gleichen Inhalt. Bei der datensatzbasierten
Replikation ist die Wirkung von DELETE
auf den
Slave eine andere. Der Master schreibt nämlich jeden aus der
Tabelle zu löschenden Datensatz in sein Binärlog. Der Slave
löscht daraufhin nur diejenigen Datensätze, die dort erscheinen
– und nicht denjenigen, der direkt auf dem Slave eingefügt
worden war. Hieraus ergeben sich unterschiedliche Inhalte der
Tabellen auf dem Master und dem Slave, was zu
Replikationsproblemen führen kann.
Informationen zur datensatzbasierten Replikation finden Sie in Abschnitt 6.3, „Zeilenbasierte Replikation“.
Die Replikation bietet Vorteile in puncto Robustheit, Geschwindigkeit und Systemadministration:
Die Robustheit wird durch eine Master/Slave-Konfiguration erhöht. Im Fall von Problemen auf dem Master können Sie auf den Slave als Sicherungskopie umschalten.
Eine verbesserte Reaktionszeit lässt sich für Clients
erzielen, indem die Last bei der Verarbeitung von
Clientabfragen auf die Master- und Slave-Server verteilt wird.
SELECT
-Abfragen können an einen Slave
geschickt werden, um die Verarbeitungsbelastung des Masters zu
senken. Allerdings sollten Anweisungen, die Daten verändern,
in jedem Fall an den Master geschickt werden, damit die
Synchronisation zwischen Master und Slaves erhalten bleibt.
Die Lastverteilungsstrategie ist effizient, wenn in erster
Linie nichtändernde Abfragen abgesetzt werden – aber dies
ist auch der Normalfall.
Ein weiterer Vorteil der Replikation besteht darin, dass Sie Datenbanksicherungen über einen Slave-Server durchführen können, ohne den Master zu stören. Der Master verarbeitet dann weiterhin alle Aktualisierungen auch während der Erstellung des Backups. Siehe auch Abschnitt 5.10.1, „Datenbank-Datensicherungen“.
Die MySQL-Replikation basiert darauf, dass der Master-Server alle Änderungen an Ihren Datenbanken (Updates, Löschvorgänge usw.) in seinen Binärlogs vermerkt. Aus diesem Grund müssen Sie das binäre Loggen auf dem Master-Server aktivieren. Siehe auch Abschnitt 5.12.3, „Die binäre Update-Logdatei“.
Alle Slave-Server erhalten vom Master die gespeicherten Änderungen, die der Master in seinem Binärlog vermerkt hat, sodass jeder Slave dieselben Änderungen an seiner Kopie der Daten vornehmen kann.
Es ist extrem wichtig, sich klar zu machen, dass das Binärlog nichts anderes als eine Aufzeichnung darstellt, die zu genau dem Zeitpunkt beginnt, an dem Sie das binäre Loggen aktivieren. Insofern benötigen alle zu konfigurierenden Slaves Kopien der Master-Datenbank mit ihrem Aussehen zum Zeitpunkt der Aktivierung der Binärlogs auf dem Master. Wenn Sie Ihre Slaves mit Datenbanken starten, die nicht hundertprozentig denselben Status haben wie der Master beim Aktivieren der Binärlogs, dann werden höchstwahrscheinlich Probleme auftreten.
Eine Möglichkeit, die Daten des Masters auf den Slave zu
kopieren, besteht im Absetzen der LOAD DATA FROM
MASTER
-Anweisung. Allerdings funktioniert LOAD
DATA FROM MASTER
nur, wenn alle Tabellen auf dem Master
die MyISAM
-Speicher-Engine verwenden. Ferner
erwirkt die Anweisung eine globale Lesesperre, d. h., während
die Tabellen auf den Slave übertragen werden, sind keine Updates
auf dem Master möglich. Sobald wir die Funktion für sperrenfreie
Tabellenbackups im laufenden Betrieb implementiert haben, wird
diese globale Lesesperre nicht mehr erforderlich sein.
Aufgrund dieser Einschränkungen empfehlen wir Ihnen bis auf
weiteres, LOAD DATA FROM MASTER
nur dann zu
verwenden, wenn die Datenmenge auf dem Master relativ gering oder
eine längere Lesesperre auf dem Master hinnehmbar ist. Zwar kann
die tatsächliche Geschwindigkeit von LOAD DATA FROM
MASTER
von System zu System variieren, aber als
Faustregel können Sie eine Übertragungsrate von 1 Mbyte
Daten/Sekunde erwarten. Dies ist ein grober Anhaltspunkt, der aber
recht genau sein sollte, wenn sowohl Master als auch Slave über
700-MHz-Pentium-Prozessoren verfügen und über ein Netzwerk mit
einer Übertragungsrate von 100 Mbit/s miteinander verbunden
sind.
Nachdem auf dem Slave eine Kopie der Master-Daten installiert
wurde, stellt er eine Verbindung zum Master her und wartet auf
Updates, die er verarbeiten kann. Fällt der Master aus oder
verliert der Slave die Verbindung zu ihm, dann versucht er in
regelmäßigen Abständen, die Verbindung neu herzustellen, bis
der Empfang von Updates wieder möglich ist. Die Option
--master-connect-retry
steuert das Intervall, in
dem die Neuverbindung versucht wird. Voreingestellt sind 60
Sekunden.
Jeder Slave vermerkt die Position, an der das Lesen beim letzten Update vom Master-Server beendet wurde. Der Master selbst weiß nicht, wie viele Slaves an ihn angeschlossen sind oder welche Slaves zu einem gegebenen Zeitpunkt aktuell sind.
Die Replikationsfunktionen in MySQL basierten ursprünglich auf der Weitergabe von SQL-Anweisungen vom Master an den Slave. Dies bezeichnete man als anweisungsbasierte Replikation (Statement-Based Replication, SBR). Seit MySQL 5.1.5 gibt es noch eine andere Basis für die Replikation: die datensatzbasierte Replikation (Row-Based Replication, RBR). Statt die SQL-Anweisungen an den Slave zu senden, schreibt der Master alle Ereignisse, die angeben, wie einzelne Datensätze in der Tabelle geändert werden, in sein Binärlog.
Bei der klassischen anweisungsbasierten Replikation kann es Probleme mit der Replikation gespeicherter Routinen geben. Diese Probleme können Sie umgehen, indem Sie stattdessen die datensatzbasierte Replikation benutzen. Eine umfassende Liste möglicher Probleme finden Sie unter Abschnitt 19.4, „Binärloggen gespeicherter Routinen und Trigger“.
Wenn Sie MySQL aus dem Quellcode erstellen, steht die
datensatzbasierte Replikation nur dann zur Verfügung, wenn Sie
configure mit der Option
--with-row-based-replication
aufrufen.
MySQL Server verwendet standardmäßig auch dann die
anweisungsbasierte Replikation, wenn MySQL mit Unterstützung der
datensatzbasierten Replikation konfiguriert wurde. Wenn Sie die
datensatzbasierte Replikation verwenden wollen, starten Sie den
Server mit der Option --binlog-format=row
, um die
datensatzbasierte Replikation global (d. h. für alle
Clientverbindungen) zu aktivieren. Die Option aktiviert
automatisch auch
innodb_locks_unsafe_for_binlog
, was bei der
datensatzbasierten Replikation sicher zu verwenden ist.
Die anweisungsbasierte Replikation kann beim Serverstart entweder
durch Angabe von --binlog-format=statement
oder
durch vollständiges Weglassen der Option
--binlog-format
ausgewählt werden.
Die datensatzbasierte Replikation bewirkt, dass die meisten Änderungen unter Verwendung des datensatzbasierten Formats in das Binärlog geschrieben werden. Allerdings müssen einige Änderungen auch als Anweisungen in das Binärlog geschrieben werden:
ANALYZE TABLE
REPAIR TABLE
OPTIMIZE TABLE
Die Option --binlog-row-event-max-size
ist für
Server verfügbar, die die datensatzbasierte Replikation
unterstützen. Datensätze werden in Blöcken von einer Größe in
das Binärlog geschrieben, die den Wert dieser Option nicht
übersteigt. Der Wert muss ein Vielfaches von 256 sein, Standard
ist 1024.
Die MySQL-Replikation wird unter Verwendung von drei Threads
implementiert: einem auf dem Master und zweien auf dem Slave. Wenn
eine START SLAVE
-Anweisung auf einem
Slave-Server abgesetzt wird, erstellt der Slave einen I/O-Thread,
der eine Verbindung zum Master herstellt und ihn auffordert, die
in seinen Binärlogs aufgezeichneten Änderungen zu senden. Der
Master erstellt daraufhin einen Thread, um die Inhalte des
Binärlogs an den Slave zu senden. Dieser Thread erscheint als
Binlog Dump
in der Ausgabe von SHOW
PROCESSLIST
auf dem Master. Der Slave-I/O-Thread liest
die Aktualisierungen, die der Binlog
Dump
-Thread des Masters sendet, und kopiert diese in
lokale Dateien, die Relay-Logs heißen und
sich im Datenverzeichnis des Slaves befinden. Der dritte Thread
ist der SQL-Thread, den der Slave erstellt, um die Relay-Logs zu
lesen und die enthaltenen Aktualisierungen auszuführen.
In der vorhergehenden Beschreibung wurden drei Threads pro Master/Slave-Verbindung beschrieben. Ein Master, der mehrere Slaves hat, erstellt einen Thread pro aktuell angeschlossenem Slave, und jeder Slave hat seine eigenen I/O- und SQL-Threads.
Der Slave verwendet zwei Threads, d. h., das Lesen der Updates vom Master und ihre Ausführung können auf zwei unabhängige Tasks verteilt werden. Auf diese Weise wird der Task zum Lesen der Anweisungen auch dann nicht verlangsamt, wenn die Anweisungsausführung selbst langsam erfolgt. Wenn beispielsweise der Slave-Server eine Zeit lang nicht ausgeführt wurde und dann gestartet wird, kann sein I/O-Thread schnell alle Inhalte des Binärlogs vom Master holen – und zwar auch dann, wenn der SQL-Thread nicht mitkommt. Sollte der Slave beendet werden, bevor der SQL-Thread alle erhaltenen Anweisungen ausgeführt hat, so hat der I/O-Thread zumindest alles abgerufen, d. h., eine sichere Kopie der Anweisungen ist lokal in den Relay-Logs auf dem Slave gespeichert und kann beim nächsten Start des Servers direkt ausgeführt werden. Auf diese Weise kann der Master-Server seine Binärlogs schneller bereinigen, da er nicht mehr warten muss, bis der Slave die Inhalte abgerufen hat.
Die SHOW PROCESSLIST
-Anweisung vermittelt
Informationen dazu, welche replikationsbezogenen Vorgänge auf
Master und Slave ablaufen. Das folgende Beispiel veranschaulicht,
wie die drei Threads in der Ausgabe von SHOW
PROCESSLIST
erscheinen.
Auf dem Master-Server sieht die Ausgabe von SHOW
PROCESSLIST
wie folgt aus:
mysql> SHOW PROCESSLIST\G
*************************** 1. row ***************************
Id: 2
User: root
Host: localhost:32931
db: NULL
Command: Binlog Dump
Time: 94
State: Has sent all binlog to slave; waiting for binlog to
be updated
Info: NULL
Hierbei ist Thread 2 ein Binlog
Dump
-Replikations-Thread für einen angeschlossenen
Slave. State
gibt an, dass alle anhängigen
Aktualisierungen an den Slave gesendet wurden und der Master
darauf wartet, dass neue Änderungen stattfinden. Wenn keine
Binlog Dump
-Threads auf einem Master vorhanden
sind, bedeutet dies, dass die Replikation nicht ausgeführt wird,
d. h., es sind derzeit keine Slaves angebunden.
Auf dem Slave-Server sieht die Ausgabe von SHOW
PROCESSLIST
wie folgt aus:
*************************** 1. row *************************** Id: 10 User: system user Host: db: NULL Command: Connect Time: 11 State: Waiting for master to send event Info: NULL *************************** 2. row *************************** Id: 11 User: system user Host: db: NULL Command: Connect Time: 11 State: Has read all relay log; waiting for the slave I/O thread to update it Info: NULL
Hieraus ist ersichtlich, dass Thread 10 der I/O-Thread ist, der
mit dem Master-Server kommuniziert. Thread 11 ist der SQL-Thread,
der die Updates verarbeitet, die in den Relay-Logs gespeichert
sind. Zum Zeitpunkt der Ausführung von SHOW
PROCESSLIST
waren beide Threads beschäftigungslos und
warteten auf weitere Aktualisierungen.
Der Wert in der Spalte Time
zeigt ggf., wie
groß der Rückstand zwischen Slave und Master ist. Siehe auch
Abschnitt 6.11, „Replikation: häufig gestellte Fragen“.
Die folgende Liste zeigt die häufigsten Statusangaben, die in
der Spalte State
für den Binlog
Dump
-Thread des Masters erscheinen können. Wenn keine
Binlog Dump
-Threads auf einem Master
vorhanden sind, bedeutet dies, dass die Replikation nicht
ausgeführt wird, d. h., es sind derzeit keine Slaves
angebunden.
Sending binlog event to slave
Binärlogs enthalten Ereignisse, wobei ein Ereignis normalerweise eine Änderung sowie zugehörige Informationen umfasst. Der Thread hat ein Ereignis aus dem Binärlog gelesen und sendet dieses nun an den Slave.
Finished reading one binlog; switching to next
binlog
Der Thread hat das Lesen einer Binärlogdatei beendet und öffnet die nächste, um sie an den Slave zu senden.
Has sent all binlog to slave; waiting for binlog to
be updated
Der Thread hat alle anhängigen Updates aus den Binärlogs gelesen und an den Slave gesendet. Er ist nun untätig und wartet auf neue Ereignisse, die aufgrund von Änderungen am Master in das Binärlog geschrieben werden.
Waiting to finalize termination
Eine nur ganz kurz angezeigte Statusangabe, die besagt, dass der Thread gerade beendet wird.
Die folgende Liste zeigt die häufigsten Statusangaben, die in
der Spalte State
für den I/O-Thread auf dem
Slave-Server erscheinen können. Dieser Status erscheint auch in
der Spalte Slave_IO_State
, die von
SHOW SLAVE STATUS
angezeigt wird. Sie können
also mit dieser Anweisung einen guten Eindruck davon erhalten,
was gerade passiert.
Connecting to master
Der Thread versucht, eine Verbindung zum Master herzustellen.
Checking master version
Eine Statusangabe, die nur ganz kurz angezeigt wird, nachdem die Verbindung zum Master erfolgreich hergestellt werden konnte.
Registering slave on master
Eine Statusangabe, die nur ganz kurz angezeigt wird, nachdem die Verbindung zum Master erfolgreich hergestellt werden konnte.
Requesting binlog dump
Eine Statusangabe, die nur ganz kurz angezeigt wird, nachdem die Verbindung zum Master erfolgreich hergestellt werden konnte. Der Thread fordert beim Master die Inhalte der Binärlogs beginnend bei der angegebenen Binärlogdatei und Position an.
Waiting to reconnect after a failed binlog dump
request
Wenn die Anforderung des Binärlogs fehlgeschlagen ist (etwa
aufgrund eines Verbindungsabbruchs), dann wechselt der
Thread in diesen Status, solange er schläft, versucht aber
in regelmäßigen Abständen, die Verbindung
wiederherzustellen. Das Intervall zwischen den
Verbindungsversuchen kann mit der Option
--master-connect-retry
angegeben werden.
Reconnecting after a failed binlog dump
request
Der Thread versucht, erneut eine Verbindung zum Master herzustellen.
Waiting for master to send event
Der Thread hat die Verbindung zum Master hergestellt und
wartet auf das Eintreffen von Binärlogereignissen. Dies
kann recht lange dauern, wenn der Master untätig ist.
Dauert der Wartevorgang länger als
slave_read_timeout
Sekunden, dann tritt
eine Zeitüberschreitung auf. Der Thread geht dann davon
aus, dass die Verbindung abgebrochen ist, und versucht, sie
neu herzustellen.
Queueing master event to the relay log
Der Thread hat ein Ereignis gelesen und kopiert es in sein Relay-Log, damit der SQL-Thread es verarbeiten kann.
Waiting to reconnect after a failed master event
read
Ein Lesefehler ist aufgetreten (aufgrund eines
Verbindungsabbruchs). Der Thread schläft für
master-connect-retry
Sekunden und
versucht dann, die Verbindung neu herzustellen.
Reconnecting after a failed master event
read
Der Thread versucht, erneut eine Verbindung zum Master
herzustellen. Wenn die Verbindung wiederhergestellt werden
konnte, wechselt der Status zu Waiting for master
to send event
.
Waiting for the slave SQL thread to free enough
relay log space
Sie verwenden einen
relay_log_space_limit
-Wert ungleich null.
Die Relay-Logs sind in ihrer Summe auf eine Größe
angewachsen, die diesen Wert überschreitet. Der I/O-Thread
wartet, bis der SQL-Thread durch die Verarbeitung von
Relay-Log-Inhalten genug Speicher freigegeben hat, sodass
Relay-Logs gelöscht werden können.
Waiting for slave mutex on exit
Eine Statusangabe, die beim Beenden des Threads ganz kurz angezeigt wird.
Die folgende Liste zeigt die häufigsten Statusangaben, die in
der Spalte State
für den SQL-Thread auf dem
Slave-Server erscheinen können.
Reading event from the relay log
Der Thread hat ein Ereignis aus dem Relay-Log gelesen, sodass dieses Ereignis verarbeitet werden kann.
Has read all relay log; waiting for the slave I/O
thread to update it
Der Thread hat alle Ereignisse in den Relay-Log-Dateien verarbeitet und wartet nun darauf, dass der I/O-Thread neue Ereignisse in das Relay-Log schreibt.
Waiting for slave mutex on exit
Eine nur ganz kurz angezeigte Statusangabe, die besagt, dass der Thread gerade beendet wird.
Die Spalte State
für den I/O-Thread kann
auch den Text einer Anweisung anzeigen. Das bedeutet, dass der
Thread ein Ereignis aus dem Relay-Log gelesen und die Anweisung
daraus extrahiert hat und diese nun ausführt.
Standardmäßig haben Dateinamen von Relay-Logs die Form
.
Hierbei ist host_name
-relay-bin.nnnnnn
host_name
der Name des
Slave-Serverhosts und nnnnnn
eine
Sequenznummer. Aufeinander folgende Relay-Log-Dateien werden mit
laufenden Sequenznummern beginnend bei 000001
erstellt. Der Slave verwendet eine Indexdatei, um die Übersicht
über die derzeit verwendeten Relay-Log-Dateien zu behalten. Der
Standardname der Relay-Log-Indexdatei lautet
.
Standardmäßig erstellt der Slave-Server die Relay-Log-Dateien
in seinem Datenverzeichnis. Die Standarddateinamen können mit
den Serveroptionen host_name
-relay-bin.index--relay-log
und
--relay-log-index
außer Kraft gesetzt werden.
Siehe auch Abschnitt 6.9, „Replikationsoptionen in my.cnf“.
Relay-Logs haben dasselbe Format wie Binärlogs und können mit
mysqlbinlog gelesen werden. Der SQL-Thread
löscht eine Relay-Log-Datei automatisch, sobald er alle
Ereignisse in dieser Datei ausgeführt hat und sie nicht mehr
benötigt. Es gibt keine dedizierte Methode zum Löschen von
Relay-Logs – der SQL-Thread kümmert sich selbst darum.
Allerdings rotiert FLUSH LOGS
die Relay-Logs,
was Auswirkungen darauf hat, wann der SQL-Thread sie löscht.
Ein Slave-Server erstellt unter den folgenden Bedingungen eine neue Relay-Log-Datei:
bei jedem Start des I/O-Threads
wenn die Logs – beispielsweise mit FLUSH
LOGS
oder mysqladmin flush-logs
– synchronisiert werden
wenn die aktuelle Relay-Log-Datei zu groß wird. Die Bedeutung von „zu groß“ ermitteln Sie wie folgt:
Wenn der Wert von max_relay_log_size
größer als 0 ist, gibt er die maximale Größe einer
Relay-Log-Datei an.
Wenn der Wert von max_relay_log_size
0 ist, bestimmt max_binlog_size
die
maximale Größe einer Relay-Log-Datei.
Ein Slave-Replikationsserver erstellt zwei weitere kleine
Dateien im Datenverzeichnis. Diese
Statusdateien heißen standardmäßig
master.info
und
relay-log.info
. Die Namen können mit den
Optionen --master-info-file
und
--relay-log-info-file
geändert werden. Siehe
auch Abschnitt 6.9, „Replikationsoptionen in my.cnf“.
Die beiden Statusdateien enthalten Informationen wie die in der
Ausgabe der Anweisung SHOW SLAVE STATUS
gezeigte (siehe auch Abschnitt 13.6.2, „SQL-Anweisungen für die Steuerung von Slave-Servern“).
Weil die Statusdateien auf der Festplatte gespeichert sind,
überdauern sie das Herunterfahren des Slave-Servers. Beim
nächsten Start des Servers liest er die beiden Dateien dann
aus, um zu ermitteln, wie weit er beim Lesen der Binärlogs vom
Master und bei der Verarbeitung der eigenen Relay-Logs gekommen
ist.
Der I/O-Thread aktualisiert die Datei
master.info
. Die folgende Tabelle zeigt die
Entsprechungen zwischen den Zeilen in der Datei und den von
SHOW SLAVE STATUS
angezeigten Spalten.
Zeile | Beschreibung |
1 | Anzahl der Zeilen in der Datei |
2 | Master_Log_File |
3 | Read_Master_Log_Pos |
4 | Master_Host |
5 | Master_User |
6 | Passwort (wird von SHOW SLAVE STATUS nicht angezeigt) |
7 | Master_Port |
8 | Connect_Retry |
9 | Master_SSL_Allowed |
10 | Master_SSL_CA_File |
11 | Master_SSL_CA_Path |
12 | Master_SSL_Cert |
13 | Master_SSL_Cipher |
14 | Master_SSL_Key |
Der SQL-Thread aktualisiert die Datei
relay-log.info
. Die folgende Tabelle zeigt
die Entsprechungen zwischen den Zeilen in der Datei und den von
SHOW SLAVE STATUS
angezeigten Spalten.
Zeile | Beschreibung |
1 | Relay_Log_File |
2 | Relay_Log_Pos |
3 | Relay_Master_Log_File |
4 | Exec_Master_Log_Pos |
Wenn Sie die Daten des Slaves sichern, sollten Sie neben den
Relay-Log-Dateien auch diese beiden Statusdateien sichern. Sie
werden stets benötigt, um die Replikation nach
Wiederherstellung der Daten auf dem Slave fortzusetzen. Wenn Sie
die Relay-Logs verlieren, aber noch über die Datei
relay-log.info
verfügen, können Sie
ermitteln, wie weit der SQL-Thread die Binärlogs des Masters
bereits ausgeführt hatte. Dann können Sie den Slave durch
Absetzen von CHANGE MASTER TO
mit den
Optionen MASTER_LOG_FILE
und
MASTER_LOG_POS
anweisen, die Binärlogs von
diesem Punkt an erneut zu lesen. (Dies setzt natürlich voraus,
dass die Binärlogs noch auf dem Master-Server vorhanden sind.)
Wenn Ihr Slave Gegenstand der Replikation von LOAD DATA
INFILE
-Anweisungen ist, sollten Sie auch alle
SQL_LOAD-*
-Dateien sichern, die in dem vom
Slave zu diesem Zweck verwendeten Verzeichnis vorhanden sind.
Der Slave benötigt diese Dateien, um die Replikation
unterbrochener LOAD DATA INFILE
-Operationen
fortzusetzen. Die Verzeichnisposition wird mit der Option
--slave-load-tmpdir
angegeben. Wird die Option
nicht angegeben, dann bezeichnet der Wert der Systemvariablen
tmpdir
die Verzeichnisposition.
Dieser Abschnitt beschreibt kurz, wie man die vollständige Replikation eines MySQL Servers konfiguriert. Es wird angenommen, dass Sie alle Datenbanken auf dem Master replizieren wollen und die Replikation zuvor noch nicht konfiguriert haben. Sie müssen Ihren Master-Server kurz herunterfahren, um die beschriebenen Schritte vollständig durchführen zu können.
Beschrieben wird der Vorgang für die Konfiguration eines einzelnen Slaves; mehrere Slaves können Sie konfigurieren, indem Sie die entsprechenden Schritte wiederholen.
Zwar ist diese Vorgehensweise die direkteste zur Konfiguration eines Slaves, sie ist aber nicht die einzige. Wenn Sie beispielsweise eine Momentaufnahme der Daten auf dem Master haben und auf diesem bereits die Serverkennung eingestellt und das binäre Loggen aktiviert ist, dann können Sie einen Slave konfigurieren, ohne den Master herunterzufahren oder auch nur Aktualisierungen zu unterbinden. Weitere Informationen finden Sie unter Abschnitt 6.11, „Replikation: häufig gestellte Fragen“.
Wenn Sie eine MySQL-Replikationskonfiguration administrieren wollen, sollten Sie dieses Kapitel vollständig lesen und alle Anweisungen ausprobieren, die in Abschnitt 13.6.1, „SQL-Anweisungen für die Steuerung von Master-Servern“, und Abschnitt 13.6.2, „SQL-Anweisungen für die Steuerung von Slave-Servern“, beschrieben sind. Ferner sollten Sie sich mit den Replikationsstartoptionen vertraut machen, die in Abschnitt 6.9, „Replikationsoptionen in my.cnf“, erläutert werden.
Hinweis: Diese Methode und einige
der replikationsspezifischen SQL-Anweisungen, die in späteren
Abschnitten beschrieben werden, erfordern die Berechtigung
SUPER
.
Vergewissern Sie sich, dass die auf dem Master und dem Slave installierten MySQL-Versionen kompatibel im Sinne der in Abschnitt 6.6, „Replikation: Kompatibilität zwischen MySQL-Versionen“, aufgeführten Tabelle sind. Im Idealfall sollten Sie die jeweils aktuellste MySQL-Version sowohl auf dem Master als auch auf dem Slave verwenden.
Wenn Sie auf ein Problem stoßen, melden Sie dieses bitte erst als Bug, nachdem Sie sich vergewissert haben, dass es auch im aktuellen MySQL-Release vorhanden ist.
Konfigurieren Sie ein Konto auf dem Master-Server, über das
der Slave eine Verbindung herstellen kann. Dieses Konto
benötigt die Berechtigung REPLICATION
SLAVE
. Wenn das Konto ausschließlich zur
Replikation verwendet wird (was wir empfehlen), dann brauchen
Sie keine weiteren Berechtigungen zu gewähren.
Nehmen wir nun an, dass Ihre Domäne
mydomain.com
heißt und dass Sie ein Konto
mit dem Benutzernamen repl
erstellen
wollen, das Slave-Server unter Angabe des Passworts
slavepass
von einem beliebigen Host in
Ihrer Domäne aus für den Zugriff auf den Master verwenden
kann. Dieses Konto erstellen Sie mit folgender
GRANT
-Anweisung:
mysql>GRANT REPLICATION SLAVE ON *.*
->TO 'repl'@'%.mydomain.com' IDENTIFIED BY 'slavepass';
Beabsichtigen Sie, die Anweisungen LOAD TABLE FROM
MASTER
oder LOAD DATA FROM MASTER
auf dem Slave-Host zu verwenden, dann müssen Sie diesem Konto
weitere Berechtigungen gewähren:
Gewähren Sie dem Konto die globalen Berechtigungen
SUPER
und RELOAD
.
Gewähren Sie die Berechtigung SELECT
für alle Tabellen, die Sie laden wollen. Alle
Master-Tabellen, für die das Konto keine
SELECT
-Berechtigung hat, werden von
LOAD DATA FROM MASTER
ignoriert.
Weitere Informationen zur Konfiguration von Benutzerkonten und Berechtigungen finden Sie in Abschnitt 5.9, „MySQL-Benutzerkontenverwaltung“.
Synchronisieren Sie alle Tabellen und unterbinden Sie
Schreibanweisungen, indem Sie eine FLUSH TABLES WITH
READ LOCK
-Anweisung ausführen:
mysql> FLUSH TABLES WITH READ LOCK;
Beachten Sie, dass FLUSH TABLES WITH READ
LOCK
bei InnoDB
-Tabellen auch
COMMIT
-Operationen sperrt. Wenn Sie eine
globale Lesesperre erwirkt haben, können Sie eine
Dateisystem-Momentaufnahme Ihrer
InnoDB
-Tabellen erstellen. Intern (d. h.
innerhalb der InnoDB
-Speicher-Engine) ist
diese Momentaufnahme nicht konsistent, weil die
InnoDB
-Caches nicht synchronisiert wurden,
aber dies ist nicht weiter problematisch, weil
InnoDB
dieses Problem beim Start beseitigt
und ein konsistentes Ergebnis abliefert. Das bedeutet, dass
bei InnoDB
die Wiederherstellung von Daten
nach einem Absturz verlustfrei möglich ist, wenn der Neustart
auf der Basis dieser Momentaufnahme erfolgt. Allerdings gibt
es keine Möglichkeit, den MySQL Server zu beenden und
gleichzeitig eine konsistente Momentaufnahme Ihrer
InnoDB
-Tabellen zu gewährleisten.
Lassen Sie den Client laufen, von dem aus Sie die
FLUSH TABLES
-Anweisung absetzen, damit die
Lesesperre aktiv bleibt. (Wenn Sie den Client beenden, wird
die Sperre aufgehoben.) Erstellen Sie nun eine Momentaufnahme
der Daten auf Ihrem Master-Server.
Die einfachste Möglichkeit zur Erstellung einer Momentaufnahme ist die Verwendung eines Archivierungsprogramms: Hiermit erstellen Sie eine binäre Sicherung der Datenbanken im Datenverzeichnis Ihres Master-Servers. Sie können beispielsweise tar unter Unix oder PowerArchiver, WinRAR, WinZip oder eine ähnliche Software unter Windows verwenden. Um mit tar ein Archiv zu erstellen, das alle Datenbanken enthält, wechseln Sie in das Datenverzeichnis des Master-Servers und führen dann folgenden Befehl aus:
shell> tar -cvf /tmp/mysql-snapshot.tar .
Wollen Sie, dass das Archiv nur eine Datenbank namens
this_db
enthält, dann verwenden Sie
stattdessen folgenden Befehl:
shell> tar -cvf /tmp/mysql-snapshot.tar ./this_db
Danach kopieren Sie die Archivdatei in das Verzeichnis
/tmp
auf dem Slave-Serverhost. Auf diesem
System wechseln Sie nun in das Datenverzeichnis des Slaves und
entpacken die Archivdatei mithilfe des folgenden Befehls:
shell> tar -xvf /tmp/mysql-snapshot.tar
Wenn auf dem Slave-Server andere Benutzerkonten als auf dem
Master vorhanden sind, sollten Sie die Datenbank
mysql
unter Umständen nicht replizieren.
In diesem Fall sollten Sie sie aus dem Archiv ausschließen.
Ferner sollten Sie weder Logdateien noch die Dateien
master.info
oder
relay-log.info
in das Archiv einfügen.
Während die mit FLUSH TABLES WITH READ
LOCK
erwirkte Lesesperre gültig ist, lesen Sie den
Namen des aktuellen Binärlogs und den Versatz auf dem Master
aus:
mysql > SHOW MASTER STATUS;
+---------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+---------------+----------+--------------+------------------+
| mysql-bin.003 | 73 | test | manual,mysql |
+---------------+----------+--------------+------------------+
Die Spalte File
zeigt den Namen der
Logdatei an, Position
den Versatz innerhalb
der Datei. In diesem Beispiel heißt die Binärlogdatei
mysql-bin.003
, der Versatz ist 73. Notieren
Sie diese Werte. Sie benötigen sie später beim Konfigurieren
des Slaves. Die Werte stellen die Replikationskoordinaten dar,
bei denen der Slave die Verarbeitung neuer Updates vom Master
startet.
Wenn der Master zuvor ohne aktiviertes Binärloggen
ausgeführt wurde, sind die von SHOW MASTER
STATUS
oder mysqldump
--master-data angezeigten Werte für Lognamen und
Position leer. In diesem Fall lauten die Werte, die Sie
später als Logdateinamen und Position auf dem Slave angeben
müssen, ''
(Leer-String) und
4
.
Nachdem Sie die Momentaufnahme erstellt und Lognamen und Versatz aufgezeichnet haben, können Sie die Schreibaktivitäten auf dem Master neu starten:
mysql> UNLOCK TABLES;
Wenn Sie InnoDB
-Tabellen einsetzen, sollten
Sie im Idealfall das Tool InnoDB
Hot Backup verwenden, welches ohne Sperre auf dem
Master-Server eine konsistente Momentaufnahme erstellt und
Lognamen und Versatz passend für die Momentaufnahme
speichert, sodass die Angaben später auf dem Slave benutzt
werden können. Hot Backup ist ein
kommerzielles (d. h. nicht kostenloses) Zusatztool, das nicht
Bestandteil der MySQL-Standarddistribution ist. Weitere
Informationen finden Sie auf der Homepage von
InnoDB
Hot Backup unter
http://www.innodb.com/manual.php.
Wenn Sie Hot Backup nicht einsetzen,
besteht die schnellste Methode zur Erstellung einer binären
Momentaufnahme der InnoDB
-Tabellen darin,
den Master-Server herunterzufahren und die Datendateien,
Logdateien und Tabellenformatdateien
(.frm
) von InnoDB
zu
kopieren. Um den aktuellen Logdateinamen und den Versatz
aufzuzeichnen, sollten Sie folgende Anweisungen absetzen,
bevor Sie den Server herunterfahren:
mysql>FLUSH TABLES WITH READ LOCK;
mysql>SHOW MASTER STATUS;
Dann notieren Sie Lognamen und Versatz aus der Ausgabe von
SHOW MASTER STATUS
wie oben beschrieben.
Danach fahren Sie den Server herunter,
ohne die Tabellen zu entsperren;
hierdurch ist sicherstellt, dass der Server mit einem Status
beendet wird, der den Angaben zu Logdatei und Versatz
entspricht:
shell> mysqladmin -u root shutdown
Eine Alternative, die sowohl bei MyISAM
-
als auch bei InnoDB
-Tabellen funktioniert,
besteht darin, einen SQL-Speicherauszug des Masters anstatt
– wie oben beschrieben – einer binären Kopie zu
erstellen. Hierzu führen Sie mysqldump
--master-data auf dem Master aus und laden die
SQL-Speicherauszugsdatei später in Ihren Slave. Allerdings
ist die Erstellung einer binären Kopie schneller.
Vergewissern Sie sich, dass der Abschnitt
[mysqld]
der Datei
my.cnf
auf dem Master-Host die Option
log-bin
enthält. Der Abschnitt sollte
ferner eine Option
server-id=
enthalten, wobei master_id
master_id
ein
positiver Integer zwischen 1 und
232 – 1 sein muss. Zum
Beispiel:
[mysqld] log-bin=mysql-bin server-id=1
Wenn diese Optionen nicht vorhanden sind, fügen Sie sie hinzu und starten den Server neu. Der Server kann erst als Replikationsmaster agieren, wenn das binäre Loggen aktiviert ist.
Hinweis: Um die größtmögliche Dauerhaftigkeit und
Konsistenz in einer Replikationskonfiguration für
InnoDB
mit Transaktionen zu erzielen,
sollten Sie
innodb_flush_log_at_trx_commit=1
und
sync_binlog=1
in der Datei
my.cnf
auf dem Master angeben.
Beenden Sie den Server, der als Slave vorgesehen ist, und
fügen Sie in seiner Datei my.cnf
die
folgenden Zeilen hinzu:
[mysqld]
server-id=slave_id
Der Wert slave_id
muss wie
master_id
auch ein positiver
Integer zwischen 1 und 232 –
1 sein. Ferner muss sich die Kennung des Slaves von der des
Masters unterscheiden. Zum Beispiel:
[mysqld] server-id=2
Wenn Sie mehrere Slaves konfigurieren, muss jeder einen
eindeutigen server-id
-Wert haben, der sich
von dem des Masters und von denen aller anderen Slaves
unterscheidet. Betrachten Sie
server-id
-Werte als etwas Ähnliches wie
IP-Adressen: Diese Kennungen identifizieren jede Serverinstanz
in der Gruppe der Replikationspartner eindeutig.
Wenn Sie keinen server-id
-Wert angeben,
wird er auf 1 gesetzt, sofern Sie
master-host
nicht definiert haben;
andernfalls wird der Wert auf 2 gesetzt. Beachten Sie, dass,
wenn Sie server-id
weglassen, ein Master
Verbindungen aller Slaves abweist und auch ein Slave sich
weigert, eine Verbindung mit einem Master herzustellen. Auf
diese Weise ist das Übergehen von
server-id
nur für ein Backup mit einem
Binärlog geeignet.
Wenn Sie eine binäre Sicherung der Daten auf dem Master-Server erstellt haben, kopieren Sie sie in das Datenverzeichnis des Slaves, bevor Sie diesen starten. Stellen Sie sicher, dass die Berechtigungen für Dateien und Verzeichnisse korrekt sind. Das Systemkonto, über das Sie den Slave-Server ausführen, muss die Dateien wie beim Master auch lesen und schreiben können.
Wenn Sie ein Backup mit mysqldump erstellen, starten Sie den Slave zuerst. Die Speicherauszugsdatei wird in einem späteren Schritt geladen.
Starten Sie den Slave-Server. Erfolgte bereits früher eine
Replikation, dann starten Sie den Slave mit der Option
--skip-slave-start
, damit er nicht sofort
versucht, eine Verbindung mit dem Master herzustellen. Sie
sollten den Slave-Server außerdem mit der Option
--log-warnings
starten, um im Falle von
Problemen (z. B. Netzwerk- oder Verbindungsproblemen) mehr
Meldungen im Fehlerlog zu erhalten. Die Option ist
standardmäßig aktiviert, aber abgebrochene Verbindungen
werden nicht im Fehlerlog vermerkt, sofern der Optionswert
nicht größer als 1 ist.
Wenn Sie mit mysqldump ein Backup der Daten auf dem Master-Server erstellt haben, laden Sie die Speicherauszugsdatei in den Slave-Server:
shell> mysql -u root -p < dump_file.sql
Führen Sie die folgende Anweisung auf dem Slave aus und ersetzen Sie dabei die Optionswerte durch die für Ihr System geeigneten Werte:
mysql>CHANGE MASTER TO
->MASTER_HOST='
->master_host_name
',MASTER_USER='
->replication_user_name
',MASTER_PASSWORD='
->replication_password
',MASTER_LOG_FILE='
->recorded_log_file_name
',MASTER_LOG_POS=
recorded_log_position
;
Die folgende Tabelle zeigt die maximal zulässige Länge bei Optionen, die String-Werte enthalten:
MASTER_HOST | 60 |
MASTER_USER | 16 |
MASTER_PASSWORD | 32 |
MASTER_LOG_FILE | 255 |
Starten Sie die Slave-Threads:
mysql> START SLAVE;
Nachdem Sie diesen Vorgang durchgeführt haben, sollte der Slave eine Verbindung mit dem Master herstellen und alle Updates nachholen, die seit Erstellung der Momentaufnahme erstellt wurden.
Wenn Sie es versäumt haben, die Option
server-id
für den Master einzustellen, dann
können Slaves keine Verbindung herstellen.
Wenn Sie es versäumt haben, die Option
server-id
für den Slave einzustellen, dann
erhalten Sie im Fehlerlog des Slaves die folgende Meldung:
Warning: You should set server-id to a non-0 value if master_host is set; we will force server id to 2, but this MySQL server will not act as a slave.
Ferner werden Sie Fehlermeldungen im Fehlerlog des Slaves vorfinden, wenn eine Replikation aus irgendeinem anderen Grund nicht möglich ist.
Sobald ein Slave mit der Replikation begonnen hat, finden Sie in
seinem Datenverzeichnis zwei Dateien namens
master.info
und
relay-log.info
. Der Slave verwendet diese
beiden Dateien, um zu vermerken, welcher Anteil des
Master-Binärlogs bereits verarbeitet wurde. Sie dürfen diese
Dateien keinesfalls entfernen oder
bearbeiten, sofern Sie nicht genau wissen, was Sie tun und welche
Auswirkungen dies haben kann. Und auch in diesem Fall sollten Sie
besser die CHANGE MASTER TO
-Anweisung
verwenden, um die Replikationsparameter zu ändern. Der Slave
aktualisiert die Statusdateien automatisch entsprechend den
Werten, die in dieser Anweisung angegeben sind.
Hinweis: Der Inhalt von
master.info
setzt einige der Serveroptionen,
die auf der Befehlszeile oder in der Datei
my.cnf
angegeben sind, außer Kraft. Weitere
Informationen finden Sie in
Abschnitt 6.9, „Replikationsoptionen in my.cnf“.
Sobald Sie über eine Momentaufnahme des Masters verfügen, können Sie diese zur Konfiguration weiterer Slaves verwenden. Folgen Sie dabei einfach der oben beschriebenen Anleitung. Sie müssen also keine neue Momentaufnahme erstellen, sondern können dieselbe auch für jeden weiteren Slave verwenden.
Das Binärlogformat, wie es in MySQL 5.1
implementiert ist, unterscheidet sich erheblich von dem vorheriger
Versionen. Dies gilt insbesondere für den Umgang mit
Zeichensätzen, LOAD DATA INFILE
und Zeitzonen.
Wir empfehlen die Verwendung der jeweils aktuellen MySQL-Version, weil die Replikationsfunktionen kontinuierlich verbessert werden. Ferner empfehlen wir die Verwendung derselben Version auf Master und Slave. Empfohlen wird außerdem die Aktualisierung von Mastern und Slaves, die unter Alpha- oder Betaversionen laufen, auf neue (Produktions-)Versionen. In vielen Fällen schlägt die Replikation von einem neueren Master auf einen älteren Slave fehl. Generell können Slaves, die unter MySQL 5.1.x laufen, mit älteren Mastern (sogar solchen unter MySQL 3.23, 4.0 oder 4.1) verwendet werden, nicht jedoch umgekehrt.
Hinweis: Sie dürfen keinesfalls eine Replikation von einem Master, der ein neueres Binärlogformat aufweist, auf einen Slave durchführen, der ein älteres Format benutzt (z. B. von MySQL 5.0 auf MySQL 4.1). Dies hat gravierende Auswirkungen auf die Aktualisierung von Replikationsservern (siehe auch Abschnitt 6.7, „Upgrade eines Replikationssetups“).
Diese Angaben beziehen sich auf die Replikationskompatibilität auf Protokollebene. Es gibt weitere Einschränkungen, z. B. bei Fragen der Kompatibilität auf SQL-Ebene. So kann etwa ein Master unter 5.1 keine Replikation auf einen Slave unter 5.0 durchführen, wenn die replizierten Anweisungen SQL-Funktionen verwenden, die zwar in 5.1, nicht aber in 5.0 vorhanden sind. Diese und andere Probleme werden in Abschnitt 6.8, „Replikation: Features und bekannte Probleme“, behandelt.
Wenn Sie Server aktualisieren, die Bestandteile einer Replikationskonfiguration sind, hängt die Vorgehensweise zur Aktualisierung von den aktuellen Serverversionen und der Version ab, auf die Sie aktualisieren.
Dieser Abschnitt betrifft die Aktualisierung der Replikation von MySQL 3.23, 4.0 oder 4.1 auf MySQL 5.1. Ein 4.0-Server sollte unter Version 4.0.3 oder höher laufen.
Wenn Sie einen Master von einer früheren MySQL-Release-Serie auf 5.1 aktualisieren, dann müssen Sie zuallererst einmal gewährleisten, dass alle Slaves dieses Masters denselben 5.1.x-Release verwenden. Ist dies nicht der Fall, dann sollten Sie zuerst die Slaves aktualisieren. Um einen Slave zu aktualisieren, fahren Sie ihn herunter, aktualisieren ihn auf die entsprechende Version 5.1.x und starten nachfolgend zunächst den Server und dann die Replikation neu. Der 5.1-Slave kann alte Relay-Logs, die vor dem Upgrade geschrieben wurden, lesen und die enthaltenen Anweisungen ausführen. Relay-Logs, die vom Slave nach dem Upgrade erstellt wurden, haben bereits das 5.1-Format.
Nachdem die Slaves aktualisiert wurden, fahren Sie den Master herunter, aktualisieren ihn auf denselben 5.1.x-Release wie die Slaves und starten ihn dann neu. Der 5.1-Master kann alte Binärlogs, die vor dem Upgrade geschrieben wurden, lesen und an die 5.1-Slaves schicken. Die Slaves erkennen das alte Format und verarbeiten es entsprechend. Binärlogs, die vom Master nach dem Upgrade erstellt wurden, haben bereits das 5.1-Format. Auch diese werden von den 5.1-Slaves erkannt.
Es sind also bei der Aktualisierung auf MySQL 5.1 keine weiteren Maßnahmen durchzuführen – Sie müssen lediglich beachten, dass Sie ggf. zuerst die Slaves auf MySQL 5.1 aktualisieren, bevor Sie dies beim Master tun. Beachten Sie, dass ein Downgrade von 5.1 auf ältere Versionen nicht so einfach ist: Sie müssen gewährleisten, dass alle Binär- und Relay-Logs im 5.1-Format vollständig verarbeitet wurden, damit Sie sie entfernen können, bevor Sie mit dem Downgrade fortfahren.
Das Downgrade einer Replikationskonfiguration auf eine ältere Version ist nicht mehr möglich, wenn Sie von der anweisungs- auf die datensatzbasierte Replikation umgestellt haben und die erste datensatzbasierte Anweisung in das Binärlog geschrieben wurde. Siehe auch Abschnitt 6.3, „Zeilenbasierte Replikation“.
Generell erfordert die Replikationskompatibilität auf SQL-Ebene,
dass alle verwendeten Funktionen sowohl vom Master als auch vom
Slave unterstützt werden. Wenn Sie eine Funktion auf einem
Master-Server verwenden, die nur ab einer bestimmten MySQL-Version
verfügbar ist, dann können Sie keine Replikation auf einen Slave
vornehmen, der älter ist als diese Version. Derartige
Inkompatibilitäten treten häufig zwischen verschiedenen Serien
auf. So können Sie beispielsweise keine Replikation von MySQL
5.1 auf 5.0 durchführen. Allerdings
können solche Inkompatibilitäten auch innerhalb derselben Serie
auftreten. So ist beispielsweise die Funktion
SLEEP()
seit MySQL 5.0.12 verfügbar. Wenn Sie
diese Funktion auf dem Master-Server verwenden, können Sie sie
nicht auf einen Slave replizieren, der älter ist als MySQL
5.0.12.
Beabsichtigen Sie, die Replikation zwischen MySQL 5.1 und einer älteren Version durchzuführen, dann sollten Sie im MySQL-Referenzhandbuch zu dieser älteren Release-Serie nach Informationen zu den Replikationseigenschaften dieser Serie suchen.
Die folgende Liste enthält genauere Angaben dazu, was
unterstützt wird und was nicht. Zusätzliche
InnoDB
-spezifische Informationen zur
Replikation finden Sie in
Abschnitt 14.2.6.5, „InnoDB
und MySQL-Replikation“.
Bei der klassischen anweisungsbasierten Replikation kann es Probleme mit der Replikation gespeicherter Routinen geben. Diese Probleme können Sie umgehen, indem Sie stattdessen die datensatzbasierte Replikation benutzen. Eine umfassende Liste möglicher Probleme finden Sie unter Abschnitt 19.4, „Binärloggen gespeicherter Routinen und Trigger“. Eine Beschreibung der datensatzbasierten Replikation finden Sie in Abschnitt 6.3, „Zeilenbasierte Replikation“.
Die Replikation von AUTO_INCREMENT
-,
LAST_INSERT_ID()
- und
TIMESTAMP
-Werten erfolgt korrekt.
Die Funktionen USER()
,
UUID()
und LOAD_FILE()
werden ohne Änderung repliziert und funktionieren daher nur
dann korrekt auf dem Slave, wenn die datensatzbasierte
Replikation aktiviert ist. (Siehe auch
Abschnitt 6.3, „Zeilenbasierte Replikation“.)
Die folgende Beschränkung gilt nur für die
anweisungsbasierte, nicht für die datensatzbasierte
Replikation. Die Funktionen
GET_LOCK()
,
RELEASE_LOCK()
,
IS_FREE_LOCK()
und
IS_USED_LOCK()
, die Sperren auf
Benutzerebene verwalten, werden repliziert, ohne dass der
Slave den zugehörigen Kontext auf dem Master kennt. Aus
diesem Grund sollten diese Funktionen nicht zum Einfügen in
eine Tabelle auf dem Master verwendet werde, da der Kontext
auf dem Slave ganz anders aussehen würde. (So sollten Sie
etwa keine Anweisung wie INSERT INTO mytable
VALUES(GET_LOCK(...))
absetzen.)
Die Variablen FOREIGN_KEY_CHECKS
,
SQL_MODE
, UNIQUE_CHECKS
und SQL_AUTO_IS_NULL
werden (ab MySQL 5.0)
alle repliziert. Die Systemvariable
storage_engine
(die auch
table_type
heißt) wird in MySQL 5.1 noch
nicht repliziert, was für die Replikation zwischen
verschiedenen Speicher-Engines von Vorteil ist.
Die Replikation funktioniert zwischen Mastern und Slaves unter MySQL 5.0 und 5.1 in beliebiger Kombination – auch dann, wenn Master und Slave unterschiedliche Werte für die Zeichensatz- und/oder die globalen Zeitzonenvariablen aufweisen. (Beachten Sie, dass dies nicht in Fällen zutrifft, in denen Master und/oder Slave unter MySQL 4.1 oder früher laufen.)
Folgendes gilt für die Replikation zwischen MySQL Servern, die unterschiedliche Zeichensätze benutzen:
Wenn der Master MySQL 4.1 verwendet, müssen Sie
immer dieselben
globalen Werte für Zeichensatz und
Sortierfolge auf dem Master und dem Slave verwenden –
unabhängig davon, welche MySQL-Version auf dem Slave
läuft. (Diese werden von den Optionen
--character-set-server
und
--collation-server
gesteuert.)
Andernfalls kann es Fehler aufgrund von
Schlüsseldubletten auf dem Slave geben, da ein
Schlüssel, der im Zeichensatz des Masters eindeutig ist,
dies im Zeichensatz des Slaves nicht unbedingt sein muss.
Beachten Sie, dass dies keine Rolle mehr spielt, wenn
Master und Slave beide unter MySQL 5.0 oder höher laufen.
Wenn der Master älter ist als MySQL 4.1.3, dann sollte
auf den beteiligten Clients kein anderer Zeichensatz als
der global angegebene verwendet werden, weil der Slave
eine solche Änderung des Zeichensatzes nicht bemerkt.
Clients sollten also SET NAMES
,
SET CHARACTER SET
usw. nicht benutzen.
Wenn sowohl Master als auch Slave unter 4.1.3 oder höher
laufen, können die Clients die zeichensatzbezogenen
Sitzungsvariablen frei einstellen, da diese Werte in das
Binärlog geschrieben und auf diese Weise dem Slave
mitgeteilt werden. Clients können also SET
NAMES
oder SET CHARACTER SET
verwenden oder Variablen wie
COLLATION_CLIENT
oder
COLLATION_SERVER
einstellen. Nicht
ändern können Clients hingegen den
globalen Wert dieser Variablen: Wie
bereits gesagt, Master und Slave müssen für den globalen
Zeichensatz immer identische Werte aufweisen.
Wenn sich auf dem Master Datenbanken mit Zeichensätzen
befinden, die sich vom globalen
character_set_server
-Wert
unterscheiden, dann sollten Sie Ihre CREATE
TABLE
-Anweisungen so formulieren, dass Tabellen
in diesen Datenbanken nicht implizit auf den
Standardzeichensatz der Datenbank angewiesen sind (siehe
auch Bug 2326). Ein guter Workaround hierfür besteht
darin, in der CREATE TABLE
-Anweisung
Zeichensatz und Sortierfolge explizit anzugeben.
Wenn der Master MySQL 4.1 verwendet, dann sollte auf Master
und Slave dieselbe Systemzeitzone eingestellt sein.
Andernfalls werden einige Anweisungen – wie etwa solche, die
die Funktionen NOW()
oder
FROM_UNIXTIME()
verwenden – nicht korrekt
repliziert. Sie können die Zeitzone, in der der MySQL Server
läuft, mit der Option
--timezone=
des Skripts timezone_name
mysqld_safe
oder durch
Einstellen der Umgebungsvariablen TZ
ändern. Master und Slave sollten ferner auch dieselbe
Standardeinstellung für die Verbindungszeitzone aufweisen,
d. h., der Wert des Parameters
--default-time-zone
sollte auf Master und
Slave gleich sein. Beachten Sie, dass dies nicht notwendig
ist, wenn der Master unter MySQL 5.0 oder höher läuft.
CONVERT_TZ(...,...,@session.time_zone)
wird
nur dann korrekt repliziert, wenn Master und Slave unter MySQL
5.0.4 oder höher laufen.
Sitzungsvariablen werden nicht korrekt repliziert, wenn sie in
Anweisungen verwendet werden, die Tabellen aktualisieren. So
fügt SET MAX_JOIN_SIZE=1000
gefolgt von
INSERT INTO mytable VALUES(@MAX_JOIN_SIZE)
auf dem Master nicht dieselben Daten ein wie auf dem Slave.
Dies betrifft allerdings nicht die gängige Sequenz aus
SET TIME_ZONE=...
gefolgt von
INSERT INTO mytable
VALUES(CONVERT_TZ(...,...,@time_zone))
.
Die Replikation von Sitzungsvariablen ist kein Problem, wenn die datensatzbasierte Replikation benutzt wird. Siehe auch Abschnitt 6.3, „Zeilenbasierte Replikation“.
Es ist auch möglich, transaktionssichere Tabellen auf dem
Master in nichttransaktionssichere Tabellen auf dem Slave zu
replizieren. Sie können beispielsweise eine
InnoDB
-Tabelle auf dem Master als
MyISAM
-Tabelle auf dem Slave replizieren.
Allerdings kommt es, wenn Sie dies tun, zu Problemen, wenn der
Slave mitten in einem
BEGIN
/COMMIT
-Block
angehalten wird, weil er nachfolgend am Anfang des
BEGIN
-Blocks neu einstartet. Dieses Problem
steht auf unserer Aufgabenliste und wird in Bälde behoben
sein.
Änderungsanweisungen, die benutzerdefinierte Variablen (also
Variablen des Typs
@
)
referenzieren, werden korrekt repliziert. (Dies gilt jedoch
nicht für Versionen vor 4.1.) Beachten Sie, dass beginnend
mit MySQL 5.0 bei den Namen von Benutzervariablen die
Groß-/Kleinschreibung unterschieden wird, wenn Sie die
Replikation zwischen MySQL 5.0 und älteren Versionen
einrichten.
var_name
Slaves können unter Verwendung von SSL eine Verbindung zum Master herstellen.
Die globale Systemvariable
slave_transaction_retries
wirkt sich wie
folgt auf die Replikation aus: Wenn ein SQL-Thread auf einem
Replikationsslave eine Transaktion nicht ausführen kann, weil
eine InnoDB
-Blockade aufgetreten ist oder
die Werte innodb_lock_wait_timeout
von
InnoDB
bzw.
TransactionDeadlockDetectionTimeout
oder
TransactionInactiveTimeout
von
NDBCluster
überschritten wurden, erfolgt
die durch slave_transaction_retries
angegebene Anzahl von Neuversuchen, bevor der Vorgang mit
einer Fehlermeldung beendet wird. Der Standardwert ist 10. Die
Gesamtzahl der Neuversuche finden Sie in der Ausgabe von
SHOW STATUS
. (Siehe auch
Abschnitt 5.2.4, „Server-Statusvariablen“.)
Wenn eine der Tabellenoptionen DATA
DIRECTORY
oder INDEX DIRECTORY
in
einer CREATE TABLE
-Anweisung auf dem
Master-Server verwendet wird, wird dieselbe Option auch auf
dem Slave umgesetzt. Dies kann zu Problemen führen, wenn im
Dateisystem des Slave-Hosts kein entsprechendes Verzeichnis
vorhanden ist, oder wenn es zwar vorhanden ist, aber der
Slave-Server nicht darauf zugreifen kann. MySQL unterstützt
eine sql_mode
-Option namens
NO_DIR_IN_CREATE
. Wenn dieser SQL-Modus am
Slave-Server aktiviert ist, ignoriert der Slave die
Tabellenoptionen DATA DIRECTORY
und
INDEX DIRECTORY
beim Replizieren von
CREATE TABLE
-Anweisungen. Infolgedessen
werden die MyISAM
-Daten- und Indexdateien
im Datenbankverzeichnis der Tabelle erstellt.
Die folgende Beschränkung betrifft nur die anweisungsbasierte Replikation, nicht die datensatzbasierte Replikation: Die Daten auf dem Master und dem Slave können verschieden werden, wenn eine Abfrage so formuliert wird, dass die Datenänderung nichtdeterministisch ist, d. h. dem Gutdünken des Abfrageoptimierers überlassen wird. (Dies ist auch abgesehen von der Replikation nicht zu empfehlen.) Eine umfassende Erläuterung dieses Problems finden Sie unter Abschnitt A.8.1, „Offene Probleme in MySQL“.
FLUSH LOGS
, FLUSH
MASTER
, FLUSH SLAVE
und
FLUSH TABLES WITH READ LOCK
werden nicht
geloggt, weil dies bei der Replikation auf einen Slave
Probleme verursachen würde. Ein Syntaxbeispiel finden Sie in
Abschnitt 13.5.5.2, „FLUSH
“. Die Anweisungen FLUSH
TABLES
, ANALYZE TABLE
,
OPTIMIZE TABLE
und REPAIR
TABLE
werden in das Binärlog geschrieben und
infolgedessen auf die Slaves repliziert. Dies ist
normalerweise unproblematisch, weil diese Anweisungen die
Tabellendaten nicht verändern. Allerdings kann dies unter
bestimmten Umständen trotzdem Probleme verursachen. Wenn Sie
die Berechtigungstabellen in der
mysql
-Datenbank replizieren und diese
Tabellen direkt und ohne Verwendung von
GRANT
aktualisieren, müssen Sie eine
FLUSH PRIVILEGES
-Anweisung auf den Slaves
absetzen, damit die neuen Berechtigungen gültig werden.
Ferner müssen Sie, wenn Sie FLUSH TABLES
beim Umbenennen einer MyISAM
-Tabelle
absetzen, die Teil einer MERGE
-Tabelle ist,
auf den Slaves eine FLUSH TABLES
-Anweisung
manuell absetzen. Diese Anweisungen werden in das Binärlog
geschrieben, sofern Sie nicht
NO_WRITE_TO_BINLOG
oder den Alias
LOCAL
angegeben haben.
MySQL unterstützt genau einen Master und mehrere Slaves.
Zukünftig beabsichtigen wir, einen Votieralgorithmus
hinzuzufügen, der den Master automatisch wechselt, falls
Probleme in Verbindung mit dem aktuellen Master auftreten.
Ferner werden wir Agentenprozesse zur Durchführung einer
Lastverteilung implementieren, indem
SELECT
-Anweisungen an verschiedene Slaves
gesendet werden.
Wenn ein Server heruntergefahren wird und neu startet, werden
seine MEMORY
-Tabellen geleert. Der Master
repliziert diesen Effekt wie folgt auf seine Slaves: Wenn der
Master eine MEMORY
-Tabelle nach dem Start
zum ersten Mal verwendet, loggt er ein Ereignis, welches den
Slaves angibt, dass die Tabelle geleert werden muss, indem
eine DELETE
-Anweisung für die betreffende
Tabelle in das Binärlog geschrieben wird. Weitere
Informationen finden Sie in
Abschnitt 14.4, „Die MEMORY
-Speicher-Engine“.
Beachten Sie, dass das Folgende nicht gilt, wenn die datensatzbasierte Replikation verwendet wird, denn diese erfordert überhaupt keine Replikation von Temporärtabellen. (Siehe auch Abschnitt 6.3, „Zeilenbasierte Replikation“.)
Temporärtabellen werden normalerweise repliziert. Eine Ausnahme liegt vor, wenn Sie den Slave-Server (und nicht nur die Slave-Threads) heruntergefahren und Temporärtabellen repliziert haben, die in Updates verwendet werden, welche noch nicht auf dem Slave ausgeführt wurden. Haben Sie den Slave-Server heruntergefahren, dann stehen die Temporärtabellen, die von diesen Aktualisierungen benötigt werden, beim Neustart des Servers nicht mehr zur Verfügung. Um dieses Problem zu umgehen, fahren Sie den Slave nicht herunter, solange Temporärtabellen geöffnet sind. Stattdessen wenden Sie folgende Vorgehensweise an:
Setzen Sie eine STOP SLAVE
-Anweisung
ab.
Überprüfen Sie mit SHOW STATUS
den
Wert der Variablen
Slave_open_temp_tables
.
Wenn der Wert 0 ist, beenden Sie den Slave mit einem mysqladmin shutdown-Befehl.
Ist der Wert nicht 0, dann starten Sie die Slave-Threads
mit START SLAVE
neu.
Wiederholen Sie den Vorgang nachfolgend so oft, bis die
Variable Slave_open_temp_tables
0 ist
und Sie den Slave beenden können.
Die Verbindung mit Servern in einer
Master/Slave-Zirkelbeziehung ist sicher, wenn Sie die Option
--log-slave-updates
benutzen. Das bedeutet,
dass Sie eine Konfiguration wie die folgende erstellen
können:
A -> B -> C -> A
Allerdings funktionieren viele Anweisungen in einer solchen Konfiguration nicht einwandfrei, sofern Ihr Code nicht so formuliert ist, dass potenzielle Probleme berücksichtigt werden, die aufgrund von auf verschiedenen Servern in unterschiedlicher Reihenfolge durchgeführten Updates entstehen können.
Serverkennungen werden in Binärlogereignisse kodiert, d. h.,
Server A erkennt, wenn ein Ereignis, das er liest,
ursprünglich von ihm selbst erstellt worden ist, und führt
es dann nicht aus (es sei denn, Server A wurde mit der Option
--replicate-same-server-id
gestartet, die
aber nur in wenigen Fällen wichtig ist). Es kommt also nicht
zu Endlosschleifen. Eine solche Zirkelkonfiguration
funktioniert nur, wenn Sie keine Updates durchführen, durch
die es zu Konflikten zwischen Tabellen kommt: Wenn Sie Daten
sowohl auf A als auch auf C einfügen, sollten Sie keinesfalls
einen Datensatz auf A einfügen, dessen Schlüssel unter
Umständen mit einem Datensatz auf C kollidiert. Ebenso wenig
sollten Sie dieselben Datensätze auf zwei Servern
aktualisieren, wenn die Reihenfolge, in der die Updates
durchgeführt werden, von Bedeutung ist.
Wenn eine Anweisung auf einem Slave einen Fehler erzeugt, wird
der Slave-SQL-Thread terminiert, und der Slave schreibt eine
Meldung in sein Fehlerlog. In diesem Fall sollten Sie manuell
eine Verbindung zum Slave herstellen und die Ursache des
Problems bestimmen. (Hierfür ist SHOW SLAVE
STATUS
recht praktisch.) Danach beheben Sie das
Problem (z. B. durch Erstellen einer nichtvorhandenen
Tabelle) und führen dann START SLAVE
aus.
Einen Master-Server herunterzufahren und später neu zu
starten ist sicher. Wenn ein Slave seine Verbindung zum Master
verliert, versucht er sofort eine Neuverbindung und wiederholt
diesen Versuch in regelmäßigen Abständen, bis er
erfolgreich ist. Standardmäßig erfolgt alle 60 Sekunden ein
Versuch zur Neuverbindung. Dies lässt sich mit der Option
--master-connect-retry
ändern. Ein Slave
kann auch mit Ausfällen der Netzwerkkonnektivität
zurechtkommen. Allerdings bemerkt er einen solchen Ausfall
erst, wenn er für slave_net_timeout
Sekunden keine Daten vom Master empfangen hat. Sind die
Ausfälle kurz, dann sollten Sie den Wert von
slave_net_timeout
verringern. Siehe auch
Abschnitt 5.2.2, „Server-Systemvariablen“.
Das (saubere) Herunterfahren des Slaves ist auch sicher, weil
er vermerkt, an welcher Stelle er beendet wurde. Unsauberes
Herunterfahren hingegen kann insbesondere dann Probleme
verursachen, wenn der Festplatten-Cache vor Terminierung des
Systems nicht auf die Festplatte geschrieben worden war. Ihre
Systemfehlertoleranz erhöht sich erheblich, wenn Sie eine
gute unterbrechungsfreie Stromversorgung verwenden. Eine
unsaubere Beendigung des Masters kann Inkonsistenzen zwischen
dem Inhalt der Tabellen und dem Binärlog auf dem Master zur
Folge haben. Dies lässt sich durch Verwendung von
InnoDB
-Tabellen und der Option
--innodb-safe-binlog
auf dem Master
vermeiden. Siehe auch Abschnitt 5.12.3, „Die binäre Update-Logdatei“.
Hinweis:
--innodb-safe-binlog
wird in MySQL 5.1 nicht
benötigt, weil es durch die in MySQL 5.0 eingeführte
Unterstützung von XA-Transaktionen obsolet geworden ist.
Siehe auch Abschnitt 13.4.7, „XA-Transaktionen“.
Aufgrund des nichttransaktionssicheren Wesens von
MyISAM
-Tabellen kann es vorkommen, dass
eine Anweisung eine Tabelle nur teilweise aktualisiert und
dann einen Fehlercode zurückgibt. Dies kann beispielsweise
beim Einfügen mehrerer Datensätze geschehen, wenn einer
dieser Datensätze gegen einen Schlüssel-Constraint
verstößt, oder wenn eine lange Update-Anweisung nach
Aktualisierung einer Anzahl von Datensätzen terminiert wurde.
Wenn dies auf dem Master passiert, wird der Slave-Thread
beendet. Es liegt dann am Datenbankadministrator, zu
entscheiden, was zu tun ist, sofern der Fehlercode nicht
zulässig ist und die Ausführung der Anweisung auf dem Slave
denselben Fehlercode verursacht. Wenn dieses Verhalten der
Fehlercodeauswertung nicht gewünscht ist, können einige oder
alle Fehler mit der Option
--slave-skip-errors
maskiert (d. h.
ignoriert) werden.
Wenn Sie transaktionssichere Tabellen aus
nichttransaktionssicheren Tabellen in einer
BEGIN
/COMMIT
-Sequenz
aktualisieren, sind die Änderungen im Binärlog unter
Umständen nicht synchron zu den Tabellenzuständen, wenn die
nichttransaktionssichere Tabelle aktualisiert wird, bevor die
Transaktion übergeben wird. Die Ursache hierfür ist, dass
die Transaktion erst dann in das Binärlog geschrieben wird,
wenn sie übergeben wird.
In Situationen, in denen Transaktionen Updates für transaktionssichere und nichttransaktionssichere Tabellen vermischen, ist die Reihenfolge der Anweisungen im Binärlog korrekt, und alle erforderlichen Anweisungen werden – auch bei einem Rollback – in das Binärlog geschrieben. Aktualisiert allerdings eine zweite Verbindung die nichttransaktionssichere Tabelle, bevor die Transaktion der ersten Verbindung abgeschlossen ist, dann kann die geloggte Anweisungsreihenfolge falsch sein, weil die Änderung der zweiten Verbindung unmittelbar nach ihrer Ausführung geschrieben wird – unabhängig von dem Zustand der Transaktion, die von der ersten Verbindung durchgeführt wurde.
Dieser Abschnitt beschreibt die Optionen, die Sie auf Replikationsslaves verwenden können. Sie können diese Optionen wahlweise auf der Befehlszeile oder in einer Optionsdatei angeben.
Auf dem Master und jedem Slave müssen Sie die Option
server-id
angeben, um eine eindeutige
Replikationskennung zu erstellen. Wählen Sie auf jedem Server
eine eindeutige Zahl zwischen 1 und 232
– 1. Außerdem muss jede Kennung sich von jeder anderen
Kennung unterscheiden. Zum Beispiel:
server-id=3
Optionen, die Sie auf dem Master-Server zur Steuerung des binären Loggens verwenden können, sind in Abschnitt 5.12.3, „Die binäre Update-Logdatei“, beschrieben.
Einige Replikationsoptionen für Slave-Server werden in dem Sinne
speziell gehandhabt, dass sie ignoriert werden, wenn beim Start
des Slaves eine Datei master.info
vorhanden
ist und diese einen Wert für die betreffende Option enthält.
Dies betrifft die folgenden Optionen:
--master-host
--master-user
--master-password
--master-port
--master-connect-retry
--master-ssl
--master-ssl-ca
--master-ssl-capath
--master-ssl-cert
--master-ssl-cipher
--master-ssl-key
Die Datei master.info
in MySQL
5.1 enthält Werte, die den SSL-Optionen entsprechen.
Daneben sieht das Format dieser Datei in der ersten Zeile auch die
Nennung der Gesamtanzahl aller Zeilen in der Datei vor. Wenn Sie
einen älteren Server (vor MySQL 4.1.1) auf eine neuere Version
aktualisieren, setzt der neue Server die Datei
master.info
beim Start automatisch auf das
neue Format. Wenn Sie hingegen ein Downgrade auf einen älteren
Server durchführen, sollten Sie die erste Zeile manuell
entfernen, bevor Sie den älteren Server zum ersten Mal starten.
Ist beim Start des Slave-Servers keine Datei
master.info
vorhanden, dann werden für diese
Optionen die Werte verwendet, die in Optionsdateien oder auf der
Befehlszeile angegeben wurden. Dies ist etwa der Fall, wenn Sie
den Server zum ersten Mal als Replikationsslave starten, oder wenn
Sie RESET SLAVE
ausgeführt haben und den Slave
nun herunterfahren und neu starten.
Ist die Datei master.info
beim Start des
Slaves vorhanden, dann verarbeitet der Server ihren Inhalt und
ignoriert Werte, die für die in der Datei aufgeführten Optionen
übergeben wurden. Wenn Sie den Slave-Server also mit anderen
Werten für die Startoptionen starten als denen in der Datei
master.info
, dann haben die von Ihnen
übergebenen Werte keine Auswirkung, weil der Server die Angaben
der Datei master.info
entnimmt. Um andere
Werte verwenden zu können, müssen Sie entweder nach dem
Entfernen der Datei master.info
einen
Neustart durchführen oder die Werte bei laufendem Slave-Server
mit der Anweisung CHANGE MASTER TO
zurücksetzen (Letztere ist die empfohlene Methode).
Angenommen, Sie geben folgende Option in Ihrer Datei
my.cnf
an:
[mysqld]
master-host=some_host
Wenn Sie den Server zum ersten Mal als Replikationsslave starten,
liest und verwendet er diese Option aus der Datei
my.cnf
. Danach zeichnet der Server den Wert
in der Datei master.info
auf. Wenn Sie den
Server beim nächsten Mal starten, liest er den Master-Hostwert
nur aus der Datei master.info
und ignoriert
den Wert in der Optionsdatei. Wenn Sie später in der Datei
my.cnf
den anderen Master-Host
some_other_host
angeben, hat diese
Änderung keine Auswirkungen. Sie müssen stattdessen
CHANGE MASTER TO
verwenden.
Da der Server einer vorhandenen Datei
master.info
Vorrang vor den gerade
beschriebenen Startoptionen gewährt, sollten Sie diese Werte
unter Umständen überhaupt nicht mit Startoptionen angeben,
sondern sie stattdessen mit der CHANGE MASTER
TO
-Anweisung festlegen. Siehe auch
Abschnitt 13.6.2.1, „CHANGE MASTER TO
“.
Dieses Beispiel zeigt eine etwas umfangreichere Nutzung der Startoptionen zur Konfiguration eines Slave-Servers:
[mysqld] server-id=2 master-host=db-master.mycompany.com master-port=3306 master-user=pertinax master-password=freitag master-connect-retry=60 report-host=db-slave.mycompany.com
Die folgende Liste beschreibt die Startoptionen zur Steuerung der
Replikation. Viele dieser Optionen können bei laufendem Server
mit der Anweisung CHANGE MASTER TO
zurückgesetzt werden. Andere wie beispielsweise die
--replicate-*
-Optionen können nur beim Start des
Slave-Servers zurückgesetzt werden. Wir beabsichtigen dies zu
beheben.
--log-slave-updates
Normalerweise vermerkt ein Slave Updates, die er von einem
Master-Server erhalten hat, nicht in seinem eigenen Binärlog.
Diese Option weist den Slave jedoch an, Updates, die von
seinem SQL-Thread ausgeführt wurden, in sein eigenes
Binärlog zu schreiben. Damit diese Option Wirkung zeigt, muss
der Slave auch mit der Option --log-bin
gestartet werden, um das binäre Loggen zu aktivieren.
--log-slave-updates
wird verwendet, wenn Sie
Replikationsserver seriell verketten. Nehmen wir an, Sie
wollen die Replikationsserver wie folgt anordnen:
A -> B -> C
Hier dient A als Master von Slave B, und B agiert seinerseits
als Master von Slave C. Damit dies funktioniert, muss B
gleichermaßen Master und Slave sein. Sie
müssen A und B mit der Option --log-bin
starten, um das binäre Loggen zu aktivieren. Ferner muss B
auch mit der Option --log-slave-updates
gestartet werden, damit Änderungen, die von A empfangen
wurden, von B auch im eigenen Binärlog vermerkt werden.
--log-warnings
Mit dieser Option schreibt ein Server mehr Meldungen zu seinen
Aktionen in das Fehlerlog. In Hinsicht auf die Replikation
erzeugt der Server Warnungen, wenn er nach einem Netzwerk-
oder Verbindungsausfall eine Neuverbindung herstellen konnte,
und gibt auch an, wann die einzelnen Slave-Threads gestartet
wurden. Die Option ist standardmäßig aktiviert. Sie können
sie mithilfe von --skip-log-warnings
deaktivieren. Unterbrochene Verbindungen werden nicht in das
Fehlerlog protokolliert, sofern der Wert größer als 1 ist.
--master-connect-retry=
seconds
Die Anzahl von Sekunden, für die der Slave-Thread im Falle
eines Ausfalls der Verbindung oder des Master-Servers
schläft, bevor er eine Neuverbindung mit dem Master
herzustellen versucht. Der entsprechende Wert in der Datei
master.info
hat ggf. Vorrang. Ist der
Wert nicht angegeben, dann wird 60 als Vorgabe benutzt.
--master-host=
host_name
Hostname oder IP-Adresse des Master-Replikationsservers. Der
entsprechende Wert in der Datei
master.info
hat ggf. Vorrang. Ist kein
Master-Host angegeben, dann wird der Slave-Thread nicht
gestartet.
--master-info-file=
file_name
Der Name der Datei, in der der Slave Angaben zum Master
vermerkt. Der Standardname lautet
mysql.info
im Datenverzeichnis.
--master-password=
password
Das Passwort des Kontos, welches der Slave zur
Authentifizierung verwendet, wenn er sich beim Master
anmeldet. Der entsprechende Wert in der Datei
master.info
hat ggf. Vorrang. Sofern
nicht angegeben, wird ein leeres Passwort angenommen.
--master-port=
port_number
Die Nummer des TCP/IP-Ports, auf dem der Master horcht. Der
entsprechende Wert in der Datei
master.info
hat ggf. Vorrang. Sofern
nicht angegeben, wird der einkompilierte Wert (normalerweise
3306) als Vorgabe verwendet.
--master-retry-count=
count
Häufigkeit, mit der der Slave eine Neuverbindung mit dem Master probiert, bevor er aufgibt.
--master-ssl
,
--master-ssl-ca=
,
file_name
--master-ssl-capath=
,
directory_name
--master-ssl-cert=
,
file_name
--master-ssl-cipher=
,
cipher_list
--master-ssl-key=
file_name
Diese Optionen werden zur Einstellung einer sicheren,
SSL-verschlüsselten Replikationsverbindung zum Master-Server
benutzt. Die Bedeutungen sind mit denen der entsprechenden
Optionen --ssl
, --ssl-ca
,
--ssl-capath
, --ssl-cert
,
--ssl-cipher
und --ssl-key
identisch, die in Abschnitt 5.9.7.5, „SSL-Befehlsoptionen“, beschrieben
werden. Die entsprechenden Werte in der Datei
master.info
haben ggf. Vorrang.
--master-user=
user_name
Der Benutzername des Kontos, welches der Slave zur
Authentifizierung verwendet, wenn er sich beim Master
anmeldet. Dieses Konto benötigt die Berechtigung
REPLICATION SLAVE
. Der entsprechende Wert
in der Datei master.info
hat ggf.
Vorrang. Wenn der Master-Benutzername nicht angegeben ist,
wird der Name test
als Vorgabe verwendet.
--max-relay-log-size=
size
Größe, bei der der Server die Relay-Logs automatisch rotiert. Weitere Informationen finden Sie unter Abschnitt 6.4.4, „Relay- und Statusdateien bei der Replikation“.
--read-only
Bewirkt, dass der Slave keine Updates gestattet, sofern diese
nicht von Slave-Threads oder von Benutzern mit der
Berechtigung SUPER
stammen. Auf diese Weise
lässt sich sicherstellen, dass ein Slave-Server keine
Aktualisierungen von Clients akzeptiert. Diese Option gilt
nicht für TEMPORARY
-Tabellen.
--relay-log=
file_name
Der Name des Relay-Logs. Der Standardname lautet
,
wobei host_name
-relay-bin.nnnnnn
host_name
der Name des
Slave-Serverhosts ist und nnnnnn
angibt, dass Relay-Logs mit fortlaufender Nummerierung
erstellt werden. Sie können die Option angeben, um vom
Hostnamen unabhängige Namen für Relay-Logs zu erstellen.
Ferner ist sie praktisch, wenn Ihre Relay-Logs dazu tendieren,
sehr groß zu werden (und Sie
max_relay_log_size
nicht verringern
wollen), und Sie sie an einer anderen Position als im
Datenverzeichnis ablegen müssen, oder wenn Sie die
Geschwindigkeit durch eine Lastverteilung auf mehrere
Festplatten optimieren wollen.
--relay-log-index=
file_name
Der Name, der für die Indexdatei des Relay-Logs verwendet
wird. Der Standardname lautet
im Datenverzeichnis, wobei
host_name
-relay-bin.indexhost_name
der Name des
Slave-Servers ist.
--relay-log-info-file=
file_name
Der Name der Datei, in der der Slave Angaben zu den Relay-Logs
vermerkt. Der Standardname lautet
relay-log.info
im Datenverzeichnis.
--relay-log-purge={0|1}
Aktiviert oder deaktiviert das automatische Löschen von
Relay-Logs, wenn sie nicht mehr benötigt werden. Der
Vorgabewert ist 1 (aktiviert). Dies ist eine globale Variable,
die dynamisch mit SET GLOBAL relay_log_purge =
geändert werden kann.
N
--relay-log-space-limit=
size
Diese Option setzt eine Obergrenze für die Gesamtgröße
aller Relay-Logs auf dem Slave, angegeben in Byte. Der Wert 0
hat die Bedeutung „unbeschränkt“. Die Option ist
praktisch auf Slave-Servern, bei denen die
Festplattenkapazität begrenzt ist. Wenn der Grenzwert
erreicht wird, beendet der I/O-Thread das Auslesen von
Ereignissen aus dem Binärlog des Masters, bis der SQL-Thread
aufgeholt und eine Anzahl nicht mehr benötigter Relay-Logs
gelöscht hat. Beachten Sie, dass das Limit nicht absolut ist:
Es gibt Fälle, in denen der SQL-Thread mehr Ereignisse
benötigt, bevor er Relay-Logs löschen kann. In diesem Fall
überschreitet der I/O-Thread den Grenzwert so weit, wie es
notwendig ist, damit der SQL-Thread einige Relay-Logs löschen
kann (andernfalls würde der Slave nämlich blockiert). Sie
sollten --relay-log-space-limit
auf einen
Wert setzen, der mindestens zweimal so groß ist wie der Wert
von --max-relay-log-size
(oder
--max-binlog-size
, sofern
--max-relay-log-size
0 ist). In diesem Fall
besteht die Möglichkeit, dass der I/O-Thread auf freien
Speicher warten muss, weil
--relay-log-space-limit
überschritten wurde,
der SQL-Thread aber kein Relay-Log löschen und deswegen die
Anforderung des I/O-Threads nicht bearbeiten kann. Also ist
der I/O-Thread gezwungen,
--relay-log-space-limit
vorübergehend zu
ignorieren.
--replicate-do-db=
db_name
Weist den Slave an, die Replikation auf Anweisungen zu
beschränken, deren Standarddatenbank (also die von
USE
gewählte Datenbank)
db_name
ist. Um mehrere Datenbanken
anzugeben, verwenden Sie diese Option mehrfach (d. h. jeweils
einmal pro Datenbank). Beachten Sie, dass hierbei keine
datenbankübergreifenden Anweisungen wie UPDATE
repliziert werden, solange eine andere
Datenbank (oder gar keine Datenbank) gewählt ist.
some_db.some_table
SET
foo='bar'
Hier ein Beispiel für etwas, das nicht so funktioniert, wie
Sie es vielleicht erwarten: Wenn der Slave mit der Option
--replicate-do-db=sales
gestartet wird und
Sie die folgenden Anweisungen auf dem Master absetzen, wird
die UPDATE
-Anweisung
nicht repliziert:
USE prices; UPDATE sales.january SET amount=amount+1000;
Der wichtigste Grund für dieses Verhalten nach dem Motto
„Nur die Standarddatenbank überprüfen“ besteht
darin, dass es schwierig ist, allein der Anweisung zu
entnehmen, ob sie repliziert werden soll (wenn Sie
beispielsweise DELETE
-Anweisungen für
mehrere Tabellen oder UPDATE
-Anweisungen
für mehrere Tabellen verwenden, die datenbankübergreifend
agieren). Außerdem geht es schneller, wenn nur die
Standarddatenbank (statt aller Datenbanken) überprüft wird,
sofern es keinen Grund dafür gibt.
Wenn Sie datenbankübergreifende Aktualisierungen zum Laufen
bringen wollen, verwenden Sie stattdessen
--replicate-wild-do-table=
.
Siehe auch Abschnitt 6.10, „Wie Server Replikationsregeln auswerten“.
db_name
.%
--replicate-do-table=
db_name.tbl_name
Weist den Slave-Thread an, die Replikation auf die angegebene
Tabelle zu beschränken. Um mehrere Tabellen anzugeben,
verwenden Sie diese Option mehrfach (d. h. jeweils einmal pro
Tabelle). Dies funktioniert – anders als
--replicate-do-db
– auch bei
datenbankübergreifenden Änderungen. Siehe auch
Abschnitt 6.10, „Wie Server Replikationsregeln auswerten“.
--replicate-ignore-db=
db_name
Weist den Slave an, keine Anweisungen zu replizieren, deren
Standarddatenbank (also die von USE
gewählte Datenbank) db_name
ist.
Um mehrere zu ignorierende Datenbanken anzugeben, verwenden
Sie diese Option mehrfach (d. h. jeweils einmal pro
Datenbank). Sie sollten die Option allerdings nicht angeben,
wenn Sie datenbankübergreifende Änderungen ausführen, die
aber nicht repliziert werden sollen. Siehe auch
Abschnitt 6.10, „Wie Server Replikationsregeln auswerten“.
Hier ein Beispiel für etwas, das nicht so funktioniert, wie
Sie es vielleicht erwarten: Wenn der Slave mit der Option
--replicate-ignore-db=sales
gestartet wird
und Sie die folgenden Anweisungen auf dem Master absetzen,
wird die UPDATE
-Anweisung
nicht repliziert:
USE prices; UPDATE sales.january SET amount=amount+1000;
Wenn Sie datenbankübergreifende Aktualisierungen zum Laufen
bringen wollen, verwenden Sie stattdessen
--replicate-wild-ignore-table=
.
Siehe auch Abschnitt 6.10, „Wie Server Replikationsregeln auswerten“.
db_name
.%
--replicate-ignore-table=
db_name.tbl_name
Weist den Slave-Thread an, eine Anweisung, die die angegebene
Tabelle ändert, auch dann nicht zu replizieren, wenn andere
Tabellen von derselben Anweisung geändert werden könnten. Um
mehrere zu ignorierende Tabellen anzugeben, verwenden Sie
diese Option mehrfach (d. h. jeweils einmal pro Tabelle).
Dies funktioniert – anders als
--replicate-ignore-db
– auch bei
datenbankübergreifenden Änderungen. Siehe auch
Abschnitt 6.10, „Wie Server Replikationsregeln auswerten“.
--replicate-rewrite-db=
from_name
->to_name
Weist den Slave an, die Standarddatenbank (also die von
USE
gewählte Datenbank) in
to_name
zu übersetzen, wenn sie
auf dem Master den Namen from_name
hatte. Hiervon sind nur tabellenbezogene Anweisungen betroffen
(also keine Anweisungen wie CREATE
DATABASE
, DROP DATABASE
und
ALTER DATABASE
), und diese auch nur dann,
wenn from_name
die
Standarddatenbank auf dem Master ist. Dies funktioniert bei
datenbankübergreifenden Änderungen nicht. Die Übersetzung
des Datenbanknamens erfolgt vor dem
Prüfen der --replicate-*
-Regeln.
Wenn Sie diese Option auf der Befehlszeile verwenden und das
Zeichen ‘>
’ für Ihren
Befehls-Interpreter ein Sonderzeichen ist, müssen Sie den
Optionswert in Anführungszeichen setzen. Zum Beispiel:
shell> mysqld --replicate-rewrite-db="olddb
->newdb
"
--replicate-same-server-id
Wird auf Slave-Servern verwendet. Normalerweise sollten Sie
die Standardeinstellung 0 verwenden, um durch eine
Kreisreplikation verursachte Endlosschleifen zu verhindern.
Wenn Sie den Wert 1 wählen, überspringt der Slave keine
Ereignisse, die seine eigene Serverkennung enthalten – dies
ist normalerweise nur in seltenen Fällen gewollt. Der Wert 1
kann bei Verwendung von --log-slave-updates
nicht gewählt werden. Beachten Sie, dass der Slave-I/O-Thread
standardmäßig noch nicht einmal dann Ereignisse aus dem
Binärlog in das Relay-Log schreibt, wenn diese die Kennung
des Slaves aufweisen (diese Optimierung hilft beim Einsparen
von Festplattenkapazität). Wenn Sie also
--replicate-same-server-id
verwenden wollen,
müssen Sie den Slave in jedem Fall mit dieser Option starten,
bevor Sie ihn dazu bringen, eigene Ereignisse zu lesen, die
der Slave-SQL-Thread ausführen soll.
--replicate-wild-do-table=
db_name.tbl_name
Weist den Slave-Thread an, die Replikation auf Anweisungen zu
beschränken, bei denen die aktualisierten Tabellen den
angegebenen Mustern für Datenbank- und Tabellennamen
entsprechen. Muster dürfen die Jokerzeichen
‘%
’ und
‘_
’ enthalten; diese haben
dieselbe Bedeutung wie beim Mustervergleichsoperator
LIKE
. Um mehrere Tabellen anzugeben,
verwenden Sie diese Option mehrfach (d. h. jeweils einmal pro
Tabelle). Dies funktioniert bei datenbankübergreifenden
Änderungen. Siehe auch
Abschnitt 6.10, „Wie Server Replikationsregeln auswerten“.
Beispiel: --replicate-wild-do-table=foo%.bar%
repliziert nur Updates, die eine Tabelle betreffen, bei der
der Datenbankname mit foo
und der
Tabellenname mit bar
beginnt.
Wenn als Muster für den Tabellennamen %
angegeben wird, dann liegt eine Entsprechung für jeden
Tabellennamen vor, und die Option gilt auch für Anweisungen
auf Datenbankebene (CREATE DATABASE
,
DROP DATABASE
und ALTER
DATABASE
). Wenn Sie beispielsweise
--replicate-wild-do-table=foo%.%
angeben,
werden die Anweisungen auf Datenbankebene repliziert, wenn der
Datenbankname foo%
entspricht.
Um Jokerzeichen literal in den Mustern für Datenbank- oder
Tabellennamen zu verwenden, kennzeichnen Sie sie mit einem
Backslash. Um also beispielsweise alle Tabellen einer
Datenbank namens my_own%db
zu replizieren,
nicht aber Tabellen aus my1ownAABCdb
,
sollten Sie die Zeichen ‘_
’ und
‘%
’ wie folgt kennzeichnen:
--replicate-wild-do-table=my\_own\%db
. Wenn
Sie die Option auf der Befehlszeile angeben, müssen Sie unter
Umständen je nach Befehls-Interpreter die Backslashes
verdoppeln oder den Optionswert in Anführungszeichen setzen.
So müssen Sie bei der bash-Shell etwa
--replicate-wild-do-table=my\\_own\\%db
angeben.
--replicate-wild-ignore-table=
db_name.tbl_name
Weist den Slave-Thread an, eine Anweisung nicht zu replizieren, bei der eine beliebige Tabelle dem angegebenen Jokerzeichenmuster entspricht. Um mehrere zu ignorierende Tabellen anzugeben, verwenden Sie diese Option mehrfach (d. h. jeweils einmal pro Tabelle). Dies funktioniert bei datenbankübergreifenden Änderungen. Siehe auch Abschnitt 6.10, „Wie Server Replikationsregeln auswerten“.
Beispiel:
--replicate-wild-ignore-table=foo%.bar%
repliziert keine Updates, die eine Tabelle betreffen, bei der
der Datenbankname mit foo
und der
Tabellenname mit bar
beginnt.
Informationen zur Funktionsweise von Mustervergleichen
entnehmen Sie der Beschreibung zur Option
--replicate-wild-do-table
. Die Regeln zur
Verwendung literaler Jokerzeichen im Optionswert sind
dieselben wie bei
--replicate-wild-ignore-table
.
--report-host=
slave_name
Hostname oder IP-Adresse des Slaves, der oder die bei der
Slave-Registrierung an den Master gemeldet wurde. Dieser Wert
erscheint in der Ausgabe von SHOW SLAVE
HOSTS
auf dem Master-Server. Lassen Sie den Wert
ungesetzt, wenn Sie nicht wollen, dass der Slave sich
selbstständig beim Master registriert. Beachten Sie, dass es
für den Master nicht ausreichend ist, die IP-Adresse des
Slaves bei dessen Verbindungsherstellung einfach dem
TCP/IP-Socket zu entnehmen. Aufgrund der
Netzadressübersetzung (NAT) und anderer Routing-relevanter
Probleme kann diese IP-Adresse unter Umständen nicht
verwendet werden, um den Slave vom Master oder anderen Hosts
aus zu kontaktieren.
--report-port=
slave_port_num
Die Nummer des TCP/IP-Ports zur Verbindung mit dem Slave, die bei der Slave-Registrierung an den Master gemeldet wurde. Nehmen Sie die Einstellung nur vor, wenn der Slave nicht auch einem Standardport lauscht oder Sie einen speziellen Tunnel vom Master oder anderen Clients zum Slave verwenden. Wenn Sie sich nicht sicher sind, verwenden Sie die Option nicht.
--skip-slave-start
Weist den Slave-Server an, die Slave-Threads nicht zu starten,
wenn der Server startet. Um die Threads später zu starten,
können Sie die Anweisung START SLAVE
verwenden.
--slave_compressed_protocol={0|1}
Wenn diese Option auf 1 gesetzt ist, wird eine Komprimierung des Slave/Master-Protokolls verwendet, wenn sowohl Slave als auch Master diese unterstützen.
--slave-load-tmpdir=
file_name
Der Name des Verzeichnisses, in dem der Slave Temporärdateien
erstellt. Diese Option entspricht standardmäßig dem Wert der
Systemvariablen tmpdir
. Wenn der
Slave-SQL-Thread eine LOAD DATA
INFILE
-Anweisung repliziert, extrahiert er die zu
ladende Datei aus dem Relay-Log in Temporärdateien und lädt
diese dann in die Tabelle. Wenn die auf dem Master geladene
Datei sehr groß ist, sind auch die Temporärdateien auf dem
Slave groß. Aus diesem Grund kann es sich empfehlen, den
Slave mit dieser Option anzuweisen, die Temporärdateien in
ein Verzeichnis auf einem Dateisystem zu speichern, auf dem
ausreichend viel Festplattenkapazität vorhanden ist. In
diesem Fall sind auch die Relay-Logs riesig, weswegen Sie auch
diese mit der Option --relay-log
gleichermaßen auf jenem Dateisystem ablegen sollten.
Das mit dieser Option angegebene Verzeichnis sollte auf einem
festplattenbasierten (d. h. nicht speicherresidenten)
Dateisystem liegen, da die Temporärdateien, die zur
Replikation von LOAD DATA INFILE
verwendet
werden, einen Systemneustart überdauern müssen. Das
Verzeichnis sollte außerdem nicht eines sein, welches beim
Systemstart vom Betriebssystem geleert wird.
--slave-net-timeout=
seconds
Anzahl der Sekunden, für die auf weitere Daten vom Master
gewartet wird, bevor der Slave die Verbindung als unterbrochen
betrachtet, den Lesevorgang abbricht und eine Neuverbindung
probiert. Der erste Versuch findet unmittelbar nach
Überschreiten dieses Werts statt. Die Abstände zwischen den
Neuversuchen werden von der Option
--master-connect-retry
gesteuert.
--slave-skip-errors=[
err_code1
,err_code2
,...|all]
Normalerweise wird die Replikation beendet, wenn ein Fehler auf dem Slave auftritt. Sie haben auf diese Weise die Möglichkeit, Inkonsistenzen in den Daten manuell zu beheben. Diese Option weist den Slave-SQL-Thread an, mit der Replikation fortzufahren, wenn eine Anweisung einen der im Optionswert aufgeführten Fehler zurückgibt.
Verwenden Sie diese Option nicht, sofern Sie nicht genau wissen, warum Sie Fehler erhalten. Sind in Ihrer Replikationskonfiguration und Clientprogrammen ebenso wenig Fehler vorhanden wie Bugs in MySQL, dann sollte eigentlich nie ein Fehler auftreten, der die Replikation beendet. Die unüberlegte Verwendung dieser Option hat zur Folge, dass die Synchronisation zwischen Master und Slave unwiederbringlich verloren geht, ohne dass Sie überhaupt wissen, warum dies so ist.
Die Fehlercodes sind als Zahlenangaben in den Fehlermeldungen
im Fehlerlog des Slaves und in der Ausgabe von SHOW
SLAVE STATUS
enthalten.
Anhang B, Fehlercodes und -meldungen, listet die Serverfehlercodes
auf.
Sie könnten theoretisch auch den nicht sehr empfehlenswerten
Wert all
angeben, damit der Slave alle
Fehlermeldungen ignoriert und weiterarbeitet – egal, was
auch passiert. Aber das sollten Sie besser lassen.
Selbstredend gibt es, wenn Sie all
verwenden, keine Garantie bezüglich der Datenintegrität.
Sollten die Daten auf dem Slave in einem solchen Fall auch
nicht annähernd denen auf dem Master entsprechen, so bitten
wir von Beschwerden (und der Meldung von Bugs) abzusehen.
Wir haben Sie gewarnt!
Ein paar Beispiele:
--slave-skip-errors=1062,1053 --slave-skip-errors=all
Wenn ein Master-Server keine Anweisung in sein Binärlog schreibt, wird die Anweisung auch nicht repliziert. Schreibt der Server die Anweisung hingegen in das Log, dann wird die Anweisung an alle Slaves geschickt, und jeder Slave bestimmt, ob er sie ausführt oder ignoriert.
Auf der Master-Seite basieren die Entscheidungen darüber, welche
Anweisungen zu loggen sind, auf den Optionen
--binlog-do-db
und
--binlog-ignore-db
, die das binäre Loggen
steuern. Eine Beschreibung der Regeln, die der Server bei der
Auswertung dieser Optionen verwendet, finden Sie in
Abschnitt 5.12.3, „Die binäre Update-Logdatei“.
Auf der Slave-Seite werden die Entscheidungen darüber, ob und
welche vom Master empfangenen Anweisungen ausgeführt oder
ignoriert werden, entsprechend den
--replicate-*
-Optionen getroffen, mit denen der
Slave gestartet wurde. Der Slave wertet diese Optionen
entsprechend der folgenden Vorgehensweise aus.
Sind --replicate-do-db
- oder
--replicate-ignore-db
-Optionen vorhanden?
Ja: Unter Verwendung derselben Regeln
testen wie bei den Optionen
--binlog-do-db
und
--binlog-ignore-db
. Welches Ergebnis hat
der Test?
Anweisung ignorieren: Ignorieren und beenden.
Anweisung zulassen: Anweisung nicht sofort ausführen, sondern die Entscheidung verschieben. Mit nächstem Schritt fortfahren.
Nein: Mit nächstem Schritt fortfahren.
Wird gerade eine gespeicherte Funktion ausgeführt?
Ja: Abfrage ausführen und beenden.
Nein: Mit nächstem Schritt fortfahren.
Sind --replicate-*-table
-Optionen vorhanden?
Nein: Abfrage ausführen und beenden.
Ja: In diesem Fall hängt das Verhalten davon ab, ob die anweisungsbasierte Replikation oder die datensatzbasierte Replikation verwendet wird:
Anweisungsbasierte Replikation:
Mit nächstem Schritt fortfahren und mit der
Auswertung der Tabellenregeln in der angegebenen
Reihenfolge (zuerst die Nicht-„wild“-,
dann die „wild“-Regeln) beginnen. Nur
Tabellen, die aktualisiert werden sollen, werden mit
den Regeln verglichen. Heißt die Anweisung etwa
INSERT INTO sales SELECT * FROM
prices
, dann wird nur
sales
mit den Regeln verglichen.
Wenn mehrere Tabellen durch eine entsprechende
Anweisung aktualisiert werden, gewinnt die erste
Tabelle, die „Do“ oder
„Ignore“ entspricht: Der Server
vergleicht die erste Tabelle also mit den Regeln.
Konnte keine Entscheidung getroffen werden, dann
überprüft er die zweite Tabelle usw.
Datensatzbasierte Replikation:
Alle Änderungen an Tabellendatensätzen werden
einzeln gefiltert. Bei Updates für mehrere Tabellen
wird jede Tabelle entsprechend den Regeln separat
gefiltert. Einige Änderungen werden ausgeführt,
andere unter Umständen nicht – dies hängt jeweils
von den Regeln und den vorgenommenen Änderungen ab.
Die datensatzbasierte Replikation verarbeitet Fälle,
die bei der anweisungsbasierten Replikation nicht
korrekt repliziert würden, ihrerseits korrekt.
Betrachten Sie folgendes Beispiel, welches davon
ausgeht, dass Tabellen in der Datenbank
foo
repliziert werden sollen:
mysql>USE bar;
mysql>INSERT INTO foo.sometable VALUES (1);
Gibt es --replicate-do-table
-Regeln?
Ja: Entspricht die Tabelle einer dieser Regeln?
Ja: Abfrage ausführen und beenden.
Nein: Mit nächstem Schritt fortfahren.
Nein: Mit nächstem Schritt fortfahren.
Gibt es --replicate-ignore-table
-Regeln?
Ja: Entspricht die Tabelle einer dieser Regeln?
Ja: Abfrage ignorieren und beenden.
Nein: Mit nächstem Schritt fortfahren.
Nein: Mit nächstem Schritt fortfahren.
Gibt es --replicate-wild-do-table
-Regeln?
Ja: Entspricht die Tabelle einer dieser Regeln?
Ja: Abfrage ausführen und beenden.
Nein: Mit nächstem Schritt fortfahren.
Nein: Mit nächstem Schritt fortfahren.
Gibt es --replicate-wild-ignore-table
-Regeln?
Ja: Entspricht die Tabelle einer dieser Regeln?
Ja: Abfrage ignorieren und beenden.
Nein: Mit nächstem Schritt fortfahren.
Nein: Mit nächstem Schritt fortfahren.
Es gab keine Entsprechung für eine
--replicate-*-table
-Regel. Gibt es noch eine
weitere Tabelle, die auf diese Regeln geprüft werden kann?
Ja: Schleife wiederholen.
Nein: Wir haben nun alle zu
aktualisierenden Tabellen getestet und konnten keine
Übereinstimmung mit einer Regel finden. Sind
--replicate-do-table
- oder
--replicate-wild-do-table
-Regeln
vorhanden?
Ja: Es gab „Do“-Regeln, aber keine Übereinstimmung. Abfrage ignorieren und beenden.
Nein: Abfrage ausführen und beenden.
Frage: Wie konfiguriere ich einen Slave, wenn der Master ausgeführt wird und ich ihn nicht anhalten will?
Antwort: Es gibt mehrere
Möglichkeiten. Wenn Sie zu einem bestimmten Zeitpunkt ein auf
einer Momentaufnahme basiertes Backup des Masters erstellt und den
Binärlognamen und den Versatz (aus der Ausgabe von SHOW
MASTER STATUS
) für die Momentaufnahme notiert haben,
gehen Sie wie folgt vor:
Stellen Sie sicher, dass der Slave eine eindeutige Serverkennung hat.
Führen Sie die folgende Anweisung auf dem Slave aus. Geben Sie dabei für jede Option die passenden Werte an:
mysql>CHANGE MASTER TO
->MASTER_HOST='
->master_host_name
',MASTER_USER='
->master_user_name
',MASTER_PASSWORD='
->master_pass
',MASTER_LOG_FILE='
->recorded_log_file_name
',MASTER_LOG_POS=
recorded_log_position
;
Führen Sie START SLAVE
auf dem Slave aus.
Wenn Sie über keine Sicherungskopie des Master-Servers verfügen, können Sie wie nachfolgend beschrieben ganz einfach eine solche erstellen. Alle Schritte sind dabei auf dem Master-Host durchzuführen.
Setzen Sie die folgende Anweisung ab, um eine globale Lesesperre zu erwirken:
mysql> FLUSH TABLES WITH READ LOCK;
Führen Sie bei weiterhin aktiver Sperre den folgenden Befehl (oder eine entsprechende Variante) aus:
shell> tar zcf /tmp/backup.tar.gz /var/lib/mysql
Setzen Sie nun folgende Anweisung ab und notieren Sie die Ausgabe (Sie werden sie später noch benötigen):
mysql> SHOW MASTER STATUS;
Heben Sie die Sperre auf:
mysql> UNLOCK TABLES;
Eine Alternative zu dieser Vorgehensweise zur Erstellung einer binären Kopie besteht darin, einen SQL-Speicherauszug des Masters zu erstellen. Hierzu führen Sie mysqldump --master-data auf dem Master aus und laden die SQL-Speicherauszugsdatei später in Ihren Slave. Allerdings ist die Erstellung einer binären Kopie schneller.
Unabhängig davon, welche der beiden Methoden Sie verwenden, befolgen Sie danach die Anleitung für den Fall, dass Sie eine Momentaufnahme erstellt und den Logdateinamen und den Offset vermerkt haben. Sie können dieselbe Momentaufnahme mehrfach verwenden. Wenn Sie die Momentaufnahme des Masters erst einmal haben, können Sie beliebig lang mit der Konfiguration des Slaves warten: Es müssen lediglich die Binärlogs auf dem Master intakt bleiben. Allerdings bestehen zwei praktische Beschränkungen, die Sie beachten müssen: Sie dürfen nicht länger als notwendig warten, um zu vermeiden, dass die zur Aufnahme der Binärlogs auf dem Master erforderliche Speichermenge zu groß wird und dass der Slave nicht schnell genug auf den Stand des Masters gebracht werden kann.
Sie können außerdem LOAD DATA FROM MASTER
verwenden. Dies ist eine praktische Anweisung, die eine
Momentaufnahme auf den Slave überträgt und gleichzeitig auch
noch den Logdateinamen und den Versatz automatisch einstellt.
Zukünftig wird LOAD DATA FROM MASTER
die
empfohlene Vorgehensweise zur Konfiguration eines Slaves werden.
Beachten Sie allerdings, dass die Anweisung nur bei
MyISAM
-Tabellen funktioniert und für einen
relativ langen Zeitraum eine Lesesperre setzt. Sie ist noch nicht
so effektiv implementiert, wie wir uns das wünschen. Wenn Sie
größere Tabellen haben, besteht die bevorzugte Methode also
derzeit noch darin, nach der Ausführung von FLUSH TABLES
WITH READ LOCK
eine binäre Momentaufnahme auf dem
Master-Server zu erstellen.
Frage: Muss der Slave fortlaufend mit dem Master verbunden sein?
Antwort: Nein. Der Slave kann stunden- oder sogar tagelang ausgeschaltet oder getrennt sein – erfolgt eine Neuverbindung, dann werden alle Aktualisierungen aufgeholt. Sie können beispielsweise eine Master/Slave-Beziehung über eine Wählverbindung konfigurieren, bei der die Verbindung nur sporadisch und nur für kurze Zeit hergestellt wird. Eine Auswirkung hiervon ist natürlich, dass man zu keinem Zeitpunkt die Synchronisation zwischen Slave und Master gewährleisten kann, sofern nicht bestimmte Maßnahmen ergriffen werden. Zukünftig wird eine Option eingeführt werden, mit der der Master blockiert wird, bis mindestens ein Slave synchronisiert wurde.
Frage: Wie erkenne ich, wie weit ein Slave im Vergleich zum Master im Rückstand ist? Anders formuliert: Wie ermittle ich den Zeitpunkt der letzten vom Slave replizierten Abfrage?
Antwort: Lesen Sie die Spalte
Seconds_Behind_Master
in der Ausgabe von
SHOW SLAVE STATUS
aus. Siehe auch
Abschnitt 6.4, „Replikation: Implementationsdetails“.
Wenn der Slave-SQL-Thread ein Ereignis ausführt, welches er vom
Master gelesen hat, dann setzt er seine eigene Zeit auf den
Zeitstempel des Ereignisses um. (Dies ist auch Voraussetzung
dafür, dass TIMESTAMP
korrekt repliziert
wird.) In der Spalte Time
der Ausgabe von
SHOW PROCESSLIST
beschreibt die angezeigte
Sekundenzahl für den Slave-SQL-Thread die Anzahl der Sekunden
zwischen dem Zeitstempel des letzten replizierten Ereignisses und
der Echtzeit des Slave-Systems. Auf diese Weise können Sie den
Zeitpunkt des letzten replizierten Ereignisses ermitteln. Beachten
Sie, dass, wenn Ihr Slave für eine Stunde vom Master getrennt
wurde und dann eine neue Verbindung herstellt, in der Spalte
Time
sofort Werte wie 3600 für den
Slave-SQL-Thread in der Ausgabe von SHOW
PROCESSLIST
erscheinen. Dies liegt daran, dass der Slave
Anweisungen ausführt, die eine Stunde alt sind.
Frage: Wie kann ich den Master zwingen, Updates zu sperren, bis der Slave den Rückstand aufgeholt hat?
Antwort: Gehen Sie wie folgt vor:
Führen Sie auf dem Master die folgenden Anweisungen aus:
mysql>FLUSH TABLES WITH READ LOCK;
mysql>SHOW MASTER STATUS;
Notieren Sie die Replikationskoordinaten (Logdateiname und
Versatz) in der Ausgabe der SHOW
-Anweisung.
Setzen Sie auf dem Slave folgende Anweisung ab. Die Argumente
für die Funktion MASTER_POS_WAIT()
sind
die Replikationskoordinaten, die Sie im vorherigen Schritt
ermittelt haben:
mysql> SELECT MASTER_POS_WAIT('log_name
', log_offset
);
Die SELECT
-Anweisung sperrt den Master, bis
der Slave die entsprechende Position in der angegebenen
Logdatei erreicht hat. An dieser Stelle läuft der Slave
synchron zum Master, und die Anweisung gibt ihre Werte
zurück.
Setzen Sie nun auf dem Master die folgende Anweisung ab, damit er wieder Updates verarbeiten kann:
mysql> UNLOCK TABLES;
Frage: Welche Aspekte muss ich bei der Konfiguration der 2-Wege-Replikation beachten?
Antwort: Die MySQL-Replikation unterstützt derzeit kein Sperrprotokoll zwischen Master und Server, mit dem die Atomizität eines verteilten (serverübergreifenden) Updates gewährleistet werden kann. Es ist also möglich, dass Client A ein Update auf dem Co-Master 1 vornimmt, während gleichzeitig (also bevor dieses Update an den Co-Master 2 weitergegeben wird) Client B ein Update auf dem Co-Master 2 durchführt, welches für das Update von Client A eine andere Wirkung hervorruft als auf Co-Master 1. Auf diese Weise erzeugt das Update von Client A nach der Ankunft auf dem Co-Master 2 Tabellen, die sich von denen auf dem Co-Master 1 unterscheiden – und zwar auch, nachdem alle Updates von Co-Master 2 ebenfalls weitergegeben wurden. Dies bedeutet, dass Sie niemals zwei Server in einer 2-Wege-Replikationsbeziehung miteinander verketten sollten, sofern Sie nicht sicher sind, dass Ihre Updates in beliebiger Reihenfolge erfolgen können, oder im Clientcode den Fall unterschiedlicher Updatereihenfolgen irgendwie berücksichtigen.
Sie sollten auch daran denken, dass, soweit es Updates betrifft, die 2-Wege-Replikation die Leistungsfähigkeit – sofern überhaupt – nicht allzu sehr optimiert. Jeder Server muss dieselbe Anzahl von Updates ausführen – ebenso wie es auch bei nur einem Server der Fall wäre. Der einzige Unterschied besteht darin, dass es zu weniger konkurrierenden Sperranforderungen kommt, weil die Updates, die von einem anderen Server kommen, in nur einem Slave-Thread serialisiert werden. Aber auch dieser Vorteil kann durch Netzwerklatenzen schon wieder aufgewogen werden.
Frage: Wie kann ich mit der Replikation die Leistung meines Systems verbessern?
Antwort: Sie sollten einen Server
als Master konfigurieren und alle Schreiboperationen an ihn
richten. Nachfolgend sollten Sie so viele Slaves einrichten, wie
es Budget und Platzverhältnisse zulassen, und Leseoperationen
dann auf Master und Slaves verteilen. Sie können die Slaves auch
mit den Optionen --skip-innodb
,
--skip-bdb
,
--low-priority-updates
und
--delay-key-write=ALL
starten, um Slave-seitig
Geschwindigkeitsvorteile erzielen zu können. In diesem Fall
verwendet der Slave nichttransaktionssichere
MyISAM
-Tabellen statt
InnoDB
- und BDB
-Tabellen, um
den transaktionsbedingten Mehraufwand zu umgehen und die
Geschwindigkeit so zu steigern.
Frage: Was kann ich tun, um den Clientcode in meinen eigenen Anwendungen so zu formulieren, dass eine leistungssteigernde Replikation verwendet wird?
Antwort: Wenn der Teil Ihres Codes, der für den Datenbankzugriff zuständig ist, einwandfrei abstrahiert bzw. modularisiert ist, sollte die Konvertierung in eine Form, die in einer Replikationskonfiguration läuft, schnell und einfach erfolgen. Ändern Sie die Implementierung Ihres Datenbankzugriffs so, dass alle Schreiboperationen an den Master gesendet werden, und senden Sie die Leseoperationen an den Master oder einen Slave. Wenn Ihr Code nicht derart abstrahierbar ist, bietet Ihnen die Konfiguration eines Replikationssystems vielleicht die Möglichkeit und die Motivation, ihn entsprechend zu bereinigen. Erstellen Sie zunächst eine Wrapper-Bibliothek oder ein Wrapper-Modul, das die folgenden Funktionen implementiert:
safe_writer_connect()
safe_reader_connect()
safe_reader_statement()
safe_writer_statement()
Der Namensteil safe_
in den Funktionsnamen
verweist darauf, dass die jeweilige Funktion alle
Fehlerbedingungen selbst abfängt. Sie können für die Funktionen
auch andere Namen verwenden. Wichtig ist lediglich, dass Sie über
eine einheitliche Schnittstelle verfügen, um Lese- und
Schreibverbindungen herzustellen und Lese- oder Schreiboperationen
auszuführen.
Nachfolgend konvertieren Sie Ihren Clientcode so, dass er die Wrapper-Bibliothek verwendet. Unter Umständen ist dies anfangs ein schmerzlicher und beängstigender Vorgang, der sich aber langfristig auszahlt. Alle Anwendungen, die den gerade beschriebenen Ansatz verfolgen, können von einer Master/Slave-Konfiguration profitieren, auch wenn diese mehrere Slaves umfasst. Der Code ist weitaus einfacher zu pflegen, und das Hinzufügen von Problembehandlungsoptionen ist trivial. Sie müssen nur ein oder zwei Funktionen modifizieren – beispielsweise, wie lang eine Anweisung zur Ausführung benötigte oder welche der abgesetzten Anweisungen den Fehler zurückgegeben hat.
Wenn Sie viel Code geschrieben haben, sollten Sie diese Konvertierungsarbeit mit dem Hilfsprogramm replace automatisieren, welches Bestandteil der MySQL-Standarddistributionen ist, oder Ihr eigenes Konvertierungsskript abfassen. Im Idealfall verwendet Ihr Code konsistent die gängigen Stilkonventionen bei der Programmierung. Andernfalls wird es ohnehin einfacher sein, ihn neu zu erstellen oder ihn zumindest durchzuarbeiten und dabei manuell so zu vereinheitlichen, dass der Stil konsistent ist.
Frage: Wie stark und unter welchen Umständen kann die MySQL-Replikation die Leistung meines Systems verbessern?
Antwort: Die MySQL-Replikation ist am vorteilhaftesten für Systeme, die häufig Leseoperationen und seltener Schreiboperationen verarbeiten müssen. Theoretisch können Sie Ihr System bei Implementierung einer Konfiguration mit einem Master und mehreren Slaves skalieren, indem Sie weitere Slaves hinzufügen, bis entweder Ihre Netzwerkbandbreite erschöpft ist oder Ihr Aktualisierungsaufkommen so stark zugenommen hat, dass es der Master nicht mehr verarbeiten kann.
Um zu ermitteln, wie viele Slaves Sie verwenden können, bevor die
Vorteile sich zu relativieren beginnen, und wie weit Sie die
Leistungsfähigkeit Ihres Standorts verbessern können, müssen
Sie Ihre Abfragemuster und das Verhältnis zwischen dem Durchsatz
für Leseoperationen (Leseoperationen/Sekunde oder
reads
) und Schreiboperationen
(writes
)
kennen auf einem typischen Master und einem typischen Slave durch
Benchmark-Tests in Erfahrung bringen. Das folgende Beispiel zeigt
eine relativ stark vereinfachte Berechnung der Auswirkungen der
Replikation auf einem hypothetischen System.
Angenommen, die Systemlast umfasst 10 Prozent Schreiboperationen
und 90 Prozent Leseoperationen. Durch ein Benchmarking haben wir
ermittelt, dass reads
1200 – 2 ×
writes
ist. Anders gesagt, kann das System 1200
Leseoperationen pro Sekunde ohne Schreiboperationen verarbeiten,
ein Schreibvorgang erfolgt durchschnittlich halb so schnell wie
ein Lesevorgang, und die Beziehung ist linear. Nehmen wir nun
ferner an, dass der Master und jeder Slave jeweils die gleiche
Kapazität aufweisen und dass wir einen Master und
N
Slaves haben. Daraus ergibt sich für
jeden Server (Master oder Slave):
reads = 1200 – 2 × writes
reads = 9 × writes / (
(Leseoperationen werden aufgeteilt, während
Schreiboperationen an alle Server gehen)
N
+ 1)
9 × writes / (
N
+ 1) + 2
× writes = 1200
writes = 1200 / (2 +
9/(
N
+1))
Die letzte Gleichung gibt die maximale Anzahl von
Schreibvorgängen für N
Slaves
basierend auf einer maximalen Leserate von 1200 pro Minute und
einem Verhältnis von neun Leseoperationen pro Schreiboperation
an.
Diese Analyse lässt die folgenden Rückschlüsse zu:
Wenn N
= 0 ist (d. h. keine
Replikation), dann kann unser System ca. 1200 ÷ 11 = 109
Schreiboperationen pro Sekunde verarbeiten.
Bei N
= 1 sind 184
Schreiboperationen pro Sekunde möglich.
Bei N
= 8 sind 400
Schreiboperationen pro Sekunde möglich.
Bei N
= 17 sind 480
Schreiboperationen pro Sekunde möglich.
Schließlich kommen wir, je mehr sich
N
der Unendlichkeit (und unserem
Budget der negativen Unendlichkeit) annähert, auf einen Wert
von 600 Schreiboperationen pro Sekunde, während wir unseren
Systemdurchsatz etwa auf das 5,5fache gesteigert haben. Bei
nur acht Servern beträgt die Steigerung hingegen knapp das
Vierfache.
Beachten Sie, dass diese Berechnungen eine uneingeschränkte
Netzwerkbandbreite voraussetzen und mehrere andere Faktoren
vernachlässigen, die für Ihr System von Bedeutung sein könnten.
In vielen Fällen können Sie keine Berechnung ähnlich der obigen
durchführen, mit der sich exakt voraussagen ließe, wie sich das
Hinzufügen von N
Replikationsslaves
auf Ihr System auswirken würde. Allerdings kann Ihnen die
Beantwortung der folgenden Fragen dabei helfen, zu bestimmen, ob
und inwieweit eine Replikation die Leistungsfähigkeit Ihres
Systems verbessern könnte:
Welches Verhältnis besteht zwischen Lese- und Schreiboperationen auf Ihrem System?
Wie viel mehr Schreiboperationen kann ein Server verarbeiten, wenn Sie die Anzahl der Leseoperationen verringern?
Wie viele Slaves unterstützt die Bandbreite in Ihrem Netzwerk?
Frage: Wie kann ich mithilfe der Replikation eine Redundanz oder Hochverfügbarkeit realisieren?
Antwort: Mit den derzeit verfügbaren Funktionen sollten Sie einen Master und einen Slave (oder mehrere Slaves) einrichten und ein Skript verfassen, welches den Master auf Verfügbarkeit prüft. Dann weisen Sie Ihre Anwendungen und die Slaves an, bei einem Ausfall des Masters einen anderen Master zu wählen. Hier ein paar Vorschläge:
Verwenden Sie die CHANGE MASTER
TO
-Anweisung, um einen Slave anzuweisen, den Master
zu wechseln.
Eine gute Möglichkeit, Ihre Anwendungen bezüglich des
Standorts des Masters auf dem aktuellen Stand zu halten, ist
die Verwendung eines dynamischen DNS-Eintrags für den Master.
Bei bind
können Sie
nsupdate
verwenden, um Ihr DNS dynamisch
zu aktualisieren.
Starten Sie Ihre Slaves mit der Option
--log-bin
und ohne die Option
--log-slave-updates
. Auf diese Weise ist ein
Slave in der Lage, zum Master zu werden, sobald Sie die
Anweisungen STOP SLAVE
, RESET
MASTER
und CHANGE MASTER TO
auf
anderen Slaves absetzen. Angenommen, wir hätten folgende
Konfiguration:
WC \ v WC----> M / | \ / | \ v v v S1 S2 S3
In diesem Diagramm bezeichnet M
den Master,
S
die Slaves und WC
die
Clients, die Schreib- und Lesevorgänge an die Datenbank
absetzen. (Clients, die nur aus der Datenbank lesen, sind
nicht vorhanden, da bei ihnen keine Änderungen erforderlich
sind.) S1
, S2
und
S3
sind Slaves, die mit der Option
--log-bin
und ohne
--log-slave-updates
laufen. Da die von einem
Slave empfangenen Updates nicht im Binärlog vermerkt werden,
sofern nicht die Option --log-slave-updates
angegeben ist, sind die Binärlogs auf den Slaves anfangs
leer. Fällt nun M
aus irgendeinem Grund
aus, dann können Sie einen der Slaves auswählen, der dann
der neue Master wird. Wenn Sie also etwa S1
auswählen, sollten alle WC
auf
S1
umgelenkt werden, der die Updates in
sein Binärlog schreibt. S2
und
S3
replizieren nachfolgend von
S1
.
Sinn der Ausführung des Slaves ohne
--log-slave-updates
ist es, zu verhindern,
dass Slaves Updates zweimal erhalten, was vorkommen kann, wenn
einer der Slaves zum neuen Master wird. Nehmen wir einmal an,
bei S1
wäre die Option
--log-slave-updates
aktiviert. Er schreibt
nun Updates, die er von M
empfängt, in
sein eigenes Binärlog. Wenn S2
von
M
auf S1
also
umschaltet, empfängt er Updates von S1
,
die er bereits von M
erhalten hat.
Stellen Sie sicher, dass alle Slaves alle Anweisungen im
jeweiligen Relay-Log verarbeitet haben. Setzen Sie auf jedem
Slave STOP SLAVE IO_THREAD
ab und suchen
Sie dann in der Ausgabe von SHOW
PROCESSLIST
die Angabe Has read all relay
log
. Wenn dieser Zustand von allen Slaves erreicht
wurde, können sie auf die neue Konfiguration umgestellt
werden. Auf dem Slave S1
, der neuer Master
werden soll, setzen Sie STOP SLAVE
und
RESET MASTER
ab.
Auf den anderen Slaves S2
und
S3
setzen Sie STOP SLAVE
und CHANGE MASTER TO MASTER_HOST='S1'
ab
(wobei 'S1'
den echten Hostnamen von
S1
darstellt). Zu CHANGE
MASTER
fügen Sie nun alle Informationen darüber
hinzu, wie von S2
oder
S3
aus eine Verbindung mit
S1
hergestellt wird (also
user
,
password
,
port
). Sie müssen in
CHANGE MASTER
den Namen des Binärlogs von
S1
oder der Binärlogposition, ab der
gelesen werden soll, nicht angeben. Wir wissen, dass es das
erste Binärlog und die Position 4 ist (dies sind die
Standardwerte von CHANGE MASTER
).
Abschließend setzen Sie START SLAVE
auf
S2
und S3
ab.
Nun weisen Sie alle WC
an, ihre Anweisung
an S1
zu leiten. Von diesem Punkt an werden
alle Updateanweisungen, die von WC
an
S1
gesendet werden, in das Binärlog von
S1
geschrieben, welches dann alle
Updateanweisungen enthält, die seit dem Ausfall von
M
an S1
gesendet wurden.
Das Ergebnis ist folgende Konfiguration:
WC / | WC | M(unavailable) \ | \ | v v S1<--S2 S3 ^ | +-------+
Wenn M
wieder betriebsbereit ist, müssen
Sie darauf dieselbe CHANGE MASTER
-Anweisung
absetzen, die Sie auf S2
und
S3
verwendet haben, damit
M
ein Slave von S1
wird
und alle WC
-Schreiboperationen empfängt,
die er seit dem Ausfall verpasst hat. Um M
wieder zum Master zu machen (etwa weil es sich dabei um das
leistungsfähigste System handelt), verwenden Sie die
beschriebene Methode erneut und tun dabei so, als ob
S1
nicht mehr verfügbar wäre und
M
nun zum neuen Master wird. Während
dieses Vorgangs dürfen Sie nicht vergessen, RESET
MASTER
auf M
auszuführen, bevor
Sie S1
, S2
und
S3
zu Slaves von M
machen. Andernfalls empfangen diese Server alte
WC
-Schreiboperationen, die abgesetzt
wurden, bevor M
ausfiel.
Frage: Woher weiß ich, ob ein Master-Server das anweisungsbasierte oder das datensatzbasierte Binärlogformat verwendet?
Antwort: Überprüfen Sie den
Wert der Systemvariablen binlog_format
:
mysql> SHOW VARIABLES LIKE 'binlog_format';
Dieser heißt entweder STATEMENT
(anweisungsbasierte Replikation) oder ROW
(datensatzbasierte Replikation).
Frage: Wie weise ich einen Slave an, die datensatzbasierte Replikation zu verwenden?
Antwort: Slaves wissen automatisch, welches Format sie verwenden müssen.
Jedes Binärlogformat hat seine Vor- und Nachteile. Dieser Abschnitt fasst diese zusammen, um Ihnen eine Einschätzung zu erlauben, welches Format in Ihrer speziellen Situation das geeignetere ist.
Vorteile der anweisungsbasierten Replikation:
Bewährte Technologie, seit MySQL 3.23 vorhanden.
Kleinere Logdateien. Wenn Änderungs- oder Löschvorgänge viele Datensätze betreffen, sind die Logdateien wesentlich kleiner. Kleinere Logdateien erfordern weniger Speicherplatz und sind schneller gesichert.
Logdateien enthalten alle Anweisungen, mit denen Änderungen vorgenommen wurden, d. h., sie können zur Überwachung der Datenbank verwendet werden.
Logdateien können nicht nur zu Replikationszwecken, sondern auch zur Point-in-Time-Wiederherstellung verwendet werden. Siehe auch Abschnitt 5.10.3, „Zeitpunktbezogene Wiederherstellung“.
Ein Slave kann eine neuere MySQL-Version mit einer anderen Datensatzstruktur verwenden.
Nachteile der anweisungsbasierten Replikation:
Nicht alle UPDATE
-Anweisungen können
repliziert werden: Jedes nichtdeterministische Verhalten
(z. B. bei der Verwendung von Zufallsfunktionen in einer
SQL-Anweisung) ist bei der anweisungsbasierten Replikation
schwer zu replizieren. Bei Anweisungen, die eine
nichtdeterministische benutzerdefinierte Funktion
(User-Defined Function, UDF) verwenden, ist die Replikation
des Ergebnisses bei der anweisungsbasierten Replikation
überhaupt nicht möglich (dagegen repliziert die
datensatzbasierte Replikation einfach den von der UDF
zurückgegebenen Wert).
Anweisungen können nicht korrekt repliziert werden, wenn sie eine UDF verwenden, die nichtdeterministisch ist (d. h. deren Wert von anderen Aspekten als den übergebenen Parametern abhängt).
Anweisungen können nicht korrekt repliziert werden, wenn sie eine der folgenden Funktionen enthalten:
LOAD_FILE()
UUID()
USER()
FOUND_ROWS()
Alle übrigen Funktionen (einschließlich
RAND()
, NOW()
,
LOAD DATA INFILE
usw.) werden korrekt
repliziert.
INSERT ... SELECT
erfordert eine höhere
Zahl von Sperren auf Datensatzebene als bei der
datensatzbasierten Replikation.
UPDATE
-Anweisungen, die einen Tabellenscan
erfordern (weil in der WHERE
-Klausel kein
Index verwendet wird), müssen eine höhere Anzahl von
Datensätzen sperren als bei der datensatzbasierten
Replikation.
(Nur bei InnoDB
) Eine
INSERT
-Anweisung, die
AUTO_INCREMENT
verwendet, blockiert andere,
nicht kollidierende INSERT
-Anweisungen.
Langsamere Umsetzung von Daten auf dem Slave bei komplexen Abfragen.
Gespeicherte Funktionen (nicht aber gespeicherte Prozeduren)
werden mit demselben NOW()
-Wert wie die
aufrufende Anweisung ausgeführt. (Dies kann abhängig von den
Umständen ein Vor- oder Nachteil sein.)
Deterministische UDFs müssen auf die Slaves angewendet werden.
Wenn am Slave etwas nicht stimmt, nehmen die Unterschiede zwischen Master und Slave im Laufe der Zeit zu.
Tabellen müssen auf dem Master und dem Slave (fast) identisch sein.
Vorteile der datensatzbasierten Replikation:
Alles kann repliziert werden. Dies ist die sicherste Form der
Replikation. Beachten Sie, dass zurzeit DDL-Anweisungen (Data
Definition Language) wie etwa CREATE TABLE
anweisungsbasiert repliziert werden, während bei
DML-Anweisungen (Data Manipulation Language) sowie bei
GRANT
- und
REVOKE
-Anweisungen die Replikation
datensatzbasiert erfolgt. Für Anweisungen wie CREATE
... SELECT
wird eine
CREATE
-Anweisung aus der Tabellendefinition
erstellt, die dann anweisungsbasiert repliziert wird, während
das Einfügen von Datensätzen datensatzbasiert repliziert
wird.
Die Technologie ist dieselbe wie bei den meisten anderen Datenbanksystemen – Kenntnisse anderer Systeme lassen sich einfach auf MySQL übertragen.
In vielen Fällen geht es bei Tabellen mit Primärschlüsseln schneller, wenn man die Daten auf den Slave anwendet.
Bei den folgenden Anweisungstypen werden weniger Sperren auf dem Master benötigt (was die Nebenläufigkeit erhöht):
INSERT ... SELECT
INSERT
-Anweisungen mit
AUTO_INCREMENT
UPDATE
- oder
DELETE
-Anweisungen mit
WHERE
-Klauseln, die keine Schlüssel
verwenden und die meisten der untersuchten Datensätze
unverändert lassen
Weniger Sperren auf dem Slave bei INSERT
-,
UPDATE
- oder
DELETE
-Anweisungen.
Es ist möglich, mehrere Threads hinzuzufügen, um Daten zukünftig auf den Slave anzuwenden (dies funktioniert bei SMP-Systemen besser).
Nachteile der datensatzbasierten Replikation:
Größere Logdateien (in manchen Fällen sogar wesentlich größer).
Das Binärlog enthält Daten für umfangreiche Anweisungen, die per Rollback rückgängig gemacht wurden.
Wenn Sie mit der datensatzbasierten Replikation eine Anweisung
(z. B. eine UPDATE
- oder
DELETE
-Anweisung) replizieren, muss jeder
geänderte Datensatz in das Binärlog geschrieben werden. Im
Gegensatz dazu wird bei Verwendung der anweisungsbasierten
Replikation nur die Anweisung in das Binärlog geschrieben.
Wenn die Anweisung viele Datensätze ändert, schreibt die
datensatzbasierte Replikation deutlich mehr Daten in das
Binärlog. In diesem Fall wird das Binärlog für eine
längere Zeit gesperrt, um die Daten schreiben zu können, was
Probleme mit der Nebenläufigkeit verursachen kann.
Deterministische UDFs, die große
BLOB
-Werte erzeugen, werden merklich
langsamer repliziert.
Sie können die Logs darauf überprüfen, welche Anweisungen ausgeführt wurden.
Sie können auf dem Slave nicht nachprüfen, welche Anweisungen vom Master empfangen und dann ausgeführt wurden.
Wenn Sie die Anleitung befolgt haben und Ihre Replikationskonfiguration trotzdem nicht funktioniert, sollten Sie zuallererst das Fehlerlog auf Meldungen überprüfen. Allzu viele Benutzer haben bei Auftreten eines Problems kostbare Zeit damit vergeudet, dies nicht gleich gemacht zu haben.
Wenn Sie aus dem Fehlerlog nicht ableiten können, welches Problem vorliegt, probieren Sie die folgenden Methoden aus:
Überprüfen Sie, ob am Master das binäre Loggen aktiviert
ist, indem Sie eine SHOW MASTER
STATUS
-Anweisung absetzen. Bei aktiviertem Loggen
ist Position
ungleich null. Sollte das
binäre Loggen nicht aktiviert sein, dann stellen Sie sicher,
dass der Master mit den Optionen --log-bin
und --server-id
läuft.
Überprüfen Sie, ob der Slave ausgeführt wird. Mit
SHOW SLAVE STATUS
können Sie feststellen,
ob die Werte von Slave_IO_Running
und
Slave_SQL_Running
jeweils
Yes
lauten. Andernfalls überprüfen Sie
die Optionen, die beim Start des Slave-Servers angegeben
waren. So verhindert etwa --skip-slave-start
,
dass die Slave-Threads gestartet werden, bis Sie eine
START SLAVE
-Anweisung absetzen.
Wird der Slave ausgeführt, dann prüfen Sie, ob er eine
Verbindung zum Master herstellen konnte. Setzen Sie
SHOW PROCESSLIST
ab, suchen Sie die I/O-
und SQL-Threads und überprüfen Sie die zugehörigen
State
-Spalten. Siehe auch
Abschnitt 6.4, „Replikation: Implementationsdetails“. Wenn
für den I/O-Thread als Status Connecting to
master
angegeben ist, überprüfen Sie die
Berechtigungen für den Replikationsbenutzer auf dem Master,
den Hostnamen des Masters und Ihre DNS-Konfiguration und
stellen Sie sicher, dass der Master ausgeführt wird und auch
vom Slave erreicht werden kann.
Wurde der Slave bereits vorher ausgeführt, dann aber beendet, dann liegt das in der Regel daran, dass irgendeine Anweisung, die auf dem Master erfolgreich verarbeitet wurde, auf dem Slave fehlgeschlagen ist. Dies sollte niemals passieren, wenn Sie eine korrekte Momentaufnahme auf dem Master erstellt und die Daten auf dem Slave niemals außerhalb des Slave-Threads modifiziert haben. Wird der Slave unerwartet beendet, dann liegt entweder ein Bug vor, oder Sie sind auf eine der bekannten Einschränkungen der Replikation gestoßen, die in Abschnitt 6.8, „Replikation: Features und bekannte Probleme“, beschrieben sind. Wenn es sich um einen Bug handelt, lesen Sie Abschnitt 6.14, „Berichten von Replikationsfehlern und -problemen“, um zu erfahren, wie Sie diesen melden.
Wenn eine Anweisung, die auf dem Master klaglos verarbeitet wurde, nicht auf dem Slave ausgeführt werden kann, probieren Sie folgende Vorgehensweise aus, sofern die Durchführung einer vollständigen Datenbankneusynchronisierung durch Löschen der Datenbanken auf dem Slave und Kopieren einer neuen Momentaufnahme vom Master nicht realisierbar ist:
Ermitteln Sie, ob die betreffende Tabelle auf dem Slave
sich von der auf dem Master unterscheidet. Versuchen Sie
zu ergründen, was geschehen ist. Dann machen Sie die
Tabelle auf dem Slave identisch zu der auf dem Master und
führen START SLAVE
aus.
Funktioniert der vorherige Schritt nicht oder ist er nicht durchführbar, dann prüfen Sie, ob es sicher ist, die Änderung (sofern erforderlich) manuell durchzuführen und die nächste Anweisung vom Master zu ignorieren.
Wenn Sie feststellen, dass Sie die nächste Anweisung vom Master übergehen können, setzen Sie die folgenden Anweisungen ab:
mysql>SET GLOBAL SQL_SLAVE_SKIP_COUNTER =
mysql>N
;START SLAVE;
Der Wert von N
sollte 1 sein,
wenn die nächste Anweisung vom Master weder
AUTO_INCREMENT
noch
LAST_INSERT_ID()
verwendet. Andernfalls
wählen Sie den Wert 2. Grund hierfür ist die Tatsache,
dass Anweisungen, die AUTO_INCREMENT
oder LAST_INSERT_ID()
verwenden, zwei
Ereignisse in das Binärlog des Masters schreiben.
Wenn Sie ganz sicher sind, dass der Slave vollkommen synchron zum Master gestartet wurde und niemand die betreffenden Tabellen außerhalb des Slave-Threads modifiziert hat, dann ist die Diskrepanz mit hoher Wahrscheinlichkeit Ergebnis eines Bugs. Wenn Sie die aktuelle MySQL-Version verwenden, melden Sie dieses Problem bitte. Wenn Sie hingegen eine ältere Version einsetzen, aktualisieren Sie – sofern möglich – auf den aktuellen Produktions-Release, um festzustellen, ob das Problem fortbesteht.
Wenn Sie festgestellt haben, dass kein benutzerseitiger Fehler vorliegt und die Replikation trotzdem nicht stabil ist oder womöglich gar nicht funktioniert, ist es an der Zeit, uns einen Bugreport zu schicken. Wir benötigen von Ihnen so viele Informationen wie möglich, um den Bug aufzuspüren. Bitte nehmen Sie sich für die Vorbereitung des Bugreports Zeit und seien Sie sorgfältig bei Ihren Angaben.
Wenn Sie einen reproduzierbaren Testfall haben, der den Bug demonstriert, geben Sie diesen bitte in unsere Fehlerdatenbank ein. Eine Anleitung zur Vorgehensweise finden Sie in Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“. Wenn Sie ein „Phantomproblem“ haben (d. h. eines, welches sich nicht gezielt reproduzieren lässt), dann gehen Sie wie folgt vor:
Stellen Sie sicher, dass kein Fehler vorhanden ist. Wenn Sie am Slave beispielsweise Änderungen außerhalb des Slave-Threads vornehmen, dann sind die Daten nicht mehr synchron, und es kann bei Updates zu Verstößen aufgrund von Dubletten eindeutiger Schlüssel kommen. In diesem Fall bleibt der Slave-Thread stehen und wartet, bis Sie die Tabellen manuell bereinigt und die Synchronisation auf diese Weise wiederhergestellt haben. Dies ist kein replikationsbezogenes Problem. Die Replikation schlägt vielmehr aufgrund eines äußeren Störeinflusses fehl.
Führen Sie den Slave mit den Optionen
--log-slave-updates
und
--log-bin
aus. Diese Optionen bewirken, dass
der Slave die Updates, die er vom Master erhält, in seine
eigenen Binärlogs schreibt.
Speichern Sie alle Beweismittel, bevor Sie den Replikationsstatus zurücksetzen. Wenn wir keine oder nur bruchstückhafte Informationen erhalten, wird es schwierig bis unmöglich, die Problemursache zu ermitteln. Folgende Beweisstücke sollten Sie übermitteln:
alle Binärlogs des Masters
alle Binärlogs des Slaves
Ausgabe von SHOW MASTER STATUS
auf dem
Master zum Zeitpunkt der Feststellung des Problems
Ausgabe von SHOW SLAVE STATUS
auf dem
Slave zum Zeitpunkt der Feststellung des Problems
Fehlerlogs von Master und Slave
Überprüfen Sie mit mysqlbinlog die
Binärlogs. Folgender Befehl sollte zur Ermittlung der
problematischen Abfrage hilfreich sein. Hierbei sind
log_pos
und
log_file
die Werte
Master_Log_File
bzw.
Read_Master_Log_Pos
in der Ausgabe von
SHOW SLAVE STATUS
.
shell>mysqlbinlog -j
log_pos
\
log_file
| head
Nachdem Sie alle Beweisstücke für das Problem gesammelt haben, versuchen Sie es zunächst als separaten Testfall zu extrahieren. Geben Sie das Problem danach mit möglichst vielen Informationen in unsere Bugdatenbank ein. Die Vorgehensweise ist in Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“, beschrieben.
Wenn mehrere Server als Replikationsmaster konfiguriert sind,
müssen spezielle Schritte unternommen werden, um
Schlüsselkollisionen bei der Verwendung von
AUTO_INCREMENT
-Spalten zu verhindern;
andernfalls könnten mehrere Master beim Einfügen von
Datensätzen versuchen, denselben
AUTO_INCREMENT
-Wert zu verwenden.
Die Systemvariablen auto_increment_increment
und auto_increment_offset
ermöglichen die
Multi-Master-Replikation in Verbindung mit
AUTO_INCREMENT
-Spalten. Jede dieser Variablen
hat einen Standard- und Mindestwert von 1. Der Höchstwert
beträgt jeweils 65.535.
Diese beiden Variablen beeinflussen das Verhalten von
AUTO_INCREMENT
-Spalten wie folgt:
auto_increment_increment
steuert das
Intervall zwischen aufeinander folgenden
AUTO_INCREMENT
-Werten.
auto_increment_offset
bestimmt den
Startwert der Spalte AUTO_INCREMENT
.
Durch Auswahl nichtkollidierender Werte auf verschiedenen Mastern
wird dafür gesorgt, dass Server in einer Multimaster-Umgebung
beim Einfügen neuer Datensätze in dieselbe Tabelle keine
kollidierenden AUTO_INCREMENT
-Werte verwenden.
Stellen Sie die Variablen wie folgt ein, um
N
Master-Server zu konfigurieren:
Setzen Sie auto_increment_increment
auf
jedem Master auf N
.
Stellen Sie auf jedem der N
Master
einen unterschiedlichen Wert für
auto_increment_offset
ein (0, 1, 2,
… , N
– 1).
Weitere Informationen zu
auto_increment_increment
und
auto_increment_offset
finden Sie in
Abschnitt 5.2.2, „Server-Systemvariablen“.
Inhaltsverzeichnis
SELECT
-Anweisungen und andere Anfragen optimierenEXPLAIN
-Syntax (Informationen über ein
SELECT
erhalten)SELECT
-AnweisungenWHERE
-KlauselIS NULL
-OptimierungDISTINCT
LEFT JOIN
und RIGHT
JOIN
ORDER BY
-OptimierungGROUP BY
-OptimierungLIMIT
-OptimierungINSERT
-AnweisungenUPDATE
-AnweisungenDELETE
-AnfragenMyISAM
-Schlüssel-CacheMyISAM
-IndexstatistikenDie Optimierung ist eine komplexe Aufgabe, denn sie setzt letztendlich ein umfassendes Verständnis des gesamten zu optimierenden Systems voraus. Zwar ist es möglich, in eingeschränktem Maße lokale Optimierungen ohne umfangreiche Kenntnisse Ihres Systems oder Ihrer Anwendung vorzunehmen, aber je optimaler Sie Ihr System gestalten wollen, desto mehr müssen Sie darüber wissen.
In diesem Kapitel werden wir versuchen, die verschiedenen Möglichkeiten zur Optimierung von MySQL zu erläutern und entsprechende Beispiele zu geben. Bedenken Sie aber, dass es stets zusätzliche Möglichkeiten gibt, das System zu beschleunigen, wobei dabei jedoch immer auch der entsprechende Aufwand zu berücksichtigen ist.
Der wesentlichste Faktor bei der Beschleunigung eines Systems ist sein grundsätzlicher Aufbau. Ferner müssen Sie wissen, welche Bearbeitungen Ihr System durchführt und wo Engpässe vorliegen. In den meisten Fällen treten Engpässe aufgrund folgender Ursachen auf:
Suchvorgänge auf der Festplatte. Die Festplatte braucht Zeit, um Daten zu finden. Bei modernen Festplatten beträgt die durchschnittliche Dauer eines Suchvorgangs weniger als 10 Millisekunden, d. h., wir können von einem theoretischen Wert von 100 Suchvorgängen pro Sekunden ausgehen. Dieser Wert lässt sich durch neue Festplatten nur geringfügig verbessern und ist für nur eine einzige Tabelle sehr schwierig zu optimieren. Die Verteilung von Daten auf mehrere Festplatten ist jedoch geeignet, die Suchdauer zu verbessern.
Lese- und Schreiboperationen auf Festplatte. Wenn die Festplatte die korrekte Position erreicht hat, müssen die Daten gelesen werden. Moderne Festplatten liefern einen Datendurchsatz von mindestens 10 bis 20 Mbyte/s. Dieser Wert ist einfacher zu optimieren als der Suchwert, da parallel von mehreren Festplatten gelesen werden kann.
Prozessorzyklen. Wenn die Daten im Hauptspeicher gelandet sind, müssen wir sie verarbeiten, um das gewünschte Ergebnis zu erhalten. Der am meisten einengende Faktor ist das Vorhandensein von im Vergleich zum verfügbaren Speicher kleinen Tabellen. Bei kleinen Tabellen wiederum ist Geschwindigkeit jedoch nicht das Problem.
Speicherbandbreite. Wenn der Prozessor mehr Daten benötigt, als in den Prozessor-Cache passen, dann wird die Bandbreite des Hauptspeichers zum Engpass. Dies kommt zwar bei den meisten Systemen höchst selten vor, sollte jedoch immer in Betracht gezogen werden.
Wenn Sie die MyISAM
-Speicher-Engine
verwenden, benutzt MySQL eine extrem schnelle Tabellensperrung,
die mehrere lesende Benutzer oder einen schreibenden Benutzer
gestattet. Das größte Problem bei dieser Speicher-Engine tritt
auf, wenn ein konstanter Strom von gemischten Änderungs- und
langsamen Auswahlanweisungen für eine einzelne Tabelle
vorhanden ist. Wenn dies bei bestimmten Tabellen ein Problem
darstellt, können Sie für diese eine andere Speicher-Engine
verwenden. Siehe auch Kapitel 14, Speicher-Engines und Tabellentypen.
MySQL kann sowohl mit transaktionssicheren als auch mit
nichttransaktionssicheren Tabellen arbeiten. Um die reibungslose
Arbeit mit nichttransaktionssicheren Tabellen (also Tabellen,
für die im Fehlerfall kein Rollback durchgeführt werden kann)
zu erleichtern, unterstützt MySQL die folgenden Regeln.
Beachten Sie, dass diese Regeln nur dann
gültig sind, wenn MySQL nicht im strikten SQL-Modus ausgeführt
wird oder Sie IGNORE
für
INSERT
- oder
UPDATE
-Anweisungen angegeben haben.
Für alle Spalten gibt es Vorgabewerte.
Wenn Sie einen unpassenden oder ungültigen Wert in eine Spalte eingeben, setzt MySQL diesen automatisch auf den „bestmöglichen“ Wert, statt einen Fehler zu melden. Bei numerischen Werten ist dies entweder 0 oder der kleinst- oder größtmögliche Wert. Bei Strings wird entweder der Leer-String oder der Bestandteil des Strings benutzt, der noch in der Spalte gespeichert werden kann.
Alle berechneten Ausdrücke geben einen Wert zurück, der
verwendet werden kann, statt eine Fehlerbedingung
auszugeben. So gibt etwa 1 ÷ 0 NULL
zurück.
Um obiges Verhalten zu ändern, können Sie eine striktere
Datenverarbeitung aktivieren, indem Sie den SQL-Modus auf dem
Server entsprechend ändern. Weitere Informationen zum Umgang
mit Daten finden Sie in Abschnitt 1.9.6, „Wie MySQL mit Constraints umgeht“,
Abschnitt 5.2.5, „Der SQL-Modus des Servers“, und Abschnitt 13.2.4, „INSERT
“.
Da alle SQL-Server unterschiedliche Teile des SQL-Standards implementieren, ist die Entwicklung portierbarer Datenbankanwendungen sehr aufwändig. Bei sehr simplen Auswahl- und Einfügeoperationen mag die einfache Portierbarkeit noch gegeben sein, aber je mehr Funktionalitäten Sie benötigen, umso komplexer wird sie. Wenn Sie eine Anwendung brauchen, die auf vielen verschiedenen Datenbanksystemen schnell ist, wird es noch schwieriger.
Alle Datenbanksysteme haben Schwachpunkte: Entwicklungsseitig enthalten sie Kompromisse, die ein unterschiedliches Verhalten verursachen.
Um eine komplexe Anwendung portierbar zu machen, müssen Sie zunächst ermitteln, auf welchen SQL-Servern sie laufen muss, und dann bestimmen, welche Funktionen diese Server unterstützen. Sie können mit dem MySQL-Programm crash-me Funktionen, Typen und Einschränkungen ermitteln, die für eine Auswahl von Datenbankservern gelten. crash-me prüft nicht alle denkbaren Funktionen, ist aber mit etwa 450 Tests vergleichsweise umfassend. Ein Beispiel für die Art von Informationen, die sich mit crash-me ermitteln lassen, ist etwa die Tatsache, dass Sie keine Spaltennamen verwenden sollten, die mehr als 18 Zeichen umfassen, wenn Sie Informix oder DB2 einsetzen wollen.
Das Programm crash-me und die
MySQL-Benchmarks hängen stark von der jeweiligen Datenbank ab.
Sehen Sie sich einmal an, wie sie geschrieben sind, um ein
Gefühl dafür erhalten, was Sie tun müssen, um Ihre eigenen
Anweisungen so datenbankunabhängig wie möglich zu machen. Sie
finden die Programme im Verzeichnis
sql-bench
der MySQL-Quelldistributionen.
Sie sind in Perl geschrieben und verwenden die
DBI-Datenbankschnittstelle. Bereits die Verwendung von DBI löst
das Portabilitätsproblem teilweise, denn die Schnittstelle
bietet datenbankübergreifende Zugriffsmethoden. Siehe auch
Abschnitt 7.1.4, „Die MySQL-Benchmark-Reihe“.
Wenn Sie nach Datenbankunabhängigkeit streben, brauchen Sie ein
gutes Gespür für die Engpässe auf den einzelnen SQL-Servern.
So ist MySQL beispielsweise sehr schnell, wenn es um das Abrufen
und Aktualisieren von Datensätzen in
MyISAM
-Tabellen geht, hat aber Probleme bei
Fällen, in denen gleichzeitig langsame Lese- und
Schreibvorgänge verwaltet werden müssen. Oracle andererseits
zeigt sich ausgesprochen widerspenstig, wenn Sie auf Datensätze
zugreifen wollen, die Sie kürzlich aktualisiert (und noch nicht
auf Festplatte synchronisiert) haben. Transaktionssichere
Datenbanksysteme sind generell nicht besonders gut zur
Erstellung von Zusammenfassungstabellen aus Logtabellen
geeignet, weil in diesem Fall die Sperrung von Datensätzen
praktisch nutzlos ist.
Um Ihre Anwendung wirklich datenbankunabhängig zu machen, sollten Sie eine leicht zu erweiternde Schnittstelle definieren, über die Sie Ihre Daten manipulieren. C++ beispielsweise ist auf den meisten Systemen verfügbar, weswegen es sinnvoll ist, eine Datenbankschnittstelle auf Basis einer C++-Klasse zu verwenden.
Wenn Sie die eine oder andere Funktion verwenden, die für ein
gegebenes Datenbanksystem spezifisch ist (z. B. die
MySQL-Anweisung REPLACE
), dann sollten Sie
dieselbe Funktion für andere SQL-Server implementieren, indem
Sie eine alternative Methode einkodieren. Auch wenn diese
Alternative langsamer ist, so erlaubt sie es anderen Servern
doch, dieselben Aufgaben auszuführen.
Bei MySQL können Sie mit der Syntax /*! */
MySQL-spezifische Schlüsselwörter zu einer Anweisung
hinzufügen. Der Code in /* */
wird von den
meisten anderen SQL-Servern als Kommentar betrachtet (und
insofern ignoriert). Informationen zum Schreiben von Kommentaren
finden Sie in Abschnitt 9.4, „Kommentar“.
Wenn die Leistungsfähigkeit wichtiger ist als die Genauigkeit (wie es beispielsweise bei Webanwendungen der Fall ist), dann können Sie eine Anwendungsschicht erstellen, die alle Ergebnisse zwischenspeichert, um die Performance noch besser zu optimieren. Indem Sie ältere Ergebnisse nach einer bestimmten Zeit ungültig werden lassen, können Sie den Cache ausreichend aktuell halten. Auf diese Weise können Sie Belastungsspitzen abfangen, indem Sie die Cache-Größe dynamisch erhöhen und den Ungültigkeitszeitpunkt nach hinten verschieben, bis sich die Belastung wieder normalisiert hat.
In diesem Fall sollten die Angaben zur Tabellenerstellung Informationen zur ursprünglichen Cache-Größe und dazu enthalten, wie oft die Tabelle normalerweise aktualisiert wird.
Eine interessante Alternative zur Implementierung eines Anwendungs-Caches ist die Verwendung des Abfrage-Caches von MySQL. Wenn Sie den Abfrage-Cache aktivieren, bestimmt der Server selbst, ob ein Abfrageergebnis wiederverwendet werden kann. Dies vereinfacht Ihre Anwendung. Siehe auch Abschnitt 5.14, „MySQL-Anfragen-Cache“.
Dieser Abschnitt beschreibt eine sehr frühe Anwendung für MySQL.
Im Verlauf der ursprünglichen Entwicklung von MySQL wurden die Funktionen an die Anforderungen unseres größten Kunden angepasst, der das Data-Warehousing für einige der großen schwedischen Handelshäuser implementierte.
Von allen Läden erhielten wir wöchentliche Übersichten über alle Kundenkartentransaktionen, und es wurde von uns verlangt, brauchbare Informationen für Geschäftsinhaber bereitzustellen, damit diese feststellen konnten, wie sich ihre Werbekampagnen auf das Kaufverhalten ihrer Kunden auswirkten.
Das Datenvolumen war gewaltig (ca. sieben Millionen Transaktionen pro Monat), und wir hatten Daten für vier bis zehn Jahre, die wir den Benutzern präsentieren sollten. Allwöchentlich erhielten wir Anfragen von unseren Kunden, die sofortigen Zugriff auf neue, auf diesen Daten basierende Berichte benötigten.
Dieses Problem lösten wir, indem wir alle Daten eines Monats in komprimierten „Transaktionstabellen“ speicherten. Wir hatten eine Anzahl einfacher Makros, die aus den Tabellen, in denen die Transaktionen gespeichert waren, nach verschiedenen Kriterien (Produktgruppe, Kundennummer, Filiale usw.) gruppierte Übersichtstabellen erstellten. Diese Berichte waren Webseiten, die mithilfe eines kleinen Perl-Skripts dynamisch erzeugt wurden. Das Skript analysierte eine Webseite, führte die enthaltenen SQL-Anweisungen aus und fügte die Ergebnisse ein. Wir hätten stattdessen sicher PHP oder mod_perl verwendet, aber diese waren seinerzeit noch nicht verfügbar.
Für die grafische Ausgabe schrieben wir ein kleines Tool in C, das SQL-Abfrageergebnisse verarbeiten und auf Basis der Ergebnisse GIF-Grafiken erstellen konnte. Auch dieses Tool wurde von dem Perl-Skript, welches die Webseiten analysierte, dynamisch ausgeführt.
In den meisten Fällen konnte ein neuer Bericht einfach erstellt werden, indem man ein vorhandenes Skript kopierte und die von ihm verwendete SQL-Abfrage einfach anpasste. In manchen Fällen mussten wir neue Spalten zu einer vorhandenen Übersichtstabelle hinzufügen oder eine neue Tabelle erstellen. Auch dies war ganz einfach, weil wir alle Tabellen mit den Transaktionen auf Festplatte speicherten. (In der Summe hatten wir dann 50 Gbyte Transaktionstabellen sowie 200 Gbyte weiterer Kundendaten.)
Außerdem gestatteten wir unseren Kunden via ODBC den direkten Zugriff auf die Übersichtstabellen, sodass Kunden bei Bedarf selbst mit den Daten experimentieren konnten.
Dieses System funktionierte gut, und wir hatten keine Probleme mit der Verwaltung der Daten auf einer eher bescheidenen Hardware (Sun Ultra SPARCstation, 2 × 200 MHz). Am Ende wurde das System dann auf Linux migriert.
Anhand dieser Benchmark-Reihe kann jeder Benutzer ermitteln,
welche Operationen eine gegebene SQL-Implementierung gut oder
weniger gut ausführt. Sie können sich einen guten Eindruck
davon verschaffen, wie die Benchmarks funktionieren, indem Sie
sich den Code und die Ergebnisse im Verzeichnis
sql-bench
einer beliebigen
MySQL-Quelldistribution ansehen.
Beachten Sie, dass diese Benchmark nur einen Thread verwendet – sie misst also die Mindestdauer der durchgeführten Operationen. Wir planen, die Benchmark-Reihe in Zukunft durch Multithread-Tests zu ergänzen.
Um die Benchmark-Reihe verwenden zu können, müssen folgende Voraussetzungen erfüllt sein:
Die Benchmark-Reihe wird als Bestandteil der MySQL-Quelldistributionen ausgeliefert. Sie können entweder eine Release-Version von http://dev.mysql.com/downloads/ herunterladen oder den aktuellen Entwicklungs-Source-Tree verwenden. (Siehe auch Abschnitt 2.8.3, „Installation vom Entwicklungs-Source-Tree“.)
Die Benchmark-Skripten sind in Perl geschrieben und
verwenden das Perl-DBI-Modul für den Zugriff auf
Datenbankserver; insofern muss DBI installiert sein. Ferner
benötigen Sie die serverspezifischen BDB-Treiber für jeden
Server, den Sie testen wollen. Um beispielsweise MySQL,
PostgreSQL und DB2 prüfen zu können, müssen die Module
DBD::mysql
, DBD::Pg
und DBD::DB2
installiert sein. Siehe auch
Abschnitt 2.13, „Anmerkungen zur Perl-Installation“.
Nachdem Sie sich eine MySQL-Quelldistribution besorgt haben,
finden Sie die Benchmark-Reihe im dortigen Verzeichnis
sql-bench
. Um die Benchmark-Tests
durchzuführen, erstellen Sie MySQL und wechseln dann in das
Verzeichnis sql-bench
. Dort führen Sie das
Skript run-all-tests
aus:
shell>cd sql-bench
shell>perl run-all-tests --server=
server_name
server_name
sollte der Name eines der
unterstützten Server sein. Um eine Liste aller Optionen und
unterstützten Server zu erhalten, rufen Sie folgenden Befehl
auf:
shell> perl run-all-tests --help
Das Skript crash-me befindet sich ebenfalls
im Verzeichnis sql-bench
.
crash-me versucht durch Ausführung von
Abfragen zu ermitteln, welche Funktionen ein Datenbanksystem
unterstützt und welche Fähigkeiten und Einschränkungen es
aufweist. Beispielsweise wird ermittelt,
welche Datentypen unterstützt werden,
wie viele Indizes unterstützt werden,
welche Funktionen unterstützt werden,
wie groß eine Abfrage sein darf,
wie groß eine VARCHAR
-Spalte sein darf.
Die Ergebnisse von crash-me finden Sie für viele verschiedene Datenbankserver unter http://dev.mysql.com/tech-resources/crash-me.php. Weitere Informationen zu Benchmark-Ergebnissen finden Sie unter http://dev.mysql.com/tech-resources/benchmarks/.
Sie sollten Ihre Anwendung und Ihre Datenbank in jedem Fall mit der Benchmark-Reihe prüfen, um festzustellen, wo ggf. Engpässe vorhanden sind. Wenn Sie einen Engpass behoben (oder ihn durch ein „Dummymodul“ ersetzt) haben, können Sie mit der Suche nach weiteren Engpässen fortfahren. Auch wenn die Gesamtleistung für Ihre Anwendung derzeit akzeptabel sein sollte, sollten Sie zumindest einen Plan für jeden Engpass erstellen und entscheiden, wie Sie ihn bei Bedarf beseitigen, sofern dieser Bedarf eines Tages auftreten sollte.
Beispiele für portable Benchmark-Programme finden Sie in der MySQL-Benchmark-Reihe. Siehe auch Abschnitt 7.1.4, „Die MySQL-Benchmark-Reihe“. Sie können ein beliebiges Programm dieser Reihe nehmen und an Ihre eigenen Bedürfnisse anpassen. Dies erlaubt Ihnen, verschiedene Lösungen für Ihr Problem auszuprobieren und zu ermitteln, welche wirklich die schnellste ist.
Eine weitere kostenlose Benchmark-Reihe ist die Open Source Database Benchmark, die Sie unter http://osdb.sourceforge.net/ erhalten.
Häufig treten Probleme nur dann auf, wenn das System sehr stark ausgelastet ist. Viele unserer Kunden wenden sich an uns, wenn sie ein (getestetes) Produktionssystem haben, welches unter Last Ausfallerscheinungen zeigt. In den meisten Fällen werden leistungsbezogene Probleme durch Faktoren des grundlegenden Datenbankdesigns (etwa im Fall von Schwächen bei Tabellenscans unter Last) oder durch Probleme mit dem Betriebssystem oder mit Bibliotheken verursacht. Meistens würden sich diese Probleme wesentlich einfacher beheben lassen, wenn das jeweilige System nicht bereits in der Produktion verwendet würde.
Um derartige Probleme zu vermeiden, sollten Sie den Aufwand auf sich nehmen und Benchmark-Tests Ihrer Anwendung unter maximaler Last durchführen:
Das Programm mysqlslap kann eine hohe Belastung simulieren, indem die Auswirkungen von durch mehrere Clients gleichzeitig abgesetzte Abfragen nachgestellt werden. Siehe auch Abschnitt 8.14, „mysqlslap — Client zur Lastemulation“.
Sie können auch Super Smack ausprobieren, welches Sie unter http://jeremy.zawodny.com/mysql/super-smack/ finden.
Wie die Namen dieser Programme bereits suggerieren, besteht ihr Zweck darin, Ihr System in die Knie zu zwingen. Es sollte also klar sein, dass Sie diese Programme nur auf Entwicklungssystemen einsetzen.
EXPLAIN
-Syntax (Informationen über ein
SELECT
erhalten)SELECT
-AnweisungenWHERE
-KlauselIS NULL
-OptimierungDISTINCT
LEFT JOIN
und RIGHT
JOIN
ORDER BY
-OptimierungGROUP BY
-OptimierungLIMIT
-OptimierungINSERT
-AnweisungenUPDATE
-AnweisungenDELETE
-Anfragen
Zunächst einmal gibt es einen Faktor, der sich auf alle
Anweisungen auswirkt: Je komplexer Ihre Berechtigungskonfiguration
ist, desto höher ist der Aufwand für MySQL. Die Verwendung
einfacherer Berechtigungen beim Absetzen von
GRANT
-Anweisungen gestattet MySQL eine
Verringerung der berechtigungsbedingten Mehrbelastung, wenn
Clients Anweisungen ausführen. Wenn Sie beispielsweise keine
Berechtigungen auf Tabellen- oder Spaltenebene gewähren, muss der
Server keinerlei Überprüfung der Tabellen
tables_priv
und columns_priv
durchführen. Analog ist auch keine Ressourcenzählung
durchzuführen, wenn Sie die Ressourcen für kein Konto
beschränken. Wenn Sie eine sehr hohe Auslastung durch die
Anweisungsverarbeitung haben, kann es lohnenswert sein, eine
vereinfachte Gewährungsstruktur zu verwenden, um die
Mehrbelastung durch die Überprüfung von Berechtigungen zu
verringern.
Hängt Ihr Problem mit einem bestimmten MySQL-Ausdruck oder einer
MySQL-Funktion zusammen, dann können Sie eine Timingprüfung
durchführen, indem Sie die Funktion
BENCHMARK()
mithilfe des Clientprogramms
mysql aufrufen. Die Syntax lautet
BENCHMARK(
.
Der Rückgabewert ist immer null, aber mysql
gibt eine Zeile aus, die näherungsweise die Ausführungsdauer der
Anweisung angibt. Zum Beispiel:
loop_count
,expression
)
mysql> SELECT BENCHMARK(1000000,1+1);
+------------------------+
| BENCHMARK(1000000,1+1) |
+------------------------+
| 0 |
+------------------------+
1 row in set (0.32 sec)
Dieses Ergebnis wurde mit einem Pentium II-System (400 MHz) ermittelt. Es zeigt, dass MySQL auf diesem System 1.000.000 einfache Additionsausdrücke in 0,32 Sekunden ausführen kann.
Eigentlich sollten alle MySQL-Funktionen hochgradig optimiert
sein, aber es gibt unter Umständen ein paar Ausnahmen.
BENCHMARK()
ist ein hervorragendes Tool, um zu
ermitteln, ob irgendeine Funktion für Ihre Abfragen problematisch
sein könnte.
EXPLAIN tbl_name
Oder:
EXPLAIN [EXTENDED | PARTITIONS] SELECT
select_options
Die EXPLAIN
-Anweisung kann entweder als
Synonym für DESCRIBE
oder als Möglichkeit
verwendet werden, um Informationen bezüglich der Frage zu
ermitteln, wie MySQL eine SELECT
-Anweisung
ausführt:
EXPLAIN
ist synonym zu
tbl_name
DESCRIBE
oder
tbl_name
SHOW COLUMNS FROM
.
tbl_name
Wenn Sie einer SELECT
-Anweisung das
Schlüsselwort EXPLAIN
voranstellen,
zeigt MySQL Informationen des Optimierers zum
Ausführungsplan der Abfrage an. MySQL erläutert also, wie
es die SELECT
-Anweisung verarbeiten
würde, und gibt zudem an, wie und in welcher Reihenfolge
Tabellen miteinander verknüpft werden.
EXPLAIN PARTITIONS
ist seit MySQL 5.1.5
verfügbar. Es ist nur praktisch, wenn Sie Abfragen
untersuchen, die sich auf partitionierte Tabellen beziehen.
Detaillierte Informationen finden Sie in
Abschnitt 17.3.4, „Abruf von Informationen über Partitionen“.
Dieser Abschnitt beschreibt die zweite Verwendungsmöglichkeit
von EXPLAIN
: die Anforderung von
Informationen zum Abfrageausführungsplan. Eine Beschreibung der
Anweisungen DESCRIBE
und SHOW
COLUMNS
finden Sie in Abschnitt 13.3.1, „DESCRIBE
(Informationen über Spalten abrufen)“, und
Abschnitt 13.5.4.3, „SHOW COLUMNS
“.
Mithilfe von EXPLAIN
können Sie ermitteln,
wo Sie Indizes für Tabellen konfigurieren sollten, um
SELECT
-Anweisungen zu beschleunigen, die
Datensätze mithilfe von Indizes finden. Sie können mit
EXPLAIN
auch überprüfen, ob der Optimierer
die Tabellen in optimaler Reihenfolge verknüpft. Um den
Optimierer zur Verwendung einer Verknüpfungsreihenfolge zu
zwingen, die der Reihenfolge entspricht, in der die Tabellen in
der SELECT
-Anweisung aufgeführt sind,
beginnen Sie die Anweisung mit SELECT
STRAIGHT_JOIN
statt mit SELECT
.
Wenn das Problem auftritt, dass Indizes nicht benutzt werden,
obwohl Sie annehmen, dass dies eigentlich der Fall sein sollte,
dann führen Sie ANALYZE TABLE
aus, um die
Tabellenstatistiken wie etwa die Kardinalität der Schlüssel,
die sich auf die durch den Optimierer vorgenommene Auswahl
auswirken kann, zu aktualisieren. Siehe auch
Abschnitt 13.5.2.1, „ANALYZE TABLE
“.
EXPLAIN
gibt je einen Datensatz für jede in
der SELECT
-Anweisung verwendete Tabelle
zurück. Die Tabellen sind in der Ausgabe in der Reihenfolge
aufgeführt, in der MySQL sie bei der Verarbeitung der Abfrage
lesen würde. MySQL löst alle Joins mithilfe einer Methode auf,
die Single-Sweep-Multi-Join heißt.
Hierbei liest MySQL einen Datensatz aus der ersten Tabelle und
sucht dann einen passenden Datensatz in der zweiten Tabelle, der
dritten Tabelle usw. Sind alle Tabellen verarbeitet, dann gibt
MySQL die gewählten Spalten aus und durchsucht die
Tabellenliste in umgekehrter Reihenfolge, bis eine Tabelle
gefunden wird, bei der mehr passende Datensätze vorhanden sind.
Der nächste Datensatz wird aus genau dieser Tabelle gelesen,
und dann wird der Prozess mit der nächsten Tabelle fortgesetzt.
Wenn das Schlüsselwort EXTENDED
verwendet
wird, erzeugt EXPLAIN
zusätzliche
Informationen, die durch Absetzen einer SHOW
WARNINGS
-Anweisung nach der
EXPLAIN
-Anweisung angezeigt werden können.
Diese Informationen geben Hinweise zum Optimierungsprozess,
z. B. wie der Optimierer Tabellen- und Spaltennamen in der
SELECT
-Anweisung qualifiziert oder wie die
SELECT
-Anweisung nach der Anwendung der
Umformulierungs- und Optimierungsregeln aussieht.
Hinweis: Sie können die
Schlüsselwörter EXTENDED
und
PARTITIONS
nicht gemeinsam in derselben
EXPLAIN
-Anweisung verwenden.
Jeder von EXPLAIN
ausgegebene Datensatz
enthält Angaben zu genau einer Tabelle. Dabei enthält jeder
Datensatz die folgenden Spalten:
id
Der SELECT
-Bezeichner. Dies ist die
Sequenznummer der SELECT
-Anweisung
innerhalb der Abfrage.
select_type
Der Typ der SELECT
-Anweisung. Dies kann
jeder der in der folgenden Tabelle aufgeführten Typen sein:
SIMPLE | einfache SELECT -Anweisung (ohne
UNION oder Unterabfragen). |
PRIMARY | äußerste SELECT -Anweisung. |
UNION | zweite oder spätere SELECT -Anweisung in einer
UNION . |
DEPENDENT UNION | zweite oder spätere SELECT -Anweisung in einer
UNION , abhängig von der
äußeren Abfrage. |
UNION RESULT | Ergebnis einer UNION . |
SUBQUERY | erste SELECT -Anweisung in einer Unterabfrage. |
DEPENDENT SUBQUERY | erste SELECT -Anweisung in einer Unterabfrage,
abhängig von der äußeren Abfrage. |
DERIVED | abgeleitete Tabellen-SELECT -Anweisung (Unterabfrage
in FROM -Klausel). |
DEPENDENT
bezeichnet normalerweise die
Verwendung einer korrelierten Unterabfrage. Siehe auch
Abschnitt 13.2.8.7, „Korrelierte Unterabfragen“.
table
Die Tabelle, die der Ausgabedatensatz referenziert.
type
Der Join-Typ. Die verschiedenen Join-Typen sind nachfolgend aufgelistet, sortiert vom besten bis zum schlechtesten:
Diese Tabelle hat nur einen Datensatz (Systemtabelle).
Dies ist ein Sonderfall des Join-Typs
const
.
Die Tabelle hat maximal einen passenden Datensatz, der
beim Start der Abfrage gelesen wird. Da nur ein
Datensatz vorhanden ist, können die Werte aus den
Spalten dieses Datensatzes vom Optimierer im Folgenden
als Konstanten behandelt werden.
const
-Tabellen sind sehr schnell, da
sie nur einmal gelesen werden.
const
wird verwendet, wenn Sie alle
Teile eines Primärschlüssels oder eines eindeutigen
Indexes mit Konstantenwerten vergleichen. In der
folgenden Abfrage kann
tbl_name
als
const
-Tabelle verwendet werden:
SELECT * FROMtbl_name
WHEREprimary_key
=1; SELECT * FROMtbl_name
WHEREprimary_key_part1
=1 ANDprimary_key_part2
=2;
eq_ref
Für jede Datensatzkombination aus den vorherigen
Tabellen wird genau ein Datensatz aus dieser Tabelle
gelesen. Anders als die Typen system
und const
ist dies der beste
Join-Typ. Er wird verwendet, wenn alle Teile eines
Indexes vom Join verwendet werden und der Index ein
Primärschlüssel oder ein eindeutiger Index ist.
eq_ref
kann für indizierte Spalten
benutzt werden, die mithilfe des Operators
=
verglichen werden. Der
Vergleichswert kann eine Konstante oder ein Ausdruck
sein, der Spalten aus Tabellen verwendet, die vor dieser
Tabelle gelesen wurden. In den folgenden Beispielen kann
MySQL einen eq_ref
-Join zur
Verarbeitung von ref_table
verwenden:
SELECT * FROMref_table
,other_table
WHEREref_table
.key_column
=other_table
.column
; SELECT * FROMref_table
,other_table
WHEREref_table
.key_column_part1
=other_table
.column
ANDref_table
.key_column_part2
=1;
ref
Alle Datensätze mit passenden Indexwerten werden aus
dieser Tabelle für jede Kombination von Datensätzen in
den vorherigen Tabellen gelesen. ref
wird benutzt, wenn der Join nur ein linkes Präfix des
Schlüssels verwendet oder der Schlüssel kein
Primärschlüssel und auch kein eindeutiger Index ist
(d. h., wenn der Join keinen einzelnen Datensatz
basierend auf dem Schlüsselwert auswählen kann). Wenn
der verwendete Schlüssel nur einigen wenigen
Datensätzen entspricht, ist dies ein guter Join-Typ.
ref
kann für indizierte Spalten
benutzt werden, die mithilfe der Operatoren
=
oder <=>
verglichen werden. In den folgenden Beispielen kann
MySQL einen ref
-Join zur Verarbeitung
von ref_table
verwenden:
SELECT * FROMref_table
WHEREkey_column
=expr
; SELECT * FROMref_table
,other_table
WHEREref_table
.key_column
=other_table
.column
; SELECT * FROMref_table
,other_table
WHEREref_table
.key_column_part1
=other_table
.column
ANDref_table
.key_column_part2
=1;
ref_or_null
Dieser Join-Typ ähnelt ref
weitgehend, allerdings führt MySQL hierbei eine
zusätzliche Suche nach Datensätzen durch, die
NULL
-Werte enthalten. Diese
Join-Typ-Optimierung wird meistens bei der Auflösung
von Unterabfragen verwendet. In den folgenden Beispielen
kann MySQL einen ref_or_null
-Join zur
Verarbeitung von ref_table
verwenden:
SELECT * FROMref_table
WHEREkey_column
=expr
ORkey_column
IS NULL;
Siehe auch Abschnitt 7.2.7, „IS NULL
-Optimierung“.
index_merge
Dieser Join-Typ gibt an, dass die
Indexverschmelzungsoptimierung verwendet wird. In diesem
Fall enthält die Spalte key
im
ausgegebenen Datensatz eine Liste der verwendeten
Indizes, und key_len
enthält eine
Liste der längsten Schlüsselteile für die verwendeten
Indizes. Weitere Informationen finden Sie unter
Abschnitt 7.2.6, „Optimierung durch Indexverschmelzung“.
unique_subquery
Dieser Typ ersetzt ref
in einigen
IN
-Unterabfragen der folgenden Form:
value
IN (SELECTprimary_key
FROMsingle_table
WHEREsome_expr
)
unique_subquery
ist eine
Nachschlagefunktion für Indizes, die zur
Effizienzsteigerung die Unterabfrage vollständig
ersetzt.
index_subquery
Dieser Join-Typ ähnelt
unique_subquery
. Er ersetzt
IN
-Unterabfragen, funktioniert aber
bei nichteindeutigen Indizes in Unterabfragen folgender
Form:
value
IN (SELECTkey_column
FROMsingle_table
WHEREsome_expr
)
range
Es werden nur Datensätze abgerufen, die in einem
gegebenen Bereich liegen. Sie werden anhand eines
Indexes ausgewählt. Die Spalte key
im Ausgabedatensatz zeigt an, welcher Index verwendet
wird. key_len
enthält den längsten
verwendeten Schlüsselteil. Die Spalte
ref
ist für diesen Typ
NULL
.
range
kann verwendet werden, wenn
eine Schlüsselspalte unter Verwendung eines der
Operatoren =
,
<>
, >
,
>=
, <
,
<=
, IS NULL
,
<=>
, BETWEEN
oder IN
mit einer Konstante
verglichen wird:
SELECT * FROMtbl_name
WHEREkey_column
= 10; SELECT * FROMtbl_name
WHEREkey_column
BETWEEN 10 and 20; SELECT * FROMtbl_name
WHEREkey_column
IN (10,20,30); SELECT * FROMtbl_name
WHEREkey_part1
= 10 ANDkey_part2
IN (10,20,30);
index
Dieser Join-Typ ist mit ALL
bis auf
die Tatsache identisch, dass nur der Indexbaum gescannt
wird. Insofern ist er in der Regel schneller als
ALL
, weil die Indexdatei gewöhnlich
kleiner ist als die Datendatei.
MySQL kann diesen Join-Typ verwenden, wenn die Abfrage nur Spalten benutzt, die Teil eines einzelnen Indexes sind.
ALL
Ein vollständiger Tabellenscan wird für jede
Kombination von Datensätzen aus den vorherigen Tabellen
durchgeführt. Dies ist normalerweise nicht von Vorteil,
wenn die Tabelle die erste nicht als
const
gekennzeichnete Tabelle ist,
und in allen anderen Fällen sogar ganz
schlimm. Sie können ALL
normalerweise vermeiden, indem Sie Indizes hinzufügen,
die das Abrufen von Datensätzen aus der Tabelle
basierend auf Konstanten- oder Spaltenwerten aus
früheren Tabellen erlauben.
possible_keys
Die Spalte possible_keys
gibt an, unter
welchen Indizes MySQL auswählen kann, um Datensätze in
dieser Tabelle zu suchen. Beachten Sie, dass diese Spalte
vollständig unabhängig von der Reihenfolge der Tabellen
ist, wie sie in der Ausgabe von EXPLAIN
angezeigt wird. Das bedeutet, dass einige der Schlüssel in
possible_keys
mit der erzeugten
Tabellenreihenfolge unter Umständen praktisch nicht
verwendbar sind.
Wenn diese Spalte NULL
ist, gibt es keine
relevanten Indizes. In diesem Fall können Sie die
Leistungsfähigkeit Ihrer Abfrage möglicherweise
verbessern, indem Sie die WHERE
-Klausel
daraufhin untersuchen, ob sie eine oder mehrere Spalten
referenziert, die für die Indexerstellung geeignet wären.
Sollte dies der Fall sein, so erstellen Sie einen passenden
Index und überprüfen die Abfrage dann mit
EXPLAIN
erneut. Siehe auch
Abschnitt 13.1.2, „ALTER TABLE
“.
Um anzuzeigen, welche Indizes eine Tabelle hat, verwenden
Sie SHOW INDEX FROM
.
tbl_name
key
Die Spalte key
gibt den Schlüssel(index)
an, für dessen Verwendung sich MySQL tatsächlich
entschieden hat. Der Schlüssel ist NULL
,
wenn kein Index ausgewählt wurde. Um das Verwenden oder
Ignorieren eines Indexes, der in der Spalte
possible_keys
aufgeführt ist, durch
MySQL zu erzwingen oder zu ignorieren, verwenden Sie
FORCE INDEX
oder USE
INDEX
bzw. IGNORE INDEX
in
Ihrer Abfrage. Siehe auch Abschnitt 13.2.7, „SELECT
“.
Bei MyISAM
- und
BDB
-Tabellen erleichtert die Ausführung
von ANALYZE TABLE
dem Optimierer die
Auswahl geeigneter Indizes. Bei
MyISAM
-Tabellen tut myisamchk
--analyze dasselbe. Siehe auch
Abschnitt 13.5.2.1, „ANALYZE TABLE
“, und
Abschnitt 5.10.4, „Benutzung von myisamchk
für Tabellenwartung und Absturzreparatur“.
key_len
Die Spalte key_len
gibt die Länge des
Schlüssels an, für dessen Verwendung sich MySQL
entschieden hat. Die Länge ist NULL
,
wenn in der Spalte key
NULL
steht. Beachten Sie, dass der Wert
von key_len
Ihnen die Feststellung
gestattet, wie viele Teile eines mehrteiligen Schlüssels
MySQL tatsächlich verwendet.
ref
Die Spalte ref
zeigt an, welche Spalten
oder Konstanten mit dem in der Spalte key
genannten Index verglichen werden, um Datensätze aus der
Tabelle auszuwählen.
rows
Die Spalte rows
gibt die Anzahl der
Datensätze an, die MySQL glaubt untersuchen zu müssen, um
die Abfrage ausführen zu können.
Extra
Diese Spalte enthält zusätzliche Angaben dazu, wie MySQL die Abfrage auflöst. Es folgt eine Erläuterung der Werte, die in dieser Spalte erscheinen können:
Distinct
MySQL sucht nach unterschiedlichen Werten, d. h., die Suche nach weiteren Datensätzen zur aktuellen Datensatzkombination wird beendet, sobald der erste Datensatz gefunden wurde.
Not exists
MySQL konnte eine LEFT
JOIN
-Optimierung an der Abfrage vornehmen und
untersucht für die vorhergehende Datensatzkombination
keine weiteren Datensätze in dieser Tabelle, sobald ein
Datensatz gefunden wurde, der den LEFT
JOIN
-Kriterien entspricht. Hier ein Beispiel
für einen Abfragetyp, der auf diese Weise optimiert
werden kann:
SELECT * FROM t1 LEFT JOIN t2 ON t1.id=t2.id WHERE t2.id IS NULL;
Nehmen wir an, t2.id
sei als
NOT NULL
definiert. In diesem Fall
scannt MySQL t1
und sucht die
Datensätze in t2
unter Verwendung
der Werte aus t1.id
heraus. Findet
MySQL einen passenden Datensatz in
t2
, dann weiß es, dass
t2.id
niemals NULL
sein kann, und scannt die weiteren Datensätze in
t2
, die denselben
id
-Wert aufweisen, nicht mehr. Für
jeden Datensatz in t1
muss MySQL also
nur einen einzigen Suchvorgang in t2
durchführen – unabhängig davon, wie viele
entsprechende Datensätze in t2
tatsächlich vorhanden sind.
range checked for each record (index map:
N
)
MySQL hat keinen geeigneten Index gefunden, aber
festgestellt, dass einige der Indizes verwendet werden
könnten, nachdem Spaltenwerte aus vorhergehenden
Tabellen bekannt geworden sind. Für jede
Datensatzkombination in den vorherigen Tabellen
überprüft MySQL, ob es möglich ist, zum Abrufen von
Datensätzen eine der Zugriffsmethoden
range
oder
index_merge
zu verwenden. Dies ist
nicht sehr schnell, aber immer noch schneller als die
Durchführung eines Joins ohne Index. Die
Anwendbarkeitskriterien entsprechen den in
Abschnitt 7.2.5, „Bereichsoptimierung“, und
Abschnitt 7.2.6, „Optimierung durch Indexverschmelzung“,
beschriebenen, nur sind hier alle Spaltenwerte für die
vorhergehende Tabelle bekannt und werden als Konstanten
betrachtet.
Using filesort
MySQL muss einen zusätzlichen Durchlauf vornehmen, um
zu ermitteln, wie die Datensätze in sortierter
Reihenfolge abgerufen werden können. Diese Sortierung
erfolgt, indem alle Datensätze entsprechend dem
Join-Typ überprüft und Sortierschlüssel sowie der
Zeiger auf den Datensatz für alle Datensätze
gespeichert werden, die der
WHERE
-Klausel entsprechen. Die
Schlüssel werden dann sortiert und die Datensätze
entsprechend in sortierter Reihenfolge abgerufen. Siehe
auch
Abschnitt 7.2.12, „ORDER BY
-Optimierung“.
Using index
Die Spaltendaten werden ausschließlich unter Verwendung von Angaben im Indexbaum aus der Tabelle abgerufen – es erfolgt kein zusätzlicher Suchvorgang, um jeweils den eigentlichen Datensatz auszulesen. Diese Strategie kann verwendet werden, wenn die Abfrage nur Spalten benutzt, die Teil eines einzelnen Indexes sind.
Using temporary
Um die Abfrage aufzulösen, muss MySQL eine
Temporärtabelle zur Aufnahme des Ergebnisses erstellen.
Dies geschieht typischerweise, wenn die Abfrage
GROUP BY
- und ORDER
BY
-Klauseln enthält, die Spalten
unterschiedlich auflisten.
Using where
Mit einer WHERE
-Klausel wird
festgelegt, welche Datensätze mit der nächsten Tabelle
verglichen oder an den Client gesendet werden. Sofern
Sie nicht gezielt alle Datensätze aus der Tabelle
abrufen oder untersuchen wollen, haben Sie in der
Abfrage einen Fehler gemacht, wenn der Wert
Extra
nicht Using
where
ist und ALL
oder
index
als Join-Typ für die Tabelle
angegeben ist.
Wollen Sie Ihre Abfragen so schnell wie möglich machen,
dann sollten Sie nach den
Extra
-Werten Using
filesort
und Using
temporary
suchen.
Using sort_union(…)
,
Using union(…)
, Using
intersect(…)
Diese Werte geben an, wie Indexscans für den Join-Typ
index_merge
zusammengefasst werden.
Weitere Informationen finden Sie in
Abschnitt 7.2.6, „Optimierung durch Indexverschmelzung“.
Using index for group-by
Ähnlich wie die Tabellenzugriffsmethode Using
index
gibt Using index for
group-by
an, dass MySQL einen Index gefunden
hat, der zum Abrufen aller Datensätze einer
GROUP BY
- oder
DISTINCT
-Abfrage ohne zusätzlichen
Festplattenzugriff auf die eigentliche Tabelle verwendet
werden kann. Außerdem wird der Index auf die
effizienteste Art und Weise verwendet, sodass für jede
Gruppe nur ein paar wenige Indexeinträge gelesen
werden. Detaillierte Informationen finden Sie in
Abschnitt 7.2.13, „GROUP BY
-Optimierung“.
Using where with pushed condition
Dieses Element ist ausschließlich
für NDB Cluster
-Tabellen verfügbar.
Es bedeutet, dass MySQL Cluster einen
Bedingungs-Pushdown verwendet, um
die Effizienz eines direkten Vergleichs
(=
) zwischen einer nichtindizierten
Spalte und einer Konstanten zu steigern. In solchen
Fällen wird die Bedingung in den Datenknoten des
Clusters „eingekellert“, wo sie dann in
allen Partitionen gleichzeitig ausgewertet wird.
Hierdurch wird der Versand unpassender Datensätze über
das Netzwerk vermieden, und die entsprechenden Abfragen
werden um den Faktor 5 bis 10 im Vergleich zu Fällen
beschleunigt, in denen ein Bedingungs-Pushdown hätte
verwendet werden können, aber nicht verwendet wurde.
Angenommen, eine Cluster-Tabelle sei wie folgt definiert:
CREATE TABLE t1 ( a INT, b INT, KEY(a) ) ENGINE=NDBCLUSTER;
In diesem Fall kann ein Bedingungs-Pushdown bei einer Abfrage wie der folgenden verwendet werden:
SELECT a,b FROM t1 WHERE b = 10;
Die Ausgabe von EXPLAIN SELECT
sieht
dann wie folgt aus:
mysql> EXPLAIN SELECT a,b FROM t1 WHERE b = 10\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t1
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 10
Extra: Using where with pushed condition
Ein Bedingungs-Pushdown kann nicht mit einer der beiden folgenden Abfragen verwendet werden:
SELECT a,b FROM t1 WHERE a = 10; SELECT a,b FROM t1 WHERE b + 1 = 10;
Bezüglich der ersten dieser zwei Abfragen ist der
Bedingungs-Pushdown nicht anwendbar, weil in der Spalte
a
ein Index vorhanden ist. Im Falle
der zweiten Abfrage kann ein Bedingungs-Pushdown nicht
verwendet werden, weil der Vergleich unter
Berücksichtigung der nichtindizierten Spalte
b
ein indirekter Vergleich ist. (Er
wäre allerdings gültig, wenn Sie in der
WHERE
-Klausel b + 1 =
10
auf b = 9
reduzieren
würden.)
Allerdings kann ein Bedingungs-Pushdown auch verwendet
werden, wenn eine indizierte Spalte unter Verwendung
eines der Operatoren >
oder
<
mit einer Konstanten verglichen
wird:
mysql> EXPLAIN SELECT a,b FROM t1 WHERE a<2\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t1
type: range
possible_keys: a
key: a
key_len: 5
ref: NULL
rows: 2
Extra: Using where with pushed condition
Merken Sie sich in Bezug auf einen Bedingungs-Pushdown Folgendes:
Der Bedingungs-Pushdown ist nur für MySQL Cluster relevant und tritt nicht auf, wenn Sie Abfragen unter Verwendung anderer Speicher-Engines an Tabellen absetzen.
Bedingungs-Pushdowns werden nicht standardmäßig
eingesetzt. Um sie zu aktivieren, können Sie
mysqld mit der Option
--engine-condition-pushdown
oder
die folgende Anweisung ausführen:
SET engine_condition_pushdown=On;
Sie erhalten einen geeigneten Anhaltspunkt zu der Frage, wie gut
ein Join ist, indem Sie das Produkt der Werte in der Spalte
rows
der Ausgabe von
EXPLAIN
erstellen. Hieraus ergibt sich grob,
wie viele Datensätze MySQL untersuchen muss, um die Abfrage
auszuführen. Wenn Sie die Abfragen mit der Systemvariablen
max_join_size
beschränken, wird dieses
Datensatzprodukt auch benutzt, um zu bestimmen, welche
SELECT
-Anweisungen für mehrere Tabellen
ausgeführt und welche abgebrochen werden. Siehe auch
Abschnitt 7.5.2, „Serverparameter feineinstellen“.
Das folgende Beispiel zeigt, wie ein Join mehrerer Tabellen auf
der Basis der von EXPLAIN
übermittelten
Angaben progressiv optimiert werden kann.
Angenommen, Sie hätten die folgende
SELECT
-Anweisung, die Sie mit
EXPLAIN
untersuchen wollen:
EXPLAIN SELECT tt.TicketNumber, tt.TimeIn, tt.ProjectReference, tt.EstimatedShipDate, tt.ActualShipDate, tt.ClientID, tt.ServiceCodes, tt.RepetitiveID, tt.CurrentProcess, tt.CurrentDPPerson, tt.RecordVolume, tt.DPPrinted, et.COUNTRY, et_1.COUNTRY, do.CUSTNAME FROM tt, et, et AS et_1, do WHERE tt.SubmitTime IS NULL AND tt.ActualPC = et.EMPLOYID AND tt.AssignedPC = et_1.EMPLOYID AND tt.ClientID = do.CUSTNMBR;
Für dieses Beispiel gelten die folgenden Annahmen:
Die zu vergleichenden Spalten wurden wie folgt deklariert:
Tabelle | Spalte | Datentyp |
tt | ActualPC | CHAR(10) |
tt | AssignedPC | CHAR(10) |
tt | ClientID | CHAR(10) |
et | EMPLOYID | CHAR(15) |
do | CUSTNMBR | CHAR(15) |
Die Tabellen haben die nachfolgenden Indizes:
Tabelle | Index |
tt | ActualPC |
tt | AssignedPC |
tt | ClientID |
et | EMPLOYID (Primärschlüssel) |
do | CUSTNMBR (Primärschlüssel) |
Die tt.ActualPC
-Werte sind nicht
gleichmäßig verteilt.
Anfangs – also vor der Durchführung von Optimierungen –
erzeugt die EXPLAIN
-Anweisung die folgenden
Angaben:
table type possible_keys key key_len ref rows Extra et ALL PRIMARY NULL NULL NULL 74 do ALL PRIMARY NULL NULL NULL 2135 et_1 ALL PRIMARY NULL NULL NULL 74 tt ALL AssignedPC, NULL NULL NULL 3872 ClientID, ActualPC range checked for each record (key map: 35)
Da type
für jede Tabelle
ALL
ist, gibt diese Ausgabe an, dass MySQL
ein kartesisches Produkt aller Tabellen erzeugt, also jede
mögliche Kombination von Datensätzen. Dies dauert recht lang,
weil das Produkt der Anzahl der Datensätze in jeder Tabelle
untersucht werden muss. Im vorliegenden Fall beträgt dieses
Produkt 74 × 2135 × 74 × 3872 = 45.268.558.720
Datensätze. Wenn die Tabellen noch größer wären, kann man
sich nur vage vorstellen, wie lange dies dauern würde.
Ein Problem besteht hier darin, dass MySQL Indizes für Spalten
effizienter verwenden kann, wenn sie mit demselben Typ und
derselben Größe deklariert wurden. In diesem Kontext werden
VARCHAR
und CHAR
als
identisch betrachtet, wenn sie mit derselben Größe deklariert
werden. tt.ActualPC
wird aber als
CHAR(10)
und et.EMPLOYID
als CHAR(15)
deklariert – die Längen
stimmen also nicht überein.
Um diese Fehlanpassung zwischen den Spaltenlängen aufzuheben,
verlängern Sie ActualPC
mit ALTER
TABLE
von 10 auf 15 Zeichen Länge:
mysql> ALTER TABLE tt MODIFY ActualPC VARCHAR(15);
Nun sind tt.ActualPC
und
et.EMPLOYID
beide
VARCHAR(15)
. Die erneute Ausführung der
EXPLAIN
-Anweisung erzeugt folgende Ausgabe:
table type possible_keys key key_len ref rows Extra tt ALL AssignedPC, NULL NULL NULL 3872 Using ClientID, where ActualPC do ALL PRIMARY NULL NULL NULL 2135 range checked for each record (key map: 1) et_1 ALL PRIMARY NULL NULL NULL 74 range checked for each record (key map: 1) et eq_ref PRIMARY PRIMARY 15 tt.ActualPC 1
Dies ist noch nicht perfekt, aber es ist schon wesentlich
besser: Das Produkt der rows
-Werte ist
bereits um den Faktor 74 geringer – die Ausführung dieser
Version dauert nur ein paar Sekunden.
Eine weitere Änderung kann vorgenommen werden, um die
Nichtübereinstimmung der Spaltenlängen für die Vergleiche
tt.AssignedPC = et_1.EMPLOYID
und
tt.ClientID = do.CUSTNMBR
zu beseitigen:
mysql>ALTER TABLE tt MODIFY AssignedPC VARCHAR(15),
->MODIFY ClientID VARCHAR(15);
Nach dieser Änderung sieht die Ausgabe von
EXPLAIN
so aus:
table type possible_keys key key_len ref rows Extra et ALL PRIMARY NULL NULL NULL 74 tt ref AssignedPC, ActualPC 15 et.EMPLOYID 52 Using ClientID, where ActualPC et_1 eq_ref PRIMARY PRIMARY 15 tt.AssignedPC 1 do eq_ref PRIMARY PRIMARY 15 tt.ClientID 1
An dieser Stelle ist die Abfrage schon fast perfekt optimiert.
Als letztes Problem verbleibt die Tatsache, dass MySQL
standardmäßig voraussetzt, dass Werte in der Spalte
tt.ActualPC
gleichmäßig verteilt sind; dies
ist aber bei der Tabelle tt
nicht der Fall.
Glücklicherweise ist es einfach, MySQL zur Analyse der
Schlüsselverteilung zu bewegen:
mysql> ANALYZE TABLE tt;
Mit den zusätzlichen Indexangaben ist der Join perfekt, und
EXPLAIN
erzeugt folgendes Ergebnis:
table type possible_keys key key_len ref rows Extra tt ALL AssignedPC NULL NULL NULL 3872 Using ClientID, where ActualPC et eq_ref PRIMARY PRIMARY 15 tt.ActualPC 1 et_1 eq_ref PRIMARY PRIMARY 15 tt.AssignedPC 1 do eq_ref PRIMARY PRIMARY 15 tt.ClientID 1
Beachten Sie, dass die Spalte rows
in der
Ausgabe von EXPLAIN
eine begründete Annahme
des MySQL-Join-Optimierers ist. Sie sollten überprüfen, ob die
Zahlen annähernd realistisch sind, indem Sie das
rows
-Produkt mit der tatsächlichen Anzahl
der von der Abfrage zurückgegebenen Datensätze vergleichen.
Unterscheiden sich diese Werte erheblich, dann erhalten Sie
unter Umständen eine bessere Leistung, wenn Sie
STRAIGHT_JOIN
in Ihrer
SELECT
-Abfrage verwenden und versuchen, die
Tabellen in der FROM
-Klausel in einer anderen
Reihenfolge aufzulisten.
In den meisten Fällen können Sie die Leistungsfähigkeit von
Abfragen einschätzen, indem Sie die Anzahl der Suchvorgänge
auf der Festplatte ermitteln. Bei kleinen Tabellen finden Sie
gewöhnlich pro derartigen Suchvorgang einen Datensatz (weil der
Index im Zweifelsfall im Cache liegt). Bei größeren Tabellen
können Sie bei der Verwendung von B-Tree-Indizes
schätzungsweise die folgende Anzahl von Suchvorgängen
annehmen, um einen Datensatz zu finden:
log(
.
row_count
) /
log(index_block_length
/ 3 × 2
/ (index_length
+
data_pointer_length
)) + 1
In MySQL ist ein Indexblock gewöhnlich 1024 Byte groß, der
Datenzeiger umfasst weitere vier Byte. Bei einer Tabelle mit
500.000 Datensätzen und einer Indexlänge von drei Byte (der
Größe von MEDIUMINT
) gibt die Formel
log(500.000/log(1024/3*2/(3+4))+1
=
4
Suchvorgänge aus.
Dieser Index würde eine Speicherkapazität von 500.000 × 7 × 3/2 = 5,2 Mbyte benötigen (ein typisches Indexpuffer-Füllungsverhältnis von 2 : 3 vorausgesetzt), d. h., Sie hätten wahrscheinlich einen Großteil des Indexes im Speicher und benötigen nur ein oder zwei Aufrufe zum Datenlesen, um den Datensatz zu finden.
Bei Schreiboperationen hingegen benötigen Sie vier Suchanforderungen, um zu ermitteln, wo ein neuer Indexwert abgelegt werden muss, und normalerweise zwei Suchvorgänge, um den Index zu aktualisieren und den Datensatz zu schreiben.
Beachten Sie, dass die vorangegangene Beschreibung nicht
bedeutet, dass Ihre Anwendungsleistung sich nach und nach um den
Logarithmus N
verringert. Solange
alles vom Betriebssystem oder vom MySQL Server
zwischengespeichert wird, verringert sich die Geschwindigkeit
nur marginal, wenn die Tabellen größer werden. Sobald die
Daten zu umfangreich geworden sind, um zwischengespeichert zu
werden, geht alles viel langsamer, bis Ihre Anwendungen nur noch
mit Suchvorgängen auf der Festplatte beschäftigt sind (deren
Anzahl sich um log N
erhöht). Um
dies zu vermeiden, müssen Sie die Größe des Schlüssel-Caches
erhöhen, wenn der Umfang Ihrer Daten zunimmt. Bei
MyISAM
-Tabellen wird die Größe des
Schlüssel-Caches von der Systemvariablen
key_buffer_size
gesteuert. Siehe auch
Abschnitt 7.5.2, „Serverparameter feineinstellen“.
Wenn Sie eine langsame SELECT …
WHERE
-Anweisung beschleunigen wollen, besteht der
erste Schritt in aller Regel darin, zu überprüfen, ob Sie
einen Index hinzufügen können. Alle Referenzierungen zwischen
verschiedenen Tabellen sollten normalerweise über Indizes
erfolgen. Sie können mit der
EXPLAIN
-Anweisung ermitteln, welche Indizes
für eine SELECT
-Anweisung verwendet werden.
Siehe auch Abschnitt 7.2.1, „EXPLAIN
-Syntax (Informationen über ein
SELECT
erhalten)“, und
Abschnitt 7.4.5, „Wie MySQL Indizes benutzt“.
Hier ein paar allgemeine Tipps zur Beschleunigung von Abfragen
für MyISAM
-Tabellen:
Um MySQL bei der Optimierung von Abfragen zu unterstützen,
verwenden Sie ANALYZE TABLE
oder führen
myisamchk --analyze für eine Tabelle
aus, nachdem Sie die Daten dort eingeladen haben. Hierdurch
wird ein Wert für jeden Indexteil geändert, der die
durchschnittliche Anzahl von Datensätzen angibt, die
denselben Wert haben. (Bei eindeutigen Indizes ist dies
immer 1.) MySQL entscheidet anhand dessen, welcher Index
ausgewählt wird, wenn Sie zwei Tabellen basierend auf einem
nichtkonstanten Ausdruck verknüpfen. Sie können das
Ergebnis der Tabellenanalyse mit SHOW INDEX FROM
und
nachfolgender Überprüfung des Werts
tbl_name
Cardinality
verifizieren.
myisamchk --description --verbose zeigt
Angaben zur Indexverteilung.
Um einen Index und die Daten gemäß diesem Index zu sortieren, verwenden Sie myisamchk --sort-index --sort-records=1 (in diesem Beispiel erfolgt die Sortierung nach Index 1). Dies ist eine gute Möglichkeit, Abfragen zu beschleunigen, wenn Sie einen eindeutigen Index haben, anhand dessen Sie alle Datensätze in der von Index vorgegebenen Reihenfolge auslesen wollen. Beachten Sie, dass, wenn Sie beim ersten Mal eine große Tabelle auf diese Weise sortieren, dies sehr lang dauern kann.
Dieser Abschnitt behandelt Optimierungen, die für die
Verarbeitung von WHERE
-Klauseln durchgeführt
werden können. Die Beispiele verwenden
SELECT
-Anweisungen, dieselben Optimierungen
gelten aber auch für WHERE
-Klauseln in
DELETE
- und
UPDATE
-Anweisungen.
Wir arbeiten fortlaufend am MySQL-Optimierer, weswegen dieser Abschnitt nicht vollständig ist. MySQL führt eine Vielzahl von Optimierungen durch, die nicht alle an dieser Stelle dokumentiert sind.
Es folgen einige von MySQL durchgeführte Optimierungen:
Entfernung unnötiger Klammern:
((a AND b) AND c OR (((a AND b) AND (c AND d)))) -> (a AND b AND c) OR (a AND b AND c AND d)
Umstellen von Konstanten:
(a<b AND b=c) AND a=5 -> b>5 AND b=c AND a=5
Entfernung von Konstantenbedingungen (erforderlich zum Umstellen von Konstanten):
(B>=5 AND B=5) OR (B=6 AND 5=5) OR (B=7 AND 5=6) -> B=5 OR B=6
Konstantenausdrücke, die von Indizes verwendet werden, werden nur einmal ausgewertet.
COUNT(*)
für eine einzelne Tabelle ohne
WHERE
wird direkt aus den Tabellendaten
für MyISAM
- und
MEMORY
-Tabellen abgerufen. Dies wird auch
für jeden NOT NULL
-Ausdruck gemacht, der
nur für eine einzige Tabelle verwendet wird.
Früherkennung ungültiger Konstantenausdrücke. MySQL
erkennt sehr schnell, wenn eine
SELECT
-Anweisung nicht möglich ist, und
gibt keine Datensätze zurück.
HAVING
wird mit WHERE
verschmolzen, wenn Sie GROUP BY
nicht
verwenden oder Funktionen (wie COUNT()
,
MIN()
usw.) zusammenfassen.
Für jede Tabelle in einem Join wird eine einfachere
WHERE
-Klausel erstellt, um eine schnelle
WHERE
-Auswertung für die Tabelle zu
erhalten und außerdem Datensätze so früh wie möglich zu
überspringen.
Bevor andere Tabellen in der Abfrage gelesen werden, werden zunächst alle Konstantentabellen ausgelesen. Zu den Konstantentabellen gehören die folgenden:
Leere Tabellen oder solche mit nur einem Datensatz.
Tabellen, die mit einer WHERE
-Klausel
für einen Primärschlüssel oder einen eindeutigen
Index verwendet werden, wobei alle Indexteile mit
Konstantenausdrücken verglichen werden und als
NOT NULL
definiert sind.
Alle folgenden Tabellen werden als Konstantentabellen verwendet:
SELECT * FROM t WHEREprimary_key
=1; SELECT * FROM t1,t2 WHERE t1.primary_key
=1 AND t2.primary_key
=t1.id;
Die beste Join-Kombination zur Verknüpfung der Tabellen
wird durch Ausprobieren aller Möglichkeiten ermittelt. Wenn
alle Spalten in den ORDER BY
- und
GROUP BY
-Klauseln aus derselben Tabelle
stammen, dann wird diese Tabelle beim Verknüpfen bevorzugt.
Wenn eine ORDER BY
- und eine davon
unterschiedliche GROUP BY
-Klausel
vorhanden sind, oder wenn ORDER BY
oder
GROUP BY
Spalten aus anderen als der
ersten Tabelle in der Join-Warteschlange enthalten, dann
wird eine Temporärtabelle erstellt.
Wenn Sie die Option SQL_SMALL_RESULT
verwenden, dann benutzt MySQL eine speicherresidente
Temporärtabelle.
Alle Tabellenindizes werden abgefragt, und der beste Index wird verwendet, sofern der Optimierer nicht der Ansicht ist, dass die Verwendung eines Tabellenscans effizienter ist. Früher wurde ein Scan basierend darauf eingesetzt, ob der beste Index sich über einen Anteil von mehr als 30 Prozent der Tabelle erstreckte; mittlerweile wird die Frage, ob ein Index oder ein Scan verwendet werden soll, nicht mehr auf der Basis eines festen Prozentwerts entschieden. Der Optimierer ist mittlerweile komplexer, und seine Schätzungen fußen auf weiteren Faktoren wie Tabellengröße, Anzahl der Datensätze und I/O-Blockgröße.
In manchen Fällen kann MySQL Datensätze aus dem Index auslesen, ohne überhaupt die Datendatei abfragen zu müssen. Wenn alle aus dem Index verwendeten Spalten numerisch sind, wird zur Auflösung der Abfrage nur der Indexbaum verwendet.
Bevor ein Datensatz ausgegeben wird, werden alle
Datensätze, die nicht der HAVING
-Klausel
entsprechen, übersprungen.
Hier einige Beispiele für Abfragen, die sehr schnell sind:
SELECT COUNT(*) FROMtbl_name
; SELECT MIN(key_part1
),MAX(key_part1
) FROMtbl_name
; SELECT MAX(key_part2
) FROMtbl_name
WHEREkey_part1
=constant
; SELECT ... FROMtbl_name
ORDER BYkey_part1
,key_part2
,... LIMIT 10; SELECT ... FROMtbl_name
ORDER BYkey_part1
DESC,key_part2
DESC, ... LIMIT 10;
MySQL löst die folgenden Abfragen nur mithilfe des Indexbaums auf und setzt dabei voraus, dass die indizierten Spalten numerisch sind:
SELECTkey_part1
,key_part2
FROMtbl_name
WHEREkey_part1
=val
; SELECT COUNT(*) FROMtbl_name
WHEREkey_part1
=val1
ANDkey_part2
=val2
; SELECTkey_part2
FROMtbl_name
GROUP BYkey_part1
;
Die folgenden Abfragen verwendet die Indizierung zur Abfrage von Datensätzen in sortierter Reihenfolge ohne separaten Sortierdurchlauf:
SELECT ... FROMtbl_name
ORDER BYkey_part1
,key_part2
,... ; SELECT ... FROMtbl_name
ORDER BYkey_part1
DESC,key_part2
DESC, ... ;
Die Zugriffsmethode range
ruft mithilfe eines
einzelnen Indexes eine Teilmenge der Datensätze ab, die in der
Tabelle innerhalb eines oder mehrerer Indexwertintervalle
liegen. Sie kann für einen ein- oder mehrteiligen Index
verwendet werden. Die folgenden Abschnitte erläutern
detailliert, wie Intervalle aus der
WHERE
-Klausel extrahiert werden.
Bei einem einteiligen Index lassen sich die
Indexwertintervalle bequem durch entsprechende Bedingungen in
der WHERE
-Klausel darstellen. Deswegen
sprechen wir in diesem Fall von
Bereichsbedingungen statt von
„Intervallen“.
Die Definition einer Bereichsbedingung für einen einteiligen Index sieht wie folgt aus:
Bei BTREE
- und
HASH
-Indizes ist der Vergleich eines
Schlüsselteils mit einem Konstantenwert eine
Bereichsbedingung, wenn die Operatoren
=
, <=>
,
IN
, IS NULL
oder
IS NOT NULL
verwendet werden.
Bei BTREE
-Indizes ist der Vergleich
eines Schlüsselteils mit einem Konstantenwert eine
Bereichsbedingung, wenn die Operatoren
>
, <
,
>=
, <=
,
BETWEEN
, !=
oder
<>
verwendet werden, oder aber
bei LIKE
'
(wobei
pattern
''
nicht mit einem Jokerzeichen beginnt).
pattern
'
Bei allen Indextypen bilden mehrere Bereichsbedingungen,
die mit OR
oder AND
kombiniert werden, eine Bereichsbedingung.
In den obigen Erläuterungen bezeichnet „Konstantenwert“ eines der folgenden Elemente:
eine Konstante aus dem Abfrage-String
eine Spalte aus einer const
- oder
system
-Tabelle aus demselben Join
das Ergebnis einer unkorrelierten Unterabfrage
jeden Ausdruck, der vollständig aus Unterausdrücken der vorangegangenen Typen zusammengesetzt ist
Es folgen ein paar Beispiele für Abfragen mit
Bereichsbedingungen in der WHERE
-Klausel:
SELECT * FROM t1 WHEREkey_col
> 1 ANDkey_col
< 10; SELECT * FROM t1 WHEREkey_col
= 1 ORkey_col
IN (15,18,20); SELECT * FROM t1 WHEREkey_col
LIKE 'ab%' ORkey_col
BETWEEN 'bar' AND 'foo';
Beachten Sie, dass einige nichtkonstante Werte während der Weitergabephase für Konstanten ihrerseits in Konstanten umgewandelt werden könnten.
MySQL versucht, die Bereichsbedingungen für alle möglichen
Indizes aus der WHERE
-Klausel zu
extrahieren. Während des Extraktionsvorgangs werden
Bedingungen, die nicht zur Bildung der Bereichsbedingung
verwendet werden können, gelöscht; Bedingungen, die
überschneidende Bereiche erzeugen, werden kombiniert;
schließlich werden Bedingungen, die leere Bereiche erzeugen,
entfernt.
Betrachten Sie die folgende Anweisung (hierbei ist
key1
eine indizierte Spalte, während
nonkey
nicht indiziert ist):
SELECT * FROM t1 WHERE (key1 < 'abc' AND (key1 LIKE 'abcde%' OR key1 LIKE '%b')) OR (key1 < 'bar' AND nonkey = 4) OR (key1 < 'uux' AND key1 > 'z');
Der Extraktionsprozess für den Schlüssel
key1
sieht wie folgt aus:
Am Anfang steht die ursprüngliche
WHERE
-Klausel:
(key1 < 'abc' AND (key1 LIKE 'abcde%' OR key1 LIKE '%b')) OR (key1 < 'bar' AND nonkey = 4) OR (key1 < 'uux' AND key1 > 'z')
Nun werden nonkey = 4
und key1
LIKE '%b'
entfernt, weil sie für einen
Bereichsscan nicht verwendet werden können. Die korrekte
Vorgehensweise zur Entfernung besteht darin, sie durch
TRUE
zu ersetzen, damit bei der
Durchführung des Bereichsscans keine passenden
Datensätze übersehen werden. Nach der Ersetzung mit
TRUE
erhalten wir Folgendes:
(key1 < 'abc' AND (key1 LIKE 'abcde%' OR TRUE)) OR (key1 < 'bar' AND TRUE) OR (key1 < 'uux' AND key1 > 'z')
Die folgenden Kollapsbedingungen sind immer wahr oder falsch:
(key1 LIKE 'abcde%' OR TRUE)
ist
immer wahr.
(key1 < 'uux' AND key1 > 'z')
ist immer falsch.
Wenn wir diese Bedingungen durch Konstanten ersetzen, erhalten wir Folgendes:
(key1 < 'abc' AND TRUE) OR (key1 < 'bar' AND TRUE) OR (FALSE)
Durch Entfernen unnötiger TRUE
- und
FALSE
-Konstanten erhalten wir:
(key1 < 'abc') OR (key1 < 'bar')
Die Zusammenfassung überschneidender Intervalle hat die Bedingung zum Ergebnis, die endgültig für den Bereichsscan verwendet werden muss:
(key1 < 'bar')
Im Allgemeinen (und wie auch durch obiges Beispiel
veranschaulicht) ist die für einen Bereichsscan verwendete
Bedingung weniger restriktiv als die
WHERE
-Klausel. MySQL führt eine
zusätzliche Prüfung durch, um Datensätze auszufiltern, die
zwar die Bereichsbedingung erfüllen, nicht aber die
vollständige WHERE
-Klausel.
Der Extraktionsalgorithmus für die Bereichsbedingung kann
verschachtelte AND
- und/oder
OR
-Konstrukte beliebiger Tiefe verarbeiten.
Außerdem hängt seine Ausgabe nicht von der Reihenfolge ab,
in der die Bedingungen in der WHERE
-Klausel
erscheinen.
Die Bereichsbedingungen für einen mehrteiligen Index stellen eine Erweiterung der Bereichsbedingungen für einen einteiligen Index dar. Eine Bereichsbedingung für einen mehrteiligen Index beschränkt die Indexdatensätze auf solche, die innerhalb eines oder mehrerer Schlüsseltupelintervalle liegen. Schlüsseltupelintervalle werden über eine Menge von Schlüsseltupeln definiert, wobei die Sortierung dem Index entnommen wird.
Betrachten Sie beispielsweise einen mehrteiligen Index, der
als key1(
definiert ist,
und die folgende Menge der in der Schlüsselreihenfolge
aufgelisteten Schlüsseltupel:
key_part1
,
key_part2
,
key_part3
)
key_part1
key_part2
key_part3
NULL 1 'abc' NULL 1 'xyz' NULL 2 'foo' 1 1 'abc' 1 1 'xyz' 1 2 'abc' 2 1 'aaa'
Die Bedingung
definiert das folgende Intervall:
key_part1
=
1
(1,-inf,-inf) <= (key_part1
,key_part2
,key_part3
) < (1,+inf,+inf)
Das Intervall deckt das vierte, das fünfte und das sechste Tupel in der obigen Datenmenge ab und kann von der Bereichszugriffsmethode verwendet werden.
Im Gegensatz dazu definiert die Bedingung
kein einzelnes Intervall und kann von der
Bereichszugriffsmethode nicht verwendet werden.
key_part3
=
'abc'
Die folgenden Beschreibungen erläutern im Detail, wie Bereichsbedingungen bei mehrteiligen Indizes funktionieren.
Bei HASH
-Indizes kann jedes Intervall
verwendet werden, das identische Werte enthält. Das
bedeutet, dass das Intervall nur für Bedingungen in der
folgenden Form erzeugt werden kann:
key_part1
cmp
const1
ANDkey_part2
cmp
const2
AND ... ANDkey_partN
cmp
constN
;
Hierbei sind const1
,
const2
, … Konstanten,
cmp
ist einer der
Vergleichsoperatoren =
,
<=>
oder IS
NULL
, und die Bedingungen decken alle
Indexbestandteile ab. (Das bedeutet, es gibt
N
Bedingungen: eine für jeden
Teil eines N
-teiligen Indexes.)
Nachfolgend gezeigt ist etwa eine Bereichsbedingung für
einen dreiteiligen HASH
-Index:
key_part1
= 1 ANDkey_part2
IS NULL ANDkey_part3
= 'foo'
Eine Definition dessen, was als Konstanten betrachtet wird, finden Sie in Abschnitt 7.2.5.1, „Die Bereichszugriffsmethode (Range Access) für Indizes, die aus einzelnen Komponenten bestehen“.
Bei einem BTREE
-Index kann ein
Intervall für Bedingungen verwendbar sein, die mit
AND
kombiniert wurden, wobei jede
Bedingung einen Schlüsselteil mit einem Konstantenwert
unter Verwendung von =
,
<=>
, IS NULL
,
>
, <
,
>=
, <=
,
!=
, <>
,
BETWEEN
oder LIKE
'
vergleicht
(wobei
pattern
''
nicht mit einem Jokerzeichen beginnen darf). Ein Intervall
kann verwendet werden, solange es möglich ist, ein
einzelnes Schlüsseltupel zu bestimmen, das alle
Datensätze enthält, die der Bedingung entsprechen (bzw.
zwei Intervalle, wenn pattern
'<>
oder
!=
verwendet werden). Betrachten Sie
etwa folgende Bedingung:
key_part1
= 'foo' ANDkey_part2
>= 10 ANDkey_part3
> 10
Das einzelne Intervall ist:
('foo',10,10) < (key_part1
,key_part2
,key_part3
) < ('foo',+inf,+inf)
Es ist möglich, dass das erstellte Intervall mehr
Datensätze enthält als die Ursprungsbedingung. So
umfasst das obige Intervall beispielsweise den Wert
('foo', 11, 0)
, der die ursprüngliche
Bedingung nicht erfüllt.
Wenn Bedingungen, die Mengen von Datensätzen innerhalb
von Intervallen abdecken, mit OR
kombiniert werden, bilden sie eine Bedingung, die eine
Menge von Datensätzen abdeckt, die in der Union dieser
Intervalle enthalten sind. Werden die Bedingungen mit
AND
kombiniert, dann bilden sie eine
Bedingung, die die Menge von Datensätzen in der
Schnittmenge der Intervalle abdeckt. Betrachten Sie etwa
die folgende Bedingung für einen zweiteiligen Index:
(key_part1
= 1 ANDkey_part2
< 2) OR (key_part1
> 5)
Die Intervalle sehen hier wie folgt aus:
(1,-inf) < (key_part1
,key_part2
) < (1,2) (5,-inf) < (key_part1
,key_part2
)
In diesem Beispiel verwendet das Intervall für die erste
Zeile einen Schlüsselteil für die linke Grenze und zwei
Schlüsselteile für die rechte Grenze. Das Intervall in
der zweiten Zeile benutzt dagegen nur einen
Schlüsselteil. Die Spalte key_len
in
der Ausgabe von EXPLAIN
gibt die
maximale Länge des verwendeten Schlüsselpräfixes an.
In manchen Fällen kann key_len
anzeigen, dass ein Schlüsselteil verwendet wurde, aber
dies entspricht unter Umständen nicht dem, was Sie
erwarten. Angenommen, key_part1
und key_part2
können
NULL
sein. In diesem Fall zeigt die
Spalte key_len
zwei
Schlüsselteillängen für die folgende Bedingung an:
key_part1
>= 1 ANDkey_part2
< 2
Tatsächlich aber wird die Bedingung wie folgt konvertiert:
key_part1
>= 1 ANDkey_part2
IS NOT NULL
Abschnitt 7.2.5.1, „Die Bereichszugriffsmethode (Range Access) für Indizes, die aus einzelnen Komponenten bestehen“, beschreibt, wie Optimierungen zur Kombination oder Beseitigung von Intervallen für Bereichsbedingungen für einen einteiligen Index durchgeführt werden. Für Bereichsbedingungen für mehrteilige Indizes werden die Schritte analog durchgeführt.
Die Indexverschmelzungsmethode wird
verwendet, um Datensätze mit mehreren
range
-Scans abzurufen und deren Ergebnisse zu
einem Ergebnis zu verschmelzen. Die Verschmelzung kann Unions,
Schnittmengen oder Schnittmengen-Unions der zugrunde liegenden
Scans erzeugen.
In der Ausgabe von EXPLAIN
erscheint die
Indexverschmelzungsmethode als index_merge
in
der type
-Spalte. In diesem Fall enthält die
Spalte key
eine Liste der verwendeten
Indizes, und key_len
enthält eine Liste der
längsten Schlüsselteile für diese Indizes.
Ein paar Beispiele:
SELECT * FROMtbl_name
WHEREkey_part1
= 10 ORkey_part2
= 20; SELECT * FROMtbl_name
WHERE (key_part1
= 10 ORkey_part2
= 20) ANDnon_key_part
=30; SELECT * FROM t1, t2 WHERE (t1.key1
IN (1,2) OR t1.key2
LIKE 'value
%') AND t2.key1
=t1.some_col
; SELECT * FROM t1, t2 WHERE t1.key1
=1 AND (t2.key1
=t1.some_col
OR t2.key2
=t1.some_col2
);
Die Indexverschmelzungsmethode umfasst mehrere
Zugriffsalgorithmen (diese können dem Feld
Extra
in der Ausgabe von
EXPLAIN
entnommen werden):
Using intersect(…)
Using union(…)
Using sort_union(…)
Die folgenden Abschnitte beschreiben diese Methoden im Detail.
Hinweis: Der Optimierungsalgorithmus für die Indexverschmelzung weist die folgenden bekannten Defizite auf:
Wenn ein Bereichsscan für einen Schlüssel möglich ist, wird eine Indexverschmelzung nicht in Betracht gezogen. Betrachten Sie etwa folgende Abfrage:
SELECT * FROM t1 WHERE (goodkey1 < 10 OR goodkey2 < 20) AND badkey < 30;
Hierbei sind zwei Pläne möglich:
ein Indexverschmelzungsscan unter Verwendung der
Bedingung (goodkey1 < 10 OR goodkey2 <
20)
ein Bereichsscan unter Verwendung der Bedingung
badkey < 30
Der Optimierer allerdings zieht nur den zweiten Plan in
Betracht. Wenn Sie dies nicht wollen, können Sie mit
IGNORE INDEX
oder FORCE
INDEX
dafür sorgen, dass der Optimierer auch die
Indexverschmelzung berücksichtigt. Die folgenden beiden
Abfragen werden unter Verwendung der Indexverschmelzung
ausgeführt:
SELECT * FROM t1 FORCE INDEX(goodkey1,goodkey2) WHERE (goodkey1 < 10 OR goodkey2 < 20) AND badkey < 30; SELECT * FROM t1 IGNORE INDEX(badkey) WHERE (goodkey1 < 10 OR goodkey2 < 20) AND badkey < 30;
Wenn Ihre Abfrage eine komplexe
WHERE
-Klausel mit tiefer
AND
- oder
OR
-Verschachtelung enthält und MySQL
nicht den optimalen Plan auswählt, versuchen Sie die Terme
mithilfe der folgenden Identitätsgesetze zu verteilen:
(x
ANDy
) ORz
= (x
ORz
) AND (y
ORz
) (x
ORy
) ANDz
= (x
ANDz
) OR (y
ANDz
)
Die Indexverschmelzung ist nicht für Volltextindizes einsetzbar. Wir beabsichtigen, dies in einem zukünftigen MySQL-Release zu ändern.
Die Auswahl zwischen verschiedenen möglichen Varianten der Indexverschmelzungsmethode und anderen Zugriffsmethoden basiert auf Kostenschätzungen der verschiedenen verfügbaren Optionen.
Diese Zugriffsmethode kann verwendet werden, wenn eine
WHERE
-Klausel in mehrere
Bereichsbedingungen für verschiedene, mit
AND
kombinierte Schlüssel konvertiert
wurde und jede Bedingung eines der folgenden Elemente ist:
In dieser Form, wo der Index genau
N
Teile hat (d. h. alle
Indexteile sind abgedeckt):
key_part1
=const1
ANDkey_part2
=const2
... ANDkey_partN
=constN
Jede Bereichsbedingung über einen Primärschlüssel einer
InnoDB
- oder
BDB
-Tabelle.
Ein paar Beispiele:
SELECT * FROMinnodb_table
WHEREprimary_key
< 10 ANDkey_col1
=20; SELECT * FROMtbl_name
WHERE (key1_part1
=1 ANDkey1_part2
=2) ANDkey2
=2;
Der Indexverschmelzungs-Schnittmengenalgorithmus führt gleichzeitige Scans aller verwendeten Indizes durch und erzeugt die Schnittmenge der Datensatzsequenzen, die er den verschmolzenen Indexscans entnimmt.
Wenn alle in der Abfrage verwendeten Spalten von den
verwendeten Indizes abgedeckt werden, werden keine
vollständigen Tabellendatensätze abgerufen. (In diesem Fall
enthält die Ausgabe von EXPLAIN
Using index
im Feld
Extra
.) Hier ein Beispiel für eine solche
Abfrage:
SELECT COUNT(*) FROM t1 WHERE key1=1 AND key2=1;
Wenn die verwendeten Indizes nicht alle in der Abfrage verwendeten Spalten abdecken, werden vollständige Datensätze nur dann abgerufen, wenn die Bereichsbedingungen für alle Schlüssel erfüllt sind.
Wenn eine der verschmolzenen Bedingungen eine Bedingung über
einen Primärschlüssel einer InnoDB
- oder
BDB
-Tabelle ist, dann wird sie nicht zum
Abrufen von Datensätzen, sondern zum Ausfiltern von
Datensätzen verwendet, die mit anderen Bedingungen abgerufen
wurden.
Die Anwendbarkeitskriterien für diesen Algorithmus ähneln
denen des Schnittmengenalgorithmus der
Indexverschmelzungsmethode. Dieser Algorithmus kann verwendet
werden, wenn die WHERE
-Klausel der Tabelle
in mehrere Bereichsbedingungen für verschiedene, mit
OR
kombinierte Schlüssel konvertiert wurde
und jede Bedingung eines der folgenden Elemente ist:
In dieser Form, wo der Index genau
N
Teile hat (d. h. alle
Indexteile sind abgedeckt):
key_part1
=const1
ANDkey_part2
=const2
... ANDkey_partN
=constN
Jede Bereichsbedingung über einen Primärschlüssel einer
InnoDB
- oder
BDB
-Tabelle.
Eine Bedingung, auf die der Schnittmengenalgorithmus der Indexverschmelzungsmethode anwendbar ist.
Ein paar Beispiele:
SELECT * FROM t1 WHEREkey1
=1 ORkey2
=2 ORkey3
=3; SELECT * FROMinnodb_table
WHERE (key1
=1 ANDkey2
=2) OR (key3
='foo' ANDkey4
='bar') ANDkey5
=5;
Dieser Zugriffsalgorithmus wird verwendet, wenn die
WHERE
-Klausel in verschiedene
Bereichsbedingungen konvertiert wurde, die mit
OR
verknüpft wurden, aber für die der
Union-Algorithmus der Indexverschmelzungsmethode nicht
anwendbar ist.
Ein paar Beispiele:
SELECT * FROMtbl_name
WHEREkey_col1
< 10 ORkey_col2
< 20; SELECT * FROMtbl_name
WHERE (key_col1
> 10 ORkey_col2
= 20) ANDnonkey_col
=30;
Der Unterschied zwischen dem Sort-Union-Algorithmus und dem Union-Algorithmus besteht darin, dass der Sort-Union-Algorithmus zunächst die Datensatzkennungen aller Datensätze abrufen und diese sortieren muss, bevor er Datensätze zurückgeben kann.
MySQL kann dieselbe Optimierung an
col_name
IS NULL
vornehmen, die es auch für col_name
=
constant_value
durchführen kann. So kann MySQL etwa Indizes und Bereiche zur
Suche nach NULL
mit IS
NULL
verwenden.
Ein paar Beispiele:
SELECT * FROMtbl_name
WHEREkey_col
IS NULL; SELECT * FROMtbl_name
WHEREkey_col
<=> NULL; SELECT * FROMtbl_name
WHEREkey_col
=const1
ORkey_col
=const2
ORkey_col
IS NULL;
Wenn eine WHERE
-Klausel eine Bedingung
col_name
IS NULL
für eine Spalte enthält, die als NOT NULL
deklariert ist, dann wird dieser Ausdruck wegoptimiert. Diese
Optimierung findet allerdings nicht in Fällen statt, in denen
die Spalte ohnehin NULL
erzeugen könnte –
z. B. wenn sie aus einer Tabelle auf der rechten Seite eines
LEFT JOIN
stammt.
MySQL kann auch die Kombination
optimieren; diese Form tritt bei aufgelösten Unterabfragen
häufig auf. col_name
=
expr
AND
col_name
IS NULLEXPLAIN
zeigt
ref_or_null
an, wenn diese Optimierung
verwendet wird.
Diese Optimierung kann je Schlüsselteil eine IS
NULL
-Bedingung verarbeiten.
Es folgen einige Beispiele für optimierte Abfragen (hierbei
wird davon ausgegangen, dass ein Index für die Spalten
a
und b
der Tabelle
t2
vorhanden ist):
SELECT * FROM t1 WHERE t1.a=expr
OR t1.a IS NULL;
SELECT * FROM t1, t2 WHERE t1.a=t2.a OR t2.a IS NULL;
SELECT * FROM t1, t2
WHERE (t1.a=t2.a OR t2.a IS NULL) AND t2.b=t1.b;
SELECT * FROM t1, t2
WHERE t1.a=t2.a AND (t2.b=t1.b OR t2.b IS NULL);
SELECT * FROM t1, t2
WHERE (t1.a=t2.a AND t2.a IS NULL AND ...)
OR (t1.a=t2.a AND t2.a IS NULL AND ...);
Bei ref_or_null
wird zunächst der
Referenzschlüssel ausgelesen. Danach erfolgt eine separate
Suche nach Datensätzen mit einem
NULL
-Schlüsselwert.
Beachten Sie, dass die Optimierung nur eine IS
NULL
-Ebene verarbeiten kann. In der folgenden Abfrage
verwendet MySQL Schlüsselsuchvorgänge nur für den Ausdruck
(t1.a=t2.a AND t2.a IS NULL)
. Der
Schlüsselteil zu b
kann von MySQL nicht
verwendet werden:
SELECT * FROM t1, t2 WHERE (t1.a=t2.a AND t2.a IS NULL) OR (t1.b=t2.b AND t2.b IS NULL);
DISTINCT
kombiniert mit ORDER
BY
benötigt in vielen Fällen eine Temporärtabelle.
Weil DISTINCT
unter Umständen GROUP
BY
verwendet, sollten Sie wissen, wie MySQL mit
Spalten in ORDER BY
- oder
HAVING
-Klauseln verfährt, die nicht Teil der
gewählten Spalten sind. Siehe auch
Abschnitt 12.11.3, „GROUP BY
mit versteckten Feldern“.
In vielen Fällen kann eine DISTINCT
-Klausel
als Sonderfall von GROUP BY
betrachtet
werden. So sind beispielsweise die beiden folgenden Abfragen
gleichwertig:
SELECT DISTINCT c1, c2, c3 FROM t1 WHERE c1 >const
; SELECT c1, c2, c3 FROM t1 WHERE c1 >const
GROUP BY c1, c2, c3;
Aufgrund dieser Äquivalenz können die Optimierungen, die für
GROUP BY
-Abfragen verwendbar sind, auch auf
Abfragen mit einer DISTINCT
-Klausel
angewendet werden. Insofern sollten Sie, um weitere
Informationen zu Optimierungsmöglichkeiten bei
DISTINCT
-Abfragen zu erhalten, unter
Abschnitt 7.2.13, „GROUP BY
-Optimierung“, nachschlagen.
Wenn Sie LIMIT
mit
row_count
DISTINCT
kombinieren, beendet MySQL die
Abfrage, sobald row_count
eindeutige
Datensätze gefunden wurden.
Wenn Sie nicht Spalten aus allen in einer Abfrage aufgeführten
Tabellen verwenden, beendet MySQL das Scannen unbenutzter
Tabellen, sobald die erste Übereinstimmung gefunden wurde. Im
folgenden Fall (in dem vorausgesetzt wird, dass
t1
vor t2
benutzt wird,
was mit EXPLAIN
verifiziert werden kann)
beendet MySQL das Auslesen von t2
für einen
beliebigen Datensatz in t1
, sobald der erste
Datensatz in t2
gefunden wird:
SELECT DISTINCT t1.a FROM t1, t2 where t1.a=t2.a;
MySQL implementiert
wie
folgt:
A
LEFT
JOIN B
join_condition
Tabelle B
ist so konfiguriert,
dass sie von Tabelle A
und allen
Tabellen abhängt, von denen auch Tabelle
A
abhängt.
Tabelle A
ist ihrerseits so
konfiguriert, dass sie von allen Tabellen (mit Ausnahme von
B
) abhängt, die in der
LEFT JOIN
-Bedingung verwendet werden.
Anhand der LEFT JOIN
-Bedingung wird
entschieden, wie Datensätze aus der Tabelle
B
abgerufen werden. (Das
bedeutet, dass keine Bedingung in der
WHERE
-Klausel verwendet wird.)
Alle Standardoptimierungen für Joins werden durchgeführt; einzige Ausnahme ist, dass jede Tabelle stets erst gelesen wird, nachdem alle Tabellen gelesen wurden, von denen sie abhängt. Gibt es eine Zirkelabhängigkeit, dann gibt MySQL einen Fehler aus.
Alle Standardoptimierungen für WHERE
werden durchgeführt.
Wenn ein Datensatz in A
vorhanden
ist, der der WHERE
-Klausel entspricht,
aber kein Datensatz in B
, der der
ON
-Bedingung entspricht, dann wird ein
zusätzlicher Datensatz in B
erzeugt, bei dem alle Spalten auf NULL
gesetzt sind.
Wenn Sie mit LEFT JOIN
Datensätze
suchen, die in keiner der Tabellen vorhanden sind, und die
Überprüfung
im col_name
IS NULLWHERE
-Teil vorhanden
ist (wobei col_name
eine als
NOT NULL
deklarierte Spalte ist), dann
beendet MySQL die Suche nach weiteren Datensätzen (für
eine bestimmte Schlüsselkombination), wenn es genau einen
Datensatz gefunden hat, der der LEFT
JOIN
-Bedingung entspricht.
Die Implementierung von RIGHT JOIN
erfolgt
analog zu der von LEFT JOIN
, wobei lediglich
die Rollen der Tabellen umgekehrt werden.
Der Join-Optimierer berechnet die Reihenfolge, in der die
Tabellen verknüpft werden sollten. Die durch LEFT
JOIN
oder STRAIGHT_JOIN
erzwungene
Lesereihenfolge für die Tabellen unterstützt den
Join-Optimierer bei seiner Arbeit wesentlich effizienter, weil
erheblich weniger Tabellenumstellungen zu überprüfen sind.
Beachten Sie, dass dies bedeutet, dass, wenn Sie eine Abfrage
folgenden Typs ausführen, MySQL einen vollständigen Scan in
b
durchführt, weil diese Tabelle aufgrund
von LEFT JOIN
vor d
gelesen wird:
SELECT * FROM a,b LEFT JOIN c ON (c.key=a.key) LEFT JOIN d ON (d.key=a.key) WHERE b.key=d.key;
Die Lösung besteht in diesem Fall darin, die Reihenfolge
umzukehren, in der a
und b
in der FROM
-Klausel aufgelistet werden:
SELECT * FROM b,a LEFT JOIN c ON (c.key=a.key) LEFT JOIN d ON (d.key=a.key) WHERE b.key=d.key;
Wenn bei einem LEFT JOIN
die
WHERE
-Bedingung für den erzeugten
NULL
-Datensatz immer falsch ist, dann wird
der LEFT JOIN
in einen normalen Join
umgesetzt. So wäre beispielsweise die
WHERE
-Klausel in der folgenden Abfrage
falsch, wenn t2.column1
NULL
wäre:
SELECT * FROM t1 LEFT JOIN t2 ON (column1) WHERE t2.column2=5;
Aus diesem Grund kann die Abfrage problemlos in einen normalen Join konvertiert werden:
SELECT * FROM t1, t2 WHERE t2.column2=5 AND t1.column1=t2.column1;
Dies kann schneller erfolgen, weil MySQL die Tabelle
t2
vor t1
verwenden kann,
sofern dies einen besseren Abfrageplan zum Ergebnis hätte. Mit
STRAIGHT_JOIN
können Sie eine bestimmte
Tabellenreihenfolge erzwingen.
Die Syntax zum Ausdrücken von Joins gestattet auch
verschachtelte Joins. Die nachfolgende Beschreibung bezieht sich
auf die in Abschnitt 13.2.7.1, „JOIN
“, beschriebene Join-Syntax.
Die Syntax von table_factor
ist im
Vergleich zum SQL-Standard erweitert. SQL akzeptiert nur
table_reference
, nicht aber eine in
Klammern gesetzte Liste mit Referenzierungen. Dies ist eine
konservative Erweiterung, sofern wir jedes Komma in einer Liste
mit table_reference
-Elementen als
äquivalent zu einem inneren Join betrachten. Zum Beispiel:
SELECT * FROM t1 LEFT JOIN (t2, t3, t4) ON (t2.a=t1.a AND t3.b=t1.b AND t4.c=t1.c)
ist äquivalent mit
SELECT * FROM t1 LEFT JOIN (t2 CROSS JOIN t3 CROSS JOIN t4) ON (t2.a=t1.a AND t3.b=t1.b AND t4.c=t1.c)
In MySQL ist CROSS JOIN
syntaktisch ein
Äquivalent zu INNER JOIN
(diese lassen sich
gegeneinander austauschen). Nach SQL-Standard hingegen sind
beide nicht äquivalent. INNER JOIN
wird bei
einer ON
-Klausel und CROSS
JOIN
andernfalls verwendet.
Klammern können in Join-Ausdrücken, die nur innere Join-Operationen enthalten, ignoriert werden. Betrachten Sie folgenden Ausdruck:
t1 LEFT JOIN (t2 LEFT JOIN t3 ON t2.b=t3.b OR t2.b IS NULL) ON t1.a=t2.a
Nach Entfernen der Klammern und Gruppieren der Operationen auf der linken Seite entsteht folgender Ausdruck:
(t1 LEFT JOIN t2 ON t1.a=t2.a) LEFT JOIN t3 ON t2.b=t3.b OR t2.b IS NULL
Trotzdem sind die beiden Ausdrücke nicht äquivalent. Um dies
nachzuweisen, nehmen wir an, dass die Tabellen
t1
, t2
und
t3
die folgenden Zustände haben:
Tabelle t1
enthält die Datensätze
{1}
, {2}
.
Tabelle t2
enthält den Datensatz
{1,101}
.
Tabelle t3
enthält den Datensatz
{101}
.
In diesem Fall gibt der erste Ausdruck eine Ergebnismenge mit
den Datensätzen {1,1,101,101}
,
{2,NULL,NULL,NULL}
zurück; der zweite
Ausdruck hingegen gibt die Datensätze
{1,1,101,101}
,
{2,NULL,NULL,101}
zurück:
mysql>SELECT *
->FROM t1
->LEFT JOIN
->(t2 LEFT JOIN t3 ON t2.b=t3.b OR t2.b IS NULL)
->ON t1.a=t2.a;
+------+------+------+------+ | a | a | b | b | +------+------+------+------+ | 1 | 1 | 101 | 101 | | 2 | NULL | NULL | NULL | +------+------+------+------+ mysql>SELECT *
->FROM (t1 LEFT JOIN t2 ON t1.a=t2.a)
->LEFT JOIN t3
->ON t2.b=t3.b OR t2.b IS NULL;
+------+------+------+------+ | a | a | b | b | +------+------+------+------+ | 1 | 1 | 101 | 101 | | 2 | NULL | NULL | 101 | +------+------+------+------+
Im folgenden Beispiel wird ein äußerer Join gemeinsam mit einem inneren Join verwendet:
t1 LEFT JOIN (t2, t3) ON t1.a=t2.a
Dieser Ausdruck kann nicht in den folgenden Ausdruck transformiert werden:
t1 LEFT JOIN t2 ON t1.a=t2.a, t3.
Für die gegebenen Tabellenzustände geben die beiden Ausdrücke verschiedene Datensatzmengen zurück:
mysql>SELECT *
->FROM t1 LEFT JOIN (t2, t3) ON t1.a=t2.a;
+------+------+------+------+ | a | a | b | b | +------+------+------+------+ | 1 | 1 | 101 | 101 | | 2 | NULL | NULL | NULL | +------+------+------+------+ mysql>SELECT *
->FROM t1 LEFT JOIN t2 ON t1.a=t2.a, t3;
+------+------+------+------+ | a | a | b | b | +------+------+------+------+ | 1 | 1 | 101 | 101 | | 2 | NULL | NULL | 101 | +------+------+------+------+
Aus diesem Grund ändern wir, wenn wir in einem Join-Ausdruck mit äußeren Join-Operatoren die Klammern weglassen, unter Umständen die Ergebnismenge für den ursprünglichen Ausdruck.
Genauer formuliert: Wir dürfen die Klammern im rechten Operanden der linken äußeren Join-Operation und im linken Operanden einer rechten Join-Operation nicht ignorieren. Oder: Die Klammern der inneren Tabellenausdrücke äußerer Join-Operationen dürfen nicht unbeachtet bleiben. Klammern für den anderen Operanden (d. h. den Operanden der äußeren Tabelle) können hingegen ignoriert werden.
Der Ausdruck
(t1,t2) LEFT JOIN t3 ON P(t2.b,t3.b)
ist äquivalent zu folgendem Ausdruck:
t1, t2 LEFT JOIN t3 ON P(t2.b,t3.b)
Dies gilt für alle Tabellen t1,t2,t3
und
alle Bedingungen P
für Attribute
t2.b
und t3.b
.
Immer dann, wenn die Join-Operationen in einem Join-Ausdruck
(join_table
) nicht von links nach
rechts ausgeführt werden, redet man von verschachtelten Joins.
Betrachten Sie einmal die folgenden Abfragen:
SELECT * FROM t1 LEFT JOIN (t2 LEFT JOIN t3 ON t2.b=t3.b) ON t1.a=t2.a WHERE t1.a > 1 SELECT * FROM t1 LEFT JOIN (t2, t3) ON t1.a=t2.a WHERE (t2.b=t3.b OR t2.b IS NULL) AND t1.a > 1
Diese Abfragen enthalten die folgenden verschachtelten Joins:
t2 LEFT JOIN t3 ON t2.b=t3.b t2, t3
Der verschachtelte Join wird in der ersten Abfrage mit einem Left-Join gebildet, während er in der zweiten Abfrage aufgrund einer inneren Join-Operation entsteht.
In der ersten Abfrage können die Klammern weggelassen werden:
Die grammatische Struktur des Join-Ausdrucks schreibt dieselbe
Ausführungsreihenfolge für Join-Operationen vor. Bei der
zweiten Abfrage dürfen die Klammern nicht weggelassen werden,
obwohl der Join-Ausdruck hier auch ohne sie eindeutig
interpretiert werden könnte. (In unserer erweiterten Syntax
sind die Klammern im Ausdruck (t2, t3)
der
zweiten Abfrage erforderlich, obwohl die Abfrage theoretisch
auch ohne sie analysiert werden könnte: Wir hätten immer noch
eine eindeutige syntaktische Struktur für die Abfrage, da
LEFT JOIN
und ON
die Rolle
der linken und rechten Begrenzungen für den Ausdruck
(t2,t3)
übernähmen.)
Die obigen Beispiele veranschaulichen die folgenden Aspekte:
Bei Join-Ausdrücken, die nur innere Joins (und keine äußeren Joins) enthalten, können die Klammern entfernt werden. Sie können die Klammern entfernen und die Auswertung von links nach rechts vornehmen (tatsächlich kann die Auswertung der Tabellen sogar in beliebiger Reihenfolge erfolgen).
Dies gilt allerdings in der Regel nicht für äußere Joins oder mit inneren Joins gemischte äußere Joins. Ein Entfernen der Klammern kann das Ergebnis ändern.
Abfragen mit verschachtelten äußeren Joins werden in derselben
Weise ausgeführt wie Abfragen mit inneren Joins. Genauer
gesagt, wird eine Abwandlung des Join-Algorithmus mit
verschachtelten Schleifen benutzt. Vergegenwärtigen Sie sich,
mit welchem Algorithmusschema ein Join mit verschachtelten
Schleifen eine Abfrage ausführt. Angenommen, wir haben eine
Join-Abfrage über drei Tabellen T1,T2,T3
der
folgenden Form:
SELECT * FROM T1 INNER JOIN T2 ON P1(T1,T2) INNER JOIN T3 ON P2(T2,T3) WHERE P(T1,T2,T3).
Hierbei seien P1(T1,T2)
und
P2(T3,T3)
Join-Bedingungen (für Ausdrücke),
während P(t1,t2,t3)
eine Bedingung über
Spalten der Tabellen T1,T2,T3
ist.
Der Algorithmus für Joins mit verschachtelten Schleifen würde die Abfrage wie folgt ausführen:
FOR each row t1 in T1 { FOR each row t2 in T2 such that P1(t1,t2) { FOR each row t3 in T3 such that P2(t2,t3) { IF P(t1,t2,t3) { t:=t1||t2||t3; OUTPUT t; } } } }
Die Notation t1||t2||t3
bedeutet einen
„Datensatz, der durch Verkettung der Spalten der
Datensätze t1
, t2
und
t3
entsteht“. In einigen der folgenden
Beispiele bezeichnet, wenn ein Datensatzname erscheint,
NULL
die Tatsache, dass
NULL
für jede Spalte dieses Datensatzes
benutzt wird. Beispielsweise bedeutet
t1||t2||NULL
„einen Datensatz, der aus
den verketteten Spalten der Datensätze t1
und t2
sowie NULL
für
jede Spalte von t3
besteht“.
Betrachten wir nun eine Abfrage mit verschachtelten äußeren Joins:
SELECT * FROM T1 LEFT JOIN (T2 LEFT JOIN T3 ON P2(T2,T3)) ON P1(T1,T2) WHERE P(T1,T2,T3).
Für diese Abfrage ändern wir das Muster für verschachtelte Schleifen ab und erhalten Folgendes:
FOR each row t1 in T1 { BOOL f1:=FALSE; FOR each row t2 in T2 such that P1(t1,t2) { BOOL f2:=FALSE; FOR each row t3 in T3 such that P2(t2,t3) { IF P(t1,t2,t3) { t:=t1||t2||t3; OUTPUT t; } f2=TRUE; f1=TRUE; } IF (!f2) { IF P(t1,t2,NULL) { t:=t1||t2||NULL; OUTPUT t; } f1=TRUE; } } IF (!f1) { IF P(t1,NULL,NULL) { t:=t1||NULL||NULL; OUTPUT t; } } }
Generell wird für jede verschachtelte Schleife für die erste
innere Tabelle einer äußeren Join-Operation ein Flag
eingeführt, welches vor der Schleife gelöscht und danach
wieder gesetzt wird. Das Flag wird gesetzt, wenn für den
aktuellen Datensatz aus der äußeren Tabelle eine Entsprechung
in der Tabelle gefunden wird, die den inneren Operanden
darstellt. Wenn das Flag am Ende des Schleifenzyklus immer noch
nicht gelöscht ist, dann wurde für den aktuellen Datensatz in
der äußeren Tabelle keine Entsprechung gefunden. In diesem
Fall wird der Datensatz mit NULL
-Werten für
die Spalten der inneren Tabellen ergänzt. Der Ergebnisdatensatz
wird zur letzten Überprüfung an die Ausgabe oder in die
nächste verschachtelte Schleife übergeben – aber nur dann,
wenn der Datensatz die Join-Bedingung für alle eingebetteten
äußeren Joins erfüllt.
In unserem Beispiel ist die mit dem folgenden Ausdruck beschriebene äußere Join-Tabelle eingebettet:
(T2 LEFT JOIN T3 ON P2(T2,T3))
Beachten Sie, dass der Optimierer für die Abfrage mit inneren Joins eine andere Reihenfolge für verschachtelte Schleifen wählen könnte – etwa die folgende:
FOR each row t3 in T3 { FOR each row t2 in T2 such that P2(t2,t3) { FOR each row t1 in T1 such that P1(t1,t2) { IF P(t1,t2,t3) { t:=t1||t2||t3; OUTPUT t; } } } }
Bei Abfragen mit äußeren Joins kann der Optimierer nur eine Reihenfolge wählen, bei der Schleifen für äußere Tabellen den Schleifen für die inneren Tabellen vorangehen. Insofern ist für unsere Abfrage mit äußeren Joins nur eine Verschachtelungsreihenfolge möglich. Bei der folgenden Abfrage wird der Optimierer zwei verschiedene Verschachtelungen auswerten:
SELECT * T1 LEFT JOIN (T2,T3) ON P1(T1,T2) AND P2(T1,T3) WHERE P(T1,T2,T3)
Die Verschachtelungen sind
FOR each row t1 in T1 { BOOL f1:=FALSE; FOR each row t2 in T2 such that P1(t1,t2) { FOR each row t3 in T3 such that P2(t1,t3) { IF P(t1,t2,t3) { t:=t1||t2||t3; OUTPUT t; } f1:=TRUE } } IF (!f1) { IF P(t1,NULL,NULL) { t:=t1||NULL||NULL; OUTPUT t; } } }
und
FOR each row t1 in T1 { BOOL f1:=FALSE; FOR each row t3 in T3 such that P2(t1,t3) { FOR each row t2 in T2 such that P1(t1,t2) { IF P(t1,t2,t3) { t:=t1||t2||t3; OUTPUT t; } f1:=TRUE } } IF (!f1) { IF P(t1,NULL,NULL) { t:=t1||NULL||NULL; OUTPUT t; } } }
In beiden Verschachtelungen muss T1
in der
äußeren Schleife verarbeitet werden, weil sie in einem
äußeren Join verwendet wird. T2
und
T3
werden hingegen in einem inneren Join
benutzt, d. h., der Join muss in der inneren Schleife
verarbeitet werden. Allerdings können, weil der Join ein
innerer Join ist, T2
und
T3
in beliebiger Ordnung verarbeitet werden.
Bei der Beschreibung des Algorithmus mit verschachtelten
Schleifen für innere Joins haben wir ein paar Details
übergangen, deren Wirkung auf die Leistungsfähigkeit der
Abfrageausführung beträchtlich sein kann. Wir haben
beispielsweise so genannte „Pushdown-Bedingungen“
nicht erwähnt. Angenommen, unsere
WHERE
-Bedingung
P(T1,T2,T3)
könnte mit einer konjunktiven
Formel dargestellt werden:
P(T1,T2,T2) = C1(T1) AND C2(T2) AND C3(T3).
In diesem Fall verwendet MySQL in der Tat das folgende Schema mit verschachtelten Schleifen zur Ausführung der Abfrage mit inneren Joins:
FOR each row t1 in T1 such that C1(t1) { FOR each row t2 in T2 such that P1(t1,t2) AND C2(t2) { FOR each row t3 in T3 such that P2(t2,t3) AND C3(t3) { IF P(t1,t2,t3) { t:=t1||t2||t3; OUTPUT t; } } } }
Sie erkennen, dass die Konjunkte C1(T1)
,
C2(T2)
und C3(T3)
aus der
innersten in die äußerste Schleife verschoben werden, wo sie
dann ausgewertet werden können. Wenn C1(T1)
eine sehr restriktive Bedingung ist, dann kann dieser
Bedingungs-Pushdown die Anzahl der Datensätze aus Tabelle
T1
, die an die inneren Schleifen
weitergegeben werden, erheblich verringern. Hieraus ergibt sich
eine beachtliche Verbesserung bei der Ausführungszeit für die
Abfrage.
Bei einer Abfrage mit äußeren Joins muss die
WHERE
-Bedingung erst geprüft werden, wenn
festgestellt wurde, dass für den aktuellen Datensatz in der
äußeren Tabelle eine Entsprechung in den inneren Tabellen
vorhanden ist. Aufgrund dessen kann die Optimierung mit einer
Pushdown-Bedingung aus den inneren verschachtelten Schleifen
nicht direkt auf Abfragen mit äußeren Joins angewendet werden.
Deswegen müssen an dieser Stelle konditionale
Pushdown-Prädikate in Verbindung mit Überwachungs-Flags
eingeführt werden, die gesetzt werden, sobald eine
Übereinstimmung gefunden wurde.
Betrachten Sie noch einmal unser Beispiel mit äußeren Joins:
P(T1,T2,T3)=C1(T1) AND C(T2) AND C3(T3)
Hier sieht das Schema der verschachtelten Schleifen unter Verwendung überwachter Pushdown-Bedingungen wie folgt aus:
FOR each row t1 in T1 such that C1(t1) { BOOL f1:=FALSE; FOR each row t2 in T2 such that P1(t1,t2) AND (f1?C2(t2):TRUE) { BOOL f2:=FALSE; FOR each row t3 in T3 such that P2(t2,t3) AND (f1&&f2?C3(t3):TRUE) { IF (f1&&f2?TRUE:(C2(t2) AND C3(t3))) { t:=t1||t2||t3; OUTPUT t; } f2=TRUE; f1=TRUE; } IF (!f2) { IF (f1?TRUE:C2(t2) && P(t1,t2,NULL)) { t:=t1||t2||NULL; OUTPUT t; } f1=TRUE; } } IF (!f1 && P(t1,NULL,NULL)) { t:=t1||NULL||NULL; OUTPUT t; } }
Generell können Pushdown-Prädikate aus Join-Bedingungen wie
P1(T1,T2)
und P(T2,T3)
extrahiert werden. In diesem Fall wird ein Pushdown-Prädikat
auch von einem Flag überwacht, das eine Überprüfung des
Prädikats auf den mit NULL
ergänzten
Datensatz verhindert, der im Zuge der entsprechenden
Join-Operation erzeugt wurde.
Beachten Sie, dass ein Zugriff nach Schlüssel aus einer inneren
Tabelle auf eine andere Tabelle im selben verschachtelten Join
unzulässig ist, wenn er durch ein Prädikat aus der
WHERE
-Bedingung herbeigeführt wird. (Wir
könnten in diesem Fall einen bedingten Schlüsselzugriff
verwenden, aber diese Methode ist in MySQL 5.1 noch
nicht implementiert.)
Tabellenausdrücke in der FROM
-Klausel einer
Abfrage werden in vielen Fällen vereinfacht.
Auf der Parserebene werden Abfragen mit rechten äußeren Join-Operationen in gleichwertige Abfragen konvertiert, die nur Left-Join-Operationen enthalten. Im Allgemeinen erfolgt die Konvertierung auf der Basis der folgenden Regel:
(T1, ...) RIGHT JOIN (T2,...) ON P(T1,...,T2,...) = (T2, ...) LEFT JOIN (T1,...) ON P(T1,...,T2,...).
Alle inneren Join-Ausdrücke der Form T1 INNER JOIN T2
ON P(T1,T2)
werden durch die Liste
T1,T2
ersetzt, und
P(T1,T2)
wird als Konjunkt mit der
WHERE
-Bedingung (oder mit der Join-Bedingung
des einbettenden Joins, sofern vorhanden) verknüpft.
Wenn der Optimierer Pläne für Join-Abfragen mit einer äußeren Join-Operation auswertet, berücksichtigt er nur diejenigen Pläne, bei denen bei einer solchen Operation zunächst auf die äußeren und erst dann auf die inneren Tabellen zugegriffen wird. Die Optimiereroptionen sind eingeschränkt, weil nur solche Pläne uns die Ausführung von Abfragen mit äußeren Join-Operationen über das Schema mit verschachtelten Schleifen gestatten.
Angenommen, wir haben eine Abfrage folgenden Aussehens:
SELECT * T1 LEFT JOIN T2 ON P1(T1,T2) WHERE P(T1,T2) AND R(T2)
Hierbei schränkt R(T2)
die Anzahl passender
Datensätze aus der Tabelle T2
erheblich ein.
Wenn wir die Abfrage in ihrer ursprünglichen Form ausgeführt
hätten, hätte der Optimierer keine andere Chance gehabt, als
zuerst auf die Tabelle T1
und erst dann auf
T2
zuzugreifen. Dies hätte einen sehr
ineffizienten Ausführungsplan zur Folge gehabt.
Glücklicherweise wandelt MySQL eine solche Abfrage in eine
Abfrage ohne äußere Join-Operation um, wenn die
WHERE
-Bedingung nullabweisend wird. Eine
Bedingung heißt nullabweisend für eine äußere
Join-Operation, wenn sie für jeden
NULL
-ergänzten Datensatz, der für die
Operation erstellt wurde, stets FALSE
oder
UNKNOWN
ist.
Betrachten Sie folgenden äußeren Join:
T1 LEFT JOIN T2 ON T1.A=T2.A
Für ihn sind Bedingungen wie die folgenden nullabweisend:
T2.B IS NOT NULL, T2.B > 3, T2.C <= T1.C, T2.B < 2 OR T2.C > 1
Bedingungen wie die folgenden sind hingegen nicht nullabweisend:
T2.B IS NULL, T1.B < 3 OR T2.B IS NOT NULL, T1.B < 3 OR T2.B > 3
Die allgemeinen Regeln zur Überprüfung, ob eine Bedingung für einen äußeren Join nullabweisend ist oder nicht, sind recht einfach. Eine Bedingung ist nullabweisend, wenn sie
die Form A IS NOT NULL
hat, wobei
A
ein Attribut einer der inneren Tabellen
ist,
ein Prädikat ist, das eine innere Tabelle referenziert, die
UNKNOWN
ist, wenn eines ihrer Argumente
NULL
ist,
eine Konjunktion mit einer nullabweisenden Bedingung als Konjunkt ist,
eine Disjunktion nullabweisender Bedingungen ist.
Eine Bedingung kann für eine äußere Join-Operation nullabweisend sein und gleichzeitig für eine andere nicht. Betrachten Sie folgende Abfrage:
SELECT * FROM T1 LEFT JOIN T2 ON T2.A=T1.A LEFT JOIN T3 ON T3.B=T1.B WHERE T3.C > 0
Hier ist die WHERE
-Bedingung für die zweite
äußere Join-Operation nullabweisend, nicht jedoch für die
erste.
Wenn die WHERE
-Bedingung für eine äußere
Join-Operation in einer Abfrage nullabweisend ist, wird die
äußere Join-Operation durch eine innere Join-Operation
ersetzt.
So wird etwa obige Abfrage durch die folgende ersetzt:
SELECT * FROM T1 LEFT JOIN T2 ON T2.A=T1.A INNER JOIN T3 ON T3.B=T1.B WHERE T3.C > 0
Für die ursprüngliche Abfrage würde der Optimierer Pläne
auswerten, die mit der Zugriffsreihenfolge
T1,T2,T3
kompatibel wären. Für die
ersetzende Abfrage wird außerdem die Zugriffssequenz
T3,T1,T2
in Betracht gezogen.
Eine Konvertierung einer äußeren Join-Operation kann eine Konvertierung einer anderen derartigen Operation auslösen. Betrachten Sie folgende Abfrage:
SELECT * FROM T1 LEFT JOIN T2 ON T2.A=T1.A LEFT JOIN T3 ON T3.B=T2.B WHERE T3.C > 0
Diese wird in die folgende Abfrage konvertiert:
SELECT * FROM T1 LEFT JOIN T2 ON T2.A=T1.A INNER JOIN T3 ON T3.B=T2.B WHERE T3.C > 0
Diese wiederum ist äquivalent mit dieser Abfrage:
SELECT * FROM (T1 LEFT JOIN T2 ON T2.A=T1.A), T3 WHERE T3.C > 0 AND T3.B=T2.B
Nun kann die verbleibende äußere Join-Operation ebenfalls
durch einen inneren Join ersetzt werden, weil die Bedingung
T3.B=T2.B
nullabweisend ist und wir eine
Abfrage erhalten, die überhaupt keine äußeren Joins enthält:
SELECT * FROM (T1 INNER JOIN T2 ON T2.A=T1.A), T3 WHERE T3.C > 0 AND T3.B=T2.B
Manchmal gelingt es, eine eingebettete äußere Join-Operation zu ersetzen, aber der einbettende äußere Join kann nicht konvertiert werden. Betrachten Sie folgende Abfrage:
SELECT * FROM T1 LEFT JOIN (T2 LEFT JOIN T3 ON T3.B=T2.B) ON T2.A=T1.A WHERE T3.C > 0
Sie wird wie folgt konvertiert:
SELECT * FROM T1 LEFT JOIN (T2 INNER JOIN T3 ON T3.B=T2.B) ON T2.A=T1.A WHERE T3.C > 0,
Dies lässt sich nur in einer Form umschreiben, die nach wie vor die einbettende äußere Join-Operation enthält:
SELECT * FROM T1 LEFT JOIN (T2,T3) ON (T2.A=T1.A AND T3.B=T2.B) WHERE T3.C > 0.
Wenn Sie versuchen, eine eingebettete äußere Join-Operation zu
konvertieren, dann müssen Sie die Join-Bedingung für den
einbettenden äußeren Join gemeinsam mit der
WHERE
-Bedingung berücksichtigen. Betrachten
Sie folgende Abfrage:
SELECT * FROM T1 LEFT JOIN (T2 LEFT JOIN T3 ON T3.B=T2.B) ON T2.A=T1.A AND T3.C=T1.C WHERE T3.D > 0 OR T1.D > 0
Hier ist die WHERE
-Bedingung für den
eingebetteten äußeren Join nicht nullabweisend, wohl aber die
Join-Bedingung des einbettenden äußeren Joins
T2.A=T1.A
AND T3.C=T1.C
.
Insofern kann die Abfrage wie folgt konvertiert werden:
SELECT * FROM T1 LEFT JOIN (T2, T3) ON T2.A=T1.A AND T3.C=T1.C AND T3.B=T2.B WHERE T3.D > 0 OR T1.D > 0
In manchen Fällen kann MySQL mit einem Index eine
ORDER BY
-Klausel erfüllen, ohne dass eine
zusätzliche Sortierung erforderlich wäre.
Der Index kann auch verwendet werden, wenn die ORDER
BY
-Klausel dem Index nicht exakt entspricht, solange
alle nicht verwendeten Bestandteile des Indexes und alle
zusätzlichen ORDER BY
-Spalten Konstanten in
der WHERE
-Klausel sind. Die folgenden
Abfragen lösen den ORDER BY
-Teil mithilfe
des Indexes auf:
SELECT * FROM t1 ORDER BYkey_part1
,key_part2
,... ; SELECT * FROM t1 WHEREkey_part1
=constant
ORDER BYkey_part2
; SELECT * FROM t1 ORDER BYkey_part1
DESC,key_part2
DESC; SELECT * FROM t1 WHEREkey_part1
=1 ORDER BYkey_part1
DESC,key_part2
DESC;
In manchen Fällen kann MySQL Indizes nicht
zur Auflösung von ORDER BY
verwenden, obwohl
es mithilfe der Indizes Datensätze findet, die der
WHERE
-Klausel entsprechen. Dies betrifft
u. a. die folgenden Fälle:
Sie verwenden ORDER BY
für verschiedene
Schlüssel:
SELECT * FROM t1 ORDER BYkey1
,key2
;
Sie verwenden ORDER BY
für Teile eines
Schlüssels, die nicht aufeinander folgen:
SELECT * FROM t1 WHEREkey2
=constant
ORDER BYkey_part2
;
Sie verwenden ASC
und
DESC
gemischt:
SELECT * FROM t1 ORDER BYkey_part1
DESC,key_part2
ASC;
Der Schlüssel, der zum Holen der Datensätze verwendet
wird, ist nicht derselbe wie derjenige, der in der
ORDER BY
-Klausel verwendet wird:
SELECT * FROM t1 WHEREkey2
=constant
ORDER BYkey1
;
Sie verknüpfen zahlreiche Tabellen, und die Spalten in der
ORDER BY
-Klausel stammen nicht alle aus
der ersten nichtkonstanten Tabelle, die zum Abrufen von
Datensätzen verwendet wird. (Dies ist die erste Tabelle in
der Ausgabe von EXPLAIN
, die nicht den
Join-Typ const
aufweist.)
Sie haben verschiedene ORDER BY
- und
GROUP BY
-Ausdrücke.
Der Typ des verwendeten Tabellenindexes speichert die
Datensätze nicht in ihrer Reihenfolge. Dies gilt
beispielsweise für einen HASH
-Index in
einer MEMORY
-Tabelle.
Mit EXPLAIN SELECT … ORDER BY
können
Sie überprüfen, ob MySQL Indizes zur Auflösung der Abfrage
verwenden kann. Wenn Sie Using filesort
in
der Spalte Extra
sehen, ist dies nicht
möglich. Siehe auch Abschnitt 7.2.1, „EXPLAIN
-Syntax (Informationen über ein
SELECT
erhalten)“.
Die verwendete filesort
-Optimierung vermerkt
nicht nur den Sortierschlüsselwert und die Datensatzposition,
sondern auch die Spalten, die für die Abfrage erforderlich
sind. Hiermit wird verhindert, dass Datensätze zweimal
ausgelesen werden. Der filesort
-Algorithmus
funktioniert wie folgt:
Die Datensätze, die der WHERE
-Klausel
entsprechen, werden gelesen.
Für jeden Datensatz wird ein Tupel mit Werten aufgezeichnet, die den Sortierschlüsselwert und die Datensatzposition sowie die Spalten umfassen, die für die Abfrage erforderlich sind.
Die Tupel werden nach dem Sortierschlüsselwert sortiert.
Die Datensätze werden in der sortierten Reihenfolge abgerufen, aber die erforderlichen Spalten werden direkt aus den sortierten Tupeln ausgelesen, statt ein zweites Mal auf die Tabelle zuzugreifen.
Dieser Algorithmus stellt gegenüber dem in älteren MySQL-Versionen verwendeten eine erhebliche Verbesserung dar.
Um eine Verlangsamung zu vermeiden, wird diese Optimierung nur
verwendet, wenn die Gesamtgröße der zusätzlichen Spalten im
Sortiertupel den Wert der Systemvariablen
max_length_for_sort_data
nicht
überschreitet. (Wenn Sie dieser Variablen einen zu hohen Wert
zuweisen, treten typische Symptome wie eine hohe Festplatten-
und eine niedrige Prozessoraktivität auf.)
Wenn Sie die Geschwindigkeit von ORDER BY
erhöhen wollen, überprüfen Sie, ob Sie MySQL dazu bewegen
können, Indizes statt einer zusätzlichen Sortierphase zu
verwenden. Ist dies nicht möglich, dann können Sie die
folgenden Strategien ausprobieren:
Sie erhöhen den Wert der Variablen
sort_buffer_size
.
Sie erhöhen den Wert der Variablen
read_rnd_buffer_size
.
Sie ändern tmpdir
so, dass die Variable
auf ein dediziertes Dateisystem mit viel freiem Speicher
weist. Die Option akzeptiert mehrere Pfade, die zyklisch
abwechselnd verwendet werden. Die Pfade sollten unter Unix
mit Doppelpunkten (‘:
’) und
unter Windows, NetWare und OS/2 mit Semikola
(‘;
’) voneinander getrennt
werden. Mithilfe dieser Funktion können Sie die Last auf
mehrere Verzeichnisse verteilen.
Hinweis: Die Pfade sollten auf
Verzeichnisse in Dateisystemen verweisen, die sich auf
verschiedenen physischen Festplatten
befinden – nicht auf verschiedenen Partitionen derselben
Festplatte.
Standardmäßig sortiert MySQL alle GROUP BY
-Abfragen so,
als ob Sie in der Abfrage auch col1
,
col2
, …ORDER BY
angegeben
hätten. Wenn Sie ausdrücklich eine col1
,
col2
, …ORDER
BY
-Klausel angeben, die dieselbe Spaltenliste
enthält, optimiert MySQL diese ohne Geschwindigkeitseinbuße
weg, auch wenn die Sortierung tatsächlich stattfindet. Enthält
eine Abfrage eine GROUP BY
-Klausel, während
Sie die Mehrbelastung durch die Sortierung des Ergebnisses
vermeiden wollen, dann können Sie diese Sortierung durch Angabe
von ORDER BY NULL
unterdrücken. Zum
Beispiel:
INSERT INTO foo SELECT a, COUNT(*) FROM bar GROUP BY a ORDER BY NULL;
Die allgemeinste Art und Weise, eine GROUP
BY
-Klausel zu erfüllen, besteht darin, die gesamte
Tabelle zu scannen und eine neue Temporärtabelle zu erstellen,
in der alle Datensätze aus allen Gruppen aufeinander folgend
aufgeführt sind, und dann mithilfe dieser Temporärtabelle
Gruppen zu erkennen und – sofern möglich –
Zusammenfassungsfunktionen anzuwenden. In manchen Fällen kann
MySQL jedoch auf andere Weise wesentlich effizienter vorgehen
und die Erstellung von Temporärtabellen umgehen, indem ein
Indexzugriff verwendet wird.
Die wichtigsten Voraussetzungen zur Verwendung von Indizes für
GROUP BY
bestehen darin, dass alle
GROUP BY
-Spalten Attribute aus demselben
Index referenzieren und dass der Index seine Schlüssel in der
Reihenfolge speichert (beispielsweise ist dies ein
BTREE
- und kein
HASH
-Index). Ob die Verwendung von
Temporärtabellen durch einen Indexzugriff ersetzt werden kann,
hängt auch davon ab, welche Teile eines Indexes in einer
Abfrage verwendet werden, welche Bedingungen für diese Teile
spezifiziert sind und welche Zusammenfassungsfunktionen
ausgewählt wurden.
Es gibt zwei Möglichkeiten, eine GROUP
BY
-Abfrage über den Indexzugriff auszuführen; sie
beide werden in den folgenden Abschnitten beschrieben. Bei der
ersten Methode wird die Gruppierungsoperation ggf. gemeinsam mit
allen Bereichsprädikaten angewandt. Die zweite Methode führt
zunächst einen Bereichsscan durch und gruppiert dann die
Ergebnistupel.
Die effizienteste Möglichkeit, GROUP BY
zu
verarbeiten, besteht in der Verwendung des Indexes zum
direkten Abrufen der Gruppenfelder. Bei dieser Zugriffsmethode
verwendet MySQL die Eigenschaft einiger Indextypen, dass die
Schlüssel sortiert sind (z. B. BTREE
).
Diese Eigenschaft erlaubt die Verwendung von
Suchvorgangsgruppen in einem Index, ohne dass alle Schlüssel
im Index berücksichtigt werden müssten, die die
WHERE
-Bedingungen erfüllen. Diese
Zugriffsmethode berücksichtigt also nur einen Bruchteil der
Schlüssel in einem Index und heißt deswegen
lockerer Indexscan. Wenn keine
WHERE
-Klausel vorhanden ist, liest ein
lockerer Indexscan so viele Schlüssel, wie Gruppen vorhanden
sind. Diese Anzahl kann bedeutend kleiner sein als die aller
Schlüssel. Wenn die WHERE
-Klausel
Bereichsprädikate enthält (siehe auch die Beschreibung des
Join-Typs range
in
Abschnitt 7.2.1, „EXPLAIN
-Syntax (Informationen über ein
SELECT
erhalten)“), dann sucht ein lockerer Indexscan
nach dem jeweils ersten Schlüssel aller Gruppen, die die
Bereichsbedingungen erfüllen, und liest dann erneut die
kleinstmögliche Anzahl Schlüssel aus. Dies ist unter den
folgenden Bedingungen möglich:
Die Abfrage gilt einer einzelnen Tabelle.
Die GROUP BY
-Klausel enthält die
ersten aufeinander folgenden Teile des Indexes. (Wenn die
Abfrage statt einer GROUP BY
- eine
DISTINCT
-Klausel enthält,
referenzieren alle den Anfang des Indexes.)
Wenn überhaupt, so werden als einzige
Zusammenfassungsfunktionen MIN()
und
MAX()
verwendet, die zudem alle
dieselbe Spalte referenzieren.
Alle Teile des Indexes, die nicht aus der in der Abfrage
referenzierten GROUP BY
-Klausel
stammen, müssen Konstanten sein (d. h., sie müssen in
Gleichungen mit Konstanten referenziert werden).
Ausgenommen ist lediglich das Argument der Funktionen
MIN()
und MAX()
.
Die EXPLAIN
-Ausgabe für solche Abfragen
zeigt Using index for group-by
in der
Spalte Extra
an.
Die folgenden Abfragen gehören in diese Kategorie,
vorausgesetzt, ein Index idx(c1,c2,c3)
ist
für die Tabelle t1(c1,c2,c3,c4)
vorhanden:
SELECT c1, c2 FROM t1 GROUP BY c1, c2; SELECT DISTINCT c1, c2 FROM t1; SELECT c1, MIN(c2) FROM t1 GROUP BY c1; SELECT c1, c2 FROM t1 WHERE c1 <const
GROUP BY c1, c2; SELECT MAX(c3), MIN(c3), c1, c2 FROM t1 WHERE c2 >const
GROUP BY c1, c2; SELECT c2 FROM t1 WHERE c1 <const
GROUP BY c1, c2; SELECT c1, c2 FROM t1 WHERE c3 =const
GROUP BY c1, c2;
Die folgenden Abfragen können aus den angegebenen Gründen nicht mit dieser schnellen Auswahlmethode ausgeführt werden:
Es sind andere Zusammenfassungsfunktionen als
MIN()
oder MAX()
vorhanden, z. B.:
SELECT c1, SUM(c2) FROM t1 GROUP BY c1;
Die Felder in der GROUP BY
-Klausel
referenzieren nicht den Anfang des Indexes:
SELECT c1,c2 FROM t1 GROUP BY c2, c3;
Die Abfrage referenziert einen Teil eines Schlüssels, der
nach dem GROUP BY
-Teil kommt und für
den keine Gleichzeit mit einer Konstante vorliegt. Ein
Beispiel:
SELECT c1,c3 FROM t1 GROUP BY c1, c2;
Ein enggefasster Indexscan kann je nach Abfragebedingung entweder ein vollständiger Indexscan oder ein Bereichsindexscan sein.
Wenn die Bedingungen für einen lockeren Indexscan nicht
erfüllt werden, ist es trotzdem möglich, die Erstellung von
Temporärtabellen für GROUP BY
-Abfragen zu
umgehen. Wenn in der WHERE
-Klausel
Bereichsbedingungen vorhanden sind, liest diese Methode nur
die Schlüssel aus, die diese Bedingungen erfüllen.
Andernfalls wird ein Indexscan durchgeführt. Da diese Methode
alle Schlüssel in jedem von der
WHERE
-Klausel definierten Bereich liest
oder den gesamten Index scannt, sofern keine
Bereichsbedingungen vorhanden sind, sprechen wir hier vom
enggefassten Indexscan. Beachten Sie,
dass die Gruppierungsoperation beim enggefassten Indexscan
erst durchgeführt wird, wenn alle Schlüssel gefunden wurden,
die die Bereichsbedingungen erfüllen.
Damit diese Methode funktioniert, ist eine
Konstantengleichheitsbedingung für alle Spalten in einer
Abfrage ausreichend, wenn diese Abfrage die Schlüssel
referenziert, die vor oder zwischen den Teilen des
GROUP BY
-Schlüssels auftreten. Die
Konstanten aus den Gleichheitsbedingungen füllen alle
„Lücken“ in den Suchschlüsseln auf, sodass es
möglich ist, vollständige Präfixe des Indexes zu bilden.
Diese Indexpräfixe können dann für Indexsuchvorgänge
verwendet werden. Wenn Sie die Sortierung des GROUP
BY
-Ergebnisses benötigen und es möglich ist,
Suchschlüssel zu bilden, die Präfixe des Indexes sind, dann
vermeidet MySQL außerdem zusätzliche Sortieroperationen,
weil das Suchen mit Präfixen in einem sortierten Index
bereits alle Schlüssel in der korrekten Reihenfolge abruft.
Die folgenden Abfragen funktionieren beim oben beschriebenen
lockeren Indexscan nicht, wohl allerdings beim enggefassten
Indexscan (sofern ein Index idx(c1,c2,c3)
für die Tabelle t1(c1,c2,c3,c4)
vorhanden
ist).
In der GROUP BY
-Klausel ist zwar eine
Lücke vorhanden, aber diese wird von der Bedingung
c2 = 'a'
abgedeckt.
SELECT c1, c2, c3 FROM t1 WHERE c2 = 'a' GROUP BY c1, c3;
GROUP BY
beginnt nicht mit dem ersten
Teil des Schlüssels, aber es ist eine Bedingung
vorhanden, die eine Konstante für diesen Teil angibt:
SELECT c1, c2, c3 FROM t1 WHERE c1 = 'a' GROUP BY c2, c3;
In manchen Fällen verarbeitet MySQL eine Abfrage anders, wenn
Sie LIMIT
verwenden und
row_count
HAVING
nicht einsetzen:
Wenn Sie nur ein paar Datensätze mit
LIMIT
auswählen, benutzt MySQL in
manchen Fällen Indizes, obwohl eigentlich ein
vollständiger Tabellenscan zu bevorzugen wäre.
Wenn Sie LIMIT
mit
row_count
ORDER BY
benutzen, beendet MySQL die
Sortierung, sobald die ersten
row_count
Datensätze des
sortierten Ergebnisses gefunden wurden, statt das gesamte
Ergebnis zu sortieren. Erfolgt die Sortierung mithilfe eines
Indexes, dann ist sie sehr schnell. Ist eine Dateisortierung
erforderlich, dann müssen alle Datensätze ausgewählt
werden, die der Abfrage ohne
LIMIT
-Klausel entsprechen, und die
meisten davon (oder alle) müssen sortiert werden, bevor
sichergestellt ist, dass die ersten
row_count
Datensätze gefunden
wurden. In jedem Fall ist es, wenn die ersten Datensätze
gefunden wurden, nicht mehr notwendig, den Rest der
Ergebnismenge zu sortieren, weswegen MySQL dies auch nicht
tut.
Wenn Sie LIMIT
mit
row_count
DISTINCT
kombinieren, beendet MySQL die
Abfrage, sobald row_count
eindeutige Datensätze gefunden wurden.
In manchen Fällen kann eine GROUP
BY
-Klausel durch Lesen des Schlüssels in der
Reihenfolge (oder Durchführung einer Sortierung für den
Schlüssel) und nachfolgende Berechnung von
Zusammenfassungen aufgelöst werden, bis der Schlüsselwert
sich ändert. In diesem Fall berechnet LIMIT
keine
unnötigen row_count
GROUP BY
-Werte.
Sobald MySQL die erforderliche Anzahl von Datensätzen an
den Client gesendet hat, bricht es die Abfrage ab, sofern
Sie nicht SQL_CALC_FOUND_ROWS
verwenden.
LIMIT 0
gibt schnell eine leere Menge
zurück. Dies kann praktisch sein, um die Gültigkeit einer
Abfrage zu überprüfen. Wenn Sie eines der MySQL-APIs
verwenden, können Sie damit auch die Typen der
Ergebnisspalten ermitteln. (Dieser Trick funktioniert nicht
im MySQL Monitor, der in solchen Fällen lediglich
Empty set
anzeigt. Stattdessen sollten
Sie SHOW COLUMNS
oder
DESCRIBE
für diesen Zweck verwenden.)
Wenn der Server Temporärtabellen zur Auflösung der Abfrage
verwendet, dann berechnet er auf der Basis der
LIMIT
-Klausel, wie
viel Speicher erforderlich ist.
row_count
Die Ausgabe von EXPLAIN
zeigt
ALL
in der type
-Spalte,
wenn MySQL die Abfrage unter Verwendung eines Tabellenscans
auflöst. Dies geschieht in der Regel unter den folgenden
Bedingungen:
Die Tabelle ist so klein, dass ein Tabellenscan schneller ist als eine Schlüsselsuche. Dies betrifft in erster Linie Tabellen mit weniger als zehn Datensätzen und geringer Datensatzlänge.
In der ON
- oder
WHERE
-Klausel für indizierte Spalten
sind keine verwendbaren Einschränkungen vorhanden.
Sie vergleichen indizierte Spalten mit Konstantenwerten, und
MySQL hat (basierend auf dem Indexbaum) berechnet, dass die
Konstanten einen zu großen Teil der Tabelle abdecken und
ein Tabellenscan schneller ginge. Siehe auch
Abschnitt 7.2.4, „Optimierungen der WHERE
-Klausel“.
Sie verwenden einen Schlüssel mit niedriger Kardinalität (d. h., viele Datensätze entsprechen dem Schlüsselwert) über eine andere Spalte. In diesem Fall geht MySQL davon aus, dass die Verwendung des Schlüssels viele Suchvorgänge nach sich ziehen würde und ein Tabellenscan schneller ginge.
Bei kleinen Tabellen ist ein Tabellenscan oft die passende Lösung. Die Auswirkungen auf die Leistung sind vernachlässigbar. Bei großen Tabellen sollten Sie die folgenden Methoden ausprobieren, damit der Optimierer sich nicht fälschlicherweise für einen Tabellenscan entscheidet:
Aktualisieren Sie die Schlüsselverteilung in der gescannten
Tabelle mit ANALYZE TABLE
. Siehe auch
Abschnitt 13.5.2.1, „tbl_name
ANALYZE TABLE
“.
Verwenden Sie FORCE INDEX
für die
gescannte Tabelle, um MySQL mitzuteilen, dass Tabellenscans
im Vergleich zur Verwendung des angegebenen Indexes sehr
kostspielig sind:
SELECT * FROM t1, t2 FORCE INDEX (index_for_column
) WHERE t1.col_name
=t2.col_name
;
Siehe auch Abschnitt 13.2.7, „SELECT
“.
Starten Sie mysqld mit der Option
--max-seeks-for-key=1000
, oder weisen Sie
den Optimierer mit SET
max_seeks_for_key=1000
an, vorauszusetzen, dass
kein Schlüsselscan mehr als 1000 Schlüsselsuchvorgänge
auslösen wird. Siehe auch
Abschnitt 5.2.2, „Server-Systemvariablen“.
Die Zeit, die für das Einfügen eines Datensatzes erforderlich ist, wird von den folgenden Faktoren bestimmt (hierbei geben die Zahlen in den Klammern näherungsweise den Anteil an):
Verbindung herstellen: (3)
Abfrage an den Server senden: (2)
Abfrage analysieren: (2)
Datensatz einfügen: (1 × Datensatzlänge)
Indizes einfügen: (1 × Anzahl der Indizes)
Schließen: (1)
Hierbei wird der Mehraufwand für das Öffnen von Tabellen nicht berücksichtigt (dies ist einmal je nebenläufiger Abfrageausführung erforderlich).
Die Größe der Tabelle verlangsamt das Einfügen von Indizes um
den Faktor LogN
(für
B-Tree-Indizes).
Sie können Einfügeoperationen mit den folgenden Methoden beschleunigen:
Wenn Sie gleichzeitig viele Datensätze vom selben Client
aus einfügen, verwenden Sie
INSERT
-Anweisungen mit mehreren
VALUES
-Listen, um mehrere Datensätze zur
selben Zeit einzufügen. Dies ist erheblich (in manchen
Fällen sogar um mehrere Größenordnungen) schneller als
die Verwendung separater
INSERT
-Anweisungen für je einen
Datensatz. Wenn Sie zu einer Tabelle, die nicht leer ist,
Daten hinzufügen, dann können Sie die Variable
bulk_insert_buffer_size
optimieren, um
das Einfügen noch mehr zu beschleunigen. Siehe auch
Abschnitt 5.2.2, „Server-Systemvariablen“.
Wenn Sie eine große Menge Datensätze von verschiedenen
Clients einfügen, können Sie den Vorgang durch Verwendung
der INSERT DELAYED
-Anweisung
beschleunigen. Siehe auch Abschnitt 13.2.4.2, „INSERT DELAYED
“.
Bei einer MyISAM
-Tabelle können Sie
nebenläufige Einfügeoperationen verwenden, um Datensätze
einzufügen, während gleichzeitig
SELECT
-Anweisungen ausgeführt werden,
sofern sich in der Mitte der Tabelle keine gelöschten
Datensätze befinden. Siehe auch
Abschnitt 7.3.3, „Gleichzeitige Einfügevorgänge“.
Wenn Sie eine Tabelle aus einer Textdatei laden, verwenden
Sie LOAD DATA INFILE
. Dies ist
normalerweise 20-mal schneller als die Verwendung von
INSERT
-Anweisungen. Siehe auch
Abschnitt 13.2.5, „LOAD DATA INFILE
“.
Durch geringen Mehraufwand können Sie LOAD DATA
INFILE
für eine MyISAM
-Tabelle
noch schneller machen, wenn diese Tabelle viele Indizes
enthält. Gehen Sie wie folgt vor:
Erstellen Sie die Tabelle mit CREATE
TABLE
(optional).
Führen Sie eine FLUSH
TABLES
-Anweisung oder den Befehl
mysqladmin flush-tables aus.
Setzen Sie myisamchk --keys-used=0 -rq
/path/to/db/tbl_name
ab. Hierdurch wird die Verwendung aller Indizes für die
Tabelle unterbunden.
Fügen Sie mit LOAD DATA INFILE
Daten
in die Tabelle ein. Hierbei werden keine Indizes
aktualisiert – der Vorgang ist also sehr schnell.
Wenn Sie zukünftig nur aus der Tabelle lesen wollen, komprimieren Sie sie mit myisampack. Siehe auch Abschnitt 14.1.3.3, „Kennzeichen komprimierter Tabellen“.
Erstellen Sie die Indizes mit myisamchk -rq
/path/to/db/tbl_name
neu. Hierdurch wird der Indexbaum zunächst im Speicher
erstellt, bevor er auf die Festplatte geschrieben wird.
Dies ist viel schneller als die Aktualisierung des
Indexes im Zuge von LOAD DATA INFILE
,
da zahlreiche Suchvorgänge auf der Festplatte
entfallen. Außerdem ist der resultierende Indexbaum
einwandfrei verteilt.
Führen Sie eine FLUSH
TABLES
-Anweisung oder den Befehl
mysqladmin flush-tables aus.
Beachten Sie, dass LOAD DATA INFILE
obige
Optimierung automatisch durchführt, wenn die
MyISAM
-Tabelle, in die Sie die Daten
einfügen, leer ist. Der wesentliche Unterschied besteht
darin, dass Sie myisamchk wesentlich mehr
Temporärspeicher für die Indexerstellung zuweisen können,
als Sie durch den Server zur Indexneuerstellung reservieren
lassen würden, wenn er die LOAD DATA
INFILE
-Anweisung ausführt.
Sie können die Indizes für eine
MyISAM
-Tabelle ferner aktivieren oder
deaktivieren, indem Sie statt myisamchk
die folgenden Anweisungen verwenden. Bei Verwendung dieser
Anweisungen können Sie die FLUSH
TABLE
-Operationen übergehen:
ALTER TABLEtbl_name
DISABLE KEYS; ALTER TABLEtbl_name
ENABLE KEYS;
Um INSERT
-Operationen zu beschleunigen,
die mit mehreren Anweisungen durchgeführt werden, sperren
Sie Ihre Tabellen:
LOCK TABLES a WRITE; INSERT INTO a VALUES (1,23),(2,34),(4,33); INSERT INTO a VALUES (8,26),(6,29); UNLOCK TABLES;
Hiervon profitiert die Leistungsfähigkeit, weil der
Indexpuffer nur einmal auf die Festplatte synchronisiert
wird, nachdem alle INSERT
-Anweisungen
abgeschlossen wurden. Im Normalfall gäbe es so viele
Synchronisierungsvorgänge für Indexpuffer, wie
INSERT
-Anweisungen vorhanden sind.
Explizite Sperranweisungen sind nicht erforderlich, wenn Sie
alle Datensätze mit einer einzelnen
INSERT
-Anweisung einfügen können.
Bei transaktionssicheren Tabellen sollten Sie START
TRANSACTION
und COMMIT
statt
LOCK TABLES
benutzen, um die
Einfügeoperationen zu beschleunigen.
Eine Sperrung verringert auch die Gesamtdauer für die Überprüfung mehrerer Verbindungen, auch wenn sich die Gesamtwartezeit für einzelne Verbindungen erhöhen kann, weil diese auf das Erwirken der Sperren warten. Zum Beispiel:
Verbindung 1 führt 1.000 Einfügeoperationen durch.
Die Verbindungen 2, 3 und 4 fügen je eine Einfügeoperation durch.
Verbindung 5 führt 1.000 Einfügeoperationen durch.
Wenn Sie keine Sperrung verwenden, werden die Verbindungen 2, 3 und 4 vor den Verbindungen 1 und 5 beendet; setzen Sie hingegen eine Sperre, dann werden die Verbindungen 2, 3 und 4 zwar (wahrscheinlich) nicht eher als die Verbindungen 1 und 5 enden, aber der gesamte Zeitbedarf verringert sich um ca. 40 Prozent.
INSERT
-, UPDATE
- und
DELETE
-Operationen sind in MySQL sehr
schnell, aber Sie können eine noch bessere
Gesamtperformance erzielen, indem Sie Sperren für alles
setzen, was mehr als fünf Einfüge- oder
Änderungsoperationen in einem Datensatz umfasst. Wenn Sie
sehr viele Einfügeoperationen in einem Datensatz vornehmen,
könnten Sie ab und zu (d. h. etwa alle 1.000 Datensätze)
ein LOCK TABLES
gefolgt von einem
UNLOCK TABLES
absetzen, damit auch andere
Threads auf die Tabelle zugreifen können. Dies bringt trotz
allem einen ansehnlichen Leistungsgewinn.
Auch wenn Sie die soeben beschriebenen Strategien verwenden,
ist INSERT
beim Laden von Daten
allerdings nach wie vor wesentlich langsamer als
LOAD DATA INFILE
.
Um die Leistung bei MyISAM
-Tabellen für
LOAD DATA INFILE
und
INSERT
gleichermaßen zu optimieren,
vergrößern Sie den Schlüssel-Cache, indem Sie den Wert
der Systemvariablen key_buffer_size
erhöhen. Siehe auch Abschnitt 7.5.2, „Serverparameter feineinstellen“.
Eine Änderungsanweisung wird wie eine
SELECT
-Abfrage optimiert, es kommt jedoch der
zusätzliche Mehraufwand einer Schreiboperation hinzu. Die
Geschwindigkeit der Schreiboperation hängt von der Menge der zu
ändernden Daten und der Anzahl der zu aktualisierenden Indizes
ab. Indizes, die nicht geändert werden, werden nicht
aktualisiert.
Eine andere Möglichkeit, Updates zu beschleunigen, besteht darin, sie aufzuschieben und dann viele Updates direkt hintereinander durchzuführen. Wenn Sie die Tabelle sperren, ist die gemeinsame Durchführung vieler Änderungen wesentlich schneller, als wenn Sie immer nur ein Update zur selben Zeit durchführen.
Bei einer MyISAM
-Tabelle, die das dynamische
Datensatzformat verwendet, kann die Änderung eines Datensatzes
auf eine höhere Gesamtlänge dazu führen, dass der Datensatz
geteilt wird. Wenn Sie dies oft tun, dürfen Sie keinesfalls
vergessen, gelegentlich OPTIMIZE TABLE
abzusetzen. Siehe auch Abschnitt 13.5.2.5, „OPTIMIZE TABLE
“.
Die zum Löschen einzelner Datensätze erforderliche Zeit ist
direkt proportional zur Anzahl der Indizes. Um Datensätze
schneller zu löschen, können Sie den Wert des
Schlüssel-Caches erhöhen, indem Sie die Systemvariable
key_buffer_size
entsprechend einstellen.
Siehe auch Abschnitt 7.5.2, „Serverparameter feineinstellen“.
Wenn Sie alle Datensätze aus einer Tabelle löschen wollen, ist
TRUNCATE TABLE
schneller als
tbl_name
DELETE FROM
. Siehe auch
Abschnitt 13.2.9, „tbl_name
TRUNCATE
“.
Dieser Abschnitt listet eine Anzahl verschiedener Tipps zur Verbesserung der Abfrageverarbeitungsgeschwindigkeit auf:
Verwenden Sie permanente Verbindungen zur Datenbank, um die
zusätzliche Belastung durch das Herstellen und Abbauen von
Verbindungen zu umgehen. Können Sie keine
Permanentverbindungen verwenden und stellen Sie viele neue
Verbindungen zur Datenbank her, dann sollten Sie den Wert
der Variablen thread_cache_size
ändern.
Siehe auch Abschnitt 7.5.2, „Serverparameter feineinstellen“.
Überprüfen Sie immer, ob alle Ihre Abfragen wirklich die
Indizes verwenden, die Sie in den Tabellen erstellt haben.
In MySQL können Sie dies mit der
EXPLAIN
-Anweisung tun. Siehe auch
Abschnitt 7.2.1, „EXPLAIN
-Syntax (Informationen über ein
SELECT
erhalten)“.
Versuchen Sie komplexe SELECT
-Abfragen an
häufig aktualisierte MyISAM
-Tabellen zu
umgehen, um Probleme in Verbindung mit der Tabellensperrung
zu vermeiden, die aufgrund des konkurrierenden Zugriffs
durch Leser und Schreiber entstehen.
Bei MyISAM
-Tabellen, bei denen in der
Mitte keine gelöschten Datensätze vorhanden sind, können
Sie Datensätze am Ende einfügen, während gleichzeitig
eine andere Abfrage aus der Tabelle liest. Wenn ein solches
Verhalten wichtig ist, sollten Sie die Tabelle so verwenden,
dass möglichst keine Datensätze gelöscht werden. Eine
andere Möglichkeit besteht darin, die Tabelle mit
OPTIMIZE TABLE
zu defragmentieren, wenn
Sie viele Datensätze gelöscht haben. Siehe auch
Abschnitt 14.1, „Die MyISAM
-Speicher-Engine“.
Um komprimierungsbedingte Probleme zu beheben, die im
Zusammenhang mit ARCHIVE
-Tabellen
auftreten können, können Sie OPTIMIZE
TABLE
verwenden. Siehe auch
Abschnitt 14.8, „Die ARCHIVE
-Speicher-Engine“.
Verwenden Sie ALTER TABLE … ORDER BY
, wenn
Sie Datensätze gewöhnlich in der Reihenfolge
expr1
,
expr2
, …
abrufen. Wenn Sie diese Option nach umfangreicheren
Änderungen in der Tabelle verwenden, können Sie die
Leistung unter Umständen steigern.
expr1
,
expr2
, …
In manchen Fällen kann es sinnvoll sein, eine Spalte hinzuzufügen, die auf den Daten in anderen Spalten basierende „Hash-Werte“ enthält. Wenn diese Spalte kurz und ausreichend eindeutig ist, kann dies wesentlich schneller sein als ein „breiter“ Index über viele Spalten. In MySQL ist die Verwendung dieser Zusatzspalte ganz einfach:
SELECT * FROMtbl_name
WHEREhash_col
=MD5(CONCAT(col1
,col2
)) ANDcol1
='constant
' ANDcol2
='constant
';
Bei MyISAM
-Tabellen, die sich häufig
verändern, sollten Sie die Verwendung von Spalten variabler
Länge (VARCHAR
, BLOB
und TEXT
) möglichst unterlassen. Die
Tabelle verwendet das dynamische Datensatzformat, sobald
auch nur eine einzige Spalte variabler Länge vorhanden ist.
Siehe auch Kapitel 14, Speicher-Engines und Tabellentypen.
Es ist normalerweise nicht sinnvoll, eine Tabelle in mehrere
getrennte Tabellen zu unterteilen, weil die Datensätze dann
sehr groß werden. Beim Zugriff auf einen Datensatz besteht
die größte Anforderung aus leistungstechnischer Sicht im
Suchvorgang, der auf der Festplatte ausgeführt wird, um das
erste Byte des Datensatzes zu finden. Wurde der Beginn der
Daten gefunden, dann können die meisten modernen
Festplatten den vollständigen Datensatz für die meisten
Anwendungen ausreichend schnell lesen. Die einzigen Fälle,
in denen das Aufteilen einer Tabelle einen nennenswerten
Unterschied macht, liegen vor, wenn es sich um eine
MyISAM
-Tabelle handelt, die das
dynamische Datensatzformat verwendet, welches Sie in eine
feste Datensatzgröße umwandeln können, oder wenn Sie die
Tabelle sehr häufig scannen müssen, die meisten Spalten
aber nicht benötigen. Siehe auch
Kapitel 14, Speicher-Engines und Tabellentypen.
Müssen Sie häufig Ergebnisse wie beispielsweise Summenwerte basierend auf Daten aus einer Vielzahl von Datensätzen berechnen, dann kann es praktisch sein, eine neue Tabelle einzurichten und den Zähler in Echtzeit zu aktualisieren. Eine Änderung der folgenden Form ist sehr schnell:
UPDATEtbl_name
SETcount_col
=count_col
+1 WHEREkey_col
=constant
;
Dies ist sehr wichtig, wenn Sie MySQL-Speicher-Engines wie
MyISAM
verwenden, die nur Sperren auf
Tabellenebene bieten (d. h. mehrere Leser bei einem
Schreiber). Dies bietet auch bei den meisten anderen
Datenbanksystemen eine bessere Performance, da der
Datensatzsperrmanager in diesem Fall weniger zu tun hat.
Wenn Sie Statistiken aus großen Logtabellen ermitteln müssen, sollten Sie Zusammenfassungstabellen verwenden, statt die gesamte Logtabelle zu scannen. Die Erstellung der Zusammenfassungen sollte wesentlich schneller sein als die Berechnung von „Echtzeitstatistiken“. Die Neuerstellung von Übersichtstabellen aus den Logs ist, wenn sich (abhängig von Geschäftsentscheidungen) Faktoren ändern, schneller als eine Anpassung der laufenden Anwendung.
Sofern möglich, sollten Sie Berichte als „Echtzeitberichte“ oder als „statistische Berichte“ klassifizieren, wobei die für die statistischen Berichte erforderlichen Daten nur aus Zusammenfassungstabellen erzeugt werden, die ihrerseits in regelmäßigen Abständen aus den Echtzeitdaten erstellt werden.
Nutzen Sie die Tatsache, dass Spalten Standardwerte haben. Fügen Sie Werte nur dann explizit ein, wenn sich der einzufügende Wert von der Vorgabe unterscheidet. Hierdurch verringern Sie die Analysearbeit für MySQL und erhöhen die Einfügegeschwindigkeit.
In manchen Fällen ist es sinnvoll, Daten zu packen und in
einer BLOB
-Spalte zu speichern. In diesem
Fall muss Ihre Anwendung zwar Code zum Packen und Entpacken
der Daten enthalten, aber Sie sparen sich auf einer gewissen
Ebene viele Zugriffe. Dies ist praktisch, wenn Sie Daten
haben, die sich nicht gut in die zeilen- und spaltenbasierte
Struktur einer Tabelle einfügen lassen.
Normalerweise sollten Sie alle Daten nichtredundant halten. (Beachten Sie dabei die in der Datenbanktheorie so genannte Dritte Normalform.) Allerdings gibt es auch Situationen, in denen die Duplizierung von Daten oder die Erstellung zusammenfassender Tabellen zur Geschwindigkeitssteigerung beitragen können.
Bei einigen Aufgaben können etwa gespeicherte Routinen oder benutzerdefinierte Funktionen Optionen zur Optimierung der Leistung sein. Weitere Informationen finden Sie in Kapitel 19, Gespeicherte Prozeduren und Funktionen, und Abschnitt 26.3, „Hinzufügen neuer Funktionen zu MySQL“.
Sie können immer einen kleinen Geschwindigkeitsvorteil gewinnen, indem Sie Abfragen oder Antworten in Ihrer Anwendung in einem Cache ablegen und dann zahlreiche Einfüge- oder Aktualisierungsvorgänge gemeinsam ausführen. Wenn Ihr Datenbanksystem Tabellensperren unterstützt (wie es beispielsweise bei MySQL und Oracle der Fall ist), dann sollten Sie so sicherstellen können, dass der Index-Cache nur einmal nach Durchführung aller Änderungen synchronisiert wird. Sie können auch vom Abfrage-Cache von MySQL profitieren, um ähnliche Ergebnisse zu erhalten (siehe auch Abschnitt 5.14, „MySQL-Anfragen-Cache“).
Verwenden Sie INSERT DELAYED
, wenn Sie
nicht unbedingt wissen müssen, wann Ihre Daten geschrieben
werden. Dies verringert die Gesamtauswirkungen von
Einfügeoperationen, weil zahlreiche Datensätze im Zuge
eines einzigen Schreibvorgangs auf die Festplatte
geschrieben werden.
Verwenden Sie INSERT LOW_PRIORITY
, wenn
Sie SELECT
-Anweisungen Vorrang vor den
Einfügeoperationen gewähren wollen.
Verwenden Sie SELECT HIGH_PRIORITY
, um
abgerufene Datensätze in der Warteschlange nach vorne zu
setzen: In diesem Fall wird die
SELECT
-Anweisung auch ausgeführt, wenn
ein anderer Client darauf wartet, schreiben zu können.
Verwenden Sie INSERT
-Anweisungen für
mehrere Datensätze, um zahlreiche Daten mit einer
SQL-Anweisung zu speichern. Dies wird von vielen SQL-Servern
(einschließlich MySQL) unterstützt.
Laden Sie mit LOAD DATA INFILE
große
Datenmengen. Dies ist schneller als die Verwendung von
INSERT
-Anweisungen.
Erzeugen Sie mit AUTO_INCREMENT
eindeutige Werte.
Verwenden Sie hin und wieder OPTIMIZE
TABLE
, um eine Fragmentierung von
MyISAM
-Tabellen mit dynamischem
Datensatzformat zu verhindern. Siehe auch
Abschnitt 14.1.3, „MyISAM-Tabellenformate“.
Verwenden Sie, sofern möglich,
MEMORY
-Tabellen, um die Geschwindigkeit
zu erhöhen. Siehe auch
Abschnitt 14.4, „Die MEMORY
-Speicher-Engine“.
MEMORY
-Tabellen sind für nichtkritische
Daten nützlich, auf die häufig zugegriffen wird, also etwa
Informationen zum zuletzt angezeigten Werbebanner für
Benutzer, in deren Webbrowser Cookies nicht aktiviert sind.
In vielen Webanwendungen stellen Benutzersitzungen eine
andere Alternative für den Umgang mit flüchtigen
Statusdaten dar.
Bei Webservern sollten Bilder und andere Binärressourcen normalerweise als Dateien gespeichert werden: In der Datenbank speichern Sie also statt der Datei selbst nur einen Verweis darauf. Die meisten Webserver können Dateien besser zwischenspeichern als Datenbankinhalte, weswegen die Verwendung von Dateien in der Regel schneller ist.
Spalten mit identischen Daten in verschiedenen Tabellen sollten mit identischen Datentypen deklariert werden, damit auf den entsprechenden Spalten basierende Joins beschleunigt werden.
Verwenden Sie möglichst einfache Spaltennamen. In einer
Tabelle namens customer
sollten Sie statt
einer Spalte customer_name
besser einfach
den Spaltennamen name
benutzen. Damit die
Namen auf andere SQL-Server portierbar sind, sollten Sie sie
stets kürzer als 18 Zeichen halten.
Wenn Geschwindigkeit für Sie ein absoluter Schlüsselaspekt
ist, sollten Sie einen Blick auf maschinennahe
Schnittstellen zur Datenspeicherung werfen, die von
verschiedenen SQL-Servern unterstützt werden. Indem Sie
beispielsweise direkt auf die
MyISAM
-Speicher-Engine von MySQL
zugreifen, können Sie die Geschwindigkeit im Vergleich zur
SQL-Schnittstelle um das Zwei- bis Fünffache erhöhen. Zu
diesem Zweck müssen die Daten auf demselben Server wie die
Anwendung liegen, und der Zugriff sollte möglichst nur von
einem Prozess aus erfolgen (da die externe Dateisperrung
wirklich langsam ist). Man könnte diese Probleme
beseitigen, indem man maschinennahe
MyISAM
-Befehle am MySQL Server
implementiert (dies wäre eine einfache Möglichkeit, bei
Bedarf mehr Leistung herauszuholen). Durch sorgfältiges
Design der Datenbankschnittstelle könnte es recht einfach
sein, diesen Optimierungstyp zu unterstützen.
Wenn Sie numerische Daten verwenden, ist es in vielen Fällen schneller, auf Daten in einer Datenbank (über eine laufende Verbindung) statt in einer Textdatei zuzugreifen. Die Daten in der Datenbank sind wahrscheinlich in einem kompakteren Format gespeichert als in der Textdatei, weswegen beim Zugriff weniger Festplattenzugriffe auftreten. Außerdem können Sie Code in Ihrer Anwendung einsparen, denn Sie müssen die Textdateien nicht analysieren, um Zeilen- und Spaltenbegrenzungen zu finden.
Bei einigen Operationen kann die Replikation einen Leistungsgewinn bringen. Sie können die Abrufvorgänge durch die Clients auf mehrere Server verteilen, um einen Lastausgleich zu erzielen. Damit der Master bei der Erstellung von Backups nicht verlangsamt wird, können Sie Sicherungen mit einem Slave-Server erstellen. Siehe auch Kapitel 6, Replikation bei MySQL.
Die Deklaration einer MyISAM
-Tabelle mit
der Tabellenoption DELAY_KEY_WRITE=1
beschleunigt Indexaktualisierungen, da diese erst auf
Festplatte geschrieben werden, wenn die Tabelle geschlossen
wird. Der Nachteil besteht darin, dass Sie, wenn der Server
terminiert wird, während eine solche Tabelle geöffnet ist,
sicherstellen müssen, dass die Tabelle unbeschädigt ist,
indem Sie den Server mit der Option
--myisam-recover
ausführen oder
myisamchk verwenden, bevor Sie den Server
neu starten. (Allerdings sollten Sie auch in diesem Fall
keine Daten verlieren, wenn Sie
DELAY_KEY_WRITE
verwenden, weil die
Schlüsselinformationen sich immer aus den Datensätzen in
der Datendatei ableiten lassen.)
MySQL verwendet die Sperrung auf Tabellenebene für
MyISAM
- und
MEMORY
-Tabellen, die Sperrung auf Seitenebene
für BDB
-Tabellen und die Sperrung auf
Datensatzebene für InnoDB
-Tabellen.
In vielen Fällen können Sie eine begründete Annahme dazu treffen, welcher Sperrungstyp der beste für eine Anwendung ist; generell ist es aber schwierig zu sagen, dass ein bestimmter Sperrungstyp besser ist als ein anderer. Alles hängt von der Anwendung ab, und verschiedene Teile einer Anwendung können unterschiedliche Sperrungstypen erfordern.
Um zu entscheiden, ob Sie eine Speicher-Engine mit Sperrung auf
Datensatzebene verwenden sollten, müssen Sie einschätzen, was
Ihre Anwendung tut und welche Mischung aus Auswahl- und
Änderungsanweisungen sie verwendet. Die meisten Webanwendungen
führen beispielsweise sehr viele Auswahloperationen, relativ
wenig Löschvorgänge, vorzugsweise auf Schlüsselwerten
basierende Änderungen und Einfügungen in nur ein paar
bestimmte Tabellen durch. Die
MyISAM
-Basiskonfiguration von MySQL ist für
solche Zwecke hervorragend geeignet.
Die Tabellensperrung in MySQL schließt ein Deadlock bei Speicher-Engines aus, die Sperren auf Tabellenebene verwenden. Die Deadlock-Vermeidung wird verwaltet, indem zu Anfang einer Abfrage immer alle erforderlichen Sperren auf einmal angefordert und die Tabellen immer in derselben Reihenfolge gesperrt werden.
Die Tabellensperrmethode, die MySQL für
WRITE
-Sperren verwendet, funktioniert wie
folgt:
Wenn keine Sperre für die Tabelle vorhanden ist, wird eine Schreibsperre verhängt.
Andernfalls wird die Sperranforderung in die Warteschlange für Schreibsperranforderungen gesetzt.
Die Tabellensperrmethode, die MySQL für
READ
-Sperren verwendet, funktioniert wie
folgt:
Wenn keine Schreibsperre für die Tabelle vorhanden ist, wird eine Lesesperre verhängt.
Andernfalls wird die Sperranforderung in die Warteschlange für Lesesperranforderungen gesetzt.
Wenn eine Sperre aufgehoben wird, wird die Sperrmöglichkeit
zunächst den Threads in der Warteschleife für
Schreibsperranforderungen und dann den Threads in der
Warteschleife für Lesesperranforderungen verfügbar gemacht:
Wenn Sie also viele Änderungen an einer Tabelle vorgenommen
haben, warten SELECT
-Anweisungen, bis keine
Änderungen mehr anhängig sind.
Sie können die Zugriffssituation bezüglich der Tabellensperren
auf Ihrem System analysieren, indem Sie die Statusvariablen
Table_locks_waited
und
Table_locks_immediate
überprüfen:
mysql> SHOW STATUS LIKE 'Table%';
+-----------------------+---------+
| Variable_name | Value |
+-----------------------+---------+
| Table_locks_immediate | 1151552 |
| Table_locks_waited | 15324 |
+-----------------------+---------+
Wenn eine MyISAM
-Tabelle keine freien Blöcke
in der Mitte enthält, werden Datensätze immer am Ende der
Datendatei eingefügt. In diesem Fall können Sie
INSERT
- und
SELECT
-Anweisungen bei einer
MyISAM
-Tabelle ohne Sperre gleichzeitig
verwenden. Sie können also Datensätze in eine
MyISAM
-Tabelle einfügen, während andere
Clients zur selben Zeit daraus lesen. (Löcher können
entstehen, wenn Datensätze in der Mitte der Tabelle gelöscht
oder aktualisiert wurden. Wenn Löcher vorhanden sind, sind
gleichzeitige Einfügeoperationen nicht möglich; sie werden
allerdings sofort wieder verfügbar, sobald alle Löcher mit
neuen Daten gefüllt wurden.)
Wenn Sie viele INSERT
- und
SELECT
-Operationen an einer Tabelle
durchführen wollen, während gleichzeitige Einfügeoperationen
gerade nicht möglich sind, dann können Sie Datensätze in eine
Temporärtabelle einfügen und die echte Tabelle dann sporadisch
mit den Datensätzen aus dieser Temporärtabelle aktualisieren.
Dies ist etwa mit dem folgenden Code möglich:
mysql>LOCK TABLES real_table WRITE, insert_table WRITE;
mysql>INSERT INTO real_table SELECT * FROM insert_table;
mysql>TRUNCATE TABLE insert_table;
mysql>UNLOCK TABLES;
InnoDB
verwendet Datensatzsperren,
BDB
hingegen Seitensperren. Bei diesen beiden
Speicher-Engines sind Deadlocks möglich, weil sie während der
Verarbeitung von SQL-Anweisungen automatisch Sperren erwirken
– und nicht gleich beim Start der Transaktion.
Vorteile der Sperrung auf Datensatzebene:
weniger Sperrkonflikte beim Zugriff auf verschiedene Datensätze in vielen Threads
weniger Änderungen bei Rollbacks
Möglichkeit einer sehr langen Sperrdauer für einen Datensatz
Nachteile der Sperrung auf Datensatzebene:
erfordert mehr Speicher als die Sperrung auf Seiten- oder Tabellenebene
langsamer als die Sperrung auf Seiten- oder Tabellenebene, wenn sie für einen großen Teil der Tabelle verwendet wird, weil Sie wesentlich mehr Sperren erwirken müssen
definitiv wesentlich langsamer als die anderen
Sperrungsoptionen, wenn Sie häufig GROUP
BY
-Operationen für einen großen Teil der Daten
durchführen oder oft die gesamte Tabelle scannen müssen
Tabellensperren sind Sperren auf Seiten- oder Datensatzebene in den folgenden Fällen überlegen:
Die meisten Anweisungen für die Tabelle sind Leseoperationen.
Eine Mischung von Lese- und Schreiboperationen, wobei die Schreiboperationen Updates oder Löschvorgänge für einen einzelnen Datensatz sind, der mit einem Schlüssellesevorgang geholt werden kann:
UPDATEtbl_name
SETcolumn
=value
WHEREunique_key_col
=key_value
; DELETE FROMtbl_name
WHEREunique_key_col
=key_value
;
SELECT
in Kombination mit gleichzeitigen
INSERT
-Anweisungen und sehr wenigen
UPDATE
- oder
DELETE
-Anweisungen.
Viele Scans oder GROUP BY
-Operationen
über die gesamte Tabelle ohne Schreiber.
Bei Sperren höherer Ebene können Sie Anwendungen einfacher optimieren, indem Sie Sperren verschiedener Typen unterstützen, weil der Overhead wesentlich geringer ist als bei Sperren auf Datensatzebene.
Andere Optionen als Sperrungen auf Datensatz- und Seitenebene:
Versionierung (wie sie beispielsweise in MySQL für nebenläufige Einfügeoperationen verwendet wird). Hierbei können ein Schreiber und mehrere Leser nebeneinander arbeiten. Dies bedeutet, dass die Datenbank oder Tabelle verschiedene Views der Daten abhängig vom Zeitpunkt des Zugriffsbeginns unterstützt. Andere gängige Bezeichnungen hierfür sind „Zeitreise“, „Copy on Write“ (Kopieren beim Schreiben) und „Copy on Demand“ (Kopieren bei Bedarf).
Copy on Demand ist der Sperrung auf Seiten- oder Datensatzebene in vielen Fällen überlegen. Schlimmstenfalls kann sie jedoch wesentlich mehr Speicher beanspruchen als normale Sperren.
Anstelle von Sperren auf Datensatzebene können Sie auch
Sperren auf Anwendungsebene verwenden – in MySQL etwa
GET_LOCK()
und
RELEASE_LOCK()
. Dies sind beratende
Sperren, d. h., sie funktionieren nur in
„wohlerzogenen“ Anwendungen.
Um eine sehr hohe Sperrgeschwindigkeit zu erzielen, verwendet
MySQL die Tabellensperrung (statt der Sperrung auf Seiten-,
Datensatz- oder Spaltenebene) für alle Speicher-Engines mit
Ausnahme von InnoDB
und
BDB
.
Bei InnoDB
- und
BDB
-Tabellen setzt MySQL die Tabellensperrung
nur dann ein, wenn Sie die Tabelle mit LOCK
TABLES
explizit sperren. Bei diesen Speicher-Engines
raten wir von der Verwendung von LOCK TABLES
vollständig ab, weil InnoDB
eine
automatische Sperrung auf Datensatzebene und
BDB
die Sperrung auf Seitenebene verwendet,
um die Transaktionsisolierung sicherzustellen.
Bei großen Tabellen ist die Tabellensperrung für die meisten Anwendungen wesentlich besser als die Datensatzsperrung. Es gibt allerdings auch ein paar Fallstricke:
Die Tabellensperrung gestattet mehreren Threads das Lesen aus der Tabelle zur selben Zeit; will ein Thread hingegen in eine Tabelle schreiben, so muss er zunächst exklusiven Zugriff erhalten. Alle anderen Threads, die auf die betreffende Tabelle zugreifen wollen, müssen warten, bis das Update abgeschlossen ist.
Tabellenupdates erhalten eine höhere Priorität als
Abrufvorgänge, weil sie normalerweise als wichtiger
betrachtet werden. Auf diese Weise soll sichergestellt
werden, dass Updates für eine Tabelle auch dann nicht
„verhungern“, wenn sehr viele
SELECT
-Anweisungen für die Tabelle
abgesetzt werden.
Die Tabellensperre kann beispielsweise Probleme verursachen, wenn ein Thread wartet, weil die Festplatte voll ist und erst freier Speicher benötigt wird, damit er fortgesetzt werden kann. In diesem Fall werden alle Threads, die auf die problematische Tabelle zugreifen wollen, ebenfalls in einen Wartezustand versetzt, bis wieder genug Festplattenkapazität verfügbar ist.
Die Tabellensperre ist auch in folgendem Szenario nachteilig:
Ein Client setzt eine SELECT
-Anweisung
ab, deren Ausführung sehr lange dauert.
Ein anderer Client setzt dann eine
UPDATE
-Anweisung für dieselbe Tabelle
ab. Dieser Client wartet, bis die
SELECT
-Anweisung abgeschlossen ist.
Wieder ein anderer Client setzt eine weitere
SELECT
-Anweisung für dieselbe Tabelle
ab. Weil UPDATE
aber eine höhere
Priorität hat als SELECT
, wartet diese
SELECT
-Anweisung darauf, dass die
UPDATE
-Anweisung wie
auch die erste
SELECT
-Anweisung fertig gestellt werden.
Die folgenden Punkte beschreiben einige Möglichkeiten, um den konkurrierenden Zugriff, der durch Tabellensperren verursacht werden kann, zu vermeiden oder zumindest zu verringern:
Versuchen Sie die Ausführung der
SELECT
-Anweisungen zu beschleunigen,
sodass die Tabellensperren verkürzt werden. Zu diesem Zweck
müssen Sie unter Umständen einige Zusammenfassungstabellen
erstellen.
Starten Sie mysqld mit der Option
--low-priority-updates
. So erhalten alle
Anweisungen, die eine Tabelle aktualisieren (also ändern),
eine niedrigere Priorität gegenüber
SELECT
-Anweisungen. In diesem Fall würde
die zweite SELECT
-Anweisung in obigem
Beispiel vor der UPDATE
-Anweisung
ausgeführt werden, und Sie müssten nicht warten, bis die
erste SELECT
-Anweisung abgeschlossen ist.
Sie können mit der Anweisung SET
LOW_PRIORITY_UPDATES=1
festlegen, dass alle
Aktualisierungen, die über eine bestimmte Verbindung
erfolgen, mit niedrigerer Priorität verarbeitet werden
sollen. Siehe auch Abschnitt 13.5.3, „SET
“.
Sie können einer bestimmten INSERT
-,
UPDATE
- oder
DELETE
-Anweisung mit dem Attribut
LOW_PRIORITY
eine niedrigere Priorität
zuweisen.
Sie können einer bestimmten
SELECT
-Anweisung mit dem Attribut
HIGH_PRIORITY
eine höhere Priorität
zuweisen. Siehe auch Abschnitt 13.2.7, „SELECT
“.
Sie können mysqld mit einem niedrigen
Wert für die Systemvariable
max_write_lock_count
starten: In diesem
Fall wird MySQL gezwungen, die Priorität aller
SELECT
-Anweisungen, die auf eine Tabelle
warten, zu senken, nachdem eine bestimmte Anzahl von
Einfügeoperationen in die Tabelle stattgefunden hat. Auf
diese Weise können nach einer bestimmten Anzahl von
WRITE
-Sperren auch
READ
-Sperren gesetzt werden.
Wenn Sie Probleme mit INSERT
in
Verbindung mit SELECT
haben, sollten Sie
in Betracht ziehen, auf MyISAM
-Tabellen
umzustellen, denn diese unterstützen gleichzeitige
SELECT
- und
INSERT
-Anweisungen.
Mischen Sie Einfüge- und Löschoperationen in derselben
Tabelle, dann kann INSERT DELAYED
sehr
hilfreich sein. Siehe auch Abschnitt 13.2.4.2, „INSERT DELAYED
“.
Wenn Sie Probleme mit gemischten SELECT
-
und DELETE
-Anweisungen haben, dann kann
die Option LIMIT
für
DELETE
nützlich sein. Siehe auch
Abschnitt 13.2.1, „DELETE
“.
Die Verwendung von SQL_BUFFER_RESULT
bei
SELECT
-Anweisungen kann dabei helfen, die
Dauer der Tabellensperren zu verkürzen. Siehe auch
Abschnitt 13.2.7, „SELECT
“.
Sie können den Sperrcode in
mysys/thr_lock.c
so abändern, dass nur
eine einzelne Warteschlange verwendet wird. In diesem Fall
hätten Schreib- und Lesesperren dieselbe Priorität, was
bei einigen Anwendungen von Nutzen sein kann.
Hier noch ein paar Tipps zu Tabellensperren in MySQL:
Gleichzeitige Benutzer stellen kein Problem dar, wenn Sie Update- nicht mit Auswahloperationen mischen, die viele Datensätze in derselben Tabelle untersuchen müssen.
Sie können mit LOCK TABLES
die
Geschwindigkeit erhöhen, weil viele Updates innerhalb einer
einzelnen Sperre wesentlich schneller erfolgen als die
Durchführung von Updates ohne Sperre. Auch das Aufteilen
des Tabelleninhalts auf mehrere Tabellen kann hilfreich
sein.
Wenn Sie auf geschwindigkeitsspezifische Probleme in
Verbindung mit Tabellensperren bei MySQL treffen, können
Sie die Leistung möglicherweise durch Konvertierung einiger
Ihrer Tabellen in InnoDB
- oder
BDB
-Tabellen verbessern. Siehe auch
Abschnitt 14.2, „InnoDB
-Tabellen“, und
Abschnitt 14.5, „Die BDB
-Speicher-Engine“.
Bei einer MyISAM
-Tabelle können Sie
nebenläufige Einfügeoperationen verwenden, um Datensätze
einzufügen, während gleichzeitig
SELECT
-Anweisungen ausgeführt werden, sofern
sich in der Mitte der Tabelle keine gelöschten Datensätze
befinden.
Unter Umständen, bei denen gleichzeitige Einfügeoperationen
verwendet werden können, ist es nur sehr selten notwendig, den
Modifizierer DELAYED
für
INSERT
-Anweisungen zu verwenden. Siehe
Abschnitt 13.2.4.2, „INSERT DELAYED
“.
Wenn Sie das Binärlog verwenden, werden nebenläufige in
normale Einfügeoperationen für die Anweisungen CREATE
... SELECT
oder INSERT ... SELECT
umgewandelt. Hierdurch wird gewährleistet, dass Sie eine exakte
Kopie Ihrer Tabellen neu erstellen können, indem Sie das Log
während eines Sicherungsvorgangs anwenden.
Bei LOAD DATA INFILE
können, wenn Sie
CONCURRENT
bei einer
MyISAM
-Tabelle angeben, die die Bedingungen
für gleichzeitige Einfügeoperationen erfüllt (d. h. keine
freien Blöcke in der Mitte enthält), andere Threads Daten aus
der Tabelle abrufen, während LOAD DATA
ausgeführt wird. Die Verwendung dieser Option beeinflusst die
Leistungsfähigkeit von LOAD DATA
auch dann
geringfügig, wenn gleichzeitig kein anderer Thread die Tabelle
verwendet.
MyISAM
-Schlüssel-CacheMyISAM
-IndexstatistikenMySQL speichert Datensätze und Indexdaten in separaten Dateien. Viele andere Datenbanksysteme (sogar fast alle) speichern Datensätze und Indexdaten in derselben Datei. Wir sind allerdings der Ansicht, dass die Vorgehensweise von MySQL für eine Vielzahl moderner Systeme die bessere Wahl ist.
Eine andere Möglichkeit zur Speicherung der Datensätze besteht darin, die Daten für jede Spalte in einem separaten Bereich zu halten (Beispiele für Datenbanksysteme, die diesen Ansatz verwenden, sind SDBM und Focus). Allerdings führt dies zu einem erheblichen Leistungseinbruch, sobald auf mehr als eine Spalte zugegriffen wird. Aufgrund dieses Verhaltens beim Zugriff auf mehrere Spalten glauben wir nicht, dass dieses Modell für universelle Datenbanken gut geeignet ist.
Der häufigere Fall ist jedoch der, dass Indizes und Daten gemeinsam gespeichert werden (wie beispielsweise bei Oracle/Sybase usw.). In diesem Fall finden Sie die Datensatzinformationen auf der Blattseite des Indexes. Der Vorteil dieses Designs besteht darin, dass hierbei in vielen Fällen – abhängig davon, wie gut der Index zwischengespeichert wird – ein Lesevorgang auf der Festplatte eingespart wird. Es gibt aber auch Nachteile:
Tabellenscans sind wesentlich langsamer, weil Sie die Indizes durchlesen müssen, um an die Daten zu kommen.
Sie können die Daten für eine Abfrage nicht einfach der Indextabelle entnehmen.
Sie verbrauchen mehr Speicherplatz, weil Sie Indizes aus den Knoten duplizieren müssen (Sie können den Datensatz nicht in den Knoten speichern).
Aufgrund von Löschvorgängen degeneriert die Tabelle im Laufe der Zeit, weil die Indizes in Knoten normalerweise bei Löschvorgängen nicht aktualisiert werden.
Es ist schwieriger, nur die Indexdaten zwischenzuspeichern.
Eine der einfacheren Optimierungen besteht darin, Ihre Tabellen so zu implementieren, dass sie möglichst wenig Platz auf der Festplatte einnehmen. Dies kann erhebliche Verbesserungen zur Folge haben, weil die Lesevorgänge von der Festplatte schneller erfolgen und kleinere Tabellen normalerweise weniger Hauptspeicher benötigen, während ihre Inhalte bei der Abfrageausführung aktiv verarbeitet werden. Auch die Indizierung ist weniger ressourcenbeanspruchend, wenn sie an schmaleren Spalten vorgenommen wird.
MySQL unterstützt viele verschiedene Speicher-Engines (Tabellentypen) und Datensatzformate. Für jede Tabelle können Sie neu entscheiden, welche Speicher- und Indizierungsmethode verwendet werden soll. Die Auswahl des für Ihre Anwendung geeigneten Tabellenformats kann Ihnen einen erheblichen Performancezuwachs bringen. Siehe auch Kapitel 14, Speicher-Engines und Tabellentypen.
Sie können die Leistungsfähigkeit Ihrer Tabellen optimieren und den Speicherbedarf minimieren, indem Sie die folgenden Methoden benutzen:
Verwenden Sie den jeweils effizientesten (d. h.
kleinstmöglichen) Datentyp. MySQL bietet viele
Spezialtypen, mit denen sich Festplatten- und
Arbeitsspeicher einsparen lassen. Setzen Sie beispielsweise
möglichst die kleineren Integer-Typen ein, um kleinere
Tabellen zu erhalten. MEDIUMINT
ist
häufig besser geeignet als INT
, weil
eine MEDIUMINT
-Spalte 25 Prozent weniger
Platz benötigt.
Wenn möglich, deklarieren Sie Spalten als NOT
NULL
. Hierdurch wird alles schneller, und Sie
sparen ein Bit je Spalte. Wenn Sie NULL
in Ihrer Anwendung wirklich benötigen, sollten Sie es
natürlich benutzen; Sie sollten lediglich verhindern, dass
alle Spalten vorgabeseitig so eingestellt sind.
Wenn Ihre MyISAM
-Tabellen keine Spalten
variabler Länge (VARCHAR
,
TEXT
oder BLOB
)
enthalten, wird ein festes Datensatzformat verwendet. Dieses
ist schneller, kann allerdings mehr Platz beanspruchen.
Siehe auch Abschnitt 14.1.3, „MyISAM-Tabellenformate“.
Sie können mit der Option
ROW_FORMAT=FIXED
für CREATE
TABLE
angeben, dass Sie Datensätze fester Länge
verwenden wollen, auch wenn
VARCHAR
-Spalten vorhanden sind.
InnoDB
-Tabellen verwenden ein kompaktes
Speicherformat. In Versionen vor MySQL 5.0.3 enthalten
InnoDB
-Datensätze einige redundante
Informationen, z. B. die Anzahl und die Längen der
einzelnen Spalten (und zwar auch bei Spalten fester
Größe). Standardmäßig werden Tabellen im kompakten
Format erstellt (ROW_FORMAT=COMPACT
).
Wenn Sie ein Downgrade auf eine ältere MySQL-Version
durchführen wollen, können Sie das alte Format mit
ROW_FORMAT=REDUNDANT
anfordern.
Das kompakte InnoDB
-Format ändert auch
die Art und Weise, wie CHAR
-Spalten, die
Daten im UTF-8-Format enthalten, gespeichert werden. Bei
ROW_FORMAT=REDUNDANT
belegt eine Spalte
CHAR(
im
UTF-8-Format 3 × N
)N
Byte
(davon ausgehend, dass die maximale Länge eines
UTF-8-kodierten Zeichens drei Byte beträgt). Viele Sprachen
können vorwiegend mit UTF-8-Zeichen geschrieben werden, die
nur ein Byte umfassen, weswegen eine feste Speicherlänge
häufig Platzverschwendung ist. Beim
ROW_FORMAT=COMPACT
-Format reserviert
InnoDB
eine variable Speichermenge im
Bereich zwischen N
und 3 ×
N
Byte für diese Spalten, indem
Leerzeichen am Ende nach Bedarf abgeschnitten werden. Die
Mindestspeichergröße wird als N
Byte vermerkt, um in typischen Fällen interne Updates
durchführen zu können.
Der Primärindex einer Tabelle sollte so kurz wie möglich sein. Dies macht die Identifizierung eines Datensatzes einfach und effizient.
Erstellen Sie nur Indizes, die Sie auch wirklich benötigen. Indizes sind praktisch, um Daten abzurufen, aber von Nachteil, wenn Sie Daten schnell speichern müssen. Wenn Sie auf eine Tabelle in erster Linie durch das Durchsuchen einer Kombination von Spalten zugreifen, dann erstellen Sie für diese Kombination einen Index. Der erste Teil des Indexes sollte die meistverwendete Spalte sein. Wenn Sie beim Auswählen aus der Tabelle immer viele Spalten verwenden, sollten Sie die Spalte benutzen, die mehr Dubletten aufweist, damit der Index besser komprimiert werden kann.
Wenn es sehr wahrscheinlich ist, dass eine String-Spalte ein
eindeutiges Präfix innerhalb der ersten paar Zeichen
aufweist, dann ist es besser, nur dieses Präfix zu
indizieren. Hierzu verwenden Sie die MySQL-Funktionalität
zur Erstellung eines Indexes aus dem linken Teil der Spalte
(siehe Abschnitt 13.1.4, „CREATE INDEX
“). Kürzere Indizes
sind nicht nur deswegen schneller, weil sie weniger
Festplattenkapazität benötigen, sondern auch, weil sie auf
diese Weise mehr Treffer im Index-Cache erhalten (d. h., es
sind weniger Suchvorgänge auf der Festplatte erforderlich).
Siehe auch Abschnitt 7.5.2, „Serverparameter feineinstellen“.
Unter manchen Umständen kann es von Vorteil sein, eine Tabelle, die sehr häufig gescannt wird, in zwei Tabellen aufzutrennen. Dies gilt insbesondere, wenn es sich um eine Tabelle im dynamischen Format handelt und es möglich ist, dass eine kleinere statische Tabelle entsteht, die beim Scannen der Tabelle zum Auffinden der gewünschten Datensätze benutzt werden kann.
Alle MySQL-Datentypen lassen sich indizieren. Die Verwendung von
Indizes der relevanten Spalten ist die beste Möglichkeit, die
Leistung von SELECT
-Operationen zu
optimieren.
Die maximale Anzahl von Indizes pro Tabelle und die maximale Indexlänge werden durch die verwendete Speicher-Engine bestimmt. Siehe auch Kapitel 14, Speicher-Engines und Tabellentypen. Alle Speicher-Engines unterstützen mindestens 16 Indizes pro Tabelle und eine Indexgesamtlänge von mindestens 256 Byte. Bei den meisten Speicher-Engines liegen die Grenzen höher.
Mit der Syntax
in einer Indexdefinition können Sie einen Index erstellen, der
nur die ersten col_name
(N
)N
Zeichen einer
String-Spalte verwendet. Wenn Sie auf diese Weise nur ein
Präfix der Spaltenwerte indizieren, kann dies die Indexdatei
erheblich kleiner machen. Bei der Indizierung einer
BLOB
- oder TEXT
-Spalte
müssen Sie eine Präfixlänge für den
Index angeben. Zum Beispiel:
CREATE TABLE test (blob_col BLOB, INDEX(blob_col(10)));
Präfixe können bis zu 1.000 Byte lang sein (767 Byte bei
InnoDB
-Tabellen). Beachten Sie, dass
Präfixbeschränkungen in Byte angegeben werden, wohingegen die
Präfixlänge in CREATE TABLE
-Anweisungen als
Anzahl der Zeichen interpretiert wird. Dies muss bei
der Angabe einer Präfixlänge für eine Spalte, die einen
Multibytezeichensatz verwendet, in jedem Fall berücksichtigt
werden.
Sie können außerdem FULLTEXT
-Indizes
erstellen. Diese werden für die Volltextsuche verwendet. Nur
die MyISAM
-Speicher-Engine unterstützt
FULLTEXT
-Indizes, und auch nur für
CHAR
-, VARCHAR
- und
TEXT
-Spalten. Die Indizierung erfolgt stets
über die gesamte Spalte – eine Teilindizierung
(Spaltenpräfix) wird nicht unterstützt. Detaillierte
Informationen finden Sie in Abschnitt 12.7, „MySQL-Volltextsuche“.
Sie können auch Indizes für raumbezogene Typen erstellen.
Derzeit unterstützt nur MyISAM
R-Tree-Indizes für raumbezogene Typen. Andere Speicher-Engines
verwenden B-Trees zur Indizierung raumbezogener Typen.
(Ausnahmen sind lediglich ARCHIVE
und
NDBCLUSTER
, die überhaupt keine raumbezogene
Indizierung unterstützen.)
Die MEMORY
-Engine verwendet standardmäßig
HASH
-Indizes, unterstützt aber auch
BTREE
-Indizes.
MySQL kann zusammengesetzte Indizes erstellen (d. h. Indizes über mehrere Spalten). Ein Index kann bis zu 15 Spalten umfassen. Bei bestimmten Datentypen können Sie ein Präfix der Spalte indizieren (siehe Abschnitt 7.4.3, „Spaltenindizes“).
Ein mehrspaltiger Index kann als sortiertes Array betrachtet werden, das Werte enthält, die durch Verkettung der Werte der indizierten Spalten entstanden sind.
MySQL verwendet mehrspaltige Indizes derart, dass Abfragen
schnell sind, wenn Sie einen bekannten Teil der ersten Spalte
des Indexes in einer WHERE
-Klausel angeben
– und zwar auch dann, wenn Sie keine Werte für andere Spalten
angeben.
Angenommen, eine Tabelle habe die folgende Spezifikation:
CREATE TABLE test ( id INT NOT NULL, last_name CHAR(30) NOT NULL, first_name CHAR(30) NOT NULL, PRIMARY KEY (id), INDEX name (last_name,first_name) );
Der Index name
ist ein Index über die
Spalten last_name
und
first_name
. Der Index kann für Abfragen, die
Werte in einem bekannten Bereich für
last_name
angeben, oder sowohl für
last_name
als auch für
first_name
verwendet werden. Aus diesem Grund
wird der Index name
in den folgenden Abfragen
benutzt:
SELECT * FROM test WHERE last_name='Widenius'; SELECT * FROM test WHERE last_name='Widenius' AND first_name='Michael'; SELECT * FROM test WHERE last_name='Widenius' AND (first_name='Michael' OR first_name='Monty'); SELECT * FROM test WHERE last_name='Widenius' AND first_name >='M' AND first_name < 'N';
Im Gegensatz dazu wird der Index name
in den
folgenden Abfragen nicht benutzt:
SELECT * FROM test WHERE first_name='Michael'; SELECT * FROM test WHERE last_name='Widenius' OR first_name='Michael';
Die Art und Weise, wie MySQL Indizes zur Verbesserung der Abfrageleistung verwendet, wird in Abschnitt 7.4.5, „Wie MySQL Indizes benutzt“, näher beschrieben.
Indizes werden verwendet, um schnell Datensätze mit bestimmten Spaltenwerten zu finden. Ohne Index müsste MySQL mit der Suche beim ersten Datensatz beginnen und dann die gesamte Tabelle nach passenden Datensätzen durchforsten. Je größer die Tabelle, desto höher sind die Kosten dafür. Wenn die Tabelle einen Index für die fraglichen Spalten aufweist, kann MySQL die Position in der Mitte der Datendatei, an der die Suche beginnen soll, schnell bestimmen, ohne alle Daten in der Datei überprüfen zu müssen. Wenn eine Tabelle 1.000 Datensätze hat, ist dies mindestens hundertmal schneller als ein sequenzielles Lesen. Wenn Sie hingegen auf die meisten Datensätze zugreifen müssen, ist das sequenzielle Lesen schneller, weil die Anzahl der Festplattenzugriffe geringer ist.
Die meisten MySQL-Indizes (PRIMARY KEY
,
UNIQUE
, INDEX
und
FULLTEXT
) sind in B-Trees gespeichert. Zu
erwähnende Ausnahmen sind, dass Indizes für raumbezogene
Datentypen R-Typen verwenden und
MEMORY
-Tabellen auch Hash-Indizes
unterstützen.
Strings werden automatisch präfixkomprimiert; Gleiches gilt
für Leerzeichen am Ende des Strings. Siehe auch
Abschnitt 13.1.4, „CREATE INDEX
“.
Generell werden Indizes wie nachfolgend beschrieben verwendet.
Die spezifischen Eigenschaften von Hash-Indizes, die in
Verbindung mit MEMORY
-Tabellen verwendet
werden, werden am Ende dieses Abschnitts erläutert.
MySQL verwendet Indizes für die folgenden Operationen:
Zum schnellen Auffinden von Datensätzen, die der
WHERE
-Klausel entsprechen.
Zum Ignorieren bestimmter Datensätze. Wenn mehrere Indizes vorhanden sind, verwendet MySQL normalerweise denjenigen, der die kleinste Anzahl von Datensätzen findet.
Zum Abrufen von Datensätzen aus anderen Tabellen bei der Durchführung von Joins.
Zum Auffinden des MIN()
- oder
MAX()
-Werts für eine bestimmte
indizierte Spalte key_col
. Dies
wird mit einem Vorprozessor optimiert, der überprüft, ob
Sie WHERE
für alle
Schlüsselteile verwenden, die im Index vor
key_part_N
=
constant
key_col
erscheinen. In diesem
Fall führt MySQL eine einfache Schlüsselsuche nach jedem
MIN()
- oder
MAX()
-Ausdruck durch und ersetzt ihn
durch eine Konstante. Wenn alle Ausdrücke durch Konstanten
ersetzt werden konnten, wird die Abfrage umgehend
abgeschlossen. Zum Beispiel:
SELECT MIN(key_part2
),MAX(key_part2
) FROMtbl_name
WHEREkey_part1
=10;
Zum Sortieren oder Gruppieren einer Tabelle, sofern das
Sortieren bzw. Gruppieren auf der Basis des linken Präfixes
eines verwendbaren Schlüssels erfolgt (z. B.
ORDER BY
). Wenn auf
alle Schlüsselteile key_part1
,
key_part2
DESC
folgt, wird der
Schlüssel in umgekehrter Reihenfolge gelesen. Siehe auch
Abschnitt 7.2.12, „ORDER BY
-Optimierung“.
In manchen Fällen kann eine Abfrage so optimiert werden, dass sie Werte abruft, ohne die eigentlichen Datensätze zu untersuchen. Wenn eine Abfrage nur Spalten einer Tabelle verwendet, die numerisch sind und bei einem Schlüssel ein linkes Präfix bilden, dann können die ausgewählten Werte auch aus dem Indexbaum abgerufen werden, was deutlich schneller ist:
SELECTkey_part3
FROMtbl_name
WHEREkey_part1
=1
Nehmen wir an, dass Sie folgende
SELECT
-Anweisung absetzen:
mysql> SELECT * FROM tbl_name
WHERE col1=val1
AND col2=val2
;
Wenn für col1
und col2
ein mehrspaltiger Index vorhanden ist, können die
entsprechenden Datensätze direkt abgerufen werden. Sind
separate einspaltige Indizes für col1
und
col2
vorhanden, dann versucht der Optimierer,
den restriktivsten Index zu ermitteln, indem er überprüft,
welcher Index weniger Spalten findet; dieser Index wird dann zum
Abrufen von Datensätzen benutzt.
Wenn die Tabelle einen mehrspaltigen Index aufweist, kann ein
beliebiges linkes Präfix des Indexes vom Optimierer zum Suchen
von Datensätzen verwendet werden. Haben Sie beispielsweise
einen dreispaltigen Index für (col1, col2,
col3)
, dann bietet dieser Suchfunktionalität für
(col1)
, (col1, col2)
und
(col1, col2, col3)
.
MySQL kann keinen Teilindex verwenden, wenn die Spalten kein
linkes Präfix für den Index bilden. Betrachten Sie einmal die
folgenden SELECT
-Anweisungen:
SELECT * FROMtbl_name
WHERE col1=val1
; SELECT * FROMtbl_name
WHERE col1=val1
AND col2=val2
; SELECT * FROMtbl_name
WHERE col2=val2
; SELECT * FROMtbl_name
WHERE col2=val2
AND col3=val3
;
Wenn ein Index für (col1, col2, col3)
vorhanden ist, verwenden diese nur die ersten beiden Abfragen.
Die dritte und die vierte Abfrage beziehen sich zwar auf
indizierte Spalten, aber (col2)
und
(col2, col3)
sind keine linken Präfixe von
(col1, col2, col3)
.
Ein B-Tree-Index kann für Spaltenvergleiche in Ausdrücken
benutzt werden, die die Operatoren =
,
>
, >=
,
<
, <=
oder
BETWEEN
verwenden. Der Index kann auch für
LIKE
-Vergleiche benutzt werden, wenn das
Argument zu LIKE
ein Konstanten-String ist,
der nicht mit einem Jokerzeichen beginnt. Die folgenden
SELECT
-Anweisungen verwenden beispielsweise
Indizes:
SELECT * FROMtbl_name
WHEREkey_col
LIKE 'Patrick%'; SELECT * FROMtbl_name
WHEREkey_col
LIKE 'Pat%_ck%';
In der ersten Anweisung werden nur Datensätze mit
'Patrick' <=
berücksichtigt. In der zweiten Anweisung
werden nur Datensätze mit key_col
<
'Patricl''Pat' <=
berücksichtigt.
key_col
< 'Pau'
Die folgenden SELECT
-Anweisungen verwenden
keine Indizes:
SELECT * FROMtbl_name
WHEREkey_col
LIKE '%Patrick%'; SELECT * FROMtbl_name
WHEREkey_col
LIKEother_col
;
In der ersten Anweisung beginnt der Wert LIKE
mit einem Jokerzeichen. In der zweiten Anweisung ist der
LIKE
-Wert keine Konstante.
Wenn Sie … LIKE
'%
verwenden und
string
%'string
mehr als drei Zeichen umfasst,
verwendet MySQL den
Turbo-Boyer-Moore-Algorithmus zur
Initialisierung des Musters für den String; mit diesem Muster
wird die Suche dann schneller durchgeführt.
Eine Suche unter Verwendung von
setzt Indizes ein, wenn col_name
IS NULLcol_name
indiziert ist.
Ein Index, der nicht alle AND
-Ebenen in der
WHERE
-Klausel einbezieht, wird nicht zur
Optimierung der Abfrage benutzt. Um also einen Index verwenden
zu können, muss in jeder AND
-Gruppe ein
Präfix des Indexes benutzt werden.
Die folgenden WHERE
-Klauseln verwenden
Indizes:
... WHEREindex_part1
=1 ANDindex_part2
=2 ANDother_column
=3 /*index
= 1 ORindex
= 2 */ ... WHEREindex
=1 OR A=10 ANDindex
=2 /* optimized like "index_part1
='hello'" */ ... WHEREindex_part1
='hello' ANDindex_part3
=5 /* Can use index onindex1
but not onindex2
orindex3
*/ ... WHEREindex1
=1 ANDindex2
=2 ORindex1
=3 ANDindex3
=3;
Die folgenden WHERE
-Klauseln verwenden
Indizes nicht:
/*index_part1
is not used */ ... WHEREindex_part2
=1 ANDindex_part3
=2 /* Index is not used in both parts of the WHERE clause */ ... WHEREindex
=1 OR A=10 /* No index spans all rows */ ... WHEREindex_part1
=1 ORindex_part2
=10
Manchmal verwendet MySQL auch dann keinen Index, wenn ein
solcher vorhanden ist. Ein Umstand, unter dem dies geschieht,
liegt vor, wenn der Optimierer der Ansicht ist, dass MySQL bei
Verwendung eines Indexes auf einen sehr großen Anteil der
Datensätze in der Tabelle zugreifen muss. (In diesem Fall ist
ein Tabellenscan mit hoher Wahrscheinlichkeit schneller, weil
weniger Suchvorgänge erforderlich sind.) Wenn eine solche
Abfrage jedoch dank einer LIMIT
-Klausel nur
ein paar Datensätze abruft, verwendet MySQL trotzdem einen
Index, da sich die Datensätze, die zum Ergebnis gehören, auf
diese Weise schneller finden lassen.
Hash-Indizes weisen etwas andere Eigenschaften auf als die soeben beschriebenen:
Sie werden nur zu Vergleichen verwendet, die die Operatoren
=
oder <=>
benutzen (aber sie sind extrem
schnell). Nicht verwendet werden sie für Vergleiche mit
<
, bei denen ein Wertebereich gefunden
wird.
Der Optimierer kann einen Hash-Index nicht zur
Beschleunigung von ORDER BY
-Operationen
verwenden. (Dieser Indextyp kann nicht zur Suche nach dem
nächsten Eintrag in der Reihenfolge benutzt werden.)
MySQL kann nicht näherungsweise bestimmen, wie viele
Datensätze zwischen zwei Werten vorhanden sind (diese
Angabe verwendet der Bereichsoptimierer für die
Entscheidung, welchen Index er verwenden soll). Dies kann
sich auf einige Abfragen auswirken, wenn Sie eine
MyISAM
-Tabelle in eine
MEMORY
-Tabelle mit einem Hash-Index
konvertieren.
Nur vollständige Schlüssel können zur Suche nach einem Datensatz benutzt werden. (Bei einem B-Tree-Index kann dagegen ein beliebiges linkes Präfix des Schlüssels zum Suchen von Datensätzen eingesetzt werden.)
Um die Festplattenzugriffe zu minimieren, verwendet die
MyISAM
-Speicher-Engine eine Strategie, auf
der zahlreiche Datenbanksysteme basieren. Sie benutzt einen
Cache-Mechanismus, um die am häufigsten abgerufenen
Tabellenblöcke im Speicher zu halten:
Für Indexblöcke wird eine spezielle Struktur namens Schlüssel-Cache (oder Schlüsselpuffer) implementiert. Diese Struktur enthält eine Anzahl von Blockpuffern, in denen die meistverwendeten Indexblöcke abgelegt werden.
Für Datenblöcke verwendet MySQL keinen speziellen Cache. Stattdessen wird der Dateisystem-Cache des nativen Betriebssystems benutzt.
Dieser Abschnitt beschreibt zunächst den grundlegenden Betrieb
des MyISAM
-Schlüssel-Caches. Nachfolgend
werden Funktionen erläutert, die die Leistungsfähigkeit des
Schlüssel-Caches optimieren und mit denen Sie den Cache-Betrieb
besser steuern können:
Mehrere Threads können gleichzeitig auf den Cache zugreifen.
Sie können mehrere Schlüssel-Caches einrichten und Tabellenindizes speziellen Caches zuweisen.
Die Größe des Schlüssel-Caches stellen Sie mit der
Systemvariablen key_buffer_size
ein. Wenn
diese Variable auf null gesetzt ist, wird kein Cache verwendet.
Der Schlüssel-Cache wird ferner nicht benutzt, wenn der Wert
key_buffer_size
zu klein ist, um die
Mindestanzahl von Blockpuffern (8) zu reservieren.
Wenn der Schlüssel-Cache nicht betriebsbereit ist, erfolgt der Zugriff auf Indexdateien nur über die Puffer des nativen Dateisystems, die vom Betriebssystem bereitgestellt werden. (Anders gesagt, wird auf Tabellenindexblöcke unter Verwendung derselben Methode zugegriffen wie auf Tabellendatenblöcke.)
Ein Indexblock ist eine zusammenhängende Zugriffseinheit für
MyISAM
-Indexdateien. Normalerweise entspricht
die Größe eines Indexblocks der Größe der Knoten des
B-Trees. (Indizes werden auf der Festplatte mit einer
B-Tree-Datenstruktur dargestellt. Knoten am unteren Ende des
Trees sind Blattknoten, Knoten oberhalb der Blätter
Nichtblattknoten.)
Alle Blockpuffer in einer Schlüssel-Cache-Struktur haben dieselbe Größe. Diese Größe kann der Größe eines Tabellenindexblocks entsprechen, sie kann aber auch höher oder niedriger sein. Normalerweise ist einer dieser beiden Werte ein Vielfaches des anderen.
Wenn ein Zugriff auf Daten aus einem Tabellenindexblock erfolgen muss, dann überprüft der Server zunächst, ob er in einem Blockpuffer des Schlüssel-Caches vorhanden ist. Ist dies der Fall, dann greift der Server auf die Daten im Schlüssel-Cache statt auf der Festplatte zu: Er liest aus und/oder schreibt in den Cache statt auf die Festplatte. Andernfalls wählt der Server einen Cache-Blockpuffer, der einen oder mehrere andere Tabellenindexblöcke enthält, und ersetzt die dortigen Daten durch eine Kopie des erforderlichen Tabellenindexblocks. Sobald der neue Indexblock sich im Cache befindet, kann auf die Indexdaten zugegriffen werden.
Wenn ein für die Ersetzung gewählter Block modifiziert wurde, wird dieser als „schmutzig“ bezeichnet. In diesem Fall wird der Inhalt vor der Ersetzung in den Tabellenindex geschrieben, von dem er kam.
Normalerweise verwendet der Server eine LRU-Strategie (Least Recently Used): Wenn ein Block zur Ersetzung gewählt werden muss, entscheidet er sich für den Indexblock, der am längsten nicht mehr verwendet wurde. Um die Auswahl zu erleichtern, unterhält das Schlüssel-Cache-Modul eine spezielle Warteschlange (die LRU-Kette) mit allen verwendeten Blöcken. Wenn auf einen Block zugegriffen wird, wird er ans Ende der Warteschlange gesetzt. Müssen Blöcke ersetzt werden, dann sind die Blöcke am Anfang der Warteschlange die am längsten nicht verwendeten und werden infolgedessen als Erste geräumt.
Threads können gleichzeitig auf Schlüssel-Cache-Puffer zugreifen. Dabei ist Folgendes zu beachten:
Ein Puffer kann von mehreren Threads benutzt werden, sofern er derzeit nicht aktualisiert wird.
Wenn ein Puffer gerade aktualisiert wird, müssen Threads, die ihn verwenden wollen, warten, bis das Update abgeschlossen ist.
Mehrere Threads können Anfragen erzeugen, die zu Ersetzungen im Cache-Block führen können, solange sie sich nicht gegenseitig stören (d. h. solange sie verschiedene Indexblöcke benötigen und insofern auch verschiedene Cache-Blöcke ersetzt werden).
Der gemeinsame Zugriff auf den Schlüssel-Cache ermöglicht dem Server eine erhebliche Verbesserung des Durchsatzes.
Der gemeinsame Zugriff auf den Schlüssel-Cache verbessert die Leistung, beseitigt das Problem des gleichzeitigen Zugriffs durch mehrere Threads aber nicht vollständig. Diese wetteifern weiterhin um Steuerstrukturen, mit denen der Zugriff auf die Schlüssel-Cache-Puffer verwaltet wird. Um also die Rivalität um den Schlüssel-Cache-Zugriff weiter zu verringern, stellt MySQL zusätzlich mehrere Schlüssel-Caches bereit. Diese Funktion erlaubt es Ihnen, verschiedenen Schlüssel-Caches unterschiedliche Tabellenindizes zuzuweisen.
Wenn mehrere Schlüssel-Caches vorhanden sind, muss der Server
wissen, welchen Cache er bei der Verarbeitung von Abfragen
für eine gegebene MyISAM
-Tabelle verwenden
soll. Standardmäßig werden alle
MyISAM
-Tabellenindizes im vorgabeseitigen
Schlüssel-Cache zwischengespeichert. Um Tabellenindizes einem
bestimmten Schlüssel-Cache zuzuweisen, verwenden Sie die
Anweisung CACHE INDEX
(siehe
Abschnitt 13.5.5.1, „CACHE INDEX
“). Die folgende Anweisung
beispielsweise weist Indizes der Tabellen
t1
, t2
und
t3
dem Schlüssel-Cache namens
hot_cache
zu:
mysql> CACHE INDEX t1, t2, t3 IN hot_cache;
+---------+--------------------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+---------+--------------------+----------+----------+
| test.t1 | assign_to_keycache | status | OK |
| test.t2 | assign_to_keycache | status | OK |
| test.t3 | assign_to_keycache | status | OK |
+---------+--------------------+----------+----------+
Der in der CACHE INDEX
-Anweisung
referenzierte Schlüssel-Cache kann erstellt werden, indem
seine Größe mit einer SET
GLOBAL
-Anweisung zur Parametereinstellung oder in
den Startoptionen des Servers angegeben wird. Zum Beispiel:
mysql> SET GLOBAL keycache1.key_buffer_size=128*1024;
Um einen Schlüssel-Cache zu beseitigen, setzen Sie seine Größe auf null:
mysql> SET GLOBAL keycache1.key_buffer_size=0;
Beachten Sie, dass Sie den vorgabeseitigen Schlüssel-Cache nicht zerstören können. Alle diesbezüglichen Versuche werden ignoriert:
mysql>SET GLOBAL key_buffer_size = 0;
mysql>show variables like 'key_buffer_size';
+-----------------+---------+ | Variable_name | Value | +-----------------+---------+ | key_buffer_size | 8384512 | +-----------------+---------+
Schlüssel-Cache-Variablen sind strukturierte Systemvariablen,
die einen Namen und Komponenten aufweisen. Bei
keycache1.key_buffer_size
etwa ist
keycache1
der Cache-Variablenname und
key_buffer_size
die Cache-Komponente. Eine
Beschreibung der Syntax zur Referenzierung strukturierter
Systemvariablen für den Schlüssel-Cache finden Sie in
Abschnitt 5.2.3.1, „Strukturierte Systemvariablen“.
Standardmäßig werden Tabellenindizes dem vorgabeseitigen Schlüssel-Cache (Haupt-Schlüssel-Cache) zugewiesen, der beim Serverstart erstellt wird. Wird ein Schlüssel-Cache zerstört, dann werden alle ihm zugewiesenen Indizes wieder dem Standard-Schlüssel-Cache zugewiesen.
Für einen gut ausgelasteten Server empfehlen wir eine Strategie mit drei Schlüssel-Caches:
Ein „heißer“ Schlüssel-Cache, der 20 Prozent des für alle Schlüssel-Caches reservierten Speichers verwendet. Diesen setzen Sie für Tabellen ein, in denen sehr viele Suchvorgänge, aber keine Änderungen erfolgen.
Ein „kalter“ Schlüssel-Cache, der weitere 20 Prozent des für alle Schlüssel-Caches reservierten Speichers verwendet. Dieser Cache unterstützt mittelgroße, häufig geänderte Tabellen (z. B. Temporärtabellen).
Ein „warmer“ Schlüssel-Cache, der die verbleibenden 60 Prozent des Schlüssel-Cache-Speichers belegt. Diesen verwenden Sie als vorgabeseitigen Schlüssel-Cache, der standardmäßig von allen anderen Tabellen benutzt wird.
Ein Grund dafür, warum die Verwendung dreier Schlüssel-Caches von Vorteil ist, besteht darin, dass der Zugriff auf eine Schlüssel-Cache-Struktur den Zugriff auf die anderen nicht behindert. Anweisungen, die auf Tabellen zugreifen, die dem einen Cache zugewiesen sind, konkurrieren nicht mit Anweisungen, deren referenzierte Tabellen auf einen anderen Cache zugreifen. Ein Leistungsgewinn wird aber auch aus anderen Gründen erzielt:
Der heiße Cache wird nur für anfordernde Abfragen verwendet, d. h., sein Inhalt ändert sich nicht. Dies bedeutet, dass, wann immer ein Indexblock von der Festplatte abgerufen werden muss, der Inhalt des für die Ersetzung gewählten Cache-Blocks nicht zuerst synchronisiert werden muss.
Ist ein Index dem heißen Cache zugewiesen, dann ist, wenn keine Abfragen kommen, die einen Indexscan erfordern, die Wahrscheinlichkeit hoch, dass die Indexblöcke, die den Nichtblattknoten des B-Trees entsprechen, im Cache verbleiben.
Ein Updatevorgang, wie er am häufigsten für Temporärtabellen vorgenommen wird, wird wesentlich schneller durchgeführt, wenn der geänderte Knoten sich im Cache befindet und nicht erst von der Festplatte gelesen werden muss. Wenn die Größe der Indizes der Temporärtabellen mit der Größe des kalten Schlüssel-Caches vergleichbar ist, dann ist die Wahrscheinlichkeit, dass der aktualisierte Knoten sich im Cache befindet, extrem hoch.
CACHE INDEX
richtet eine Verknüpfung
zwischen einer Tabelle und einem Schlüssel-Cache ein, die
jedoch nur bis zum nächsten Serverneustart bestehen bleibt.
Wenn diese Verknüpfung jedes Mal, wenn der Server neu
startet, erstellt werden soll, können Sie dies etwa mit einer
Optionsdatei erreichen: Setzen Sie Variableneinstellungen, mit
denen Ihre Schlüssel-Caches konfiguriert werden, und eine
Option namens init-file
in die
Optionsdatei, die eine Datei bezeichnet, welche die
auszuführenden CACHE INDEX
-Anweisungen
enthält. Zum Beispiel:
key_buffer_size = 4G hot_cache.key_buffer_size = 2G cold_cache.key_buffer_size = 2G init_file=/path/to/data-directory/mysqld_init.sql
Die Anweisungen in mysqld_init.sql
werden
bei jedem Start des Servers ausgeführt. Die Datei sollte eine
SQL-Anweisung pro Zeile enthalten. Das folgende Beispiel weist
verschiedene Tabellen jeweils hot_cache
und
cold_cache
zu:
CACHE INDEX db1.t1, db1.t2, db2.t3 IN hot_cache CACHE INDEX db1.t4, db2.t5, db2.t6 IN cold_cache
Standardmäßig verwendet das System zur Schlüssel-Cache-Verwaltung die LRU-Strategie zur Auswahl der zu räumenden Schlüssel-Cache-Blöcke, unterstützt aber auch eine komplexere Methode namens Strategie des Einfügens am Mittelpunkt.
Bei Verwendung dieser Strategie wird die LRU-Kette in zwei
Teile aufgeteilt: eine heiße Unterkette und eine warme
Unterkette. Der Trennpunkt zwischen diesen beiden Teilen ist
nicht fest, sondern das Schlüssel-Cache-Verwaltungssystem
achtet darauf, dass der warme Teil nicht „zu
klein“ wird und immer mindestens
key_cache_division_limit
Prozent der
Schlüssel-Cache-Blöcke enthält.
key_cache_division_limit
ist eine
Komponente der strukturierten Schlüssel-Cache-Variablen,
d. h., ihr Wert ist ein Parameter, der pro Cache eingestellt
werden kann.
Wenn ein Indexblock aus einer Tabelle in den Schlüssel-Cache eingelesen wird, wird er an das Ende der warmen Unterkette gesetzt. Nach einer bestimmten Anzahl von Treffern (d. h. von Zugriffen auf den Block) wird er in die heiße Unterkette hochgestuft. Zurzeit ist die Anzahl der für das Hochstufen eines Blocks erforderlichen Treffer für alle Indexblöcke gleich (nämlich 3).
Ein Block, der in die heiße Unterkette hochgestuft wurde,
wird an das Ende der Kette gesetzt. Der Block kreist dann
innerhalb dieser Unterkette. Bleibt der Block lang genug am
Anfang der Unterkette, dann wird er in die warme Unterkette
zurückgestuft. Der Zeitpunkt wird vom Wert der
Schlüssel-Cache-Komponente
key_cache_age_threshold
bestimmt.
Der Schwellwert definiert, dass bei einem Schlüssel-Cache mit
N
Blöcken der am Anfang der
heißen Unterkette stehende Block an den Anfang der warmen
Unterkette gesetzt wird, sofern er nicht innerhalb der letzten
Treffer aufgerufen
wurde. Er wird dann erster Anwärter auf die Räumung, weil
für die Ersetzung vorgesehene Blöcke am Anfang der warmen
Unterkette entfernt werden.
N
×
key_cache_age_threshold / 100
Die Strategie des Einfügens am Mittelpunkt gestattet Ihnen,
Blöcke, die offensichtlich wichtig sind, immer im Cache zu
behalten. Wenn Sie die direkte LRU-Strategie bevorzugen,
belassen Sie den Wert von
key_cache_division_limit
auf der Vorgabe
von 100.
Die Strategie des Einfügens am Mittelpunkt ist hilfreich zur
Leistungssteigerung, wenn die Ausführung einer Abfrage einen
Indexscan erfordert und so im Endeffekt all diejenigen
Indexblöcke aus dem Cache wirft, die wichtigen B-Tree-Knoten
entsprechen. Um dies zu vermeiden, müssen Sie die Strategie
mit einem Wert von deutlich weniger als 100 für
key_cache_division_limit
verwenden, denn so
werden „wertvolle“, häufig gefundene Knoten auch
bei einem Indexscan in der heißen Unterkette gehalten.
Sind genug Blöcke in einem Schlüssel-Cache vorhanden, um die Blöcke eines vollständigen Indexes – oder zumindest die Blöcke, die den Nichtblattknoten entsprechen – aufzunehmen, dann ist es sinnvoll, den Schlüssel-Cache mit den Indexblöcken schon vor der eigentlichen Verwendung vorab zu laden. Dieses Vorabladen gestattet es Ihnen, die Tabellenindexblöcke auf effizienteste Art und Weise in einem Schlüssel-Cache-Puffer abzulegen – nämlich durch sequenzielles Lesen der Indexblöcke von der Festplatte.
Ohne Vorabladen werden die Blöcke so im Schlüssel-Cache abgelegt, wie sie von den Abfragen benötigt werden. Zwar bleiben die Blöcke dann im Cache, weil genug Puffer für sie alle vorhanden sind, aber sie werden dann nicht sequenziell, sondern in zufälliger Abfolge von der Festplatte abgerufen.
Um einen Index vorab in einen Cache zu laden, verwenden Sie
die Anweisung LOAD INDEX INTO CACHE
. Die
folgende Anweisung beispielsweise lädt Knoten (Indexblöcke)
mit Indizes der Tabellen t1
und
t2
:
mysql> LOAD INDEX INTO CACHE t1, t2 IGNORE LEAVES;
+---------+--------------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+---------+--------------+----------+----------+
| test.t1 | preload_keys | status | OK |
| test.t2 | preload_keys | status | OK |
+---------+--------------+----------+----------+
Der Modifizierer IGNORE LEAVES
bewirkt,
dass nur Blöcke für Indexknoten, die nicht Endknoten
(Blätter) sind, geladen werden. Auf diese Weise lädt die
gezeigte Anweisung alle Indexblöcke von
t1
, von t2
hingegen nur
Blöcke für die Nichtblattknoten.
Wenn ein Index mit einer CACHE
INDEX
-Anweisung einem Schlüssel-Cache zugewiesen
wurde, platziert das Vorabladen die Indexblöcke in diesem
Cache. Andernfalls wird der Index in den vorgabeseitigen
Schlüssel-Cache geladen.
Mit der Variablen key_cache_block_size
ist
es möglich, die Größe von Blockpuffern für einen einzelnen
Schlüssel-Cache anzugeben. Auf diese Weise können Sie die
Leistung von I/O-Operationen für Indexdateien optimieren.
Die beste Leistung für I/O-Operationen erhalten Sie, wenn die Größe der Lesepuffer der Größe der I/O-Puffer des nativen Betriebssystems entspricht. Allerdings gewährleistet das Einstellen der Schlüsselknotengröße auf die Größe der I/O-Puffer nicht immer die beste Gesamtperformance. Wenn der Server die großen Blattknoten ausliest, ruft er eine Menge unnötiger Daten ab, wodurch im Endeffekt das Lesen anderer Blattknoten verhindert wird.
Zurzeit lässt sich die Größe der Indexblöcke in einer
Tabelle nicht steuern. Der Größenwert wird vom Server
eingestellt, wenn die .MYI
-Indexdatei
erstellt wird, und hängt von der Größe der Schlüssel in
den in der Tabellendefinition vorhandenen Indizes ab. In den
meisten Fällen ist sie identisch mit der I/O-Puffergröße.
Ein Schlüssel-Cache kann jederzeit durch Änderung seiner Parameterwerte umstrukturiert werden. Zum Beispiel:
mysql> SET GLOBAL cold_cache.key_buffer_size=4*1024*1024;
Wenn Sie den Schlüssel-Cache-Komponenten
key_buffer_size
oder
key_cache_block_size
einen anderen als den
aktuellen Wert zuweisen, zerstört der Server die alte
Struktur des Caches und erstellt eine neue, die auf den
geänderten Werten basiert. Wenn der Cache schmutzige Blöcke
enthält, speichert der Server sie auf der Festplatte, bevor
er den Cache zerstört und neu erstellt. Eine Umstrukturierung
findet hingegen nicht statt, wenn Sie andere
Schlüssel-Cache-Parameter einstellen.
Wenn Sie einen Schlüssel-Cache umstrukturieren, synchronisiert der Server zunächst die Inhalte schmutziger Puffer (soweit vorhanden) auf die Festplatte. Danach ist der Inhalt des Caches nicht mehr verfügbar. Allerdings blockiert die Umstrukturierung keine Abfragen, die dem Cache zugewiesene Indizes verwenden müssen. Stattdessen greift der Server in diesem Fall über das native Dateisystem-Caching direkt auf die Tabellenindizes zu. Das Dateisystem-Caching ist nicht so effizient wie ein Schlüssel-Cache, d. h., die Abfragen werden zwar ausgeführt, aber Sie können von Geschwindigkeitseinbußen ausgehen. Nachdem der Cache umstrukturiert wurde, werden ihm zugewiesene Indizes dort wieder zwischengespeichert, und das Dateisystem-Caching wird nicht mehr für die Indizes verwendet.
Speicher-Engines sammeln tabellenspezifische Statistiken, die der Optimierer verwenden kann. Tabellenstatistiken basieren auf Wertegruppen. Eine Wertegruppe ist eine Menge von Datensätzen mit demselben Schlüsselpräfixwert. Für die Zwecke des Optimierers ist die durchschnittliche Wertegruppengröße eine wichtige Angabe.
MySQL verwendet diese Information,
um zu bestimmen, wie viele Datensätze für jeden
ref
-Zugriff gelesen werden müssen,
um einzuschätzen, wie viele Datensätze ein Teil-Join – oder, genauer, eine Operation der folgenden Form – erzeugt:
(...) JOINtbl_name
ONtbl_name
.key
=expr
Wenn die Durchschnittsgröße der Wertegruppen für einen Index ansteigt, wird der Index für diese beiden Aufgaben zunehmend weniger nützlich, weil auch die durchschnittliche Anzahl von Datensätzen pro Suchvorgang steigt: Damit der Index für Optimierungszwecke gut geeignet ist, wäre es optimal, wenn jeder Indexwert auf eine kleine Anzahl von Datensätzen in der Tabelle abzielt. Hat ein gegebener Indexwert eine hohe Zahl von Datensätzen zum Ergebnis, dann ist sein Nutzen eingeschränkt, und die Wahrscheinlichkeit, dass MySQL ihn verwendet, ist geringer.
Die durchschnittliche Wertegruppengröße bezieht sich auf die
Kardinalität der Tabelle, d. h. die Anzahl der Wertegruppen.
Die SHOW INDEX
-Anweisung zeigt einen
Kardinalitätswert basierend auf N
÷
S
an, wobei
N
die Anzahl der Datensätze in der
Tabelle und S
die durchschnittliche
Wertegruppengröße darstellt. Dieses Verhältnis gibt einen
Näherungswert für die Anzahl der Wertegruppen in der Tabelle
an.
Bei einem Join, der auf dem Vergleichsoperator
<=>
basiert, wird
NULL
nicht anders behandelt als andere Werte:
NULL <=> NULL
(wie
für jeden anderen Wert
N
<=>
N
N
).
Basiert ein Join jedoch auf dem Operator =
,
dann unterscheidet sich NULL
von
Nicht-NULL
-Werten:
ist nicht wahr, wenn
expr1
=
expr2
expr1
oder
expr2
(oder beide)
NULL
sind. Dies wirkt sich auf
ref
-Zugriffe für Vergleiche der Form
aus: MySQL greift
nicht auf die Tabelle zu, wenn der aktuelle Wert von
tbl_name.key
=
expr
expr
NULL
ist,
weil der Vergleich nicht wahr sein kann.
Bei =
-Vergleichen spielt es keine Rolle, wie
viele NULL
-Werte in der Tabelle vorhanden
sind. Der für Optimierungszwecke relevante Wert ist die
Durchschnittsgröße der Gruppe von
Nicht-NULL
-Werten. Allerdings gestattet MySQL
derzeit keine Ermittlung oder Verwendung dieser
Durchschnittsgröße.
Bei MyISAM
-Tabellen haben Sie mit der
Systemvariablen myisam_stats_method
in
eingeschränktem Maße Kontrolle über die Ermittlung der
Tabellenstatistiken. Diese Variable hat zwei mögliche Werte,
die sich wie folgt voneinander unterscheiden:
Wenn myisam_stats_method
nulls_equal
ist, dann werden alle
NULL
-Werte als identisch behandelt
(d. h., sie alle bilden eine Wertegruppe).
Wenn die NULL
-Wertegruppe wesentlich
größer ist als die Durchschnittsgröße der Gruppe der
Nicht-NULL
-Werte, dann erhöht diese
Methode die durchschnittliche Wertegruppengröße. Aufgrund
dessen erscheint der Index dem Optimierer weniger nützlich,
als er es für Joins, die nach
Nicht-NULL
-Werten suchen, tatsächlich
ist. Im Ergebnis kann die
nulls_equal
-Methode also dazu führen,
dass der Optimierer den Index für ref
nicht verwendet, obwohl er es sollte.
Wenn myisam_stats_method
nulls_unequal
ist, werden
NULL
-Werte nicht als identisch
betrachtet. Stattdessen bildet jeder
NULL
-Wert eine separate Wertegruppe der
Größe 1.
Wenn Sie viele NULL
-Werte haben,
verschiebt diese Methode den Durchschnittswert für die
Wertegruppengröße nach unten. Ist der Durchschnittswert
der Gruppe der Nicht-NULL
-Werte hoch,
dann kann dieses Verhalten dazu führen, dass der Optimierer
den Wert des Indexes für Joins überschätzt, die nach
Nicht-NULL
-Werten suchen. Aufgrund dessen
kann der nulls_unequal
-Ansatz dazu
führen, dass der Optimierer diesen Index für
ref
-Suchvorgänge verwendet, obwohl
andere Methoden besser geeignet wären.
Wenn Sie häufig viele Joins benutzen, die
<=>
statt =
verwenden, dann werden NULL
-Werte in
Vergleichen nicht gesondert betrachtet, sondern ein
NULL
-Wert entspricht dem anderen. In diesem
Fall ist nulls_equal
die passende
Statistikmethode.
Die Systemvariable myisam_stats_method
hat
globale und sitzungsbezogene Werte. Das Einstellen des globalen
Werts wirkt sich auf die
MyISAM
-Statistikermittlung bei allen
MyISAM
-Tabellen aus. Im Gegensatz dazu wirkt
der Sitzungswert nur auf Statistiken zur aktuellen
Clientverbindung. Sie können also, indem Sie den Sitzungswert
von myisam_stats_method
einstellen, die
Neuerstellung der Statistiken zu einer Tabelle mit einer
gegebenen Methode erzwingen, ohne dass andere Clients hiervon
beeinträchtigt würden.
Zur Neuerstellung der Tabellenstatistiken können Sie eine der folgenden Methoden benutzen:
Stellen Sie myisam_stats_method
ein und
setzen Sie dann eine CHECK
TABLE
-Anweisung ab.
Führen Sie myisamchk
--stats_method=method_name
--analyze aus.
Ändern Sie die Tabelle so ab, dass die Statistiken veralten
(indem Sie beispielsweise einen Datensatz einfügen und ihn
dann löschen), stellen Sie
myisam_stats_method
ein und setzen Sie
eine ANALYZE TABLE
-Anweisung ab.
Die Verwendung von myisam_stats_method
hat
auch ein paar Nachteile:
Sie können die Ermittlung von Tabellenstatistiken wie gerade
beschrieben erzwingen. Allerdings kann MySQL die Statistiken
auch automatisch sammeln. Wenn beispielsweise während der
Ausführung von Anweisungen für eine Tabelle einige dieser
Anweisungen die Tabelle ändern, ermittelt MySQL unter
Umständen Statistiken. (Dies kann etwa bei Masseneinfüge- oder
-löschoperationen oder bei bestimmten ALTER
TABLE
-Anweisungen der Fall sein.) Wenn dies geschieht,
werden die Statistiken ohne Berücksichtigung des aktuellen
Werts von myisam_stats_method
gesammelt. Wenn
Sie also Statistiken mit einer bestimmten Methode ermitteln,
aber myisam_stats_method
bei einer späteren
automatischen Statistiksammlung auf eine andere Methode gesetzt
wird, dann wird diese andere Methode verwendet.
Es gibt keine Möglichkeit, festzustellen, welche Methode zur
Erzeugung von Statistiken für eine gegebene
MyISAM
-Tabelle verwendet wurde.
myisam_stats_method
gilt nur für
MyISAM
-Tabellen. Die übrigen
Speicher-Engines haben jeweils eigene Methoden zur Ermittlung
von Tabellenstatistiken. Diese ähneln der Methode
nulls_equal
.
Wenn Sie einen mysqladmin status-Befehl ausführen, sollten Sie etwa folgendes Ergebnis erhalten:
Uptime: 426 Running threads: 1 Questions: 11082 Reloads: 1 Open tables: 12
Der Open tables
-Wert von 12 kann etwas
verwirrend sein, wenn Sie nur sechs Tabellen haben.
MySQL arbeitet mit mehreren Threads, d. h., mehrere Clients
setzen unter Umständen gleichzeitig Abfragen für eine gegebene
Tabelle ab. Um das Problem mit mehreren Client-Threads, die
unterschiedliche Zustände bezüglich derselben Tabelle haben,
zu minimieren, wird die Tabelle von allen nebenläufigen Threads
unabhängig geöffnet. Zwar wird hierdurch mehr Speicher
verbraucht, aber in der Regel wird die Leistung verbessert. Bei
MyISAM
-Tabellen ist pro Client, der eine
Tabelle geöffnet hält, ein zusätzlicher Dateideskriptor für
die Datendatei erforderlich. (Dies steht im Gegensatz zum
Indexdateideskriptor, der von allen Threads gemeinsam verwendet
wird.)
Die Systemvariablen table_open_cache
,
max_connections
und
max_tmp_tables
bestimmen die maximale Anzahl
der Dateien, die der Server geöffnet hält. Wenn Sie einen oder
mehrere dieser Werte erhöhen, stoßen Sie unter Umständen auf
ein Limit, das Ihr Betriebssystem bezüglich der
prozessbezogenen Anzahl offener Dateideskriptoren setzt. Viele
Betriebssysteme erlauben Ihnen eine Anhebung der Beschränkung
für offene Dateien, auch wenn sich die jeweilige Methode von
Betriebssystem zu Betriebssystem unterscheidet. Informationen
dazu, ob und wie es möglich ist, diesen Wert anzuheben,
entnehmen Sie der Dokumentation zu Ihrem Betriebssystem.
table_open_cache
bezieht sich auf
max_connections
. So sollten Sie etwa für 200
gleichzeitig laufende Verbindungen einen Tabellen-Cache mit
einer Größe von mindestens 200 ×
haben, wobei
N
N
die maximale Anzahl von Tabellen
pro Join in einer beliebigen von Ihnen ausgeführten Abfrage
ist. Sie müssen ferner einige zusätzliche Dateideskriptoren
für Temporärtabellen und -dateien reservieren.
Stellen Sie sicher, dass Ihr Betriebssystem die Anzahl der mit
der Einstellung von table_open_cache
verbundenen Deskriptoren für offene Dateien verarbeiten kann.
Wenn für table_open_cache
ein zu hoher Wert
eingestellt ist, stehen für MySQL irgendwann unter Umständen
keine Dateideskriptoren mehr zur Verfügung: MySQL verweigert
dann Verbindungen, kann Abfragen nicht ausführen und wird im
Ganzen sehr instabil. Sie müssen ferner berücksichtigen, dass
die MyISAM
-Speicher-Engine zwei
Dateideskriptoren für jede offene Tabelle benötigt. Sie
können die Anzahl der MySQL zur Verfügung stehenden
Dateideskriptoren mit der Startoption
--open-files-limit
für
mysqld_safe erhöhen. Siehe auch
Abschnitt A.2.17, „Datei nicht gefunden“.
Der Cache für die offenen Tabellen wird auf einem Niveau von
table_open_cache
Einträgen gehalten. Der
Standardwert beträgt 64, kann aber mit der Option
--table_open_cache
für
mysqld geändert werden. Beachten Sie, dass
MySQL zur Ausführung von Abfragen vorübergehend auch mehr
Tabellen öffnen kann.
MySQL schließt nicht verwendete Tabellen und entfernt sie aus dem Tabellen-Cache, wenn
der Cache voll ist und ein Thread eine Tabelle zu öffnen versucht, die nicht im Cache enthalten ist,
der Cache mehr als table_open_cache
Einträge enthält und eine Tabelle im Cache von keinem
Thread mehr verwendet wird,
die Tabelle synchronisiert wird. Dies passiert, wenn jemand
eine FLUSH TABLES
-Anweisung absetzt oder
einen der Befehle mysqladmin flush-tables
oder mysqladmin refresh ausführt.
Wenn der Tabellen-Cache Einträge enthält, ermittelt der Server einen zu verwendenden Cache-Eintrag wie folgt:
Tabellen, die zurzeit nicht verwendet werden, werden freigegeben. Hierbei wird mit der Tabelle begonnen, die am längsten nicht verwendet wurde.
Wenn eine neue Tabelle geöffnet werden muss, der Cache aber voll ist und keine Tabelle freigegeben werden kann, dann wird der Cache vorübergehend nach Bedarf erweitert.
Ist der Cache vorübergehend erweitert und eine Tabelle erhält den Status „nicht verwendet“, dann wird diese Tabelle geschlossen und aus dem Cache entfernt.
Eine Tabelle wird für jeden nebenläufigen Zugriff geöffnet.
Das bedeutet, dass die Tabelle zweimal geöffnet werden muss,
wenn zwei Threads auf dieselbe Tabelle zugreifen oder ein Thread
die Tabelle zweimal in derselben Abfrage referenziert
(beispielsweise beim Join einer Tabelle mit sich selbst). Jeder
gleichzeitige Öffnungsvorgang erfordert einen Eintrag im
Tabellen-Cache. Der erste Öffnungsvorgang einer
MyISAM
-Tabelle nimmt zwei Dateideskriptoren
entgegen, nämlich je einen für die Daten- und die Indexdatei.
Jede zusätzliche Verwendung der Tabelle benötigt nur einen
Deskriptor für die Datendatei. Der Deskriptor für die
Indexdateien wird von allen Threads gemeinsam verwendet.
Wenn Sie eine Tabelle mit der Anweisung HANDLER
öffnen, wird
für den Thread ein dediziertes Tabellenobjekt reserviert.
Dieses Tabellenobjekt wird nicht mit anderen Threads gemeinsam
genutzt und wird erst geschlossen, wenn der Thread
tbl_name
OPENHANDLER
aufruft oder beendet wird. In diesem Fall wird
die Tabelle in den Tabellen-Cache zurückgeführt (sofern dieser
nicht voll ist). Siehe auch Abschnitt 13.2.3, „tbl_name
CLOSEHANDLER
“.
Sie können ermitteln, ob Ihr Tabellen-Cache zu klein ist, indem
Sie die Statusvariable Opened_tables
für
mysqld überprüfen:
mysql> SHOW STATUS LIKE 'Opened_tables';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Opened_tables | 2741 |
+---------------+-------+
Wenn der Wert sehr groß ist (und zwar auch dann, wenn Sie nicht
viele FLUSH TABLES
-Anweisungen abgesetzt
haben), dann sollten Sie die Größe des Tabellen-Caches
erhöhen. Siehe auch Abschnitt 5.2.2, „Server-Systemvariablen“,
und Abschnitt 5.2.4, „Server-Statusvariablen“.
Wenn sich viele MyISAM
-Tabellen im selben
Datenbankverzeichnis befinden, verlaufen Operationen wie das
Öffnen, Schließen und Erstellen von Tabellen sehr langsam.
Führen Sie SELECT
-Anweisungen für viele
verschiedene Tabellen aus, dann tritt eine geringe Mehrbelastung
auf, wenn der Tabellen-Cache voll ist, weil für jede Tabelle,
die geöffnet wird, eine andere geschlossen werden muss. Sie
können diese Mehrbelastung verringern, indem Sie den
Tabellen-Cache vergrößern.
Wir beginnen mit den Faktoren auf der Systemebene, weil einige dieser Entscheidungen sehr früh getroffen werden müssen, um einen beträchtlichen Leistungszugewinn zu erzielen. In anderen Fällen kann ein kurzer Blick in diesen Abschnitt ausreichen. Allerdings kann es immer praktisch sein, ein Gespür dafür zu entwickeln, welcher Zugewinn sich durch Änderung von Faktoren auf dieser Ebene erzielen lässt.
Das Betriebssystem, welches verwendet werden soll, ist ein wesentlicher Faktor. Um aus Mehrprozessorrechnern die optimale Leistung zu erzielen, sollten Sie Solaris (aufgrund seiner gut funktionierenden Thread-Implementierung) oder Linux verwenden (weil der Kernel der Versionen 2.4 und höher eine gute SMP-Unterstützung bietet). Beachten Sie, dass ältere Linux-Kernels standardmäßig eine Dateigrößenbeschränkung auf 2 Gbyte aufweisen. Wenn Sie einen solchen Kernel verwenden, Ihre Dateien aber größer werden könnten als 2 Gbyte, dann sollten Sie sich den LFS-Patch (Large File Support) für das ext2-Dateisystem besorgen. Andere Dateisysteme wie ReiserFS und XFS weisen diese Beschränkung auf 2 Gbyte nicht auf.
Bevor Sie MySQL in die Produktion nehmen, sollten Sie es auf der vorgesehenen Plattform testen.
Weitere Tipps:
Wenn Sie genug RAM haben, können Sie in Betracht ziehen, alle Auslagerungsgeräte zu entfernen. Einige Betriebssysteme verwenden unter bestimmten Umständen ein Auslagerungsgerät auch dann, wenn freier Speicher vorhanden ist.
Vermeiden Sie externe Sperren. Seit MySQL 4.0 ist die
externe Sperrung standardmäßig auf allen Systemen
deaktiviert. Mit den Optionen
--external-locking
und
--skip-external-locking
können Sie externe
Sperren explizit aktivieren bzw. deaktivieren.
Beachten Sie, dass die Deaktivierung externer Sperren die Funktionalität von MySQL nicht beeinträchtigt, solange Sie nur einen einzelnen Server ausführen. Denken Sie aber immer daran, den Server abzuschalten (oder die relevanten Tabellen zu sperren und zu synchronisieren), bevor Sie myisamchk ausführen. Auf einigen Systemen ist die Deaktivierung externer Sperren obligatorisch, weil sie dort ohnehin nicht funktionieren.
Der einzige Fall, in dem Sie die externe Sperrung nicht deaktivieren können, liegt vor, wenn Sie mehrere MySQL Server (nicht Clients) mit demselben Datenbestand betreiben, oder wenn Sie mit myisamchk eine Tabelle überprüfen (nicht reparieren), ohne den Server zuvor angewiesen zu haben, die Tabellen zuerst zu sperren und zu synchronisieren. Beachten Sie, dass von der Verwendung mehrerer MySQL Server für den gleichzeitigen Zugriff auf dieselben Daten generell abzuraten ist, sofern Sie nicht MySQL Cluster verwenden.
Die Anweisungen LOCK TABLES
und
UNLOCK TABLES
verwenden interne Sperren,
d. h., Sie können sie auch bei deaktivierter externer
Sperrung verwenden.
Mit dem folgenden Befehl können Sie die standardmäßigen Puffergrößen festlegen, die der Server mysqld verwendet:
shell> mysqld --verbose --help
Dieser Befehl erzeugt eine Liste aller mysqld-Optionen und konfigurierbarer Systemvariablen. Die Ausgabe enthält die Standardwerte der Variablen und sieht etwa so aus:
help TRUE abort-slave-event-count 0 allow-suspicious-udfs FALSE auto-increment-increment 1 auto-increment-offset 1 automatic-sp-privileges TRUE basedir /home/jon/bin/mysql/ bdb FALSE bind-address (No default value) character-set-client-handshake TRUE character-set-server latin1 character-sets-dir /home/jon/bin/mysql/share/mysql/charsets/ chroot (No default value) collation-server latin1_swedish_ci completion-type 0 concurrent-insert 1 console FALSE datadir /home/jon/bin/mysql/var/ default-character-set latin1 default-collation latin1_swedish_ci default-time-zone (No default value) disconnect-slave-event-count 0 enable-locking FALSE enable-pstack FALSE engine-condition-pushdown FALSE external-locking FALSE gdb FALSE large-pages FALSE init-connect (No default value) init-file (No default value) init-slave (No default value) innodb TRUE innodb_checksums TRUE innodb_data_home_dir (No default value) innodb_doublewrite TRUE innodb_fast_shutdown 1 innodb_file_per_table FALSE innodb_flush_log_at_trx_commit 1 innodb_flush_method (No default value) innodb_locks_unsafe_for_binlog FALSE innodb_log_arch_dir (No default value) innodb_log_group_home_dir (No default value) innodb_max_dirty_pages_pct 90 innodb_max_purge_lag 0 innodb_status_file FALSE innodb_table_locks TRUE innodb_support_xa TRUE isam FALSE language /home/jon/bin/mysql/share/mysql/english local-infile TRUE log /home/jon/bin/mysql/var/master1.log log-bin /home/jon/bin/mysql/var/master1 log-bin-index (No default value) log-bin-trust-routine-creators FALSE log-error /home/jon/bin/mysql/var/master1.err log-isam myisam.log log-queries-not-using-indexes FALSE log-short-format FALSE log-slave-updates FALSE log-slow-admin-statements FALSE log-slow-queries (No default value) log-tc tc.log log-tc-size 24576 log-update (No default value) log-warnings 1 low-priority-updates FALSE master-connect-retry 60 master-host (No default value) master-info-file master.info master-password (No default value) master-port 3306 master-retry-count 86400 master-ssl FALSE master-ssl-ca (No default value) master-ssl-capath (No default value) master-ssl-cert (No default value) master-ssl-cipher (No default value) master-ssl-key (No default value) master-user test max-binlog-dump-events 0 memlock FALSE myisam-recover OFF ndbcluster FALSE ndb-connectstring (No default value) ndb-mgmd-host (No default value) ndb-nodeid 0 ndb-autoincrement-prefetch-sz 32 ndb-distibution KEYHASH ndb-force-send TRUE ndb_force_send TRUE ndb-use-exact-count TRUE ndb_use_exact_count TRUE ndb-shm FALSE ndb-optimized-node-selection TRUE ndb-cache-check-time 0 ndb-index-stat-enable TRUE ndb-index-stat-cache-entries 32 ndb-index-stat-update-freq 20 new FALSE old-alter-table FALSE old-passwords FALSE old-style-user-limits FALSE pid-file /home/jon/bin/mysql/var/hostname.pid1 port 3306 relay-log (No default value) relay-log-index (No default value) relay-log-info-file relay-log.info replicate-same-server-id FALSE report-host (No default value) report-password (No default value) report-port 3306 report-user (No default value) rpl-recovery-rank 0 safe-user-create FALSE secure-auth FALSE server-id 1 show-slave-auth-info FALSE skip-grant-tables FALSE skip-slave-start FALSE slave-load-tmpdir /tmp/ socket /tmp/mysql.sock sporadic-binlog-dump-fail FALSE sql-mode OFF symbolic-links TRUE tc-heuristic-recover (No default value) temp-pool TRUE timed_mutexes FALSE tmpdir (No default value) use-symbolic-links TRUE verbose TRUE warnings 1 back_log 50 binlog_cache_size 32768 bulk_insert_buffer_size 8388608 connect_timeout 5 date_format (No default value) datetime_format (No default value) default_week_format 0 delayed_insert_limit 100 delayed_insert_timeout 300 delayed_queue_size 1000 expire_logs_days 0 flush_time 0 ft_max_word_len 84 ft_min_word_len 4 ft_query_expansion_limit 20 ft_stopword_file (No default value) group_concat_max_len 1024 innodb_additional_mem_pool_size 1048576 innodb_autoextend_increment 8 innodb_buffer_pool_awe_mem_mb 0 innodb_buffer_pool_size 8388608 innodb_concurrency_tickets 500 innodb_file_io_threads 4 innodb_force_recovery 0 innodb_lock_wait_timeout 50 innodb_log_buffer_size 1048576 innodb_log_file_size 5242880 innodb_log_files_in_group 2 innodb_mirrored_log_groups 1 innodb_open_files 300 innodb_sync_spin_loops 20 innodb_thread_concurrency 20 innodb_commit_concurrency 0 innodb_thread_sleep_delay 10000 interactive_timeout 28800 join_buffer_size 131072 key_buffer_size 8388600 key_cache_age_threshold 300 key_cache_block_size 1024 key_cache_division_limit 100 long_query_time 10 lower_case_table_names 0 max_allowed_packet 1048576 max_binlog_cache_size 4294967295 max_binlog_size 1073741824 max_connect_errors 10 max_connections 100 max_delayed_threads 20 max_error_count 64 max_heap_table_size 16777216 max_join_size 4294967295 max_length_for_sort_data 1024 max_relay_log_size 0 max_seeks_for_key 4294967295 max_sort_length 1024 max_tmp_tables 32 max_user_connections 0 max_write_lock_count 4294967295 multi_range_count 256 myisam_block_size 1024 myisam_data_pointer_size 6 myisam_max_extra_sort_file_size 2147483648 myisam_max_sort_file_size 2147483647 myisam_repair_threads 1 myisam_sort_buffer_size 8388608 myisam_stats_method nulls_unequal net_buffer_length 16384 net_read_timeout 30 net_retry_count 10 net_write_timeout 60 open_files_limit 0 optimizer_prune_level 1 optimizer_search_depth 62 preload_buffer_size 32768 query_alloc_block_size 8192 query_cache_limit 1048576 query_cache_min_res_unit 4096 query_cache_size 0 query_cache_type 1 query_cache_wlock_invalidate FALSE query_prealloc_size 8192 range_alloc_block_size 2048 read_buffer_size 131072 read_only FALSE read_rnd_buffer_size 262144 div_precision_increment 4 record_buffer 131072 relay_log_purge TRUE relay_log_space_limit 0 slave_compressed_protocol FALSE slave_net_timeout 3600 slave_transaction_retries 10 slow_launch_time 2 sort_buffer_size 2097144 sync-binlog 0 sync-frm TRUE sync-replication 0 sync-replication-slave-id 0 sync-replication-timeout 10 table_open_cache 64 table_lock_wait_timeout 50 thread_cache_size 0 thread_concurrency 10 thread_stack 196608 time_format (No default value) tmp_table_size 33554432 transaction_alloc_block_size 8192 transaction_prealloc_size 4096 updatable_views_with_limit 1 wait_timeout 28800
Wird gerade ein mysqld-Server ausgeführt, dann können Sie die aktuellen Werte seiner Systemvariablen anzeigen, indem Sie eine Verbindung mit ihm herstellen und die folgende Anweisung absetzen:
mysql> SHOW VARIABLES;
Mit der folgenden Anweisung können Sie statistische Informationen und Statusangaben für einen laufenden Server abrufen:
mysql> SHOW STATUS;
Angaben zu Systemvariablen und Status erhalten Sie auch mit mysqladmin:
shell>mysqladmin variables
shell>mysqladmin extended-status
Eine vollständige Beschreibung aller System- und Statusvariablen finden Sie in Abschnitt 5.2.2, „Server-Systemvariablen“, und Abschnitt 5.2.4, „Server-Statusvariablen“.
MySQL verwendet Algorithmen, die sehr gut skalierbar sind, d. h., Sie können MySQL gewöhnlich mit sehr wenig Speicher ausführen. Andererseits erhalten Sie eine umso bessere Performance, je mehr Speicher Sie MySQL zugestehen.
Wenn Sie einen MySQL Server optimieren, dann sind die beiden
wichtigsten zu konfigurierenden Variablen
key_buffer_size
und
table_open_cache
. Sie sollten erst ganz
sicher sein, dass Sie für diese Variablen geeignete Werte
eingestellt haben, bevor Sie andere Variablen zu konfigurieren
versuchen.
Die folgenden Beispiele zeigen einige typische Variablenwerte für verschiedene Laufzeitkonfigurationen.
Wenn Sie mindestens 256 Mbyte Speicher und viele Tabellen haben und für eine moderate Anzahl von Clients die optimale Leistung erzielen wollen, sollten Sie einmal Folgendes probieren:
shell>mysqld_safe --key_buffer_size=64M --table_open_cache=256 \
--sort_buffer_size=4M --read_buffer_size=1M &
Haben Sie nur 128 Mbyte Speicher und nur ein paar Tabellen, die aber häufig sortiert werden müssen, dann können Sie Folgendes ausprobieren:
shell> mysqld_safe --key_buffer_size=16M --sort_buffer_size=1M
Bei sehr vielen gleichzeitigen Problemen können Auslagerungsprobleme auftreten, sofern mysqld nicht für die Verwendung von sehr wenig Speicher für die jeweilige Verbindung konfiguriert wurde. mysqld arbeitet besser, wenn Sie genug Speicher für alle Verbindungen haben.
Bei sehr wenig Speicher und vielen Verbindungen verwenden Sie Folgendes:
shell>mysqld_safe --key_buffer_size=512K --sort_buffer_size=100K \
--read_buffer_size=100K &
Oder sogar Folgendes:
shell>mysqld_safe --key_buffer_size=512K --sort_buffer_size=16K \
--table_open_cache=32 --read_buffer_size=8K \
--net_buffer_length=1K &
Wenn Sie GROUP BY
- oder ORDER
BY
-Operationen an Tabellen durchführen, die
wesentlich größer sind als der verfügbare Speicher, dann
sollten Sie den Wert von read_rnd_buffer_size
erhöhen, um nach Durchführung von Sortieroperationen das
Auslesen von Datensätzen zu beschleunigen.
Wenn Sie MySQL installiert haben, enthält das Verzeichnis
support-files
eine Anzahl verschiedener
my.cnf
-Beispieldateien, nämlich
my-huge.cnf
,
my-large.cnf
,
my-medium.cnf
und
my-small.cnf
. Diese können Sie als Basis
zur Optimierung Ihres Systems verwenden. (Unter Windows schauen
Sie im MySQL-Installationsverzeichnis nach.)
Wenn Sie für mysqld oder mysqld_safe eine Option auf der Befehlszeile angeben, ist diese nur für den betreffenden Aufruf des Servers gültig. Um diese Option jedes Mal bei Ausführung des Servers zu verwenden, müssen Sie sie in einer Optionsdatei ablegen.
Um die Wirkung einer Parameteränderung zu prüfen, können Sie Folgendes tun:
shell> mysqld --key_buffer_size=32M --verbose --help
Die Variablenwerte sind kurz vor Ende der Ausgabe aufgeführt.
Vergewissern Sie sich, dass die Optionen
--verbose
und --help
am Ende
stehen. Andernfalls werden die Auswirkungen von Optionen, die
nach diesen beiden Optionen auf der Befehlszeile angegeben
wurden, in der Ausgabe nicht berücksichtigt.
Informationen zur Optimierung der
InnoDB
-Speicher-Engine finden Sie in
Abschnitt 14.2.11, „Tipps zur Leistungssteigerung“.
Die Aufgabe des Abfrageoptimierers besteht darin, einen optimalen Plan für die Ausführung einer SQL-Abfrage zu entwickeln. Da der Unterschied zwischen „gut“ und „schlecht“ aus leistungstechnischer Sicht mehrere Größenordnungen betragen kann (d. h. Sekunden im Vergleich zu Stunden oder sogar Tagen), führten die meisten Abfrageoptimierer (einschließlich des MySQL-Optimierers) unter allen möglichen Plänen zur Abfragebewertung eine mehr oder minder umfangreiche Suche nach dem optimalen Plan durch. Bei Join-Abfragen wächst die Anzahl möglicher Pläne, die vom MySQL-Optimierer untersucht werden, exponentiell mit der Anzahl der Tabellen, die in einer Abfrage referenziert werden. Bei einer kleinen Anzahl von Tabellen (etwa 7 bis 10) ist dies unproblematisch. Werden hingegen größere Abfragen abgesetzt, dann kann die für die Abfrageoptimierung erforderliche Zeit schnell zum Engpass für die Leistung des Servers werden.
Eine flexiblere Methode zur Abfrageoptimierung gewährt dem Benutzer Kontrolle darüber, wie erschöpfend der Optimierer bei der Suche nach einem optimalen Abfragebewertungsplan vorgeht. Hintergedanke ist, dass umso weniger Zeit für die Kompilierung einer Abfrage aufgewendet wird, je weniger Pläne vom Optimierer untersucht werden. Andererseits kann es sein, dass der Optimierer, weil er einige Pläne überspringt, den optimalen Plan übersieht.
Das Verhalten des Optimierers in Bezug auf die Anzahl der Pläne, die er bewertet, kann über zwei Systemvariablen gesteuert werden:
Die Variable optimizer_prune_level
weist
den Optimierer an, bestimmte Pläne basierend auf der
geschätzten Anzahl der Datensätze, auf die pro Tabelle
zugegriffen wird, zu übergehen. Unsere Erfahrung zeigt,
dass diese Art der „begründeten Annahme“
optimale Pläne nur in sehr seltenen Fällen verfehlt. Aus
diesem Grund ist die Option standardmäßig aktiviert
(optimizer_prune_level=1
). Wenn Sie
allerdings das Gefühl haben, dass der Optimierer einen
besseren Abfrageplan hätte finden können, dann können Sie
die Option auch abschalten
(optimizer_prune_level=0
); allerdings
besteht dann das Risiko, dass die Abfragekompilierung
deutlich länger dauert. Beachten Sie, dass der Optimierer
auch bei Verwendung dieser Heuristik eine grob exponentielle
Anzahl von Plänen untersucht.
Die Variable optimizer_search_depth
sagt
dem Optimierer, wie weit er bei unvollständigen Plänen
„vorausschauen“ soll, um einzuschätzen, ob ein
Plan erweitert werden soll. Niedrige Werte für
optimizer_search_depth
führen zu um
mehrere Größenordnungen kürzeren
Abfragekompilierungszeiten. So kann die Kompilierung von
Abfragen mit 12, 13 oder mehr Tabellen leicht Stunden oder
sogar Tage dauern, wenn
optimizer_search_depth
einen Wert hat,
der annähernd der Anzahl der Tabellen in der Abfrage
entspricht. Umgekehrt benötigt der Compiler für dieselbe
Abfrage noch nicht einmal eine Minute, wenn
optimizer_search_depth
den Wert 3 oder 4
hat. Wenn Sie nicht sicher sind, welcher Wert für
optimizer_search_depth
sinnvoll sein
könnte, können Sie ihn auf 0 setzen; so weisen Sie den
Optimierer an, den Wert automatisch zu ermitteln.
Die meisten der folgenden Tests wurden unter Linux mit den MySQL-Benchmarks durchgeführt, sie sollten aber trotzdem ausreichend aussagekräftig auch für andere Betriebssysteme und Belastungsbereiche sein.
Sie erhalten die schnellsten ausführbaren Dateien, indem Sie
mit der Option -static
verknüpfen.
Unter Linux kompilieren Sie den Server am besten mit
pgcc und -O3
. Sie benötigen
etwa 200 Mbyte Speicher zur Kompilierung von
sql_yacc.cc
mit diesen Optionen, weil
gcc oder pgcc eine Menge
Speicher benötigt, um alle Funktionen zu integrieren. Ferner
sollten Sie bei der Konfiguration von MySQL
CXX=gcc
einstellen, um die Miteinbeziehung
der Bibliothek libstdc++
zu vermeiden, denn
diese wird nicht benötigt. Beachten Sie, dass bei einigen
Versionen von pgcc die resultierende
Binärdatei nur auf echten Pentium-Prozessoren läuft, auch wenn
Sie eine Compileroption verwendet haben, mit der Sie angeben
wollten, dass der Ergebniscode auf allen x586-Prozessoren
(z. B. AMD) laufen soll.
Sie können eine Geschwindigkeitszunahme von 10 bis 30 Prozent erzielen, indem Sie einen besseren Compiler und geeignetere Kompilierungsoptionen verwenden. Dies ist besonders wichtig, wenn Sie den MySQL Server selbst kompilieren.
Als wir die Cygnus CodeFusion- und Fujitsu-Compiler testeten, stellte sich heraus, dass keiner von diesen ausreichend wenig Bugs aufwies, um MySQL mit aktivierten Optimierungen zu kompilieren.
MySQL-Standarddistributionen werden mit der Unterstützung für
alle Zeichensätze kompiliert. Wenn Sie MySQL selbst
kompilieren, sollten Sie die Unterstützung nur für diejenigen
Zeichensätze integrieren, die Sie tatsächlich verwenden
werden. Dies wird mit der Option --with-charset
für configure gesteuert.
Es folgt eine Liste einiger Maßnahmen, die wir vorgenommen haben:
Wenn Sie pgcc verwenden und alles mit
-O6
kompilieren, ist der Server
mysqld um ein Prozent schneller als mit
gcc 2.95.2.
Wenn Sie dynamisch verknüpfen (also ohne
-static
), ist das Ergebnis unter Linux um
13 Prozent langsamer. Beachten Sie, dass Sie eine dynamisch
verknüpfte MySQL-Bibliothek weiterhin für Ihre
Clientanwendungen benutzen können. Es ist der Server, der
für die Leistungsfähigkeit die kritischste Komponente
darstellt.
Wenn Sie Ihre mysqld-Binärdatei mit
strip mysqld
bearbeiten, kann die
resultierende Binärdatei um bis zu 4 Prozent schneller
sein.
Bei einer Verbindung von einem Client zu einem Server, der
auf demselben Host läuft, ist die Leistung um 7,5 Prozent
geringer, wenn Sie die Verbindung über TCP/IP statt über
eine Unix-Socketdatei herstellen. (Unter Unix verwendet
MySQL, wenn Sie die Verbindung zum Hostnamen
localhost
herstellen, standardmäßig
eine Socketdatei.)
TCP/IP-Verbindungen von einem Client mit einem Server sind um 8 bis 11 Prozent langsamer, wenn der Server auf einem entfernten System liegt, als bei Verbindung mit einem Server auf demselben Host (und zwar auch bei Verbindungen über 100-Mbit/s-Ethernet).
Bei Ausführung unserer Benchmark-Tests über sichere Verbindungen (d. h., alle Daten wurden durch die interne SSL-Unterstützung verschlüsselt) war die Leistung um 55 Prozent geringer als bei unverschlüsselten Verbindungen.
Wenn Sie mit --with-debug=full
kompilieren,
sind die meisten Abfragen 20 Prozent langsamer. Einige
Abfragen können deutlich länger benötigen; so laufen die
MySQL-Benchmarks um 35 Prozent langsamer. Wenn Sie
--with-debug
(ohne
=full
) angeben, liegt der
Geschwindigkeitsverlust lediglich bei 15 Prozent. Bei einer
Version von mysqld, die mit
--with-debug=full
kompiliert wurde, können
Sie die Speicherüberprüfung zur Laufzeit abschalten, indem
Sie sie mit der Option --skip-safemalloc
starten. Die Ausführungsgeschwindigkeit sollte in diesem
Fall nicht allzu weit unter derjenigen liegen, die sich bei
einer Konfiguration mit --with-debug
erzielen lässt.
Auf einem Sun UltraSPARC-IIe ist ein mit Forte 5.0 kompilierter Server 4 Prozent schneller als ein mit gcc 3.2 kompilierter Server.
Auf einem Sun UltraSPARC-IIe ist ein mit Forte 5.0 kompilierter Server im 32-Bit-Modus 4 Prozent schneller als im 64-Bit-Modus.
Die Kompilierung mit gcc 2.95.2 für
UltraSPARC mit den Optionen
-mcpu=v8 -Wa
und -xarch=v8plusa
bietet einen
Leistungszuwachs von 4 Prozent.
Auf Solaris 2.5.1 ist MIT-pthreads 8 bis 12 Prozent langsamer als native Solaris-Threads auf einem einzelnen Prozessor. Bei hoher Belastung oder mehr Prozessoren sollte der Unterschied noch größer sein.
Die Kompilierung auf Linux-x86 mit gcc
ohne Frame-Zeiger (-fomit-frame-pointer
oder -fomit-frame-pointer -ffixed-ebp
)
macht mysqld 1 bis 4 Prozent schneller.
Von MySQL AB angebotene MySQL-Binärdistributionen für Linux wurden früher generell mit pgcc kompiliert. Aufgrund eines Bugs in pgcc, der dazu führte, dass die erzeugten Binärdateien nicht auf AMD-Prozessoren liefen, mussten wir jedoch zu gcc zurückkehren. Wir werden gcc weiterhin verwenden, bis dieser Bug behoben ist. In der Zwischenzeit können Sie, wenn Sie kein AMD-System haben, durch Kompilierung mit pgcc eine schnellere Binärdatei erstellen. Die MySQL-Standardbinärdatei für Linux ist statisch verknüpft, um Geschwindigkeit und Portabilität zu optimieren.
Die folgende Liste gibt einige Möglichkeiten an, wie der mysqld-Server Speicher verwendet. Sofern anwendbar, wird der Name der Systemvariablen angegeben, die für die Speichernutzung relevant ist:
Der Schlüsselpuffer (Variable
key_buffer_size
) wird von allen Threads
gemeinsam verwendet. Andere Puffer, die der Server benutzt,
werden nach Bedarf zugewiesen. Siehe auch
Abschnitt 7.5.2, „Serverparameter feineinstellen“.
Jede Verbindung verwendet mehrere Thread-spezifische Bereiche:
einen Stapel (standardmäßig 192 Kbyte groß, Variable
thread_stack
)
einen Verbindungspuffer (Variable
net_buffer_length
)
einen Ergebnispuffer (Variable
net_buffer_length
)
Verbindungs- und Ergebnispuffer werden nach Bedarf dynamisch
bis auf den durch max_allowed_packet
angegebenen Wert vergrößert. Während der Ausführung
einer Abfrage wird eine Kopie des aktuellen Abfrage-Strings
ebenfalls reserviert.
Alle Threads verwenden denselben Basisspeicher.
Wenn ein Thread nicht mehr benötigt wird, wird der ihm zugewiesene Speicher freigegeben und dem System zurückgegeben, sofern der Thread nicht zurück in den Thread-Cache wandert (in diesem Fall bleibt der Speicher reserviert).
Vor MySQL 5.1.4 wurden nur für komprimierte
MyISAM
-Tabellen Speicher zugeordnet. Seit
MySQL 5.1.4 lässt sich die Systemvariable
myisam_use_mmap
auf 1 setzen, um die
Speicherzuordnung für alle
MyISAM
-Tabellen zu aktivieren.
Abschnitt 5.2.2, „Server-Systemvariablen“.
Jede Anforderung, die einen sequenziellen Scan einer Tabelle
durchführt, reserviert einen
Lesepuffer (Variable
read_buffer_size
).
Beim Lesen von Datensätzen in willkürlicher Folge (z. B.
nach einer Sortierung) kann ein
Zufallslesepuffer reserviert werden,
um Festplattenzugriffe zu umgehen (Variable
read_rnd_buffer_size
).
Alle Joins werden in einem einzigen Durchlauf ausgeführt,
und die meisten Joins können sogar ohne Temporärtabelle
erledigt werden. Die meisten Temporärtabellen sind
speicherbasierte Hash-Tabellen. Temporärtabellen mit einer
großen Datensatzlänge (berechnet als Summe aller
Spaltenlängen) oder solche, die
BLOB
-Spalten enthalten, werden auf der
Festplatte gespeichert.
Wenn eine interne HEAP-Tabelle die durch
tmp_table_size
angegebene Größe
überschreitet, macht MySQL die HEAP-Tabelle im Speicher
nach Bedarf automatisch zu einer festplattenbasierten
MyISAM
-Tabelle. Sie können auch die
Größe der Temporärtabelle erhöhen, indem Sie die
mysqld-Option
tmp_table_size
oder die SQL-Option
SQL_BIG_TABLES
im Clientprogramm
einstellen. Siehe auch Abschnitt 13.5.3, „SET
“.
Die meisten Anforderungen, die eine Sortierung durchführen, reservieren einen Sortierpuffer und abhängig von der Größe der Ergebnismenge null bis zwei Temporärdateien. Siehe auch Abschnitt A.4.4, „Wohin MySQL temporäre Dateien speichert“.
Praktisch die gesamte Analyse und Berechnung erfolgt in
einem lokalen Speicherbereich. Bei kleinen Elementen ist
keine Speichermehrbelastung gegeben, d. h., die normale
langsame Speicherreservierung und -freigabe werden umgangen.
Speicher wird nur für unerwartet große Strings reserviert.
Dies wird mit malloc()
und
free()
bewerkstelligt.
Für jede MyISAM
-Tabelle, die geöffnet
wird, wird die Indexdatei einmal geöffnet. Die Datendatei
wird für jeden gleichzeitig laufenden Thread einmal
geöffnet. Für jeden nebenläufigen Thread werden eine
Tabellenstruktur, Spaltenstrukturen für jede Spalte und ein
Puffer der Größe 3 ×
reserviert. (Hierbei
ist N
N
die maximale
Datensatzlänge abzüglich vorhandener
BLOB
-Spalten.) Eine
BLOB
-Spalte erfordert fünf bis acht Byte
zuzüglich der Länge der BLOB
-Daten. Die
MyISAM
-Speicher-Engine unterhält einen
zusätzlichen Puffer zur internen Verwendung.
Bei Tabellen mit BLOB
-Spalten wird ein
Puffer dynamisch vergrößert, um größere
BLOB
-Werte einlesen zu können. Wenn Sie
eine Tabelle scannen, wird ein Puffer reserviert, der so
groß ist wie der größte BLOB
-Wert.
Handler-Strukturen für alle in Verwendung befindlichen Tabellen werden in einem Cache gespeichert und als FIFO verwaltet. Standardmäßig hat der Cache 64 Einträge. Wenn eine Tabelle von zwei laufenden Threads gleichzeitig verwendet wurde, enthält der Cache zwei Einträge für die Tabelle. Siehe auch Abschnitt 7.4.8, „Nachteile der Erzeugung großer Mengen von Tabellen in derselben Datenbank“.
Eine FLUSH TABLES
-Anweisung oder der
Befehl mysqladmin flush-tables schließt
alle Tabellen, die gerade nicht verwendet werden, und
kennzeichnet alle in Verwendung befindlichen Tabellen, damit
diese geschlossen werden, sobald der ausführende Thread
endet. Hierdurch wird der größte Teil des in Verwendung
befindlichen Speichers freigegeben. FLUSH
TABLES
wird erst abgeschlossen, wenn alle Tabellen
geschlossen wurden.
ps und andere Systemstatusprogramme melden
unter Umständen, dass mysqld viel Speicher
benötigt. Dies kann von Thread-Stapeln an verschiedenen
Speicheradressen verursacht werden. Die Solaris-Version von
ps beispielsweise zählt die Menge des nicht
verwendeten Speichers zwischen den Stapeln als verwendeten
Speicher. Sie können dies überprüfen, indem Sie den
verfügbaren Auslagerungsspeicher mit swap -s
verifizieren. Wir testen mysqld mit
verschiedenen Speicherleckdetektoren (sowohl kommerzieller als
auch freier Herkunft), d. h., es sollten keine Speicherlecks
vorhanden sein.
Wenn ein neuer Client eine Verbindung mit mysqld herstellt, dann erzeugt mysqld einen neuen Thread, um die Anforderung zu bearbeiten. Dieser Thread überprüft zunächt, ob der Hostname sich im Hostnamens-Cache befindet. Ist dies nicht der Fall, dann versucht der Thread, den Hostnamen aufzulösen:
Wenn das Betriebssystem die Thread-sicheren Aufrufe
gethostbyaddr_r()
und
gethostbyname_r()
unterstützt, führt
der Thread unter ihrer Verwendung die Hostnamensauflösung
durch.
Unterstützt das Betriebssystem die Thread-sicheren Aufrufe
nicht, dann sperrt der Thread ein Mutex und ruft stattdessen
gethostbyaddr()
und
gethostbyname()
auf. In diesem Fall kann
ein anderer Thread Hostnamen, die nicht im Hostnamens-Cache
vorhanden sind, erst auflösen, wenn der erste Thread das
Mutex wieder aufgehoben hat.
Sie können DNS-Lookups für Hostnamen deaktivieren, indem Sie
mysqld mit der Option
--skip-name-resolve
starten. Allerdings können
Sie in diesem Fall nur IP-Adressen in den MySQL-Grant-Tabellen
verwenden.
Wenn Ihr DNS sehr langsam ist und Sie viele Hosts haben, können
Sie die Leistung steigern, indem Sie entweder DNS-Lookups mit
--skip-name-resolve
deaktivieren oder den
HOST_CACHE_SIZE
-Wert (Standard: 128) erhöhen
und mysqld neu kompilieren.
Sie können den Hostnamens-Cache deaktivieren, indem Sie den
Server mit der Option --skip-host-cache
starten. Um den Cache zu leeren, setzen Sie eine FLUSH
HOSTS
-Anweisung ab oder führen den Befehl
mysqladmin flush-hosts aus.
Wenn Sie TCP/IP-Verbindungen vollständig deaktivieren wollen,
starten Sie mysqld mit der Option
--skip-networking
.
Suchvorgänge auf der Festplatte stellen einen für die Leistung beträchtlichen Engpass dar. Dieses Problem wird in dem Moment umso offensichtlicher, wenn die Datenmengen so groß werden, dass ein effizientes Caching unmöglich wird. Bei großen Datenbanken, bei denen der Datenzugriff mehr oder weniger zufällig erfolgt, können Sie sich darauf verlassen, dass Sie mindestens einen Lese- und mehrere Suchvorgänge benötigen, um Daten zu schreiben. Um dieses Problem zu verringern, sollten Sie Festplatten mit schnellen Zugriffszeiten verwenden.
Erhöhen Sie die Anzahl der verfügbaren Festplattenspindeln (und verringern Sie dadurch die Suchbelastung), indem Sie entweder Dateien auf anderen Festplatten symbolisch verknüpfen oder das Striping verwenden:
Symbolische Verknüpfungen
Sie verknüpfen die Index- und Datendateien von
MyISAM
-Tabellen von ihren normalen
Positionen im Datenverzeichnis aus auf eine andere
Festplatte (für die zudem das Striping angewendet werden
kann). Hierdurch werden Such- und Lesezeiten verkürzt
(vorausgesetzt, die Festplatte wird nicht noch für andere
Zwecke verwendet). Siehe auch
Abschnitt 7.6.1, „Symbolische Verknüpfungen“.
Striping bedeutet, dass Sie viele Festplatten haben und
den ersten Block auf der ersten Festplatte, den zweiten
Block auf der zweiten und den
N
-ten Block auf der Festplatte
mit der Nummer
ablegen. Wenn Ihre normale Datengröße also geringer ist
als die Stripe-Größe (oder perfekt angepasst ist), dann
erhalten Sie eine wesentlich bessere Performance. Das
Striping hängt sehr stark vom Betriebssystem und der
Stripe-Größe ab. Insofern sollten Sie Benchmark-Tests
Ihrer Anwendung mit verschiedenen Stripe-Größen
durchführen. Siehe auch
Abschnitt 7.1.5, „Wie Sie Ihre eigenen Benchmarks benutzen“.
N
MOD
number_of_disks
Der Geschwindigkeitsunterschied für das Striping hängt in erheblichem Maße von den Parametern ab. Je nachdem, wie Sie Ihre Striping-Parameter einstellen und über wie viel Festplatten Sie verfügen, können die Unterschiede mehrere Größenordnungen betragen. Sie müssen sich entscheiden, ob Sie die Optimierung für den wahlfreien oder den sequenziellen Zugriff durchführen wollen.
Aus Gründen der Zuverlässigkeit sollten Sie RAID 0+1
(Striping plus Spiegelung) verwenden, allerdings benötigen
Sie in diesem Fall 2 × N
Laufwerke, um N
Laufwerke mit Daten
aufzunehmen. Dies ist die wahrscheinlich beste Option, sofern
Sie über das nötige Kleingeld verfügen. Allerdings müssen
Sie unter Umständen in eine Volumeverwaltungssoftware
investieren, um ein solches Setup effizient steuern zu
können.
Empfehlenswert ist auch der Ansatz, den RAID-Level
entsprechend der Wichtigkeit der Daten zu variieren. So
können Sie etwa Daten moderater Wichtigkeit, die sich
wiederherstellen lassen, auf einer RAID-0-Festplatte
speichern, wirklich wichtige Daten (z. B. Hostinformationen
und Logdateien) hingegen auf einer RAID 0+1- oder einer
RAID-N
-Festplatte ablegen. RAID
N
kann problematisch werden, wenn
Sie viele Schreibvorgänge haben, da die Aktualisierung der
Paritätsbits zeitaufwändig werden kann.
Unter Linux können Sie deutlich mehr Leistung erzielen, indem
Sie die Schnittstelle Ihrer Festplatte mit
hdparm
konfigurieren. (Bis zu 100 Prozent
unter Last sind nicht ungewöhnlich.) Die folgenden
hdparm
-Optionen sollten für MySQL – und
auch für viele andere Anwendungen – recht gut geeignet
sein:
hdparm -m 16 -d 1
Beachten Sie, dass, wenn Sie diesen Befehl verwenden, Leistung
und Zuverlässigkeit von Ihrer Hardware abhängen; aus diesem
Grund empfehlen wir Ihnen dringend, Ihr System nach der
Verwendung von hdparm
umfassend zu testen.
Weitere Informationen entnehmen Sie der
hdparm
-Manpage. Die unvorsichtige
Verwendung von hdparm
kann zu Schäden am
Dateisystem führen! Erstellen Sie deswegen immer ein Backup,
bevor Sie zu experimentieren beginnen.
Ferner können Sie die Parameter für das von der Datenbank verwendete Dateisystem einstellen:
Wenn Sie nicht wissen müssen, wann zuletzt auf die Dateien
zugegriffen wurde (was bei einem Datenbankserver eigentlich
auch nicht wichtig ist), dann können Sie Ihre Dateisysteme
mit der Option -o noatime
einbinden.
Hierdurch werden Updates bis zum letzten Zugriffszeitpunkt in
Inoden auf dem Dateisystem übersprungen, wodurch einige
Suchvorgänge auf der Festplatte unnötig werden.
Bei vielen Betriebssystemen können Sie für ein Dateisystem
eine asynchrone Aktualisierung konfigurieren; hierzu binden
Sie es mit der Option -o async
ein. Wenn Ihr
Computer ausreichend stabil ist, sollten Sie auf diese Weise
mehr Performance erhalten, ohne zu viel Zuverlässigkeit zu
opfern. (Unter Linux ist dieses Flag standardmäßig aktiv.)
Sie können Tabellen und Datenbanken aus dem Datenbankverzeichnis an andere Positionen verschieben und sie durch symbolische Verknüpfungen auf diese neuen Positionen ersetzen. Sie könnten dies beispielsweise tun, um eine Datenbank auf ein Dateisystem mit mehr freiem Speicher zu verschieben oder die Geschwindigkeit Ihres Systems durch Verteilen Ihrer Tabellen auf verschiedene Festplatten zu erhöhen.
Die empfohlene Vorgehensweise hierfür besteht schlicht darin, für Datenbanken symbolische Verknüpfungen auf eine andere Festplatte zu erstellen. Symbolische Verknüpfungen für Tabellen sollten hingegen nur als letzter Ausweg verwendet werden.
Unter Unix erstellen Sie eine symbolische Verknüpfung mit einer Datenbank, indem Sie zuerst ein Verzeichnis auf einer Festplatte erstellen, auf der sich genug freier Speicher befindet, und dann eine symbolische Verknüpfung zu diesem Verzeichnis aus dem MySQL-Datenverzeichnis einrichten.
shell>mkdir /dr1/databases/test
shell>ln -s /dr1/databases/test
/path/to/datadir
MySQL unterstützt Verknüpfungen von einem Verzeichnis auf
mehrere Datenbanken nicht. Das Ersetzen eines
Datenbankverzeichnisses durch eine symbolische Verknüpfung
funktioniert, solange Sie keine symbolischen Verknüpfungen
zwischen Datenbanken erstellen. Angenommen, Sie haben eine
Datenbank db1
im MySQL-Datenverzeichnis und
erstellen dann eine symbolische Verknüpfung
db2
, die auf db1
zeigt:
shell>cd
shell>/path/to/datadir
ln -s db1 db2
Im Ergebnis scheint für jede Tabelle tbl_a
in db1
offenbar auch eine Tabelle
tbl_a
in db2
vorhanden
zu sein. Wenn ein Client db1.tbl_a
und ein
anderer Client db2.tbl_a
aktualisiert, sind
Probleme vorprogrammiert.
Wenn Sie dies aber wirklich tun müssen, ist es möglich,
indem Sie die Quelldatei
mysys/my_symlink.c
ändern. Suchen Sie
dort nach folgender Anweisung:
if (!(MyFlags & MY_RESOLVE_LINK) || (!lstat(filename,&stat_buff) && S_ISLNK(stat_buff.st_mode)))
Ändern Sie diese wie folgt ab:
if (1)
Auf Systemen, die keinen vollständig funktionsfähigen
realpath()
-Aufruf aufweisen, sollten Sie
Tabellen nicht symbolisch verknüpfen. (Linux und Solaris
unterstützen realpath()
.) Sie können
überprüfen, ob Ihr System symbolische Verknüpfungen
unterstützt, indem Sie eine SHOW VARIABLES LIKE
'have_symlink'
-Anweisung absetzen.
Symbolische Verknüpfungen werden nur bei
MyISAM
-Tabellen vollständig unterstützt.
Bei Dateien, die von auf anderen Speicher-Engines basierenden
Tabellen verwendet werden, werden Sie seltsame Probleme
bekommen, wenn Sie versuchen, symbolische Verknüpfungen zu
verwenden.
Die Verarbeitung symbolischer Verknüpfungen für
MyISAM
-Tabellen funktioniert wie folgt:
Im Datenverzeichnis befinden sich immer die
Tabellenformatdatei (.frm
-Datei), die
Datendatei (.MYD
-Datei) und die
Indexdatei (.MYI
-Datei). Die Daten-
und die Indexdatei können an eine andere Position
verschoben und durch symbolische Verknüpfungen im
Datenverzeichnis ersetzt werden. Für die Formatdatei ist
dies nicht möglich.
Sie können die Daten- und die Indexdatei separat in verschiedene Verzeichnisse verschieben und durch Verknüpfungen ersetzen.
Sie können einen laufenden MySQL Server anweisen, die
symbolischen Verknüpfungen mithilfe der Optionen
DATA DIRECTORY
und INDEX
DIRECTORY
für CREATE TABLE
zu erstellen. Siehe auch Abschnitt 13.1.5, „CREATE TABLE
“.
Alternativ können die Verknüpfungen mithilfe von
ln -s
auch manuell über die
Befehlszeile eingerichtet werden, wenn
mysqld nicht ausgeführt wird.
myisamchk ersetzt eine symbolische Verknüpfung nicht durch die Daten- oder Indexdatei, sondern bearbeitet direkt die Datei, auf die die Verknüpfung verweist. Temporärdateien werden in dem Verzeichnis erstellt, in dem sich die Daten- bzw. Indexdatei befindet.
Hinweis: Wenn Sie eine
Tabelle löschen, die symbolische Verknüpfungen erstellt,
dann werden sowohl die Verknüpfung als auch die
Datei, auf die die Verknüpfung verweist,
gelöscht. Dies ist ein ausgesprochen triftiger
Grund, warum Sie mysqld
nicht als root
des
Systems ausführen oder Benutzern Schreibzugriff auf die
MySQL-Datenbankverzeichnisse gewähren sollten.
Wenn Sie eine Tabelle mit ALTER TABLE …
RENAME
umbenennen und sie nicht in einer
Datenbank verschieben, werden die symbolischen
Verknüpfungen im Datenbankverzeichnis auf die neuen Namen
umgestellt und die Daten- und Indexdatei entsprechend
umbenannt.
Verwenden Sie ALTER TABLE …
RENAME
zur Verschiebung einer Tabelle in eine
andere Datenbank, dann wird die Tabelle in das andere
Datenbankverzeichnis verschoben. Die alten Verknüpfungen
und die Dateien, auf die sie verwiesen, werden gelöscht.
Dies bedeutet, dass es für die neue Tabelle keine
symbolische Verknüpfung gibt.
Wenn Sie keine symbolischen Verknüpfungen verwenden,
sollten Sie die Option
--skip-symbolic-links
für
mysqld einsetzen, um zu gewährleisten,
dass niemand mit mysqld eine Datei
außerhalb des Datenverzeichnisses löschen oder
umbenennen kann.
Die folgenden tabellenbezogenen Operationen in Verbindung mit symbolischen Verknüpfungen werden noch nicht unterstützt:
ALTER TABLE
ignoriert die
Tabellenoptionen DATA DIRECTORY
und
INDEX DIRECTORY
.
BACKUP TABLE
und RESTORE
TABLE
beachten symbolische Verknüpfungen nicht.
Die .frm
-Datei darf
niemals eine symbolische Verknüpfung
sein (wie oben bereits angemerkt; nur Daten- und
Indexdateien dürfen symbolische Verknüpfungen sein).
Wenn Sie dies trotzdem versuchen (um beispielsweise
Synonyme zu erstellen), dann erhalten Sie falsche
Ergebnisse. Angenommen, Sie haben eine Datenbank
db1
im MySQL-Datenverzeichnis und eine
Tabelle tbl1
in dieser Datenbank. Nun
erstellen Sie im Verzeichnis db1
eine
symbolische Verknüpfung tbl2
, die auf
tbl1
verweist:
shell>cd
shell>/path/to/datadir
/db1ln -s tbl1.frm tbl2.frm
shell>ln -s tbl1.MYD tbl2.MYD
shell>ln -s tbl1.MYI tbl2.MYI
Probleme treten auf, wenn ein Thread
db1.tbl1
liest und ein anderer
db1.tbl2
aktualisiert:
Der Abfrage-Cache wird „hintergangen“
(denn er kann nicht wissen, dass
tbl1
nicht geändert wurde, und
gibt aufgrund dessen veraltete Ergebnisse zurück).
ALTER
-Anweisungen für
tbl2
schlagen ebenfalls fehl.
Symbolische Verknüpfungen sind standardmäßig auf allen
Windows-Servern aktiv. Auf diese Weise können Sie ein
Datenbankverzeichnis auf eine andere Festplatte verschieben,
indem Sie eine Verknüpfung darauf erstellen. Dies ähnelt der
Art und Weise, wie symbolische Verknüpfungen unter Unix
funktionieren, auch wenn die Vorgehensweise zur Einrichtung
der Verknüpfung eine andere ist. Wenn Sie keine symbolischen
Verknüpfungen benötigen, können Sie sie mit der Option
--skip-symbolic-links
deaktivieren.
Unter Windows erstellen Sie eine Verknüpfung mit einer
MySQL-Datenbank, indem Sie eine Datei im Datenverzeichnis
anlegen, die den Pfad zum Zielverzeichnis enthält. Diese
Datei sollte
heißen, wobei db_name
.symdb_name
der Name der
Datenbank ist.
Angenommen, das MySQL-Datenverzeichnis heißt
C:\mysql\data
. Nun wollen Sie, dass die
Datenbank foo
auf
D:\data\foo
abgelegt wird. Gehen Sie wie
folgt vor, um eine symbolische Verknüpfung zu erstellen:
Vergewissern Sie sich, dass das Verzeichnis
D:\data\foo
vorhanden ist
(andernfalls müssen Sie es erstellen). Wenn sich in Ihrem
Datenverzeichnis bereits ein Datenbankverzeichnis namens
foo
befindet, sollten Sie es nach
D:\data
verschieben. Andernfalls wird
die Verknüpfung unbrauchbar sein. Um Probleme zu
vermeiden, stellen Sie sicher, dass der Server beim
Verschieben des Datenbankverzeichnisses nicht ausgeführt
wird.
Erstellen Sie eine Textdatei namens
C:\mysql\data\foo.sym
, die den
Pfadnamen D:\data\foo\
enthält.
Danach werden alle Tabellen, die Sie in der Datenbank
foo
anlegen, in
D:\data\foo
erstellt. Beachten
Sie, dass die symbolische Verknüpfung nicht verwendet wird,
wenn ein Verzeichnis mit demselben Namen wie die Datenbank im
MySQL-Datenverzeichnis vorhanden ist.
Inhaltsverzeichnis
Es gibt eine Vielzahl verschiedener MySQL-Clientprogramme, die Verbindungen mit dem Server herstellen, um auf Datenbanken zuzugreifen oder administrative Aufgaben durchzuführen. Auch andere Hilfsprogramme sind verfügbar. Diese stellen keine Clientverbindung mit dem Server her, sondern führen MySQL-spezifische Operationen durch.
In diesem Kapitel bieten wir einen kurzen Überblick über diese Programme und beschreiben sie nachfolgend jeweils im Detail. In der Beschreibung der Programme sind die Syntax zum Aufruf und die unterstützten Optionen enthalten. In Kapitel 4, Benutzung von MySQL-Programmen, finden Sie allgemeine Informationen zum Aufruf von Programmen und zur Angabe von Programmoptionen.
Die folgende Liste stellt eine kurze Beschreibung der MySQL-Clientprogramme und Hilfsprogramme dar:
Mit diesem Hilfsprogramm können Sie
MyISAM
-Tabellen beschreiben, überprüfen,
optimieren und reparieren. Siehe auch
Abschnitt 8.2, „myisamchk — Hilfsprogramm für die Tabellenwartung von MyISAM“.
Ein Hilfsprogramm, das den Inhalt einer
MyISAM
-Logdatei verarbeitet. Siehe auch
Abschnitt 8.4, „myisampack — Erzeugung komprimierter, schreibgeschützter MyISAM Tabellen“.
Ein Hilfsprogramm, das MyISAM
-Tabellen
komprimiert und so kleinere schreibgeschützte Tabellen
erzeugt. Siehe auch Abschnitt 8.4, „myisampack — Erzeugung komprimierter, schreibgeschützter MyISAM Tabellen“.
Befehlszeilen-Tool zur interaktiven Eingabe von SQL-Anweisungen und zur Ausführung solcher Anweisungen aus einer Datei im Stapelbetriebsmodus. Siehe auch Abschnitt 8.5, „mysql — Das MySQL-Befehlszeilenwerkzeug mysql“.
Ein Skript, welches die Zugriffsberechtigungen für eine Kombination aus Hostnamen, Benutzernamen und Datenbank überprüft. Siehe auch Abschnitt 8.6, „mysqlaccess — Client für die Überprüfung von Zugriffsberechtigungen“.
Ein Client, der administrative Operationen durchführt. Hierzu gehören etwa das Erstellen und Löschen von Datenbanken, das Neuladen der Grant-Tabellen, das Synchronisieren von Tabellen auf Festplatte und das Neuöffnen von Logdateien. mysqladmin kann auch verwendet werden, um Versions-, Prozess- und Statusinformationen vom Server abzurufen. Siehe auch Abschnitt 8.7, „mysqladmin — Client für die Verwaltung eines MySQL Servers“.
Ein Hilfsprogramm zum Lesen von Anweisungen aus einem Binärlog. Die im Binärlog enthaltene Abfolge der ausgeführten Anweisungen kann zur Wiederherstellung nach einem Absturz nützlich sein. Siehe auch Abschnitt 8.8, „mysqlbinlog — Hilfsprogramm für die Verarbeitung binärer Logdateien“.
Ein Client zur Wartung von Tabellen. Überprüft, repariert, analysiert und optimiert Tabellen. Siehe auch Abschnitt 8.9, „mysqlcheck — Hilfsprogramm für die Wartung und Reparatur von Tabellen“.
Ein Client, der eine MySQL-Datenbank in Form von SQL-Anweisungen oder als tabulatorgetrennte Texte in eine Datei speichert. Siehe auch Abschnitt 8.10, „mysqldump — Programm zur Datensicherung“.
Ein Hilfsprogramm, welches schnelle Backups von
MyISAM
-Tabellen erstellt, während der
Server ausgeführt wird. Siehe auch
Abschnitt 8.11, „mysqlhotcopy — Backup-Programm für Datenbanken“.
Ein Client, der Textdateien mithilfe von LOAD DATA
INFILE
in die jeweiligen Tabellen importiert. Siehe
auch Abschnitt 8.12, „mysqlimport — Programm zum Datenimport“.
Ein Client, der Informationen zu Datenbanken, Tabellen, Spalten und Indizes anzeigt. Siehe auch Abschnitt 8.13, „mysqlshow — Anzeige von Informationen über Datenbanken, Tabellen und Spalten“.
Ein Client, dessen Zweck die Emulation einer Clientlast für einen MySQL Server ist und der zeitbezogene Angaben der einzelnen Operationsstufen meldet. Er simuliert den Zugriff mehrerer Clients auf den Server. Abschnitt 8.14, „mysqlslap — Client zur Lastemulation“.
Ein Hilfsprogramm, mit dem Prozesse terminiert werden, bei denen eine Übereinstimmung für einen Mustervergleich vorliegt. Abschnitt 8.15, „mysql_zap — Prozesse beenden, die einem Muster entsprechen“.
Ein Hilfsprogramm, das die Bedeutung von System- oder MySQL-Fehlercodes anzeigt. Siehe auch Abschnitt 8.16, „perror — Erklärung der Fehlercodes“.
Ein Hilfsprogramm, das Strings in eingegebenem Text ersetzt. Siehe auch Abschnitt 8.17, „replace — Hilfsprogramm für String-Ersetzungen“.
MySQL AB bietet auch eine Anzahl von Tools mit grafischer Oberfläche an, um MySQL Server zu administrieren oder anderweitig zu bearbeiten. Grundlegende Informationen zu diesen Programmen finden Sie in Kapitel 4, Benutzung von MySQL-Programmen.
Jedes MySQL-Programm akzeptiert viele verschiedene Optionen. Die
meisten Programme enthalten eine Option --help
,
über die Sie eine vollständige Beschreibung der verschiedenen
Programmoptionen erhalten können. Probieren Sie z. B.
mysql --help aus.
MySQL-Clientprogramme, die unter Verwendung der MySQL-Client/Server-Bibliothek mit dem Server kommunizieren, verwenden die folgenden Umgebungsvariablen:
MYSQL_UNIX_PORT | die vorgabeseitige Unix-Socketdatei. Sie wird für Verbindungen mit
localhost verwendet. |
MYSQL_TCP_PORT | die Standardportnummer. Wird für TCP/IP-Verbindungen verwendet. |
MYSQL_PWD | das Standardpasswort. |
MYSQL_DEBUG | gibt Trace-Optionen für das Debuggen an. |
TMPDIR | Verzeichnis, in dem Temporärtabellen und -dateien erstellt werden. |
Die Verwendung von MYSQL_PWD
ist nicht sicher.
Siehe auch Abschnitt 5.9.6, „Wie Sie Ihre Kennwörter sicher halten“.
Sie können die standardmäßigen oder durch Umgebungsvariablen festgelegten Optionswerte für alle Standardprogramme außer Kraft setzen, indem Sie andere Optionen in einer Optionsdatei oder über die Befehlszeile angeben. Siehe auch Abschnitt 4.3, „Angabe von Programmoptionen“.
Das Hilfsprogramm myisamchk holt
Informationen zu Ihren Datenbanktabellen und überprüft,
repariert und optimiert sie. myisamchk
funktioniert bei MyISAM
-Tabellen (d. h.
Tabellen, die über .MYD
- und
.MYI
-Dateien zum Speichern von Daten und
Indizes verfügen).
Rufen Sie myisamchk wie folgt auf:
shell> myisamchk [options
] tbl_name
...
Mithilfe von Optionen geben Sie myisamchk an, was es tun soll. Diese Optionen sind in den folgenden Abschnitten beschrieben. Eine Liste der Optionen erhalten Sie ferner, indem Sie myisamchk --help aufrufen.
Ohne Angabe von Optionen überprüft myisamchk Ihre Tabelle; dies ist die Standardoperation. Um weitere Informationen abzurufen oder myisamchk zur Durchführung von Korrekturmaßnahmen anzuweisen, geben Sie die Optionen wie nachfolgend beschrieben an.
tbl_name
ist dabei die
Datenbanktabelle, die Sie überprüfen oder reparieren wollen.
Führen Sie myisamchk in einem anderen als
dem Datenbankverzeichnis aus, dann müssen Sie den Pfad zum
Datenbankverzeichnis angeben, weil
myisamchk sonst nicht weiß, wo es die
Datenbank suchen soll. Eigentlich ist es
myisamchk sogar egal, ob die Dateien, die
Sie verarbeiten wollen, sich im Datenbankverzeichnis befinden.
Sie können die Dateien, die einer Datenbanktabelle
entsprechen, an eine andere Position kopieren und
Wiederherstellungsoperationen auch dort vornehmen.
Bei Bedarf können Sie auf der Befehlszeile auch mehrere
Tabellen für myisamchk angeben. Ferner ist
es möglich, eine Tabelle durch Angabe ihrer Indexdatei
(d. h. der Datei mit der Dateierweiterung
.MYI
) auszuwählen. Auf diese Weise
können Sie alle Tabellen in einem Verzeichnis auswählen,
indem Sie das Muster *.MYI
verwenden.
Befinden Sie sich beispielsweise in einem
Datenbankverzeichnis, dann können Sie alle dort vorhandenen
MyISAM
-Tabellen wie folgt überprüfen:
shell> myisamchk *.MYI
Befinden Sie sich nicht im Datenbankverzeichnis, dann können Sie alle dort vorhandenen Tabellen trotzdem überprüfen, indem Sie den Verzeichnispfad angeben:
shell> myisamchk /path/to/database_dir/*.MYI
Sie können sogar alle Tabellen in allen Datenbanken überprüfen. Hierzu geben Sie den Pfad zum MySQL-Datenverzeichnis mit Jokerzeichen an:
shell> myisamchk /path/to/datadir
/*/*.MYI
Die empfohlene Vorgehensweise zur schnellen Überprüfung
aller MyISAM
-Tabellen ist die folgende:
shell> myisamchk --silent --fast /path/to/datadir
/*/*.MYI
Wenn Sie alle MyISAM
-Tabellen überprüfen
und alle ggf. beschädigten Tabellen reparieren wollen,
können Sie den folgenden Befehl verwenden:
shell>myisamchk --silent --force --fast --update-state \
--key_buffer_size=64M --sort_buffer_size=64M \
--read_buffer_size=1M --write_buffer_size=1M \
/path/to/datadir/
*/*.MYI
Dieser Befehl setzt mindestens 64 Mbyte freien Arbeitsspeicher
voraus. Weitere Informationen zur Speicherzuweisung bei
myisamchk finden Sie in
Abschnitt 8.2.5, „Speicherbenutzung von myisamchk
“.
Sie müssen sicherstellen, dass kein anderes Programm die Tabellen verwendet, während Sie myisamchk ausführen. Andernfalls kann bei der Ausführung von myisamchk folgende Fehlermeldung angezeigt werden:
warning: clients are using or haven't closed the table properly
Das bedeutet, dass Sie gerade versuchen, eine Tabelle zu überprüfen, die von einem anderen Programm (z. B. dem Server mysqld) verändert wurde, welches die Datei noch nicht geschlossen hat oder abgestürzt ist, bevor es die Datei korrekt schließen konnte.
Wenn mysqld läuft, müssen Sie durch
Verwendung von FLUSH TABLES
das
Synchronisieren aller Änderungen an Tabellen erzwingen, die
noch im Speicher gepuffert sind. Nachfolgend müssen Sie
sicherstellen, dass kein anderes Programm die Tabellen
verwendet, während Sie myisamchk
ausführen. Die einfachste Möglichkeit, dieses Problem zu
umgehen, ist die Tabellenüberprüfung mit CHECK
TABLE
anstelle von myisamchk.
Die in diesem Abschnitt beschriebenen Optionen können für alle Arten von Wartungsvorgängen verwendet werden, die von myisamchk an Tabellen vorgenommen werden. Die nachfolgenden Abschnitte beschreiben dann Optionen, die spezifisch für bestimmte Operationen wie die Überprüfung oder Reparatur von Tabellen sind.
--help
, -?
Zeigt eine Hilfemeldung an und wird dann beendet.
--debug=
debug_options
,
-# debug_options
Schreibt ein Debuglog. Der String
debug_options
heißt häufig
'd:t:o,
.
file_name
'
--silent
, -s
Stummer Modus. Eine Ausgabe erfolgt nur, wenn ein Fehler
auftritt. Sie können -s
zweimal angeben
(-ss
), um myisamchk
vollständig zum Verstummen zu bringen.
--verbose
, -v
Ausführlicher Modus. Es werden zusätzliche Angaben zu
den Aktivitäten des Programms ausgegeben. Die Option kann
gemeinsam mit -d
und -e
eingesetzt werden. Verwenden Sie -v
mehrfach (-vv
, -vvv
), um
noch mehr Angaben auszugeben.
--version
, -V
Zeigt die Versionsinformation an und wird dann beendet.
--wait
, -w
Statt mit einem Fehler beendet zu werden, wenn die Tabelle gesperrt ist, wartet das Programm, bis die Sperre aufgehoben ist, und fährt dann mit der Ausführung fort. Beachten Sie, dass, wenn Sie mysqld mit deaktivierter externer Sperrung ausführen, die Tabelle nur durch einen weiteren myisamchk-Befehl gesperrt werden kann.
Sie können mit der Syntax
--
auch die folgenden Variablen einstellen:
var_name
=value
Variable | Standardwert |
decode_bits | 9 |
ft_max_word_len | versionsspezifisch |
ft_min_word_len | 4 |
ft_stopword_file | integrierte Liste |
key_buffer_size | 523264 |
myisam_block_size | 1024 |
read_buffer_size | 262136 |
sort_buffer_size | 2097144 |
sort_key_blocks | 16 |
stats_method | nulls_unequal |
write_buffer_size | 262136 |
Welche myisamchk-Variablen unterstützt werden und welche Standardwerte sie haben, ermitteln Sie mit myisamchk --help:
sort_buffer_size
wird benutzt, wenn die
Schlüssel durch Sortierung repariert werden, was bei
Verwendung von --recover
der Normalfall ist.
key_buffer_size
verwenden Sie bei der
Überprüfung der Tabelle mit --extend-check
oder aber dann, wenn die Schlüssel durch Einfügen von
Schlüsseldatensätzen in die Tabelle (ähnlich normalen
Einfügeoperationen) repariert werden. Die Reparatur über den
Schlüsselpuffer wird in den folgenden Fällen verwendet:
Sie verwenden --safe-recover
.
Die zur Sortierung der Schlüssel erforderlichen
Temporärdateien wären mehr als doppelt so groß wie bei
der direkten Erstellung der Schlüsseldatei. Dies passiert
häufig, wenn Sie große Schlüsselwerte für
CHAR
-, VARCHAR
- oder
TEXT
-Spalten haben, weil im Zuge des
Sortiervorgangs die vollständigen Schlüsselwerte
gespeichert werden müssen. Wenn Sie viel Speicher für
temporäre Daten haben und die Reparatur durch Sortierung
mithilfe von myisamchk erzwingen
wollen, verwenden Sie die Option
--sort-recover
.
Die Reparatur über den Schlüsselpuffer benötigt wesentlich weniger Festplattenspeicher als die Sortierung, ist allerdings auch langsamer.
Wenn Sie eine schnellere Reparatur wünschen, setzen Sie die
Variablen key_buffer_size
und
sort_buffer_size
auf einen Wert von ca. 25
Prozent Ihres verfügbaren Speichers. Sie können beide
Variablen auf hohe Werte setzen, da immer nur eine von ihnen
gleichzeitig verwendet wird.
myisam_block_size
ist die Größe, die für
Indexblöcke verwendet wird.
stats_method
beeinflusst, wie
NULL
-Werte bei der Erfassung von
Indexstatistiken behandelt werden, wenn die Option
--analyze
angegeben wurde. Sie agiert wie die
Systemvariable myisam_stats_method
. Weitere
Informationen entnehmen Sie der Beschreibung von
myisam_stats_method
in
Abschnitt 5.2.2, „Server-Systemvariablen“, und
Abschnitt 7.4.7, „Sammlung von MyISAM
-Indexstatistiken“.
ft_min_word_len
und
ft_max_word_len
geben die minimale bzw.
maximale Wortlänge für FULLTEXT
-Indizes
an. ft_stopword_file
gibt die Datei mit den
Stoppwörtern an. Diese Optionen müssen unter den nachfolgend
beschriebenen Umständen eingestellt werden.
Wenn Sie mit myisamchk eine Operation
durchführen, die Tabellenindizes verändert (dies können
etwa Reparatur- oder Analyseoperationen sein), dann werden die
FULLTEXT
-Indizes unter Verwendung der
standardmäßigen Volltextparameterwerte für die minimale und
maximale Wortlänge und die Stoppwortdatei verwendet, sofern
Sie nichts anderes angeben. Dies kann dazu führen, dass
Abfragen fehlschlagen.
Das Problem tritt auf, weil diese Parameter nur dem Server
bekannt sind. Sie werden nicht in den
MyISAM
-Indexdateien gespeichert. Um das
Problem zu umgehen, wenn Sie die minimale oder maximale
Wortlänge oder die Stoppwortdatei am Server geändert haben,
geben Sie dieselben Werte ft_min_word_len
,
ft_max_word_len
und
ft_stopword_file
für
myisamchk an, die Sie für
mysqld verwendet haben. Haben Sie also
beispielsweise die Mindestwortlänge auf 3 gesetzt, dann
können Sie eine Tabelle mit myisamchk wie
folgt reparieren:
shell> myisamchk --recover --ft_min_word_len=3 tbl_name
.MYI
Wenn Sie gewährleisten wollen, dass
myisamchk und der Server dieselben Werte
für Volltextparameter verwenden, können Sie sie jeweils in
die Abschnitte [mysqld]
und
[myisamchk]
einer Optionsdatei eintragen:
[mysqld] ft_min_word_len=3 [myisamchk] ft_min_word_len=3
Eine Alternative zur Verwendung von
myisamchk besteht in der Nutzung von
REPAIR TABLE
, ANALYZE
TABLE
, OPTIMIZE TABLE
oder
ALTER TABLE
. Diese Anweisungen werden vom
Server ausgeführt, der die korrekten Werte der
Volltextparameter kennt.
myisamchk unterstützt die folgenden Optionen für Operationen zur Tabellenüberprüfung:
--check
, -c
Überprüft die Tabelle auf Fehler. Dies ist die Standardoption; sie wird verwendet, wenn Sie keine Option angeben, die ausdrücklich einen Operationstyp spezifiziert.
--check-only-changed
, -C
Überprüft nur Tabellen, die seit der letzten Überprüfung geändert wurden.
--extend-check
, -e
Überprüft die Tabelle sehr gründlich. Das kann recht lange dauern, wenn die Tabelle viele Indizes hat. Sie sollten die Option nur in Extremfällen einsetzen. Normalerweise sollten Sie mit myisamchk oder myisamchk --medium-check ermitteln können, ob Fehler in einer Tabelle vorhanden sind.
Wenn Sie --extend-check
verwenden und
viel Speicher haben, können Sie die Variable
key_buffer_size
auf einen großen Wert
setzen. Hierdurch wird der Reparaturvorgang schneller
ausgeführt.
--fast
, -F
Überprüft nur Tabellen, die nicht ordnungsgemäß geschlossen wurden.
--force
, -f
Führt eine Reparaturoperation automatisch aus, wenn
myisamchk Fehler in der Tabelle findet.
Der Reparaturtyp ist derselbe, der auch mit der Option
--recover
bzw. -r
angegeben wird.
--information
, -i
Gibt informative Statistiken zur überprüften Tabelle aus.
--medium-check
, -m
Führt eine Überprüfung durch, die schneller ist als
eine --extend-check
-Operation. Hierdurch
werden nur 99,99 Prozent aller Fehler gefunden (dies
sollte allerdings in den meisten Fällen ausreichend
sein).
--read-only
, -T
Kennzeichnet die Tabelle nicht als überprüft. Das kann praktisch sein, wenn Sie mit myisamchk eine Tabelle überprüfen, die gerade von einer anderen Anwendung benutzt wird, welche keine Sperrung verwendet. Dies kann beispielsweise mysqld sein, wenn es mit deaktivierter externer Sperrung ausgeführt wird.
--update-state
, -U
Speichert Daten in der .MYI
-Datei,
die angeben, wann die Tabelle zum letzten Mal überprüft
wurde und ob sie abgestürzt war. Diese Option sollten Sie
verwenden, um die Option
--check-only-changed
optimal nutzen zu
können, nicht jedoch, wenn der Server
mysqld die Tabelle verwendet und ohne
externe Sperrung ausgeführt wurde.
myisamchk unterstützt die folgenden Optionen für Operationen zur Tabellenreparatur:
--backup
, -B
Erstellt ein Backup der Datei .MYD
als
.
file_name
-time
.BAK
--character-sets-dir=
path
Das Verzeichnis, in dem Zeichensätze installiert sind. Siehe auch Abschnitt 5.11.1, „Der für Daten und zum Sortieren benutzte Zeichensatz“.
--correct-checksum
Korrigiert die Prüfsummeninformation für die Tabelle.
--data-file-length=
len
,
-D len
Gibt die maximale Länge der Datendatei an (zur Neuerstellung der Datendatei, wenn diese „voll“ ist).
--extend-check
, -e
Führt eine Reparatur durch, die alle Datensätze aus der Datendatei wiederherzustellen versucht, bei denen dies möglich ist. Normalerweise werden hierdurch auch viele nicht mehr erforderliche Datensätze gefunden. Verwenden Sie diese Option nur, wenn Sie vollkommen verzweifelt sind.
--force
, -f
Überschreibt alte Zwischendateien (Dateien mit Namen wie
)
anstatt abzubrechen.
tbl_name
.TMD
--keys-used=
,
val
-k
val
Bei myisamchk ist die Option ein Bitwert, der angibt, welche Indizes aktualisiert werden müssen. Jedes Binärbit des Optionswerts entspricht einem Tabellenindex, wobei der erste Index Bit 0 ist. Der Optionswert 0 deaktiviert Änderungen an allen Indizes, was zur Beschleunigung von Einfügeoperationen genutzt werden kann. Deaktivierte Indizes können mit myisamchk -r reaktiviert werden.
--parallel-recover
, -p
Verwendet dieselbe Methode wie -r
und
-n
, erstellt aber alle Schlüssel
parallel unter Verwendung verschiedener Threads.
Der Code hat bislang nur Betaqualität.
Verwendung auf eigene Gefahr!
--quick
, -q
Beschleunigt die Reparatur, da die Datendatei nicht geändert wird. Sie können diese Option zweimal angeben, um die Änderung der Originaldatendatei durch myisamchk im Falle von Schlüsseldubletten zu erzwingen.
--recover
, -r
Führt eine Reparatur aus, die praktisch jedes Problem
behebt (ausgenommen sind eindeutige Schlüssel, die nicht
eindeutig sind – ein Fehler, der bei
MyISAM
-Tabellen extrem selten
vorkommt). Wenn Sie eine Tabelle wiederherstellen wollen,
sollten Sie diese Option zuerst ausprobieren.
--safe-recover
sollten Sie nur verwenden,
wenn myisamchk meldet, dass die Tabelle
mit --recover
nicht wiederhergestellt
werden kann. (In dem unwahrscheinlichen Fall, dass
--recover
fehlschlägt, bleibt die
Datendatei intakt.)
Wenn Sie sehr viel Speicher haben, sollten Sie den Wert
von sort_buffer_size
erhöhen.
--safe-recover
, -o
Führt eine Reparatur unter Verwendung einer alten
Wiederherstellungsmethode durch, die alle Datensätze der
Reihe nach ausliest und alle Indexbäume entsprechend den
gefundenen Datensätzen aktualisiert. Dies ist um eine
Größenordnung langsamer als --recover
,
kann aber ein paar sehr unwahrscheinliche Fälle beheben,
die --recover
nicht korrigiert. Diese
Methode verwendet überdies wesentlich weniger
Festplattenspeicher als --recover
.
Normalerweise sollten Sie zuerst eine Reparatur mit
--recover
durchführen und
--safe-recover
nur dann verwenden, wenn
--recover
fehlschlägt.
Wenn Sie sehr viel Speicher haben, sollten Sie den Wert
von key_buffer_size
erhöhen.
--set-collation=
name
Gibt die für die Tabellen zu verwendende Sortierung an. Dabei wird der Zeichensatzname implizit durch den ersten Teil des Sortierungsnamens festgelegt.
--sort-recover
, -n
Erzwingt die Verwendung der Sortierung zur Auflösung von Schlüsseln durch myisamchk auch für den Fall, dass die Temporärdateien sehr groß werden würden.
--tmpdir=
path
, -t
path
Pfad zu dem Verzeichnis, in dem die Temporärdateien
gespeichert werden. Wenn diese Einstellung nicht
vorgenommen wird, verwendet myisamchk
den Wert der Umgebungsvariablen TMPDIR
.
tmpdir
kann eine Liste der
Verzeichnispfade enthalten, in denen zyklisch abwechselnd
die Temporärdateien erstellt werden. Die Verzeichnispfade
sind unter Unix mit Doppelpunkten
(‘:
’) und unter Windows,
NetWare und OS/2 mit Semikola
(‘;
’) voneinander zu
trennen.
--unpack
, -u
Entpackt eine Tabelle, die mit myisampack gepackt wurde.
myisamchk unterstützt die folgenden Optionen für andere Vorgänge als die Überprüfung und Reparatur von Tabellen:
--analyze
, -a
Analysiert die Verteilung der Schlüsselwerte. Hierdurch
wird die Leistungsfähigkeit von Joins verbessert, denn
der Join-Optimierer kann die Reihenfolge, in der die
Tabellen verknüpft werden, und die zu verwendenden
Indizes besser auswählen. Um Angaben zur
Schlüsselverteilung zu erhalten, verwenden Sie den Befehl
myisamchk --description --verbose
tbl_name
oder die
Anweisung SHOW INDEX FROM
.
tbl_name
--description
, -d
Gibt eine Beschreibung der Tabelle aus.
--set-auto-increment[=
,
value
]-A[
value
]
Erzwingt für neue Datensätze den Start der
AUTO_INCREMENT
-Nummerierung beim
angegebenen Wert (oder einem höheren Wert, sofern
Datensätze mit derart großen
AUTO_INCREMENT
-Werten bereits vorhanden
sind). Wenn value
nicht
angegeben wurde, beginnen die
AUTO_INCREMENT
-Zahlen für neue
Datensätze beim höchsten derzeit in der Tabelle
vorhandenen Wert plus 1.
--sort-index
, -S
Sortiert die Blöcke des Indexbaums in absteigender Reihenfolge. Hierdurch werden Suchvorgänge optimiert und Tabellenscans, die Indizes benutzen, beschleunigt.
--sort-records=
N
, -R
N
Sortiert Datensätze nach einem bestimmten Index.
Hierdurch werden Ihre Daten stärker lokalisiert, und
bereichsbasierte SELECT
- und
ORDER BY
-Operationen, die diesen Index
benutzen, werden beschleunigt. (Wenn Sie diese Option zur
Sortierung einer Tabelle zum ersten Mal verwenden, kann
sie sehr langsam arbeiten.) Um die Indexnummern einer
Tabelle zu bestimmen, verwenden Sie SHOW
INDEX
. Hierdurch werden die Indizes einer
Tabelle in derselben Reihenfolge angezeigt, in der sie
auch myisamchk erkennt. Die Indizes
sind beginnend mit 1 nummeriert.
Wenn die Schlüssel nicht gepackt sind
(PACK_KEYS=0)
), dann haben sie dieselbe
Länge. Insofern überschreibt
myisamchk, wenn es Datensätze sortiert
und verschiebt, einfach nur Datensatzoffsets im Index.
Sind die Schlüssel hingegen gepackt
(PACK_KEYS=1
), dann muss
myisamchk die Schlüsselblöcke zuerst
entpacken, dann die Indizes neu erstellen und die
Schlüsselblöcke abschließend wieder packen. (In diesem
Fall ist die Neuerstellung der Indizes schneller als die
Aktualisierung der Offsets für jeden Index.)
Die Speicherreservierung ist für die Ausführung von myisamchk sehr wichtig. myisamchk verwendet niemals mehr Speicher als über seine speicherbezogenen Variablen angegeben. Wenn Sie myisamchk für sehr große Tabellen verwenden, sollten Sie zunächst entscheiden, wie viel Speicher Sie verwenden wollen. Standardmäßig werden zur Durchführung von Reparaturen nur etwa 3 Mbyte benutzt. Durch Verwendung höherer Werte können Sie die Verarbeitungsgeschwindigkeit von myisamchk beschleunigen. Wenn Sie beispielsweise mehr als 32 Mbyte RAM haben, könnten Sie Optionen wie die folgenden (zusätzlich zu ggf. anderen angegebenen Optionen) verwenden:
shell>myisamchk --sort_buffer_size=16M --key_buffer_size=16M \
--read_buffer_size=1M --write_buffer_size=1M ...
Die Nutzung von --sort_buffer_size=16M
sollte
in den meisten Fällen ausreichend sein.
Beachten Sie, dass myisamchk
Temporärdateien in TMPDIR
benutzt. Wenn
TMPDIR
auf ein Speicherdateisystem
verweist, kann es leicht zu Problemen aufgrund mangelnden
Hauptspeichers kommen. In diesem Fall führen Sie
myisamchk mit der Option
--tmpdir=
aus,
um ein Verzeichnis auf einem Dateisystem anzugeben, auf dem
mehr Speicher zur Verfügung steht.
path
Bei der Reparatur benötigt myisamchk auch eine Menge Festplattenkapazität.
Die doppelte Größe der Datendatei (einmal für die
Originaldatei, einmal für die Kopie). Dieser
Festplattenspeicher wird nicht benötigt, wenn Sie eine
Reparatur mit der Option --quick
durchführen, denn in diesem Fall wird nur die Indexdatei
neu erstellt. Der Festplattenspeicher muss auf demselben
Dateisystem wie die ursprüngliche Datendatei vorhanden
sein! (Das liegt daran, dass die Kopie im gleichen
Verzeichnis erstellt wird wie die Originaldatei.)
Platz für die neue Indexdatei, die die alte Datei ersetzt. Die alte Indexdatei wird zu Beginn der Reparaturoperation gekürzt, d. h., Sie können diesen Speicherbedarf in der Regel ignorieren. Der Festplattenspeicher muss auf demselben Dateisystem wie die ursprüngliche Indexdatei vorhanden sein!
Wenn Sie --recover
oder
--sort-recover
(nicht aber
--safe-recover
) verwenden, benötigen Sie
Platz für einen Sortierpuffer. Die folgende Formel
ermöglicht die Berechnung der erforderlichen Kapazität:
(largest_key
+row_pointer_length
) ×number_of_rows
× 2
Sie können die Länge der Schlüssel und
row_pointer_length
mit
myisamchk -dv
tbl_name
überprüfen. Diese Festplattenkapazität wird im
Temporärverzeichnis reserviert, das mit
TMPDIR
oder
--tmpdir=
angegeben wird.
path
Sollte während der Reparatur ein Problem in Bezug auf den
Festplattenspeicher auftreten, dann können Sie
--safe-recover
statt
--recover
verwenden.
myisamlog verarbeitet den Inhalt einer
MyISAM
-Logdatei.
Rufen Sie myisamlog wie folgt auf:
shell> myisamlog [options
] [log_file
[tbl_name
] ...]
Die Standardoperation ist die Aktualisierung
(-u
). Erfolgt eine Wiederherstellung (Option
-r
), dann werden alle Schreiboperationen und
ggf. Änderungen und Löschungen durchgeführt. Fehler werden
nur gezählt. Der Standardname der Logdatei lautet
myisam.log
, sofern kein Argument
log_file
übergeben wurde. Werden
auf der Befehlszeile Tabellen angegeben, dann werden auch nur
diese Tabellen aktualisiert.
myisamlog versteht die folgenden Optionen:
-?
, -I
Zeigt eine Hilfemeldung an und wird dann beendet.
-c
N
Führt nur N
Befehle aus.
-f
N
Gibt die maximale Anzahl offener Dateien an.
-i
Zeigt vor dem Beenden zusätzliche Informationen an.
-o
offset
Gibt den Startoffset an.
-p
N
Entfernt N
Komponenten aus dem
Pfad.
-r
Führt eine Wiederherstellungsoperation durch.
-R
record_pos_file
record_pos
Gibt die Datensatzpositionsdatei und die Datensatzposition an.
-u
Führt eine Aktualisierungsoperation durch.
-v
Ausführlicher Modus. Es werden zusätzliche Angaben zu den Aktivitäten des Programms ausgegeben. Diese Option kann mehrfach angegeben werden, um den Umfang der Ausgabe kontinuierlich zu erhöhen.
-w
write_file
Gibt die zu schreibende Datei an.
-V
Zeigt Versionsinformationen an.
Das Hilfsprogramm myisampack komprimiert
MyISAM
-Tabellen. Es komprimiert dabei jede
Spalte in der Tabelle separat. Normalerweise erzielt
myisampack für die Datendatei
Komprimierungsraten von 40 bis 70 Prozent.
Wird die Tabelle später verwendet, dann liest der Server die zur Dekomprimierung der Spalten erforderlichen Angaben in den Speicher ein. Hierdurch wird die Leistungsfähigkeit beim Zugriff auf einzelne Datensätze erheblich verbessert, da Sie nur genau einen Datensatz dekomprimieren müssen.
Sofern möglich, verwendet MySQL mmap()
für die Speicherzuordnung bei komprimierten Tabellen.
Funktioniert mmap()
nicht, dann nutzt MySQL
ersatzweise normale Schreib- und Leseoperationen für Dateien.
Beachten Sie bitte Folgendes:
Wenn der mysqld-Server mit deaktivierter externer Sperrung aufgerufen wurde, sollte myisampack nicht aufgerufen werden, sofern die Möglichkeit besteht, dass die Tabelle während des Komprimierungsvorgangs durch den Server aktualisiert werden könnte. Am besten wird der Server vor der Komprimierung der Tabellen beendet.
Wenn eine Tabelle gepackt wurde, ist sie schreibgeschützt. Dies ist normalerweise auch beabsichtigt (z. B. beim Zugriff auf komprimierte Tabellen auf einer CD). Die Möglichkeit, in eine gepackte Tabelle zu schreiben, ist von uns zur mittel- bis langfristigen Implementierung vorgesehen.
myisampack kann
BLOB
- oder
TEXT
-Spalten packen. (Das ältere
Programm pack_isam für
ISAM
-Tabellen bot diese Möglichkeit
nicht.)
Rufen Sie myisampack wie folgt auf:
shell> myisampack [options
] file_name
...
Jedes Dateinamensargument sollte der Name einer Indexdatei
(.MYI
-Datei) sein. Wenn Sie sich nicht im
Datenbankverzeichnis befinden, sollten Sie auch den Pfadnamen
zu der Datei angeben. Die Erweiterung
.MYI
dürfen Sie nach Belieben weglassen.
Nachdem Sie eine Tabelle mit myisampack komprimiert haben, sollten Sie myisamchk -rq zur Neuerstellung der Indizes verwenden. Siehe Abschnitt 8.2, „myisamchk — Hilfsprogramm für die Tabellenwartung von MyISAM“.
myisampack unterstützt die folgenden Optionen:
--help
, -?
Zeigt eine Hilfemeldung an und wird dann beendet.
--backup
, -b
Erstellt ein Backup der Datendateien aller Tabellen. Die
Sicherungsdateien erhalten den Namen
.
tbl_name
.OLD
--debug[=
,
debug_options
]-#
[
debug_options
]
Schreibt ein Debuglog. Der String
debug_options
heißt häufig
'd:t:o,
.
file_name
'
--force
, -f
Erzeugt auch dann eine gepackte Tabelle, wenn diese
größer als die Ursprungstabelle wird oder noch eine
Zwischendatei von myisampack vorhanden
ist. (myisampack erzeugt im Verlauf der
Komprimierung eine Zwischendatei namens
im Datenbankverzeichnis. Wenn Sie
myisampack terminieren, dann wird die
tbl_name
.TMD.TMD
-Datei unter Umständen nicht
gelöscht.) Normalerweise wird
myisampack mit einem Fehler beendet,
wenn es eine vorhandene Datei
findet. Mit tbl_name
.TMD--force
packt
myisampack die Tabelle jedoch in jedem
Fall.
--join=
,
big_tbl_name
-j
big_tbl_name
Fasst alle auf der Befehlszeile aufgeführten Tabellen zu
einer großen Tabelle
big_tbl_name
zusammen. Alle
Tabellen, die zusammengefasst werden sollen,
müssen eine identische Struktur
aufweisen (d. h. gleiche Spaltennamen und -typen, gleiche
Indizes usw.).
--packlength=
,
len
-p
len
Gibt die Speichergröße für die Datensatzlänge (in Byte) an. Der Wert darf zwischen 1 und 3 liegen. myisampack speichert alle Datensätze mit 1, 2 oder 3 Byte langen Längenzeigern. In den meisten normalen Fällen kann myisampack den korrekten Längenwert bestimmen, bevor es mit dem Packen der Datei beginnt. Es kann allerdings während des Packvorgangs feststellen, dass es eine geringere Länge hätte verwenden können. In diesem Fall gibt myisampack einen Hinweis aus, dass Sie, wenn Sie dieselbe Datei beim nächsten Mal packen, eine geringere Datensatzlänge verwenden können.
--silent
, -s
Stummer Modus. Eine Ausgabe erfolgt nur, wenn ein Fehler auftritt.
--test
, -t
Die Tabelle wird nicht gepackt, sondern das Packen wird lediglich geprüft.
--tmpdir=
,
path
-T
path
Verwendet das angegebene Verzeichnis als Position, an der myisamchk Temporärdateien erstellt.
--verbose
, -v
Ausführlicher Modus. Gibt Informationen zum Fortschritt des Komprimierungsvorgangs und -ergebnisses aus.
--version
, -V
Zeigt die Versionsinformation an und wird dann beendet.
--wait
, -w
Sorgt dafür, dass der Packvorgang nach einer Wartezeit neu versucht wird, wenn die Tabelle gerade verwendet wird. Wenn der mysqld-Server mit deaktivierter externer Sperrung aufgerufen wurde, sollte myisampack nicht aufgerufen werden, sofern die Möglichkeit besteht, dass die Tabelle während des Komprimierungsvorgangs durch den Server aktualisiert werden könnte.
Die nachfolgend gezeigte Befehlsfolge veranschaulicht eine typische Tabellenkomprimierungssitzung:
shell>ls -l station.*
-rw-rw-r-- 1 monty my 994128 Apr 17 19:00 station.MYD -rw-rw-r-- 1 monty my 53248 Apr 17 19:00 station.MYI -rw-rw-r-- 1 monty my 5767 Apr 17 19:00 station.frm shell>myisamchk -dvv station
MyISAM file: station Isam-version: 2 Creation time: 1996-03-13 10:08:58 Recover time: 1997-02-02 3:06:43 Data records: 1192 Deleted blocks: 0 Datafile parts: 1192 Deleted data: 0 Datafile pointer (bytes): 2 Keyfile pointer (bytes): 2 Max datafile length: 54657023 Max keyfile length: 33554431 Recordlength: 834 Record format: Fixed length table description: Key Start Len Index Type Root Blocksize Rec/key 1 2 4 unique unsigned long 1024 1024 1 2 32 30 multip. text 10240 1024 1 Field Start Length Type 1 1 1 2 2 4 3 6 4 4 10 1 5 11 20 6 31 1 7 32 30 8 62 35 9 97 35 10 132 35 11 167 4 12 171 16 13 187 35 14 222 4 15 226 16 16 242 20 17 262 20 18 282 20 19 302 30 20 332 4 21 336 4 22 340 1 23 341 8 24 349 8 25 357 8 26 365 2 27 367 2 28 369 4 29 373 4 30 377 1 31 378 2 32 380 8 33 388 4 34 392 4 35 396 4 36 400 4 37 404 1 38 405 4 39 409 4 40 413 4 41 417 4 42 421 4 43 425 4 44 429 20 45 449 30 46 479 1 47 480 1 48 481 79 49 560 79 50 639 79 51 718 79 52 797 8 53 805 1 54 806 1 55 807 20 56 827 4 57 831 4 shell>myisampack station.MYI
Compressing station.MYI: (1192 records) - Calculating statistics normal: 20 empty-space: 16 empty-zero: 12 empty-fill: 11 pre-space: 0 end-space: 12 table-lookups: 5 zero: 7 Original trees: 57 After join: 17 - Compressing file 87.14% Remember to run myisamchk -rq on compressed tables shell>ls -l station.*
-rw-rw-r-- 1 monty my 127874 Apr 17 19:00 station.MYD -rw-rw-r-- 1 monty my 55296 Apr 17 19:04 station.MYI -rw-rw-r-- 1 monty my 5767 Apr 17 19:00 station.frm shell>myisamchk -dvv station
MyISAM file: station Isam-version: 2 Creation time: 1996-03-13 10:08:58 Recover time: 1997-04-17 19:04:26 Data records: 1192 Deleted blocks: 0 Datafile parts: 1192 Deleted data: 0 Datafile pointer (bytes): 3 Keyfile pointer (bytes): 1 Max datafile length: 16777215 Max keyfile length: 131071 Recordlength: 834 Record format: Compressed table description: Key Start Len Index Type Root Blocksize Rec/key 1 2 4 unique unsigned long 10240 1024 1 2 32 30 multip. text 54272 1024 1 Field Start Length Type Huff tree Bits 1 1 1 constant 1 0 2 2 4 zerofill(1) 2 9 3 6 4 no zeros, zerofill(1) 2 9 4 10 1 3 9 5 11 20 table-lookup 4 0 6 31 1 3 9 7 32 30 no endspace, not_always 5 9 8 62 35 no endspace, not_always, no empty 6 9 9 97 35 no empty 7 9 10 132 35 no endspace, not_always, no empty 6 9 11 167 4 zerofill(1) 2 9 12 171 16 no endspace, not_always, no empty 5 9 13 187 35 no endspace, not_always, no empty 6 9 14 222 4 zerofill(1) 2 9 15 226 16 no endspace, not_always, no empty 5 9 16 242 20 no endspace, not_always 8 9 17 262 20 no endspace, no empty 8 9 18 282 20 no endspace, no empty 5 9 19 302 30 no endspace, no empty 6 9 20 332 4 always zero 2 9 21 336 4 always zero 2 9 22 340 1 3 9 23 341 8 table-lookup 9 0 24 349 8 table-lookup 10 0 25 357 8 always zero 2 9 26 365 2 2 9 27 367 2 no zeros, zerofill(1) 2 9 28 369 4 no zeros, zerofill(1) 2 9 29 373 4 table-lookup 11 0 30 377 1 3 9 31 378 2 no zeros, zerofill(1) 2 9 32 380 8 no zeros 2 9 33 388 4 always zero 2 9 34 392 4 table-lookup 12 0 35 396 4 no zeros, zerofill(1) 13 9 36 400 4 no zeros, zerofill(1) 2 9 37 404 1 2 9 38 405 4 no zeros 2 9 39 409 4 always zero 2 9 40 413 4 no zeros 2 9 41 417 4 always zero 2 9 42 421 4 no zeros 2 9 43 425 4 always zero 2 9 44 429 20 no empty 3 9 45 449 30 no empty 3 9 46 479 1 14 4 47 480 1 14 4 48 481 79 no endspace, no empty 15 9 49 560 79 no empty 2 9 50 639 79 no empty 2 9 51 718 79 no endspace 16 9 52 797 8 no empty 2 9 53 805 1 17 1 54 806 1 3 9 55 807 20 no empty 3 9 56 827 4 no zeros, zerofill(2) 2 9 57 831 4 no zeros, zerofill(1) 2 9
myisampack zeigt die folgenden Informationen an:
normal
Anzahl der Spalten, für die keine zusätzliche Komprimierung verwendet wird.
empty-space
Anzahl der Spalten, die ausschließlich aus Leerzeichen bestehende Werte enthalten. Diese benötigen genau ein Bit.
empty-zero
Anzahl der Spalten, die ausschließlich aus binären Nullen bestehende Werte enthalten. Diese benötigen genau 1 Bit.
empty-fill
Anzahl der Integer-Spalten, die nicht den gesamten
Bytebereich des entsprechenden Typs besetzen. Diese werden
auf einen kleineren Typ umgestellt. So kann beispielsweise
eine BIGINT
-Spalte (8 Byte) als
TINYINT
-Spalte (1 Byte) gespeichert
werden, wenn alle in ihr enthaltenen Werte zwischen
-128
und 127
liegen.
pre-space
Anzahl der Dezimalspalten, die mit Leerzeichen am Anfang gespeichert werden. In diesem Fall enthält jeder Wert die Anzahl dieser Leerzeichen.
end-space
Anzahl der Spalten, die viele Leerzeichen am Ende aufweisen. In diesem Fall enthält jeder Wert die Anzahl dieser Leerzeichen.
table-lookup
Die Spalte enthielt nur eine kleine Anzahl verschiedener
Werte und wurde deswegen vor der Komprimierung in eine
ENUM
-Spalte konvertiert.
zero
Anzahl der Spalten, in der alle Werte null sind.
Original trees
Anfängliche Anzahl der Huffman-Bäume.
After join
Anzahl der separaten Huffman-Bäume, die nach dem Verknüpfen von Bäumen zum Zwecke der Speicherersparnis übrig bleiben.
Nachdem eine Tabelle komprimiert wurde, zeigt myisamchk -dvv zusätzliche Informationen zu allen Tabellenspalten an:
Type
Der Datentyp. Der Wert kann die folgenden Deskriptoren enthalten:
constant
Alle Datensätze haben denselben Wert.
no endspace
Leerzeichen am Ende nicht speichern.
no endspace, not_always
Leerzeichen am Ende nicht speichern, für alle Werte keine Komprimierung für Leerzeichen am Ende durchführen.
no endspace, no empty
Leerzeichen am Ende nicht speichern. Leere Werte nicht speichern.
table-lookup
Die Spalte wurde in eine
ENUM
-Spalte konvertiert.
zerofill(
N
)
Die N
höchstwertigen Bytes
im Wert sind immer 0 und werden nicht gespeichert.
no zeros
Nullen nicht speichern.
always zero
Nullwerte werden nur mit einem Bit gespeichert.
Huff tree
Anzahl der mit der Spalte verknüpften Huffman-Bäume.
Bits
Anzahl der im Huffman-Baum verwendeten Bits.
Nachdem Sie myisampack ausgeführt haben, müssen Sie myisamchk starten, um die Indizes neu zu erstellen. Zur gleichen Zeit können Sie auch die Indexblöcke sortieren und Statistiken erstellen, die der MySQL-Optimierer benötigt, um effizienter arbeiten zu können:
shell> myisamchk -rq --sort-index --analyze tbl_name
.MYI
Nachdem Sie die gepackte Tabelle im MySQL-Datenbankverzeichnis installiert haben, sollten Sie mysqladmin flush-tables ausführen, um die Verwendung der neuen Tabelle durch mysqld zu erzwingen.
Um eine gepackte Tabelle zu entpacken, verwenden Sie die
Option --unpack
für
myisamchk.
mysql ist eine einfache SQL-Shell (mit
GNU-readline
-Fähigkeiten). Es unterstützt
interaktiven wie auch nichtinteraktiven Einsatz. Bei
interaktiver Nutzung werden die Abfrageergebnisse im
ASCII-Tabellenformat angezeigt. Wird es hingegen
nichtinteraktiv verwendet (z. B. als Filter), dann wird das
Ergebnis durch Tabulatoren getrennt aufgelistet. Das
Ausgabeformat kann mit den folgenden Befehlsoptionen
beeinflusst werden.
Wenn Sie bei großen Ergebnismengen Probleme aufgrund
mangelnden Speichers haben, verwenden Sie die Option
--quick
. Hierdurch wird
mysql gezwungen, die Ergebnisse
datensatzweise vom Server abzurufen, statt vor der Anzeige die
gesamte Ergebnismenge zu holen und sie temporär im Speicher
abzulegen. Dies wird durch Rückgabe der Ergebnismenge
mithilfe der C-API-Funktion
mysql_use_result()
in der
Client/Server-Bibliothek statt mit
mysql_store_result()
ermöglicht.
Die Verwendung von mysql ist ganz leicht. Rufen Sie es einfach wie folgt über die Eingabeaufforderung Ihres Befehls-Interpreters auf:
shell> mysql db_name
Oder:
shell> mysql --user=user_name
--password=your_password
db_name
Geben Sie dann eine SQL-Anweisung ein, die auf
‘;
’, \g
oder
\G
endet, und betätigen Sie die
Eingabetaste.
Sie können SQL-Anweisungen wie folgt in einer Skriptdatei (Stapelverarbeitungsdatei) ausführen:
shell> mysql db_name
< script.sql
> output.tab
mysql unterstützt die folgenden Optionen:
Zeigt eine Hilfemeldung an und wird dann beendet.
Gibt die Ergebnisse mit einem Tabulator als Spaltentrennzeichen aus. Jeder Datensatz beginnt in einer neuen Zeile. Bei dieser Option verwendet mysql die Verlaufsdatei nicht.
Das Verzeichnis, in dem Zeichensätze installiert sind. Siehe auch Abschnitt 5.11.1, „Der für Daten und zum Sortieren benutzte Zeichensatz“.
Komprimiert alle Daten, die zwischen Client und Server ausgetauscht werden, sofern beide die Komprimierung unterstützen.
--database=
,
db_name
-D
db_name
Die zu verwendende Datenbank. Diese Option ist in erster Linie für Optionsdateien gedacht.
--debug[=
,
debug_options
]-#
[
debug_options
]
Schreibt ein Debuglog. Der String
debug_options
heißt häufig
'd:t:o,
.
Standardwert ist
file_name
''d:t:o,/tmp/mysql.trace'
.
Gibt einige Debuginformationen aus, wenn das Programm beendet wird.
--default-character-set=
charset_name
Verwendet charset_name
als
Standardzeichensatz. Siehe auch
Abschnitt 5.11.1, „Der für Daten und zum Sortieren benutzte Zeichensatz“.
--execute=
,
statement
-e
statement
Führt die Anweisung aus und wird dann beendet. Das
Standardausgabeformat entspricht dem mit
--batch
erzeugten. Einige Beispiele
finden Sie in Abschnitt 4.3.1, „Befehlszeilenoptionen für mysqld“.
Das Programm wird auch dann fortgesetzt, wenn ein SQL-Fehler auftritt.
--host=
,
host_name
-h
host_name
Stellt eine Verbindung zum MySQL Server auf dem angegebenen Host her.
Erzeugt eine HTML-formatierte Ausgabe.
Ignoriert Leerzeichen nach Funktionsnamen. Die Auswirkung
dieser Option wird in der Erläuterung zu
IGNORE_SPACE
in
Abschnitt 5.2.5, „Der SQL-Modus des Servers“, beschrieben.
Aktiviert oder deaktiviert die
LOCAL
-Funktionalität für
LOAD DATA INFILE
. Ohne angegebenen Wert
aktiviert die Option LOCAL
. Die Option
kann als --local-infile=0
oder als
--local-infile=1
angegeben werden, wenn
LOCAL
ausdrücklich deaktiviert bzw.
aktiviert werden soll. Die Aktivierung von
LOCAL
wirkt sich nicht aus, wenn die
Unterstützung durch den Server fehlt.
Aktiviert benannte mysql-Befehle. Neben
Befehlen im Kurzformat sind auch solche mit langen Namen
zulässig. Beispielsweise werden sowohl
quit
als auch \q
akzeptiert. Siehe auch Abschnitt 8.5.2, „mysql-Befehle“.
Das automatische Rehashing wird unterbunden. Diese Option
sorgt zwar für einen schnelleren Start von
mysql, aber Sie müssen den Befehl
rehash
absetzen, wenn Sie die
Vervollständigung von Tabellen- und Spaltennamen
verwenden wollen.
Unterbindet die Ausgabe eines Warntons bei Auftreten eines Fehlers.
Deaktiviert benannte Befehle. Verwenden Sie nur die Form
\*
oder setzen Sie benannte Befehle nur
am Anfang einer Zeile ein, die mit einem Semikolon
(‘;
’) endet.
mysql startet standardmäßig mit
aktivierter Option. Allerdings
funktionieren Befehle im langen Format auch bei dieser
Option noch in der ersten Zeile. Siehe auch
Abschnitt 8.5.2, „mysql-Befehle“.
Die Abfrageergebnisse sollen nicht mit dem Pager (d. h. nicht seitenweise) ausgegeben werden. Abschnitt 8.5.2, „mysql-Befehle“, enthält eine eingehendere Beschreibung zum Pager.
Unterbindet das Kopieren der Ausgabe in einer Datei. Abschnitt 8.5.2, „mysql-Befehle“, enthält eine eingehendere Beschreibung von Tee-Dateien.
Ignoriert alle Anweisungen mit Ausnahme derjenigen, die an die auf der Befehlszeile genannte Standarddatenbank gerichtet sind. Dies ist nützlich, um Aktualisierungen anderer Datenbanken im Binärlog zu übergehen.
Verwendet den angegebenen Befehl zur Anzeige der
Abfrageausgabe Seite für Seite. Wird der Befehl
weggelassen, dann wird der Standardpager verwendet, der in
Ihrer Umgebungsvariable PAGER
gespeichert ist. Gültige Pager sind
less, more,
cat [> filename] usw. Diese Option
wird nur unter Unix verwendet. Im Stapelbetrieb
funktioniert sie nicht. Abschnitt 8.5.2, „mysql-Befehle“,
enthält eine eingehendere Beschreibung zum Pager.
--password[=
,
password
]-p[
password
]
Verwendet das angegebene Passwort zur Verbindung mit dem
Server. Wenn Sie die Kurzform der Option
(-p
) verwenden, dürfen Sie
kein Leerzeichen zwischen Option und
Passwort setzen. Lassen Sie den Wert
password
auf die Option
--password
bzw. -p
folgend weg, dann werden Sie zur Eingabe des Passworts
aufgefordert.
Die Angabe eines Passworts direkt auf der Befehlszeile ist als nicht sicher einzuordnen. Siehe auch Abschnitt 5.9.6, „Wie Sie Ihre Kennwörter sicher halten“.
Die TCP/IP-Portnummer, die für die Verbindung verwendet werden soll.
Setzt die Eingabeaufforderung auf das angegebene Format.
Standardwert ist mysql>
. Die
Sondersequenzen, die die Eingabeaufforderung enthalten
kann, sind unter Abschnitt 8.5.2, „mysql-Befehle“,
beschrieben.
--protocol={TCP|SOCKET|PIPE|MEMORY}
Das zu verwendende Verbindungsprotokoll.
Unterbindet die Zwischenspeicherung der einzelnen Abfrageergebnisse (d. h., jeder Datensatz wird direkt beim Empfang angezeigt). Hierdurch kann der Server verlangsamt werden, wenn die Ausgabe aussetzt. Bei dieser Option verwendet mysql die Verlaufsdatei nicht.
Schreibt Spaltenwerte ohne Konvertierung mit
Escape-Zeichen. Wird häufig mit der Option
--batch
verwendet.
Wenn die Verbindung zum Server abbricht, wird automatisch
eine Wiederverbindung versucht. Bei jedem
Verbindungsabbruch wird genau ein Wiederverbindungsversuch
unternommen. Um diese Versuche zu unterbinden, verwenden
Sie --skip-reconnect
.
--safe-updates
,
--i-am-a-dummy
, -U
Gestattet nur diejenigen UPDATE
- und
DELETE
-Anweisungen, die über
Schlüsselwerte angeben, welche Datensätze zu ändern
sind. Wenn Sie diese Option in einer Optionsdatei
angegeben haben, können Sie sie mithilfe von
--safe-updates
auf der Befehlszeile
außer Kraft setzen. Weitere Informationen zu dieser
Option finden Sie in Abschnitt 8.5.4, „mysql: Tipps“.
Sendet kein Passwort im alten (d. h. vor MySQL 4.1.1 gültigen) Format an den Server. Hierdurch werden Verbindungen auf solche Server beschränkt, die das neue Passwortformat verwenden.
Sorgt dafür, dass – sofern erforderlich – nach jeder Anweisung Warnungen angezeigt werden. Diese Option gilt für den interaktiven und den Stapelbetrieb.
Ignoriert SIGINT
-Signale (diese werden
normalerweise durch Eingabe von
Strg+C
abgesetzt).
Stummer Modus. Erzeugt weniger Ausgabedaten. Diese Option kann mehrfach angegeben werden, um den Umfang der Ausgabe kontinuierlich zu verringern.
Schreibt keine Spaltennamen in die Ergebnisse.
Schreibt keine Zeilennummern für Fehler. Dies ist praktisch, wenn Sie Ergebnisdateien vergleichen wollen, die Fehlermeldungen enthalten.
Bei Verbindungen mit localhost
ist dies
die zu verwendende Unix-Socketdatei bzw. (unter Windows)
der Name der zu verwendenden Named Pipe.
Zeigt die Ausgabe im Tabellenformat an. Dies ist das Standardverhalten bei interaktivem Betrieb und kann zudem für die Ausgabe im Stapelbetrieb verwendet werden.
Hängt eine Kopie der Ausgabe an die angegebene Datei an. Diese Option funktioniert im Stapelbetrieb nicht. Eine eingehendere Beschreibung von Tee-Dateien finden Sie in Abschnitt 8.5.2, „mysql-Befehle“.
Synchronisiert den Puffer nach jeder Abfrage.
--user=
,
user_name
-u
user_name
Verwendet den angegebenen MySQL-Benutzernamen zur Verbindung mit dem Server.
Ausführlicher Modus. Es werden zusätzliche Angaben zu
den Aktivitäten des Programms erzeugt. Diese Option kann
mehrfach angegeben werden, um den Umfang der Ausgabe
kontinuierlich zu erhöhen. (Beispielsweise erzeugt
-v -v -v
auch im Stapelbetrieb eine
Ausgabe im Tabellenformat.)
Zeigt die Versionsinformation an und wird dann beendet.
Gibt die Abfrageausgabe vertikal angeordnet aus (d. h.
eine Zeile pro Spaltenwert). Ohne diese Option können Sie
die vertikale Ausgabe für einzelne Anweisungen festlegen,
indem Sie sie mit \G
abschließen.
Wenn die Verbindung nicht hergestellt werden kann, erfolgt anstelle eines Abbruchs nach einer Wartezeit ein neuer Verbindungsversuch.
Erzeugt eine XML-formatierte Ausgabe.
Sie können mit der Syntax
--
auch die folgenden Variablen einstellen:
var_name
=value
Anzahl der Sekunden bis zur Zeitüberschreitung der
Verbindung. (Der Vorgabewert ist 0
.)
Maximaler Umfang der vom Server gesendeten oder empfangenen Pakete. (Der Vorgabewert ist 16 Mbyte.)
Das automatische Limit für Datensätze in einem Join bei
Verwendung von --safe-updates
. (Der
Vorgabewert beträgt 1.000.000.)
Puffergröße für die TCP/IP- und Socketkommunikation. (Der Vorgabewert ist 16 Kbyte.)
Automatisches Limit für
SELECT
-Anweisungen bei Verwendung von
--safe-updates
. (Der Vorgabewert beträgt
1.000.)
Es ist ferner möglich, Variablen über die Syntax
--set-variable=
oder var_name
=value
-O
einzustellen. Diese Syntax ist jedoch
veraltet.
var_name
=value
Unter Unix schreibt der mysql-Client einen
Eintrag mit ausgeführten Anweisungen in eine Verlaufsdatei.
Standardmäßig heißt diese Verlaufsdatei
.mysql_history
und wird im
Stammverzeichnis erstellt. Durch Einstellen der
Umgebungsvariablen MYSQL_HISTFILE
können
Sie eine andere Datei angeben.
Wenn Sie keine Verlaufsdatei führen wollen, entfernen Sie
zunächst .mysql_history
(sofern
vorhanden) und verwenden daraufhin eine der folgenden
Methoden:
Setzen Sie die Variable MYSQL_HISTFILE
auf /dev/null
. Damit diese
Einstellung bei jeder Anmeldung angewendet wird, müssen
Sie sie in eine der Startdateien Ihrer Shell schreiben.
Erstellen Sie .mysql_history
als
symbolische Verknüpfung auf
/dev/null
:
shell> ln -s /dev/null $HOME/.mysql_history
Dies müssen Sie nur einmal tun.
mysql sendet jede von Ihnen abgesetzte
SQL-Anweisung zur Ausführung an den Server. Es gibt aber auch
eine Reihe von Befehlen, die mysql selbst
interpretiert. Eine Liste dieser Befehle erhalten Sie, indem
Sie help
oder \h
an der
Eingabeaufforderung mysql>
eingeben:
mysql> help
List of all MySQL commands:
Note that all text commands must be first on line and end with ';'
? (\?) Synonym for `help'.
clear (\c) Clear command.
connect (\r) Reconnect to the server. Optional arguments are db and host.
delimiter (\d) Set statement delimiter. NOTE: Takes the rest of the line as
new delimiter.
edit (\e) Edit command with $EDITOR.
ego (\G) Send command to mysql server, display result vertically.
exit (\q) Exit mysql. Same as quit.
go (\g) Send command to mysql server.
help (\h) Display this help.
nopager (\n) Disable pager, print to stdout.
notee (\t) Don't write into outfile.
pager (\P) Set PAGER [to_pager]. Print the query results via PAGER.
print (\p) Print current command.
prompt (\R) Change your mysql prompt.
quit (\q) Quit mysql.
rehash (\#) Rebuild completion hash.
source (\.) Execute an SQL script file. Takes a file name as an argument.
status (\s) Get status information from the server.
system (\!) Execute a system shell command.
tee (\T) Set outfile [to_outfile]. Append everything into given
outfile.
use (\u) Use another database. Takes database name as argument.
warnings (\W) Show warnings after every statement.
nowarning (\w) Don't show warnings after every statement.
Für jeden Befehl gibt es eine Lang- und eine Kurzform. Anders als bei der Langform wird die Groß-/Kleinschreibung bei der Kurzform unterschieden. Der Langform eines Befehls kann optional ein Semikolon als Trennzeichen folgen; dieses sollte bei der Kurzform weggelassen werden.
Für den Befehl delimiter
sollten Sie die
Verwendung des Backslashs (‘\
’)
vermeiden, da dieser bei MySQL als Escape-Zeichen dient.
Die Befehle edit, nopager, pager und system funktionieren nur unter Unix.
Der Befehl status
bietet Informationen zur
Verbindung und zum verwendeten Server. Wenn der Client mit
--safe-updates
gestartet wurde, gibt
status
auch die Werte für die
mysql-Variablen aus, die sich auf Ihre
Abfragen auswirken.
Um Abfragen und ihre Ausgaben zu loggen, verwenden Sie den
Befehl tee. Alle auf dem Bildschirm
angezeigten Daten werden an eine angegebene Datei angehängt.
Dies kann auch zu Debugzwecken sehr praktisch sein. Sie
können diese Funktion auf der Befehlszeile mit der Option
--tee
oder interaktiv mit dem Befehl
tee aktivieren. Die Datei
tee kann interaktiv mit dem Befehl
notee deaktiviert werden. Die erneute
Ausführung von tee reaktiviert das Loggen
wieder. Wird kein Parameter angegeben, dann wird die vorherige
Datei verwendet. Beachten Sie, dass tee
Abfrageergebnisse nach jeder Anweisung synchronisiert –
unmittelbar bevor mysql die nächste
Eingabeaufforderung anzeigt.
Mithilfe der Option --pager
können Sie
Abfrageergebnisse im interaktiven Modus mit Unix-Programmen
wie less, more o. Ä.
durchsuchen. Wenn Sie keinen Wert für die Option angeben,
überprüft mysql den Wert der
Umgebungsvariablen PAGER
und setzt den
Pager auf diesen Wert. Interaktiv lässt sich das Paging
mithilfe des Befehls pager aktivieren und
mit nopager deaktivieren. Der Befehl nimmt
ein optionales Argument entgegen; ist es vorhanden, dann wird
das entsprechende Pager-Programm ausgewählt. Ohne
Argumentangabe wird der Pager, der über die Befehlszeile
angegeben wurde, oder stdout
ausgewählt
(sofern überhaupt kein Pager festgelegt wurde).
Die seitenweise Ausgabe funktioniert nur unter Unix, da sie
die Funktion popen()
verwendet, die unter
Windows nicht existiert. Unter Windows kann stattdessen die
Option tee zur Speicherung der
Abfrageausgabe verwendet werden, auch wenn dies in bestimmten
Situationen zum Durchsuchen der Ausgabe nicht so praktisch ist
wie pager.
Es folgen ein paar Tipps zum Befehl pager:
Sie können damit in eine Datei schreiben, und die Ergebnisse landen dann auch nur in dieser Datei:
mysql> pager cat > /tmp/log.txt
Sie können auch Optionen für das Programm übergeben, das Sie als Pager verwenden wollen:
mysql> pager less -n -i -S
Beachten Sie die Option -S
im obigen
Beispiel. Sie kann zum Durchblättern sehr breiter
Abfrageergebnisse recht praktisch sein. Manchmal sind sehr
breite Ergebnismengen auf dem Bildschirm schlecht zu
lesen. Die Option -S
für den Befehl
less kann die Lesbarkeit der Ergebnisse
erheblich steigern, denn sie erlaubt das horizontale
Scrolling mit den Pfeiltasten auf der Computertastatur.
Sie können die Option -S
auch interaktiv
innerhalb von less verwenden, um das
horizontale Scrolling nach Belieben ein- und
auszuschalten. Weitere Informationen finden Sie auf der
Manpage zu less:
shell> man less
Sie können zur Verarbeitung der Ausgabe sehr komplexe Pager-Befehle angeben:
mysql>pager cat | tee /dr1/tmp/res.txt \
| tee /dr2/tmp/res2.txt | less -n -i -S
In diesem Beispiel würde der Befehl die Abfrageergebnisse
an zwei Dateien in zwei verschiedenen Verzeichnissen auf
zwei separaten Dateisystemen senden, die als
/dr1
und /dr2
eingebunden sind. Via less werden die
Ergebnisse aber auch auf dem Bildschirm angezeigt.
Sie können die Funktionen von tee und pager auch kombinieren. Wenn Sie eine tee-Datei aktivieren und pager auf less setzen, können Sie die Ergebnisse mit dem Programm less durchsuchen und gleichzeitig alles an eine Datei anhängen. Der Unterschied zwischen tee unter Unix, wenn es mit dem pager-Befehl verwendet wird, und dem in mysql integrierten tee-Befehl besteht darin, dass das integrierte tee auch dann funktioniert, wenn der Unix-Befehl tee nicht vorhanden ist. Außerdem loggt das integrierte tee alles, was auf dem Bildschirm ausgegeben wird; im Gegensatz dazu wird von dem unter Unix mit pager verwendeten tee nicht so viel protokolliert. Zudem lässt sich das tee-Dateiloggen interaktiv aus mysql heraus ein- und ausschalten. Dies ist nützlich, wenn Sie nur einige, nicht aber alle Abfragen in einer Datei loggen wollen.
Die Standardeingabeaufforderung mysql>
kann umkonfiguriert werden. Der String zur Definition der
Eingabeaufforderung kann die folgenden Spezialsequenzen
enthalten:
Option | Beschreibung |
\v | Serverversion |
\d | Standarddatenbank |
\h | Serverhost |
\p | aktuelle TCP/IP-Port bzw. aktuelle Socketdatei |
\u | Ihr Benutzername |
\U | Ihr vollständiger
-Kontenname |
\\ | literales ‘\ ’-Backslash-Zeichen |
\n | Zeilenwechselzeichen |
\t | Tabulatorzeichen |
\ | Leerzeichen (folgt dem Backslash) |
\_ | Leerzeichen |
\R | aktuelle Uhrzeit im 24-Stunden-Format (0 - 23) |
\r | aktuelle Uhrzeit im 12-Stunden-Format (1 - 12) |
\m | Minuten der aktuellen Uhrzeit |
\y | aktuelles Jahr (zweistellig) |
\Y | aktuelles Jahr (vierstellig) |
\D | aktuelles vollständiges Datum |
\s | Sekunden der aktuellen Uhrzeit |
\w | aktueller Wochentag, angegeben mit drei Buchstaben („Mon“, „Tue“ usw.) |
\P | AM/PM |
\o | aktueller Monat im numerischen Format |
\O | aktueller Monat, angegeben mit drei Buchstaben („Jan“, „Feb“ usw.) |
\c | Zähler, der bei jeder von Ihnen abgesetzten Anweisung hochgezählt wird |
\S | Semikolon |
\' | einfaches Anführungszeichen |
\" | doppeltes Anführungszeichen |
‘\
’ gefolgt von einem
beliebigen anderen Buchstaben wird zu genau diesem Buchstaben.
Wenn Sie den Befehl prompt
ohne Argument
eingeben, setzt mysql die
Eingabeaufforderung auf die Standardform
(mysql>
) zurück.
Sie können die Eingabeaufforderung auf verschiedene Weise einstellen:
Sie verwenden eine Umgebungsvariable.
Sie können der Umgebungsvariablen
MYSQL_PS1
als Wert einen
Eingabeaufforderungs-String zuweisen. Zum Beispiel:
shell> export MYSQL_PS1="(\u@\h) [\d]> "
Sie verwenden eine
Befehlszeilenoption. Sie können für
mysql die Option
--prompt
auf der Befehlszeile angeben.
Zum Beispiel:
shell> mysql --prompt="(\u@\h) [\d]> "
(user@host) [database]>
Sie verwenden eine Optionsdatei. Sie
können die Option prompt
im Abschnitt
[mysql]
einer beliebigen
MySQL-Optionsdatei (z. B.
/etc/my.cnf
oder
.my.cnf
) in Ihrem Stammverzeichnis
angeben. Zum Beispiel:
[mysql] prompt=(\\u@\\h) [\\d]>\\_
Beachten Sie in diesem Beispiel die doppelten Backslashs.
Wenn Sie die Eingabeaufforderung mit der Option
prompt
in einer Optionsdatei
einstellen, sollten Sie die Backslashes verdoppeln, wenn
Sie bestimmte Optionen für die Eingabeaufforderung
angeben. Es gibt eine Reihe von Überschneidungen zwischen
den zulässigen Optionen für die Eingabeaufforderung und
den speziellen Escape-Sequenzen, die in Optionsdateien
erkannt werden. (Diese Sequenzen sind in
Abschnitt 4.3.2, „my.cnf-Optionsdateien“, aufgelistet.) Diese
Überschneidungen können bei Verwendung einzelner
Backslashs Probleme verursachen. So wird etwa
\s
als Leerzeichen statt als aktueller
Sekundenwert interpretiert. Das folgende Beispiel zeigt,
wie Sie eine Eingabeaufforderung in einer Optionsdatei so
definieren, dass die aktuelle Uhrzeit im Format
HH:MM:SS>
enthalten ist:
[mysql] prompt="\\r:\\m:\\s> "
Sie stellen die Eingabeaufforderung interaktiv
ein. Sie können Ihre Eingabeaufforderung auch
interaktiv mithilfe des Befehls prompt
(oder \R
) einstellen. Zum Beispiel:
mysql>prompt (\u@\h) [\d]>\_
PROMPT set to '(\u@\h) [\d]>\_' (user
@host
) [database
]> (user
@host
) [database
]> prompt Returning to default PROMPT of mysql> mysql>
Der Client mysql wird normalerweise interaktiv verwendet. Das sieht etwa so aus:
shell> mysql db_name
Es ist allerdings auch möglich, SQL-Anweisungen in einer
Datei abzulegen und mysql dann anzuweisen,
seine Eingabe aus dieser Datei auszulesen. Zu diesem Zweck
erstellen Sie eine Textdatei
text_file
, die die Anweisungen
enthält, die Sie ausführen wollen. Danach rufen Sie
mysql wie folgt auf:
shell> mysql db_name
< text_file
Wenn Sie als Erstes eine USE
-Anweisung in die
Datei setzen, müssen Sie den Datenbanknamen nicht mehr auf
der Befehlszeile angeben:
db_name
shell> mysql < text_file
Wird mysql bereits ausgeführt, dann
können Sie eine SQL-Skriptdatei mithilfe des Befehls
source
oder \.
ausführen:
mysql>source
mysql>file_name
\.
file_name
In bestimmten Fällen kann es sinnvoll sein, ein Skript Fortschrittsinformationen für den Benutzer anzeigen zu lassen. Hierzu können Sie Anweisungen wie die folgende einfügen:
SELECT '<info_to_display>' AS ' ';
Die gezeigte Anweisung gibt
<info_to_display>
aus.
Weitere Informationen zum Stapelbetrieb finden Sie in
Abschnitt 3.5, „mysql
im Stapelbetrieb“.
Dieser Abschnitt beschreibt einige Methoden, mit deren Hilfe Sie mysql effizienter benutzen können.
Die Lesbarkeit bestimmter Abfrageergebnisse wird erhöht,
wenn diese nicht in einem horizontalen, sondern einem
vertikalen Tabellenformat angezeigt werden. Die Abfrage wird
vertikal angezeigt, indem sie mit \G
statt mit einem Semikolon abgeschlossen wird. So lassen sich
etwa längere Textwerte mit Zeilenumbrüchen häufig besser
lesen, wenn sie vertikal ausgegeben werden:
mysql> SELECT * FROM mails WHERE LENGTH(txt) < 300 LIMIT 300,1\G
*************************** 1. row ***************************
msg_nro: 3068
date: 2000-03-01 23:29:50
time_zone: +0200
mail_from: Monty
reply: monty@no.spam.com
mail_to: "Thimble Smith" <tim@no.spam.com>
sbj: UTF-8
txt: >>>>> "Thimble" == Thimble Smith writes:
Thimble> Hi. I think this is a good idea. Is anyone familiar
Thimble> with UTF-8 or Unicode? Otherwise, I'll put this on my
Thimble> TODO list and see what happens.
Yes, please do that.
Regards,
Monty
file: inbox-jani-1
hash: 190402944
1 row in set (0.09 sec)
Für MySQL-Neulinge kann die Startoption
--safe-updates
(bzw.
--i-am-a-dummy
, was den gleichen Effekt
hat) ausgesprochen nützlich sein. Sie hilft in Fällen, in
denen Sie eine DELETE FROM
-Anweisung
abgesetzt, aber die tbl_name
WHERE
-Klausel
vergessen haben. Normalerweise werden durch eine solche
Anweisung nämlich alle Datensätze in der Tabelle
gelöscht. Mit --safe-updates
können Sie
Datensätze nur dann löschen, wenn die Schlüsselwerte
angegeben sind, mit denen sie identifiziert werden. Auf
diese Weise werden Unfälle verhindert.
Wenn Sie die Option --safe-updates
benutzen, setzt mysql beim Herstellen der
Verbindung zum MySQL Server die folgende Anweisung ab:
SET SQL_SAFE_UPDATES=1,SQL_SELECT_LIMIT=1000, SQL_MAX_JOIN_SIZE=1000000;
Siehe auch Abschnitt 13.5.3, „SET
“.
Die Anweisung SET
hat die folgenden
Auswirkungen:
Sie dürfen eine UPDATE
- oder
DELETE
-Anweisung nur dann ausführen,
wenn Sie einen Schlüssel-Constraint in der
WHERE
-Klausel spezifiziert oder eine
LIMIT
-Klausel angegeben haben (oder
beides). Zum Beispiel:
UPDATEtbl_name
SETnot_key_column
=val
WHEREkey_column
=val
; UPDATEtbl_name
SETnot_key_column
=val
LIMIT 1;
Der Server beschränkt alle umfangreichen
SELECT
-Ergebnisse auf 1.000
Datensätze, sofern die Anweisung keine
LIMIT
-Klausel enthält.
Der Server bricht tabellenübergreifende
SELECT
-Anweisungen ab, bei denen
voraussichtlich mehr als 1.000.000
Datensatzkombinationen untersucht werden müssten.
Um andere Grenzen als 1.000 und 1.000.000 anzugeben, können
Sie die Vorgaben mithilfe der Optionen
--select_limit
und
--max_join_size
außer Kraft setzen:
shell> mysql --safe-updates --select_limit=500 --max_join_size=10000
Wenn die Verbindung zwischen dem mysql-Client und dem Server während des Versands einer Abfrage abbricht, dann versucht der Client, die Verbindung sofort und automatisch wiederherzustellen, und sendet die Abfrage dann erneut. Ihre vorherige Verbindung ist aber auch dann, wenn mysql die Neuverbindung gelingt, definitiv beendet, d. h., alle vorherigen Sitzungsobjekte und Einstellungen sind verloren: Temporärtabellen, Autocommit-Modus und benutzerdefinierte und Sitzungsvariablen. Außerdem wird für alle aktuellen Transaktionen ein Rollback durchgeführt. Dieses Verhalten kann für Sie gefährlich sein. Beachten Sie das folgende Beispiel, in dem der Server heruntergefahren und neu gestartet wurde, ohne dass Sie davon erfahren haben:
mysql>SET @a=1;
Query OK, 0 rows affected (0.05 sec) mysql>INSERT INTO t VALUES(@a);
ERROR 2006: MySQL server has gone away No connection. Trying to reconnect... Connection id: 1 Current database: test Query OK, 1 row affected (1.30 sec) mysql>SELECT * FROM t;
+------+ | a | +------+ | NULL | +------+ 1 row in set (0.05 sec)
Die Benutzervariable @a
ist mit der
Verbindung verloren gegangen und nach der Neuverbindung
undefiniert. Wenn wichtig ist, dass mysql
in dem Fall, dass die Verbindung abreißt, mit einem Fehler
beendet wird, dann können Sie den
mysql-Client mit der Option
--skip-reconnect
starten.
mysqlaccess ist ein Diagnosetool, das Yves
Carlier für die MySQL-Distribution erstellt hat. Es
überprüft die Zugriffsberechtigungen für eine Kombination
aus Hostnamen, Benutzernamen und Datenbank. Beachten Sie, dass
mysqlaccess den Zugriff nur mithilfe der
Tabellen user
, db
und
host
überprüft. Nicht verifiziert werden
Tabellen-, Spalten- oder Routineberechtigungen, die in den
Tabellen tables_priv
,
columns_priv
bzw.
procs_priv
festgelegt sind.
Rufen Sie mysqlaccess wie folgt auf:
shell> mysqlaccess [host_name
[user_name
[db_name
]]] [options
]
mysqlaccess versteht die folgenden Optionen:
--help
, -?
Zeigt eine Hilfemeldung an und wird dann beendet.
--brief
, -b
Erzeugt Berichte in einem einzeiligen tabellarischen Format.
--commit
Kopiert die neuen Zugriffsberechtigungen aus den Temporärtabellen in die ursprünglichen Grant-Tabellen. Damit die neuen Berechtigungen angewendet werden, müssen die Grant-Tabellen auf Festplatte synchronisiert werden. (Führen Sie hierzu etwa den Befehl mysqladmin reload aus.)
--copy
Lädt die temporären Grant-Tabellen aus den Originaltabellen.
--db=
,
db_name
-d
db_name
Gibt den Datenbanknamen an.
--debug=
N
Gibt die Debugstufe an. N
ist
ein Integer zwischen 0 und 3.
--host=
,
host_name
-h
host_name
Der in den Zugriffsberechtigungen zu verwendende Hostname.
--howto
Zeigt einige Beispiele für die Verwendung von mysqlaccess an.
--old_server
Legt fest, dass der Server ein alter MySQL Server (vor
MySQL 3.21) ist, der vollständige
WHERE
-Klauseln noch nicht verarbeiten
kann.
--password[=
,
password
]-p[
password
]
Verwendet das angegebene Passwort zur Verbindung mit dem
Server. Lassen Sie den Wert
password
auf die Option
--password
bzw. -p
folgend weg, dann werden Sie zur Eingabe des Passworts
aufgefordert.
Die Angabe eines Passworts direkt auf der Befehlszeile ist als nicht sicher einzuordnen. Siehe auch Abschnitt 5.9.6, „Wie Sie Ihre Kennwörter sicher halten“.
--plan
Zeigt Vorschläge und Ideen für zukünftige Releases an.
--preview
Zeigt die Unterschiede in den Berechtigungen nach der Durchführung von Änderungen in den Grant-Tabellen an.
--relnotes
Zeigt die Versionshinweise an.
--rhost=
,
host_name
-H
host_name
Stellt eine Verbindung zum MySQL Server auf dem angegebenen Host her.
--rollback
Macht die letzten Änderungen an den temporären Grant-Tabellen rückgängig.
--spassword[=
,
password
]-P[
password
]
Verwendet das angegebene Passwort zur Verbindung als
Superuser mit dem Server. Lassen Sie den Wert
password
auf die Option
--password
bzw. -p
folgend weg, dann werden Sie zur Eingabe des Passworts
aufgefordert.
Die Angabe eines Passworts direkt auf der Befehlszeile ist als nicht sicher einzuordnen. Siehe auch Abschnitt 5.9.6, „Wie Sie Ihre Kennwörter sicher halten“.
--superuser=
,
user_name
-U
user_name
Gibt den Benutzernamen zur Verbindung als Superuser an.
--table
, -t
Erzeugt Berichte im Tabellenformat.
--user=
,
user_name
-u
user_name
Der in den Zugriffsberechtigungen zu verwendende Benutzername.
--version
, -v
Zeigt die Versionsinformation an und wird dann beendet.
Wenn Ihre MySQL-Distribution an einer anderen als der
Standardposition installiert ist, müssen Sie die Position
ändern, an der mysqlaccess das
Vorhandensein des mysql-Clients erwartet.
Sie müssen das Skript mysqlaccess
im
Bereich der Zeile 18 editieren. Suchen Sie nach einer Zeile
ähnlich der folgenden:
$MYSQL = '/usr/local/bin/mysql'; # path to mysql executable
Ändern Sie den Pfad so ab, dass er die Position wiedergibt,
an der mysql tatsächlich auf Ihrem System
gespeichert ist. Andernfalls erhalten Sie den Fehler
Broken pipe
, wenn Sie
mysqlaccess ausführen.
mysqladmin ist ein Client zur Durchführung administrativer Aufgaben. Sie können damit Konfiguration und aktuellen Status des Servers überprüfen, Datenbanken erstellen und löschen und vieles mehr.
Rufen Sie mysqladmin wie folgt auf:
shell> mysqladmin [options
] command
[command-arg
] [command
[command-arg
]] ...
mysqladmin unterstützt die in der folgenden Liste beschriebenen Befehle. Einige Befehle nehmen auf den Befehlsnamen folgend ein Argument entgegen.
create
db_name
Erstellt eine neue Datenbank namens
db_name
.
debug
Weist den Server an, Debuginformationen in das Fehlerlog zu schreiben.
drop
db_name
Löscht die Datenbank namens
db_name
und alle in ihr
enthaltenen Tabellen.
extended-status
Zeigt die Serverstatusvariablen und ihre jeweiligen Werte an.
flush-hosts
Synchronisiert alle Daten in den Host-Cache.
flush-logs
Schreibt alle Logs auf Festplatte.
flush-privileges
Lädt die Grant-Tabellen neu (wie
reload
).
flush-status
Löscht die Statusvariablen.
flush-tables
Synchronisiert alle Tabellen auf Festplatte.
flush-threads
Synchronisiert den Thread-Cache.
kill
id
,id
,…
Terminiert Server-Threads. Werden mehrere Thread-Kennungswerte übergeben, dann dürfen in der Liste keine Leerzeichen enthalten sein.
old-password
new-password
Entspricht dem Befehl password
,
speichert das Passwort aber im alten (vor MySQL 4.1
verwendeten) Hashing-Format. (Siehe auch
Abschnitt 5.8.9, „Kennwort-Hashing ab MySQL 4.1“.)
password
new-password
Legt ein neues Passwort fest. Hierdurch wird das Passwort
des Kontos, das Sie bei mysqladmin zur
Verbindung mit dem Server verwenden, auf
new-password
gesetzt. Wenn Sie
also beim nächsten Mal mysqladmin
(oder ein anderes Clientprogramm) über dieses Konto
aufrufen, müssen Sie das neue Passwort angeben.
Wenn der Wert new-password
Leerzeichen oder andere Zeichen enthält, die von Ihrem
Befehls-Interpreter als Sonderzeichen interpretiert
werden, dann müssen Sie es in Anführungszeichen setzen.
Dabei sind unter Windows in jedem Fall doppelte statt
einfache Anführungszeichen zu benutzen, da Letztere bei
der Verarbeitung nicht entfernt, sondern als Teil des
Passworts betrachtet werden. Zum Beispiel:
shell> mysqladmin password "my new password"
ping
Überprüft, ob der Server ausgeführt wird. Der
Rückgabestatus von mysqladmin ist 0,
wenn der Server läuft, andernfalls 1. 0 ist auch im Falle
eines Fehlers wie Access denied
das
Ergebnis, denn hierbei hat der Server die Verbindung zwar
abgewiesen, wird aber trotzdem ausgeführt.
processlist
Zeigt eine Liste aktiver Server-Threads an. Dies ähnelt
der Ausgabe der Anweisung SHOW
PROCESSLIST
. Wird die Option
--verbose
angegeben, dann entspricht die
Ausgabe derjenigen von SHOW FULL
PROCESSLIST
. (Siehe auch
Abschnitt 13.5.4.19, „SHOW PROCESSLIST
“.)
reload
Lädt die Grant-Tabellen neu.
refresh
Synchronisiert alle Tabellen und schließt und öffnet die Logdateien.
shutdown
Beendet den Server.
start-slave
Startet die Replikation auf einem Slave-Server.
status
Zeigt eine kurze Meldung zum Serverstatus an.
stop-slave
Beendet die Replikation auf einem Slave-Server.
variables
Zeigt die Serversystemvariablen und ihre jeweiligen Werte an.
version
Zeigt Versionsinformationen vom Server an.
Alle Befehle lassen sich auf ein beliebiges eindeutiges Präfix kürzen. Zum Beispiel:
shell> mysqladmin proc stat
+----+-------+-----------+----+---------+------+-------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+-------+-----------+----+---------+------+-------+------------------+
| 51 | monty | localhost | | Query | 0 | | show processlist |
+----+-------+-----------+----+---------+------+-------+------------------+
Uptime: 1473624 Threads: 1 Questions: 39487
Slow queries: 0 Opens: 541 Flush tables: 1
Open tables: 19 Queries per second avg: 0.0268
Die Ausgabe des Befehls mysqladmin status zeigt die folgenden Werte an:
Dauer seit dem Serverstart (in Sekunden).
Anzahl der aktiven Threads (Clients).
Anzahl der Abfragen, die seit dem Serverstart von Clients eingegangen sind.
Anzahl der Abfragen, die länger als die durch
long_query_time
angegebene Anzahl von
Sekunden dauerten. Siehe auch
Abschnitt 5.12.4, „Die Logdatei für langsame Anfragen“.
Anzahl der Tabellen, die vom Server geöffnet wurden.
Anzahl der vom Server ausgeführten
flush-*
-, refresh
-
und reload
-Befehle.
Anzahl der derzeit offenen Tabellen.
Umfang des Speichers, der direkt von
mysqld reserviert wurde. Der Wert wird
nur angezeigt, wenn MySQL mit der Option
--with-debug=full
kompiliert wurde.
Maximaler Umfang des Speichers, der direkt von
mysqld reserviert wurde. Der Wert wird
nur angezeigt, wenn MySQL mit der Option
--with-debug=full
kompiliert wurde.
Wenn Sie mysqladmin shutdown beim Herstellen einer Verbindung zu einem lokalen Server mithilfe einer Unix-Socketdatei ausführen, wartet mysqladmin, bis die Prozesskennungsdatei des Servers entfernt wurde, um sicherzustellen, dass der Server korrekt beendet wurde.
mysqladmin unterstützt die folgenden Optionen:
--help
, -?
Zeigt eine Hilfemeldung an und wird dann beendet.
--character-sets-dir=
path
Das Verzeichnis, in dem Zeichensätze installiert sind. Siehe auch Abschnitt 5.11.1, „Der für Daten und zum Sortieren benutzte Zeichensatz“.
--compress
, -C
Komprimiert alle Daten, die zwischen Client und Server ausgetauscht werden, sofern beide die Komprimierung unterstützen.
--count=
,
N
-c
N
Anzahl der Iterationen, die für die wiederholte
Befehlsausführung erforderlich sind. Funktioniert nur mit
der Option --sleep
.
--debug[=
,
debug_options
]-#
[
debug_options
]
Schreibt ein Debuglog. Der String
debug_options
heißt häufig
'd:t:o,
.
Standardwert ist
file_name
''d:t:o,/tmp/mysqladmin.trace'
.
--default-character-set=
charset_name
Verwendet charset_name
als
Standardzeichensatz. Siehe auch
Abschnitt 5.11.1, „Der für Daten und zum Sortieren benutzte Zeichensatz“.
--force
, -f
Fordert für den Befehl drop
keine
Bestätigung an. Bei mehreren Befehlen erfolgt auch bei
Auftreten eines Fehlers kein Abbruch.
db_name
--host=
,
host_name
-h
host_name
Stellt eine Verbindung zum MySQL Server auf dem angegebenen Host her.
--password[=
,
password
]-p[
password
]
Verwendet das angegebene Passwort zur Verbindung mit dem
Server. Wenn Sie die Kurzform der Option
(-p
) verwenden, dürfen Sie
kein Leerzeichen zwischen Option und
Passwort setzen. Lassen Sie den Wert
password
auf die Option
--password
bzw. -p
folgend weg, dann werden Sie zur Eingabe des Passworts
aufgefordert.
Die Angabe eines Passworts direkt auf der Befehlszeile ist als nicht sicher einzuordnen. Siehe auch Abschnitt 5.9.6, „Wie Sie Ihre Kennwörter sicher halten“.
--port=
,
port_num
-P
port_num
Die TCP/IP-Portnummer, die für die Verbindung verwendet werden soll.
--protocol={TCP|SOCKET|PIPE|MEMORY}
Das zu verwendende Verbindungsprotokoll.
--relative
, -r
Zeigt bei gemeinsamer Verwendung mit der Option
--sleep
den Unterschied zwischen
aktuellem und vorherigem Wert. Derzeit funktioniert diese
Option nur mit dem Befehl
extended-status
.
--silent
, -s
Wenn keine Verbindung zum Server hergestellt werden kann, erfolgt eine stillschweigende Beendigung.
--sleep=
,
delay
-i
delay
Führt Befehle wiederholt aus, wobei dazwischen die mit
delay
angegebene Anzahl von
Sekunden verstreicht. Die Option --count
bestimmt die Anzahl der Iterationen.
--socket=
,
path
-S
path
Bei Verbindungen mit localhost
ist dies
die zu verwendende Unix-Socketdatei bzw. (unter Windows)
der Name der zu verwendenden Named Pipe.
--user=
,
user_name
-u
user_name
Verwendet den angegebenen MySQL-Benutzernamen zur Verbindung mit dem Server.
--verbose
, -v
Ausführlicher Modus. Es werden zusätzliche Angaben zur Tätigkeit des Programms ausgegeben.
--version
, -V
Zeigt die Versionsinformation an und wird dann beendet.
--vertical
, -E
Erzeugt eine vertikale Ausgabe. Dies ähnelt
--relative
, die Ausgabe erfolgt jedoch
vertikal.
--wait[=
,
count
]-w[
count
]
Wenn die Verbindung nicht hergestellt werden kann, erfolgt
anstelle eines Abbruchs nach einer Wartezeit ein neuer
Verbindungsversuch. Wenn ein
count
-Wert spezifiziert wird,
gibt dieser die Anzahl der Wiederholungsversuche an.
Standardmäßig erfolgt genau eine Wiederholung.
Sie können mit der Syntax
--
auch die folgenden Variablen einstellen:
var_name
=value
Es ist ferner möglich, Variablen über die Syntax
--set-variable=
oder var_name
=value
-O
einzustellen. Diese Syntax ist jedoch
veraltet.
var_name
=value
Die Binärlogdateien, die der Server erzeugt, sind im Binärformat geschrieben. Um diese Dateien in Textform zu untersuchen, verwenden Sie das Hilfsprogramm mysqlbinlog.
Rufen Sie mysqlbinlog wie folgt auf:
shell> mysqlbinlog [options
] log_file
...
Um beispielsweise den Inhalt einer Binärlogdatei namens
binlog.000003
anzuzeigen, verwenden Sie
folgenden Befehl:
shell> mysqlbinlog binlog.0000003
Die Ausgabe enthält alle Ereignisse, die in
binlog.000003
enthalten sind. Zu den
einzelnen Ereignisdaten gehören u. a. die ausgeführte
Anweisung, die Ausführungsdauer der Anweisung, die
Thread-Kennung des absetzenden Clients und der Zeitstempel der
Ausführung.
Die Ausgabe von mysqlbinlog kann – beispielsweise durch Verwendung als Eingabe für mysql – neu ausgeführt werden, um die Anweisungen im Log erneut anzuwenden. Dies ist etwa zur Wiederherstellung nach einem Serverabsturz praktisch. Mehr Anwendungsbeispiele finden Sie im weiteren Verlauf dieses Abschnitts.
Normalerweise verwenden Sie mysqlbinlog zum
direkten Auslesen von Binärlogdateien und zu deren Anwendung
auf den lokalen MySQL Server. Es ist ferner möglich,
Binärlogs von einem entfernten Server auszulesen, indem Sie
die Option --read-from-remote-server
verwenden. Wenn Sie entfernte Binärlogs auslesen, kann mit
Verbindungsparameteroptionen angegeben werden, wie die
Verbindung zum Server herzustellen ist. Diese Optionen sind
--host
, --password
,
--port
, --protocol
,
--socket
und --user
; sie
werden allerdings ignoriert, wenn Sie nicht auch die Option
--read-from-remote-server
angeben.
Sie können mit mysqlbinlog auch Relay-Logdateien auslesen, die von einem Slave-Server in einer Replikationskonfiguration geschrieben wurden. Relay-Logs haben das gleiche Format wie Binärlogdateien.
Weitere Informationen zu Binär- und Relay-Logs finden Sie in Abschnitt 5.12.3, „Die binäre Update-Logdatei“, und Abschnitt 6.4.4, „Relay- und Statusdateien bei der Replikation“.
mysqlbinlog unterstützt die folgenden Optionen:
--help
, -?
Zeigt eine Hilfemeldung an und wird dann beendet.
--base64-output
Gibt alle Binärlogeinträge unter Verwendung der base64-Kodierung aus. Dies dient nur Debugzwecken. Logs, die mithilfe dieser Option erzeugt wurden, sollten nicht auf Produktionssysteme angewendet werden. Diese Option wurde in MySQL 5.1.5 hinzugefügt.
--database=
,
db_name
-d
db_name
Listet Einträge nur für genau diese Datenbank auf (nur lokales Log).
--force-read
, -f
Mit dieser Option gibt mysqlbinlog, wenn es ein Binärlogereignis liest, das es nicht erkennt, eine Warnung aus, ignoriert das Ereignis und fährt fort. Ohne diese Option beendet sich mysqlbinlog beim Lesen eines solchen Ereignisses.
--hexdump
, -H
Zeigt einen hexadezimalen Speicherauszug des Logs in Kommentaren an. Diese Ausgabe kann für das Debuggen der Replikation hilfreich sein. Das Format des hexadezimalen Speicherauszugs wird im weiteren Verlauf dieses Abschnitts beschrieben. Diese Option wurde in MySQL 5.1.2 hinzugefügt.
--host=
,
host_name
-h
host_name
Holt das Binärlog vom MySQL Server des angegebenen Hosts.
--local-load=
,
path
-l
path
Bereitet lokale Temporärdateien für LOAD DATA
INFILE
im angegebenen Verzeichnis vor.
--offset=
,
N
-o
N
Überspringt die ersten N
Einträge im Log.
--password[=
,
password
]-p[
password
]
Verwendet das angegebene Passwort zur Verbindung mit dem
Server. Wenn Sie die Kurzform der Option
(-p
) verwenden, dürfen Sie
kein Leerzeichen zwischen Option und
Passwort setzen. Lassen Sie den Wert
password
auf die Option
--password
bzw. -p
folgend weg, dann werden Sie zur Eingabe des Passworts
aufgefordert.
Die Angabe eines Passworts direkt auf der Befehlszeile ist als nicht sicher einzuordnen. Siehe auch Abschnitt 5.9.6, „Wie Sie Ihre Kennwörter sicher halten“.
--port=
,
port_num
-P
port_num
Die TCP/IP-Portnummer, die zur Verbindung mit einem entfernten Server verwendet werden soll.
--position=
,
N
-j
N
Veraltet. Verwenden Sie stattdessen
--start-position
.
--protocol={TCP|SOCKET|PIPE|MEMORY}
Das zu verwendende Verbindungsprotokoll.
--read-from-remote-server
,
-R
Liest das Binärlog von einem MySQL Server, statt eine
lokale Logdatei auszulesen. Sofern diese Option nicht
angegeben ist, werden auch alle weiteren
Verbindungsparameteroptionen ignoriert. Diese Optionen
sind --host
, --password
,
--port
, --protocol
,
--socket
und --user
.
--result-file=
,
name
-r
name
Die Ausgabe erfolgt direkt in die angegebene Datei.
--server-id=
id
Extrahiert nur diejenigen Ereignisse, die vom Server mit der angegebenen Serverkennung stammen. Diese Option wurde in MySQL 5.1.4 hinzugefügt.
--short-form
, -s
Zeigt nur die im Log enthaltenen Anweisungen (d. h. keine zusätzlichen Informationen) an.
--socket=
,
path
-S
path
Bei Verbindungen mit localhost
ist dies
die zu verwendende Unix-Socketdatei bzw. (unter Windows)
der Name der zu verwendenden Named Pipe.
--start-datetime=
datetime
Startet das Auslesen des Binärlogs beim ersten Ereignis,
dessen Zeitstempel dem durch
datetime
angegebenen oder einem
späteren Zeitpunkt entspricht. Der
datetime
-Wert ist relativ zur
lokalen Zeitzone des Computers, auf dem Sie
mysqlbinlog ausführen. Der Wert sollte
in einem Format angegeben sein, das für die
DATETIME
- oder
TIMESTAMP
-Datentypen unterstützt wird.
Zum Beispiel:
shell> mysqlbinlog --start-datetime="2005-12-25 11:25:56" binlog.000003
Diese Option ist für eine Point-in-Time-Wiederherstellung nützlich. Siehe auch Abschnitt 5.10.2, „Beispielhaftes Vorgehen zur Datensicherung und Wiederherstellung“.
--stop-datetime=
datetime
Beendet das Auslesen des Binärlogs beim ersten Ereignis,
dessen Zeitstempel dem durch
datetime
angegebenen oder einem
späteren Zeitpunkt entspricht. Diese Option ist für eine
Point-in-Time-Wiederherstellung nützlich. Informationen
zum datetime
-Wert finden Sie
weiter oben in der Beschreibung zur Option
--start-datetime
.
--start-position=
N
Startet das Auslesen des Binärlogs beim ersten Ereignis,
dessen Position dem Argument N
entspricht.
--stop-position=
N
Beendet das Auslesen des Binärlogs beim ersten Ereignis,
dessen Position N
oder höher
ist.
--to-last-log
, -t
Beendet die Verarbeitung nicht am Ende des bei einem MySQL
Server angeforderten Binärlogs, sondern fährt mit der
Ausgabe bis zum Ende des letzten Binärlogs fort. Wenn Sie
die Ausgabe zum selben MySQL Server leiten, kann dies eine
Endlosschleife verursachen. Diese Option erfordert
--read-from-remote-server
.
--disable-log-bin
, -D
Deaktiviert das binäre Loggen. Dies ist nützlich zur
Vermeidung einer Endlosschleife, wenn Sie die Option
--to-last-log
verwenden und die Ausgabe
an denselben MySQL Server senden. Ferner ist die Option
praktisch bei der Datenwiederherstellung nach einem
Absturz: Sie vermeiden hiermit eine Duplizierung der
protokollierten Anweisungen.
Für diese Option benötigen Sie die Berechtigung
SUPER
. Sie sorgt dafür, dass
mysqlbinlog in seine Ausgabe eine
SET SQL_LOG_BIN=0
-Anweisung einfügt,
um das binäre Loggen der restlichen Ausgabe zu
deaktivieren. Die SET
-Anweisung wird
nur dann ausgeführt, wenn Sie die Berechtigung
SUPER
haben.
--user=
,
user_name
-u
user_name
Verwendet den angegebenen MySQL-Benutzernamen zur Verbindung mit dem entfernten Server.
--version
, -V
Zeigt die Versionsinformation an und wird dann beendet.
Sie können mit der Syntax
--
auch die folgenden Variablen einstellen:
var_name
=value
Es ist ferner möglich, Variablen über die Syntax
--set-variable=
oder var_name
=value
-O
einzustellen. Diese Syntax ist jedoch
veraltet.
var_name
=value
Sie können die Ausgabe von mysqlbinlog in den Client mysql umleiten, um die im Binärlog enthaltenen Anweisungen auszuführen. Diese Vorgehensweise dient der Wiederherstellung nach einem Absturz bei Vorhandensein eines alten Backups (siehe Abschnitt 5.10.1, „Datenbank-Datensicherungen“). Zum Beispiel:
shell> mysqlbinlog binlog.000001 | mysql
Oder:
shell> mysqlbinlog binlog.[0-9]* | mysql
Sie können die Ausgabe von mysqlbinlog stattdessen auch in eine Textdatei umleiten, wenn Sie das Anweisungslog zunächst modifizieren müssen (indem Sie beispielsweise Anweisungen entfernen, deren Ausführung Sie aus irgendeinem Grund nicht wünschen). Nach der Editierung der Datei führen Sie die enthaltenen Anweisungen aus, indem Sie sie als Eingabe für das Programm mysql verwenden.
mysqlbinlog verfügt über eine Option
--start-position
, die nur diejenigen
Anweisungen ausgibt, deren Position mindestens der angegebenen
Position entspricht (die angegebene Position muss mit dem
Start genau eines Ereignisses zusammenfallen). Ferner sind
Optionen zum Beenden und Starten bei Erkennung eines
Ereignisses mit einem angegebenen Zeitpunkt (Datum und
Uhrzeit) vorhanden. Dies ermöglicht Ihnen die Durchführung
einer Point-in-Time-Wiederherstellung mithilfe der Option
--stop-datetime
: Sie können so etwa eine
Wiederherstellung nach dem Prinzip „Datenbanken auf den
Stand von heute, 10:30 Uhr, setzen“ durchführen.
Wenn Sie mehr als nur ein Binärlog auf dem MySQL Server ausführen wollen, besteht die sichere Methode darin, alle Logs über dieselbe Serververbindung zu verarbeiten. Das folgende Beispiel veranschaulicht, welche Vorgehensweise unsicher sein könnte:
shell>mysqlbinlog binlog.000001 | mysql # DANGER!!
shell>mysqlbinlog binlog.000002 | mysql # DANGER!!
Eine derartige Verarbeitung von Binärlogs über verschiedene
Serververbindungen verursacht Probleme, wenn die erste
Logdatei eine CREATE TEMPORARY
TABLE
-Anweisung und das zweite Log eine Anweisung
enthält, die die Temporärtabelle verwendet. Wenn der erste
mysql-Prozess beendet wird, löscht der
Server die Temporärtabelle. Versucht der zweite
mysql-Prozess nun auf die Tabelle
zuzugreifen, dann meldet der Server eine „unbekannte
Tabelle“.
Um solche Probleme zu vermeiden, verwenden Sie stets die gleiche Verbindung zur Ausführung der Inhalte aller Binärlogs, die Sie verarbeiten wollen. Nachfolgend ist eine Möglichkeit beschrieben, dies zu erreichen:
shell> mysqlbinlog binlog.000001 binlog.000002 | mysql
Ein weiterer Ansatz besteht darin, alle Logs in eine einzelne Datei zu schreiben und diese Datei dann zu verarbeiten:
shell>mysqlbinlog binlog.000001 > /tmp/statements.sql
shell>mysqlbinlog binlog.000002 >> /tmp/statements.sql
shell>mysql -e "source /tmp/statements.sql"
mysqlbinlog kann eine Ausgabe erzeugen, die
eine LOAD DATA INFILE
-Operation ohne die
ursprüngliche Datendatei reproduziert.
mysqlbinlog kopiert die Daten in eine
Temporärdatei und schreibt eine LOAD DATA LOCAL
INFILE
-Anweisung, die diese Datei referenziert. Die
Standardposition des Verzeichnisses, in das diese Dateien
geschrieben werden, ist systemspezifisch. Um ein Verzeichnis
explizit anzugeben, verwenden Sie die Option
--local-load
.
Da mysqlbinlog LOAD DATA
INFILE
- in LOAD DATA LOCAL
INFILE
-Anweisungen konvertiert (d. h.
LOCAL
ergänzt), müssen sowohl der Client
als auch der Server, den Sie zur Verarbeitung der Anweisungen
verwenden, so konfiguriert sein, dass LOCAL
unterstützt wird. Siehe auch
Abschnitt 5.7.4, „Sicherheitsprobleme mit LOAD DATA LOCAL
“.
Warnung: Die für die
LOAD DATA LOCAL
-Anweisungen erstellten
Temporärdateien werden nicht automatisch
gelöscht, weil sie benötigt werden, bis Sie diese
Anweisungen tatsächlich ausführen. Sie sollten die
Temporärdateien also selbst entfernen, wenn Sie das
Anweisungslog nicht mehr benötigen. Die Dateien befinden sich
im Temporärdateiverzeichnis und haben Namen wie
original_file_name-#-#
.
Die Option --hexdump
erzeugt einen
hexadezimalen Speicherauszug („Hex-Dump“) des
Loginhalts in Kommentaren:
shell> mysqlbinlog --hexdump master-bin.000001
Beim obigen Befehl sieht die Ausgabe etwa so aus:
/*!40019 SET @@session.max_insert_delayed_threads=0*/; /*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; # at 4 #051024 17:24:13 server id 1 end_log_pos 98 # Position Timestamp Type Master ID Size Master Pos Flags # 00000004 9d fc 5c 43 0f 01 00 00 00 5e 00 00 00 62 00 00 00 00 00 # 00000017 04 00 35 2e 30 2e 31 35 2d 64 65 62 75 67 2d 6c |..5.0.15.debug.l| # 00000027 6f 67 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |og..............| # 00000037 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| # 00000047 00 00 00 00 9d fc 5c 43 13 38 0d 00 08 00 12 00 |.......C.8......| # 00000057 04 04 04 04 12 00 00 4b 00 04 1a |.......K...| # Start: binlog v 4, server v 5.0.15-debug-log created 051024 17:24:13 # at startup ROLLBACK;
Die Hex-Dump-Ausgabe enthält derzeit die nachfolgend aufgeführten Elemente. Das Format kann sich allerdings bei zukünftigen Versionen ändern.
Position
: Byteposition in der Logdatei.
Timestamp
: Zeitstempel des Ereignisses.
Im gezeigten Beispiel ist '9d fc 5c 43'
die Darstellung von '051024 17:24:13'
in hexadezimaler Form.
Type
: Typ des Logereignisses. Im
gezeigten Beispiel bedeutet '0f'
, dass
das Beispielereignis
FORMAT_DESCRIPTION_EVENT
ist. Die
nachfolgende Tabelle listet mögliche Typen auf.
Geben Sie nun Folgendes ein: | Name | Bedeutung |
00 | UNKNOWN_EVENT | Dieses Ereignis sollte keinesfalls im Log vorhanden sein. |
01 | START_EVENT_V3 | Zeigt den Anfang einer Logdatei an, die von MySQL 4 oder früher geschrieben wurde. |
02 | QUERY_EVENT | Der häufigste Ereignistyp. Er bezeichnet Anweisungen, die auf dem Master-Server ausgeführt wurden. |
03 | STOP_EVENT | Gibt an, dass der Master beendet wurde. |
04 | ROTATE_EVENT | Wird geschrieben, wenn der Master eine neue Logdatei eröffnet. |
05 | INTVAR_EVENT | Wird hauptsächlich für AUTO_INCREMENT -Werte und in
Situationen verwendet, in denen die
LAST_INSERT_ID() -Funktion in
der Anweisung verwendet wird. |
06 | LOAD_EVENT | Wird für LOAD DATA INFILE in MySQL 3.23 verwendet. |
07 | SLAVE_EVENT | Für zukünftige Verwendung reserviert. |
08 | CREATE_FILE_EVENT | Wird für LOAD DATA INFILE -Anweisungen verwendet.
Hiermit wird der Start der Ausführung einer
solchen Anweisung angezeigt. Auf dem Slave-Server
wird eine Temporärdatei erstellt. Wird nur in
MySQL 4 verwendet. |
09 | APPEND_BLOCK_EVENT | Enthält Daten, die in einer LOAD DATA
INFILE -Anweisung verwendet werden. Die
Daten werden in einer Temporärdatei auf dem Slave
gespeichert. |
0a | EXEC_LOAD_EVENT | Wird für LOAD DATA INFILE -Anweisungen verwendet. Der
Inhalt der Temporärdatei wird in der Tabelle auf
dem Slave gespeichert. Wird nur in MySQL 4
verwendet. |
0b | DELETE_FILE_EVENT | Rollback einer LOAD DATA INFILE -Anweisung. Die
Temporärdatei auf dem Slave sollte gelöscht
werden. |
0c | NEW_LOAD_EVENT | Wird für LOAD DATA INFILE in MySQL 4 und früher
verwendet. |
0d | RAND_EVENT | Wird für den Versand von Informationen zu Zufallswerten benutzt, wenn
die Funktion RAND() in der
Anweisung verwendet wird. |
0e | USER_VAR_EVENT | Dient der Replikation von Benutzervariablen. |
0f | FORMAT_DESCRIPTION_EVENT | Zeigt den Anfang einer Logdatei an, die von MySQL 5 oder später geschrieben wurde. |
10 | XID_EVENT | Ereignis, welches das Schreiben einer XA-Transaktion anzeigt. |
11 | BEGIN_LOAD_QUERY_EVENT | Wird für LOAD DATA INFILE -Anweisungen in MySQL 5 und
höher verwendet. |
12 | EXECUTE_LOAD_QUERY_EVENT | Wird für LOAD DATA INFILE -Anweisungen in MySQL 5 und
höher verwendet. |
13 | TABLE_MAP_EVENT | Für zukünftige Verwendung reserviert. |
14 | WRITE_ROWS_EVENT | Für zukünftige Verwendung reserviert. |
15 | UPDATE_ROWS_EVENT | Für zukünftige Verwendung reserviert. |
16 | DELETE_ROWS_EVENT | Für zukünftige Verwendung reserviert. |
Master ID
: Serverkennung des Masters,
der das Ereignis erstellt hat.
Size
: Größe des Ereignisses in Byte.
Master Pos
: Position des Ereignisses in
der ursprünglichen Logdatei auf dem Master.
Flags
: 16 Flags. Zurzeit werden die
nachfolgend aufgeführten Flags verwendet. Die übrigen
sind für zukünftige Verwendung reserviert.
Flag | Name | Bedeutung |
01 | LOG_EVENT_BINLOG_IN_USE_F | Logdatei korrekt geschlossen. (Wird nur in
FORMAT_DESCRIPTION_EVENT
verwendet.) Wenn bei einem Ereignis
FORMAT_DESCRIPTION_EVENT das
Flag gesetzt ist (d. h. wenn der Flagwert
beispielsweise '01 00' lautet),
dann wurde die Logdatei nicht korrekt geschlossen.
In aller Regel liegt dies an einem Absturz des
Masters (etwa aufgrund eines Stromausfalls). |
02 | Für zukünftige Verwendung reserviert. | |
04 | LOG_EVENT_THREAD_SPECIFIC_F | Ist gesetzt, wenn das Ereignis von der Verbindung abhängig ist, über
die es erfolgte (z. B. '04
00' ). Ein solcher Fall liegt etwa vor,
wenn das Ereignis Temporärtabellen verwendet. |
08 | LOG_EVENT_SUPPRESS_USE_F | Wird unter bestimmten Umständen gesetzt, wenn das Ereignis nicht von der Standarddatenbank abhängt. |
Die übrigen Flags sind für eine zukünftige Verwendung reserviert.
Der Client mysqlcheck prüft, repariert, optimiert und analysiert Tabellen.
mysqlcheck ähnelt hinsichtlich seines Funktionsumfangs myisamchk, funktioniert aber anders. Der wesentliche Unterschied besteht darin, dass mysqlcheck verwendet werden muss, wenn der Server mysqld ausgeführt wird, wohingegen myisamchk verwendet werden sollte, wenn er nicht läuft. Der Vorteil der Verwendung von mysqlcheck besteht darin, dass Sie den Server nicht beenden müssen, um Ihre Tabellen zu überprüfen oder zu reparieren.
mysqlcheck verwendet die SQL-Anweisungen
CHECK TABLE
, REPAIR
TABLE
, ANALYZE TABLE
und
OPTIMIZE TABLE
auf eine für den Benutzer
praktische Weise. Das Programm bestimmt, welche Anweisungen
für die gewünschte Operation durchzuführen sind, und sendet
diese Anweisungen dann zur Ausführung an den Server. Weitere
Informationen dazu, bei welchen Speicher-Engines die
jeweiligen Anweisungen funktionieren, finden Sie in
Kapitel 13, SQL-Anweisungssyntax.
Die MyISAM
-Speicher-Engine unterstützt
alle vier Anweisungen, d. h., mysqlcheck
kann zur Durchführung aller vier Operationen an
MyISAM
-Tabellen verwendet werden. Andere
Speicher-Engines unterstützen nicht unbedingt alle
Operationen. Gegebenenfalls wird eine Fehlermeldung angezeigt.
Wenn beispielsweise test.t
eine
MEMORY
-Tabelle ist, dann führt der
Versuch, sie zu überprüfen, zu folgendem Ergebnis:
shell> mysqlcheck test t
test.t
note : The storage engine for the table doesn't support check
Es gibt drei Möglichkeiten, mysqlcheck aufzurufen:
shell>mysqlcheck [
shell>options
]db_name
[tables
]mysqlcheck [
shell>options
] --databasesdb_name1
[db_name2
db_name3
...]mysqlcheck [
options
] --all-databases
Wenn Sie auf db_name
folgend keine
Tabellen aufführen oder die Optionen
--databases
oder
--all-databases
verwenden, dann werden ganze
Datenbanken überprüft.
mysqlcheck bietet eine im Vergleich zu
anderen Clientprogrammen spezielle Funktion. Das
Standardverhalten des Überprüfens von Tabellen
(--check
) kann geändert werden, indem die
Binärdatei umbenannt wird. Wenn Sie ein Tool benötigen, das
Tabellen standardmäßig repariert, sollten Sie einfach eine
Kopie von mysqlcheck namens
mysqlrepair oder eine symbolische
Verknüpfung zu mysqlcheck namens
mysqlrepair erstellen. Wenn Sie dann
mysqlrepair aufrufen, werden die Tabellen
standardmäßig repariert.
Die folgenden Namen können verwendet werden, um das Standardverhalten von mysqlcheck zu ändern:
mysqlrepair | Die Standardoption ist --repair . |
mysqlanalyze | Die Standardoption ist --analyze . |
mysqloptimize | Die Standardoption ist --optimize . |
mysqlcheck unterstützt die folgenden Optionen:
--help
, -?
Zeigt eine Hilfemeldung an und wird dann beendet.
--all-databases
, -A
Überprüft alle Tabellen in allen Datenbanken. Dies
entspricht der Option --databases
bei
gleichzeitiger Nennung aller Datenbanken auf der
Befehlszeile.
--all-in-1
, -1
Statt eine Anweisung für jede Tabelle einzeln abzusetzen, wird eine einzelne Anweisung für jede Datenbank ausgeführt, die alle zu verarbeitenden Tabellen aus dieser Datenbank benennt.
--analyze
, -a
Analysiert die Tabellen.
--auto-repair
Wenn eine überprüfte Tabelle beschädigt ist, wird sie automatisch repariert. Reparaturarbeiten werden erledigt, nachdem alle Tabellen überprüft wurden.
--character-sets-dir=
path
Das Verzeichnis, in dem Zeichensätze installiert sind. Siehe auch Abschnitt 5.11.1, „Der für Daten und zum Sortieren benutzte Zeichensatz“.
--check
, -c
Überprüft die Tabellen auf Fehler. Dies ist die Standardoperation.
--check-only-changed
, -C
Überprüft nur solche Tabellen, die seit der letzten Überprüfung geändert oder aber nicht korrekt geschlossen wurden.
--compress
Komprimiert alle Daten, die zwischen Client und Server ausgetauscht werden, sofern beide die Komprimierung unterstützen.
--databases
, -B
Verarbeitet alle Tabellen in den aufgeführten Datenbanken. Normalerweise betrachtet mysqlcheck das erste Namensargument auf der Befehlszeile als Datenbank- und alle nachfolgenden Argumente als Tabellennamen. Bei dieser Option hingegen werden alle Namensargumente als Datenbanknamen behandelt.
--debug[=
,
debug_options
]-#
[
debug_options
]
Schreibt ein Debuglog. Der String
debug_options
heißt häufig
'd:t:o,
.
file_name
'
--default-character-set=
charset_name
Verwendet charset_name
als
Standardzeichensatz. Siehe auch
Abschnitt 5.11.1, „Der für Daten und zum Sortieren benutzte Zeichensatz“.
--extended
, -e
Wenn Sie diese Option zur Überprüfung von Tabellen einsetzen, ist sichergestellt, dass diese hundertprozentig konsistent sind; der Vorgang dauert allerdings sehr lange.
Wenn Sie die Option bei der Reparatur von Tabellen einsetzen, wird eine erweiterte Reparatur durchgeführt, deren Ausführung nicht nur extrem lange dauert, sondern die auch eine Menge überflüssiger Datensätze erzeugt!
--fast
, -F
Überprüft nur Tabellen, die nicht ordnungsgemäß geschlossen wurden.
--force
, -f
Das Programm wird auch dann fortgesetzt, wenn ein SQL-Fehler auftritt.
--host=
,
host_name
-h
host_name
Stellt eine Verbindung zum MySQL Server auf dem angegebenen Host her.
--medium-check
, -m
Führt eine Überprüfung durch, die schneller ist als
eine --extended
-Operation. Hierdurch
werden nur 99,99 Prozent aller Fehler gefunden (dies
sollte allerdings in den meisten Fällen ausreichend
sein).
--optimize
, -o
Optimiert die Tabellen.
--password[=
,
password
]-p[
password
]
Verwendet das angegebene Passwort zur Verbindung mit dem
Server. Wenn Sie die Kurzform der Option
(-p
) verwenden, dürfen Sie
kein Leerzeichen zwischen Option und
Passwort setzen. Lassen Sie den Wert
password
auf die Option
--password
bzw. -p
folgend weg, dann werden Sie zur Eingabe des Passworts
aufgefordert.
Die Angabe eines Passworts direkt auf der Befehlszeile ist als nicht sicher einzuordnen. Siehe auch Abschnitt 5.9.6, „Wie Sie Ihre Kennwörter sicher halten“.
--port=
,
port_num
-P
port_num
Die TCP/IP-Portnummer, die für die Verbindung verwendet werden soll.
--protocol={TCP|SOCKET|PIPE|MEMORY}
Das zu verwendende Verbindungsprotokoll.
--quick
, -q
Wenn Sie mit dieser Option Tabellen überprüfen, wird verhindert, dass die Datensätze auf falsche Verknüpfungen geprüft werden. Dies ist die schnellste Prüfmethode.
Wenn Sie die Option bei der Reparatur von Tabellen einsetzen, wird versucht, nur den Indexbaum zu reparieren. Dies ist die schnellste Reparaturmethode.
--repair
, -r
Führt eine Reparatur durch, die fast alle Fehler beheben kann. Ausgenommen sind lediglich eindeutige Schlüssel, die nicht eindeutig sind.
--silent
, -s
Stummer Modus. Gibt nur Fehlermeldungen aus.
--socket=
,
path
-S
path
Bei Verbindungen mit localhost
ist dies
die zu verwendende Unix-Socketdatei bzw. (unter Windows)
der Name der zu verwendenden Named Pipe.
--tables
Setzt die Option --databases
bzw.
-B
außer Kraft. Alle auf die Option
folgenden Namensargumente werden als Tabellennamen
betrachtet.
--user=
,
user_name
-u
user_name
Verwendet den angegebenen MySQL-Benutzernamen zur Verbindung mit dem Server.
--verbose
, -v
Ausführlicher Modus. Gibt Informationen zu den verschiedenen Stufen des Programmablaufs aus.
--version
, -V
Zeigt die Versionsinformation an und wird dann beendet.
Der Client mysqldump ist ein Sicherungsprogramm, das ursprünglich von Igor Romanenko geschrieben wurde. Er kann zur Erstellung eines Speicherauszugs einer Datenbank oder einer Sammlung von Datenbanken zu Sicherungszwecken oder zur Übertragung von Daten auf einen anderen SQL-Server verwendet werden (dies muss nicht unbedingt ein MySQL Server sein). Der Speicherauszug enthält SQL-Anweisungen zur Erstellung und/oder zum Ausfüllen einer Tabelle.
Wenn Sie eine Sicherung auf dem Server durchführen und es
sich bei Ihren Tabellen ausschließlich um
MyISAM
-Tabellen handelt, sollten Sie
stattdessen die Verwendung von mysqlhotcopy
in Betracht ziehen, weil dies Sicherung und Wiederherstellung
erheblich beschleunigt. Siehe auch
Abschnitt 8.11, „mysqlhotcopy — Backup-Programm für Datenbanken“.
Es gibt drei Möglichkeiten, mysqldump aufzurufen:
shell>mysqldump [
shell>options
]db_name
[tables
]mysqldump [
shell>options
] --databasesdb_name1
[db_name2
db_name3
...]mysqldump [
options
] --all-databases
Wenn Sie auf db_name
folgend keine
Tabellen aufführen oder die Optionen
--databases
oder
--all-databases
verwenden, dann werden
Speicherauszüge ganzer Datenbanken erstellt.
Um eine Liste der Optionen zu erhalten, die Ihre Version von mysqldump unterstützt, führen Sie mysqldump --help aus.
Wenn Sie mysqldump ohne die Optionen
--quick
oder --opt
ausführen, lädt mysqldump den gesamten
Ergebnissatz in den Speicher, bevor der Speicherauszug
erstellt wird. Dies kann bei einem Speicherauszug einer
großen Datenbank ein Problem darstellen. Standardmäßig ist
die Option --opt
aktiviert, kann aber mit
--skip-opt
deaktiviert werden.
Wenn Sie eine relativ aktuelle Kopie von
mysqldump zur Erzeugung eines
Speicherauszugs verwenden, der in einen sehr alten MySQL
Server geladen werden soll, dann sollten Sie die Optionen
--opt
oder --extended-insert
nicht benutzen. Verwenden Sie stattdessen
--skip-opt
.
mysqldump unterstützt die folgenden Optionen:
--help
, -?
Zeigt eine Hilfemeldung an und wird dann beendet.
--add-drop-database
Fügt eine DROP DATABASE
-Anweisung vor
jede CREATE DATABASE
-Anweisung ein.
--add-drop-table
Fügt eine DROP TABLE
-Anweisung vor
jede CREATE TABLE
-Anweisung ein.
--add-locks
Setzt jeden Tabellenspeicherauszug zwischen eine
LOCK TABLES
- und eine UNLOCK
TABLES
-Anweisung. Hierdurch werden die
Einfügevorgänge beim Neuladen der Speicherauszugsdatei
beschleunigt. Siehe auch Abschnitt 7.2.16, „Geschwindigkeit von INSERT
-Anweisungen“.
--all-databases
, -A
Erstellt einen Speicherauszug aller Tabellen in allen
Datenbanken. Dies entspricht der Option
--databases
bei gleichzeitiger Nennung
aller Datenbanken auf der Befehlszeile.
--all-tablespaces
, -Y
Fügt zum Tabellenspeicherauszug alle SQL-Anweisungen
hinzu, die zur Erstellung von Tablespaces für eine
NDB Cluster
-Tabelle erforderlich sind.
Diese Informationen können nur auf diese Weise in der
Ausgabe von mysqldump angegeben werden.
Die Option ist derzeit nur für MySQL-Cluster-Tabellen
relevant.
Diese Option wurde in MySQL 5.1.6 hinzugefügt.
--allow-keywords
Erlaubt die Erstellung von Spaltennamen, die Schlüsselwörter sind. Dies funktioniert, indem jedem Spaltennamen der Tabellenname vorangestellt wird.
--comments[={0|1}]
Wenn 0
angegeben wird, unterdrückt die
Option zusätzliche Informationen in der
Speicherauszugsdatei wie etwa Programmversion,
Serverversion und Host. --skip-comments
hat den gleichen Effekt wie --comments=0
.
Der Standardwert ist 1
, d. h., die
genannten Informationen sind enthalten.
--compact
Erzeugt eine weniger ausführliche Ausgabe. Die Option
unterdrückt Kommentare und aktiviert die Optionen
--skip-add-drop-table
,
--no-set-names
,
--skip-disable-keys
und
--skip-add-locks
.
--compatible=
name
Erzeugt eine Ausgabe, bei der die Kompatibilität mit
anderen Datenbanksystemen oder älteren MySQL Servern
höher ist. name
kann folgende Werte
annehmen: ansi
,
mysql323
, mysql40
,
postgresql
, oracle
,
mssql
, db2
,
maxdb
,
no_key_options
,
no_table_options
oder
no_field_options
. Um mehrere Werte zu
verwenden, trennen Sie diese durch Kommata. Diese Werte
haben dieselbe Bedeutung wie die entsprechenden Optionen
zur Einstellung des SQL-Modus am Server. Siehe auch
Abschnitt 5.2.5, „Der SQL-Modus des Servers“.
Die Option garantiert keine Kompatibilität mit anderen
Servern. Vielmehr aktiviert sie nur diejenigen
SQL-Moduswerte, die zum gegebenen Zeitpunkt verfügbar
sind, um die Kompatibilität der Speicherauszugsausgabe zu
erhöhen. So führt --compatible=oracle
weder eine Zuordnung von Datentypen zu Oracle-Typen durch
noch wird die Oracle-Kommentarsyntax verwendet.
--complete-insert
, -c
Verwendet vollständige
INSERT
-Anweisungen, die auch
Spaltennamen enthalten.
--compress
, -C
Komprimiert alle Daten, die zwischen Client und Server ausgetauscht werden, sofern beide die Komprimierung unterstützen.
--create-options
Fügt alle MySQL-spezifischen Tabellenoptionen in die
CREATE TABLE
-Anweisungen ein.
--databases
, -B
Erstellt einen Speicherauszug mehrerer Datenbanken.
Normalerweise betrachtet mysqldump das
erste Namensargument auf der Befehlszeile als Datenbank-
und alle nachfolgenden Argumente als Tabellennamen. Bei
dieser Option werden jedoch alle Namensargumente als
Datenbanknamen betrachtet. CREATE
DATABASE
- und USE
-Anweisungen
werden für jede neue Datenbank in die Ausgabe eingefügt.
--debug[=
,
debug_options
]-#
[
debug_options
]
Schreibt ein Debuglog. Der String
debug_options
heißt häufig
'd:t:o,
.
Standardwert ist
file_name
''d:t:o,/tmp/mysqldump.trace'
.
--default-character-set=
charset_name
Verwendet charset_name
als
Standardzeichensatz. Siehe auch
Abschnitt 5.11.1, „Der für Daten und zum Sortieren benutzte Zeichensatz“. Sofern nicht angegeben,
verwendet mysqldump
utf8
.
--delayed-insert
Schreibt INSERT DELAYED
- statt
INSERT
-Anweisungen.
--delete-master-logs
Löscht auf einem Master-Replikationsserver nach
Erstellung des Speicherauszugs die Binärlogs. Diese
Option aktiviert automatisch
--master-data
.
--disable-keys
, -K
Setzt bei jeder Tabelle die
INSERT
-Anweisungen zwischen
/*!40000 ALTER TABLE
- und tbl_name
DISABLE KEYS
*/;/*!40000 ALTER TABLE
-Anweisungen. Dies beschleunigt das Laden der
Speicherauszugsdatei, weil die Indizes nach Einfügen
aller Datensätze erstellt werden. Diese Option ist nur
bei tbl_name
ENABLE KEYS
*/;MyISAM
-Tabellen wirksam.
--extended-insert
, -e
Verwendet die INSERT
-Syntax für
mehrere Datensätze (diese enthält verschiedene
VALUES
-Listen). Ergebnis sind eine
kleinere Speicherauszugsdatei und beschleunigte
Einfügeoperationen beim Neuladen der Datei.
--fields-terminated-by=…
,
--fields-enclosed-by=…
,
--fields-optionally-enclosed-by=…
,
--fields-escaped-by=…
,
--lines-terminated-by=…
Diese Optionen werden mit der Option -T
verwendet und haben dieselben Bedeutungen wie die
jeweiligen Klauseln für LOAD DATA
INFILE
. Siehe auch Abschnitt 13.2.5, „LOAD DATA INFILE
“.
--first-slave
, -x
Veraltet. Heißt jetzt --lock-all-tables
.
--flush-logs
, -F
Synchronisiert die Logdateien des MySQL Servers auf
Festplatte, bevor der Speicherauszugsvorgang gestartet
wird. Diese Option erfordert die Berechtigung
RELOAD
. Beachten Sie, dass, wenn Sie
diese Option in Verbindung mit der Option
--all-databases
(bzw.
-A
) verwenden, die Logs für
jede Datenbank, für die ein Speicherauszug erstellt
wird, synchronisiert werden. Eine Ausnahme
liegt vor, wenn Sie --lock-all-tables
oder --master-data
verwenden: In diesem
Fall werden die Logs nur einmal geschrieben, und zwar in
dem Augenblick, in dem alle Tabellen gesperrt sind. Wenn
Sie wollen, dass Speicherauszug und Logsynchronisierung im
exakt gleichen Moment erfolgen, sollten Sie
--flush-logs
wahlweise gemeinsam mit
--lock-all-tables
oder
--master-data
verwenden.
--force
, -f
Setzt die Ausführung auch dann fort, wenn ein SQL-Fehler während eines Speicherauszugsvorgangs auftritt.
--host=
,
host_name
-h
host_name
Speichert den Speicherauszug der Daten vom MySQL Server
auf den angegebenen Host. Der Standardhost ist
localhost
.
--hex-blob
Erstellt den Speicherauszug unter Verwendung der
Hexadezimalnotation (z. B. wird aus
'abc'
0x616263
).
Betroffen sind die Datentypen BINARY
,
VARBINARY
, BLOB
und
BIT
.
--lock-all-tables
, -x
Sperrt datenbankübergreifend alle Tabellen. Dieses wird
erreicht, indem eine globale Lesesperre für die
Gesamtdauer des Speicherauszugs erwirkt wird. Die Option
schaltet --single-transaction
und
--lock-tables
automatisch ab.
--lock-tables
, -l
Sperrt alle Tabellen vor Beginn des Speicherauszugs. Die
Tabellen werden im Falle von
MyISAM
-Tabellen mit READ
LOCAL
gesperrt, um nebenläufige
Einfügeoperationen durchführen zu können. Bei
transaktionssicheren Tabellen wie
InnoDB
und BDB
ist
--single-transaction
eine wesentlich
bessere Option, denn sie erfordert überhaupt kein Sperren
der Tabellen.
Beachten Sie, dass, wenn Sie Speicherauszüge mehrerer
Datenbanken erstellen, --lock-tables
die
Tabellen für jede Datenbank separat sperrt. Insofern
stellt diese Option nicht sicher, dass die Tabellen in der
Speicherauszugsdatei datenbankübergreifend logisch
konsistent sind. Die Tabellen in verschiedenen
Datenbanken, von denen ein Speicherauszug erstellt wird,
befinden sich unter Umständen in vollkommen
unterschiedlichen Zuständen.
--master-data[=
value
]
Schreibt Dateinamen und Position des Binärlogs in die
Ausgabe. Diese Option erfordert die Berechtigung
RELOAD
, und das Binärlog muss
aktiviert sein. Wenn der Optionswert 1 ist, werden
Position und Dateiname in die Form einer CHANGE
MASTER
-Anweisung in die Ausgabe des
Speicherauszugs geschrieben. Dies ermöglicht den Start
eines Slave-Servers an der korrekten Position in den
Binärlogs des Masters, wenn Sie diesen SQL-Speicherauszug
des Masters zur Konfiguration eines Slaves einsetzen. Wenn
der Optionswert 2 ist, dann wird die CHANGE
MASTER
-Anweisung als SQL-Kommentar geschrieben.
Dies ist auch die Standardaktion, wenn
value
nicht angegeben wird.
Die Option --master-data
aktiviert
--lock-all-tables
, sofern
--single-transaction
nicht ebenfalls
angegeben ist (in diesem Fall wird eine globale Lesesperre
nur für einen kurzen Zeitraum zum Beginn des
Speicherauszugsvorgangs erwirkt). (Siehe auch die
Beschreibung zu --single-transaction
.) In
allen Fällen erfolgen Vorgänge an Logs im exakten Moment
des Speicherauszugs. Die Option schaltet
--lock-tables
automatisch ab.
--no-create-db
, -n
Diese Option unterdrückt die CREATE
DATABASE
-Anweisungen, die andernfalls in der
Ausgabe enthalten wären, wenn die Optionen
--databases
oder
--all-databases
angegeben wurden.
--no-create-info
, -t
Es werden keine CREATE
TABLE
-Anweisungen geschrieben, die jede
gespeicherte Tabelle neu erstellen.
--no-data
, -d
Schreibt keine Datensatzinformationen für die Tabelle.
Dies ist recht nützlich, wenn Sie einen Speicherauszug
nur für die CREATE TABLE
-Anweisung
für die Tabelle erstellen wollen.
--opt
Dies ist eine Kurzform, die für folgende Option steht:
--add-drop-table --add-locks --create-options
--disable-keys --extended-insert --lock-tables --quick
--set-charset
. Ergebnis sollte ein schneller
Speicherauszugsprozess sein, an dessen Ende eine
Speicherauszugsdatei steht, die problemlos in einen MySQL
Server eingeladen werden kann.
Standardmäßig ist diese Option aktiviert, kann
aber mit --skip-opt
deaktiviert
werden. Um nur einige der mit
--opt
aktivierten Optionen zu
deaktivieren, verwenden Sie die entsprechenden
--skip
-Optionen (z. B.
--skip-add-drop-table
oder
--skip-quick
).
--password[=
,
password
]-p[
password
]
Verwendet das angegebene Passwort zur Verbindung mit dem
Server. Wenn Sie die Kurzform der Option
(-p
) verwenden, dürfen Sie
kein Leerzeichen zwischen Option und
Passwort setzen. Lassen Sie den Wert
password
auf die Option
--password
bzw. -p
folgend weg, dann werden Sie zur Eingabe des Passworts
aufgefordert.
Die Angabe eines Passworts direkt auf der Befehlszeile ist als nicht sicher einzuordnen. Siehe auch Abschnitt 5.9.6, „Wie Sie Ihre Kennwörter sicher halten“.
--port=
,
port_num
-P
port_num
Die TCP/IP-Portnummer, die für die Verbindung verwendet werden soll.
--protocol={TCP|SOCKET|PIPE|MEMORY}
Das zu verwendende Verbindungsprotokoll.
--quick
, -q
Diese Option ist nützlich, um einen Speicherauszug großer Tabellen zu erstellen. Hier wird mysqldump gezwungen, die Datensätze für eine Tabelle datensatzweise vom Server abzurufen, statt vor dem Schreiben die gesamte Ergebnismenge zu holen und sie temporär im Speicher abzulegen.
--quote-names
, -Q
Setzt Datenbank-, Tabellen- und Spaltennamen in
‘`
’-Zeichen. Wenn der
SQL-Modus ANSI_QUOTES
aktiviert ist,
werden die Namen in die
‘"
’-Anführungszeichen
gesetzt. Die Option ist standardmäßig aktiviert. Sie
kann mit --skip-quote-names
deaktiviert
werden, aber diese Option sollte nach anderen Optionen wie
etwa --compatible
angegeben werden, mit
denen --quote-names
aktiviert werden
könnte.
--replace
Schreibt REPLACE
- statt
INSERT
-Anweisungen. Wurde in MySQL
5.1.3 hinzugefügt.
--result-file=
,
file
-r
file
Die Ausgabe erfolgt direkt in die angegebene Datei. Diese
Option sollte unter Windows benutzt werden, um die
Konvertierung von Zeilenumbrüchen
(‘\n
’) in Folgen von
Absatzschaltung und Zeilenumbruch
(‘\r\n
’) zu verhindern.
--routines
, -R
Erstellt einen Speicherauszug gespeicherter Routinen
(Funktionen und Prozeduren) aus
Datenbankspeicherauszügen. Die mit
---routines
erzeugte Ausgabe enthält
CREATE PROCEDURE
- und CREATE
FUNCTION
-Anweisungen zur Neuerstellung der
Routinen. Allerdings enthalten diese Anweisungen keine
Attribute wie die Routinendefinition oder die Zeitstempel
für Erstellung und Änderung. Das bedeutet, dass die
Routinen, wenn sie neu geladen werden, mit dem
Definitionssatz für den neu ladenden Benutzer und den
Zeitstempeln für den Zeitpunkt des Neuladens erstellt
werden.
Wenn Sie Routinen benötigen, die mit den
Originalattributen für Definition und Zeitstempel neu
erstellt wurden, verwenden Sie --routines
nicht. Stattdessen erstellen Sie unter Verwendung eines
MySQL-Kontos, das die erforderlichen Berechtigungen für
die Datenbank mysql
hat, direkt einen
Speicherauszug des Inhalts der Tabelle
mysql.proc
und laden diesen Inhalt dann
neu.
Diese Option wurde in MySQL 5.1.2 hinzugefügt. Zuvor war ein Speicherauszug gespeicherter Routinen nicht möglich.
--set-charset
Fügt SET NAMES
zur Ausgabe hinzu. Die Option ist standardmäßig
aktiviert. Um die default_character_set
SET NAMES
-Anweisung
zu unterdrücken, verwenden Sie
--skip-set-charset
.
--single-transaction
Diese Option setzt eine SQL-Anweisung
BEGIN
ab, bevor der Speicherauszug vom
Server durchgeführt wird. Sie ist nur bei
transaktionssicheren Tabellen wie
InnoDB
und BDB
nützlich, denn der Speicherauszug spiegelt den
konsistenten Zustand der Datenbank zu dem Zeitpunkt wider,
an dem BEGIN
abgesetzt wurde, ohne dass
Anwendungen gesperrt werden.
Wenn Sie diese Option verwenden, sollten Sie beachten,
dass ein Speicherauszug nur von
InnoDB
-Tabellen in einem konsistenten
Zustand erstellt werden kann. MyISAM
-
oder HEAP
-Tabellen, für die unter
Verwendung dieser Option ein Speicherauszug erstellt wird,
können ihren Zustand trotzdem noch ändern.
Die Optionen --single-transaction
und
--lock-tables
schließen sich gegenseitig
aus, weil LOCK TABLES
implizit das
Schreiben anhängiger Transaktionen auslöst.
Um Speicherauszüge großer Tabellen zu erstellen, sollten
Sie diese Option mit --quick
kombinieren.
--socket=
,
path
-S
path
Bei Verbindungen mit localhost
ist dies
die zu verwendende Unix-Socketdatei bzw. (unter Windows)
der Name der zu verwendenden Named Pipe.
--skip-comments
Siehe Beschreibung zu --comments
.
--tab=
,
path
-T
path
Erzeugt tabulatorgetrennte Datendateien. Für jede
Tabelle, für die ein Speicherauszug erstellt wurde,
erzeugt mysqldump eine
-Datei,
welche die tbl_name
sqlCREATE TABLE
-Anweisung, mit
der die Tabelle erstellt wird, enthält, und eine
mit den Daten dieser Tabelle. Der Optionswert ist das
Verzeichnis, in das die Dateien geschrieben werden.
tbl_name
.txt
Standardmäßig werden die
.txt
-Datendateien mit
Tabulatorzeichen zwischen den Spaltenwerten und einem
Zeilenumbruch am Ende jeder Zeile formatiert. Das Format
kann aber auch explizit mit den Optionen
--fields-
und
xxx
--lines--
angegeben werden.
xxx
Hinweis: Diese Option
sollte nur dann verwendet werden, wenn
mysqldump auf demselben Computer läuft
wie der Server mysqld. Sie benötigen
die Berechtigung FILE
, und der Server
muss eine Berechtigung zum Schreiben von Dateien in das
von Ihnen angegebene Verzeichnis haben.
--tables
Setzt die Option --databases
bzw.
-B
außer Kraft. Alle auf die Option
folgenden Namensargumente werden als Tabellennamen
betrachtet.
--triggers
Erstellt einen Speicherauszug für Trigger für jede
Tabelle, für die ein Speicherauszug erstellt wurde. Die
Option ist standardmäßig aktiviert. Sie können sie
mithilfe von --skip-triggers
deaktivieren.
--tz-utc
Fügt SET TIME_ZONE='+00:00'
zur
Speicherauszugsdatei hinzu, sodass
TIMESTAMP
-Spalten in den Speicherauszug
integriert und dann auch auf Server in anderen Zeitzonen
geladen werden können. Ohne diese Option werden
TIMESTAMP
-Spalten in den Zeitzonen
gespeichert und geladen, die für den Quell- bzw.
Zielserver lokal sind; dies kann Werteänderungen zur
Folge haben. Außerdem schützt --tz-utc
gegen sommerzeitbedingte Änderungen.
--tz-utc
ist standardmäßig aktiviert.
Um es zu deaktivieren, verwenden Sie
--skip-tz-utc
. Diese Option wurde in
MySQL 5.1.2 hinzugefügt.
--user=
,
user_name
-u
user_name
Verwendet den angegebenen MySQL-Benutzernamen zur Verbindung mit dem Server.
--verbose
, -v
Ausführlicher Modus. Es werden zusätzliche Angaben zu den Aktivitäten des Programms ausgegeben.
--version
, -V
Zeigt die Versionsinformation an und wird dann beendet.
--where='
,
where_condition
'-w
'
where_condition
'
Fügt nur diejenigen Datensätze in den Speicherauszug
ein, die aufgrund der WHERE
-Bedingung
ausgewählt werden. Beachten Sie, dass die Bedingung
zwingend in Anführungszeichen gesetzt werden muss, wenn
sie Leerzeichen oder andere Zeichen enthält, die Ihr
Befehls-Interpreter als Sonderzeichen interpretiert.
Ein paar Beispiele:
--where="user='jimf'" -w"userid>1" -w"userid<1"
--xml
, -X
Schreibt die Ausgabe des Speicherauszugs als sauber formatiertes XML.
Sie können mit der Syntax
--
auch die folgenden Variablen einstellen:
var_name
=value
max_allowed_packet
Maximale Größe des Puffers für die Client/Server-Kommunikation. Der Maximalwert beträgt 1 Gbyte.
net_buffer_length
Ausgangsgröße des Puffers für die
Client/Server-Kommunikation. Wenn Sie Einfügeanweisungen
für mehrere Datensätze (wie etwa mit den Optionen
--extended-insert
oder
--opt
) erstellen, legt
mysqldump Datensätze an, deren
maximale Länge durch net_buffer_length
festgelegt ist. Wenn Sie den Wert dieser Variablen
erhöhen, sollten Sie auch sicherstellen, dass die
Variable net_buffer_length
am MySQL
Server mindestens genauso groß ist.
Es ist ferner möglich, Variablen über die Syntax
--set-variable=
oder var_name
=value
-O
einzustellen. Diese Syntax ist jedoch
veraltet.
var_name
=value
Die häufigste Anwendung von mysqldump ist wahrscheinlich die Erstellung eines Backups einer vollständigen Datenbank:
shell> mysqldump --opt db_name
> backup-file.sql
Die Speicherauszugsdatei können Sie wie folgt wieder in den Server einlesen.
shell> mysql db_name
< backup-file.sql
Oder aber so:
shell> mysql -e "source /path-to-backup/backup-file.sql
" db_name
mysqldump ist ferner sehr nützlich zum Ausfüllen von Datenbanken durch Kopieren von Daten von einem MySQL Server auf einen anderen:
shell> mysqldump --opt db_name
| mysql --host=remote_host
-C db_name
Sie können mit einem einzigen Befehl einen Speicherauszug mehrerer Datenbanken erstellen:
shell> mysqldump --databases db_name1
[db_name2
...] > my_databases.sql
Um einen Speicherauszug aller Datenbanken zu erstellen,
verwenden Sie die Option --all-databases
:
shell> mysqldump --all-databases > all_databases.sql
Bei InnoDB
-Tabellen bietet
mysqldump
die Möglichkeit, eine
Online-Sicherung zu erstellen:
shell> mysqldump --all-databases --single-transaction > all_databases.sql
Diese Datensicherung muss vor Beginn des
Speicherauszugsvorgangs lediglich (mit FLUSH TABLES
WITH READ LOCK
) eine globale Lesesperre für alle
Tabellen erwirken. Sobald diese Sperre aktiv ist, werden die
Koordinaten des Binärlogs ausgelesen, und die Sperre wird
aufgehoben. Wenn beim Absetzen der
FLUSH
-Anweisung gerade eine umfangreiche
Änderungsanweisung ausgeführt wird, dann – und nur dann!
– kann der MySQL Server stehen bleiben, bis diese lange
Anweisung ausgeführt ist; danach ist der Server sperrfrei.
Wenn die vom MySQL Server empfangenen Änderungsanweisungen
(in Bezug auf ihre Ausführungsdauer) kurz sind, sollte die
anfängliche Sperrperiode auch bei vielen Änderungen nicht
spürbar sein.
Bei der Point-in-Time-Wiederherstellung (die auch als „Roll-Forward“ bezeichnet wird, wenn Sie ein altes Backup wiederherstellen und die seitdem durchgeführten Änderungen neu aufspielen müssen) ist es häufig nützlich, das Binärlog zu rotieren (siehe Abschnitt 5.12.3, „Die binäre Update-Logdatei“) oder zumindest die Binärlogkoordinaten zu kennen, denen der Speicherauszug entspricht:
shell> mysqldump --all-databases --master-data=2 > all_databases.sql
Oder:
shell>mysqldump --all-databases --flush-logs --master-data=2
> all_databases.sql
Die gleichzeitige Verwendung von
--master-data
und
--single-transaction
stellt eine praktische
Möglichkeit dar, ein für die Point-in-Time-Wiederherstellung
geeignetes Onlinebackup zu erstellen, wenn Tabellen in der
InnoDB
-Engine gespeichert sind.
Weitere Informationen zur Erstellung von Backups finden Sie in Abschnitt 5.10.1, „Datenbank-Datensicherungen“, und Abschnitt 5.10.2, „Beispielhaftes Vorgehen zur Datensicherung und Wiederherstellung“.
mysqlhotcopy ist ein Perl-Skript, das
ursprünglich von Tim Bunce entwickelt und beigetragen wurde.
Es erstellt mithilfe von LOCK TABLES
,
FLUSH TABLES
und cp
oder
scp
ein schnelles Backup der Datenbank.
Dieses Skript stellt die schnellste Möglichkeit dar, eine
Sicherungskopie der Datenbank oder einzelner Tabellen zu
erstellen, kann aber nur auf dem Computer ausgeführt werden,
auf dem auch die Datenbankverzeichnisse gespeichert sind.
mysqlhotcopy erlaubt lediglich die
Sicherung von MyISAM
-Tabellen. Es läuft
unter Unix und NetWare.
shell> mysqlhotcopy db_name
[/path/to/new_directory
]
shell> mysqlhotcopy db_name_1
... db_name_n
/path/to/new_directory
Gesichert werden Tabellen in der angegebenen Datenbank, die einem regulären Ausdruck entsprechen:
shell> mysqlhotcopy db_name
./regex
/
Der reguläre Ausdruck für den Tabellennamen kann verneint
werden, indem man ihm eine Tilde
(‘~
’) voranstellt:
shell> mysqlhotcopy db_name
./~regex
/
mysqlhotcopy unterstützt die folgenden Optionen:
--help
, -?
Zeigt eine Hilfemeldung an und wird dann beendet.
--addtodest
Benennt das Zielverzeichnis (sofern vorhanden) nicht um, sondern fügt nur Dateien hinzu.
--allowold
Bricht nicht ab, wenn das Ziel vorhanden ist, sondern
benennt es durch Anhängen des Suffix
_old
um.
--checkpoint=
db_name
.tbl_name
Fügt Prüfpunkteinträge in die angegebene Datenbank
db_name
und Tabelle
tbl_name
ein.
--chroot=
path
Basisverzeichnis des
chroot-Käfigs, auf dem
mysqld läuft. Der Wert
path
sollte mit dem der Option
--chroot
übereinstimmen, die für
mysqld angegeben wurde.
--debug
Aktiviert die Debugausgabe.
--dryrun
, -n
Meldet Aktionen, ohne sie auszuführen.
--flushlog
Synchronisiert Logs, nachdem alle Tabellen gesperrt wurden.
--host=
,
host_name
-h
host_name
Hostname des lokalen Hosts, der zur Herstellung einer
TCP/IP-Verbindung zum lokalen Server verwendet wird.
Standardmäßig erfolgt die Verbindung zu
localhost
über eine Unix-Socketdatei.
--keepold
Gibt an, dass das vorherige (umbenannte) Ziel nach Abschluss nicht gelöscht wird.
--method=
command
Methode zum Kopieren von Dateien (cp
oder scp
).
--noindices
Gibt an, dass vollständige Indexdateien nicht Bestandteil der Sicherung sind. Hierdurch wird die Sicherung beschleunigt, und die Backup-Datei wird kleiner. Die Indizes der neu geladenen Tabellen lassen sich später mit myisamchk -rq rekonstruieren.
--password=
,
password
-p
password
Verwendet das angegebene Passwort zur Verbindung mit dem Server. Beachten Sie, dass der Passwortwert – anders als bei anderen MySQL-Programmen – bei dieser Option nicht optional ist. Wenn Sie das Passwort nicht auf der Befehlszeile angeben wollen, können Sie auch eine Optionsdatei verwenden.
Die Angabe eines Passworts direkt auf der Befehlszeile ist als nicht sicher einzuordnen. Siehe auch Abschnitt 5.9.6, „Wie Sie Ihre Kennwörter sicher halten“.
--port=
,
port_num
-P
port_num
Die TCP/IP-Portnummer, die zur Verbindung mit dem lokalen Server verwendet werden soll.
--quiet
, -q
Stummer Modus (außer bei Fehlern).
--record_log_pos=
db_name
.tbl_name
Zeichnet den Status von Master und Slave in der
angegebenen Datenbank db_name
und Tabelle tbl_name
auf.
--regexp=
expr
Kopiert alle Datenbanken, deren Namen dem angegebenen regulären Ausdruck entsprechen.
--resetmaster
Setzt das Binärlog nach Sperren aller Tabellen zurück.
--resetslave
Setzt die Datei master.info
nach
Sperren aller Tabellen zurück.
--socket=
,
path
-S
path
Unix-Socketdatei, die für die Verbindung verwendet werden soll.
--suffix=
str
Suffix für Namen kopierter Datenbanken.
--tmpdir=
path
Das Temporärverzeichnis. Vorgabe ist
/tmp
.
--user=
,
user_name
-u
user_name
Verwendet den angegebenen MySQL-Benutzernamen zur Verbindung mit dem Server.
mysqlhotcopy liest die Abschnitte
[client]
und
[mysqlhotcopy]
aus Optionsdateien aus.
Um mysqlhotcopy auszuführen, müssen Sie
Zugriff auf die Dateien der zu sichernden Tabellen haben und
benötigen zudem die Berechtigung SELECT
für diese Tabellen sowie die Berechtigung
RELOAD
(damit Sie FLUSH
TABLES
ausführen können).
perldoc
bietet eine umfassende
Dokumentation zu mysqlhotcopy
einschließlich Informationen zur Struktur der Tabellen, die
für die Optionen --checkpoint
und
--record_log_pos
erforderlich sind:
shell> perldoc mysqlhotcopy
Der Client mysqlimport stellt eine
Befehlszeilenoberfläche für die SQL-Anweisung LOAD
DATA INFILE
bereit. Die meisten Optionen für
mysqlimport entsprechen direkt Klauseln der
LOAD DATA INFILE
-Syntax. Siehe auch
Abschnitt 13.2.5, „LOAD DATA INFILE
“.
Rufen Sie mysqlimport wie folgt auf:
shell> mysqlimport [options
] db_name
textfile1
[textfile2
...]
Bei jeder Textdatei, die auf der Befehlszeile angegeben wird,
entfernt mysqlimport die
Dateinamenserweiterung und bestimmt anhand des Ergebnisses den
Namen der Tabelle, in die der Inhalt der Datei importiert
werden soll. So würden beispielsweise die Dateien mit den
Namen patient.txt
,
patient.text
und
patient
alle in eine Tabelle namens
patient
importiert.
mysqlimport unterstützt die folgenden Optionen:
--help
, -?
Zeigt eine Hilfemeldung an und wird dann beendet.
--columns=
,
column_list
-c
column_list
Diese Option nimmt eine kommagetrennte Liste der Spaltennamen als Wert entgegen. Die Reihenfolge der Spaltennamen gibt an, wie die Spalten in der Datendatei den Tabellenspalten zuzuordnen sind.
--compress
, -C
Komprimiert alle Daten, die zwischen Client und Server ausgetauscht werden, sofern beide die Komprimierung unterstützen.
--debug[=
,
debug_options
]-#
[
debug_options
]
Schreibt ein Debuglog. Der String
debug_options
heißt häufig
'd:t:o,
.
file_name
'
--delete
, -D
Leert die Tabelle vor dem Import der Textdatei.
--fields-terminated-by=…
,
--fields-enclosed-by=…
,
--fields-optionally-enclosed-by=…
,
--fields-escaped-by=…
,
--lines-terminated-by=…
Diese Optionen haben dieselbe Bedeutung wie die
entsprechenden Klauseln für LOAD DATA
INFILE
. Siehe auch Abschnitt 13.2.5, „LOAD DATA INFILE
“.
--force
, -f
Ignoriert Fehler. Wenn beispielsweise eine Tabelle für
eine Textdatei nicht vorhanden ist, wird ggf. mit der
Verarbeitung weiterer vorhandener Dateien fortgefahren.
Ohne --force
wird
mysqlimport beendet, wenn eine Tabelle
nicht vorhanden ist.
--host=
,
host_name
-h
host_name
Importiert Daten in den MySQL Server auf dem angegebenen
Host. Der Standardhost ist localhost
.
--ignore
, -i
Siehe Beschreibung zu --replace
.
--ignore-lines=
N
Ignoriert die ersten N
Zeilen
der Datendatei.
--local
, -L
Liest die Eingabedateien lokal vom Clienthost.
--lock-tables
, -l
Sperrt alle Tabellen für Schreiboperationen, bevor mit der Verarbeitung der Textdateien begonnen wird. Hierdurch ist sichergestellt, dass alle Tabellen auf dem Server synchronisiert sind.
--password[=
,
password
]-p[
password
]
Verwendet das angegebene Passwort zur Verbindung mit dem
Server. Wenn Sie die Kurzform der Option
(-p
) verwenden, dürfen Sie
kein Leerzeichen zwischen Option und
Passwort setzen. Lassen Sie den Wert
password
auf die Option
--password
bzw. -p
folgend weg, dann werden Sie zur Eingabe des Passworts
aufgefordert.
Die Angabe eines Passworts direkt auf der Befehlszeile ist als nicht sicher einzuordnen. Siehe auch Abschnitt 5.9.6, „Wie Sie Ihre Kennwörter sicher halten“.
--port=
,
port_num
-P
port_num
Die TCP/IP-Portnummer, die für die Verbindung verwendet werden soll.
--protocol={TCP|SOCKET|PIPE|MEMORY}
Das zu verwendende Verbindungsprotokoll.
--replace
, -r
Die Optionen --replace
und
--ignore
steuern den Umgang mit
eingegebenen Datensätzen, die Duplikate vorhandener
Datensätze mit eindeutigen Schlüsselwerten darstellen.
Wenn Sie --replace
angeben, ersetzen die
neuen die vorhandenen Datensätze, die denselben
eindeutigen Schlüsselwert aufweisen. Bei Angabe von
--ignore
hingegen werden neue
Datensätze, deren eindeutiger Schlüsselwert bereits
einem vorhandenen Datensatz zugewiesen ist, ignoriert.
Geben Sie keine Option an, dann tritt ein Fehler auf, wenn
ein doppelter Schlüsselwert gefunden wird; in diesem Fall
wird der Rest der Textdatei ignoriert.
--silent
, -s
Stummer Modus. Eine Ausgabe erfolgt nur, wenn ein Fehler auftritt.
--socket=
,
path
-S
path
Bei Verbindungen mit localhost
ist dies
die zu verwendende Unix-Socketdatei bzw. (unter Windows)
der Name der zu verwendenden Named Pipe.
--user=
,
user_name
-u
user_name
Verwendet den angegebenen MySQL-Benutzernamen zur Verbindung mit dem Server.
--verbose
, -v
Ausführlicher Modus. Es werden zusätzliche Angaben zu den Aktivitäten des Programms ausgegeben.
--version
, -V
Zeigt die Versionsinformation an und wird dann beendet.
Die nachfolgende Beispielsitzung veranschaulicht die Verwendung von mysqlimport:
shell>mysql -e 'CREATE TABLE imptest(id INT, n VARCHAR(30))' test
shell>ed
a 100 Max Sydow 101 Count Dracula . w imptest.txt 32 q shell>od -c imptest.txt
0000000 1 0 0 \t M a x S y d o w \n 1 0 0000020 1 \t C o u n t D r a c u l a \n 0000040 shell>mysqlimport --local test imptest.txt
test.imptest: Records: 2 Deleted: 0 Skipped: 0 Warnings: 0 shell>mysql -e 'SELECT * FROM imptest' test
+------+---------------+ | id | n | +------+---------------+ | 100 | Max Sydow | | 101 | Count Dracula | +------+---------------+
Mit dem Client mysqlshow können Sie Informationen zu den vorhandenen Datenbanken, deren Tabellen oder den Spalten oder Indizes einer Tabelle schnell anzeigen.
mysqlshow stellt eine
Befehlszeilenoberfläche für mehrere
SQL-SHOW
-Anweisungen bereit. Siehe auch
Abschnitt 13.5.4, „SHOW
“. Dieselben Informationen können Sie
auch durch direkte Verwendung dieser Anweisungen abrufen. Sie
können sie beispielsweise über das Clientprogramm
mysql absetzen.
Rufen Sie mysqlshow wie folgt auf:
shell> mysqlshow [options
] [db_name
[tbl_name
[col_name
]]]
Wenn keine Datenbank angegeben wird, erscheint eine Liste aller Datenbanknamen.
Wird keine Tabelle angegeben, dann werden alle passenden Tabellen in der Datenbank angezeigt.
Wird keine Spalte angegeben, dann werden alle passenden Spalten und Spaltentypen in der Tabelle angezeigt.
Die Ausgabe zeigt nur die Namen derjenigen Datenbanken, Tabellen oder Spalten an, für die Sie ausreichende Berechtigungen haben.
Enthält das letzte Argument Shell- oder SQL-spezifische
Jokerzeichen (‘*
’,
‘?
’,
‘%
’ oder
‘_
’), dann werden nur
diejenigen Namen gezeigt, die den jeweiligen Jokerzeichen
entsprechen. Enthält ein Datenbankname Unterstriche, dann
sollten diese mit einem Backslash (bei manchen Unix-Shells
zwingend auch mit zwei Backslashs) markiert werden, um eine
Liste der passenden Tabellen oder Spalten zu erhalten. Die
Zeichen ‘*
’ und
‘?
’ werden in die
SQL-Jokerzeichen ‘%
’ und
‘_
’ konvertiert. Dies kann zu
Verwirrung führen, wenn Sie versuchen, die Spalten einer
Tabelle mit einem ‘_
’ im Namen
anzuzeigen, denn in diesem Fall zeigt Ihnen
mysqlshow nur die Tabellennamen an, die dem
Muster entsprechen. Dieses Problem lässt sich allerdings ganz
einfach beheben, indem Sie am Ende der Befehlszeile ein
zusätzliches ‘%
’ als separates
Argument anhängen.
mysqlshow unterstützt die folgenden Optionen:
--help
, -?
Zeigt eine Hilfemeldung an und wird dann beendet.
--character-sets-dir=
path
Das Verzeichnis, in dem Zeichensätze installiert sind. Siehe auch Abschnitt 5.11.1, „Der für Daten und zum Sortieren benutzte Zeichensatz“.
--compress
, -C
Komprimiert alle Daten, die zwischen Client und Server ausgetauscht werden, sofern beide die Komprimierung unterstützen.
--debug[=
,
debug_options
]-#
[
debug_options
]
Schreibt ein Debuglog. Der String
debug_options
heißt häufig
'd:t:o,
.
file_name
'
--default-character-set=
charset_name
Verwendet charset_name
als
Standardzeichensatz. Siehe auch
Abschnitt 5.11.1, „Der für Daten und zum Sortieren benutzte Zeichensatz“.
--host=
,
host_name
-h
host_name
Stellt eine Verbindung zum MySQL Server auf dem angegebenen Host her.
--keys
, -k
Zeigt die Tabellenindizes an.
--password[=
,
password
]-p[
password
]
Verwendet das angegebene Passwort zur Verbindung mit dem
Server. Wenn Sie die Kurzform der Option
(-p
) verwenden, dürfen Sie
kein Leerzeichen zwischen Option und
Passwort setzen. Lassen Sie den Wert
password
auf die Option
--password
bzw. -p
folgend weg, dann werden Sie zur Eingabe des Passworts
aufgefordert.
Die Angabe eines Passworts direkt auf der Befehlszeile ist als nicht sicher einzuordnen. Siehe auch Abschnitt 5.9.6, „Wie Sie Ihre Kennwörter sicher halten“.
--port=
,
port_num
-P
port_num
Die TCP/IP-Portnummer, die für die Verbindung verwendet werden soll.
--protocol={TCP|SOCKET|PIPE|MEMORY}
Das zu verwendende Verbindungsprotokoll.
--show-table-type
Zeigt eine Spalte an, die den Tabellentyp angibt (wie bei
SHOW FULL TABLES
). Der Typ ist
BASE TABLE
oder
VIEW
.
--socket=
,
path
-S
path
Bei Verbindungen mit localhost
ist dies
die zu verwendende Unix-Socketdatei bzw. (unter Windows)
der Name der zu verwendenden Named Pipe.
--status
, -i
Zeigt zusätzliche Informationen zu jeder Tabelle an.
--user=
,
user_name
-u
user_name
Verwendet den angegebenen MySQL-Benutzernamen zur Verbindung mit dem Server.
--verbose
, -v
Ausführlicher Modus. Es werden zusätzliche Angaben zu den Aktivitäten des Programms ausgegeben. Diese Option kann mehrfach verwendet werden, um den Umfang der angezeigten Informationen zu erhöhen.
--version
, -V
Zeigt die Versionsinformation an und wird dann beendet.
mysqlslap ist ein Diagnoseprogramm, dessen Zweck die Emulation einer Clientlast für einen MySQL Server ist und das zeitbezogene Angaben der einzelnen Operationsstufen meldet. Das Programm simuliert den Zugriff mehrerer Clients auf den Server. mysqlslap wurde in MySQL 5.1.4 hinzugefügt.
Rufen Sie mysqlslap wie folgt auf:
shell> mysqlslap [options
]
mysqlslap unterstützt die folgenden Optionen:
--help
, -?
Zeigt eine Hilfemeldung an und wird dann beendet.
--auto-generate-sql
, -a
Erzeugt automatisch SQL-Anweisungen, wenn diese nicht in Dateien oder als Befehlsoptionen übergeben wurden.
--compress
, -C
Komprimiert alle Daten, die zwischen Client und Server ausgetauscht werden, sofern beide die Komprimierung unterstützen.
--concurrency
, -c
Anzahl der zu simulierenden Clients beim Absetzen der
SELECT
-Anweisung.
--create=
value
Datei oder String, der bzw. die zur Erstellung der Tabelle verwendet wird.
--create-schema=
value
Schema, in dem die Tests ausgeführt werden. Diese Option wurde in MySQL 5.1.5 hinzugefügt.
--csv[=
file
]
Erzeugt eine Ausgabe von Werten in kommagetrennter Form. Die Ausgabe erfolgt in die angegebene Datei oder, wenn keine Datei angegeben ist, in die Standardausgabe. Diese Option wurde in MySQL 5.1.5 hinzugefügt.
--debug[=
,
debug_options
]-#
[
debug_options
]
Schreibt ein Debuglog. Der String
debug_options
heißt häufig
'd:t:o,
.
file_name
'
--delimiter=
,
str
-F
str
Trennzeichen, das in SQL-Anweisungen verwendet wird, die in Dateien oder über Befehlsoptionen angegeben werden.
--engine=
,
engine_name
-e
engine_name
Speicher-Engine, die zur Erstellung der Tabelle verwendet wird.
--host=
,
host_name
-h
host_name
Stellt eine Verbindung zum MySQL Server auf dem angegebenen Host her.
--iterations=
,
N
-i
N
Häufigkeit, mit der die Tests durchgeführt werden.
--lock-directory=
path
Verzeichnis, das zur Speicherung von Sperren verwendet wird. Diese Option wurde in MySQL 5.1.5 hinzugefügt.
--number-char-cols=
,
N
-x
N
Anzahl der VARCHAR
-Spalten, die
verwendet werden, wenn
--auto-generate-sql
angegeben ist.
--number-int-cols=
,
N
-y
N
Anzahl der INT
-Spalten, die verwendet
werden, wenn --auto-generate-sql
angegeben ist.
--number-of-queries=
N
Anzahl der Abfragen, auf die jeder Client ungefähr beschränkt wird. Diese Option wurde in MySQL 5.1.5 hinzugefügt.
--only-print
Stellt keine Verbindung mit Datenbanken her. mysqlslap gibt dann nur aus, was es gemacht hätte. Diese Option wurde in MySQL 5.1.5 hinzugefügt.
--password[=
,
password
]-p[
password
]
Verwendet das angegebene Passwort zur Verbindung mit dem
Server. Wenn Sie die Kurzform der Option
(-p
) verwenden, dürfen Sie
kein Leerzeichen zwischen Option und
Passwort setzen. Lassen Sie den Wert
password
auf die Option
--password
bzw. -p
folgend weg, dann werden Sie zur Eingabe des Passworts
aufgefordert.
Die Angabe eines Passworts direkt auf der Befehlszeile ist als nicht sicher einzuordnen. Siehe auch Abschnitt 5.9.6, „Wie Sie Ihre Kennwörter sicher halten“.
--port=
,
port_num
-P
port_num
Die TCP/IP-Portnummer, die für die Verbindung verwendet werden soll.
--protocol={TCP|SOCKET|PIPE|MEMORY}
Das zu verwendende Verbindungsprotokoll.
--preserve-schema
Behält das Schema der mysqlslap-Ausführung bei. Diese Option wurde in MySQL 5.1.5 hinzugefügt.
--query=
,
value
-q
value
Datei oder String, der bzw. die die
SELECT
-Anweisung enthält, die zum
Abrufen von Daten verwendet wird.
--silent
, -s
Stummer Modus. Es erfolgt keine Ausgabe.
--skip-query
, -Q
Führt keine SELECT
-Anweisungen aus.
--slave
Folgt den Master-Sperren für andere
mysqlslap-Clients. Verwenden Sie diese
Option, wenn Sie die Synchronisation zu einem
Master-Server mit --lock-directory
und
NFS beabsichtigen. Diese Option wurde in MySQL 5.1.5
hinzugefügt.
--socket=
,
path
-S
path
Bei Verbindungen mit localhost
ist dies
die zu verwendende Unix-Socketdatei bzw. (unter Windows)
der Name der zu verwendenden Named Pipe.
--use-threads
Unter Unix werden standardmäßig
fork()
-Aufrufe verwendet. Bei dieser
Option werden stattdessen
pthread-Aufrufe benutzt. Unter Windows
werden pthread
-Aufrufe ohnehin
standardmäßig verwendet, d. h., die Option hat keine
Auswirkungen. Diese Option wurde in MySQL 5.1.6
hinzugefügt.
--user=
,
user_name
-u
user_name
Verwendet den angegebenen MySQL-Benutzernamen zur Verbindung mit dem Server.
--verbose
, -v
Ausführlicher Modus. Es werden zusätzliche Angaben zu den Aktivitäten des Programms ausgegeben.
--version
, -V
Zeigt die Versionsinformation an und wird dann beendet.
mysql_zap terminiert Prozesse, die mit einem Muster übereinstimmen. Das Programm verwendet den Befehl ps und Unix-Signale, läuft also unter Unix und Unix-ähnlichen Systemen.
Rufen Sie mysql_zap wie folgt auf:
shell> mysql_zap [-signal
] [-?Ift] pattern
Eine Übereinstimmung mit einem Prozess liegt vor, wenn die
Ausgabezeile von ps das Muster enthält.
Standardmäßig fordert mysql_zap für die
Terminierung eines Prozesses immer eine Bestätigung an. Geben
Sie y
ein, um den Prozess zu terminieren,
oder q
, um mysql_zap zu
beenden. Bei jeder anderen Antwort versucht
mysql_zap nicht, den Prozess zu
terminieren.
Sofern die Option
-
angegeben
ist, wird auf diese Weise der Name oder die Nummer des Signals
festgelegt, das an die betreffenden Prozesse zu senden ist.
Andernfalls versucht mysql_zap, einen
Prozess zunächst mit signal
TERM
(Signal 15) und
nachfolgend mit KILL
(Signal 9) zu beenden.
mysql_zap versteht die folgenden weiteren Optionen:
--help
, -?
,
-I
Zeigt eine Hilfemeldung an und wird dann beendet.
-f
Erzwingungsmodus. mysql_zap versucht, jeden Prozess zu terminieren, ohne eine Bestätigung anzufordern.
-t
Testmodus. Zeigt Informationen zu allen Prozessen an, terminiert sie aber nicht.
Auf den meisten Systemen zeigt MySQL neben einer internen Textmeldung den Systemfehlercode auf eine der folgenden Arten an:
message ... (errno: #) message ... (Errcode: #)
Um zu ermitteln, was der Fehlercode bedeutet, lesen Sie die Dokumentation zu Ihrem System oder verwenden das Hilfsprogramm perror.
perror gibt eine Beschreibung für einen Systemfehlercode oder den Code eines Speicher-Engine- (Tabellen-Handler-)Fehlers aus.
Rufen Sie perror wie folgt auf:
shell> perror [options
] errorcode
...
Beispiel:
shell> perror 13 64
Error code 13: Permission denied
Error code 64: Machine is not on the network
Um die Fehlermeldung für einen MySQL-Cluster-Fehlercode zu
erhalten, rufen Sie perror mit der Option
--ndb
auf:
shell> perror --ndb errorcode
Beachten Sie, dass die Bedeutung von Systemfehlermeldungen je nach verwendetem Betriebssystem unterschiedlich sein kann. Anders gesagt: Ein Fehlercode kann auf verschiedenen Betriebssystemen auf unterschiedliche Fehler verweisen.
perror unterstützt die folgenden Optionen:
Zeigt eine Hilfemeldung an und wird dann beendet.
Gibt die Fehlermeldung für einen MySQL-Cluster-Fehlercode aus.
Stummer Modus. Gibt nur die Fehlermeldung aus.
Ausführlicher Modus. Gibt den Fehlercode und die Fehlermeldung aus. Dies ist das Standardverhalten.
Zeigt die Versionsinformation an und wird dann beendet.
Das Hilfsprogramm replace ersetzt Strings in Dateien oder in der Standardeingabe.
Es gibt die folgenden Möglichkeiten, replace aufzurufen:
shell>replace from to [from to] ... -- file [file] ...
shell>replace from to [from to] ... < input
from
ist der String, nach dem
gesucht wird, und to
der String,
der den Such-String ersetzen soll. Es können ein oder mehrere
String-Paare angegeben werden.
Mit der Option --
geben Sie an, wo die Liste
mit den String-Ersetzungen endet und die Dateinamensliste
beginnt. In diesem Fall werden alle Dateien, die auf der
Befehlszeile angegeben sind, modifiziert, d. h., Sie sollten
vor der Bearbeitung eine Kopie der Originaldateien erstellen.
replace
zeigt in einer Meldung an,
welche der eingegebenen Dateien tatsächlich geändert werden.
Wenn die Option --
nicht angegeben ist, liest
replace die Standardeingabe und schreibt in
die Standardausgabe.
replace verwendet einen endlichen
Automaten, um längere Strings zuerst auf Übereinstimmung zu
prüfen. Hiermit können Strings gegeneinander ausgetauscht
werden. So werden etwa mit dem folgenden Befehl
a
und b
in den
angegebenen Dateien file1
und
file2
gegeneinander ausgetauscht:
shell> replace a b b a -- file1 file2 ...
Das Programm replace wird von msql2mysql verwendet. Siehe auch Abschnitt 24.9.1, „msql2mysql — Umwandeln von mSQL-Programmen für die Benutzung mit MySQL“.
replace unterstützt die folgenden Optionen:
-?
, -I
Zeigt eine Hilfemeldung an und wird dann beendet.
-#
debug_options
Schreibt ein Debuglog. Der String
heißt häufig
debug_options
'd:t:o,
.
file_name
'
-s
Stummer Modus. Es werden weniger Angaben zu den Aktivitäten des Programms ausgegeben.
-v
Ausführlicher Modus. Es werden zusätzliche Angaben zu den Aktivitäten des Programms ausgegeben.
-V
Zeigt die Versionsinformation an und wird dann beendet.
Inhaltsverzeichnis
Dieses Kapitel erläutert die Notationsregeln für die folgenden Elemente von SQL-Anweisungen bei der Verwendung von MySQL:
literale Werte wie etwa Strings und Zahlen
Bezeichner wie Datenbank-, Tabellen- und Spaltennamen
benutzerdefinierte und Systemvariablen
Kommentare
reservierte Wörter
In diesem Abschnitt wird erläutert, wie literale Werte in MySQL
geschrieben werden. Hierzu gehören Strings, Zahlen,
Hexadezimalwerte, boolesche Werte und NULL
.
Ferner behandeln wir hier die verschiedenen Nuancen und
Fallstricke, auf die Sie beim Umgang mit diesen Grundtypen in
MySQL treffen können.
Ein String ist eine Abfolge von Bytes oder Zeichen, die in
einfache (‘'
’) oder doppelte
Anführungszeichen (‘"
’) gesetzt
sind. Ein paar Beispiele:
'a string' "another string"
Wenn der SQL-Modus ANSI_QUOTES
aktiviert ist,
dürfen String-Literale nur in einfache Anführungszeichen
gesetzt werden. Ein in doppelten Anführungszeichen stehender
String wird als Bezeichner interpretiert.
Ein binärer String ist ein String, für den kein Zeichensatz und keine Sortierung definiert sind. Ein nichtbinärer String hingegen ist ein String, für den Zeichensatz und Sortierung definiert sind. Bei beiden String-Typen basieren Vergleiche auf den numerischen Werten der String-Einheit. Bei binären Strings ist dies das Byte, bei nichtbinären Strings das einzelne Zeichen (wobei zu beachten ist, dass manche Zeichensätze Zeichen enthalten, die aus mehreren Bytes bestehen).
String-Literale weisen unter Umständen eine optionale
Zeichensatzeinführung und eine
COLLATE
-Klausel auf:
[_charset_name
]'string
' [COLLATEcollation_name
]
Ein paar Beispiele:
SELECT _latin1'string
'; SELECT _latin1'string
' COLLATE latin1_danish_ci;
Weitere Informationen zu diesen Syntaxtypen für Strings finden Sie in Abschnitt 10.3.5, „Zeichensatz und Sortierfolge literaler Strings“.
Innerhalb eines Strings haben bestimmte Sequenzen jeweils eine
spezielle Bedeutung. Jede dieser Sequenzen beginnt mit einem
Backslash (‘\
’). Dieser wird
häufig als Escape-Zeichen bezeichnet.
MySQL erkennt die folgenden Escape-Sequenzen:
Diese Sequenzen unterscheiden die Groß-/Kleinschreibung. So
wird etwa ‘\b
’ als Rückschritt,
‘\B
’ hingegen als
‘B
’ interpretiert.
Das ASCII-Zeichen 26 kann als
‘\Z
’ kodiert werden; hierdurch
umgehen Sie Probleme mit der Tatsache, dass dieses Zeichen unter
Windows als Dateiende interpretiert wird. Das ASCII-Zeichen 26
verursacht in einer Datei Probleme, wenn Sie mysql
verwenden.
db_name
<
file_name
Die Sequenzen ‘\%
’ und
‘\_
’ erlauben die Suche nach
literalen Instanzen von ‘%
’ und
‘_
’ in Mustervergleichskontexten,
in denen sie andernfalls als Jokerzeichen interpretiert würden.
Details finden Sie in der Beschreibung zum Operator
LIKE
in
Abschnitt 12.3.1, „String-Vergleichsfunktionen“. Wenn Sie
‘\%
’ oder
‘\_
’ in Kontexten ohne
Mustervergleich verwenden, werden diese als Strings
‘\%
’ und
‘\_
’ und nicht als
‘%
’ und
‘_
’ ausgewertet.
Bei allen anderen Escape-Sequenzen wird der Backslash ignoriert.
Das bedeutet, dass das gekennzeichnete Zeichen als nicht
gekennzeichnetes interpretiert wird. So ist etwa
‘\x
’ identisch mit
‘x
’.
Es gibt mehrere Möglichkeiten, Anführungszeichen in einen String zu setzen:
Ein ‘'
’ in einem String, der
in ‘'
’ gesetzt ist, kann als
‘''
’ geschrieben werden.
Ein ‘"
’ in einem String, der
in ‘"
’ gesetzt ist, kann als
‘""
’ geschrieben werden.
Sie stellen dem Anführungszeichen ein Escape-Zeichen
(‘\
’) voran.
Ein ‘'
’ in einem String, der
in ‘"
’ gesetzt ist, erfordert
keine spezielle Behandlung und muss weder verdoppelt noch
mit einem Escape-Zeichen versehen werden. Ebenso erfordert
ein ‘"
’ in einem String, der
in ‘'
’ gesetzt ist, keine
Sonderbehandlung.
Die folgenden SELECT
-Anweisungen
veranschaulichen die Verwendung von Anführungs- und
Escape-Zeichen:
mysql>SELECT 'hello', '"hello"', '""hello""', 'hel''lo', '\'hello';
+-------+---------+-----------+--------+--------+ | hello | "hello" | ""hello"" | hel'lo | 'hello | +-------+---------+-----------+--------+--------+ mysql>SELECT "hello", "'hello'", "''hello''", "hel""lo", "\"hello";
+-------+---------+-----------+--------+--------+ | hello | 'hello' | ''hello'' | hel"lo | "hello | +-------+---------+-----------+--------+--------+ mysql>SELECT 'This\nIs\nFour\nLines';
+--------------------+ | This Is Four Lines | +--------------------+ mysql>SELECT 'disappearing\ backslash';
+------------------------+ | disappearing backslash | +------------------------+
Wenn Sie Binärdaten in eine String-Spalte (z. B. eine
BLOB
-Spalte) einfügen wollen, müssen die
folgenden Zeichen durch Escape-Sequenzen dargestellt werden:
NUL | NUL -Byte (ASCII 0). Dieses Zeichen wird mit
‘\0 ’ (einem Backslash
gefolgt vom Zeichen ASCII
‘0 ’) dargestellt. |
\ | Backslash (ASCII 92). Stellen Sie dieses Zeichen als
‘\\ ’ dar. |
' | Einfaches Anführungszeichen (ASCII 39). Stellen Sie dieses Zeichen als
‘\' ’ dar. |
" | Doppeltes Anführungszeichen (ASCII 34). Stellen Sie dieses Zeichen als
‘\" ’ dar. |
Wenn Sie Anwendungsprogramme schreiben, muss jeder String, der eines dieser Sonderzeichen enthalten kann, korrekt gekennzeichnet werden, bevor er als Datenwert in einer SQL-Anweisung verwendet wird, die an den MySQL Server gesendet wird. Dies lässt sich auf zweierlei Weise realisieren:
Sie verarbeiten den String mit einer Funktion, die die
Sonderzeichen entsprechend kennzeichnet. In einem C-Programm
können Sie die C-API-Funktion
mysql_real_escape_string()
zur
Kennzeichnung von Sonderzeichen verwenden. Siehe auch
Abschnitt 24.2.3.52, „mysql_real_escape_string()
“. Die
Perl-DBI-Schnittstelle stellt eine Methode
quote
zur Konvertierung von Sonderzeichen
in die entsprechenden Escape-Sequenzen bereit. Siehe auch
Abschnitt 24.4, „MySQLs Perl-API“. Andere Spracheschnittstellen bieten
unter Umständen ähnliche Funktionalitäten.
Eine Alternative zur expliziten Kennzeichnung von Sonderzeichen stellt die Platzhalterfunktion dar, die von vielen MySQL-APIs geboten wird. Sie erlaubt Ihnen das Einfügen spezieller Markierungen in einen Anweisungs-String und das nachfolgende Binden der Datenwerte an diese Markierungen beim Absetzen der Anweisung. In diesem Fall nimmt Ihnen die API die Kennzeichnung der Sonderzeichen in den Werten ab.
Integer-Zahlen werden als Abfolge von Ziffern dargestellt.
Fließkommazahlen verwenden den Punkt
(‘.
’) als Dezimaltrennzeichen.
Bei allen Zahlentypen werden durch ein vorangestelltes
‘-
’- oder
‘+
’-Zeichen negative bzw.
positive Werte angezeigt.
Beispiele gültiger Integers:
1221 0 -32
Beispiele gültiger Fließkommazahlen:
294.42 -32032.6809e+10 148.00
Ein Integer kann durchaus in einem Fließkommakontext angegeben werden. Er wird dann als die entsprechende Fließkommazahl interpretiert.
MySQL unterstützt Hexadezimalwerte. In numerischen Kontexten verhalten sich diese wie Integers (mit 64-Bit-Präzision). In String-Kontexten hingegen agieren sie als binäre Strings, wobei jedes Hexadezimalziffernpaar in ein Zeichen umgewandelt wird:
mysql>SELECT x'4D7953514C';
-> 'MySQL' mysql>SELECT 0xa+0;
-> 10 mysql>SELECT 0x5061756c;
-> 'Paul'
Der Standardtyp eines Hexadezimalwerts ist ein String. Wenn Sie
gewährleisten wollen, dass der Wert als Zahl behandelt wird,
können Sie CAST(... AS UNSIGNED)
verwenden:
mysql> SELECT 0x41, CAST(0x41 AS UNSIGNED);
-> 'A', 65
Die Syntax
x'
basiert auf Standard-SQL. Die Syntax hexstring
'0x
basiert auf ODBC. Hexadezimal-Strings werden von ODBC häufig
zur Angabe von Werten für BLOB
-Spalten
verwendet.
Sie können mit der Funktion HEX()
einen
String oder eine Zahl in einen String im Hexadezimalformat
umwandeln:
mysql>SELECT HEX('cat');
-> '636174' mysql>SELECT 0x636174;
-> 'cat'
Die Konstanten TRUE
und
FALSE
werden als 1
bzw.
0
ausgewertet. Bei den Konstantennamen wird
die Groß-/Kleinschreibung nicht unterschieden.
mysql> SELECT TRUE, true, FALSE, false;
-> 1, 1, 0, 0
Bitfeldwerte können unter Verwendung der Notation
b'
geschrieben werden. Hierbei ist value
'value
ein Binärwert, der mit Nullen und Einsen notiert wird.
Die Bitfeldnotation ist zur Angabe von Werten nützlich, die
BIT
-Spalten zugewiesen werden sollen:
mysql>CREATE TABLE t (b BIT(8));
mysql>INSERT INTO t SET b = b'11111111';
mysql>INSERT INTO t SET b = b'1010';
+------+----------+----------+----------+ | b+0 | BIN(b+0) | OCT(b+0) | HEX(b+0) | +------+----------+----------+----------+ | 255 | 11111111 | 377 | FF | | 10 | 1010 | 12 | A | +------+----------+----------+----------+
Der Wert NULL
bedeutet „keine
Daten“. Die Groß-/Kleinschreibung wird bei
NULL
nicht unterschieden.
Beachten Sie, dass der NULL
-Wert sich von
Werten wie 0
für numerische Typen oder vom
Leer-String für String-Typen unterscheidet. Siehe auch
Abschnitt A.5.3, „Probleme mit NULL
-Werten“.
Bei Import- oder Exportoperationen für Textdateien, die mit
LOAD DATA INFILE
oder SELECT ...
INTO OUTFILE
durchgeführt werden, wird
NULL
durch die Sequenz \N
dargestellt. Siehe auch Abschnitt 13.2.5, „LOAD DATA INFILE
“.
Namen von Datenbanken, Tabellen, Indizes, Spalten und Aliasen sind Bezeichner. Dieser Abschnitt beschreibt die für Bezeichner in MySQL zulässige Syntax.
Die folgende Tabelle beschreibt die Maximallänge und die erlaubten Zeichen für jeden Bezeichnertyp.
Bezeichner | Maximale Länge (in Byte) | Erlaubte Zeichen |
Datenbank | 64 | Jedes Zeichen, das in einem Verzeichnisnamen zulässig ist. Ausgenommen
sind ‘/ ’,
‘\ ’ und
‘. ’ |
Tabelle | 64 | Jedes Zeichen, das in einem Dateinamen zulässig ist. Ausgenommen sind
‘/ ’,
‘\ ’ und
‘. ’ |
Spalte | 64 | Alle Zeichen |
Index | 64 | Alle Zeichen |
Alias | 255 | Alle Zeichen |
Neben den in der Tabelle genannten Einschränkungen dürfen Bezeichner weder das ASCII-Zeichen 0 noch ein Byte mit dem Wert 255 enthalten. Namen von Datenbanken, Tabellen und Spalten sollten nicht auf Leerzeichen enden. Die Verwendung von Anführungszeichen in Bezeichnern ist zulässig, sollte allerdings möglichst vermieden werden.
Bezeichner werden im Unicode-Format (UTF-8) gespeichert. Dies gilt
für Bezeichner in Tabellendefinitionen, die in
.frm
-Dateien gespeichert sind, ebenso wie
für solche in den Grant-Tabellen der Datenbank
mysql
. Die Länge der String-Spalten in den
Grant-Tabellen (und in allen anderen Tabellen) in MySQL
5.1 wird als Anzahl von Zeichen angegeben. Das
bedeutet, dass Sie (anders als bei älteren MySQL-Versionen)
Multibytezeichen verwenden können, ohne die Anzahl der Zeichen
verringern zu müssen, die für in diesen Spalten gespeicherte
Werte erlaubt sind.
Ein Bezeichner kann mit und ohne Anführungszeichen geschrieben
werden. Wenn ein Bezeichner ein reserviertes Wort ist oder
Sonderzeichen enthält, müssen sie ihn bei
jeder Referenzierung in Anführungszeichen setzen. (Ausnahme: Ein
Wort, das auf einen Punkt in einem qualifizierten Namen folgt,
muss ein Bezeichner sein; es muss also auch dann nicht in
Anführungszeichen gesetzt werden, wenn es sich um ein
reserviertes Wort handelt.) Eine Liste reservierter Wörter finden
Sie unter Abschnitt 9.5, „Ist MySQL pingelig hinsichtlich reservierter Wörter?“. Als Sonderzeichen
werden ‘_
’ und
‘$
’ sowie alle nicht
alphanumerischen Zeichen des aktuellen Zeichensatzes betrachtet.
Das Anführungszeichen für Bezeichner ist der Backtick
(‘`
’):
mysql> SELECT * FROM `select` WHERE `select`.id > 100;
Wenn der SQL-Modus ANSI_QUOTES
aktiviert ist,
können Sie Bezeichner auch in doppelte Anführungszeichen setzen:
mysql>CREATE TABLE "test" (col INT);
ERROR 1064: You have an error in your SQL syntax. (...) mysql>SET sql_mode='ANSI_QUOTES';
mysql>CREATE TABLE "test" (col INT);
Query OK, 0 rows affected (0.00 sec)
Hinweis: Da der Server bei aktiviertem
ANSI_QUOTES
-Modus Strings in doppelten
Anführungszeichen in jedem Fall als Bezeichner interpretiert,
müssen String-Literale in einfache Anführungszeichen gesetzt
werden; doppelte Anführungszeichen dürfen in diesem Fall nicht
für String-Literale verwendet werden.
Wie der SQL-Modus des Servers gesteuert wird, entnehmen Sie Abschnitt 5.2.5, „Der SQL-Modus des Servers“.
Anführungszeichen für Bezeichner können in einem Bezeichner
enthalten sein, wenn Sie den Bezeichner in
Anführungszeichen setzen. Wenn das im Bezeichner
enthaltene Zeichen dasselbe ist, mit dem auch der Bezeichner
selbst umschlossen ist, dann müssen Sie das Zeichen im Bezeichner
verdoppeln. Die folgende Anweisung erstellt eine Tabelle namens
a`b
, die eine Spalte namens
c"d
enthält:
mysql> CREATE TABLE `a``b` (`c"d` INT);
Es wird davon abgeraten, Namen des Formats
oder
M
e
(wie etwa M
eN
1e
oder 2e2
) zu
verwenden, weil ein Ausdruck wie 1e+3
nicht
eindeutig ist: Abhängig vom Kontext kann er als Ausdruck
1e + 3
oder als Zahl 1e+3
interpretiert werden.
Seien Sie vorsichtig, wenn Sie mit MD5()
Tabellennamen erstellen, da hiermit Namen in unzulässigen oder
mehrdeutigen Formaten (so, wie gerade beschrieben) erzeugt werden
können.
MySQL unterstützt Namen, die aus einem oder mehreren
Bezeichnern bestehen. Die Bestandteile eines mehrteiligen Namens
sollten durch Punkte (‘.
’)
getrennt werden. Die ersten Bestandteile eines mehrteiligen
Namens agieren als Qualifikationsmerkmal, das den Kontext
beeinflusst, in dem der endgültige Bezeichner interpretiert
wird.
Bei MySQL können Sie eine Spalte auf jede der folgenden Weisen referenzieren:
Spaltenreferenzierung | Bedeutung |
col_name | Die Spalte col_name einer in der Anweisung
verwendeten Tabelle hat diesen Namen. |
tbl_name.col_name | Die Spalte col_name der Tabelle
tbl_name aus der
Standarddatenbank. |
db_name.tbl_name.col_name | Die Spalte col_name der Tabelle
tbl_name aus der Datenbank
db_name . |
Wenn Bestandteile eines mehrteiligen Namens Anführungszeichen
erfordern, müssen Sie diese Bestandteile einzeln (statt des
gesamten Namens) in Anführungszeichen setzen. So ist etwa
`my-table`.`my-column`
zulässig – anders
als `my-table.my-column`
.
Sie müssen das Präfix tbl_name
oder
db_name.tbl_name
für eine
Spaltenreferenzierung in einer Anweisung nicht angeben, sofern
die Referenzierung eindeutig ist. Angenommen, die Tabellen
t1
und t2
enthalten
jeweils eine Spalte c
. Nun wollen Sie
c
in einer
SELECT
-Anweisung abrufen, die sowohl
t1
als auch t2
verwendet.
In diesem Fall ist c
unklar, weil es in Bezug
auf die in der Anweisung angegebenen Tabellen nicht eindeutig
ist. Sie müssen es mit einem Tabellennamen wie
t1.c
bzw. t2.c
qualifizieren, um anzugeben, welche Tabelle Sie meinen. Analog
müssen Sie, um Spaltenwerte aus einer Tabelle
t
in der Datenbank db1
und
einer Tabelle t
in der Datenbank
db2
in einer Anweisung abzurufen, Spalten in
diesen Tabellen als db1.t.col_name
und
db2.t.col_name
referenzieren.
Ein Wort, das auf einen Punkt in einem qualifizierten Namen folgt, muss ein Bezeichner sein; es muss also auch dann nicht in Anführungszeichen gesetzt werden, wenn es sich um ein reserviertes Wort handelt.
Die Syntax .tbl_name
bezeichnet die
Tabelle tbl_name
in der
Standarddatenbank. Diese Syntax wird aus Gründen der
ODBC-Kompatibilität akzeptiert, weil einige ODBC-Programme
Tabellennamen das Zeichen ‘.
’
voranstellen.
Bei MySQL entsprechen Datenbanken den Verzeichnissen im
Datenverzeichnis. Jede Tabelle in einer Datenbank entspricht
mindestens einer Datei (abhängig von der Speicher-Engine
möglicherweise auch mehreren) im Datenbankverzeichnis. Hieraus
folgt, dass bezüglich der Groß-/Kleinschreibung von Datenbank-
und Tabellennamen die Regeln des zugrunde liegenden
Betriebssystems beachtet werden müssen. Dies bedeutet, dass die
Groß-/Kleinschreibung von Datenbank- und Tabellennamen bei den
meisten Unix-Varianten unterschieden wird, bei Windows hingegen
nicht. Eine beachtenswerte Ausnahme ist Mac OS X, welches zwar
auf Unix basiert, standardmäßig aber einen Dateisystemtyp
verwendet, der die Groß-/Kleinschreibung nicht unterscheidet.
Allerdings unterstützt Mac OS X auch UFS-Volumes, die wie bei
Unix üblich die Groß-/Kleinschreibung unterscheiden. Siehe
auch Abschnitt 1.9.4, „MySQL-Erweiterungen zu ANSI SQL92“. Die Systemvariable
lower_case_table_names
beeinflusst ebenfalls
die Vorgehensweise des Servers in Bezug auf die
Groß-/Kleinschreibung bei Bezeichnern. Weitere Informationen
hierzu folgen in diesem Abschnitt.
Hinweis: Zwar wird die
Groß-/Kleinschreibung bei Datenbank- und Tabellennamen auf
manchen Plattformen nicht unterschieden, aber Sie sollten eine
gegebene Datenbank oder Tabelle auch nicht mit unterschiedlichen
Schreibweisen innerhalb derselben Anweisung referenzieren. Die
folgende Anweisung würde nicht funktionieren, weil sie eine
Tabelle sowohl als my_table
als auch als
MY_TABLE
referenziert:
mysql> SELECT * FROM my_table WHERE MY_TABLE.col=1;
Bei Namen von Spalten, Indizes, gespeicherten Routinen und Triggern wird die Groß-/Kleinschreibung auf keiner Plattform unterschieden. Gleiches gilt für Spaltenaliase.
Standardmäßig wird die Groß-/Kleinschreibung bei
Tabellenaliasen unter Unix, nicht aber unter Windows oder Mac OS
X unterschieden. Die folgende Anweisung würde unter Unix nicht
funktionieren, da sie einen Alias sowohl als
a
als auch als A
referenziert:
mysql>SELECT
->col_name
FROMtbl_name
AS aWHERE a.
col_name
= 1 OR A.col_name
= 2;
Unter Windows hingegen ist diese Anweisung zulässig. Damit Sie diesen Unterschieden möglichst wenig Beachtung schenken müssen, sollten Sie am besten eine konsistente Benennungskonvention verwenden, in der Datenbanken und Tabellen immer mit aus Kleinbuchstaben bestehenden Namen erstellt und referenziert werden. Eine solche Konvention wird im Sinne maximaler Portabilität und Benutzerfreundlichkeit empfohlen.
Wie Tabellen- und Datenbanknamen auf Festplatte gespeichert und
in MySQL verwendet werden, bestimmt die Systemvariable
lower_case_table_names
, die Sie beim Start
von mysqld einstellen können.
lower_case_table_names
kann die in der
nachfolgenden Tabelle aufgeführten Werte annehmen. Unter Unix
ist der Standardwert von
lower_case_table_names
0, unter Windows 1 und
unter Mac OS X 2.
Wert | Bedeutung |
0 | Tabellen- und Datenbanknamen werden in der Schreibweise auf Festplatte
gespeichert, die in der CREATE TABLE -
bzw. CREATE DATABASE -Anweisung
angegeben wurde. Beim Namensvergleich wird die
Groß-/Kleinschreibung unterschieden. Beachten Sie,
dass, wenn Sie diese Variable auf einem Dateisystem ohne
Unterscheidung der Groß-/Kleinschreibung mit
--lower-case-table-names=0 explizit auf
0 setzen und dann MyISAM -Tabellen mit
Namen in anderer Schreibung aufrufen, dies zu einer
Beschädigung der Indizes führen kann. |
1 | Tabellennamen werden in Kleinbuchstaben auf Festplatte gespeichert. Beim Namensvergleich wird die Groß-/Kleinschreibung nicht unterschieden. MySQL konvertiert beim Speichern und Abrufen alle Tabellennamen in Kleinbuchstaben. Dieses Verhalten gilt auch für Datenbanknamen und Tabellenaliase. |
2 | Tabellen- und Datenbanknamen werden in der Schreibweise auf Festplatte
gespeichert, die in der CREATE TABLE -
bzw. CREATE DATABASE -Anweisung
angegeben wurde; beim Nachschlagen konvertiert MySQL sie
jedoch in Kleinbuchstaben. Beim Namensvergleich wird die
Groß-/Kleinschreibung nicht unterschieden.
Hinweis: Dies
funktioniert nur auf Dateisystemen,
die die Groß-/Kleinschreibung nicht unterscheiden!
InnoDB -Tabellennamen werden in
Kleinbuchstaben (wie bei
lower_case_table_names=1 )
gespeichert. |
Wenn Sie MySQL nur auf einer Plattform verwenden, dann müssen
Sie die Variable lower_case_table_names
normalerweise nicht umstellen. Allerdings kann es zu Problemen
kommen, wenn Sie Tabellen auf andere Plattformen mit
unterschiedlicher Behandlung der Groß-/Kleinschreibung
portieren wollen. So können Sie unter Unix beispielsweise zwei
verschiedene Tabellen mit den Namen my_table
und MY_TABLE
verwenden; unter Windows jedoch
werden diese beiden Namen als identisch betrachtet. Um
Transferprobleme aufgrund der Schreibweise von Datenbank- oder
Tabellennamen zu vermeiden, haben Sie zwei Optionen:
Sie verwenden lower_case_table_names=1
auf allen Systemen. Der wesentliche Nachteil besteht hierbei
darin, dass Sie, wenn Sie SHOW TABLES
bzw. SHOW DATABASES
verwenden, die Namen
nicht in der ursprünglichen Schreibweise angezeigt
bekommen.
Sie verwenden unter Unix
lower_case_table_names=0
und unter
Windows lower_case_table_names=2
.
Hierdurch wird die Schreibweise von Datenbank- und
Tabellennamen beibehalten. Allerdings müssen Sie in diesem
Fall gewährleisten, dass Ihre Anweisungen unter Windows die
korrekte Schreibweise für Datenbank- und Tabellennamen
enthalten. Wenn Sie Ihre Anweisungen dann auf Unix
übertragen, wo die Groß-/Kleinschreibung unterschieden
wird, dann funktionieren sie aufgrund der falschen
Schreibweise nicht mehr.
Ausnahme: Wenn Sie
InnoDB
-Tabellen verwenden, sollten Sie
lower_case_table_names
auf allen
Plattformen auf 1 setzen. Hiermit wird die Konvertierung von
Namen in die Kleinschreibung erzwungen.
Beachten Sie, dass Sie, wenn Sie die Systemvariable
lower_case_table_names
unter Unix auf 1
setzen wollen, zunächst Ihre alten Datenbank- und Tabellennamen
in die Kleinschreibung konvertieren müssen, bevor Sie
mysqld mit der neuen Variableneinstellung neu
starten.
Sie können einen Wert in einer Benutzervariablen speichern und diese dann später referenzieren. Auf diese Weise können Sie Werte von einer Anweisung an eine andere übergeben. Benutzerdefinierte Variablen sind verbindungsspezifisch, d. h., eine Benutzervariable, die von einem Client definiert wurde, wird von anderen Clients nicht gesehen und kann von diesen auch nicht verwendet werden. Alle Variablen einer gegebenen Clientverbindung werden automatisch freigegeben, wenn diese Verbindung beendet wird.
Benutzervariablen werden als
@
notiert,
wobei der Variablenname var_name
var_name
aus
alphanumerischen Zeichen des aktuellen Zeichensatzes sowie
‘.
’,
‘_
’ und
‘$
’ bestehen kann. Der
Standardzeichensatz ist latin1
(cp1252 West
European). Er lässt sich mit der Option
--default-character-set
für
mysqld ändern. Siehe auch
Abschnitt 5.11.1, „Der für Daten und zum Sortieren benutzte Zeichensatz“. Der Name einer Benutzervariablen
darf auch andere Zeichen enthalten, wenn Sie ihn als String oder
Bezeichner in Anführungszeichen setzen (z. B.
@'my-var'
, @"my-var"
oder
@`my-var`
).
Hinweis: Bei MySQL vor Version 5.0 wird die Groß-/Kleinschreibung unterschieden, ab MySQL 5.0 hingegen nicht mehr.
Eine Möglichkeit zur Einstellung einer benutzerdefinierten
Variablen besteht im Absetzen einer
SET
-Anweisung:
SET @var_name
=expr
[, @var_name
=expr
] ...
Bei SET
kann entweder =
oder
:=
als Zuweisungsoperator verwendet werden. Der
Wert expr
einer Variablen kann als
Integer, reale Zahl, String oder NULL
-Wert
ausgewertet werden.
Sie können einer Benutzervariablen auch mit einer anderen
Anweisung als SET
einen Wert zuweisen. In
diesem Fall muss der Zuweisungsoperator :=
sein; =
darf nicht verwendet werden, da es in
anderen Anweisungen als SET
als
Vergleichsoperator benutzt wird:
mysql>SET @t1=0, @t2=0, @t3=0;
mysql>SELECT @t1:=(@t2:=1)+@t3:=4,@t1,@t2,@t3;
+----------------------+------+------+------+ | @t1:=(@t2:=1)+@t3:=4 | @t1 | @t2 | @t3 | +----------------------+------+------+------+ | 5 | 5 | 1 | 4 | +----------------------+------+------+------+
Benutzervariablen können in Kontexten eingesetzt werden, in denen
Ausdrücke zulässig sind. Hierzu gehören zurzeit keine Kontexte,
die explizit einen literalen Wert erfordern, also beispielsweise
die LIMIT
-Klausel einer
SELECT
-Anweisung oder die IGNORE
-Klausel einer
N
LINESLOAD DATA
-Anweisung.
Wenn einer Benutzervariablen ein String-Wert zugewiesen wird, hat sie denselben Zeichensatz und dieselbe Sortierung wie dieser String. Die Erzwingbarkeit ist Benutzervariablen implizit. (Es handelt sich um dieselbe Erzwingbarkeit wie bei Werten einer Tabellenspalte.)
Hinweis: In einer
SELECT
-Anweisung wird jeder Ausdruck erst dann
ausgewertet, wenn er an den Client gesendet wird. Das bedeutet,
dass in einer HAVING
-, GROUP
BY
- oder ORDER BY
-Klausel keine
Referenzierung eines Ausdrucks möglich ist, der Variablen
beinhaltet, die in der SELECT
-Liste eingestellt
werden. Die folgende Anweisung beispielsweise funktioniert
nicht wie erwartet:
mysql> SELECT (@aa:=id) AS a, (@aa+3) AS b FROM tbl_name
HAVING b=5;
Die Referenzierung von b
in der
HAVING
-Klausel verweist auf ein Alias eines
Ausdrucks in der SELECT
-Liste, die
@aa
verwendet. Das funktioniert nicht so, wie
man es eigentlich erwarten würde: @aa
enthält
den Wert von id
aus dem zuvor ausgewählten
(und nicht dem aktuellen) Datensatz.
Allgemein gesagt darf man niemals einer Benutzervariablen in einem Teil einer Anweisung einen Wert zuweisen und dieselbe Variable in einem anderen Teil derselben Anweisung verwenden. Vielleicht erhalten Sie die erwarteten Ergebnisse, aber dies ist nicht sicher.
Ein weiteres Problem in Zusammenhang mit der Einstellung einer Variablen und ihrer Verwendung in derselben Anweisung besteht darin, dass der standardmäßige Ergebnistyp einer Variablen zu Beginn der Anweisung auf dem Variablentyp basiert. Das folgende Beispiel veranschaulicht dies:
mysql>SET @a='test';
mysql>SELECT @a,(@a:=20) FROM
tbl_name
;
Bei dieser SELECT
-Anweisung meldet MySQL dem
Client, dass Spalte eins ein String ist, und konvertiert alle
Zugriffe auf @a
in Strings, obwohl
@a
für den zweiten Datensatz eine Zahlenmenge
ist. Nachdem die SELECT
-Anweisung ausgeführt
wurde, wird @a
für die nächste Anweisung als
Zahl betrachtet.
Um Probleme in Zusammenhang mit diesem Verhalten zu vermeiden,
sollten Sie entweder dieselbe Variable nicht gleichzeitig in ein
und derselben Anweisung einstellen und verwenden oder aber die
Variable auf 0
, 0.0
oder
''
setzen, um vor ihrer Verwendung den Typ zu
definieren.
Wenn Sie eine Variable referenzieren, die noch nicht initialisiert
wurde, dann hat diese den Wert NULL
, und der
Variablentyp ist ein String.
Der MySQL Server unterstützt drei Kommentarstile:
Vom Zeichen ‘#
’ bis zum
Zeilenende.
Von der Sequenz ‘--
’ bis zum
Zeilenende. Bei MySQL erfordert der Kommentarstil
‘--
’ (doppelter Bindestrich)
mindestens ein nachfolgendes Whitespace- oder Steuerzeichen
(z. B. ein Leerzeichen, einen Tabulator, einen Zeilenwechsel
usw.). Diese Syntax unterscheidet sich leicht von der
SQL-Standardkommentarsyntax, wie sie in
Abschnitt 1.9.5.7, „'--
' als Beginn eines Kommentars“, beschrieben ist.
Von der Sequenz /*
bis zur folgenden
Sequenz */
, wie man es von der
Programmiersprache C her kennt. Diese Syntax ermöglicht
Kommentare, die sich über mehrere Zeilen erstrecken, da
öffnende und schließende Sequenz nicht in derselben Zeile
stehen müssen.
Das folgende Beispiel veranschaulicht alle drei Kommentarstile:
mysql>SELECT 1+1; # This comment continues to the end of line
mysql>SELECT 1+1; -- This comment continues to the end of line
mysql>SELECT 1 /* this is an in-line comment */ + 1;
mysql>SELECT 1+
/*
this is a
multiple-line comment
*/
1;
MySQL Server unterstützt mehrere Kommentarvarianten im C-Stil. Hiermit können Sie Code schreiben, der MySQL-Erweiterungen enthält, aber trotzdem portierbar ist; Sie müssen dann Kommentare in der folgenden Form verwenden:
/*! MySQL-specific code
*/
In diesem Fall verarbeitet MySQL Server den Code innerhalb des
Kommentars wie normale SQL-Anweisungen; andere SQL-Server hingegen
ignorieren die Erweiterungen. So erkennt MySQL Server
beispielsweise anders als andere Server das Schlüsselwort
STRAIGHT_JOIN
in der folgenden Anweisung:
SELECT /*! STRAIGHT_JOIN */ col1 FROM table1,table2 WHERE ...
Wenn Sie nach dem Zeichen ‘!
’ die
Versionsnummer angeben, wird die Syntax nur ausgeführt, wenn die
betreffende oder eine neuere MySQL-Version verwendet wird. Das
Schlüsselwort TEMPORARY
im folgenden Kommentar
wird nur von Servern ausgeführt, auf denen MySQL 3.23.02 oder
höher läuft:
CREATE /*!32302 TEMPORARY */ TABLE t (a INT);
Die beschriebene Kommentarsyntax wirkt sich darauf aus, wie der Server mysqld SQL-Anweisungen verarbeitet. Auch das Clientprogramm mysql verarbeitet die Anweisungen teilweise, bevor es sie an den Server sendet. (Dies tut es, um die Anweisungsgrenzen in einer Eingabezeile mit mehreren Anweisungen zu ermitteln.)
Ein häufig auftretendes Problem liegt vor, wenn Sie einen
Bezeichner (z. B. einen Tabellen- oder Datenbanknamen) verwenden
wollen, der ein reserviertes Wort wie SELECT
oder den Namen eines werksseitig vorhandenen MySQL-Datentyps oder
einer Funktion wie TIMESTAMP
oder
GROUP
enthält.
Wenn ein Bezeichner ein reserviertes Wort ist, müssen Sie ihn wie in Abschnitt 9.2, „Datenbank-, Tabellen-, Index-, Spalten- und Aliasnamen“, beschrieben in Anführungszeichen setzen. Ausnahme: Ein Wort, das auf einen Punkt in einem qualifizierten Namen folgt, muss ein Bezeichner sein; es muss also auch dann nicht in Anführungszeichen gesetzt werden, wenn es sich um ein reserviertes Wort handelt.
Funktionsnamen dürfen Sie als Bezeichner verwenden.
Beispielsweise ist ABS
als Spaltenname
zulässig. Standardmäßig ist nämlich bei Funktionsaufrufen kein
Whitespace zwischen dem Funktionsnamen und dem nachfolgenden
Zeichen ‘(
’ zulässig; auf diese
Weise kann ein Funktionsaufruf von der Referenzierung eines
Spaltennamens unterschieden werden.
Eine Begleiterscheinung dieses Verhaltens besteht darin, dass das Weglassen eines Leerzeichens in manchen Kontexten dazu führen kann, dass ein Bezeichner als Funktionsname interpretiert wird. Folgende Anweisung beispielsweise ist zulässig:
mysql> CREATE TABLE abs (val INT);
Das Weglassen des Leerzeichens nach abs
verursacht einen Syntaxfehler, da die Anweisung in diesem Fall die
Funktion ABS()
aufzurufen scheint:
mysql> CREATE TABLE abs(val INT);
ERROR 1064 (42000) at line 2: You have an error in your SQL
syntax ... near 'abs(val INT)'
Ist der SQL-Modus IGNORE_SPACE
aktiviert, dann
gestattet der Server bei Funktionsaufrufen das Vorhandensein von
Whitespace zwischen dem Funktionsnamen und dem nachfolgenden
Zeichen ‘(
’. Hierdurch werden
Funktionsnamen als reservierte Wörter behandelt. Infolgedessen
müssen Bezeichner, die mit Funktionsnamen identisch sind, wie in
Abschnitt 9.2, „Datenbank-, Tabellen-, Index-, Spalten- und Aliasnamen“, beschrieben in Anführungszeichen
gesetzt werden. Wie der SQL-Modus des Servers gesteuert wird,
entnehmen Sie Abschnitt 5.2.5, „Der SQL-Modus des Servers“.
Die Wörter in der folgenden Tabelle sind explizit für MySQL
5.1 reserviert. Für den Fall, dass Sie später
einmal auf eine höhere Version zu aktualisieren beabsichtigen,
sollten Sie auch solche Wörter beachten, die in Zukunft
reserviert sein werden. Sie finden diese in den Handbüchern zu
höheren MySQL-Versionen. Die meisten der Wörter in der Tabelle
sind in Standard-SQL als Spalten- oder Tabellennamen unzulässig
(z. B. GROUP
). Einige der Wörter sind auch
reserviert, weil MySQL sie benötigt und (derzeit) einen
yacc-Parser verwendet. Ein reserviertes Wort
darf als Bezeichner verwendet werden, wenn Sie es in
Anführungszeichen setzen.
ACCESSIBLE | ADD | ALL |
ALTER | ANALYZE | AND |
AS | ASC | ASENSITIVE |
BEFORE | BETWEEN | BIGINT |
BINARY | BLOB | BOTH |
BY | CALL | CASCADE |
CASE | CHANGE | CHAR |
CHARACTER | CHECK | COLLATE |
COLUMN | CONDITION | CONNECTION |
CONSTRAINT | CONTINUE | CONVERT |
CREATE | CROSS | CURRENT_DATE |
CURRENT_TIME | CURRENT_TIMESTAMP | CURRENT_USER |
CURSOR | DATABASE | DATABASES |
DAY_HOUR | DAY_MICROSECOND | DAY_MINUTE |
DAY_SECOND | DEC | DECIMAL |
DECLARE | DEFAULT | DELAYED |
DELETE | DESC | DESCRIBE |
DETERMINISTIC | DISTINCT | DISTINCTROW |
DIV | DOUBLE | DROP |
DUAL | EACH | ELSE |
ELSEIF | ENCLOSED | ESCAPED |
EXISTS | EXIT | EXPLAIN |
FALSE | FETCH | FLOAT |
FLOAT4 | FLOAT8 | FOR |
FORCE | FOREIGN | FROM |
FULLTEXT | GRANT | GROUP |
HAVING | HIGH_PRIORITY | HOUR_MICROSECOND |
HOUR_MINUTE | HOUR_SECOND | IF |
IGNORE | IN | INDEX |
INFILE | INNER | INOUT |
INSENSITIVE | INSERT | INT |
INT1 | INT2 | INT3 |
INT4 | INT8 | INTEGER |
INTERVAL | INTO | IS |
ITERATE | JOIN | KEY |
KEYS | KILL | LEADING |
LEAVE | LEFT | LIKE |
LIMIT | LINEAR | LINES |
LOAD | LOCALTIME | LOCALTIMESTAMP |
LOCK | LONG | LONGBLOB |
LONGTEXT | LOOP | LOW_PRIORITY |
MATCH | MEDIUMBLOB | MEDIUMINT |
MEDIUMTEXT | MIDDLEINT | MINUTE_MICROSECOND |
MINUTE_SECOND | MOD | MODIFIES |
NATURAL | NOT | NO_WRITE_TO_BINLOG |
NULL | NUMERIC | ON |
OPTIMIZE | OPTION | OPTIONALLY |
OR | ORDER | OUT |
OUTER | OUTFILE | PRECISION |
PRIMARY | PROCEDURE | PURGE |
RANGE | READ | READS |
READ_ONLY | READ_WRITE | REAL |
REFERENCES | REGEXP | RELEASE |
RENAME | REPEAT | REPLACE |
REQUIRE | RESTRICT | RETURN |
REVOKE | RIGHT | RLIKE |
SCHEMA | SCHEMAS | SECOND_MICROSECOND |
SELECT | SENSITIVE | SEPARATOR |
SET | SHOW | SMALLINT |
SPATIAL | SPECIFIC | SQL |
SQLEXCEPTION | SQLSTATE | SQLWARNING |
SQL_BIG_RESULT | SQL_CALC_FOUND_ROWS | SQL_SMALL_RESULT |
SSL | STARTING | STRAIGHT_JOIN |
TABLE | TERMINATED | THEN |
TINYBLOB | TINYINT | TINYTEXT |
TO | TRAILING | TRIGGER |
TRUE | UNDO | UNION |
UNIQUE | UNLOCK | UNSIGNED |
UPDATE | USAGE | USE |
USING | UTC_DATE | UTC_TIME |
UTC_TIMESTAMP | VALUES | VARBINARY |
VARCHAR | VARCHARACTER | VARYING |
WHEN | WHERE | WHILE |
WITH | WRITE | X509 |
XOR | YEAR_MONTH | ZEROFILL |
Folgende reservierte Wörter sind neu in MySQL 5.1:
LINEAR
, RANGE
.
MySQL gestattet auch die Verwendung bestimmter Schlüsselwörter als Bezeichner ohne Anführungszeichen, da viele Benutzer sie in der Vergangenheit bereits eingesetzt haben. Beispiele entnehmen Sie der folgenden Liste:
ACTION
BIT
DATE
ENUM
NO
TEXT
TIME
TIMESTAMP
Inhaltsverzeichnis
COLLATE
in SQL-AnweisungenCOLLATE
-KlauselnBINARY
-Operator
MySQL enthält eine Zeichensatzunterstützung, mit deren Hilfe Sie
Daten mit einer Vielzahl von Zeichensätzen speichern und Vergleiche
auf der Basis einer Vielzahl von Sortierfolgen durchführen können.
Sie können Zeichensätze auf der Server-, der Datenbank-, der
Tabellen- und der Spaltenebene angeben. MySQL unterstützt die
Verwendung von Zeichensätzen für die Speicher-Engines
MyISAM
, MEMORY
,
NDBCluster
und InnoDB
.
Dieses Kapitel behandelt die folgenden Themen:
Was sind Zeichensätze und Sortierfolgen?
Standardzeichensatzsystem auf mehreren Ebenen
Syntax zur Angabe von Zeichensätzen und Sortierfolgen
Betroffene Funktionen und Operationen
Unicode-Unterstützung
Verfügbare Zeichensätze und Sortierfolgen einschließlich entsprechender Anmerkungen
Zeichensatzbezogene Aspekte wirken sich auf die Datenspeicherung,
aber auch auf die Kommunikation zwischen Clientprogrammen und dem
MySQL Server aus. Wenn Sie wollen, dass das Clientprogramm mit dem
Server unter Verwendung eines Zeichensatzes kommuniziert, der sich
vom Standardzeichensatz unterscheidet, dann müssen Sie angeben,
welcher Zeichensatz verwendet werden soll. Um beispielsweise den
utf8
-Unicode-Zeichensatz zu verwenden, setzen Sie
nach der Herstellung einer Serververbindung folgende Anweisung ab:
SET NAMES 'utf8';
Weitere Informationen zu zeichensatzbezogenen Fragen in der Client/Server-Kommunikation finden Sie in Abschnitt 10.4, „Verbindungszeichensatz und -sortierfolge“.
Ein Zeichensatz ist eine Menge mit Symbolen und Kodierungen. Eine Sortierfolge ist ein Regelsatz für den Vergleich von Zeichen in einem Zeichensatz. Folgendes Beispiel, welches einen imaginären Zeichensatz verwendet, soll den Unterschied verdeutlichen.
Angenommen, wir haben ein Alphabet mit vier Buchstaben:
‘A
’,
‘B
’,
‘a
’,
‘b
’. Jedem Buchstaben weisen wir
nun eine Zahl zu: ‘A
’ = 0,
‘B
’ = 1,
‘a
’ = 2,
‘b
’ = 3. Der Buchstabe
‘A
’ ist ein Symbol, die Zahl 0 die
Kodierung für
‘A
’. Die Kombination aller vier
Buchstaben und ihrer Kodierungen bildet den
Zeichensatz.
Angenommen, wir wollen zwei String-Werte
‘A
’ und
‘B
’ miteinander vergleichen. Die
einfachste Möglichkeit, dies zu tun, besteht in einem Blick auf
die Kodierungen: 0 für ‘A
’ und 1
für ‘B
’. Da 0 kleiner als 1 ist,
sagen wir, dass ‘A
’ kleiner als
‘B
’ ist. Was wir gerade getan
haben, war die Anwendung einer Sortierfolge für unseren
Zeichensatz. Die Sortierfolge ist eine Menge von Regeln – wenn
auch in diesem Fall nur eine Regel: „Vergleiche die
Kodierungen“. Diese einfachste aller möglichen
Sortierfolgen nennen wir Binärsortierung.
Was aber, wenn wir ausdrücken wollen, dass Klein- und
Großbuchstaben äquivalent sind? Dann hätten wir schon zwei
Regeln: (1) Betrachte die Kleinbuchstaben
‘a
’ und
‘b
’ als äquivalent zu den
entsprechenden Großbuchstaben ‘A
’
und ‘B
’. (2) Vergleiche die
Kodierungen. Dies ist eine Sortierfolge ohne
Unterscheidung der Groß-/Kleinschreibung. Sie ist ein
kleines bisschen komplexer als eine Binärsortierung.
Im wirklichen Leben umfassen die meisten Zeichensätze viele
Zeichen: nicht nur ‘A
’ und
‘B
’, sondern ganze Alphabete –
manchmal sogar mehrere Alphabete oder fernöstliche Schreibsysteme
mit Tausenden von Zeichen – sowie viele Sonder- und
Interpunktionszeichen. Auch für Sortierfolgen gibt es im
wirklichen Leben viele Regeln, die nicht nur die Behandlung der
Groß-/Kleinschreibung angeben, sondern auch, ob Akzente und
Tremata (die Punkte etwa auf den deutschen Umlauten Ä, Ö und Ü)
unterschieden und wie Folgen aus mehreren Zeichen zugeordnet
werden (beispielsweise die Regel, dass bei einer der beiden
deutschen Sortierfolgen die Gleichung
‘Ö
’ =
‘OE
’ gilt).
MySQL erlaubt Ihnen
das Speichern von Strings in einer Vielzahl von Zeichensätzen,
das Vergleichen von Strings unter Verwendung einer Vielzahl von Sortierfolgen,
das Mischen von Strings verschiedener Zeichensätze oder Sortierfolgen auf demselben Server, in derselben Datenbank oder sogar derselben Tabelle,
die Angabe von Zeichensatz und Sortierfolge auf beliebiger Ebene.
In dieser Hinsicht ist MySQL den meisten anderen Datenbanksystemen weit überlegen. Allerdings müssen Sie, um diese Funktionen effizient nutzen zu können, wissen, welche Zeichensätze und Sortierfolgen verfügbar sind, wie Sie die Standardeinstellungen ändern und wie diese das Verhalten von String-Operatoren und -Funktionen beeinflussen.
Der MySQL Server kann viele Zeichensätze unterstützen. Um die
verfügbaren Zeichensätze aufzulisten, verwenden Sie die
Anweisung SHOW CHARACTER SET
. Nachfolgend ist
eine Teilausgabe abgebildet. Umfassendere Informationen finden Sie
in Abschnitt 10.9, „Zeichensätze und Sortierfolgen, die MySQL unterstützt“.
mysql> SHOW CHARACTER SET;
+----------+-----------------------------+---------------------+--------+
| Charset | Description | Default collation | Maxlen |
+----------+-----------------------------+---------------------+--------+
| big5 | Big5 Traditional Chinese | big5_chinese_ci | 2 |
| dec8 | DEC West European | dec8_swedish_ci | 1 |
| cp850 | DOS West European | cp850_general_ci | 1 |
| hp8 | HP West European | hp8_english_ci | 1 |
| koi8r | KOI8-R Relcom Russian | koi8r_general_ci | 1 |
| latin1 | cp1252 West European | latin1_swedish_ci | 1 |
| latin2 | ISO 8859-2 Central European | latin2_general_ci | 1 |
| swe7 | 7bit Swedish | swe7_swedish_ci | 1 |
| ascii | US ASCII | ascii_general_ci | 1 |
| ujis | EUC-JP Japanese | ujis_japanese_ci | 3 |
| sjis | Shift-JIS Japanese | sjis_japanese_ci | 2 |
| hebrew | ISO 8859-8 Hebrew | hebrew_general_ci | 1 |
| tis620 | TIS620 Thai | tis620_thai_ci | 1 |
| euckr | EUC-KR Korean | euckr_korean_ci | 2 |
| koi8u | KOI8-U Ukrainian | koi8u_general_ci | 1 |
| gb2312 | GB2312 Simplified Chinese | gb2312_chinese_ci | 2 |
| greek | ISO 8859-7 Greek | greek_general_ci | 1 |
| cp1250 | Windows Central European | cp1250_general_ci | 1 |
| gbk | GBK Simplified Chinese | gbk_chinese_ci | 2 |
| latin5 | ISO 8859-9 Turkish | latin5_turkish_ci | 1 |
...
Ein gegebener Zeichensatz hat stets mindestens eine Sortierfolge.
Es können aber auch mehrere sein. Um die verfügbaren
Sortierfolgen eines Zeichensatzes aufzulisten, verwenden Sie die
Anweisung SHOW COLLATION
. Um etwa die
Sortierfolgen für den Zeichensatz latin1
(cp1252, westeuropäisch) aufzulisten, suchen Sie mit der
folgenden Anweisung die Sortierfolgennamen, die mit
latin1
beginnen:
mysql> SHOW COLLATION LIKE 'latin1%';
+---------------------+---------+----+---------+----------+---------+
| Collation | Charset | Id | Default | Compiled | Sortlen |
+---------------------+---------+----+---------+----------+---------+
| latin1_german1_ci | latin1 | 5 | | | 0 |
| latin1_swedish_ci | latin1 | 8 | Yes | Yes | 1 |
| latin1_danish_ci | latin1 | 15 | | | 0 |
| latin1_german2_ci | latin1 | 31 | | Yes | 2 |
| latin1_bin | latin1 | 47 | | Yes | 1 |
| latin1_general_ci | latin1 | 48 | | | 0 |
| latin1_general_cs | latin1 | 49 | | | 0 |
| latin1_spanish_ci | latin1 | 94 | | | 0 |
+---------------------+---------+----+---------+----------+---------+
Die latin1
-Sortierfolgen haben die nachfolgend
beschriebenen Bedeutungen:
Sortierfolge | Bedeutung |
latin1_german1_ci | Deutsch, DIN-1 |
latin1_swedish_ci | Schwedisch/Finnisch |
latin1_danish_ci | Dänisch/Norwegisch |
latin1_german2_ci | Deutsch, DIN-2 |
latin1_bin | Binärsortierung nach latin1 -Kodierung |
latin1_general_ci | Mehrsprachig (westeuropäisch) |
latin1_general_cs | Mehrsprachig (ISO, westeuropäisch), Unterscheidung der Groß-/Kleinschreibung |
latin1_spanish_ci | Modernes Spanisch |
Sortierfolgen haben die folgenden Eigenschaften:
Zwei verschiedene Zeichensätze können nicht dieselbe Sortierfolge aufweisen.
Jeder Zeichensatz hat genau eine Sortierfolge, die die
Standardsortierfolge ist. So ist die
Standardsortierfolge für latin1
beispielsweise latin1_swedish_ci
. Die
Ausgabe von SHOW CHARACTER SET
zeigt an,
welche Sortierfolgen standardmäßig für die angezeigten
Zeichensätze verwendet werden.
Für Sortierfolgennamen gibt es eine Konvention: Sie beginnen
mit dem Namen des Zeichensatzes, mit dem sie verknüpft sind,
enthalten in der Regel den Namen der betreffenden Sprache und
enden auf _ci
(keine Unterscheidung der
Groß-/Kleinschreibung), _cs
(Unterscheidung der Groß-/Kleinschreibung) oder
_bin
(Binärsortierung).
Standardeinstellungen für Zeichensätze und Sortierfolgen gibt es auf vier Ebenen, nämlich der Server-, der Datenbank-, der Tabellen- und der Spaltenebene. Die folgende Beschreibung mag komplex erscheinen, es hat sich aber in der Praxis gezeigt, dass Standardeinstellungen auf mehreren Ebenen zu natürlichen und offensichtlichen Ergebnissen führen.
CHARACTER SET
wird in Klauseln verwendet, die
einen Zeichensatz angeben. CHARSET
kann als
Synonym von CHARACTER SET
benutzt werden.
MySQL Server bietet einen Serverzeichensatz und eine Serversortierfolge. Diese können beim Serverstart eingestellt und zur Laufzeit geändert werden.
Anfangs hängen Zeichensatz und Sortierfolge des Servers von den
Optionen ab, die Sie beim Start von mysqld
verwenden. Sie können --character-set-server
für den Zeichensatz benutzen. Daneben können Sie
--collation-server
hinzufügen, um die
Sortierfolge anzugeben. Wenn Sie keinen Zeichensatz bestimmen,
entspricht dies der Festlegung
--character-set-server=latin1
. Geben Sie nur
einen Zeichensatz (z. B. latin1
), aber keine
Sortierfolge an, dann entspricht dies der Festlegung
--character-set-server=latin1
--collation-server=latin1_swedish_ci
, weil
latin1_swedish_ci
die Standardsortierfolge
für latin1
ist. Aus diesem Grund haben die
folgenden drei Befehle dieselben Auswirkungen:
shell>mysqld
shell>mysqld --character-set-server=latin1
shell>mysqld --character-set-server=latin1 \
--collation-server=latin1_swedish_ci
Eine Möglichkeit, die Einstellungen zu ändern, ist eine
Neukompilierung. Wenn Sie die Vorgaben für Zeichensatz und
Sortierfolge beim Erstellen aus dem Quellcode ändern wollen,
verwenden Sie --with-charset
und
--with-collation
als Argumente für
configure. Zum Beispiel:
shell> ./configure --with-charset=latin1
Oder:
shell>./configure --with-charset=latin1 \
--with-collation=latin1_german1_ci
Sowohl mysqld als auch configure stellen sicher, dass die Kombination aus Zeichensatz und Sortierfolge gültig ist. Andernfalls zeigt jedes Programm eine Fehlermeldung an und wird dann beendet.
Die aktuellen Werte für Zeichensatz und Sortierfolge können
den Systemvariablen character_set_server
und
collation_server
entnommen werden. Diese
Variablen lassen sich zur Laufzeit ändern.
Jede Datenbank hat einen datenbankspezifischen Zeichensatz und
eine Datenbanksortierfolge. Die Anweisungen CREATE
DATABASE
und ALTER DATABASE
bieten
optionale Klauseln zur Angabe von Zeichensatz und Sortierfolge:
CREATE DATABASEdb_name
[[DEFAULT] CHARACTER SETcharset_name
] [[DEFAULT] COLLATEcollation_name
] ALTER DATABASEdb_name
[[DEFAULT] CHARACTER SETcharset_name
] [[DEFAULT] COLLATEcollation_name
]
Statt DATABASE
kann auch das Schlüsselwort
SCHEMA
verwendet werden.
Alle Datenbankoptionen werden in einer Textdatei namens
db.opt
gespeichert, die sich im
Datenbankverzeichnis befindet.
Die Klauseln CHARACTER SET
und
COLLATE
ermöglichen die Erstellung von
Datenbanken mit unterschiedlichen Zeichensätzen und
Sortierfolgen auf demselben MySQL Server.
Beispiel:
CREATE DATABASE db_name
CHARACTER SET latin1 COLLATE latin1_swedish_ci;
MySQL wählt Zeichensatz und Sortierfolge für die Datenbank auf folgende Weise:
Wenn sowohl CHARACTER SET
als auch
X
COLLATE
angegeben werden, dann werden der Zeichensatz
Y
X
und die Sortierfolge
Y
eingestellt.
Wenn CHARACTER SET
ohne
X
COLLATE
angegeben wird, dann wird der
Zeichensatz X
mit seiner
Standardsortierfolge eingestellt.
Wenn COLLATE
ohne Y
CHARACTER SET
angegeben wird, dann
wird der mit Y
verknüpfte
Zeichensatz mit der Sortierfolge
Y
eingestellt.
Andernfalls werden die Standardwerte für Zeichensatz und Sortierfolge eingestellt.
Datenbankzeichensatz und -sortierfolge werden als Standardwerte
verwendet, wenn Zeichensatz und Sortierfolge für die Tabelle
nicht in CREATE TABLE
-Anweisungen angegeben
werden. Einen anderen Zweck haben sie nicht.
Die Werte für Zeichensatz und Sortierfolge der
Standarddatenbank können den Systemvariablen
character_set_database
und
collation_database
entnommen werden. Der
Server stellt diese Variablen immer dann ein, wenn die
Standarddatenbank sich ändert. Ist keine Standarddatenbank
vorhanden, dann haben die Variablen denselben Wert wie die
entsprechenden Systemvariablen für die Serverebene
(character_set_server
und
collation_server
).
Jede Tabelle hat einen tabellenspezifischen Zeichensatz und eine
Tabellensortierfolge. Die Anweisungen CREATE
TABLE
und ALTER TABLE
bieten
optionale Klauseln zur Angabe von Zeichensatz und Sortierfolge:
CREATE TABLEtbl_name
(column_list
) [[DEFAULT] CHARACTER SETcharset_name
] [COLLATEcollation_name
]] ALTER TABLEtbl_name
[[DEFAULT] CHARACTER SETcharset_name
] [COLLATEcollation_name
]
Beispiel:
CREATE TABLE t1 ( ... ) CHARACTER SET latin1 COLLATE latin1_danish_ci;
MySQL wählt Zeichensatz und Sortierfolge für die Tabelle auf folgende Weise:
Wenn sowohl CHARACTER SET
als auch
X
COLLATE
angegeben werden, dann werden der Zeichensatz
Y
X
und die Sortierfolge
Y
eingestellt.
Wenn CHARACTER SET
ohne
X
COLLATE
angegeben wird, dann wird der
Zeichensatz X
mit seiner
Standardsortierfolge eingestellt.
Wenn COLLATE
ohne Y
CHARACTER SET
angegeben wird, dann
wird der mit Y
verknüpfte
Zeichensatz mit der Sortierfolge
Y
eingestellt.
Andernfalls werden die datenbankspezifischen Standardwerte für Zeichensatz und Sortierfolge eingestellt.
Tabellenzeichensatz und -sortierfolge werden als Standardwerte verwendet, wenn Zeichensatz und Sortierfolge in den Definitionen einzelner Spalten nicht angegeben sind. Tabellenzeichensatz und -sortierfolge sind MySQL-Erweiterungen, die es im SQL-Standard nicht gibt.
Jede „Zeichenspalte“ (d. h. eine Spalte des Typs
CHAR
, VARCHAR
oder
TEXT
) hat einen Spaltenzeichensatz und eine
Spaltensortierfolge. Die Spaltendefinitionssyntax bietet
optionale Klauseln zur Angabe von Spaltenzeichensatz und
-sortierfolge:
col_name
{CHAR | VARCHAR | TEXT} (col_length
) [CHARACTER SETcharset_name
[COLLATEcollation_name
]]
Beispiel:
CREATE TABLE Table1 ( column1 VARCHAR(5) CHARACTER SET latin1 COLLATE latin1_german1_ci );
MySQL wählt Zeichensatz und Sortierfolge für eine Spalte auf folgende Weise:
Wenn sowohl CHARACTER SET
als auch
X
COLLATE
angegeben werden, dann werden der Zeichensatz
Y
X
und die Sortierfolge
Y
eingestellt.
Wenn CHARACTER SET
ohne
X
COLLATE
angegeben wird, dann wird der
Zeichensatz X
mit seiner
Standardsortierfolge eingestellt.
Wenn COLLATE
ohne Y
CHARACTER SET
angegeben wird, dann
wird der mit Y
verknüpfte
Zeichensatz mit der Sortierfolge
Y
eingestellt.
Andernfalls werden die tabellenspezifischen Standardwerte für Zeichensatz und Sortierfolge eingestellt.
Die Klauseln CHARACTER SET
und
COLLATE
entsprechen dem SQL-Standard.
Jeder Zeichen-String-Literal hat einen Zeichensatz und eine Sortierfolge.
Ein String-Literal weist unter Umständen eine optionale
Zeichensatzeinführung und eine
COLLATE
-Klausel auf:
[_charset_name
]'string
' [COLLATEcollation_name
]
Ein paar Beispiele:
SELECT 'string
'; SELECT _latin1'string
'; SELECT _latin1'string
' COLLATE latin1_danish_ci;
Für die einfache Anweisung SELECT
'
werden Zeichensatz
und Sortierfolge des Strings definiert von den Systemvariablen
string
'character_set_connection
und
collation_connection
.
Der Ausdruck
_
heißt formal Einführung. Die Einführung
zeigt dem Parser an, dass der nachfolgende String den
Zeichensatz charset_name
X
verwendet. Da dies in
der Vergangenheit zu Verwirrung bei Benutzern geführt hat,
wollen wir an dieser Stelle betonen, dass eine Einführung keine
Konvertierung zur Folge hat – es handelt sich lediglich um ein
Signal, das den Wert des Strings nicht ändert. Eine Einführung
ist auch zulässig vor der standardmäßigen und der numerischen
hexadezimalen Literalnotation
(x'
bzw.
literal
'0x
) sowie vor
nnnn
?
(Parameterersetzung bei der Verwendung
vorbereiteter Anweisungen innerhalb einer
Programmiersprachen-Schnittstelle).
Ein paar Beispiele:
SELECT _latin1 x'AABBCC'; SELECT _latin1 0xAABBCC; SELECT _latin1 ?;
MySQL wählt Zeichensatz und Sortierfolge eines Literals auf folgende Weise:
Wenn sowohl _X
als auch
COLLATE
angegeben werden, dann werden der Zeichensatz
Y
X
und die Sortierfolge
Y
eingestellt.
Wenn _X
angegeben ist,
COLLATE
aber nicht, dann wird der
Zeichensatz X
mit der
Standardsortierfolge verwendet.
Andernfalls werden als Zeichensatz und Sortierfolge die
Werte der Systemvariablen
character_set_connection
bzw.
collation_connection
gesetzt.
Ein paar Beispiele:
Ein String mit dem Zeichensatz latin1
und
der Sortierfolge latin1_german1_ci
:
SELECT _latin1'Müller' COLLATE latin1_german1_ci;
Ein String mit dem Zeichensatz latin1
und
der Standardsortierfolge
(latin1_swedish_ci
):
SELECT _latin1'Müller';
Ein String mit Standardzeichensatz und -sortierfolge der Verbindung:
SELECT 'Müller';
Zeichensatzeinführungen und die
COLLATE
-Klausel sind entsprechend den
Spezifikationen des SQL-Standards implementiert.
Der SQL-Standard definiert NCHAR
oder
NATIONAL CHAR
als Möglichkeit, anzugeben,
dass eine CHAR
-Spalte einen bestimmten
vordefinierten Zeichensatz verwenden soll. MySQL
5.1 verwendet utf8
als
vordefinierten Zeichensatz. So sind beispielsweise die folgenden
Datentypdeklarationen gleichwertig:
CHAR(10) CHARACTER SET utf8 NATIONAL CHARACTER(10) NCHAR(10)
Gleiches gilt für die folgenden:
VARCHAR(10) CHARACTER SET utf8 NATIONAL VARCHAR(10) NCHAR VARCHAR(10) NATIONAL CHARACTER VARYING(10) NATIONAL CHAR VARYING(10)
Sie können mit
N'
einen
String im Nationalzeichensatz erstellen. Die folgenden beiden
Anweisungen sind äquivalent:
literal
'
SELECT N'some text'; SELECT _utf8'some text';
Informationen zur Aktualisierung von Zeichensätzen auf MySQL 5.1 von Versionen vor 4.1 finden Sie im MySQL-Referenzhandbuch für die Versionen 3.23, 4.0 und 4.1.
Die folgenden Beispiele zeigen, wie MySQL die Standardwerte für den Zeichensatz und die Sortierfolge ermittelt.
Beispiel 1: Tabellen- und Spaltendefinition
CREATE TABLE t1 ( c1 CHAR(10) CHARACTER SET latin1 COLLATE latin1_german1_ci ) DEFAULT CHARACTER SET latin2 COLLATE latin2_bin;
Hier haben wir eine Spalte mit dem Zeichensatz
latin1
und der Sortierfolge
latin1_german1_ci
. Die Definition ist
explizit, d. h., die Werte ergeben sich von selbst. Beachten
Sie, dass das Speichern einer latin1
-Spalte
in einer latin2
-Tabelle unproblematisch ist.
Beispiel 2: Tabellen- und Spaltendefinition
CREATE TABLE t1 ( c1 CHAR(10) CHARACTER SET latin1 ) DEFAULT CHARACTER SET latin1 COLLATE latin1_danish_ci;
Hier nun haben wir eine Spalte mit dem Zeichensatz
latin1
und der Standardsortierfolge. Obwohl
es naheliegend erscheint, wird die Standardsortierfolge nicht
von der Tabellenebene übernommen. Stattdessen hat, weil die
Standardsortierfolge von latin1
immer
latin1_swedish_ci
ist, die Spalte
c1
die Sortierfolge
latin1_swedish_ci
(und nicht
latin1_danish_ci
).
Beispiel 3: Tabellen- und Spaltendefinition
CREATE TABLE t1 ( c1 CHAR(10) ) DEFAULT CHARACTER SET latin1 COLLATE latin1_danish_ci;
Hier haben wir eine Spalte mit den Standardwerten für
Zeichensatz und Sortierfolge. Unter diesen Umständen bestimmt
MySQL anhand der Angaben auf der Tabellenebene den Zeichensatz
und die Sortierfolge für die Spalte. Es ergibt sich, dass der
Zeichensatz latin1
und die zugehörige
Sortierfolge latin1_danish_ci
für die Spalte
c1
eingestellt werden.
Beispiel 4: Datenbank-, Tabellen- und Spaltendefinition
CREATE DATABASE d1 DEFAULT CHARACTER SET latin2 COLLATE latin2_czech_ci; USE d1; CREATE TABLE t1 ( c1 CHAR(10) );
Wir erstellen eine Spalte ohne Angabe von Zeichensatz und
Sortierfolge. Ebenso wenig geben wir einen Zeichensatz und eine
Sortierfolge auf der Tabellenebene an. Unter diesen Umständen
überprüft MySQL die Datenbankebene, um die
Tabelleneinstellungen zu ermitteln, die daraufhin auch zu den
Spalteneinstellungen werden. Es ergibt sich, dass der
Zeichensatz latin2
und die zugehörige
Sortierfolge latin2_czech_ci
für die Spalte
c1
eingestellt werden.
Verschiedene Systemvariablen zu Zeichensätzen und Sortierfolgen sind spezifisch für die Interaktion eines Clients mit dem Server. Einige dieser Variablen wurden bereits in früheren Abschnitten erwähnt:
Die Werte für Zeichensatz und Sortierfolge können den
Systemvariablen character_set_server
und
collation_server
entnommen werden.
Die Werte für Zeichensatz und Sortierfolge der
Standarddatenbank können den Systemvariablen
character_set_database
und
collation_database
entnommen werden.
Weitere Systemvariablen zu Zeichensätzen und Sortierfolgen betreffen die Handhabung der Daten einer Verbindung zwischen einem Client und dem Server. Jeder Client hat verbindungsspezifische Systemvariablen für Zeichensatz und Sortierfolge.
Sehen wir uns doch einmal an, was eine „Verbindung“ ist: Sie stellen eine solche her, wenn Sie sich mit dem Server verbinden. Der Client sendet SQL-Anweisungen wie etwa Abfragen über die Verbindung an den Server. Der Server beantwortet diese, indem er beispielsweise Ergebnismengen über die Verbindung an den Client zurückschickt. Dies wirft eine Reihe von Fragen zum Umgang mit Zeichensatz und Sortierfolge bei Clientverbindungen auf, die sich aber alle auf der Basis von Systemvariablen beantworten lassen:
Welchen Zeichensatz verwendet eine Anweisung, wenn sie den Client verlässt?
Der Server entnimmt der Systemvariablen
character_set_client
den Zeichensatz, in
dem sich vom Client gesendete Anweisungen befinden.
In welchen Zeichensatz sollte der Server eine Anweisung übersetzen, nachdem er sie erhalten hat?
Hierzu verwendet der Server die Systemvariablen
character_set_connection
und
collation_connection
. Er wandelt die
Anweisungen, die vom Client gesendet wurden, aus
character_set_client
in
character_set_connection
um (ausgenommen
hiervon sind String-Literale, die eine Einführung wie
_latin1
oder _utf8
aufweisen). collation_connection
ist
wichtig für Vergleiche literaler Strings. Für Vergleiche von
Strings mit Spaltenwerten ist
collation_connection
hingegen unerheblich,
da Spalten eine eigene Sortierfolge haben, die in diesem Fall
Vorrang hat.
In welchen Zeichensatz soll der Server übersetzen, bevor er Ergebnismengen oder Fehlermeldungen an den Client zurückschickt?
Die Systemvariable character_set_results
gibt den Zeichensatz an, in dem der Server Abfrageergebnisse
an den Client zurückgibt. Hierzu gehören Ergebnisdaten wie
etwa Spaltenwerte und ergebnisbezogene Metadaten wie
beispielsweise Spaltennamen.
Sie können die Einstellungen dieser Variablen optimieren oder einfach die Standardeinstellungen verwenden.
Es gibt zwei Anweisungen, die sich auf die Zeichensätze einer Verbindung auswirken:
SET NAMES 'charset_name
' SET CHARACTER SETcharset_name
SET NAMES
gibt an, welchen Zeichensatz der
Client zum Versand von SQL-Anweisungen an den Server verwendet.
SET NAMES 'cp1251'
bedeutet mithin: „Ab
jetzt haben von diesem Client eingehende Nachrichten den
Zeichensatz cp1251
“. Außerdem gibt die
Anweisung den Zeichensatz an, den der Server zum Zurücksenden der
Ergebnisse an den Client verwenden soll. (Beispielsweise legt er
fest, welcher Zeichensatz für Spaltenwerte benutzt werden soll,
wenn Sie eine SELECT
-Anweisung absetzen.)
Eine SET NAMES
'
-Anweisung ist äquivalent
zu den folgenden drei Anweisungen:
x
'
SET character_set_client =x
; SET character_set_results =x
; SET character_set_connection =x
;
Das Einstellen von character_set_connection
auf
x
setzt
collation_connection
auf die
Standardsortierfolge für x
.
SET CHARACTER SET
ähnelt SET
NAMES
, setzt Zeichensatz und Sortierfolge der Verbindung
aber auf die Werte der Datenbank. Eine SET CHARACTER SET
-Anweisung ist äquivalent
zu den folgenden drei Anweisungen:
x
SET character_set_client =x
; SET character_set_results =x
; SET collation_connection = @@collation_database;
Wenn Sie collation_connection
einstellen,
setzen Sie damit gleichzeitig
character_set_connection
auf den Zeichensatz,
der mit dieser Sortierfolge verknüpft ist.
Wenn ein Client eine Verbindung herstellt, sendet er den Namen des
Zeichensatzes, den er verwenden will, an den Server. Der Server
stellt auf der Basis dieses Namens die Systemvariablen
character_set_client
,
character_set_results
und
character_set_connection
ein. Im Endeffekt
führt der Server eine SET NAMES
-Operation
unter Verwendung des Zeichensatznamens aus.
Beim mysql-Client ist die Ausführung von
SET NAMES
bei jedem Systemstart nicht
notwendig, wenn Sie einen anderen als den Standardzeichensatz
verwenden wollen. Fügen Sie der
mysql-Anweisungszeile oder Ihrer Optionsdatei
einfach die Option --default-character-set
hinzu.
Die folgende Option beispielsweise setzt die drei
Zeichensatzvariablen bei jedem Aufruf von mysql
auf koi8r
:
[mysql] default-character-set=koi8r
Beispiel: Nehmen wir an, column1
sei als
CHAR(5) CHARACTER SET latin2
definiert. Wenn
Sie SET NAMES
oder SET CHARACTER
SET
nicht angeben, dann sendet der Server bei
SELECT column1 FROM t
alle Werte für
column1
zurück und verwendet dazu den
Zeichensatz, den der Client bei der Verbindungsherstellung
angegeben hat. Im Gegensatz dazu konvertiert, wenn Sie
SET NAMES 'latin1'
oder SET CHARACTER
SET latin1
vor dem Absetzen der
SELECT
-Anweisung angeben, der Server die
latin2
-Werte in latin1
,
bevor er die Ergebnisse zurückschickt. Die Konvertierung kann
verlustbehaftet sein, wenn Zeichen verwendet werden, die nicht in
beiden Zeichensätzen vorhanden sind.
Wenn Sie nicht wollen, dass der Server Ergebnismengen konvertiert,
dann setzen Sie character_set_results
auf
NULL
:
SET character_set_results = NULL;
Hinweis: Derzeit kann UCS-2 nicht
als Clientzeichensatz verwendet werden, d. h., SET NAMES
'ucs2'
funktioniert nicht.
Um die Werte der Zeichensatz- und Sortierfolgevariablen anzuzeigen, die für Ihre Verbindung gelten, verwenden Sie die folgenden Anweisungen:
SHOW VARIABLES LIKE 'character_set%'; SHOW VARIABLES LIKE 'collation%';
COLLATE
in SQL-AnweisungenCOLLATE
-KlauselnBINARY
-OperatorDie folgenden Abschnitte beschreiben verschiedene Aspekte der Sortierfolgen bei Zeichensätzen.
Mit der COLLATE
-Klausel können Sie die
Standardsortierfolge für einen Vergleich außer Kraft setzen.
COLLATE
kann in verschiedenen Teilen von
SQL-Anweisungen verwendet werden. Hier ein paar Beispiele:
Bei ORDER BY
:
SELECT k FROM t1 ORDER BY k COLLATE latin1_german2_ci;
Bei AS
:
SELECT k COLLATE latin1_german2_ci AS k1 FROM t1 ORDER BY k1;
Bei GROUP BY
:
SELECT k FROM t1 GROUP BY k COLLATE latin1_german2_ci;
Bei Zusammenfassungsfunktionen:
SELECT MAX(k COLLATE latin1_german2_ci) FROM t1;
Bei DISTINCT
:
SELECT DISTINCT k COLLATE latin1_german2_ci FROM t1;
Bei WHERE
:
SELECT * FROM t1 WHERE _latin1 'Müller' COLLATE latin1_german2_ci = k;
SELECT * FROM t1 WHERE k LIKE _latin1 'Müller' COLLATE latin1_german2_ci;
Bei HAVING
:
SELECT k FROM t1 GROUP BY k HAVING k = _latin1 'Müller' COLLATE latin1_german2_ci;
Die COLLATE
-Klausel hat eine hohe Priorität
(höher als ||
), d. h., die folgenden beiden
Ausdrücke sind äquivalent:
x || y COLLATE z x || (y COLLATE z)
Der Operator BINARY
wandelt den ihm
nachfolgenden String in einen Binär-String um. Dies ist eine
einfache Möglichkeit, einen Spaltenvergleich byte- statt
zeichenweise durchzuführen. BINARY
berücksichtigt auch am Ende stehende Leerzeichen.
mysql>SELECT 'a' = 'A';
-> 1 mysql>SELECT BINARY 'a' = 'A';
-> 0 mysql>SELECT 'a' = 'a ';
-> 1 mysql>SELECT BINARY 'a' = 'a ';
-> 0
BINARY
ist
eine Abkürzung für
str
CAST(
.
str
AS
BINARY)
Das Attribut BINARY
in
Zeichenspaltendefinitionen hat einen anderen Effekt. Einer
Zeichenspalte, die mit dem Attribut BINARY
definiert ist, wird die Binärsortierung des Zeichensatzes der
Spalte zugewiesen. Jeder Zeichensatz hat eine
Binärsortierfolge. So heißt etwa die Binärsortierung des
Zeichensatzes latin1
latin1_bin
. Wenn also der Standardzeichensatz
der Tabelle latin1
ist, dann sind die
folgenden beiden Definitionen äquivalent:
CHAR(10) BINARY CHAR(10) CHARACTER SET latin1 COLLATE latin1_bin
Der Effekt von BINARY
als Spaltenattribut
unterscheidet sich von dessen Wirkungsweise vor MySQL 4.1.
Ursprünglich führte BINARY
zu einer Spalte,
die als Binär-String behandelt wurde. Ein Binär-String ist ein
String aus Bytes, der weder einen Zeichensatz noch eine
Sortierfolge hat; hierin liegt der Unterschied zu einem
nichtbinären Zeichen-String, der eine Binärsortierung hat. Bei
beiden String-Typen basieren Vergleiche auf den numerischen
Werten der String-Einheit, aber bei nichtbinären Strings ist
die Einheit das Zeichen, und einige Zeichensätze unterstützen
Multibytezeichen. Siehe Abschnitt 11.4.2, „Die BINARY
- und VARBINARY
-Typen“.
Die Verwendung von CHARACTER SET binary
in
der Definition einer CHAR
-,
VARCHAR
- oder TEXT
-Spalte
bewirkt, dass diese als binärer Datentyp behandelt wird. So
sind beispielsweise die folgenden Definitionspaare gleichwertig:
CHAR(10) CHARACTER SET binary BINARY(10) VARCHAR(10) CHARACTER SET binary VARBINARY(10) TEXT CHARACTER SET binary BLOB
Bei der überwiegenden Mehrheit der Anweisungen ist
offensichtlich, welche Sortierfolge MySQL zur Auflösung einer
Vergleichsoperation verwendet. Beispielsweise sollte es in den
folgenden Fällen klar sein, dass die Sortierfolge der Spalte
x
verwendet wird:
SELECT x FROM T ORDER BY x; SELECT x FROM T WHERE x = x; SELECT DISTINCT x FROM T;
Wenn allerdings mehrere Operanden vorhanden sind, kann es zu Mehrdeutigkeiten kommen. Zum Beispiel:
SELECT x FROM T WHERE x = 'Y';
Soll diese Abfrage die Sortierfolge der Spalte
x
oder die des String-Literals
'Y'
verwenden?
Der SQL-Standard löst solche Fragen mithilfe so genannter
„Sortierfolgevorrangsregeln“. Im Grunde genommen
bedeutet dies: Sowohl x
als auch
'Y'
haben Sortierfolgen – welche
Sortierfolge also hat Vorrang? Dies kann schwierig zu lösen
sein, aber die folgenden Regeln sollten die meisten Situationen
abdecken:
Eine explizite COLLATE
-Klausel hat einen
Sortierfolgenvorrangswert von 0 (d. h. gar keinen Vorrang).
Die Verkettung zweier Strings mit verschiedenen Sortierfolgen hat einen Sortierfolgenvorrangswert von 1.
Die Verkettung einer Spalte, eines Parameters einer gespeicherten Routine oder einer lokalen Variablen hat einen Sortierfolgenvorrangswert von 2.
Eine „Systemkonstante“ (d. h. der von
Funktionen wie USER()
oder
VERSION()
zurückgegebene String) hat
einen Sortierfolgenvorrangswert von 3.
Die Sortierfolge eines Literals hat einen Sortierfolgenvorrangswert von 4
NULL
oder ein Ausdruck, der von
NULL
abgeleitet ist, hat einen
Sortierfolgenvorrangswert von 5.
Die genannten Sortierfolgenvorrangswerte gelten für MySQL 5.1.
Diese Regeln lösen Mehrdeutigkeiten wie folgt auf:
Die Sortierfolge mit dem niedrigsten Sortierfolgenvorrangswert wird verwendet.
Weisen beide Seiten hierfür denselben Wert auf, dann wird ein Fehler ausgegeben, wenn die Sortierfolgen nicht identisch sind.
Ein paar Beispiele:
column1 = 'A' | Verwendet die Sortierfolge von column1 |
column1 = 'A' COLLATE x | Verwendet die Sortierfolge von 'A' |
column1 COLLATE x = 'A' COLLATE y | Fehler |
Mithilfe der Funktion COERCIBILITY()
können
Sie den Sortierfolgenvorrangswert eines String-Ausdrucks
bestimmen:
mysql>SELECT COERCIBILITY('A' COLLATE latin1_swedish_ci);
-> 0 mysql>SELECT COERCIBILITY(VERSION());
-> 3 mysql>SELECT COERCIBILITY('A');
-> 4
Siehe auch Abschnitt 12.10.3, „Informationsfunktionen“.
Jeder Zeichensatz hat eine oder mehrere Sortierfolgen, aber jede
Sortierfolge ist nur mit genau einem Zeichensatz verknüpft.
Insofern führt die folgende Anweisung zu einer Fehlermeldung,
weil die Sortierfolge latin2_bin
für den
Zeichensatz latin1
unzulässig ist:
mysql> SELECT _latin1 'x' COLLATE latin2_bin;
ERROR 1253 (42000): COLLATION 'latin2_bin' is not valid
for CHARACTER SET 'latin1'
Angenommen, die Spalte X
in der Tabelle
T
hat die folgenden
latin1
-Spaltenwerte:
Muffler Müller MX Systems MySQL
Nehmen wir nun weiter an, dass die Spaltenwerte mithilfe der folgenden Anweisung abgerufen werden:
SELECT X FROM T ORDER BY X COLLATE collation_name
;
Die folgende Tabelle zeigt die sich ergebende Reihenfolge der
Werte, wenn wir ORDER BY
mit verschiedenen
Sortierfolgen verwenden:
latin1_swedish_ci | latin1_german1_ci | latin1_german2_ci |
Muffler | Muffler | Müller |
MX Systems | Müller | Muffler |
Müller | MX Systems | MX Systems |
MySQL | MySQL | MySQL |
Das Zeichen, welches in diesem Fall die verschiedenen
Sortierfolgen bewirkt, ist der deutsche Umlaut
ü
.
Die erste Spalte zeigt das Ergebnis von
SELECT
unter Verwendung der
schwedisch-finnischen Sortierfolgenregel, die besagt, dass
Ü bei Y einsortiert wird.
Die zweite Spalte zeigt das Ergebnis von
SELECT
unter Verwendung der deutschen
Regel DIN-1, die besagt, dass Ü bei U einsortiert wird.
Die dritte Spalte zeigt das Ergebnis von
SELECT
unter Verwendung der deutschen
Regel DIN-2, die besagt, dass Ü bei UE einsortiert wird.
Dieser Abschnitt beschreibt Operationen, die Zeichensatzinformationen berücksichtigen.
MySQL hat viele Operatoren und Funktionen, die einen String zurückgeben. In diesem Abschnitt wollen wir die Frage beantworten, welchen Zeichensatz und welche Sortierfolge ein solcher String hat.
Bei einfachen Funktionen, die den String als Eingabe
entgegennehmen und einen String als Ergebnis ausgeben, sind
Zeichensatz und Sortierfolge des Ausgabe-Strings dieselben wie
beim ersten Eingabewert. Beispielsweise gibt
UPPER(
einen
String zurück, dessen Zeichensatz und Sortierfolge dieselben
sind wie bei X
)X
. Gleiches gilt für
INSTR()
, LCASE()
,
LOWER()
, LTRIM()
,
MID()
, REPEAT()
,
REPLACE()
, REVERSE()
,
RIGHT()
, RPAD()
,
RTRIM()
, SOUNDEX()
,
SUBSTRING()
, TRIM()
,
UCASE()
und UPPER()
.
Hinweis: Anders als alle anderen Funktionen ignoriert die
REPLACE()
-Funktion stets die Sortierfolge des
Eingabe-Strings und führt einen Vergleich mit Unterscheidung
der Groß-/Kleinschreibung durch.
Wenn ein Eingabe-String oder ein Funktionsergebnis einen
Binär-String zum Ergebnis haben, hat dieser String keinen
Zeichensatz und keine Sortierfolge. Dies kann mithilfe der
Funktionen CHARSET()
und
COLLATION()
überprüft werden, die beide
binary
zurückgeben, wenn das Argument ein
Binär-String ist:
mysql> SELECT CHARSET(BINARY 'a'), COLLATION(BINARY 'a');
+---------------------+-----------------------+
| CHARSET(BINARY 'a') | COLLATION(BINARY 'a') |
+---------------------+-----------------------+
| binary | binary |
+---------------------+-----------------------+
Bei Operationen, die mehrere Eingabe-Strings kombinieren und einen einzelnen Ausgabe-String zurückgeben, gelten die „Zusammenfassungsregeln“ des SQL-Standards zur Bestimmung der Sortierfolge des Ergebnisses:
Wenn eine explizite COLLATE
vorhanden ist, wird
X
X
verwendet.
Wenn explizite COLLATE
und X
COLLATE
auftreten, wird ein
Fehler zurückgegeben.
Y
Andernfalls wird, wenn alle Sortierfolgen
X
sind,
X
verwendet.
Ansonsten hat das Ergebnis keine Sortierfolge.
Beispielsweise ist bei CASE ... WHEN a THEN b WHEN b
THEN c COLLATE
die
resultierende Sortierfolge X
ENDX
.
Gleiches gilt für CASE
,
UNION
, ||
,
CONCAT()
, ELT()
,
GREATEST()
, IF()
und
LEAST()
.
Bei Operationen, die Zeichendaten umwandeln, werden der
Zeichensatz und die Sortierfolge der Strings, die sich aus
diesen Operationen ergeben, durch die Systemvariablen
character_set_connection
und
collation_connection
definiert. Dies gilt
für CAST()
, CHAR()
,
CONV()
, FORMAT()
,
HEX()
und SPACE()
.
CONVERT()
stellt eine Möglichkeit zur
Konvertierung von Daten zwischen verschiedenen Zeichensätzen
dar. Die Syntax sieht wie folgt aus:
CONVERT(expr
USINGtranscoding_name
)
Bei MySQL sind die Transkodierungs- mit den entsprechenden Zeichensatznamen identisch.
Ein paar Beispiele:
SELECT CONVERT(_latin1'Müller' USING utf8); INSERT INTO utf8table (utf8column) SELECT CONVERT(latin1field USING utf8) FROM latin1table;
CONVERT(... USING ...)
ist entsprechend der
SQL-Standardspezifikation implementiert.
Sie können auch mit CAST()
einen String in
einen anderen Zeichensatz umwandeln. Die Syntax sieht wie folgt
aus:
CAST(character_string
AScharacter_data_type
CHARACTER SETcharset_name
)
Beispiel:
SELECT CAST(_latin1'test' AS CHAR CHARACTER SET utf8);
Wenn Sie CAST()
ohne Angabe von
CHARACTER SET
verwenden, werden Zeichensatz
und Sortierfolge des Ergebnisses durch die Systemvariablen
character_set_connection
und
collation_connection
definiert. Wenn Sie
CAST()
mit CHARACTER SET X
benutzen, hat das Ergebnis den Zeichensatz X
und als Sortierfolge die Standardsortierfolge von
X
.
Sie können eine COLLATE
-Klausel nicht
innerhalb, wohl aber außerhalb von CAST()
verwenden. Mithin ist CAST(... COLLATE ...)
unzulässig, CAST(...) COLLATE ...
aber ist
zulässig.
Beispiel:
SELECT CAST(_latin1'test' AS CHAR CHARACTER SET utf8) COLLATE utf8_bin;
Mehrere SHOW
-Anweisungen vermitteln
zusätzliche Angaben zu Zeichensätzen. Hierzu gehören
SHOW CHARACTER SET
, SHOW
COLLATION
, SHOW CREATE DATABASE
,
SHOW CREATE TABLE
und SHOW
COLUMNS
. Diese Anweisungen wollen wir hier kurz
beschreiben. Weitere Informationen finden Sie unter
Abschnitt 13.5.4, „SHOW
“.
INFORMATION_SCHEMA
gibt mehrere Tabellen aus,
deren Inhalt dem ähnelt, was sich mit
SHOW
-Anweisungen anzeigen lässt. So
enthalten beispielsweise die Tabellen
CHARACTER_SETS
und
COLLATIONS
die Angaben, die sich auch mit
SHOW CHARACTER SET
bzw. SHOW
COLLATION
ermitteln lassen. Siehe
Kapitel 22, Die Datenbank INFORMATION_SCHEMA
.
Der Befehl SHOW CHARACTER SET
zeigt alle
verfügbaren Zeichensätze an. Er nimmt eine optionale
LIKE
-Klausel entgegen, die angibt, auf welche
Zeichensatznamen zu prüfen ist. Zum Beispiel:
mysql> SHOW CHARACTER SET LIKE 'latin%';
+---------+-----------------------------+-------------------+--------+
| Charset | Description | Default collation | Maxlen |
+---------+-----------------------------+-------------------+--------+
| latin1 | cp1252 West European | latin1_swedish_ci | 1 |
| latin2 | ISO 8859-2 Central European | latin2_general_ci | 1 |
| latin5 | ISO 8859-9 Turkish | latin5_turkish_ci | 1 |
| latin7 | ISO 8859-13 Baltic | latin7_general_ci | 1 |
+---------+-----------------------------+-------------------+--------+
Die Ausgabe von SHOW COLLATION
enthält alle
verfügbaren Zeichensätze. Die Anweisung nimmt eine optionale
LIKE
-Klausel entgegen, die angibt, auf welche
Sortierfolgennamen zu prüfen ist. Zum Beispiel:
mysql> SHOW COLLATION LIKE 'latin1%';
+-------------------+---------+----+---------+----------+---------+
| Collation | Charset | Id | Default | Compiled | Sortlen |
+-------------------+---------+----+---------+----------+---------+
| latin1_german1_ci | latin1 | 5 | | | 0 |
| latin1_swedish_ci | latin1 | 8 | Yes | Yes | 0 |
| latin1_danish_ci | latin1 | 15 | | | 0 |
| latin1_german2_ci | latin1 | 31 | | Yes | 2 |
| latin1_bin | latin1 | 47 | | Yes | 0 |
| latin1_general_ci | latin1 | 48 | | | 0 |
| latin1_general_cs | latin1 | 49 | | | 0 |
| latin1_spanish_ci | latin1 | 94 | | | 0 |
+-------------------+---------+----+---------+----------+---------+
SHOW CREATE DATABASE
zeigt die
CREATE DATABASE
-Anweisung an, die eine
gegebene Datenbank erstellt:
mysql> SHOW CREATE DATABASE test;
+----------+-----------------------------------------------------------------+
| Database | Create Database |
+----------+-----------------------------------------------------------------+
| test | CREATE DATABASE `test` /*!40100 DEFAULT CHARACTER SET latin1 */ |
+----------+-----------------------------------------------------------------+
Wird keine COLLATE
-Klausel angezeigt, dann
wird die Standardsortierfolge des Zeichensatzes verwendet.
SHOW CREATE TABLE
ist ähnlich, zeigt aber
die CREATE TABLE
-Anweisung zur Erstellung der
Tabelle an. Die Spaltendefinitionen enthalten alle ggf.
vorhandenen Zeichensatzspezifikationen, und die Tabellenoptionen
enthalten in jedem Fall Zeichensatzangaben.
Die SHOW COLUMNS
-Anweisung zeigt die
Sortierfolgen der Spalten einer Tabelle an, wenn sie mit
SHOW FULL COLUMNS
aufgerufen wird. Spalten
der Datentypen CHAR
,
VARCHAR
und TEXT
haben
Sortierfolgen. Numerische und andere nicht zeichenbasierte Typen
haben keine Sortierfolge (dies wird durch
NULL
als Collation
-Wert
angezeigt). Zum Beispiel:
mysql> SHOW FULL COLUMNS FROM person\G
*************************** 1. row ***************************
Field: id
Type: smallint(5) unsigned
Collation: NULL
Null: NO
Key: PRI
Default: NULL
Extra: auto_increment
Privileges: select,insert,update,references
Comment:
*************************** 2. row ***************************
Field: name
Type: char(60)
Collation: latin1_swedish_ci
Null: NO
Key:
Default:
Extra:
Privileges: select,insert,update,references
Comment:
Der Zeichensatz erscheint nicht direkt in der Anzeige, wohl aber als Teil des Sortierfolgennamens.
MySQL 5.1 unterstützt zur Speicherung von Unicode-Daten zwei Zeichensätze:
ucs2
(Unicode-Zeichensatz UCS-2)
utf8
(UTF-8-Kodierung des
Unicode-Zeichensatzes)
Bei UCS-2 (binäre Unicode-Darstellung) wird jedes Zeichen durch
einen 2 Byte umfassenden Unicode-Code dargestellt, wobei das
höherwertige Byte zuerst aufgeführt ist. Zum Beispiel:
LATIN CAPITAL LETTER A
hat den Code
0x0041
und wird als 2-Byte-Sequenz gespeichert:
0x00 0x41
. CYRILLIC SMALL LETTER
YERU
(Unicode 0x044B
) wird als
2-Byte-Sequenz gespeichert: 0x04 0x4B
. Weitere
Informationen zu Unicode-Zeichen und ihren Codes erhalten Sie auf
der Unicode-Homepage.
Derzeit kann UCS-2 nicht als Clientzeichensatz verwendet werden,
d. h., SET NAMES 'ucs2'
funktioniert nicht.
Der UTF-8-Zeichensatz (transformierte Unicode-Darstellung) ist eine alternative Möglichkeit zur Speicherung von Unicode-Daten. Er ist entsprechend RFC 3629 implementiert. Die Idee hinter dem UTF-8-Zeichensatz ist die, dass verschiedene Unicode-Zeichen mit Bytesequenzen unterschiedlicher Länge kodiert werden:
Einfache lateinische Buchstaben, Ziffern und Interpunktionszeichen verwenden je ein Byte.
Die Schriftzeichen der meisten europäischen und nahöstlichen Sprachen passen in eine 2-Byte-Sequenz. Dies gilt für die Buchstaben des erweiterten Lateins (einschließlich Tilde, Längestrich, Akut, Gravis und weitere Akzente) sowie das Kyrillische, Griechische, Armenische, Hebräische, Arabische, Syrische usw.
Die koreanischen, chinesischen und japanischen Ideogramme schließlich verwenden je 3 Byte.
RFC 3629 beschreibt Sequenzen, die 1 bis 4 Byte umfassen. Zurzeit umfasst die UTF-8-Unterstützung durch MySQL keine 4-Byte-Sequenzen. (Ein älterer Standard für die UTF-8-Kodierung ist in RFC 2279 enthalten, wo UTF-8-Sequenzen mit einer Länge von bis zu 6 Byte beschrieben werden. RFC 3629 hat RFC 2279 ersetzt, weswegen Sequenzen mit 5 oder 6 Byte heute nicht mehr verwendet werden.)
Tipp: Um mit UTF-8 Speicher zu
sparen, verwenden Sie VARCHAR
statt
CHAR
. Andernfalls muss MySQL 3 Byte pro Zeichen
in einer CHAR CHARACTER SET utf8
-Spalte
reservieren, da dies die maximale Länge ist. So muss MySQL etwa
30 Byte für eine CHAR(10) CHARACTER SET
utf8
-Spalte vorsehen.
Metadaten sind „Daten über
Daten“. Alle Daten, die die Datenbank
beschreiben – nicht aber solche, die in der
Datenbank enthalten sind – bezeichnet man
als Metadaten. Insofern sind etwa Spalten-, Datenbank-, Benutzer-
und Versionsnamen sowie die meisten String-Ergebnisse aus
SHOW
-Anweisungen Metadaten. Dies gilt auch für
die Inhalte von Tabellen in INFORMATION_SCHEMA
,
weil diese Tabellen per Definition Informationen zu
Datenbankobjekten enthalten.
Die Darstellung von Metadaten muss den folgenden Anforderungen genügen:
Alle Metadaten müssen im selben Zeichensatz stehen.
Andernfalls würden weder die SHOW
-Befehle
noch SELECT
-Anweisungen für Tabellen im
INFORMATION_SCHEMA
korrekt arbeiten, weil
verschiedene Datensätze in derselben Spalte der Ergebnisse
für diese Operationen in verschiedenen Zeichensätzen stehen
würden.
Metadaten müssen alle Zeichen in allen Sprachen enthalten. Andernfalls könnten Benutzer unter Umständen Spalten und Tabellen nicht in ihrer eigenen Sprache benennen.
Um beide Bedingungen zu erfüllen, speichert MySQL Metadaten in einem Unicode-Zeichensatz (nämlich UTF-8). Dies sorgt keinesfalls für Probleme, wenn Sie keine Buchstaben mit Akzent oder nichtlateinische Zeichen verwenden. Andernfalls aber sollten Sie berücksichtigen, dass Metadaten in UTF-8 stehen.
Die Anforderungen an Metadaten sehen vor, dass die Rückgabewerte
der Funktionen USER()
,
CURRENT_USER()
, DATABASE()
und VERSION()
standardmäßig den
UTF-8-Zeichensatz verwenden; dies gilt auch für Synonyme wie
SESSION_USER()
und
SYSTEM_USER()
.
Der Server setzt die Systemvariable
character_set_system
auf den Namen des
Metadaten-Zeichensatzes:
mysql> SHOW VARIABLES LIKE 'character_set_system';
+----------------------+-------+
| Variable_name | Value |
+----------------------+-------+
| character_set_system | utf8 |
+----------------------+-------+
Die Speicherung von Metadaten unter Verwendung von Unicode hat
nicht zur Folge, dass der Server
Spaltenüberschriften und die Ergebnisse von
DESCRIBE
-Funktionen standardmäßig im durch
character_set_system
angegebenen Zeichensatz
zurückgibt. Wenn Sie SELECT column1 FROM t
verwenden, wird der Name column1
selbst vom
Server an den Client in dem Zeichensatz zurückgegeben, der vom
Wert der Systemvariablen character_set_results
angegeben wird (deren Standartwert ist latin1
).
Wenn Sie wollen, dass der Server Metadatenergebnisse in einem
anderen Zeichensatz zurückgibt, erzwingen Sie mit der
SET NAMES
-Anweisung eine
Zeichensatzkonvertierung am Server. SET NAMES
stellt character_set_results
und andere
zugehörige Systemvariablen um. (Siehe auch
Abschnitt 10.4, „Verbindungszeichensatz und -sortierfolge“.) Alternativ kann ein
Clientprogramm die Konvertierung nach Empfang des Ergebnisses vom
Server vornehmen. Die Konvertierung durch den Client ist
effizienter, aber diese Option ist nicht immer verfügbar.
Wenn character_set_results
den Wert
NULL
hat, wird keine Konvertierung
durchgeführt und der Server gibt Metadaten im ursprünglichen
(d. h. dem durch character_set_system
angegebenen) Zeichensatz zurück.
Fehlermeldungen, die der Server an den Client zurückgibt, werden wie Metadaten automatisch in den Zeichensatz des Clients konvertiert.
Keine Sorge, wenn Sie (beispielsweise) die Funktion
USER()
für einen Vergleich oder eine Zuordnung
innerhalb einer einzelnen Anweisung verwenden: MySQL führt die
Konvertierung für Sie automatisch durch.
SELECT * FROM Table1 WHERE USER() = latin1_column;
Dies funktioniert, weil der Inhalt von
latin1_column
vor dem Vergleich automatisch in
UTF-8 konvertiert wird.
INSERT INTO Table1 (latin1_column) SELECT USER();
Dies funktioniert, weil der Inhalt von USER()
vor der Zuweisung automatisch in latin1
konvertiert wird. Die automatische Konvertierung ist noch nicht
vollständig implementiert, sollte aber in einer zukünftigen
Version korrekt arbeiten.
Zwar ist die automatische Konvertierung nicht Bestandteil des SQL-Standards, aber das SQL-Standarddokument besagt, dass jeder Zeichensatz (hinsichtlich der unterstützten Zeichen) eine „Teilmenge“ von Unicode ist. Aufgrund des bekannten Prinzips „Was für eine übergeordnete Menge gilt, kann auch für eine Teilmenge gelten“ nehmen wir an, dass eine Sortierfolge für Unicode auch für Vergleiche mit Nicht-Unicode-Strings gelten kann.
MySQL unterstützt mehr als 70 Sortierfolgen für über 30 Zeichensätze. In diesem Abschnitt sind die Zeichensätze aufgelistet, die MySQL unterstützt. Es gibt einen Unterabschnitt für jede Gruppe zusammengehöriger Zeichensätze. Für jeden Zeichensatz werden die zulässigen Sortierfolgen aufgeführt.
Sie können die verfügbaren Zeichensätze und ihre jeweiligen
Standardsortierfolgen jederzeit mit der Anweisung SHOW
CHARACTER SET
anzeigen:
mysql> SHOW CHARACTER SET;
+----------+-----------------------------+---------------------+
| Charset | Description | Default collation |
+----------+-----------------------------+---------------------+
| big5 | Big5 Traditional Chinese | big5_chinese_ci |
| dec8 | DEC West European | dec8_swedish_ci |
| cp850 | DOS West European | cp850_general_ci |
| hp8 | HP West European | hp8_english_ci |
| koi8r | KOI8-R Relcom Russian | koi8r_general_ci |
| latin1 | cp1252 West European | latin1_swedish_ci |
| latin2 | ISO 8859-2 Central European | latin2_general_ci |
| swe7 | 7bit Swedish | swe7_swedish_ci |
| ascii | US ASCII | ascii_general_ci |
| ujis | EUC-JP Japanese | ujis_japanese_ci |
| sjis | Shift-JIS Japanese | sjis_japanese_ci |
| hebrew | ISO 8859-8 Hebrew | hebrew_general_ci |
| tis620 | TIS620 Thai | tis620_thai_ci |
| euckr | EUC-KR Korean | euckr_korean_ci |
| koi8u | KOI8-U Ukrainian | koi8u_general_ci |
| gb2312 | GB2312 Simplified Chinese | gb2312_chinese_ci |
| greek | ISO 8859-7 Greek | greek_general_ci |
| cp1250 | Windows Central European | cp1250_general_ci |
| gbk | GBK Simplified Chinese | gbk_chinese_ci |
| latin5 | ISO 8859-9 Turkish | latin5_turkish_ci |
| armscii8 | ARMSCII-8 Armenian | armscii8_general_ci |
| utf8 | UTF-8 Unicode | utf8_general_ci |
| ucs2 | UCS-2 Unicode | ucs2_general_ci |
| cp866 | DOS Russian | cp866_general_ci |
| keybcs2 | DOS Kamenicky Czech-Slovak | keybcs2_general_ci |
| macce | Mac Central European | macce_general_ci |
| macroman | Mac West European | macroman_general_ci |
| cp852 | DOS Central European | cp852_general_ci |
| latin7 | ISO 8859-13 Baltic | latin7_general_ci |
| cp1251 | Windows Cyrillic | cp1251_general_ci |
| cp1256 | Windows Arabic | cp1256_general_ci |
| cp1257 | Windows Baltic | cp1257_general_ci |
| binary | Binary pseudo charset | binary |
| geostd8 | GEOSTD8 Georgian | geostd8_general_ci |
| cp932 | SJIS for Windows Japanese | cp932_japanese_ci |
| eucjpms | UJIS for Windows Japanese | eucjpms_japanese_ci |
+----------+-----------------------------+---------------------+
MySQL umfasst zwei Unicode-Zeichensätze. Sie können mit diesen beiden Zeichensätzen Text in ca. 650 Sprachen speichern.
Sortierfolgen für ucs2
(UCS-2-Unicode):
ucs2_bin
ucs2_czech_ci
ucs2_danish_ci
ucs2_esperanto_ci
ucs2_estonian_ci
ucs2_general_ci
(Standard)
ucs2_hungarian_ci
ucs2_icelandic_ci
ucs2_latvian_ci
ucs2_lithuanian_ci
ucs2_persian_ci
ucs2_polish_ci
ucs2_roman_ci
ucs2_romanian_ci
ucs2_slovak_ci
ucs2_slovenian_ci
ucs2_spanish2_ci
ucs2_spanish_ci
ucs2_swedish_ci
ucs2_turkish_ci
ucs2_unicode_ci
Sortierfolgen für utf8
(UTF-8-Unicode):
utf8_bin
utf8_czech_ci
utf8_danish_ci
utf8_esperanto_ci
utf8_estonian_ci
utf8_general_ci
(Standard)
utf8_hungarian_ci
utf8_icelandic_ci
utf8_latvian_ci
utf8_lithuanian_ci
utf8_persian_ci
utf8_polish_ci
utf8_roman_ci
utf8_romanian_ci
utf8_slovak_ci
utf8_slovenian_ci
utf8_spanish2_ci
utf8_spanish_ci
utf8_swedish_ci
utf8_turkish_ci
utf8_unicode_ci
Die Sortierfolgen ucs2_hungarian_ci
und
utf8_hungarian_ci
wurden in MySQL 5.1.5
hinzugefügt.
MySQL implementiert die Sortierfolge
utf8_unicode_ci
entsprechend dem UCA (Unicode
Collation Algorithm, Unicode-Sortierfolgenalgorithmus), der
unter http://www.unicode.org/reports/tr10/
beschrieben ist. Die Sortierfolge verwendet die
UCA-Gewichtungsschlüssel nach Version 4.0.0 (siehe
http://www.unicode.org/Public/UCA/4.0.0/allkeys-4.0.0.txt).
Die folgende Beschreibung verwendet
utf8_unicode_ci
, gilt aber für
ucs2_unicode_ci
gleichermaßen.
Zurzeit bietet die Sortierfolge
utf8_unicode_ci
nur teilweise Unterstützung
für den UCA. Einige Zeichen werden noch nicht unterstützt.
Gleiches gilt für diakritische Zeichen. Dies betrifft in erster
Linie das Vietnamesische und einige Minderheitensprachen in
Russland wie etwa das Udmurtische, das Tatarische, das
Baschkirische und Mari.
Die bedeutsamste Funktion in utf8_unicode_ci
besteht darin, dass Erweiterungen unterstützt werden, d. h.,
wenn ein Zeichen mit einer Kombination anderer Zeichen
gleichgesetzt wird. Beispielsweise wird im Deutschen und einigen
anderen Sprachen ‘ß
’ mit
‘ss
’ gleichgesetzt.
utf8_general_ci
ist eine ältere
Sortierfolge, die Erweiterungen nicht unterstützt. Hier können
nur 1 : 1-Vergleiche zwischen Zeichen durchgeführt werden:
Vergleiche für die
utf8_general_ci
-Sortierfolge sind also
schneller, aber unter Umständen weniger korrekt als Vergleiche
für utf8_unicode_ci
.
Die folgenden Gleichstellungen beispielsweise sind sowohl in
utf8_general_ci
als auch in
utf8_unicode_ci
zutreffend:
Ä = A Ö = O Ü = U
Ein Unterschied zwischen den Sortierfolgen besteht darin, dass
Folgendes für utf8_general_ci
wahr ist:
ß = s
Dagegen ist Folgendes für utf8_unicode_ci
wahr:
ß = ss
MySQL implementiert sprachspezifische Sortierfolgen für den
utf8
-Zeichensatz nur dann, wenn die
Sortierung mit utf8_unicode_ci
bei einer
Sprache nicht gut funktioniert. So arbeitet
utf8_unicode_ci
etwa für das Deutsche oder
das Französische einwandfrei, weswegen für diese beiden
Sprachen keine utf8
-Spezialsortierungen
erforderlich sind.
Auch utf8_general_ci
ist für Deutsch und
Französisch weitgehend angemessen, nur wird hier
‘ß
’ mit
‘s
’ (statt
‘ss
’) gleichgesetzt. Sofern es
für Ihre Anwendung ausreichend sein sollte, sollten Sie
utf8_general_ci
verwenden, weil diese
Sortierfolge schneller ist. Ansonsten benutzen Sie
utf8_unicode_ci
, denn diese Sortierfolge
arbeitet exakter.
utf8_swedish_ci
wurde wie andere
sprachspezifische utf8
-Sortierfolgen auch von
utf8_unicode_ci
abgeleitet und mit
zusätzlichen Sprachregeln ergänzt. Beispielsweise funktioniert
im Schwedischen die folgende Beziehung – etwas, das der
deutsche oder französische Muttersprachler nicht erwarten
würde:
Ü = Y < Ö
Die Sortierfolgen utf8_spanish_ci
und
utf8_spanish2_ci
entsprechen dem modernen
bzw. dem traditionellen Spanisch. Bei beiden Sortierfolgen ist
‘ñ
’ (n mit Tilde) ein separater
Buchstabe zwischen ‘n
’ und
‘o
’. Ferner ist beim
traditionellen Spanisch ‘ch
’ ein
separater Buchstabe zwischen ‘c
’
und d
und ‘ll
’
ein separater Buchstabe zwischen
‘l
’ und
‘m
’.
Westeuropäische Zeichensätze decken die meisten westeuropäischen Sprachen ab, so etwa Französisch, Spanisch, Katalanisch, Baskisch, Portugiesisch, Italienisch, Albanisch, Niederländisch, Deutsch, Dänisch, Schwedisch, Norwegisch, Finnisch, Färöisch, Isländisch, Irisch, Schottisch und Englisch.
Sortierfolgen von ascii
(US ASCII):
ascii_bin
ascii_general_ci
(Standard)
Sortierfolgen von cp850
(DOS,
westeuropäisch):
cp850_bin
cp850_general_ci
(Standard)
Sortierfolgen von dec8
(DEC,
westeuropäisch):
dec8_bin
dec8_swedish_ci
(Standard)
Sortierfolgen von hp8
(HP,
westeuropäisch):
hp8_bin
hp8_english_ci
(Standard)
Sortierfolgen von latin1
(cp1252,
westeuropäisch):
latin1_bin
latin1_danish_ci
latin1_general_ci
latin1_general_cs
latin1_german1_ci
latin1_german2_ci
latin1_spanish_ci
latin1_swedish_ci
(Standard)
latin1
ist der Standardzeichensatz.
latin1
von MySQL entspricht dem
Windows-Zeichensatz cp1252
. Mithin ist er
mit dem offiziellen latin1
nach
ISO 8859-1
bzw. dem
latin1
-Zeichensatz der IANA (Internet
Assigned Numbers Authority) identisch, aber der
IANA-Zeichensatz behandelt die Codepunkte zwischen
0x80
und 0x9f
als
„undefiniert“, während
cp1252
(und damit auch der
latin1
-Zeichensatz von MySQL) diesen
Positionen Zeichen zuweist. So ist etwa
0x80
das Eurozeichen. Für die
„undefinierten“ Einträge in
cp1252
übersetzt MySQL
0x81
in das Unicode-Zeichen
0x0081
, 0x8d
in
0x008d
, 0x8f
in
0x008f
, 0x90
in
0x0090
und 0x9d
in
0x009d
.
Die Sortierfolge latin1_swedish_ci
ist
die Standardsortierfolge, die von der Mehrzahl der
MySQL-Kunden wahrscheinlich verwendet wird. Obwohl häufig
gesagt wird, dass sie auf den Sortierregeln für das
Schwedische und das Finnische basiert, gibt es viele
Schweden und Finnen, die dieser Aussage widersprechen.
Die Sortierfolgen latin1_german1_ci
und
latin1_german2_ci
basieren auf den DIN-1-
und DIN-2-Normen. DIN ist das Deutsche
Institut für Normung, also die deutsche
Standardisierungsorganisation. DIN-1 heißt
„Wörterbuchsortierung“, DIN-2
„Telefonbuchsortierung“.
Regeln für latin1_german1_ci
(Wörterbuchsortierung):
Ä = A Ö = O Ü = U ß = s
Regeln für latin1_german2_ci
(Telefonbuchsortierung):
Ä = AE Ö = OE Ü = UE ß = ss
Bei der Sortierfolge latin1_spanish_ci
ist ‘ñ
’ ein separater
Buchstabe zwischen ‘n
’ und
‘o
’.
Sortierfolgen von macroman
(Mac,
westeuropäisch):
macroman_bin
macroman_general_ci
(Standard)
Sortierfolgen von swe7
(Schwedisch, 7
Bit):
swe7_bin
swe7_swedish_ci
(Standard)
MySQL bietet in eingeschränktem Maße Unterstützung für die Zeichensätze, die in Tschechien, der Slowakei, Ungarn, Rumänien, Slowenien, Kroatien und Polen verwendet werden.
Sortierfolgen von cp1250
(Windows,
mitteleuropäisch):
cp1250_bin
cp1250_croatian_ci
cp1250_czech_cs
cp1250_general_ci
(Standard)
cp1250_polish_ci
Sortierfolgen von cp852
(DOS,
mitteleuropäisch):
cp852_bin
cp852_general_ci
(Standard)
Sortierfolgen von keybcs2
(DOS,
Kamenicky-tschechoslowakisch):
keybcs2_bin
keybcs2_general_ci
(Standard)
Sortierfolgen von latin2
(ISO 8859-2,
mitteleuropäisch):
latin2_bin
latin2_croatian_ci
latin2_czech_cs
latin2_general_ci
(Standard)
latin2_hungarian_ci
Sortierfolgen von macce
(Mac,
mitteleuropäisch):
macce_bin
macce_general_ci
(Standard)
Zu den südeuropäischen und nahöstlichen Zeichensätzen, die von MySQL unterstützt werden, gehören das Armenische, das Arabische, das Georgische, das Griechische, das Hebräische und das Türkische.
Sortierfolgen für armscii8
(ARMSCII-8,
armenisch):
armscii8_bin
armscii8_general_ci
(Standard)
Sortierfolgen von cp1256
(Windows,
arabisch):
cp1256_bin
cp1256_general_ci
(Standard)
Sortierfolgen von geostd8
(GEOSTD8,
georgisch):
geostd8_bin
geostd8_general_ci
(Standard)
Sortierfolgen von greek
(ISO 8859-7,
griechisch):
greek_bin
greek_general_ci
(Standard)
Sortierfolgen von hebrew
(ISO 8859-8,
hebräisch):
hebrew_bin
hebrew_general_ci
(Standard)
Sortierfolgen von latin5
(ISO 8859-9,
türkisch):
latin5_bin
latin5_turkish_ci
(Standard)
Die baltischen Zeichensätze decken die estnische, die lettische und die litauische Sprache ab.
Sortierfolgen von cp1257
(Windows,
baltisch):
cp1257_bin
cp1257_general_ci
(Standard)
cp1257_lithuanian_ci
Sortierfolgen von latin7
(ISO 8859-13,
baltisch):
latin7_bin
latin7_estonian_cs
latin7_general_ci
(Standard)
latin7_general_cs
Die kyrillischen Zeichensätze und Sortierfolgen werden für das Weißrussische, das Bulgarische, das Russische und das Ukrainische verwendet.
Sortierfolgen von cp1251
(Windows,
kyrillisch):
cp1251_bin
cp1251_bulgarian_ci
cp1251_general_ci
(Standard)
cp1251_general_cs
cp1251_ukrainian_ci
Sortierfolgen von cp866
(DOS, russisch):
cp866_bin
cp866_general_ci
(Standard)
Sortierfolgen von koi8r
(KOI8-R, Relcom,
russisch):
koi8r_bin
koi8r_general_ci
(Standard)
Sortierfolgen von koi8u
(KOI8-U,
ukrainisch):
koi8u_bin
koi8u_general_ci
(Standard)
Die von uns unterstützten asiatischen Zeichensätze sind das
Chinesische, das Japanische, das Koreanische und das
Thailändische. Diese können sehr komplex sein. Beispielsweise
müssen die chinesischen Zeichensätze Tausende verschiedener
Zeichen zulassen. Weitere Informationen zu den Zeichensätzen
cp932
und sjis
finden Sie
in Abschnitt 10.9.7.1, „Der Zeichensatz cp932
“.
Sortierfolgen von big5
(Big5, chinesisch
traditionell):
big5_bin
big5_chinese_ci
(Standard)
Sortierfolgen von cp932
(SJIS für
Windows, japanisch):
cp932_bin
cp932_japanese_ci
(Standard)
Sortierfolgen von eucjpms
(UJIS für
Windows, japanisch):
eucjpms_bin
eucjpms_japanese_ci
(Standard)
Sortierfolgen von euckr
(EUC-KR,
koreanisch):
euckr_bin
euckr_korean_ci
(Standard)
Sortierfolgen von gb2312
(GB2312,
chinesisch vereinfacht):
gb2312_bin
gb2312_chinese_ci
(Standard)
Sortierfolgen von gbk
(GBK, chinesisch
vereinfacht):
gbk_bin
gbk_chinese_ci
(Standard)
Sortierfolgen von sjis
(Shift-JIS,
japanisch):
sjis_bin
sjis_japanese_ci
(Standard)
Sortierfolgen von tis620
(TIS620,
thailändisch):
tis620_bin
tis620_thai_ci
(Standard)
Sortierfolgen von ujis
(EUC-JP,
japanisch):
ujis_bin
ujis_japanese_ci
(Standard)
Warum ist cp932
erforderlich?
In MySQL entspricht der Zeichensatz sjis
dem von der IANA definierten Zeichensatz
Shift_JIS
, der JIS X0201- und JIS
X0208-Zeichen unterstützt. (Siehe auch
http://www.iana.org/assignments/character-sets.)
Allerdings ist die Bedeutung von „SHIFT JIS“ als
Begriff zu Beschreibungszwecken sehr vage geworden und umfasst
häufig auch die Erweiterungen auf
Shift_JIS
, die von verschiedenen Anbietern
definiert werden.
So ist beispielsweise das in japanischsprachigen
Windows-Umgebungen verwendete „SHIFT JIS“ eine
Microsoft-Erweiterung von Shift_JIS
, deren
exakter Name
Microsoft Windows Codepage : 932
oder
cp932
lautet. Neben den von
Shift_JIS
unterstützten Zeichen
unterstützt cp932
Erweiterungszeichen wie
NEC-Sonderzeichen, NEC-Auswahl-/IBM-Erweiterungszeichen sowie
IBM-Auswahlzeichen.
Viele japanische Benutzer haben Probleme mit diesen Erweiterungszeichen. Ursache hierfür sind die folgenden Faktoren:
MySQL wandelt Zeichensätze automatisch um.
Zeichensätze werden via Unicode (ucs2
)
konvertiert.
Der Zeichensatz sjis
unterstützt keine
Konvertierung dieser Erweiterungszeichen.
Es gibt mehrere Regeln für die Konvertierung aus dem so genannten „SHIFT JIS“ in Unicode, und je nach Konvertierungsregeln werden einige Zeichen anders in Unicode konvertiert. MySQL unterstützt nur eine dieser Regeln (diese wird weiter unten beschrieben).
Der MySQL-Zeichensatz cp932
wurde
entwickelt, um diese Probleme zu beseitigen.
Weil MySQL die Zeichensatzkonvertierung unterstützt, ist es
wichtig, die beiden Zeichensätze Shift_JIS
(IANA) und cp932
in zwei verschiedene
Zeichensätze aufzuteilen, weil diese unterschiedliche
Konvertierungsregeln bieten.
Wie unterscheidet sich
cp932
von
sjis
?
Der Zeichensatz cp932
unterscheidet sich
von sjis
wie folgt:
cp932
unterstützt NEC-Sonderzeichen,
NEC-Auswahl-/IBM-Erweiterungszeichen sowie
IBM-Auswahlzeichen.
Einige cp932
-Zeichen haben zwei
verschiedene Codepunkte, die beide in denselben
Unicode-Codepunkt konvertiert werden. Wenn Sie aus Unicode
in cp932
zurückkonvertieren, muss
einer dieser beiden Codepunkte ausgewählt werden. Bei
solchen „Roundtrip-Konvertierungen“ wird die
von Microsoft empfohlene Regel verwendet. (Siehe auch
http://support.microsoft.com/kb/170559/EN-US/.)
Die Konvertierungsregel funktioniert wie folgt:
Wenn das Zeichen sowohl in JIS X 0208 als auch in den NEC-Sonderzeichen enthalten ist, wird der Codepunkt von JIS X 0208 verwendet.
Wenn das Zeichen sowohl in den NEC-Sonderzeichen als auch in den IBM-Auswahlzeichen enthalten ist, wird der Codepunkt für NEC-Sonderzeichen verwendet.
Wenn das Zeichen sowohl in den IBM-Auswahlzeichen als auch in den NEC-Auswahl-/IBM-Erweiterungszeichen enthalten ist, wird der Codepunkt für IBM-Erweiterungszeichen verwendet.
Die unter
http://www.microsoft.com/globaldev/reference/dbcs/932.htm
gezeigte Tabelle enthält Informationen zu den
Unicode-Werten der cp932
-Zeichen. Bei
cp932
-Tabelleneinträgen mit Zeichen,
unter denen eine vierstellige Zahl erscheint, stellt diese
die entsprechende Unicode-Kodierung
(ucs2
) dar. Bei Tabelleneinträgen mit
einem unterstrichenen zweistelligen Wert gibt es einen
Bereich mit cp932
-Zeichenwerten, die
bei diesen beiden Stellen beginnen. Wenn Sie auf einen
solchen Tabelleneintrag klicken, gelangen Sie auf eine
Seite, auf der der Unicode-Wert für jedes
cp932
-Zeichen angezeigt wird, das mit
diesen Stellen beginnt.
Die folgenden Links verdienen Ihr besonderes Interesse. Sie entsprechen den Kodierungen der folgenden Zeichenbestände:
NEC-Sonderzeichen:
http://www.microsoft.com/globaldev/reference/dbcs/932/932_87.htm
NEC-Auswahl-/IBM-Erweiterungszeichen:
http://www.microsoft.com/globaldev/reference/dbcs/932/932_ED.htm http://www.microsoft.com/globaldev/reference/dbcs/932/932_EE.htm
IBM-Auswahlzeichen:
http://www.microsoft.com/globaldev/reference/dbcs/932/932_FA.htm http://www.microsoft.com/globaldev/reference/dbcs/932/932_FB.htm http://www.microsoft.com/globaldev/reference/dbcs/932/932_FC.htm
cp932
unterstützt die Konvertierung
benutzerdefinierter Zeichen in Kombination mit
eucjpms
und beseitigt die Probleme bei
der
sjis
-/ujis
-Konvertierung.
Weitere Informationen erhalten Sie unter
http://www.opengroup.or.jp/jvc/cde/sjis-euc-e.html.
Bei einigen Zeichen ist die Konvertierung von und nach
ucs2
bei sjis
und
cp932
unterschiedlich. Die folgenden
Tabellen veranschaulichen diese Unterschiede.
Konvertierung nach ucs2
:
sjis -/cp932 -Wert | Konvertierung sjis nach
ucs2 | Konvertierung cp932 nach
ucs2 |
5C | 005C | 005C |
7E | 007E | 007E |
815C | 2015 | 2015 |
815F | 005C | FF3C |
8160 | 301C | FF5E |
8161 | 2016 | 2225 |
817C | 2212 | FF0D |
8191 | 00A2 | FFE0 |
8192 | 00A3 | FFE1 |
81CA | 00AC | FFE2 |
Konvertierung von ucs2
:
ucs2 -Wert | Konvertierung ucs2 nach
sjis | Konvertierung ucs2 nach
cp932 |
005C | 815F | 5C |
007E | 7E | 7E |
00A2 | 8191 | 3F |
00A3 | 8192 | 3F |
00AC | 81CA | 3F |
2015 | 815C | 815C |
2016 | 8161 | 3F |
2212 | 817C | 3F |
2225 | 3F | 8161 |
301C | 8160 | 3F |
FF0D | 3F | 817C |
FF3C | 3F | 815F |
FF5E | 3F | 8160 |
FFE0 | 3F | 8191 |
FFE1 | 3F | 8192 |
FFE2 | 3F | 81CA |
Inhaltsverzeichnis
MySQL unterstützt eine Vielzahl von Datentypen verschiedener Kategorien: numerische Typen, Typen für Datum und Uhrzeit und auch String-Typen (zeichenbasierte Typen). In diesem Kapitel erhalten Sie zunächst eine Übersicht über diese Datentypen. Nachfolgend finden Sie eine detaillierte Beschreibung der Eigenschaften von Typen der jeweiligen Kategorien und eine Zusammenfassung der Speicheranforderungen dieser Datentypen. Die einführende Übersicht ist bewusst kurz gehalten. Detailinformationen zu bestimmten Datentypen – z. B. zu den zur Werteangabe zulässigen Formaten – entnehmen Sie am besten den ausführlicheren Beschreibungen im Verlauf des Kapitels.
MySQL unterstützt auch Erweiterungen zur Verarbeitung raumbezogener Daten. Kapitel 18, Raumbezogene Erweiterungen in MySQL, enthält Informationen zu diesen Datentypen.
Die folgenden Konventionen gelten für eine Reihe der nachfolgenden Datentypbeschreibungen:
gibt die
maximale Anzeigebreite für Integer-Typen an. Bei Fließkomma-
und Festkommatypen beschreibt M
M
die
maximale Anzahl der Stellen. Bei String-Typen schließlich ist
M
die maximale Länge. Der maximal
zulässige Wert für M
hängt vom
jeweiligen Datentyp ab.
gibt bei
Fließkomma- und Festkommatypen die Anzahl der Stellen nach dem
Dezimalpunkt an. Der maximale Wert ist 30. Allerdings sollte er
nie größer gewählt werden als D
M
– 2.
Eckige Klammern (‘[
’ und
‘]
’) zeigen optionale
Bestandteile der Typendefinition an.
Es folgt eine Übersicht zu den numerischen Datentypen. Weitere Informationen finden Sie unter Abschnitt 11.2, „Numerische Datentypen“. Die Speicheranforderungen für die Typen sind in Abschnitt 11.5, „Speicherbedarf von Spaltentypen“, beschrieben.
M
zeigt die maximale Anzeigebreite
an. Der höchste zulässige Wert ist 255. Die Anzeigebreite hat
keinen Bezug zur Speichergröße oder zum zulässigen
Wertebereich des betreffenden Typs (siehe auch
Abschnitt 11.2, „Numerische Datentypen“).
Wenn Sie ZEROFILL
für eine numerische Spalte
angeben, fügt MySQL automatisch das Attribut
UNSIGNED
für die Spalte hinzu.
SERIAL
ist ein Alias für BIGINT
UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE
.
SERIAL DEFAULT VALUE
ist in der Definition
einer Integer-Spalte ein Alias für NOT NULL
AUTO_INCREMENT UNIQUE
.
Warnung: Wenn Sie die
Subtraktion für Integer-Werte verwenden, von denen einer vom
Typ UNSIGNED
ist, dann hat das Ergebnis kein
Vorzeichen. Siehe auch Abschnitt 12.8, „Cast-Funktionen und Operatoren“.
Bitfeldtyp. M
gibt die Anzahl von
Bits pro Wert in einem Bereich zwischen 1 und 64 an. Wenn
M
weggelassen wird, wird
standardmäßig 1 verwendet.
TINYINT[(
M
)] [UNSIGNED]
[ZEROFILL]
Sehr kleiner Integer. Der vorzeichenbehaftete Bereich liegt
zwischen -128
und 127
.
Der vorzeichenlose Bereich liegt zwischen
0
und 255
.
Diese Typen sind Synonyme für
TINYINT(1)
. Der Wert Null wird als falsch
ausgewertet, Werte ungleich null als wahr.
Die Implementierung der vollständigen Verarbeitung boolescher Typen entsprechend dem SQL-Standard ist für die Zukunft vorgesehen.
SMALLINT[(
M
)] [UNSIGNED]
[ZEROFILL]
Kleiner Integer. Der vorzeichenbehaftete Bereich liegt
zwischen -32768
und
32767
. Der vorzeichenlose Bereich liegt
zwischen 0
und 65535
.
MEDIUMINT[(
M
)]
[UNSIGNED] [ZEROFILL]
Mittelgroßer Integer. Der vorzeichenbehaftete Bereich liegt
zwischen -8388608
und
8388607
. Der vorzeichenlose Bereich liegt
zwischen 0
und
16777215
.
INT[(
M
)] [UNSIGNED]
[ZEROFILL]
Integer normaler Größe. Der vorzeichenbehaftete Bereich
liegt zwischen -2147483648
und
2147483647
. Der vorzeichenlose Bereich
liegt zwischen 0
und
4294967295
.
INTEGER[(
M
)] [UNSIGNED]
[ZEROFILL]
Dieser Typ ist synonym zu INT
.
BIGINT[(
M
)] [UNSIGNED]
[ZEROFILL]
Großer Integer. Der vorzeichenbehaftete Bereich liegt
zwischen -9223372036854775808
und
9223372036854775807
. Der vorzeichenlose
Bereich liegt zwischen 0
und
18446744073709551615
.
Bestimmte Aspekte sollten Sie in Bezug auf
BIGINT
-Spalten beachten:
Alle Berechnungen werden unter Verwendung
vorzeichenbehafteter BIGINT
- oder
DOUBLE
-Werte durchgeführt. Aus
diesem Grund sollten Sie – mit Ausnahme von
Bitfunktionen – keine vorzeichenlosen großen
Integer-Zahlen benutzen, die größer sind als
9223372036854775807
(63 Bits)!
Andernfalls können, wenn Sie einen
BIGINT
- in einen
DOUBLE
-Wert konvertieren, die letzten
Stellen des Ergebnisses aufgrund von Rundungsfehlern
unter Umständen falsch sein.
MySQL kann BIGINT
in den folgenden
Fällen verarbeiten:
Bei der Verwendung von Integer-Zahlen zur
Speicherung großer vorzeichenloser Werte in einer
BIGINT
-Spalte.
In
MIN(
oder
col_name
)MAX(
,
wobei col_name
)col_name
eine
BIGINT
-Spalte referenziert.
Bei der Verwendung von Operatoren
(+
, -
,
*
usw.), wenn beide Operanden
Integers sind.
Sie können einen exakten Integer-Wert jederzeit in
einer BIGINT
-Spalte speichern, indem
Sie zur Speicherung einen String verwenden. In diesem
Fall führt MySQL eine Konvertierung des Strings in eine
Zahl durch, wobei keine zwischenzeitliche Darstellung
mit doppelter Genauigkeit erfolgt.
Die Operatoren -
,
+
und *
verwenden
die BIGINT
-Arithmetik, wenn beide
Operanden Integers sind. Das bedeutet, dass Sie, wenn
Sie zwei große Integers (oder Ergebnisse von
Funktionen, die Integers zurückgeben) miteinander
multiplizieren, unerwartete Ergebnisse erhalten können,
wenn das Ergebnis größer als
9223372036854775807
ist.
FLOAT[(
M
,D
)]
[UNSIGNED] [ZEROFILL]
Kleine Fließkommazahl (mit einfacher Genauigkeit).
Zulässige Werte sind der Bereich zwischen
-3.402823466E+38
und
-1.175494351E-38
, 0
und der Bereich zwischen 1.175494351E-38
und 3.402823466E+38
. Dies sind
theoretische Werte, die auf dem IEEE-Standard basieren. Der
tatsächliche Wertebereich kann abhängig von Ihrer Hardware
oder Ihrem Betriebssystem ein wenig kleiner sein.
M
ist die Gesamtzahl von
Dezimalstellen, D
die Anzahl der
Stellen hinter dem Dezimalpunkt. Wenn
M
und
D
nicht angegeben werden, werden
die Werte im Rahmen dessen gespeichert, was hardwareseitig
unterstützt wird. Eine Fließkommazahl mit einfacher
Genauigkeit ist auf etwa sieben Dezimalstellen genau.
Sofern angegeben, verbietet UNSIGNED
negative Werte.
Durch die Verwendung von FLOAT
können
sich unerwartete Probleme ergeben, weil alle Berechnungen in
MySQL mit doppelter Genauigkeit erfolgen. Siehe auch
Abschnitt A.5.7, „Lösung von Problemen mit nicht übereinstimmenden Zeilen“.
DOUBLE[(
M
,D
)]
[UNSIGNED] [ZEROFILL]
Fließkommazahl normaler Größe (mit doppelter
Genauigkeit). Zulässige Werte sind der Bereich zwischen
-1.7976931348623157E+308
und
-2.2250738585072014E-308
,
0
und der Bereich zwischen
2.2250738585072014E-308
und
1.7976931348623157E+308
. Dies sind
theoretische Werte, die auf dem IEEE-Standard basieren. Der
tatsächliche Wertebereich kann abhängig von Ihrer Hardware
oder Ihrem Betriebssystem ein wenig kleiner sein.
M
ist die Gesamtzahl von
Dezimalstellen, D
die Anzahl der
Stellen hinter dem Dezimalpunkt. Wenn
M
und
D
nicht angegeben werden, werden
die Werte im Rahmen dessen gespeichert, was hardwareseitig
unterstützt wird. Eine Fließkommazahl mit doppelter
Genauigkeit ist auf etwa 15 Dezimalstellen genau.
Sofern angegeben, verbietet UNSIGNED
negative Werte.
DOUBLE
PRECISION[(
,
M
,D
)]
[UNSIGNED] [ZEROFILL]REAL[(
M
,D
)]
[UNSIGNED] [ZEROFILL]
Diese Typen sind Synonyme für DOUBLE
.
Ausnahme: Wenn der SQL-Modus
REAL_AS_FLOAT
aktiviert ist, ist
REAL
ein Synonym für
FLOAT
statt für
DOUBLE
.
FLOAT(
p
) [UNSIGNED]
[ZEROFILL]
Fließkommazahl. p
steht für die
Genauigkeit in Bit, aber MySQL verwendet diesen Wert nur zur
Bestimmung, ob als Datentyp für das Ergebnis
FLOAT
oder DOUBLE
zugewiesen werden soll. Liegt p
zwischen 0 und 24, dann wird FLOAT
(ohne
M
- und
D
-Werte) als Typ gewählt. Liegt
p
zwischen 25 und 53, dann wird
DOUBLE
(ohne
M
- und
D
-Werte) als Typ gewählt. Der
Bereich der Ergebnisspalte entspricht den Datentypen
FLOAT
mit einfacher Genauigkeit oder
DOUBLE
mit doppelter Genauigkeit
entsprechend obiger Beschreibung.
Die Syntax
FLOAT(
wird
aus Gründen der ODBC-Kompatibilität unterstützt.
p
)
DECIMAL[(
M
[,D
])]
[UNSIGNED] [ZEROFILL]
Gepackte „exakte“ Festkommazahl.
M
ist die Gesamtzahl von
Dezimalstellen (Genauigkeit), D
die Anzahl der Stellen hinter dem Dezimalpunkt. Der
Dezimalpunkt sowie das Zeichen
‘-
’ (für negative Zahlen)
werden bei der Zählung für M
nicht berücksichtigt. Wenn D
0
ist, haben die Werte keinen Dezimalpunkt und keine
Nachkommastellen. Die maximale Anzahl der Stellen
(M
) beträgt bei
DECIMAL
65, die maximale Anzahl
unterstützter Dezimalstellen (D
)
30. Wird D
weggelassen, dann wird
als Vorgabe 0 verwendet; fehlt die Angabe
M
, dann ist 10 der Standardwert.
Sofern angegeben, verbietet UNSIGNED
negative Werte.
Berechnungen in den Grundrechenarten (+, -, *,
/
) erfolgen bei DECIMAL
-Spalten
stets mit einer Genauigkeit von 65 Stellen.
DEC[(
,
M
[,D
])]
[UNSIGNED] [ZEROFILL]NUMERIC[(
,
M
[,D
])]
[UNSIGNED] [ZEROFILL]FIXED[(
M
[,D
])]
[UNSIGNED] [ZEROFILL]
Diese Typen sind Synonyme für DECIMAL
.
Das Synonym FIXED
steht aus Gründen der
Kompatibilität mit anderen Datenbanksystemen zur
Verfügung.
Es folgt eine Übersicht über die zeitbezogenen Datentypen. Weitere Informationen finden Sie unter Abschnitt 11.3, „Datums- und Zeittypen“. Die Speicheranforderungen für die Typen sind in Abschnitt 11.5, „Speicherbedarf von Spaltentypen“, beschrieben.
Die Zusammenfassungsfunktionen SUM()
und
AVG()
funktionieren bei Zeitwerten nicht.
(Sie konvertieren die Werte in Zahlen, wodurch alles, was nach
dem ersten nichtnumerischen Zeichen auftaucht, verloren geht.)
Um dieses Problem zu umgehen, können Sie die Werte in
numerische Einheiten konvertieren, dann die
Zusammenfassungsfunktion ausführen und abschließend eine
Rückkonvertierung in den Zeitwert durchführen. Ein paar
Beispiele:
SELECT SEC_TO_TIME(SUM(TIME_TO_SEC(time_col
))) FROMtbl_name
; SELECT FROM_DAYS(SUM(TO_DAYS(date_col
))) FROMtbl_name
;
Datum. Der unterstützte Bereich liegt zwischen
'1000-01-01'
und
'9999-12-31'
. MySQL zeigt
DATE
-Werte im Format
'YYYY-MM-DD'
an, gestattet Ihnen aber,
wahlweise Strings oder Zahlen in
DATE
-Spalten einzugeben.
Kombination aus Datum und Uhrzeit. Der unterstützte Bereich
liegt zwischen '1000-01-01 00:00:00'
und
'9999-12-31 23:59:59'
. MySQL zeigt
DATETIME
-Werte im Format
'YYYY-MM-DD HH:MM:SS'
an, gestattet Ihnen
aber, wahlweise Strings oder Zahlen in
DATETIME
-Spalten einzugeben.
Zeitstempel. Der Bereich liegt zwischen '1970-01-01
00:00:00'
und einem Zeitpunkt irgendwann im Jahr
2037
.
Eine TIMESTAMP
-Spalte ist nützlich, um
Datum und Uhrzeit einer INSERT
- oder
UPDATE
-Operation aufzunehmen.
Standardmäßig wird die erste
TIMESTAMP
-Spalte in einer Tabelle
automatisch auf das Datum und die Uhrzeit der zuletzt
durchgeführten Operation gesetzt, sofern Sie nicht selbst
einen Wert angeben. Sie können
TIMESTAMP
-Spalten auch auf die aktuellen
Werte für Datum und Uhrzeit setzen, indem Sie einen
NULL
-Wert zuweisen. Varianten der
automatischen Initialisierung und Eigenschaften von
Änderungen sind in Abschnitt 11.3.1.1, „TIMESTAMP
-Eigenschaften ab MySQL 4.1“,
beschrieben.
Ein TIMESTAMP
-Wert wird als String im
Format 'YYYY-MM-DD HH:MM:SS'
zurückgegeben, dessen Anzeigebreite auf 19 Zeichen
festgelegt ist. Um den Wert als Zahl zu erhalten, sollten
Sie +0
zur Zeitstempelspalte hinzufügen.
Hinweis: Das vor MySQL 4.1
verwendete TIMESTAMP
-Format wird von
MySQL 5.1 nicht unterstützt. Informationen zum
veralteten Format finden Sie im
MySQL-Referenzhandbuch für die Versionen 3.23,
4.0 und 4.1.
Eine Zeitangabe. Der Bereich liegt zwischen
'-838:59:59'
und
'838:59:59'
. MySQL zeigt
TIME
-Werte im Format
'HH:MM:SS'
an, gestattet Ihnen aber,
wahlweise Strings oder Zahlen in
TIME
-Spalten einzugeben.
Ein Jahr im zwei- oder vierstelligen Format. Das
vierstellige Format ist standardmäßig voreingestellt. In
diesem Format sind zulässige Werte der Bereich zwischen
1901
und 2155
sowie
0000
. Im zweistelligen Format ist der
Bereich 70
bis 69
zulässig; er bezeichnet die Jahre 1970 bis 2069. MySQL
zeigt YEAR
-Werte im Format
YYYY
an, gestattet Ihnen aber, wahlweise
Strings oder Zahlen in YEAR
-Spalten
einzugeben.
Es folgt eine Übersicht über die String-Datentypen. Weitere Informationen finden Sie unter Abschnitt 11.4, „String-Typen“. Die Speicheranforderungen für die Typen sind in Abschnitt 11.5, „Speicherbedarf von Spaltentypen“, beschrieben.
Seit MySQL 4.1 weisen die String-Typen eine Reihe von Funktionen auf, die Sie, wenn Sie bislang nur mit älteren MySQL-Versionen (vor 4.1) gearbeitet haben, unter Umständen nicht kennen:
Spaltendefinitionen für viele String-Datentypen können ein
Attribut CHARACTER SET
enthalten, mit dem
der Zeichensatz angegeben wird. (CHARSET
ist ein Synonym für CHARACTER SET
.) Das
Attribut COLLATE
gibt die Sortierung für
den Zeichensatz an. Diese Attribute gelten für
CHAR
, VARCHAR
, die
TEXT
-Typen, ENUM
und
SET
. Zum Beispiel:
CREATE TABLE t ( c1 VARCHAR(20) CHARACTER SET utf8, c2 TEXT CHARACTER SET latin1 COLLATE latin1_general_cs );
Diese Tabellendefinition erstellt zwei Spalten namens
c1
und c2
. Für die
erste Spalte sind der Zeichensatz utf8
und die Standardsortierung für diesen Zeichensatz
festgelegt, für die zweite latin1
und
eine Sortierung mit Unterscheidung der
Groß-/Kleinschreibung.
MySQL 5.1 interpretiert Längenangaben in Zeichenspaltendefinitionen als Anzahl von Zeichen. (Früher wurde als Grundlage die Einheit Byte verwendet.)
Bei CHAR
, VARCHAR
und
den TEXT
-Typen wird, wenn das Attribut
BINARY
angegeben ist, der Spalte die
binäre Sortierung des spaltenspezifischen Zeichensatzes
zugewiesen. (In älteren Versionen konnte eine Spalte bei
Angabe von BINARY
binäre Strings
speichern.)
Sortierung und Vergleiche basieren bei Zeichenspalten auf
dem Zeichensatz, der der Spalte zugewiesen ist. (Früher
basierten Sortierung und Vergleich auf der Sortierung des
Serverzeichensatzes.) Bei CHAR
-und
VARCHAR
-Spalten können Sie eine binäre
Sortierung oder aber das Attribut BINARY
angeben, damit für Sortierung und Vergleiche statt der
lexikalen Reihenfolge die zugrunde liegenden
Zeichencodewerte benutzt werden.
Kapitel 10, Zeichensatz-Unterstützung, enthält weitere Informationen zur Verwendung von Zeichensätzen in MySQL.
[NATIONAL] CHAR(
M
)
[BINARY | ASCII | UNICODE]
Ein String fester Länge, der bei der Speicherung mit
Leerzeichen auf die angegebene Länge aufgefüllt wird.
M
steht für die Spaltenlänge.
M
liegt in einem Bereich zwischen
0 und 255 Zeichen.
Hinweis: Am Ende stehende
Leerzeichen werden beim Abrufen von
CHAR
-Werten entfernt.
Wenn Sie versuchen, die Länge einer
CHAR
-Spalte auf einen Wert größer 255
zu setzen, dann schlägt die CREATE
TABLE
- oder ALTER
TABLE
-Anweisung, mit der Sie dies tun, fehl und
gibt eine Fehlermeldung aus:
mysql>CREATE TABLE c1 (col1 INT, col2 CHAR(500));
ERROR 1074 (42000): Column length too big for column 'col' (max = 255); use BLOB or TEXT instead mysql>SHOW CREATE TABLE c1;
ERROR 1146 (42S02): Table 'test.c1' doesn't exist
CHAR
ist eine Abkürzung für
CHARACTER
. NATIONAL
CHAR
(und die äquivalente Kurzform
NCHAR
) ist bei SQL die Standardmethode,
um festzulegen, dass eine CHAR
-Spalte
einen bestimmten vordefinierten Zeichensatz verwendet. Seit
Version 4.1 ist utf8
bei MySQL dieser
vordefinierte Zeichensatz. Siehe
Abschnitt 10.3.6, „Nationaler Zeichensatz“.
Das Attribut BINARY
ist eine Kurzform zur
Festlegung der binären Sortierung des Spaltenzeichensatzes.
In diesem Fall basieren Sortierung und Vergleich auf
numerischen Zeichenwerten.
Das Attribut ASCII
ist eine Abkürzung
für CHARACTER SET latin1
.
Das Attribut UNICODE
ist eine Abkürzung
für CHARACTER SET ucs2
.
Der Datentyp CHAR BYTE
ist ein Alias für
den Typ BINARY
. Grund hierfür sind
Kompatibilitätsaspekte.
MySQL gestattet Ihnen die Erstellung einer Spalte des Typs
CHAR(0)
. Dies ist in erster Linie
praktisch, wenn eine Kompatibilität mit alten Anwendungen
erforderlich ist, die auf das Vorhandensein einer Spalte
angewiesen sind, aber deren Wert überhaupt nicht nutzen.
CHAR(0)
ist ferner recht praktisch, wenn
Sie eine Spalte benötigen, die nur zwei Werte annehmen
kann: Eine CHAR(0)
-Spalte, die nicht als
NOT NULL
definiert ist, besetzt genau ein
Bit und kann nur die Werte NULL
und
''
(Leer-String) aufnehmen.
CHAR
Dieser Typ ist synonym zu CHAR(1)
.
[NATIONAL] VARCHAR(
M
)
[BINARY]
Ein String variabler Länge. M
gibt die maximale Spaltenlänge an. Für
M
liegt der zulässige Bereich
zwischen 0 und 65.535. (Die tatsächliche Maximallänge
einer VARCHAR
-Spalte wird durch die
maximale Datensatzlänge und den von Ihnen verwendeten
Zeichensatz bestimmt. Die effektive
Maximallänge beträgt 65.532 Byte.)
Hinweis: MySQL
5.1 beachtet die Spezifikation des
SQL-Standards und entfernt am Anfang stehende Leerzeichen
aus VARCHAR
-Werten
nicht.
VARCHAR
ist eine Abkürzung für
CHARACTER VARYING
.
Das Attribut BINARY
ist eine Kurzform zur
Festlegung der binären Sortierung des Spaltenzeichensatzes.
In diesem Fall basieren Sortierung und Vergleich auf
numerischen Zeichenwerten.
VARCHAR
wird mit einem Präfix von 1 oder
2 Byte Länge und den Daten gespeichert. 2 Byte beträgt die
Länge des Präfixes, wenn die
VARCHAR
-Spalte mit einer Länge größer
255 deklariert wurde.
Der Typ BINARY
ähnelt
CHAR
, speichert aber Strings aus binären
Bytes statt nichtbinärer Zeichen-Strings.
Der Typ VARBINARY
ähnelt
VARCHAR
, speichert aber Strings aus
binären Bytes statt nichtbinärer Zeichen-Strings.
Eine BLOB
-Spalte mit einer Maximallänge
von 255 (28 – 1) Byte.
Eine TEXT
-Spalte mit einer Maximallänge
von 255 (28 – 1) Zeichen.
Eine BLOB
-Spalte mit einer Maximallänge
von 65.535 (216 – 1) Byte.
Für diesen Typ kann optional die Länge
M
angegeben werden. In diesem
Fall erstellt MySQL die Spalte mit dem kleinsten
BLOB
-Typ, der groß genug zur Aufnahme
von Werten mit einer Länge von M
Bytes ist.
Eine TEXT
-Spalte mit einer Maximallänge
von 65.535 (216 – 1)
Zeichen.
Für diesen Typ kann optional die Länge
M
angegeben werden. In diesem
Fall erstellt MySQL die Spalte mit dem kleinsten
TEXT
-Typ, der groß genug zur Aufnahme
von Werten mit einer Länge von M
Zeichen ist.
Eine BLOB
-Spalte mit einer Maximallänge
von 16.777.215 (224 – 1)
Byte.
Eine TEXT
-Spalte mit einer Maximallänge
von 16.777.215 (224 – 1)
Zeichen.
Eine BLOB
-Spalte mit einer Maximallänge
von 4.294.967.295 (232 – 1)
Byte (4 Gbyte). Die maximale effektive
(d. h. zulässige) Länge von
LONGBLOB
-Spalten hängt von der maximalen
Paketgröße im Client/Server-Protokoll und dem verfügbaren
Speicher ab.
Eine TEXT
-Spalte mit einer Maximallänge
von 4.294.967.295 (232 – 1)
Zeichen. Die maximale effektive (d. h.
zulässige) Länge von LONGTEXT
-Spalten
hängt von der maximalen Paketgröße im
Client/Server-Protokoll und dem verfügbaren Speicher ab.
Eine Auflistung. Es handelt sich dabei um ein String-Objekt,
das aus der Liste der Werte
'
,
value1
''
,
value2
'...
, NULL
und einem
speziellen Fehlerwert ''
genau einen Wert
auswählt. Eine ENUM
-Spalte kann maximal
65.535 verschiedene Werte aufweisen.
ENUM
-Werte werden intern als Integers
dargestellt.
Eine Menge. Es handelt sich um ein String-Objekt, dass null
oder mehr Werte haben kann, die jeweils aus der Werteliste
'
,
value1
''
,
value2
'...
stammen. Eine
SET
-Spalte kann maximal 64 Mitglieder
haben. SET
-Werte werden intern als
Integers dargestellt.
Die Klausel DEFAULT
in der Spezifikation
eines Datentyps gibt einen Vorgabewert für eine Spalte an. Mit
einer Ausnahme muss der Vorgabewert immer eine Konstante sein.
Funktionen oder Ausdrücke sind als Vorgaben nicht zulässig.
Das bedeutet, dass Sie beispielsweise als Vorgabewert einer
Datumsspalte nicht den Wert einer Funktion wie
value
NOW()
oder CURRENT_DATE
angeben dürfen. Die genannte Ausnahme besteht darin, dass Sie
CURRENT_TIMESTAMP
als Vorgabe für eine
TIMESTAMP
-Spalte festlegen können. Siehe
auch Abschnitt 11.3.1.1, „TIMESTAMP
-Eigenschaften ab MySQL 4.1“.
Für BLOB
- und
TEXT
-Spalten können keine Vorgaben
festgelegt werden.
Wenn eine Spaltendefinition keinen expliziten
DEFAULT
-Wert enthält, bestimmt MySQL diesen
wie folgt:
Wenn die Spalte NULL
als Wert annehmen kann,
wird sie mit einer expliziten DEFAULT
NULL
-Klausel definiert.
Kann die Spalte NULL
nicht als Wert annehmen,
dann definiert MySQL die Spalte ohne explizite
DEFAULT
-Klausel. Wenn bei der Dateneingabe
eine INSERT
- oder
REPLACE
-Anweisung keinen Wert für die Spalte
enthält, verarbeitet MySQL sie entsprechend dem zum
betreffenden Zeitpunkt gültigen SQL-Modus:
Wenn der strikte SQL-Modus nicht aktiviert ist, setzt MySQL die Spalte auf den impliziten Standardwert für den Datentyp der Spalte.
Ist der strikte Modus hingegen aktiv, dann erscheint bei transaktionssicheren Tabellen ein Fehler, und für die Anweisung wird ein Rollback durchgeführt. Bei nichttransaktionssicheren Tabellen erscheint ebenfalls ein Fehler; allerdings bleiben, wenn dies erst beim zweiten oder einem nachfolgenden Datensatz geschieht, zuvor eingefügte Datensätze erhalten.
Nehmen wir einmal an, eine Tabelle t
sei wie
folgt definiert:
CREATE TABLE t (i INT NOT NULL);
In diesem Fall hat i
keinen expliziten
Vorgabewert, d. h., im strikten Modus würde jede der folgenden
Anweisungen einen Fehler erzeugen, und es würde kein Datensatz
eingefügt. Wird der strikte Modus nicht verwendet, dann erzeugt
nur die dritte Anweisung einen Fehler; bei den ersten beiden
Anweisungen wird die implizite Vorgabe eingefügt, die dritte
Anweisung schlägt hingegen fehl, weil
DEFAULT(i)
keinen Wert erzeugen kann:
INSERT INTO t VALUES(); INSERT INTO t VALUES(DEFAULT); INSERT INTO t VALUES(DEFAULT(i));
Siehe auch Abschnitt 5.2.5, „Der SQL-Modus des Servers“.
Sie können für eine gegebene Tabelle die Anweisung
SHOW CREATE TABLE
verwenden, um anzuzeigen,
welche Spalten eine explizite DEFAULT
-Klausel
aufweisen.
MySQL unterstützt alle im SQL-Standard vorgesehen numerischen
Datentypen. Hierzu gehören exakte numerische Datentypen
(INTEGER
, SMALLINT
,
DECIMAL
und NUMERIC
) ebenso
wie annähernde Typen (FLOAT
,
REAL
und DOUBLE PRECISION
).
Das Schlüsselwort INT
ist ein Synonym für
DECIMAL
, und das Schlüsselwort
INTEGER
ist ein Synonym für
DEC
. Informationen zu den Speicheranforderungen
numerischer Typen finden Sie in
Abschnitt 11.5, „Speicherbedarf von Spaltentypen“.
Der Datentyp BIT
speichert Bitfeldwerte und
wird für MyISAM
-, MEMORY
-,
InnoDB
- und BDB
-Tabellen
unterstützt.
In Erweiterung des SQL-Standards unterstützt MySQL auch die
Integer-Typen TINYINT
,
MEDIUMINT
und BIGINT
. Die
folgende Tabelle zeigt den erforderlichen Speicherplatz und den
zulässigen Wertebereich der Integer-Typen.
Typ | Bytes | Minimum | Maximum |
(vorzeichenbehaftet/vorzeichenlos) | (vorzeichenbehaftet/vorzeichenlos) | ||
TINYINT | 1 | -128 | 127 |
0 | 255 | ||
SMALLINT | 2 | -32768 | 32767 |
0 | 65535 | ||
MEDIUMINT | 3 | -8388608 | 8388607 |
0 | 16777215 | ||
INT | 4 | -2147483648 | 2147483647 |
0 | 4294967295 | ||
BIGINT | 8 | -9223372036854775808 | 9223372036854775807 |
0 | 18446744073709551615 |
Eine andere Erweiterung wird von MySQL zur optionalen
Spezifizierung der Anzeigebreite eines Integer-Werts unterstützt.
Die Angabe erfolgt auf das Schlüsselwort für den Datentyp
folgend in Klammern (z. B. INT(4)
). Diese
optionale Angabe der Anzeigebreite wird verwendet, um die Anzeige
von Werten, die eine geringere als die für die Spalte festgelegte
Breite aufweisen, nach links mit Leerzeichen aufzufüllen.
Die Anzeigebreite schränkt weder die in einer Spalte speicherbaren Wertebereiche noch die Anzahl der Stellen ein, die für Werte angezeigt werden, deren Breite die festgelegte Spaltenbreite überschreitet.
Wenn hierzu das optionale Erweiterungsattribut
ZEROFILL
verwendet wird, erfolgt ein Auffüllen
nicht mehr mit Leerzeichen, sondern mit Nullen. Bei einer Spalte
etwa, die als INT(5) ZEROFILL
deklariert ist,
wird der Wert 4
als 00004
abgerufen. Beachten Sie, dass, wenn Sie Werte in einer
Integer-Spalte speichern, die größer sind als die Anzeigebreite,
unter Umständen Probleme auftauchen, wenn MySQL Temporärtabellen
für einige komplizierte Joins anlegt, denn in diesen Fällen
setzt MySQL voraus, dass die Daten in die ursprüngliche
Spaltenbreite passen.
Für alle Integer-Typen gibt es das (nicht standardkonforme)
Attribut UNSIGNED
. Vorzeichenlose Werte können
verwendet werden, wenn in einer Spalte nur nichtnegative Zahlen
zulässig sind und Sie für die Spalte einen nach oben erweiterten
numerischen Wertebereich benötigen. Wenn beispielsweise eine
INT
-Spalte als UNSIGNED
deklariert wird, ist die Spaltengröße gleich; zulässige Werte
entstammen nun aber nicht mehr dem Bereich zwischen
-2147483648
und 2147483647
,
sondern dem Bereich zwischen 0
und
4294967295
.
Auch Fließkommazahlen und Festkommazahlen können vorzeichenlos sein. Wie bei Integer-Typen verhindert dieses Attribut die Speicherung negativer Werte in der Spalte. Anders als bei jenen aber bleibt das Maximum für die Spaltenwerte unverändert.
Wenn Sie ZEROFILL
für eine numerische Spalte
angeben, fügt MySQL automatisch das Attribut
UNSIGNED
für die Spalte hinzu.
Bei Fließkommadatentypen verwendet MySQL 4 Byte für Werte einfacher und 8 Byte für Werte doppelter Genauigkeit.
Die Datentypen FLOAT
und
DOUBLE
werden zur Darstellung annähernder
numerischer Datenwerte verwendet. Für FLOAT
gestattet der SQL-Standard optional die Angabe der Genauigkeit
(nicht aber des Bereichs des Exponenten) in Bits, die dem
Schlüsselwort FLOAT
in Klammern folgen. Auch
MySQL unterstützt diese optionale Genauigkeitsangabe, der
Genauigkeitswert wird allerdings nur zur Bestimmung der
Speichergröße verwendet. Eine Genauigkeit von 0 bis 23 hat eine
vier Byte lange FLOAT
-Spalte mit einfacher
Genauigkeit zum Ergebnis. Bei einer Genauigkeit von 24 bis 53
entsteht eine acht Byte lange DOUBLE
-Spalte mit
doppelter Genauigkeit.
MySQL gestattet eine nicht standardkonforme Syntax:
FLOAT(
oder
M
,D
)REAL(
oder M
,D
)DOUBLE
PRECISION(
.
Hierbei bedeutet
„M
,D
)(
“,
dass Werte mit bis zu M
,D
)M
Stellen
insgesamt angezeigt werden, wovon D
Nachkommastellen sind. Beispielsweise erscheint eine Spalte, die
als FLOAT(7,4)
definiert wurde, in der Anzeige
als -999.9999
. MySQL führt die Rundung beim
Speichern der Werte durch, d. h. wenn Sie
999.00009
in einer
FLOAT(7,4)
-Spalte einfügen, ist das Ergebnis
näherungsweise 999.0001
.
MySQL behandelt DOUBLE
als Synonym für
DOUBLE PRECISION
(dies ist eine nicht
standardkonforme Erweiterung). Ferner behandelt MySQL
REAL
als Synonym für DOUBLE
PRECISION
(nicht standardkonforme Variante), sofern der
SQL-Modus REAL_AS_FLOAT
nicht aktiviert ist.
Wenn Sie maximale Portabilität benötigen, sollten Sie in Code,
in dem die Speicherung annähernder numerischer Datenwerte
erforderlich ist, FLOAT
oder DOUBLE
PRECISION
ohne Angabe der Genauigkeit oder der Stellen
verwenden.
Die Datentypen DECIMAL
und
NUMERIC
werden zur Speicherung exakter
numerischer Datenwerte verwendet. In MySQL ist
NUMERIC
als DECIMAL
implementiert. Diese Typen werden zur Speicherung von Werten
benutzt, bei denen die Beibehaltung der exakten Genauigkeit
entscheidend ist (z. B. bei Finanzberechnungen).
MySQL 5.1 speichert DECIMAL
- und
NUMERIC
-Werte im binären Format. In älteren
Versionen erfolgte die Speicherung als Strings. Siehe auch
Kapitel 23, Präzisionsberechnungen.
Wenn Sie eine DECIMAL
- oder
NUMERIC
-Spalte deklarieren, können (und
sollten) Genauigkeit und Anzahl der Nachkommastellen angegeben
werden. Zum Beispiel:
salary DECIMAL(5,2)
In diesem Beispiel ist 5
die Genauigkeit und
2
die Anzahl der Nachkommastellen. Die
Genauigkeit stellt die Anzahl der signifikanten Stellen dar, die
für Werte gespeichert werden. Ist für die Nachkommastellen 0
festgelegt, dann haben DECIMAL
- und
NUMERIC
-Werte keinen Dezimalpunkt und keine
Nachkommastellen.
Der SQL-Standard erfordert, dass die Spalte
salary
jeden Wert mit fünf Stellen und zwei
Nachkommastellen speichern können muss. Dies bedeutet also, dass
der in der Spalte salary
speicherbare
Wertebereich zwischen -999.99
und
999.99
liegt.
Beim SQL-Standard ist die Syntax
DECIMAL(
gleichbedeutend mit
M
)DECIMAL(
.
Ähnlich hat die Syntax M
,0)DECIMAL
die gleiche
Bedeutung wie
DECIMAL(
, wobei
der Implementierung die Entscheidung zum Wert von
M
,0)M
überlassen bleibt. MySQL
unterstützt diese beiden Varianten der
DECIMAL
- und NUMERIC
-Syntax.
Der Vorgabewert von M
ist 10.
Die maximale Anzahl von Stellen für DECIMAL
oder NUMERIC
beträgt 65, der tatsächliche
Bereich für eine gegebene DECIMAL
- oder
NUMERIC
-Spalte kann jedoch durch die Angaben
für Genauigkeit oder Nachkommastellen eingeschränkt werden. Wenn
einer solchen Spalte ein Wert mit mehr Nachkommastellen als
zulässig zugewiesen wird, dann wird der Wert der zulässigen
Anzahl Nachkommastellen angepasst. (Das exakte Verhalten ist
betriebssystemspezifisch, aber in der Regel werden überzählige
Nachkommastellen einfach abgeschnitten.)
Der Datentyp BIT
wird zur Speicherung von
Bitfeldwerten verwendet. Der Typ
BIT(
gestattet die
Speicherung von M
)M
-Bit-Werten. Dabei
kann M
in einem Bereich zwischen 1 und
64 liegen.
Zur Angabe von Bitwerten kann die Notation
b'
verwendet
werden. value
'value
ist ein Binärwert, der
aus Einsen und Nullen besteht. So stehen etwa
b'111'
und b'100000000'
für
die Zahlen 7 bzw. 128. Siehe auch
Abschnitt 9.1.5, „Bitfeldwerte“.
Wenn Sie einer
BIT(
-Spalte einen
Wert zuweisen, der weniger als M
)M
Bits
lang ist, dann wird der Wert nach links mit Nullen aufgefüllt. So
entspricht die Zuweisung des Werts b'101'
an
eine Spalte BIT(6)
im Endeffekt der Zuweisung
von b'000101'
.
Wenn MySQL einen Wert in einer numerischen Spalte speichern soll,
der außerhalb des für den Datentyp zulässigen Bereichs liegt,
dann hängt das Verhalten von MySQL von dem zum betreffenden
Zeitpunkt aktiven SQL-Modus ab. Wenn etwa keine restriktiven Modi
aktiviert sind, setzt MySQL den Wert auf den jeweiligen Endwert
des Bereichs und speichert dann diesen Wert. Wenn als Modus jedoch
TRADITIONAL
aktiviert ist, weist MySQL einen
Wert außerhalb des Bereichs mit einer Fehlermeldung ab. In diesem
Fall schlägt die Einfügeoperation fehl – ganz so, wie es der
SQL-Standard vorsieht.
Wird im nichtstrikten Modus einer Integer-Spalte ein Wert
außerhalb des zulässigen Bereichs zugewiesen, dann speichert
MySQL den Wert, der dem entsprechenden Endpunkt für den Datentyp
der Spalte entspricht. Speichern Sie also etwa 256 in einer
TINYINT
- oder TINYINT
UNSIGNED
-Spalte, dann speichert MySQL 255 bzw. 127. Wird
einer Fließkomma- oder Festkommaspalte ein Wert außerhalb des
durch die angegebene (oder vorgabeseitige) Genauigkeit und
Nachkommastellenanzahl festgelegten Bereichs zugewiesen, dann
speichert MySQL ebenfalls den für diesen Bereich vorgesehenen
Endpunkt:
Konvertierungen, die aufgrund von Kürzungsoperationen
stattfinden, wenn MySQL nicht im strikten Modus läuft, werden als
Warnungen für ALTER TABLE
-, LOAD DATA
INFILE
- und UPDATE
-Anweisungen sowie
INSERT
-Anweisungen für mehrere Datensätze
gemeldet. Wenn MySQL im strikten Modus ausgeführt wird, schlagen
diese Anweisungen fehl, und einige oder alle Werte werden nicht
eingefügt bzw. geändert (dies hängt davon, ob die Tabelle
transaktionssicher ist, sowie von weiteren Faktoren ab).
Detaillierte Informationen finden Sie in
Abschnitt 5.2.5, „Der SQL-Modus des Servers“.
Datentypen für Datum und Uhrzeit erlauben die Darstellung
zeitlicher Werte. In diese Kategorie fallen die Typen
DATETIME
, DATE
,
TIMESTAMP
, TIME
und
YEAR
. Jeder zeitbezogene Typ hat einen Bereich
zulässiger Werte sowie einen „Nullwert“, der
verwendet werden kann, wenn Sie einen unzulässigen Wert angeben,
den MySQL nicht darstellen kann. Der Typ
TIMESTAMP
unterstützt ein spezielles Verhalten
der automatischen Aktualisierung, welches im weiteren Verlauf
beschrieben werden wird. Informationen zu den
Speicheranforderungen zeitbezogener Typen finden Sie in
Abschnitt 11.5, „Speicherbedarf von Spaltentypen“.
MySQL gibt Warnungen oder Fehler aus, wenn Sie einen unzulässigen
Wert einzufügen versuchen. Indem Sie den passenden SQL-Modus
wählen, können Sie genauer festlegen, welche Datenarten MySQL
unterstützen soll. (Siehe auch
Abschnitt 5.2.5, „Der SQL-Modus des Servers“.) Wenn Sie etwa den Modus
ALLOW_INVALID_DATES
verwenden, akzeptiert MySQL
auch bestimmte irreale Daten wie '1999-11-31'
.
Dies ist praktisch, wenn Sie einen „möglicherweise
falschen“ Wert, den ein Benutzer eingegeben hat (z. B. in
ein Webformular), für die zukünftige Verarbeitung in der
Datenbank speichern wollen. In diesem Modus überprüft MySQL
lediglich, ob der Monat im Bereich zwischen 0 und 12 und der Tag
im Bereich zwischen 0 und 31 liegt. Diese Bereiche umfassen
deswegen die Null, weil MySQL in DATE
- oder
DATETIME
-Spalten auch die Speicherung von
Datumsangaben gestattet, bei denen der Tag oder der Monat und der
Tag null sind. Dies ist recht nützlich bei Anwendungen, die ein
Geburtsdatum speichern sollen, das Sie nicht genau kennen. In
diesem Fall speichern Sie das Datum einfach als
'1999-00-00'
oder
'1999-01-00'
. Wenn Sie Datumsangaben auf diese
Weise speichern, können Sie nicht davon ausgehen, für Funktionen
wie DATE_SUB()
oder DATE_ADD
korrekte Ergebnisse zu erhalten, denn diese erfordern
vollständige Datumsangaben. (Wenn Sie Nullen in Daten
nicht erlauben wollen, können Sie den
SQL-Modus NO_ZERO_IN_DATE
aktivieren.)
MySQL gestattet ferner die Speicherung von
'0000-00-00'
als „Pseudodatum“
(hierfür darf der SQL-Modus NO_ZERO_DATE
jedoch nicht aktiv sein). Dies ist in bestimmten Fällen bequemer
(und benötigt zudem weniger Speicher für Daten und Indizes) als
die Verwendung von NULL
-Werten.
Es folgen einige Gesichtspunkte, die Sie bei der Arbeit mit Datentypen für Datum und Uhrzeit beachten sollten:
MySQL ruft Werte für einen Datentyp für Datum und Uhrzeit in einem Standardausgabeformat ab, versucht aber eine Vielzahl von Eingabewertformaten zu verarbeiten, die von Ihnen eingegeben wurden (z. B. wenn Sie einen Wert angeben, der einem zeitbezogenen Typ zugewiesen oder mit diesem verglichen werden soll). Nur die in den folgenden Abschnitten beschriebenen Formate werden unterstützt. Es wird erwartet, dass Sie zulässige Werte angeben. Wenn Sie Werte in anderen Formaten angeben, können unvorhersehbare Ergebnisse die Folge sein.
Datumsangaben mit zwei Stellen für die Jahreszahl sind mehrdeutig, da das Jahrhundert unbekannt ist. MySQL interpretiert Werte mit zweistelligen Jahreszahlen gemäß den folgenden Regeln:
Jahreszahlen im Bereich zwischen 70 und 99 werden als
1970-1999
interpretiert.
Jahreszahlen im Bereich zwischen 00 und 69 werden als
2000-2069
interpretiert.
Zwar versucht MySQL, Werte in verschiedenen Formaten zu
interpretieren, aber Datumsangaben müssen immer in der
Reihenfolge Jahr, Monat, Tag angegeben werden (z. B.
'98-09-04'
); die Reihenfolge Monat, Tag,
Jahr ('09-04-98'
) oder die im
deutschsprachigen Raum verwendete Reihenfolge Tag, Monat, Jahr
('04-09-98'
) werden nicht unterstützt.
MySQL konvertiert Werte eines zeitbezogenen Typs automatisch in eine Zahl, wenn der Wert in einem numerischen Kontext verwendet werden soll (und umgekehrt).
Wenn MySQL auf einen zeitbezogenen Wert trifft, der außerhalb
des zulässigen Bereichs liegt oder für den betreffenden Typ
anderweitig ungültig ist, wird dieser in den
„Nullwert“ des betreffenden Typs umgewandelt.
Eine Ausnahme liegt bei TIME
-Werten
außerhalb des gültigen Bereichs vor: Diese werden auf den
entsprechenden Endpunkt des TIME
-Bereichs
gesetzt.
Die folgende Tabelle zeigt das Format der
„Nullwerte“ für die einzelnen Typen. Beachten
Sie, dass die Verwendung dieser Werte Warnungen erzeugt, wenn
der SQL-Modus NO_ZERO_DATE
aktiviert ist.
Datentyp | „Nullwert“ |
DATETIME | '0000-00-00 00:00:00' |
DATE | '0000-00-00' |
TIMESTAMP | '0000-00-00 00:00:00' |
TIME | '00:00:00' |
YEAR | 0000 |
Die „Nullwerte“ sind zwar speziell, aber Sie
können sie speichern oder explizit referenzieren, indem Sie
die Werte in der Tabelle verwenden. Alternativ können Sie
dies auch unter Verwendung der Werte '0'
oder 0
tun, die einfacher zu schreiben
sind.
„Nullwerte“ für Datum und Uhrzeit, die über
MyODBC verwendet werden, werden ab MyODBC 2.50.12 automatisch
zu NULL
konvertiert, da ODBC mit solchen
Werten nicht umgehen kann.
Die Typen DATETIME
, DATE
und TIMESTAMP
gehören zusammen. In diesem
Abschnitt werden ihre Eigenschaften sowie Gemeinsamkeiten und
Unterschiede beschrieben.
Den Typ DATETIME
verwenden Sie, wenn Sie
Werte benötigen, die sowohl ein Datum als auch eine Uhrzeit
enthalten. MySQL ruft DATETIME
-Werte im
Format 'YYYY-MM-DD HH:MM:SS'
ab und zeigt sie
auch so an. Der unterstützte Bereich liegt zwischen
'1000-01-01 00:00:00'
und
'9999-12-31 23:59:59'
.
(„Unterstützt“ bedeutet hier, dass früher
liegende Werte zwar funktionieren können, dies aber nicht
garantiert ist.)
Der Typ DATE
erlaubt die Benutzung eines
Datums ohne Zeitangabe. MySQL ruft DATE
-Werte
im Format 'YYYY-MM-DD'
ab und zeigt sie auch
so an. Der unterstützte Bereich liegt zwischen
'1000-01-01'
und
'9999-12-31'
.
Der Datentyp TIMESTAMP
schließlich hat je
nach MySQL-Version und SQL-Modus des Servers verschiedene
Eigenschaften, die im Verlauf dieses Abschnitts noch beschrieben
werden.
Sie können DATETIME
-,
DATE
- und TIMESTAMP
-Werte
mit einem der folgenden gängigen Formate angeben:
Als String im Format 'YYYY-MM-DD
HH:MM:SS'
oder 'YY-MM-DD
HH:MM:SS'
. Eine weniger strikte Syntax ist
ebenfalls erlaubt: Ein beliebiges Interpunktionszeichen darf
als Trennzeichen zwischen Datums- oder Zeiteinheiten benutzt
werden. Beispielsweise sind '98-12-31
11:30:45'
, '98.12.31 11+30+45'
,
'98/12/31 11*30*45'
und
'98@12@31 11^30^45'
gleichwertig.
Als String im Format 'YYYY-MM-DD'
oder
'YY-MM-DD'
. Eine weniger strikte Syntax
ist auch hier erlaubt. Beispielsweise sind
'98-12-31'
,
'98.12.31'
, '98/12/31'
und '98@12@31'
gleichwertig.
Als String ohne Trennzeichen in den Formaten
'YYYYMMDDHHMMSS'
oder
'YYMMDDHHMMSS'
, sofern der String als
Datum sinngebend ist. Zum Beispiel werden
'19970523091528'
und
'970523091528'
als '1997-05-23
09:15:28'
interpretiert, aber
'971122129015'
ist unzulässig (der
Minutenanteil ist unsinnig) und wird deswegen zu
'0000-00-00 00:00:00'
.
Als String ohne Trennzeichen in den Formaten
'YYYYMMDD'
oder
'YYMMDD'
, sofern der String als Datum
sinngebend ist. Zum Beispiel werden
'19970523'
und
'970523'
als
'1997-05-23'
interpretiert, aber
'971332'
ist unzulässig (der Tages- und
der Minutenanteil sind unsinnig) und wird deswegen zu
'0000-00-00'
.
Als Zahl in den Formaten YYYYMMDDHHMMSS
oder YYMMDDHHMMSS
, sofern die Zahl als
Datum sinngebend ist. Beispielsweise werden sowohl
19830905132800
als auch
830905132800
als '1983-09-05
13:28:00'
interpretiert.
Als Zahl in den Formaten YYYYMMDD
oder
YYMMDD
, sofern die Zahl als Datum
sinngebend ist. Beispielsweise werden sowohl
19830905
als auch
830905
als
'1983-09-05'
interpretiert.
Als Ergebnis einer Funktion, die einen Wert zurückgibt, der
im Kontext von DATETIME
,
DATE
oder TIMESTAMP
sinngebend ist, z. B. NOW()
oder
CURRENT_DATE
.
Unzulässige DATETIME
-,
DATE
- oder TIMESTAMP
-Werte
werden in den „Nullwert“ des entsprechenden Typs
umgewandelt ('0000-00-00 00:00:00'
oder
'0000-00-00'
).
Bei als Strings angegebenen Werten, die Trennzeichen für
Datumsbestandteile enthalten, ist es nicht erforderlich, zwei
Stellen für Monats- oder Tageswerte anzugeben, die kleiner als
10
sind. So wird etwa
'1979-6-9'
als
'1979-06-09'
ausgewertet. Ähnlich ist es bei
als Strings angegebenen Werten, die Trennzeichen für
Uhrzeitbestandteile enthalten, nicht erforderlich, zwei Stellen
für Stunden-, Minuten oder Sekundenwerte anzugeben, die kleiner
als 10
sind: '1979-10-30
01:02:03'
ist das Gleiche wie '1979-10-30
1:2:3'
.
Als Zahlen angegebene Werte sollten eine Länge von 6, 8, 12
oder 14 Stellen haben. Wenn eine Zahl 8 oder 14 Stellen lang
ist, werden die Formate YYYYMMDD
bzw.
YYYYMMDDHHMMSS
angenommen, wobei das Jahr
durch die ersten vier Stellen angegeben wird. Umfasst die Zahl 6
oder 12 Stellen, dann werden die Formate
YYMMDD
bzw. YYMMDDHHMMSS
angenommen, wobei das Jahr durch die ersten beiden Stellen
angegeben ist. Zahlen, die eine andere Länge aufweisen, werden
so interpretiert, als ob sie am Anfang mit Nullen auf die
nächste Länge aufgefüllt würden.
Werte, die als Strings ohne Trennzeichen angegeben werden,
werden entsprechend ihrer Länge interpretiert. Ist der String 8
oder 14 Zeichen lang, dann wird angenommen, dass die ersten vier
Zeichen das Jahr angeben. Andernfalls wird die Jahresangabe
durch die ersten zwei Zeichen erwartet. Der String wird von
links nach rechts interpretiert, als Reihenfolge wird Jahr,
Monat, Tag, Stunde, Minute und Sekunde angenommen – je
nachdem, wie viele Bestandteil im String vorhanden sind. Das
bedeutet, dass Sie niemals Strings mit weniger als sechs Zeichen
verwenden sollten. Wenn Sie beispielsweise
'9903'
angeben, um den März 1999
darzustellen, dann fügt MySQL einen „Nullwert“
für das Datum in Ihre Tabelle ein. Dies geschieht, weil die
Jahres- und Monatsangaben 99
bzw.
03
sind, der Tag aber vollständig fehlt: Der
Wert ist kein gültiges Datum. Sie können jedoch ausdrücklich
einen Wert Null zur Darstellung fehlender Monats- oder
Tagesangaben spezifizieren. So können Sie etwa
'990300'
verwenden, um den Wert
'1999-03-00'
einzufügen.
Sie können bis zu einem gewissen Grad Werte eines Datumstyps einem Objekt zuweisen, welches von einem anderen Datumstyp ist. Allerdings kann es hierdurch zu Werteänderungen oder Datenverlust kommen:
Wenn Sie einen DATE
-Wert einem
DATETIME
- oder
TIMESTAMP
-Objekt zuweisen, wird die
Uhrzeit des resultierenden Werts auf
'00:00:00'
gesetzt, da
DATE
diese Information nicht enthält.
Wenn Sie einen DATETIME
- oder
TIMESTAMP
-Wert einem
DATE
-Objekt zuweisen, wird die Uhrzeit
des resultierenden Werts gelöscht, weil der Typ
DATE
diese Information nicht speichert.
Beachten Sie, dass DATETIME
-,
DATE
- und
TIMESTAMP
-Werte zwar alle in denselben
Formatvarianten angegeben werden können, aber die Typen
nicht dieselben Wertebereiche aufweisen. So kann ein
TIMESTAMP
-Wert nicht vor
1970
und nicht nach
2037
liegen. Das bedeutet, dass ein Datum
wie '1968-01-01'
zwar als
DATETIME
- und
DATE
-Wert zulässig, als
TIMESTAMP
-Wert jedoch illegal ist und
deswegen zu 0
konvertiert wird.
Beachten Sie die folgenden Widrigkeiten bei der Angabe von Datumswerten:
Das weniger strikte Format, welches die Angabe von Werten
als Strings gestattet, kann heimtückisch sein. So sieht
etwa ein Wert wie '10:11:12'
wegen des
als Trennzeichen verwendeten Doppelpunkts
(‘:
’) wie eine Uhrzeit aus,
in einem Datumskontext wird er jedoch als
'2010-11-12'
interpretiert. Der Wert
'10:45:15'
wird zu
'0000-00-00'
konvertiert, weil
'45'
kein zulässiger Monat ist.
Für den Server ist es erforderlich, dass Monats- und
Tagesangaben gültig sind und sich nicht einfach nur in den
Bereichen 1 bis 12 bzw. 1 bis 31 bewegen. Wenn der strikte
Modus deaktiviert ist, werden ungültige Daten wie
'2004-04-31'
in
'0000-00-00'
umgewandelt, und es wird
eine Warnung erzeugt. Ist der strikte Modus hingegen
aktiviert, dann erzeugen ungültige Datumsangaben einen
Fehler. Um derartige Daten zuzulassen, aktivieren Sie
ALLOW_INVALID_DATES
. Weitere
Informationen finden Sie in
Abschnitt 5.2.5, „Der SQL-Modus des Servers“.
Datumsangaben mit zwei Stellen für die Jahreszahl sind mehrdeutig, da das Jahrhundert unbekannt ist. MySQL interpretiert Werte mit zweistelligen Jahreszahlen gemäß den folgenden Regeln:
Jahreszahlen im Bereich zwischen 00 und 69 werden als
2000-2069
interpretiert.
Jahreszahlen im Bereich zwischen 70 und 99 werden als
1970-1999
interpretiert.
Hinweis: Bei älteren
MySQL-Versionen (vor 4.1) unterscheiden sich die Eigenschaften
des Datentyps TIMESTAMP
erheblich von dem,
was in diesem Abschnitt beschrieben wurde. Wenn Sie ältere
TIMESTAMP
-Daten konvertieren müssen, damit
sie in MySQL 5.1 funktionieren, lesen Sie in
jedem Fall die einschlägigen Abschnitte im
MySQL-Referenzhandbuch für die Versionen 3.23, 4.0
und 4.1.
TIMESTAMP
-Spalten werden im selben Format
angezeigt wie DATETIME
-Spalten. Mit anderen
Worten ist die Anzeigebreite auf 19 Zeichen festgesetzt, und
das Format lautet YYYY-MM-DD HH:MM:SS
.
Der MySQL Server kann auch mit aktiviertem SQL-Modus
MAXDB
laufen. Wenn am Server dieser Modus
aktiv ist, ist TIMESTAMP
mit
DATETIME
identisch. Das bedeutet, dass,
wenn dieser Modus zum Zeitpunkt der Erstellung einer Tabelle
aktiviert ist, TIMESTAMP
-Spalten als
DATETIME
-Spalten erstellt werden. Aufgrund
dessen verwenden solche Spalten das
DATETIME
-Anzeigeformat und haben denselben
Wertebereich, und es gibt keine automatische Initialisierung
oder Aktualisierung auf die aktuellen Werte für Datum und
Uhrzeit.
Um den Modus MAXDB
zu aktivieren, setzen
Sie entweder den SQL-Modus des Servers beim Start mit der
Serveroption --sql-mode=MAXDB
auf
MAXDB
, oder Sie stellen die globale
Variable sql_mode
zur Laufzeit ein:
mysql> SET GLOBAL sql_mode=MAXDB;
Ein Client kann den Server auch so einstellen, dass die eigene
Verbindung im MAXDB
-Modus läuft:
mysql> SET SESSION sql_mode=MAXDB;
Beachten Sie, dass die Informationen im nachfolgenden
Abschnitt nur für TIMESTAMP
-Spalten in
solchen Tabellen gelten, die nicht mit
MAXDB
als aktivem Modus erstellt wurden,
weil solche Spalten als DATETIME
-Spalten
erstellt werden.
MySQL akzeptiert keine Zeitstempelwerte, die eine Null in der
Tages- oder Monatsspalte oder andere Werte enthalten, die kein
gültiges Datum darstellen. Die einzige Ausnahme dieser Regel
ist der Sonderwert '0000-00-00 00:00:00'
.
Bei der Bestimmung, wann die automatische
TIMESTAMP
-Initialisierung und
-Aktualisierung erfolgen soll und welche Spalten dieses
Verhalten aufweisen sollen, verfügen Sie über ausgesprochen
viel Flexibilität:
Für eine TIMESTAMP
-Spalte in einer
Tabelle können Sie den aktuellen Zeitstempel als
Standardwert und Wert für die automatische Aktualisierung
angeben. Es ist möglich, den aktuellen Zeitstempel als
Vorgabewert für die Initialisierung der Spalte und/oder
als Wert für die automatische Aktualisierung zu
verwenden. Es ist jedoch nicht möglich, den aktuellen
Zeitstempel als Vorgabewert für eine Spalte und als Wert
für die automatische Aktualisierung einer anderen Spalte
zu verwenden.
Sie können festlegen, welche
TIMESTAMP
-Spalte sich automatisch
initialisieren oder auf die aktuellen Werte für Datum und
Uhrzeit setzen soll. Dies muss nicht unbedingt die erste
TIMESTAMP
-Spalte sein.
Die folgenden Regeln bestimmen die Initialisierung und
Aktualisierung von TIMESTAMP
-Spalten:
Wird ein DEFAULT
-Wert für die erste
TIMESTAMP
-Spalte in einer Tabelle
festgelegt, so wird dieser nicht ignoriert. Als Vorgabe
kann CURRENT_TIMESTAMP
oder ein
konstanter Wert für Datum und Uhrzeit verwendet werden.
DEFAULT NULL
ist bei der
ersten
TIMESTAMP
-Spalte dasselbe wie
DEFAULT CURRENT_TIMESTAMP
. Bei jeder
anderen TIMESTAMP
-Spalte hingegen wird
DEFAULT NULL
als DEFAULT
0
behandelt.
Jede einzelne TIMESTAMP
-Spalte in einer
Tabelle kann als diejenige benutzt werden, die mit dem
aktuellen Zeitstempel initialisiert oder automatisch
aktualisiert wird.
In einer CREATE TABLE
-Anweisung kann
die erste TIMESTAMP
-Spalte auf eine der
folgenden Weisen deklariert werden:
Wenn sowohl DEFAULT
CURRENT_TIMESTAMP
- als auch ON
UPDATE CURRENT_TIMESTAMP
-Klauseln vorhanden
sind, dann hat die Spalte den aktuellen Zeitstempel
als Vorgabewert und wird automatisch aktualisiert.
Fehlen sowohl DEFAULT
- als auch
ON UPDATE
-Klausel, dann ist dies
das Gleiche wie DEFAULT CURRENT_TIMESTAMP ON
UPDATE CURRENT_TIMESTAMP
.
Mit DEFAULT CURRENT_TIMESTAMP
-,
aber ohne ON UPDATE
-Klausel hat die
Spalte den aktuellen Zeitstempel als Vorgabewert, wird
jedoch nicht automatisch aktualisiert.
Ohne DEFAULT
-, aber mit ON
UPDATE CURRENT_TIMESTAMP
-Klausel hat die
Spalte den Standardwert 0 und wird automatisch
aktualisiert.
Bei einem konstanten DEFAULT
-Wert
erhält die Spalte den angegebenen Standardwert. Wenn
die Spalte eine ON UPDATE
CURRENT_TIMESTAMP
-Klausel hat, wird sie
automatisch aktualisiert, andernfalls nicht.
Anders gesagt: Sie können den aktuellen Zeitstempel
sowohl als Initialisierungs- als auch als
Aktualisierungswert, als einen dieser beiden Werte oder
gar nicht verwenden. (So können Sie beispielsweise
ON UPDATE
angeben, um die automatische
Aktualisierung zu aktivieren, ohne dass die Spalte
automatisch initialisiert werden müsste.)
CURRENT_TIMESTAMP
,
CURRENT_TIMESTAMP()
und
NOW()
können gleichermaßen in
DEFAULT
- und ON
UPDATE
-Klauseln verwendet werden. Sie alle haben
die Bedeutung „aktueller Zeitstempel“.
Die Reihenfolge der DEFAULT
- und
ON UPDATE
-Attribute ist unerheblich.
Wenn sowohl DEFAULT
als auch
ON UPDATE
für eine
TIMESTAMP
-Spalte angegeben werden, kann
das eine Attribut vor oder hinter dem anderen stehen. So
sind beispielsweise die folgenden Anweisungen
gleichwertig:
CREATE TABLE t (ts TIMESTAMP); CREATE TABLE t (ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP); CREATE TABLE t (ts TIMESTAMP ON UPDATE CURRENT_TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
Um für eine andere als die erste
TIMESTAMP
-Spalte die automatische
Initialisierung oder Aktualisierung festzulegen, müssen
Sie dieses Verhalten für die erste
TIMESTAMP
-Spalte unterdrücken. Dies
tun Sie, indem Sie ihr explizit einen konstanten
DEFAULT
-Wert zuweisen (z. B.
DEFAULT 0
oder DEFAULT
'2003-01-01 00:00:00'
). Nachfolgend gelten für
die andere TIMESTAMP
-Spalte dieselben
Regeln wie für die erste; die einzige Ausnahme besteht
darin, dass, wenn Sie sowohl DEFAULT
als auch ON UPDATE
weglassen, keine
automatische Initialisierung oder Aktualisierung erfolgt.
So sind beispielsweise die folgenden Anweisungen gleichwertig:
CREATE TABLE t ( ts1 TIMESTAMP DEFAULT 0, ts2 TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP); CREATE TABLE t ( ts1 TIMESTAMP DEFAULT 0, ts2 TIMESTAMP ON UPDATE CURRENT_TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
Sie können die aktuelle Zeitzone für jede Verbindung separat
einstellen (siehe Beschreibung in
Abschnitt 5.11.8, „Zeitzonen-Unterstützung des MySQL-Servers“).
TIMESTAMP
-Werte werden in UTC gespeichert;
zur Speicherung werden sie aus der aktuellen Zeitzone
konvertiert und beim Abrufen wieder in die aktuelle Zeitzone
zurückkonvertiert. Solange die Zeitzoneneinstellung gleich
bleibt, erhalten Sie denselben Wert zurück, den Sie auch
gespeichert haben. Wenn Sie einen
TIMESTAMP
-Wert speichern, dann die Zeitzone
ändern und den Wert abrufen, unterscheidet sich dieser
abgerufene vom gespeicherten Wert. Grund hierfür ist die
Tatsache, dass unterschiedliche Zeitzonen für die beiden
Konvertierungsvorgänge benutzt wurden. Die aktuelle Zeitzone
ist über den Wert der Systemvariablen
time_zone
verfügbar.
Sie können das Attribut NULL
in die
Definition einer TIMESTAMP
-Spalte
einfügen, damit die Spalte auch NULL
-Werte
enthalten kann. Zum Beispiel:
CREATE TABLE t ( ts1 TIMESTAMP NULL DEFAULT NULL, ts2 TIMESTAMP NULL DEFAULT 0, ts3 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP );
Wenn das Attribut NULL
nicht angegeben
wurde und die Spalte auf NULL
gesetzt wird,
wird sie automatisch auf den aktuellen Zeitstempel umgestellt.
Beachten Sie, dass eine TIMESTAMP
-Spalte,
die NULL
-Werte gestattet, den aktuellen
Zeitstempel nur unter einer der folgenden
Bedingungen annimmt:
Ihr Vorgabewert ist als
CURRENT_TIMESTAMP
definiert.
NOW()
oder
CURRENT_TIMESTAMP
werden in die Spalte
eingefügt.
Mit anderen Worten: Eine TIMESTAMP
-Spalte,
die als NULL
definiert ist, wird nur dann
automatisch aktualisiert, wenn sie unter Verwendung einer
Definition wie der folgenden erstellt wurde:
CREATE TABLE t (ts TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP);
Betrachten Sie im Unterschied dazu folgende Definition einer
TIMESTAMP
-Spalte, die
NULL
-Werte erlaubt, DEFAULT
TIMESTAMP
aber nicht verwendet:
CREATE TABLE t1 (ts TIMESTAMP NULL DEFAULT NULL); CREATE TABLE t2 (ts TIMESTAMP NULL DEFAULT '0000-00-00 00:00:00');
In diesem Fall müssen Sie explizit einen Wert einfügen, der den aktuellen Werten für Datum und Uhrzeit entspricht. Zum Beispiel:
INSERT INTO t1 VALUES (NOW()); INSERT INTO t2 VALUES (CURRENT_TIMESTAMP);
Abruf und Anzeige von TIME
-Werten durch MySQL
erfolgen im Format 'HH:MM:SS'
(oder im Format
'HHH:MM:SS'
bei einer großen Zahl von
Stunden). TIME
-Werte liegen in einem Bereich
zwischen '-838:59:59'
und
'838:59:59'
. Der Stundenteil kann so groß
sein, weil TIME
nicht nur eine Uhrzeit
darstellen kann (diese muss kleiner sein als 24 Stunden),
sondern auch die verstrichene Zeit oder ein Zeitintervall
zwischen zwei Ereignissen. Ein solches Intervall kann wesentlich
länger als 24 Stunden oder sogar negativ sein.
Zur Angabe von TIME
-Werten steht eine
Vielzahl von Formaten zur Verfügung:
Als String im Format 'D
HH:MM:SS.fraction'
. Sie können auch eines der
folgenden weniger stringenten Syntaxformate verwenden:
'HH:MM:SS.fraction'
,
'HH:MM:SS'
, 'HH:MM'
,
'D HH:MM:SS'
, 'D
HH:MM'
, 'D HH'
oder
'SS'
. Hierbei steht D
für Tage und kann einen Wert zwischen 0 und 34 haben.
Beachten Sie, dass MySQL den Bruchteil
(fraction
) nicht speichert.
Als String ohne Trennzeichen im Format
'HHMMSS'
, sofern er als Zeitangabe
sinngebend ist. Zum Beispiel wird
'101112'
als
'10:11:12'
interpretiert, aber
'109712'
ist unzulässig (der
Minutenanteil ist unsinnig) und wird deswegen zu
'00:00:00'
.
Als Zahl im Format HHMMSS
, sofern er als
Zeitangabe sinngebend ist. So wird etwa
101112
als '10:11:12'
interpretiert. Die folgenden alternativen Formate werden
ebenfalls verstanden: SS
,
MMSS
, HHMMSS
,
HHMMSS.fraction
. Beachten Sie, dass MySQL
den Bruchteil nicht speichert.
Als Ergebnis einer Funktion, die einen Wert zurückgibt, der
im Kontext von TIME
sinngebend ist,
z. B. CURRENT_TIME
.
Bei als String angegebenen TIME
-Werten, die
Trennzeichen für Uhrzeitbestandteile enthalten, ist es nicht
erforderlich, zwei Stellen für Stunden-, Minuten oder
Sekundenwerte anzugeben, die kleiner als 10
sind: '8:3:2'
ist das Gleiche wie
'08:03:02'
.
Seien Sie vorsichtig bei der Zuweisung abgekürzter Werte zu
einer TIME
-Spalte. Ohne Doppelpunkte
interpretiert MySQL die Werte in der Annahme, dass die beiden
ganz rechts stehenden Stellen die Sekunden angeben. (MySQL
interpretiert TIME
-Werte nicht als Uhrzeit,
sondern als verstrichene Zeit.) So könnte man etwa annehmen,
dass '1112'
und 1112
die
Bedeutung '11:12:00'
(also 12 Minuten nach 11
Uhr) hätten; MySQL liest die Angabe jedoch als
'00:11:12'
(also 11 Minuten und 12 Sekunden).
Ähnlich werden '12'
und
12
als '00:00:12'
interpretiert. TIME
-Werte mit Doppelpunkten
hingegen werden immer als Uhrzeit betrachtet:
'11:12'
bedeutet also
'11:12:00'
und nicht
'00:11:12'
.
Standardmäßig werden Werte, die außerhalb des für
TIME
zulässigen Bereichs liegen, aber
ansonsten zulässig sind, auf den nächstgelegenen Endpunkt des
Bereichs gesetzt. Beispielsweise werden
'-850:00:00'
und
'850:00:00'
zu
'-838:59:59'
bzw.
'838:59:59'
konvertiert. Unzulässige
TIME
-Werte werden zu
'00:00:00'
konvertiert. Beachten Sie, dass
es, weil '00:00:00'
selbst ein zulässiger
TIME
-Wert ist, keine Möglichkeit gibt,
festzustellen, ob ein in der Tabelle gespeicherter Wert
'00:00:00'
als '00:00:00'
oder als unzulässiger Wert angegeben wurde.
Zur restriktiveren Behandlung ungültiger
TIME
-Werte aktivieren Sie den strikten
SQL-Modus. In diesem Fall werden Fehler ausgegeben. Siehe auch
Abschnitt 5.2.5, „Der SQL-Modus des Servers“.
Der Datentyp YEAR
hat genau ein Byte und
dient der Darstellung von Jahreszahlen.
MySQL ruft YEAR
-Werte im Format
YYYY
ab und zeigt sie auch so an. Der Bereich
liegt zwischen 1901
und
2155
.
Zur Angabe von YEAR
-Werten steht eine
Vielzahl von Formaten zur Verfügung:
Als vierstelliger String im Bereich
'1901'
bis '2155'
.
Als vierstellige Zahl im Bereich 1901
bis
2155
.
Als zweistelliger String im Bereich '00'
bis '99'
. Werte in den Bereichen
'00'
bis '69'
und
'70'
bis '99'
werden
zu YEAR
-Werten in den Bereichen
2000
bis 2069
bzw.
1970
bis 1999
konvertiert.
Als zweistellige Zahl im Bereich 1
bis
99
. Werte in den Bereichen
1
bis 69
und
70
bis 99
werden zu
YEAR
-Werten in den Bereichen
2001
bis 2069
bzw.
1970
bis 1999
konvertiert. Beachten Sie, dass sich der Bereich der
zweistelligen Zahlen leicht von dem der zweistelligen
Strings unterscheidet, da Sie Null nicht direkt als Zahl
angeben und als 2000
interpretieren
lassen können. Die Angabe muss vielmehr als String
'0'
oder '00'
erfolgen, andernfalls wird sie als 0000
interpretiert.
Als Ergebnis einer Funktion, die einen Wert zurückgibt, der
im Kontext von YEAR
sinngebend ist,
z. B. NOW()
.
Unzulässige YEAR
-Werte werden zu
0000
konvertiert.
Wie in Abschnitt 1.4.5, „Jahr-2000-Konformität“, beschrieben, ist MySQL selbst Jahr-2000-sicher; bestimmte Werte, die in MySQL eingegeben werden, sind es jedoch unter Umständen nicht. Jeder Wert, der eine zweistellige Jahresangabe enthält, ist mehrdeutig, da das Jahrhundert unbekannt ist. Solche Werte müssen in das vierstellige Format umgesetzt werden, da MySQL Jahreszahlen intern vierstellig speichert.
Bei den Typen DATETIME
,
DATE
, TIMESTAMP
und
YEAR
interpretiert MySQL nicht eindeutige
Jahreszahlen entsprechend den folgenden Regeln:
Jahreszahlen im Bereich zwischen 00 und 69 werden als
2000-2069
interpretiert.
Jahreszahlen im Bereich zwischen 70 und 99 werden als
1970-1999
interpretiert.
Denken Sie daran, dass diese Regeln nur heuristischer Natur sind und sinnvoll zu erschließen versuchen, was Ihr Datenwert bedeuten könnte. Wenn die von MySQL verwendeten Regeln keine korrekten Werte erzeugen, sollten Sie eindeutige Angaben mit vierstelligen Jahreszahlen machen.
ORDER BY
sortiert zweistellige
YEAR
-Werte wie erwartet.
Einige Funktionen wie MIN()
und
MAX()
konvertieren einen
YEAR
-Wert in eine Zahl. Das bedeutet, dass
ein Wert mit einer zweistelligen Jahresangabe für diese
Funktionen ungeeignet ist. Dieses Problem beheben Sie, indem Sie
den TIMESTAMP
- oder
YEAR
-Wert in das vierstellige Jahresformat
konvertieren.
Es gibt die folgenden String-Datentypen: CHAR
,
VARCHAR
, BINARY
,
VARBINARY
, BLOB
,
TEXT
, ENUM
und
SET
. In diesem Abschnitt wird erläutert, wie
diese Typen funktionieren und wie Sie sie in Ihren Abfragen
verwenden. Informationen zu den Speicheranforderungen von
String-Typen finden Sie in Abschnitt 11.5, „Speicherbedarf von Spaltentypen“.
Die Typen CHAR
und VARCHAR
ähneln einander, werden aber auf unterschiedliche Weise
gespeichert und abgerufen. Weitere Unterschiede sind die
maximale Länge und die Behandlung von Leerzeichen am
String-Ende. Beim Speichern und Abrufen solcher Werte erfolgt
keine Wandlung der Groß-/Kleinschreibung.
Die Typen CHAR
und VARCHAR
werden unter Angabe einer Länge deklariert, die die maximale
Anzahl von Zeichen spezifiziert, die gespeichert werden kann. So
kann ein CHAR(30)
-Wert beispielsweise 30
Zeichen aufnehmen.
Die Länge einer CHAR
-Spalte ist auf den von
Ihnen beim Anlegen der Tabelle deklarierten Wert beschränkt.
Dieser kann zwischen 0 und 255 liegen. Wenn
CHAR
-Werte gespeichert werden, dann werden
sie nach rechts mit Leerzeichen bis auf die angegebene Länge
aufgefüllt. Beim Abrufen von CHAR
-Werten
werden die am Ende stehenden Leerzeichen dann entfernt.
Werte in VARCHAR
-Spalten sind Strings
variabler Länge. Diese kann zwischen 0 und 65.535 liegen. (Die
effektive Maximallänge einer VARCHAR
-Spalte
wird durch die maximale Datensatzgröße und den verwendeten
Zeichensatz bestimmt. Die gesamte Maximallänge liegt bei 65.532
Byte.)
Im Gegensatz zu CHAR
- werden
VARCHAR
-Werte nur mit so vielen Zeichen wie
erforderlich zuzüglich eines Bytes gespeichert, welches die
Länge angibt (bei Spalten, die mit einer Länge größer 255
deklariert sind, werden hierfür 2 Byte verwendet).
VARCHAR
-Werte werden beim Speichern nicht
aufgefüllt. Ferner werden am Ende stehende Leerzeichen
entsprechend dem SQL-Standard beim Speichern und Abrufen
beibehalten.
Wenn Sie einer CHAR
- oder
VARCHAR
-Spalte einen Wert zuweisen, der die
deklarierte Länge der Spalte überschreitet, dann wird der Wert
so weit gekürzt, bis er passend ist. Handelt es sich bei den
abgeschnittenen Zeichen nicht um Leerzeichen, dann wird eine
Warnung erzeugt. Wenn Sie den strikten SQL-Modus verwenden,
erscheint beim Abschneiden von anderen Zeichen als Leerzeichen
eine Fehlermeldung (statt einer Warnung), und der Wert wird
nicht eingefügt. Siehe auch Abschnitt 5.2.5, „Der SQL-Modus des Servers“.
Die folgende Tabelle veranschaulicht die Unterschiede zwischen
den Typen CHAR
und
VARCHAR
. Hierzu wird das jeweilige Ergebnis
der Speicherung verschiedener String-Werte in
CHAR(4)
- und
VARCHAR(4)
-Spalten angezeigt:
Wert | CHAR(4) | Erforderlicher Speicherplatz | VARCHAR(4) | Erforderlicher Speicherplatz |
'' | ' ' | 4 Byte | '' | 1 Byte |
'ab' | 'ab ' | 4 Byte | 'ab ' | 3 Byte |
'abcd' | 'abcd' | 4 Byte | 'abcd' | 5 Byte |
'abcdefgh' | 'abcd' | 4 Byte | 'abcd' | 5 Byte |
Beachten Sie, dass die in der letzten Zeile der Tabelle gezeigten Werte nur gelten, wenn der strikte Modus nicht verwendet wird; wird MySQL hingegen im strikten Modus ausgeführt, dann werden Werte, die die Spaltenlänge überschreiten, nicht gespeichert, und ein Fehler wird ausgegeben.
Wird ein gegebener Wert in die Spalten
CHAR(4)
und VARCHAR(4)
gespeichert, dann sind die aus den Spalten abgerufenen Werte
nicht immer identisch, weil in CHAR
-Spalten
am Ende stehende Leerzeichen beim Abrufen entfernt werden. Das
folgende Beispiel veranschaulicht diesen Unterschied:
mysql>CREATE TABLE vc (v VARCHAR(4), c CHAR(4));
Query OK, 0 rows affected (0.01 sec) mysql>INSERT INTO vc VALUES ('ab ', 'ab ');
Query OK, 1 row affected (0.00 sec) mysql>SELECT CONCAT('(', v, ')'), CONCAT('(', c, ')') FROM vc;
+---------------------+---------------------+ | CONCAT('(', v, ')') | CONCAT('(', c, ')') | +---------------------+---------------------+ | (ab ) | (ab) | +---------------------+---------------------+ 1 row in set (0.06 sec)
Werte in CHAR
- und
VARCHAR
-Spalten werden entsprechend der
zeichensatzspezifischen Sortierungsweise, die der Spalte
zugewiesen ist, sortiert und verglichen.
Beachten Sie, dass alle MySQL-Sortierungen vom Typ
PADSPACE
sind, d. h. alle
CHAR
- und VARCHAR
-Werte in
MySQL werden ohne Berücksichtigung der am Ende stehenden
Leerzeichen verglichen. Zum Beispiel:
mysql>CREATE TABLE names (myname CHAR(10), yourname VARCHAR(10));
Query OK, 0 rows affected (0.09 sec) mysql>INSERT INTO names VALUES ('Monty ', 'Monty ');
Query OK, 1 row affected (0.00 sec) mysql>SELECT myname = 'Monty ', yourname = 'Monty ' FROM names;
+--------------------+----------------------+ | myname = 'Monty ' | yourname = 'Monty ' | +--------------------+----------------------+ | 1 | 1 | +--------------------+----------------------+ 1 row in set (0.00 sec)
Dies gilt für alle MySQL-Versionen ungeachtet des gewählten SQL-Modus.
Bei solchen Fällen, in denen Leerzeichen am Ende entfernt
werden oder Vergleiche diese ignorieren, hat, wenn eine Spalte
einen Index hat, der eindeutige Werte erfordert, das Einfügen
von Werten, die sich nur durch die Anzahl am Ende stehender
Füllleerzeichen unterscheiden, eine Fehlermeldung bezüglich
einer Schlüsseldublette zur Folge. Wenn beispielsweise eine
Tabelle den Wert 'a'
enthält, wird diese
Fehlermeldung erzeugt, sobald Sie versuchen,
'a '
zu speichern.
Die Typen BINARY
und
VARBINARY
ähneln CHAR
bzw. VARCHAR
. Der Unterschied besteht darin,
dass diese beiden Typen binäre (statt nichtbinärer) Strings
speichern, d. h., sie enthalten byte- statt zeichenbasierter
Strings. Diese Datentypen haben aufgrund dessen keinen
Zeichensatz: Sortierung und Vergleiche basieren in diesem Fall
auf den numerischen Werten der Bytes in den Werten.
Die zulässige Maximallänge von BINARY
und
VARBINARY
entspricht der von
CHAR
bzw. VARCHAR
, nur
wird die Länge von BINARY
und
VARBINARY
in Bytes statt in Zeichen
angegeben.
Die Datentypen BINARY
und
VARBINARY
sind nicht identisch mit den Typen
CHAR BINARY
und VARCHAR
BINARY
Bei Letzteren hat das Attribut
BINARY
nicht zur Folge, dass die Spalte als
binäre String-Spalte behandelt wird. Stattdessen aktiviert sie
die binäre Sortierung für den Spaltenzeichensatz, und die
Spalte selbst enthält nichtbinäre zeichenbasierte Strings
statt binärer bytebasierter Strings. So wird beispielsweise
CHAR(5) BINARY
als CHAR(5) CHARACTER
SET latin1 COLLATE latin1_bin
behandelt
(vorausgesetzt, der Standardzeichensatz ist
latin1
). Hier liegt ein Unterschied zu
BINARY(5)
vor, das binäre Strings mit einer
Länge von 5 Byte speichert, für die kein Zeichensatz und keine
Sortierung definiert sind.
Wenn BINARY
-Werte gespeichert werden, werden
sie nach rechts hin mit dem Füllwert auf die gewünschte Länge
aufgefüllt. Der Füllwert ist 0x00
(das
Nullbyte). Beim Einfügen werden Werte nach rechts hin mit
0x00
aufgefüllt, und beim Auswählen werden
am Ende stehende Nullbytes nicht entfernt. Alle Bytes werden in
Vergleichen (einschließlich ORDER BY
- und
DISTINCT
-Operationen) berücksichtigt.
0x00
-Bytes und Leerzeichen sind in
Vergleichen unterschiedlich, wobei 0x00
einen
kleineren Wert als das Leerzeichen hat.
Beispiel: Bei einer BINARY(3)
-Spalte wird
'a '
beim Einfügen zu
'a \0'
. 'a\0'
wird
beim Einfügen zu 'a\0\0'
. Bei der Auswahl
bleiben die gewählten Werte unverändert.
Bei VARBINARY
werden weder beim Einfügen
Füllbytes angehängt noch bei der Auswahl Bytes abgeschnitten.
Alle Bytes werden in Vergleichen (einschließlich ORDER
BY
- und DISTINCT
-Operationen)
berücksichtigt. 0x00
-Bytes und Leerzeichen
sind in Vergleichen unterschiedlich, wobei
0x00
einen kleineren Wert als das Leerzeichen
hat.
Bei solchen Fällen, in denen Füllbytes am Ende entfernt werden
oder Vergleiche diese ignorieren, hat, wenn eine Spalte einen
Index hat, der eindeutige Werte erfordert, das Einfügen von
Werten, die sich nur durch die Anzahl am Ende stehender
Füllbytes unterscheiden, eine Fehlermeldung bezüglich einer
Schlüsseldublette zur Folge. Wenn beispielsweise eine Tabelle
den Wert 'a'
enthält, wird diese
Fehlermeldung erzeugt, sobald Sie versuchen,
'a\0'
zu speichern.
Wenn Sie den Datentyp BINARY
zur Speicherung
binärer Daten verwenden wollen und es wichtig ist, dass der
abgerufene mit dem zuvor gespeicherten Wert vollständig
identisch ist, dann sollten Sie die beschriebenen Merkmale zum
Auffüllen und Abschneiden sorgfältig lesen. Das folgende
Beispiel veranschaulicht, wie sich das Auffüllen von
BINARY
-Werten mit 0x00
auf
Vergleiche von Spaltenwerten auswirkt:
mysql>CREATE TABLE t (c BINARY(3));
Query OK, 0 rows affected (0.01 sec) mysql>INSERT INTO t SET c = 'a';
Query OK, 1 row affected (0.01 sec) mysql>SELECT HEX(c), c = 'a', c = 'a\0\0' from t;
+--------+---------+-------------+ | HEX(c) | c = 'a' | c = 'a\0\0' | +--------+---------+-------------+ | 610000 | 0 | 1 | +--------+---------+-------------+ 1 row in set (0.09 sec)
Wenn der abgerufene Wert mit dem zur Speicherung angegebenen
Wert identisch sein muss, ohne dass aufgefüllt wird, dann
sollten Sie unter Umständen besser VARBINARY
oder einen der BLOB
-Datentypen verwenden.
Ein BLOB
ist ein binäres großes Objekt,
welches eine variable Menge von Daten aufnehmen kann. Die vier
BLOB
-Typen sind TINYBLOB
,
BLOB
, MEDIUMBLOB
und
LONGBLOB
. Sie unterscheiden sich lediglich in
der maximalen Länge der Werte, die sie aufnehmen können. Die
vier TEXT
-Typen sind
TINYTEXT
, TEXT
,
MEDIUMTEXT
und LONGTEXT
.
Sie entsprechen den vier BLOB
-Typen, d. h.,
sie haben dieselben Längenbeschränkungen und
Speicheranforderungen. Siehe auch
Abschnitt 11.5, „Speicherbedarf von Spaltentypen“. Beim Speichern und
Abrufen von TEXT
- und
BLOB
-Spalten erfolgt keine Wandlung der
Groß-/Kleinschreibung.
BLOB
-Spalten werden als binäre Strings
(Byte-Strings) behandelt, TEXT
-Spalten als
nichtbinäre Strings (zeichenbasierte Strings).
BLOB
-Spalten haben keinen Zeichensatz, und
die Sortierung basiert auf den numerischen Werten der Bytes in
den Spaltenwerten; TEXT
-Spalten hingegen
haben einen Zeichensatz, dessen Sortierung auch bestimmt, wie
die Werte sortiert und verglichen werden.
Wird eine TEXT
-Spalte indiziert, dann werden
Vergleiche von Indexeinträgen am Ende mit Leerzeichen
aufgefüllt. Das bedeutet, dass, wenn der Index eindeutige Werte
erfordert, Fehlermeldungen zu doppelt vorhandenen Schlüsseln
auftreten werden, wenn sich Werte lediglich in der Anzahl der am
Ende stehenden Leerzeichen unterscheiden. Wenn beispielsweise
eine Tabelle den Wert 'a'
enthält, wird
diese Fehlermeldung erzeugt, sobald Sie versuchen,
'a '
zu speichern. Für
BLOB
-Spalten trifft dies allerdings nicht zu.
Wenn Sie im strikten Modus einer BLOB
- oder
TEXT
-Spalte einen Wert zuweisen, der die
zulässige Länge des Datentyps überschreitet, dann wird der
Wert so weit gekürzt, bis er passend ist. Handelt es sich bei
den abgeschnittenen Zeichen nicht um Leerzeichen, dann wird eine
Warnung erzeugt. Wenn Sie den strikten SQL-Modus verwenden,
erscheint stattdessen eine Fehlermeldung, und der Wert wird
nicht eingefügt. Siehe auch Abschnitt 5.2.5, „Der SQL-Modus des Servers“.
In vielerlei Hinsicht können Sie eine
BLOB
-Spalte als
VARBINARY
-Spalte betrachten, die beliebig
groß sein kann. Ähnlich können Sie eine
TEXT
-Spalte auch als
VARCHAR
-Spalte betrachten.
BLOB
und TEXT
unterscheiden sich wie folgt von VARBINARY
bzw. VARCHAR
:
Bei Indizes in BLOB
- und
TEXT
-Spalten müssen Sie eine Länge für
das Indexpräfix angeben. Bei CHAR
und
VARCHAR
ist die Präfixlänge optional.
Siehe auch Abschnitt 7.4.3, „Spaltenindizes“.
LONG
und LONG VARCHAR
lassen sich dem Datentyp MEDIUMTEXT
zuordnen.
Grund hierfür sind Kompatibilitätsaspekte. Wenn Sie das
Attribut BINARY
mit einem
TEXT
-Datentyp verwenden, wird der Spalte die
binäre Sortierung des Spaltenzeichensatzes zugewiesen.
MySQL Connector/ODBC definiert BLOB
-Werte als
LONGVARBINARY
und
TEXT
-Werte als
LONGVARCHAR
-Werte.
Da BLOB
- und TEXT
-Werte
sehr lang sein können, können Sie bei ihrer Verwendung auf
einige Einschränkungen treffen:
Nur die ersten max_sort_length
Bytes der
Spalte werden zur Sortierung verwendet. Der Standardwert von
max_sort_length
beträgt 1024. Dieser
Wert kann mithilfe der Option
--max_sort_length=
beim Start des mysqld-Servers geändert
werden. Siehe auch
Abschnitt 5.2.2, „Server-Systemvariablen“.
N
Sie können die Berücksichtigung von mehr Bytes bei der
Sortierung oder Gruppierung implementieren, indem Sie den
Wert von max_sort_length
zur Laufzeit
erhöhen. Jeder Client kann den Wert für seine
Sitzungsvariable max_sort_length
selbst
ändern:
mysql>SET max_sort_length = 2000;
mysql>SELECT id, comment FROM t
->ORDER BY comment;
Eine andere Möglichkeit, GROUP BY
oder
ORDER BY
für eine
BLOB
- oder
TEXT
-Spalte, die lange Werte enthält, zu
verwenden und dabei mehr als die mit
max_sort_length
angegebene Anzahl von
Bytes zu berücksichtigen, besteht darin, den Spaltenwert in
ein Objekt fester Länge zu konvertieren. Standardmäßig
erfolgt eine solche Konvertierung mit der Funktion
SUBSTRING
. Die folgende Anweisung
beispielsweise hat die Berücksichtigung von 2000 Byte in
der Spalte comment
für die Sortierung
zur Folge:
mysql>SELECT id, SUBSTRING(comment,1,2000) FROM t
->ORDER BY SUBSTRING(comment,1,2000);
Die maximale Größe eines BLOB
- oder
TEXT
-Objekts ist durch seinen Typ
bestimmt. Der größte Wert jedoch, den Sie tatsächlich
zwischen Client und Server übertragen können, wird durch
die Menge des verfügbaren Speichers und die Größe der
Kommunikationspuffer festgelegt. Sie können die Größe des
Meldungspuffers ändern, indem Sie der Variablen
max_allowed_packet
einen anderen Wert
zuweisen. Dies muss allerdings sowohl für den Server als
auch für Ihr Clientprogramm erfolgen. So können Sie etwa
sowohl mit mysql als auch mit
mysqldump den
max_allowed_packet
-Wert auf der
Clientseite verändern. Siehe auch
Abschnitt 7.5.2, „Serverparameter feineinstellen“, Abschnitt 8.5, „mysql — Das MySQL-Befehlszeilenwerkzeug mysql“
und Abschnitt 8.10, „mysqldump — Programm zur Datensicherung“.
Jeder BLOB
- und TEXT
-Wert
wird intern durch ein separat reserviertes Objekt dargestellt.
Dies steht im Gegensatz zu allen anderen Datentypen, für die
der Speicherplatz pro Spalte genau einmal beim Öffnen der
Tabelle reserviert wird.
In manchen Fällen kann es wünschenswert sein, Binärdaten wie
Mediendateien in BLOB
- oder
TEXT
-Spalten zu speichern. Beim Umgang mit
solchen Daten können sich die MySQL-Funktionen zur
String-Verarbeitung als recht praktisch erweisen. Siehe auch
Abschnitt 12.3, „String-Funktionen“. Aus Sicherheits- und anderen
Gründen empfiehlt es sich in der Regel, dies im Anwendungscode
zu tun, statt Benutzern der Anwendung die Berechtigung
FILE
zu gewähren. Details zu Sprachen und
Plattformen können Sie in den MySQL-Foren
(http://forums.mysql.com/) diskutieren.
Der Datentyp ENUM
ist ein String-Objekt mit
einem Wert, der aus einer Liste zulässiger Werte ausgewählt
wird, die beim Erstellen der Tabelle explizit in der
Spaltendefinition aufgelistet werden.
Als Werte kommen unter bestimmten Umständen auch der
Leer-String (''
) oder NULL
in Frage:
Wenn Sie einen ungültigen Wert (d. h. einen String, der
nicht in der Liste zulässiger Werte vorhanden ist) in eine
ENUM
-Spalte einzufügen versuchen, dann
wird stattdessen als spezieller Fehlerwert der Leer-String
eingefügt. Dieser String lässt sich von einem
„normalen“ leeren String dadurch unterscheiden,
dass er den numerischen Wert 0 hat. Weitere Informationen
hierzu folgen weiter unten.
Wenn der strikte SQL-Modus aktiviert ist, führen Versuche,
ungültige ENUM
-Werte einzufügen, zu
einer Fehlermeldung.
Wird für eine ENUM
-Spalte die
Zulässigkeit von NULL
deklariert, dann
ist der NULL
-Wert für die Spalte
erlaubt. Ferner ist in diesem Fall auch der Standardwert
NULL
. Wenn eine
ENUM
-Spalte als NOT
NULL
deklariert wird, dann wird als Vorgabe das
erste Element der Liste zulässiger Werte verwendet.
Jeder Wert in der Auflistung hat einen Index:
Werte aus der Liste zulässiger Elemente in der Spaltenspezifikation werden beginnend mit 1 nummeriert.
Der Indexwert des als Fehlerwert verwendeten Leer-Strings
ist 0. Sie können also folgende
SELECT
-Anweisung verwenden, um
Datensätze zu ermitteln, bei denen ungültige
ENUM
-Werte zugewiesen wurden:
mysql> SELECT * FROM tbl_name
WHERE enum_col
=0;
Der Indexwert des NULL
-Werts ist
NULL
.
Der Begriff „Index“ bezeichnet in diesem Kontext nur die Position innerhalb der Auflistung möglicher Werte. Es gibt keine Verbindung zu Tabellenindizes.
Eine Spalte, die als ENUM('one', 'two',
'three')
definiert ist, kann jeden der nachfolgend
angegebenen Werte annehmen. Auch die Indizes der einzelnen Werte
werden angezeigt:
Wert | Index |
NULL | NULL |
'' | 0 |
'one' | 1 |
'two' | 2 |
'three' | 3 |
Eine Auflistung darf maximal 65.535 Elemente enthalten.
Beim Erstellen der Tabelle werden bei
ENUM
-Mitgliedswerten am Ende stehende
Leerzeichen in der Tabellendefinition automatisch entfernt.
Beim Abrufen werden Werte, die in einer
ENUM
-Spalte gespeichert sind, in der
Groß-/Kleinschreibung angezeigt, die bei der Spaltendefinition
verwendet wurde. Beachten Sie, dass
ENUM
-Spalten ein Zeichensatz und eine
Sortierung zugewiesen werden können. Bei binären Sortierungen
oder solchen, bei denen die Groß-/Kleinschreibung unterschieden
wird, wird die Schreibweise beim Zuweisen von Werten zur Spalte
berücksichtigt.
Wenn Sie einen ENUM
-Wert in einem numerischen
Kontext abrufen, wird der Index des Spaltenwerts zurückgegeben.
So können Sie beispielsweise numerische Werte wie folgt aus
einer ENUM
-Spalte abrufen:
mysql> SELECT enum_col
+0 FROM tbl_name
;
Wenn Sie eine Zahl in einer ENUM
-Spalte
ablegen, wird diese als Index behandelt, und der mit diesem
Index verknüpfte Mitgliedswert wird in der Spalte gespeichert.
(Allerdings funktioniert dies nicht bei LOAD
DATA
, weil diese Anweisung alle Eingaben als Strings
behandelt.) Es ist nicht ratsam, eine
ENUM
-Spalte mit Auflistungswerten zu
definieren, die wie Zahlen aussehen, da dies schnell zu
Verwirrung führen kann. So hat beispielsweise die folgende
Spalte Auflistungswerte mit den String-Werten
'0'
, '1'
und
'2'
, aber die numerischen Indexwerte
1
, 2
und
3
:
numbers ENUM('0','1','2')
ENUM
-Werte werden entsprechend der
Reihenfolge sortiert, in der sie in der Spaltendefinition
aufgeführt wurden. (Anders gesagt:
ENUM
-Werte werden nach ihren Indexzahlen
sortiert.) So wird beispielsweise bei ENUM('a',
'b')
'a'
vor 'b'
einsortiert, bei ENUM('b', 'a')
hingegen wird
'b'
vor 'a'
einsortiert.
Der Leer-String wird immer vor nichtleeren Strings einsortiert,
und NULL
-Werte werden vor allen anderen
Auflistungswerten einsortiert. Um unerwünschte Ergebnisse zu
vermeiden, geben Sie die ENUM
-Liste am besten
in alphabetischer Reihenfolge an. Sie können auch mit
GROUP BY CAST(col AS CHAR)
oder
GROUP BY CONCAT(col)
sicherstellen, dass die
Spalte lexikalisch statt nach Indexnummer sortiert wird.
Wenn Sie alle möglichen Werte für eine
ENUM
-Spalte bestimmen wollen, verwenden Sie
SHOW COLUMNS FROM
und
verarbeiten die tbl_name
LIKE enum_col
ENUM
-Definition in der Spalte
Type
der Ausgabe.
Der Datentyp SET
(Menge) ist ein
String-Objekt, das null oder mehr Werte haben kann. Alle diese
Werte entstammen einer Liste zulässiger Werte, die beim
Erstellen der Tabelle angegeben werden. Bei
SET
-Spaltenwerten, die mehrere Mitglieder der
Menge umfassen, werden die Mitgliedswerte durch Kommata
(‘,
’) getrennt angegeben. Hieraus
ergibt sich, dass SET
-Mitgliedswerte
ihrerseits keine Kommata enthalten sollten.
Eine Spalte, die als SET('one', 'two') NOT
NULL
definiert ist, kann jeden der folgenden Werte
annehmen:
'' 'one' 'two' 'one,two'
Ein SET
kann maximal 64 Mitgliedswerte
umfassen.
Beim Erstellen der Tabelle werden bei
SET
-Mitgliedswerten am Ende stehende
Leerzeichen in der Tabellendefinition automatisch entfernt.
Beim Abrufen werden Werte, die in einer
SET
-Spalte gespeichert sind, in der
Groß-/Kleinschreibung angezeigt, die bei der Spaltendefinition
verwendet wurde. Beachten Sie, dass
SET
-Spalten ein Zeichensatz und eine
Sortierung zugewiesen werden können. Bei binären Sortierungen
oder solchen, bei denen die Groß-/Kleinschreibung unterschieden
wird, wird die Schreibweise beim Zuweisen von Werten zur Spalte
berücksichtigt.
MySQL speichert SET
-Werte numerisch, wobei
das niederwertige Bit des gespeicherten Werts dem ersten
Mitgliedswert der Menge entspricht. Wenn Sie einen
SET
-Wert in einem numerischen Kontext
abrufen, sind die Bits dieses Werts entsprechend den
Mitgliedswerten der Menge gesetzt, die den Spaltenwert bilden.
So können Sie beispielsweise numerische Werte wie folgt aus
einer SET
-Spalte abrufen:
mysql> SELECT set_col
+0 FROM tbl_name
;
Wenn eine Zahl in einer SET
-Spalte
gespeichert wird, bestimmen die Bits, die in der Binärform der
Zahl gesetzt sind, die im Spaltenwert vorhandenen Mitglieder.
Bei einer Spalte, die als
SET('a','b','c','d')
definiert ist, haben die
Mitglieder die folgenden Dezimal- und Binärwerte:
SET Mitgliedswert | Dezimalwert | Binärwert |
'a' | 1 | 0001 |
'b' | 2 | 0010 |
'c' | 4 | 0100 |
'd' | 8 | 1000 |
Wenn Sie dieser Spalte den Wert 9
zuweisen,
entspricht dies dem Binärwert 1001
, d. h.,
der erste und der vierte SET
-Mitgliedswert
('a'
und 'd'
) werden
ausgewählt. Das Ergebnis lautet also 'a,d'
.
Bei einem Wert, der mehr als ein SET
-Element
enthält, spielt es keine Rolle, in welcher Reihenfolge die
Elemente beim Einfügen des Werts aufgeführt sind. Ebenso wenig
ist relevant, wie häufig ein gegebenes Element in der Liste
auftaucht. Wenn der Wert später abgerufen wird, erscheint jedes
Element des Werts genau einmal in der Liste, und diese ist in
der Reihenfolge sortiert, in der die Mitglieder bei Erstellung
der Tabelle aufgeführt wurden. Nehmen wir beispielsweise einmal
an, eine Spalte sei als SET('a','b','c','d')
definiert:
mysql> CREATE TABLE myset (col SET('a', 'b', 'c', 'd'));
Nun fügen Sie die Werte 'a,d'
,
'd,a'
, 'a,d,d'
,
'a,d,a'
und 'd,a,d'
ein:
mysql> INSERT INTO myset (col) VALUES
-> ('a,d'), ('d,a'), ('a,d,a'), ('a,d,d'), ('d,a,d');
Query OK, 5 rows affected (0.01 sec)
Records: 5 Duplicates: 0 Warnings: 0
Beim Abrufen erscheinen alle diese Werte als
'a,d'
:
mysql> SELECT col FROM myset;
+------+
| col |
+------+
| a,d |
| a,d |
| a,d |
| a,d |
| a,d |
+------+
5 rows in set (0.04 sec)
Wenn Sie eine SET
-Spalte auf einen nicht
unterstützten Wert setzen, wird dieser ignoriert, und es wird
eine Warnung ausgegeben:
mysql>INSERT INTO myset (col) VALUES ('a,d,d,s');
Query OK, 1 row affected, 1 warning (0.03 sec) mysql>SHOW WARNINGS;
+---------+------+------------------------------------------+ | Level | Code | Message | +---------+------+------------------------------------------+ | Warning | 1265 | Data truncated for column 'col' at row 1 | +---------+------+------------------------------------------+ 1 row in set (0.04 sec) mysql>SELECT col FROM myset;
+------+ | col | +------+ | a,d | | a,d | | a,d | | a,d | | a,d | | a,d | +------+ 6 rows in set (0.01 sec)
Wenn der strikte SQL-Modus aktiviert ist, führen Versuche,
ungültige SET
-Werte einzufügen, zu einer
Fehlermeldung.
SET
-Werte werden numerisch sortiert.
NULL
-Werte werden dabei vor
Nicht-NULL
-Werten einsortiert.
Meist werden Sie SET
-Werte mithilfe der
Funktion FIND_IN_SET()
oder des Operators
LIKE
durchsuchen:
mysql>SELECT * FROM
mysql>tbl_name
WHERE FIND_IN_SET('value
',set_col
)>0;SELECT * FROM
tbl_name
WHEREset_col
LIKE '%value
%';
Die erste Anweisung findet Datensätze, bei denen
set_col
den Mitgliedswert
value
enthält. Die zweite ist
ähnlich, aber nicht identisch: Sie findet Datensätze, bei
denen set_col
value
an beliebiger Stelle (auch als
Teil-String eines anderen Mitglieds) enthält.
Die folgenden Anweisungen sind ebenfalls zulässig:
mysql>SELECT * FROM
mysql>tbl_name
WHEREset_col
& 1;SELECT * FROM
tbl_name
WHEREset_col
= 'val1
,val2
';
Die erste Anweisung sucht nach Werten, die das erste Mitglied
der Menge enthalten. Die zweite sucht nach einer exakten
Übereinstimmung. Seien Sie bei Vergleichen des zweiten Typs
vorsichtig. Der Vergleich von Mengenwerten mit
'
gibt andere Resultate zurück als der Vergleich mit
val1
,val2
''
.
Sie sollten die Werte in derselben Reihenfolge angeben, in der
sie in der Spaltendefinition aufgelistet sind.
val2
,val1
'
Wenn Sie alle möglichen Werte für eine
SET
-Spalte bestimmen wollen, verwenden Sie
SHOW COLUMNS FROM
und
verarbeiten die tbl_name
LIKE set_col
SET
-Definition in der Spalte
Type
der Ausgabe.
Die Speicheranforderungen der einzelnen von MySQL unterstützten Datentypen sind nachfolgend nach Kategorie sortiert aufgelistet.
Die maximale Größe eines Datensatzes in einer
MyISAM
-Tabelle beträgt 65.534 Byte. Jede
BLOB
- oder TEXT
-Spalte
trägt nur zwischen 5 und 9 Byte zu dieser Größe bei.
Speicheranforderungen für numerische Typen
Datentyp | Erforderlicher Speicherplatz |
TINYINT | 1 Byte |
SMALLINT | 2 Byte |
MEDIUMINT | 3 Byte |
INT , INTEGER | 4 Byte |
BIGINT | 8 Byte |
FLOAT( | 4 Byte, sofern 0 <= p <= 24; 8 Byte,
sofern 25 <= p <= 53 |
FLOAT | 4 Byte |
DOUBLE [PRECISION] , REAL | 8 Byte |
DECIMAL( ,
NUMERIC( | Variiert (siehe nachfolgende Beschreibung) |
BIT( | ca. (M +7) ÷ 8 Byte |
Werte für DECIMAL
-Spalten (und auch für
NUMERIC
-Spalten) werden in einem Binärformat
dargestellt, das 9 Dezimalstellen (Basis 10) mit 4 Byte
repräsentiert. Die Speicheranforderungen für ganzzahlige und
Bruchteile eines Werts werden separat bestimmt. Jedes Vielfache
von 9 Stellen erfordert 4 Byte, und die „restlichen“
Stellen erfordern einen Bruchteil von 4 Byte. Der für
überzählige Stellen erforderliche Speicherplatz ist in der
folgenden Tabelle angegeben:
Überzählige Stellen | Anzahl Bytes |
0 | 0 |
1 | 1 |
2 | 1 |
3 | 2 |
4 | 2 |
5 | 3 |
6 | 3 |
7 | 4 |
8 | 4 |
9 | 4 |
Speicheranforderungen für Datums- und Uhrzeittypen
Datentyp | Erforderlicher Speicherplatz |
DATE | 3 Byte |
DATETIME | 8 Byte |
TIMESTAMP | 4 Byte |
TIME | 3 Byte |
YEAR | 1 Byte |
Speicheranforderungen für String-Typen
Datentyp | Erforderlicher Speicherplatz |
CHAR( | Bytes, 0 <=
255 |
VARCHAR( | L + 1 Byte, wobei
und 0
<= 255 (siehe nachfolgender Hinweis)
or L + 2
Byte, wobei und 256
<= 65535 (siehe nachfolgender Hinweis) |
BINARY( | Bytes, 0 <=
255 |
VARBINARY( | L + 1 Byte, wobei
und 0
<= 255 (siehe nachfolgender Hinweis)
or L + 2
Byte, wobei und 256
<= 65535 (siehe nachfolgender Hinweis) |
TINYBLOB , TINYTEXT | L +1 Byte, wobei L
< 28 |
BLOB , TEXT | L +2 Byte, wobei L
< 216 |
MEDIUMBLOB , MEDIUMTEXT | L +3 Byte, wobei L
< 224 |
LONGBLOB , LONGTEXT | L +4 Byte, wobei L
< 232 |
ENUM(' | 1 oder 2 Byte, abhängig von der Anzahl der Auflistungswerte (maximal 65.535) |
SET(' | 1, 2, 3, 4 oder 8 Byte, abhängig von der Anzahl der Mitglieder der Menge (maximal 64) |
Bei den Typen CHAR
, VARCHAR
und TEXT
sollten die Werte
L
und M
in
obiger Tabelle als Anzahl der Zeichen aufgefasst werden. Längen
für diese Typen in der Spaltendefinition geben die Anzahl der
Zeichen an. Um beispielsweise einen
TINYTEXT
-Wert zu speichern, benötigen Sie
L
Zeichen plus 1 Byte.
VARCHAR
und die VARBINARY
-
und BLOB
- und TEXT
-Typen
haben jeweils variable Längen. Bei ihnen hängen die
Speicheranforderungen von den folgenden Faktoren ab:
der tatsächlichen Länge des Spaltenwerts
der maximal zulässigen Länge der Spalte
dem für die Spalte verwendeten Zeichensatz
Eine VARCHAR(10)
-Spalte beispielsweise kann
einen String mit einer maximalen Länge von 10 aufnehmen. Wenn man
voraussetzt, dass die Spalte den Zeichensatz
latin1
verwendet (bei dem jedes Zeichen durch 1
Byte dargestellt wird), dann entspricht die tatsächliche
Speicheranforderung der Länge des Strings
(L
) zuzüglich eines Bytes zur Angabe
der String-Länge. Beim String 'abcd'
ist
L
4, und der Speicherbedarf beträgt 5
Byte. Wenn dieselbe Spalte stattdessen als
VARCHAR(500)
deklariert würde, dann benötigte
der String 'abcd'
4 + 2 = 6 Bytes. Es
werden 2 Byte (statt nur eines) für das Präfix benötigt, da die
Länge der Spalte größer als 255 Zeichen ist.
Um die Anzahl der Bytes zu berechnen, die zur
Speicherung eines bestimmten CHAR
-,
VARCHAR
- oder
TEXT
-Spaltenwerts benötigt werden, müssen Sie
den Zeichensatz der betreffenden Spalte in Betracht ziehen. Dies
gilt insbesondere bei Verwendung des
utf8
-Unicode-Zeichensatzes: Hierbei ist darauf
zu achten, dass nicht alle utf8
-Zeichen
dieselbe Anzahl Bytes verwenden. Eine Auflistung der
Speicheranforderungen verschiedener Kategorien von
utf8
-Zeichen finden Sie in
Abschnitt 10.7, „Unicode-Unterstützung“.
Hinweis: Die
effektive Maximallänge einer
VARCHAR
- oder
VARBINARY
-Spalte beträgt 65.532.
Die NDBCLUSTER
-Speicher-Engine in MySQL 5.1
unterstützt echte Spalten variabler Breite. Das bedeutet, dass
eine VARCHAR
-Spalte in einer
MySQL-Cluster-Tabelle dieselbe Menge Speicher benötigt, die sie
bei Verwendung einer beliebigen anderen Speicher-Engine erfordern
würde. Dieses Verhalten unterscheidet sich von dem früherer
Versionen von NDBCLUSTER
.
Die Typen BLOB
und TEXT
erfordern je nach maximal möglicher Länge des Datentyps 1 bis 4
Byte zur Aufnahme des Spaltenwerts. Siehe auch
Abschnitt 11.4.3, „Die Spaltentypen BLOB
und TEXT
“.
TEXT
- und BLOB
-Spalten sind
in der NDBCLUSTER
-Speicher-Engine
unterschiedlich implementiert. Dabei besteht jeder Datensatz in
einer TEXT
-Spalte aus zwei separaten Teilen.
Der eine Teil hat eine feste Größe von 256 Byte und wird
tatsächlich in der Ursprungstabelle gespeichert. Der andere
besteht aus den Daten, die den Umfang von 256 Byte überschreiten.
Diese werden in einer verborgenen Tabelle gespeichert. Die
Datensätze in dieser zweiten Tabelle sind immer 2.000 Byte lang.
Das bedeutet, dass die Größe einer
TEXT
-Spalte 256 beträgt, wenn
size
<= 256 (wobei
size
die Größe des Datensatzes
darstellt); andernfalls beträgt die Größe 256 +
size
+ (2000 –
(size
– 256) % 2000).
Die Größe eines ENUM
-Objekts wird anhand der
Anzahl verschiedener Auflistungswerte bestimmt. Ein Byte wird für
Auflistungen mit bis zu 255 möglichen Werten benötigt. 2 Byte
sind für Auflistungen erforderlich, die zwischen 256 und 65.535
mögliche Werte besitzen. Siehe auch Abschnitt 11.4.4, „Der Spaltentyp ENUM
“.
Die Größe eines SET
-Objekts wird anhand der
Anzahl verschiedener Mitglieder der Menge bestimmt. Wenn die
Größe der Menge N
ist, dann benötigt
das Objekt (
Byte, gerundet auf 1, 2, 3, 4 oder 8 Byte. Ein
N
+7)/8SET
kann maximal 64 Mitgliedswerte umfassen.
Siehe auch Abschnitt 11.4.5, „Der Spaltentyp SET
“.
Um den Speicher optimal zu nutzen, sollten Sie in allen Fällen
den geeignetsten Datentyp auswählen. Wird eine Integer-Spalte
etwa für Werte im Bereich zwischen 1
und
99999
verwendet, dann ist MEDIUMINT
UNSIGNED
als Typ am besten geeignet. Von allen Typen,
die alle erforderlichen Werte darstellen können, verwendet dieser
Typ am wenigsten Speicher.
Berechnungen in den Grundrechenarten (+,-,*,/
)
erfolgen bei DECIMAL
-Spalten stets mit einer
Genauigkeit von 65 Dezimalstellen (Basis 10). Siehe auch
Abschnitt 11.1.1, „Überblick über numerische Datentypen“.
Für Berechnungen mit DECIMAL
-Werten werden
Operationen mit doppelter Genauigkeit verwendet. Sofern die
Genauigkeit nicht zu wichtig ist oder Geschwindigkeit die höchste
Priorität hat, kann der Typ DOUBLE
unter
Umständen ausreichend sein. Für eine hohe Genauigkeit können
Sie jederzeit eine Konvertierung in einen Festkommatyp
durchführen, der als BIGINT
gespeichert wird.
Dies ermöglicht Ihnen die Durchführung aller Berechnungen mit
64-Bit-Integers und nachfolgend ggf. die Rückkonvertierung der
Ergebnisse in Fließkommawerte.
Um die Verwendung von Code zu erleichtern, den andere Anbieter für SQL-Implementierungen geschrieben haben, ordnet MySQL Datentypen entsprechend der folgenden Tabelle zu. Diese Zuordnungen vereinfachen den Import von Tabellendefinitionen aus anderen Datenbanksystemen in MySQL:
Datentyp bei anderem Anbieter | Typ bei MySQL |
BOOL , | TINYINT |
BOOLEAN | TINYINT |
CHAR VARYING( | VARCHAR( |
DEC | DECIMAL |
FIXED | DECIMAL |
FLOAT4 | FLOAT |
FLOAT8 | DOUBLE |
INT1 | TINYINT |
INT2 | SMALLINT |
INT3 | MEDIUMINT |
INT4 | INT |
INT8 | BIGINT |
LONG VARBINARY | MEDIUMBLOB |
LONG VARCHAR | MEDIUMTEXT |
LONG | MEDIUMTEXT |
MIDDLEINT | MEDIUMINT |
NUMERIC | DECIMAL |
Die Datentypzuordnung erfolgt zum Zeitpunkt der
Tabellenerstellung. Nachfolgend werden die ursprünglichen
Typenspezifikationen verworfen. Wenn Sie eine Tabelle mit von
anderen Anbietern verwendeten Typen erstellen und dann eine
DESCRIBE
-Anweisung absetzen,
meldet MySQL die Tabellenstruktur unter Verwendung der
gleichwertigen MySQL-Typen. Zum Beispiel:
tbl_name
mysql>CREATE TABLE t (a BOOL, b FLOAT8, c LONG VARCHAR, d NUMERIC);
Query OK, 0 rows affected (0.00 sec) mysql>DESCRIBE t;
+-------+---------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+---------------+------+-----+---------+-------+ | a | tinyint(1) | YES | | NULL | | | b | double | YES | | NULL | | | c | mediumtext | YES | | NULL | | | d | decimal(10,0) | YES | | NULL | | +-------+---------------+------+-----+---------+-------+ 4 rows in set (0.01 sec)
Inhaltsverzeichnis
GROUP
BY
-Klauseln
Ausdrücke können an mehreren Stellen in MySQL-Anweisungen
verwendet werden, so etwa in den ORDER BY
- oder
HAVING
-Klauseln von
SELECT
-Anweisungen, in der
WHERE
-Klausel einer SELECT
-,
DELETE
- oder UPDATE
-Anweisung
oder in SET
-Anweisungen. Ausdrücke können unter
Verwendung von literalen Werten, Spaltenwerten,
NULL
, integrierten Funktionen, gespeicherten
Funktionen, benutzerdefinierten Funktionen und Operatoren
geschrieben werden. Dieses Kapitel beschreibt die Funktionen und
Operatoren, die für das Formulieren von Ausdrücken in MySQL
zulässig sind. Hinweise zum Schreiben gespeicherter und
benutzerdefinierter Funktionen finden Sie in
Kapitel 19, Gespeicherte Prozeduren und Funktionen, und
Abschnitt 26.3, „Hinzufügen neuer Funktionen zu MySQL“.
Ein Ausdruck, der NULL
enthält, erzeugt immer
einen NULL
-Wert, sofern in der Dokumentation zur
betreffenden Funktion bzw. zum Operator nichts anderes angegeben
ist.
Hinweis: Standardmäßig darf kein Whitespace zwischen einem Funktionsnamen und der ihm folgenden Klammer stehen. Auf diese Weise kann der MySQL-Parser zwischen Funktionsaufrufen und Referenzierungen von Tabellen oder Spalten unterscheiden, die den gleichen Namen wie die Funktion haben. Die Funktionsargumente umgebenden Leerzeichen sind hingegen zulässig.
Sie können den MySQL Server anweisen, Leerzeichen nach
Funktionsnamen zu akzeptieren, indem Sie beim Start die Option
--sql-mode=IGNORE_SPACE
angeben. (Siehe auch
Abschnitt 5.2.5, „Der SQL-Modus des Servers“.) Einzelne Clientprogramme können
dieses Verhalten anfordern, indem sie die Option
CLIENT_IGNORE_SPACE
für
mysql_real_connect()
angeben. In beiden Fällen
werden alle Funktionsnamen zu reservierten Wörtern.
Um Weitschweifigkeiten zu verhindern, stellen die meisten Beispiele in diesem Kapitel die Ausgabe von mysql in gekürzter Form dar. Die folgende Ausgabe zeigt das vollständige Format:
mysql> SELECT MOD(29,9);
+-----------+
| mod(29,9) |
+-----------+
| 2 |
+-----------+
1 rows in set (0.00 sec)
Stattdessen benutzen wir jedoch folgende Ausgabe:
mysql> SELECT MOD(29,9);
-> 2
Die folgende Liste zeigt die Rangordnung der Operatoren in umgekehrter Reihenfolge. Operatoren in der gleichen Zeile haben die gleiche Rangstufe.
:= ||, OR, XOR &&, AND NOT BETWEEN, CASE, WHEN, THEN, ELSE =, <=>, >=, >, <=, <, <>, !=, IS, LIKE, REGEXP, IN | & <<, >> -, + *, /, DIV, %, MOD ^ - (unary minus), ~ (unary bit inversion) ! BINARY, COLLATE
Hinweis: Wenn der SQL-Modus
HIGH_NOT_PRECEDENCE
aktiviert ist, entspricht
die Rangstufe von NOT
der des Operators
!
. Siehe auch
Abschnitt 5.2.5, „Der SQL-Modus des Servers“.
Die Abfolge der Operatoren bestimmt die Auswertungsreihenfolge der Begriffe in einem Ausdruck. Um diese Reihenfolge außer Kraft zu setzen und Begriffe explizit zu gruppieren, verwenden Sie Klammern. Zum Beispiel:
mysql>SELECT 1+2*3;
-> 7 mysql>SELECT (1+2)*3;
-> 9
Wenn ein Operator mit Operanden verschiedener Typen verwendet wird, findet eine Typenkonvertierung statt, um die Operanden kompatibel zu machen. Einige Konvertierungen treten implizit auf. So wandelt MySQL beispielsweise Zahlen nach Bedarf in Strings um und umgekehrt.
mysql>SELECT 1+'1';
-> 2 mysql>SELECT CONCAT(2,' test');
-> '2 test'
Es ist auch möglich, explizite Konvertierungen durchzuführen.
Wenn Sie eine Zahl explizit in einen String umwandeln wollen,
verwenden Sie die Funktionen CAST()
oder
CONCAT()
(wobei CAST()
vorzuziehen ist):
mysql>SELECT 38.8, CAST(38.8 AS CHAR);
-> 38.8, '38.8' mysql>SELECT 38.8, CONCAT(38.8);
-> 38.8, '38.8'
Die folgenden Regeln beschreiben, wie die Konvertierung bei Vergleichsoperationen erfolgt:
Wenn eines der Argumente (oder beide)
NULL
ist, dann ist das Vergleichsergebnis
NULL
. Eine Ausnahme ist der
NULL
-sichere Gleichheitsoperator
<=>
. Bei NULL <=>
NULL
ist das Ergebnis wahr.
Wenn beide Argumente in einer Vergleichsoperation Strings sind, werden sie als Strings verglichen.
Sind beide Argumente Integers, dann werden sie als Integers verglichen.
Hexadezimalwerte werden als binäre Strings behandelt, wenn sie nicht mit einer Zahl verglichen werden.
Wenn eines der Argumente eine TIMESTAMP
-
oder DATETIME
-Spalte und das andere
Argument eine Konstante ist, dann wird die Konstante vor
Durchführung des Vergleichs in einen Zeitstempel
umgewandelt. Dies erhöht die ODBC-Kompatibilität. Beachten
Sie jedoch, dass dies nicht bei Argumenten für
IN()
gemacht wird! Um ganz sicher zu
sein, sollten Sie bei Vergleichen immer vollständige
Strings für Datum und/oder Uhrzeit verwenden.
In allen anderen Fällen werden die Argumente als Fließkommazahlen (reale Zahlen) verglichen.
Die folgenden Beispiele veranschaulichen die Konvertierung von Strings in Zahlen für Vergleichsoperationen:
mysql>SELECT 1 > '6x';
-> 0 mysql>SELECT 7 > '6x';
-> 1 mysql>SELECT 0 > 'x6';
-> 0 mysql>SELECT 0 = 'x6';
-> 1
Beachten Sie, dass, wenn Sie eine String-Spalte mit einer Zahl
vergleichen, MySQL keinen Index für die Spalte verwenden kann,
um den Wert schnell abzurufen. Ist
str_col
eine indizierte
String-Spalte, dann kann der Index nicht verwendet werden, um
für die folgende Anweisung eine Suche durchzuführen:
SELECT * FROMtbl_name
WHEREstr_col
=1;
Dies liegt daran, dass es viele verschiedene Strings gibt, die
in den Wert 1
konvertiert werden:
'1'
, ' 1'
,
'1a'
, …
Vergleichsoperationen haben einen der Werte 1
(TRUE
), 0
(FALSE
) oder NULL
zum
Ergebnis. Diese Operationen funktionieren bei Zahlen und Strings
gleichermaßen: Nach Bedarf werden Strings in Zahlen und Zahlen
in Strings umgewandelt.
Einige der in diesem Abschnitt beschriebenen Funktionen (z. B.
LEAST()
und GREATEST()
)
geben andere Werte als 1
(TRUE
), 0
(FALSE
) oder NULL
zurück.
Der Rückgabewert basiert jedoch auf Vergleichsoperationen, die
entsprechend den in Abschnitt 12.1.2, „Typumwandlung bei der Auswertung von Ausdrücken“
beschriebenen Regeln durchgeführt wurden.
Um einen Wert zu Vergleichszwecken in einen beliebigen Typ zu
konvertieren, können Sie die Funktion CAST()
verwenden. String-Werte lassen sich mithilfe von
CONVERT()
in einen anderen Zeichensatz
konvertieren. Siehe auch Abschnitt 12.8, „Cast-Funktionen und Operatoren“.
Standardmäßig wird die Groß-/Kleinschreibung bei
String-Vergleichen nicht unterschieden. Ferner wird hierbei der
aktuelle Zeichensatz verwendet. Die Vorgabe ist
latin1
(cp1252 West European). Dieser
Zeichensatz ist auch für Deutsch geeignet.
Gleich:
mysql>SELECT 1 = 0;
-> 0 mysql>SELECT '0' = 0;
-> 1 mysql>SELECT '0.0' = 0;
-> 1 mysql>SELECT '0.01' = 0;
-> 0 mysql>SELECT '.01' = 0.01;
-> 1
NULL
-sicheres Gleich. Dieser Operator
führt ebenso wie =
eine
Vergleichsoperation durch, gibt aber 1
statt NULL
zurück, wenn beide Operanden
NULL
sind, und 0
statt
NULL
, wenn einer der Operanden
NULL
ist.
mysql>SELECT 1 <=> 1, NULL <=> NULL, 1 <=> NULL;
-> 1, 1, 0 mysql>SELECT 1 = 1, NULL = NULL, 1 = NULL;
-> 1, NULL, NULL
Ungleich:
mysql>SELECT '.01' <> '0.01';
-> 1 mysql>SELECT .01 <> '0.01';
-> 0 mysql>SELECT 'zapp' <> 'zappp';
-> 1
Kleiner oder gleich:
mysql> SELECT 0.1 <= 2;
-> 1
Kleiner als:
mysql> SELECT 2 < 2;
-> 0
Größer oder gleich:
mysql> SELECT 2 >= 2;
-> 1
Größer als:
mysql> SELECT 2 > 2;
-> 0
IS
,
boolean_value
IS NOT
boolean_value
Vergleicht einen Wert mit einem booleschen Wert, wobei
boolean_value
TRUE
, FALSE
oder
UNKNOWN
sein kann.
mysql>SELECT 1 IS TRUE, 0 IS FALSE, NULL IS UNKNOWN;
-> 1, 1, 1 mysql>SELECT 1 IS NOT UNKNOWN, 0 IS NOT UNKNOWN, NULL IS NOT UNKNOWN;
-> 1, 1, 0
Prüft, ob ein Wert NULL
ist oder nicht.
mysql>SELECT 1 IS NULL, 0 IS NULL, NULL IS NULL;
-> 0, 0, 1 mysql>SELECT 1 IS NOT NULL, 0 IS NOT NULL, NULL IS NOT NULL;
-> 1, 1, 0
Zum Zwecke der Kompatibilität mit ODBC-Programmen
unterstützt MySQL die folgenden Zusatzfunktionen bei der
Verwendung von IS NULL
:
Sie können den Datensatz, der den aktuellen
AUTO_INCREMENT
-Wert enthält, durch
Absetzen einer Anweisung der folgenden Form unmittelbar
nach Erzeugung des Werts ermitteln:
SELECT * FROMtbl_name
WHEREauto_col
IS NULL
Dieses Verhalten kann mithilfe von
SQL_AUTO_IS_NULL=0
deaktiviert
werden. Siehe auch Abschnitt 13.5.3, „SET
“.
Bei DATE
- und
DATETIME
- Spalten, die als
NOT NULL
deklariert sind, können Sie
das Sonderdatum '0000-00-00'
mithilfe
einer Anweisung wie der folgenden ermitteln:
SELECT * FROMtbl_name
WHEREdate_column
IS NULL
Dies ist erforderlich, um einige ODBC-Anwendungen zum
Laufen zu bringen, weil ODBC den Datumswert
'0000-00-00'
nicht unterstützt.
Wenn expr
größer oder gleich
min
und
expr
kleiner oder gleich
max
ist, gibt
BETWEEN
1
zurück,
andernfalls 0
. Dies ist äquivalent zu
dem Ausdruck (
, sofern alle
Argumente vom selben Typ sind. Andernfalls findet die
Typenkonvertierung entsprechend den in
Abschnitt 12.1.2, „Typumwandlung bei der Auswertung von Ausdrücken“, beschriebenen Regeln
statt, wird aber auf alle drei Argumente angewendet.
min
<=
expr
AND
expr
<=
max
)
mysql>SELECT 1 BETWEEN 2 AND 3;
-> 0 mysql>SELECT 'b' BETWEEN 'a' AND 'c';
-> 1 mysql>SELECT 2 BETWEEN 2 AND '3';
-> 1 mysql>SELECT 2 BETWEEN 2 AND 'x-3';
-> 0
Dies ist das Gleiche wie NOT
(
.
expr
BETWEEN
min
AND
max
)
Gibt den ersten Nicht-NULL
-Wert in der
Liste oder aber NULL
zurück, sofern
keine Nicht-NULL
-Werte vorhanden sind.
mysql>SELECT COALESCE(NULL,1);
-> 1 mysql>SELECT COALESCE(NULL,NULL,NULL);
-> NULL
Gibt von zwei oder mehr Argumenten das größte (d. h. das
mit dem höchsten Wert) zurück. Die Argumente werden nach
denselben Regeln wie bei LEAST()
verglichen.
mysql>SELECT GREATEST(2,0);
-> 2 mysql>SELECT GREATEST(34.0,3.0,5.0,767.0);
-> 767.0 mysql>SELECT GREATEST('B','A','C');
-> 'C'
GREATEST()
gibt NULL
zurück, sofern ein Argument NULL
ist.
Gibt 1
zurück, wenn
expr
gleich einem der Werte in
der IN
-Liste ist, andernfalls wird
0
zurückgegeben. Wenn alle Werte
Konstanten sind, werden sie entsprechend dem Typ von
expr
ausgewertet und sortiert.
Nachfolgend erfolgt die Suche nach dem Element unter
Verwendung einer binären Suche. Das heißt auch, dass
IN
sehr schnell ist, wenn die
IN
-Werteliste ausschließlich aus
Konstanten besteht. Andernfalls findet die
Typenkonvertierung entsprechend den in
Abschnitt 12.1.2, „Typumwandlung bei der Auswertung von Ausdrücken“, beschriebenen Regeln
statt, wird aber auf alle Argumente angewendet.
mysql>SELECT 2 IN (0,3,5,'wefwf');
-> 0 mysql>SELECT 'wefwf' IN (0,3,5,'wefwf');
-> 1
Die Anzahl der Werte in der IN
-Liste wird
nur durch den Wert von max_allowed_packet
beschränkt.
Um mit dem SQL-Standard konform zu gehen, gibt
IN
NULL
nicht nur dann
zurück, wenn der Ausdruck auf der linken Seite
NULL
ist, sondern auch dann, wenn keine
Übereinstimmung in der Liste gefunden wird und einer der
Ausdrücke in der Liste NULL
ist.
Die IN()
-Syntax kann auch zum Schreiben
verschiedener Arten von Unterabfragen verwendet werden.
Siehe auch Abschnitt 13.2.8.3, „Unterabfragen mit ANY
, IN
und
SOME
“.
Dies ist das Gleiche wie NOT
(
.
expr
IN
(value
,...))
Wenn expr
NULL
ist, gibt ISNULL()
1
zurück, andernfalls 0
.
mysql>SELECT ISNULL(1+1);
-> 0 mysql>SELECT ISNULL(1/0);
-> 1
ISNULL()
kann anstelle von
=
verwendet werden, um zu überprüfen,
ob ein Wert NULL
ist. (Der Vergleich
eines Werts mit NULL
unter Verwendung von
=
gibt immer FALSE
aus.)
Die Funktion ISNULL()
weist einige
spezielle Eigenschaften des Vergleichsoperators IS
NULL
auf. Siehe auch die Beschreibung zu
IS NULL
.
Gibt 0
zurück, wenn
N
<
N1
ist, 1
,
wenn N
<
N2
usw., oder
-1
, wenn N
NULL
ist. Alle Argumente werden als
Integers behandelt. Es ist erforderlich, dass
N1
<
N2
<
N3
< ...
< Nn
ist, damit diese Funktion
einwandfrei arbeitet. Das liegt daran, dass eine binäre
(und damit sehr schnelle) Suche verwendet wird.
mysql>SELECT INTERVAL(23, 1, 15, 17, 30, 44, 200);
-> 3 mysql>SELECT INTERVAL(10, 1, 10, 100, 1000);
-> 2 mysql>SELECT INTERVAL(22, 23, 30, 44, 200);
-> 0
Gibt von zwei oder mehr Argumenten das kleinste (d. h. das mit dem niedrigsten Wert) zurück. Die Argumente werden unter Anwendung der folgenden Regeln verglichen:
Wenn der Rückgabewert in einem
INTEGER
-Kontext verwendet wird oder
alle Argumente Integer-Werte sind, dann werden sie als
Integers verglichen.
Wenn der Rückgabewert in einem
REAL
-Kontext verwendet wird oder alle
Argumente reale Zahlen sind, dann werden sie als reale
Zahlen verglichen.
Ist ein Argument ein String mit Unterscheidung der Groß-/Kleinschreibung, dann werden die Argumente als Strings mit Unterscheidung der Groß-/Kleinschreibung verglichen.
In allen anderen Fällen werden die Argumente als Strings ohne Unterscheidung der Groß-/Kleinschreibung verglichen.
LEAST()
gibt NULL
zurück, sofern ein Argument NULL
ist.
mysql>SELECT LEAST(2,0);
-> 0 mysql>SELECT LEAST(34.0,3.0,5.0,767.0);
-> 3.0 mysql>SELECT LEAST('B','A','C');
-> 'A'
Beachten Sie, dass die oben beschriebenen Konvertierungsregeln in einigen Grenzfällen fragwürdige Ergebnisse erzeugen können:
mysql> SELECT CAST(LEAST(3600, 9223372036854775808.0) as SIGNED);
-> -9223372036854775808
Dies passiert, weil MySQL
9223372036854775808.0
in einem
Integer-Kontext liest. Das Integer-Format ist aber nicht
geeignet, den Wert darzustellen, d. h., er wird in einen
vorzeichenbehafteten Integer umgewandelt.
In SLQ werden alle logischen Operatoren als
TRUE
, FALSE
oder
NULL
(UNKNOWN
)
ausgewertet. In MySQL ist dies als 1 (TRUE
),
0 (FALSE
) und NULL
implementiert. Dies ist größtenteils auf den verschiedenen
SQL-Datenbankservern identisch, auch wenn einige Server einen
beliebigen Nichtnullwert für TRUE
zurückgeben.
Logisches NOT (NICHT). Wird zu 1
, wenn
der Operand 0
ist, und zu
0
, wenn der Operand nicht null ist.
NOT NULL
gibt NULL
zurück.
mysql>SELECT NOT 10;
-> 0 mysql>SELECT NOT 0;
-> 1 mysql>SELECT NOT NULL;
-> NULL mysql>SELECT ! (1+1);
-> 0 mysql>SELECT ! 1+1;
-> 1
Das letzte Beispiel erzeugt 1
, weil der
Ausdruck auf die gleiche Weise ausgewertet wird wie
(!1)+1
.
Logisches AND (UND). Gibt 1
zurück, wenn
alle Operanden weder null noch NULL
sind;
wenn ein oder mehr Operanden 0
sind, wird
0
zurückgegeben, andernfalls
NULL
.
mysql>SELECT 1 && 1;
-> 1 mysql>SELECT 1 && 0;
-> 0 mysql>SELECT 1 && NULL;
-> NULL mysql>SELECT 0 && NULL;
-> 0 mysql>SELECT NULL && 0;
-> 0
Logisches OR (ODER). Wenn beide Operanten nicht
NULL
sind, ist das Ergebnis
1
, sofern ein beliebiger Operand nicht
null ist, andernfalls 0
. Bei einem
NULL
-Operanden ist das Ergebnis
1
, wenn der andere Operand nicht null
ist, andernfalls ist es NULL
. Sind beide
Operanden NULL
, dann ist das Ergebnis
NULL
.
mysql>SELECT 1 || 1;
-> 1 mysql>SELECT 1 || 0;
-> 1 mysql>SELECT 0 || 0;
-> 0 mysql>SELECT 0 || NULL;
-> NULL mysql>SELECT 1 || NULL;
-> 1
Logisches XOR (exklusives ODER). Gibt
NULL
zurück, wenn ein Operand
NULL
ist. Bei
Nicht-NULL
-Operanden wird
1
zurückgegeben, wenn eine ungerade
Anzahl von Operanden nicht null ist, andernfalls wird
0
zurückgegeben.
mysql>SELECT 1 XOR 1;
-> 0 mysql>SELECT 1 XOR 0;
-> 1 mysql>SELECT 1 XOR NULL;
-> NULL mysql>SELECT 1 XOR 1 XOR 1;
-> 1
a XOR b
ist mathematisch identisch mit
(a AND (NOT b)) OR ((NOT a) and b)
.
CASE
value
WHEN
[compare_value
] THEN
result
[WHEN
[compare_value
] THEN
result
...] [ELSE
result
] END
CASE WHEN [
condition
] THEN
result
[WHEN
[condition
] THEN
result
...] [ELSE
result
] END
Die erste Version gibt result
zurück, wobei gilt:
.
Die zweite Version gibt das Ergebnis der ersten Bedingung
zurück, die wahr ist. Wenn kein passender Ergebniswert
existiert, wird das Ergebnis nach value
=compare_value
ELSE
oder
aber NULL
(sofern kein
ELSE
-Teil vorhanden ist) zurückgegeben.
mysql>SELECT CASE 1 WHEN 1 THEN 'one'
->WHEN 2 THEN 'two' ELSE 'more' END;
-> 'one' mysql>SELECT CASE WHEN 1>0 THEN 'true' ELSE 'false' END;
-> 'true' mysql>SELECT CASE BINARY 'B'
->WHEN 'a' THEN 1 WHEN 'b' THEN 2 END;
-> NULL
Der vorgabeseitige Rückgabetyp eines
CASE
-Ausdrucks ist der kompatible
zusammengefasste Typ aller Rückgabewerte, hängt aber auch
vom Kontext ab, in dem er verwendet wird. Bei Verwendung in
einem String-Kontext wird das Ergebnis als String
zurückgegeben. Bei Verwendung in einem numerischen Kontext
wird das Ergebnis als Dezimalwert, reale Zahl oder
Integer-Wert zurückgegeben.
Hinweis: Die hier gezeigte
Syntax des
CASE
-Ausdrucks
unterscheidet sich ein wenig von der SQL-Syntax der
CASE
-Anweisung, wie
sie in Abschnitt 19.2.10.2, „CASE
-Anweisung“, zur Verwendung in
gespeicherten Routinen beschrieben wird. Die
CASE
-Anweisung kann keine ELSE
NULL
-Klausel haben und wird mit END
CASE
anstelle von END
abgeschlossen.
Wenn expr1
TRUE
ist (
und expr1
<>
0
), dann gibt expr1
<> NULLIF()
expr2
zurück; andernfalls gibt es
expr3
zurück.
IF()
gibt je nach Verwendungskontext einen
numerischen oder einen String-Wert zurück.
mysql>SELECT IF(1>2,2,3);
-> 3 mysql>SELECT IF(1<2,'yes','no');
-> 'yes' mysql>SELECT IF(STRCMP('test','test1'),'no','yes');
-> 'no'
Ist nur einer der Ausdrücke expr2
oder expr3
explizit
NULL
, dann ist der Ergebnistyp der
IF()
-Funktion der Typ des
Nicht-NULL
-Ausdrucks.
expr1
wird als Integer-Wert
ausgewertet, d. h., wenn Sie Fließkomma- oder String-Werte
prüfen, sollten Sie dies mit einer Vergleichsoperation tun.
mysql>SELECT IF(0.1,1,0);
-> 0 mysql>SELECT IF(0.1<>0,1,0);
-> 1
Im ersten gezeigten Fall gibt IF(0.1)
0
zurück, weil 0.1
in
einen Integer-Wert konvertiert wird, was zur Prüfung von
IF(0)
führt. Dies ist unter Umständen
nicht das, was Sie erwarten. Im zweiten Fall prüft der
Vergleich den ursprünglichen Fließkommawert, um
festzustellen, ob dieser nicht null ist. Das Ergebnis des
Vergleichs wird als Integer verwendet.
Der Standardrückgabetyp von IF()
(der
wichtig sein kann, wenn er in einer Temporärtabelle
gespeichert wird) wird wie folgt berechnet:
Ausdruck | Rückgabewert |
expr2 oder expr3
gibt einen String zurück | String |
expr2 oder expr3
gibt einen Fließkommawert zurück | Fließkommazahl |
expr2 oder expr3
gibt einen Integer zurück | Integer |
Wenn sowohl expr2
als auch
expr3
Strings sind, wird beim
Ergebnis die Groß-/Kleinschreibung unterschieden, sofern dies
bei einem der Strings ebenfalls der Fall ist.
Hinweis: Es gibt auch eine
IF
-Anweisung, die sich
von der hier beschriebenen
IF()
-Funktion
unterscheidet. Siehe auch Abschnitt 19.2.10.1, „IF
-Anweisung“.
Wenn expr1
nicht
NULL
ist, gibt IFNULL()
expr1
zurück; andernfalls wird
expr2
zurückgegeben.
IFNULL()
gibt je nach Verwendungskontext
einen numerischen oder einen String-Wert zurück.
mysql>SELECT IFNULL(1,0);
-> 1 mysql>SELECT IFNULL(NULL,10);
-> 10 mysql>SELECT IFNULL(1/0,10);
-> 10 mysql>SELECT IFNULL(1/0,'yes');
-> 'yes'
Der Standardergebniswert von
IFNULL(
ist der „allgemeinere“ der beiden Ausdrücke in
der Reihenfolge expr1
,expr2
)STRING
,
REAL
oder INTEGER
.
Betrachten Sie den Fall einer auf Ausdrücken basierenden
Tabelle oder einen Fall, in dem MySQL einen von
IFNULL()
zurückgegebenen Wert intern in
einer Temporärtabelle speichern muss:
mysql>CREATE TABLE tmp SELECT IFNULL(1,'test') AS test;
mysql>DESCRIBE tmp;
+-------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+---------+------+-----+---------+-------+ | test | char(4) | | | | | +-------+---------+------+-----+---------+-------+
In diesem Beispiel ist der Typ der Spalte
test
CHAR(4)
.
Gibt NULL
zurück, wenn
wahr ist;
andernfalls wird expr1
=
expr2
expr1
zurückgegeben. Dies ist das Gleiche wie CASE WHEN
.
expr1
=
expr2
THEN NULL ELSE
expr1
END
mysql>SELECT NULLIF(1,1);
-> NULL mysql>SELECT NULLIF(1,2);
-> 1
Beachten Sie, dass MySQL expr1
zweimal auswertet, wenn die Argumente nicht gleich sind.
String-Funktionen geben NULL
zurück, wenn die
Länge des Ergebnisses größer wäre als der Wert der
Systemvariablen max_allowed_packet
. Siehe auch
Abschnitt 7.5.2, „Serverparameter feineinstellen“.
Bei Funktionen, die mit String-Positionen operieren, hat die erste Position die Nummer 1.
Gibt den numerischen Wert des Zeichens ganz links im String
str
zurück. Gibt
0
zurück, wenn
str
der Leer-String ist. Gibt
NULL
zurück, wenn
str
NULL
ist.
ASCII()
funktioniert bei Zeichen mit
numerischen Werten zwischen 0
und
255
.
mysql>SELECT ASCII('2');
-> 50 mysql>SELECT ASCII(2);
-> 50 mysql>SELECT ASCII('dx');
-> 100
Siehe auch die Funktion ORD()
.
Gibt eine String-Darstellung des Binärwerts
N
zurück, wobei
N
eine
BIGINT
-Zahl ist. Dies ist äquivalent mit
CONV(
.
Gibt N
,10,2)NULL
zurück, wenn
N
NULL
ist.
mysql> SELECT BIN(12);
-> '1100'
Gibt die Länge des Strings str
angegeben in Bit zurück.
mysql> SELECT BIT_LENGTH('text');
-> 32
CHAR(
N
,... [USING
charset_name
])
CHAR()
interpretiert jedes Argument
N
als Integer und gibt einen String
zurück, der aus den Zeichen besteht, die durch die Codewerte
dieser Integers beschrieben werden.
NULL
-Werte werden übersprungen.
mysql>SELECT CHAR(77,121,83,81,'76');
-> 'MySQL' mysql>SELECT CHAR(77,77.3,'77.3');
-> 'MMM'
CHAR()
-Argumente, die größer als 255
sind, werden in mehrere Ergebnisbytes konvertiert. So ist
beispielsweise CHAR(256)
äquivalent zu
CHAR(1,0)
, und
CHAR(256*256)
ist äquivalent zu
CHAR(1,0,0)
:
mysql>SELECT HEX(CHAR(1,0)), HEX(CHAR(256));
+----------------+----------------+ | HEX(CHAR(1,0)) | HEX(CHAR(256)) | +----------------+----------------+ | 0100 | 0100 | +----------------+----------------+ mysql>SELECT HEX(CHAR(1,0,0)), HEX(CHAR(256*256));
+------------------+--------------------+ | HEX(CHAR(1,0,0)) | HEX(CHAR(256*256)) | +------------------+--------------------+ | 010000 | 010000 | +------------------+--------------------+
Standardmäßig gibt CHAR()
einen
Binär-String zurück. Um einen String in einem gegebenen
Zeichensatz zu erzeugen, verwenden Sie die optionale Klausel
USING
:
mysql> SELECT CHARSET(CHAR(0x65)), CHARSET(CHAR(0x65 USING utf8));
+---------------------+--------------------------------+
| CHARSET(CHAR(0x65)) | CHARSET(CHAR(0x65 USING utf8)) |
+---------------------+--------------------------------+
| binary | utf8 |
+---------------------+--------------------------------+
Wenn USING
angegeben wird und der
Ergebnis-String für den angegebenen Zeichensatz unzulässig
ist, wird eine Warnung ausgegeben. Ferner wird, wenn der
strikte SQL-Modus aktiviert ist, das Ergebnis von
CHAR()
zu NULL
.
Gibt die Länge des Strings str
angegeben in Zeichen zurück. Ein Multibytezeichen wird als
ein Zeichen gezählt. Das bedeutet, dass
LENGTH()
für einen aus fünf
Zweibytezeichen bestehenden String 10
zurückgibt, CHAR_LENGTH()
hingegen
5
.
CHARACTER_LENGTH()
ist ein Synonym für
CHAR_LENGTH()
.
Gibt den String zurück, der aus der Verkettung der Argumente entsteht. Kann ein oder mehrere Argumente haben. Sind alle Argumente nichtbinäre Strings, dann ist das Ergebnis ein nichtbinärer String. Enthalten die Argumente Binär-Strings, dann ist das Ergebnis ein Binär-String. Ein numerisches Argument wird in seinen äquivalenten Binär-String konvertiert. Wollen Sie dies vermeiden, dann können Sie wie im folgenden Beispiel eine explizite Typenumwandlung vornehmen:
SELECT CONCAT(CAST(int_col
AS CHAR),char_col
);
CONCAT()
gibt NULL
zurück, sofern ein Argument NULL
ist.
mysql>SELECT CONCAT('My', 'S', 'QL');
-> 'MySQL' mysql>SELECT CONCAT('My', NULL, 'QL');
-> NULL mysql>SELECT CONCAT(14.3);
-> '14.3'
CONCAT_WS(
separator
,str1
,str2
,...)
CONCAT_WS()
(Concatenate With Separator)
ist eine Sonderform von CONCAT()
. Das erste
Argument ist das Trennzeichen für die verbleibenden
Argumente. Das Trennzeichen wird zwischen die zu verkettenden
Strings gesetzt. Das Trennzeichen kann ein String wie auch die
übrigen Argumente sein. Wenn das Trennzeichen
NULL
ist, ist das Ergebnis ebenfalls
NULL
.
mysql>SELECT CONCAT_WS(',','First name','Second name','Last Name');
-> 'First name,Second name,Last Name' mysql>SELECT CONCAT_WS(',','First name',NULL,'Last Name');
-> 'First name,Last Name'
CONCAT_WS()
überspringt Leer-Strings
nicht. NULL
-Werte nach dem
Trennzeichenargument werden hingegen übersprungen.
Wandelt Zahlen zwischen verschiedenen Zahlenbasen um. Gibt
eine String-Darstellung der Zahl N
zurück, die von der Basis
from_base
in die Basis
to_base
konvertiert wurde. Gibt
NULL
zurück, wenn eines der Argumente
NULL
ist. Das Argument
N
wird als Integer interpretiert,
kann aber als Integer oder als String angegeben werden. Die
kleinste Basis ist 2
, die größte
36
. Wenn to_base
eine negative Zahl ist, wird N
als
vorzeichenbehaftete Zahl betrachtet. Andernfalls wird
N
als vorzeichenlos behandelt.
CONV()
arbeitet mit einer Genauigkeit von
64 Bit.
mysql>SELECT CONV('a',16,2);
-> '1010' mysql>SELECT CONV('6E',18,8);
-> '172' mysql>SELECT CONV(-17,10,-18);
-> '-H' mysql>SELECT CONV(10+'10'+'10'+0xa,10,10);
-> '40'
Gibt str1
zurück, wenn
N
= 1
ist,
str2
, wenn
N
= 2
usw. Gibt
NULL
zurück, wenn
N
kleiner als 1
oder größer als die Anzahl der Argumente ist.
ELT()
ist die Ergänzung zu
FIELD()
.
mysql>SELECT ELT(1, 'ej', 'Heja', 'hej', 'foo');
-> 'ej' mysql>SELECT ELT(4, 'ej', 'Heja', 'hej', 'foo');
-> 'foo'
EXPORT_SET(
bits
,on
,off
[,separator
[,number_of_bits
]])
Gibt einen String zurück. Dabei erhalten Sie für jedes im
Wert bits
gesetzte Bit den String
on
und für jedes nicht gesetzte
Bit den String off
. Bits in
bits
werden von rechts nach links
(d. h. von den niederwertigen zu den höherwertigen Bits)
untersucht. Strings werden dem Ergebnis hingegen von links
nach rechts hinzugefügt. Sie sind durch einen Trenn-String
voneinander getrennt (standardmäßig ist dies das
Kommazeichen ‘,
’). Die Anzahl
der zu untersuchenden Bits wird über
number_of_bits
angegeben (Standard:
64).
mysql>SELECT EXPORT_SET(5,'Y','N',',',4);
-> 'Y,N,Y,N' mysql>SELECT EXPORT_SET(6,'1','0',',',10);
-> '0,1,1,0,0,0,0,0,0,0'
Gibt den Index (d. h. die Position) von
str
in der Liste
str1
,
str2
,
str3
, ...
zurück. Gibt 0
zurück, wenn
str
nicht gefunden wird.
Sind alle Argumente für FIELD()
Strings,
dann werden alle Argumente als Strings verglichen. Sind alle
Argumente Zahlen, dann werden sie als Zahlen verglichen.
Andernfalls werden die Argumente als Fließkommazahlen
verglichen.
Wenn str
NULL
ist, ist der Rückgabewert 0
, weil ein
Vergleich von NULL
mit einem beliebigen
Wert fehlschlägt. FIELD()
ist die
Ergänzung zu ELT()
.
mysql>SELECT FIELD('ej', 'Hej', 'ej', 'Heja', 'hej', 'foo');
-> 2 mysql>SELECT FIELD('fo', 'Hej', 'ej', 'Heja', 'hej', 'foo');
-> 0
Gibt einen Wert im Bereich zwischen 1 und
N
zurück, wenn der String
str
Bestandteil der String-Liste
strlist
ist, die aus
N
Teil-Strings besteht. Eine
String-Liste ist ein String, der aus durch Kommata getrennten
Teil-Strings besteht. Wenn das erste Argument ein konstanter
String und das zweite eine Spalte des Typs
SET
ist, wird die Funktion
FIND_IN_SET()
so optimiert, dass sie eine
Bitarithmetik verwendet. Gibt 0
zurück,
wenn str
nicht in
strlist
enthalten oder
strlist
der Leer-String ist. Gibt
NULL
zurück, wenn eines der Argumente
NULL
ist. Diese Funktion arbeitet nicht
einwandfrei, wenn das erste Argument ein Komma
(‘,
’) enthält.
mysql> SELECT FIND_IN_SET('b','a,b,c,d');
-> 2
Formatiert die Zahl X
in ein Format
wie '#,###,###.##'
, gerundet auf
D
Dezimalstellen, und gibt das
Ergebnis als String zurück. Wenn D
0
ist, hat das Ergebnis keinen Dezimalpunkt
und keine Nachkommastellen.
mysql>SELECT FORMAT(12332.123456, 4);
-> '12,332.1235' mysql>SELECT FORMAT(12332.1,4);
-> '12,332.1000' mysql>SELECT FORMAT(12332.2,0);
-> '12,332'
Wenn N_or_S
eine Zahl ist, wird
eine String-Darstellung des Hexadezimalwerts von
N
zurückgegeben, wobei
N
eine Longlong-Zahl
(BIGINT
) ist. Dies ist äquivalent mit
CONV(N,10,16)
.
Wenn N_or_S
ein String ist, wird
eine hexadezimale String-Darstellung von
N_or_S
zurückgegeben, wobei jedes
Zeichen in N_or_S
in zwei
Hexadezimalstellen konvertiert wird.
mysql>SELECT HEX(255);
-> 'FF' mysql>SELECT 0x616263;
-> 'abc' mysql>SELECT HEX('abc');
-> 616263
Gibt den String str
zurück.
Hierbei wird der an der Position
pos
beginnende und
len
Zeichen lange Teil-String durch
den String newstr
ersetzt. Gibt den
Ursprungs-String zurück, wenn pos
größer als die Gesamtlänge des Strings ist. Ersetzt wird
der Rest des an der Position pos
beginnenden Strings, wenn len
größer ist als der verbleibende String. Gibt
NULL
zurück, wenn eines der Argumente
NULL
ist.
mysql>SELECT INSERT('Quadratic', 3, 4, 'What');
-> 'QuWhattic' mysql>SELECT INSERT('Quadratic', -1, 4, 'What');
-> 'Quadratic' mysql>SELECT INSERT('Quadratic', 3, 100, 'What');
-> 'QuWhat'
Diese Funktion ist multibytesicher.
Gibt die Position des ersten Auftretens des Teil-Strings
substr
im String
str
zurück. Dies ist weitgehend
identisch mit der mit zwei Argumenten arbeitenden Form von
LOCATE()
; der einzige Unterschied besteht
darin, dass die Reihenfolge der Argumente umgekehrt ist.
mysql>SELECT INSTR('foobarbar', 'bar');
-> 4 mysql>SELECT INSTR('xbar', 'foobar');
-> 0
Diese Funktion ist multibytesicher. Die Groß-/Kleinschreibung wird nur dann unterschieden, wenn mindestens ein Argument ein Binär-String ist.
LCASE()
ist ein Synonym für
LOWER()
.
Gibt beginnend von links die durch
len
angegebene Anzahl von Zeichen
des Strings str
zurück.
mysql> SELECT LEFT('foobarbar', 5);
-> 'fooba'
Gibt die Länge des Strings str
angegeben in Byte zurück. Ein Multibytezeichen wird als
mehrere Bytes gezählt. Das bedeutet, dass
LENGTH()
für einen aus fünf
Zweibytezeichen bestehenden String 10
zurückgibt, CHAR_LENGTH()
hingegen
5
.
mysql> SELECT LENGTH('text');
-> 4
Liest die Datei und gibt den Dateiinhalt als String zurück.
Damit diese Funktion verwendet werden kann, muss die Datei auf
dem Serverhost liegen. Sie benötigen die Berechtigung
FILE
und müssen den vollständigen
Pfadnamen der Datei angeben. Die Datei muss von allen lesbar
und ihre Größe geringer als
max_allowed_packet
Bytes sein.
Wenn die Datei nicht vorhanden ist oder nicht gelesen werden
kann, weil eine der vorherigen Bedingungen nicht erfüllt ist,
gibt die Funktion NULL
zurück.
mysql>UPDATE t
SET blob_col=LOAD_FILE('/tmp/picture')
WHERE id=1;
LOCATE(
,
substr
,str
)LOCATE(
substr
,str
,pos
)
Die erste Syntax gibt die Position des ersten Auftretens des
Teil-Strings substr
im String
str
zurück. Die zweite Syntax gibt
die Position des ersten Auftretens des Teil-Strings
substr
im String
str
beginnend bei der Position
pos
zurück. Gibt
0
zurück, wenn
substr
nicht in
str
enthalten ist.
mysql>SELECT LOCATE('bar', 'foobarbar');
-> 4 mysql>SELECT LOCATE('xbar', 'foobar');
-> 0 mysql>SELECT LOCATE('bar', 'foobarbar', 5);
-> 7
Diese Funktion ist multibytesicher. Die Groß-/Kleinschreibung wird nur dann unterschieden, wenn mindestens ein Argument ein Binär-String ist.
Gibt den String str
mit allen
Zeichen zurück, die aufgrund der aktuellen
Zeichensatzzuordnung in Kleinbuchstaben umgewandelt wurden.
Der Standardzeichensatz ist latin1
(cp1252
West European).
mysql> SELECT LOWER('QUADRATICALLY');
-> 'quadratically'
Diese Funktion ist multibytesicher.
Gibt den String str
zurück. Dieser
wurde nach links mit dem String
padstr
auf eine Länge von
len
Zeichen aufgefüllt. Wenn
str
länger als
len
ist, wird der Rückgabewert auf
len
Zeichen gekürzt.
mysql>SELECT LPAD('hi',4,'??');
-> '??hi' mysql>SELECT LPAD('hi',1,'??');
-> 'h'
Gibt den String str
zurück, bei
dem alle Leerzeichen am Anfang entfernt wurden.
mysql> SELECT LTRIM(' barbar');
-> 'barbar'
Diese Funktion ist multibytesicher.
Gibt einen Mengenwert (d. h. einen String, der aus mit
Kommata getrennten Teil-Strings besteht) zurück. Dieser
besteht aus den Strings, bei denen das entsprechende Bit in
bits
gesetzt ist.
str1
entspricht Bit 0,
str2
Bit 1 usw.
NULL
-Werte in
str1
,
str2
, ...
werden
nicht an das Ergebnis angehängt.
mysql>SELECT MAKE_SET(1,'a','b','c');
-> 'a' mysql>SELECT MAKE_SET(1 | 4,'hello','nice','world');
-> 'hello,world' mysql>SELECT MAKE_SET(1 | 4,'hello','nice',NULL,'world');
-> 'hello' mysql>SELECT MAKE_SET(0,'a','b','c');
-> ''
MID(
ist ein Synonym für
str
,pos
,len
)SUBSTRING(
.
str
,pos
,len
)
Gibt eine String-Darstellung des Oktalwerts
N
zurück, wobei
N
eine
BIGINT
-Zahl ist. Dies ist äquivalent mit
CONV(
.
Gibt N
,10,8)NULL
zurück, wenn
N
NULL
ist.
mysql> SELECT OCT(12);
-> '14'
OCTET_LENGTH()
ist ein Synonym für
LENGTH()
.
Wenn das Zeichen ganz links im String
str
ein Multibytezeichen ist, wird
der Code dieses Zeichens zurückgegeben. Dieser wird aus den
numerischen Werten der Bytes gebildet, aus denen das Zeichen
besteht. Hierbei kommt folgende Formel zum Einsatz:
(1st byte code) + (2nd byte code × 256) + (3rd byte code × 2562) ...
Wenn das Zeichen ganz links im String kein Multibytezeichen
ist, gibt ORD()
denselben Wert zurück wie
die Funktion ASCII()
.
mysql> SELECT ORD('2');
-> 50
POSITION(
ist ein Synonym für
substr
IN
str
)LOCATE(
.
substr
,str
)
Setzt einen String in Anführungszeichen, um ein Ergebnis zu
erzeugen, das als angemessen gekennzeichneter Datenwert in
einer SQL-Anweisung verwendet werden kann. Der String wird in
einfache Anführungszeichen gesetzt zurückgegeben. Jedem
enthaltenen einzelnen Anführungszeichen
(‘'
’), Backslash
(‘\
’),
ASCII-NUL
und Strg+Z wird ein Backslash
vorangestellt. Wenn das Argument NULL
ist,
ist der Rückgabewert das Wort „NULL“ ohne
Anführungszeichen.
mysql>SELECT QUOTE('Don\'t!');
-> 'Don\'t!' mysql>SELECT QUOTE(NULL);
-> NULL
Gibt einen String zurück, der aus dem String
str
besteht, welcher
count
Mal wiederholt wird. Wenn
count
kleiner als 1 ist, wird ein
leerer String zurückgegeben. Gibt NULL
zurück, wenn str
oder
count
NULL
sind.
mysql> SELECT REPEAT('MySQL', 3);
-> 'MySQLMySQLMySQL'
Gibt den String str
zurück, bei
dem jedes Auftreten des Strings
from_str
durch den String
to_str
ersetzt wurde.
REPLACE()
führt bei der Suche nach
from_str
einen Vergleich unter
Berücksichtigung der Groß-/Kleinschreibung durch.
mysql> SELECT REPLACE('www.mysql.com', 'w', 'Ww');
-> 'WwWwWw.mysql.com'
Diese Funktion ist multibytesicher.
Gibt den String str
zurück, bei
dem die Reihenfolge der Zeichen umgekehrt wurde.
mysql> SELECT REVERSE('abc');
-> 'cba'
Diese Funktion ist multibytesicher.
Gibt beginnend von rechts die durch
len
angegebene Anzahl von Zeichen
des Strings str
zurück.
mysql> SELECT RIGHT('foobarbar', 4);
-> 'rbar'
Diese Funktion ist multibytesicher.
Gibt den String str
zurück. Dieser
wurde nach rechts mit dem String
padstr
auf eine Länge von
len
Zeichen aufgefüllt. Wenn
str
länger als
len
ist, wird der Rückgabewert auf
len
Zeichen gekürzt.
mysql>SELECT RPAD('hi',5,'?');
-> 'hi???' mysql>SELECT RPAD('hi',1,'?');
-> 'h'
Diese Funktion ist multibytesicher.
Gibt den String str
zurück, bei
dem alle Leerzeichen am Ende entfernt wurden.
mysql> SELECT RTRIM('barbar ');
-> 'barbar'
Diese Funktion ist multibytesicher.
Gibt einen Soundex-String aus str
zurück. Zwei Strings, die fast identisch klingen, sollten
identische Soundex-Strings haben. Ein Soundex-String ist
standardmäßig vier Zeichen lang, die Funktion
SOUNDEX()
gibt aber einen beliebig langen
String zurück. Sie können SUBSTRING()
für das Ergebnis verwenden, um einen Standard-Soundex-String
zu erhalten. Alle nicht alphabetischen Zeichen in
str
werden ignoriert. Alle
internationalen alphabetischen Zeichen außerhalb des Bereichs
A bis Z werden als Vokale behandelt.
mysql>SELECT SOUNDEX('Hello');
-> 'H400' mysql>SELECT SOUNDEX('Quadratically');
-> 'Q36324'
Hinweis: Diese Funktion implementiert den Soundex-Originalalgorithmus und nicht die gängigere erweiterte Version, wie sie auch von D. Knuth beschrieben wird. Der Unterschied besteht darin, dass die Originalversion zuerst Vokale und dann Duplikate verwirft, während die erweiterte Version umgekehrt vorgeht.
Dies ist das Gleiche wie
SOUNDEX(
.
expr1
) =
SOUNDEX(expr2
)
Gibt einen String zurück, der aus
N
Leerzeichen besteht.
mysql> SELECT SPACE(6);
-> ' '
SUBSTRING(
,
str
,pos
)SUBSTRING(
,
str
FROM
pos
)SUBSTRING(
,
str
,pos
,len
)SUBSTRING(
str
FROM
pos
FOR
len
)
Die Formen ohne len
-Argument geben
einen Teil-String des Strings str
zurück, der an der Position pos
beginnt. Die Formen mit
len
-Argument geben einen
Teil-String des Strings str
mit
einer Länge von len
Zeichen
zurück, der an der Position pos
beginnt. Die Formen, die FROM
verwenden,
sind SQL-Standardsyntax. Es ist auch möglich, einen negativen
Wert für pos
zu verwenden. In
diesem Fall liegt der Anfang des Teil-Strings
pos
Zeichen vom Ende des Strings
(statt von seinem Anfang) entfernt. Ein negativer Wert kann
für pos
in allen Formen dieser
Funktion verwendet werden.
mysql>SELECT SUBSTRING('Quadratically',5);
-> 'ratically' mysql>SELECT SUBSTRING('foobarbar' FROM 4);
-> 'barbar' mysql>SELECT SUBSTRING('Quadratically',5,6);
-> 'ratica' mysql>SELECT SUBSTRING('Sakila', -3);
-> 'ila' mysql>SELECT SUBSTRING('Sakila', -5, 3);
-> 'aki' mysql>SELECT SUBSTRING('Sakila' FROM -4 FOR 2);
-> 'ki'
Diese Funktion ist multibytesicher.
Wenn len
kleiner als 1 ist, wird
der Leer-String zurückgegeben.
SUBSTR()
ist ein Synonym für
SUBSTRING()
.
SUBSTRING_INDEX(
str
,delim
,count
)
Gibt einen Teil-String des Strings
str
zurück. Der Teil-String
umfasst den Teil des Strings vom Anfang bis zum
count
-sten Auftreten des
Trennzeichens delim
. Wenn
count
positiv ist, wird alles links
vom (von links gezählt) letzten Trennzeichen zurückgegeben.
Wenn count
negativ ist, wird alles
rechts vom (von rechts gezählt) letzten Trennzeichen
zurückgegeben. SUBSTRING_INDEX()
führt
bei der Suche nach delim
einen
Vergleich unter Berücksichtigung der Groß-/Kleinschreibung
durch.
mysql>SELECT SUBSTRING_INDEX('www.mysql.com', '.', 2);
-> 'www.mysql' mysql>SELECT SUBSTRING_INDEX('www.mysql.com', '.', -2);
-> 'mysql.com'
Diese Funktion ist multibytesicher.
TRIM([{BOTH | LEADING | TRAILING}
[
,
remstr
] FROM]
str
)TRIM(
remstr
FROM]
str
)
Gibt den String str
zurück, bei
dem alle remstr
-Präfixe oder
-Suffixe entfernt wurden. Wenn keine der Konfigurationsangaben
BOTH
, LEADING
oder
TRAILING
angegeben wurde, wird
BOTH
vorausgesetzt.
remstr
ist optional; sofern es
nicht angegeben ist, werden Leerzeichen entfernt.
mysql>SELECT TRIM(' bar ');
-> 'bar' mysql>SELECT TRIM(LEADING 'x' FROM 'xxxbarxxx');
-> 'barxxx' mysql>SELECT TRIM(BOTH 'x' FROM 'xxxbarxxx');
-> 'bar' mysql>SELECT TRIM(TRAILING 'xyz' FROM 'barxxyz');
-> 'barx'
Diese Funktion ist multibytesicher.
UCASE()
ist ein Synonym für
UPPER()
.
Führt die umgekehrte Operation von
HEX(
durch:
Jedes Paar Hexadezimalziffern im Argument wird als Zahl
interpretiert und in das Zeichen umgewandelt, das durch die
Zahl dargestellt wird. Das Ergebnis wird als Binär-String
zurückgegeben.
str
)
mysql>SELECT UNHEX('4D7953514C');
-> 'MySQL' mysql>SELECT 0x4D7953514C;
-> 'MySQL' mysql>SELECT UNHEX(HEX('string'));
-> 'string' mysql>SELECT HEX(UNHEX('1267'));
-> '1267'
Gibt den String str
mit allen
Zeichen zurück, die aufgrund der aktuellen
Zeichensatzzuordnung in Großbuchstaben umgewandelt wurden.
Der Standardzeichensatz ist latin1
(cp1252
West European).
mysql> SELECT UPPER('Hej');
-> 'HEJ'
Diese Funktion ist multibytesicher.
Wenn einer String-Funktion ein Binär-String als Argument übergeben wird, ist der Ergebnis-String ebenfalls ein Binär-String. Eine Zahl, die in einen String konvertiert wird, wird als Binär-String behandelt. Dies betrifft nur Vergleiche.
Wenn ein Ausdruck in einem String-Vergleich die Groß-/Kleinschreibung unterscheidet, dann wird der Vergleich ebenfalls mit Unterscheidung der Groß-/Kleinschreibung durchgeführt.
expr
LIKE
pat
[ESCAPE
'escape_char
']
Mustervergleich unter Verwendung eines einfachen
SQL-Vergleichs mit regulären Ausdrücken. Gibt
1
(TRUE
) oder
0
(FALSE
) zurück.
Wenn entweder expr
oder
pat
NULL
sind,
ist das Ergebnis NULL
.
Das Muster muss kein literaler String sein. Es kann beispielsweise auch als String-Ausdruck oder als Tabellenspalte angegeben werden.
Gemäß dem SQL-Standard führt LIKE
die
Überprüfung auf Zeichenbasis durch, kann also Ergebnisse
erzeugen, die sich von denen des Vergleichsoperators
=
unterscheiden:
mysql>SELECT 'ä' LIKE 'ae' COLLATE latin1_german2_ci;
+-----------------------------------------+ | 'ä' LIKE 'ae' COLLATE latin1_german2_ci | +-----------------------------------------+ | 0 | +-----------------------------------------+ mysql>SELECT 'ä' = 'ae' COLLATE latin1_german2_ci;
+--------------------------------------+ | 'ä' = 'ae' COLLATE latin1_german2_ci | +--------------------------------------+ | 1 | +--------------------------------------+
Bei LIKE
können Sie die folgenden beiden
Jokerzeichen im Muster verwenden:
Zeichen | Beschreibung |
% | entspricht einer beliebigen Anzahl von Zeichen (einschließlich null Zeichen). |
_ | entspricht genau einem Zeichen. |
mysql>SELECT 'David!' LIKE 'David_';
-> 1 mysql>SELECT 'David!' LIKE '%D%v%';
-> 1
Um auf literale Instanzen eines Jokerzeichens zu prüfen,
stellen Sie ihm ein Escape-Zeichen voran. Wenn Sie das
Escape-Zeichen nicht angeben, wird
‘\
’ angenommen.
String | Beschreibung |
\% | entspricht einem ‘% ’-Zeichen. |
\_ | entspricht einem ‘_ ’-Zeichen. |
mysql>SELECT 'David!' LIKE 'David\_';
-> 0 mysql>SELECT 'David_' LIKE 'David\_';
-> 1
Um ein anderes Escape-Zeichen anzugeben, verwenden Sie die
ESCAPE
-Klausel:
mysql> SELECT 'David_' LIKE 'David|_' ESCAPE '|';
-> 1
Die Escape-Sequenz sollte leer oder genau ein Zeichen lang
sein. Ab MySQL 5.1.2 darf die Sequenz nicht leer sein, wenn
der SQL-Modus NO_BACKSLASH_ESCAPES
aktiviert wurde.
Die folgenden beiden Anweisungen veranschaulichen, dass die Groß-/Kleinschreibung bei String-Vergleichen nicht unterschieden wird, sofern nicht einer der Operanden ein Binär-String ist:
mysql>SELECT 'abc' LIKE 'ABC';
-> 1 mysql>SELECT 'abc' LIKE BINARY 'ABC';
-> 0
In MySQL ist LIKE
für numerische
Ausdrücke zulässig. (Dies stellt eine Erweiterung zu
LIKE
nach SQL-Standard dar.)
mysql> SELECT 10 LIKE '1%';
-> 1
Hinweis: Weil MySQL die
C-Escape-Syntax in Strings verwendet (z. B.
‘\n
’ zur Darstellung eines
Zeilenwechsels), müssen Sie jedes
‘\
’, das Sie in
LIKE
-Strings verwenden, verdoppeln. Um
beispielsweise nach ‘\n
’ zu
suchen, geben Sie es als
‘\\n
’ an. Um nach
‘\
’ zu suchen, geben Sie es
als ‘\\\\
’ an; dies ist
erforderlich, weil Backslashs einmal vom Parser und dann
noch einmal bei Durchführung des Mustervergleichs
umgewandelt werden – so bleibt für den Vergleich ein
einzelner Backslash übrig.
expr
NOT LIKE
pat
[ESCAPE
'escape_char
']
Dies ist das Gleiche wie NOT
(
.
expr
LIKE
pat
[ESCAPE
'escape_char
'])
,
expr
NOT REGEXP
pat
expr
NOT RLIKE
pat
Dies ist das Gleiche wie NOT
(
.
expr
REGEXP
pat
)
expr
REGEXP
pat
expr
RLIKE
pat
Führt einen Mustervergleich eines String-Ausdrucks
expr
mit einem Muster
pat
durch. Das Muster kann ein
erweiterter regulärer Ausdruck sein. Die Syntax für
reguläre Ausdrücke wird in Anhang G, Beschreibung der MySQL-Syntax für reguläre Ausdrücke,
beschrieben. Gibt 1
zurück, wenn
expr
mit
pat
übereinstimmt; andernfalls
wird 0
zurückgegeben. Wenn entweder
expr
oder
pat
NULL
sind,
ist das Ergebnis auch NULL
.
RLIKE
ist ein Synonym für
REGEXP
, welches aus Gründen der
mSQL
-Kompatibilität vorhanden ist.
Das Muster muss kein literaler String sein. Es kann beispielsweise auch als String-Ausdruck oder als Tabellenspalte angegeben werden.
Hinweis: Weil MySQL die
C-Escape-Syntax in Strings verwendet (z. B.
‘\n
’ zur Darstellung eines
Zeilenwechsels), müssen Sie jedes
‘\
’, das Sie in
REGEXP
-Strings verwenden, verdoppeln.
REGEXP
unterscheidet die
Groß-/Kleinschreibung nur dann, wenn sie mit Binär-Strings
verwendet wird.
mysql>SELECT 'Monty!' REGEXP 'm%y%%';
-> 0 mysql>SELECT 'Monty!' REGEXP '.*';
-> 1 mysql>SELECT 'new*\n*line' REGEXP 'new\\*.\\*line';
-> 1 mysql>SELECT 'a' REGEXP 'A', 'a' REGEXP BINARY 'A';
-> 1 0 mysql>SELECT 'a' REGEXP '^[a-d]';
-> 1
REGEXP
und RLIKE
verwenden zur Erkennung des Typs eines Zeichens den
aktuellen Zeichensatz. Der Standardzeichensatz ist
latin1
(cp1252 West European).
Warnung: Diese Operatoren
sind nicht multibytesicher.
STRCMP()
gibt 0
zurück, wenn die Strings identisch sind,
-1
, wenn das erste Argument entsprechend
der aktuellen Sortierreihenfolge kleiner ist als das zweite,
und 1
in jedem anderen Fall.
mysql>SELECT STRCMP('text', 'text2');
-> -1 mysql>SELECT STRCMP('text2', 'text');
-> 1 mysql>SELECT STRCMP('text', 'text');
-> 0
STRCMP()
verwendet zur Durchführung von
Vergleichsoperationen den aktuellen Zeichensatz. Insofern
wird die Groß-/Kleinschreibung bei Vergleichen
standardmäßig nicht unterschieden, sofern nicht mindestens
einer der Operanden ein Binär-String ist.
Es stehen die normalen arithmetischen Operatoren zur Verfügung.
Beachten Sie, dass das Ergebnis im Fall von
-
, +
und *
mit
BIGINT
-Genauigkeit (64-Bit-Genauigkeit)
berechnet wird, sofern beide Argumente Integers sind. Wenn eines
der Argumente ein vorzeichenloser Integer und das andere auch
ein Integer ist, dann ist das Ergebnis ein vorzeichenloser
Integer. Siehe auch Abschnitt 12.8, „Cast-Funktionen und Operatoren“.
Addition:
mysql> SELECT 3+5;
-> 8
Subtraktion:
mysql> SELECT 3-5;
-> -2
Monadisches Minus. Dieser Operator ändert das Vorzeichen des Arguments.
mysql> SELECT - 2;
-> -2
Hinweis: Wenn der Operator
mit einem BIGINT
verwendet wird, ist der
Rückgabewert ebenfalls ein BIGINT
. Das
bedeutet, dass Sie die Verwendung von
–
bei Integers vermeiden sollten,
die den Wert –263 annehmen
könnten.
Multiplikation:
mysql>SELECT 3*5;
-> 15 mysql>SELECT 18014398509481984*18014398509481984.0;
-> 324518553658426726783156020576256.0 mysql>SELECT 18014398509481984*18014398509481984;
-> 0
Das Ergebnis des letzten Ausdrucks ist falsch, weil das
Ergebnis der Integer-Multiplikation den 64-Bit-Bereich von
BIGINT
-Berechnungen überschreitet.
(Siehe auch Abschnitt 11.2, „Numerische Datentypen“.)
Division:
mysql> SELECT 3/5;
-> 0.60
Die Division durch null erzeugt das Ergebnis
NULL
:
mysql> SELECT 102/(1-1);
-> NULL
Eine Division wird nur dann mit
BIGINT
-Arithmetik berechnet, wenn sie in
einem Kontext durchgeführt wird, in dem das Ergebnis in
einen Integer konvertiert wird.
Integer-Division. Ähnlich wie FLOOR()
,
aber sicher bei BIGINT
-Werten.
mysql> SELECT 5 DIV 2;
-> 2
Alle mathematischen Funktionen geben im Fehlerfall
NULL
zurück.
Gibt den absoluten Wert von X
zurück.
mysql>SELECT ABS(2);
-> 2 mysql>SELECT ABS(-32);
-> 32
Diese Funktion kann sicher mit
BIGINT
-Werten eingesetzt werden.
Gibt den Arkuskosinus von X
zurück, d. h. den Wert, dessen Kosinus
X
ist. Gibt
NULL
zurück, wenn
X
nicht im Bereich zwischen
-1
und 1
liegt.
mysql>SELECT ACOS(1);
-> 0 mysql>SELECT ACOS(1.0001);
-> NULL mysql>SELECT ACOS(0);
-> 1.5707963267949
Gibt den Arkussinus von X
zurück, d. h. den Wert, dessen Sinus
X
ist. Gibt
NULL
zurück, wenn
X
nicht im Bereich zwischen
-1
und 1
liegt.
mysql>SELECT ASIN(0.2);
-> 0.20135792079033 mysql>SELECT ASIN('foo');
+-------------+ | ASIN('foo') | +-------------+ | 0 | +-------------+ 1 row in set, 1 warning (0.00 sec) mysql>SHOW WARNINGS;
+---------+------+-----------------------------------------+ | Level | Code | Message | +---------+------+-----------------------------------------+ | Warning | 1292 | Truncated incorrect DOUBLE value: 'foo' | +---------+------+-----------------------------------------+
Gibt den Arkustangens von X
zurück, d. h. den Wert, dessen Tangens
X
ist.
mysql>SELECT ATAN(2);
-> 1.1071487177941 mysql>SELECT ATAN(-2);
-> -1.1071487177941
Gibt den Arkustangens der beiden Variablen
X
und
Y
zurück. Dies ähnelt der
Berechnung des Arkustangens von
; der einzige
Unterschied besteht darin, dass die Vorzeichen beider
Argumente zur Bestimmung des Quadranten des Ergebnisses
verwendet werden.
Y
/
X
mysql>SELECT ATAN(-2,2);
-> -0.78539816339745 mysql>SELECT ATAN2(PI(),0);
-> 1.5707963267949
Gibt den kleinsten Integer-Wert zurück, der nicht kleiner
als X
ist.
mysql>SELECT CEILING(1.23);
-> 2 mysql>SELECT CEIL(-1.23);
-> -1
Diese beiden Funktionen sind synonym. Beachten Sie, dass der
Rückgabewert in ein BIGINT
konvertiert
wird.
Gibt den Kosinus von X
zurück,
wobei X
in rad angegeben wird.
mysql> SELECT COS(PI());
-> -1
Gibt den Kotangens von X
zurück.
mysql>SELECT COT(12);
-> -1.5726734063977 mysql>SELECT COT(0);
-> NULL
Berechnet einen Prüfsummenwert (CRC, Cyclic Redundancy
Check) und gibt einen vorzeichenlosen 32-Bit-Wert zurück.
Das Ergebnis ist NULL
, wenn das Argument
NULL
ist. Als Argument wird ein String
erwartet, der dann (sofern möglich) so behandelt wird, als
wäre er keiner.
mysql>SELECT CRC32('MySQL');
-> 3259397556 mysql>SELECT CRC32('mysql');
-> 2501908538
Gibt das Argument X
umgewandelt
von rad in Grad zurück.
mysql>SELECT DEGREES(PI());
-> 180 mysql>SELECT DEGREES(PI() / 2);
-> 90
Gibt den Wert von e (Basis natürlicher
Logarithmen) zur Potenz X
zurück.
mysql>SELECT EXP(2);
-> 7.3890560989307 mysql>SELECT EXP(-2);
-> 0.13533528323661 mysql>SELECT EXP(0);
-> 1
Gibt den größten Integer-Wert zurück, der nicht größer
als X
ist.
mysql>SELECT FLOOR(1.23);
-> 1 mysql>SELECT FLOOR(-1.23);
-> -2
Beachten Sie, dass der Rückgabewert in ein
BIGINT
konvertiert wird.
FORMAT(
X
,D
)
Formatiert die Zahl X
in ein
Format wie '#,###,###.##'
, gerundet auf
D
Dezimalstellen, und gibt das
Ergebnis als String zurück. Detaillierte Informationen
finden Sie in Abschnitt 12.3, „String-Funktionen“.
Gibt den natürlichen Logarithmus von
X
zurück, d. h. den Logarithmus
von X
zur Basis
e.
mysql>SELECT LN(2);
-> 0.69314718055995 mysql>SELECT LN(-2);
-> NULL
Diese Funktion ist synonym zu
LOG(
.
X
)
Sofern mit einem Parameter aufgerufen, gibt diese Funktion
den natürlichen Logarithmus von
X
zurück.
mysql>SELECT LOG(2);
-> 0.69314718055995 mysql>SELECT LOG(-2);
-> NULL
Wenn der Aufruf mit zwei Parametern erfolgt, gibt die
Funktion den Logarithmus von X
zur (beliebig anzugebenden) Basis
B
zurück.
mysql>SELECT LOG(2,65536);
-> 16 mysql>SELECT LOG(10,100);
-> 2
LOG(
ist äquivalent mit
B
,X
)LOG(
.
X
) /
LOG(B
)
Gibt den Logarithmus von
zur Basis 2
zurück.
X
mysql>SELECT LOG2(65536);
-> 16 mysql>SELECT LOG2(-100);
-> NULL
LOG2()
ist praktisch, um zu ermitteln,
wie viele Bits eine Zahl zur Speicherung benötigt. Die
Funktion ist äquivalent zu dem Ausdruck
LOG(
.
X
) /
LOG(2)
Gibt den Logarithmus von X
zur
Basis 10 zurück.
mysql>SELECT LOG10(2);
-> 0.30102999566398 mysql>SELECT LOG10(100);
-> 2 mysql>SELECT LOG10(-100);
-> NULL
LOG10(
ist
äquivalent mit
X
)LOG(10,
.
X
)
Modulooperation. Gibt den Rest von
N
geteilt durch
M
zurück.
mysql>SELECT MOD(234, 10);
-> 4 mysql>SELECT 253 % 7;
-> 1 mysql>SELECT MOD(29,9);
-> 2 mysql>SELECT 29 MOD 9;
-> 2
Diese Funktion kann mit BIGINT
-Werten
sicher eingesetzt werden.
MOD()
funktioniert auch bei Werten mit
Nachkommastellen und gibt den exakten Rest nach der Division
zurück:
mysql> SELECT MOD(34.5,3);
-> 1.5
Gibt den Wert von π (Pi) zurück. Standardmäßig werden sieben Dezimalstellen angezeigt, MySQL verwendet intern jedoch den vollständigen Wert doppelter Genauigkeit.
mysql>SELECT PI();
-> 3.141593 mysql>SELECT PI()+0.000000000000000000;
-> 3.141592653589793116
Gibt den Wert von X
potenziert zu
Y
an.
mysql>SELECT POW(2,2);
-> 4 mysql>SELECT POW(2,-2);
-> 0.25
Gibt das Argument X
umgewandelt
von Grad in rad zurück. (Beachten Sie, dass π rad 180
Grad entspricht.)
mysql> SELECT RADIANS(90);
-> 1.5707963267949
Gibt einen zufälligen Fließkommawert
v
zwischen 0
und 1
inklusive (d. h. im Bereich
0
<= v
<= 1.0
) zurück. Wenn ein
Integer-Argument N
angegeben ist,
wird es als Ausgangswert verwendet, der eine wiederholbare
Sequenz erzeugt.
mysql>SELECT RAND();
-> 0.9233482386203 mysql>SELECT RAND(20);
-> 0.15888261251047 mysql>SELECT RAND(20);
-> 0.15888261251047 mysql>SELECT RAND();
-> 0.63553050033332 mysql>SELECT RAND();
-> 0.70100469486881 mysql>SELECT RAND(20);
-> 0.15888261251047
Um einen zufälligen Integer R
im
Bereich i
<=
R
<=
j
zu erhalten, verwenden Sie den
Ausdruck FLOOR(
. Um
beispielsweise einen ganzzahligen Zufallswert im Bereich
zwischen 7 und 12 (einschließlich) zu erhalten, können Sie
die folgende Anweisung verwenden:
i
+
RAND() * (j
–
i
+ 1))
SELECT FLOOR(7 + (RAND() * 6));
Sie können eine Spalte mit RAND()
-Werten
nicht in einer ORDER BY
-Klausel angeben,
weil ORDER BY
die Spalte mehrfach
auswerten würde. Allerdings können Sie Datensätze in
zufälliger Folge abrufen. Das funktioniert wie folgt:
mysql> SELECT * FROM tbl_name
ORDER BY RAND();
ORDER BY RAND()
in Kombination mit
LIMIT
ist nützlich zur Auswahl eines
Zufallswerts aus einer Datensatzmenge:
mysql>SELECT * FROM table1, table2 WHERE a=b AND c<d
->ORDER BY RAND() LIMIT 1000;
Beachten Sie, dass RAND()
in einer
WHERE
-Klausel jedes Mal, wenn
WHERE
ausgeführt wird, neu ausgewertet
wird.
RAND()
ist nicht als perfekter
Zufallsgenerator gedacht, sondern stellt eine gute
Möglichkeit da, ad hoc
Zufallszahlen zu erzeugen, die innerhalb derselben
MySQL-Version plattformübergreifend funktioniert.
Gibt das Argument X
gerundet auf
den nächstgelegenen Integer zurück. Bei zwei übergebenen
Argumenten wird X
gerundet auf
D
Dezimalstellen zurückgegeben.
D
kann negativ sein; in diesem
Fall werden D
Stellen links des
Dezimalpunkts des Werts X
null.
mysql>SELECT ROUND(-1.23);
-> -1 mysql>SELECT ROUND(-1.58);
-> -2 mysql>SELECT ROUND(1.58);
-> 2 mysql>SELECT ROUND(1.298, 1);
-> 1.3 mysql>SELECT ROUND(1.298, 0);
-> 1 mysql>SELECT ROUND(23.298, -1);
-> 20
Der Rückgabetyp ist derselbe wie der des ersten Arguments (vorausgesetzt, dies ist ein Integer, eine Fließkommazahl oder eine Dezimalzahl). Das bedeutet, dass bei einem Integer-Argument das Ergebnis ein Integer ist (der keine Dezimalstellen aufweist).
ROUND()
verwendet für genaue Zahlen die
Precision-Math-Bibliothek, wenn das erste Argument ein
Dezimalwert ist:
Bei genauen Zahlen verwendet ROUND()
die gängigen Rundungsregeln: Ein Wert mit einem Wert
von 5 oder größer nach dem Komma wird auf den
nächsten Integer aufgerundet bzw. (bei negativen
Werten) abgerundet. (Anders gesagt: Die Rundung erfolgt
von Null weg.) Ein Wert mit einem Wert von weniger als 5
nach dem Komma wird auf den nächsten Integer abgerundet
bzw. (bei negativen Werten) aufgerundet.
Bei Näherungswerten hängt das Ergebnis von der
C-Bibliothek ab. Auf vielen Systemen bedeutet dies, dass
ROUND()
die Regel „auf nächste
gerade Zahl aufrunden“ einsetzt: Ein Wert mit
Nachkommastellen wird auf den nächsten geraden Integer
gerundet.
Das folgende Beispiel zeigt, wie die Rundung sich bei exakten und bei Näherungswerten voneinander unterscheidet:
mysql> SELECT ROUND(2.5), ROUND(25E-1);
+------------+--------------+
| ROUND(2.5) | ROUND(25E-1) |
+------------+--------------+
| 3 | 2 |
+------------+--------------+
Weitere Informationen finden Sie unter Kapitel 23, Präzisionsberechnungen.
Gibt das Vorzeichen des Arguments als -1
,
0
oder 1
abhängig
davon zurück, ob X
negativ, null
oder positiv ist.
mysql>SELECT SIGN(-32);
-> -1 mysql>SELECT SIGN(0);
-> 0 mysql>SELECT SIGN(234);
-> 1
Gibt den Sinus von X
zurück,
wobei X
in rad angegeben wird.
mysql>SELECT SIN(PI());
-> 1.2246063538224e-16 mysql>SELECT ROUND(SIN(PI()));
-> 0
Gibt die Quadratwurzel einer nichtnegativen Zahl
X
zurück.
mysql>SELECT SQRT(4);
-> 2 mysql>SELECT SQRT(20);
-> 4.4721359549996 mysql>SELECT SQRT(-16);
-> NULL
Gibt den Tangens von X
zurück,
wobei X
in rad angegeben wird.
mysql>SELECT TAN(PI());
-> -1.2246063538224e-16 mysql>SELECT TAN(PI()+1);
-> 1.5574077246549
Gibt die Zahl X
auf
D
Dezimalstellen beschnitten
zurück. Wenn D
0
ist, hat das Ergebnis keinen
Dezimalpunkt und keine Nachkommastellen.
D
kann auch negativ sein. In
diesem Fall werden D
Stellen
links vom Dezimalpunkt des Werts
X
null.
mysql>SELECT TRUNCATE(1.223,1);
-> 1.2 mysql>SELECT TRUNCATE(1.999,1);
-> 1.9 mysql>SELECT TRUNCATE(1.999,0);
-> 1 mysql>SELECT TRUNCATE(-1.999,1);
-> -1.9 mysql>SELECT TRUNCATE(122,-2);
-> 100 mysql>SELECT TRUNCATE(10.28*100,0);
-> 1028
Alle Zahlen werden nach null hin gerundet.
Dieser Abschnitt beschreibt die Funktionen, die zur Manipulation von zeitbezogenen Werten verwendet werden können. Eine Beschreibung der Wertebereiche für Datums- und Uhrzeittypen und der gültigen Formate, in denen Werte angegeben werden können, finden Sie in Abschnitt 11.3, „Datums- und Zeittypen“.
Es folgt ein Beispiel, welches Datumsfunktionen verwendet. Die
folgende Abfrage wählt alle Datensätze aus, die einen
date_col
-Wert haben, der in den letzten
30 Tagen liegt:
mysql>SELECT
->something
FROMtbl_name
WHERE DATE_SUB(CURDATE(),INTERVAL 30 DAY) <=
date_col
;
Beachten Sie, dass die Abfrage auch Datensätze mit Daten auswählt, die in der Zukunft liegen.
Funktionen, die Datumswerte erwarten, akzeptieren normalerweise
auch DATETIME
-Werte und ignorieren dabei den
Uhrzeitbestandteil. Ähnlich akzeptieren Funktionen, die Zeitwerte
erwarten, normalerweise auch DATETIME
-Werte und
ignorieren den Datumsbestandteil.
Funktionen, die das aktuelle Datum oder die Uhrzeit zurückgeben,
werden nur einmal pro Abfrage ausgewertet, nämlich beim Start der
Abfrageausführung. Das bedeutet, dass mehrere Referenzierungen
einer Funktion wie NOW()
in einer Abfrage immer
zum selben Ergebnis führen (für unsere Zwecke enthält eine
einzelne Abfrage auch einen Aufruf einer gespeicherten Routine
oder eines Triggers sowie alle Subroutinen, die von dieser Routine
oder diesem Trigger aufgerufen werden). Dieses Prinzip gilt auch
für CURDATE()
, CURTIME()
,
UTC_DATE()
, UTC_TIME()
,
UTC_TIMESTAMP()
und für alle zugehörigen
Synonyme.
Die Funktionen CURRENT_TIMESTAMP()
,
CURRENT_TIME()
,
CURRENT_DATE()
und
FROM_UNIXTIME()
geben Werte in der aktuellen
Zeitzone der Verbindung zurück, die als Wert der Systemvariablen
time_zone
verfügbar ist. Ferner setzt
UNIX_TIMESTAMP()
voraus, dass sein Argument ein
DATETIME
-Wert in der aktuellen Zeitzone ist.
Siehe auch Abschnitt 5.11.8, „Zeitzonen-Unterstützung des MySQL-Servers“.
Einige Datumsfunktionen können mit „Nulldaten“ oder
unvollständigen Daten wie '2001-11-00'
verwendet werden, während dies bei anderen nicht möglich ist.
Funktionen, die Teile von Datumsangaben extrahieren, arbeiten
meist auch mit unvollständigen Daten. Zum Beispiel:
mysql> SELECT DAYOFMONTH('2001-11-00'), MONTH('2005-00-00');
-> 0, 0
Andere Funktionen erwarten vollständige Daten und geben
NULL
zurück, wenn unvollständige Daten
übergeben werden. Hierzu gehören Funktionen, die
Datumsberechnungen durchführen oder Teile von Datumsangaben Namen
zuordnen. Zum Beispiel:
mysql>SELECT DATE_ADD('2006-05-00',INTERVAL 1 DAY);
-> NULL mysql>SELECT DAYNAME('2006-05-00');
-> NULL
ADDDATE(
,
date
,INTERVAL
expr
type
)ADDDATE(
expr
,days
)
Wenn mit der Form INTERVAL
für das zweite
Argument aufgerufen, ist ADDDATE()
ein
Synonym von DATE_ADD()
. Die zugehörige
Funktion SUBDATE()
ist ein Synonym für
DATE_SUB()
. Weitere Informationen zum
Argument INTERVAL
finden Sie in der
Beschreibung zu DATE_ADD()
.
mysql>SELECT DATE_ADD('1998-01-02', INTERVAL 31 DAY);
-> '1998-02-02' mysql>SELECT ADDDATE('1998-01-02', INTERVAL 31 DAY);
-> '1998-02-02'
Wenn mit der Form days
für das
zweite Argument aufgerufen, wird es von MySQL als ganzzahlige
Anzahl von Tagen behandelt, die
expr
hinzugefügt wird.
mysql> SELECT ADDDATE('1998-01-02', 31);
-> '1998-02-02'
ADDTIME()
fügt
expr2
expr
hinzu und gibt das Ergebnis
zurück. expr
ist eine Zeitangabe
oder ein DATETIME
-Wert,
expr2
eine Zeitangabe.
mysql>SELECT ADDTIME('1997-12-31 23:59:59.999999',
->'1 1:1:1.000002');
-> '1998-01-02 01:01:01.000001' mysql>SELECT ADDTIME('01:00:00.999999', '02:00:00.999998');
-> '03:00:01.999997'
CONVERT_TZ()
wandelt einen
DATETIME
-Wert dt
von der angegebenen Ausgangszeitzone
from_tz
in die Zielzeitzone
to_tz
um und gibt das Ergebnis
zurück. Zeitzonen werden wie in
Abschnitt 5.11.8, „Zeitzonen-Unterstützung des MySQL-Servers“, beschrieben angegeben.
Die Funktion gibt NULL
zurück, wenn die
Argumente ungültig sind.
Fiele der Wert durch die Konvertierung aus
from_tz
in UTC außerhalb des vom
Typ TIMESTAMP
unterstützten Bereichs, dann
erfolgt keine Konvertierung. Der für
TIMESTAMP
gültige Bereich ist in
Abschnitt 11.1.2, „Überblick über Datums- und Zeittypen“, beschrieben.
mysql>SELECT CONVERT_TZ('2004-01-01 12:00:00','GMT','MET');
-> '2004-01-01 13:00:00' mysql>SELECT CONVERT_TZ('2004-01-01 12:00:00','+00:00','+10:00');
-> '2004-01-01 22:00:00'
Hinweis: Wenn Sie benannte
Zeitzonen wie 'MET'
oder
'Europe/Moscow'
verwenden wollen, müssen
die Zeitzonentabellen korrekt konfiguriert sein. Eine
Anleitung finden Sie in Abschnitt 5.11.8, „Zeitzonen-Unterstützung des MySQL-Servers“.
Gibt das aktuelle Datum als Wert in den Formaten
'YYYY-MM-DD'
oder
YYYYMMDD
aus. Das Ausgabeformat hängt
davon ab, ob die Funktion in einem String- oder einem
numerischen Kontext verwendet wird.
mysql>SELECT CURDATE();
-> '1997-12-15' mysql>SELECT CURDATE() + 0;
-> 19971215
CURRENT_DATE
und
CURRENT_DATE()
sind Synonyme von
CURDATE()
.
Gibt die aktuelle Uhrzeit als Wert in den Formaten
'HH:MM:SS'
oder HHMMSS
aus. Das Ausgabeformat hängt davon ab, ob die Funktion in
einem String- oder einem numerischen Kontext verwendet wird.
mysql>SELECT CURTIME();
-> '23:50:26' mysql>SELECT CURTIME() + 0;
-> 235026
CURRENT_TIME
und
CURRENT_TIME()
sind Synonyme von
CURTIME()
.
CURRENT_TIMESTAMP
,
CURRENT_TIMESTAMP()
CURRENT_TIMESTAMP
und
CURRENT_TIMESTAMP()
sind Synonyme von
NOW()
.
Extrahiert den Datumsteil aus dem DATE
-
oder DATETIME
-Ausdruck
expr
.
mysql> SELECT DATE('2003-12-31 01:02:03');
-> '2003-12-31'
DATEDIFF()
gibt die Anzahl der Tage
zwischen dem Startdatum expr
und
dem Enddatum expr2
zurück.
expr
und
expr2
sind DATE
-
oder DATETIME
-Ausdrücke. Nur die
Datumsanteile der Werte werden in der Berechnung verwendet.
mysql>SELECT DATEDIFF('1997-12-31 23:59:59','1997-12-30');
-> 1 mysql>SELECT DATEDIFF('1997-11-30 23:59:59','1997-12-31');
-> -31
DATE_ADD(
,
date
,INTERVAL
expr
type
)DATE_SUB(
date
,INTERVAL
expr
type
)
Diese Funktionen führen Datumsberechnungen durch.
date
ist ein
DATETIME
- oder
DATE
-Wert, der das Startdatum angibt.
expr
ist ein Ausdruck, der den vom
Startdatum hinzuzufügenden oder abzuziehenden Intervallwert
angibt. expr
ist dabei ein String
und kann bei negativen Intervallen mit einem
‘-
’ beginnen.
type
ist ein Schlüsselwort, das
angibt, wie der Ausdruck zu interpretieren ist.
Das Schlüsselwort INTERVAL
und die Angabe
type
unterscheiden die
Groß-/Kleinschreibung nicht.
Die folgende Tabelle zeigt die erwartete Form des Arguments
expr
für die einzelnen
type
-Werte.
type Wert | Erwartetes
expr -Format |
MICROSECOND | MICROSECONDS |
SECOND | SECONDS |
MINUTE | MINUTES |
HOUR | HOURS |
DAY | DAYS |
WEEK | WEEKS |
MONTH | MONTHS |
QUARTER | QUARTERS |
YEAR | YEARS |
SECOND_MICROSECOND | 'SECONDS.MICROSECONDS' |
MINUTE_MICROSECOND | 'MINUTES.MICROSECONDS' |
MINUTE_SECOND | 'MINUTES:SECONDS' |
HOUR_MICROSECOND | 'HOURS.MICROSECONDS' |
HOUR_SECOND | 'HOURS:MINUTES:SECONDS' |
HOUR_MINUTE | 'HOURS:MINUTES' |
DAY_MICROSECOND | 'DAYS.MICROSECONDS' |
DAY_SECOND | 'DAYS HOURS:MINUTES:SECONDS' |
DAY_MINUTE | 'DAYS HOURS:MINUTES' |
DAY_HOUR | 'DAYS HOURS' |
YEAR_MONTH | 'YEARS-MONTHS' |
MySQL erlaubt die Verwendung beliebiger Interpunktionszeichen
als Trennzeichen im Format von
expr
. Die in der Tabelle gezeigten
Trennzeichen sind als Vorschläge aufzufassen. Wenn das
Argument date
ein
DATE
-Wert ist und Ihre Berechnungen nur die
Teile YEAR
, MONTH
und
DAY
(also keine uhrzeitbezogenen Teile)
betreffen, ist das Ergebnis ein DATE
-Wert.
Andernfalls ist das Ergebnis ein
DATETIME
-Wert.
Datumsberechnungen können auch mit
INTERVAL
in Kombination mit den Operatoren
+
und -
durchgeführt
werden:
date
+ INTERVALexpr
type
date
- INTERVALexpr
type
INTERVAL
ist auf beiden
Seiten des Operators expr
type
+
zulässig, wenn der
Ausdruck auf der jeweils anderen Seite ein
DATE
- oder DATETIME
-Wert
ist. Beim Operator -
ist INTERVAL
nur auf der rechten
Seite der Gleichung zulässig, da das Abziehen eines
expr
type
DATE
- oder
DATETIME
-Werts von einem Intervall unsinnig
wäre.
mysql>SELECT '1997-12-31 23:59:59' + INTERVAL 1 SECOND;
-> '1998-01-01 00:00:00' mysql>SELECT INTERVAL 1 DAY + '1997-12-31';
-> '1998-01-01' mysql>SELECT '1998-01-01' - INTERVAL 1 SECOND;
-> '1997-12-31 23:59:59' mysql>SELECT DATE_ADD('1997-12-31 23:59:59',
->INTERVAL 1 SECOND);
-> '1998-01-01 00:00:00' mysql>SELECT DATE_ADD('1997-12-31 23:59:59',
->INTERVAL 1 DAY);
-> '1998-01-01 23:59:59' mysql>SELECT DATE_ADD('1997-12-31 23:59:59',
->INTERVAL '1:1' MINUTE_SECOND);
-> '1998-01-01 00:01:00' mysql>SELECT DATE_SUB('1998-01-01 00:00:00',
->INTERVAL '1 1:1:1' DAY_SECOND);
-> '1997-12-30 22:58:59' mysql>SELECT DATE_ADD('1998-01-01 00:00:00',
->INTERVAL '-1 10' DAY_HOUR);
-> '1997-12-30 14:00:00' mysql>SELECT DATE_SUB('1998-01-02', INTERVAL 31 DAY);
-> '1997-12-02' mysql>SELECT DATE_ADD('1992-12-31 23:59:59.000002',
->INTERVAL '1.999999' SECOND_MICROSECOND);
-> '1993-01-01 00:00:01.000001'
Wenn Sie einen Intervallwert angeben, der zu kurz ist (d. h.
nicht alle Intervallteile enthält, die aufgrund des
Schlüsselworts type
erwartet
werden), dann geht MySQL davon aus, dass Sie den linken Teil
des Intervallwerts weggelassen haben. Geben Sie also etwa als
type
DAY_SECOND
an, dann
wird erwartet, dass der Wert von
expr
Teile für Tage, Stunden,
Minuten und Sekunden enthält. Bei einer Angabe
'1:10'
setzt MySQL voraus, dass die Teile
für Tage und Stunden fehlen und der Wert Minuten und Sekunden
angibt. Anders gesagt, wird '1:10'
DAY_SECOND
als äquivalent zu '1:10'
MINUTE_SECOND
interpretiert. Dies entspricht auch
der Art und Weise, wie MySQL TIME
-Werte als
verstrichene Zeit (statt als Uhrzeit) auffasst.
Wenn Sie etwas zu einem Datum hinzuaddieren oder davon
abziehen, das einen Uhrzeitteil enthält, dann wird das
Ergebnis automatisch in einen DATETIME
-Wert
umgewandelt:
mysql>SELECT DATE_ADD('1999-01-01', INTERVAL 1 DAY);
-> '1999-01-02' mysql>SELECT DATE_ADD('1999-01-01', INTERVAL 1 HOUR);
-> '1999-01-01 01:00:00'
Wenn Sie MONTH
,
YEAR_MONTH
oder YEAR
hinzuaddieren und das Ergebnis einen Tageswert hat, der
größer ist als der letzte Tag des neuen Monats, dann wird
der Tag im neuen Monat auf den letzten Tag gesetzt:
mysql> SELECT DATE_ADD('1998-01-30', INTERVAL 1 MONTH);
-> '1998-02-28'
Datumsberechnungen erfordern vollständige Datumsangaben;
unvollständige Angaben wie '2005-07-00'
oder erheblich fehlerhaft formatierte Werte wie die folgenden
funktionieren nicht:
mysql>SELECT DATE_ADD('2006-07-00', INTERVAL 1 DAY);
-> NULL mysql>SELECT '2005-03-32' + INTERVAL 1 MONTH;
-> NULL
Formatiert den Wert date
entsprechend dem String format
.
Die folgenden Konfigurationsangaben können im String
format
verwendet werden. Das
Zeichen ‘%
’ ist vor jede
Formatangabe zu setzen.
Konfigurationsangabe | Beschreibung |
%a | Abgekürzter Name des Wochentags (Sun ...
Sat ) |
%b | Abgekürzter Name des Monats (Jan ...
Dec ) |
%c | Monat, numerisch (0 ... 12 ) |
%D | Tag im Monat mit englischem Suffix (0th ,
1st , 2nd ,
3rd , …) |
%d | Tag im Monat, numerisch (00 ...
31 ) |
%e | Tag im Monat, numerisch (0 ... 31 ) |
%f | Mikrosekunden (000000 ... 999999 ) |
%H | Stunde (00 ... 23 ) |
%h | Stunde (01 ... 12 ) |
%I | Stunde (01 ... 12 ) |
%i | Minuten, numerisch (00 ... 59 ) |
%j | Tag im Jahr (001 ... 366 ) |
%k | Stunde (0 ... 23 ) |
%l | Stunde (1 ... 12 ) |
%M | Monatsname (January ... December ) |
%m | Monat, numerisch (00 ... 12 ) |
%p | AM oder PM |
%r | Uhrzeit im 12-Stunden-Format (hh:mm:ss gefolgt von
AM oder PM ) |
%S | Sekunden (00 ... 59 ) |
%s | Sekunden (00 ... 59 ) |
%T | Uhrzeit im 24-Stunden-Format (hh:mm:ss ) |
%U | Woche (00 ... 53 ), wobei Sonntag
der erste Tag der Woche ist |
%u | Woche (00 ... 53 ), wobei Montag
der erste Tag der Woche ist |
%V | Woche (01 ... 53 ), wobei Sonntag
der erste Tag der Woche ist; wird mit
%X verwendet |
%v | Woche (01 ... 53 ), wobei Montag
der erste Tag der Woche ist; wird mit
%x verwendet |
%W | Name des Wochentags (Sunday ...
Saturday ) |
%w | Tag in der Woche (0 =Sonntag ...
6 =Sonnabend) |
%X | Jahr der Woche, wobei Sonntag der erste Tag der Woche ist, numerisch,
vierstellig; wird mit %V verwendet |
%x | Jahr der Woche, wobei Montag der erste Tag der Woche ist, numerisch,
vierstellig; wird mit %v verwendet |
%Y | Jahr, numerisch, vierstellig |
%y | Jahr, numerisch, zweistellig |
%% | Literales ‘% ’-Zeichen |
% | x , steht für jedes nicht oben aufgeführte
‘x ’ |
Da MySQL die Speicherung unvollständiger Daten wie
'2004-00-00'
gestattet, beginnen die
Bereiche für die monats- und tagesbezogenen
Konfigurationsangaben bei null.
mysql>SELECT DATE_FORMAT('1997-10-04 22:23:00', '%W %M %Y');
-> 'Saturday October 1997' mysql>SELECT DATE_FORMAT('1997-10-04 22:23:00', '%H:%i:%s');
-> '22:23:00' mysql>SELECT DATE_FORMAT('1997-10-04 22:23:00',
'%D %y %a %d %m %b %j'); -> '4th 97 Sat 04 10 Oct 277' mysql>SELECT DATE_FORMAT('1997-10-04 22:23:00',
'%H %k %I %r %T %S %w'); -> '22 22 10 10:23:00 PM 22:23:00 00 6' mysql>SELECT DATE_FORMAT('1999-01-01', '%X %V');
-> '1998 52' mysql>SELECT DATE_FORMAT('2006-06-00', '%d');
-> '00'
DAY()
ist ein Synonym für
DAYOFMONTH()
.
Gibt den Namen des Wochentags für
date
zurück.
mysql> SELECT DAYNAME('1998-02-05');
-> 'Thursday'
Gibt den Tag im Monat für date
zurück. Der Bereich liegt zwischen 0
und
31
.
mysql> SELECT DAYOFMONTH('1998-02-03');
-> 3
Gibt den Wochentagindex für date
zurück (1
= Sonntag, 2
= Montag, …, 7
= Sonnabend). Diese
Indexwerte entsprechen dem ODBC-Standard.
mysql> SELECT DAYOFWEEK('1998-02-03');
-> 3
Gibt den Tag im Jahr für date
zurück. Der Bereich liegt zwischen 1
und
366
.
mysql> SELECT DAYOFYEAR('1998-02-03');
-> 34
Die Funktion EXTRACT()
verwendet dieselben
Angaben für den Intervalltyp wie
DATE_ADD()
oder
DATE_SUB()
, extrahiert aber Teile des
Datums, statt daran Berechnungen durchzuführen.
mysql>SELECT EXTRACT(YEAR FROM '1999-07-02');
-> 1999 mysql>SELECT EXTRACT(YEAR_MONTH FROM '1999-07-02 01:02:03');
-> 199907 mysql>SELECT EXTRACT(DAY_MINUTE FROM '1999-07-02 01:02:03');
-> 20102 mysql>SELECT EXTRACT(MICROSECOND
->FROM '2003-01-02 10:30:00.00123');
-> 123
Gibt für eine Tagesanzahl N
den
DATE
-Wert zurück.
mysql> SELECT FROM_DAYS(729669);
-> '1997-10-07'
Verwenden Sie FROM_DAYS()
bei alten
Datumsangaben mit Vorsicht. Die Funktion ist nicht zur
Verwendung mit Daten gedacht, die vor der Einführung des
gregorianischen Kalenders (1582) liegen. Siehe auch
Abschnitt 12.6, „Welchen Kalender benutzt MySQL?“.
FROM_UNIXTIME(
,
unix_timestamp
)FROM_UNIXTIME(
unix_timestamp
,format
)
Gibt eine Darstellung des
unix_timestamp
-Arguments als Wert
in den Formaten 'YYYY-MM-DD HH:MM:SS'
oder
YYYYMMDDHHMMSS
zurück. Das Ausgabeformat
hängt davon ab, ob die Funktion in einem String- oder einem
numerischen Kontext verwendet wird.
unix_timestamp
ist ein interner
Zeitstempelwert, der von der Funktion
UNIX_TIMESTAMP()
erzeugt wird.
Wenn format
angegeben ist, wird das
Ergebnis entsprechend dem String
format
formatiert, der so verwendet
wird wie im Abschnitt zur Funktion
DATE_FORMAT()
beschrieben.
mysql>SELECT FROM_UNIXTIME(875996580);
-> '1997-10-04 22:23:00' mysql>SELECT FROM_UNIXTIME(875996580) + 0;
-> 19971004222300 mysql>SELECT FROM_UNIXTIME(UNIX_TIMESTAMP(),
->'%Y %D %M %h:%i:%s %x');
-> '2003 6th August 06:22:58 2003'
Hinweis: Wenn Sie UNIX_TIMESTAMP()
und
FROM_UNIXTIME()
zur Konvertierung zwischen
TIMESTAMP
-Werten und Unix-Zeitstempelwerten
verwenden, ist die Konvertierung verlustbehaftet, weil die
Zuordnung nicht in beiden Richtungen 1 : 1 erfolgt. Weitere
Informationen entnehmen Sie der Beschreibung der Funktion
UNIX_TIMESTAMP()
.
GET_FORMAT(DATE|TIME|DATETIME,
'EUR'|'USA'|'JIS'|'ISO'|'INTERNAL')
Gibt einen Format-String zurück. Diese Funktion ist praktisch
in Verbindung mit den Funktionen
DATE_FORMAT()
und
STR_TO_DATE()
.
Die zulässigen Werte für das erste und zweite Argument
ergeben verschiedene Möglichkeiten für Format-Strings. (Die
Konfigurationsangaben entnehmen Sie der Tabelle in der
Beschreibung zu DATE_FORMAT()
.) Das
ISO-Format verweist auf ISO 9075, nicht auf ISO 8601.
Funktionsaufruf | Ergebnis |
GET_FORMAT(DATE,'USA') | '%m.%d.%Y' |
GET_FORMAT(DATE,'JIS') | '%Y-%m-%d' |
GET_FORMAT(DATE,'ISO') | '%Y-%m-%d' |
GET_FORMAT(DATE,'EUR') | '%d.%m.%Y' |
GET_FORMAT(DATE,'INTERNAL') | '%Y%m%d' |
GET_FORMAT(DATETIME,'USA') | '%Y-%m-%d-%H.%i.%s' |
GET_FORMAT(DATETIME,'JIS') | '%Y-%m-%d %H:%i:%s' |
GET_FORMAT(DATETIME,'ISO') | '%Y-%m-%d %H:%i:%s' |
GET_FORMAT(DATETIME,'EUR') | '%Y-%m-%d-%H.%i.%s' |
GET_FORMAT(DATETIME,'INTERNAL') | '%Y%m%d%H%i%s' |
GET_FORMAT(TIME,'USA') | '%h:%i:%s %p' |
GET_FORMAT(TIME,'JIS') | '%H:%i:%s' |
GET_FORMAT(TIME,'ISO') | '%H:%i:%s' |
GET_FORMAT(TIME,'EUR') | '%H.%i.%S' |
GET_FORMAT(TIME,'INTERNAL') | '%H%i%s' |
TIMESTAMP
kann auch als erstes Argument
für GET_FORMAT()
verwendet werden. In
diesem Fall gibt die Funktion dieselben Werte wie bei
DATETIME
zurück.
mysql>SELECT DATE_FORMAT('2003-10-03',GET_FORMAT(DATE,'EUR'));
-> '03.10.2003' mysql>SELECT STR_TO_DATE('10.31.2003',GET_FORMAT(DATE,'USA'));
-> '2003-10-31'
Gibt die Stundenangabe in time
zurück. Der Bereich des Rückgabewerts liegt zwischen
0
und 23
bei
Tageszeitwerten. Allerdings ist der zulässige Bereich für
TIME
wesentlich größer, d. h.,
HOUR
kann Werte zurückgeben, die größer
als 23
sind.
mysql>SELECT HOUR('10:05:03');
-> 10 mysql>SELECT HOUR('272:59:59');
-> 272
Nimmt einen DATE
- oder
DATETIME
-Wert entgegen und gibt den
entsprechenden Wert des letzten Tages des betreffenden Monats
zurück. Gibt NULL
zurück, wenn das
Argument unzulässig ist.
mysql>SELECT LAST_DAY('2003-02-05');
-> '2003-02-28' mysql>SELECT LAST_DAY('2004-02-05');
-> '2004-02-29' mysql>SELECT LAST_DAY('2004-01-01 01:01:01');
-> '2004-01-31' mysql>SELECT LAST_DAY('2003-03-32');
-> NULL
LOCALTIME
und
LOCALTIME()
sind Synonyme von
NOW()
.
LOCALTIMESTAMP
,
LOCALTIMESTAMP()
LOCALTIMESTAMP
und
LOCALTIMESTAMP()
sind Synonyme von
NOW()
.
Gibt ein Datum zurück, welches auf den übergebenen Werten
für das Jahr und den Tag im Jahr basiert.
dayofyear
muss größer als 0 sein,
andernfalls ist das Ergebnis NULL
.
mysql>SELECT MAKEDATE(2001,31), MAKEDATE(2001,32);
-> '2001-01-31', '2001-02-01' mysql>SELECT MAKEDATE(2001,365), MAKEDATE(2004,365);
-> '2001-12-31', '2004-12-30' mysql>SELECT MAKEDATE(2001,0);
-> NULL
Gibt einen Zeitwert zurück, der aus den Argumenten
hour
,
minute
und
second
berechnet wird.
mysql> SELECT MAKETIME(12,15,30);
-> '12:15:30'
Gibt die Anzahl der Mikrosekunden für den übergebenen
TIME
- oder
DATETIME
-Ausdruck
expr
als Zahl im Bereich zwischen
0
und 999999
zurück.
mysql>SELECT MICROSECOND('12:00:00.123456');
-> 123456 mysql>SELECT MICROSECOND('1997-12-31 23:59:59.000010');
-> 10
Gibt die Minute für time
im
Bereich zwischen 0
und
59
zurück.
mysql> SELECT MINUTE('98-02-03 10:05:03');
-> 5
Gibt den Monat für date
im Bereich
zwischen 0
und 12
zurück.
mysql> SELECT MONTH('1998-02-03');
-> 2
Gibt den vollständigen Namen des Monats für
date
zurück.
mysql> SELECT MONTHNAME('1998-02-05');
-> 'February'
Gibt die aktuellen Werte für Datum und Uhrzeit als Wert in
den Formaten YYYYMMDDHHMMSS
oder
'YYYY-MM-DD HH:MM:SS'
aus. Das
Ausgabeformat hängt davon ab, ob die Funktion in einem
String- oder einem numerischen Kontext verwendet wird.
mysql>SELECT NOW();
-> '1997-12-15 23:50:26' mysql>SELECT NOW() + 0;
-> 19971215235026
Aus einer gespeicherten Routine oder einem Trigger heraus gibt
NOW()
einen Zeitpunkt als Konstante
zurück, zu dem die Ausführung der Routine bzw. des Triggers
begann. Hier liegt ein Unterschied zum Verhalten von
SYSDATE()
vor, welches die exakte Zeit
seiner Ausführung zurückgibt.
Fügt N
Monate zum Zeitraum
P
(im Format
YYMM
oder YYYYMM
) hinzu.
Gibt einen Wert im Format YYYYMM
zurück.
Beachten Sie, dass das Zeitraumargument
P
kein
Datumswert ist.
mysql> SELECT PERIOD_ADD(9801,2);
-> 199803
Gibt die Anzahl der Monate zwischen den Zeiträumen
P1
und
P2
zurück.
P1
und
P2
sollten im Format
YYMM
oder YYYYMM
übergeben werden. Beachten Sie, dass die Zeitraumargumente
P1
und
P2
keine
Datumswerte sind.
mysql> SELECT PERIOD_DIFF(9802,199703);
-> 11
Gibt das Quartal im Jahr für date
zurück. Der Bereich liegt zwischen 1
und
4
.
mysql> SELECT QUARTER('98-04-01');
-> 2
Gibt die Sekunde für time
im
Bereich zwischen 0
und
59
zurück.
mysql> SELECT SECOND('10:05:03');
-> 3
Gibt das Argument seconds
,
konvertiert in Stunden, Minuten und Sekunden, als Wert in den
Formaten 'HH:MM:SS'
oder
HHMMSS
aus. Das Ausgabeformat hängt davon
ab, ob die Funktion in einem String- oder einem numerischen
Kontext verwendet wird.
mysql>SELECT SEC_TO_TIME(2378);
-> '00:39:38' mysql>SELECT SEC_TO_TIME(2378) + 0;
-> 3938
Dies ist die Umkehrung der Funktion
DATE_FORMAT()
. Sie nimmt einen String
str
und einen Format-String
format
entgegen.
STR_TO_DATE()
gibt einen
DATETIME
-Wert zurück, wenn der
Format-String sowohl Datums- als auch Uhrzeitteile enthält,
oder einen DATE
-
TIME
-Wert, wenn der String nur Datums- bzw.
Uhrzeitteile umfasst.
Die DATE
-, TIME
- oder
DATETIME
-Werte, die in
str
enthalten sind, sollten in dem
Format angegeben werden, das durch
format
spezifiziert wurde.
Informationen zu den in format
verwendbaren Konfigurationsangaben finden Sie in der
Beschreibung zur Funktion DATE_FORMAT()
.
Wenn str
einen unzulässigen
DATE
-, TIME
- oder
DATETIME
-Wert enthält, gibt
STR_TO_DATE()
NULL
zurück. Außerdem erzeugt ein unzulässiger Wert eine
Warnung.
Die Bereichsprüfung der Teile von Datumswerten erfolgt wie in
Abschnitt 11.3.1, „Die DATETIME
-, DATE
- und
TIMESTAMP
-Typen“, beschrieben. Das bedeutet, dass
„Nulldaten“ oder solche, bei denen Bestandteile 0
sind, zulässig sind, sofern dem nicht der aktive SQL-Modus
widerspricht.
mysql>SELECT STR_TO_DATE('00/00/0000', '%m/%d/%Y');
-> '0000-00-00' mysql>SELECT STR_TO_DATE('04/31/2004', '%m/%d/%Y');
-> '2004-04-31'
SUBDATE(
,
date
,INTERVAL
expr
type
)SUBDATE(
expr
,days
)
Wenn mit der Form INTERVAL
für das zweite
Argument aufgerufen wird, ist SUBDATE()
ein
Synonym von DATE_SUB()
. Weitere
Informationen zum Argument INTERVAL
finden
Sie in der Beschreibung zu DATE_ADD()
.
mysql>SELECT DATE_SUB('1998-01-02', INTERVAL 31 DAY);
-> '1997-12-02' mysql>SELECT SUBDATE('1998-01-02', INTERVAL 31 DAY);
-> '1997-12-02'
Die zweite Form gestattet die Verwendung eines Integer-Werts
für days
. In solchen Fällen wird
der Wert als Anzahl von Tagen interpretiert, die vom
DATE
- oder
DATETIME
-Ausdruck
expr
abgezogen werden.
mysql> SELECT SUBDATE('1998-01-02 12:00:00', 31);
-> '1997-12-02 12:00:00'
Hinweis: Sie können mit dem
Format "%X%V"
keine Konvertierung eines aus
einer Jahres- und einer Wochenangabe bestehenden Strings in
ein Datum durchführen, weil diese Kombination nicht eindeutig
ein Jahr und einen Monat bezeichnet, wenn eine Woche eine
Monatsgrenze überschreitet. Insofern müssen Sie, wenn Sie
eine Jahr-/Wochen-Kombination in ein Datum umwandeln wollen,
auch den Wochentag angeben:
mysql> SELECT STR_TO_DATE('200442 Monday', '%X%V %W');
-> '2004-10-18'
SUBTIME()
zieht
expr2
von
expr
ab und gibt das Ergebnis
zurück. expr
ist eine
Uhrzeitangabe oder ein DATETIME
-Wert,
expr2
eine Uhrzeitangabe.
mysql>SELECT SUBTIME('1997-12-31 23:59:59.999999','1 1:1:1.000002');
-> '1997-12-30 22:58:58.999997' mysql>SELECT SUBTIME('01:00:00.999999', '02:00:00.999998');
-> '-00:59:59.999999'
Gibt die aktuellen Werte für Datum und Uhrzeit als Wert in
den Formaten YYYYMMDDHHMMSS
oder
'YYYY-MM-DD HH:MM:SS'
aus. Das
Ausgabeformat hängt davon ab, ob die Funktion in einem
String- oder einem numerischen Kontext verwendet wird.
Aus einer gespeicherten Routine oder einem Trigger heraus gibt
SYSDATE()
die Zeit zurück, zu der sie
ausgeführt wird. Dies unterscheidet sich vom Verhalten von
NOW()
, welches die Uhrzeit zurückgibt, zu
der die Ausführung der Routine- oder Trigger-Anweisung
begann.
Extrahiert den Zeitbestandteil des TIME
-
oder DATETIME
-Ausdrucks
expr
und gibt diesen als String
zurück.
mysql>SELECT TIME('2003-12-31 01:02:03');
-> '01:02:03' mysql>SELECT TIME('2003-12-31 01:02:03.000123');
-> '01:02:03.000123'
TIMEDIFF()
gibt den Zeitraum zwischen der
Startzeit expr
und der Endzeit
expr2
zurück.
expr
und
expr2
sind Zeit- oder
DATETIME
-Ausdrücke, müssen aber vom
selben Typ sein.
mysql>SELECT TIMEDIFF('2000:01:01 00:00:00',
->'2000:01:01 00:00:00.000001');
-> '-00:00:00.000001' mysql>SELECT TIMEDIFF('1997-12-31 23:59:59.000001',
->'1997-12-30 01:01:01.000002');
-> '46:58:57.999999'
TIMESTAMP(
,
expr
)TIMESTAMP(
expr
,expr2
)
Bei nur einem Argument gibt diese Funktion den Datums- oder
DATETIME
-Ausdruck
expr
als
DATETIME
-Wert zurück. Bei zwei Argumenten
wird der Zeitausdruck expr2
zum
Datums- oder DATETIME
-Ausdruck
expr
hinzugefügt und das Ergebnis
als DATETIME
-Wert zurückgegeben.
mysql>SELECT TIMESTAMP('2003-12-31');
-> '2003-12-31 00:00:00' mysql>SELECT TIMESTAMP('2003-12-31 12:00:00','12:00:00');
-> '2004-01-01 00:00:00'
TIMESTAMPADD(
interval
,int_expr
,datetime_expr
)
Fügt den Integer-Ausdruck int_expr
zum Datums- oder DATETIME
-Ausdruck
datetime_expr
hinzu. Die Einheit
für int_expr
wird durch das
Argument interval
angegeben, das einen der
folgenden Werte haben sollte: FRAC_SECOND
,
SECOND
, MINUTE
,
HOUR
, DAY
,
WEEK
, MONTH
,
QUARTER
oder YEAR
.
Der interval
-Wert kann mithilfe
eines der angegebenen Schlüsselwörter oder mit dem Präfix
SQL_TSI_
angegeben werden. Beispielsweise
sind sowohl DAY
als auch
SQL_TSI_DAY
zulässig.
mysql>SELECT TIMESTAMPADD(MINUTE,1,'2003-01-02');
-> '2003-01-02 00:01:00' mysql>SELECT TIMESTAMPADD(WEEK,1,'2003-01-02');
-> '2003-01-09'
TIMESTAMPDIFF(
interval
,datetime_expr1
,datetime_expr2
)
Gibt den Unterschied zwischen den Datums- oder
DATETIME
-Ausdrücken
datetime_expr1
und
datetime_expr2
zurück. Die Einheit
für das Ergebnis wird über das Argument
interval
angegeben. Die zulässigen
Werte für interval
entsprechen den
in der Beschreibung zu TIMESTAMPADD()
aufgelisteten Optionen.
mysql>SELECT TIMESTAMPDIFF(MONTH,'2003-02-01','2003-05-01');
-> 3 mysql>SELECT TIMESTAMPDIFF(YEAR,'2002-05-01','2001-01-01');
-> -1
Wird wie die Funktion DATE_FORMAT()
verwendet, der String format
darf
aber nur Formatangaben für Stunden, Minuten und Sekunden
enthalten. Andere Konfigurationsangaben erzeugen einen
NULL
-Wert oder 0
.
Wenn der time
-Wert einen
Stundenbestandteil enthält, der größer als
23
ist, erzeugen die Stundenformatangaben
%H
und %k
einen Wert,
der größer ist als der normale Bereich 0 ...
23
. Die übrigen Konfigurationsangaben für das
Stundenformat erzeugen den Stundenwert mod 12.
mysql> SELECT TIME_FORMAT('100:00:00', '%H %k %h %I %l');
-> '100 100 04 04 4'
Gibt das Argument time
in Sekunden
konvertiert zurück.
mysql>SELECT TIME_TO_SEC('22:23:00');
-> 80580 mysql>SELECT TIME_TO_SEC('00:39:38');
-> 2378
Gibt zu einem Datum date
eine
Anzahl von Tagen zurück. Diese gibt die Anzahl der seit dem
Jahr 0 bis zu diesem Datum verstrichenen Tage zurück.
mysql>SELECT TO_DAYS(950501);
-> 728779 mysql>SELECT TO_DAYS('1997-10-07');
-> 729669
TO_DAYS()
ist nicht für die Verwendung mit
Werten geeignet, die vor der Einführung des gregorianischen
Kalenders (1582) liegen, da die bei der Kalenderumstellung
„verlorenen“ Tage von der Funktion nicht
berücksichtigt werden. Bei Daten vor 1582 (und
standortabhängig möglicherweise auch danach) sind die
Ergebnisse dieser Funktion nicht zuverlässig. Weitere
Informationen finden Sie in Abschnitt 12.6, „Welchen Kalender benutzt MySQL?“.
Denken Sie daran, dass MySQL zweistellige Jahresangaben unter
Verwendung der in Abschnitt 11.3, „Datums- und Zeittypen“,
beschriebenen Regeln in das vierstellige Format umwandelt.
Beispielsweise werden '1997-10-07'
und
'97-10-07'
als identische Daten betrachtet.
mysql> SELECT TO_DAYS('1997-10-07'), TO_DAYS('97-10-07');
-> 729669, 729669
UNIX_TIMESTAMP()
,
UNIX_TIMESTAMP(
date
)
Sofern ohne Argument aufgerufen, gibt die Funktion einen
Unix-Zeitstempel (Sekunden seit '1970-01-01
00:00:00'
im UTC-Format) als vorzeichenlosen Integer
zurück. Wenn UNIX_TIMESTAMP()
mit einem
Argument date
aufgerufen wird, gibt
es den Wert des Arguments als seit dem Zeitpunkt
'1970-01-01 00:00:00'
(UTC) verstrichene
Sekunden zurück. date
kann ein
DATE
-String, ein
DATETIME
-String, ein
TIMESTAMP
oder eine Zahl im Format
YYMMDD
oder YYYYMMDD
sein. Der Server interpretiert date
als Wert in der aktuellen Zeitzone und wandelt es in einen
internen Wert in UTC um. Clients können ihre Zeitzone wie in
Abschnitt 5.11.8, „Zeitzonen-Unterstützung des MySQL-Servers“, beschrieben einstellen.
mysql>SELECT UNIX_TIMESTAMP();
-> 882226357 mysql>SELECT UNIX_TIMESTAMP('1997-10-04 22:23:00');
-> 875996580
Wenn UNIX_TIMESTAMP
für eine
TIMESTAMP
-Spalte verwendet wird, gibt die
Funktion den internen Zeitstempelwert direkt zurück, d. h.
ohne implizite Konvertierung des Strings in einen
Unix-Zeitstempel. Wenn Sie einen Wert außerhalb des
zulässigen Bereichs an UNIX_TIMESTAMP()
übergeben, wird 0
zurückgegeben.
Hinweis: Wenn Sie UNIX_TIMESTAMP()
und
FROM_UNIXTIME()
zur Konvertierung zwischen
TIMESTAMP
-Werten und Unix-Zeitstempelwerten
verwenden, ist die Konvertierung verlustbehaftet, weil die
Zuordnung nicht in beiden Richtungen 1 : 1 erfolgt.
Beispielsweise kann es aufgrund der Konventionen zur Änderung
der lokalen Zeitzone möglich sein, dass zwei
UNIX_TIMESTAMP()
-Funktionen zwei
TIMESTAMP
-Werte in denselben
Unix-Zeitstempelwert umwandeln.
FROM_UNIXTIME()
wiederum konvertiert den
Wert dann in nur einen der ursprünglichen
TIMESTAMP
-Werte zurück. Es folgt ein
Beispiel unter Verwendung von
TIMESTAMP
-Werten in der Zeitzone
CET
(mitteleuropäische Zeit):
mysql>SELECT UNIX_TIMESTAMP('2005-03-27 03:00:00');
+---------------------------------------+ | UNIX_TIMESTAMP('2005-03-27 03:00:00') | +---------------------------------------+ | 1111885200 | +---------------------------------------+ mysql>SELECT UNIX_TIMESTAMP('2005-03-27 02:00:00');
+---------------------------------------+ | UNIX_TIMESTAMP('2005-03-27 02:00:00') | +---------------------------------------+ | 1111885200 | +---------------------------------------+ mysql>SELECT FROM_UNIXTIME(1111885200);
+---------------------------+ | FROM_UNIXTIME(1111885200) | +---------------------------+ | 2005-03-27 03:00:00 | +---------------------------+
Wenn Sie UNIX_TIMESTAMP()
-Spalten
subtrahieren wollen, sollten Sie das Ergebnis in
vorzeichenbehaftete Integers umwandeln. Siehe auch
Abschnitt 12.8, „Cast-Funktionen und Operatoren“.
Gibt das aktuelle UTC-Datum als Wert in den Formaten
'YYYY-MM-DD'
oder
YYYYMMDD
aus. Das Ausgabeformat hängt
davon ab, ob die Funktion in einem String- oder einem
numerischen Kontext verwendet wird.
mysql> SELECT UTC_DATE(), UTC_DATE() + 0;
-> '2003-08-14', 20030814
Gibt die aktuelle UTC-Uhrzeit als Wert in den Formaten
'HH:MM:SS'
oder HHMMSS
aus. Das Ausgabeformat hängt davon ab, ob die Funktion in
einem String- oder einem numerischen Kontext verwendet wird.
mysql> SELECT UTC_TIME(), UTC_TIME() + 0;
-> '18:07:53', 180753
UTC_TIMESTAMP
,
UTC_TIMESTAMP()
Gibt die aktuellen UTC-Werte für Datum und Uhrzeit als Wert
in den Formaten YYYYMMDDHHMMSS
oder
'YYYY-MM-DD HH:MM:SS'
aus. Das
Ausgabeformat hängt davon ab, ob die Funktion in einem
String- oder einem numerischen Kontext verwendet wird.
mysql> SELECT UTC_TIMESTAMP(), UTC_TIMESTAMP() + 0;
-> '2003-08-14 18:08:04', 20030814180804
Diese Funktion gibt die Nummer der Woche für
date
zurück. Wird
WEEK()
mit zwei Argumenten verwendet, dann
gestattet Ihnen die Funktion die Angabe, ob die Woche am
Sonntag oder Montag beginnt und ob der Rückgabewert im
Bereich zwischen 0
und
53
oder 1
und
53
liegen soll. Wird das Argument
mode
weggelassen, so wird der Wert
der Systemvariablen default_week_format
verwendet. Siehe auch
Abschnitt 5.2.2, „Server-Systemvariablen“.
Die folgende Tabelle beschreibt, wie das Argument
mode
funktioniert.
Erster | |||
Modus | Wochentag | Bereich | Woche 1 ist die erste Woche … |
0 | Sonntag | 0–53 | mit einem Sonntag in diesem Jahr |
1 | Montag | 0–53 | mit mehr als drei Tagen innerhalb dieses Jahres |
2 | Sonntag | 1–53 | mit einem Sonntag in diesem Jahr |
3 | Montag | 1–53 | mit mehr als drei Tagen innerhalb dieses Jahres |
4 | Sonntag | 0–53 | mit mehr als drei Tagen innerhalb dieses Jahres |
5 | Montag | 0–53 | mit einem Montag in diesem Jahr |
6 | Sonntag | 1–53 | mit mehr als drei Tagen innerhalb dieses Jahres |
7 | Montag | 1–53 | mit einem Montag in diesem Jahr |
mysql>SELECT WEEK('1998-02-20');
-> 7 mysql>SELECT WEEK('1998-02-20',0);
-> 7 mysql>SELECT WEEK('1998-02-20',1);
-> 8 mysql>SELECT WEEK('1998-12-31',1);
-> 53
Beachten Sie, dass, wenn ein Datum in die letzte Woche des
vorherigen Jahres fällt, MySQL 0
zurückgibt, sofern Sie nicht 2
,
3
, 6
oder
7
als optionales
mode
-Argument angeben:
mysql> SELECT YEAR('2000-01-01'), WEEK('2000-01-01',0);
-> 2000, 0
Man könnte nun anführen, dass MySQL doch eigentlich
52
für die Funktion
WEEK()
zurückgeben sollte, da das
angegebene Datum eigentlich in der 52. Woche des Jahres 1999
liegt. Wir haben aber beschlossen, stattdessen
0
zurückgeben zu lassen, weil die Funktion
„Nummer der Woche im angegebenen Jahr“
zurückgeben soll. Dies macht die Verwendung der Funktion
WEEK()
zuverlässig, wenn sie mit anderen
Funktionen kombiniert wird, die einen Tagesbestandteil aus dem
Datum extrahieren.
Wenn Sie eine Auswertung des Ergebnisses in Bezug auf das Jahr
vorziehen, das den ersten Tag der Woche des angegebenen Datums
enthält, dann verwenden Sie 0
,
2
, 5
oder
7
als optionales
mode
-Argument.
mysql> SELECT WEEK('2000-01-01',2);
-> 52
Alternativ verwenden Sie die Funktion
YEARWEEK()
:
mysql>SELECT YEARWEEK('2000-01-01');
-> 199952 mysql>SELECT MID(YEARWEEK('2000-01-01'),5,2);
-> '52'
Gibt den Wochentagindex für date
zurück (0
= Montag, 1
=
Dienstag, …, 6
= Sonntag).
mysql>SELECT WEEKDAY('1998-02-03 22:23:00');
-> 1 mysql>SELECT WEEKDAY('1997-11-05');
-> 2
Gibt die Kalenderwoche des Datums als Zahl im Bereich zwischen
1
und 53
zurück.
WEEKOFYEAR()
ist eine
Kompatibilitätsfunktion, die äquivalent zu
WEEK(
ist.
date
,3)
mysql> SELECT WEEKOFYEAR('1998-02-20');
-> 8
Gibt das Jahr für date
im Bereich
zwischen 1000
und 9999
oder aber 0
für das
„Nulldatum“ zurück.
mysql> SELECT YEAR('98-02-03');
-> 1998
YEARWEEK(
,
date
)YEARWEEK(
date
,start
)
Gibt Jahr und Woche für ein Datum zurück. Das Argument
start
funktioniert ganz genauso wie
das Argument start
für
WEEK()
. Das Jahr im Ergebnis kann sich im
Falle der ersten und der letzten Woche des Jahres vom Jahr im
Datumsargument unterscheiden.
mysql> SELECT YEARWEEK('1987-01-01');
-> 198653
Beachten Sie, dass die Wochennummer sich von dem, was die
Funktion WEEK()
für ihre optionalen
Argumente 0
oder 1
zurückgäbe (nämlich 0
), unterscheidet,
denn WEEK()
gibt die Woche im Kontext des
angegebenen Jahres zurück.
MySQL verwendet den so genannten proleptischen gregorianischen Kalender.
Jedes Land, das die Zeitrechnung vom julianischen auf den gregorianischen Kalender umgestellt hat, hat bei dieser Umstellung mindestens zehn Tage verloren. Um zu verstehen, wie dies funktioniert, betrachten Sie den Oktober 1582, als die erste Umstellung vom julianischen auf den gregorianischen Kalender erfolgte:
Montag | Dienstag | Mittwoch | Donnerstag | Freitag | Sonnabend | Sonntag |
1 | 2 | 3 | 4 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
Zwischen dem 4. und dem 15. Oktober liegen keine Daten. Diese Unstetigkeit nennt man Ausschaltung. Alle Daten vor der Ausschaltung waren julianisch, alle nachfolgenden gregorianisch. Die Daten während der Ausschaltung existieren schlichtweg nicht.
Ein Kalender, der für Daten angewendet wird, zu deren Zeit er
(noch) nicht verwendet wurde, heißt
proleptisch. Auf diese Weise haben wir,
wenn wir voraussetzen, dass niemals eine Ausschaltung
stattgefunden hat und die Regeln des gregorianischen Kalenders
immer gegolten haben, einen proleptischen gregorianischen
Kalender. Diesen verwenden wir entsprechend der Vorgabe von SQL
auch bei MySQL. Aus diesem Grund müssen vor der Ausschaltung
liegende Daten, die als DATE
- oder
DATETIME
-Werte in MySQL gespeichert werden,
angepasst werden, um den Unterschied auszugleichen. Wichtig ist in
diesem Zusammenhang die Tatsache, dass die Ausschaltung nicht in
allen Ländern gleichzeitig erfolgte und dass umso mehr Tage
verloren gingen, je später sie erfolgte. In Großbritannien
beispielsweise fand sie 1752 statt, als auf Mittwoch, den 2.
September, Donnerstag, der 14. September, folgte. Russland behielt
den julianischen Kalender bis 1918 bei und verlor bei der
Umstellung 13 Tage – was auch bedeutet, dass die berühmte
Oktoberrevolution eigentlich im November stattfand.
MATCH
(
col1
,col2
,...)
AGAINST (expr
[IN BOOLEAN MODE |
WITH QUERY EXPANSION])
MySQL unterstützt die Volltextindizierung und -suche. Ein
Volltextindex ist in MySQL ein Index des Typs
FULLTEXT
.
FULLTEXT
-Indizes können nur bei
MyISAM
-Tabellen eingesetzt werden. Sie
lassen sich für CHAR
-,
VARCHAR
- und
TEXT
-Spalten mit CREATE
TABLE
erstellen oder mit ALTER
TABLE
oder CREATE INDEX
im
Nachhinein hinzufügen. Bei größeren Datenmengen erfolgt das
Laden Ihrer Daten in eine Tabelle ohne
FULLTEXT
-Index und das nachfolgende
Erstellen des Indexes wesentlich schneller als das Einladen in
eine Tabelle mit vorhandenem
FULLTEXT
-Index.
Hinweise zu Einschränkungen bei der Volltextsuche finden Sie in Abschnitt 12.7.4, „Beschränkungen der Volltextsuche“.
Die Volltextsuche wird mit der Funktion MATCH()
ausgeführt.
mysql>CREATE TABLE articles (
->id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
->title VARCHAR(200),
->body TEXT,
->FULLTEXT (title,body)
->);
Query OK, 0 rows affected (0.00 sec) mysql>INSERT INTO articles (title,body) VALUES
->('MySQL Tutorial','DBMS stands for DataBase ...'),
->('How To Use MySQL Well','After you went through a ...'),
->('Optimizing MySQL','In this tutorial we will show ...'),
->('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
->('MySQL vs. YourSQL','In the following database comparison ...'),
->('MySQL Security','When configured properly, MySQL ...');
Query OK, 6 rows affected (0.00 sec) Records: 6 Duplicates: 0 Warnings: 0 mysql>SELECT * FROM articles
->WHERE MATCH (title,body) AGAINST ('database');
+----+-------------------+------------------------------------------+ | id | title | body | +----+-------------------+------------------------------------------+ | 5 | MySQL vs. YourSQL | In the following database comparison ... | | 1 | MySQL Tutorial | DBMS stands for DataBase ... | +----+-------------------+------------------------------------------+ 2 rows in set (0.00 sec)
Die Funktion MATCH()
führt eine
natursprachliche Suche nach einem String in einer
Textsammlung durch. Eine Sammlung ist eine
Menge von einer oder mehreren Spalten, die Bestandteil eines
FULLTEXT
-Indexes sind. Der Such-String wird als
Argument an AGAINST()
übergeben. Für jeden
Datensatz in der Tabelle gibt MATCH()
einen
Relevanzwert zurück, d. h. eine Maßangabe für die Ähnlichkeit
zwischen dem Such-String und dem Text in den in
MATCH()
aufgelisteten Spalten dieses
Datensatzes.
Standardmäßig wird die Suche ohne Unterscheidung der
Groß-/Kleinschreibung durchgeführt. Sie können jedoch auch eine
Suche unter Berücksichtigung der Groß-/Kleinschreibung
durchführen, indem Sie eine binäre Sortierung für die
indizierten Spalten verwenden. So können Sie etwa einer Spalte,
die den Zeichensatz latin1
verwendet, die
Sortierung latin1_bin
zuweisen, damit bei der
Volltextsuche die Groß-/Kleinschreibung unterschieden wird.
Wenn MATCH()
in einer
WHERE
-Klausel verwendet wird (vgl. obiges
Beispiel), dann werden die zurückgegebenen Datensätze
automatisch nach absteigender Relevanz sortiert. Relevanzwerte
sind nichtnegative Fließkommazahlen. Nullrelevanz bezeichnet
keinerlei Ähnlichkeit. Die Relevanz wird auf der Basis der Anzahl
der Wörter im Datensatz, der Anzahl eindeutiger Wörter im
Datensatz, der Gesamtanzahl der Wörter in der Sammlung und der
Anzahl der Dokumente (Datensätze) berechnet, die ein bestimmtes
Wort enthalten.
Bei der natursprachlichen Volltextsuche ist es erforderlich, dass
die in der MATCH()
-Funktion genannten Spalten
dieselben Spalten sind, die in einem in Ihrer Tabelle vorhandenen
FULLTEXT
-Index enthalten sind. Beachten Sie bei
der obigen Abfrage, dass die in der
MATCH()
-Funktion aufgeführten Spalten
(title
und body
) dieselben
sind, die in der Definition des
FULLTEXT
-Indexes der Tabelle
article
genannt sind. Sollten Sie nun
title
oder body
separat
durchsuchen wollen, dann müssten Sie für jede Spalte separate
FULLTEXT
-Indizes erstellen.
Es ist auch möglich, eine boolesche Suche oder eine Suche mit Abfrageerweiterung durchzuführen. Diese Suchtypen sind in Abschnitt 12.7.1, „Boolesche Volltextsuche“, und Abschnitt 12.7.2, „Volltextsuche mit Abfragenerweiterung“, beschrieben.
Das obige Beispiel ist eine einfache Veranschaulichung, die zeigt,
wie man die Funktion MATCH()
verwendet, wobei
Datensätze nach absteigender Relevanz sortiert zurückgegeben
werden. Das nächste Beispiel zeigt, wie man die Relevanzwerte
explizit abruft. Zurückgegebene Datensätze werden nicht
sortiert, weil die SELECT
-Anweisung weder eine
WHERE
- noch eine ORDER
BY
-Klausel enthält:
mysql>SELECT id, MATCH (title,body) AGAINST ('Tutorial')
->FROM articles;
+----+-----------------------------------------+ | id | MATCH (title,body) AGAINST ('Tutorial') | +----+-----------------------------------------+ | 1 | 0.65545833110809 | | 2 | 0 | | 3 | 0.66266459226608 | | 4 | 0 | | 5 | 0 | | 6 | 0 | +----+-----------------------------------------+ 6 rows in set (0.00 sec)
Das folgende Beispiel ist komplexer. Die Abfrage gibt die
Relevanzwerte zurück und sortiert die Datensätze zudem nach
absteigender Relevanz. Um dieses Ergebnis zu erhalten, sollten Sie
MATCH()
zweimal angeben: einmal in der
SELECT
-Liste und ein weiteres Mal in der
WHERE
-Klausel. Hierdurch wird die
Systembelastung nicht erhöht, da der MySQL-Optimierer bemerkt,
dass die beiden MATCH()
-Aufrufe identisch sind,
und den Code für die Volltextsuche insofern nur einmal aufruft.
mysql>SELECT id, body, MATCH (title,body) AGAINST
->('Security implications of running MySQL as root') AS score
->FROM articles WHERE MATCH (title,body) AGAINST
->('Security implications of running MySQL as root');
+----+-------------------------------------+-----------------+ | id | body | score | +----+-------------------------------------+-----------------+ | 4 | 1. Never run mysqld as root. 2. ... | 1.5219271183014 | | 6 | When configured properly, MySQL ... | 1.3114095926285 | +----+-------------------------------------+-----------------+ 2 rows in set (0.00 sec)
Die FULLTEXT
-Implementierung von MySQL
betrachtet alle Folgen echter Wortzeichen (Buchstaben, Ziffern und
Unterstriche) als Wort. Die Folge kann auch Apostrophe
('
) enthalten, aber nur eines je Datensatz. Das
bedeutet, dass aaa'bbb
als ein Wort betrachtet
wird, aaa''bbb
hingegen als zwei Wörter.
Apostrophe am Anfang oder Ende eines Wortes werden vom
FULLTEXT
-Parser entfernt, d. h., er
verarbeitet 'aaa'bbb'
als
aaa'bbb
.
Der FULLTEXT
-Parser bestimmt anhand bestimmter
Trennzeichen wie ‘
’
(Leerzeichen), ‘,
’ (Komma), und
‘.
’ (Punkt), wo Wörter anfangen
und enden. Wenn Wörter nicht durch Trennzeichen getrennt werden
(wie es beispielsweise im Chinesischen der Fall ist), kann der
FULLTEXT
-Parser nicht ermitteln, wo ein Wort
beginnt oder endet. Damit Wörter oder andere indizierte Begriffe
in solchen Sprachen einem FULLTEXT
-Index
hinzugefügt werden können, müssen Sie eine Vorabverarbeitung
durchführen und sie so durch ein beliebiges Trennzeichen (z. B.
‘"
’) voneinander abtrennen.
In MySQL 5.1 ist es möglich, ein Plug-In zu
schreiben, das den integrierten Volltext-Parser ersetzt.
Detaillierte Informationen finden Sie in
Abschnitt 26.2, „Die MySQL-Plug-In-Schnittstelle“. Ein Beispiel für den Quellcode
eines solchen Parser-Plug-Ins finden Sie im Verzeichnis
plugin/fulltext
einer
MySQL-Quelldistribution.
Einige Wörter werden bei der Volltextsuche ignoriert:
Ignoriert werden alle Wörter, die zu kurz sind. Die standardmäßige Mindestlänge von Wörtern, die von der Volltextsuche gefunden werden, beträgt vier Zeichen.
Auch Wörter, die auf der Liste der Stoppwörter stehen, werden ignoriert. Ein Stoppwort ist ein Wort wie „the“ oder „some“, das so verbreitet ist, dass sein semantischer Wert als vernachlässigbar betrachtet wird. Es gibt eine bereits vorhandene Liste mit Stoppwörtern, die aber mit einer benutzerdefinierten Liste überschrieben werden kann.
Die Standardliste mit den Stoppwörtern finden Sie in Abschnitt 12.7.3, „Stoppwörter in der Volltextsuche“. Mindestwortlänge und Stoppwortliste lassen sich wie in Abschnitt 12.7.5, „MySQL-Volltextsuche feineinstellen“, beschrieben ändern.
Jedes korrekte Wort in der Sammlung und in der Abfrage wird entsprechend seiner Bedeutung in der Sammlung oder Abfrage gewichtet. Hieraus ergibt sich, dass ein Wort, dass in vielen Dokumenten vorhanden ist, ein niedrigeres Gewicht (oder sogar ein Nullgewicht) hat, weil sein semantischer Wert in dieser speziellen Sammlung geringer ist. Umgekehrt erhält ein Wort, das selten vorkommt, ein höheres Gewicht. Die Gewichtungen der Wörter werden zusammengefasst, und auf dieser Basis wird die Relevanz des Datensatzes berechnet.
Eine solche Methode funktioniert am besten mit großen Sammlungen
(und sie wurde auch speziell auf diesen Zweck hin sorgfältig
optimiert). Bei sehr kleinen Tabellen spiegelt die Wortverteilung
ihren jeweiligen semantischen Wert nicht adäquat wider. So ist
etwa das Wort „MySQL“ in jedem Datensatz der oben
gezeigten Tabelle articles
vorhanden, d. h.,
eine Suche nach diesem Wort führt zu keinem Ergebnis:
mysql>SELECT * FROM articles
->WHERE MATCH (title,body) AGAINST ('MySQL');
Empty set (0.00 sec)
Das Suchergebnis ist leer, weil das Wort „MySQL“ in mindestens 50 Prozent der Datensätze vorhanden ist. Insofern wird es letztendlich als Stoppwort behandelt. Bei großen Datenmengen ist dieses Verhalten wünschenswert: Eine natursprachliche Abfrage sollte keinesfalls jeden zweiten Datensatz aus einer 1 Gbyte großen Tabelle zurückgeben. Bei kleinen Datenmengen hingegen ist der Ansatz nicht sehr praktisch.
Ein Wort, das in der Hälfte der Datensätze in einer Tabelle auftritt, scheint wenig geeignet, relevante Dokumente zu finden. Tatsächlich werden in einem solchen Fall viele irrelevante Dokumente gefunden. Wie wir alle wissen, passiert dies viel zu häufig, etwa wenn wir versuchen, mit einer Suchmaschine etwas im Internet zu finden. Hieraus ist zu schließen, dass Datensätzen, die das Wort enthalten, ein niedriger semantischer Wert für die spezielle Datenmenge, in der sie auftreten, zugewiesen wird. Denn ein Wort kann die 50-Prozent-Marke in einer Datenmenge überschreiten, in einer anderen jedoch nicht.
Diese Marke hat eine große Bedeutung, wenn Sie die Volltextsuche zum ersten Mal ausprobieren, um zu sehen, wie sie funktioniert: Wenn Sie eine Tabelle erstellen und nur einen oder zwei Datensätze mit Text einfügen, tritt jedes Wort im Text in mindestens 50 Prozent aller Datensätze auf. Die Suche gibt also in keinem Fall Ergebnisse zurück. Sie sollten also mindestens drei (und am besten noch mehr) Datensätze einfügen. Benutzer, die die 50-Prozent-Grenze umgehen wollen, können den booleschen Suchmodus verwenden. Siehe auch Abschnitt 12.7.1, „Boolesche Volltextsuche“.
MySQL kann eine boolesche Volltextsuche unter Verwendung des
Modifizierers IN BOOLEAN MODE
durchführen:
mysql>SELECT * FROM articles WHERE MATCH (title,body)
->AGAINST ('+MySQL -YourSQL' IN BOOLEAN MODE);
+----+-----------------------+-------------------------------------+ | id | title | body | +----+-----------------------+-------------------------------------+ | 1 | MySQL Tutorial | DBMS stands for DataBase ... | | 2 | How To Use MySQL Well | After you went through a ... | | 3 | Optimizing MySQL | In this tutorial we will show ... | | 4 | 1001 MySQL Tricks | 1. Never run mysqld as root. 2. ... | | 6 | MySQL Security | When configured properly, MySQL ... | +----+-----------------------+-------------------------------------+
Die Operatoren +
und -
geben an, dass ein Wort vorhanden sein muss bzw. nicht sein
darf, damit eine Übereinstimmung vorliegt. Insofern ruft diese
Abfrage alle Datensätze ab, die das Wort „MySQL“,
aber nicht das Wort „YourSQL“
enthalten.
Die boolesche Volltextsuche hat die folgenden Merkmale:
Sie verwendet die 50-Prozent-Marke nicht.
Datensätze werden nicht automatisch nach absteigender Relevanz sortiert. Dies erkennen Sie am obigen Abfrageergebnis: Der Datensatz mit der höchsten Relevanz ist derjenige, der „MySQL“ zweimal enthält. Er wird aber nicht als Erster, sondern als Letzter aufgeführt.
Sie funktioniert auch ohne
FULLTEXT
-Index, auch wenn eine derart
ausgeführte Suche recht lange dauert.
Die Volltextparameter für minimale und maximale Wortlängen werden angewendet.
Die Stoppwortliste wird angewendet.
Die boolesche Volltextsuche unterstützt die folgenden Operatoren:
+
Ein führendes Pluszeichen gibt an, dass das betreffende Wort in jedem zurückgegebenen Datensatz vorhanden sein muss.
-
Ein führendes Minuszeichen gibt an, dass dieses Wort nicht in einem Datensatz vorhanden sein darf, der zurückgegeben wird.
Hinweis: Der Operator -
schließt nur
solche Datensätze aus, die andernfalls Bestandteil des
Ergebnisses wären. Aufgrund dessen gibt eine boolesche
Suche, die nur mit Minuszeichen gekennzeichnete Begriffe
enthält, ein leeres Ergebnis zurück, nicht jedoch
„alle Datensätze mit Ausnahme derer, die einen der
ausgeschlossenen Begriffe enthalten“.
(kein Operator)
Standardmäßig (also wenn weder +
noch
-
angegeben sind) ist das Wort optional,
aber Datensätze, die es enthalten, werden weiter oben
einsortiert. Dies ahmt das Verhalten von MATCH()
... AGAINST()
ohne den Modifizierer IN
BOOLEAN MODE
nach.
> <
Diese beiden Operatoren werden verwendet, um den Anteil
eines Worts am Relevanzwert zu ändern, der einem Datensatz
zugewiesen wird. Der Operator >
erhöht den Anteil, der Operator <
verringert ihn. Ein Beispiel finden Sie nach dieser Liste.
( )
Mit Klammern werden Wörter zu Unterausdrücken zusammengefasst. Gruppen in Klammern können verschachtelt werden.
~
Eine führende Tilde fungiert als Negationsoperator, d. h.,
der Anteil des Wortes an der Relevanz des Datensatzes wird
negativ gewertet. Dies ist nützlich, um
„Störungswörter“ zu kennzeichnen. Ein
Datensatz, der ein solches Wort enthält, erhält eine
geringere Relevanz als andere, wird aber – anders als bei
-
– nicht vollständig aus dem Ergebnis
ausgeschlossen.
*
Das Sternchen dient als Kürzungs- oder Jokeroperator.
Anders als andere Operatoren wird es an das betreffende Wort
angehängt. Eine Übereinstimmung liegt
bei Wörtern vor, die mit dem vor dem Operator
*
stehenden Wort beginnen.
"
Eine Phrase, die in doppelte Anführungszeichen
(‘"
’) gesetzt ist, entspricht
nur solchen Datensätzen, in denen diese Phrase
wortwörtlich (d. h. wie eingegeben)
vorkommt. Die Volltextsuche unterteilt die Phrase in Wörter
und führt dann eine Suche nach ihnen im
FULLTEXT
-Index durch. Bei Zeichen, die
nicht zum Wort gehören, muss keine exakte Übereinstimmung
vorliegen: Die Phrasensuche erfordert lediglich, dass bei
passenden Datensätzen dieselben Wörter in genau der in der
Phrase angegebenen Reihenfolge vorhanden sind. So entspricht
beispielsweise "test phrase"
"test, phrase"
.
Wenn die Phrase keine Wörter enthält, die im Index vorhanden sind, ist das Ergebnis leer. Wenn beispielsweise alle Wörter Stoppwörter oder kürzer sind als die Mindestlänge für indizierte Wörter, dann ist das Ergebnis leer.
Die folgenden Beispiele veranschaulichen einige Such-Strings, die boolesche Volltextoperatoren verwenden:
'apple banana'
Findet Datensätze, die mindestens eines der beiden Wörter enthalten.
'+apple +juice'
Findet Datensätze, die beide Wörter enthalten.
'+apple macintosh'
Findet Datensätze, die das Wort „apple“ enthalten, stuft aber solche Datensätze höher ein, die auch „macintosh“ enthalten.
'+apple -macintosh'
Findet Datensätze, die das Wort „apple“, aber nicht das Wort „macintosh“ enthalten.
'+apple ~macintosh'
Findet Datensätze, die das Wort „apple“
enthalten. Datensätze, die außerdem das Wort
„macintosh“ enthalten, werden niedriger
eingestuft als solche, die es nicht enthalten. Dies ist
„sanfter“ als eine Suche nach '+apple
-macintosh'
, bei der ein Datensatz bei
Vorhandensein von „macintosh“ überhaupt nicht
zurückgegeben wird.
'+apple +(>turnover <strudel)'
Findet Datensätze, die die Wörter „apple“ und „turnover“ oder „apple“ und „strudel“ (in beliebiger Reihenfolge) enthalten, aber stuft „apple turnover“ höher ein als „apple strudel“.
'apple*'
Findet Datensätze, die Wörter wie „apple“, „apples“, „applesauce“ oder „applet“ enthalten.
'"some words"'
Findet Datensätze, die die exakte Phrase „some
words“ enthalten. Dies wäre etwa „some words
of wisdom“, nicht aber „some noise
words“. Beachten Sie, dass die
‘"
’-Anführungszeichen, die
die Phrase umschließen, Operatorzeichen sind, die der
Trennung der Phrase dienen. Es handelt sich hierbei nicht um
Anführungszeichen, die den Such-String selbst umfassen.
Die Volltextsuche unterstützt die Abfrageerweiterung (und insbesondere die Variante „blinde Abfrageerweiterung“). Dies ist in der Regel nützlich, wenn eine Suchphrase zu kurz ist, was oft bedeutet, dass der Benutzer auf implizites Wissen angewiesen ist, welches der Volltextsuch-Engine fehlt. So weiß ein Benutzer, der nach dem Begriff „database“ sucht, normalerweise, dass „MySQL“, „Oracle“, „DB2“ und „RDBMS“ Phrasen sind, die „database“ entsprechen und insofern ebenfalls zurückgegeben werden sollten. Dies nennt man implizites Wissen.
Die blinde Abfrageerweiterung (auch „automatisches
Relevanzfeedback“ genannt) wird durch Anhängen von
WITH QUERY EXPANSION
an die Suchphrase
aktiviert. Sie funktioniert, indem die Suche zweimal
durchgeführt wird, wobei die Suchphrase für die zweite Suche
der ursprünglichen Suchphrase entspricht, die mit einigen
wenigen Dokumenten aus der ersten Suche verkettet wurde. Wenn
also eines der Dokumente das Wort „database“ und
das Wort „MySQL“ enthält, findet die zweite Suche
Dokumente, die das Wort „MySQL“ enthalten – und
zwar auch dann, wenn „database“ gar nicht enthalten
ist. Das folgende Beispiel veranschaulicht diesen Unterschied:
mysql>SELECT * FROM articles
->WHERE MATCH (title,body) AGAINST ('database');
+----+-------------------+------------------------------------------+ | id | title | body | +----+-------------------+------------------------------------------+ | 5 | MySQL vs. YourSQL | In the following database comparison ... | | 1 | MySQL Tutorial | DBMS stands for DataBase ... | +----+-------------------+------------------------------------------+ 2 rows in set (0.00 sec) mysql>SELECT * FROM articles
->WHERE MATCH (title,body)
->AGAINST ('database' WITH QUERY EXPANSION);
+----+-------------------+------------------------------------------+ | id | title | body | +----+-------------------+------------------------------------------+ | 1 | MySQL Tutorial | DBMS stands for DataBase ... | | 5 | MySQL vs. YourSQL | In the following database comparison ... | | 3 | Optimizing MySQL | In this tutorial we will show ... | +----+-------------------+------------------------------------------+ 3 rows in set (0.00 sec)
Ein weiteres Beispiel könnte die Suche nach den Maigret-Büchern von Georges Simenon sein, wobei der Benutzer nicht genau weiß, wie sich „Maigret“ schreibt. Eine Suche nach „Megre and the reluctant witnesses“ findet ohne Abfrageerweiterung nur „Maigret and the Reluctant Witnesses“. Eine Suche mit Abfrageerweiterung findet im zweiten Durchlauf alle Bücher mit dem Wort „Maigret“.
Hinweis: Da die blinde Abfrageerweiterung sehr viele irrelevante Dokumente zurückgibt, ist sie nur sinnvoll, wenn die Suchphrase sehr kurz ist.
Die folgende Tabelle zeigt die Standardliste der Stoppwörter für die Volltextsuche. Die Stoppwörter sind englisch. Eine Lokalisierung, zum Beispiel die Übersetzung in die deutsche Sprache, ist derzeit noch nicht vorgesehen. (Die Stoppwörter sind im Quellcode hardkodiert.)
a's | able | about | above | according |
accordingly | across | actually | after | afterwards |
again | against | ain't | all | allow |
allows | almost | alone | along | already |
also | although | always | am | among |
amongst | an | and | another | any |
anybody | anyhow | anyone | anything | anyway |
anyways | anywhere | apart | appear | appreciate |
appropriate | are | aren't | around | as |
aside | ask | asking | associated | at |
available | away | awfully | be | became |
because | become | becomes | becoming | been |
before | beforehand | behind | being | believe |
below | beside | besides | best | better |
between | beyond | both | brief | but |
by | c'mon | c's | came | can |
can't | cannot | cant | cause | causes |
certain | certainly | changes | clearly | co |
com | come | comes | concerning | consequently |
consider | considering | contain | containing | contains |
corresponding | could | couldn't | course | currently |
definitely | described | despite | did | didn't |
different | do | does | doesn't | doing |
don't | done | down | downwards | during |
each | edu | eg | eight | either |
else | elsewhere | enough | entirely | especially |
et | etc | even | ever | every |
everybody | everyone | everything | everywhere | ex |
exactly | example | except | far | few |
fifth | first | five | followed | following |
follows | for | former | formerly | forth |
four | from | further | furthermore | get |
gets | getting | given | gives | go |
goes | going | gone | got | gotten |
greetings | had | hadn't | happens | hardly |
has | hasn't | have | haven't | having |
he | he's | hello | help | hence |
her | here | here's | hereafter | hereby |
herein | hereupon | hers | herself | hi |
him | himself | his | hither | hopefully |
how | howbeit | however | i'd | i'll |
i'm | i've | ie | if | ignored |
immediate | in | inasmuch | inc | indeed |
indicate | indicated | indicates | inner | insofar |
instead | into | inward | is | isn't |
it | it'd | it'll | it's | its |
itself | just | keep | keeps | kept |
know | knows | known | last | lately |
later | latter | latterly | least | less |
lest | let | let's | like | liked |
likely | little | look | looking | looks |
ltd | mainly | many | may | maybe |
me | mean | meanwhile | merely | might |
more | moreover | most | mostly | much |
must | my | myself | name | namely |
nd | near | nearly | necessary | need |
needs | neither | never | nevertheless | new |
next | nine | no | nobody | non |
none | noone | nor | normally | not |
nothing | novel | now | nowhere | obviously |
of | off | often | oh | ok |
okay | old | on | once | one |
ones | only | onto | or | other |
others | otherwise | ought | our | ours |
ourselves | out | outside | over | overall |
own | particular | particularly | per | perhaps |
placed | please | plus | possible | presumably |
probably | provides | que | quite | qv |
rather | rd | re | really | reasonably |
regarding | regardless | regards | relatively | respectively |
right | said | same | saw | say |
saying | says | second | secondly | see |
seeing | seem | seemed | seeming | seems |
seen | self | selves | sensible | sent |
serious | seriously | seven | several | shall |
she | should | shouldn't | since | six |
so | some | somebody | somehow | someone |
something | sometime | sometimes | somewhat | somewhere |
soon | sorry | specified | specify | specifying |
still | sub | such | sup | sure |
t's | take | taken | tell | tends |
th | than | thank | thanks | thanx |
that | that's | thats | the | their |
theirs | them | themselves | then | thence |
there | there's | thereafter | thereby | therefore |
therein | theres | thereupon | these | they |
they'd | they'll | they're | they've | think |
third | this | thorough | thoroughly | those |
though | three | through | throughout | thru |
thus | to | together | too | took |
toward | towards | tried | tries | truly |
try | trying | twice | two | un |
under | unfortunately | unless | unlikely | until |
unto | up | upon | us | use |
used | useful | uses | using | usually |
value | various | very | via | viz |
vs | want | wants | was | wasn't |
way | we | we'd | we'll | we're |
we've | welcome | well | went | were |
weren't | what | what's | whatever | when |
whence | whenever | where | where's | whereafter |
whereas | whereby | wherein | whereupon | wherever |
whether | which | while | whither | who |
who's | whoever | whole | whom | whose |
why | will | willing | wish | with |
within | without | won't | wonder | would |
would | wouldn't | yes | yet | you |
you'd | you'll | you're | you've | your |
yours | yourself | yourselves | zero |
Die Volltextsuche wird nur für
MyISAM
-Tabellen unterstützt.
Sie kann mit den meisten Multibytezeichensätzen benutzt
werden. Eine Ausnahme ist Unicode: Der Zeichensatz
utf8
kann verwendet werden, nicht aber
der Zeichensatz ucs2
.
Ideografische Sprachen wie das Chinesische und das
Japanische kennen keine Worttrennzeichen. Aus diesem Grund
kann der FULLTEXT
-Parser bei diesen und
anderen Sprachen nicht bestimmen, wo
ein Wort anfängt oder endet. Die entsprechenden
Auswirkungen und einige Workarounds für das Problem sind in
Abschnitt 12.7, „MySQL-Volltextsuche“ beschrieben.
Zwar wird die Verwendung mehrerer Zeichensätze innerhalb
einer Tabelle unterstützt, aber alle Spalten in einem
FULLTEXT
-Index müssen denselben
Zeichensatz und dieselbe Sortierung haben.
Die MATCH()
-Spaltenliste muss exakt mit
der Spaltenliste in einer
FULLTEXT
-Indexdefinition der Tabelle
übereinstimmen, sofern für MATCH()
nicht der Modus IN BOOLEAN MODE
aktiviert
ist. Die boolesche Suche kann auch in nichtindizierten
Spalten erfolgen, ist dann allerdings recht langsam.
Das Argument AGAINST()
muss eine
String-Konstante sein.
Die Volltextsuchfunktion von MySQL bietet einige wenige vom Benutzer einstellbare Parameter. Sie können mehr Kontrolle über das Verhalten der Volltextsuche erhalten, wenn Sie eine MySQL-Quelldistribution verwenden, denn einige Änderungen erfordern Anpassungen am Quellcode. Siehe auch Abschnitt 2.8, „Installation der Quelldistribution“.
Beachten Sie, dass die Volltextsuche standardmäßig bereits für maximale Effektivität optimiert ist. Eine Modifikation des Standardverhaltens kann in den meisten Fällen zu einer Verringerung der Effizienz führen. Ändern Sie den MySQL-Quellcode nur dann, wenn Sie genau wissen, was Sie tun!
Die meisten Volltextvariablen, die in diesem Abschnitt beschrieben werden, müssen beim Serverstart eingestellt werden. Um sie zu ändern, ist ein Serverneustart erforderlich – eine Modifikation bei laufendem Server ist nicht möglich.
Einige Variablenänderungen erfordern eine Neuerstellung der
FULLTEXT
-Indizes in Ihren Tabellen. Hinweise
hierzu finden Sie am Ende dieses Abschnitts.
Die minimalen und maximalen Längen von zu indizierenden
Wörtern werden mit den Systemvariablen
ft_min_word_len
und
ft_max_word_len
definiert. (Siehe auch
Abschnitt 5.2.2, „Server-Systemvariablen“.) Die
standardmäßige Mindestlänge beträgt vier Zeichen, die
vorgabeseitige Höchstlänge hängt von der Version ab. Wenn
Sie einen der Werte ändern, müssen Sie ihre
FULLTEXT
-Indizes neu erstellen. Wünschen
Sie beispielsweise, dass Wörter mit drei Zeichen durchsucht
werden können sollen, dann können Sie die Variable
ft_min_word_len
umstellen, indem Sie die
folgenden Zeilen in eine Optionsdatei schreiben:
[mysqld] ft_min_word_len=3
Danach müssen Sie den Server neu starten und die
FULLTEXT
-Indizes neu erstellen. Beachten
Sie insbesondere die Anmerkungen zu
myisamchk in der Anleitung, die auf diese
Liste folgt.
Um die standardmäßige Stoppwortliste außer Kraft zu
setzen, müssen Sie die Systemvariable
ft_stopword_file
einstellen. (Siehe auch
Abschnitt 5.2.2, „Server-Systemvariablen“.) Der
Variablenwert sollte der Pfadname zu der Datei, die die
Stoppwortliste enthält, oder der Leer-String sein (in
diesem Fall wird die Stoppwortfilterung deaktiviert).
Nachdem Sie den Wert dieser Variablen oder den Inhalt der
Stoppwortdatei geändert haben, starten Sie den Server neu
und erstellen Ihre FULLTEXT
-Indizes dann
neu.
Die Stoppwortliste hat eine freie Form, d. h., Sie können
beliebige nichtalphanumerische Zeichen wie den
Zeilenwechsel, das Leerzeichen oder das Komma verwenden, um
Stoppwörter zu trennen. Ausnahmen sind der Unterstrich
(_
) und ein einzelnes Apostroph
('
), die als Teil eines Wortes behandelt
werden. Der Zeichensatz der Stoppwortliste ist der
Standardzeichensatz des Servers (siehe auch
Abschnitt 10.3.1, „Serverzeichensatz und -sortierfolge“).
Die 50-Prozent-Marke für natursprachliche Suchvorgänge
wird vom jeweiligen Gewichtungsschema bestimmt. Um sie zu
deaktivieren, suchen Sie in
myisam/ftdefs.h
nach der folgenden
Zeile:
#define GWS_IN_USE GWS_PROB
Ändern Sie sie wie folgt ab:
#define GWS_IN_USE GWS_FREQ
Dann kompilieren Sie MySQL neu. In diesem Fall ist es nicht
notwendig, die Indizes neu zu erstellen.
Hinweis: Durch diese
Änderung beeinträchtigen Sie die Fähigkeit von MySQL zur
Bereitstellung passender Relevanzwerte für die Funktion
MATCH()
erheblich.
Wenn Sie tatsächlich nach solchen gängigen Wörtern suchen
müssen, sollten Sie stattdessen im Modus IN
BOOLEAN MODE
suchen, denn bei diesem wird die
50-Prozent-Marke ignoriert.
Um die für die boolesche Volltextsuche verwendeten
Operatoren zu ändern, stellen Sie die Systemvariable
ft_boolean_syntax
ein. Diese Variable
kann zur Laufzeit des Servers geändert werden, allerdings
benötigen Sie hierfür die Berechtigung
SUPER
. Eine Neuerstellung der Indizes ist
in diesem Fall nicht notwendig. Weitere Informationen finden
Sie in Abschnitt 5.2.2, „Server-Systemvariablen“, wo auch
die Regeln für die Einstellung dieser Variablen beschrieben
werden.
Wenn Sie Volltextvariablen ändern, die die Indizierung
beeinflussen (ft_min_word_len
,
ft_max_word_len
oder
ft_stopword_file
), oder die Stoppwortdatei
selbst ändern, müssen Sie Ihre
FULLTEXT
-Indizes nach Durchführung der
Änderungen und dem Neustart des Servers neu erstellen. Um die
Indizes in diesem Fall neu zu erstellen, reicht es aus, eine
QUICK
-Reparaturoperation durchzuführen:
mysql> REPAIR TABLE tbl_name
QUICK;
Beachten Sie, dass, wenn Sie mit myisamchk
eine Operation durchführen, die die Tabellenindizes verändert
(dies können etwa Reparatur- oder Analyseoperationen sein), die
FULLTEXT
-Indizes unter Verwendung der
standardmäßigen Volltextparameterwerte
für die minimale und maximale Wortlänge und die Stoppwortdatei
verwendet werden, sofern Sie nichts anderes angeben. Dies kann
dazu führen, dass Abfragen fehlschlagen.
Das Problem tritt auf, weil diese Parameter nur dem Server
bekannt sind. Sie werden nicht in den
MyISAM
-Indexdateien gespeichert. Um das
Problem zu umgehen, wenn Sie die Werte für die minimale oder
maximale Wortlänge oder die Stoppwortdatei am Server geändert
haben, geben Sie dieselben Werte
ft_min_word_len
,
ft_max_word_len
und
ft_stopword_file
für
myisamchk an, die Sie für
mysqld verwendet haben. Haben Sie also
beispielsweise die Mindestwortlänge auf 3 gesetzt, dann können
Sie eine Tabelle mit myisamchk wie folgt
reparieren:
shell> myisamchk --recover --ft_min_word_len=3 tbl_name
.MYI
Wenn Sie gewährleisten wollen, dass
myisamchk und der Server dieselben Werte für
Volltextparameter verwenden, können Sie sie jeweils in die
Abschnitte [mysqld]
und
[myisamchk]
einer Optionsdatei eintragen:
[mysqld] ft_min_word_len=3 [myisamchk] ft_min_word_len=3
Eine Alternative zur Verwendung von myisamchk
besteht in der Nutzung von REPAIR TABLE
-,
ANALYZE TABLE
-, OPTIMIZE
TABLE
- oder ALTER
TABLE
-Anweisungen. Diese Anweisungen werden vom Server
ausgeführt, der die korrekten Werte der Volltextparameter
kennt.
Der Operator BINARY
wandelt den ihm
nachfolgenden String in einen Binär-String um. Dies ist eine
einfache Möglichkeit, einen Spaltenvergleich byte- statt
zeichenweise durchzuführen. Auf diese Weise unterscheidet der
Vergleich die Groß-/Kleinschreibung auch dann, wenn die
Spalte nicht als BINARY
oder
BLOB
definiert ist.
BINARY
berücksichtigt auch am Ende
stehende Leerzeichen.
mysql>SELECT 'a' = 'A';
-> 1 mysql>SELECT BINARY 'a' = 'A';
-> 0 mysql>SELECT 'a' = 'a ';
-> 1 mysql>SELECT BINARY 'a' = 'a ';
-> 0
In einem Vergleich wirkt sich BINARY
auf
die gesamte Operation aus. Es kann vor einen beliebigen
Operanden gesetzt werden – das Ergebnis bleibt stets das
Gleiche.
BINARY
ist
eine Abkürzung für
str
CAST(
.
str
AS
BINARY)
Beachten Sie, dass, wenn Sie in bestimmten Kontexten eine
indizierte Spalte in BINARY
umwandeln,
MySQL den Index nicht mehr effizient verwenden kann.
CAST(
,
expr
AS
type
)CONVERT(
,
expr
,type
)CONVERT(
expr
USING
transcoding_name
)
Die Funktionen CAST()
und
CONVERT()
nehmen einen Wert eines Typs
entgegen und erzeugen einen Wert eines anderen Typs.
type
kann einen der folgenden Werte
haben:
BINARY[(
N
)]
CHAR[(
N
)]
DATE
DATETIME
DECIMAL
SIGNED [INTEGER]
TIME
UNSIGNED [INTEGER]
BINARY
erzeugt einen String des Datentyps
BINARY
. Eine Erläuterung, wie sich dies
auf Vergleiche auswirkt, finden Sie in
Abschnitt 11.4.2, „Die BINARY
- und VARBINARY
-Typen“. Wird die optionale Länge
N
angegeben, dann verwendet
BINARY[
zur
Umwandlung nicht mehr als N
]N
Bytes
des Arguments. Werte, die kürzer als
N
Bytes sind, werden mit
0x00
-Bytes auf die Länge
N
aufgefüllt.
Mit CHAR[
werden bei der Umwandlung nicht mehr als
N
]N
Zeichen des Arguments verwendet.
CAST()
und CONVERT(... USING
...)
sind SQL-Standardsyntax. Die Form von
CONVERT()
ohne USING
hingegen ist ODBC-Syntax.
CONVERT()
wird mit USING
zur Konvertierung von Daten zwischen verschiedenen
Zeichensätzen konvertiert. Bei MySQL sind die
Transkodierungs- mit den entsprechenden Zeichensatznamen
identisch. Die folgende Anweisung beispielsweise konvertiert
den String 'abc'
im Standardzeichensatz in
den entsprechenden String im Zeichensatz
utf8
:
SELECT CONVERT('abc' USING utf8);
Normalerweise können Sie einen BLOB
-Wert oder
einen anderen binären Wert nur mit Unterscheidung der
Groß-/Kleinschreibung vergleichen, da Binär-Strings keinen
Zeichensatz (und deswegen auch keine Groß-/Kleinschreibung)
haben. Um einen Vergleich ohne Unterscheidung der
Groß-/Kleinschreibung durchzuführen, konvertieren Sie den Wert
mit der Funktion CONVERT()
in einen
nichtbinären String. Wenn der Zeichensatz des Ergebnisses eine
Sortierung mit Unterscheidung der Groß-/Kleinschreibung hat, dann
unterscheidet die LIKE
-Operation die
Groß-/Kleinschreibung nicht:
SELECT 'A' LIKE CONVERT(blob_col
USING latin1) FROMtbl_name
;
Um einen anderen Zeichensatz zu verwenden, ersetzen Sie
latin1
in der obigen Anweisung durch dessen
Namen. Wenn Sie gewährleisten wollen, dass eine Sortierung ohne
Unterscheidung der Groß-/Kleinschreibung verwendet wird, geben
Sie auf den Aufruf von CONVERT()
folgend eine
COLLATE
-Klausel an.
CONVERT()
kann – allgemeiner gesagt – für
den Vergleich von Strings verwendet werden, die in
unterschiedlichen Zeichensätzen dargestellt werden.
Die Umwandlungsfunktionen sind nützlich, um eine Spalte eines
bestimmten Typs in einer CREATE ...
SELECT
-Anweisung zu erstellen:
CREATE TABLE new_table SELECT CAST('2000-01-01' AS DATE);
Die Funktionen können auch praktisch sein, um
ENUM
-Spalten in lexikaler Reihenfolge zu
sortieren. Normalerweise erfolgt die Sortierung von
ENUM
-Spalten unter Verwendung der internen
numerischen Werte. Die Umwandlung der Werte in
CHAR
führt zu einer lexikalen Sortierung:
SELECTenum_col
FROMtbl_name
ORDER BY CAST(enum_col
AS CHAR);
CAST(
ist das Gleiche wie str
AS BINARY)BINARY
.
str
CAST(
behandelt den Ausdruck als String mit dem Standardzeichensatz.
expr
AS CHAR)
CAST()
ändert das Ergebnis auch, wenn Sie es
als Teil eines komplexeren Ausdrucks wie etwa
CONCAT('Date: ',CAST(NOW() AS DATE))
verwenden.
Sie sollten CAST()
nicht zur Extraktion von
Daten in verschiedenen Formaten benutzen, sondern stattdessen
String-Funktionen wie LEFT()
oder
EXTRACT()
verwenden. Siehe auch
Abschnitt 12.5, „Datums- und Zeitfunktionen“.
Um einen String in einem Zahlenkontext in einen numerischen Wert umzuwandeln, müssen Sie normalerweise nichts anderes tun, als den String-Wert wie eine Zahl zu verwenden:
mysql> SELECT 1+'1';
-> 2
Wenn Sie eine Zahl im String-Kontext verwenden, wird die Zahl
automatisch in einen BINARY
-String konvertiert.
mysql> SELECT CONCAT('hello you ',2);
-> 'hello you 2'
MySQL unterstützt Berechnungen mit vorzeichenbehafteten wie auch
vorzeichenlosen 64-Bit-Werten. Wenn Sie numerische Operationen
(wie +
) verwenden und einer der Operanden ein
vorzeichenloser Integer ist, dann ist auch das Ergebnis
vorzeichenlos. Sie können dieses Verhalten außer Kraft setzen,
indem Sie die Umwandlungsoperatoren SIGNED
und
UNSIGNED
zur Umwandlung des Operanden in einen
vorzeichenbehafteten bzw. vorzeichenlosen 64-Bit-Integer benutzen.
mysql>SELECT CAST(1-2 AS UNSIGNED)
-> 18446744073709551615 mysql>SELECT CAST(CAST(1-2 AS UNSIGNED) AS SIGNED);
-> -1
Beachten Sie, dass, wenn ein Operand ein Fließkommawert ist, das
Ergebnis ebenfalls ein Fließkommawert sein wird; die obige Regel
findet in diesem Fall keine Anwendung. (In diesem Kontext werden
DECIMAL
-Spalten als Fließkommawerte
betrachtet.)
mysql> SELECT CAST(1 AS UNSIGNED) - 2.0;
-> -1.0
Wenn Sie in einer Rechenoperation einen String verwenden, dann wird dieser in eine Fließkommazahl umgewandelt.
Konvertieren Sie einen „Nulldatums“-String in ein
Datum, dann geben CONVERT()
und
CAST()
NULL
zurück und
erzeugen bei aktiviertem SQL-Modus NO_ZERO_DATE
außerdem eine Warnung.
Dieser Abschnitt beschreibt XML und zugehörige Funktionalitäten in MySQL.
Beachten Sie, dass es möglich ist, in den MySQL-Clients
mysql und mysqldump eine
XML-formatierte Ausgabe zu erhalten, indem man sie mit der Option
--xml
aufruft. Siehe auch
Abschnitt 8.5, „mysql — Das MySQL-Befehlszeilenwerkzeug mysql“, und Abschnitt 8.10, „mysqldump — Programm zur Datensicherung“.
Seit Version 5.1.5 enthält MySQL zwei Funktionen, die grundlegende XPath-Funktionalitäten (XML Path Language) bereitstellen.
Beachten Sie, dass sich diese Funktionen derzeit noch in Entwicklung befinden. Wir werden diese und andere Aspekte von XML und XPath in MySQL 5.1 und höher kontinuierlich verbessern. Sie können diese Funktionen im MySQL XML User Forum diskutieren, Fragen stellen und entsprechende Hilfe von anderen Benutzern erhalten.
ExtractValue(
xml_frag
,
xpath_expr
)
Diese Funktion nimmt zwei String-Argumente – ein
XML-Fragment xml_frag
und einen
XPath-Ausdruck xpath_expr
(auch
Lokator genannt) – entgegen und gibt
den xpath_expr
entsprechenden Wert
zurück. Beachten Sie, dass ExtractValue()
nur das CDATA
zurückgibt, das direkt im
xpath_expr
entsprechenden Tag
enthalten ist, nicht jedoch Tags, die innerhalb des
entsprechenden Tags enthalten sind, oder deren Inhalte (siehe
auch das als val1
im folgenden Beispiel
zurückgegebene Ergebnis).
Wird keine Übereinstimmung für
xpath_expr
gefunden, dann gibt die
Funktion einen Leer-String zurück.
Werden mehrere Übereinstimmungen gefunden, dann werden die
Inhalte aller entsprechenden Elemente (in der Reihenfolge der
Übereinstimmung) in einem leerzeichengetrennten String
zurückgegeben.
mysql>SELECT
->ExtractValue('<a>ccc<b>ddd</b></a>', '/a') AS val1,
->ExtractValue('<a>ccc<b>ddd</b></a>', '/a/b') AS val2,
->ExtractValue('<a>ccc<b>ddd</b></a>', '//b') AS val3,
->ExtractValue('<a>ccc<b>ddd</b></a>', '/b') AS val4,
->ExtractValue('<a>ccc<b>ddd</b><b>eee</b></a>', '//b') AS val5;
+------+------+------+------+---------+ | val1 | val2 | val3 | val4 | val5 | +------+------+------+------+---------+ | ccc | ddd | ddd | | ddd eee | +------+------+------+------+---------+
UpdateXML(
xml_target
,
xpath_expr
,
new_xml
)
Diese Funktion ersetzt einen Teil eines gegebenen
XML-Fragments xml_target
durch ein
neues XML-Fragment new_xml
und gibt
das geänderte XML dann zurück. Der Teil von
xml_target
, der ersetzt wird,
entspricht einem XPath-Ausdruck
xpath_expr
, der vom Benutzer
übergeben wurde. Wird kein Ausdruck entdeckt, der
xpath_expr
entspricht, dann gibt
die Funktion das ursprüngliche XML-Fragment
xml_target
zurück. Alle drei
Argumente müssen Strings sein.
mysql>SELECT
->UpdateXML('<a><b>ccc</b><d></d></a>', '/a', '<e>fff</e>') AS val1,
->UpdateXML('<a><b>ccc</b><d></d></a>', '/b', '<e>fff</e>') AS val2,
->UpdateXML('<a><b>ccc</b><d></d></a>', '//b', '<e>fff</e>') AS val3,
->UpdateXML('<a><b>ccc</b><d></d></a>', '/a/d', '<e>fff</e>') AS val4
->\G
*************************** 1. row *************************** val1: <e>fff</e> val2: <a><b>ccc</b><d></d></a> val3: <a><e>fff</e><d></d></a> val4: <a><b>ccc</b><e>fff</e></a>
Es folgen nun Beschreibungen und Beispiele einiger einfacher XPath-Ausdrücke:
/
tag
Entspricht
<
,
wenn (und nur wenn)
tag
/><
das
Stammelement ist.
tag
/>
Beispiel: /a
findet eine Übereinstimmung
in <a><b/></a>
, weil es
dem äußersten Tag (Stamm-Tag) entspricht. Es entspricht
nicht dem inneren a
-Element in
<b><a/></b>
, weil es in
dieser Instanz ein einem anderen Element untergeordnetes
Element ist.
/
tag1
/tag2
Entspricht
<
,
wenn (und nur wenn) es ein untergeordnetes Element von
tag2
/><
und
tag1
/><
das Stammelement ist.
tag1
/>
Beispiel: /a/b
entspricht dem Element
b
im XML-Fragment
<a><b/></a>
, weil es ein
untergeordnetes Element des Stammelements
a
ist. Keine Entsprechung liegt in
<b><a/></b>
vor, weil in
diesem Fall b
das Stammelement (und
damit kein einem anderen Element untergeordnetes Element) ist.
Ebenso wenig hat der XPath-Ausdruck eine Übereinstimmung in
<a><c><b/></c></a>
;
hier stammt b
zwar von
a
ab, ist aber im engen Sinne kein
a
untergeordnetes Element.
Dieses Konstrukt ist auf drei oder mehr Elemente erweiterbar.
So entspricht beispielsweise der XPath-Ausdruck
/a/b/c
dem Element
c
im Fragment
<a><b><c/></b></a>
.
//
tag
Entspricht jeder Instanz von tag
.
Beispiel: //a
entspricht dem Element
a
in allen folgenden Fragmenten:
<a><b><c/></b></a>
;
<c><a><b/></a></b>
;
<c><b><a/></b></c>
.
//
kann mit /
kombiniert
werden. Beispielsweise entspricht //a/b
dem
Element b
in den Fragmenten
<a><b/></a>
und
<a><b><c/></b></a>
.
Der Operator *
agiert als Jokerzeichen,
welches jedem Element entspricht. So entspricht beispielsweise
der Ausdruck /*/b
dem Element
b
in den XML-Fragmenten
<a><b/></a>
und
<c><b/></c>
. Allerdings
erzeugt der Ausdruck keine Übereinstimmung im Fragment
<b><a/></b>
, weil
b
ein einem anderen Element
untergeordnetes Element sein muss. Das Jokerzeichen kann an
beliebiger Position verwendet werden: Der Ausdruck
/*/b/*
entspricht jedem untergeordneten
Element eines Elements b
, welches
selbst nicht das Stammelement ist.
Mehrere Lokatoren können mit dem Operator
|
(logisches OR
)
verglichen werden. So entspricht etwa der Ausdruck
//b|//c
allen b
-
und c
-Elementen im XML-Ziel.
Es ist auch möglich, ein Element basierend auf dem Wert eines
oder mehrerer seiner Attribute zu vergleichen. Dies erfolgt
mit der Syntax
.
So entspricht beispielsweise der Ausdruck
tag
[@attribute
="value
"]//b[@id="idB"]
dem zweiten Element
b
im Fragment
<a><b id="idA"/><c/><b
id="idB"/></a>
. Um einen Vergleich mit
einem beliebigen Element mit
durchzuführen, benutzen Sie den XPath-Ausdruck
attribute
="value
"//*[
.
attribute
="value
"]
Um mehrere Attributwerte zu filtern, benutzen Sie einfach
mehrere aufeinander folgende Attributvergleichsklauseln. Der
Ausdruck //b[@c="x"][@d="y"]
beispielsweise
entspricht dem Element <b c="x"
d="y"/>
an beliebiger Stelle in einem gegebenen
XML-Fragment.
Um Elemente zu finden, für die dasselbe Attribut genau einem
von mehreren Werten entspricht, müssen Sie mehrere Lokatoren
benutzen, die mit dem Operator |
verknüpft
werden. Um also etwa eine Übereinstimmung für alle Elemente
b
zu erzielen, deren Attribute
c
entweder den Wert 17 oder den
Wert 23 haben, verwenden Sie den Ausdruck
//b[@c="23"]|b[@c="17"]
.
Eine detaillierte Beschreibung zu Syntax und Einsatz von XPath würde den Rahmen dieses Handbuchs sprengen. Umfassende Informationen erhalten Sie unter XML Path Language (XPath) 1.0 standard. Eine nützliche Ressource für Neulinge im Bereich XPath oder für solche Leser, die ihre Kenntnisse ein wenig auffrischen wollen, ist das Zvon.org XPath Tutorial, das in mehreren Sprachen verfügbar ist.
Die von diesen Funktionen unterstützte XPath-Syntax unterliegt derzeit den folgenden Beschränkungen:
Nodeset-Nodeset-Vergleiche (wie etwa
'/a/b[@c=@d]'
) werden nicht unterstützt.
Nur Vergleiche der Form
[@
,
wobei attribute
="const
"]const
ein konstanter Wert
ist, sind zurzeit möglich. Beachten Sie, dass Gleichheit und
Ungleichheit (=
und !=
)
die einzigen unterstützten Vergleichsoperatoren sind.
Relative Lokatorausdrücke werden nicht unterstützt.
XPath-Ausdrücke müssen mit /
oder
//
beginnen.
Der Operator ::
wird nicht unterstützt.
Die folgenden XPath-Funktionen werden nicht unterstützt:
id()
lang()
last()
local-name()
name()
namespace-uri()
normalize-space()
starts-with()
string()
substring-after()
substring-before()
translate()
Die folgenden Axes werden nicht unterstützt:
following-sibling
following
preceding-sibling
preceding
MySQL verwendet die BIGINT
-Arithmetik
(64-Bit-Arithmetik) für Bitoperationen, d. h., diese
Operatoren haben einen maximalen Bereich von 64 Bits.
Bit-OR:
mysql> SELECT 29 | 15;
-> 31
Das Ergebnis ist ein vorzeichenloser 64-Bit-Integer.
Bit-AND:
mysql> SELECT 29 & 15;
-> 13
Das Ergebnis ist ein vorzeichenloser 64-Bit-Integer.
Bit-XOR:
mysql>SELECT 1 ^ 1;
-> 0 mysql>SELECT 1 ^ 0;
-> 1 mysql>SELECT 11 ^ 3;
-> 8
Das Ergebnis ist ein vorzeichenloser 64-Bit-Integer.
Verschiebt eine Longlong-Zahl (BIGINT
)
nach links.
mysql> SELECT 1 << 2;
-> 4
Das Ergebnis ist ein vorzeichenloser 64-Bit-Integer.
Verschiebt eine Longlong-Zahl (BIGINT
)
nach rechts.
mysql> SELECT 4 >> 2;
-> 1
Das Ergebnis ist ein vorzeichenloser 64-Bit-Integer.
Invertiert alle Bits.
mysql> SELECT 5 & ~1;
-> 4
Das Ergebnis ist ein vorzeichenloser 64-Bit-Integer.
Gibt die Anzahl der Bits zurück, die im Argument
N
gesetzt sind.
mysql> SELECT BIT_COUNT(29), BIT_COUNT(b'101010');
-> 4, 3
Die in diesem Abschnitt beschriebenen Funktionen führen Ver- und Entschlüsselung sowie Komprimierung und Dekomprimierung durch.
Hinweis: Die Verschlüsselungs-
und Komprimierungsfunktionen geben Binär-Strings zurück. Bei
vielen dieser Funktionen kann das Ergebnis willkürliche
Bytewerte enthalten. Wenn Sie diese Ergebnisse speichern wollen,
verwenden Sie eine BLOB
-Spalte statt einer
CHAR
- oder VARCHAR
-Spalte,
um potenzielle Probleme zu vermeiden, die aufgrund einer
Datenwertänderung durch das Entfernen von Leerzeichen am Ende
entstehen könnten.
Hinweis: Für die MD5- und SHA-1-Algorithmen sind Exploits bekannt. Sie sollten deswegen die Verwendung einer anderen Verschlüsselungsfunktion in Betracht ziehen, die in diesem Abschnitt beschrieben sind.
AES_ENCRYPT(
,
str
,key_str
)AES_DECRYPT(
crypt_str
,key_str
)
Diese Funktionen gestatten die Ver- und Entschlüsselung von Daten mithilfe des offiziellen AES-Algorithmus (Advanced Encryption Standard; dieser war früher als „Rijndael“ bekannt). Die Verschlüsselung erfolgt mit einem 128-Bit-Schlüssel, den Sie aber durch Modifizierung des Quellcodes auf 256 Bits erweitern können. Wir haben uns für eine Schlüsselbreite von 128 Bits entschieden, da diese bei hoher Verarbeitungsgeschwindigkeit für die meisten Zwecke ausreichend sicher ist.
AES_ENCRYPT()
verschlüsselt einen String
und gibt einen Binär-String zurück.
AES_DESCRIPT()
entschlüsselt den
verschlüsselten String und gibt den Original-String
zurück. Die Eingabeargumente dürfen eine beliebige Länge
haben. Wenn eines der Argumente NULL
ist,
ist das Ergebnis dieser Funktion ebenfalls
NULL
.
Da AES als Algorithmus auf Blockebene arbeitet, werden Strings unterschiedlicher Länge bei der Verschlüsselung mit Füllzeichen erweitert. Die Länge des Ergebnis-Strings lässt sich mit folgender Formel berechnen:
16 × (trunc(string_length
/ 16) + 1)
Wenn AES_DECRYPT()
ungültige Daten oder
ein inkorrektes Auffüllen erkennt, gibt es
NULL
zurück. Es ist allerdings möglich,
dass AES_DECRYPT()
einen
Nicht-NULL
-Wert zurückgibt, wenn
Eingabedaten oder Schlüssel ungültig sind. (Der
Rückgabewert ist dann in aller Regel unsinnig).
Sie können die AES-Funktionen zur Speicherung von Daten in verschlüsselter Form verwenden, indem Sie Ihre Abfragen abändern:
INSERT INTO t VALUES (1,AES_ENCRYPT('text','password'));
AES_ENCRYPT()
und
AES_DECRYPT()
können als die aus
kryptografischer Sicht sichersten
Verschlüsselungsfunktionen gelten, die derzeit in MySQL zur
Verfügung stehen.
Komprimiert einen String und gibt das Ergebnis als
Binär-String zurück. Diese Funktion erfordert es, dass
MySQL mit einer Komprimierungsbibliothek wie etwa
zlib
kompiliert wurde. Andernfalls ist
der Rückgabewert immer NULL
. Der
komprimierte String kann mit UNCOMPRESS()
wieder dekomprimiert werden.
mysql>SELECT LENGTH(COMPRESS(REPEAT('a',1000)));
-> 21 mysql>SELECT LENGTH(COMPRESS(''));
-> 0 mysql>SELECT LENGTH(COMPRESS('a'));
-> 13 mysql>SELECT LENGTH(COMPRESS(REPEAT('a',16)));
-> 15
Der Inhalt des komprimierten Strings wird wie folgt gespeichert:
Leere Strings werden als Leer-Strings gespeichert.
Nichtleere Strings werden als unkomprimierte Strings mit
einer Länge von 4 Byte gespeichert (wobei das
niedrigste Byte zuerst kommt), gefolgt vom komprimierten
String. Wenn der String mit einem Leerzeichen endet,
wird ein zusätzliches Zeichen
‘.
’ hinzugefügt, um
Probleme mit dem Abschneiden von Leerzeichen am Ende
für den Fall zu vermeiden, dass das Ergebnis in einer
CHAR
- oder
VARCHAR
-Spalte gespeichert wird. (Von
der Verwendung von CHAR
oder
VARCHAR
zur Speicherung komprimierter
Strings wird abgeraten. Verwenden Sie stattdessen besser
eine BLOB
-Spalte.)
Entschlüsselt den verschlüsselten String
crypt_str
mit
pass_str
als Passwort.
crypt_str
sollte ein String sein,
der von ENCODE()
zurückgegeben wurde.
Verschlüsselt str
unter
Verwendung von pass_str
als
Passwort. Zur Entschlüsselung des Ergebnisses verwenden Sie
DECODE()
.
Das Ergebnis ist ein Binär-String derselben Länge wie
str
.
DES_DECRYPT(
crypt_str
[,key_str
])
Entschlüsselt einen String, der mit
DES_ENCRYPT()
verschlüsselt wurde. Wenn
ein Fehler auftritt, gibt die Funktion
NULL
zurück.
Beachten Sie, dass diese Funktion nur funktioniert, wenn MySQL mit SSL-Unterstützung konfiguriert wurde. Siehe auch Abschnitt 5.9.7, „Verwendung sicherer Verbindungen“.
Wird kein Argument key_str
angegeben, dann untersucht DES_DECRYPT()
das erste Byte des verschlüsselten Strings, um die
DES-Schlüsselnummer zu ermitteln, die zur Verschlüsselung
des ursprünglichen Strings verwendet wurde, und liest den
Schlüssel dann aus der DES-Schlüsseldatei aus, um die
Nachricht zu entschlüsseln. Damit dies klappt, benötigt
der Benutzer die Berechtigung SUPER
. Die
Schlüsseldatei kann mit der Serveroption
--des-key-file
angegeben werden.
Wenn Sie der Funktion ein Argument
key_str
übergeben, wird dieser
String als Schlüssel zur Entschlüsselung der Nachricht
verwendet.
Wenn das Argument crypt_str
kein
verschlüsselter String zu sein scheint, gibt MySQL den
übergebenen String crypt_str
zurück.
DES_ENCRYPT(
str
[,(key_num
|key_str
)])
Verschlüsselt den String mit dem angegebenen Schlüssel unter Verwendung des Triple-DES-Algorithmus.
Beachten Sie, dass diese Funktion nur funktioniert, wenn MySQL mit SSL-Unterstützung konfiguriert wurde. Siehe auch Abschnitt 5.9.7, „Verwendung sicherer Verbindungen“.
Der für die Verschlüsselung zu verwendende Schlüssel wird
basierend auf dem zweiten Argument zu
DES_ENCRYPT()
(sofern vorhanden)
ausgewählt:
Argument | Beschreibung |
Kein Argument | Der erste Schlüssel aus der DES-Schlüsseldatei wird verwendet. |
key_num | Der angegebene Schlüssel (0 bis 9) aus der DES-Schlüsseldatei wird verwendet. |
key_str | Der angegebene String wird zur Verschlüsselung von
str benutzt. |
Die Schlüsseldatei kann mit der Serveroption
--des-key-file
angegeben werden.
Der Rückgabe-String ist ein Binär-String, bei dem das
erste Zeichen CHAR(128 | key_num)
ist.
Wenn ein Fehler auftritt, gibt
DES_ENCRYPT()
NULL
zurück.
Die 128 wird hinzugefügt, um die Erkennung eines
verschlüsselten Schlüssels zu erleichtern. Wenn Sie einen
String-Schlüssel verwenden, ist
key_num
127.
Die String-Länge des Ergebnisses wird mit dieser Formel angegeben:
new_len
=orig_len
+ (8 - (orig_len
% 8)) + 1
Jede Zeile in der DES-Schlüsseldatei hat das folgende Format:
key_num
des_key_str
Jeder key_num
-Wert muss eine Zahl
zwischen 0
und 9
sein.
Die Zeilen können in der Datei beliebig sortiert sein.
des_key_str
ist der String, der
zur Verschlüsselung der Nachricht verwendet wird. Es sollte
mindestens ein Leerzeichen zwischen der Zahl und dem
Schlüssel stehen. Der erste Schlüssel ist der
Standardschlüssel: Er wird benutzt, wenn kein
Schlüsselargument für DES_ENCRYPT()
angegeben wurde.
Sie können MySQL mit der Anweisung FLUSH
DES_KEY_FILE
anweisen, neue Schlüsselwerte aus
der Schlüsseldatei einzulesen. Dies erfordert die
Berechtigung RELOAD
.
Ein Vorteil der Verwendung eines Satzes mit Standardschlüsseln besteht darin, dass dies Anwendungen eine Möglichkeit bietet, auf das Vorhandensein verschlüsselter Spaltenwerte zu prüfen, ohne dem Endbenutzer das Recht zur Verschlüsselung dieser Werte zu geben.
mysql>SELECT customer_address FROM customer_table
>WHERE crypted_credit_card = DES_ENCRYPT('credit_card_number');
Verschlüsselt str
unter
Verwendung des Unix-Systemaufrufs crypt()
und gibt einen Binär-String zurück. Das Argument
salt
sollte ein String mit
mindestens zwei Zeichen sein. Wird kein
salt
-Argument angegeben, dann
wird ein zufälliger Wert verwendet.
mysql> SELECT ENCRYPT('hello');
-> 'VxuFAJXVARROc'
ENCRYPT()
ignoriert zumindest auf einigen
Systemen alle bis auf die ersten acht Zeichen von
str
. Dieses Verhalten wird von
der Implementierung des zugrunde liegenden
crypt()
-Systemaufrufs bestimmt.
Wenn crypt()
nicht auf Ihrem System
verfügbar ist (wie es bei Windows der Fall ist), gibt
ENCRYPT()
immer NULL
zurück.
Berechnet eine MD5-Prüfsumme mit 128 Bits für den String.
Der Wert wird als 32 Hexadezimalstellen umfassender
Binär-String zurückgegeben. Ist das Argument
NULL
, so wird auch
NULL
zurückgegeben. Der Rückgabewert
kann z. B. als Hash-Schlüssel verwendet werden.
mysql> SELECT MD5('testing');
-> 'ae2b1fca515949e5d54fb22b8ed95575'
Dies ist der „MD5-Message-Digest-Algorithmus“ von RSA Data Security, Inc.
Wenn Sie den Wert in Großbuchstaben konvertieren wollen,
lesen Sie die Beschreibung zur Konvertierung von
Binär-Strings im Abschnitt zum Operator
BINARY
(Abschnitt 12.8, „Cast-Funktionen und Operatoren“).
Beachten Sie auch die Anmerkung zum MD5-Algorithmus am Anfang dieses Abschnitts.
OLD_PASSWORD()
wurde zu MySQL
hinzugefügt, als die Implementierung von
PASSWORD()
geändert wurde, um die
Sicherheit zu verbessern. OLD_PASSWORD()
gibt den Wert der alten (d. h. vor Version 4.1 verwendeten)
Implementierung von PASSWORD()
als
Binär-String zurück und soll Ihnen das Zurücksetzen von
Passwörtern auf Clients vor Version 4.1 gestatten, die mit
Ihrem MySQL Server unter Version 5.1 eine
Verbindung herstellen können sollen, ohne ausgesperrt zu
werden. Siehe auch Abschnitt 5.8.9, „Kennwort-Hashing ab MySQL 4.1“.
Berechnet einen Passwort-String aus dem Klartextpasswort
str
und gibt diesen zurück. Der
Rückgabewert ist ein Binär-String oder aber
NULL
, sofern das Argument
NULL
war. Diese Funktion wird zur
Verschlüsselung von MySQL-Passwörtern zur Speicherung in
der Spalte Password
der Grant-Tabelle
user
benutzt.
mysql> SELECT PASSWORD('badpwd');
-> '*AAB3E285149C0135D51A520E1940DD3263DC008C'
Die PASSWORD()
-Verschlüsselung ist
unidirektional (d. h. unumkehrbar).
PASSWORD()
führt keine
Passwortverschlüsselung in der Art der Verschlüsselung von
Unix-Passwörtern durch. Siehe auch
ENCRYPT()
.
Hinweis: Die Funktion
PASSWORD()
wird in MySQL Server vom
Authentifizierungssystem verwendet. Sie sollten Sie
nicht in Ihren eigenen Anwendungen
einsetzen. Ziehen Sie zu diesem Zweck eher
MD5()
oder SHA1()
in
Betracht. Ferner können Sie RFC 2195 weitere Informationen
zum sicheren Umgang mit Passwörtern und Authentifizierung
in Ihren Anwendungen entnehmen.
Berechnet eine 160 Bits umfassende SHA-1-Prüfsumme für den
String. (Siehe auch RFC 3174 mit dem Titel „Secure
Hash Algorithm“). Der Wert wird als 40
Hexadezimalstellen umfassender Binär-String zurückgegeben.
Ist das Argument NULL
, so wird auch
NULL
zurückgegeben. Diese Funktion
lässt sich etwa für die Erstellung eines Hash-Schlüssels
verwenden. Sie können sie auch als Kryptografiefunktion zur
Speicherung von Passwörtern verwenden.
SHA()
ist synonym zu
SHA1()
.
mysql> SELECT SHA1('abc');
-> 'a9993e364706816aba3e25717850c26c9cd0d89d'
SHA1()
kann als aus kryptografischer
Sicht sichereres Äquivalent zu MD5()
betrachtet werden. Allerdings sollten Sie auch die Anmerkung
zu den MD5- und SHA-1-Algorithmen am Anfang dieses
Abschnitts beachten.
UNCOMPRESS(
string_to_uncompress
)
Entkomprimiert einen String, der mit der Funktion
COMPRESS()
komprimiert wurde. Wenn dieses
Argument kein komprimierter Wert ist, ist das Ergebnis
NULL
. Diese Funktion erfordert es, dass
MySQL mit einer Komprimierungsbibliothek wie etwa
zlib
kompiliert wurde. Andernfalls ist
der Rückgabewert immer NULL
.
mysql>SELECT UNCOMPRESS(COMPRESS('any string'));
-> 'any string' mysql>SELECT UNCOMPRESS('any string');
-> NULL
UNCOMPRESSED_LENGTH(
compressed_string
)
Gibt die Länge zurück, die der komprimierte String vor der Länge hatte.
mysql> SELECT UNCOMPRESSED_LENGTH(COMPRESS(REPEAT('a',30)));
-> 30
Die Funktion BENCHMARK()
wiederholt die
Ausführung des Ausdrucks expr
mit der mit count
angegebenen
Häufigkeit. Sie kann verwendet werden, um zu ermitteln, wie
schnell MySQL den Ausdruck verarbeitet. Der Ergebniswert ist
immer 0
. Vorgesehen ist die Verwendung
dieser Funktion aus dem Client mysql
heraus. Dieser gibt dann die Ausführungszeiten der Abfrage
an:
mysql> SELECT BENCHMARK(1000000,ENCODE('hello','goodbye'));
+----------------------------------------------+
| BENCHMARK(1000000,ENCODE('hello','goodbye')) |
+----------------------------------------------+
| 0 |
+----------------------------------------------+
1 row in set (4.74 sec)
Die gemeldete Zeit ist die auf der Clientseite verstrichene
Zeit und nicht die Prozessorzeit auf der Serverseite. Wir
empfehlen die mehrfache Ausführung von
BENCHMARK()
und die Interpretation des
Ergebnisses im Hinblick darauf, wie hoch die Belastung des
Servercomputers ist.
Gibt den Zeichensatz des String-Arguments zurück.
mysql>SELECT CHARSET('abc');
-> 'latin1' mysql>SELECT CHARSET(CONVERT('abc' USING utf8));
-> 'utf8' mysql>SELECT CHARSET(USER());
-> 'utf8'
Gibt den Sortierfolgenvorrangswert des String-Arguments zurück.
mysql>SELECT COERCIBILITY('abc' COLLATE latin1_swedish_ci);
-> 0 mysql>SELECT COERCIBILITY(USER());
-> 3 mysql>SELECT COERCIBILITY('abc');
-> 4
Die Rückgabewerte haben die in der folgenden Tabelle aufgeführten Bedeutungen. Niedrigere Werte haben dabei eine höhere Rangstufe.
Sortierfolgenvorrang | Bedeutung | Beispiel |
0 | Explizite Sortierung | Wert mit COLLATE -Klausel |
1 | Keine Sortierung | Verkettung von Strings mit unterschiedlichen Sortierungen |
2 | Implizite Sortierung | Spaltenwert, Parameter einer gespeicherten Routine oder lokale Variable |
3 | Systemkonstante | USER() -Rückgabewert |
4 | Sortierfolgenvorrang einstellbar | Literaler String |
5 | Ignorierbar | NULL oder ein Ausdruck, der von
NULL abgeleitet wurde |
Gibt die Sortierung des String-Arguments zurück.
mysql>SELECT COLLATION('abc');
-> 'latin1_swedish_ci' mysql>SELECT COLLATION(_utf8'abc');
-> 'utf8_general_ci'
Gibt die Verbindungskennung (Thread-ID) der Verbindung zurück. Jede Verbindung hat eine Kennung, die in der Gesamtzahl der aktuell verbundenen Clients eindeutig ist.
mysql> SELECT CONNECTION_ID();
-> 23786
Gibt die Kombination aus Benutzer- und Hostnamen für das
MySQL-Konto zurück, das der Server zur Authentifizierung
des aktuellen Clients verwendet hat. Dieses Konto bestimmt
Ihre Zugriffsberechtigungen. Innerhalb einer gespeicherten
Routine, die mit dem Merkmal SQL SECURITY
DEFINER
definiert wurde, gibt
CURRENT_USER()
den Ersteller der Routine
zurück. Der Rückgabewert ist ein String im Zeichensatz
utf8
.
Der Wert von CURRENT_USER()
kann sich vom
Wert von USER()
unterscheiden.
mysql>SELECT USER();
-> 'davida@localhost' mysql>SELECT * FROM mysql.user;
ERROR 1044: Access denied for user ''@'localhost' to database 'mysql' mysql>SELECT CURRENT_USER();
-> '@localhost'
Das Beispiel veranschaulicht, dass, obwohl der Client den
Benutzernamen davida
(gemäß dem Wert
der Funktion USER()
) angegeben hat, der
Server den Client unter Verwendung eines anonymen
Benutzerkontos authentifiziert hat. Dies geht aus dem leeren
Benutzernamensteil des
CURRENT_USER()
-Werts hervor. Eine
mögliche Ursache hierfür besteht darin, dass in den
Grant-Tabellen kein Konto davida
aufgeführt ist.
Gibt den Namen der Standarddatenbank (d. h. der aktuellen
Datenbank) als String im Zeichensatz utf8
zurück. Ist keine Standarddatenbank vorhanden, dann gibt
DATABASE()
NULL
zurück. Innerhalb einer gespeicherten Routine ist die
Standarddatenbank diejenige, mit der die Routine assoziiert
ist. Dies muss nicht unbedingt die gleiche Datenbank sein,
die als Standarddatenbank im aufrufenden Kontext verwendet
wird.
mysql> SELECT DATABASE();
-> 'test'
Ist keine Standarddatenbank vorhanden, dann gibt
DATABASE()
NULL
zurück.
Eine SELECT
-Anweisung kann eine
LIMIT
-Klausel enthalten, die die Anzahl
der Datensätze beschränkt, die der Server an den Client
zurückgibt. In manchen Fällen kann es wünschenswert sein,
zu wissen, wie viele Datensätze die Anweisung ohne
LIMIT
-Klausel zurückgegeben hätte, ohne
dass man die Anweisung hierzu erneut ausführen müsste. Um
diese Anzahl zu ermitteln, fügen Sie die Option
SQL_CALC_FOUND_ROWS
in die
SELECT
-Anweisung ein und rufen danach
FOUND_ROWS()
auf:
mysql>SELECT SQL_CALC_FOUND_ROWS * FROM
->tbl_name
WHERE id > 100 LIMIT 10;
mysql>SELECT FOUND_ROWS();
Die zweite SELECT
-Anweisung gibt eine
Zahl zurück, die angibt, wie viele Datensätze die erste
SELECT
-Anweisung zurückgegeben hätte,
wenn die LIMIT
-Klausel nicht enthalten
gewesen wäre. (Wenn die vorangegangene
SELECT
-Anweisung die Option
SQL_CALC_FOUND_ROWS
nicht enthält, dann
gibt FOUND_ROWS()
mit
LIMIT
unter Umständen ein anderes
Ergebnis als ohne.)
Die mit FOUND_ROWS()
ermittelte Anzahl
der Datensätze ist flüchtig und sollte nicht über die der
SELECT SQL_CALC_FOUND_ROWS
-Anweisung
nachfolgende Anweisung hinaus verfügbar bleiben. Wenn Sie
den Wert später noch einmal benötigen sollten, dann
sollten Sie ihn speichern:
mysql>SELECT SQL_CALC_FOUND_ROWS * FROM ... ;
mysql>SET @rows = FOUND_ROWS();
Wenn Sie SELECT SQL_CALC_FOUND_ROWS
verwenden, muss MySQL berechnen, wie viele Datensätze in
der vollständigen Ergebnismenge enthalten sind. Allerdings
ist dies schneller, als die Abfrage ohne
LIMIT
erneut auszuführen, weil die
Ergebnismenge nicht an den Client gesendet werden muss.
SQL_CALC_FOUND_ROWS
und
FOUND_ROWS()
können in Situationen
nützlich sein, in denen Sie die Anzahl der von einer
Abfrage zurückgegebenen Datensätze beschränken, aber auch
die Anzahl der Datensätze im vollständigen Ergebnis
ermitteln wollen, ohne die Abfrage erneut auszuführen. Ein
Beispiel hierfür wäre ein Webskript, das seitenweise eine
Darstellung mit Links auf Seiten anzeigt, die auf andere
Bereiche eines Suchergebnisses verweisen. Mithilfe von
FOUND_ROWS()
können Sie bestimmen, wie
viele andere Seiten für den Rest des Ergebnisses benötigt
werden.
Die Verwendung von SQL_CALC_FOUND_ROWS
und FOUND_ROWS()
ist bei
UNION
-Anweisungen komplexer als bei
einfachen SELECT
-Anweisungen, weil
LIMIT
an mehreren Stellen in einer
UNION
auftreten kann. Es kann auf
einzelne SELECT
-Anweisungen in der
UNION
oder aber global auf das Ergebnis
der UNION
als Ganzes angewendet werden.
Der Zweck von SQL_CALC_FOUND_ROWS
bei
UNION
besteht in der Rückgabe der Anzahl
von Datensätzen, die ohne globale
LIMIT
-Klausel zurückgegeben worden
wäre. Die Benutzung von
SQL_CALC_FOUND_ROWS
mit
UNION
ist folgenden Bedingungen
unterworfen:
Das Schlüsselwort
SQL_CALC_FOUND_ROWS
muss in der
ersten SELECT
-Anweisung der
UNION
auftreten.
Der Wert von FOUND_ROWS()
ist nur
exakt, wenn UNION ALL
verwendet wird.
Wenn UNION
ohne
ALL
verwendet wird, findet eine
Entfernung von Dubletten statt, weswegen der Wert von
FOUND_ROWS()
nur näherungsweise ist.
Wenn LIMIT
nicht in der
UNION
vorhanden ist, wird
SQL_CALC_FOUND_ROWS
ignoriert und
gibt die Anzahl der Reihen in der Temporärtabelle
zurück, die zur Verarbeitung der
UNION
verwendet wird.
LAST_INSERT_ID()
,
LAST_INSERT_ID(
expr
)
Gibt den ersten automatisch erzeugten
Wert zurück, der für eine
AUTO_INCREMENT
-Spalte durch die
aktuelle INSERT
-
oder UPDATE
-Anweisung eingestellt wurde,
die eine solche Spalte modifiziert hat.
mysql> SELECT LAST_INSERT_ID();
-> 195
Die erzeugte Kennung wird auf dem Server
verbindungsspezifisch gehandhabt: Der
von der Funktion an einen bestimmten Client zurückgegebene
Wert ist der erste AUTO_INCREMENT
-Wert,
der für die zuletzt abgesetzte Anweisung, die eine
AUTO_INCREMENT
-Spalte
betraf, von diesem Client erzeugt
wurde. Dieser Wert darf nicht von anderen Clients bearbeitet
werden, auch wenn diese selbst
AUTO_INCREMENT
-Werte erzeugen. Dieses
Verhalten gewährleistet, dass jeder Client seine eigene
Kennung abrufen kann, ohne die Aktivitäten anderer Clients
berücksichtigen oder Sperren setzen bzw. Transaktionen
verwenden zu müssen.
Der Wert von LAST_INSERT_ID()
wird nicht
geändert, wenn Sie die
AUTO_INCREMENT
-Spalte eines Datensatzes
auf einen „nichtmagischen“ Wert (d. h. einen
Wert, der nicht NULL
und nicht
0
ist) setzen.
Wichtig: Wenn Sie mehrere
Datensätze mithilfe einer einzelnen
INSERT
-Anweisung einfügen, gibt
LAST_INSERT_ID()
nur
denjenigen Wert zurück, der für den
ersten eingefügten Datensatz erzeugt
wurde. Grund hierfür ist, dass es möglich sein soll,
dieselbe INSERT
-Anweisung problemlos auf
einem anderen Server zu reproduzieren.
Zum Beispiel:
mysql>USE test;
Database changed mysql>CREATE TABLE t (
->id INT AUTO_INCREMENT NOT NULL PRIMARY KEY,
->name VARCHAR(10) NOT NULL
->);
Query OK, 0 rows affected (0.09 sec) mysql>INSERT INTO t VALUES (NULL, 'Bob');
Query OK, 1 row affected (0.01 sec) mysql>SELECT * FROM t;
+----+------+ | id | name | +----+------+ | 1 | Bob | +----+------+ 1 row in set (0.01 sec) mysql>SELECT LAST_INSERT_ID();
+------------------+ | LAST_INSERT_ID() | +------------------+ | 1 | +------------------+ 1 row in set (0.00 sec) mysql>INSERT INTO t VALUES
->(NULL, 'Mary'), (NULL, 'Jane'), (NULL, 'Lisa');
Query OK, 3 rows affected (0.00 sec) Records: 3 Duplicates: 0 Warnings: 0 mysql> SELECT * FROM t; +----+------+ | id | name | +----+------+ | 1 | Bob | | 2 | Mary | | 3 | Jane | | 4 | Lisa | +----+------+ 4 rows in set (0.01 sec) mysql>SELECT LAST_INSERT_ID();
+------------------+ | LAST_INSERT_ID() | +------------------+ | 2 | +------------------+ 1 row in set (0.00 sec)
Obwohl die zweite INSERT
-Anweisung drei
neue Datensätze in t
eingefügt hat, war
die für den ersten dieser Datensätze erzeugte Kennung
2
, und diesen Wert hat
LAST_INSERT_ID()
auch für die folgende
SELECT
-Anweisung zurückgegeben.
Wenn Sie INSERT IGNORE
verwenden und der
Datensatz ignoriert wird, wird der
AUTO_INCREMENT
-Zähler nicht erhöht, und
LAST_INSERT_ID()
gibt
0
zurück, um anzuzeigen, dass kein
Datensatz eingefügt wurde.
Wenn expr
als Argument für
LAST_INSERT_ID()
angegeben wird, wird der
Wert des Arguments von der Funktion zurückgegeben und als
nächster Wert von LAST_INSERT_ID()
zurückzugebender Wert vermerkt. Dies kann zur Simulierung
von Sequenzen verwendet werden:
Erstellen Sie eine Tabelle zur Aufnahme des Sequenzzählers und initialisieren Sie sie:
mysql>CREATE TABLE sequence (id INT NOT NULL);
mysql>INSERT INTO sequence VALUES (0);
Erstellen Sie mit dieser Tabelle wie folgt Sequenznummern:
mysql>UPDATE sequence SET id=LAST_INSERT_ID(id+1);
mysql>SELECT LAST_INSERT_ID();
Die UPDATE
-Anweisung erhöht den
Sequenzzähler und sorgt dafür, dass der nächste
Aufruf von LAST_INSERT_ID()
den
aktualisierten Wert zurückgibt. Die
SELECT
-Anweisung ruft diesen Wert ab.
Die C-API-Funktion mysql_insert_id()
kann ebenfalls zum Abrufen des Werts verwendet werden.
Siehe auch Abschnitt 24.2.3.36, „mysql_insert_id()
“.
Sie können Sequenzen zwar auch ohne Aufruf von
LAST_INSERT_ID()
erzeugen, aber die
Funktion auf diese Weise zu verwenden hat den Vorteil, dass
der Kennungswert am Server als letzter automatisch erzeugter
Wert vermerkt wird. Dies ist im Multiuser-Betrieb sicher,
weil mehrere Clients die Anweisung UPDATE
absetzen und jeweils einen eigenen Sequenzwert mit der
SELECT
-Anweisung (oder
mysql_insert_id()
) erhalten, ohne andere
Clients, die eigene Sequenzwerte erstellen, zu
beeinträchtigen bzw. von ihnen beeinträchtigt zu werden.
Beachten Sie, dass mysql_insert_id()
erst
nach den INSERT
- und
UPDATE
-Anweisungen aktualisiert wird,
d. h., Sie können die C-API-Funktion nicht zum Abrufen des
Werts von
LAST_INSERT_ID(
verwenden, nachdem andere SQL-Anweisungen wie
expr
)SELECT
oder SET
ausgeführt wurden.
ROW_COUNT()
gibt die Anzahl der von der
vorherigen Anweisung aktualisierten, eingefügten oder
gelöschten Datensätze zurück. Dies entspricht der
Datensatzanzahl, die vom Client mysql
angezeigt wird, und dem Wert der C-API-Funktion
mysql_affected_rows()
.
mysql>INSERT INTO t VALUES(1),(2),(3);
Query OK, 3 rows affected (0.00 sec) Records: 3 Duplicates: 0 Warnings: 0 mysql>SELECT ROW_COUNT();
+-------------+ | ROW_COUNT() | +-------------+ | 3 | +-------------+ 1 row in set (0.00 sec) mysql>DELETE FROM t WHERE i IN(1,2);
Query OK, 2 rows affected (0.00 sec) mysql>SELECT ROW_COUNT();
+-------------+ | ROW_COUNT() | +-------------+ | 2 | +-------------+ 1 row in set (0.00 sec)
Diese Funktion ist synonym zu DATABASE()
.
SESSION_USER()
ist ein Synonym für
USER()
.
SYSTEM_USER()
ist ein Synonym für
USER()
.
Gibt den aktuellen MySQL-Benutzer- und Hostnamen als String
im Zeichensatz utf8
zurück.
mysql> SELECT USER();
-> 'davida@localhost'
Der Wert gibt den Benutzernamen, den Sie beim Herstellen der
Verbindung zum Server eingegeben haben, und den Clienthost
an, über den die Verbindung hergestellt wurde. Der Wert
kann sich von dem von CURRENT_USER()
unterscheiden.
Sie können den Benutzernamensanteil wie folgt extrahieren:
mysql> SELECT SUBSTRING_INDEX(USER(),'@',1);
-> 'davida'
Gibt einen String zurück, der die MySQL Server-Version
angibt. Der String verwendet den Zeichensatz
utf8
.
mysql> SELECT VERSION();
-> '5.1.5-alpha-standard'
Beachten Sie, dass, wenn Ihr Versions-String mit
-log
endet, dies bedeutet, dass das
Loggen aktiviert ist.
Gibt den Standardwert einer Tabellenspalte zurück. Wenn die Spalte keinen Standardwert hat, wird ein Fehler erzeugt.
mysql> UPDATE t SET i = DEFAULT(i)+1 WHERE id < 100;
FORMAT(
X
,D
)
Formatiert die Zahl X
in ein
Format wie '#,###,###.##'
, gerundet auf
D
Dezimalstellen, und gibt das
Ergebnis als String zurück. Detaillierte Informationen
finden Sie in Abschnitt 12.3, „String-Funktionen“.
Versucht eine Sperre mit dem String
str
als Namen zu erwirken.
Hierbei wird ein Zeitüberschreitungswert von
timeout
Sekunden angewendet. Gibt
1
zurück, wenn die Sperrung erfolgreich
war, 0
, wenn es zu einer
Zeitüberschreitung kam (etwa weil zuvor ein anderer Client
den Namen gesperrt hatte), oder NULL
,
wenn ein Fehler aufgetreten ist (z. B. aufgrund von
Speichermangel oder einer Terminierung des Threads mit
mysqladmin kill). Wurde eine Sperre mit
GET_LOCK()
erwirkt, so wird diese wieder
aufgehoben, wenn Sie RELEASE_LOCK()
oder
noch einmal GET_LOCK()
ausführen oder
Ihre Verbindung – gewünscht oder unvorhergesehen –
endet.
Diese Funktion kann zur Implementierung von
Anwendungssperren oder zur Simulation von Datensatzsperren
verwendet werden. Die Namen werden serverweit gesperrt. Wenn
ein Name von einem Client gesperrt wird, blockiert
GET_LOCK()
alle weiteren Anforderungen
von gleichnamigen Sperren durch andere Clients. So wiederum
können Clients, die einem gegebenen Sperrennamen zustimmen,
diesen Namen zur Durchführung kooperativer beratender
Sperrungen verwenden. Sie müssen allerdings beachten, dass
auf diese Weise auch Clients, die nicht zu den
kooperierenden Clients gehören, unbeabsichtigt oder gezielt
einen Namen sperren und so verhindern können, dass ein
kooperierender Client den Namen sperren kann. Sie können
die Wahrscheinlichkeit hierfür verringern, indem Sie
Sperrnamen verwenden, die datenbank- oder
anwendungsspezifisch sind. Verwenden Sie beispielsweise
Sperrnamen der Form db_name.str
oder app_name.str
.
mysql>SELECT GET_LOCK('lock1',10);
-> 1 mysql>SELECT IS_FREE_LOCK('lock2');
-> 1 mysql>SELECT GET_LOCK('lock2',10);
-> 1 mysql>SELECT RELEASE_LOCK('lock2');
-> 1 mysql>SELECT RELEASE_LOCK('lock1');
-> NULL
Der zweite RELEASE_LOCK()
-Aufruf gibt
NULL
zurück, weil die Sperre
'lock1'
automatisch durch den zweiten
GET_LOCK()
-Aufruf aufgehoben wurde.
Hinweis: Wenn ein Client versucht, eine Sperre zu erwirken,
die bereits von einem anderen Client gehalten wird, dann
erfolgt die Sperrung gemäß dem Argument
timeout
. Wird der blockierte
Client beendet, dann wird der Thread erst terminiert, wenn
eine Zeitüberschreitung der Sperranforderung erfolgt.
Dieser Bug ist bekannt.
Wird eine Netzwerkadresse als String in der üblichen Schreibweise (vier punktgetrennte Oktette) übergeben, dann gibt die Funktion einen Integer zurück, der den numerischen Wert der Adresse angibt. Adressen können 4 oder 8 Byte umfassen.
mysql> SELECT INET_ATON('209.207.224.40');
-> 3520061480
Die Zahl wird immer in der Reihenfolge der Netzwerkbytes erzeugt. Beim obigen Beispiel wird sie als 209×2563 + 207×2562 + 224×256 + 40 berechnet.
INET_ATON()
versteht auch IP-Adressen in
der Kurzform:
mysql> SELECT INET_ATON('127.0.0.1'), INET_ATON('127.1');
-> 2130706433, 2130706433
Hinweis: Wenn Sie Werte
speichern, die von INET_ATON()
erzeugt
wurden, empfehlen wir die Verwendung einer INT
UNSIGNED
-Spalte. Wenn Sie eine
(vorzeichenbehaftete) INT
-Spalte
verwenden, können Werte, die IP-Adressen entsprechen, deren
erstes Oktett größer als 127 ist, nicht korrekt
gespeichert werden. Siehe auch
Abschnitt 11.2, „Numerische Datentypen“.
Wenn eine numerische Netzwerkadresse mit einer Länge von 4 oder 8 Byte übergeben wird, gibt die Funktion die punktgetrennte Darstellung der Adresse als String zurück.
mysql> SELECT INET_NTOA(3520061480);
-> '209.207.224.40'
Überprüft, ob die Sperre mit dem Namen
str
frei (d. h. nicht gesperrt)
ist und verwendet werden kann. Gibt 1
zurück, wenn die Sperre verfügbar ist (also von niemandem
benutzt wird), 0
, wenn die Sperre aktiv
ist, und NULL
, wenn ein Fehler
aufgetreten ist (z. B. bei einem falschen Argument).
Überprüft, ob die Sperre mit dem Namen
str
verwendet wird (d. h. nicht
gesperrt ist). Ist dies der Fall, dann wird die
Verbindungskennung des Clients zurückgegeben, der die
Sperre hält. Andernfalls wird NULL
zurückgegeben.
MASTER_POS_WAIT(
log_name
,log_pos
[,timeout
])
Diese Funktion ist praktisch zur Steuerung der
Master/Slave-Synchronisation. Sie blockiert, bis der Slave
alle Änderungen bis zur im Master-Log angegebenen Position
gelesen und übernommen hat. Der Rückgabewert ist die
Anzahl der Logereignisse, auf die der Slave warten musste,
um bis zur angegebenen Position fortschreiten zu können.
Die Funktion gibt NULL
zurück, wenn der
SQL-Slave-Thread nicht gestartet wurde, die Master-Daten des
Slaves nicht initialisiert wurden, die Argumente inkorrekt
sind oder ein Fehler auftritt. -1
wird
bei einer Zeitüberschreitung zurückgegeben. Wenn der
SQL-Slave-Thread endet, während
MASTER_POS_WAIT()
wartet, gibt die
Funktion NULL
zurück. Befindet sich der
Slave bereits jenseits der angegebenen Position, dann
erfolgt die Rückgabe durch die Funktion unmittelbar.
Wenn ein timeout
-Wert angegeben
wird, beendet MASTER_POS_WAIT()
den
Wartevorgang, sobald timeout
Sekunden verstrichen sind.
timeout
muss größer als 0 sein;
ein Nullwert oder ein negativer
timeout
-Wert haben die Bedeutung
„kein timeout
-Wert“.
Gibt den angegebenen Wert zurück. Wenn
NAME_CONST()
zur Erzeugung einer
Ergebnismengenspalte verwendet wird, erhält die Spalte den
angegebenen Namen.
mysql> SELECT NAME_CONST('myname', 14);
+--------+
| myname |
+--------+
| 14 |
+--------+
Die Funktion wurde in MySQL 5.0.12 hinzugefügt und ist nur zur internen Verwendung vorgesehen. Der Server verwendet sie, wenn er Anweisungen aus gespeicherten Routinen schreibt, die Referenzen auf lokale Routinenvariablen haben (siehe Beschreibung in Abschnitt 19.4, „Binärloggen gespeicherter Routinen und Trigger“). Sie sehen die Funktion unter Umständen in der Ausgabe von mysqlbinlog.
Hebt die Sperre namens str
auf,
die mit GET_LOCK()
erwirkt wurde. Gibt
1
zurück, wenn die Sperre aufgehoben
wurde, 0
, wenn die Sperre nicht durch
diesen Thread erwirkt worden war (wobei die Sperre auch
nicht aufgehoben wird), und NULL
, wenn
der Name nicht existiert. Die Sperre existiert nicht, wenn
sie niemals von einem GET_LOCK()
-Aufruf
erwirkt worden war oder zuvor bereits aufgehoben wurde.
Die DO
-Anweisung ist in Kombination mit
RELEASE_LOCK()
sehr praktisch. Siehe auch
Abschnitt 13.2.2, „DO
“.
Setzt eine Unterbrechung mit einer Länge von der durch
duration
angegebenen Anzahl von
Sekunden und gibt dann 0 zurück. Wenn
SLEEP()
unterbrochen wird, wird 1
zurückgegeben. Die Dauer kann einen in Mikrosekunden
angegebenen Bruchteil enthalten.
Gibt eine UUID (Universal Unique Identifier) gemäß „DCE 1.1: Remote Procedure Call“ (Anhang A) der CAE-Spezifikation (Common Applications Environment Specifications), veröffentlicht von The Open Group im Oktober 1997 (Dokument Nr. C706, http://www.opengroup.org/public/pubs/catalog/c706.htm), zurück.
Eine UUID ist eine Zahl, die in Raum und Zeit eindeutig ist.
Bei zwei Aufrufen von UUID()
wird die
Erzeugung zweier vollkommen unterschiedlicher Werte erwartet
– und zwar auch dann, wenn diese beiden Aufrufe auf zwei
separaten Computern erfolgen, die nicht miteinander
verbunden sind.
Die UUID ist eine 128-Bit-Zahl, die durch einen String aus
fünf Hexadezimalzahlen im Format
aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
dargestellt wird:
Die ersten drei Zahlen werden aus einem Zeitstempel erzeugt.
Die vierte Zahl bewahrt die zeitbezogene Eindeutigkeit für den Fall, dass der Zeitstempel seine Monotonie verliert (z. B. aufgrund der Sommerzeit).
Die fünfte Zahl schließlich ist eine IEEE 802-Knotennummer, die die räumliche Eindeutigkeit gewährleistet. Ersatzweise wird eine Zufallszahl eingesetzt, wenn die Knotennummer nicht vorhanden ist (weil der Computer beispielsweise keine Ethernetkarte hat oder wir nicht wissen, wie man die Hardwareadresse einer Schnittstelle unter Ihrem Betriebssystem ermitteln kann). In diesem Fall ist die räumliche Eindeutigkeit nicht garantiert. Nichtsdestoweniger ist eine Kollision sehr unwahrscheinlich.
Derzeit wird die MAC-Adresse einer Schnittstelle nur unter FreeBSD und Linux berücksichtigt. Unter anderen Betriebssystemen verwendet MySQL eine zufällig erzeugte 48-Bit-Zahl.
mysql> SELECT UUID();
-> '6ccd780c-baba-1026-9564-0040f4311e29'
Beachten Sie, dass UUID()
noch nicht in
Verbindung mit der Replikation funktioniert.
In einer INSERT ... ON DUPLICATE KEY
UPDATE
-Anweisung können Sie die Funktion
VALUES(
in der col_name
)UPDATE
-Klausel verwenden, um
Spaltenwerte aus dem INSERT
-Teil der
Anweisung zu referenzieren. Anders gesagt, verweist
VALUES(
in der col_name
)UPDATE
-Klausel auf den Wert von
col_name
, der eingefügt worden
wäre, wäre nicht ein Konflikt aufgrund einer
Schlüsseldublette aufgetreten. Diese Funktion ist
insbesondere bei Einfügevorgängen für mehrere Datensätze
praktisch. Die Funktion VALUES()
ist nur
sinnvoll in INSERT ... ON DUPLICATE KEY
UPDATE
-Anweisungen zu verwenden; andernfalls gibt
sie NULL
zurück.
Abschnitt 13.2.4.3, „INSERT ... ON DUPLICATE KEY UPDATE
“.
mysql>INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)
->ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);
Dieser Abschnitt beschreibt Gruppenfunktionen
(Zusammenfassungsfunktionen), die Wertemengen bearbeiten. Sofern
nicht anders angegeben, ignorieren Gruppenfunktionen
NULL
-Werte.
Wenn Sie eine Gruppenfunktion in einer Anweisung verwenden, die
keine GROUP BY
-Klausel enthält, entspricht
dies der Gruppierung aller Datensätze.
Die Zusammenfassungsfunktionen SUM()
und
AVG()
funktionieren bei Zeitwerten nicht.
(Sie konvertieren die Werte in Zahlen, wodurch alles, was nach
dem ersten nichtnumerischen Zeichen auftaucht, verloren geht.)
Um dieses Problem zu umgehen, können Sie die Werte in
numerische Einheiten konvertieren, dann die
Zusammenfassungsfunktion ausführen und abschließend eine
Rückkonvertierung in den Zeitwert durchführen. Ein paar
Beispiele:
SELECT SEC_TO_TIME(SUM(TIME_TO_SEC(time_col
))) FROMtbl_name
; SELECT FROM_DAYS(SUM(TO_DAYS(date_col
))) FROMtbl_name
;
Gibt den Durchschnittswert von
zurück.
Die Option expr
DISTINCT
kann verwendet
werden, um den Durchschnitt der unterschiedlichen Werte von
expr
zurückzugeben.
AVG()
gibt NULL
zurück, wenn keine passenden Datensätze vorhanden waren.
mysql>SELECT student_name, AVG(test_score)
->FROM student
->GROUP BY student_name;
Gibt das Bit-AND aller Bits in
expr
zurück. Die Berechnung
erfolgt mit 64-Bit-Genauigkeit
(BIGINT
-Genauigkeit).
Die Funktion gibt 18446744073709551615
zurück, wenn keine passenden Datensätze vorhanden waren.
(Dies ist der Wert eines vorzeichenlosen
BIGINT
-Werts, bei dem alle Bits gesetzt
sind.)
Gibt das Bit-OR aller Bits in
expr
zurück. Die Berechnung
erfolgt mit 64-Bit-Genauigkeit
(BIGINT
-Genauigkeit).
Die Funktion gibt 0
zurück, wenn keine
passenden Datensätze vorhanden waren.
Gibt das Bit-XOR aller Bits in
expr
zurück. Die Berechnung
erfolgt mit 64-Bit-Genauigkeit
(BIGINT
-Genauigkeit).
Die Funktion gibt 0
zurück, wenn keine
passenden Datensätze vorhanden waren.
Gibt die Anzahl der Nicht-NULL
-Werte in
den von einer SELECT
-Anweisung
abgerufenen Datensätzen an.
COUNT()
gibt 0
zurück, wenn keine passenden Datensätze vorhanden waren.
mysql>SELECT student.student_name,COUNT(*)
->FROM student,course
->WHERE student.student_id=course.student_id
->GROUP BY student_name;
COUNT(*)
ist dahingehend ein wenig
anders, dass es die Anzahl der abgerufenen Datensätze
unabhängig davon angibt, ob diese
NULL
-Werte enthält oder nicht.
COUNT(*)
ist auf eine sehr schnelle
Rückgabe optimiert, wenn die
SELECT
-Anweisung nur Daten aus einer
Tabelle abruft, andere Spalten nicht abgerufen werden und
keine WHERE
-Klausel vorhanden ist. Zum
Beispiel:
mysql> SELECT COUNT(*) FROM student;
Diese Optimierung gilt nur für
MyISAM
-Tabellen, weil eine exakte
Datensatzanzahl für diese Speicher-Engine gespeichert wird
und so sehr schnell abgerufen werden kann. Bei
transaktionssicheren Speicher-Engines wie
InnoDB
und BDB
ist die
Speicherung einer exakten Datensatzanzahl problematischer,
weil zum gegebenen Zeitpunkt mehrere Transaktionen
stattfinden können, die jede für sich Auswirkungen auf die
Anzahl der Datensätze haben kann.
COUNT(DISTINCT
expr
,[expr
...])
Gibt die Anzahl unterschiedlicher
Nicht-NULL
-Werte zurück.
COUNT(DISTINCT)
gibt 0
zurück, wenn keine passenden Datensätze vorhanden waren.
mysql> SELECT COUNT(DISTINCT results) FROM student;
In MySQL können Sie die Anzahl unterschiedlicher
Ausdruckskombinationen abrufen, die nicht
NULL
enthalten, indem Sie eine Liste mit
Ausdrücken übergeben. In Standard-SQL müssten Sie hierzu
eine Verkettung aller Ausdrücke in COUNT(DISTINCT
...)
angeben.
Diese Funktion gibt einen String als Ergebnis zurück.
Dieser gibt die verketteten
Nicht-NULL
-Werte einer Gruppe zurück.
NULL
wird zurückgegeben, wenn keine
Nicht-NULL
-Werte vorhanden sind. Die
vollständige Syntax sieht wie folgt aus:
GROUP_CONCAT([DISTINCT]expr
[,expr
...] [ORDER BY {unsigned_integer
|col_name
|expr
} [ASC | DESC] [,col_name
...]] [SEPARATORstr_val
])
mysql>SELECT student_name,
->GROUP_CONCAT(test_score)
->FROM student
->GROUP BY student_name;
Oder:
mysql>SELECT student_name,
->GROUP_CONCAT(DISTINCT test_score
->ORDER BY test_score DESC SEPARATOR ' ')
->FROM student
->GROUP BY student_name;
In MySQL können Sie die verketteten Werte von
Ausdruckskombinationen erhalten. Dubletten können Sie
mithilfe von DISTINCT
beseitigen. Wenn
Sie Werte im Ergebnis sortieren wollen, sollten Sie eine
ORDER BY
-Klausel verwenden. Um in
umgekehrter (absteigender) Reihenfolge zu sortieren, fügen
Sie in der ORDER BY
-Klausel das
Schlüsselwort DESC
zum Namen der Spalte
zu, nach der die Sortierung erfolgt: Standardmäßig erfolgt
die Sortierung aufsteigend. Dies kann mit dem Schlüsselwort
ASC
explizit festgelegt werden. Auf
SEPARATOR
folgt der String-Wert, der
zwischen die Ergebniswerte gesetzt werden soll. Der
Vorgabewert ist ein Komma
(‘,
’). Sie können das
Trennzeichen vollständig beseitigen, indem Sie
SEPARATOR ''
angeben.
Sie können mit der Systemvariablen
group_concat_max_len
eine zulässige
Maximallänge angeben. (Der Vorgabewert ist 1024.) Um dies
zur Laufzeit zu machen, verwenden Sie folgende Syntax
(hierbei ist val
ein
vorzeichenloser Integer):
SET [SESSION | GLOBAL] group_concat_max_len = val
;
Wurde eine Maximallänge eingestellt, dann wird das Ergebnis auf diesen Wert gekürzt.
Siehe auch CONCAT()
und
CONCAT_WS()
:
Abschnitt 12.3, „String-Funktionen“.
MIN([DISTINCT]
,
expr
)MAX([DISTINCT]
expr
)
Gibt den Mindest- bzw. den Höchstwert von
expr
zurück.
MIN()
und MAX()
können ein String-Argument entgegennehmen; in diesen
Fällen geben Sie den niedrigsten bzw. höchsten String-Wert
zurück. Siehe auch Abschnitt 7.4.5, „Wie MySQL Indizes benutzt“. Das
Schlüsselwort DISTINCT
können Sie
verwenden, um den kleinsten bzw. größten unterschiedlichen
Wert im Ausdruck expr
zu
ermitteln; allerdings wird hierbei das gleiche Ergebnis wie
beim Weglassen von DISTINCT
erzielt.
MIN()
und MAX()
geben
NULL
zurück, wenn keine passenden
Datensätze vorhanden waren.
mysql>SELECT student_name, MIN(test_score), MAX(test_score)
->FROM student
->GROUP BY student_name;
Bei MIN()
, MAX()
und
anderen Zusammenfassungsfunktionen vergleicht MySQL zurzeit
ENUM
- und SET
-Spalten
nach ihrem String-Wert anstelle der relativen Position des
Strings in der Menge. Dies unterscheidet sich von der von
ORDER BY
verwendeten Vergleichsmethode.
Eine Behebung ist für einen zukünftigen MySQL-Release
vorgesehen.
Gibt die Populationsstandardabweichung von
expr
zurück. Dies stellt eine
Erweiterung des SQL-Standards dar. Die Form
STDDEV()
dieser Funktion ist zum Zweck
der Oracle-Kompatibilität vorhanden. Stattdessen kann die
SQL-Standardfunktion STDDEV_POP()
verwendet werden.
Diese Funktionen geben NULL
zurück, wenn
keine passenden Datensätze vorhanden waren.
Gibt die Populationsstandardabweichung von
expr
(Quadratwurzel von
VAR_POP()
) zurück. Sie können auch
STD()
oder STDDEV()
verwenden, die äquivalent, aber nicht SQL-Standard sind.
STDDEV_POP()
gibt NULL
zurück, wenn keine passenden Datensätze vorhanden waren.
Gibt die Beispielstandardabweichung von
expr
(Quadratwurzel von
VAR_SAMP()
) zurück.
STDDEV_SAMP()
gibt
NULL
zurück, wenn keine passenden
Datensätze vorhanden waren.
Gibt die Summe von expr
zurück.
Wenn die Rückgabemenge keine Datensätze enthält, gibt
SUM()
NULL
zurück.
Das Schlüsselwort DISTINCT
kann in MySQL
5.1 benutzt werden, um nur die Summe
unterschiedlicher Werte in expr
zu bilden.
SUM()
gibt NULL
zurück, wenn keine passenden Datensätze vorhanden waren.
Gibt die Populationsstandardvarianz von
expr
zurück. Hierbei werden
Datensätze als gesamte Population und nicht als Beispiel
betrachtet, d. h., die Anzahl der Datensätze ist der
Nenner. Sie können auch VARIANCE()
verwenden, das äquivalent, aber nicht SQL-Standard ist.
VAR_POP()
gibt NULL
zurück, wenn keine passenden Datensätze vorhanden waren.
Gibt die Beispielvarianz von expr
zurück. Hieraus ergibt sich, dass der Nenner die Anzahl der
Datensätze minus 1 ist.
VAR_SAMP()
gibt NULL
zurück, wenn keine passenden Datensätze vorhanden waren.
Gibt die Populationsstandardvarianz von
expr
zurück. Dies stellt eine
Erweiterung des SQL-Standards dar. Stattdessen kann die
SQL-Standardfunktion VAR_POP()
verwendet
werden.
VARIANCE()
gibt NULL
zurück, wenn keine passenden Datensätze vorhanden waren.
Die GROUP BY
-Klausel gestattet die Verwendung
eines Modifizierers WITH ROLLUP
, der bewirkt,
dass zusätzliche Datensätze zur zusammenfassenden Ausgabe
hinzugefügt werden. Diese Datensätze stellen
Zusammenfassungsoperationen einer höherer Ebene (so genannte
Superaggregate) dar. ROLLUP
gestattet Ihnen
auf diese Weise die Beantwortung von Fragen auf mehreren
Analyseebenen mit einer einzelnen Abfrage. Es kann
beispielsweise verwendet werden, um eine OLAP-Unterstützung
(Online Analytical Processing) zu implementieren.
Nehmen wir an, dass in einer Tabelle namens
sales
die Spalten year
,
country
, product
und
profit
zur Aufzeichnung der
Vertriebsrentabilität vorhanden wären:
CREATE TABLE sales ( year INT NOT NULL, country VARCHAR(20) NOT NULL, product VARCHAR(32) NOT NULL, profit INT );
Der Inhalt der Tabelle kann jahresbezogen wie folgt mit einer
einfachen GROUP BY
-Abfrage zusammengefasst
werden:
mysql> SELECT year, SUM(profit) FROM sales GROUP BY year;
+------+-------------+
| year | SUM(profit) |
+------+-------------+
| 2000 | 4525 |
| 2001 | 3010 |
+------+-------------+
Die Ausgabe zeigt die Gesamtrendite pro Jahr an. Wenn Sie aber auch die Rendite für den Gesamtzeitraum bestimmen wollen, müssen Sie die einzelnen Werte selbst hinzufügen oder eine zusätzliche Abfrage ausführen.
Alternativ verwenden Sie ROLLUP
, wodurch sich
die beiden Analyseebenen in einer Abfrage zusammenfassen lassen.
Das Hinzufügen eines WITH
ROLLUP
-Modifizierers zur GROUP
BY
-Klausel bewirkt, dass die Abfrage einen anderen
Datensatz erstellt, der die Endsumme über alle vier Jahre
angibt:
mysql> SELECT year, SUM(profit) FROM sales GROUP BY year WITH ROLLUP;
+------+-------------+
| year | SUM(profit) |
+------+-------------+
| 2000 | 4525 |
| 2001 | 3010 |
| NULL | 7535 |
+------+-------------+
Die Super-Aggregat-Zeile, die die Endsumme zusammenfasst, lässt
sich am Wert NULL
in der Spalte
year
erkennen.
Die Wirkung von ROLLUP
ist etwas komplexer,
wenn mehrere GROUP BY
-Klauseln vorhanden
sind. In diesem Fall erzeugt die Abfrage jedes Mal, wenn eine
„Unterbrechung“ (also eine Wertänderung) in einer
beliebigen Spalte (mit Ausnahme der letzten Gruppenspalte)
vorhanden ist, einen Super-Aggregat-Datensatz.
So könnte etwa ohne ROLLUP
eine
Zusammenfassung der Tabelle sales
basierend
auf year
, country
und
product
wie folgt aussehen:
mysql>SELECT year, country, product, SUM(profit)
->FROM sales
->GROUP BY year, country, product;
+------+---------+------------+-------------+ | year | country | product | SUM(profit) | +------+---------+------------+-------------+ | 2000 | Finland | Computer | 1500 | | 2000 | Finland | Phone | 100 | | 2000 | India | Calculator | 150 | | 2000 | India | Computer | 1200 | | 2000 | USA | Calculator | 75 | | 2000 | USA | Computer | 1500 | | 2001 | Finland | Phone | 10 | | 2001 | USA | Calculator | 50 | | 2001 | USA | Computer | 2700 | | 2001 | USA | TV | 250 | +------+---------+------------+-------------+
Die Ausgabe zeigt Zusammenfassungswerte nur auf der Jahres-,
Länder- und/oder Produktebene der Analyse an. Wird nun
ROLLUP
hinzugefügt, dann erzeugt die Abfrage
diverse zusätzliche Datensätze:
mysql>SELECT year, country, product, SUM(profit)
->FROM sales
->GROUP BY year, country, product WITH ROLLUP;
+------+---------+------------+-------------+ | year | country | product | SUM(profit) | +------+---------+------------+-------------+ | 2000 | Finland | Computer | 1500 | | 2000 | Finland | Phone | 100 | | 2000 | Finland | NULL | 1600 | | 2000 | India | Calculator | 150 | | 2000 | India | Computer | 1200 | | 2000 | India | NULL | 1350 | | 2000 | USA | Calculator | 75 | | 2000 | USA | Computer | 1500 | | 2000 | USA | NULL | 1575 | | 2000 | NULL | NULL | 4525 | | 2001 | Finland | Phone | 10 | | 2001 | Finland | NULL | 10 | | 2001 | USA | Calculator | 50 | | 2001 | USA | Computer | 2700 | | 2001 | USA | TV | 250 | | 2001 | USA | NULL | 3000 | | 2001 | NULL | NULL | 3010 | | NULL | NULL | NULL | 7535 | +------+---------+------------+-------------+
Bei dieser Abfrage bewirkt das Hinzufügen von
ROLLUP
, dass die Ausgabe
Zusammenfassungsinformationen auf vier Analyseebenen (und nicht
nur auf einer) enthält. Die Ausgabe von
ROLLUP
interpretieren Sie wie folgt:
Auf jede Menge von Produktdatensätzen für ein gegebenes
Jahr und Land folgend wird ein zusätzlicher Datensatz
erzeugt, der die Gesamtzahl aller Produkte angibt. Bei
diesen Datensätzen ist die Spalte
product
auf NULL
gesetzt.
Auf jede Menge von Datensätzen für ein gegebenes Jahr und
Land folgend wird ein zusätzlicher Datensatz erzeugt, der
die Endsumme für alle Länder und Produkte angibt. Bei
diesen Datensätzen sind die Spalten
country
und products
auf NULL
gesetzt.
Abschließend wird auf alle anderen Datensätze folgend ein
zusätzlicher zusammenfassender Datensatz erzeugt, der die
Endsumme für alle Jahre, Länder und Produkte angibt. Bei
diesem Datensatz sind die Spalten year
,
country
und products
auf NULL
gesetzt.
Weitere Aspekte der Benutzung von
ROLLUP
Die folgenden Punkte beschreiben einige für die
MySQL-Implementierung von ROLLUP
spezifischen
Verhaltensweisen:
Wenn Sie ROLLUP
verwenden, dürfen Sie nicht
gleichzeitig auch eine ORDER BY
-Klausel zur
Sortierung der Ergebnisse einsetzen. Mit anderen Worten,
ROLLUP
und ORDER BY
schließen sich gegenseitig aus. Trotzdem können Sie Einfluss
auf die Sortierreihenfolge nehmen. GROUP BY
sortiert in MySQL Ergebnisse, und Sie können die
Schlüsselwörter ASC
und
DESC
ausdrücklich für Spaltennamen in der
GROUP BY
-Liste angeben, um die Sortierfolge
für einzelne Spalten zu spezifizieren. (Die von
ROLLUP
hinzugefügten
Zusammenfassungsdatensätze höherer Ebene erscheinen ungeachtet
der Sortierfolge trotzdem erst hinter den Datensätzen, aus
denen sie berechnet wurden.)
Mit LIMIT
können Sie die Anzahl der an den
Client zurückgegebenen Datensätze beschränken.
LIMIT
wird nach ROLLUP
angewendet, d. h., die Beschränkung betrifft auch die
zusätzlichen Datensätze, die von ROLLUP
hinzugefügt worden sind. Zum Beispiel:
mysql>SELECT year, country, product, SUM(profit)
->FROM sales
->GROUP BY year, country, product WITH ROLLUP
->LIMIT 5;
+------+---------+------------+-------------+ | year | country | product | SUM(profit) | +------+---------+------------+-------------+ | 2000 | Finland | Computer | 1500 | | 2000 | Finland | Phone | 100 | | 2000 | Finland | NULL | 1600 | | 2000 | India | Calculator | 150 | | 2000 | India | Computer | 1200 | +------+---------+------------+-------------+
Die Verwendung von LIMIT
mit
ROLLUP
kann Ergebnisse erzeugen, die
schwieriger zu interpretieren sind, weil Sie weniger Kontext
haben, um die Super-Aggregate zu verstehen.
Die NULL
-Indikatoren in jedem
Super-Aggregat-Datensatz werden erzeugt, wenn der Datensatz an
den Client gesendet wird. Der Server prüft alle in der
GROUP BY
-Klausel genannten Spalten, die auf
die erste (am weitesten links stehende) Spalte folgen, deren
Wert geändert wurde. Bei jeder Spalte in der Ergebnismenge,
deren Name lexikalisch mit einem dieser Namen übereinstimmt,
wird der Wert auf NULL
gesetzt. (Wenn Sie
Gruppenspalten über die Spaltennummer angeben, identifiziert
der Server die auf NULL
zu setzenden Spalten
anhand ihrer Nummer.)
Weil die NULL
-Werte in den
Super-Aggregat-Datensätzen als solche während der
Abfrageverarbeitung relativ spät in das Ergebnis eingefügt
werden, können Sie sie nicht wie NULL
-Werte
innerhalb der Abfrage selbst überprüfen. So können Sie
beispielsweise HAVING product IS NULL
nicht
zur Abfrage hinzufügen, um alle Datensätze mit Ausnahme der
Super-Aggregat-Datensätze aus der Ausgabe zu entfernen.
Andererseits erscheinen die NULL
-Werte als
NULL
auf der Clientseite und können insofern
mithilfe einer beliebigen MySQL-Clientprogrammierschnittstelle
geprüft werden.
MySQL erweitert die Verwendung von GROUP BY
dahingehend, dass Sie Spalten oder Berechnungen in der
SELECT
-Liste verwenden können, die nicht in
der GROUP BY
-Klausel erscheinen. Dies steht
für „ein beliebiger Wert für diese Gruppe“. Sie
können die Leistung dadurch optimieren, dass Sie das Sortieren
und Gruppieren unnötiger Elemente umgehen. So müssen Sie
beispielsweise in der folgenden Abfrage keine Gruppierung von
customer.name
durchführen:
SELECT order.custid, customer.name, MAX(payments) FROM order,customer WHERE order.custid = customer.custid GROUP BY order.custid;
In Standard-SQL hätten Sie hier
customer.name
zur GROUP
BY
-Klausel hinzufügen müssen. In MySQL ist der Name
redundant, wenn bei der Ausführung der SQL-Modus
ONLY_FULL_GROUP_BY
nicht aktiviert ist.
Verwenden Sie diese Funktion nicht, wenn
die Spalten, die Sie im GROUP BY
-Anteil
weglassen, in der Gruppe nicht eindeutig sind! Sie erhalten
ansonsten nicht vorhersehbare Ergebnisse.
In manchen Fällen können Sie mit MIN()
und
MAX()
einen bestimmten Spaltenwert auch dann
erhalten, wenn dieser nicht eindeutig ist. Folgendes übergibt
den Wert von column
aus dem Datensatz, der
den niedrigsten Wert in der Spalte sort
hat:
SUBSTR(MIN(CONCAT(RPAD(sort,6,' '),column)),7)
Siehe auch Abschnitt 3.6.4, „Die Zeilen, die das gruppenweise Maximum eines bestimmten Felds enthalten“.
Beachten Sie, dass Sie, wenn Sie sich an den SQL-Standard halten
wollen, Ausdrücke nicht in GROUP BY
-Klauseln
verwenden dürfen. Sie können diese Einschränkung umgehen,
indem Sie ein Alias für den Ausdruck verwenden:
SELECT id,FLOOR(value/100) AS val
FROM tbl_name
GROUP BY id, val;
MySQL gestattet hingegen die Benutzung von Ausdrücken in
GROUP BY
-Klauseln. Zum Beispiel:
SELECT id,FLOOR(value/100)
FROM tbl_name
GROUP BY id, FLOOR(value/100);
Inhaltsverzeichnis
CREATE
, DROP
,
ALTER
SELECT
, INSERT
,
UPDATE
, DELETE
Dieses Kapitel beschreibt die Syntax für die meisten von MySQL unterstützten SQL-Anweisungen. Weitere Beschreibungen zu Anweisungen finden Sie in den folgenden Kapiteln:
Kapitel 7, Optimierung, beschreibt die
EXPLAIN
-Anweisung.
Kapitel 19, Gespeicherte Prozeduren und Funktionen, behandelt Anweisungen zum Schreiben gespeicherter Routinen.
Kapitel 20, Trigger, behandelt Anweisungen zum Schreiben von Triggern.
Kapitel 21, Views, behandelt View-spezifische Anweisungen.
ALTER {DATABASE | SCHEMA} [db_name
]alter_specification
[,alter_specification
] ...alter_specification
: [DEFAULT] CHARACTER SETcharset_name
| [DEFAULT] COLLATEcollation_name
Mit ALTER DATABASE
können Sie die
grundlegenden Eigenschaften einer Datenbank ändern. Diese
Eigenschaften sind in der Datei db.opt
im
Datenbankverzeichnis gespeichert. Um ALTER
DATABASE
verwenden zu können, benötigen Sie die
Berechtigung ALTER
für die Datenbank.
ALTER SCHEMA
ist ein Synonym für
ALTER DATABASE
.
Die Klausel CHARACTER SET
ändert den
Standardzeichensatz der Datenbank. Die Klausel
COLLATE
ändert die Standardsortierfolge der
Datenbank. Kapitel 10, Zeichensatz-Unterstützung, behandelt Namen von
Zeichensätzen und Sortierfolgen.
Der Datenbankname kann weggelassen werden. In diesem Fall bezieht sich die Anweisung auf die Standarddatenbank.
ALTER [IGNORE] TABLEtbl_name
alter_specification
[,alter_specification
] ...alter_specification
: ADD [COLUMN]column_definition
[FIRST | AFTERcol_name
] | ADD [COLUMN] (column_definition
,...) | ADD INDEX [index_name
] [index_type
] (index_col_name
,...) | ADD [CONSTRAINT [symbol
]] PRIMARY KEY [index_type
] (index_col_name
,...) | ADD [CONSTRAINT [symbol
]] UNIQUE [INDEX] [index_name
] [index_type
] (index_col_name
,...) | ADD FULLTEXT [INDEX] [index_name
] (index_col_name
,...) [WITH PARSERparser_name
] | ADD SPATIAL [INDEX] [index_name
] (index_col_name
,...) | ADD [CONSTRAINT [symbol
]] FOREIGN KEY [index_name
] (index_col_name
,...) [reference_definition
] | ALTER [COLUMN]col_name
{SET DEFAULTliteral
| DROP DEFAULT} | CHANGE [COLUMN]old_col_name
column_definition
[FIRST|AFTERcol_name
] | MODIFY [COLUMN]column_definition
[FIRST | AFTERcol_name
] | DROP [COLUMN]col_name
| DROP PRIMARY KEY | DROP INDEXindex_name
| DROP FOREIGN KEYfk_symbol
| DISABLE KEYS | ENABLE KEYS | RENAME [TO]new_tbl_name
| ORDER BYcol_name
| CONVERT TO CHARACTER SETcharset_name
[COLLATEcollation_name
] | [DEFAULT] CHARACTER SETcharset_name
[COLLATEcollation_name
] | DISCARD TABLESPACE | IMPORT TABLESPACE |table_options
|partition_options
| ADD PARTITIONpartition_definition
| DROP PARTITIONpartition_names
| COALESCE PARTITIONnumber
| REORGANIZE PARTITIONpartition_names
INTO (partition_definitions
) | ANALYZE PARTITIONpartition_names
| CHECK PARTITIONpartition_names
| OPTIMIZE PARTITIONpartition_names
| REBUILD PARTITIONpartition_names
| REPAIR PARTITIONpartition_names
ALTER TABLE
ermöglicht Ihnen das Ändern der
Struktur einer vorhandenen Tabelle. Sie können beispielsweise
Spalten hinzufügen oder entfernen, Indizes erstellen oder
löschen, den Typ einer vorhandenen Spalte ändern oder Spalten
oder die Tabelle umbenennen. Ferner können Sie den Kommentar
für die Tabelle und auch den Tabellentyp modifizieren.
Die Syntax für viele der zulässigen Änderungen ähnelt
Klauseln der CREATE TABLE
-Anweisung. Hierzu
gehören table_options
-Modifikationen
für Optionen wie ENGINE
,
AUTO_INCREMENT
und
AVG_ROW_LENGTH
. (Allerdings ignoriert
ALTER TABLE
die Tabellenoptionen
DATA DIRECTORY
und INDEX
DIRECTORY
.) Abschnitt 13.1.5, „CREATE TABLE
“, listet
alle Tabellenoptionen auf.
Bei manchen Operationen kann eine Warnung erzeugt werden, wenn
diese auf eine Tabelle angewendet werden sollen, deren
Speicher-Engine die Operation nicht unterstützt. Diese
Warnungen lassen sich mit SHOW WARNINGS
anzeigen. Siehe auch Abschnitt 13.5.4.25, „SHOW WARNINGS
“.
ALTER TABLE
erstellt zunächst eine
temporäre Kopie der Ursprungstabelle. Die Änderung wird dann
an der Kopie vorgenommen, und schließlich wird die
Originaltabelle gelöscht und die Kopie entsprechend umbenannt.
Während der Ausführung von ALTER TABLE
kann
die Originaltabelle von anderen Clients gelesen werden.
Änderungs- und Schreiboperationen in der Tabelle werden
blockiert, bis die neue Tabelle bereit ist, und dann automatisch
in die neue Tabelle umgeleitet. Aktualisierungen schlagen nicht
fehl.
Beachten Sie, dass, wenn Sie eine andere ALTER
TABLE
-Option als RENAME
verwenden,
MySQL immer eine Temporärtabelle erstellt – und zwar auch
dann, wenn die Daten strenggenommen nicht kopiert werden
müssten (z. B. wenn Sie nur den Namen einer Spalte ändern).
Bei MyISAM
-Tabellen ist die Neuerstellung des
Indexes der zeitaufwändigste Teil des Änderungsvorgangs. Sie
können diesen beschleunigen, indem Sie die Systemvariable
myisam_sort_buffer_size
auf einen hohen Wert
setzen.
Um ALTER TABLE
zu verwenden, benötigen
Sie die Berechtigungen ALTER
,
INSERT
und CREATE
für
die Tabelle.
IGNORE
ist eine MySQL-Erweiterung zum
SQL-Standard. Sie steuert, wie ALTER
TABLE
funktioniert, wenn Dubletten eindeutiger
Schlüssel in der neuen Tabelle vorhanden sind oder (bei
aktiviertem striktem Modus) Warnungen auftreten. Wenn
IGNORE
nicht angegeben ist, wird der
Vorgang bei Auftreten von Schlüsseldubletten abgebrochen,
und ein Rollback wird durchgeführt. Ist
IGNORE
angegeben, dann wird nur der erste
von mehreren Datensätzen mit Dubletten eindeutiger
Schlüssel verwendet. Die übrigen betroffenen Datensätze
werden gelöscht. Falsche Werte werden auf den
nächstliegenden zulässigen Wert gesetzt.
Sie können mehrere ADD
-,
ALTER
-, DROP
- und
CHANGE
-Klauseln in einer ALTER
TABLE
-Anweisung angeben. Diese werden durch
Kommata getrennt. Dies ist eine MySQL-Erweiterung zum
SQL-Standard, der nur jeweils eine dieser Klauseln je
ALTER TABLE
-Anweisung zulässt. Um
beispielsweise mehrere Spalten mit einer einzelnen Anweisung
zu löschen, tun Sie Folgendes:
ALTER TABLE t2 DROP COLUMN c, DROP COLUMN d;
CHANGE
, col_name
DROP
und
col_name
DROP INDEX
sind MySQL-Erweiterungen zum
SQL-Standard.
MODIFY
ist eine Oracle-Erweiterung zu
ALTER TABLE
.
Das Wort COLUMN
ist optional und darf
weggelassen werden.
Wenn Sie ALTER TABLE
ohne
zusätzliche Optionen sehen, benennt MySQL alle Dateien, die
der Tabelle tbl_name
RENAME TO
new_tbl_name
tbl_name
entsprechen,
einfach um. Es ist nicht notwendig, eine Temporärtabelle zu
erstellen. (Sie können zum Umbenennen von Tabellen auch die
Anweisung RENAME TABLE
verwenden. Siehe
auch Abschnitt 13.1.9, „RENAME TABLE
“.)
column_definition
-Klauseln
verwenden dieselbe Syntax für ADD
und
CHANGE
wie bei CREATE
TABLE
. Beachten Sie, dass diese Syntax den
Spaltennamen (und nicht nur den Datentyp) enthält. Siehe
auch Abschnitt 13.1.5, „CREATE TABLE
“.
Sie können eine Spalte mithilfe einer CHANGE
-Klausel
umbenennen. Zu diesem Zweck geben Sie den alten und den
neuen Spaltennamen sowie den Typ an, den die Spalte zurzeit
hat. Um beispielsweise eine
old_col_name
column_definition
INTEGER
-Spalte von a
zu b
umzubenennen, geben Sie Folgendes
ein:
ALTER TABLE t1 CHANGE a b INTEGER;
Wenn Sie den Typ einer Spalte, nicht aber ihren Namen
ändern wollen, erfordert die
CHANGE
-Syntax trotzdem einen alten und
neuen Spaltennamen, auch wenn diese dann identisch sind. Zum
Beispiel:
ALTER TABLE t1 CHANGE b b BIGINT NOT NULL;
Sie können den Spaltentyp auch mit
MODIFY
ändern, ohne die Spalte
umzubenennen:
ALTER TABLE t1 MODIFY b BIGINT NOT NULL;
Wenn Sie CHANGE
oder
MODIFY
zum Kürzen einer Spalte
verwenden, für die ein Index vorhanden ist, und die Länge
der Spalte nach der Operation geringer ist als die
Indexlänge, dann kürzt MySQL den Index automatisch.
Ändern Sie einen Datentyp mit CHANGE
oder MODIFY
, dann versucht MySQL,
vorhandene Spaltenwerte bestmöglich in den neuen Typ zu
konvertieren.
Um eine Spalte an eine bestimmte Position in einer
Tabellenzeile hinzuzufügen, verwenden Sie
FIRST
oder AFTER
.
Standardmäßig werden neue Spalten am Ende eingefügt. Sie
können col_name
FIRST
und
AFTER
auch bei CHANGE
-
oder MODIFY
-Operationen verwenden.
ALTER ... SET DEFAULT
oder ALTER
... DROP DEFAULT
geben einen neuen Vorgabewert
für eine Spalte an bzw. entfernen den vorhandenen
Vorgabewert. Wenn die alte Vorgabe entfernt wird und die
Spalte NULL
werden kann, dann wird
NULL
zum neuen Vorgabewert. Kann die
Spalte nicht NULL
werden, dann weist
MySQL einen Standardwert zu (siehe auch
Abschnitt 11.1.4, „Vorgabewerte von Datentypen“).
DROP INDEX
entfernt einen Index. Dies ist
eine MySQL-Erweiterung zum SQL-Standard. Siehe auch
Abschnitt 13.1.7, „DROP INDEX
“.
Wenn Spalten aus einer Tabelle entfernt werden, werden die Spalten auch aus allen Indizes gelöscht, deren Bestandteil sie sind. Wenn alle Spalten, die einen Index bilden, gelöscht wurden, dann wird auch der Index gelöscht.
Enthält eine Tabelle nur eine Spalte, dann kann diese nicht
gelöscht werden. Zur Entfernung der Tabelle verwenden Sie
stattdessen DROP TABLE
.
DROP PRIMARY KEY
löscht den
Primärschlüssel. Hinweis: Bei
älteren MySQL-Versionen löscht DROP PRIMARY
KEY
, wenn kein Primärindex vorhanden ist, den
ersten eindeutigen Index in der Tabelle. Dies trifft bei
MySQL 5.1 nicht mehr zu: Wenn Sie hier
DROP PRIMARY KEY
auf eine Tabelle ohne
Primärschlüssel anzuwenden versuchen, erhalten Sie einen
Fehler.
Wenn Sie einer Tabelle mit UNIQUE INDEX
oder PRIMARY KEY
einen eindeutigen Index
bzw. einen Primärschlüssel hinzufügen, wird dieser vor
jedem nichteindeutigen Index gespeichert, sodass MySQL
Schlüsseldubletten schnellstmöglich erkennt.
ORDER BY
erlaubt Ihnen die Erstellung
einer neuen Tabelle mit allen Datensätzen in einer
bestimmten Reihenfolge. Beachten Sie, dass diese Reihenfolge
nach Einfüge- und Löschoperationen nicht aufrechterhalten
wird. Diese Option ist in erster Linie nützlich, wenn Sie
wissen, dass die Datensätze meistens in einer bestimmten
Reihenfolge abgefragt werden. Wenn Sie diese Option nach
umfangreicheren Änderungen in der Tabelle verwenden,
können Sie die Leistung unter Umständen steigern. In
bestimmten Fällen kann es MySQL das Sortieren erleichtern,
wenn die Tabelle in der Reihenfolge der Spalte angeordnet
ist, nach der Sie sie später auch sortieren wollen.
Wenn Sie ALTER TABLE
auf eine
MyISAM
-Tabelle anwenden, werden alle
nichteindeutigen Indizes in einer separaten Stapeloperation
erstellt (wie bei REPAIR TABLE
). Dies
sollte ALTER TABLE
erheblich
beschleunigen, wenn Sie viele Indizes haben.
Die Funktion lässt sich explizit aktivieren. ALTER
TABLE ... DISABLE KEYS
weist MySQL an, die
Aktualisierung nichteindeutiger Indizes für eine
MyISAM
-Tabelle zu beenden. Danach sollte
ALTER TABLE ... ENABLE KEYS
verwendet
werden, um die fehlenden Indizes neu zu erstellen. MySQL tut
dies mit einem speziellen Algorithmus, der wesentlich
schneller ist als das aufeinander folgende Einfügen von
Schlüsseln. Insofern sollte die Deaktivierung von
Schlüsseln vor umfangreichen Einfügeoperationen diese
erheblich beschleunigen. Die Verwendung von ALTER
TABLE ... DISABLE KEYS
erfordert neben den bereits
genannten Berechtigungen auch die Berechtigung
INDEX
.
Die Klauseln FOREIGN KEY
und
REFERENCES
werden von der
InnoDB
-Speicher-Engine unterstützt, die
ADD [CONSTRAINT
[
implementiert. Siehe auch
Abschnitt 14.2.6.4, „Fremdschlüssel-Beschränkungen“. Von
anderen Speicher-Engines werden die Klauseln zwar erkannt,
aber ignoriert. Zudem wird die Klausel
symbol
]] FOREIGN KEY (...)
REFERENCES ... (...)CHECK
von allen Speicher-Engines erkannt,
aber ignoriert. Siehe auch Abschnitt 13.1.5, „CREATE TABLE
“.
Diese Verhaltensweise – das Erkennen und nachfolgende
Ignorieren von Syntaxklauseln – ist aus
Kompatibilitätsgründen vorhanden. Sie erleichtert die
Portierung von Codes anderer SQL-Server und die Ausführung
von Anwendungen, die Tabellen mit Referenzen erstellen.
Siehe auch Abschnitt 1.9.5, „MySQL: Unterschiede im Vergleich zu ANSI SQL92“.
In separaten Klauseln derselben ALTER
TABLE
-Anweisung können Sie keinen Fremdschlüssel
hinzufügen und einen Fremdschlüssel löschen. Sie müssen
hierzu separate Anweisungen verwenden.
InnoDB
unterstützt die Verwendung von
ALTER TABLE
zum Löschen von
Fremdschlüsseln:
ALTER TABLEtbl_name
DROP FOREIGN KEYfk_symbol
;
In separaten Klauseln derselben ALTER
TABLE
-Anweisung können Sie keinen Fremdschlüssel
hinzufügen und einen Fremdschlüssel löschen. Sie müssen
hierzu separate Anweisungen verwenden.
Weitere Informationen finden Sie unter Abschnitt 14.2.6.4, „Fremdschlüssel-Beschränkungen“.
Wenn Sie den Standardzeichensatz einer Tabelle und den
Zeichensatz aller Zeichenspalten (CHAR
,
VARCHAR
, TEXT
) auf
einen neuen Zeichensatz umstellen wollen, verwenden Sie eine
Anweisung wie die folgende:
ALTER TABLEtbl_name
CONVERT TO CHARACTER SETcharset_name
;
Warnung: Die obige
Operation wandelt Spaltenwerte zwischen Zeichensätzen um.
Sie sollten dies keinesfalls tun, wenn
Sie eine Spalte in einem Zeichensatz (z. B.
latin1
) haben, die gespeicherten Werte
aber eigentlich einen anderen inkompatiblen Zeichensatz (wie
utf8
) verwenden. In diesem Fall müssen
Sie bei solchen Spalten Folgendes tun:
ALTER TABLE t1 CHANGE c1 c1 BLOB; ALTER TABLE t1 CHANGE c1 c1 TEXT CHARACTER SET utf8;
Der Grund, warum dies funktioniert, ist, dass, wenn Sie von
oder in BLOB
-Spalten konvertieren, keine
Konvertierung stattfindet.
Wenn Sie CONVERT TO CHARACTER SET binary
angeben, werden die CHAR
-,
VARCHAR
- und
TEXT
-Spalten in ihre entsprechenden
binären String-Typen umgewandelt
(BINARY
, VARBINARY
,
BLOB
). Das bedeutet, dass die Spalten
keinen Zeichensatz mehr haben; eine nachfolgende
CONVERT TO
-Operation hat also keine
Auswirkungen mehr.
Um nur den Standardzeichensatz einer Tabelle zu ändern, verwenden Sie folgende Anweisung:
ALTER TABLEtbl_name
DEFAULT CHARACTER SETcharset_name
;
Das Wort DEFAULT
ist optional. Der
Standardzeichensatz ist der Zeichensatz, der verwendet wird,
wenn Sie den Zeichensatz für eine neue Spalte, die Sie
(etwa mit ALTER TABLE ... ADD column
) zu
einer Tabelle hinzufügen, nicht explizit angegeben haben.
Bei einer InnoDB
-Tabelle, die mit einem
eigenen Tablespace in einer .ibd
-Datei
erstellt wurde, kann diese Datei verworfen und importiert
werden. Mit folgender Anweisung können Sie die
.ibd
-Datei verwerfen:
ALTER TABLE tbl_name
DISCARD TABLESPACE;
Hierbei wird die aktuelle .ibd
-Datei
gelöscht, d. h., Sie sollten zuerst ein Backup erstellt
haben. Der Versuch des Zugriffs auf die Tabelle, während
die Tablespace-Datei verworfen wird, führt zu einem Fehler.
Um die .ibd
-Sicherungsdatei in die
Tabelle zurückzuimportieren, kopieren Sie sie ins
Datenbankverzeichnis und setzen dann folgende Anweisung ab:
ALTER TABLE tbl_name
IMPORT TABLESPACE;
Siehe auch Abschnitt 14.2.3.1, „Verwendung von Tabellen-Tablespaces (ein Tablespace pro Tabelle)“.
ALTER TABLE
kann auch bei partitionierten
Tabellen verwendet werden, um Partitionen hinzuzufügen, zu
löschen, zu verbinden oder aufzutrennen. Auch die
Partitionierungswartung ist hiermit möglich.
Die einfache Angabe einer
partition_options
-Klausel zu
ALTER TABLE
für eine partitionierte
Tabelle partitioniert diese entsprechend dem
Partitionierungsschema neu, welches über die
partition_options
angegeben
wurde. Diese Klausel beginnt immer mit PARTITION
BY
und verwendet ansonsten dieselbe Syntax und die
Regeln, die auch auf die
partition_options
-Klausel für
CREATE TABLE
zutreffen. (Weitere
Informationen finden Sie in Abschnitt 13.1.5, „CREATE TABLE
“).
Hinweis: Diese Syntax wird
derzeit vom MySQL 5.1 Server akzeptiert, tut aber eigentlich
noch gar nichts. Wir erwarten die Implementierung im Zuge
der Fortentwicklung von MySQL 5.1.
Die partition_definition
-Klausel
für ALTER TABLE ADD PARTITION
unterstützt dieselben Optionen wie die gleichnamige Klausel
für die CREATE TABLE
-Anweisung.
(Informationen zu Syntax und eine Beschreibung finden Sie in
Abschnitt 13.1.5, „CREATE TABLE
“.) Angenommen, Sie haben wie
folgt eine partitionierte Tabelle erstellt:
CREATE TABLE t1 ( id INT, year_col INT ) PARTITION BY RANGE (year_col) ( PARTITION p0 VALUES LESS THAN (1991), PARTITION p1 VALUES LESS THAN (1995), PARTITION p2 VALUES LESS THAN (1999) );
Sie können dieser Tabelle nun wie folgt eine neue Partition
p3
hinzufügen, die Werte aufnehmen kann,
die kleiner als 2002
sind.
ALTER TABLE t1 ADD PARTITION p3 VALUES LESS THAN (2002);
Hinweis: Sie können
ALTER TABLE
nicht zum Hinzufügen von
Partitionen zu einer Tabelle verwenden, die (noch) nicht
partitioniert ist.
Mit DROP PARTITION
können Sie eine oder
mehrere RANGE
- oder
LIST
-Partitionen löschen. Diese
Anweisung kann nicht für HASH
- oder
KEY
-Partitionen verwendet werden; dort
benutzen Sie stattdessen COALESCE
PARTITION
(siehe unten). In gelöschten
Partitionen vorhandene Daten, die in der Liste
partition_names
aufgeführt sind,
werden verworfen. So können Sie beispielsweise in der zuvor
definierten Tabelle t1
die Partitionen
p0
und p1
wie folgt
löschen:
ALTER TABLE DROP PARTITION p0, p1;
Beachten Sie, dass DROP PARTITION
nicht
bei Tabellen funktioniert, die die NDB
Cluster
-Speicher-Engine verwenden. Siehe auch
Abschnitt 17.3.1, „Verwaltung von RANGE
- und
LIST
-Partitionen“, und
Abschnitt 16.8, „Bekannte Beschränkungen von MySQL Cluster“.
ADD PARTITION
und DROP
PARTITION
unterstützen IF [NOT]
EXISTS
derzeit nicht. Ferner ist es nicht
möglich, eine Partition oder eine partitionierte Tabelle
umzubenennen. Stattdessen müssen Sie, wenn Sie eine
Partition umbenennen wollen, diese löschen und neu
erstellen. Wollen Sie eine partitionierte Tabelle
umbenennen, dann müssen Sie zunächst alle Partitionen
löschen, die Tabelle dann umbenennen und schließlich alle
gelöschten Partitionen neu erstellen.
COALESCE PARTITION
kann bei Tabellen
benutzt werden, die mit HASH
oder
KEY
partitioniert wurden, um die Anzahl
der Partitionen um den Wert
number
zu verringern. Angenommen,
Sie haben die Tabelle t2
mit der
folgenden Definition erstellt:
CREATE TABLE t2 ( name VARCHAR (30), started DATE ) PARTITION BY HASH(YEAR(started)) PARTITIONS (6);
Sie können die Anzahl der von t2
verwendeten Partitionen nun mit der folgenden Anweisung von
6 auf 4 verringern:
ALTER TABLE t2 COALESCE PARTITION 2;
Die in den letzten number
Partitionen enthaltenen Daten werden in die verbleibenden
Partitionen eingefügt. In diesem Fall werden die
Partitionen 4 und 5 in die ersten vier Partitionen (0 bis 3)
eingefügt.
Um einige, aber nicht alle Partitionen zu ändern, die von
einer partitionierten Tabelle verwendet werden, können Sie
REORGANIZE PARTITION
verwenden. Diese
Anweisung kann auf mehrere Arten verwendet werden:
Um mehrere Partitionen zu einer zusammenzufassen. Hierzu
zählen Sie mehrere Partitionen in der
partition_names
-Liste auf und
geben genau eine Definition für
partition_definition
an.
Um eine vorhandene Partition in mehrere Partitionen
aufzuspalten. Hierzu benennen Sie genau eine Partition
für partition_names
und
geben in
partition_definitions
mehrere
Definitionen an.
Um die Bereiche für eine Teilmenge der Partitionen, die
mit VALUES LESS THAN
definiert wird,
oder die Wertelisten für eine Teilmenge der Partitionen
zu ändern, die mit VALUES IN
definiert wird.
Hinweis: Bei Partitionen,
die nicht explizit aufgeführt wurden, verwendet MySQL
automatisch die Standardnamen p0
,
p1
, p2
usw.
Weitere Informationen zu ALTER TABLE ... REORGANIZE
PARTITION
-Anweisungen und zugehörige Beispiele
finden Sie in Abschnitt 17.3, „Partitionsverwaltung“.
Mehrere zusätzliche Klauseln ermöglichen die Wartung und
Reparatur von Partitionen analog zu der Art und Weise, wie
diese Funktionalitäten bei nicht partitionierten Tabellen
durch Anweisungen wie CHECK TABLE
und
REPAIR TABLE
(welche von partitionierten
Tabellen nicht unterstützt werden)
implementiert sind. Hierzu gehören ANALYZE
PARTITION
, CHECK PARTITION
,
OPTIMIZE PARTITION
, REBUILD
PARTITION
und REPAIR PARTITION
.
Jede dieser Optionen nimmt eine
partition_names
-Klausel entgegen,
die einen oder mehrere durch Kommata getrennte
Partitionsnamen umfasst. Die Partitionen müssen in der zu
ändernden Tabelle bereits vorhanden sein. Weitere
Informationen hierzu und zugehörige Beispiele finden Sie in
Abschnitt 17.3.3, „Wartung von Partitionen“.
Mit der C-API-Funktion mysql_info()
können
Sie ermitteln, wie viele Datensätze kopiert und (sofern
IGNORE
verwendet wird) aufgrund doppelt
vorhandener eindeutiger Schlüsselwerte gelöscht wurden. Siehe
auch Abschnitt 24.2.3.34, „mysql_info()
“.
Es folgen ein paar Beispiele, die Anwendungsmöglichkeiten für
ALTER TABLE
zeigen. Beginnen wir mit einer
Tabelle t1
, die wie folgt erstellt wird:
CREATE TABLE t1 (a INTEGER,b CHAR(10));
So benennen Sie die Tabelle von t1
in
t2
um:
ALTER TABLE t1 RENAME t2;
So ändern Sie den Typ der Spalte a
von
INTEGER
auf TINYINT NOT
NULL
(wobei der Name erhalten bleibt) und den Typ der
Spalte b
von CHAR(10)
zu
CHAR(20)
sowie deren Namen von
b
zu c
:
ALTER TABLE t2 MODIFY a TINYINT NOT NULL, CHANGE b c CHAR(20);
So fügen Sie eine neue TIMESTAMP
-Spalte
namens d
hinzu:
ALTER TABLE t2 ADD d TIMESTAMP;
So fügen Sie Indizes zu den Spalten d
und
a
hinzu:
ALTER TABLE t2 ADD INDEX (d), ADD INDEX (a);
So entfernen Sie die Spalte c
:
ALTER TABLE t2 DROP COLUMN c;
So fügen Sie eine neue AUTO_INCREMENT
-Spalte
namens c
hinzu:
ALTER TABLE t2 ADD c INT UNSIGNED NOT NULL AUTO_INCREMENT, ADD PRIMARY KEY (c);
Beachten Sie, dass wir c
(als
PRIMARY KEY
) indiziert haben, weil
AUTO_INCREMENT
-Spalten indiziert werden
müssen, und dass wir außerdem c
als
NOT NULL
deklariert haben, weil
Primärschlüsselspalten nicht NULL
sein
dürfen.
Wenn Sie eine AUTO_INCREMENT
-Spalte
hinzufügen, werden als Spaltenwerte automatisch Sequenznummern
eingetragen. Bei MyISAM
-Tabellen können Sie
die erste Sequenznummer durch Ausführung von SET
INSERT_ID=
vor
value
ALTER TABLE
oder durch Verwendung der
Tabellenoption
AUTO_INCREMENT=
einstellen. Siehe auch Abschnitt 13.5.3, „value
SET
“.
Sie können die Tabellenoption ALTER TABLE ...
AUTO_INCREMENT=
bei
value
InnoDB
-Tabellen zur Einstellung der
Sequenznummer für neue Datensätze benutzen, wenn der Wert
größer ist als der höchste Wert in der
AUTO_INCREMENT
-Spalte. Ist der Wert
kleiner als der aktuelle Maximalwert der Spalte, dann wird keine
Fehlermeldung ausgegeben, und der aktuelle Sequenzwert wird
nicht geändert.
Wenn Sie bei MyISAM
-Tabellen die
AUTO_INCREMENT
-Spalte nicht ändern, ist die
Sequenznummer nicht betroffen. Wenn Sie eine
AUTO_INCREMENT
-Spalte löschen und dann eine
neue AUTO_INCREMENT
-Spalte hinzufügen,
beginnen die Sequenznummern wieder bei 1.
Siehe auch Abschnitt A.7.1, „Probleme mit ALTER TABLE
“.
CREATE {DATABASE | SCHEMA} [IF NOT EXISTS]db_name
[create_specification
[,create_specification
] ...]create_specification
: [DEFAULT] CHARACTER SETcharset_name
| [DEFAULT] COLLATEcollation_name
CREATE DATABASE
erstellt eine Datenbank des
angegebenen Namens. Um CREATE DATABASE
verwenden zu können, benötigen Sie die Berechtigung
CREATE
für die Datenbank. CREATE
SCHEMA
ist ein Synonym für CREATE
DATABASE
.
Die Regeln für zulässige Datenbanknamen sind in
Abschnitt 9.2, „Datenbank-, Tabellen-, Index-, Spalten- und Aliasnamen“, beschrieben. Wenn die Datenbank
vorhanden ist und Sie IF NOT EXISTS
nicht
angegeben haben, tritt ein Fehler auf.
create_specification
-Optionen geben
die Datenbankeigenschaften an. Diese Datenbankeigenschaften sind
in der Datei db.opt
im Datenbankverzeichnis
gespeichert. Die Klausel CHARACTER SET
gibt
den Standardzeichensatz der Datenbank an. Die Klausel
COLLATE
gibt die Standardsortierfolge der
Datenbank an. Kapitel 10, Zeichensatz-Unterstützung, behandelt Namen von
Zeichensätzen und Sortierfolgen.
Datenbanken werden in MySQL als Verzeichnisse implementiert, die
Dateien enthalten, welche den Tabellen der Datenbank
entsprechen. Weil bei der Erstellung einer Datenbank noch keine
Tabellen vorhanden sind, erzeugt die Anweisung CREATE
DATABASE
lediglich ein Verzeichnis im
MySQL-Datenverzeichnis sowie die Datei
db.opt
.
Wenn Sie manuell (z. B. mit mkdir) ein
Verzeichnis im Datenverzeichnis erstellen, betrachtet der Server
dieses als Datenbankverzeichnis und zeigt es in der Ausgabe von
SHOW DATABASES
an.
Sie können zur Erstellung von Datenbanken auch das Programm mysqladmin verwenden. Siehe auch Abschnitt 8.7, „mysqladmin — Client für die Verwaltung eines MySQL Servers“.
CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEXindex_name
[USINGindex_type
] ONtbl_name
(index_col_name
,...) [WITH PARSERparser_name
]index_col_name
:col_name
[(length
)] [ASC | DESC]
CREATE INDEX
wird mit einer ALTER
TABLE
-Anweisung verknüpft, um Indizes zu erstellen.
Siehe auch Abschnitt 13.1.2, „ALTER TABLE
“. Weitere Informationen
dazu, wie MySQL Indizes verwendet, finden Sie in
Abschnitt 7.4.5, „Wie MySQL Indizes benutzt“.
Normalerweise erstellen Sie alle Indizes für eine Tabelle zu
dem Zeitpunkt, an dem Sie auch die Tabelle selbst mit
CREATE TABLE
anlegen. Siehe auch
Abschnitt 13.1.5, „CREATE TABLE
“. CREATE INDEX
erlaubt Ihnen das Hinzufügen von Indizes zu vorhandenen
Tabellen.
Eine Spaltenliste in der Form (col1,col2,...)
erstellt einen mehrspaltigen Index. Indexwerte werden gebildet,
indem die Werte der betreffenden Spalten verkettet werden.
Bei CHAR
-, VARCHAR
-,
BINARY
- und
VARBINARY
-Spalten können Indizes erstellt
werden, die nur einen Teil einer Spalte verwenden. Hier
verwenden Sie die Syntax
,
um die Länge des Indexpräfixes anzugeben. Indexeinträge
umfassen dann die ersten col_name
(length
)length
Zeichen jedes Spaltenwerts bei CHAR
- und
VARCHAR
-Spalten sowie die ersten
length
Bytes jedes Spaltenwerts bei
BINARY
- und
VARBINARY
-Spalten. BLOB
-
und TEXT
-Spalten lassen sich auch indizieren,
aber eine Präfixlänge muss angegeben
werden.
Die folgende Anweisung erstellt einen Index unter Verwendung der
ersten zehn Zeichen der Spalte name
:
CREATE INDEX part_of_name ON customer (name(10));
Wenn die ersten zehn Zeichen aller Namen in der Spalte sich
durchgehend unterscheiden, dann sollte dieser Index nicht viel
langsamer sein als ein Index, der aus der gesamten Spalte
name
erstellt wurde. Auch die Verwendung von
Teilspalten für Indizes kann die Indexdatei wesentlich kleiner
machen, wodurch sich viel Festplattenspeicher sparen lässt und
INSERT
-Operationen unter Umständen auch
beschleunigt werden können.
Präfixe können bis 1.000 Byte lang sein (767 Byte bei
InnoDB
-Tabellen). Beachten Sie, dass
Präfixbeschränkungen in Byte angegeben werden, wohingegen die
Präfixlänge in CREATE INDEX
-Anweisungen bei
nichtbinären Datentypen (CHAR
,
VARCHAR
, TEXT
) als Anzahl
der Zeichen interpretiert wird. Dies muss bei der Angabe einer
Präfixlänge für eine Spalte berücksichtigt werden, die einen
Multibytezeichensatz verwendet.
In MySQL 5.1 können Sie
einen Index für eine Spalte, die
NULL
-Werte enthalten kann, nur dann
hinzufügen, wenn Sie die Speicher-Engines
MyISAM
, InnoDB
,
BDB
oder MEMORY
verwenden,
einen Index für eine BLOB
- oder
TEXT
-Spalte nur dann hinzufügen, wenn
Sie die Speicher-Engines MyISAM
,
BDB
oder InnoDB
verwenden.
Eine index_col_name
-Definition kann
auf ASC
oder DESC
enden.
Diese Schlüsselwörter sind für zukünftige Erweiterungen
zulässig, um eine Speicherung der Indexwerte in auf- oder
absteigender Reihenfolge festzulegen. Zurzeit werden sie zwar
erkannt, aber ignoriert – Indexwerte werden immer in
aufsteigender Reihenfolge gespeichert.
Einige Speicher-Engines gestatten bei der Erstellung eines
Indexes die Angabe eines Indextyps. Die Syntax für die
Konfigurationsangabe index_type
lautet USING
. Zulässige Werte
für type_name
type_name
, die von den
verschiedenen Speicher-Engines unterstützt werden, sind in der
folgenden Tabelle aufgelistet. Sind mehrere Indextypen
aufgeführt, so wird der erste standardmäßig verwendet, wenn
keine Angabe für index_type
vorhanden ist.
Speicher-Engine | Zulässige Indextypen |
MyISAM | BTREE |
InnoDB | BTREE |
MEMORY /HEAP | HASH , BTREE |
Ein paar Beispiele:
CREATE TABLE lookup (id INT) ENGINE = MEMORY; CREATE INDEX id_index USING BTREE ON lookup (id);
TYPE
kann als Synonym für type_name
USING
benutzt werden,
um einen Indextyp anzugeben. Allerdings ist
type_name
USING
die bevorzugte Form. Ferner ist der
Indexname, der in der Syntax zur Indexspezifikation vor dem
Indextyp steht, bei TYPE
nicht optional:
Anders als USING
ist TYPE
kein reserviertes Wort und wird infolgedessen nicht als
Indexname interpretiert.
Wenn Sie einen Indextyp angeben, der für eine gegebene Speicher-Engine nicht zulässig ist, aber ein anderer Indextyp vorhanden ist, den die Engine verwenden kann, ohne dass hiervon Abfrageergebnisse betroffen wären, dann verwendet die Engine diesen verfügbaren Typ.
FULLTEXT
-Indizes werden nur für
MyISAM
-Tabellen unterstützt und dürfen nur
CHAR
-, VARCHAR
- und
TEXT
-Spalten enthalten. Siehe auch
Abschnitt 12.7, „MySQL-Volltextsuche“. Eine WITH
PARSER
-Klausel kann angegeben werden, um ein
Parser-Plug-In mit dem Index zu verknüpfen, wenn
Volltextindizierungs- und Suchoperationen besondere Maßnahmen
erfordern. Diese Klausel ist nur für
FULLTEXT
-Indizes zulässig. Informationen zur
Erstellung von Plug-Ins finden Sie in
Abschnitt 26.2, „Die MySQL-Plug-In-Schnittstelle“.
SPATIAL
-Indizes werden nur für
MyISAM
-Tabellen unterstützt und dürfen nur
raumbezogene Spalten enthalten, die als NOT
NULL
definiert sind.
Kapitel 18, Raumbezogene Erweiterungen in MySQL, beschreibt raumbezogene
Datentypen.
CREATE [TEMPORARY] TABLE [IF NOT EXISTS]tbl_name
[(create_definition
,...)] [table_options
] [select_statement
]
Oder:
CREATE [TEMPORARY] TABLE [IF NOT EXISTS]tbl_name
[(] LIKEold_tbl_name
[)];create_definition
:column_definition
| [CONSTRAINT [symbol
]] PRIMARY KEY [index_type
] (index_col_name
,...) | KEY [index_name
] [index_type
] (index_col_name
,...) | INDEX [index_name
] [index_type
] (index_col_name
,...) | [CONSTRAINT [symbol
]] UNIQUE [INDEX] [index_name
] [index_type
] (index_col_name
,...) | FULLTEXT [INDEX] [index_name
] (index_col_name
,...) [WITH PARSERparser_name
] | SPATIAL [INDEX] [index_name
] (index_col_name
,...) | [CONSTRAINT [symbol
]] FOREIGN KEY [index_name
] (index_col_name
,...) [reference_definition
] | CHECK (expr
)column_definition
:col_name
type
[NOT NULL | NULL] [DEFAULTdefault_value
] [AUTO_INCREMENT] [UNIQUE [KEY] | [PRIMARY] KEY] [COMMENT 'string
'] [reference_definition
]type
: TINYINT[(length
)] [UNSIGNED] [ZEROFILL] | SMALLINT[(length
)] [UNSIGNED] [ZEROFILL] | MEDIUMINT[(length
)] [UNSIGNED] [ZEROFILL] | INT[(length
)] [UNSIGNED] [ZEROFILL] | INTEGER[(length
)] [UNSIGNED] [ZEROFILL] | BIGINT[(length
)] [UNSIGNED] [ZEROFILL] | REAL[(length
,decimals
)] [UNSIGNED] [ZEROFILL] | DOUBLE[(length
,decimals
)] [UNSIGNED] [ZEROFILL] | FLOAT[(length
,decimals
)] [UNSIGNED] [ZEROFILL] | DECIMAL(length
,decimals
) [UNSIGNED] [ZEROFILL] | NUMERIC(length
,decimals
) [UNSIGNED] [ZEROFILL] | DATE | TIME | TIMESTAMP | DATETIME | YEAR | CHAR(length
) [BINARY | ASCII | UNICODE] | VARCHAR(length
) [BINARY] | BINARY(length
) | VARBINARY(length
) | TINYBLOB | BLOB | MEDIUMBLOB | LONGBLOB | TINYTEXT [BINARY] | TEXT [BINARY] | MEDIUMTEXT [BINARY] | LONGTEXT [BINARY] | ENUM(value1
,value2
,value3
,...) | SET(value1
,value2
,value3
,...) |spatial_type
index_col_name
:col_name
[(length
)] [ASC | DESC]reference_definition
: REFERENCEStbl_name
[(index_col_name
,...)] [MATCH FULL | MATCH PARTIAL | MATCH SIMPLE] [ON DELETEreference_option
] [ON UPDATEreference_option
]reference_option
: RESTRICT | CASCADE | SET NULL | NO ACTIONtable_options
:table_option
[table_option
] ...table_option
: {ENGINE|TYPE} [=]engine_name
| AUTO_INCREMENT [=]value
| AVG_ROW_LENGTH [=]value
| [DEFAULT] CHARACTER SETcharset_name
[COLLATEcollation_name
] | CHECKSUM [=] {0 | 1} | COMMENT [=] 'string
' | CONNECTION [=] 'connect_string
' | MAX_ROWS [=]value
| MIN_ROWS [=]value
| PACK_KEYS [=] {0 | 1 | DEFAULT} | PASSWORD [=] 'string
' | DELAY_KEY_WRITE [=] {0 | 1} | ROW_FORMAT [=] {DEFAULT|DYNAMIC|FIXED|COMPRESSED|REDUNDANT|COMPACT} | UNION [=] (tbl_name
[,tbl_name
]...) | INSERT_METHOD [=] { NO | FIRST | LAST } | DATA DIRECTORY [=] 'absolute path to directory
' | INDEX DIRECTORY [=] 'absolute path to directory
'partition_options
: PARTITION BY [LINEAR] HASH(expr
) | [LINEAR] KEY(column_list
) | RANGE(expr
) | LIST(expr
) [PARTITIONSnum
] [ SUBPARTITION BY [LINEAR] HASH(expr
) | [LINEAR] KEY(column_list
) [SUBPARTITIONSnum
] ] [(partition_definition
) [, (partition_definition
)] ...]partition_definition
: PARTITIONpartition_name
[VALUES {LESS THAN (expr
) |MAXVALUE
| IN (value_list
)}] [[STORAGE] ENGINE [=]engine-name
] [COMMENT [=]'comment_text'
] [DATA DIRECTORY [=] ''] [INDEX DIRECTORY [=] '
data_dir
'] [MAX_ROWS [=]
index_dir
max_number_of_rows
] [MIN_ROWS [=]min_number_of_rows
] [TABLESPACE [=] (tablespace_name
)] [NODEGROUP [=]node_group_id
] [(subpartition_definition
) [, (subpartition_definition
)] ...]subpartition_definition
: SUBPARTITIONlogical_name
[[STORAGE] ENGINE [=]engine-name
] [COMMENT [=]'comment_text'
] [DATA DIRECTORY [=] ''] [INDEX DIRECTORY [=] '
data_dir
'] [MAX_ROWS [=]
index_dir
max_number_of_rows
] [MIN_ROWS [=]min_number_of_rows
] [TABLESPACE [=] (tablespace_name
)] [NODEGROUP [=]node_group_id
]select_statement:
[IGNORE | REPLACE] [AS] SELECT ... (Some legal select statement
)
CREATE TABLE
erstellt eine Tabelle des
angegebenen Namens. Für die Tabelle benötigen Sie die
Berechtigung CREATE
.
Die Regeln für zulässige Tabellennamen sind in Abschnitt 9.2, „Datenbank-, Tabellen-, Index-, Spalten- und Aliasnamen“, beschrieben. Standardmäßig wird die Tabelle in der Standarddatenbank erstellt. Wenn die Tabelle bereits vorhanden ist oder weder die Standarddatenbank noch die angegebene Datenbank vorhanden sind, wird ein Fehler erstellt.
Der Tabellenname kann als
db_name.tbl_name
angegeben werden, um
die Tabelle in einer bestimmten Datenbank zu erstellen. Das
funktioniert unabhängig vom Vorhandensein einer
Standarddatenbank, sofern die angegebene Datenbank vorhanden
ist. Wenn Sie Bezeichner in Anführungszeichen verwenden, setzen
Sie Datenbank- und Tabellennamen separat in Anführungszeichen.
So ist etwa `mydb`.`mytbl`
zulässig –
anders als `mydb.mytbl`
.
Sie können das Schlüsselwort TEMPORARY
bei
der Erstellung einer Tabelle verwenden. Eine
TEMPORARY
-Tabelle ist nur für die aktuelle
Verbindung sichtbar und wird beim Beenden dieser Verbindung
automatisch gelöscht. Das bedeutet, dass zwei verschiedene
Verbindungen Temporärtabellen desselben Namens verwenden
können, ohne dass es zu Konflikten mit der jeweils anderen
Tabelle oder einer nichttemporären Tabelle gleichen Namens
kommt. (Die vorhandene Tabelle wird verborgen, bis die
Temporärtabelle gelöscht wird.) Zur Erstellung von
Temporärtabellen benötigen Sie die Berechtigung
CREATE TEMPORARY TABLES
.
Die Schlüsselwörter IF NOT EXISTS
verhindern, dass ein Fehler auftritt, wenn die Tabelle vorhanden
ist. Allerdings wird nicht überprüft, ob die vorhandene
Tabelle die gleiche Struktur wie die in der CREATE
TABLE
-Anweisung angegebene Tabelle hat.
Hinweis: Wenn Sie IF NOT
EXISTS
in einer CREATE TABLE ...
SELECT
-Anweisung verwenden, werden alle durch den
SELECT
-Teil gewählten Datensätze ohne
Berücksichtigung der Frage eingefügt, ob die Tabelle bereits
vorhanden ist.
MySQL stellt jede Tabelle durch eine
.frm
-Tabellenformatdatei (Definitionsdatei)
im Datenbankverzeichnis dar. Die Speicher-Engine der Tabelle
erstellt unter Umständen auch andere Dateien. Im Falle von
MyISAM
-Tabellen erstellt die Speicher-Engine
Daten- und Indexdateien. Es gibt also für jede
MyISAM
-Tabelle
tbl_name
drei Dateien auf der
Festplatte:
Datei | Zweck |
| Tabellenformatdatei (Definitionsdatei) |
| Datendatei |
| Indexdatei |
Kapitel 14, Speicher-Engines und Tabellentypen, beschreibt, welche Dateien die einzelnen Speicher-Engines zur Darstellung von Tabellen erstellen.
type
stellt den Datentyp einer
Spaltendefinition dar. spatial_type
ist ein
raumbezogener Datentyp. Allgemeine Informationen zu den
Eigenschaften von Datentypen (außer raumbezogenen Datentypen)
finden Sie in Kapitel 11, Datentypen. Informationen zu
raumbezogenen Datentypen finden Sie in
Kapitel 18, Raumbezogene Erweiterungen in MySQL.
Wenn weder NULL
noch NOT
NULL
angegeben sind, wird die Spalte so behandelt,
als ob NULL
angegeben worden wäre.
Eine Integer-Spalte kann das Zusatzattribut
AUTO_INCREMENT
erhalten. Wenn Sie den
Wert NULL
(empfohlen) oder
0
in eine indizierte
AUTO_INCREMENT
-Spalte einfügen, wird die
Spalte auf den nächsten Sequenzwert gesetzt. Normalerweise
ist dies
, wobei
value
+1value
der derzeit größte Wert
der Spalte in der Tabelle ist.
AUTO_INCREMENT
-Sequenzen beginnen bei
1
.
Um einen AUTO_INCREMENT
-Wert nach
Einfügen eines Datensatzes abzurufen, verwenden Sie die
SQL-Funktion LAST_INSERT_ID()
oder die
C-API-Funktion mysql_insert_id()
. Siehe
auch Abschnitt 12.10.3, „Informationsfunktionen“, und
Abschnitt 24.2.3.36, „mysql_insert_id()
“.
Wenn der SQL-Modus NO_AUTO_VALUE_ON_ZERO
aktiviert ist, können Sie 0
in
AUTO_INCREMENT
-Spalten als
0
speichern, ohne einen neuen Sequenzwert
zu erzeugen. Siehe auch Abschnitt 5.2.5, „Der SQL-Modus des Servers“.
Hinweis: Es kann nur eine
AUTO_INCREMENT
-Spalte pro Tabelle geben.
Diese muss indiziert sein und darf keinen Standardwert
haben. Eine AUTO_INCREMENT
-Spalte
funktioniert nur dann einwandfrei, wenn sie ausschließlich
positive Werte enthält. Das Einfügen eines negativen Werts
wird als Einfügen einer sehr großen positiven Zahl
aufgefasst. Dies wird gemacht, um genauigkeitsspezifische
Probleme zu vermeiden, die beim „Umklappen“ von
positiven auf negative Zahlen auftreten können, und um zu
gewährleisten, dass Sie nicht versehentlich eine
AUTO_INCREMENT
-Spalte erhalten, die
0
enthält.
Bei MyISAM
- und
BDB
-Tabellen können Sie
AUTO_INCREMENT
in einer Sekundärspalte
eines mehrspaltigen Schlüssels angeben. Siehe auch
Abschnitt 3.6.9, „Verwendung von AUTO_INCREMENT
“.
Um MySQL mit einigen ODBC-Anwendungen kompatibel zu machen,
können Sie den AUTO_INCREMENT
-Wert für
den letzten eingefügten Datensatz mit der folgenden Abfrage
ermitteln:
SELECT * FROMtbl_name
WHEREauto_col
IS NULL
Das Attribut SERIAL
kann als Alias für
BIGINT UNSIGNED NOT NULL AUTO_INCREMENT
UNIQUE
verwendet werden.
Zeichendatentypen (CHAR
,
VARCHAR
, TEXT
) können
CHARACTER SET
- und
COLLATE
-Attribute zur Angabe von
Zeichensatz und Sortierfolge der Spalte enthalten. Weitere
Informationen finden Sie in Kapitel 10, Zeichensatz-Unterstützung.
CHARSET
ist ein Synonym für
CHARACTER SET
. Beispiel:
CREATE TABLE t (c CHAR(20) CHARACTER SET utf8 COLLATE utf8_bin);
MySQL 5.1 interpretiert Längenangaben in Zeichenspaltendefinitionen als Anzahl von Zeichen. (Versionen vor MySQL 4.1 interpretierten sie als Anzahl von Bytes.)
Die DEFAULT
-Klausel gibt einen
Vorgabewert für eine Spalte an. Mit einer Ausnahme muss der
Vorgabewert immer eine Konstante sein. Funktionen oder
Ausdrücke sind als Vorgabe nicht zulässig. Das bedeutet,
dass Sie beispielsweise als Vorgabewert einer Datumsspalte
nicht den Wert einer Funktion wie NOW()
oder CURRENT_DATE
angeben dürfen. Die
genannte Ausnahme besteht darin, dass Sie
CURRENT_TIMESTAMP
als Vorgabe für eine
TIMESTAMP
-Spalte festlegen können. Siehe
auch Abschnitt 11.3.1.1, „TIMESTAMP
-Eigenschaften ab MySQL 4.1“.
Wenn eine Spaltendefinition keinen expliziten
DEFAULT
-Wert enthält, bestimmt MySQL
diesen wie in Abschnitt 11.1.4, „Vorgabewerte von Datentypen“,
beschrieben.
Für BLOB
- und
TEXT
-Spalten können keine Vorgaben
festgelegt werden.
Ein Kommentar für eine Spalte kann mit der Option
COMMENT
angegeben werden. Der Kommentar
wird über die Anweisungen SHOW CREATE
TABLE
und SHOW FULL COLUMNS
angezeigt.
KEY
ist normalerweise ein Synonym für
INDEX
. Das Schlüsselattribut
PRIMARY KEY
kann auch einfach als
KEY
angegeben werden, sofern die Angabe
in einer Spaltendefinition erfolgt. Dieses Verhalten wurde
aus Gründen der Kompatibilität mit anderen
Datenbanksystemen implementiert.
Ein eindeutiger Index ist dahingehend eingeschränkt, dass
alle Werte im Index eindeutig sein müssen. Wenn Sie einen
neuen Datensatz mit einem Schlüssel hinzufügen, der dem
eines vorhandenen Datensatzes entspricht, tritt ein Fehler
auf. Eine Ausnahme hierzu besteht darin, dass, wenn eine
Spalte im Index NULL
-Werte enthalten
darf, diese mehrere NULL
-Werte enthalten
kann. Diese Ausnahme gilt jedoch nicht für
BDB
-Tabellen, bei denen eine Spalte mit
einem eindeutigen Index NULL
nur einmalig
gestattet.
Ein Primärschlüssel ist ein eindeutiger Index, bei dem
alle Schlüsselspalten als NOT NULL
definiert sein müssen. Wenn sie nicht explizit als
NOT NULL
deklariert sind, holt MySQL dies
implizit (und stillschweigend) nach. Eine Tabelle darf nur
einen Primärschlüssel enthalten. Wenn Sie keinen
Primärschlüssel haben und eine Anwendung nach dem
Primärschlüssel in Ihren Tabellen fragt, gibt MySQL als
Primärschlüssel den ersten eindeutigen Index zurück, der
keine NULL
-Spalten verwendet.
In der erstellten Tabelle wird der Primärschlüssel an die
erste Position gesetzt, gefolgt von allen eindeutigen
Indizes und nachfolgend den nichteindeutigen Indizes. Dies
erleichtert dem MySQL-Optimierer die Priorisierung der zu
verwendenden Indizes und die schnelle Erkennung von
Dubletten bei den UNIQUE
-Schlüsseln.
Ein Primärschlüssel kann ein mehrspaltiger Index sein. Sie
können allerdings keinen mehrspaltigen Index mithilfe des
Schlüsselattributs PRIMARY KEY
in einer
Spaltendefinition erstellen. Wenn Sie dies tun, wird nur
diese eine Spalte als Primärschlüssel gekennzeichnet. Sie
müssen hierzu eine separate PRIMARY
KEY(index_col_name, ...)
-Klausel verwenden.
Wenn ein Primärschlüssel oder ein eindeutiger Index aus
nur einer Spalte eines Integer-Typs bestehen, können Sie
die Spalte auch in SELECT
-Anweisungen als
_rowid
referenzieren.
In MySQL lautet der Name eines Primärschlüssels
PRIMARY
. Bei anderen Indizes erhält,
sofern Sie keinen Namen angeben, der Index jeweils denselben
Namen wie die erste indizierte Spalte. Es kann optional ein
Suffix (_2
, _3
,
...
) angegeben werden, um den Index
eindeutig zu machen. Sie können die Indexnamen für eine
Tabelle mit SHOW INDEX FROM
anzeigen.
Siehe auch Abschnitt 13.5.4.12, „tbl_name
SHOW INDEX
“.
Einige Speicher-Engines gestatten bei der Erstellung eines
Indexes die Angabe eines Indextyps. Die Syntax für die
Konfigurationsangabe index_type
lautet USING
.
type_name
Beispiel:
CREATE TABLE lookup (id INT, INDEX USING BTREE (id)) ENGINE = MEMORY;
Detaillierte Informationen zu USING
finden Sie in Abschnitt 13.1.4, „CREATE INDEX
“.
Weitere Informationen dazu, wie MySQL Indizes verwendet, finden Sie in Abschnitt 7.4.5, „Wie MySQL Indizes benutzt“.
In MySQL 5.1 unterstützen nur die
Speicher-Engines MyISAM
,
InnoDB
, BDB
und
MEMORY
Indizes bei Spalten, die
NULL
-Werte enthalten. In anderen Fällen
müssen Sie indizierte Spalten als NOT
NULL
deklarieren, andernfalls wird ein Fehler
zurückgegeben.
Mit der Syntax
in einer Indexdefinition können Sie einen Index erstellen,
der die Spalte nur teilweise verwendet. Indexeinträge
umfassen die ersten col_name
(length
)length
Zeichen jedes Spaltenwerts bei CHAR
- und
VARCHAR
-Spalten sowie die ersten
length
Bytes jedes Spaltenwerts
bei BINARY
- und
VARBINARY
-Spalten. Wenn Sie auf diese
Weise nur ein Präfix der Spaltenwerte indizieren, kann dies
die Indexdatei erheblich kleiner machen. Siehe auch
Abschnitt 7.4.3, „Spaltenindizes“.
Die Speicher-Engines MyISAM
,
BDB
und InnoDB
unterstützen die Indizierung von BLOB
-
und TEXT
-Spalten. Bei der Indizierung
einer BLOB
- oder
TEXT
-Spalte müssen
Sie eine Präfixlänge für den Index angeben. Zum Beispiel:
CREATE TABLE test (blob_col BLOB, INDEX(blob_col(10)));
Präfixe können bis 1.000 Byte lang sein (767 Byte bei
InnoDB
-Tabellen). Beachten Sie, dass
Präfixbeschränkungen in Byte angegeben werden, wohingegen
die Präfixlänge in CREATE
TABLE
-Anweisungen bei nichtbinären Datentypen
(CHAR
, VARCHAR
,
TEXT
) als Anzahl der Zeichen
interpretiert wird. Dies muss bei der Angabe einer
Präfixlänge für eine Spalte berücksichtigt werden, die
einen Multibytezeichensatz verwendet.
Eine index_col_name
-Definition
kann auf ASC
oder DESC
enden. Diese Schlüsselwörter sind für zukünftige
Erweiterungen zulässig, um eine Speicherung der Indexwerte
in auf- oder absteigender Reihenfolge festzulegen. Zurzeit
werden sie zwar erkannt, aber ignoriert – Indexwerte
werden immer in aufsteigender Reihenfolge gespeichert.
Wenn Sie ORDER BY
oder GROUP
BY
für eine TEXT
- oder
BLOB
-Spalte in einer
SELECT
-Anweisung verwenden, sortiert der
Server Werte lediglich unter Verwendung der ersten Bytes.
Wie viele Bytes dies sind, wird von der Systemvariablen
max_sort_length
angegeben. Siehe auch
Abschnitt 11.4.3, „Die Spaltentypen BLOB
und TEXT
“.
Sie können spezielle Volltextindizes erstellen, die für
die Volltextsuche verwendet werden. Nur die
MyISAM
-Speicher-Engine unterstützt
Volltextindizes. Diese können nur aus
CHAR
-, VARCHAR
- und
TEXT
-Spalten erstellt werden. Die
Indizierung erfolgt immer über die gesamte Spalte: Eine
Teilindizierung wird nicht unterstützt, und ein eventuell
angegebenes Präfix wird ignoriert. Weitere Informationen
finden Sie in Abschnitt 12.7, „MySQL-Volltextsuche“. Eine
WITH PARSER
-Klausel kann angegeben
werden, um ein Parser-Plug-In mit dem Index zu verknüpfen,
wenn Volltextindizierungs- und Suchoperationen besondere
Maßnahmen erfordern. Diese Klausel ist nur für
FULLTEXT
-Indizes zulässig. Informationen
zur Erstellung von Plug-Ins finden Sie in
Abschnitt 26.2, „Die MySQL-Plug-In-Schnittstelle“.
SPATIAL
-Indizes können Sie für
raumbezogene Typen erstellen. Solche Typen werden nur für
MyISAM
-Tabellen unterstützt, und
indizierte Spalten müssen als NOT NULL
deklariert sein. Siehe auch
Kapitel 18, Raumbezogene Erweiterungen in MySQL.
InnoDB
-Tabellen unterstützen die
Überprüfung von Fremdschlüssel-Constraints. Siehe auch
Abschnitt 14.2, „InnoDB
-Tabellen“. Beachten Sie, dass die
Fremdschlüsselsyntax in InnoDB
restriktiver ist als die zu Beginn dieses Abschnitts für
die CREATE TABLE
-Anweisung präsentierte
Syntax: Die Spalten der referenzierten Tabellen müssen
immer explizit genannt werden. InnoDB
unterstützt sowohl ON DELETE
- als auch
ON UPDATE
-Aktionen für Fremdschlüssel.
Informationen zur exakten Syntax finden Sie in
Abschnitt 14.2.6.4, „Fremdschlüssel-Beschränkungen“.
Bei anderen Speicher-Engines erkennt MySQL Server die
FOREIGN KEY
- und
REFERENCES
-Syntax in CREATE
TABLE
-Anweisungen, ignoriert sie aber. Zudem wird
die Klausel CHECK
von allen
Speicher-Engines erkannt, aber ignoriert. Siehe auch
Abschnitt 1.9.5.5, „Fremdschlüssel“.
Bei MyISAM
-Tabellen benötigt jede
NULL
-Spalte ein zusätzliches Bit,
aufgerundet auf das nächste Byte. Die maximale
Datensatzlänge in Byte kann wie folgt berechnet werden:
row length = 1 + (sum of column lengths
) + (number of NULL columns
+delete_flag
+ 7)/8 + (number of variable-length columns
)
delete_flag
ist 1 bei Tabellen
mit statischem Datensatzformat. Statische Tabellen verwenden
ein Bit im Datensatz für ein Flag, das angibt, ob der
Datensatz gelöscht wurde.
delete_flag
ist 0 bei dynamischen
Tabellen, weil das Flag im dynamischen Datensatz-Header
gespeichert wird.
Diese Berechnungen gelten nicht für
InnoDB
-Tabellen, bei denen der
Speicherbedarf von NULL
-Spalten sich
nicht von dem von NOT NULL
-Spalten
unterscheidet.
Die Tabellenoption ENGINE
gibt die
Speicher-Engine für die Tabelle an. TYPE
ist
ein Synonym hierzu, wobei ENGINE
der
bevorzugte Name ist.
Die Tabellenoption ENGINE
akzeptiert die in
der folgenden Tabelle aufgeführten Namen für Speicher-Engines.
Speicher-Engine | Beschreibung |
ARCHIVE | Speicher-Engine zur Archivierung. Siehe auch
Abschnitt 14.8, „Die ARCHIVE -Speicher-Engine“. |
BDB | Transaktionssichere Tabellen mit Seitensperrung. Heißt auch
BerkeleyDB . Siehe auch
Abschnitt 14.5, „Die BDB -Speicher-Engine“. |
CSV | Tabellen, die Datensätze als kommagetrennte Werte speichern. Siehe auch
Abschnitt 14.9, „Die CSV -Speicher-Engine“. |
EXAMPLE | Eine Beispiel-Engine. Siehe auch
Abschnitt 14.6, „Die EXAMPLE -Speicher-Engine“. |
FEDERATED | Speicher-Engine, die auf entfernte Tabellen zugreift. Siehe auch
Abschnitt 14.7, „Die FEDERATED -Speicher-Engine“. |
HEAP | Ein Synonym für MEMORY . |
ISAM (VERALTET) | In MySQL 5.1 nicht verfügbar. Wenn Sie von einer älteren
Version auf MySQL 5.1 aktualisieren,
sollten Sie alle vorhandenen
ISAM -Tabellen in
MyISAM -Tabellen konvertieren,
bevor Sie das Upgrade durchführen. |
InnoDB | Transaktionssichere Tabellen mit Datensatzsperrung und Fremdschlüsseln.
Siehe auch Abschnitt 14.2, „InnoDB -Tabellen“. |
MEMORY | Die Daten für diese Speicher-Engine werden nur im Speicher abgelegt.
Siehe auch Abschnitt 14.4, „Die MEMORY -Speicher-Engine“. |
MERGE | Eine Sammlung von MyISAM -Tabellen, die als eine
Tabelle verwendet wird. Heißt auch
MRG_MyISAM . Siehe auch
Abschnitt 14.3, „Die MERGE -Speicher-Engine“. |
MyISAM | Binäre portable Speicher-Engine, die als Standard-Engine in MySQL
verwendet wird. Siehe auch
Abschnitt 14.1, „Die MyISAM -Speicher-Engine“. |
NDBCLUSTER | Fehlertolerante, speicherbasierte Cluster-Tabellen. Heißt auch
NDB . Siehe auch
Kapitel 16, MySQL Cluster. |
Wird eine Speicher-Engine angegeben, die nicht verfügbar ist,
dann verwendet MySQL stattdessen die Standard-Engine. Im
Normalfall ist dies MyISAM
. Wenn
beispielsweise eine Tabellendefinition die Option
ENGINE=BDB
enthält, aber der MySQL Server
BDB
-Tabellen nicht unterstützt, dann wird
die Tabelle als MyISAM
-Tabelle erstellt. Auf
diese Weise ist eine Replikationskonfiguration realisierbar, bei
der Sie transaktionssichere Tabellen auf dem Master haben,
während die auf dem Slave erstellten Tabellen nicht
transaktionssicher sind (was eine Erhöhung der
Verarbeitungsgeschwindigkeit nach sich zieht). In MySQL
5.1 erscheint eine Warnung, wenn die Spezifikation
der Speicher-Engine nicht berücksichtigt werden kann.
Die übrigen Tabellenoptionen werden zur Optimierung des Verhaltens der Tabelle verwendet. In den meisten Fällen müssen Sie sie überhaupt nicht angeben. Diese Optionen gelten für alle Speicher-Engines, soweit nichts anderes angegeben ist:
AUTO_INCREMENT
Der AUTO_INCREMENT
-Startwert für die
Tabelle. In MySQL 5.1 funktioniert dies bei
MyISAM
-, MEMORY
- und
InnoDB
-Tabellen. Um den ersten
AUTO_INCREMENT
-Wert für Engines zu
setzen, die die Tabellenoption
AUTO_INCREMENT
nicht unterstützen,
fügen Sie einen „Pseudodatensatz“ mit einem
Wert ein, der um 1 niedriger ist als der gewünschte
Startwert. Nach der Erstellung der Tabelle löschen Sie den
Pseudodatensatz dann.
Bei Engines, die die Tabellenoption
AUTO_INCREMENT
in CREATE
TABLE
-Anweisungen unterstützen, können Sie auch
ALTER TABLE
verwenden, um den tbl_name
AUTO_INCREMENT = N
AUTO_INCREMENT
-Wert
zurückzusetzen.
AVG_ROW_LENGTH
Ein Näherungswert für die durchschnittliche Datensatzlänge in Ihrer Tabelle. Sie müssen die Einstellung nur bei großen Tabellen mit Datensätzen unterschiedlicher Größe vornehmen.
Wenn Sie eine MyISAM
-Tabelle erstellen,
verwendet MySQL das Produkt der Optionen
MAX_ROWS
und
AVG_ROW_LENGTH
, um zu ermitteln, wie
groß die resultierende Tabelle sein wird. Geben Sie keine
der Optionen an, dann beträgt die maximale Tabellengröße
65.536 Tbyte Daten. (Wenn Ihr Betriebssystem derart große
Dateien nicht unterstützt, wird die maximale Größe einer
Tabelle durch die betriebssystemseitige Beschränkung der
Dateigröße bestimmt.) Wenn Sie die Zeigergrößen gering
halten wollen, damit der Index kleiner und schneller wird,
und Sie eigentlich keine großen Dateien benötigen, können
Sie die Standardzeigergröße durch Einstellen der
Systemvariablen myisam_data_pointer_size
verringern. (Siehe auch
Abschnitt 5.2.2, „Server-Systemvariablen“.) Wenn Sie wollen,
dass alle Ihre Tabellen über das standardmäßige Limit
hinaus anwachsen können, und dafür in Kauf nehmen, dass
die Tabellen etwas größer und langsamer sind als
notwendig, dann können Sie die Standardzeigergröße durch
Einstellen der Variablen auch erhöhen.
[DEFAULT] CHARACTER SET
Gibt einen Standardzeichensatz für die Tabelle an.
CHARSET
ist ein Synonym für
CHARACTER SET
.
COLLATE
Gibt eine Standardsortierfolge für die Tabelle an.
CHECKSUM
Setzen Sie diese Option auf 1, wenn Sie wollen, dass MySQL
eine Prüfsumme für alle Datensätze erstellt, die zudem
bei Änderungen in der Tabelle automatisch aktualisiert
wird. Dies macht die Aktualisierung der Tabelle zwar ein
wenig langsamer, erleichtert aber das Auffinden
beschädigter Tabellen. Die Anweisung CHECKSUM
TABLE
meldet die Prüfsumme. (Nur für
MyISAM
.)
COMMENT
Ein Kommentar für die Tabelle, der bis zu 60 Zeichen lang sein kann.
CONNECTION
Der Verbindungs-String für eine
FEDERATED
-Tabelle.
(Hinweis: Ältere Versionen
von MySQL verwendeten eine Option COMMENT
für den Verbindungs-String.)
MAX_ROWS
Maximale Anzahl der Datensätze, die Sie in der Tabelle zu speichern beabsichtigen. Dies ist keine feste Beschränkung, sondern ein Indikator für die Anzahl der Datensätze, die die Tabelle zumindest speichern können muss.
MIN_ROWS
Minimale Anzahl der Datensätze, die Sie in der Tabelle zu speichern beabsichtigen.
PACK_KEYS
Setzen Sie diese Option auf 1, wenn Sie kleinere Indizes
wünschen. Hierdurch werden Updates in der Regel langsamer
und Leseoperationen schneller. Wenn Sie die Option auf 0
setzen, wird das Packen für alle Schlüssel deaktiviert.
Setzen Sie sie hingegen auf DEFAULT
, dann
wird die Speicher-Engine angewiesen, nur lange
CHAR
- und
VARCHAR
-Spalten zu packen. (Nur für
MyISAM
.)
Wenn Sie PACK_KEYS
nicht verwenden,
werden standardmäßig Strings, aber nicht Zahlen gepackt.
Bei PACK_KEYS=1
werden auch Zahlen
gepackt.
Beim Packen von binären Zahlenschlüsseln verwendet MySQL die Präfixkompression:
Jeder Schlüssel benötigt ein zusätzliches Byte, um anzugeben, wie viele Bytes des vorherigen Schlüssels beim nachfolgenden Schlüssel identisch sind.
Der Zeiger auf den Datensatz wird direkt auf den Schlüssel folgend und in absteigender Reihenfolge der Bytewertigkeit gespeichert, um die Komprimierung zu optimieren.
Das bedeutet, dass, wenn Sie viele gleiche Schlüssel in
zwei aufeinander folgenden Datensätzen haben, alle
nachfolgenden „identischen“ Schlüssel
einschließlich des Zeigers auf den Datensatz nur 2 Byte
benötigen. Vergleichen Sie dies einmal mit dem normalen
Fall, in dem die nachfolgenden Schlüssel
storage_size_for_key + pointer_size
Bytes
benötigen (wobei die Zeigergröße normalerweise 4
beträgt). Umgekehrt können Sie nur dann umfassend von der
Präfixkomprimierung profitieren, wenn Sie viele identische
Zahlen haben. Wenn alle Schlüssel vollständig
unterschiedlich sind, verwenden Sie pro Schlüssel ein Byte
mehr, wenn der jeweilige Schlüssel keine
NULL
-Werte haben kann. (In diesem Fall
wird die Länge des gepackten Schlüssels im selben Byte
gespeichert, das zur Kennzeichnung verwendet wird, wenn ein
Schlüssel NULL
ist.)
PASSWORD
Verschlüsselt die .frm
-Datei mit einem
Passwort. In der MySQL-Standardversion tut die Option
nichts.
DELAY_KEY_WRITE
Setzen Sie diese Option auf 1, wenn Sie Schlüssel-Updates
für die Tabelle auf einen Zeitpunkt verschieben wollen, an
dem die Tabelle geschlossen ist. Details finden Sie in der
Beschreibung zur Systemvariablen
delay_key_write
in
Abschnitt 5.2.2, „Server-Systemvariablen“. (Nur für
MyISAM
.)
ROW_FORMAT
Definiert, wie die Datensätze gespeichert werden sollen.
Bei MyISAM
-Tabellen kann der Optionswert
FIXED
oder DYNAMIC
für das statische wie auch das variabel lange
Datensatzformat sein. myisampack setzt
den Typ auf COMPRESSED
. Siehe auch
Abschnitt 14.1.3, „MyISAM-Tabellenformate“.
Bei InnoDB
-Tabellen werden die
Datensätze standardmäßig im kompakten Format
(ROW_FORMAT=COMPACT
) gespeichert. Das
nichtkompakte Format, welches in älteren MySQL-Versionen
verwendet wurde, kann noch über die Angabe von
ROW_FORMAT=REDUNDANT
angefordert werden.
RAID_TYPE
Die RAID
-Unterstützung wurde ab MySQL
5.0 entfernt. Informationen zu RAID
finden Sie online im MySQL-4.1-Handbuch unter
http://dev.mysql.com/doc/refman/4.1/en/create-table.html.
UNION
UNION
wird verwendet, wenn Sie auf eine
ganze Sammlung identischer
MyISAM
-Tabellen zugreifen wollen. Dies
funktioniert nur bei MERGE
-Tabellen.
Siehe auch Abschnitt 14.3, „Die MERGE
-Speicher-Engine“.
Sie benötigen die Berechtigungen SELECT
,
UPDATE
und DELETE
für
die Tabellen, um die Sammlung einer MERGE
zuordnen zu können. (Hinweis:
Ursprünglich mussten alle verwendeten Tabellen sich in der
gleichen Datenbank wie die MERGE
-Tabelle
selbst befinden. Diese Einschränkung trifft nicht mehr zu.)
INSERT_METHOD
Wenn Sie Daten in eine MERGE
-Tabelle
einfügen wollen, müssen Sie mit
INSERT_METHOD
die Tabelle festlegen, in
die der Datensatz einzufügen ist. Die Option
INSERT_METHOD
ist nur für
MERGE
-Tabellen sinnvoll. Verwenden Sie
die Werte FIRST
oder
LAST
, um die Einfügung in die erste bzw.
letzte Tabelle vorzunehmen, oder NO
, um
Einfügeoperationen ganz auszuschließen. Siehe auch
Abschnitt 14.3, „Die MERGE
-Speicher-Engine“.
DATA DIRECTORY
, INDEX
DIRECTORY
Mithilfe von DATA
DIRECTORY='
oder directory
'INDEX
DIRECTORY='
können Sie angeben, wo die
directory
'MyISAM
-Speicher-Engine die Daten- und
Indexdatei einer Tabelle ablegen soll.
directory
muss als vollständiger
Pfadname zum Verzeichnis angegeben werden; relative Pfade
sind nicht möglich.
Diese Optionen funktionieren nur, wenn Sie die Option
--skip-symbolic-links
nicht verwenden.
Außerdem muss Ihr Betriebssystem über einen
funktionsfähigen und Thread-sicheren
realpath()
-Aufruf verfügen. Weitere
Informationen finden Sie in
Abschnitt 7.6.1.2, „Benutzung symbolischer Links für Tabellen“.
Partitionierungsoptionen
(partition_options
) können zur
Steuerung der Partitionierung einer Tabelle benutzt werden,
die mit CREATE TABLE
erstellt wurde.
Sofern angegeben, muss mindestens eine PARTITION
BY
-Klausel enthalten sein. Diese Klausel enthält
die Funktion, die zur Bestimmung der Partition verwendet
wird. Die Funktion gibt einen ganzzahligen Wert zwischen 1
und num
zurück, wobei
num
die Gesamtzahl der
Partitionen ist. Die nachfolgende Liste zeigt die
Auswahlmöglichkeiten für diese Funktion in MySQL
5.1.
Wichtig: Nicht alle zu
Beginn dieses Abschnitts in der Syntax für
partition_options
aufgeführten
Optionen stehen für alle Partitionierungstypen zur
Verfügung. Entnehmen Sie den Listings für die jeweiligen
Typen die passenden Informationen. Weitere Informationen zu
Wirkungsweise und Anwendungsmöglichkeiten der
Partitionierung in MySQL sowie zusätzliche Beispiele zur
Tabellenerstellung und zu anderen partitionierungsbezogenen
Anweisungen in MySQL finden Sie in
Kapitel 17, Partitionierung.
HASH(
:
Führt ein Hashing einer oder mehrerer Spalten aus, um
einen Schlüssel zum Platzieren und Wiederauffinden von
Datensätzen zu erstellen.
expr
)expr
ist ein Ausdruck, der
eine oder mehrere Tabellenspalten verwendet. Dabei kann
es sich um einen zulässigen MySQL-Ausdruck
(einschließlich MySQL-Funktionen) handeln, der genau
einen Integer-Wert ausgibt. Die nachfolgenden
CREATE TABLE
-Anweisungen mit
PARTITION BY HASH
-Option etwa sind
alle zulässig:
CREATE TABLE t1 (col1 INT, col2 CHAR(5)) PARTITION BY HASH(col1); CREATE TABLE t1 (col1 INT, col2 CHAR(5)) PARTITION BY HASH( ORD(col2) ); CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATETIME) PARTITION BY HASH ( YEAR(col3) );
VALUES LESS THAN
- und VALUES
IN
-Klauseln dürfen nicht mit
PARTITION BY HASH
gemeinsam
eingesetzt werden.
PARTITION BY HASH
verwendet den Rest
des Ausdrucks expr
geteilt
durch die Anzahl der Partitionen (d. h. den Modulo).
Beispiele und Informationen finden Sie in
Abschnitt 17.2.3, „HASH
-Partitionierung“.
Das Schlüsselwort LINEAR
bringt
einen etwas anderen Algorithmus mit sich. In diesem Fall
wird die Nummer der Partition, auf der ein Datensatz
gespeichert ist, als Ergebnis einer oder mehrerer
logischer AND
-Operationen ermittelt.
Eine Beschreibung und Beispiele für das lineare Hashing
finden Sie in
Abschnitt 17.2.3.1, „LINEAR HASH
-Partitionierung“.
KEY(
:
Dies ähnelt column_list
)HASH
, nur wird die
Hashing-Funktion hier von MySQL selbst bereitgestellt,
um eine gleichmäßige Datenverteilung zu
gewährleisten. Das Argument
column_list
ist eine einfache
Liste mit Tabellenspalten. Dieses Beispiel zeigt eine
einfache, durch einen Schlüssel partitionierte Tabelle
mit vier Partitionen:
CREATE TABLE tk (col1 INT, col2 CHAR(5), col3 DATE) PARTITION BY KEY(col3) PARTITIONS 4;
Bei Tabellen, die durch einen Schlüssel partitioniert
sind, können Sie die lineare Partitionierung durch
Angabe des Schlüsselworts LINEAR
benutzen. Dies hat die gleichen Auswirkungen wie bei
Tabellen, die mit HASH
partitioniert
wurden: Die Partitionsnummer wird mithilfe des Operators
&
statt über den Modulo
ermittelt (siehe auch
Abschnitt 17.2.3.1, „LINEAR HASH
-Partitionierung“, und
Abschnitt 17.2.4, „KEY
-Partitionierung“). Dieses Beispiel
verwendet die lineare Partitionierung über einen
Schlüssel, um Daten auf fünf Partitionen zu verteilen:
CREATE TABLE tk (col1 INT, col2 CHAR(5), col3 DATE) PARTITION BY LINEAR KEY(col3) PARTITIONS 5;
VALUES LESS THAN
- und VALUES
IN
-Klauseln dürfen nicht mit
PARTITION BY KEY
gemeinsam eingesetzt
werden.
RANGE
: In diesem Fall zeigt
expr
unter Verwendung einer
Menge von VALUES LESS THAN
-Operatoren
einen Wertebereich an. Wenn Sie die
Bereichspartitionierung verwenden, müssen Sie
mindestens eine Partition mit VALUES LESS
THAN
angeben. VALUES IN
können Sie bei der Bereichspartitionierung nicht
einsetzen.
VALUES LESS THAN
kann entweder mit
einem literalen Wert oder einem Ausdruck benutzt werden,
der genau einen Wert zurückgibt.
Angenommen, Sie haben eine Tabelle, die Sie nach einer Spalte partitionieren wollen, die Jahreswerte enthält. Hierbei wollen Sie das folgende Schema verwenden:
Partitionsnummer: | Jahre |
0 | 1990 und früher |
1 | 1991–1994 |
2 | 1995–1998 |
3 | 1999–2002 |
4 | 2003–2005 |
5 | 2006 und später |
Eine Tabelle, die dieses Partitionierungsschema
implementiert, kann mit der folgenden CREATE
TABLE
-Anweisung erstellt werden:
CREATE TABLE t1 ( year_col INT, some_data INT ) PARTITION BY RANGE (year_col) ( PARTITION p0 VALUES LESS THAN (1991), PARTITION p1 VALUES LESS THAN (1995), PARTITION p2 VALUES LESS THAN (1999), PARTITION p3 VALUES LESS THAN (2002), PARTITION p4 VALUES LESS THAN (2006), PARTITION p5 VALUES LESS THAN MAXVALUE );
PARTITION ... VALUES LESS THAN
...
-Anweisungen arbeiten konsekutiv, d. h.,
VALUES LESS THAN MAXVALUE
verarbeitet
die „übrig gebliebenen“ Werte, die
größer sind als der anderweitig angegebene
Maximalwert.
Beachten Sie, dass VALUES LESS
THAN
-Klauseln sequenziell auf eine Weise
verarbeitet werden, die der von
case
-Abschnitten eines
switch ... case
-Blocks ähnelt, wie
man sie aus vielen Programmiersprachen wie C, Java oder
PHP her kennt: Die Klauseln müssen so angeordnet sein,
dass der obere Grenzwert einer nachfolgenden
VALUES LESS THAN
-Klausel größer ist
als der der vorherigen Klausel; dabei muss
MAXVALUE
als Letztes in der Liste
erscheinen.
LIST(
:
Dies ist praktisch, wenn man Partitionen basierend auf
einer Tabellenspalte mit einer beschränkten Menge
möglicher Werte (z. B. Land, PLZ usw.) konfiguriert.
In einem solchen Fall lassen sich alle Datensätze, die
einem bestimmten Land oder einer PLZ zuzuordnen sind,
derselben Partition zuweisen, oder eine Partition kann
für bestimmte Länder oder Postleitzahlen reserviert
werden. Dies ähnelt expr
)RANGE
mit der
Einschränkung, dass nur VALUES IN
zur Angabe zulässiger Werte für jede Partition
verwendet werden kann.
VALUES IN
wird mit einer Liste
passender Werte benutzt. Beispielsweise könnten Sie ein
Partitionierungsschema wie das folgende erstellen:
CREATE TABLE client_firms ( id INT, name VARCHAR(35) ) PARTITION BY LIST (id) ( PARTITION r0 VALUES IN (1, 5, 9, 13, 17, 21), PARTITION r1 VALUES IN (2, 6, 10, 14, 18, 22), PARTITION r2 VALUES IN (3, 7, 11, 15, 19, 23), PARTITION r3 VALUES IN (4, 8, 12, 16, 20, 24) );
Wenn Sie die Listenpartitionierung verwenden, müssen
Sie mindestens eine Partition mit VALUES
IN
angeben. VALUES LESS
THAN
können Sie bei der Listenpartitionierung
nicht einsetzen.
Hinweis: Derzeit darf
die für VALUES IN
verwendete
Werteliste nur aus Integers bestehen.
Die Anzahl der Partitionen kann optional mit einer
PARTITIONS
-Klausel
angegeben werden, wobei num
num
die Anzahl der Partitionen ist. Werden diese Klausel
und beliebige
PARTITION
-Klauseln verwendet, muss
num
gleich der Anzahl aller
Partitionen sein, die mit
PARTITION
-Klauseln deklariert wurden.
Hinweis: Unabhängig
davon, ob Sie eine PARTITIONS
-Klausel
bei der Erstellung einer Tabelle verwenden, die mit
RANGE
oder LIST
partitioniert wurde, müssen Sie in jedem Fall
mindestens eine PARTITION
VALUES
-Klausel in der Tabellendefinition
angeben (siehe unten).
Eine Partition kann optional in eine Anzahl
Unterpartitionen aufgeteilt werden. Dies kann durch
Verwendung der optionalen Klausel SUBPARTITION
BY
angegeben werden. Die Unterpartitionierung
kann mit HASH
oder
KEY
erfolgen. Beide können
LINEAR
sein. Sie funktionieren auf
die gleiche Weise wie oben für die entsprechenden
Partitionierungstypen beschrieben. (Es ist nicht
möglich, Unterpartitionen nach LIST
oder RANGE
zu erstellen.)
Die Anzahl der Unterpartitionen kann mit dem
Schlüsselwort SUBPARTITIONS
, gefolgt
von einem Integer-Wert, angegeben werden.
Jede Partition kann individuell mit einer
partition_definition
-Klausel
definiert werden. Die einzelnen Teile, aus denen die Klausel
besteht, sind die folgenden:
PARTITION
:
Gibt einen logischen Namen für die Partition an.
partition_name
VALUES
-Klausel: Bei der
Bereichspartitionierung muss jede Partition eine
VALUES LESS THAN
-Klausel enthalten,
und bei der Listenpartitionierung müssen Sie eine
VALUES IN
-Klausel je Partition
angeben. Hiermit wird bestimmt, welche Datensätze in
dieser Partition gespeichert werden sollen. Weitere
Informationen und Syntaxinformationen entnehmen Sie der
Beschreibung der Partitionierungstypen in
Kapitel 17, Partitionierung.
Eine optionale COMMENT
-Klausel kann
zur Beschreibung der Partition angegeben werden. Der
Kommentar muss in einzelne Anführungszeichen gesetzt
werden. Beispiel:
COMMENT = 'Data for the years previous to 1999'
DATA DIRECTORY
und INDEX
DIRECTORY
können zur Angabe des
Verzeichnisses verwendet werden, in dem die Daten bzw.
die Indizes dieser Partition gespeichert werden sollen.
Sowohl
als auch
data_dir
müssen absolute Pfadnamen sein. Beispiel:
index_dir
CREATE TABLE th (id INT, name VARCHAR(30), adate DATE) PARTITION BY LIST(YEAR(adate)) ( PARTITION p1999 VALUES IN (1995, 1999, 2003) DATA DIRECTORY = '/var/appdata/95/data
' INDEX DIRECTORY = '/var/appdata/95/idx
', PARTITION p2000 VALUES IN (1996, 2000, 2004) DATA DIRECTORY = '/var/appdata/96/data
' INDEX DIRECTORY = '/var/appdata/96/idx
', PARTITION p2001 VALUES IN (1997, 2001, 2005) DATA DIRECTORY = '/var/appdata/97/data
' INDEX DIRECTORY = '/var/appdata/97/idx
', PARTITION p2000 VALUES IN (1998, 2002, 2006) DATA DIRECTORY = '/var/appdata/98/data
' INDEX DIRECTORY = '/var/appdata/98/idx
' );
DATA DIRECTORY
und INDEX
DIRECTORY
verhalten sich genauso wie in der
table_option
-Klausel einer
CREATE TABLE
-Anweisung bei
MyISAM
-Tabellen.
Je Partition können ein Daten- und ein Indexverzeichnis angegeben werden. Wenn keine Angaben gemacht werden, werden Daten und Indizes standardmäßig im MySQL-Datenverzeichnis abgelegt.
MAX_ROWS
und
MIN_ROWS
können zur Angabe der
größten bzw. kleinsten Zahl von Datensätzen verwendet
werden, die in der Partition gespeichert werden. Die
Werte für max_number_of_rows
und min_number_of_rows
müssen positive ganze Zahlen sein. Wie bei den
gleichnamigen Optionen auf Tabellenebene sind auch dies
keine festen Grenzwerte, sondern nur
„Vorschläge“ für den Server.
Die optionale TABLESPACE
-Klausel kann
zur Angabe eines Tablespaces für die Partition
verwendet werden. (Nur für MySQL Cluster.)
Die optionale [STORAGE]
ENGINE
-Klausel bewirkt, dass die Tabelle in
dieser Partition die angegebene Speicher-Engine
verwendet. Dies kann jede der vom betreffenden MySQL
Server unterstützten Engines sein. Sowohl das
Schlüsselwort STORAGE
als auch das
Gleichheitszeichen (=
) sind optional.
Wird keine partitionsspezifische Speicher-Engine mit
dieser Option angegeben, dann wird die für die gesamte
Tabelle gültige Engine auch für diese Partition
verwendet.
Hinweis: Der
Partitionierungs-Handler akzeptiert eine Option
[STORAGE] ENGINE
sowohl für
PARTITION
als auch für
SUBPARTITION
. Die derzeit einzige
Möglichkeit, diese Klausel zu nutzen, besteht darin,
alle Partitionen oder alle Unterpartitionen auf dieselbe
Speicher-Engine zu setzen. Der Versuch, verschiedene
Engines für Partitionen oder Unterpartitionen einer
Tabelle einzustellen, führt zum Fehler ERROR
1469 (HY000): The mix of handlers in the partitions is
not allowed in this version of MySQL
. Wir
beabsichtigen, diese partitionierungsbezogene
Einschränkung in einem zukünftigen Release von MySQL
5.1 zu beseitigen.
Die Option NODEGROUP
kann verwendet
werden, um diese Partition zu einem Teil der
Knotengruppe zu machen, die als
node_group_id
angegeben ist.
(Nur für MySQL Cluster.)
Die Partitionsdefinition kann optional eine oder mehrere
subpartition_definition
-Klauseln
enthalten. Jede dieser Klauseln umfasst zumindest
SUBPARTITION
, wobei
name
name
ein Bezeichner für die
Unterpartition ist. Die Syntax für eine
Unterpartitionsdefinition ist mit der einer Partition
bis auf die Tatsache identisch, dass das Schlüsselwort
PARTITION
durch
SUBPARTITION
zu ersetzen ist.
Die Unterpartitionierung muss über
HASH
oder KEY
erfolgen und kann nur bei RANGE
- oder
LIST
-Partitionen durchgeführt
werden. Siehe auch
Abschnitt 17.2.5, „Unterpartitionen“.
Partitionen können geändert, verbunden und zu Tabellen
hinzugefügt sowie aus diesen gelöscht werden. Grundlegende
Informationen zu den MySQL-Anweisungen, mit denen diese
Aufgaben erledigt werden, finden Sie in
Abschnitt 13.1.2, „ALTER TABLE
“. Detaillierte Beschreibungen
und Beispiele finden Sie in
Abschnitt 17.3, „Partitionsverwaltung“.
Sie können eine Tabelle aus einer anderen Tabelle erstellen,
indem Sie am Ende der CREATE TABLE
-Anweisung
eine SELECT
-Anweisung hinzufügen:
CREATE TABLEnew_tbl
SELECT * FROMorig_tbl
;
MySQL erstellt neue Spalten für alle Elemente in der
SELECT
-Anweisung. Zum Beispiel:
mysql>CREATE TABLE test (a INT NOT NULL AUTO_INCREMENT,
->PRIMARY KEY (a), KEY(b))
->ENGINE=MyISAM SELECT b,c FROM test2;
Hierbei wird eine MyISAM
-Tabelle mit drei
Spalten a
, b
und
c
erstellt. Beachten Sie, dass die Spalten
aus der SELECT
-Anweisung rechts an die
Tabelle angehängt und nicht in diese eingesetzt werden.
Betrachten Sie einmal das folgende Beispiel:
mysql>SELECT * FROM foo;
+---+ | n | +---+ | 1 | +---+ mysql>CREATE TABLE bar (m INT) SELECT n FROM foo;
Query OK, 1 row affected (0.02 sec) Records: 1 Duplicates: 0 Warnings: 0 mysql>SELECT * FROM bar;
+------+---+ | m | n | +------+---+ | NULL | 1 | +------+---+ 1 row in set (0.00 sec)
Für jeden Datensatz in der Tabelle foo
wird
ein Datensatz in bar
mit den Werten aus
foo
und den Standardwerten bei neuen Spalten
eingefügt.
In einer Tabelle, die mit CREATE TABLE ...
SELECT
erstellt wurde, erscheinen die Spalten, die im
CREATE TABLE
-Teil genannt werden, zuerst. Die
in beiden Teilen oder nur im SELECT
-Teil
genannten Spalten folgen nach. Der Datentyp der
SELECT
-Spalten kann außer Kraft gesetzt
werden, indem die Spalte zusätzlich im CREATE
TABLE
-Teil genannt wird.
Wenn während des Kopierens der Daten in die Tabelle Fehler auftreten, wird diese automatisch gelöscht und nicht erstellt.
CREATE TABLE ... SELECT
erstellt keine
automatischen Indizes. Dies wurde bewusst so eingerichtet, um
die Anweisung so flexibel wie möglich zu halten. Wenn Sie
wollen, dass Indizes in der Tabelle erstellt werden, müssen Sie
diese vor der SELECT
-Anweisung spezifizieren:
mysql> CREATE TABLE bar (UNIQUE (n)) SELECT n FROM foo;
Es kann dadurch zu Fällen von Datentypkonvertierung kommen. So
wird z. B. das AUTO_INCREMENT
-Attribut nicht
beibehalten, und VARCHAR
-Spalten können in
CHAR
-Spalten umgewandelt werden.
Wenn Sie eine Tabelle mit CREATE ... SELECT
erstellen, müssen Sie in jedem Fall Aliase für
Funktionsaufrufe oder Ausdrücke in der Abfrage verwenden.
Andernfalls kann die CREATE
-Anweisung
fehlschlagen, oder es können unerwünschte Spaltennamen
entstehen.
CREATE TABLE artists_and_works SELECT artist.name, COUNT(work.artist_id) AS number_of_works FROM artist LEFT JOIN work ON artist.id = work.artist_id GROUP BY artist.id;
Sie können den Typ einer erzeugten Spalte auch explizit angeben:
CREATE TABLE foo (a TINYINT NOT NULL) SELECT b+1 AS a FROM bar;
Mit LIKE
können Sie eine leere Tabelle
basierend auf der Definition einer anderen Tabelle
einschließlich aller Spaltenattribute und Indizes erstellen,
die auch in der Ursprungstabelle vorhanden sind:
CREATE TABLEnew_tbl
LIKEorig_tbl
;
CREATE TABLE ... LIKE
behält weder für die
Ursprungstabelle angegebene DATA DIRECTORY
-
und INDEX DIRECTORY
-Optionen noch
Fremdschlüsseldefinitionen bei.
Sie können dem SELECT
ein
IGNORE
oder REPLACE
voranstellen, um anzugeben, wie mit Datensätzen zu verfahren
ist, in denen Dubletten für eindeutige Schlüssel auftreten.
Bei IGNORE
werden neue Datensätze, die eine
Dublette eines eindeutigen Schlüssels für einen bereits
vorhandenen Datensatz enthalten, einfach verworfen. Wenn Sie
REPLACE
angeben, ersetzen die neuen die
vorhandenen Datensätze, die denselben eindeutigen
Schlüsselwert aufweisen. Werden weder IGNORE
noch REPLACE
angegeben, dann führt das
Auftreten von Dubletten eindeutiger Schlüssel zu einem Fehler.
Um sicherzustellen, dass das Binärlog zur Wiederherstellung der
Originaltabellen verwendet werden kann, gestattet MySQL keine
gleichzeitigen Einfügeoperationen während der Ausführung
einer CREATE TABLE ... SELECT
-Anweisung.
DROP {DATABASE | SCHEMA} [IF EXISTS] db_name
DROP DATABASE
löscht alle Tabellen in der
Datenbank und nachfolgend auch die Datenbank. Seien Sie im
Umgang mit dieser Anweisung extrem
sorgfältig! Um DROP DATABASE
verwenden zu
können, benötigen Sie die Berechtigung DROP
für die Datenbank. DROP SCHEMA
ist ein
Synonym für DROP DATABASE
.
IF EXISTS
wird verwendet, um einen Fehler
abzufangen, wenn die Datenbank nicht vorhanden ist.
Wenn Sie DROP DATABASE
für eine symbolisch
verknüpfte Datenbank verwenden, werden sowohl die Verknüpfung
als auch die Originaldatenbank gelöscht.
DROP DATABASE
gibt die Anzahl der entfernten
Tabellen zurück. Diese entspricht der Anzahl der gelöschten
.frm
-Dateien.
Die DROP DATABASE
-Anweisung entfernt jene
Dateien und Verzeichnisse, die MySQL im normalen Betrieb selbst
erstellt hat, aus dem angegebenen Datenbankverzeichnis:
Alle Dateien mit den folgenden Erweiterungen:
.BAK | .DAT | .HSH |
.MRG | .MYD | .ISD |
.MYI | .db | .frm |
Alle Unterverzeichnisse mit Namen, die aus zwei
Hexadezimalstellen
(00
-ff
) bestehen. Dies
sind Unterverzeichnisse, die für
RAID
-Tabellen verwendet werden. (Diese
Verzeichnisse werden ab MySQL 5.0 nicht entfernt, weil die
Unterstützung für RAID
-Tabellen
aufgehoben wurde. Sie sollten alle vorhandenen
RAID
-Tabellen konvertieren und diese
Verzeichnisse manuell entfernen, bevor Sie auf MySQL 5.0
oder höher aktualisieren. Weitere Informationen finden Sie
im Abschnitt zur Aktualisierung von früheren Releases auf
MySQL 5.0 im MySQL 5.0 Reference Manual, welches auf der
MySQL-Website erhältlich ist.)
Datei db.opt
(sofern vorhanden).
Wenn andere Dateien oder Verzeichnisse im Datenbankverzeichnis
zurückbleiben, nachdem MySQL die genannten Elemente entfernt
hat, kann das Datenbankverzeichnis nicht gelöscht werden. In
diesem Fall müssen Sie alle verbleibenden Dateien oder
Verzeichnisse manuell entfernen und die DROP
DATABASE
-Anweisung nachfolgend erneut absetzen.
Sie können Datenbanken auch mit mysqladmin löschen. Siehe auch Abschnitt 8.7, „mysqladmin — Client für die Verwaltung eines MySQL Servers“.
DROP INDEXindex_name
ONtbl_name
DROP INDEX
löscht den Index namens
index_name
aus der Tabelle
tbl_name
. Diese Anweisung wird einer
ALTER TABLE
-Anweisung zugewiesen, die den
Index löscht. Siehe auch Abschnitt 13.1.2, „ALTER TABLE
“.
DROP [TEMPORARY] TABLE [IF EXISTS]tbl_name
[,tbl_name
] ... [RESTRICT | CASCADE]
DROP TABLE
löscht eine oder mehrere
Tabellen. Für jede Tabelle benötigen Sie die Berechtigung
DROP
. Alle Tabellendaten und die
Tabellendefinition werden entfernt! Seien
Sie also auch im Umgang mit dieser Anweisung sehr
vorsichtig!
Beachten Sie, dass DROP TABLE
bei einer
partitionierten Tabelle die Tabellendefinition, alle Partitionen
und alle in diesen Partitionen gespeicherten Daten permanent
entfernt. Ebenso gelöscht wird die
Partitionierungsdefinitiondatei (.par
) der
gelöschten Tabelle.
Verwenden Sie IF EXISTS
, um einen Fehler bei
Tabellen abzufangen, die nicht vorhanden sind. Für jede nicht
vorhandene Tabelle wird ein Hinweis erzeugt, wenn Sie
IF EXISTS
benutzen. Siehe auch
Abschnitt 13.5.4.25, „SHOW WARNINGS
“.
RESTRICT
und CASCADE
erlauben eine leichtere Portierung. Derzeit haben sie aber keine
Funktion.
Hinweis: DROP
TABLE
übergibt die derzeit aktive Transaktion sofort,
sofern Sie nicht das Schlüsselwort TEMPORARY
benutzen.
Das Schlüsselwort TEMPORARY
hat die
folgenden Auswirkungen:
Die Anweisung löscht nur Temporärtabellen.
Die Anweisung beendet keine laufende Transaktion.
Zugriffsrechte werden nicht geprüft. (Eine Temporärtabelle ist nur für den Client sichtbar, der sie erstellt hat; insofern ist eine Überprüfung unnötig.)
Die Verwendung von TEMPORARY
ist eine gute
Möglichkeit, sicherzustellen, dass Sie nicht versehentlich eine
nichttemporäre Tabelle löschen.
RENAME TABLEtbl_name
TOnew_tbl_name
[,tbl_name2
TOnew_tbl_name2
] ...
Mit dieser Anweisung werden eine oder mehrere Tabellen umbenannt.
Der Umbenennungsvorgang erfolgt automatisch, d. h., kein
anderer Thread kann währenddessen auf die umzubenennende(n)
Tabelle(n) zugreifen. Wenn Sie beispielsweise eine Tabelle
old_table
haben, können Sie eine andere
Tabelle new_table
erstellen, die dieselbe
Struktur hat, aber leer ist, und die vorhandene Tabelle dann wie
folgt durch die leere Tabelle ersetzen (sofern
backup_table
nicht bereits vorhanden ist):
CREATE TABLE new_table (...); RENAME TABLE old_table TO backup_table, new_table TO old_table;
Wenn die Anweisung mehrere Tabellen umbenennt, erfolgen die
Umbenennungen von links nach rechts. Wollen Sie zwei
Tabellennamen gegeneinander austauschen, dann können Sie dies
wie folgt tun (sofern tmp_table
nicht bereits
vorhanden ist):
RENAME TABLE old_table TO tmp_table, new_table TO old_table, tmp_table TO new_table;
Solange zwei Datenbanken sich im selben Dateisystem befinden,
können Sie mit RENAME TABLE
auch eine
Tabelle von einer Datenbank in eine andere verschieben:
RENAME TABLEcurrent_db.tbl_name
TOother_db.tbl_name;
RENAME TABLE
funktioniert auch bei Views,
solange Sie nicht versuchen, einen View in einer anderen
Datenbank umzubenennen.
Wenn Sie RENAME
ausführen, dürfen keine
Tabellen gesperrt und keine Transaktionen aktiv sein. Sie
benötigen für die Ursprungstabelle ferner die Berechtigungen
ALTER
und DROP
sowie die
Berechtigungen CREATE
und
INSERT
für die neue Tabelle.
Wenn MySQL in einer tabellenübergreifenden Umbenennungsaktion auf Fehler trifft, wird für alle umbenannten Tabellen eine umgekehrte Umbenennung durchgeführt, um den ursprünglichen Zustand wiederherzustellen.
Syntax für eine Tabelle:
DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROMtbl_name
[WHEREwhere_condition
] [ORDER BY ...] [LIMITrow_count
]
Syntax für mehrere Tabellen:
DELETE [LOW_PRIORITY] [QUICK] [IGNORE]tbl_name
[.*] [,tbl_name
[.*]] ... FROMtable_references
[WHEREwhere_condition
]
Oder:
DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROMtbl_name
[.*] [,tbl_name
[.*]] ... USINGtable_references
[WHEREwhere_condition
]
Bei der Ein-Tabellen-Syntax löscht die
DELETE
-Anweisung Datensätze aus
tbl_name
und gibt die Anzahl
gelöschter Datensätze zurück. Sofern angegeben, bestimmt die
WHERE
-Klausel die Bedingungen dafür, welche
Datensätze gelöscht werden. Ohne
WHERE
-Klausel werden alle Datensätze
gelöscht. Wenn die ORDER BY
-Klausel
vorhanden ist, werden die Datensätze in der angegebenen
Reihenfolge gelöscht. Die LIMIT
-Klausel kann
die Anzahl der zu löschenden Datensätze beschränken.
Bei der Mehrtabellensyntax löscht DELETE
aus
jeder Tabelle tbl_name
die
Datensätze, die die Bedingungen erfüllen. In diesem Fall
können ORDER BY
und LIMIT
nicht verwendet werden.
where_condition
ist ein Ausdruck, der
für jeden zu löschenden Datensatz wahr ist. Er wird wie in
Abschnitt 13.2.7, „SELECT
“, beschrieben angegeben.
Wie bereits gesagt, löscht eine
DELETE
-Anweisung ohne
WHERE
-Klausel alle Datensätze. Wenn Sie die
Anzahl der gelöschten Datensätze nicht kennen müssen, können
Sie dies schneller mit TRUNCATE TABLE
erledigen. Siehe auch Abschnitt 13.2.9, „TRUNCATE
“.
Wenn Sie den Datensatz entfernen, der den höchsten Wert für
eine AUTO_INCREMENT
-Spalte hat, dann wird der
Wert bei BDB
-Tabellen später
wiederverwendet, nicht jedoch bei MyISAM
-
oder InnoDB
-Tabellen. Wenn Sie im
AUTOCOMMIT
-Modus alle Datensätze in der
Tabelle mit DELETE FROM
(ohne
tbl_name
WHERE
-Klausel) löschen, beginnt die Sequenz
für alle Speicher-Engines mit Ausnahme von
InnoDB
und MyISAM
neu. Bei
InnoDB
-Tabellen gibt es bezüglich dieses
Verhaltens ein paar Ausnahmen, die in
Abschnitt 14.2.6.3, „Wie eine Auto-Increment-Spalte in InnoDB funktioniert“, beschrieben
sind.
Bei MyISAM
- und
BDB
-Tabellen können Sie
AUTO_INCREMENT
in einer Sekundärspalte eines
mehrspaltigen Schlüssels angeben. In diesem Fall werden Werte,
die am Anfang der Sequenz gelöscht wurden, auch bei
MyISAM
-Tabellen wiederverwendet. Siehe auch
Abschnitt 3.6.9, „Verwendung von AUTO_INCREMENT
“.
Die DELETE
-Anweisung unterstützt die
folgenden Modifizierer:
Wenn Sie LOW_PRIORITY
angeben, verzögert
der Server die Ausführung von DELETE
,
bis kein Client mehr aus der Tabelle liest.
Wenn Sie bei MyISAM
-Tabellen das
Schlüsselwort QUICK
angeben, fasst die
Speicher-Engine beim Löschen Indexzweige nicht zusammen.
Dies kann bestimmte Arten von Löschvorgängen
beschleunigen.
Das Schlüsselwort IGNORE
bewirkt, dass
MySQL alle Fehler während des Vorgangs der
Datensatzlöschung ignoriert. (Fehler, die bei der Analyse
auftreten, werden allerdings wie gewöhnlich verarbeitet.)
Fehler, die aufgrund der Verwendung von
OPTION
ignoriert werden, werden als
Warnungen zurückgegeben.
Die Geschwindigkeit von Löschoperationen kann auch von den
Faktoren beeinflusst werden, die in
Abschnitt 7.2.18, „Geschwindigkeit von DELETE
-Anfragen“, beschrieben werden.
Bei MyISAM
-Tabellen werden gelöschte
Datensätze zu einer verknüpften Liste hinzugefügt.
Nachfolgende INSERT
-Operationen verwenden die
alten Datensatzpositionen neu. Um ungenutzten Speicher wieder
freizugeben und die Dateigrößen zu verringern, verwenden Sie
die OPTIMIZE TABLE
-Anweisung oder das
Hilfsprogramm myisamchk zur Reorganisierung
der Tabellen. OPTIMIZE TABLE
ist einfacher,
myisamchk hingegen schneller. Siehe auch
Abschnitt 13.5.2.5, „OPTIMIZE TABLE
“, und
Abschnitt 8.2, „myisamchk — Hilfsprogramm für die Tabellenwartung von MyISAM“.
Der Modifizierer QUICK
bestimmt, ob
Indexzweige bei Löschoperationen zusammengefasst werden.
DELETE QUICK
ist am nützlichsten bei
Anwendungen, bei denen Indexwerte für gelöschte Datensätze
durch ähnliche Indexwerte von später eingefügten Datensätzen
ersetzt werden. In diesem Fall werden die von den gelöschten
Werten zurückgelassenen Löcher wiederverwendet.
DELETE QUICK
ist hingegen nicht nützlich,
wenn gelöschte Werte nicht aufgefüllte Indexblöcke zur Folge
haben, die einen Bereich von Indexwerten umfassen, bei denen
neue Einfügeoperationen auftreten. In diesem Fall kann die
Verwendung von QUICK
zur Verschwendung von
Speicher im Index führen, da dieser Speicher nicht mehr
freigegeben wird. Hier ein Beispiel für ein solches Szenario:
Erstellen Sie eine Tabelle, die eine indizierte
AUTO_INCREMENT
-Spalte enthält.
Fügen Sie viele Datensätze in diese Tabelle ein. Jede Einfügeoperation führt dazu, dass ein Indexwert am Ende des Indexes eingefügt wird.
Löschen Sie mit DELETE QUICK
einen Block
mit Datensätzen vorne im Spaltenbereich.
In diesem Szenario werden die Indexblöcke, die mit den
gelöschten Indexwerten verknüpft sind, nicht aufgefüllt, aber
aufgrund der Verwendung von QUICK
auch nicht
mit anderen Indexblöcken zusammengefasst. Sie bleiben also
unaufgefüllt, wenn weitere Einfügeoperationen auftreten, weil
die neuen Datensätze keine Indexwerte im gelöschten Bereich
haben. Außerdem bleiben sie auch dann unaufgefüllt, wenn Sie
später DELETE
ohne QUICK
verwenden, sofern nicht zufällig einige der gelöschten
Indexwerte in Indexblöcken innerhalb oder neben den nicht
aufgefüllten Blöcken liegen. Um ungenutzten Indexspeicher
unter diesen Umständen wieder freizugeben, verwenden Sie
OPTIMIZE TABLE
.
Wenn Sie viele Datensätze aus einer Tabelle zu löschen
beabsichtigen, kann DELETE QUICK
gefolgt von
OPTIMIZE TABLE
die schnellere Lösung sein.
Hierbei wird der Index neu erstellt, statt zahlreiche
Zusammenfassungsoperationen für Indexblöcke auszuführen.
Die MySQL-spezifische Option LIMIT
für
row_count
DELETE
nennt dem Server die maximale Anzahl
Datensätze, die gelöscht werden, bevor die Kontrolle an den
Client zurückgegeben wird. Hiermit können Sie gewährleisten,
dass eine gegebene DELETE
-Anweisung nicht zu
viel Zeit in Anspruch nimmt. Sie können die
DELETE
-Anweisung dann einfach wiederholen,
bis die Gesamtzahl betroffener Datensätze kleiner ist als der
LIMIT
-Wert.
Wenn die DELETE
-Anweisung eine ORDER
BY
-Klausel enthält, werden die Datensätze in der in
der Klausel angegebenen Reihenfolge gelöscht. Dies ist nur in
Verbindung mit LIMIT
wirklich nützlich. Die
folgende Anweisung beispielsweise findet Datensätze, die der
WHERE
-Klausel entsprechen, sortiert sie nach
timestamp_column
und löscht den ersten
(d. h. ältesten) Datensatz:
DELETE FROM somelog WHERE user = 'jcole' ORDER BY timestamp_column LIMIT 1;
Sie können in einer DELETE
-Anweisung mehrere
Tabellen angeben, aus denen je nach Bedingung der
WHERE
-Klausel Datensätze gelöscht werden.
Allerdings können Sie ORDER BY
oder
LIMIT
nicht in einer
DELETE
-Anweisung für mehrere Tabellen
verwenden. Die Klausel
table_references
listet die Tabellen
auf, die im Join berücksichtigt werden. Die Syntax ist in
Abschnitt 13.2.7.1, „JOIN
“, beschrieben.
Bei der ersten Mehrtabellensyntax werden nur passende
Datensätze aus den Tabellen gelöscht, die vor der
FROM
-Klausel aufgelistet sind. Bei der
zweiten Mehrtabellensyntax werden nur passende Datensätze aus
den Tabellen gelöscht, die in der
FROM
-Klausel (vor der
USING
-Klausel) aufgelistet sind. Die Folge
ist, dass Sie Datensätze aus vielen Tabellen gleichzeitig
löschen und gleichzeitig in weiteren Tabellen nur suchen lassen
können:
DELETE t1, t2 FROM t1, t2, t3 WHERE t1.id=t2.id AND t2.id=t3.id;
Oder:
DELETE FROM t1, t2 USING t1, t2, t3 WHERE t1.id=t2.id AND t2.id=t3.id;
Diese Anweisungen verwenden auf der Suche nach zu löschenden
Datensätzen alle drei Tabellen, aber gelöscht werden passende
Datensätze tatsächlich nur aus den Tabellen
t1
und t2
.
Die obigen Beispiele zeigen innere Joins, die den Kommaoperator
verwenden. DELETE
-Anweisungen für mehrere
Tabellen können jedoch einen beliebigen Join-Typ verwenden, der
für SELECT
-Anweisungen zulässig ist, also
etwa LEFT JOIN
.
Die Syntax erlaubt .*
nach den Tabellennamen,
um die Kompatibilität mit Access zu gewährleisten.
Wenn Sie eine DELETE
-Anweisung für mehrere
Tabellen verwenden, die auch InnoDB
-Tabellen
einbezieht, für die Fremdschlüssel-Constraints vorhanden sind,
dann verarbeitet der MySQL-Optimierer die Tabellen unter
Umständen in einer Reihenfolge, die sich von der ihrer
Parent/Child-Beziehung unterscheidet. In diesem Fall schlägt
die Anweisung fehl, und es wird ein Rollback durchgeführt.
Stattdessen sollten Sie die Löschoperation dann aus nur einer
Tabelle durchführen und sich auf die ON
DELETE
-Funktionalität verlassen, die
InnoDB
bietet, um andere Tabellen
entsprechend zu ändern.
Hinweis: Wenn Sie einen Alias für eine Tabelle angegeben haben, müssen Sie diesen bei der Referenzierung der Tabelle verwenden:
DELETE t1 FROM test AS t1, test2 WHERE ...
Datenbankübergreifende Löschvorgänge werden von Löschvorgängen für mehrere Tabellen unterstützt. In diesem Fall müssen Sie die Tabellen aber ohne Verwendung von Aliasen referenzieren. Zum Beispiel:
DELETE test1.tmp1, test2.tmp2 FROM test1.tmp1, test2.tmp2 WHERE ...
Zurzeit können Sie in einer Unterabfrage keine Löschoperation in einer Tabelle durchführen und gleichzeitig eine Auswahl in einer anderen Tabelle treffen.
DOexpr
[,expr
] ...
DO
führt Ausdrücke aus, gibt aber keine
Ergebnisse zurück. In den meisten Fällen ist
DO
eine Kurzform von SELECT
, hat aber den
Vorteil, dass es etwas schneller ist, sofern das Ergebnis für
Sie keine Rolle spielt. Allerdings meldet expr
, ...DO
keine Fehler. Stattdessen werden Fehler als Warnungen
ausgegeben.
DO
ist in erster Linie bei Funktionen
praktisch, die Begleiterscheinungen haben (z. B.
RELEASE_LOCK()
).
HANDLERtbl_name
OPEN [ ASalias
] HANDLERtbl_name
READindex_name
{ = | >= | <= | < } (value1
,value2
,...) [ WHEREwhere_condition
] [LIMIT ... ] HANDLERtbl_name
READindex_name
{ FIRST | NEXT | PREV | LAST } [ WHEREwhere_condition
] [LIMIT ... ] HANDLERtbl_name
READ { FIRST | NEXT } [ WHEREwhere_condition
] [LIMIT ... ] HANDLERtbl_name
CLOSE
Die Anweisung HANDLER
bietet direkten Zugriff
auf die Schnittstellen der Speicher-Engine einer Tabelle. Sie
steht für MyISAM
- und
InnoDB
-Tabellen zur Verfügung.
Die Anweisung HANDLER ... OPEN
öffnet eine
Tabelle und gestattet den Zugriff über nachfolgende
HANDLER ... READ
-Anweisungen. Dieses
Tabellenobjekt wird nicht mit anderen Threads gemeinsam genutzt
und wird erst geschlossen, wenn der Thread HANDLER ...
CLOSE
aufruft oder beendet wird. Wenn Sie die Tabelle
unter Verwendung eines Alias öffnen, müssen nachfolgende
Referenzierungen durch andere
HANDLER
-Anweisungen den Alias statt des
Tabellennamens verwenden.
Die erste HANDLER ... READ
-Syntax holt einen
Datensatz, bei dem der angegebene Index den übergebenen Werten
entspricht und die WHERE
-Bedingung erfüllt
ist. Wenn Sie einen mehrspaltigen Index haben, geben Sie die
Indexspaltenwerte als kommagetrennte Liste an. Entweder geben
Sie Werte für alle Spalten im Index oder aber Werte für das
links stehende Präfix der Indexspalten an. Angenommen, ein
Index my_idx
enthält drei Spalten namens
col_a
, col_b
und
col_c
in genau dieser Reihenfolge. Die
Anweisung HANDLER
kann Werte für alle drei
Spalten im Index oder für die Spalten in einem links stehenden
Präfix angeben. Zum Beispiel:
HANDLER ... READ my_idx = (col_a_val,col_b_val,col_c_val) ... HANDLER ... READ my_idx = (col_a_val,col_b_val) ... HANDLER ... READ my_idx = (col_a_val) ...
Um die HANDLER
-Schnittstelle für die
Referenzierung des Primärschlüssels einer Tabelle zu
verwenden, setzen Sie den Bezeichner in Anführungszeichen
(`PRIMARY`
).
HANDLER tbl_name
READ `PRIMARY` ...
Die zweite HANDLER ... READ
-Syntax holt aus
der Tabelle einen Datensatz in der Indexreihenfolge, die der
WHERE
-Bedingung entspricht.
Die dritte HANDLER ... READ
-Syntax holt aus
der Tabelle einen Datensatz in der natürlichen
Datensatzreihenfolge, die der WHERE
-Bedingung
entspricht. Sie ist schneller als HANDLER
, wenn ein
vollständiger Tabellenscan gewünscht wird. Die natürliche
Datensatzreihenfolge ist die Reihenfolge, in der die Datensätze
in der Datendatei einer tbl_name
READ
index_name
MyISAM
-Tabelle
gespeichert sind. Diese Anweisung funktioniert auch bei
InnoDB
-Tabellen, aber das Konzept greift hier
in Ermangelung einer separaten Datendatei nicht.
Ohne eine LIMIT
-Klausel holen alle Formen von
HANDLER ... READ
einen einzelnen Datensatz
(sofern vorhanden). Um eine bestimmte Anzahl Datensätze
zurückzugeben, fügen Sie eine LIMIT
-Klausel
ein. Sie hat dieselbe Syntax wie bei der
SELECT
-Anweisung. Siehe auch
Abschnitt 13.2.7, „SELECT
“.
HANDLER ... CLOSE
schließt eine Tabelle, die
mit HANDLER ... OPEN
geöffnet worden war.
HANDLER
ist eine etwas maschinennahe
Anweisung. Sie bietet z. B. keine Konsistenz: HANDLER
... OPEN
fertigt keine
Momentaufnahme der Tabelle an und sperrt sie
nicht. Das bedeutet, dass, nachdem eine
HANDLER ... OPEN
-Anweisung abgesetzt wurde,
die Tabellendaten (vom aktuellen, aber auch von anderen Threads)
modifiziert werden können und diese Änderungen dann für
HANDLER ... NEXT
- oder HANDLER ...
PREV
-Scans unter Umständen nur teilweise sichtbar
sind.
Es gibt eine Reihe von Gründen zur Verwendung der
HANDLER
-Schnittstelle anstelle einer normalen
SELECT
-Anweisung:
HANDLER
ist schneller als
SELECT
:
Für HANDLER ... OPEN
wird ein
dediziertes Speicher-Engine-spezifisches Handler-Objekt
reserviert. Das Objekt wird bei nachfolgenden
HANDLER
-Anweisungen für diese
Tabelle wiederverwendet; es muss nicht jeweils neu
initialisiert werden.
Der Analyseaufwand ist geringer.
Es ist kein zusätzlicher Aufwand für den Optimierer oder die Abfrageüberprüfung erforderlich.
Die Tabelle muss nicht zwischen zwei Handler-Anforderungen gesperrt werden.
Die Handler-Schnittstelle muss keine konsistente Sicht
der Daten bieten (Dirty Reads beispielsweise sind
zulässig) – die Speicher-Engine kann also
Optimierungen verwenden, die SELECT
normalerweise nicht zulassen würde.
Bei Anwendungen, die eine maschinennahe
ISAM
-artige Schnittstelle verwenden,
erleichtert HANDLER
deren Portierung auf
MySQL.
HANDLER
erlaubt Ihnen das Durchlaufen
einer Datenbank auf eine Weise, die mit
SELECT
– wenn überhaupt – nur sehr
schwierig zu realisieren ist. Die
HANDLER
-Schnittstelle ist eine
natürlicher anmutende Art der Datensicht, wenn Sie mit
Anwendungen arbeiten, die eine interaktive
Benutzeroberfläche für die Datenbank bereitstellen.
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE] [INTO]tbl_name
[(col_name
,...)] VALUES ({expr
| DEFAULT},...),(...),... [ ON DUPLICATE KEY UPDATEcol_name
=expr
, ... ]
Oder:
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE] [INTO]tbl_name
SETcol_name
={expr
| DEFAULT}, ... [ ON DUPLICATE KEY UPDATEcol_name
=expr
, ... ]
Oder:
INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE] [INTO]tbl_name
[(col_name
,...)] SELECT ... [ ON DUPLICATE KEY UPDATEcol_name
=expr
, ... ]
INSERT
fügt neue Datensätze in eine
vorhandene Tabelle ein. Die Formen INSERT ...
VALUES
und INSERT ... SET
der
Anweisung fügen Datensätze basierend auf explizit angegebenen
Werten ein. Die Form INSERT ... SELECT
fügt
Datensätze ein, die in einer oder mehreren anderen Tabellen
ausgewählt wurden. INSERT ... SELECT
wird in
Abschnitt 13.2.4.1, „INSERT ... SELECT
“, näher erläutert.
Sie können REPLACE
anstelle von
INSERT
verwenden, um alte Datensätze zu
überschreiben. REPLACE
ist das Gegenstück
zu INSERT IGNORE
bei der Behandlung neuer
Datensätze, deren eindeutige Schlüsselwerte Dubletten bereits
vorhandener Datensätze sind: Die neuen Datensätze ersetzen die
alten, statt verworfen zu werden. Siehe auch
Abschnitt 13.2.6, „REPLACE
“.
tbl_name
ist die Tabelle, in die die
Datensätze eingefügt werden sollen. Die Spalten, für die die
Anweisung Werte angibt, lassen sich wie folgt angeben:
Sie können eine kommagetrennte Liste von Spaltennamen
gefolgt vom Tabellennamen angeben. In diesem Fall muss für
jede genannte Spalte in der VALUES
-Liste
oder der SELECT
-Anweisung ein Wert
vorhanden sein.
Wenn Sie keine Liste mit Spaltennamen für INSERT
... VALUES
oder INSERT ...
SELECT
angeben, dann müssen die Werte für alle
Spalten in der Tabelle in der
VALUES
-Liste oder der
SELECT
-Anweisung vorhanden sein. Wenn Sie
die Reihenfolge der Spalten in der Tabelle nicht kennen,
ermitteln Sie sie mit DESCRIBE
.
tbl_name
Die SET
-Klausel gibt die Spaltennamen
ausdrücklich an.
Spaltenwerte lassen sich auf mehrerlei Weise übergeben:
Wenn Sie MySQL nicht im strikten SQL-Modus ausführen, dann wird jede Spalte, für die kein Wert angegeben wird, auf den (expliziten oder impliziten) Standardwert gesetzt. Wenn Sie also etwa eine Spaltenliste angeben, die nicht alle Spalten in der Tabelle aufführt, werden nicht genannte Spalten auf ihre jeweiligen Standardwerte gesetzt. Die Zuweisung von Standardwerten ist in Abschnitt 11.1.4, „Vorgabewerte von Datentypen“, beschrieben. Siehe auch Abschnitt 1.9.6.2, „Constraints auf ungültigen Daten“.
Wenn Sie wollen, dass eine
INSERT
-Anweisung einen Fehler erzeugt,
wenn Sie nicht alle Werte für alle Spalten ausdrücklich
angeben, für die kein Standardwert vorhanden ist, dann
sollten Sie den strikten Modus verwenden. Siehe auch
Abschnitt 5.2.5, „Der SQL-Modus des Servers“.
Mit dem Schlüsselwort DEFAULT
können
Sie eine Spalte explizit auf ihren Standardwert setzen. Dies
erleichtert das Formulieren von
INSERT
-Anweisungen, die allen Spalten
(bis auf einigen wenigen) Werte zuweisen, denn so brauchen
Sie keine unvollständige VALUES
-Liste zu
erstellen, die nicht für jede Spalte in der Tabelle einen
Wert enthält. Andernfalls müssten Sie die Liste der
Spaltennamen ausschreiben, die den einzelnen Werten in der
VALUES
-Liste entspricht.
Sie können auch
DEFAULT(
als eine allgemeinere Form benutzen, mit der in Ausdrücken
der Standardwert einer gegebenen Spalte erzeugt werden kann.
col_name
)
Wenn sowohl die Spaltenliste als auch die
VALUES
-Liste leer sind, erstellt
INSERT
einen Datensatz, bei dem jede
Spalte auf den jeweiligen Standardwert gesetzt ist:
INSERT INTO tbl_name
() VALUES();
Im strikten Modus tritt ein Fehler auf, wenn nicht für jede Spalte ein Standardwert angegeben ist. Andernfalls verwendet MySQL den impliziten Standardwert für jede Spalte, der kein expliziter Wert zugewiesen ist.
Sie können den Spaltenwert auch durch einen Ausdruck
expr
angeben. Dies kann eine
Typenkonvertierung bedingen, wenn der Ausdruckstyp nicht dem
Typ der Spalte entspricht. Die Konvertierung eines gegebenen
Werts kann je nach Datentyp zu unterschiedlichen
Einfügewerten führen. So hat z. B. das Einfügen des
Strings '1999.0e-2'
in eine
INT
-. FLOAT
-,
DECIMAL(10,6)
- oder
YEAR
-Spalte die Einfügewerte
1999
, 19.9921
,
19.992100
bzw. 1999
zur Folge. Der Grund dafür, dass der in den
INT
- und YEAR
-Spalten
gespeicherte Wert 1999
ist, besteht
darin, dass bei der Konvertierung des Strings in den Integer
nur der Teil des Strings berücksichtigt wird, der als
gültiger Integer bzw. als sinnvolle Jahresangabe betrachtet
wird. Bei Fließkomma- und Festkommaspalten wird bei der
Umwandlung des Strings in einen Fließkommawert der gesamte
String als zulässiger Fließkommawert betrachtet.
Ein Ausdruck expr
kann jede
Spalte referenzieren, die zuvor in einer Werteliste
eingestellt wurde. Sie könnten dies beispielsweise tun,
weil der Wert von col2
die zuvor
zugewiesene Spalte col1
referenziert:
INSERT INTO tbl_name
(col1,col2) VALUES(15,col1*2);
Die folgende Variante ist jedoch nicht zulässig, weil der
Wert für col1
die Spalte
col2
referenziert, die jedoch erst nach
col1
zugewiesen wurde:
INSERT INTO tbl_name
(col1,col2) VALUES(col2*2,15);
Eine Ausnahme betrifft Spalten, die
AUTO_INCREMENT
-Werte enthalten. Weil der
AUTO_INCREMENT
-Wert nach anderen
Wertezuweisungen erzeugt wird, gibt eine Referenzierung
einer AUTO_INCREMENT
-Spalte
0
zurück.
INSERT
-Anweisungen, die die
VALUES
-Syntax verwenden, können mehrere
Datensätze einfügen. Zu diesem Zweck fügen Sie mehrere Listen
mit Spaltenwerten ein, die jeweils in Klammern gesetzt und durch
Kommata getrennt sind. Beispiel:
INSERT INTO tbl_name
(a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);
Die Werteliste für jeden Datensatz muss in Klammern gesetzt werden. Die folgende Anweisung ist unzulässig, weil die Anzahl der Werte in der Liste nicht der Anzahl der Spaltennamen entspricht:
INSERT INTO tbl_name
(a,b,c) VALUES(1,2,3,4,5,6,7,8,9);
Der Wert der von einer INSERT
-Anweisung
betroffenen Datensätze kann mit der C-API-Funktion
mysql_affected_rows()
ermittelt werden. Siehe
auch Abschnitt 24.2.3.1, „mysql_affected_rows()
“.
Wenn Sie eine INSERT ... VALUES
-Anweisung mit
mehreren Wertelisten oder INSERT ... SELECT
verwenden, gibt die Anweisung einen Informations-String im
folgenden Format zurück:
Records: 100 Duplicates: 0 Warnings: 0
Records
gibt die Anzahl der von der Anweisung
verarbeiteten Datensätze zurück. (Dies entspricht nicht
unbedingt der Anzahl der tatsächlich eingefügten Datensätze,
weil Duplicates
auch ungleich null sein
kann.) Duplicates
gibt die Anzahl der
Datensätze an, die nicht eingefügt wurden, weil eindeutige
Schlüsselwerte andernfalls dupliziert worden wären.
Warnings
gibt die Anzahl der
Spalteneinfügeversuche an, die aus irgendeinem Grund
problematisch waren. Warnungen können unter den folgenden
Umständen auftreten:
Einfügen von NULL
in eine Spalte, die
als NOT NULL
deklariert wurde. Bei
INSERT
-Anweisung für mehrere Datensätze
oder INSERT INTO ... SELECT
-Anweisungen
wird die Spalte auf den impliziten Standardwert für den
betreffenden Spaltendatentyp gesetzt. Bei numerischen Typen
ist dies 0
, bei String-Typen der
Leer-String (''
) und der
„Nullwert“ bei Datums- und Uhrzeittypen.
INSERT INTO ... SELECT
-Anweisungen werden
auf die gleiche Weise behandelt wie Einfügeoperationen für
mehrere Datensätze, weil der Server die Ergebnismenge von
SELECT
nicht darauf überprüft, ob genau
ein Datensatz zurückgegeben wird. (Bei
INSERT
-Anweisungen für nur einen
Datensatz erscheint keine Warnung, wenn
NULL
in eine NOT
NULL
-Spalte eingefügt wird. Stattdessen schlägt
die Anweisung mit einem Fehler fehl.)
Setzen einer numerischen Spalte auf einen Wert außerhalb des zulässigen Wertebereichs. Der Wert wird auf den nächstgelegenen Endpunkt des Bereichs gesetzt.
Zuweisen eines Werts wie '10.34 a'
zu
einer numerischen Spalte. Der nichtnumerische Text am Ende
wird entfernt, und der verbleibende numerische Teil wird
eingefügt. Hat der String-Wert am Anfang keinen numerischen
Teil, dann wird die Spalte auf 0
gesetzt.
Einfügen eines Strings in eine String-Spalte
(CHAR
, VARCHAR
,
TEXT
oder BLOB
), die
die maximale Länge der Spalte überschreitet. Der Wert wird
auf die zulässige Maximallänge der Spalte gekürzt.
Einfügen eines Werts in eine Spalte für Datum oder Uhrzeit, der für diesen Datentyp nicht zulässig ist. Die Spalte wird auf den passenden Nullwert des Typs gesetzt.
Wenn Sie die C-API verwenden, kann der Informations-String durch
Aufruf der Funktion mysql_info()
ermittelt
werden. Siehe auch Abschnitt 24.2.3.34, „mysql_info()
“.
Wenn INSERT
einen Datensatz in eine Tabelle
einfügt, die eine AUTO_INCREMENT
-Spalte
enthält, dann können Sie den Wert dieser Spalte mithilfe der
SQL-Funktion LAST_INSERT_ID()
abfragen. Aus
der C-API heraus verwenden Sie die Funktion
mysql_insert_id()
. Sie sollten allerdings
beachten, dass die beiden Funktionen sich nicht immer identisch
verhalten. Das Verhalten von
INSERT
-Anweisungen in Bezug auf
AUTO_INCREMENT
-Spalten wird in
Abschnitt 12.10.3, „Informationsfunktionen“, und
Abschnitt 24.2.3.36, „mysql_insert_id()
“, ausführlicher beschrieben.
Die INSERT
-Anweisung unterstützt die
folgenden Modifizierer:
Wenn Sie das Schlüsselwort DELAYED
verwenden, legt der Server den oder die einzufügenden
Datensätze in einem Puffer ab, und der Client, der die
INSERT DELAYED
-Anweisung abgesetzt hat,
kann sofort weiterarbeiten. Wird die Tabelle gerade
verwendet, dann hält der Server die Datensätze zurück.
Sobald die Tabelle frei ist, startet der Server mit dem
Einfügen der Datensätze und prüft dabei periodisch, ob
neue Leseanforderungen für die Tabelle anstehen. In diesem
Fall wird die Warteschlange mit den verzögerten
Datensätzen angehalten, bis die Tabelle wieder frei wird.
Siehe auch Abschnitt 13.2.4.2, „INSERT DELAYED
“.
DELAYED
wird bei INSERT ...
SELECT
oder INSERT ... ON DUPLICATE KEY
UPDATE
ignoriert.
Wenn Sie das Schlüsselwort LOW_PRIORITY
angeben, wird die Ausführung von INSERT
verzögert, bis kein Client mehr aus der Tabelle liest. Dies
schließt andere Clients mit ein, die Leseoperationen
starten, während bereits vorhandene Clients aus der Tabelle
lesen und die INSERT
LOW_PRIORITY
-Anweisung wartet. Aus diesem Grund
ist es möglich, dass ein Client, der eine INSERT
LOW_PRIORITY
-Anweisung absetzt, sehr lange warten
muss – in Umgebungen mit extrem hohen Aufkommen von
Leseoperationen sogar für immer. (Dies steht im Gegensatz
zu INSERT DELAYED
, wo der Client direkt
fortfahren kann.) Beachten Sie, dass
LOW_PRIORITY
normalerweise nicht bei
MyISAM
-Tabellen benutzt werden sollte, da
auf diese Weise gleichzeitige Einfügeoperationen unmöglich
gemacht werden. Siehe auch
Abschnitt 7.3.3, „Gleichzeitige Einfügevorgänge“.
Wenn Sie HIGH_PRIORITY
angeben, setzt es
die Auswirkungen der Option
--low-priority-updates
außer Kraft, sofern
der Server mit dieser Option gestartet worden war. Außerdem
sind auch hier gleichzeitige Einfügeoperationen nicht
möglich.
Wenn Sie das Schlüsselwort IGNORE
angeben, werden Fehler, die während der Ausführung der
INSERT
-Anweisung auftreten, als Warnungen
behandelt. So würde beispielsweise ohne
IGNORE
ein Datensatz, der einen
vorhandenen eindeutigen Index oder einen
Primärschlüsselwert in der Tabelle dupliziert, einen
Dublettenfehler verursachen, woraufhin die Anweisung
abgebrochen würde. Bei IGNORE
wird der
Datensatz zwar auch nicht eingefügt, aber es wird kein
Fehler ausgegeben. Bei Fehler auslösenden
Datenkonvertierungen wird die Anweisung abgebrochen, wenn
IGNORE
nicht angegeben ist. Bei
IGNORE
hingegen werden ungültige Werte
auf den jeweils nächstgelegenen gültigen Wert gesetzt und
dann einfügt; außerdem werden Warnungen erzeugt, aber die
Anweisung wird nicht abgebrochen. Mit der C-API-Funktion
mysql_info()
können Sie ermitteln, wie
viele Datensätze tatsächlich in die Tabelle eingefügt
wurden.
Wenn Sie ON DUPLICATE KEY UPDATE
angeben
und ein Datensatz eingefügt wird, der einen doppelten Wert
in einem eindeutigen Index oder einem Primärschlüssel
erzeugen würde, dann wird für den alten Datensatz
UPDATE
ausgeführt. Siehe auch
Abschnitt 13.2.4.3, „INSERT ... ON DUPLICATE KEY UPDATE
“.
INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE] [INTO]tbl_name
[(col_name
,...)] SELECT ... [ ON DUPLICATE KEY UPDATEcol_name
=expr
, ... ]
Mit INSERT ... SELECT
können Sie schnell
mehrere Datensätze aus einer oder mehreren Tabellen in eine
Tabelle einfügen. Zum Beispiel:
INSERT INTO tbl_temp2 (fld_id) SELECT tbl_temp1.fld_order_id FROM tbl_temp1 WHERE tbl_temp1.fld_order_id > 100;
Die folgenden Bedingungen gelten für eine INSERT ...
SELECT
-Anweisung:
Geben Sie IGNORE
an, um Datensätze zu
ignorieren, die unzulässige Schlüsseldubletten erzeugen
würden.
DELAYED
wird bei INSERT ...
SELECT
ignoriert.
Die Zieltabelle der INSERT
-Anweisung
kann in der FROM
-Klausel des
SELECT
-Teils der Abfrage erscheinen.
(Dies war bei einigen älteren MySQL-Versionen nicht
möglich.)
AUTO_INCREMENT
-Spalten arbeiten wie
gewöhnlich.
Um sicherzustellen, dass das Binärlog zur
Wiederherstellung der Originaltabellen verwendet werden
kann, gestattet MySQL keine nebenläufigen
Einfügeoperationen während der Ausführung einer
INSERT ... SELECT
-Anweisung.
Zurzeit können Sie in einer Unterabfrage keine Einfügeoperation in eine Tabelle durchführen und gleichzeitig eine Auswahl in einer anderen Tabelle treffen.
Im Werteteil von ON DUPLICATE KEY UPDATE
können Sie Spalten in anderen Tabellen referenzieren, solange
Sie im SELECT
-Teil nicht GROUP
BY
verwenden. Eine Begleiterscheinung besteht darin,
dass Sie nichteindeutige Spaltennamen im Werteteil
qualifizieren müssen.
INSERT DELAYED ...
Die Option DELAYED
für die
INSERT
-Anweisung ist eine MySQL-Erweiterung
zum SQL-Standard, die sehr praktisch ist, wenn Sie Clients
haben, die nicht auf den Abschluss der
INSERT
-Anweisung warten können oder
müssen. Eine solche Situation liegt häufig vor, wenn Sie
MySQL zum Loggen verwenden und zudem regelmäßig
SELECT
- und
UPDATE
-Anweisungen ausführen, deren
Fertigstellung sehr lange dauert.
Wenn ein Client INSERT DELAYED
verwendet,
wird diese Anweisung vom Server sofort angenommen und der
Datensatz in einer Warteschlange abgelegt. Sobald die Tabelle
von keinem anderen Thread mehr verwendet wird, wird der
Datensatz dann aus der Warteschlange eingefügt.
Ein weiterer wesentlicher Vorteil von INSERT
DELAYED
besteht darin, dass Einfügeoperationen
mehrerer Clients gebündelt und dann in einem Block
geschrieben werden. Dies ist bedeutend schneller als die
Durchführung vieler separater Einfügeoperationen.
Beachten Sie, dass INSERT DELAYED
, sofern
die Tabelle gerade nicht anderweitig verwendet wird, langsamer
als eine normale INSERT
-Anweisung ist. Auch
liegt die Serverbelastung etwas höher, weil der Server für
jede Tabelle, für die verzögerte Datensätze vorhanden sind,
einen separaten Thread verwalten muss. Insofern sollten Sie
INSERT DELAYED
nur verwenden, wenn Sie
wirklich sicher sind, dass Sie die Funktionalität benötigen.
Die Datensätze in der Warteschlange verbleiben nur solange im
Speicher, bis sie in die Tabelle eingefügt wurden. Aufgrund
dessen gehen, wenn Sie mysqld – etwa mit
kill -9
– terminieren oder
mysqld unerwartet abstürzt, alle
Datensätze in der Warteschlange, die noch nicht auf
Festplatte geschrieben wurden, verloren!
Für die Verwendung von DELAYED
gelten
einige Einschränkungen:
INSERT DELAYED
funktioniert nur bei
MyISAM
-, MEMORY
- und
ARCHIVE
-Tabellen. Siehe auch
Abschnitt 14.1, „Die MyISAM
-Speicher-Engine“,
Abschnitt 14.4, „Die MEMORY
-Speicher-Engine“ und
Abschnitt 14.8, „Die ARCHIVE
-Speicher-Engine“.
Bei MyISAM
-Tabellen werden, wenn keine
freien Blöcke in der Mitte der Datendatei vorhanden sind,
gleichzeitige SELECT
- und
INSERT
-Anweisung unterstützt. Unter
diesen Umständen müssen Sie INSERT
DELAYED
bei MyISAM
nur in
sehr seltenen Fällen verwenden.
INSERT DELAYED
sollte nur für
INSERT
-Anweisungen eingesetzt werden,
die Wertelisten angeben. Bei INSERT DELAYED ...
SELECT
-Anweisungen ignoriert der Server das
DELAYED
.
Ebenso ignoriert der Server das DELAYED
bei INSERT ... SELECT
- oder
INSERT ... ON DUPLICATE KEY
UPDATE
-Anweisungen.
Weil die INSERT DELAYED
-Anweisung aus
Clientsicht abgeschlossen wird, bevor die Datensätze
tatsächlich eingefügt werden, können Sie den von der
Anweisung erstellten
AUTO_INCREMENT
-Wert nicht mit
LAST_INSERT_ID()
abrufen.
Verzögerte Datensätze werden für
SELECT
-Anweisungen erst sichtbar, wenn
sie tatsächlich eingefügt wurden.
DELAYED
wird auf
Slave-Replikationsservern ignoriert, weil andernfalls auf
dem Slave andere Daten vorhanden sein könnten als auf dem
Master.
Nachfolgend wird ausführlich beschrieben, was geschieht, wenn
Sie die Option DELAYED
für
INSERT
oder REPLACE
einsetzen. In dieser Beschreibung ist „Thread“
der Thread, der eine INSERT
DELAYED
-Anweisung empfangen hat, und
„Handler“ der Thread, der alle INSERT
DELAYED
-Anweisungen der betreffenden Tabelle
verwaltet.
Wenn ein Thread eine DELAYED
-Anweisung
für eine Tabelle ausführt, wird – sofern nicht bereits
vorhanden – ein Handler-Thread erzeugt, um alle
DELAYED
-Anweisungen für die Tabelle zu
verarbeiten.
Der Thread überprüft, ob der Handler zuvor bereits eine
DELAYED
-Sperre erwirkt hat, und weist
den Handler andernfalls dazu an. Die
DELAYED
-Sperre kann auch dann erwirkt
werden, wenn andere Threads eine READ
-
oder WRITE
-Sperre für die Tabelle
halten. Allerdings wartet der Handler, bis alle
ALTER TABLE
-Sperren aufgehoben und
FLUSH TABLES
-Anweisungen abgeschlossen
sind, um zu gewährleisten, dass die Tabellenstruktur
aktuell ist.
Der Thread führt die INSERT
-Anweisung
aus, schreibt den Datensatz aber nicht in die Tabelle,
sondern setzt eine Kopie des endgültigen Datensatzes in
eine Warteschlange, die vom Handler verwaltet wird.
Syntaxfehler werden vom Thread bemerkt und an das
Clientprogramm zurückgemeldet.
Der Client kann die Anzahl doppelter Datensätze oder den
AUTO_INCREMENT
-Wert des resultierenden
Datensatzes nicht beim Server erfragen, weil die
INSERT
-Anweisung vor Durchführung der
eigentlichen Einfügeoperation bereits abgeschlossen wird.
(Wenn Sie die C-API verwenden, dann gibt die Funktion
mysql_info()
aus demselben Grund nur
irrelevante Angaben zurück.)
Das Binärlog wird vom Handler-Thread aktualisiert, sobald der Datensatz in die Tabelle eingefügt wurde. Im Falle des Einfügens mehrerer Datensätze wird das Binärlog aktualisiert, wenn der erste Datensatz eingefügt wird.
Jedes Mal, wenn delayed_insert_limit
Datensätze geschrieben wurden, überprüft der Handler,
ob noch weitere SELECT
-Anweisungen
anhängig sind. Ist dies der Fall, so gestattet er deren
Ausführung, bevor er fortfährt.
Wenn der Handler keine Datensätze mehr in der
Warteschlange hat, wird die Tabelle entsperrt. Werden
innerhalb des durch
delayed_insert_timeout
(in Sekunden)
angegebenen Zeitraums keine neuen INSERT
DELAYED
-Anweisungen empfangen, dann wird der
Handler beendet.
Sind mehr als delayed_queue_size
Datensätze in einer bestimmten Handler-Warteschlange
anhängig, dann fordert der Thread INSERT
DELAYED
auf, zu warten, bis wieder Platz in der
Warteschlange ist. Hierdurch soll gewährleistet werden,
dass mysqld nicht den gesamten Speicher
für die Warteschlange mit den verzögerten Datensätzen
verwendet.
Der Handler-Thread erscheint in der MySQL-Prozessliste als
delayed_insert
in der Spalte
Command
. Er wird terminiert, wenn Sie
eine FLUSH TABLES
-Anweisung absetzen
oder KILL
ausführen.
Allerdings speichert er vor der Terminierung alle in der
Warteschlange vorhandenen Datensätze in die Tabelle,
bevor er beendet wird. In diesem Zeitraum werden keine
neuen thread_id
INSERT
-Anweisungen anderer
Threads angenommen. Wenn Sie nachfolgend eine
INSERT DELAYED
-Anweisung ausführen,
wird ein neuer Handler-Thread erstellt.
Beachten Sie, dass dies bedeutet, dass INSERT
DELAYED
-Anweisungen Vorrang vor normalen
INSERT
-Anweisungen haben, wenn ein
INSERT DELAYED
-Handler ausgeführt
wird. Andere Änderungsanweisungen müssen warten, bis die
INSERT DELAYED
-Warteschlange leer ist
oder jemand den Handler-Thread (mit KILL
) terminiert
oder eine thread_id
FLUSH TABLES
-Anweisung
ausführt.
Die folgenden Statusvariablen machen Angaben zu
INSERT DELAYED
-Anweisungen:
Statusvariable | Bedeutung |
Delayed_insert_threads | Anzahl der Handler-Threads |
Delayed_writes | Anzahl der mit INSERT DELAYED geschriebenen
Datensätze |
Not_flushed_delayed_rows | Anzahl der Datensätze, die noch geschrieben werden müssen |
Sie können diese Variablen anzeigen, indem Sie eine
SHOW STATUS
-Anweisung absetzen oder den
Befehl mysqladmin extended-status
ausführen.
Wenn Sie ON DUPLICATE KEY UPDATE
angeben
und ein Datensatz eingefügt wird, der einen doppelten Wert in
einem eindeutigen Index oder einem Primärschlüssel erzeugen
würde, dann wird für den alten Datensatz
UPDATE
ausgeführt. Angenommen, die Spalte
a
wird als UNIQUE
deklariert und enthält den Wert 1
; in
diesem Fall hätten die beiden folgenden Anweisungen dieselbe
Wirkung:
INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=c+1; UPDATE table SET c=c+1 WHERE a=1;
Der Wert der betroffenen Datensätze ist 1, wenn der Datensatz als neuer Datensatz eingefügt wird, und 2, wenn ein vorhandener Eintrag aktualisiert wird.
Wenn die Spalte b
ebenfalls eindeutig ist,
ist die INSERT
-Anweisung stattdessen
gleichbedeutend mit der folgenden
UPDATE
-Anweisung:
UPDATE table SET c=c+1 WHERE a=1 OR b=2 LIMIT 1;
Wenn a=1 OR b=2
mehreren Datensätzen
entspricht, wird nur ein Datensatz
aktualisiert. Generell sollten Sie von der Verwendung einer
ON DUPLICATE KEY
-Klausel bei Tabellen mit
mehreren eindeutigen Indizes absehen.
Sie können die Funktion
VALUES(
in der col_name
)UPDATE
-Klausel verwenden, um
Spaltenwerte aus dem INSERT
-Teil der
INSERT ... UPDATE
-Anweisung zu
referenzieren. Anders gesagt, verweist
VALUES(
in der col_name
)UPDATE
-Klausel auf den Wert von
col_name
, der eingefügt worden
wäre, wäre nicht ein Konflikt aufgrund einer
Schlüsseldublette aufgetreten. Diese Funktion ist
insbesondere bei Einfügevorgängen für mehrere Datensätze
praktisch. Die Funktion VALUES()
ist nur in
INSERT ... UPDATE
-Anweisungen sinnvoll zu
verwenden; andernfalls gibt sie NULL
zurück. Beispiel:
INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6) ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);
Diese Anweisung ist identisch mit den folgenden beiden Anweisungen:
INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=3; INSERT INTO table (a,b,c) VALUES (4,5,6) ON DUPLICATE KEY UPDATE c=9;
Die Option DELAYED
wird ignoriert, wenn Sie
ON DUPLICATE KEY UPDATE
verwenden.
LOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE 'file_name
' [REPLACE | IGNORE] INTO TABLEtbl_name
[FIELDS [TERMINATED BY 'string
'] [[OPTIONALLY] ENCLOSED BY 'char
'] [ESCAPED BY 'char
'] ] [LINES [STARTING BY 'string
'] [TERMINATED BY 'string
'] ] [IGNOREnumber
LINES] [(col_name_or_user_var
,...)] [SETcol_name
=expr
,...)]
Die Anweisung LOAD DATA INFILE
liest
Datensätze mit extrem hoher Geschwindigkeit aus einer Textdatei
in eine Tabelle ein. Der Dateiname muss als literaler String
übergeben werden.
Die Syntax für die FIELDS
- und
LINES
-Klauseln gilt auch für die
SELECT ... INTO OUTFILE
-Anweisung, die im
weiteren Verlauf dieses Abschnitts beschrieben wird. (Siehe auch
Abschnitt 13.2.7, „SELECT
“.)
Weitere Informationen zur Effektivität von
INSERT
im Vergleich zu LOAD DATA
INFILE
und zur Beschleunigung von LOAD DATA
INFILE
finden Sie in Abschnitt 7.2.16, „Geschwindigkeit von INSERT
-Anweisungen“.
Der von der Systemvariablen
character_set_database
angegebene Zeichensatz
wird zur Interpretation der Daten in der Datei verwendet.
SET NAMES
und die Einstellung von
character_set_client
wirken sich hingegen
nicht auf die Interpretation der Eingabe aus.
Beachten Sie, dass es derzeit nicht möglich ist, Datendateien
zu laden, die den Zeichensatz ucs2
verwenden.
Sie können Datendateien auch mithilfe des Hilfsprogramms
mysqlimport laden; dieses sendet dann eine
LOAD DATA INFILE
-Anweisung an den Server. Die
Option --local
bewirkt, dass
mysqlimport Datendateien vom Clienthost
liest. Sie können die Option --compress
angeben, um bei langsamen Netzwerken eine bessere Leistung zu
erzielen, sofern Client und Server das Komprimierungsprotokoll
unterstützen. Siehe auch Abschnitt 8.12, „mysqlimport — Programm zum Datenimport“.
Wenn Sie das Schlüsselwort LOW_PRIORITY
angeben, wird die Ausführung von LOAD DATA
verzögert, bis kein Client mehr aus der Tabelle liest.
Geben Sie CONCURRENT
bei einer
MyISAM
-Tabelle an, die die Bedingungen für
gleichzeitige Einfügeoperationen erfüllt (d. h. keine freien
Blöcke in der Mitte enthält), dann können andere Threads
Daten aus der Tabelle abrufen, während LOAD
DATA
ausgeführt wird. Die Verwendung dieser Option
beeinflusst die Leistungsfähigkeit von LOAD
DATA
auch dann geringfügig, wenn gleichzeitig kein
anderer Thread die Tabelle verwendet.
Das Schlüsselwort LOCAL
wird, sofern
angegeben, in Bezug auf die Clientseite der Verbindung
interpretiert:
Wenn LOCAL
angegeben ist, wird die Datei
vom Clientprogramm auf dem Clienthost gelesen und an den
Server geschickt. Die Datei kann als vollständiger Pfadname
angegeben werden, um die exakte Position zu beschreiben.
Erfolgt die Angabe als relativer Pfadname, dann wird der
Name relativ zum Verzeichnis interpretiert, in dem das
Clientprogramm gestartet wurde.
Wird LOCAL
nicht angegeben, dann muss die
Datei sich auf dem Serverhost befinden und wird direkt vom
Server gelesen. Der Server wendet zur Bestimmung der
Dateiposition die folgenden Regeln an:
Wenn der Dateiname absolut angegeben wurde, verwendet ihn der Server wie angegeben.
Ist der Dateiname ein relativer Pfadname mit einer oder mehreren am Anfang stehenden Komponenten, dann sucht der Server nach der Datei relativ zum eigenen Datenverzeichnis.
Wird ein Dateiname ohne Komponenten am Anfang übergeben, dann sucht der Server im Datenbankverzeichnis der Standarddatenbank nach der Datei.
Beachten Sie, dass, sofern keine LOCAL
-Option
angegeben wurde, die Regeln zur Folge haben, dass eine Datei
namens ./myfile.txt
im Datenverzeichnis des
Servers gesucht wird, während die Datei
myfile.txt
aus dem Datenbankverzeichnis der
Standarddatenbank gelesen wird. Ist also beispielsweise
db1
die Standarddatenbank, dann liest die
folgende LOAD DATA
-Anweisung die Datei
data.txt
aus dem Datenbankverzeichnis für
db1
aus, obwohl die Anweisung die Datei
explizit in die Datenbank db2
lädt:
LOAD DATA INFILE 'data.txt' INTO TABLE db2.my_table;
Windows-Pfadnamen müssen unter Verwendung von Schrägstrichen (statt Backslashs) angegeben werden. Wenn Sie Backslashs (umgekehrte Schrägstriche) verwenden, müssen Sie sie doppelt angeben.
Aus Sicherheitsgründen müssen Textdateien, die auf dem Server
ausgelesen werden, entweder im Datenbankverzeichnis liegen oder
von allen gelesen werden können. Außerdem benötigen Sie zur
Verwendung von LOAD DATA INFILE
für
Serverdateien die Berechtigung FILE
. Siehe
auch Abschnitt 5.8.3, „Von MySQL zur Verfügung gestellte Berechtigungen“.
Die Verwendung von LOCAL
ist ein wenig
langsamer als der Direktzugriff des Servers auf die Dateien,
weil der Inhalt der Datei vom Client über die Verbindung an den
Server gesendet werden muss. Die Berechtigung
FILE
benötigen Sie hingegen zum Laden
lokaler Dateien nicht.
Die Option LOCAL
funktioniert nur, wenn ihre
Verwendung sowohl am Client als auch am Server aktiviert wurde.
Wenn beispielsweise mysqld mit
--local-infile=0
gestartet wurde, funktioniert
LOCAL
nicht. Siehe auch
Abschnitt 5.7.4, „Sicherheitsprobleme mit LOAD DATA LOCAL
“.
Unter Unix können Sie, wenn LOAD DATA
über
eine Pipe lesen soll, die folgende Methode verwenden (hierbei
laden wir das Listing des Verzeichnisses /
in eine Tabelle):
mkfifo /mysql/db/x/x chmod 666 /mysql/db/x/x find / -ls > /mysql/db/x/x mysql -e "LOAD DATA INFILE 'x' INTO TABLE x" x
Die Schlüsselwörter REPLACE
und
IGNORE
steuern den Umgang mit eingegebenen
Datensätzen, die Duplikate vorhandener Datensätze mit
eindeutigen Schlüsselwerten darstellen.
Wenn Sie REPLACE
angeben, ersetzt die Eingabe
vorhandene Datensätze. Dies betrifft Datensätze, die denselben
Wert bei einem Primärschlüssel oder einem eindeutigen Index
wie die neuen Datensätze haben. Siehe auch
Abschnitt 13.2.6, „REPLACE
“.
Bei Angabe von IGNORE
hingegen werden neue
Datensätze, deren eindeutiger Schlüsselwert bereits einem
vorhandenen Datensatz zugewiesen ist, ignoriert. Wenn Sie keine
Option angeben, hängt das Verhalten davon ab, ob das
Schlüsselwort LOCAL
angegeben wird. Ohne
LOCAL
tritt ein Fehler auf, wenn ein
doppelter Schlüsselwert gefunden wird; in diesem Fall wird der
Rest der Textdatei ignoriert. Mit LOCAL
ist
das Standardverhalten so, als ob IGNORE
angegeben worden wäre. Das liegt daran, dass der Server keine
Möglichkeit hat, die Übertragung der Datei während des
Vorgangs zu beenden.
Wenn Sie Fremdschlüssel-Constraints während des Ladevorgangs
ignorieren wollen, können Sie eine SET
FOREIGN_KEY_CHECKS=0
-Anweisung vor der Ausführung von
LOAD DATA
absetzen.
Wenn Sie LOAD DATA INFILE
auf eine leere
MyISAM
-Tabelle anwenden, werden alle
nichteindeutigen Indizes in einer separaten Stapeloperation
erstellt (wie bei REPAIR TABLE
). Dies sollte
LOAD DATA INFILE
erheblich beschleunigen,
wenn Sie viele Indizes haben. In einigen Extremfällen können
Sie die Indizes noch schneller erstellen, indem Sie sie vor dem
Einladen der Datei in die Tabelle mit ALTER TABLE ...
DISABLE KEYS
abschalten und sie nach Abschluss des
Ladevorgangs mit ALTER TABLE ... ENABLE KEYS
neu erstellen. Siehe auch Abschnitt 7.2.16, „Geschwindigkeit von INSERT
-Anweisungen“.
LOAD DATA INFILE
ist das Gegenstück zu
SELECT ... INTO OUTFILE
. (Siehe auch
Abschnitt 13.2.7, „SELECT
“.) Um Daten aus einer Tabelle in eine
Datei zu schreiben, benutzen Sie SELECT ... INTO
OUTFILE
; wollen Sie die Datei wieder in eine Tabelle
einlesen, dann verwenden Sie LOAD DATA
INFILE
. Die Syntax der Klauseln
FIELDS
und LINES
ist bei
beiden Anweisungen dieselbe. Beide sind optional, aber
FIELDS
muss LINES
vorangehen, sofern beide angegeben sind.
Wenn Sie eine FIELDS
-Klausel festlegen, ist
auch jede einzelne Unterklausel (TERMINATED
BY
, [OPTIONALLY] ENCLOSED BY
und
ESCAPED BY
) ebenfalls optional – Sie
müssen lediglich mindestens eine dieser Unterklauseln angeben.
Wenn Sie keine FIELDS
-Klausel angeben,
entsprechen die Vorgabeeinstellungen dem Folgenden:
FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\'
Wenn Sie keine LINES
-Klausel angeben,
entsprechen die Vorgabeeinstellungen dem Folgenden:
LINES TERMINATED BY '\n' STARTING BY ''
Anders gesagt, die Standardwerte bewirken, dass LOAD
DATA INFILE
sich beim Einlesen wie folgt verhält:
Es wird nach Zeilenbegrenzungen bei Zeilenumbrüchen gesucht.
Zeilenpräfixe werden nicht übersprungen.
Zeilen werden bei Tabulatoren in Felder unterteilt.
Felder müssen nicht innerhalb von Anführungszeichen abgeschlossen werden.
Fälle von Tabulatoren, Zeilenumbrüchen oder
‘\
’, denen
‘\
’ vorangeht, werden als
literale Zeichen interpretiert, die Teile von Feldwerten
sind.
Umgekehrt bewirken die Voreinstellungen, dass sich
SELECT ... INTO OUTFILE
beim Schreiben einer
Ausgabe wie folgt verhält:
Tabulatoren werden zwischen Felder gesetzt.
Mehrere Felder werden nicht zwischen Anführungszeichen gesetzt.
‘\
’ wird zur Kennzeichnung
von Tabulatoren, Zeilenumbrüchen und
‘\
’ verwendet, die innerhalb
von Feldwerten auftreten.
Am Ende von Zeilen werden Zeilenumbrüche geschrieben.
Der Backslash wird bei MySQL als Escape-Zeichen in Strings
verwendet. Insofern müssen Sie, um FIELDS ESCAPED BY
'\\'
zu schreiben, zwei Backslashes angeben, damit der
Wert als ein Backslash interpretiert wird.
Hinweis: Wenn Sie die Textdatei
auf einem Windows-System erzeugt haben, müssen Sie unter
Umständen LINES TERMINATED BY '\r\n'
verwenden, um die Datei korrekt einzulesen, weil
Windows-Programme normalerweise zwei Zeichen als
Zeilenendzeichen verwenden. Einige Programme wie WordPad
verwenden beim Schreiben von Dateien unter Umständen sogar
\r
als Zeilenendzeichen. Um solche Dateien zu
lesen, verwenden Sie LINES TERMINATED BY
'\r'
.
Wenn alle Zeilen, die Sie einlesen wollen, ein gemeinsames
Präfix aufweisen, das Sie ignorieren wollen, können Sie mit
LINES STARTING BY
'
das Präfix
und alles, was davor steht, überspringen.
Enthält eine Zeile das Präfix gar nicht, dann wird die gesamte
Zeile übersprungen. Nehmen wir an, dass Sie folgende Anweisung
absetzen:
prefix_string
'
LOAD DATA INFILE '/tmp/test.txt' INTO TABLE test FIELDS TERMINATED BY ',' LINES STARTING BY 'xxx';
Nehmen wir ferner an, dass die Datendatei wie folgt aussieht:
xxx"abc",1 something xxx"def",2 "ghi",3
In diesem Fall werden als Ergebnis die Datensätze
("abc",1)
und ("def",2)
erzeugt. Der dritte Datensatz in der Datei wird übersprungen,
weil er das Präfix nicht enthält.
Die Option IGNORE
kann verwendet werden, um Zeilen am Anfang der
Datei zu ignorieren. So können Sie etwa number
LINESIGNORE 1
LINES
angeben, um eine Kopfzeile zu überspringen, die
etwa die Spaltennamen enthält:
LOAD DATA INFILE '/tmp/test.txt' INTO TABLE test IGNORE 1 LINES;
Wenn Sie SELECT ... INTO OUTFILE
gemeinsam
mit LOAD DATA INFILE
verwenden, um Daten aus
einer Datenbank in eine Datei zu schreiben und die Datei später
wieder in die Datenbank einzulesen, dann müssen die Optionen
der beiden Anweisungen zur Behandlung von Feldern und Zeilen
einander entsprechen. Andernfalls kann LOAD DATA
INFILE
den Inhalt der Datei nicht korrekt einlesen.
Angenommen, Sie schreiben mit SELECT ... INTO
OUTFILE
eine Datei mit Feldern, die kommagetrennt
sind:
SELECT * INTO OUTFILE 'data.txt' FIELDS TERMINATED BY ',' FROM table2;
Um diese kommagetrennte Datei wieder einzulesen, müssen Sie folgende Anweisung verwenden:
LOAD DATA INFILE 'data.txt' INTO TABLE table2 FIELDS TERMINATED BY ',';
Haben Sie stattdessen probiert, die Datei mit der folgenden
Anweisung einzulesen, dann ist dies nicht gelungen, da
LOAD DATA INFILE
angewiesen wird, nach
Tabulatoren zwischen den Feldern zu suchen:
LOAD DATA INFILE 'data.txt' INTO TABLE table2 FIELDS TERMINATED BY '\t';
Infolgedessen wird jede Eingabezeile wohl als separates Feld interpretiert werden.
Mit LOAD DATA INFILE
können Sie Dateien
lesen, die Sie aus externen Quellen erhalten haben.
Beispielsweise exportieren viele Programme Daten als
kommagetrennte Werte im so genannten CSV-Format (Comma-Separate
Values). Hierbei werden die Felder durch Kommata voneinander
getrennt und in doppelte Anführungszeichen gesetzt. Wenn Zeilen
in einer solchen Datei durch Zeilenumbrüche abgeschlossen
werden, veranschaulicht die folgende Anweisung die Optionen zur
Feld- und Zeilenbehandlung, wie Sie sie zum Laden der Datei
verwenden würden:
LOAD DATA INFILE 'data.txt' INTO TABLE tbl_name
FIELDS TERMINATED BY ',' ENCLOSED BY '"'
LINES TERMINATED BY '\n';
Alle Optionen zur Feld- und Zeilenbehandlung können einen
Leer-String (''
) angeben. Wenn der String
nicht leer ist, müssen die Werte FIELDS [OPTIONALLY]
ENCLOSED BY
und FIELDS ESCAPED BY
genau ein Zeichen umfassen. Die Werte FIELDS TERMINATED
BY
, LINES STARTING BY
und
LINES TERMINATED BY
können hingegen auch
mehrere Zeichen enthalten. Um etwa Zeilen zu schreiben, die
jeweils aus einem aus einer Absatzschaltung und einem
Zeilenvorschub bestehenden Zeichenpaar bestehen, geben Sie die
Klausel LINES TERMINATED BY '\r\n'
an.
Um eine Datei mit Witzen zu lesen, die durch aus
%%
bestehenden Zeilen getrennt sind, können
Sie Folgendes tun:
CREATE TABLE jokes (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, joke TEXT NOT NULL); LOAD DATA INFILE '/tmp/jokes.txt' INTO TABLE jokes FIELDS TERMINATED BY '' LINES TERMINATED BY '\n%%\n' (joke);
FIELDS [OPTIONALLY] ENCLOSED BY
steuert die
Anführungszeichen um die Felder. Bei der Ausgabe
(SELECT ... INTO OUTFILE
) werden, wenn Sie
das Wort OPTIONALLY
weglassen, alle Felder
vom durch ENCLOSED BY
angegebenen Zeichen
umschlossen. Hier ein Beispiel für eine solche Ausgabe (mit dem
Komma als Feldtrennzeichen):
"1","a string","100.20" "2","a string containing a , comma","102.20" "3","a string containing a \" quote","102.20" "4","a string containing a \", quote and comma","102.20"
Wenn Sie OPTIONALLY
angeben, wird das
ENCLOSED BY
-Zeichen nur zum Umschließen von
Werten in Spalten verwendet, die einen String-Datentyp haben
(z. B. CHAR
, BINARY
,
TEXT
oder ENUM
):
1,"a string",100.20 2,"a string containing a , comma",102.20 3,"a string containing a \" quote",102.20 4,"a string containing a \", quote and comma",102.20
Beachten Sie, dass das Auftreten des ENCLOSED
BY
-Zeichens in einem Feldwert gekennzeichnet wird,
indem man ihm das ESCAPED BY
-Zeichen
voranstellt. Ferner ist wichtig, dass es, wenn Sie einen leeren
ESCAPED BY
-Wert angeben, möglich ist,
versehentlich eine Ausgabe zu erzeugen, die von LOAD
DATA INFILE
nicht korrekt eingelesen werden kann. Die
obige Ausgabe beispielsweise würde wie folgt angezeigt werden,
wenn das Escape-Zeichen leer wäre. Sie werden bemerken, dass
das zweite Feld in der vierten Zeile ein auf das
Anführungszeichen folgendes Komma enthält, welches das Feld
abzuschließen scheint (was nicht zutrifft).
1,"a string",100.20 2,"a string containing a , comma",102.20 3,"a string containing a " quote",102.20 4,"a string containing a ", quote and comma",102.20
Bei der Eingabe wird das ENCLOSED BY
-Zeichen
– sofern vorhanden – am Ende der jeweiligen Feldwerte
entfernt. (Dies erfolgt unabhängig davon, ob
OPTIONALLY
angegeben ist oder nicht –
OPTIONALLY
hat keine Auswirkung auf die
Eingabeinterpretation.) Instanzen des ENCLOSED
BY
-Zeichens, denen das ESCAPED
BY
-Zeichen vorangestellt ist, werden als Teil des
aktuellen Feldwerts interpretiert.
Beginnt das Feld mit dem ENCLOSED BY
-Zeichen,
dann werden Instanzen dieses Zeichens nur dann als
Feldtrennzeichen ausgewertet, wenn ihnen jeweils die
TERMINATED BY
-Sequenz für Feld oder Zeile
folgt. Um Mehrdeutigkeiten zu vermeiden, können Fälle des
ENCLOSED BY
-Zeichens innerhalb eines
Feldwerts verdoppelt werden; sie werden dann als einzelne
Instanz des Zeichens ausgewertet. Wird also etwa
ENCLOSED BY '"'
angegeben, dann wird mit
Anführungszeichen wie hier gezeigt verfahren:
"The ""BIG"" boss" -> The "BIG" boss The "BIG" boss -> The "BIG" boss The ""BIG"" boss -> The ""BIG"" boss
FIELDS ESCAPED BY
steuert, wie Sonderzeichen
geschrieben oder gelesen werden. Wenn das FIELDS
ESCAPED BY
-Zeichen nicht leer ist, dann wird es bei
der Ausgabe als Präfix für die folgenden Zeichen verwendet:
FIELDS ESCAPED BY
-Zeichen
FIELDS [OPTIONALLY] ENCLOSED BY
-Zeichen
das erste Zeichen der Werte FIELDS TERMINATED
BY
und LINES TERMINATED BY
ASCII 0
(eigentlich wird auf das
Escape-Zeichen folgend ASCII
‘0
’ und kein Nullwertbyte
geschrieben)
Ist das FIELDS ESCAPED BY
-Zeichen leer, dann
werden keinerlei Zeichen gekennzeichnet und
NULL
wird als NULL
(und
nicht als \N
) ausgegeben. Es ist
wahrscheinlich nicht angeraten, ein leeres Escape-Zeichen
anzugeben; dies gilt insbesondere dann, wenn Feldwerte in Ihren
Daten eines der in der obigen Liste enthaltenen Zeichen
enthalten.
Wenn das FIELDS ESCAPED BY
-Zeichen nicht leer
ist, werden Instanzen dieses Zeichens bei der Eingabe entfernt,
und das nachfolgende Zeichen wird literal als Teil des Feldwerts
verwendet. Ausnahmen sind die gekennzeichneten Zeichen
‘0
’ oder
‘N
’ (z. B. \0
oder \N
, wenn das Escape-Zeichen
‘\
’ ist). Diese Sequenzen werden
als ASCII-NUL (Nullwertbyte) bzw. als NULL
interpretiert. Die Regeln für den Umgang mit
NULL
werden im weiteren Verlauf dieses
Abschnitts beschrieben.
Weitere Informationen zur
‘\
’-Escape-Syntax finden Sie in
Abschnitt 9.1, „Literale: wie Strings und Zahlen geschrieben werden“.
In bestimmten Fällen interagieren die Optionen zur Feld- und Zeilenbehandlung:
Wenn LINES TERMINATED BY
ein Leer-String
und FIELDS TERMINATED BY
nicht leer ist,
werden Zeilen auch mit FIELDS TERMINATED
BY
abgeschlossen.
Sind die Werte von FIELDS TERMINATED BY
und FIELDS ENCLOSED BY
beide leer
(''
), dann wird ein festes
Datensatzformat (ohne Trennzeichen) verwendet. Bei einem
solchen Format fehlt zwar das Trennzeichen, ein
Zeilenabschlusszeichen kann aber nichtsdestoweniger
vorhanden sein. Stattdessen werden Spaltenwerte unter
Berücksichtigung der Anzeigebreiten der Spalten geschrieben
und gelesen. Wird z. B. eine Spalte als
INT(7)
deklariert, dann werden Werte für
diese Spalte unter Verwendung von Feldern mit einer Länge
von sieben Zeichen geschrieben. Bei der Eingabe werden die
Spaltenwerte dann ermittelt, indem sieben Zeichen ausgelesen
werden.
LINES TERMINATED BY
wird nach wie vor zur
Trennung von Zeilen verwendet. Wenn eine Zeile nicht alle
Felder enthält, werden die verbleibenden Spalten auf ihre
Vorgabewerte gesetzt. Wenn kein Zeilenabschlusszeichen
vorhanden ist, sollten Sie dieses auf ''
setzen. In diesem Fall muss die Textdatei alle Felder für
jeden Datensatz enthalten.
Das Festformat für Datensätze beeinflusst auch den Umgang
mit NULL
-Werten (siehe unten). Beachten
Sie, dass dieses Format nicht funktioniert, wenn Sie einen
Multibytezeichensatz verwenden.
Die Handhabung von NULL
-Werten variiert
entsprechend den verwendeten FIELDS
- und
LINES
-Optionen:
Bei den FIELDS
- und
LINES
-Standardwerten wird
NULL
als Feldwert \N
in die Ausgabe geschrieben. Analog wird der Feldwert
\N
bei der Eingabe als
NULL
gelesen (vorausgesetzt, das
ESCAPED BY
-Zeichen ist
‘\
’).
Wenn FIELDS ENCLOSED BY
nicht leer ist,
dann wird ein Feld, das das Wort NULL
als
Wert enthält, als NULL
-Wert gelesen.
Dies unterscheidet sich von dem Wort
NULL
, wenn es in FIELDS ENCLOSED
BY
-Zeichen gesetzt ist – dieses wird als
'NULL'
gelesen.
Ist FIELDS ESCAPED BY
leer, dann wird
NULL
als Wort NULL
geschrieben.
Beim Festformat (welches verwendet wird, wenn
FIELDS TERMINATED BY
und FIELDS
ENCLOSED BY
beide leer sind), wird
NULL
als Leer-String geschrieben.
Beachten Sie, dass dies zur Folge hat, dass
NULL
-Werte und Leer-Strings in der
Tabelle nicht mehr unterschieden werden können, sobald sie
in die Datei geschrieben werden, weil beide als Leer-Strings
geschrieben werden. Müssen die beiden Werte nach dem
Wiedereinlesen der Datei weiterhin unterscheidbar sein, dann
sollten Sie das Festformat nicht verwenden.
Manche Fälle werden von LOAD DATA INFILE
nicht unterstützt:
Datensätze fester Länge (FIELDS TERMINATED
BY
und FIELDS ENCLOSED BY
sind
leer) und BLOB
- oder
TEXT
-Spalten.
Wenn Sie ein Trennzeichen angeben, das mit einem anderen
Trennzeichen (oder dessen Präfix) identisch ist, kann
LOAD DATA INFILE
die Eingabe nicht
korrekt interpretieren. Die folgende
FIELDS
-Klausel beispielsweise würde
Probleme verursachen:
FIELDS TERMINATED BY '"' ENCLOSED BY '"'
Wenn FIELDS ESCAPED BY
leer ist, bewirkt
ein Feldwert, der eine Instanz von FIELDS ENCLOSED
BY
oder LINES TERMINATED BY
gefolgt vom FIELDS TERMINATED BY
-Wert
enthält, dass LOAD DATA INFILE
das
Einlesen eines Felds oder einer Zeile zu früh beendet. Dies
geschieht, weil LOAD DATA INFILE
nicht
genau bestimmen kann, wo der Feld- oder Zeilenwert endet.
Das folgende Beispiel lädt alle Spalten der Tabelle
persondata
:
LOAD DATA INFILE 'persondata.txt' INTO TABLE persondata;
Standardmäßig wird, wenn keine Spaltenliste am Ende der
LOAD DATA INFILE
-Anweisung vorhanden ist,
erwartet, dass Eingabezeilen ein Feld für jede Tabellenspalte
enthalten. Wenn Sie nur einen Teil der Spalten einer Tabelle
laden wollen, müssen Sie eine Spaltenliste angeben:
LOAD DATA INFILE 'persondata.txt' INTO TABLE persondata (col1,col2,...);
Ferner müssen Sie eine Spaltenliste festlegen, wenn die Reihenfolge der Felder in der Eingabedatei sich von der Reihenfolge der Spalten in der Tabelle unterscheidet. Andernfalls kann MySQL nicht ermitteln, wie die Eingabefelder den Tabellenspalten zuzuordnen sind.
Die Spaltenliste kann entweder Spaltennamen oder
Benutzervariablen enthalten. Bei Benutzervariablen gestattet
Ihnen die SET
-Klausel die Durchführung einer
Werteumwandlung vor der Zuweisung des Ergebnisses zu den
Spalten.
Benutzervariablen in der SET
-Klausel können
auf unterschiedliche Weise verwendet werden. Die folgenden Werte
benutzen die erste Eingabespalte direkt für den Wert von
t1.column1
und weisen die zweite
Eingabespalte einer Benutzervariablen zu, an der eine Division
durchgeführt wird, bevor sie als Wert für
t1.column2
verwendet wird:
LOAD DATA INFILE 'file.txt' INTO TABLE t1 (column1, @var1) SET column2 = @var1/100;
Die SET
-Klausel kann zur Übermittlung von
Werten benutzt werden, die nicht der Eingabedatei entnommen
wurden. Die folgende Anweisung weist column3
das aktuelle Datum und die Uhrzeit zu:
LOAD DATA INFILE 'file.txt' INTO TABLE t1 (column1, column2) SET column3 = CURRENT_TIMESTAMP;
Sie können einen Eingabewert auch verwerfen, indem Sie ihn einer Benutzervariablen zuweisen, der Variablen aber keine Tabellenspalte zuordnen:
LOAD DATA INFILE 'file.txt' INTO TABLE t1 (column1, @dummy, column2, @dummy, column3);
Die Verwendung der Spalten-/Variablenliste und der
SET
-Klausel ist den folgenden
Einschränkungen unterworfen:
Zuordnungen in der SET
-Klausel sollten
auf der linken Seite des Zuweisungsoperators nur
Spaltennamen aufweisen.
Auf der rechten Seite einer SET
-Zuordnung
dürfen auch Unterabfragen zum Einsatz kommen. Eine
Unterabfrage, die einen Wert zurückgibt, der einer Spalte
zugeordnet werden soll, darf nur eine skalare Unterabfrage
sein. Außerdem können Sie eine Unterabfrage nicht für
Auswahlabfragen an die Tabelle verwenden, die gerade geladen
wird.
Zeilen, die von einer IGNORE
-Klausel
ignoriert werden, werden für die Spalten-/Variablenliste
oder die SET
-Klausel nicht verarbeitet.
Benutzervariablen können nicht verwendet werden, wenn Daten mit Festformat geladen werden, da Benutzervariablen keine Anzeigebreite haben.
Wenn eine Eingabezeile verarbeitet wird, unterteilt
LOAD DATA
sie in Felder und verwendet die
Werte entsprechend der Spalten-/Variablenliste und der
SET
-Klausel, sofern diese vorhanden sind. Der
Ergebnisdatensatz wird dann in die Tabelle eingefügt. Sind
BEFORE INSERT
- oder AFTER
INSERT
-Trigger für die Tabelle vorhanden, so werden
diese vor bzw. nach dem Einfügen des Datensatzes aktiviert.
Hat eine Eingabezeile zu viele Felder, dann werden die überzähligen Felder ignoriert und die Anzahl der Warnungen wird erhöht.
Hat eine Eingabezeile zu wenig Felder, dann werden die Tabellenspalten, deren Eingabefelder fehlen, auf ihre Standardwerte gesetzt. Die Zuweisung von Standardwerten ist in Abschnitt 11.1.4, „Vorgabewerte von Datentypen“, beschrieben.
Ein leerer Feldwert wird anders interpretiert als ein fehlender Feldwert:
Bei String-Typen wird die Spalte auf den Leer-String gesetzt.
Bei numerischen Typen wird die Spalte auf
0
gesetzt.
Bei zeitbezogenen Typen wird die Spalte auf den passenden „Nullwert“ des Typs gesetzt. Siehe auch Abschnitt 11.3, „Datums- und Zeittypen“.
Dies sind dieselben Werte, die als Ergebnis ausgegeben werden,
wenn Sie einem String, einem numerischen oder einem
zeitbezogenen Wert in einer INSERT
- oder
UPDATE
-Anweisung explizit den Leer-String
zuweisen.
TIMESTAMP
-Spalten werden nur dann auf die
aktuellen Werte für Datum und Uhrzeit gesetzt, wenn ein
NULL
-Wert (d. h. \N
) für
die Spalte vorhanden ist oder der Standardwert der
TIMESTAMP
-Spalte der aktuelle Zeitstempel ist
und in der Feldliste (sofern vorhanden) weggelassen wurde.
LOAD DATA INFILE
betrachtet alle Eingaben als
Strings, d. h., Sie können für ENUM
- oder
SET
-Spalten numerische Werte nicht so
eingeben wie von INSERT
-Anweisungen her
gewohnt. Alle ENUM
- und
SET
-Werte müssen als Strings angegeben
werden.
Wenn die LOAD DATA INFILE
-Anweisung
abgeschlossen ist, gibt sie einen Informations-String im
folgenden Format zurück:
Records: 1 Deleted: 0 Skipped: 0 Warnings: 0
Wenn Sie die C-API verwenden, können Sie Informationen zur
Anweisung durch einen Aufruf der Funktion
mysql_info()
ermitteln. Siehe auch
Abschnitt 24.2.3.34, „mysql_info()
“.
Warnungen treten unter denselben Umständen auf wie beim
Einfügen von Werten mithilfe der
INSERT
-Anweisung (siehe
Abschnitt 13.2.4, „INSERT
“); der einzige Unterschied besteht
darin, dass LOAD DATA INFILE
auch dann
Warnungen erzeugt, wenn zu wenig oder zu viel Felder im
Eingabedatensatz vorhanden sind. Die Warnungen werden nirgends
gespeichert; Sie können ihrer Anzahl lediglich entnehmen, ob
alles geklappt hat oder nicht.
Mit SHOW WARNINGS
erhalten Sie eine Liste der
ersten max_error_count
Warnungen mit
Informationen dazu, was unter Umständen nicht geklappt hat.
Siehe auch Abschnitt 13.5.4.25, „SHOW WARNINGS
“.
REPLACE [LOW_PRIORITY | DELAYED] [INTO]tbl_name
[(col_name
,...)] VALUES ({expr
| DEFAULT},...),(...),...
Oder:
REPLACE [LOW_PRIORITY | DELAYED] [INTO]tbl_name
SETcol_name
={expr
| DEFAULT}, ...
Oder:
REPLACE [LOW_PRIORITY | DELAYED] [INTO]tbl_name
[(col_name
,...)] SELECT ...
REPLACE
funktioniert auf exakt gleiche Weise
wie INSERT
. Der Unterschied besteht darin,
dass, wenn ein alter Datensatz denselben Wert wie ein neuer
Datensatz für einen Primärschlüssel oder einen eindeutigen
Index hat, der alte Datensatz gelöscht wird, bevor der neue
eingefügt wird. Siehe auch Abschnitt 13.2.4, „INSERT
“.
REPLACE
ist eine MySQL-Erweiterung zum
SQL-Standard. Es kann Datensätze einfügen, oder es kann
Datensätze löschen und einfügen. Wenn
Sie eine Anweisung suchen, die dem SQL-Standard entspricht und
die entweder einfügt oder aktualisiert,
dann benutzen Sie die INSERT ... ON DUPLICATE KEY
UPDATE
-Anweisung (siehe auch
Abschnitt 13.2.4.3, „INSERT ... ON DUPLICATE KEY UPDATE
“).
Beachten Sie, dass, sofern die Tabelle nicht einen
Primärschlüssel oder einen eindeutigen Index hat, die
Verwendung von REPLACE
unsinnig ist. Die
Anweisung wäre dann mit INSERT
identisch,
weil kein Index vorhanden ist, anhand dessen bestimmt werden
könnte, ob ein neuer Datensatz ein Duplikat eines bereits
vorhandenen darstellt.
Werte für alle Spalten werden den Werten entnommen, die in der
REPLACE
-Anweisung angegeben sind. Fehlende
Spalten werden – wie bei INSERT
– auf
ihre Standardwerte gesetzt. Es ist nicht möglich, Werte aus dem
aktuellen Datensatz zu referenzieren und diese dann im neuen
Datensatz zu verwenden. Wenn Sie eine Zuordnung wie SET
verwenden,
wird die Referenzierung des Spaltennamens auf der rechten Seite
wie
col_name
=
col_name
+ 1DEFAULT(
behandelt, d. h., die Zuordnung ist äquivalent zu col_name
)SET
.
col_name
=
DEFAULT(col_name
) + 1
Um REPLACE
zu verwenden, benötigen Sie die
Berechtigungen INSERT
und
DELETE
für die Tabelle.
Die REPLACE
-Anweisung gibt einen Wert
zurück, der die Anzahl der betroffenen Datensätze angibt.
Konkret ist dies die Summe der gelöschten und eingefügten
Datensätze. Wenn der Wert bei einer
REPLACE
-Anweisung für einen Datensatz 1
beträgt, dann wurde ein Datensatz eingefügt und keiner
gelöscht. Ist der Wert größer als 1, dann wurden ein oder
mehrere alte Datensätze gelöscht, bevor der neue Datensatz
eingefügt wurde. Ein einzelner Datensatz kann durchaus mehr als
nur einen alten Datensatz ersetzen, sofern die Tabelle mehrere
eindeutige Indizes hat und der neue Datensatz Werte
verschiedener alter Datensätze in verschiedenen eindeutigen
Indizes dupliziert.
Die Anzahl der betroffenen Datensätze erlaubt also die einfache
Bestimmung, ob REPLACE
nur einen Datensatz
hinzugefügt hat oder ob auch Datensätze ersetzt wurden:
Überprüfen Sie, ob der Wert 1 (Hinzufügung) oder größer ist
(Ersetzung).
Wenn Sie die C-API verwenden, kann die Anzahl der betroffenen
Datensätze durch die Funktion
mysql_affected_rows()
ermittelt werden.
Zurzeit können Sie in einer Unterabfrage keine Ersetzungsoperation in einer Tabelle durchführen und gleichzeitig eine Auswahl in einer anderen Tabelle treffen.
MySQL verwendet für REPLACE
(und
LOAD DATA ... REPLACE
) den folgenden
Algorithmus:
Es wird versucht, den neuen Datensatz in die Tabelle einzufügen.
Wenn die Einfügeoperation aufgrund einer Schlüsseldublette in einem Primärschlüssel oder einem eindeutigen Index fehlschlägt,
wird der konfliktauslösende Datensatz mit dem doppelten Schlüsselwert aus der Tabelle entfernt,
wird erneut versucht, den neuen Datensatz in die Tabelle einzufügen.
SELECT [ALL | DISTINCT | DISTINCTROW ] [HIGH_PRIORITY] [STRAIGHT_JOIN] [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT] [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]select_expr
, ... [FROMtable_references
[WHEREwhere_condition
] [GROUP BY {col_name
|expr
|position
} [ASC | DESC], ... [WITH ROLLUP]] [HAVINGwhere_condition
] [ORDER BY {col_name
|expr
|position
} [ASC | DESC], ...] [LIMIT {[offset
,]row_count
|row_count
OFFSEToffset
}] [PROCEDUREprocedure_name
(argument_list
)] [INTO OUTFILE 'file_name
'export_options
| INTO DUMPFILE 'file_name
'] [FOR UPDATE | LOCK IN SHARE MODE]]
SELECT
wird zum Abrufen von Datensätzen
verwendet, die aus einer oder mehreren Tabellen ausgewählt
wurden, und kann UNION
-Anweisungen und
Unterabfragen enthalten. Siehe auch Abschnitt 13.2.7.2, „UNION
“, und
Abschnitt 13.2.8, „Syntax von Unterabfragen“.
Die meistverwendeten Klauseln für SELECT
sind die folgenden:
Jede select_expr
gibt eine Spalte
an, die Sie abrufen wollen. Es muss mindestens ein
select_expr
vorhanden sein.
table_references
gibt die
Tabelle(n) an, aus der oder denen die Datensätze abgerufen
werden sollen. Die Syntax ist in Abschnitt 13.2.7.1, „JOIN
“,
beschrieben.
Die WHERE
-Klausel gibt, soweit vorhanden,
die Bedingung(en) an, die Datensätze erfüllen müssen,
damit sie ausgewählt werden.
where_condition
ist ein Ausdruck,
der für jeden auszuwählenden Datensatz wahr ist. Die
Anweisung wählt, wenn keine
WHERE
-Klausel vorhanden ist, alle
Datensätze aus.
Sie können in der WHERE
-Klausel alle von
MySQL unterstützten Funktionen und Operatoren mit Ausnahme
der Zusammenfassungsfunktionen einsetzen. Siehe auch
Kapitel 12, Funktionen für die Benutzung in SELECT
- und
WHERE
-Klauseln.
SELECT
kann auch verwendet werden, um
Datensätze abzurufen, die ohne Referenzierung einer Tabelle
berechnet wurden.
Zum Beispiel:
mysql> SELECT 1 + 1;
-> 2
Sie können DUAL
als Pseudotabellenname in
Situationen angeben, in denen keine Tabellen referenziert
werden:
mysql> SELECT 1 + 1 FROM DUAL;
-> 2
DUAL
ist ausschließlich zum Zweck der
Kompatibilität mit anderen Datenbankservern vorhanden, die eine
FROM
-Klausel erfordern. MySQL benötigt keine
solche Klausel, wenn keine Tabellen referenziert werden.
Generell müssen Klauseln in genau der Reihenfolge angegeben
werden, die in der Syntaxbeschreibung erscheint. So muss etwa
eine HAVING
-Klausel hinter den GROUP
BY
-Klauseln und vor den ORDER
BY
-Klauseln stehen. Die einzige Ausnahme ist die
INTO
-Klausel, die entweder wie in der
Syntaxbeschreibung gezeigt oder unmittelbar vor der
FROM
-Klausel stehen kann.
Einem Ausdruck select_expr
lässt
sich mit AS
ein Alias
zuweisen. Der Alias wird als Spaltenname des Ausdrucks
benutzt und kann in alias_name
GROUP BY
-,
ORDER BY
- oder
HAVING
-Klauseln verwendet werden. Zum
Beispiel:
SELECT CONCAT(last_name,', ',first_name) AS full_name FROM mytable ORDER BY full_name;
Das Schlüsselwort AS
ist beim Zuweisen
eines Alias zu select_expr
optional. Das obige Beispiel hätte auch wie folgt
geschrieben sein können:
SELECT CONCAT(last_name,', ',first_name) full_name FROM mytable ORDER BY full_name;
Allerdings kann, weil AS
optional ist,
ein kleines Problem auftreten, wenn Sie das Komma zwischen
zwei select_expr
-Ausdrücken
vergessen: MySQL interpretiert den zweiten Ausdruck als
Aliasnamen. Sie wird etwa in der folgenden Anweisung
columnb
als Aliasname behandelt:
SELECT columna columnb FROM mytable;
Aus diesem Grund hat es sich bewährt, AS
beim Festlegen von Spaltenaliasen immer explizit anzugeben.
Es ist nicht zulässig, einen Spaltenalias in einer
WHERE
-Klausel zu verwenden, weil der
Spaltenwert unter Umständen nicht bestimmt werden kann,
wenn die WHERE
-Klausel ausgeführt wird.
Siehe auch Abschnitt A.5.4, „Probleme mit alias
“.
Die Klausel FROM
gibt
die Tabelle(n) an, aus der oder denen die Datensätze
abgerufen werden sollen. Wenn Sie mehr als eine Tabelle
angeben, führen Sie einen Join durch. Informationen zur
Join-Syntax finden Sie in Abschnitt 13.2.7.1, „table_references
JOIN
“. Für jede
angegebene Tabelle können Sie optional einen Alias angeben.
tbl_name
[[AS]alias
] [{USE|IGNORE|FORCE} INDEX (key_list
)]
Wie Sie dem Optimierer mit USE INDEX
,
IGNORE INDEX
und FORCE
INDEX
Hinweise zur Auswahl der Indizes geben, ist
in Abschnitt 13.2.7.1, „JOIN
“, beschrieben.
Sie können SET
max_seeks_for_key=
als alternative Möglichkeit verwenden, um MySQL zur
Verwendung von Schlüssel- statt Tabellenscans (sofern
möglich) zu zwingen. Siehe auch
Abschnitt 5.2.2, „Server-Systemvariablen“.
value
Sie können eine Tabelle in der Standarddatenbank als
tbl_name
oder – wenn Sie eine
Datenbank ausdrücklich angeben wollen – als
db_name
.tbl_name
referenzieren. Eine Spalte können Sie als
col_name
,
tbl_name
.col_name
oder
db_name
.tbl_name
.col_name
referenzieren. Sie müssen das Präfix
tbl_name
oder
db_name
.tbl_name
für eine Spaltenreferenzierung nicht angeben, sofern die
Referenzierung eindeutig ist. Beispiele für
Mehrdeutigkeiten, die die spezifischeren Formen der
Spaltenreferenzierung erfordern, finden Sie in
Abschnitt 9.2, „Datenbank-, Tabellen-, Index-, Spalten- und Aliasnamen“.
Für einen Tabellenverweis kann mit
oder
tbl_name
AS
alias_name
tbl_name alias_name
ein Alias
erstellt werden:
SELECT t1.name, t2.salary FROM employee AS t1, info AS t2 WHERE t1.name = t2.name; SELECT t1.name, t2.salary FROM employee t1, info t2 WHERE t1.name = t2.name;
Spalten, die für die Ausgabe ausgewählt werden, lassen
sich in ORDER BY
- und GROUP
BY
-Klauseln als Spaltennamen, Spaltenaliase oder
Spaltenpositionen referenzieren. Spaltenpositionen sind
ganze Zahlen, die bei 1 beginnen:
SELECT college, region, seed FROM tournament ORDER BY region, seed; SELECT college, region AS r, seed AS s FROM tournament ORDER BY r, s; SELECT college, region, seed FROM tournament ORDER BY 2, 3;
Um in umgekehrter (absteigender) Reihenfolge zu sortieren,
fügen Sie in der ORDER BY
-Klausel das
Schlüsselwort DESC
zum Namen der Spalte
zu, nach der die Sortierung erfolgt: Standardmäßig erfolgt
die Sortierung aufsteigend. Dies kann mit dem Schlüsselwort
ASC
explizit festgelegt werden.
Die Verwendung von Spaltenpositionen ist veraltet, weil die Syntax im SQL-Standard nicht mehr vorhanden ist.
Wenn Sie GROUP BY
verwenden, werden die
Ausgabedatensätze entsprechend den GROUP
BY
-Spalten sortiert, so als ob Sie eine
ORDER BY
-Klausel für dieselben Spalten
angegeben hätten. Um eine Mehrbelastung durch das Sortieren
mit GROUP BY
zu vermeiden, fügen Sie
ORDER BY NULL
hinzu:
SELECT a, COUNT(b) FROM test_table GROUP BY a ORDER BY NULL;
MySQL erweitert die GROUP BY
-Klausel
dahingehend, dass Sie ASC
und
DESC
auch nach den in der Klausel
benannten Spalten angeben können:
SELECT a, COUNT(b) FROM test_table GROUP BY a DESC;
MySQL erweitert die Verwendung von GROUP
BY
so, dass die Auswahl von Feldern möglich ist,
die in der GROUP BY
-Klausel nicht genannt
sind. Wenn Sie bei einer Abfrage nicht die erwarteten
Ergebnisse erhalten, lesen Sie bitte die Beschreibung von
GROUP BY
in
Abschnitt 12.11, „Funktionen und Modifizierer für die Verwendung in GROUP
BY
-Klauseln“.
GROUP BY
unterstützt den Modifizierer
WITH ROLLUP
. Siehe auch
Abschnitt 12.11.2, „GROUP BY
-Modifizierer“.
Die HAVING
-Klausel wird fast als Letztes
angewandt – unmittelbar bevor die Elemente an den Client
gesendet werden, und ohne Optimierung. (Nur
LIMIT
wird noch nach
HAVING
angewandt.)
Der SQL-Standard sieht vor, dass HAVING
nur Spalten in der GROUP BY
-Klausel oder
solche Spalten referenzieren darf, die in
Zusammenfassungsfunktionen verwendet werden. Allerdings
unterstützt MySQL eine Erweiterung dieses Verhaltens und
gestattet HAVING
ferner die
Referenzierung von Spalten in der
SELECT
-Liste und Spalten in äußeren
Unterabfragen.
Wenn die HAVING
-Klausel eine Spalte
referenziert, die mehrdeutig ist, erscheint eine Warnung. In
der folgenden Anweisung ist col2
mehrdeutig, weil es sowohl als Alias als auch als
Spaltenname verwendet wird:
SELECT COUNT(col1) AS col2 FROM t GROUP BY col2 HAVING col2 = 2;
Hier wird das SQL-Standardverhalten angewandt, d. h., wenn
ein HAVING
-Spaltenname sowohl in einer
GROUP BY
-Klausel als auch als
Spaltenalias in der Liste der Ausgabespalten enthalten ist,
hat die Spalte in der GROUP BY
-Spalte
Vorrang.
Verwenden Sie HAVING
nicht für Elemente,
die in der WHERE
-Klausel aufgeführt sein
sollten. So sollten Sie beispielsweise nicht Folgendes
schreiben:
SELECTcol_name
FROMtbl_name
HAVINGcol_name
> 0;
Formulieren Sie stattdessen wie folgt:
SELECTcol_name
FROMtbl_name
WHEREcol_name
> 0;
Die HAVING
-Klausel kann
Zusammenfassungsfunktionen referenzieren, was der
WHERE
-Klausel nicht möglich ist:
SELECT user, MAX(salary) FROM users GROUP BY user HAVING MAX(salary) > 10;
(Dies funktionierte bei einigen älteren MySQL-Versionen nicht.)
Die LIMIT
-Klausel kann zur Beschränkung
der Anzahl der von der SELECT
-Anweisung
zurückgegebenen Datensätze verwendet werden.
LIMIT
nimmt ein oder zwei numerische
Argumente entgegen, die (außer bei Verwendung vorbereiteter
Anweisungen) beide nichtnegative Integer-Konstanten sein
müssen.
Von den beiden Argumenten gibt das erste den Versatz des ersten zurückzugebenden Datensatzes an, das zweite die maximale Anzahl zurückzugebender Datensätze. Der Versatz des ersten Datensatzes ist 0 (nicht 1):
SELECT * FROM tbl LIMIT 5,10; # Retrieve rows 6-15
Um alle Datensätze beginnend bei einem bestimmten Versatz bis zum Ende der Ergebnismenge zurückzugeben, können Sie als zweiten Parameter eine sehr große Zahl angeben. Die folgende Anweisung ruft alle Datensätze beginnend beim 96. bis zum letzten Datensatz ab:
SELECT * FROM tbl LIMIT 95,18446744073709551615;
Sofern nur ein Argument angegeben ist, gibt der Wert die Anzahl der Datensätze an, die beginnend beim ersten Datensatz zurückgegeben werden sollen:
SELECT * FROM tbl LIMIT 5; # Retrieve first 5 rows
Anders gesagt, ist LIMIT
äquivalent
zu row_count
LIMIT 0,
.
row_count
Bei vorbereiteten Anweisungen können Sie Platzhalter
verwenden. Die folgende Anweisung gibt genau einen Datensatz
aus der Tabelle tbl
zurück:
SET @a=1; PREPARE STMT FROM 'SELECT * FROM tbl LIMIT ?'; EXECUTE STMT USING @a;
Die folgenden Anweisungen geben den zweiten bis sechsten
Datensatz aus der Tabelle tbl
zurück:
SET @skip=1; SET @numrows=5; PREPARE STMT FROM 'SELECT * FROM tbl LIMIT ?, ?'; EXECUTE STMT USING @skip, @numrows;
Aus Gründen der Kompatibilität mit PostgreSQL unterstützt
MySQL auch die Syntax LIMIT
.
row_count
OFFSET
offset
Die Form SELECT ... INTO OUTFILE
'
der
file_name
'SELECT
-Anweisung schreibt die
ausgewählten Datensätze in eine Datei. Die Datei wird auf
dem Serverhost erstellt, d. h., Sie benötigen die
Berechtigung FILE
, um die Syntax
verwenden zu können. file_name
darf keine vorhandene Datei sein, wodurch u. a. verhindert
werden soll, dass Dateien wie
/etc/passwd
und Datenbanktabellen
zerstört werden.
Die Anweisung SELECT ... INTO OUTFILE
ist
in erster Linie dazu vorgesehen, eine Tabelle sehr schnell
in eine Textdatei auf dem Server zu speichern. Wenn Sie die
resultierende Datei auf einem Clienthost statt auf dem
Serverhost erstellen wollen, dürfen Sie SELECT ...
INTO OUTFILE
nicht verwenden. In diesem Fall
sollten Sie stattdessen einen Befehl wie mysql -e
"SELECT ..." >
benutzen, um
die Datei auf dem Clienthost anzulegen.
file_name
SELECT ... INTO OUTFILE
ist das
Gegenstück zu LOAD DATA INFILE
. Die
Syntax für den
export_options
-Teil der Anweisung
umfasst dieselben FIELDS
- und
LINES
-Klauseln, die bei LOAD
DATA INFILE
benutzt werden. Siehe auch
Abschnitt 13.2.5, „LOAD DATA INFILE
“.
FIELDS ESCAPED BY
steuert, wie
Sonderzeichen geschrieben werden. Wenn das FIELDS
ESCAPED BY
-Zeichen nicht leer ist, dann wird es
bei der Ausgabe als Präfix für die folgenden Zeichen
verwendet:
FIELDS ESCAPED BY
-Zeichen
FIELDS [OPTIONALLY] ENCLOSED
BY
-Zeichen
das erste Zeichen der Werte FIELDS TERMINATED
BY
und LINES TERMINATED BY
ASCII NUL
(das Nullwertbyte;
eigentlich wird auf das Escape-Zeichen folgend ASCII
‘0
’ und kein Nullwertbyte
geschrieben)
Die FIELDS TERMINATED BY
-,
ENCLOSED BY
-, ESCAPED
BY
- oder LINES TERMINATED
BY
-Zeichen müssen mit
Escape-Zeichen gekennzeichnet werden, damit Sie die Datei
zuverlässig wiedereinlesen können. ASCII
NUL
wird gekennzeichnet, um das Ablesen
bei manchen Pagern zu vereinfachen.
Die Ergebnisdatei muss nicht der SQL-Syntax entsprechen, weswegen weitere Zeichen nicht gekennzeichnet werden müssen.
Ist das FIELDS ESCAPED BY
-Zeichen leer,
dann werden keinerlei Zeichen gekennzeichnet und
NULL
wird als NULL
(und nicht als \N
) ausgegeben. Es ist
wahrscheinlich nicht angeraten, ein leeres Escape-Zeichen
anzugeben; dies gilt insbesondere dann, wenn Feldwerte in
Ihren Daten eines der in der obigen Liste enthaltenen
Zeichen enthalten.
Es folgt ein Beispiel, das eine Datei im CSV-Format erzeugt, welches von vielen Programmen verwendet wird:
SELECT a,b,a+b INTO OUTFILE '/tmp/result.txt' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n' FROM test_table;
Wenn Sie INTO DUMPFILE
statt
INTO OUTFILE
verwenden, schreibt MySQL
nur einen Datensatz ohne Spalten- oder Zeilentrennzeichen
und ohne Escape-Kennzeichnung in die Datei. Dies ist
praktisch, wenn Sie einen BLOB
-Wert in
die Datei speichern wollen.
Hinweis: In Dateien, die
durch INTO OUTFILE
oder INTO
DUMPFILE
erstellt wurden, kann von allen Benutzern
geschrieben werden. Grund hierfür ist die Tatsache, dass
der MySQL Server keine Datei erstellen kann, deren Besitzer
jemand anders als der Benutzer ist, unter dessen Konto der
Server ausgeführt wird. (Sie sollten aus diesem und anderen
Gründen mysqld
niemals als root
ausführen.) Die Datei muss von allen schreibbar sein, damit
Sie ihren Inhalt modifizieren können.
Die Beschreibung der SELECT
-Syntax am
Anfang dieses Abschnitts zeigt die
INTO
-Klausel gegen Ende der Anweisung.
INTO OUTFILE
oder INTO
DUMPFILE
können auch unmittelbar auf die
FROM
-Klausel folgend angegeben werden.
Eine PROCEDURE
-Klausel benennt eine
Prozedur, die die Daten in der Ergebnismenge verarbeitet.
Ein Beispiel finden Sie in
Abschnitt 26.4.1, „PROCEDURE ANALYSE“.
Wenn Sie FOR UPDATE
mit einer
Speicher-Engine verwenden, die Seiten- oder Datensatzsperren
verwendet, dann werden die von der Abfrage untersuchten
Datensätze bis zum Ende der laufenden Transaktion
schreibgesperrt. Mithilfe von LOCK IN SHARE
MODE
wird eine gemeinsame Sperre gesetzt, die
anderen Transaktionen das Lesen, nicht jedoch das Ändern
oder Löschen der untersuchten Datensätze gestattet. Siehe
auch Abschnitt 14.2.10.5, „Lesevorgänge sperren“.
Sie können auf das Schlüsselwort SELECT
folgend eine Reihe von Optionen angeben, die den Betrieb der
Anweisung beeinflusst.
Die Optionen ALL
, DISTINCT
und DISTINCTROW
geben an, ob doppelte
Datensätze zurückgegeben werden sollen. Wird keine dieser
Optionen angegeben, dann wird ALL
als Vorgabe
vorausgesetzt (d. h., alle passenden Datensätze werden
zurückgegeben). DISTINCT
und
DISTINCTROW
sind Synonyme; sie legen fest,
dass doppelte Datensätze aus der Ergebnismenge entfernt werden.
HIGH_PRIORITY
,
STRAIGHT_JOIN
und Optionen, die mit
SQL_
beginnen, sind MySQL-Erweiterungen zum
SQL-Standard.
HIGH_PRIORITY
gibt
SELECT
Vorrang vor einer Anweisung, die
eine Tabelle aktualisiert. Sie sollten die Option nur bei
Abfragen verwenden, die sehr schnell sind und sofort
erledigt werden müssen. Eine SELECT
HIGH_PRIORITY
-Anweisung, die abgesetzt wird,
während die Tabelle zum Lesen gesperrt ist, wird auch
ausgeführt, wenn eine Aktualisierungsanweisung darauf
wartet, dass die Tabelle frei wird.
HIGH_PRIORITY
kann nicht bei
SELECT
-Anweisungen verwendet werden, die
Teil einer Union sind.
STRAIGHT_JOIN
zwingt den Optimierer zur
Verknüpfung der Tabellen in der Reihenfolge, in der sie in
der FROM
-Klausel angegeben sind. Sie
können hiermit eine Abfrage beschleunigen, wenn der
Optimierer die Tabellen nicht optimal anordnet. Siehe auch
Abschnitt 7.2.1, „EXPLAIN
-Syntax (Informationen über ein
SELECT
erhalten)“. STRAIGHT_JOIN
kann auch in der
table_references
-Liste angegeben
werden. Siehe auch Abschnitt 13.2.7.1, „JOIN
“.
SQL_BIG_RESULT
kann mit GROUP
BY
oder DISTINCT
verwendet
werden. Sie teilen dem Optimierer hierdurch mit, dass die
Ergebnismenge viele Datensätze enthält. In diesem Fall
verwendet MySQL bei Bedarf direkt festplattenbasierte
Temporärtabellen und zieht die Sortierung der Verwendung
einer Temporärtabelle mit einem Schlüssel auf
GROUP BY
-Elemente vor.
SQL_BUFFER_RESULT
erzwingt das Ablegen
des Ergebnisses in einer Temporärtabelle. Auf diese Weise
kann MySQL die Tabellensperren schnell wieder aufheben. Die
Option ist zudem in Fällen hilfreich, in denen die
Übermittlung des Ergebnisses an den Client sehr lange
dauert.
SQL_SMALL_RESULT
kann mit GROUP
BY
oder DISTINCT
verwendet
werden. Sie teilen dem Optimierer hierdurch mit, dass die
Ergebnismenge klein ist. In diesem Fall verwendet MySQL
schnelle Temporärtabellen zur Speicherung der
Ergebnistabelle anstelle einer Sortierung. Normalerweise
werden Sie diese Option nicht benötigen.
SQL_CALC_FOUND_ROWS
weist MySQL an, zu
berechnen, wie viele Datensätze ohne Berücksichtigung
einer ggf. vorhandenen LIMIT
-Klausel in
der Ergebnismenge enthalten wären. Die Anzahl der
Datensätze kann dann mit SELECT
FOUND_ROWS()
abgerufen werden. Siehe auch
Abschnitt 12.10.3, „Informationsfunktionen“.
Mit SQL_CACHE
weisen Sie MySQL an, das
Abfrageergebnis im Abfrage-Cache zu speichern, wenn Sie
einen query_cache_type
-Wert von
2
oder DEMAND
verwenden. Bei einer Abfrage, die UNION
oder Unterabfragen verwendet, betrifft diese Option alle
SELECT
-Klauseln in der Abfrage. Siehe
auch Abschnitt 5.14, „MySQL-Anfragen-Cache“.
SQL_NO_CACHE
weist MySQL an, das
Abfrageergebnis nicht im Abfrage-Cache zu speichern. Siehe
auch Abschnitt 5.14, „MySQL-Anfragen-Cache“. Bei einer Abfrage, die
UNION
oder Unterabfragen verwendet,
betrifft diese Option alle
SELECT
-Klauseln in der Abfrage.
MySQL unterstützt die folgenden
JOIN
-Syntaxen für den
table_references
-Teil von
SELECT
-Anweisungen sowie von
DELETE
- und
UPDATE
-Anweisungen für mehrere Tabellen:
table_references:
table_reference
[,table_reference
] ...table_reference
:table_factor
|join_table
table_factor
:tbl_name
[[AS]alias
] [{USE|IGNORE|FORCE} INDEX (key_list
)] | (table_references
) | { OJtable_reference
LEFT OUTER JOINtable_reference
ONconditional_expr
}join_table
:table_reference
[INNER | CROSS] JOINtable_factor
[join_condition
] |table_reference
STRAIGHT_JOINtable_factor
|table_reference
STRAIGHT_JOINtable_factor
ONcondition
|table_reference
LEFT [OUTER] JOINtable_reference
join_condition
|table_reference
NATURAL [LEFT [OUTER]] JOINtable_factor
|table_reference
RIGHT [OUTER] JOINtable_reference
join_condition
|table_reference
NATURAL [RIGHT [OUTER]] JOINtable_factor
join_condition
: ONconditional_expr
| USING (column_list
)
Eine Tabellenreferenzierung heißt auch Join-Ausdruck.
Die Syntax von table_factor
ist im
Vergleich zum SQL-Standard erweitert. SQL akzeptiert nur
table_reference
, nicht aber eine in
Klammern gesetzte Liste mit Referenzierungen.
Dies ist eine konservative Erweiterung, sofern wir jedes Komma
in einer Liste mit
table_reference
-Elementen als
äquivalent zu einem inneren Join betrachten. Zum Beispiel:
SELECT * FROM t1 LEFT JOIN (t2, t3, t4) ON (t2.a=t1.a AND t3.b=t1.b AND t4.c=t1.c)
ist äquivalent mit
SELECT * FROM t1 LEFT JOIN (t2 CROSS JOIN t3 CROSS JOIN t4) ON (t2.a=t1.a AND t3.b=t1.b AND t4.c=t1.c)
In MySQL ist CROSS JOIN
syntaktisch ein
Äquivalent zu INNER JOIN
(diese lassen
sich gegeneinander austauschen). Nach SQL-Standard hingegen
sind beide nicht äquivalent. INNER JOIN
wird bei einer ON
-Klausel und
CROSS JOIN
andernfalls verwendet.
Klammern können in Join-Ausdrücken, die nur innere Join-Operationen enthalten, ignoriert werden. MySQL unterstützt auch verschachtelte Joins (siehe auch Abschnitt 7.2.10, „Optimierung verschachtelter Joins“).
Im ON
-Teil sollten keine Bedingungen
vorhanden sein, die zur Beschränkung der Datensätze in der
Ergebnismenge verwendet werden; geben Sie solche Bedingungen
besser in der WHERE
-Klausel an. Es gibt
aber Ausnahmen zu dieser Regel.
Die oben gezeigte Syntax { OJ ... LEFT OUTER JOIN
...}
ist nur aus Gründen der Kompatibilität mit
ODBC vorhanden. Die geschweiften Klammern in der Syntax
sollten literal notiert werden, sind also keine Metasyntax,
wie sie andernorts in Syntaxbeschreibungen verwendet wird.
Für einen Tabellenverweis kann mit
oder
tbl_name
AS
alias_name
tbl_name alias_name
ein Alias
erstellt werden:
SELECT t1.name, t2.salary FROM employee AS t1, info AS t2 WHERE t1.name = t2.name; SELECT t1.name, t2.salary FROM employee t1, info t2 WHERE t1.name = t2.name;
Die Bedingungsanweisung ON
ist ein
beliebiger Bedingungsausdruck der Form, die in einer
WHERE
-Klausel verwendet werden kann.
Ist für die rechte Tabelle im ON
- oder
USING
-Teil eines LEFT
JOIN
kein passender Datensatz vorhanden, dann
wird für die rechte Tabelle ein Datensatz verwendet, bei
dem alle Spalten auf NULL
gesetzt sind.
Sie können diesen Umstand nutzen, um Datensätze in einer
Tabelle zu finden, die kein Gegenstück in einer anderen
Tabelle aufweisen:
SELECT table1.* FROM table1 LEFT JOIN table2 ON table1.id=table2.id WHERE table2.id IS NULL;
Dieses Beispiel findet alle Datensätze in
table1
mit einem
id
-Wert, der nicht in
table2
vorhanden ist (d. h. alle
Datensätze in table1
ohne
entsprechenden Datensatz in table2
).
Dies setzt voraus, dass table2.id
als
NOT NULL
deklariert wurde. Siehe auch
Abschnitt 7.2.9, „Optimierung von LEFT JOIN
und RIGHT
JOIN
“.
Die
USING(
-Klausel
benennt eine Liste mit Spalten, die in beiden Tabellen
vorhanden sein müssen. Wenn die Tabellen
column_list
)a
und b
jeweils die
Spalten c1
, c2
und
c3
enthalten, dann vergleicht der
folgende Join die entsprechenden Spalten der beiden
Tabellen:
a LEFT JOIN b USING (c1,c2,c3)
Der NATURAL [LEFT] JOIN
beider Tabellen
wird als semantisch äquivalent zu einem INNER
JOIN
oder einem LEFT JOIN
mit
einer USING
-Klausel definiert, die alle
Spalten aufführt, die in beiden Tabellen vorhanden sind.
INNER JOIN
und ,
(Komma) sind semantisch gleichwertig, wenn keine
Join-Bedingung vorhanden ist: Beide erzeugen ein
kartesisches Produkt zwischen den angegebenen Tabellen
(d. h., jeder Datensatz in der ersten Tabelle wird mit
jedem Datensatz in der zweiten Tabelle verknüpft).
RIGHT JOIN
funktioniert analog zu
LEFT JOIN
. Um den Code
datenbankübergreifend portierbar zu halten, wird
empfohlen, LEFT JOIN
anstelle von
RIGHT JOIN
zu verwenden.
STRAIGHT_JOIN
ist bis auf die Tatsache,
dass die linke Tabelle immer vor der rechten gelesen wird,
identisch mit JOIN
. Dies kann für die
(wenigen) Fälle genutzt werden, in denen der
Join-Optimierer die Tabellen in der falschen Reihenfolge
anordnet.
Sie können Hinweise dazu angeben, welchen Index MySQL beim
Abrufen von Informationen aus einer Tabelle verwenden soll.
Durch Angabe von USE INDEX
(
können Sie
MySQL anweisen, nur einen der möglichen Indizes zum Ermitteln
von Datensätzen in der Tabelle zu verwenden. Mit der
alternativen Syntax key_list
)IGNORE INDEX
(
können Sie
MySQL anweisen, einen bestimmten Index nicht zu verwenden.
Solche Hinweise sind nützlich, wenn
key_list
)EXPLAIN
zeigt, dass MySQL aus einer Liste
möglicher Indizes den falschen verwendet.
Sie können auch FORCE INDEX
verwenden.
Diese Option agiert wie USE INDEX
(
, es wird aber
zusätzlich vorausgesetzt, dass ein Tabellenscan
sehr kostspielig ist. Anders gesagt: Ein
Tabellenscan wird nur verwendet, wenn die Datensätze in der
Tabelle nicht unter der Verwendung eines der gegebenen Indizes
gefunden werden können.
key_list
)
USE INDEX
, IGNORE INDEX
und FORCE INDEX
wirken sich erst darauf
aus, welche Indizes verwendet werden, wenn MySQL entschieden
hat, wie Datensätze in der Tabelle ermittelt werden und wie
der Join durchgeführt wird. Sie haben keine Auswirkungen
darauf, ob ein Index benutzt wird, wenn eine ORDER
BY
- oder GROUP BY
-Klausel
aufgelöst wird.
USE KEY
, IGNORE KEY
und
FORCE KEY
sind Synonyme von USE
INDEX
, IGNORE INDEX
und
FORCE INDEX
.
Hier einige Beispiele für Joins:
SELECT * FROM table1,table2 WHERE table1.id=table2.id; SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id; SELECT * FROM table1 LEFT JOIN table2 USING (id); SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id LEFT JOIN table3 ON table2.id=table3.id; SELECT * FROM table1 USE INDEX (key1,key2) WHERE key1=1 AND key2=2 AND key3=3; SELECT * FROM table1 IGNORE INDEX (key3) WHERE key1=1 AND key2=2 AND key3=3;
Hinweis: Natürliche Joins
und Joins mit USING
(einschließlich
Varianten mit äußeren Joins) werden entsprechend Standard
SQL:2003 verarbeitet. Diese Änderungen erhöhen die
Kompatibilität von MySQL mit dem SQL-Standard. Allerdings
kann es bei manchen Joins zu unterschiedlichen Ausgabespalten
kommen. Ferner müssen einige Abfragen, die in älteren
Versionen (vor 5.0.12) zu funktionieren schienen, neu
geschrieben werden, um dem Standard zu entsprechen. Die
folgende Liste enthält weitere Angaben zu verschiedenen
Auswirkungen der aktuellen Join-Verarbeitung im Vergleich zur
Verarbeitung in älteren Versionen. Der Begriff
„älter“ bezeichnet hier Versionen vor MySQL
5.0.12.
Die Spalten eines NATURAL
- oder
USING
-Joins können sich von denen
älterer Versionen unterscheiden. Insbesondere erscheinen
keine redundanten Ausgabespalten mehr, und die Reihenfolge
der Spalten für die Erweiterung SELECT
*
kann anders aussehen.
Beachten Sie die folgenden Anweisungen:
CREATE TABLE t1 (i INT, j INT); CREATE TABLE t2 (k INT, j INT); INSERT INTO t1 VALUES(1,1); INSERT INTO t2 VALUES(1,1); SELECT * FROM t1 NATURAL JOIN t2; SELECT * FROM t1 JOIN t2 USING (j);
In den älteren Versionen erzeugten sie folgende Ausgabe:
+------+------+------+------+ | i | j | k | j | +------+------+------+------+ | 1 | 1 | 1 | 1 | +------+------+------+------+ +------+------+------+------+ | i | j | k | j | +------+------+------+------+ | 1 | 1 | 1 | 1 | +------+------+------+------+
In der ersten SELECT
-Anweisung
erscheint Spalte i
in beiden Tabellen
und wird insofern eine Join-Spalte, d. h., sie sollte
laut SQL-Standard nur einmal (und nicht zweimal) in der
Ausgabe erscheinen. Ähnlich ist die Spalte
j
in der zweiten
SELECT
-Anweisung in der
USING
-Klausel aufgeführt und sollte
ebenfalls nur einmal (und nicht zweimal) in der Ausgabe
auftauchen. In beiden Fällen wird die redundante Spalte
nicht beseitigt. Auch ist die Reihenfolge der Spalten
nicht korrekt im Sinne des SQL-Standards.
Heute erzeugen die Anweisungen folgende Ausgabe:
+------+------+------+ | j | i | k | +------+------+------+ | 1 | 1 | 1 | +------+------+------+ +------+------+------+ | j | i | k | +------+------+------+ | 1 | 1 | 1 | +------+------+------+
Die redundante Spalte ist beseitigt. Auch die Spaltenreihenfolge ist nun korrekt im Sinne des SQL-Standards:
Zuerst werden die Spalten, die in beiden Tabellen vorhanden sind, in der Reihenfolge aufgeführt, in der sie in der ersten Tabelle erscheinen.
Als Zweites erscheinen Spalten, die nur in der ersten Tabelle vorhanden sind, und zwar in der Reihenfolge, in der sie in der Tabelle erscheinen.
Als Drittes erscheinen Spalten, die nur in der zweiten Tabelle vorhanden sind, und zwar in der Reihenfolge, in der sie in der Tabelle erscheinen.
Die Auswertung eines natürlichen Vielfach-Joins
unterscheidet sich auf eine Weise, die ein Neuformulieren
von Abfragen erforderlich machen kann. Angenommen, Sie
haben drei Tabellen t1(a,b)
,
t2(c,b)
und t3(a,c)
,
die jeweils einen Datensatz aufweisen:
t1(1,2)
, t2(10,2)
und t3(7,10)
. Nehmen wir ferner an,
dass Sie folgenden NATURAL JOIN
auf die
drei Tabellen haben:
SELECT ... FROM t1 NATURAL JOIN t2 NATURAL JOIN t3;
In älteren Versionen wurde der linke Operand des zweiten
Joins als t2
betrachtet, wohingegen er
eigentlich der verschachtelte Join (t1 NATURAL
JOIN t2)
sein sollte. Infolgedessen werden die
Spalten von t3
nur auf gemeinsame
Spalten in t2
geprüft; hat
t3
gemeinsame Spalten mit
t1
, dann werden diese nicht als
Equi-Join-Spalten betrachtet. Insofern wurde obige Abfrage
bei älteren Versionen in den folgenden Equi-Join
transformiert:
SELECT ... FROM t1, t2, t3 WHERE t1.b = t2.b AND t2.c = t3.c;
Diesem Join fehlt aber ein weiteres Equi-Join-Prädikat
(t1.a = t3.a)
. Aufgrund dessen wird als
Ergebnis ein Datensatz ausgegeben – und nicht das
korrekte leere Ergebnis. Die korrekte äquivalente Abfrage
sieht wie folgt aus:
SELECT ... FROM t1, t2, t3 WHERE t1.b = t2.b AND t2.c = t3.c AND t1.a = t3.a;
Wenn Sie in aktuellen MySQL-Versionen dasselbe Abfrageergebnis wie bei den älteren Versionen erhalten, dann formulieren Sie den natürlichen Join als Equi-Join um.
Früher hatten der Kommaoperator (,
)
und JOIN
dieselbe Rangstufe, d. h.,
der Join-Ausdruck t1, t2 JOIN t3
wurde
als ((t1, t2) JOIN t3)
interpretiert.
Jetzt hat JOIN
Vorrang vor dem Komma,
d. h., der Ausdruck wird als (t1, (t2 JOIN
t3))
ausgewertet. Diese Änderung betrifft
Anweisungen, die eine ON
-Klausel
verwenden, denn diese Klausel kann nur Spalten in den
Operanden des Joins referenzieren, und die Änderung in
der Rangstufe wirkt sich darauf aus, wie interpretiert
wird, was diese Operanden sind.
Beispiel:
CREATE TABLE t1 (i1 INT, j1 INT); CREATE TABLE t2 (i2 INT, j2 INT); CREATE TABLE t3 (i3 INT, j3 INT); INSERT INTO t1 VALUES(1,1); INSERT INTO t2 VALUES(1,1); INSERT INTO t3 VALUES(1,1); SELECT * FROM t1, t2 JOIN t3 ON (t1.i1 = t3.i3);
In älteren Versionen war die
SELECT
-Anweisung aufgrund der
impliziten Gruppierung von t1,t2
als
(t1,t2)
zulässig. Jetzt hat
JOIN
Vorrang, d. h., die Operanden
für die ON
-Klausel sind
t2
und t3
. Da
t1.i1
keine Spalte in einem der
Operanden ist, ist das Ergebnis der Fehler
Unknown column 't1.i1' in 'on clause'
.
Um die Verarbeitung des Joins zuzulassen, gruppieren Sie
die ersten beiden Tabellen explizit mithilfe von Klammern,
sodass die Operanden für die
ON
-Klausel (t1,t2)
und t3
sind:
SELECT * FROM (t1, t2) JOIN t3 ON (t1.i1 = t3.i3);
Alternativ umgehen Sie die Verwendung des Kommaoperators
und verwenden stattdessen JOIN
:
SELECT * FROM t1 JOIN t2 JOIN t3 ON (t1.i1 = t3.i3);
Diese Änderung gilt auch für INNER
JOIN
, CROSS JOIN
,
LEFT JOIN
und RIGHT
JOIN
: Sie alle haben nun Vorrang vor dem
Kommaoperator.
Früher konnte die ON
-Klausel Spalten
in Tabellen referenzieren, die auf ihrer rechten Seite
aufgeführt wurden. Jetzt kann eine
ON
-Klausel nur ihre Operanden
referenzieren.
Beispiel:
CREATE TABLE t1 (i1 INT); CREATE TABLE t2 (i2 INT); CREATE TABLE t3 (i3 INT); SELECT * FROM t1 JOIN t2 ON (i1 = i3) JOIN t3;
Früher war diese SELECT
-Anweisung
zulässig. Nun schlägt die Anweisung mit dem Fehler
Unknown column 'i3' in 'on clause'
fehl, weil i3
eine Spalte in
t3
ist, die kein Operand der
ON
-Klausel ist. Die Anweisung sollte
wie folgt umgeschrieben werden:
SELECT * FROM t1 JOIN t2 JOIN t3 ON (i1 = i3);
Früher konnte eine USING
-Klausel als
ON
-Klausel neugeschrieben werden, die
die entsprechenden Spalten vergleichen konnte. Die beiden
folgenden Klauseln etwa sind semantisch identisch:
a LEFT JOIN b USING (c1,c2,c3) a LEFT JOIN b ON a.c1=b.c1 AND a.c2=b.c2 AND a.c3=b.c3
Heute haben diese beiden Klauseln nicht mehr dieselbe Bedeutung:
Bezüglich der Ermittlung, welche Datensätze die Join-Bedingung erfüllen, bleiben beide Joins semantisch identisch.
Allerdings ist diese semantische Identität nicht mehr
in Bezug auf die Frage vorhanden, wie die für die
SELECT *
-Erweiterung anzuzeigenden
Spalten bestimmt werden. Der
USING
-Join wählt den
zusammengefassten Wert der entsprechenden Spalten,
während der ON
-Join alle Spalten
aus allen Tabellen auswählt. Bei obigem
USING
-Join wählt SELECT
*
die folgenden Werte aus:
COALESCE(a.c1,b.c1), COALESCE(a.c2,b.c2), COALESCE(a.c3,b.c3)
Beim ON
-Join wählt SELECT
*
die folgenden Werte aus:
a.c1, a.c2, a.c3, b.c1, b.c2, b.c3
Bei einem inneren Join ist
COALESCE(a.c1,b.c1)
das Gleiche wie
a.c1
oder b.c1
,
weil beide Spalten denselben Wert haben. Bei einem
äußeren Join (wie LEFT JOIN
) darf
eine der beiden Spalten NULL
sein.
Diese Spalte wird im Ergebnis weggelassen.
SELECT ... UNION [ALL | DISTINCT] SELECT ... [UNION [ALL | DISTINCT] SELECT ...]
UNION
wird verwendet, um das Ergebnis einer
Anzahl von SELECT
-Anweisungen zu einer
Ergebnismenge zusammenzufassen.
Ausgewählte Spalten, die an den entsprechenden Positionen
jeder SELECT
-Anweisung aufgelistet sind,
sollten vom selben Typ sein. (So sollte etwa die erste von der
ersten Anweisung ausgewählte Spalte denselben Typ haben wie
die erste von den anderen Anweisungen gewählte Spalte.) Die
in der ersten SELECT
-Anweisung verwendeten
Spaltennamen werden als Spaltennamen für die zurückgegebenen
Ergebnisse benutzt.
Die SELECT
-Anweisungen sind normale
Auswahlanweisungen, es gelten jedoch die folgenden
Einschränkungen:
Nur die letzte SELECT
-Anweisung kann
INTO OUTFILE
verwenden.
HIGH_PRIORITY
kann nicht bei
SELECT
-Anweisungen verwendet werden,
die Teil einer Union sind. Wenn Sie es für die erste
SELECT
-Anweisung angeben, hat dies
keine Auswirkungen. Bei einer Angabe für eine
nachfolgende SELECT
-Anweisung tritt ein
Syntaxfehler auf.
Geben Sie das Schlüsselwort ALL
an, dann
enthält das Ergebnis alle passenden Datensätze aus allen
SELECT
-Anweisungen. Wenn Sie
DISTINCT
angeben, werden doppelte
Datensätze aus dem Ergebnis entfernt. Wird kein
Schlüsselwort benutzt, dann entspricht das Standardverhalten
dem von DISTINCT
(Entfernung doppelter
Datensätze).
Das Schlüsselwort DISTINCT
ist optional
ohne Wirkung, ist aber in der Syntax zulässig, da der
SQL-Standard dies vorschreibt. (In MySQL stellt
DISTINCT
das Standardverhalten einer Union
dar.)
Sie können UNION ALL
und UNION
DISTINCT
in derselben Abfrage gemeinsam verwenden.
Derart gemischte UNION
-Typen werden
dahingehend verarbeitet, dass eine
DISTINCT
-Union Vorrang vor einer
ALL
-Union zu ihrer Linken hat. Eine
DISTINCT
-Union kann explizit mit
UNION DISTINCT
oder implizit durch
Verwendung von UNION
ohne nachfolgende
Schlüsselwörter DISTINCT
oder
ALL
erzeugt werden.
Wenn Sie eine ORDER BY
- oder
LIMIT
-Klausel zur Sortierung bzw.
Beschränkung des gesamten Ergebnisses der Union benutzen
wollen, setzen Sie die einzelnen
SELECT
-Anweisungen in Klammern und
platzieren Sie die ORDER BY
- oder
LIMIT
-Klausel an dem Ende. Das folgende
Beispiel verwendet beide Klauseln:
(SELECT a FROM t1 WHERE a=10 AND B=1) UNION (SELECT a FROM t2 WHERE a=11 AND B=2) ORDER BY a LIMIT 10;
Diese Art von ORDER BY
kann keine
Spaltenreferenzierungen verwenden, die einen Tabellennamen
enthalten (d. h. Namen im Format
tbl_name
.col_name
).
Geben Sie stattdessen einen Spaltenalias in der ersten
SELECT
-Anweisung an und referenzieren Sie
diesen Alias in der ORDER BY
-Klausel.
Alternativ können Sie die Spalten auch in der ORDER
BY
-Klausel unter Angabe ihrer Spaltenposition
referenzieren. (Ein Alias ist allerdings vorzuziehen, weil das
Angeben von Spaltenpositionen veraltet ist.)
Ferner muss, wenn einer zu sortierenden
Spalte ein Alias zugewiesen wird, die ORDER
BY
-Klausel den Alias und nicht den Spaltennamen
referenzieren. Die erste der folgenden Anweisungen
funktioniert – im Gegensatz zur zweiten, die mit dem Fehler
Unknown column 'a' in 'order clause'
fehlschlägt:
(SELECT a AS b FROM t) UNION (SELECT ...) ORDER BY b; (SELECT a AS b FROM t) UNION (SELECT ...) ORDER BY a;
Um ORDER BY
oder LIMIT
auf eine einzelne SELECT
-Anweisung
anzuwenden, setzen Sie die Klausel mit in die Klammern, die
die SELECT
-Anweisung umschließen:
(SELECT a FROMtbl_name
WHERE a=10 AND B=1 ORDER BY a LIMIT 10) UNION (SELECT a FROMtbl_name
WHERE a=11 AND B=2 ORDER BY a LIMIT 10);
Das Einfügen von ORDER BY
bei einzelnen
SELECT
-Anweisungen in Klammern hat nur in
Kombination mit LIMIT
Auswirkungen.
Andernfalls wird ORDER BY
wegoptimiert.
Typen und Längen der Spalten in der Ergebnismenge einer Union
berücksichtigen Werte, die von allen
SELECT
-Anweisungen abgerufen wurden.
Betrachten Sie etwa einmal Folgendes:
mysql> SELECT REPEAT('a',1) UNION SELECT REPEAT('b',10);
+---------------+
| REPEAT('a',1) |
+---------------+
| a |
| bbbbbbbbbb |
+---------------+
In einigen früheren Versionen von MySQL würde der zweite Datensatz auf eine Länge von 1 gekürzt.
ANY
, IN
und
SOME
ALL
EXISTS
und NOT EXISTS
FROM
-Klausel
Eine Unterabfrage ist eine SELECT
-Anweisung
innerhalb einer anderen Anweisung.
Seit MySQL 4.1 werden alle Unterabfrageformen und -operationen, die der SQL-Standard vorsieht, ebenso unterstützt wie einige weitere Funktionen, die MySQL-spezifisch sind.
Hier ein Beispiel für eine Unterabfrage:
SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t2);
In diesem Beispiel ist SELECT * FROM t1 ...
die äußere Abfrage (oder
äußere Anweisung), und (SELECT
column1 FROM t2)
ist die
Unterabfrage. Man sagt, die Unterabfrage
ist in der äußeren Abfrage verschachtelt,
und tatsächlich ist es möglich, Unterabfragen bis zu einer
beträchtlichen Tiefe zu verschachteln. Eine Unterabfrage muss
immer in Klammern stehen.
Unterabfragen haben die folgenden Vorteile:
Sie gestatten Abfragen, die strukturiert sind. Auf diese Weise ist es möglich, jeden Teil einer Anweisung zu isolieren.
Sie bieten alternative Wege zur Durchführung von Operationen, die andernfalls komplexe Joins und Unions erfordern würden.
Sie sind – zumindest nach Meinung vieler – lesbar. Die Unterabfragen waren die eigentliche Innovation, aufgrund derer man auf die Idee kam, SQL seinerzeit als „strukturierte Abfragesprache“ zu bezeichnen.
Hier eine Beispielanweisung, die die wichtigsten Aspekte der Unterabfragensyntax zeigt, wie sie im SQL-Standard spezifiziert ist und von MySQL unterstützt wird:
DELETE FROM t1 WHERE s11 > ANY (SELECT COUNT(*) /* no hint */ FROM t2 WHERE NOT EXISTS (SELECT * FROM t3 WHERE ROW(5*t2.s1,77)= (SELECT 50,11*s1 FROM t4 UNION SELECT 50,77 FROM (SELECT * FROM t5) AS t5)));
Eine Unterabfrage kann einen Skalar (einen einzelnen Wert), einen einzelnen Datensatz, eine einzelne Spalte oder eine Tabelle (d. h. eine oder mehrere Spalten von einem oder mehreren Datensätzen) zurückgeben. Man bezeichnet diese als Skalar-, Spalten-, Datensatz- und Tabellenunterabfragen. Unterabfragen, die einen bestimmten Ergebnistyp zurückgeben, können häufig nur in bestimmten Kontexten verwendet werden, die in den folgenden Abschnitten beschrieben werden.
Es gibt ein paar wenige Einschränkungen bezüglich des Typs der
Anweisungen, in denen Unterabfragen verwendet werden können.
Eine Unterabfrage kann die gleichen Schlüsselwörter oder
Klauseln enthalten wie eine gewöhnliche
SELECT
-Anweisung:
DISTINCT
, GROUP BY
,
ORDER BY
, LIMIT
, Joins,
Indexhinweise, UNION
-Konstrukte, Kommentare,
Funktionen usw.
Eine Einschränkung besteht darin, dass die äußere Anweisung
einer Unterabfrage einen der folgenden Typen aufweisen muss:
SELECT
, INSERT
,
UPDATE
, DELETE
,
SET
oder DO
. Eine weitere
Einschränkung ist die Tatsache, dass Sie eine Tabelle derzeit
nicht ändern und gleichzeitig in einer Unterabfrage eine
Auswahl aus dieser Tabelle treffen können. Dies gilt für
Anweisungen wie DELETE
,
INSERT
, REPLACE
,
UPDATE
und (da Unterabfragen in der
SET
-Klausel verwendet werden können)
LOAD DATA INFILE
. Eine umfassendere
Beschreibung der Einschränkungen bei Unterabfragen finden Sie
in Abschnitt I.3, „Beschränkungen von Unterabfragen“.
In ihrer einfachsten Form ist eine Unterabfrage eine
Skalarunterabfrage, die einen Einzelwert zurückgibt. Eine
Skalarunterabfrage ist ein einfacher Operand, und Sie können
sie fast überall dort benutzen, wo ein einzelner Spaltenwert
oder ein Literal zulässig ist. Sie können dabei
voraussetzen, dass eine solche Unterabfrage die Eigenschaften
aufweist, die alle Operanden haben: einen Datentyp, eine
Länge, eine Angabe dazu, ob sie NULL
sein
darf oder nicht usw. Zum Beispiel:
CREATE TABLE t1 (s1 INT, s2 CHAR(5) NOT NULL); INSERT INTO t1 VALUES(100, 'abcde'); SELECT (SELECT s2 FROM t1);
Die Unterabfrage in dieser SELECT
-Anweisung
gibt einen einzelnen Wert ('abcde'
)
zurück, der den Datentyp CHAR
und die
Länge 5 aufweist, Zeichensatz und Sortierfolge den mit
CREATE TABLE
konfigurierten Vorgaben
entnimmt und die Information enthält, dass der Wert in der
Spalte auch NULL
sein kann. Tatsächlich
können fast alle Unterabfragen NULL
werden. Wäre die im Beispiel verwendete Tabelle leer, dann
wäre der Wert der Unterabfrage NULL
.
Es gibt nur ganz wenig Kontexte, in denen eine skalare
Unterabfrage nicht verwendet werden kann. Wenn eine Anweisung
nur einen literalen Wert zulässt, können Sie keine
Unterabfrage einsetzen. So erfordert beispielsweise
LIMIT
literale Integer-Argumente, und
LOAD DATA INFILE
verlangt einen literalen
String für den Dateinamen. Zur Übermittlung solcher Werte
können Sie Unterabfragen nicht benutzen.
Wenn die Beispiele in den folgenden Abschnitten das recht
spartanische Konstrukt (SELECT column1 FROM
t1)
enthalten, dann vergegenwärtigen Sie sich, dass
Ihr eigener Code wesentlich komplexere und unterschiedlichere
Konstruktionen enthalten kann (und wird).
Nehmen wir an, wir erstellen zwei Tabellen:
CREATE TABLE t1 (s1 INT); INSERT INTO t1 VALUES (1); CREATE TABLE t2 (s1 INT); INSERT INTO t2 VALUES (2);
Nun führen Sie eine SELECT
-Anweisung aus:
SELECT (SELECT s1 FROM t2) FROM t1;
Das Ergebnis ist 2
, weil in Tabelle
t2
eine Spalte s1
vorhanden ist, die den Wert 2
hat.
Eine skalare Unterabfrage kann Teil eines Ausdrucks sein. Denken Sie aber immer an die Klammern – auch dann, wenn die Unterabfrage ein Operand ist, der ein Argument für eine Funktion bereitstellt. Zum Beispiel:
SELECT UPPER((SELECT s1 FROM t1)) FROM t2;
Die häufigste Form einer Unterabfrage hat das folgende Aussehen:
non_subquery_operand
comparison_operator
(subquery
)
Hierbei ist comparison_operator
einer der folgenden Operatoren:
= > < >= <= <>
Zum Beispiel:
... 'a' = (SELECT column1 FROM t1)
Früher befand sich der einzige zulässige Ort für eine Unterabfrage auf der rechten Seite eines Vergleichs; einige wenige alte Datenbanksysteme halten nach wie vor an dieser Regel fest.
Hier ein Beispiel für einen Unterabfragenvergleich in der
gängigen Form, den Sie mit einem Join nicht durchführen
können. Hierbei werden alle Werte in Tabelle
t1
gefunden, die einem Maximalwert in
Tabelle t2
entsprechen:
SELECT column1 FROM t1 WHERE column1 = (SELECT MAX(column2) FROM t2);
Es folgt ein weiteres Beispiel, welches ebenfalls mit einem
Join nicht zu realisieren ist, da für eine der Tabellen eine
Zusammenfassung erfolgt. Gefunden werden hier alle Datensätze
in der Tabelle t1
, die einen Wert
enthalten, der in einer gegebenen Spalte zweimal auftritt:
SELECT * FROM t1 AS t WHERE 2 = (SELECT COUNT(*) FROM t1 WHERE t1.id = t.id);
Bei einem Vergleich, der mit einem dieser Operatoren
durchgeführt wird, muss die Unterabfrage einen Skalar
zurückgeben. Eine Ausnahme besteht lediglich darin, dass
=
mit Datensatzunterabfragen verwendet
werden kann. Siehe auch Abschnitt 13.2.8.5, „Zeilenunterabfragen“.
Syntax:
operand
comparison_operator
ANY (subquery
)operand
IN (subquery
)operand
comparison_operator
SOME (subquery
)
Das Schlüsselwort ANY
, das einem
Vergleichsoperator folgen muss, bedeutet „Gib
TRUE
zurück, wenn der Vergleich für jeden
beliebigen Wert in der Spalte, die die Unterabfrage
zurückgibt, wahr ist“. Zum Beispiel:
SELECT s1 FROM t1 WHERE s1 > ANY (SELECT s1 FROM t2);
Nehmen wir an, dass die Tabelle t1
einen
Datensatz mit dem Inhalt (10)
umfasst. Der
Ausdruck ist wahr, wenn Tabelle t2
(21,14,7)
enthält, weil ein Wert
7
in t2
vorhanden ist,
der kleiner als 10
ist. Der Ausdruck ist
hingegen falsch, wenn Tabelle t2
(20,10)
enthält oder leer ist. Der
Ausdruck ist schließlich unbekannt
(UNKNOWN
), wenn Tabelle
t2
(NULL,NULL,NULL)
enthält.
Das Wort IN
ist ein Alias für =
ANY
. Insofern sind die folgenden beiden Anweisungen
gleichwertig:
SELECT s1 FROM t1 WHERE s1 = ANY (SELECT s1 FROM t2); SELECT s1 FROM t1 WHERE s1 IN (SELECT s1 FROM t2);
Allerdings ist NOT IN
kein Alias für
<> ANY
, wohl aber für
<> ALL
. Siehe auch
Abschnitt 13.2.8.4, „Unterabfragen mit ALL
“.
Das Wort SOME
ist ein Alias für
ANY
. Insofern sind die folgenden beiden
Anweisungen gleichwertig:
SELECT s1 FROM t1 WHERE s1 <> ANY (SELECT s1 FROM t2); SELECT s1 FROM t1 WHERE s1 <> SOME (SELECT s1 FROM t2);
Das Wort SOME
wird zwar nur selten
verwendet, dieses Beispiel zeigt aber, wofür es nützlich
sein kann. Die meisten Menschen fassen die Phrase „a ist
nicht gleich irgendeinem b“ als „Es gibt kein b,
welches gleich a ist“ auf, aber das ist bei der
SQL-Syntax nicht gemeint. Hier bedeutet dies vielmehr
„Es gibt (mindestens) ein b, dem a nicht gleich
ist“. Indem Sie stattdessen <>
SOME
verwenden, gewährleisten Sie, dass jeder die
tatsächliche Meinung der Abfrage versteht.
Syntax:
operand
comparison_operator
ALL (subquery
)
Das Wort ALL
, das einem Vergleichsoperator
folgen muss, bedeutet „Gib TRUE
zurück, wenn der Vergleich für jeden beliebigen Wert in der
Spalte, die die Unterabfrage zurückgibt, wahr ist“.
Zum Beispiel:
SELECT s1 FROM t1 WHERE s1 > ALL (SELECT s1 FROM t2);
Nehmen wir an, dass die Tabelle t1
einen
Datensatz mit dem Inhalt (10)
umfasst. Der
Ausdruck ist wahr, wenn Tabelle t2
(-5,0,+5)
enthält, weil
10
größer als alle drei Werte in
t2
ist. Der Ausdruck ist hingegen falsch,
wenn Tabelle t2
(12,6,NULL,-100)
enthält, weil es einen
Wert (12
) in Tabelle t2
gibt, der größer als 10
ist. Der Ausdruck
ist unbekannt (d. h.
NULL
), wenn Tabelle t2
(0,NULL,1)
enthält.
Schließlich ist, wenn Tabelle t2
leer ist,
das Ergebnis wahr. Aufgrund dessen ist die folgende Anweisung
wahr, wenn Tabelle t2
leer ist:
SELECT * FROM t1 WHERE 1 > ALL (SELECT s1 FROM t2);
Folgende Anweisung ist hingegen NULL
, wenn
Tabelle t2
leer ist:
SELECT * FROM t1 WHERE 1 > (SELECT s1 FROM t2);
Ferner ist auch folgende Anweisung NULL
,
wenn Tabelle t2
leer ist:
SELECT * FROM t1 WHERE 1 > ALL (SELECT MAX(s1) FROM t2);
Generell sind Tabellen, die
NULL
-Werte enthalten, und
leere Tabellen Grenzfälle. Wenn Sie
Unterabfragencode formulieren, vergewissern Sie sich immer,
dass Sie diese beiden Fälle berücksichtigt haben.
NOT IN
ist ein Alias für <>
ALL
. Insofern sind die folgenden beiden Anweisungen
gleichwertig:
SELECT s1 FROM t1 WHERE s1 <> ALL (SELECT s1 FROM t2); SELECT s1 FROM t1 WHERE s1 NOT IN (SELECT s1 FROM t2);
Bis zu diesem Punkt haben wir ausschließlich Skalar- und Spaltenunterabfragen beschrieben, also Unterabfragen, die einen einzelnen Wert oder eine Wertespalte zurückgeben. Eine Datensatzunterabfrage ist eine Unterabfragenvariante, die einen einzelnen Datensatz zurückgibt – und insofern auch mehrere Spaltenwerte zurückgeben kann. Hier zwei Beispiele:
SELECT * FROM t1 WHERE (1,2) = (SELECT column1, column2 FROM t2); SELECT * FROM t1 WHERE ROW(1,2) = (SELECT column1, column2 FROM t2);
Die gezeigten Abfragen sind beide wahr, wenn Tabelle
t2
einen Datensatz enthält, bei dem
column1 = 1
und column2 =
2
sind.
Die Ausdrücke (1,2)
und
ROW(1,2)
heißen manchmal auch
Datensatzkonstruktoren. Beide sind
äquivalent. Sie sind zudem auch in anderen Kontexten
zulässig. So sind etwa die beiden folgenden Anweisungen
semantisch äquivalent (obwohl derzeit nur die zweite
optimiert werden kann):
SELECT * FROM t1 WHERE (column1,column2) = (1,1); SELECT * FROM t1 WHERE column1 = 1 AND column2 = 1;
Der normale Anwendungsfall von Datensatzkonstruktoren sind
Vergleiche mit Unterabfragen, die zwei oder mehr Spalten
zurückgeben. So entspricht die folgende Abfrage der
Aufforderung „Suche alle Datensätze in Tabelle
t1
, die auch in Tabelle
t2
vorhanden sind“:
SELECT column1,column2,column3 FROM t1 WHERE (column1,column2,column3) IN (SELECT column1,column2,column3 FROM t2);
Wenn eine Unterabfrage irgendwelche Datensätze zurückgibt,
ist EXISTS
wahr und
subquery
NOT EXISTS
ist falsch. Zum
Beispiel:
subquery
SELECT column1 FROM t1 WHERE EXISTS (SELECT * FROM t2);
Traditionell beginnt eine
EXISTS
-Unterabfrage mit SELECT
*
, sie könnte aber auch mit SELECT
5
oder SELECT column1
oder etwas
ganz anderem anfangen: MySQL ignoriert die
SELECT
-Liste in einer solchen Unterabfrage,
mithin macht es keinen Unterschied.
Bei obigem Beispiel ist die Bedingung wahr, wenn
t2
überhaupt Datensätze enthält (und
sogar dann, wenn es sich ausschließlich um
NULL
-Werte handelt). Dies ist aber ein
recht abwegiges Beispiel, weil eine [NOT]
EXISTS
-Unterabfrage fast immer Korrelationen
enthält. Hier einige pragmatischere Beispiele:
Welche Arten von Geschäften sind in einer oder mehreren Städten vorhanden?
SELECT DISTINCT store_type FROM stores WHERE EXISTS (SELECT * FROM cities_stores WHERE cities_stores.store_type = stores.store_type);
Welche Art von Geschäften ist in keiner Stadt vorhanden?
SELECT DISTINCT store_type FROM stores WHERE NOT EXISTS (SELECT * FROM cities_stores WHERE cities_stores.store_type = stores.store_type);
Welche Art von Geschäften ist in allen Städten vorhanden?
SELECT DISTINCT store_type FROM stores s1 WHERE NOT EXISTS ( SELECT * FROM cities WHERE NOT EXISTS ( SELECT * FROM cities_stores WHERE cities_stores.city = cities.city AND cities_stores.store_type = stores.store_type));
Das letzte Beispiel ist eine doppelt verschachtelte
NOT EXISTS
-Abfrage: Sie enthält eine
NOT EXISTS
-Klausel in einer NOT
EXISTS
-Klausel. Formell beantwortet sie die Frage
„Gibt es eine Stadt mit einem Geschäft, das nicht in
Stores
vorhanden ist?“. Aber es ist
einfacher zu sagen, dass eine verschachtelte NOT
EXISTS
-Klausel die Frage „Ist
x
für alle
y
wahr?“ beantwortet.
Eine korrelierte Unterabfrage ist eine Unterabfrage, die eine Tabelle referenziert, die auch in der äußeren Abfrage erscheint. Zum Beispiel:
SELECT * FROM t1 WHERE column1 = ANY (SELECT column1 FROM t2 WHERE t2.column2 = t1.column2);
Beachten Sie, dass die Unterabfrage eine Spalte von
t1
referenziert, obwohl die
FROM
-Klausel der Unterabfrage keine Tabelle
t1
erwählt. Also sucht MySQL außerhalb
der Unterabfrage und findet t1
in der
äußeren Abfrage.
Angenommen, Tabelle t1
enthielte einen
Datensatz, bei dem column1 = 5
und
column2 = 6
sind. Gleichzeitig enthält
Tabelle t2
einen Datensatz, bei dem
column1 = 5
und column2 =
7
sind. Der einfache Ausdruck ... WHERE
column1 = ANY (SELECT column1 FROM t2)
wäre wahr,
aber in diesem Beispiel ist die
WHERE
-Klausel innerhalb der Unterabfrage
falsch (weil nämlich (5,6)
nicht gleich
(5,7)
); also ist auch die Unterabfrage als
Ganzes falsch.
Bereichsregel: MySQL wertet von innen nach außen aus. Zum Beispiel:
SELECT column1 FROM t1 AS x WHERE x.column1 = (SELECT column1 FROM t2 AS x WHERE x.column1 = (SELECT column1 FROM t3 WHERE x.column2 = t3.column1));
In dieser Anweisung muss x.column2
eine
Spalte in der Tabelle t2
sein, weil
SELECT column1 FROM t2 AS x ...
t2
umbenennt. Es ist keine Spalte in
Tabelle t1
, weil SELECT column1
FROM t1 ...
eine äußere Abfrage ist, die
weiter außen ist.
Bei Unterabfragen in HAVING
- oder
ORDER BY
-Klauseln sucht MySQL auch nach
Spaltennamen in der äußeren Auswahlliste.
In bestimmten Fällen wird eine korrelierte Unterabfrage optimiert. Zum Beispiel:
val
IN (SELECTkey_val
FROMtbl_name
WHEREcorrelated_condition
)
Andernfalls sind sie ineffizient und zudem wahrscheinlich recht langsam. Das Umschreiben der Abfrage als Join kann die Leistung unter Umständen verbessern.
Korrelierte Unterabfragen können Ergebnisse von Zusammenfassungsfunktionen in der äußeren Abfrage nicht referenzieren.
Unterabfragen sind in der FROM
-Klausel
einer SELECT
-Anweisung zulässig. Die
eigentliche Syntax lautet:
SELECT ... FROM (subquery
) [AS]name
...
Die [AS]
-Klausel ist
obligatorisch, weil jede Tabelle in einer
name
FROM
-Klausel einen Namen haben muss. Alle
Spalten, die in der
subquery
-Auswahlliste aufgeführt
sind, benötigen eindeutige Namen. Sie finden diese Syntax an
anderer Stelle in diesem Handbuch beschrieben. Dort wird der
Begriff „abgeleitete Tabellen“ verwendet.
Zur Veranschaulichung nehmen wir an, dass Sie folgende Tabelle haben:
CREATE TABLE t1 (s1 INT, s2 CHAR(5), s3 FLOAT);
Eine Unterabfrage in der FROM
-Klausel
verwenden Sie bei der Beispieltabelle wie folgt:
INSERT INTO t1 VALUES (1,'1',1.0); INSERT INTO t1 VALUES (2,'2',2.0); SELECT sb1,sb2,sb3 FROM (SELECT s1 AS sb1, s2 AS sb2, s3*2 AS sb3 FROM t1) AS sb WHERE sb1 > 1;
Ergebnis: 2, '2', 4.0
.
Es folgt ein weiteres Beispiel: Nehmen wir an, Sie wollen den Durchschnitt einer Anzahl von Summen für eine gruppierte Tabelle ermitteln. Folgendes funktioniert nicht:
SELECT AVG(SUM(column1)) FROM t1 GROUP BY column1;
Die nächste Abfrage dagegen übermittelt die gewünschte Information:
SELECT AVG(sum_column1) FROM (SELECT SUM(column1) AS sum_column1 FROM t1 GROUP BY column1) AS t1;
Beachten Sie, dass der Spaltenname, der in der Unterabfrage
verwendet wird (sum_column1
), in der
äußeren Abfrage erkannt wird.
Unterabfragen in der FROM
-Klausel können
einen Skalar, eine Spalte, einen Datensatz oder eine Tabelle
zurückgeben. Unterabfragen in der
FROM
-Klausel dürfen keine korrelierten
Unterabfragen sein.
Unterabfragen in der FROM
-Klausel werden
auch für die EXPLAIN
-Anweisung ausgeführt
(d. h., es werden abgeleitete Temporärtabellen erstellt).
Grund hierfür ist, dass Abfragen höherer Ebenen während der
Optimierungsphase Informationen zu allen Tabellen benötigen.
Es gibt eine Reihe von Fehlern, die sich nur auf Unterabfragen beziehen. Sie werden in diesem Abschnitt beschrieben.
Falsche Anzahl von Spalten aus der Unterabfrage:
ERROR 1241 (ER_OPERAND_COL) SQLSTATE = 21000 Message = "Operand should contain 1 column(s)"
Dieser Fehler tritt in Fällen wie dem folgenden auf:
SELECT (SELECT column1, column2 FROM t2) FROM t1;
Sie können eine Unterabfrage verwenden, die mehrere Spalten zurückgibt, sofern das Ziel ein Vergleich ist. Siehe auch Abschnitt 13.2.8.5, „Zeilenunterabfragen“. Allerdings muss die Unterabfrage in anderen Kontexten ein skalarer Operand sein.
Falsche Anzahl von Datensätzen aus der Unterabfrage:
ERROR 1242 (ER_SUBSELECT_NO_1_ROW) SQLSTATE = 21000 Message = "Subquery returns more than 1 row"
Dieser Fehler tritt bei Anweisungen auf, bei denen die Unterabfrage mehr als einen Datensatz zurückgibt. Betrachten Sie einmal das folgende Beispiel:
SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t2);
Wenn SELECT column1 FROM t2
nur einen
Datensatz zurückgibt, funktioniert obige Abfrage. Gibt
die Abfrage jedoch mehrere Datensätze zurück, dann tritt
der Fehler 1242 auf. In diesem Fall sollten Sie die
Abfrage wie folgt neu formulieren:
SELECT * FROM t1 WHERE column1 = ANY (SELECT column1 FROM t2);
Falsch verwendete Tabelle in der Unterabfrage:
Error 1093 (ER_UPDATE_TABLE_USED) SQLSTATE = HY000 Message = "You can't specify target table 'x' for update in FROM clause"
Dieser Fehler tritt in Fällen wie dem folgenden auf:
UPDATE t1 SET column2 = (SELECT MAX(column1) FROM t1);
Sie können eine Unterabfrage zur Zuweisung innerhalb
einer UPDATE
-Anweisung verwenden, da
Unterabfragen in UPDATE
- und
DELETE
-Anweisungen ebenso zulässig
sind wie in SELECT
-Anweisungen.
Allerdings können Sie nicht dieselbe Tabelle (in diesem
Fall Tabelle t1
) sowohl in der
FROM
-Klausel der Unterabfrage als auch
als Aktualisierungsziel angeben.
Bei transaktionssicheren Speicher-Engines schlägt bei einem Fehlschlag einer Unterabfrage die gesamte Anweisung fehl. Bei nichttransaktionssicheren Speicher-Engines bleiben Datenänderungen, die vor Auftreten des Fehlers durchgeführt wurden, erhalten.
Die Entwicklung erfolgt kontinuierlich, d. h., Optimierungstipps sind niemals auf Dauer gültig. Die folgende Liste zeigt einige interessante Tricks, mit denen Sie ein wenig herumprobieren können:
Verwendung von Klauseln in Unterabfragen, die die Anzahl oder Reihenfolge der Datensätze in der Unterabfrage betreffen. Zum Beispiel:
SELECT * FROM t1 WHERE t1.column1 IN (SELECT column1 FROM t2 ORDER BY column1); SELECT * FROM t1 WHERE t1.column1 IN (SELECT DISTINCT column1 FROM t2); SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t2 LIMIT 1);
Ersetzen Sie einen Join durch eine Unterabfrage. Probieren Sie z. B. Folgendes aus.
SELECT DISTINCT column1 FROM t1 WHERE t1.column1 IN ( SELECT column1 FROM t2);
So hätte dies ursprünglich ausgesehen:
SELECT DISTINCT t1.column1 FROM t1, t2 WHERE t1.column1 = t2.column1;
Einige Unterabfragen können aus Gründen der Kompatibilität mit älteren MySQL-Versionen, die Unterabfragen nicht unterstützen, in Joins umgewandelt werden. Allerdings wird hierdurch in einigen Fällen die Leistungsfähigkeit beeinträchtigt. Siehe auch Abschnitt 13.2.8.11, „Umschreiben von Unterabfragen in Joins für frühere MySQL-Versionen“.
Verschieben Sie Klauseln von außen in die Unterabfrage. Verwenden Sie beispielsweise diese Abfrage …
SELECT * FROM t1 WHERE s1 IN (SELECT s1 FROM t1 UNION ALL SELECT s1 FROM t2);
… statt dieser:
SELECT * FROM t1 WHERE s1 IN (SELECT s1 FROM t1) OR s1 IN (SELECT s1 FROM t2);
Ein weiteres Beispiel: Verwenden Sie diese Abfrage …
SELECT (SELECT column1 + 5 FROM t1) FROM t2;
… statt dieser:
SELECT (SELECT column1 FROM t1) + 5 FROM t2;
Verwenden Sie eine Datensatzunterabfrage statt einer korrelierten Unterabfrage. Verwenden Sie beispielsweise diese Abfrage …
SELECT * FROM t1 WHERE (column1,column2) IN (SELECT column1,column2 FROM t2);
… statt dieser:
SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t2 WHERE t2.column1=t1.column1 AND t2.column2=t1.column2);
Verwenden Sie NOT (a = ANY (...))
statt
a <> ALL (...)
.
Verwenden Sie x = ANY (
statt
table
containing (1,2)
)x=1 OR x=2
.
Verwenden Sie = ANY
statt
EXISTS
.
Bei unkorrelierten Unterabfragen, die immer genau einen
Datensatz zurückgeben, ist IN
immer
langsamer als =
. Verwenden Sie
beispielsweise diese Abfrage …
SELECT * FROM t1 WHERE t1.col_name
= (SELECT a FROM t2 WHERE b =some_const
);
… statt dieser:
SELECT * FROM t1 WHERE t1.col_name
IN (SELECT a FROM t2 WHERE b =some_const
);
Aufgrund dieser Tricks können Programme schneller, aber auch
langsamer werden. Mithilfe von MySQL-Funktionen wie
BENCHMARK()
können Sie überprüfen, was
in Ihrer speziellen Situation hilfreich sein kann. Siehe auch
Abschnitt 12.10.3, „Informationsfunktionen“.
Die folgenden Optimierungen nimmt MySQL selbst vor:
MySQL führt nichtkorrelierte Unterabfragen nur einmal
aus. Mit EXPLAIN
können Sie
sicherstellen, dass eine gegebene Unterabfrage wirklich
nichtkorreliert ist.
MySQL schreibt IN
-,
ALL
-, ANY
- und
SOME
-Unterabfragen neu, um möglichst
davon zu profitieren, dass die Auswahllistenspalten in der
Unterabfrage indiziert sind.
MySQL ersetzt Unterabfragen der folgenden Form durch eine
Indexsuchfunktion, die EXPLAIN
als
speziellen Join-Typ beschreibt
(unique_subquery
oder
index_subquery
):
... IN (SELECTindexed_column
FROMsingle_table
...)
MySQL erweitert Ausdrücke der folgenden Form mit einem
Ausdruck mit MIN()
oder
MAX()
, sofern
NULL
-Werte oder Leermengen vorhanden
sind:
value
{ALL|ANY|SOME} {> | < | >= | <=} (non-correlated subquery
)
Betrachten Sie etwa folgende
WHERE
-Klausel:
WHERE 5 > ALL (SELECT x FROM t)
Diese könnte vom Optimierer wie folgt geändert werden:
WHERE 5 > (SELECT MAX(x) FROM t)
Es gibt ein Kapitel „How MySQL Transforms Subqueries“ („Wie MySQL Unterabfragen transformiert“) im Handbuch „MySQL Internals“ (MySQL-Interna, derzeit nur auf Englisch verfügbar), welches Sie unter http://dev.mysql.com/doc/ erhalten.
Bei älteren MySQL-Versionen (vor Version 4.1) wurden nur
verschachtelte Abfragen der Formen INSERT ... SELECT
...
und REPLACE ... SELECT ...
unterstützt. Zwar trifft dies bei MySQL 5.1
nicht mehr zu, aber nach wie vor werden gelegentlich andere
Möglichkeiten eingesetzt, um auf Mitgliedschaft in einer
Wertemenge zu prüfen. Außerdem ist es unter bestimmten
Umständen nicht nur möglich, eine Abfrage ohne Unterabfrage
zu schreiben, sondern es kann auch effizienter sein, einige
der folgenden Methoden zu verwenden, statt Unterabfragen
einzusetzen. Eine dieser Methode ist das Konstrukt
IN()
:
Betrachten Sie etwa folgende Abfrage:
SELECT * FROM t1 WHERE id IN (SELECT id FROM t2);
Sie kann wie folgt umgeschrieben werden:
SELECT DISTINCT t1.* FROM t1, t2 WHERE t1.id=t2.id;
Ein anderes Beispiel sind folgende Abfragen:
SELECT * FROM t1 WHERE id NOT IN (SELECT id FROM t2); SELECT * FROM t1 WHERE NOT EXISTS (SELECT id FROM t2 WHERE t1.id=t2.id);
Auch sie lassen sich mithilfe von IN()
umschreiben:
SELECT table1.* FROM table1 LEFT JOIN table2 ON table1.id=table2.id WHERE table2.id IS NULL;
Ein LEFT [OUTER] JOIN
kann schneller sein
als die äquivalente Unterabfrage, weil der Server unter
Umständen in der Lage ist, ihn besser zu optimieren – eine
Tatsache, die nicht nur für den MySQL Server gilt. Vor SQL-92
waren äußere Joins nicht vorhanden, d. h., Unterabfragen
stellten für bestimmte Aufgaben die einzige Lösung dar.
Heute bieten MySQL Server und viele andere moderne
Datenbanksysteme eine Vielzahl von Typen für äußere Joins.
MySQL Server unterstützt
DELETE
-Anweisungen über mehrere Tabellen,
die zur effizienten gleichzeitigen Löschung von Datensätzen
basierend auf Daten in einer Tabelle (oder sogar mehreren
Tabellen) benutzt werden. Auch
UPDATE
-Anweisungen über mehrere Tabellen
werden unterstützt.
TRUNCATE [TABLE] tbl_name
TRUNCATE TABLE
leert eine Tabelle
vollständig. Logisch gesehen ist dies äquivalent zu einer
DELETE
-Anweisung, die alle Datensätze
löscht, aber es gibt unter bestimmten Umständen praktische
Unterschiede.
Bei InnoDB
-Tabellen wird TRUNCATE
TABLE
auf DELETE
umgesetzt, sofern
keine Fremdschlüssel-Constraints vorhanden sind, die die
Tabelle referenzieren; andernfalls wird das schnelle Leeren
(durch Löschen und Neuerstellen der Tabelle) verwendet. Der
AUTO_INCREMENT
-Zähler wird von
TRUNCATE TABLE
unabhängig vom Vorhandensein
eines Fremdschlüssel-Constraints zurückgesetzt.
Bei anderen Speicher-Engines unterscheidet sich
TRUNCATE TABLE
in MySQL 5.1 wie
folgt von DELETE
:
Leerungsoperationen löschen die Tabelle und erstellen sie dann neu, was wesentlich schneller ist als das aufeinander folgende Löschen aller Datensätze.
Leerungsoperationen sind nicht transaktionssicher: Wenn Sie eine solche Operation während einer aktiven Transaktion oder einer aktiven Tabellensperrung durchführen wollen, tritt ein Fehler auf.
Die Anzahl gelöschter Datensätze wird nicht zurückgegeben.
Solange die Tabellenformatdatei
gültig ist, lässt sich die Tabelle mit tbl_name
.frmTRUNCATE
TABLE
auch dann als leere Tabelle neu erstellen,
wenn die Daten- oder Indexdateien beschädigt wurden.
Der Tabellen-Handler speichert den zuletzt verwendeten
AUTO_INCREMENT
-Wert nicht, sondern fängt
mit der Zählung von vorne an. Dies gilt auch für
MyISAM
- und
InnoDB
-Tabellen, die Sequenzwerte
normalerweise nicht erneut verwenden.
Bei der Verwendung mit partitionierten Tabellen behält
TRUNCATE TABLE
die Partitionierung bei,
d. h., Daten- und Indexdateien werden gelöscht und neu
erstellt, während die Partitionsdefinitionsdatei
(.par
) hiervon unberührt bleibt.
TRUNCATE TABLE
ist eine Oracle
SQL-Erweiterung, die in MySQL übernommen wurde.
Syntax für eine Tabelle:
UPDATE [LOW_PRIORITY] [IGNORE]tbl_name
SETcol_name1
=expr1
[,col_name2
=expr2
...] [WHEREwhere_condition
] [ORDER BY ...] [LIMITrow_count
]
Syntax für mehrere Tabellen:
UPDATE [LOW_PRIORITY] [IGNORE]table_references
SETcol_name1
=expr1
[,col_name2
=expr2
...] [WHEREwhere_condition
]
Bei der Ein-Tabellen-Syntax aktualisiert die
UPDATE
-Anweisung Spalten in vorhandenen
Datensätzen in tbl_name
mit neuen Werten.
Die SET
-Klausel gibt an, welche Spalten
geändert werden und welche Werte diese erhalten sollen. Sofern
angegeben, bestimmt die WHERE
-Klausel die
Bedingungen dafür, welche Datensätze geändert werden. Ohne
WHERE
-Klausel werden alle Datensätze
aktualisiert. Wenn die ORDER BY
-Klausel
vorhanden ist, werden die Datensätze in der angegebenen
Reihenfolge aktualisiert. Die LIMIT
-Klausel
kann die Anzahl der zu aktualisierenden Datensätze
beschränken.
Bei der Mehrtabellensyntax aktualisiert
UPDATE
in jeder Tabelle
table_references
die Datensätze, die
die Bedingungen erfüllen. In diesem Fall können ORDER
BY
und LIMIT
nicht verwendet
werden.
where_condition
ist ein Ausdruck, der
für jeden zu aktualisierenden Datensatz wahr ist. Er wird wie
in Abschnitt 13.2.7, „SELECT
“, beschrieben angegeben.
Die UPDATE
-Anweisung unterstützt die
folgenden Modifizierer:
Wenn Sie das Schlüsselwort LOW_PRIORITY
angeben, wird die Ausführung von UPDATE
verzögert, bis kein Client mehr aus der Tabelle liest.
Wenn Sie das Schlüsselwort IGNORE
verwenden, bricht die UPDATE
-Anweisung
auch dann nicht ab, wenn während der Aktualisierung Fehler
auftreten. Datensätze, bei denen Konflikte aufgrund von
Schlüsseldubletten auftreten, werden nicht geändert.
Datensätze, bei denen Spalten auf Werte gesetzt werden
würden, die Datenkonvertierungsfehler zur Folge hätten,
werden stattdessen auf den nächstgelegenen gültigen Wert
gesetzt.
Wenn Sie in einem Ausdruck auf eine Spalte in der Tabelle
tbl_name
zugreifen, verwendet
UPDATE
den aktuellen Wert der Spalte. So
erhöht die folgende Anweisung beispielsweise den aktuellen Wert
in der Spalte age
um 1:
UPDATE persondata SET age=age+1;
UPDATE
-Zuordnungen werden von links nach
rechts ausgewertet. Die folgende Anweisung etwa verdoppelt die
Spalte age
und erhöht sie dann um 1:
UPDATE persondata SET age=age*2, age=age+1;
Wenn Sie eine Spalte auf den Wert aktualisieren, den sie ohnehin gerade hat, dann bemerkt MySQL dies und führt keine Aktualisierung durch.
Wenn Sie eine als NOT NULL
deklarierte Spalte
aktualisieren, indem Sie sie auf NULL
setzen,
wird die Spalte stattdessen auf den für den jeweiligen Datentyp
vorgesehenen Standardwert gesetzt und der Warnungszähler
erhöht. Der Vorgabewert ist 0
bei
numerischen Typen, der Leer-String (''
) bei
String-Typen und der „Nullwert“ für Datums- und
Uhrzeittypen.
UPDATE
gibt die Anzahl der tatsächlich
geänderten Datensätze zurück. Die C-API-Funktion
mysql_info()
hingegen gibt die Anzahl der
Datensätze, die gefunden und aktualisiert wurden, sowie die
Anzahl der Warnungen zurück, die während der
UPDATE
-Operation aufgetreten sind.
Sie können LIMIT
verwenden, um den
Geltungsbereich von row_count
UPDATE
einzuschränken.
Eine LIMIT
-Klausel ist eine Beschränkung
für Datensätze. Die Anweisung endet, sobald eine Anzahl von
row_count
Datensätzen gefunden
wurde, die der WHERE
-Klausel entsprechen –
unabhängig davon, ob sie dann auch geändert wurden oder nicht.
Wenn eine UPDATE
-Anweisung eine
ORDER BY
-Klausel enthält, werden die
Datensätze in der in der Klausel angegebenen Reihenfolge
aktualisiert.
Sie können auch UPDATE
-Operationen
durchführen, die sich auf mehrere Tabellen beziehen. Allerdings
können Sie ORDER BY
oder
LIMIT
nicht in einer
UPDATE
-Anweisung für mehrere Tabellen
verwenden. Die Klausel
table_references
listet die Tabellen
auf, die im Join berücksichtigt werden. Die Syntax ist in
Abschnitt 13.2.7.1, „JOIN
“, beschrieben. Hier ein Beispiel:
UPDATE items,month SET items.price=month.price WHERE items.id=month.id;
Das obige Beispiel zeigt einen inneren Join, der den
Kommaoperator verwendet. UPDATE
-Anweisungen
für mehrere Tabellen können jedoch einen beliebigen Join-Typ
verwenden, der für SELECT
-Anweisungen
zulässig ist, also etwa LEFT JOIN
.
Sie benötigen die Berechtigung UPDATE
nur
für diejenigen in einer UPDATE
-Anweisung
für mehrere Tabellen referenzierten Spalten, die tatsächlich
geändert werden. Die Berechtigung SELECT
hingegen benötigen Sie für alle Spalten, die gelesen, aber
nicht modifiziert werden.
Wenn Sie eine UPDATE
-Anweisung für mehrere
Tabellen verwenden, die auch InnoDB
-Tabellen
einbezieht, für die Fremdschlüssel-Constraints vorhanden sind,
dann verarbeitet der MySQL-Optimierer die Tabellen unter
Umständen in einer Reihenfolge, die sich von der ihrer
Parent/Child-Beziehung unterscheidet. In diesem Fall schlägt
die Anweisung fehl, und es wird ein Rollback durchgeführt.
Stattdessen sollten Sie die Änderung dann in nur einer Tabelle
durchführen und sich auf die ON
UPDATE
-Funktionalität verlassen, die
InnoDB
bietet, um andere Tabellen
entsprechend zu ändern. Siehe auch
Abschnitt 14.2.6.4, „Fremdschlüssel-Beschränkungen“.
Zurzeit können Sie in einer Unterabfrage keine Aktualisierungsoperation in einer Tabelle durchführen und gleichzeitig eine Auswahl in einer anderen Tabelle treffen.
{DESCRIBE | DESC}tbl_name
[col_name
|wild
]
DESCRIBE
vermittelt Informationen zu Spalten
in einer Tabelle. Es handelt sich um ein Synonym für
SHOW COLUMNS FROM
. Diese Anweisungen erlauben
auch die Anzeige von Informationen zu Views. (Siehe auch
Abschnitt 13.5.4.3, „SHOW COLUMNS
“.)
col_name
kann ein Spaltenname oder
aber ein String sein, der die SQL-Jokerzeichen
‘%
’ und
‘_
’ enthält, um eine Ausgabe nur
zu Spalten zu erhalten, die dem String entsprechen. Sie müssen
den String nicht in Anführungszeichen setzen, sofern er nicht
Leerzeichen oder andere Sonderzeichen enthält.
mysql> DESCRIBE city;
+------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+----------+------+-----+---------+----------------+
| Id | int(11) | NO | PRI | NULL | auto_increment |
| Name | char(35) | NO | | | |
| Country | char(3) | NO | UNI | | |
| District | char(20) | YES | MUL | | |
| Population | int(11) | NO | | 0 | |
+------------+----------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
Field
gibt den Spaltennamen an.
Das Feld Null
zeigt an, ob
NULL
-Werte in der Spalte gespeichert werden
können.
Das Feld Key
gibt an, ob die Spalte indiziert
ist. Mit PRI
wird angegeben, dass die Spalte
Teil des Primärschlüssels der Tabelle ist, mit
UNI
hingegen, dass sie Teil eines eindeutigen
Indexes ist. Der Wert MUL
schließlich
signalisiert, dass mehrere Instanzen eines gegebenen Werts
innerhalb der Spalte zulässig sind.
Ein möglicher Grund für die Anzeige von MUL
in einem eindeutigen Index besteht darin, dass mehrere Spalten
einen zusammengesetzten eindeutigen Index bilden. Dann ist die
Kombination der Spalten eindeutig, während die einzelnen
Spalten durchaus mehrere Instanzen eines gegebenen Werts
enthalten können. Beachten Sie, dass in einem zusammengesetzten
Index nur die links stehende Spalte einen Eintrag im Feld
Key
hat.
Das Feld Default
gibt den Standardwert der
Spalte an.
Das Feld Extra
enthält zusätzliche Angaben,
die zu einer gegebenen Spalte verfügbar sind. Im gezeigten
Beispiel gibt Extra
an, dass die Spalte
Id
mit dem Schlüsselwort
AUTO_INCREMENT
erstellt wurde.
Die Anweisung DESCRIBE
ist aus Gründen der
Kompatibilität mit Oracle vorhanden.
Auch die Anweisungen SHOW CREATE TABLE
und
SHOW TABLE STATUS
bieten Informationen zu
Tabellen. Siehe auch Abschnitt 13.5.4, „SHOW
“.
USE db_name
Die Anweisung USE
weist MySQL an, die
Datenbank db_name
db_name
als
Standarddatenbank (d. h. als aktuelle Datenbank) zu benutzen,
auf die sich nachfolgende Anweisungen beziehen. Die Datenbank
wird bis zum Ende der Sitzung oder aber so lange als Vorgabe
verwendet, bis eine andere USE
-Anweisung
abgesetzt wird:
USE db1; SELECT COUNT(*) FROM mytable; # selects from db1.mytable USE db2; SELECT COUNT(*) FROM mytable; # selects from db2.mytable
Wenn Sie eine bestimmte Datenbank mit USE
zur
Standarddatenbank machen, können Sie trotzdem auf Tabellen in
anderen Datenbanken zugreifen. Im folgenden Beispiel wird auf
die Tabelle author
in der Datenbank
db1
und die Tabelle editor
in der Datenbank db2
zugegriffen:
USE db1; SELECT author_name,editor_name FROM author,db2.editor WHERE author.editor_id = db2.editor.editor_id;
Die Anweisung USE
ist aus Gründen der
Kompatibilität mit Sybase vorhanden.
MySQL unterstützt lokale Transaktionen (über eine gegebene
Clientverbindung) unter Verwendung von Anweisungen wie
SET AUTOCOMMIT
, START
TRANSACTION
, COMMIT
und
ROLLBACK
. Siehe auch Abschnitt 13.4.1, „BEGIN/COMMIT/ROLLBACK
“.
Die Unterstützung von XA-Transaktionen erlaubt MySQL außerdem
die Teilnahme an verteilten Transaktionen. Siehe auch
Abschnitt 13.4.7, „XA-Transaktionen“.
START TRANSACTION | BEGIN [WORK] COMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE] ROLLBACK [WORK] [AND [NO] CHAIN] [[NO] RELEASE] SET AUTOCOMMIT = {0 | 1}
Die Anweisungen START TRANSACTION
und
BEGIN
starten eine neue Transaktion.
COMMIT
übergibt die aktuelle Transaktion,
macht also die entsprechenden Änderungen permanent. Mit
ROLLBACK
machen Sie die laufende Transaktion
rückgängig, d. h., alle Änderungen werden zurückgenommen.
Die Anweisung SET AUTOCOMMIT
schließlich
aktiviert oder deaktiviert den standardmäßigen
Autocommit-Modus für die aktuelle Verbindung.
Das optionale Schlüsselwort WORK
wird für
COMMIT
und RELEASE
unterstützt, ebenso die CHAIN
- und
RELEASE
-Klauseln. CHAIN
und RELEASE
können verwendet werden, um den
Transaktionsabschluss besser steuern zu können. Der Wert der
Systemvariablen completion_type
bestimmt das
Standardverhalten beim Transaktionsabschluss. Siehe auch
Abschnitt 5.2.2, „Server-Systemvariablen“.
Die AND CHAIN
-Klausel bewirkt, dass eine neue
Transaktion beginnt, sobald die aktuelle endet. Die neue
Transaktion hat dabei dieselbe Isolierungsstufe wie die zuvor
beendete Transaktion. Die RELEASE
-Klausel
bewirkt, dass der Server die aktuelle Clientverbindung nach
Abschluss der aktuellen Transaktion beendet. Das Schlüsselwort
NO
unterdrückt den Abschluss von
CHAIN
oder RELEASE
. Dies
kann nützlich sein, wenn aufgrund der Einstellung der
Systemvariablen completion_type
der Abschluss
von CHAIN
oder RELEASE
standardmäßig erzwungen wird.
Standardmäßig läuft MySQL im Autocommit-Modus. Das bedeutet, dass, sobald eine Anweisung ausgeführt wird, die eine Tabelle aktualisiert (also ändert), MySQL diese Änderung auf Festplatte speichert.
Verwenden Sie eine transaktionssichere Speicher-Engine (wie
InnoDB
, BDB
oder
NDB Cluster
), dann können Sie den
Autocommit-Modus mit der folgenden Anweisung deaktivieren:
SET AUTOCOMMIT=0;
Nach der Deaktivierung des Autocommit-Modus durch Setzen der
AUTOCOMMIT
-Variablen auf Null müssen Sie
Ihre Änderungen mit COMMIT
auf Festplatte
speichern oder mit ROLLBACK
rückgängig
machen, wenn Sie die seit Beginn der Transaktion vorgenommenen
Änderungen nicht übernehmen wollen.
Um den Autocommit-Modus für eine einzelne Abfolge von
Anweisungen zu deaktivieren, verwenden Sie die Anweisung
START TRANSACTION
:
START TRANSACTION; SELECT @A:=SUM(salary) FROM table1 WHERE type=1; UPDATE table2 SET summary=@A WHERE type=1; COMMIT;
Bei START TRANSACTION
bleibt Autocommit
deaktiviert, bis Sie die Transaktion mit
COMMIT
oder ROLLBACK
beenden. Der Autocommit-Modus kehrt dann in seinen vorherigen
Status zurück.
BEGIN
und BEGIN WORK
werden als Aliase für START TRANSACTION
benutzt, um eine Transaktion zu starten. START
TRANSACTION
ist die SQL-Standardsyntax und wird als
Möglichkeit zur Durchführung spontaner Transaktionen
empfohlen.
Die BEGIN
-Anweisung unterscheidet sich von
der Verwendung des Schlüsselworts BEGIN
,
welches eine mehrteilige BEGIN ...
END
-Anweisung einleitet. Mit Letzterem wird keine
Transaktion begonnen. Siehe auch Abschnitt 19.2.5, „BEGIN ... END
-Syntax für komplexe Anweisungen“.
Sie können eine Transaktion auch wie folgt einleiten:
START TRANSACTION WITH CONSISTENT SNAPSHOT;
Die Klausel WITH CONSISTENT SNAPSHOT
startet
eine konsistente Leseoperation für Speicher-Engines, die diese
unterstützen. Derzeit betrifft dies nur
InnoDB
. Der Effekt ist derselbe wie beim
Absetzen einer START TRANSACTION
-Anweisung
gefolgt von einer SELECT
-Anweisung für eine
beliebige InnoDB
-Tabelle. Siehe auch
Abschnitt 14.2.10.4, „Konsistentes Lesen“.
Die Klausel WITH CONSISTENT SNAPSHOT
ändert
die aktuelle Isolationsstufe der Transaktion nicht, d. h., eine
konsistente Momentaufnahme wird nur dann erstellt, wenn die
aktuelle Isolationsstufe konsistente Leseoperationen gestattet
(REPEATABLE READ
oder
SERIALIZABLE
).
Bei Beginn einer Transaktion wird implizit UNLOCK
TABLES
ausgeführt.
Beste Ergebnisse erhalten Sie, wenn Sie Transaktionen nur bei Tabellen durchführen, die mit einer einzelnen transaktionssicheren Speicher-Engine verwaltet werden. Andernfalls können die folgenden Probleme auftreten:
Wenn Ihre Tabellen mehrere transaktionssichere
Speicher-Engines verwenden (z. B. InnoDB
und BDB
) und die Isolationsstufe nicht
SERIALIZABLE
ist, besteht die
Möglichkeit, dass, wenn eine Transaktion übergeben wird,
eine andere laufende Transaktion, die dieselben Tabellen
benutzt, nur einen Teil der durch die erste Transaktion
vorgenommenen Änderungen erkennt. Die Atomizität der
Transaktionen ist mithin bei Verwendung mehrerer Engines
nicht gewährleistet, und es können Inkonsistenzen
auftreten. (Wenn Transaktionen mehrerer Engines nicht
häufig vorkommen, können Sie die Isolationsstufe mit
SET TRANSACTION ISOLATION LEVEL
für eine
Transaktion nach Bedarf auf SERIALIZABLE
setzen.)
Verwenden Sie in einer Transaktion nichttransaktionssichere Tabellen, dann werden alle Änderungen an diesen Tabellen unabhängig vom Status des Autocommit-Modus sofort gespeichert.
Wenn Sie nach Aktualisierung einer nichttransaktionssicheren
Tabelle in einer Transaktion eine
ROLLBACK
-Anweisung absetzen, erscheint
die Warnung
ER_WARNING_NOT_COMPLETE_ROLLBACK
.
Änderungen an transaktionssicheren Tabellen werden in
diesem Fall rückgängig gemacht, nicht jedoch Änderungen
an nichttransaktionssicheren Tabellen.
Jede Transaktion wird nach Absetzen von
COMMIT
am Stück in das Binärlog
geschrieben. Transaktionen, die per Rollback rückgängig
gemacht wurden, werden nicht geloggt.
(Ausnahme: Für Modifikationen
an nicht transaktionssicheren Tabellen kann kein Rollback
durchgeführt werden. Wenn eine Transaktion, für die ein
Rollback erfolgt, Änderungen an nicht transaktionssicheren
Tabellen enthält, dann wird die gesamte Transaktion am Ende mit
einer ROLLBACK
-Anweisung geloggt, um
sicherzustellen, dass die Modifikationen an diesen Tabellen
repliziert werden.) Siehe auch Abschnitt 5.12.3, „Die binäre Update-Logdatei“.
Sie können die Isolationsstufe für Transaktionen mit
SET TRANSACTION ISOLATION LEVEL
ändern.
Siehe auch Abschnitt 13.4.6, „SET TRANSACTION
“.
Ein Rollback kann ein relativ langsamer Vorgang sein, der zudem
stattfinden kann, ohne dass der Benutzer dies explizit
angefordert hat (z. B. wenn ein Fehler aufgetreten ist).
Aufgrund dieser Tatsache zeigt SHOW
PROCESSLIST
in der Spalte State
für die Verbindung Rolling back
an, solange
implizite oder (durch die SQL-Anweisung
ROLLBACK
) explizite Rollbacks durchgeführt
werden.
Es gibt Anweisungen, für die kein Rollback möglich ist. Hierzu gehören DDL-Anweisungen (Data Definition Language), z. B. solche, mit denen Datenbanken erstellt oder gelöscht oder Tabellen oder gespeicherte Routinen erstellt, gelöscht oder geändert werden.
Sie sollten Ihre Transaktionen so entwickeln, dass solche
Anweisungen nicht vorhanden sind. Wenn Sie eine Anweisung früh
in einer Transaktion absetzen, für die kein Rollback möglich
ist, und dann später eine andere Anweisung fehlschlägt, dann
können durch Absetzen der ROLLBACK
-Anweisung
nicht alle Auswirkungen der Transaktion rückgängig gemacht
werden.
Alle folgenden Anweisungen (und ggf. auch ihre Synonyme) beenden
eine Transaktion implizit – so als ob Sie vor Ausführung der
Anweisung eine COMMIT
-Anweisung abgesetzt
hätten:
ALTER FUNCTION
, ALTER
PROCEDURE
, ALTER TABLE
,
BEGIN
, CREATE
DATABASE
, CREATE FUNCTION
,
CREATE INDEX
, CREATE
PROCEDURE
, CREATE TABLE
,
DROP DATABASE
, DROP
FUNCTION
, DROP INDEX
,
DROP PROCEDURE
, DROP
TABLE
, LOAD MASTER DATA
,
LOCK TABLES
, RENAME
TABLE
, SET AUTOCOMMIT=1
,
START TRANSACTION
, TRUNCATE
TABLE
, UNLOCK TABLES
.
UNLOCK TABLES
übergibt eine Transaktion
nur dann, wenn zum betreffenden Zeitpunkt Tabellen gesperrt
sind.
Die Anweisung CREATE TABLE
in
InnoDB
wird als einzelne Transaktion
verarbeitet. Das bedeutet, dass eine
ROLLBACK
-Anweisung seitens des Benutzers
die CREATE TABLE
-Anweisungen, die der
Benutzer während der Transaktion abgesetzt hat, nicht
rückgängig machen kann.
Transaktionen können nicht verschachtelt werden. Dies ist eine
Folge des impliziten COMMIT
, das für jede
laufende Transaktion ausgeführt wird, wenn Sie eine
START TRANSACTION
-Anweisung (oder ein
entsprechendes Synonym) absetzen.
SAVEPOINTidentifier
ROLLBACK [WORK] TO SAVEPOINTidentifier
RELEASE SAVEPOINTidentifier
InnoDB
unterstützt die SQL-Anweisungen
SAVEPOINT
, ROLLBACK TO
SAVEPOINT
, RELEASE SAVEPOINT
und
das optionale Schlüsselwort WORK
für
ROLLBACK
.
Die SAVEPOINT
-Anweisung setzt einen benannten
Transaktionsspeicherpunkt mit dem Namen
identifier
. Hat die laufende
Transaktion einen Speicherpunkt gleichen Namens, dann wird der
alte Speicherpunkt gelöscht und ein neuer gesetzt.
Die Anweisung ROLLBACK TO SAVEPOINT
macht
eine Transaktion bis zum benannten Speicherpunkt rückgängig.
Änderungen, die die aktuelle Transaktion an Datensätzen nach
dem Speicherpunkt vorgenommen hat, werden im Rollback
rückgängig gemacht; allerdings hebt InnoDB
Datensatzsperren, die nach dem Speicherpunkt im Speicher
abgelegt wurden, nicht auf. (Beachten Sie,
dass bei einem neu eingefügten Datensatz die Sperrinformation
in dem im Datensatz gespeicherten Transaktionsbezeichner
enthalten ist, d. h., die Sperre wird nicht separat im Speicher
abgelegt. In diesem Fall wird die Datensatzsperre beim
Rückgängigmachen aufgehoben.) Speicherpunkte, die zeitlich
nach dem genannten Speicherpunkt liegen, werden gelöscht.
Wenn die ROLLBACK TO SAVEPOINT
-Anweisung den
folgenden Fehler zurückgibt, heißt das, dass es keinen
Speicherpunkt des angegebenen Namens gibt:
ERROR 1181: Got error 153 during ROLLBACK
Die Anweisung RELEASE SAVEPOINT
entfernt den
genannten Speicherpunkt aus der Menge der Speicherpunkte für
die laufende Transaktion. Es findet weder eine Übergabe noch
ein Rollback statt. Existiert der Speicherpunkt nicht, dann
tritt ein Fehler auf.
Alle Speicherpunkte der aktuellen Transaktion werden gelöscht,
wenn Sie eine COMMIT
- oder
ROLLBACK
-Anweisung absetzen, die keinen
Speicherpunkt benennt.
Seit MySQL 5.0.17 wird eine neue Speicherpunktstufe erstellt, wenn eine gespeicherte Funktion aufgerufen oder ein Trigger aktiviert wird. Die Speicherpunkte der vorherigen Stufen sind dann nicht mehr verfügbar, damit Konflikte mit Speicherpunkten der neuen Stufe vermieden werden. Wenn die Funktion oder der Trigger beendet wird, werden alle hierdurch erstellten Speicherpunkte gelöscht und die vorherige Speicherpunktstufe wird wiederhergestellt.
LOCK TABLEStbl_name
[ASalias
] {READ [LOCAL] | [LOW_PRIORITY] WRITE} [,tbl_name
[ASalias
] {READ [LOCAL] | [LOW_PRIORITY] WRITE}] ... UNLOCK TABLES
LOCK TABLES
sperrt Tabellen für den
aktuellen Thread. Wenn eine Tabelle von anderen Threads gesperrt
ist, wird der laufende Vorgang angehalten, bis alle Sperren
erwirkt werden können. UNLOCK TABLES
hebt
Sperren auf, die vom aktuellen Thread gehalten werden. Die
Sperren aller Tabellen, die vom aktuellen Thread gesperrt
werden, werden implizit aufgehoben, wenn der Thread eine andere
LOCK TABLES
-Anweisung absetzt oder die
Verbindung zum Server geschlossen wird.
Eine Tabellensperre schützt nur gegen unangemessene Lese- und
Schreiboperationen durch andere Clients. Der Client, der die
Sperre (auch eine Lesesperre) hält, kann Operationen auf
Tabellenebene – wie etwa DROP TABLE
–
durchführen.
Beachten Sie die folgenden Angaben zur Verwendung von
LOCK TABLES
bei transaktionssicheren
Tabellen:
LOCK TABLES
ist nicht transaktionssicher
und übergibt implizit alle aktiven Transaktionen, bevor
versucht wird, die Sperre für die Tabelle zu erwirken. Auch
das Starten einer Transaktion (z. B. bei START
TRANSACTION
) führt implizit eine UNLOCK
TABLES
-Anweisung aus. (Siehe auch
Abschnitt 13.4.3, „Anweisungen, die implizite Commits verursachen“.)
Die korrekte Vorgehensweise bei der Verwendung von
LOCK TABLES
in Verbindung mit
transaktionssicheren Tabellen wie InnoDB
besteht darin, AUTOCOMMIT = 0
zu setzen
und UNLOCK TABLES
erst dann aufzurufen,
wenn die Transaktion explizit übergeben werden soll. Wenn
Sie LOCK TABLES
aufrufen, setzt
InnoDB
intern eine eigene Tabellensperre.
Auch MySQL setzt eine eigene Tabellensperre.
InnoDB
hebt seine Sperre beim nächsten
Commit-Vorgang auf; damit MySQL seinerseits die Sperre
aufhebt, müssen Sie UNLOCK TABLES
aufrufen. Sie sollten AUTOCOMMIT = 1
nicht setzen, weil InnoDB
dann seine
Tabellensperre direkt nach dem Aufruf von LOCK
TABLES
aufhebt; auf diese Weise kann es zu einer
vollständigen Sperrung kommen. Beachten Sie, dass bei
AUTOCOMMIT = 1
die
InnoDB
-Tabellensperre überhaupt nicht
gesetzt wird, damit ältere Anwendungen sich nicht
versehentlich vollständig ausschließen.
ROLLBACK
hebt die Sperren bei den
nichttransaktionssicheren Tabellen von MySQL nicht auf.
Um LOCK TABLES
zu verwenden, benötigen Sie
die Berechtigungen LOCK TABLES
und
SELECT
für die betreffenden Tabellen.
Die wichtigsten Gründe zur Verwendung von LOCK
TABLES
sind die Emulation von Transaktionen oder die
Beschleunigung der Aktualisierung von Tabellen. Wir werden dies
weiter unten ausführlicher erläutern.
Wenn ein Thread eine Lesesperre für eine Tabelle erwirkt, kann dieser Thread (wie auch alle übrigen Threads) aus der Tabelle nur lesen. Wenn ein Thread eine Schreibsperre für eine Tabelle erwirkt, dann kann nur der Thread, der die Sperre hält, in die Tabelle schreiben. Anderen Threads wird dies untersagt, bis die Sperre aufgehoben ist.
Der Unterschied zwischen READ LOCAL
und
READ
besteht darin, dass READ
LOCAL
bei aktiver Sperre die Ausführung von
INSERT
-Anweisungen (also nebenläufigen
Einfügeoperationen) zulässt, sofern sie keine Konflikte
auslösen. Allerdings kann diese Funktion nicht verwendet
werden, um die Datenbankdateien bei aktiver Sperre außerhalb
von MySQL zu manipulieren. Bei
InnoDB
-Tabellen entspricht READ
LOCAL
READ
.
Wenn Sie LOCK TABLES
einsetzen, müssen Sie
alle Tabellen sperren, die Sie in Ihren Abfragen zu benutzen
beabsichtigen. Solange die mit einer LOCK
TABLES
-Anweisung erwirkten Sperren gültig sind,
können Sie nicht auf Tabellen zugreifen, die nicht durch die
Anweisung gesperrt wurden. Ferner können Sie eine gesperrte
Tabelle auch nicht mehrfach in derselben Abfrage verwenden.
Benutzen Sie stattdessen Aliase. In diesem Fall müssen Sie
allerdings für jeden Alias separat eine Sperre erwirken.
mysql>LOCK TABLE t WRITE, t AS t1 WRITE;
mysql>INSERT INTO t SELECT * FROM t;
ERROR 1100: Table 't' was not locked with LOCK TABLES mysql>INSERT INTO t SELECT * FROM t AS t1;
Wenn Ihre Abfragen eine Tabelle unter Verwendung eines Alias referenzieren, müssen Sie die Tabelle sperren, die denselben Alias benutzt. Die Tabelle zu sperren, ohne den Alias anzugeben, funktioniert nicht:
mysql>LOCK TABLE t READ;
mysql>SELECT * FROM t AS myalias;
ERROR 1100: Table 'myalias' was not locked with LOCK TABLES
Umgekehrt müssen Sie, wenn Sie eine Tabelle unter Verwendung eines Alias sperren, diese Tabelle unter Verwendung dieses Alias in Ihren Abfragen referenzieren:
mysql>LOCK TABLE t AS myalias READ;
mysql>SELECT * FROM t;
ERROR 1100: Table 't' was not locked with LOCK TABLES mysql>SELECT * FROM t AS myalias;
WRITE
-Sperren haben in der Regel Vorrang vor
READ
-Sperren. Hierdurch soll sichergestellt
werden, dass Aktualisierungen so schnell wie möglich
verarbeitet werden. Das bedeutet, dass, wenn ein Thread eine
READ
-Sperre erwirkt und dann ein anderer
Thread eine WRITE
-Sperre anfordert,
nachfolgende READ
-Sperranforderungen warten
müssen, bis der WRITE
-Thread die Sperre
wieder aufgehoben hat. Sie können mit LOW_PRIORITY
WRITE
-Sperren anderen Threads das Erwirken von
READ
-Sperren gestatten, während der Thread
auf die WRITE
-Sperre wartet.
LOW_PRIORITY WRITE
-Sperren sollten Sie nur
dann verwenden, wenn Sie sicher sind, dass zu einem
nachfolgenden Zeitpunkt keine Threads mehr eine
READ
-Sperre halten werden.
LOCK TABLES
funktioniert wie folgt:
Alle zu sperrenden Tabellen werden in einer intern definierten Reihenfolge sortiert. Aus Sicht des Benutzers ist diese Reihenfolge undefiniert.
Wenn eine Tabelle mit einer Lese- und einer Schreibsperre gesperrt ist, wird die Schreib- vor der Lesesperre gesetzt.
Es wird immer nur eine Tabelle gleichzeitig gesperrt, bis der Thread alle Sperren erhalten hat.
Diese Vorgehensweise gewährleistet, dass ein Aussperren ausgeschlossen ist. Es gibt jedoch ein paar andere Aspekte, die Sie bezüglich der Vorgehensweise beachten sollten:
Wenn Sie eine LOW_PRIORITY WRITE
-Sperre für
eine Tabelle verwenden, bedeutet dies lediglich, dass MySQL auf
diese bestimmte Sperre wartet, bis keine Threads mehr vorhanden
sind, die eine READ
-Sperre benötigen. Wenn
der Thread die WRITE
-Sperre erwirkt hat und
darauf wartet, die Sperre für die nächste Tabelle in der
Sperrliste zu erwirken, warten alle anderen Threads darauf, dass
die WRITE
-Sperre aufgehoben wird. Wenn dies
in Bezug auf Ihre Anwendung ein schwerwiegendes Problem
darstellen sollte, dann sollten Sie in Betracht ziehen, einige
Ihrer Tabellen in transaktionssichere Tabellen umzuwandeln.
Sie können einen Thread, der auf eine Tabellensperre wartet,
problemlos mit KILL
terminieren. Siehe auch
Abschnitt 13.5.5.3, „KILL
“.
Beachten Sie, dass Sie keine Tabellen
sperren sollen, die Sie mit INSERT DELAYED
verwenden, weil die Einfügeoperation in diesem Fall durch einen
separaten Thread durchgeführt wird.
Normalerweise müssen Sie Tabellen nicht sperren, weil alle
UPDATE
-Anweisungen für sich atomisch sind:
Kein anderer Thread kann eine andere derzeit ausgeführte
SQL-Anweisung unterbrechen. Allerdings gibt es einige wenige
Fälle, in denen das Sperren von Tabellen von Vorteil sein kann:
Wenn Sie viele Operationen für eine Anzahl von
MyISAM
-Tabellen ausführen wollen, geht
dies schneller, wenn Sie die zu verwendenden Tabellen
sperren. Das Sperren von MyISAM
-Tabellen
beschleunigt das Einfügen, Aktualisieren und Löschen in
diesen Tabellen. Der Nachteil besteht darin, dass kein
Thread eine READ
-gesperrte Tabelle
ändern kann (einschließlich derjenigen, die die Sperre
hält) und dass kein Thread auf eine
WRITE
-gesperrte Tabelle mit Ausnahme
derjenigen zugreifen kann, die die Sperre hält.
Der Grund dafür, dass MyISAM
-Operationen
unter LOCK TABLES
schneller ausgeführt
werden, besteht darin, dass MySQL den Schlüssel-Cache
gesperrter Tabellen erst beim Aufruf von UNLOCK
TABLES
synchronisiert. Normalerweise wird der
Schlüssel-Cache nach jeder SQL-Anweisung synchronisiert.
Wenn Sie eine Speicher-Engine in MySQL verwenden, die
Transaktionen nicht unterstützt, müssen Sie LOCK
TABLES
einsetzen, um sicherzustellen, dass kein
anderer Thread zwischen eine SELECT
- und
eine UPDATE
-Anweisung gelangt. Folgendes
Beispiel erfordert LOCK TABLES
, um sicher
ausgeführt werden zu können:
LOCK TABLES trans READ, customer WRITE; SELECT SUM(value) FROM trans WHERE customer_id=some_id
; UPDATE customer SET total_value=sum_from_previous_statement
WHERE customer_id=some_id
; UNLOCK TABLES;
Ohne LOCK TABLES
könnte ein anderer
Thread unter Umständen zwischen der Ausführung der
SELECT
- und der Ausführung der
UPDATE
-Anweisung einen neuen Datensatz in
die trans
-Tabelle einfügen.
Sie können die Verwendung von LOCK TABLES
in
vielen Fällen umgehen, indem Sie relative Updates
(UPDATE customer SET
)
oder die Funktion value
=value
+new_value
LAST_INSERT_ID()
verwenden.
Siehe auch Abschnitt 1.9.5.3, „Transaktionen“.
Sie können das Sperren von Tabellen in manchen Fällen auch
umgehen, indem Sie Funktionen für beratende Sperrungen auf
Benutzerebene (GET_LOCK()
und
RELEASE_LOCK()
) verwenden. Diese Sperren
werden in einer Hash-Tabelle auf dem Server gespeichert und mit
pthread_mutex_lock()
und
pthread_mutex_unlock()
mit dem Ziel einer
hohen Geschwindigkeit implementiert. Siehe auch
Abschnitt 12.10.4, „Verschiedene Funktionen“.
Weitere Informationen zu Methoden beim Sperren finden Sie in Abschnitt 7.3.1, „Wie MySQL Tabellen sperrt“.
Sie können mit der Anweisung FLUSH TABLES WITH READ
LOCK
Lesesperren für alle Tabellen in allen
Datenbanken setzen. Siehe auch Abschnitt 13.5.5.2, „FLUSH
“. Dies ist
eine recht praktische Möglichkeit der Datensicherung, wenn Sie
ein Dateisystem wie Veritas einsetzen, das rechtzeitig
Schnappschüsse erstellt.
Hinweis: Wenn Sie
ALTER TABLE
für eine gesperrte Tabelle
ausführen, kann die Sperre unter Umständen aufgehoben werden.
Siehe auch Abschnitt A.7.1, „Probleme mit ALTER TABLE
“.
SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL { READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE }
Diese Anweisung bestimmt die Transaktionsisolationsstufe für die nächste Transaktion, global oder für die aktuelle Sitzung.
Das Standardverhalten von SET TRANSACTION
besteht darin, die Isolationsstufe für die nächste (d. h.
noch nicht gestartete) Transaktion einzustellen. Wenn Sie das
Schlüsselwort GLOBAL
verwenden, setzt die
Anweisung die Standardtransaktionsstufe global für alle neuen
Verbindungen, die nachfolgend hergestellt werden. Vorhandene
Verbindungen werden hiervon nicht berührt. Für diesen Zweck
benötigen Sie die Berechtigung SUPER
. Bei
Verwendung des Schlüsselworts SESSION
wird
die standardmäßige Transaktionsstufe für alle zukünftigen
Transaktionen gesetzt, die über die aktuelle Verbindung
durchgeführt werden.
Beschreibungen aller
InnoDB
-Transaktionsisolationsstufen finden
Sie in Abschnitt 14.2.10.3, „InnoDB
und TRANSACTION ISOLATION
LEVEL
“.
InnoDB
unterstützt in MySQL 5.1
alle Stufen. Die Standardstufe ist REPEATABLE
READ
.
Um die globale Standardisolationsstufe für
mysqld festzulegen, verwenden Sie die Option
--transaction-isolation
. Siehe auch
Abschnitt 5.2.1, „Befehlsoptionen für mysqld“.
Die Unterstützung von XA-Transaktionen ist für die
InnoDB
-Speicher-Engine verfügbar. Die
XA-Implementierung bei MySQL basiert auf dem X/Open CAE-Dokument
Distributed Transaction Processing: The XA
Specification („Verteilte
Transaktionsverarbeitung: Die XA-Spezifikation“). Dieses
Dokument wurde von The Open Group veröffentlicht und ist unter
http://www.opengroup.org/public/pubs/catalog/c193.htm
erhältlich. Die Grenzen der aktuellen XA-Implementierung sind
in Abschnitt I.5, „Beschränkungen bei XA-Transaktionen“ beschrieben.
Clientseitig gibt es keine besonderen Anforderungen. Die
XA-Schnittstelle zu einem MySQL Server besteht aus
SQL-Anweisungen, die mit dem Schlüsselwort
XA
beginnen. MySQL-Clientprogramme müssen
SQL-Anweisungen senden und die Semantik der
XA-Anweisungsschnittstelle verstehen können. Sie müssen nicht
mit einer aktuellen Clientbibliothek verknüpft sein: Es können
auch ältere Clientbibliotheken verwendet werden.
Derzeit unterstützt MySQL Connector/J 5.0.0 XA direkt (mithilfe einer Klassenschnittstelle, die die XA-SQL-Anweisungsschnittstelle für Sie verwaltet).
XA unterstützt verteilte Transaktionen, d. h., mehrere separate transaktionssichere Ressourcen können an einer globalen Transaktion teilnehmen. Transaktionssichere Ressourcen sind häufig relationale Datenbanksysteme, es gibt aber auch andere Ressourcentypen.
Eine globale Transaktion umfasst mehrere Aktionen, die für sich
transaktionssicher sind; sie alle aber müssen entweder als
Gruppe erfolgreich abgeschlossen werden, oder sie werden im
Rahmen eines Rollbacks gemeinsam rückgängig gemacht. Im
Endeffekt erweitert dies die ACID-Eigenschaften um eine
„Ebene nach oben“, sodass mehrere
ACID-Transaktionen konzertiert als Komponenten einer globalen
Operation ausgeführt werden, die ebenfalls ACID-Eigenschaften
hat. (Allerdings müssen Sie bei einer verteilten Transaktion
die Isolationsstufe SERIALIZABLE
benutzen, um
ACID-Eigenschaften zu erhalten. Bei nichtverteilten
Transaktionen ist REPEATABLE READ
ausreichend, nicht aber bei verteilten Transaktionen.)
Es folgen einige Beispiele für verteilte Transaktionen:
Eine Anwendung kann als Integrations-Tool agieren, welches einen Messaging-Dienst mit einem relationalen Datenbanksystem kombiniert. Die Anwendung stellt sicher, dass Transaktionen, die Versand, Abruf und Verarbeitung von Mitteilungen in Verbindung mit einer transaktionssicheren Datenbank regeln, auch alle in einer globalen Transaktion erfolgen. Man könnte sich dies als „transaktionssichere E-Mail“ vorstellen.
Eine Anwendung führt Aktionen durch, die verschiedene Datenbankserver betrifft, z. B. einen MySQL und einen Oracle-Server (oder auch mehrere MySQL Server). Hierbei müssen Aktionen, die mehrere Server betreffen, als Teil einer globalen Transaktion statt als separate Transaktionen stattfinden, die auf jedem Server getrennt ausgeführt werden.
Eine Bank speichert Kontendaten in einem relationalen Datenbanksystem. Empfang und Versand von Geld erfolgen über Bankautomaten. Es muss dabei gewährleistet sein, dass alle Vorgänge an den Automaten auf den Konten umgesetzt werden. Dies ist aber nicht allein mit dem Datenbanksystem möglich: Ein globaler Transaktionsmanager integriert Bankautomat- und Datenbankressourcen, um die Gesamtkonsistenz der Finanztransaktionen sicherzustellen.
Anwendungen, die globale Transaktionen verwenden, umfassen einen oder mehrere Ressourcenmanager und einen Transaktionsmanager:
Der Ressourcenmanager (RM) ermöglicht den Zugriff auf transaktionssichere Ressourcen. Ein Datenbankserver ist eine Art von Ressourcenmanager. Transaktionen, die vom RM verwaltet werden, müssen entweder im Rahmen eines Commits geschrieben oder im Zuge eines Rollbacks rückgängig gemacht werden können.
Ein Transaktionsmanager (TM) koordiniert die Transaktionen, die Teil einer globalen Transaktion sind. Er kommuniziert mit den RMs, die die einzelnen Transaktionen verwalten. Die einzelnen Transaktionen innerhalb einer globalen Transaktion sind die „Verzweigungen“ der globalen Transaktion. Globale Transaktionen und ihre Verzweigungen werden anhand eines Namensschemas unterschieden, welches weiter unten beschrieben werden wird.
Die MySQL-Implementierung von XA erlaubt es einem MySQL Server, als RM zu agieren, der XA-Transaktionen innerhalb einer globalen Transaktion verwaltet. Ein Clientprogramm, das eine Verbindung mit dem MySQL Server herstellt, agiert als TM.
Um eine globale Transaktion auszuführen, ist es erforderlich zu wissen, welche Komponenten betroffen sind, und jede dieser Komponenten an einen Punkt zu bringen, an dem sie übergeben oder rückgängig gemacht werden kann. Abhängig davon, was jede Komponente bezüglich ihres Erfolgs oder Fehlschlags meldet, müssen sie alle als atomische Gruppe übergeben oder rückgängig gemacht werden: Es müssen also entweder alle Komponenten geschrieben werden oder alle Komponenten werden im Zuge eines Rollbacks ungeschehen gemacht. Um eine globale Transaktion verwalten zu können, muss berücksichtigt werden, dass jede Komponente fehlschlagen oder auch das sie verbindende Netzwerk ausfallen kann.
Der Prozess zur Ausführung einer globalen Transaktion basiert auf 2PC (2-Phase Commit, Übergabe in zwei Phasen). Dies findet statt, nachdem die von den Verzweigungen der globalen Transaktion durchgeführten Vorgänge erledigt sind.
In der ersten Phase werden alle Verzweigungen vorbereitet: Sie werden vom TM angewiesen, sich für die Übergabe bereitzuhalten. Normalerweise bedeutet dies, dass jeder RM, der eine Verzweigung verwaltet, die Aktionen für diese Verzweigung in einem zuverlässigen Speicher ablegt. Die Verzweigungen geben an, ob dies jeweils für sie möglich ist. Die Ergebnisse werden in der zweiten Phase verwendet.
In der zweiten Phase weist der TM die RMs an, eine Übergabe oder einen Rollback durchzuführen. Wenn alle Verzweigungen bei der Vorbereitung angegeben haben, dass sie für eine Übergabe bereit sind, werden sie alle zur Übergabe angewiesen. Hat jedoch mindestens eine Verzweigung im Zuge der Vorbereitung gemeldet, dass bei ihr keine Übergabe möglich ist, dann werden alle Verzweigungen zu einem Rollback angewiesen.
In manchen Fällen verwendet eine globale Transaktion unter Umständen nur eine einphasige Übergabe (1PC). Stellt beispielsweise ein TM fest, dass eine globale Transaktion nur eine einzige transaktionssichere Ressource (also nur eine Verzweigung) umfasst, dann kann diese Ressource zur selben Zeit zur Vorbereitung und Übergabe angewiesen werden.
Um XA-Transaktionen in MySQL durchzuführen, verwenden Sie die folgenden Anweisungen:
XA {START|BEGIN}xid
[JOIN|RESUME] XA ENDxid
[SUSPEND [FOR MIGRATE]] XA PREPARExid
XA COMMITxid
[ONE PHASE] XA ROLLBACKxid
XA RECOVER
Bei XA START
werden die Klauseln
JOIN
und RESUME
nicht
unterstützt.
Bei XA END
wird die Klausel
SUSPEND [FOR MIGRATE]
nicht unterstützt.
Jede XA-Anweisung beginnt mit dem Schlüsselwort
XA
. Die meisten dieser Anweisungen
erfordern einen xid
-Wert.
xid
ist ein
XA-Transaktionsbezeichner. Er gibt an, für welche Transaktion
die Anweisung gilt. xid
-Werte
werden vom Client übergeben oder auf dem MySQL Server
erzeugt. Ein xid
-Wert besteht aus
einem bis drei Teilen:
xid
:gtrid
[,bqual
[,formatID
]]
gtrid
ist ein globaler
Transaktionsbezeichner, bqual
ein
Verzweigungsbezeichner und formatID
eine Zahl, die das Format angibt, welches von den
gtrid
- und
bqual
-Werten verwendet wird. Wie
aus der Syntax hervorgeht, sind
bqual
und
formatID
optional. Der Standardwert
von bqual
ist
''
, sofern nichts anderes angegeben ist.
Der Standardwert von formatID
ist
1, sofern nichts anderes angegeben ist.
gtrid
und
bqual
müssen String-Literale sein,
die jeweils bis zu 64 Byte (nicht Zeichen) lang sein dürfen.
gtrid
und
bqual
können auf unterschiedliche
Art und Weise angegeben werden. Sie können einen String in
Anführungszeichen ('ab'
), einen
Hexadezimal-String (0x6162
,
X'ab'
) oder einen Bitwert
(b'
)
angeben.
nnnn
'
formatID
ist ein vorzeichenloser
Integer.
Die gtrid
- und
bqual
-Werte werden von den
XA-Supportroutinen auf dem MySQL Server als Bytewerte
interpretiert. Allerdings benutzt der Server bei der Analyse
einer SQL-Anweisung, die eine XA-Anweisung enthält, einen
speziellen Zeichensatz. Wenn Sie sichergehen wollen, notieren
Sie gtrid
und
bqual
als Hexadezimal-String.
xid
-Werte werden normalerweise vom
TM erzeugt. Die Werte, die von einem TM erzeugt werden,
müssen sich von denen unterscheiden, die von anderen TMs
gebildet werden. Ein gegebener TM muss seine eigenen
xid
-Werte in einer Werteliste, die
von der Anweisung XA RECOVER
zurückgegeben
wird, erkennen können.
XA START
startet eine XA-Transaktion mit dem gegebenen
xid
xid
-Wert. Jede XA-Transaktion
benötigt einen eindeutigen
xid
-Wert, d. h., der Wert darf
nicht gleichzeitig von einer anderen XA-Transaktion verwendet
werden. Diese Eindeutigkeit wird mithilfe der Werte
gtrid
und
bqual
erzielt. Alle nachfolgenden
XA-Anweisungen für die XA-Transaktion müssen unter
Verwendung desselben xid
-Werts
angegeben werden, der in der XA
START
-Anweisung übergeben wurde. Verwenden Sie eine
dieser Anweisungen und geben dabei keinen
xid
-Wert an, der einer laufenden
XA-Transaktion entspricht, dann tritt ein Fehler auf.
Eine oder mehrere XA-Transaktionen können Teil derselben
globalen Transaktion sein. Alle XA-Transaktionen in einer
gegebenen globalen Transaktion müssen denselben
gtrid
-Wert im
xid
-Wert benutzen. Aus diesem Grund
müssen gtrid
-Werte global
eindeutig sein, damit keine Mehrdeutigkeiten darüber
aufkommen können, zu welcher globalen Transaktion eine
gegebene XA-Transaktion gehört. Der Teil
bqual
des
xid
-Werts muss sich für jede
XA-Transaktion innerhalb einer globalen Transaktion
unterscheiden. (Die Anforderung, dass
bqual
-Werte unterschiedlich sein
müssen, stellt eine Einschränkung der aktuellen
XA-Implementierung in MySQL dar. Sie ist nicht Teil der
XA-Spezifikation.)
Die Anweisung XA RECOVER
gibt Informationen
zu denjenigen XA-Transaktionen auf dem MySQL Server zurück,
die den Status PREPARED
haben. (Siehe auch
Abschnitt 13.4.7.2, „XA-Transaktionszustände“.) Die Ausgabe enthält einen
Datensatz für jede derartige XA-Transaktion auf dem Server
– unabhängig davon, welcher Client sie gestartet hat.
Die Ausgabedatensätze von XA RECOVER
sehen
wie folgt aus (für einen
xid
-Beispielwert, der aus den
Teilen 'abc'
, 'def'
und
7
besteht):
mysql> XA RECOVER;
+----------+--------------+--------------+--------+
| formatID | gtrid_length | bqual_length | data |
+----------+--------------+--------------+--------+
| 7 | 3 | 3 | abcdef |
+----------+--------------+--------------+--------+
Die Ausgabespalten haben die nachfolgend beschriebenen Bedeutungen:
formatID
ist der
formatID
-Teil der Transaktion
xid
.
gtrid_length
ist die Länge des
gtrid
-Teils der Transaktion
xid
in Byte.
bqual_length
ist die Länge des
bqual
-Teils der Transaktion
xid
in Byte.
data
ist die Verkettung der Teile
gtrid
und
bqual
der Transaktion
xid
.
Eine XA-Transaktion umfasst die folgenden Phasen:
Starten Sie mit XA START
eine
XA-Transaktion und versetzen Sie sie in den Status
ACTIVE
.
Sobald die XA-Transaktion aktiv ist, setzen Sie die
SQL-Anweisungen für die Transaktion ab. Zuletzt setzen
Sie eine XA END
-Anweisung ab, mit der
Sie die Transaktion in den Zustand IDLE
versetzen.
Bei einer XA-Transaktion in diesem Zustand können Sie
entweder eine XA PREPARE
-Anweisung oder
eine XA COMMIT ... ONE PHASE
-Anweisung
absetzen:
XA PREPARE
versetzt die Transaktion
in den Zustand PREPARED
. Bei
Eingabe einer XA RECOVER
-Anweisung
an dieser Stelle wird der
xid
-Wert der Transaktion in
die Ausgabe integriert, weil XA
RECOVER
alle XA-Transaktionen auflistet,
deren Zustand PREPARED
ist.
XA COMMIT ... ONE PHASE
bereit die
Transaktion vor und übergibt sie dann direkt. Der
xid
-Wert wird von
XA RECOVER
nicht aufgelistet, weil
die Transaktion endet.
Bei einer XA-Transaktion im Zustand
PREPARED
können Sie eine XA
COMMIT
-Anweisung absetzen, um sie zu übergeben
und zu beenden, oder Sie machen sie mit einer XA
ROLLBACK
-Anweisung rückgängig (sie wird dann
ebenfalls beendet).
Es folgt eine einfache XA-Transaktion, die im Rahmen einer globalen Transaktion einen Datensatz in eine Tabelle einfügt:
mysql>XA START 'xatest';
Query OK, 0 rows affected (0.00 sec) mysql>INSERT INTO mytable (i) VALUES(10);
Query OK, 1 row affected (0.04 sec) mysql>XA END 'xatest';
Query OK, 0 rows affected (0.00 sec) mysql>XA PREPARE 'xatest';
Query OK, 0 rows affected (0.00 sec) mysql>XA COMMIT 'xatest';
Query OK, 0 rows affected (0.00 sec)
Im Kontext einer gegebenen Clientverbindung schließen sich
XA-Transaktionen und lokale Transaktionen (also
Nicht-XA-Transaktionen) gegenseitig aus. Wenn beispielsweise
mit XA START
eine XA-Transaktion gestartet
wurde, dann kann eine lokale Transaktion erst begonnen werden,
wenn die XA-Transaktion übergeben oder rückgängig gemacht
wurde. Umgekehrt können, wenn eine lokale Transaktion mit
START TRANSACTION
begonnen wurde,
XA-Anweisungen erst dann verwendet werden, wenn die
Transaktion übergeben oder rückgängig gemacht wurde.
MySQL-Kontendaten sind in Tabellen der Datenbank
mysql
gespeichert. Diese Datenbank und das
Zugriffssteuerungssystem sind in
Kapitel 5, Datenbankverwaltung, ausführlich
beschrieben. Sie finden dort weitere Informationen.
Wichtig: Einige Releases von MySQL enthalten Änderungen an der Struktur der Grant-Tabellen, damit neue Berechtigungen oder Funktionen hinzugefügt werden können. Wenn Sie ein Upgrade auf eine neue MySQL-Version durchführen, sollten Sie Ihre Grant-Tabellen aktualisieren, damit sichergestellt ist, dass diese auf der aktuellen Struktur basieren und auf diese Weise neue Funktionalitäten nutzen können. Siehe auch Abschnitt 5.6, „mysql_fix_privilege_tables — Upgrade von MySQL-Systemtabellen“.
CREATE USERuser
[IDENTIFIED BY [PASSWORD] 'password
'] [,user
[IDENTIFIED BY [PASSWORD] 'password
']] ...
Die CREATE USER
-Anweisung erstellt neue
MySQL-Konten. Um sie zu verwenden, benötigen Sie die globale
Berechtigung CREATE USER
oder die
Berechtigung INSERT
für die Datenbank
mysql
. Für jedes Konto richtet
CREATE USER
einen neuen Datensatz in der
Tabelle mysql.user
ein, der keine
Berechtigungen hat. Ist das Konto bereits vorhanden, dann
tritt ein Fehler auf. Jedes Konto wird im selben Format wie
bei der GRANT
-Anweisung benannt (z. B.
'jeffrey'@'localhost'
). Die Benutzer- und
Hostbestandteile des Kontonamens entsprechen den Werten der
Spalten User
und Host
des kontenspezifischen Datensatzes in der Tabelle
user
.
Das Konto erhält ein Passwort mit der optionalen
IDENTIFIED BY
-Klausel. Der Wert
user
und das Passwort werden auf
gleiche Weise übergeben wie bei der
GRANT
-Anweisung. Insbesondere müssen Sie
das Schlüsselwort PASSWORD
weglassen, um
das Passwort im Klartext angeben zu können. Wenn Sie das
Passwort hingegen als von der Funktion
PASSWORD()
zurückgegebenen Hash-Wert
angeben wollen, schließen Sie das Schlüsselwort
PASSWORD
mit ein. Siehe auch
Abschnitt 13.5.1.3, „GRANT
und REVOKE
“.
DROP USERuser
[,user
] ...
Die Anweisung DROP USER
entfernt ein oder
mehrere MySQL-Konten. Sie löscht die Berechtigungsdatensätze
des Kontos aus allen Grant-Tabellen. Um diese Anweisung zu
verwenden, benötigen Sie die globale Berechtigung
CREATE USER
oder die Berechtigung
DELETE
für die Datenbank
mysql
. Jedes Konto wird im selben Format
wie bei der GRANT
-Anweisung benannt (z. B.
'jeffrey'@'localhost'
). Die Benutzer- und
Hostbestandteile des Kontonamens entsprechen den Werten der
Spalten User
und Host
des kontenspezifischen Datensatzes in der Tabelle
user
.
Mit DROP USER
können Sie ein Konto und
seine Berechtigungen wie folgt entfernen:
DROP USER user
;
Wichtig
: DROP USER
schließt offene
Benutzersitzungen nicht automatisch. Stattdessen wird, wenn
ein zu löschender Benutzer gerade eine offene Sitzung hat,
die Anweisung erst umgesetzt, wenn die Sitzung dieses
Benutzers beendet wurde. Sobald die Sitzung beendet ist, wird
der Benutzer gelöscht: Nachfolgende Versuche des Benutzers,
sich anzumelden, schlagen dann fehl. Dies ist
bewusst so implementiert.
GRANTpriv_type
[(column_list
)] [,priv_type
[(column_list
)]] ... ON [object_type
] {tbl_name
| * | *.* |db_name
.*} TOuser
[IDENTIFIED BY [PASSWORD] 'password
'] [,user
[IDENTIFIED BY [PASSWORD] 'password
']] ... [REQUIRE NONE | [{SSL| X509}] [CIPHER 'cipher
' [AND]] [ISSUER 'issuer
' [AND]] [SUBJECT 'subject
']] [WITHwith_option
[with_option
] ...]object_type
= TABLE | FUNCTION | PROCEDUREwith_option
= GRANT OPTION | MAX_QUERIES_PER_HOURcount
| MAX_UPDATES_PER_HOURcount
| MAX_CONNECTIONS_PER_HOURcount
| MAX_USER_CONNECTIONScount
Die GRANT
-Anweisung erlaubt
Systemadministratoren die Erstellung von MySQL-Benutzerkonten
und die Vergabe von Rechten an diese Konten. Um
GRANT
verwenden zu können, benötigen Sie
die Berechtigung GRANT OPTION
sowie alle
Berechtigungen, die Sie selbst gewähren. Die
REVOKE
-Anweisung ist in diesem Zusammenhang
ebenfalls zu nennen: Sie gestattet Administratoren das
Entfernen von Kontenberechtigungen. Siehe auch
Abschnitt 13.5.1.5, „REVOKE
“.
MySQL-Kontendaten sind in Tabellen der Datenbank
mysql
gespeichert. Diese Datenbank und das
Zugriffssteuerungssystem sind in
Kapitel 5, Datenbankverwaltung, ausführlich
beschrieben. Sie finden dort weitere Informationen.
Wichtig: Einige Releases von MySQL enthalten Änderungen an der Struktur der Grant-Tabellen, damit neue Berechtigungen oder Funktionen hinzugefügt werden können. Wenn Sie ein Upgrade auf eine neue MySQL-Version durchführen, sollten Sie Ihre Grant-Tabellen aktualisieren, damit sichergestellt ist, dass diese auf der aktuellen Struktur basieren und auf diese Weise neue Funktionalitäten nutzen können. Siehe auch Abschnitt 5.6, „mysql_fix_privilege_tables — Upgrade von MySQL-Systemtabellen“.
Wenn in den Grant-Tabellen Berechtigungsdatensätze vorhanden
sind, die Datenbank- oder Tabellennamen mit gemischter
Groß-/Kleinschreibung enthalten, und die Systemvariable
lower_case_table_names
auf einen
Nicht-Null-Wert gesetzt ist, dann können diese Berechtigungen
nicht mit REVOKE
widerrufen werden. Es ist
dann erforderlich, die Grant-Tabellen direkt zu manipulieren.
(GRANT
erstellt solche Datensätze zwar
nicht, wenn lower_case_table_names
eingestellt ist, aber unter Umständen wurden derartige
Datensätze bereits vor Einstellen der Variablen erstellt.)
Berechtigungen können auf unterschiedlichen Ebenen gewährt werden:
Globale Ebene
Globale Berechtigungen gelten für alle Datenbanken auf
einem gegebenen Server. Sie werden in der Tabelle
mysql.user
gespeichert. GRANT
ALL ON *.*
und REVOKE ALL ON
*.*
gewähren bzw. widerrufen nur globale
Berechtigungen.
Datenbankebene
Datenbankberechtigungen gelten für alle Objekte in einer
gegebenen Datenbank. Sie werden in den Tabellen
mysql.db
und
mysql.host
gespeichert. GRANT
ALL ON
und
db_name
.*REVOKE ALL ON
gewähren
bzw. widerrufen nur Datenbankberechtigungen.
db_name
.*
Tabellenebene
Tabellenberechtigungen gelten für alle Spalten in einer
gegebenen Tabelle. Sie werden in der Tabelle
mysql.tables_priv
gespeichert.
GRANT ALL ON
und
db_name.tbl_name
REVOKE ALL ON
gewähren bzw. widerrufen nur Tabellenberechtigungen.
db_name.tbl_name
Spaltenebene
Spaltenberechtigungen gelten für einzelne Spalten in
einer gegebenen Tabelle. Sie werden in der Tabelle
mysql.columns_priv
gespeichert. Wenn
Sie REVOKE
verwenden, müssen Sie
dieselben Spalten angeben, denen die Berechtigungen zuvor
gewährt wurden.
Routinenebene
Die Berechtigungen CREATE ROUTINE
,
ALTER ROUTINE
,
EXECUTE
und GRANT
gelten für gespeicherte Routinen (Funktionen und
Prozeduren). Sie können auf der globalen und der
Datenbankebene gewährt werden. Ferner lassen sich diese
Berechtigungen mit Ausnahme von CREATE
ROUTINE
auf Routinenebene für einzelne Routinen
gewähren und werden in der Tabelle
mysql.procs_priv
gespeichert.
Die Klausel object_type
sollte als
TABLE
, FUNCTION
bzw. als
PROCEDURE
angegeben werden, wenn das
nachfolgende Objekt eine Tabelle, eine gespeicherte Funktion
oder eine gespeicherte Prozedur ist.
Für die Anweisungen GRANT
und
REVOKE
kann
priv_type
wie folgt angegeben
werden:
Berechtigung | Bedeutung |
ALL [PRIVILEGES] | Setzt alle einfachen Berechtigungen außer GRANT
OPTION . |
ALTER | Erlaubt die Verwendung von ALTER TABLE . |
ALTER ROUTINE | Erlaubt die Änderung oder Löschung gespeicherter Routinen. |
CREATE | Erlaubt die Verwendung von CREATE TABLE . |
CREATE ROUTINE | Erlaubt die Erstellung gespeicherter Routinen. |
CREATE TEMPORARY TABLES | Erlaubt die Verwendung von CREATE TEMPORARY TABLE . |
CREATE USER | Erlaubt die Verwendung von CREATE USER , DROP
USER , RENAME USER und
REVOKE ALL PRIVILEGES . |
CREATE VIEW | Erlaubt die Verwendung von CREATE VIEW . |
DELETE | Erlaubt die Verwendung von DELETE . |
DROP | Erlaubt die Verwendung von DROP TABLE . |
EVENT | Erlaubt die Erstellung von Ereignissen für den Ereignisplaner. |
EXECUTE | Erlaubt dem Benutzer die Ausführung gespeicherter Routinen. |
FILE | Erlaubt die Verwendung von SELECT ... INTO OUTFILE
und LOAD DATA INFILE . |
INDEX | Erlaubt die Verwendung von CREATE INDEX und
DROP INDEX . |
INSERT | Erlaubt die Verwendung von INSERT . |
LOCK TABLES | Erlaubt die Verwendung von LOCK TABLES für Tabellen,
für die Sie die Berechtigung
SELECT haben. |
PROCESS | Erlaubt die Verwendung von SHOW FULL PROCESSLIST . |
REFERENCES | Nicht implementiert. |
RELOAD | Erlaubt die Verwendung von FLUSH . |
REPLICATION CLIENT | Erlaubt dem Benutzer, die Positionen von Slave- oder Master-Servern zu erfragen. |
REPLICATION SLAVE | Für Replikationsslaves erforderlich (zum Lesen von Binärlogeinträgen auf dem Master). |
SELECT | Erlaubt die Verwendung von SELECT . |
SHOW DATABASES | SHOW DATABASES zeigt alle Datenbanken. |
SHOW VIEW | Erlaubt die Verwendung von SHOW CREATE VIEW . |
SHUTDOWN | Erlaubt die Verwendung von mysqladmin shutdown. |
SUPER | Erlaubt die Verwendung der Anweisungen CHANGE MASTER ,
KILL , PURGE MASTER
LOGS und SET GLOBAL und
des Befehls mysqladmin debug.
Erlaubt ferner die (einmalige) Verbindungsherstellung
auch in dem Fall, dass der Wert für
max_connections erreicht wurde. |
TRIGGER | Erlaubt dem Benutzer das Erstellen und Löschen von Triggern. |
UPDATE | Erlaubt die Verwendung von UPDATE . |
USAGE | Synonym für „keine Berechtigungen“ |
GRANT OPTION | Erlaubt die Gewährung von Berechtigungen. |
Die Berechtigungen EVENT
und
TRIGGER
wurden in MySQL 5.1.6 hinzugefügt.
Ein Trigger ist mit einer Tabelle verknüpft, d. h., um einen
Trigger zu erstellen oder zu löschen, benötigen Sie die
Berechtigung TRIGGER
für die Tabelle,
nicht für den Trigger. (Vor MySQL 5.1.6 war für das
Erstellen und Löschen von Triggern die Berechtigung
SUPER
erforderlich.)
Die Berechtigung REFERENCES
wird derzeit
nicht benutzt.
USAGE
kann angegeben werden, wenn Sie einen
Benutzer ohne Berechtigungen erstellen wollen.
Verwenden Sie SHOW GRANTS
, um zu bestimmen,
welche Berechtigungen ein Konto hat. Siehe auch
Abschnitt 13.5.4.11, „SHOW GRANTS
“.
Sie können globale Berechtigungen mit der Syntax ON
*.*
oder Berechtigungen auf Datenbankebene mit der
Syntax ON
konfigurieren.
Wenn Sie db_name
.*ON *
angeben und eine
Standarddatenbank festgelegt haben, werden die Berechtigungen
in dieser Datenbank gewährt.
(Warnung: Wenn Sie
ON *
angeben und keine
Standarddatenbank ausgewählt haben, werden die Berechtigungen
global gewährt.)
Die Berechtigungen FILE
,
PROCESS
, RELOAD
,
REPLICATION CLIENT
, REPLICATION
SLAVE
, SHOW DATABASES
,
SHUTDOWN
und SUPER
sind
administrative Berechtigungen, die nur global gewährt werden
können (hierzu wird die Syntax ON *.*
verwendet).
Andere Berechtigungen können wahlweise global oder auf individuellen Ebenen festgelegt werden.
Die priv_type
-Werte, die Sie für
eine Tabelle angeben können, sind SELECT
,
INSERT
, UPDATE
,
DELETE
, CREATE
,
DROP
, GRANT OPTION
,
INDEX
, ALTER
,
CREATE VIEW
, SHOW VIEW
und TRIGGER
.
Die priv_type
-Werte, die Sie (bei
Verwendung einer
column_list
-Klausel) für eine
Spalte angeben können, sind SELECT
,
INSERT
und UPDATE
.
Die priv_type
-Werte, die Sie auf
der Routinenebene angeben können, sind ALTER
ROUTINE
, EXECUTE
und
GRANT OPTION
. CREATE
ROUTINE
ist keine Berechtigung auf Routinenebene,
weil Sie diese Berechtigung bereits zur Erstellung einer
Routine benötigen.
Auf der globalen, der Datenbank-, der Tabellen- und der
Routinenebene weist GRANT ALL
nur
diejenigen Berechtigungen zu, die auf der gewährten Ebene
vorhanden sind. So ist beispielsweise GRANT ALL ON
eine Anweisung
auf Datenbankebene, d. h., es lassen sich hiermit keine nur
auf globaler Ebene vorhandenen Berechtigungen (wie z. B.
db_name
.*FILE
) gewähren.
MySQL gestattet die Konfiguration von Berechtigungen auch für
Datenbankobjekte, die nicht existieren. In diesen Fällen muss
zu den zu gewährenden Berechtigungen auch die Berechtigung
CREATE
gehören. Dies ist bewusst
so implementiert und soll es dem
Datenbankadministrator gestatten, Benutzerkonten und
Berechtigungen für Datenbankobjekte vorzubereiten, die erst
später erstellt werden.
Wichtig: Wenn Sie eine Tabelle oder Datenbank löschen, widerruft MySQL Berechtigungen nicht automatisch. Wenn Sie allerdings eine Routine löschen, werden alle Berechtigungen auf Routinenebene widerrufen, die für diese Routine gewährt wurden.
Hinweis: Die Jokerzeichen
‘_
’ und
‘%
’ sind bei der Angabe von
Datenbanknamen in GRANT
-Anweisungen, die
Berechtigungen auf der globalen und der Datenbankebene
gewähren, zulässig. Das bedeutet beispielsweise, dass Sie,
wenn Sie das Zeichen ‘_
’ als
Bestandteil eines Datenbanknamens verwenden wollen, dieses
Zeichen als ‘\_
’ in der
GRANT
-Anweisung angeben müssen, damit der
Benutzer nicht auf weitere Datenbanken zugreifen kann, die dem
entstandenen Muster entsprechen (z. B. GRANT ... ON
`foo\_bar`.* TO ...
).
Um das Gewähren von Rechten an Benutzer über beliebige Hosts
zu gestatten, unterstützt MySQL die Angabe des
user
-Werts in der Form
.
Wenn ein user_name
@host_name
user_name
- oder
host_name
-Wert als vorzeichenloser
Bezeichner zulässig ist, müssen Sie ihn nicht in
Anführungszeichen setzen. Allerdings sind Anführungszeichen
erforderlich, um einen
user_name
-String mit Sonderzeichen
(z. B. ‘-
’) oder einen
host_name
-String mit Sonder- oder
Jokerzeichen (wie ‘%
’)
anzugeben. Ein Beispiel hierfür wäre
'test-user'@'test-hostname'
. Setzen Sie
Benutzer- und Hostnamen separat in Anführungszeichen.
Sie können Jokerzeichen im Hostnamen verwenden. So bezeichnet
etwa
jeden user_name
@'%.loc.gov'user_name
auf einem
beliebigen Host in der Domäne loc.gov
, und
bezeichnet user_name
@'144.155.166.%'user_name
auf einem
beliebigen Host im Klasse-C-Subnetz
144.155.166
.
Die einfache Form user_name
ist ein
Synonym für
.
user_name
@'%'
MySQL unterstützt keine Jokerzeichen in
Benutzernamen. Anonyme Benutzer werden durch
Einfügen von Einträgen mit User=''
in die
Tabelle mysql.user
oder durch Erstellen
eines Benutzers mit einem leeren Namen mit der
GRANT
-Anweisung definiert:
GRANT ALL ON test.* TO ''@'localhost' ...
Wenn Sie Werte in Anführungszeichen angeben, setzen Sie
Datenbank-, Tabellen-, Spalten- und Routinenamen als
Bezeichner in Backticks (‘`
’).
Host- und Benutzernamen sowie Passwörter werden als Strings
in einfache Anführungszeichen
(‘'
’) gesetzt.
Warnung: Wenn Sie anonymen
Benutzern eine Verbindung zum MySQL Server gestatten wollen,
sollten Sie auch allen lokalen Benutzern als
Berechtigungen gewähren. Andernfalls wird das anonyme
Benutzerkonto für user_name
@localhostlocalhost
in der Tabelle
mysql.user
verwendet, wenn benannte
Benutzer versuchen, sich über das lokale System am MySQL
Server anzumelden (die Tabelle wird bei der Installation von
MySQL erstellt). Detaillierte Informationen finden Sie in
Abschnitt 5.8.5, „Zugriffskontrolle, Phase 1: Verbindungsüberprüfung“.
Sie können feststellen, ob dies für Sie zutrifft, indem Sie die folgende Abfrage ausführen, die alle ggf. vorhandenen anonymen Benutzer auflistet:
SELECT Host, User FROM mysql.user WHERE User='';
Wenn Sie das lokale anonyme Benutzerkonto löschen wollen, um das beschriebene Problem zu umgehen, dann verwenden Sie folgende Anweisungen:
DELETE FROM mysql.user WHERE Host='localhost' AND User=''; FLUSH PRIVILEGES;
GRANT
unterstützt Hostnamen mit einer
Länge von bis zu 60 Zeichen. Die Namen von Datenbanken,
Tabellen, Spalten und Routinen dürfen bis zu 64 Zeichen lang
sein. Benutzernamen können bis zu 16 Zeichen umfassen.
Hinweis: Die
zulässige Länge für Benutzernamen kann nicht durch
Änderungen an der Tabelle mysql.user
modifiziert werden. Wenn Sie dies dennoch versuchen, kann dies
zu unvorhersehbaren Folgen führen, die schlimmstenfalls sogar
ein Anmelden von Benutzern am MySQL Server verhindern
können. Sie sollten die Tabellen in der
mysql
-Datenbank grundsätzlich nicht auf
eine andere als die von MySQL AB vorgeschriebene, in
Abschnitt 5.6, „mysql_fix_privilege_tables — Upgrade von MySQL-Systemtabellen“, geschilderte
Weise ändern.
Die Berechtigungen für eine Tabelle, eine Spalte oder eine
Routine werden kumulativ über ein logisches
OR
der Berechtigungen auf jeder der
einzelnen Ebenen gebildet. Wenn die Tabelle
mysql.user
beispielsweise angibt, dass ein
Benutzer die globale Berechtigung SELECT
hat, kann ihm diese Berechtigung nicht auf der Datenbank-, der
Tabellen- oder der Spaltenebene verweigert werden.
Die Berechtigungen für eine Spalte lassen sich wie folgt berechnen:
global privileges OR (database privileges AND host privileges) OR table privileges OR column privileges OR routine privileges
In den meisten Fällen gewähren Sie einem Benutzer nur auf einer dieser Berechtigungsebenen Rechte – das Leben ist also normalerweise nicht so kompliziert. Ausführlich beschrieben wird die Überprüfung von Berechtigungen in Abschnitt 5.8, „Allgemeine Sicherheitsaspekte und das MySQL-Zugriffsberechtigungssystem“.
Wenn Sie Berechtigungen für eine Kombination aus Benutzer-
und Hostnamen gewähren, die nicht in der Tabelle
mysql.user
vorhanden ist, wird ein Eintrag
hinzugefügt und verbleibt dort, bis er mit einer
DELETE
-Anweisung gelöscht wird. Anders
gesagt, GRANT
kann Einträge in der Tabelle
user
erstellen; diese lassen sich aber
nicht mit REVOKE
entfernen, sondern müssen
explizit mit DROP USER
oder
DELETE
gelöscht werden.
Warnung: Wenn Sie einen neuen
Benutzer ohne IDENTIFIED BY
-Klausel
erstellen, hat der Benutzer kein Passwort. Dies ist sehr
unsicher. Sie können jedoch den SQL-Modus
NO_AUTO_CREATE_USER
aktivieren: Hierbei
wird verhindert, dass GRANT
Benutzer
automatisch erstellt, wenn diesem nicht mit der
IDENTIFIED BY
-Klausel ein nichtleeres
Passwort zugewiesen wird.
Wenn ein neuer Benutzer erstellt wird oder Sie globale
Gewährungsberechtigungen haben, dann wird das Passwort des
Benutzers auf das in der IDENTIFIED
BY
-Klausel gewählte Passwort gesetzt (sofern
vorhanden). Hat der Benutzer bereits ein Passwort, so wird
dieses durch das neue Passwort ersetzt.
Passwörter können auch mit der Anweisung SET
PASSWORD
eingestellt werden. Siehe auch
Abschnitt 13.5.1.6, „SET PASSWORD
“.
In der IDENTIFIED BY
-Klausel sollte das
Passwort als literaler Passwortwert übergeben werden. Es ist
– anders als bei der SET
PASSWORD
-Anweisung – nicht erforderlich, die
Funktion PASSWORD()
zu verwenden. Zum
Beispiel:
GRANT ... IDENTIFIED BY 'mypass';
Wenn Sie das Passwort nicht unverschlüsselt senden wollen und
den Hash-Wert kennen, den PASSWORD()
für
das Passwort zurückgeben würde, dann können Sie diesen
Hash-Wert nach dem Schlüsselwort PASSWORD
angeben:
GRANT ... IDENTIFIED BY PASSWORD '*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4';
In einem C-Programm können Sie den Hash-Wert mit der
C-API-Funktion make_scrambled_password()
ermitteln.
Wenn Sie Berechtigungen für eine Datenbank gewähren, wird
bei Bedarf ein Eintrag in der Tabelle
mysql.db
erstellt. Wenn alle Berechtigungen
für die Datenbank mit REVOKE
entfernt
werden, wird dieser Eintrag gelöscht.
Die Berechtigung SHOW DATABASES
ermöglicht
dem Konto die Anzeige von Datenbanknamen durch Absetzen einer
SHOW DATABASE
-Anweisung. Konten, die diese
Berechtigung nicht haben, sehen nur solche Datenbanken, für
die sie Berechtigungen haben; wurde der Server mit der Option
--skip-show-database
gestartet, dann kann die
Anweisung überhaupt nicht verwendet werden.
Wenn ein Benutzer keine Berechtigungen für eine Tabelle hat,
wird, wenn er (z. B. mit SHOW TABLES
) eine
Liste der Tabellen anfordert, der Name der betreffenden
Tabelle nicht angezeigt.
Die WITH GRANT OPTION
-Klausel gibt dem
Benutzer die Möglichkeit, anderen Benutzern beliebige
Berechtigungen zu gewähren, die der Benutzer selbst auf einer
bestimmten Berechtigungsebene hat. Sie sollten bei der Vergabe
der Berechtigung GRANT OPTION
mit Umsicht
vorgehen, weil zwei Benutzer mit unterschiedlichen
Berechtigungen sich diese unter Umständen gegenseitig
gewähren können!
Sie können einem anderen Benutzer keine Berechtigung
gewähren, die Sie selbst nicht haben – mit GRANT
OPTION
können Sie nur solche Berechtigungen
vergeben, über die Sie selbst auch verfügen.
Beachten Sie, dass, wenn Sie einem Benutzer die Berechtigung
GRANT OPTION
für eine bestimmte
Berechtigungsebene gewähren, dieser Benutzer alle
Berechtigungen, die er für diese Ebene hat (oder in Zukunft
erhält), beliebig anderen Benutzern zuweisen kann.
Angenommen, Sie gewähren einem Benutzer die Berechtigung
INSERT
für eine Datenbank. Wenn Sie
nachfolgend die Berechtigung SELECT
für
die Datenbank gewähren und WITH GRANT
OPTION
angeben, dann kann dieser Benutzer anderen
Benutzern nicht nur die Berechtigung SELECT
gewähren, sondern auch die Berechtigung
INSERT
. Wenn Sie dann dem Benutzer die
Berechtigung UPDATE
für die Datenbank
gewähren, kann der Benutzer die Berechtigungen
INSERT
, SELECT
und
UPDATE
gewähren.
Einem nichtadministrativen Benutzer sollten Sie die
Berechtigung ALTER
weder global noch für
die Datenbank mysql
gewähren. Andernfalls
kann der Benutzer das Berechtigungssystem unterlaufen, indem
er Tabellen umbenennt!
Die Optionen MAX_QUERIES_PER_HOUR
,
count
MAX_UPDATES_PER_HOUR
und
count
MAX_CONNECTIONS_PER_HOUR
begrenzen die
Anzahl der Abfrage-, Update- und Anmeldevorgänge, die ein
Benutzer im Verlauf einer Stunde ausführen kann. Wenn
count
count
0
ist
(Standardeinstellung), dann heißt das, dass für den Benutzer
keine Beschränkung gilt.
Die Option MAX_USER_CONNECTIONS
schränkt die
maximale Anzahl gleichzeitiger Verbindungen ein, die das Konto
herstellen kann. Wenn count
count
0
ist (Standardeinstellung), dann bestimmt
die Systemvariable max_user_connections
die
Anzahl gleichzeitiger Verbindungen für das Konto.
Hinweis: Um für einen vorhandenen Benutzer eine solche Option
zur Ressourcenbeschränkung anzugeben, ohne vorhandene
Berechtigungen einzuschränken, verwenden Sie GRANT
USAGE ON *.* ... WITH MAX_...
.
Siehe auch Abschnitt 5.9.4, „Begrenzen von Benutzer-Ressourcen“.
MySQL kann zusätzlich zur normalen, auf Benutzernamen und
Passwörtern basierenden Authentifizierung Attribute von
X509-Zertifikaten überprüfen. Um SSL-spezifische Optionen
für ein MySQL-Konto anzugeben, verwenden Sie die
REQUIRE
-Klausel der
GRANT
-Anweisung. (Hintergrundinformationen
zur Verwendung von SSL mit MySQL finden Sie in
Abschnitt 5.9.7, „Verwendung sicherer Verbindungen“.)
Es gibt mehrere verschiedene Gründe zur Beschränkung der Verbindungstypen für ein gegebenes Konto:
Wenn für das Konto keine SSL- oder X509-Anforderungen vorhanden sind, sind unverschlüsselte Verbindungen zulässig, sofern Benutzername und Passwort gültig sind. Allerdings können nach Maßgabe des Clients auch verschlüsselte Verbindungen benutzt werden, sofern der Client über die entsprechenden Zertifikats- und Schlüsseldateien verfügt.
Die Option REQUIRE SSL
weist den Server
an, nur SSL-verschlüsselte Verbindungen für das Konto
zuzulassen. Beachten Sie, dass diese Option weggelassen
werden kann, wenn Zugriffssteuerungs-Datensätze vorhanden
sind, die Nicht-SSL-Verbindungen zulassen.
GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost' IDENTIFIED BY 'goodsecret' REQUIRE SSL;
REQUIRE X509
bedeutet, dass der Client
ein gültiges Zertifikat vorweisen muss, dass aber das
Zertifikat selbst, der Aussteller und der Zweck keine
Rolle spielen. Erforderlich ist einzig und allein, dass
die Signatur bei einem Zertifikat geprüft werden können
muss.
GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost' IDENTIFIED BY 'goodsecret' REQUIRE X509;
REQUIRE ISSUER
'
schränkt
Verbindungsversuche dahingehend ein, dass der Client ein
gültiges X509-Zertifikat vorweisen muss, welches von der
Zertifizierungsstelle
issuer
''
ausgestellt wurde. Wenn der Client ein Zertifikat
vorweist, das zwar gültig ist, aber von einem anderen
Anbieter stammt, dann weist der Server die Verbindung ab.
Die Verwendung von X509-Zertifikaten impliziert immer auch
eine Verschlüsselung, d. h., die Option
issuer
'SSL
wird in diesem Fall nicht
benötigt.
GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost' IDENTIFIED BY 'goodsecret' REQUIRE ISSUER '/C=FI/ST=Some-State/L=Helsinki/ O=MySQL Finland AB/CN=Tonu Samuel/Email=tonu@example.com';
Beachten Sie, dass die
'
-Werte
als einzelner String eingegeben werden sollten.
issuer
'
REQUIRE SUBJECT
'
schränkt
Verbindungsversuche dahingehend ein, dass der Client ein
gültiges X509-Zertifikat vorweisen muss, bei dem als
Zweck subject
'subject
angegeben ist.
Wenn der Client ein Zertifikat vorweist, das zwar gültig
ist, aber einen anderen Zweck angibt, dann weist der
Server die Verbindung ab.
GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost' IDENTIFIED BY 'goodsecret' REQUIRE SUBJECT '/C=EE/ST=Some-State/L=Tallinn/ O=MySQL demo client certificate/ CN=Tonu Samuel/Email=tonu@example.com';
Beachten Sie, dass die
'
-Werte
als einzelner String eingegeben werden sollten.
subject
'
REQUIRE CIPHER
'
ist
erforderlich, um sicherzustellen, dass Chiffren und
Schlüssellängen ausreichender Stärke verwendet werden.
SSL selbst kann schwach sein, wenn alte Algorithmen kurze
Schlüssel zur Verschlüsselung einsetzen. Mit dieser
Option können Sie die Verwendung einer bestimmten
Chiffriermethode vorsehen, damit die Verbindung zulässig
ist.
cipher
'
GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost' IDENTIFIED BY 'goodsecret' REQUIRE CIPHER 'EDH-RSA-DES-CBC3-SHA';
Die Optionen SUBJECT
,
ISSUER
und CIPHER
können in der REQUIRE
-Klausel wie folgt
kombiniert werden:
GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost' IDENTIFIED BY 'goodsecret' REQUIRE SUBJECT '/C=EE/ST=Some-State/L=Tallinn/ O=MySQL demo client certificate/ CN=Tonu Samuel/Email=tonu@example.com' AND ISSUER '/C=FI/ST=Some-State/L=Helsinki/ O=MySQL Finland AB/CN=Tonu Samuel/Email=tonu@example.com' AND CIPHER 'EDH-RSA-DES-CBC3-SHA';
Das Schlüsselwort AND
zwischen den
REQUIRE
-Optionen ist optional.
Die Reihenfolge der Optionen ist unerheblich, allerdings darf keine Option zweimal angegeben werden.
Wenn mysqld startet, werden alle Berechtigungen in den Speicher eingelesen. Detaillierte Informationen finden Sie in Abschnitt 5.8.7, „Wann Berechtigungsänderungen wirksam werden“.
Beachten Sie, dass, wenn Sie Tabellen-, Spalten- oder Routineberechtigungen auch für nur einen einzigen Benutzer verwenden, der Server die Tabellen-, Spalten- und Routineberechtigungen für alle Benutzer prüft. Dies kann MySQL ein wenig verlangsamen. Analog muss der Server, wenn Sie die Anzahl von Abfragen, Updates oder Verbindungen für Benutzer beschränken wollen, auch diese Werte überwachen.
Die wesentlichsten Unterschiede zwischen dem SQL-Standard und
den MySQL-Versionen von GRANT
sind die
folgenden:
In MySQL werden Berechtigungen mit einer Kombination aus Host- und Benutzernamen (und nicht nur mit einem Benutzernamen) verknüpft.
Der SQL-Standard bietet keine Berechtigungen auf globaler oder Datenbankebene und unterstützt auch nicht alle von MySQL unterstützten Berechtigungstypen.
MySQL unterstützt die Berechtigungen
TRIGGER
und UNDER
des SQL-Standards nicht.
Berechtigungen nach SQL-Standard sind hierarchisch
strukturiert. Wenn Sie einen Benutzer entfernen, werden
alle Berechtigungen widerrufen, die dieser Benutzer hatte.
Dies gilt auch für MySQL, wenn Sie DROP
USER
verwenden. Siehe auch
Abschnitt 13.5.1.2, „DROP USER
“.
Wenn Sie in Standard-SQL eine Tabelle löschen, werden
alle Berechtigungen für die Tabelle widerrufen. Wenn Sie
in Standard-SQL eine Berechtigung widerrufen, werden alle
Berechtigungen, die basierend auf dieser Berechtigung
gewährt wurden, ebenfalls widerrufen. In MySQL können
Berechtigungen nur mit expliziten
REVOKE
-Anweisungen oder durch
Manipulation der in den MySQL-Grant-Tabellen gespeicherten
Werte gelöscht werden.
In MySQL können INSERT
-Berechtigungen
auch für nur einige der Spalten in einer Tabelle gewährt
werden. In diesem Fall können Sie
INSERT
-Anweisungen für die Tabelle
trotzdem ausführen, sofern Sie diejenigen Spalten
weglassen, für die Sie keine
INSERT
-Berechtigung haben. Die
übergangenen Spalten können auf ihre impliziten
Vorgabewerte gesetzt werden, sofern der strikte SQL-Modus
nicht aktiviert ist. Im strikten Modus wird die Anweisung
abgewiesen, wenn eine der übergangenen Spalten keinen
Vorgabewert hat. (Der SQL-Standard sieht vor, dass Sie die
INSERT
-Berechtigung für alle Spalten
benötigen.) Abschnitt 5.2.5, „Der SQL-Modus des Servers“, beschreibt
den strikten Modus. Abschnitt 11.1.4, „Vorgabewerte von Datentypen“,
erläutert implizite Vorgabewerte.
RENAME USERold_user
TOnew_user
[,old_user
TOnew_user
] ...
Die RENAME USER
-Anweisung benennt
MySQL-Konten um. Um sie zu verwenden, benötigen Sie die
globale Berechtigung CREATE USER
oder die
Berechtigung UPDATE
für die Datenbank
mysql
. Ein Fehler tritt auf, wenn ein Konto
mit dem alten oder neuen Namen bereits existiert. Jedes Konto
wird im selben Format wie bei der
GRANT
-Anweisung benannt (z. B.
'jeffrey'@'localhost'
). Die Benutzer- und
Hostbestandteile des Kontonamens entsprechen den Werten der
Spalten User
und Host
des kontenspezifischen Datensatzes in der Tabelle
user
.
REVOKEpriv_type
[(column_list
)] [,priv_type
[(column_list
)]] ... ON [object_type
] {tbl_name
| * | *.* |db_name
.*} FROMuser
[,user
] ... REVOKE ALL PRIVILEGES, GRANT OPTION FROMuser
[,user
] ...
Die REVOKE
-Anweisung erlaubt
Systemadministratoren das Widerrufen von Berechtigungen für
MySQL-Konten. Um REVOKE
verwenden zu
können, benötigen Sie die Berechtigung GRANT
OPTION
sowie alle Berechtigungen, die Sie
widerrufen.
Informationen zu den Ebenen, auf denen Berechtigungen
vorhanden sind, den zulässigen Werten für
priv_type
und der Syntax zur Angabe
von Benutzern und Passwörtern finden Sie in
Abschnitt 13.5.1.3, „GRANT
und REVOKE
“.
Wenn in den Grant-Tabellen Berechtigungsdatensätze vorhanden
sind, die Datenbank- oder Tabellennamen mit gemischter
Groß-/Kleinschreibung enthalten, und die Systemvariable
lower_case_table_names
auf einen
Nicht-Null-Wert gesetzt ist, dann können diese Berechtigungen
nicht mit REVOKE
widerrufen werden. Es ist
dann erforderlich, die Grant-Tabellen direkt zu manipulieren.
(GRANT
erstellt solche Datensätze zwar
nicht, wenn lower_case_table_names
eingestellt ist, aber unter Umständen wurden derartige
Datensätze bereits vor Einstellen der Variablen erstellt.)
Um alle Berechtigungen zu widerrufen, verwenden Sie die folgende Syntax. Hiermit löschen Sie alle globalen Berechtigungen sowie alle Berechtigungen auf Datenbank-, Tabellen- und Spaltenebene für den oder die aufgeführten Benutzer:
REVOKE ALL PRIVILEGES, GRANT OPTION FROMuser
[,user
] ...
Um diese REVOKE
-Syntax zu verwenden,
benötigen Sie die globale Berechtigung CREATE
USER
oder die Berechtigung UPDATE
für die Datenbank mysql
.
SET PASSWORD = PASSWORD('some password
') SET PASSWORD FORuser
= PASSWORD('some password
')
Die Anweisung SET PASSWORD
weist einem
vorhandenen MySQL-Benutzerkonto ein Passwort zu.
Die erste Syntax stellt das Passwort für den aktuellen Benutzer ein. Ein Client, der über ein nichtanonymes Konto eine Verbindung mit dem Server hergestellt hat, kann das Passwort für dieses Konto ändern.
Die zweite Syntax stellt das Passwort für ein bestimmtes
Konto auf dem aktuellen Serverhost ein. Nur Clients mit der
Berechtigung UPDATE
für die Datenbank
mysql
können dies tun. Der Wert
user
sollte im Format
angegeben werden, wobei user_name
@host_name
user_name
und host_name
exakt so aufgeführt
werden müssen, wie sie in den Spalten User
bzw. Host
des entsprechenden Eintrags in
der Tabelle mysql.user
notiert sind. Wenn
Sie beispielsweise einen Eintrag mit den Werten
'bob'
und '%.loc.gov'
in
den Spalten User
bzw.
Host
haben, dann würden Sie die Anweisung
wie folgt schreiben:
SET PASSWORD FOR 'bob'@'%.loc.gov' = PASSWORD('newpass
');
Dies entspricht den folgenden Anweisungen:
UPDATE mysql.user SET Password=PASSWORD('newpass
')
WHERE User='bob' AND Host='%.loc.gov';
FLUSH PRIVILEGES;
Hinweis: Wenn Sie mit einem
Clientprogramm vor Version 4.1 eine Verbindung zu einem Server
unter MySQL 4.1 oder höher herstellen, verwenden Sie die
obigen Anweisungen SET PASSWORD
oder
UPDATE
erst, wenn Sie
Abschnitt 5.8.9, „Kennwort-Hashing ab MySQL 4.1“, gelesen haben. Das
Passwortformat wurde in MySQL 4.1 geändert, und unter
bestimmten Bedingungen ist es möglich, dass Sie, wenn Sie Ihr
Passwort ändern, nachfolgend keine Serververbindung mehr
herstellen können.
Sie können anzeigen, unter welchem Konto der Server Sie
authentifiziert hat, indem Sie SELECT
CURRENT_USER()
ausführen.
ANALYZE [LOCAL | NO_WRITE_TO_BINLOG] TABLEtbl_name
[,tbl_name
] ...
ANALYZE TABLE
analysiert und speichert die
Schlüsselverteilung für eine Tabelle. Während der Analyse
ist die Tabelle mit einer Lesesperre versehen. Diese Anweisung
funktioniert nur bei MyISAM
-,
BDB
- und
InnoDB
-Tabellen. Bei
MyISAM
-Tabellen ist sie äquivalent zur
Verwendung von myisamchk -a.
MySQL verwendet die gespeicherte Schlüsselverteilung, um die Reihenfolge zu ermitteln, in der die Tabellen verknüpft werden sollen, wenn Sie einen Join mit etwas anderem als einer Konstante durchführen.
ANALYZE TABLE
gibt eine Ergebnismenge mit
den folgenden Spalten zurück:
Spalte | Wert |
Table | der Tabellenname |
Op | ist immer analyze |
Msg_type | status , error ,
info oder
warning |
Msg_text | die Nachricht |
Sie können die gespeicherte Schlüsselverteilung mit der
SHOW INDEX
-Anweisung vergleichen. Siehe
auch Abschnitt 13.5.4.12, „SHOW INDEX
“.
Wenn die Tabelle seit der letzten ANALYZE
TABLE
-Anweisung nicht geändert wurde, wird die
Tabelle nicht erneut analysiert.
ANALYZE TABLE
-Anweisungen werden in das
Binärlog geschrieben, sofern das optionale Schlüsselwort
NO_WRITE_TO_BINLOG
(oder sein Alias
LOCAL
) nicht verwendet wird. Dies wird
gemacht, damit ANALYZE TABLE
-Anweisungen,
die auf einem MySQL Server verwendet werden, der als
Replikationsmaster agiert, standardmäßig auf den
Replikationsslave repliziert werden.
BACKUP TABLEtbl_name
[,tbl_name
] ... TO '/path/to/backup/directory
'
Hinweis: Diese Anweisung ist veraltet. Wir arbeiten derzeit an einem besseren Ersatz, der auch die Online-Sicherung unterstützt. In der Zwischenzeit kann stattdessen das Skript mysqlhotcopy verwendet werden.
BACKUP TABLE
kopiert die minimale Anzahl an
Tabellendateien, die zur Wiederherstellung der Tabelle
benötigt werden, in das Sicherungsverzeichnis, nachdem ggf.
gepufferte Änderungen auf Festplatte geschrieben wurden. Die
Anweisung funktioniert nur bei
MyISAM
-Tabellen. Sie kopiert die
Definitionsdatei (.frm
) und die
Datendatei (.MYD
). Die
.MYI
-Indexdatei kann aus diesen beiden
Dateien neu erstellt werden. Das Verzeichnis sollte als
vollständiger Pfadname angegeben werden. Um die Tabelle
wiederherzustellen, verwenden Sie RESTORE
TABLE
.
Während des Backups wird für jede Tabelle für den Verlauf
des Sicherungsvorgangs eine Lesesperre gehalten (d. h. immer
für eine Tabelle gleichzeitig). Wenn Sie mehrere Tabellen als
Momentaufnahme sichern wollen (und dabei vermeiden wollen,
dass diese während der Sicherung geändert werden), setzen
Sie zunächst eine LOCK TABLES
-Anweisung
ab, um eine Lesesperre für alle betreffenden Tabellen zu
erwirken.
BACKUP TABLE
gibt eine Ergebnismenge mit
den folgenden Spalten zurück:
Spalte | Wert |
Table | der Tabellenname |
Op | ist immer backup |
Msg_type | status , error ,
info oder
warning |
Msg_text | die Nachricht |
CHECK TABLEtbl_name
[,tbl_name
] ... [option
] ...option
= {QUICK | FAST | MEDIUM | EXTENDED | CHANGED}
CHECK TABLE
prüft eine oder mehrere
Tabellen auf Fehler. CHECK TABLE
funktioniert bei MyISAM
- und
InnoDB
-Tabellen. Bei
MyISAM
-Tabellen werden auch die
Schlüsselstatistiken aktualisiert.
CHECK TABLE
kann auch Views auf Probleme
prüfen, z. B. in der View-Definition referenzierte Tabellen,
die nicht mehr vorhanden sind.
CHECK TABLE
gibt eine Ergebnismenge mit den
folgenden Spalten zurück:
Spalte | Wert |
Table | der Tabellenname |
Op | ist immer check |
Msg_type | status , error ,
info oder
warning |
Msg_text | die Nachricht |
Beachten Sie, dass die Anweisung unter Umständen viele
Datensätze für die überprüfte Tabelle ausgeben kann. Der
letzte Datensatz hat den Msg_type
-Wert
status
; Msg_text
sollte
normalerweise den Wert OK
haben. Wenn Sie
nicht den Wert OK
oder aber die Meldung
Table is already up to date
erhalten,
sollten Sie eine Reparatur der Tabelle durchführen. Siehe
auch Abschnitt 5.10.4, „Benutzung von myisamchk
für Tabellenwartung und Absturzreparatur“. Table is
already up to date
bedeutet, dass die
Speicher-Engine für die Tabelle angegeben hat, dass es keine
Notwendigkeit zur Überprüfung gibt.
Die verschiedenen Prüfoptionen, die angegeben werden können,
sind in der folgenden Tabelle aufgeführt. Die Optionen dienen
nur der Überprüfung von MyISAM
-Tabellen;
bei InnoDB
-Tabellen und Views werden sie
ignoriert.
Typ | Bedeutung |
QUICK | überprüft Datensätze nicht auf falsche Verknüpfungen. |
FAST | Überprüft nur Tabellen, die nicht ordnungsgemäß geschlossen wurden. |
CHANGED | überprüft nur solche Tabellen, die seit der letzten Überprüfung geändert oder aber nicht korrekt geschlossen wurden. |
MEDIUM | prüft Datensätze, um sicherzustellen, dass gelöschte Verknüpfungen gültig sind. Hierbei wird auch eine Schlüsselprüfsumme für die Datensätze berechnet, die dann mit einer berechneten Prüfsumme für die Schlüssel verglichen wird. |
EXTENDED | führt eine vollständige Schlüsselsuche für alle Schlüssel in jedem Datensatz durch. Hierdurch wird sichergestellt, dass die Tabelle hundertprozentig konsistent ist, der Vorgang dauert aber sehr lange. |
Wenn keine der Optionen QUICK
,
MEDIUM
oder EXTENDED
angegeben wird, wird standardmäßig MEDIUM
als Prüftyp für dynamische
MyISAM
-Tabellen verwendet. Dies hat
dieselben Auswirkungen wie die Ausführung von
myisamchk --medium-check
tbl_name
für die
Tabelle. Auch bei statischen
MyISAM
-Tabellen ist
MEDIUM
der Standardtyp, sofern nicht
CHANGED
oder FAST
angegeben wurde. (In diesen Fällen ist
QUICK
der Vorgabewert.) Der Datensatzscan
wird bei CHANGED
und
FAST
übersprungen, weil die Datensätze
sehr selten beschädigt sind.
Sie können Prüfoptionen auch kombinieren. Im folgenden Beispiel etwa erfolgt eine schnelle Prüfung der Tabelle, um zu ermitteln, ob sie korrekt geschlossen wurde:
CHECK TABLE test_table FAST QUICK;
Hinweis: In manchen Fällen
verändert CHECK TABLE
die Tabelle. Dies
geschieht, wenn die Tabelle als „beschädigt“
oder „nicht korrekt geschlossen“ gekennzeichnet
wurde, aber CHECK TABLE
keine Probleme in
der Tabelle findet. In diesem Fall kennzeichnet CHECK
TABLE
die Tabelle als fehlerfrei.
Wenn eine Tabelle beschädigt ist, liegt das Problem wahrscheinlich bei den Indizes und nicht im Datenteil vor. Alle bislang genannten Prüftypen führen eine umfassende Indexprüfung durch und sollten aufgrund dessen die meisten Fehler finden.
Wenn Sie eine Tabelle, bei der Sie davon ausgehen, dass sie in
Ordnung ist, nur sicherheitshalber überprüfen wollen, dann
sollten Sie entweder keine Prüfoption oder die Option
QUICK
angeben. Letzteres sollten Sie tun,
wenn Sie sehr in Eile sind und das sehr geringe Risiko in Kauf
nehmen wollen, dass QUICK
einen Fehler in
der Datendatei nicht findet. (In den meisten Fällen sollte
MySQL bei normaler Verwendung alle ggf. in der Datendatei
vorhandenen Fehler finden. Geschieht dies, so wird die Tabelle
als „beschädigt“ gekennzeichnet und kann erst
wieder verwendet werden, nachdem sie repariert wurde.)
FAST
und CHANGED
sollen
in erster Linie aus Skripten (die etwa mit
cron ausgeführt werden) heraus verwendet
werden, wenn Sie Ihre Tabellen von Zeit zu Zeit überprüfen
wollen. In den meisten Fällen ist FAST
CHANGED
vorzuziehen. (Der einzige Fall, wo
dies nicht zutrifft, liegt vor, wenn Sie annehmen, einen Bug
im MyISAM
-Code gefunden zu haben.)
EXTENDED
sollte erst verwendet werden, wenn
Sie bereits eine normale Überprüfung durchgeführt haben,
aber immer noch merkwürdige Fehler zu einer Tabelle erhalten,
sobald MySQL versucht, einen Datensatz zu aktualisieren oder
einen Datensatz nach seinem Schlüssel zu finden. Die
Wahrscheinlichkeit, dass so etwas nach einer normalen
Überprüfung passiert, ist sehr gering.
Einige Probleme, die von CHECK TABLE
gemeldet werden, können nicht automatisch behoben werden:
Found row where the auto_increment column has the
value 0
.
Das bedeutet, dass Sie einen Datensatz in der Tabelle
haben, bei dem die
AUTO_INCREMENT
-Indexspalte den Wert 0
enthält. (Ein Datensatz, bei dem die
AUTO_INCREMENT
-Spalte 0 ist, kann
tatsächlich erzeugt werden, indem die Spalte mit
UPDATE
explizit auf 0 gesetzt wird.)
Dies ist an sich kein Fehler, kann aber Probleme
verursachen, wenn Sie beschließen, die Tabelle zu
speichern und sie dann wiederherzustellen, oder eine
ALTER TABLE
-Anweisung an die Tabelle
absetzen. In diesem Fall ändert die
AUTO_INCREMENT
-Spalte ihren Wert
entsprechend den Regeln für
AUTO_INCREMENT
-Spalten, was Probleme
wie beispielsweise Schlüsseldubletten verursachen kann.
Um die Warnung zu beseitigen, führen Sie einfach eine
UPDATE
-Anweisung aus, um die Spalte auf
einen anderen Wert als 0 zu setzen.
CHECKSUM TABLEtbl_name
[,tbl_name
] ... [ QUICK | EXTENDED ]
CHECKSUM TABLE
meldet eine
Tabellenprüfsumme.
Bei QUICK
wird – sofern möglich – die
mitlaufende Prüfsumme gemeldet, andernfalls
NULL
. Dies ist sehr schnell. Eine
mitlaufende Prüfsumme wird durch Angabe der Tabellenoption
CHECKSUM = 1
bei Erstellung der Tabelle
aktiviert. Zurzeit wird dies nur bei
MyISAM
-Tabellen unterstützt. Siehe auch
Abschnitt 13.1.5, „CREATE TABLE
“.
Bei EXTENDED
wird die gesamte Tabelle
Datensatz für Datensatz gelesen und die Prüfsumme berechnet.
Dies kann bei großen Tabellen sehr lange dauern.
Wenn weder QUICK
noch
EXTENDED
angegeben sind, gibt MySQL eine
mitlaufende Prüfsumme zurück, wenn die Speicher-Engine der
Tabelle dies unterstützt; andernfalls wird die Tabelle
gescannt.
Bei einer nichtexistenten Tabelle gibt CHECKSUM
TABLE
NULL
zurück und erzeugt
eine Warnung.
OPTIMIZE [LOCAL | NO_WRITE_TO_BINLOG] TABLEtbl_name
[,tbl_name
] ...
OPTIMIZE TABLE
sollte verwendet werden,
wenn Sie einen umfangreichen Teil einer Tabelle gelöscht oder
viele Änderungen an einer Tabelle mit Datensätzen variabler
Länge (also Tabellen mit VARCHAR
-,
VARBINARY
-, BLOB
- oder
TEXT
-Spalten) vorgenommen haben. Gelöschte
Datensätze werden zu einer verknüpften Liste hinzugefügt.
Nachfolgende INSERT
-Operationen verwenden
die alten Datensatzpositionen neu. Sie können mit
OPTIMIZE TABLE
nichtverwendeten Speicher in
der Tabelle freigeben und die Datendatei defragmentieren.
In den meisten Konfigurationen müssen Sie OPTIMIZE
TABLE
gar nicht ausführen. Auch wenn Sie viele
Änderungen an Datensätzen variabler Länge vorgenommen
haben, ist die Wahrscheinlichkeit, dass Sie dies häufiger als
einmal in der Woche oder im Monat tun müssen, sehr gering –
und selbst dies nur bei bestimmten Tabellen.
OPTIMIZE TABLE
funktioniert nur bei
MyISAM
-, BDB
- und
InnoDB
-Tabellen.
Bei MyISAM
-Tabellen funktioniert
OPTIMIZE TABLE
wie folgt:
Wenn die Tabelle gelöschte oder geteilte Datensätze aufweist, wird die Tabelle repariert.
Wenn die Indexseiten nicht sortiert sind, werden sie sortiert.
Wenn die Tabellenstatistiken nicht aktuell sind (und eine Reparatur durch Sortierung des Indexes nicht erfolgreich war), werden sie aktualisiert.
Bei BDB
wird OPTIMIZE
TABLE
zurzeit auf ANALYZE TABLE
umgesetzt. Siehe auch Abschnitt 13.5.2.1, „ANALYZE TABLE
“.
Bei InnoDB
wird OPTIMIZE
TABLE
auf ALTER TABLE
umgesetzt,
wodurch die Tabelle neu erstellt wird, um Indexstatistiken zu
aktualisieren und ungenutzten Speicher im Cluster-Index
freizugeben.
Sie können OPTIMIZE TABLE
auch bei anderen
Speicher-Engines zum Laufen bringen, indem Sie
mysqld mit den Optionen
--skip-new
oder --safe-mode
starten. In diesem Fall wird OPTIMIZE TABLE
einfach auf ALTER TABLE
umgesetzt.
OPTIMIZE TABLE
gibt eine Ergebnismenge mit
den folgenden Spalten zurück:
Spalte | Wert |
Table | der Tabellenname |
Op | ist immer optimize |
Msg_type | status , error ,
info oder
warning |
Msg_text | die Nachricht |
Beachten Sie, dass MySQL die Tabelle während der Laufzeit von
OPTIMIZE TABLE
sperrt.
OPTIMIZE TABLE
-Anweisungen werden in das
Binärlog geschrieben, sofern das optionale Schlüsselwort
NO_WRITE_TO_BINLOG
(oder sein Alias
LOCAL
) nicht verwendet wird. Dies wird
gemacht, damit OPTIMIZE TABLE
-Anweisungen,
die auf einem MySQL Server verwendet werden, der als
Replikationsmaster agiert, standardmäßig auf den
Replikationsslave repliziert werden.
REPAIR [LOCAL | NO_WRITE_TO_BINLOG] TABLEtbl_name
[,tbl_name
] ... [QUICK] [EXTENDED] [USE_FRM]
REPAIR TABLE
repariert eine unter
Umständen beschädigte Tabelle. Standardmäßig hat dies
dieselbe Wirkung wie myisamchk --recover
tbl_name
. REPAIR
TABLE
funktioniert bei MyISAM
-
und ARCHIVE
-Tabellen. Siehe auch
Abschnitt 14.1, „Die MyISAM
-Speicher-Engine“, und
Abschnitt 14.8, „Die ARCHIVE
-Speicher-Engine“.
Im Normalfall werden Sie diese Anweisung niemals ausführen.
Im Katastrophenfall kann REPAIR TABLE
Ihnen
aber sehr wahrscheinlich alle Daten aus einer
MyISAM
-Tabelle wiederherstellen. Treten bei
Ihren Tabellen häufig Beschädigungen auf, dann sollten Sie
versuchen, den Grund dafür zu ermitteln, um REPAIR
TABLE
nicht mehr fortlaufend einsetzen zu müssen.
Siehe auch Abschnitt A.4.2, „Was zu tun ist, wenn MySQL andauernd abstürzt“, und
Abschnitt 14.1.4, „MyISAM-Tabellenprobleme“.
Warnung: Wenn sich der Server
während eines REPAIR TABLE
-Vorgangs
aufhängt, ist es unabdingbar, unmittelbar nach dem Neustart
eine neue REPAIR TABLE
-Anweisung für die
Tabelle abzusetzen, bevor Sie weitere Operationen an ihr
vornehmen. (Es bietet sich ohnehin immer an, zuallererst ein
Backup zu erstellen.) Im schlimmsten Fall haben Sie unter
Umständen eine neue saubere Indexdatei ohne Informationen zur
Datendatei – und könnten im nächsten Schritt
möglicherweise Ihre Datendatei überschreiben! Dies ist ein
unwahrscheinliches, aber durchaus mögliches Szenario.
REPAIR TABLE
gibt eine Ergebnismenge mit
den folgenden Spalten zurück:
Spalte | Wert |
Table | der Tabellenname |
Op | ist immer repair |
Msg_type | status , error ,
info oder
warning |
Msg_text | die Nachricht |
Die Anweisung REPAIR TABLE
kann unter
Umständen viele Datensätze für die reparierte Tabelle
ausgeben. Der letzte Datensatz hat den
Msg_type
-Wert status
;
Msg_test
sollte normalerweise den Wert
OK
haben. Wenn Sie einen anderen Status als
OK
erhalten, sollten Sie die Tabelle mit
myisamchk --safe-recover zu reparieren
versuchen. (REPAIR TABLE
implementiert noch
nicht alle Optionen von myisamchk. Wir
beabsichtigen aber, die Anweisung in Zukunft flexibler zu
gestalten.) Mit myisamchk --safe-recover
können Sie auch Optionen verwenden, die REPAIR
TABLE
nicht unterstützt (z. B.
--max-record-length
).
Wenn QUICK
angegeben wird, versucht
REPAIR TABLE
, nur den Indexbaum zu
reparieren. Dieser Reparaturtyp ähnelt dem von
myisamchk --recover --quick.
Wenn Sie EXTENDED
verwenden, erstellt MySQL
den Index Datensatz für Datensatz, statt einen Index
gleichzeitig beim Sortieren zu erzeugen. Dieser Reparaturtyp
ähnelt dem von myisamchk --safe-recover.
Es gibt auch einen Modus USE_FRM
für
REPAIR TABLE
. Diesen verwenden Sie, wenn
die .MYI
-Indexdatei fehlt oder ihr Header
beschädigt ist. In diesem Modus erstellt MySQL die
.MYI
-Datei auf der Basis der Daten aus
der .frm
-Datei neu. Diese Art der
Reparatur ist mit myisamchk nicht möglich.
Hinweis: Verwenden Sie diesen
Modus nur, wenn Sie die regulären
REPAIR
-Modi nicht einsetzen können. Der
.MYI
-Header enthält wichtige
Tabellenmetadaten (insbesondere etwa den
AUTO_INCREMENT
-Wert und Delete
link
), die bei REPAIR ... USE_FRM
verloren gehen. Verwenden Sie USE_FRM
nicht
für eine komprimierte Tabelle, weil diese Informationen auch
in der .MYI
-Datei gespeichert sind.
REPAIR TABLE
-Anweisungen werden in das
Binärlog geschrieben, sofern das optionale Schlüsselwort
NO_WRITE_TO_BINLOG
(oder sein Alias
LOCAL
) nicht verwendet wird. Dies wird
gemacht, damit REPAIR TABLE
-Anweisungen,
die auf einem MySQL Server verwendet werden, der als
Replikationsmaster agiert, standardmäßig auf den
Replikationsslave repliziert werden.
RESTORE TABLEtbl_name
[,tbl_name
] ... FROM '/path/to/backup/directory
'
RESTORE TABLE
stellt eine oder mehrere
Tabellen aus einer Sicherung, die mit BACKUP
TABLE
erstellt wurde, wieder her. Vorhandene
Tabellen werden nicht überschrieben: Wenn Sie versuchen, eine
vorhandene Tabelle durch Wiederherstellen zu überschreiben,
dann tritt ein Fehler auf. Wie BACKUP TABLE
funktioniert auch RESTORE TABLE
derzeit nur
für MyISAM
-Tabellen. Das Verzeichnis
sollte als vollständiger Pfadname angegeben werden.
Das Backup einer Tabelle besteht aus ihrer
.frm
-Formatdatei und der
.MYD
-Datendatei. Beim
Wiederherstellungsvorgang werden diese Dateien zunächst
wiederhergestellt; darauf basierend wird dann die
.MYI
-Indexdatei erstellt. Die
Wiederherstellung dauert länger als die Sicherung, weil die
Indizes neu erstellt werden müssen. Je mehr Indizes die
Tabelle hat, desto länger dauert der Vorgang.
RESTORE TABLE
gibt eine Ergebnismenge mit
den folgenden Spalten zurück:
Spalte | Wert |
Table | der Tabellenname |
Op | ist immer restore |
Msg_type | status , error ,
info oder
warning |
Msg_text | die Nachricht |
SETvariable_assignment
[,variable_assignment
] ...variable_assignment
:user_var_name
=expr
| [GLOBAL | SESSION]system_var_name
=expr
| [@@global. | @@session. | @@]system_var_name
=expr
Die Anweisung SET
weist verschiedenen Arten
von Variablen, die sich auf den Betrieb des Servers oder Ihres
Clients auswirken, Werte zu.
Dieser Abschnitt beschreibt die Verwendung von
SET
zur Zuweisung von Werten an System- oder
Benutzervariablen. Allgemeine Informationen zu diesen
Variablentypen finden Sie in
Abschnitt 5.2.2, „Server-Systemvariablen“, und
Abschnitt 9.3, „Benutzerdefinierte Variablen“. Eine Liste der
Systemvariablen, die dynamisch zur Laufzeit geändert werden
können, finden Sie in
Abschnitt 5.2.3.2, „Dynamische Systemvariablen“.
Hinweis: Ältere Versionen von MySQL
verwendeten SET OPTION
. Diese Funktionalität
ist jedoch veraltet – mittlerweile wird SET
nur noch ohne OPTION
benutzt.
Es gibt auch Varianten der SET
-Syntax, die in
anderen Kontexten verwendet werden:
SET PASSWORD
weist Kontenpasswörter zu.
Siehe auch Abschnitt 13.5.1.6, „SET PASSWORD
“.
SET TRANSACTION ISOLATION LEVEL
bestimmt
die Isolierungsstufe für die Transaktionsverarbeitung.
Siehe auch Abschnitt 13.4.6, „SET TRANSACTION
“.
SET
wird in gespeicherten Routinen
benutzt, um lokalen Routinenvariablen Werte zuzuweisen.
Siehe auch Abschnitt 19.2.7.2, „Variable SET
-Anweisung“.
Die folgende Erläuterung zeigt die verschiedenen
SET
-Syntaxen, die zur Einstellung von
Variablen benutzt werden können. In den Beispielen wird jeweils
der Zuweisungsoperator =
benutzt, der
Operator :=
ist aber ebenfalls zulässig.
Eine Benutzervariable wird als
@
geschrieben und kann wie folgt eingestellt werden:
var_name
SET @var_name
=expr
;
Systemvariablen werden in SET
-Anweisungen als
var_name
referenziert. Unter
Umständen kann ihnen auch ein Modifizierer vorangestellt sein:
Um explizit anzugeben, dass eine Variable eine globale
Variable ist, stellen Sie dem Namen
GLOBAL
oder @@global.
voran. Zum Einstellen globaler Variablen ist die
Berechtigung SUPER
erforderlich.
Um explizit anzugeben, dass eine Variable eine
Sitzungsvariable ist, stellen Sie dem Namen
SESSION
oder
@@session.
voran.
LOCAL
und @@local.
sind Synonyme von SESSION
bzw.
@@session.
.
Ist kein Modifizierer vorhanden, dann stellt
SET
die Sitzungsvariable ein.
Ein paar Beispiele:
SET sort_buffer_size=10000; SET @@local.sort_buffer_size=10000; SET GLOBAL sort_buffer_size=1000000, SESSION sort_buffer_size=1000000; SET @@sort_buffer_size=1000000; SET @@global.sort_buffer_size=1000000, @@local.sort_buffer_size=1000000;
Die Syntax
@@
für
Systemvariablen wird unterstützt, damit die MySQL-Syntax mit
einigen anderen Datenbanksystemen kompatibel ist.
var_name
Wenn Sie mehrere Systemvariablen in derselben Anweisung
einstellen, wird die zuletzt angegebene
GLOBAL
- oder
SESSION
-Option für Variablen verwendet,
deren Modus nicht näher spezifiziert ist.
Wenn Sie eine sitzungsspezifische Systemvariable einstellen, bleibt der Wert gültig, bis die aktuelle Sitzung endet oder Sie der Variablen einen anderen Wert zuweisen. Stellen Sie eine globale Systemvariable ein, dann wird der Wert gespeichert und bis zum nächsten Neustart des Servers für alle neuen Verbindungen verwendet. Wenn Sie den Wert einer globalen Systemvariablen permanent ändern wollen, sollten Sie diesen in eine Optionsdatei eintragen. Siehe auch Abschnitt 4.3.2, „my.cnf-Optionsdateien“.
Um eine falsche Verwendung zu verhindern, erzeugt MySQL einen
Fehler, wenn Sie SET GLOBAL
für eine
Variable verwenden, für die nur SET SESSION
zulässig ist, oder GLOBAL
(bzw.
@@global.
) beim Einstellen einer globalen
Variablen nicht angeben.
Um eine SESSION
-Variable auf den
GLOBAL
-Wert oder eine
GLOBAL
-Variable auf den in MySQL
einkompilierten Standardwert zu setzen, verwenden Sie das
Schlüsselwort DEFAULT
. So sind
beispielsweise die beiden folgenden Anweisungen dahingehend
identisch, dass sie den Sitzungswert von
max_join_size
auf den globalen Wert setzen:
SET max_join_size=DEFAULT; SET @@session.max_join_size=@@global.max_join_size;
Es lassen sich nicht alle Systemvariablen auf
DEFAULT
setzen. In solchen Fällen tritt bei
Verwendung von DEFAULT
ein Fehler auf.
Eine Liste der Systemvariablen und ihrer Werte zeigen Sie mit
der SHOW VARIABLES
-Anweisung an. (Siehe auch
Abschnitt 13.5.4.24, „SHOW VARIABLES
“.) Um einen bestimmten
Variablennamen oder eine Liste der Namen zu erhalten, die einem
Muster entsprechen, verwenden Sie eine
LIKE
-Klausel wie folgt:
SHOW VARIABLES LIKE 'max_join_size'; SHOW GLOBAL VARIABLES LIKE 'max_join_size';
Zum Anzeigen einer Variablenliste, deren Namen einem Muster
entsprechen, verwenden Sie das Jokerzeichen
‘%
’:
SHOW VARIABLES LIKE '%size%'; SHOW GLOBAL VARIABLES LIKE '%size%';
Jokerzeichen können an beliebiger Position im Vergleichsmuster stehen.
Sie können den Wert einer bestimmten Systemvariablen auch mit
SELECT
ermitteln, indem Sie die Syntax
@@[global.|session.]
benutzen:
var_name
SELECT @@global.max_join_size, @@session.max_join_size;
Wenn Sie eine Variable mit SELECT
@@
(ohne
Modifizierer) abrufen, gibt MySQL den
var_name
SESSION
-Wert, sofern dieser vorhanden ist,
und andernfalls den GLOBAL
-Wert zurück.
(Hier liegt ein Unterschied zu SET
@@
vor, wo immer der
Sitzungswert referenziert wird.)
var_name
=
value
Die folgende Liste beschreibt Variablen, die keine
Standardsyntax aufweisen oder nicht in der in
Abschnitt 5.2.2, „Server-Systemvariablen“, aufgeführten Liste
der Systemvariablen beschrieben sind. Zwar werden die hier
beschriebenen Variablen nicht von SHOW
VARIABLES
angezeigt, Sie können die Werte aber mit
SELECT
abrufen (Ausnahmen sind
CHARACTER SET
und SET
NAMES
). Zum Beispiel:
mysql> SELECT @@AUTOCOMMIT;
+--------------+
| @@AUTOCOMMIT |
+--------------+
| 1 |
+--------------+
Die Groß-/Kleinschreibung dieser Optionen ist irrelevant.
AUTOCOMMIT = {0 | 1}
Stellt den Autocommit-Modus ein. Mit der Einstellung 1
werden alle Änderungen direkt übernommen. Wenn Sie 0
wählen, müssen Sie eine Transaktion mit
COMMIT
übergeben oder sie mit
ROLLBACK
abbrechen. Standardmäßig
starten Clientverbindungen mit dem
AUTOCOMMIT
-Wert 1. Wenn Sie
AUTOCOMMIT
von 0 auf 1 umstellen, führt
MySQL automatisch eine COMMIT
-Anweisung
für alle offenen Transaktionen aus. Eine andere
Möglichkeit, eine Transaktion zu starten, besteht in der
Verwendung der Anweisungen START
TRANSACTION
oder BEGIN
. Siehe
auch Abschnitt 13.4.1, „BEGIN/COMMIT/ROLLBACK
“.
Beim Wert 1 werden alle Temporärtabellen auf der Festplatte
statt im Arbeitsspeicher abgelegt. Dies ist ein wenig
langsamer, aber der Fehler The table
tritt
nicht bei tbl_name
is fullSELECT
-Operationen auf, die
eine große Temporärtabelle erfordern. Der Standardwert bei
einer neuen Verbindung ist 0 (d. h., es werden
speicherresidente Temporärtabellen verwendet). Im
Normalfall sollten Sie diese Variable niemals umstellen
müssen, da speicherresidente Tabellen nach Bedarf
automatisch in festplattenbasierte Tabellen konvertiert
werden. (Hinweis: Diese
Variable hieß früher SQL_BIG_TABLES
.)
CHARACTER SET
{
charset_name
|
DEFAULT}
Hiermit werden alle Strings vom und an den Client den
Angaben entsprechend konvertiert. Sie können neue
Zuordnungen angeben, indem Sie die Datei
sql/convert.cc
in der
MySQL-Quelldistribution bearbeiten. SET CHARACTER
SET
stellt drei sitzungsspezifische
Systemvariablen ein: character_set_client
und character_set_results
werden auf den
angegebenen Zeichensatz gesetzt,
character_set_connection
auf den Wert von
character_set_database
. Siehe auch
Abschnitt 10.4, „Verbindungszeichensatz und -sortierfolge“.
Die Standardzuordnung kann mit dem Wert
DEFAULT
wiederhergestellt werden.
Beachten Sie, dass die Syntax sich bei SET
CHARACTER SET
von der zur Einstellung der meisten
anderen Optionen unterscheidet.
FOREIGN_KEY_CHECKS = {0 | 1}
Bei der Einstellung 1 (Vorgabe) werden
Fremdschlüssel-Constraints für
InnoDB
-Tabellen überprüft. Bei der
Einstellung 0 werden sie ignoriert. Die Deaktivierung der
Fremdschlüsselüberprüfung kann nützlich sein, um
InnoDB
-Tabellen in einer anderen als der
Reihenfolge neu zu laden, die von den
Parent/Child-Beziehungen erfordert wird. Siehe auch
Abschnitt 14.2.6.4, „Fremdschlüssel-Beschränkungen“.
IDENTITY =
value
Diese Variable ist synonym zur Variablen
LAST_INSERT_ID
. Sie ist aus Gründen der
Kompatibilität mit anderen Datenbanksystemen vorhanden. Sie
können ihren Wert mit SELECT @@IDENTITY
auslesen und mit SET IDENTITY
einstellen.
INSERT_ID =
value
Stellt den von der folgenden INSERT
- oder
ALTER TABLE
-Anweisung zu verwendenden
Wert ein, wenn ein AUTO_INCREMENT
-Wert
eingefügt wird. Wird in erster Linie beim Binärlog
benutzt.
LAST_INSERT_ID =
value
Stellt den von LAST_INSERT_ID()
zurückzugebenden Wert ein. Dieser wird im Binärlog
gespeichert, wenn Sie LAST_INSERT_ID()
in
einer Anweisung verwenden, die eine Tabelle aktualisiert.
Durch Einstellen dieser Variablen wird der von der
C-API-Funktion mysql_insert_id()
zurückgegebene Wert nicht geändert.
NAMES {'
charset_name
' |
DEFAULT}
SET NAMES
setzt die drei Systemvariablen
character_set_client
,
character_set_connection
und
character_set_results
auf den angegebenen
Zeichensatz. Das Einstellen von
character_set_connection
auf
charset_name
setzt
collation_connection
auf die
Standardsortierfolge für charset_name
.
Siehe auch Abschnitt 10.4, „Verbindungszeichensatz und -sortierfolge“.
Die Standardzuordnung kann mit dem Wert
DEFAULT
wiederhergestellt werden.
Beachten Sie, dass die Syntax sich bei SET
NAMES
von der zur Einstellung der meisten anderen
Optionen unterscheidet.
ONE_SHOT
Diese Option ist ein Modifizierer und keine Variable. Sie
kann verwendet werden, um die Wirkung von Variablen zu
beeinflussen, die den Zeichensatz, die Sortierfolge und die
Zeitzone einstellen. ONE_SHOT
wird in
erster Linie zu Replikationszwecken eingesetzt.
mysqlbinlog verwendet SET
ONE_SHOT
zur vorübergehenden Änderung der Werte
von Zeichensatz-, Sortierfolgen- und Zeitzonenvariablen, um
die ursprünglichen Werte für einen Rollforward zu
speichern.
Sie können ONE_SHOT
nur mit den
zulässigen Variablen verwenden, andernfalls erhalten Sie
einen Fehler wie den folgenden:
mysql> SET ONE_SHOT max_allowed_packet = 1;
ERROR 1382 (HY000): The 'SET ONE_SHOT' syntax is reserved for purposes
internal to the MySQL server
Wenn ONE_SHOT
mit zulässigen Variablen
benutzt wird, ändert es die Variablen nach Bedarf –
jedoch nur für die nächste Anweisung, die nicht
SET
ist. Nachfolgend setzt der Server
alle zeichensatz-, sortierfolgen- und zeitzonenspezifischen
Systemvariablen auf ihre vorherigen Werte. Beispiel:
mysql>SET ONE_SHOT character_set_connection = latin5;
mysql>SET ONE_SHOT collation_connection = latin5_turkish_ci;
mysql>SHOW VARIABLES LIKE '%_connection';
+--------------------------+-------------------+ | Variable_name | Value | +--------------------------+-------------------+ | character_set_connection | latin5 | | collation_connection | latin5_turkish_ci | +--------------------------+-------------------+ mysql>SHOW VARIABLES LIKE '%_connection';
+--------------------------+-------------------+ | Variable_name | Value | +--------------------------+-------------------+ | character_set_connection | latin1 | | collation_connection | latin1_swedish_ci | +--------------------------+-------------------+
SQL_AUTO_IS_NULL = {0 | 1}
Bei der Einstellung 1 (Vorgabe) ermitteln Sie den zuletzt
eingefügten Datensatz für eine Tabelle, die eine
AUTO_INCREMENT
-Spalte umfasst, mithilfe
des folgenden Konstrukts:
WHERE auto_increment_column
IS NULL
Dieses Verhalten wird von einigen ODBC-Programmen wie etwa Access verwendet.
SQL_BIG_SELECTS = {0 | 1}
Bei der Einstellung 0 bricht MySQL
SELECT
-Anweisungen ab, deren Ausführung
voraussichtlich sehr lange dauern wird (d. h., Anweisungen,
bei denen der Optimierer eine Anzahl von untersuchten
Datensätzen annimmt, deren Wert
max_join_size
überschreitet. Dies ist
praktisch, wenn eine nicht empfehlenswerte
WHERE
-Anweisung abgesetzt wurde. Der
Standardwert für eine neue Verbindung ist 1, d. h., alle
SELECT
-Anweisungen sind zulässig.
Wenn Sie die Systemvariable max_join_size
auf einen anderen Wert als DEFAULT
setzen, wird SQL_BIG_SELECTS
auf 0
gesetzt.
SQL_BUFFER_RESULT = {0 | 1}
SQL_BUFFER_RESULT
bewirkt, dass
Ergebnisse aus SELECT
-Anweisungen in
Temporärtabellen abgelegt werden. Auf diese Weise kann
MySQL die Tabellensperren schnell wieder aufheben. Die
Option ist zudem in Fällen hilfreich, in denen die
Übermittlung der Ergebnisse an den Client sehr lange
dauert.
SQL_LOG_BIN = {0 | 1}
Bei der Einstellung 0 erfolgt für den Client keine
Aufzeichnung in das Binärlog. Der Client benötigt die
Berechtigung SUPER
, um diese Option
einzustellen.
SQL_LOG_OFF = {0 | 1}
Bei der Einstellung 1 erfolgt für den Client keine
Aufzeichnung in das Log für allgemeine Abfragen. Der Client
benötigt die Berechtigung SUPER
, um
diese Option einzustellen.
SQL_LOG_UPDATE = {0 | 1}
Diese Variable ist veraltet und wird auf
SQL_LOG_BIN
umgesetzt.
SQL_NOTES = {0 | 1}
Bei der Einstellung 1 (Standard) werden Warnungen auf
Note
-Ebene aufgezeichnet. Wird hingegen 0
gewählt, dann werden Note
-Warnungen
unterdrückt. mysqldump enthält eine
Ausgabe, die diese Variable auf 0 setzt, sodass ein Neuladen
der Dumpdatei keine Warnungen für Ereignisse erzeugt, die
die Integrität des Neuladevorgangs nicht beeinträchtigen.
SQL_QUOTE_SHOW_CREATE = {0 | 1}
Bei der Einstellung 1 setzt der Server Bezeichner für die
Anweisungen SHOW CREATE TABLE
und
SHOW CREATE DATABASE
in
Anführungszeichen. Bei 0 werden keine Anführungszeichen
gesetzt. Die Option ist standardmäßig aktiviert, damit die
Replikation auch bei Bezeichnern funktioniert, die
Anführungszeichen erfordern. Siehe auch
Abschnitt 13.5.4.6, „SHOW CREATE TABLE
“, und
Abschnitt 13.5.4.4, „SHOW CREATE DATABASE
“.
SQL_SAFE_UPDATES = {0 | 1}
Bei der Einstellung 1 bricht MySQL
UPDATE
- und
DELETE
-Anweisungen ab, die keinen
Schlüssel in der WHERE
-Klausel oder
einer LIMIT
-Klausel verwenden. Auf diese
Weise lassen sich UPDATE
- oder
DELETE
-Anweisungen abfangen, bei denen
Schlüssel nicht korrekt eingesetzt werden und die unter
Umständen eine große Zahl von Datensätzen ändern oder
löschen würden.
SQL_SELECT_LIMIT =
{
value
| DEFAULT}
Die maximale Anzahl von Datensätzen, die von
SELECT
-Anweisungen zurückgegeben werden
können. Der Standardwert bei einer neuen Verbindung lautet
„unbegrenzt“. Wenn Sie den Grenzwert geändert
haben, kann der Standardwert mit dem Wert
DEFAULT
für
SQL_SELECT_LIMIT
wiederhergestellt
werden.
Wenn eine SELECT
-Anweisung eine
LIMIT
-Klausel aufweist, hat diese
LIMIT
-Klausel Vorrang vor dem Wert von
SQL_SELECT_LIMIT
.
SQL_SELECT_LIMIT
gilt nicht für
SELECT
-Anweisungen, die in gespeicherten
Routinen ausgeführt werden. Ebenso wenig gelten sie für
SELECT
-Anweisungen, die keine
Ergebnismenge erzeugen, die an den Client zurückgegeben
wird. Hierzu gehören SELECT
-Anweisungen
in Unterabfragen, CREATE TABLE ... SELECT
und INSERT INTO ... SELECT
.
SQL_WARNINGS = {0 | 1}
Diese Variable steuert, ob
INSERT
-Anweisungen für einen Datensatz
einen Informations-String erzeugen, wenn Warnungen
auftreten. Die Standardeinstellung ist 0. Setzen Sie den
Wert auf 1, um einen Informations-String zu generieren.
TIMESTAMP =
{
timestamp_value
|
DEFAULT}
Stellt die Zeit für diesen Client ein. Auf deren Basis wird
der ursprüngliche Zeitstempel ermittelt, wenn Sie
Datensätze mit dem Binärlog wiederherstellen.
timestamp_value
sollte ein
Unix-Epochenzeitstempel und kein MySQL-Zeitstempel sein.
UNIQUE_CHECKS = {0 | 1}
Bei der Einstellung 1 (Standard) werden
Eindeutigkeitsprüfungen für Sekundärindizes in
InnoDB
-Tabellen durchgeführt. Wenn der
Wert 0 eingestellt wurde, werden keine
Eindeutigkeitsprüfungen für Indexeinträge durchgeführt,
die in den InnoDB
-Einfügepuffer
eingefügt wurden. Wenn Sie ganz sicher wissen, dass Ihre
Daten keine Verstöße gegen das Eindeutigkeitsgebot
enthalten, können Sie hier 0 wählen, um den Import großer
Tabellen in InnoDB
zu beschleunigen.
SHOW CHARACTER SET
SHOW COLLATION
SHOW COLUMNS
SHOW CREATE DATABASE
SHOW CREATE PROCEDURE
und SHOW CREATE
FUNCTION
SHOW CREATE TABLE
SHOW DATABASES
SHOW ENGINE
SHOW ENGINES
SHOW ERRORS
SHOW GRANTS
SHOW INDEX
SHOW INNODB STATUS
SHOW LOGS
SHOW OPEN TABLES
SHOW PLUGIN
SHOW PRIVILEGES
SHOW PROCEDURE STATUS
und SHOW FUNCTION
STATUS
SHOW PROCESSLIST
SHOW STATUS
SHOW TABLE STATUS
SHOW TABLES
SHOW TRIGGERS
SHOW VARIABLES
SHOW WARNINGS
Es gibt viele Formen von SHOW
, die
Informationen zu Datenbanken, Tabellen oder Spalten sowie
Statusangaben zum Server vermitteln. In diesem Abschnitt werden
die folgenden SHOW
-Anweisungen beschrieben:
SHOW [FULL] COLUMNS FROMtbl_name
[FROMdb_name
] [LIKE 'pattern
'] SHOW CREATE DATABASEdb_name
SHOW CREATE FUNCTIONfuncname
SHOW CREATE PROCEDUREprocname
SHOW CREATE TABLEtbl_name
SHOW DATABASES [LIKE 'pattern
'] SHOW ENGINEengine_name
{LOGS | STATUS } SHOW [STORAGE] ENGINES SHOW ERRORS [LIMIT [offset
,]row_count
] SHOW FUNCTION STATUS [LIKE 'pattern
'] SHOW GRANTS FORuser
SHOW INDEX FROMtbl_name
[FROMdb_name
] SHOW INNODB STATUS SHOW PROCEDURE STATUS [LIKE 'pattern
'] SHOW [BDB] LOGS SHOW PLUGIN SHOW PRIVILEGES SHOW [FULL] PROCESSLIST SHOW [GLOBAL | SESSION] STATUS [LIKE 'pattern
'] SHOW TABLE STATUS [FROMdb_name
] [LIKE 'pattern
'] SHOW [OPEN] TABLES [FROMdb_name
] [LIKE 'pattern
'] SHOW TRIGGERS SHOW [GLOBAL | SESSION] VARIABLES [LIKE 'pattern
'] SHOW WARNINGS [LIMIT [offset
,]row_count
]
Es gibt zusätzliche Formen der
SHOW
-Anweisung, die Informationen zu
Replikationsmaster- und -slave-Servern vermitteln (diese werden
in Abschnitt 13.6, „SQL-Befehle in Bezug auf Replikation“, beschrieben):
SHOW BINLOG EVENTS SHOW MASTER LOGS SHOW MASTER STATUS SHOW SLAVE HOSTS SHOW SLAVE STATUS
Wenn die Syntax für eine gegebene
SHOW
-Anweisung einen LIKE
'
-Teil enthält,
ist pattern
''
ein
String, der die SQL-Jokerzeichen
‘pattern
'%
’ und
‘_
’ enthalten kann. Dieses Muster
ist praktisch, um die Ausgabe der Anweisung auf passende Werte
zu beschränken.
Mehrere SHOW
-Anweisungen akzeptieren zudem
eine WHERE
-Klausel, die mehr Flexibilität
bei der Angabe der anzuzeigenden Datensätze bietet. Siehe auch
Abschnitt 22.22, „Erweiterungen der SHOW
-Anweisungen“.
SHOW CHARACTER SET [LIKE 'pattern
']
Die Anweisung SHOW CHARACTER SET
zeigt alle
verfügbaren Zeichensätze an. Sie nimmt eine optionale
LIKE
-Klausel entgegen, die angibt, auf
welche Zeichensatznamen zu prüfen ist. Zum Beispiel:
mysql> SHOW CHARACTER SET LIKE 'latin%';
+---------+-----------------------------+-------------------+--------+
| Charset | Description | Default collation | Maxlen |
+---------+-----------------------------+-------------------+--------+
| latin1 | cp1252 West European | latin1_swedish_ci | 1 |
| latin2 | ISO 8859-2 Central European | latin2_general_ci | 1 |
| latin5 | ISO 8859-9 Turkish | latin5_turkish_ci | 1 |
| latin7 | ISO 8859-13 Baltic | latin7_general_ci | 1 |
+---------+-----------------------------+-------------------+--------+
Die Spalte Maxlen
zeigt die maximale Anzahl
von Bytes an, die zur Speicherung eines Zeichens erforderlich
sind.
SHOW COLLATION [LIKE 'pattern
']
Die Ausgabe von SHOW COLLATION
enthält
alle verfügbaren Zeichensätze. Sie nimmt eine optionale
LIKE
-Klausel entgegen, bei der
pattern
angibt, auf welche
Sortierfolgennamen zu prüfen ist. Zum Beispiel:
mysql> SHOW COLLATION LIKE 'latin1%';
+-------------------+---------+----+---------+----------+---------+
| Collation | Charset | Id | Default | Compiled | Sortlen |
+-------------------+---------+----+---------+----------+---------+
| latin1_german1_ci | latin1 | 5 | | | 0 |
| latin1_swedish_ci | latin1 | 8 | Yes | Yes | 0 |
| latin1_danish_ci | latin1 | 15 | | | 0 |
| latin1_german2_ci | latin1 | 31 | | Yes | 2 |
| latin1_bin | latin1 | 47 | | Yes | 0 |
| latin1_general_ci | latin1 | 48 | | | 0 |
| latin1_general_cs | latin1 | 49 | | | 0 |
| latin1_spanish_ci | latin1 | 94 | | | 0 |
+-------------------+---------+----+---------+----------+---------+
Die Spalte Default
gibt ab, ob eine
Sortierfolge standardmäßig für den Zeichensatz verwendet
wird. Compiled
zeigt an, ob der Zeichensatz
in den Server einkompiliert ist. Sortlen
schließlich bezieht sich auf die Menge des Speichers, die zum
Sortieren der im Zeichensatz ausgedrückten Strings
erforderlich ist.
SHOW [FULL] COLUMNS FROMtbl_name
[FROMdb_name
] [LIKE 'pattern
']
SHOW COLUMNS
vermittelt Informationen zu
Spalten in einer Tabelle. Die Anweisung funktioniert auch bei
Views.
Das Schlüsselwort FULL
bewirkt, dass die
Ausgabe ihre Berechtigungen sowie alle spaltenspezifischen
Kommentare für jede Spalte enthält.
Sie können db_name.tbl_name
als
Alternative zur Syntax
verwenden. Die
beiden folgenden Anweisungen sind mithin äquivalent:
tbl_name
FROM
db_name
mysql>SHOW COLUMNS FROM mytable FROM mydb;
mysql>SHOW COLUMNS FROM mydb.mytable;
SHOW FIELDS
ist ein Synonym für
SHOW COLUMNS
. Sie können die Spalten einer
Tabelle auch mit dem Befehl mysqlshow
db_name
tbl_name
auflisten.
Die Anweisung DESCRIBE
ermittelt ähnliche
Informationen wie SHOW COLUMNS
. Siehe auch
Abschnitt 13.3.1, „DESCRIBE
(Informationen über Spalten abrufen)“.
SHOW CREATE {DATABASE | SCHEMA} db_name
Zeigt die CREATE DATABASE
-Anweisung an, mit
der die übergebene Datenbank erstellt wurde. SHOW
CREATE SCHEMA
ist ein Synonym zu SHOW
CREATE DATABASE
.
mysql>SHOW CREATE DATABASE test\G
*************************** 1. row *************************** Database: test Create Database: CREATE DATABASE `test` /*!40100 DEFAULT CHARACTER SET latin1 */ mysql>SHOW CREATE SCHEMA test\G
*************************** 1. row *************************** Database: test Create Database: CREATE DATABASE `test` /*!40100 DEFAULT CHARACTER SET latin1 */
SHOW CREATE DATABASE
setzt Tabellen- und
Spaltennamen entsprechend dem Wert von
SQL_QUOTE_SHOW_CREATE
in
Anführungszeichen. Siehe auch Abschnitt 13.5.3, „SET
“.
SHOW CREATE {PROCEDURE | FUNCTION} sp_name
Diese Anweisung ist eine MySQL-Erweiterung. Analog zu
SHOW CREATE TABLE
gibt sie den exakten
String zurück, mit dem die genannte Routine neu erstellt
werden kann.
mysql> SHOW CREATE FUNCTION test.hello\G
*************************** 1. row ***************************
Function: hello
sql_mode:
Create Function: CREATE FUNCTION `test`.`hello`(s CHAR(20)) RETURNS CHAR(50)
RETURN CONCAT('Hello, ',s,'!')
SHOW CREATE TABLE tbl_name
Zeigt die CREATE TABLE
-Anweisung an, mit
der die übergebene Tabelle erstellt wurde. Diese Anweisung
funktioniert auch bei Views.
mysql> SHOW CREATE TABLE t\G
*************************** 1. row ***************************
Table: t
Create Table: CREATE TABLE t (
id INT(11) default NULL auto_increment,
s char(60) default NULL,
PRIMARY KEY (id)
) ENGINE=MyISAM
SHOW CREATE TABLE
setzt Tabellen- und
Spaltennamen entsprechend dem Wert von
SQL_QUOTE_SHOW_CREATE
in
Anführungszeichen. Siehe auch Abschnitt 13.5.3, „SET
“.
SHOW {DATABASES | SCHEMAS} [LIKE 'pattern
']
SHOW DATABASES
listet die Datenbanken auf
dem MySQL Server-Host auf. Sofern Sie nicht über die
Berechtigung SHOW DATABASES
verfügen,
werden Ihnen nur diejenigen Datenbanken angezeigt, für die
Sie Berechtigungen haben. Sie können diese Liste auch mit
mysqlshow anzeigen.
Wurde der Server mit der Option
--skip-show-database
gestartet, dann können
Sie diese Anweisung ohne die Berechtigung SHOW
DATABASES
überhaupt nicht verwenden.
SHOW SCHEMAS
kann ebenfalls verwendet
werden.
SHOW ENGINE engine_name
{LOGS | STATUS }
SHOW ENGINE
zeigt Log- und
Statusinformationen zu Speicher-Engines an. Die folgenden
Anweisungen werden derzeit unterstützt:
SHOW ENGINE BDB LOGS SHOW ENGINE INNODB STATUS
SHOW ENGINE BDB LOGS
zeigt
Statusinformationen zu vorhandenen
BDB
-Logdateien an. Zurückgegeben werden
die folgenden Felder:
File
Der vollständige Pfad zur Logdatei.
Type
Der Logdateityp (BDB
bei Berkeley
DB-Logdateien).
Status
Der Status der Logdatei (FREE
, wenn die
Datei entfernt werden kann, oder IN
USE
, wenn die Datei vom Transaktionssubsystem
benötigt wird).
SHOW ENGINE INNODB STATUS
zeigt umfassende
Informationen zum Zustand der
InnoDB
-Speicher-Engine an.
Ältere (und mittlerweile nicht mehr verwendete) Synonyme für
diese Anweisungen sind SHOW [BDB] LOGS
und
SHOW INNODB STATUS
.
SHOW [STORAGE] ENGINES
SHOW ENGINES
zeigt Statusinformationen zu
den Speicher-Engines des Servers an. Dies ist besonders
nützlich, um zu überprüfen, ob eine Speicher-Engine
unterstützt wird, oder um festzustellen, welche Engine
standardmäßig benutzt wird. SHOW TABLE
TYPES
ist ein veraltetes Synonym.
mysql> SHOW ENGINES\G
*************************** 1. row ***************************
Engine: MEMORY
Support: YES
Comment: Hash based, stored in memory, useful for temporary tables
Transactions: NO
XA: NO
Savepoints: NO
*************************** 2. row ***************************
Engine: MyISAM
Support: DEFAULT
Comment: Default engine as of MySQL 3.23 with great performance
Transactions: NO
XA: NO
Savepoints: NO
*************************** 3. row ***************************
Engine: InnoDB
Support: YES
Comment: Supports transactions, row-level locking, and foreign keys
Transactions: YES
XA: YES
Savepoints: YES
*************************** 4. row ***************************
Engine: BerkeleyDB
Support: YES
Comment: Supports transactions and page-level locking
Transactions: YES
XA: NO
Savepoints: NO
*************************** 5. row ***************************
Engine: EXAMPLE
Support: YES
Comment: Example storage engine
Transactions: NO
XA: NO
Savepoints: NO
*************************** 6. row ***************************
Engine: ARCHIVE
Support: YES
Comment: Archive storage engine
Transactions: NO
XA: NO
Savepoints: NO
*************************** 7. row ***************************
Engine: CSV
Support: YES
Comment: CSV storage engine
Transactions: NO
XA: NO
Savepoints: NO
*************************** 8. row ***************************
Engine: BLACKHOLE
Support: YES
Comment: /dev/null storage engine (anything you write to it disappears)
Transactions: NO
XA: NO
Savepoints: NO
*************************** 9. row ***************************
Engine: FEDERATED
Support: YES
Comment: Federated MySQL storage engine
Transactions: NO
XA: NO
Savepoints: NO
*************************** 10. row ***************************
Engine: MRG_MYISAM
Support: YES
Comment: Collection of identical MyISAM tables
Transactions: NO
XA: NO
Savepoints: NO
Der Wert Support
gibt an, ob die
betreffende Speicher-Engine unterstützt wird und welches die
standardmäßig verwendete Engine ist. Wird der Server
beispielsweise mit der Option
--default-table-type=InnoDB
gestartet, dann
hat der Wert Support
für den Datensatz
InnoDB
den Wert DEFAULT
.
Siehe auch Kapitel 14, Speicher-Engines und Tabellentypen.
Die Spalten Transactions
,
XA
und Savepoints
wurden
in MySQL 5.1.2 hinzugefügt. Sie geben jeweils an, ob die
Speicher-Engine Transaktionen, XA-Transaktionen und/oder
Speicherpunkte unterstützt.
SHOW ERRORS [LIMIT [offset
,]row_count
] SHOW COUNT(*) ERRORS
Diese Anweisung ähnelt SHOW WARNINGS
; der
Unterschied besteht darin, dass statt Fehlern, Warnungen und
Hinweisen lediglich Fehler angezeigt werden.
Die LIMIT
-Klausel hat dieselbe Syntax wie
bei der SELECT
-Anweisung. Siehe auch
Abschnitt 13.2.7, „SELECT
“.
Die SHOW COUNT(*) ERRORS
-Anweisung zeigt
die Anzahl der Fehler an. Sie können diese Anzahl auch der
Variablen error_count
entnehmen:
SHOW COUNT(*) ERRORS; SELECT @@error_count;
Weitere Informationen finden Sie unter
Abschnitt 13.5.4.25, „SHOW WARNINGS
“.
SHOW GRANTS FOR user
Diese Anweisung listet die
GRANT
-Anweisung(en) auf, die abgesetzt
werden muss bzw. müssen, um die Berechtigungen zu kopieren,
die einem MySQL-Benutzerkonto zugewiesen sind. Das Konto wird
im selben Format wie bei der
GRANT
-Anweisung angegeben (z. B.
'jeffrey'@'localhost'
). Die Benutzer- und
Hostbestandteile des Kontonamens entsprechen den Werten der
Spalten User
und Host
des kontenspezifischen Datensatzes in der Tabelle
user
.
mysql> SHOW GRANTS FOR 'root'@'localhost';
+---------------------------------------------------------------------+
| Grants for root@localhost |
+---------------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION |
+---------------------------------------------------------------------+
Um die Berechtigungen des Kontos aufzulisten, über das Sie mit dem Server verbunden sind, können Sie eine der folgenden Anweisungen verwenden:
SHOW GRANTS; SHOW GRANTS FOR CURRENT_USER; SHOW GRANTS FOR CURRENT_USER();
SHOW GRANTS
zeigt nur die Berechtigungen
an, die dem genannten Konto explizit zugewiesen sind. Das
Konto kann also über weitere Berechtigungen verfügen, die
nicht aufgelistet sind. Ist beispielsweise ein anonymes Konto
vorhanden, dann kann das genannte Konto dessen Berechtigungen
unter Umständen nutzen; dies wird aber von SHOW
GRANTS
nicht angezeigt.
SHOW INDEX FROMtbl_name
[FROMdb_name
]
SHOW INDEX
gibt Informationen zum
Tabellenindex zurück. Das Format erinnert an das des Aufrufs
SQLStatistics
in ODBC.
SHOW INDEX
gibt die folgenden Felder
zurück:
Table
Der Name der Tabelle.
Non_unique
0, wenn der Index keine Dubletten enthalten darf, andernfalls 1.
Key_name
Der Name des Indexes.
Seq_in_index
Die Sequenznummer der Spalte im Index, beginnend bei 1.
Column_name
Der Spaltenname.
Gibt an, wie die Spalte im Index sortiert ist. In MySQL
können die Werte ‘A
’
(aufsteigend) oder NULL
(nicht
sortiert) auftreten.
Schätzung der Anzahl eindeutiger Werte im Index.
Aktualisiert wird der Wert durch Ausführung von
ANALYZE TABLE
oder myisamchk
-a. Cardinality
wird
basierend auf Statistiken gezählt, die als Integers
gespeichert werden, d. h., der Wert ist auch bei kleinen
Tabellen unter Umständen nicht exakt. Je höher die
Kardinalität, desto größer ist die Chance, dass MySQL
den Index bei der Durchführung von Joins verwendet.
Sub_part
Die Anzahl der indizierten Zeichen, wenn die Spalte nur
teilweise indiziert ist, oder NULL
,
wenn die gesamte Spalte indiziert ist.
Packed
Gibt an, wie der Schlüssel gepackt ist.
NULL
zeigt an, dass der Schlüssel
nicht gepackt ist.
Null
Enthält YES
, wenn die Spalte
NULL
sein kann. Andernfalls enthält
die Spalte NO
.
Index_type
Der verwendete Indextyp (BTREE
,
FULLTEXT
, HASH
,
RTREE
).
Comment
Verschiedene Anmerkungen.
Sie können
db_name
.tbl_name
als Alternative zur Syntax
verwenden. Die
folgenden beiden Anweisungen sind äquivalent:
tbl_name
FROM
db_name
SHOW INDEX FROM mytable FROM mydb; SHOW INDEX FROM mydb.mytable;
SHOW KEYS
ist ein Synonym für
SHOW INDEX
. Sie können die Indizes einer
Tabelle auch mit dem Befehl mysqlshow -k
db_name
tbl_name
auflisten.
SHOW INNODB STATUS
In MySQL 5.1 ist dies ein veraltetes Synonym für
SHOW ENGINE INNODB STATUS
. Siehe auch
Abschnitt 13.5.4.8, „SHOW ENGINE
“.
SHOW [BDB] LOGS
In MySQL 5.1 ist dies ein veraltetes Synonym für
SHOW ENGINE BDB LOGS
. Siehe auch
Abschnitt 13.5.4.8, „SHOW ENGINE
“.
SHOW OPEN TABLES [FROMdb_name
] [LIKE 'pattern
']
SHOW OPEN TABLES
listet die
nichttemporären Tabellen auf, die derzeit im Tabellen-Cache
geöffnet sind. Siehe auch Abschnitt 7.4.8, „Nachteile der Erzeugung großer Mengen von Tabellen in derselben
Datenbank“.
SHOW OPEN TABLES
gibt die folgenden Felder
zurück:
Database
Die Datenbank, die die Tabelle enthält.
Table
Der Tabellenname.
In_use
Häufigkeit, mit der die Tabelle zurzeit von Abfragen verwendet wird. Wenn der Wert null ist, dann ist die Tabelle geöffnet, wird aber derzeit nicht verwendet.
Name_locked
Gibt an, ob der Tabellenname gesperrt ist. Die Namenssperrung wird bei Operationen wie dem Löschen oder Umbenennen von Tabellen verwendet.
SHOW PLUGIN
SHOW PLUGIN
zeigt Informationen zu
bekannten Plug-Ins an.
mysql> SHOW PLUGIN;
+------------+--------+----------------+---------+
| Name | Status | Type | Library |
+------------+--------+----------------+---------+
| MEMORY | ACTIVE | STORAGE ENGINE | NULL |
| MyISAM | ACTIVE | STORAGE ENGINE | NULL |
| InnoDB | ACTIVE | STORAGE ENGINE | NULL |
| ARCHIVE | ACTIVE | STORAGE ENGINE | NULL |
| CSV | ACTIVE | STORAGE ENGINE | NULL |
| BLACKHOLE | ACTIVE | STORAGE ENGINE | NULL |
| FEDERATED | ACTIVE | STORAGE ENGINE | NULL |
| MRG_MYISAM | ACTIVE | STORAGE ENGINE | NULL |
+------------+--------+----------------+---------+
SHOW PLUGIN
wurde in MySQL 5.1.5
hinzugefügt.
SHOW PRIVILEGES
SHOW PRIVILEGES
zeigt eine Liste mit
Systemberechtigungen an, die der MySQL Server unterstützt.
Wie diese Liste genau aussieht, hängt von der Version Ihres
Servers ab.
mysql> SHOW PRIVILEGES\G
*************************** 1. row ***************************
Privilege: Alter
Context: Tables
Comment: To alter the table
*************************** 2. row ***************************
Privilege: Alter routine
Context: Functions,Procedures
Comment: To alter or drop stored functions/procedures
*************************** 3. row ***************************
Privilege: Create
Context: Databases,Tables,Indexes
Comment: To create new databases and tables
*************************** 4. row ***************************
Privilege: Create routine
Context: Functions,Procedures
Comment: To use CREATE FUNCTION/PROCEDURE
*************************** 5. row ***************************
Privilege: Create temporary tables
Context: Databases
Comment: To use CREATE TEMPORARY TABLE
...
SHOW {PROCEDURE | FUNCTION} STATUS [LIKE 'pattern
']
Diese Anweisung ist eine MySQL-Erweiterung. Sie gibt Eigenschaften von Routinen zurück, z. B. Datenbank, Name, Typ und Ersteller sowie Erstellungs- und Änderungsdatum. Wird kein Muster angegeben, dann werden abhängig von der verwendeten Anweisung Informationen zu allen gespeicherten Prozeduren oder allen gespeicherten Funktionen aufgelistet.
mysql> SHOW FUNCTION STATUS LIKE 'hello'\G
*************************** 1. row ***************************
Db: test
Name: hello
Type: FUNCTION
Definer: testuser@localhost
Modified: 2004-08-03 15:29:37
Created: 2004-08-03 15:29:37
Security_type: DEFINER
Comment:
Sie können Informationen zu gespeicherten Routinen auch der
Tabelle ROUTINES
in
INFORMATION_SCHEMA
entnehmen. Siehe auch
Abschnitt 22.14, „Die Tabelle INFORMATION_SCHEMA ROUTINES
“.
SHOW [FULL] PROCESSLIST
SHOW PROCESSLIST
zeigt Ihnen, welche
Threads gerade ausgeführt werden. Sie können diese
Information auch mit mysqladmin processlist
anzeigen. Wenn Sie die Berechtigung SUPER
haben, werden alle Threads angezeigt. Andernfalls werden nur
Ihre eigenen Threads (d. h. Threads, die mit dem
MySQL-Benutzerkonto verknüpft sind, das Sie verwenden)
angezeigt. Siehe auch Abschnitt 13.5.5.3, „KILL
“. Wenn Sie das
Schlüsselwort FULL
nicht angeben, werden
nur die ersten hundert Zeichen jeder Anweisung im Feld
Info
angezeigt.
Diese Anweisung ist recht praktisch, wenn Sie die
Fehlermeldung „Too many connections“ erhalten und
herausfinden wollen, was gerade passiert. MySQL reserviert
eine zusätzliche Verbindung für Konten, die die Berechtigung
SUPER
haben, damit gewährleistet ist, dass
Administratoren jederzeit Verbindungen herstellen können, um
das System zu überprüfen. (Dies setzt natürlich voraus,
dass Sie diese Berechtigung nicht allen Benutzern gewähren.)
Die Ausgabe von SHOW PROCESSLIST
kann etwa
so aussehen:
mysql> SHOW FULL PROCESSLIST\G *************************** 1. row *************************** Id: 1 User: system user Host: db: NULL Command: Connect Time: 1030455 State: Waiting for master to send event Info: NULL *************************** 2. row *************************** Id: 2 User: system user Host: db: NULL Command: Connect Time: 1004 State: Has read all relay log; waiting for the slave I/O thread to update it Info: NULL *************************** 3. row *************************** Id: 3112 User: replikator Host: artemis:2204 db: NULL Command: Binlog Dump Time: 2144 State: Has sent all binlog to slave; waiting for binlog to be updated Info: NULL *************************** 4. row *************************** Id: 3113 User: replikator Host: iconnect2:45781 db: NULL Command: Binlog Dump Time: 2086 State: Has sent all binlog to slave; waiting for binlog to be updated Info: NULL *************************** 5. row *************************** Id: 3123 User: stefan Host: localhost db: apollon Command: Query Time: 0 State: NULL Info: SHOW FULL PROCESSLIST 5 rows in set (0.00 sec)
Die Spalten haben die nachfolgend beschriebenen Bedeutungen:
Id
Der Verbindungsbezeichner.
User
Der MySQL-Benutzer, der die Anweisung abgesetzt hat. Die
Anzeige system user
bezeichnet einen
clientlosen Thread, den der Server erzeugt hat, um Tasks
intern zu verwalten. Es kann sich dabei um den I/O- oder
den SQL-Thread, der auf dem Replikationsserver verwendet
wird, oder einen Handler für verzögerte Datensätze
handeln. Für den system user
ist in
der Spalte Host
kein Host angegeben.
Host
Der Hostname des Clients, der die Anweisung absetzt
(außer bei system user
, wo kein Host
angegeben wird).
SHOW PROCESSLIST
meldet den Hostnamen
für TCP/IP-Verbindungen im Format
,
damit Sie schneller feststellen können, welcher Client
was tut.
host_name
:client_port
db
Die Standarddatenbank, sofern eine solche ausgewählt
wurde; andernfalls NULL
.
Command
Der Wert dieser Spalte entspricht den
COM_
-Befehlen
des Client/Server-Protokolls. Siehe auch
Abschnitt 5.2.4, „Server-Statusvariablen“.
xxx
Der Wert Command
kann einen der
folgenden Werte haben: Binlog Dump
,
Change user
, Close
stmt
, Connect
,
Connect Out
, Create
DB
, Debug
, Delayed
insert
, Drop DB
,
Error
, Execute
,
Fetch
, Field List
,
Init DB
, Kill
,
Long Data
, Ping
,
Prepare
,
Processlist
, Query
,
Quit
, Refresh
,
Register Slave
, Reset
stmt
, Set option
,
Shutdown
, Sleep
,
Statistics
, Table
Dump
, Time
Time
Die Zeit (in Sekunden), die seit dem Start der Anweisung oder des Befehls bis jetzt vergangen ist.
State
Eine Aktion, ein Ereignis oder ein Zustand. Folgende Werte
sind möglich: After create
,
Analyzing
, Changing
master
, Checking master
version
, Checking table
,
Connecting to master
, Copying
to group table
, Copying to tmp
table
, Creating delayed
handler
, Creating index
,
Creating sort index
, Creating
table from master dump
, Creating tmp
table
, Execution of
init_command
, FULLTEXT
initialization
, Finished reading one
binlog; switching to next binlog
,
Flushing tables
,
Killed
, Killing
slave
, Locked
,
Making temp file
, Opening
master dump table
, Opening
table
, Opening tables
,
Processing request
, Purging
old relay logs
, Queueing master event
to the relay log
, Reading event from
the relay log
, Reading from
net
, Reading master dump table
data
, Rebuilding the index on master
dump table
, Reconnecting after a failed
binlog dump request
, Reconnecting after
a failed master event read
, Registering
slave on master
, Removing
duplicates
, Reopen tables
,
Repair by sorting
, Repair
done
, Repair with keycache
,
Requesting binlog dump
,
Rolling back
, Saving
state
, Searching rows for
update
, Sending binlog event to
slave
, Sending data
,
Sorting for group
, Sorting for
order
, Sorting index
,
Sorting result
, System
lock
, Table lock
,
Thread initialized
,
Updating
, User lock
,
Waiting for INSERT
, Waiting
for master to send event
, Waiting for
master update
, Waiting for slave mutex
on exit
, Waiting for table
,
Waiting for tables
, Waiting
for the next event in relay log
,
Waiting on cond
, Waiting to
finalize termination
, Waiting to
reconnect after a failed binlog dump request
,
Waiting to reconnect after a failed master event
read
, Writing to net
,
allocating local table
,
cleaning up
, closing
tables
, converting HEAP to
MyISAM
, copy to tmp table
,
creating table
, deleting from
main table
, deleting from reference
tables
,
discard_or_import_tablespace
,
end
, freeing items
,
got handler lock
, got old
table
, info
,
init
, insert
,
logging slow query
,
login
, preparing
,
purging old relay logs
, query
end
, removing tmp table
,
rename
, rename result
table
, reschedule
,
setup
, starting
slave
, statistics
,
storing row into queue
,
update
, updating
,
updating main table
, updating
reference tables
, upgrading
lock
, waiting for delay_list
,
waiting for handler insert
,
waiting for handler lock
,
waiting for handler open
Die gängigsten State
-Werte werden im
Folgenden beschrieben. Die Mehrzahl der anderen
State
-Werte sind in erster Linie
praktisch, um Bugs im Server zu finden. Weitere
Informationen zu Prozesszuständen bei Replikationsservern
finden Sie in
Abschnitt 6.4, „Replikation: Implementationsdetails“.
Für die SHOW PROCESSLIST
-Anweisung ist
der State
-Wert NULL
.
Info
Die Anweisung, die der Thread ausführt, oder
NULL
, sofern er keine Anweisung
ausführt.
Einige State
-Werte finden Sie in der
Ausgabe von SHOW PROCESSLIST
recht häufig:
Checking table
Der Thread führt eine Tabellenprüfung durch.
Closing tables
Der Thread synchronisiert die geänderten Tabellendaten auf die Festplatte und schließt die verwendeten Tabellen. Dies sollte ein sehr schneller Vorgang sein. Andernfalls sollten Sie überprüfen, ob Ihre Festplatte nicht voll ist oder stark frequentiert wird.
Connect Out
Ein Replikationsslave stellt eine Verbindung zum Master her.
Copying to tmp table
Der Server kopiert Daten in eine Temporärtabelle im Speicher.
Copying to tmp table on disk
Der Server kopiert Daten in eine Temporärtabelle auf die
Festplatte. Die temporäre Ergebnismenge war größer als
tmp_table_size
, und der Thread stellt
die Temporärtabelle deswegen vom speicherresidenten in
das festplattenbasierte Format um, um Speicher zu sparen.
Creating tmp table
Der Thread erstellt eine Temporärtabelle, die einen Teil des Abfrageergebnisses aufnehmen soll.
deleting from main table
Der Server führt den ersten Teil eines Löschvorgangs über mehrere Tabellen aus. Der Löschvorgang erfolgt nur in der ersten Tabelle und speichert Felder und Offsets, die zum Löschen aus anderen (Referenz-)Tabellen benutzt werden.
deleting from reference tables
Der Server führt den zweiten Teil eines Löschvorgangs über mehrere Tabellen aus und löscht die entsprechenden Datensätze aus anderen Tabellen.
Flushing tables
Der Thread führt FLUSH TABLES
aus und
wartet, bis alle Threads ihre Tabellen geschlossen haben.
FULLTEXT initialization
Der Server bereitet die Ausführung einer natursprachlichen Volltextsuche vor.
Killed
Jemand hat eine KILL
-Anweisung an den
Thread abgesetzt. Der Thread wird abgebrochen, wenn beim
nächsten Mal das Terminierungs-Flag gesetzt wird. Dieses
Flag wird in jeder größeren Schleife in MySQL gesetzt.
Trotzdem kann es unter Umständen einen Moment dauern, bis
der Thread terminiert ist. Ist der Thread durch einen
anderen Thread gesperrt, dann erfolgt die Terminierung
erst, wenn der andere Thread die Sperre aufgehoben hat.
Locked
Die Abfrage wird durch eine andere Abfrage gesperrt.
Sending data
Der Thread verarbeitet Datensätze für eine
SELECT
-Anweisung und sendet zudem Daten
an den Client.
Sorting for group
Der Thread führt eine Sortierung infolge einer
GROUP BY
-Klausel durch.
Sorting for order
Der Thread führt eine Sortierung infolge einer
ORDER BY
-Klausel durch.
Opening tables
Der Thread versucht, eine Tabelle zu öffnen. Dies sollte
ein sehr schneller Vorgang sein, sofern das Öffnen nicht
durch irgendeinen Umstand verhindert wird. So kann
beispielsweise eine ALTER TABLE
- oder
eine LOCK TABLE
-Anweisung das Öffnen
einer Tabelle bis zum Abschluss der Anweisung unterbinden.
Reading from net
Der Server liest ein Paket aus dem Netzwerk.
Removing duplicates
Die Abfrage verwendete SELECT DISTINCT
so, dass MySQL die DISTINCT
-Operation
nicht zu einem frühen Zeitpunkt wegoptimieren konnte. Aus
diesem Grund erfordert MySQL eine zusätzliche Phase, um
alle duplizierten Datensätze zu entfernen, bevor das
Ergebnis an den Client gesendet wird.
Reopen table
Der Thread hat eine Sperre für die Tabelle erwirkt, danach aber festgestellt, dass die zugrunde liegende Tabellenstruktur sich geändert hat. Der Thread hat die Sperre dann aufgehoben und die Tabelle geschlossen und versucht nun, sie wieder zu öffnen.
Repair by sorting
Der Reparaturcode verwendet einen Sortiervorgang zur Erstellung der Indizes.
Repair with keycache
Der Reparaturcode erstellt einen Schlüssel nach dem
anderen über den Schlüssel-Cache. Dies ist wesentlich
langsamer als Repair by sorting
.
Searching rows for update
Der Thread durchläuft die erste Phase zur Suche nach
passenden Datensätzen, bevor er sie aktualisiert. Dies
muss getan werden, wenn UPDATE
den
Index ändert, der für die Suche nach den betreffenden
Datensätzen verwendet wird.
Sleeping
Der Thread wartet darauf, dass der Client eine neue Anweisung an ihn sendet.
statistics
Der Server berechnet Statistiken zur Entwicklung eines Abfrageausführungsplans.
Der Thread wartet darauf, eine externe Systemsperre für
die Tabelle zu erhalten. Wenn Sie nicht mehrere
mysqld-Server verwenden, die auf die
gleichen Tabellen zugreifen, können Sie Systemsperren mit
der Option --skip-external-locking
deaktivieren.
Upgrading lock
Der Handler INSERT DELAYED
versucht,
eine Sperre für die Tabelle zu erwirken, um Datensätze
einzufügen.
Updating
Der Thread sucht nach zu aktualisierenden Datensätzen und aktualisiert diese dann.
updating main table
Der Server führt den ersten Teil eines Änderungsvorgangs über mehrere Tabellen aus. Er führt Änderungen nur in der ersten Tabelle aus und speichert Felder und Offsets, die zur Aktualisierung anderer (Referenz-)Tabellen benutzt werden.
updating reference tables
Der Server führt den zweiten Teil eines Änderungsvorgangs über mehrere Tabellen aus und aktualisiert die entsprechenden Datensätze in den anderen Tabellen.
User Lock
Der Thread wartet auf ein GET_LOCK()
.
Waiting for tables
Der Thread hat eine Mitteilung erhalten, dass die einer Tabelle zugrunde liegende Struktur sich geändert hat und er die Tabelle neu öffnen muss, um die neue Struktur zu erhalten. Um die Tabelle allerdings neu öffnen zu können, muss er warten, bis alle anderen Threads die fragliche Tabelle geschlossen haben.
Diese Benachrichtigung erfolgt, wenn ein anderer Thread
FLUSH TABLES
oder eine der folgenden
Anweisungen für die betreffende Tabelle verwendet hat:
FLUSH TABLES
,
tbl_name
ALTER TABLE
, RENAME
TABLE
, REPAIR TABLE
,
ANALYZE TABLE
oder OPTIMIZE
TABLE
.
waiting for handler insert
Der INSERT DELAYED
-Handler hat alle
anhängigen Einfügeoperationen verarbeitet und wartet auf
neue.
Writing to net
Der Server schreibt ein Paket in das Netzwerk.
Die meisten Zustände entsprechen sehr schnellen Operationen. Wenn ein Thread für mehrere Sekunden in einem dieser Zustände verbleibt, dann weist dies auf ein Problem hin, das untersucht werden muss.
SHOW [GLOBAL | SESSION] STATUS [LIKE 'pattern
']
SHOW STATUS
zeigt Serverstatusinformationen
an. Diese Informationen können auch mit dem Befehl
mysqladmin extended-status ermittelt
werden.
Nachfolgend ist auszugsweise eine Ausgabe aufgelistet. Die Liste der Variablen und ihrer Werte kann auf Ihrem Server anders aussehen. Die Bedeutung der Variablen ist in Abschnitt 5.2.4, „Server-Statusvariablen“, beschrieben.
mysql> SHOW STATUS;
+--------------------------+------------+
| Variable_name | Value |
+--------------------------+------------+
| Aborted_clients | 0 |
| Aborted_connects | 0 |
| Bytes_received | 155372598 |
| Bytes_sent | 1176560426 |
| Connections | 30023 |
| Created_tmp_disk_tables | 0 |
| Created_tmp_tables | 8340 |
| Created_tmp_files | 60 |
...
| Open_tables | 1 |
| Open_files | 2 |
| Open_streams | 0 |
| Opened_tables | 44600 |
| Questions | 2026873 |
...
| Table_locks_immediate | 1920382 |
| Table_locks_waited | 0 |
| Threads_cached | 0 |
| Threads_created | 30022 |
| Threads_connected | 1 |
| Threads_running | 1 |
| Uptime | 80380 |
+--------------------------+------------+
Mit einer LIKE
-Klausel zeigt die Anweisung
nur die Variablen an, die dem Muster entsprechen:
mysql> SHOW STATUS LIKE 'Key%';
+--------------------+----------+
| Variable_name | Value |
+--------------------+----------+
| Key_blocks_used | 14955 |
| Key_read_requests | 96854827 |
| Key_reads | 162040 |
| Key_write_requests | 7589728 |
| Key_writes | 3813196 |
+--------------------+----------+
Wenn die Option GLOBAL
angegeben wird,
erhalten Sie die Statuswerte für alle Verbindungen zu MySQL.
Bei SESSION
erhalten Sie hingegen die
Statuswerte der aktuellen Verbindung. Geben Sie überhaupt
keine Option an, dann wird SESSION
als
Vorgabe verwendet. LOCAL
ist ein Synonym
für SESSION
.
Einige Statusvariablen haben nur einen globalen Wert. Bei
diesen erhalten Sie denselben Wert sowohl für
GLOBAL
als auch für
SESSION
.
SHOW TABLE STATUS [FROMdb_name
] [LIKE 'pattern
']
SHOW TABLE STATUS
funktioniert wie
SHOW TABLE
, vermittelt aber zahlreiche
Informationen zu den einzelnen Tabellen. Sie können diese
Liste auch mit mysqlshow --status
db_name
anzeigen.
Diese Anweisung erlaubt auch die Anzeige von Informationen zu Views.
SHOW TABLE STATUS
gibt die folgenden Felder
zurück:
Name
Den Namen der Tabelle.
Engine
Die Speicher-Engine der Tabelle. Siehe auch
Kapitel 14, Speicher-Engines und Tabellentypen. Vor MySQL 4.1.2 hieß
dieser Wert Type
.
Version
Die Versionsnummer der .frm
-Datei der
Tabelle.
Row_format
Das Format für die Datensatzspeicherung
(Fixed
, Dynamic
,
Compressed
,
Redundant
, Compact
).
Das Format von InnoDB
-Tabellen wird als
Redundant
oder
Compact
gemeldet.
Rows
Anzahl der Datensätze. Einige Speicher-Engines wie etwa
MyISAM
speichern die exakte Anzahl.
Bei anderen Engines wie InnoDB
hingegen
ist dies ein Schätzwert, der vom tatsächlichen Wert um
bis zu 40 oder 50 Prozent abweichen kann. In solchen
Fällen sollten Sie mit SELECT COUNT(*)
eine exakte Anzahl ermitteln.
Der Rows
-Wert ist
NULL
bei Tabellen in der Datenbank
INFORMATION_SCHEMA
.
Avg_row_length
Durchschnittliche Länge eines Datensatzes.
Data_length
Die Länge der Datendatei.
Max_data_length
Die maximale Länge der Datendatei. Dies ist die Gesamtzahl der Bytes, die in der Tabelle gespeichert werden können. Sie wird auf der Basis der verwendeten Zeigergröße berechnet.
Index_length
Die Länge der Indexdatei.
Data_free
Anzahl der reservierten, aber nicht verwendeten Bytes.
Auto_increment
Der nächste AUTO_INCREMENT
-Wert.
Create_time
Zeitpunkt der Tabellenerstellung.
Update_time
Zeitpunkt der letzten Aktualisierung der Datendatei.
Check_time
Zeitpunkt der letzten Tabellenüberprüfung. Nicht alle
Speicher-Engines aktualisieren diese Zeitangabe (in
solchen Fällen ist der Wert stets
NULL
).
Collation
Zeichensatz und Sortierung der Tabelle.
Checksum
Wert der mitlaufenden Prüfsumme (sofern vorhanden).
Create_options
Zusätzliche Optionen, die bei CREATE
TABLE
angegeben wurden.
Comment
Bei der Erstellung der Tabelle angegebener Kommentar (oder Angaben dazu, warum MySQL nicht auf die Tabellendaten zugreifen konnte).
Im Tabellenkommentar meldet InnoDB
den
freien Speicher des Tablespaces, zu dem die Tabelle gehört.
Bei einer Tabelle, die sich in einem gemeinsamen Tablespace
befindet, ist dies der freie Speicher des gemeinsamen
Tablespaces. Verwenden Sie mehrere Tablespaces und hat die
Tabelle einen eigenen Tablespace, dann bezieht sich die Angabe
des freien Speichers nur auf diese Tabelle.
Bei MEMORY
-Tabellen geben die Werte
Data_length
,
Max_data_length
und
Index_length
näherungsweise die
tatsächliche Menge des reservierten Speichers an. Der
Reservierungsalgorithmus reserviert in großem Umfang
Speicher, um die Anzahl der Reservierungsoperationen zu
verringern.
Bei NDB Cluster
-Tabellen zeigt die Ausgabe
dieser Anweisung annähernde Werte für die Spalten
Avg_row_length
und
Data_length
. Ausgenommen sind lediglich
BLOB
-Spalten, die nicht berücksichtigt
werden. Außerdem wird die Anzahl der Repliken in der
Comment
-Spalte (als
number_of_replicas
) angegeben.
Bei Views sind alle von SHOW TABLE STATUS
angezeigten Felder NULL
; lediglich
Name
zeigt den Namen des Views an, und
Comment
enthält view
.
SHOW [FULL] TABLES [FROMdb_name
] [LIKE 'pattern
']
SHOW TABLES
listet alle nichttemporären
Tabellen in einer gegebenen Datenbank auf. Sie können diese
Liste auch mit mysqlshow
db_name
anzeigen.
Die Anweisung listet außerdem alle Views in der Datenbank
auf. Der Modifizierer FULL
wird dahingehend
unterstützt, dass SHOW FULL TABLES
eine
zweite Ausgabespalte anzeigt. Werte der zweiten Spalte sind
BASE TABLE
bei einer Tabelle und
VIEW
bei einem View.
Hinweis: Wenn Sie keine
Berechtigungen für eine Tabelle haben, dann erscheint diese
nicht in der Ausgabe von SHOW TABLES
oder
mysqlshow db_name.
SHOW TRIGGERS [FROMdb_name
] [LIKEexpr
]
SHOW TRIGGERS
listet die derzeit auf dem
MySQL Server definierten Trigger auf. Diese Anweisung
erfordert die Berechtigung SUPER
.
Für den Trigger ins_sum
, wie er in
Abschnitt 20.3, „Verwendung von Triggern“, definiert ist, sieht die
Ausgabe der Anweisung wie folgt aus:
mysql> SHOW TRIGGERS LIKE 'acc%'\G
*************************** 1. row ***************************
Trigger: ins_sum
Event: INSERT
Table: account
Statement: SET @sum = @sum + NEW.amount
Timing: BEFORE
Created: NULL
sql_mode:
Definer: myname@localhost
Hinweis: Wenn Sie eine
LIKE
-Klausel mit SHOW
TRIGGERS
verwenden, wird der zu prüfende Ausdruck
expr
mit dem Namen der Tabelle
verglichen, für die der Trigger deklariert wurde, und nicht
mit dem Namen des Triggers:
mysql> SHOW TRIGGERS LIKE 'ins%';
Empty set (0.01 sec)
Es folgt eine kurze Erläuterung der Spalten in der Ausgabe der Anweisung:
Trigger
Der Name des Triggers.
Event
Das Ereignis, welches die Trigger-Aktivierung ausgelöst
hat: 'INSERT'
,
'UPDATE'
oder
'DELETE'
.
Table
Die Tabelle, für die der Trigger definiert ist.
Statement
Die bei Aktivierung des Triggers auszuführende Anweisung.
Diese entspricht dem Text in der Spalte
ACTION_STATEMENT
von
INFORMATION_SCHEMA.TRIGGERS
.
Timing
Einer der beiden Werte 'BEFORE'
oder
'AFTER'
.
Created
Der Wert dieser Spalte ist zurzeit immer
NULL
.
sql_mode
Der bei der Ausführung des Triggers gültige SQL-Modus.
Definer
Das Konto, welches den Trigger erstellt hat.
Siehe auch Abschnitt 22.16, „Die Tabelle INFORMATION_SCHEMA TRIGGERS
“.
SHOW [GLOBAL | SESSION] VARIABLES [LIKE 'pattern
']
SHOW VARIABLES
zeigt den Wert einiger
MySQL-Systemvariablen. Diese Informationen können auch mit
dem Befehl mysqladmin variables ermittelt
werden.
Mit der Option GLOBAL
erhalten Sie die
Werte, die für neue Verbindungen mit MySQL verwendet werden.
Mit SESSION
erhalten Sie hingegen die für
die aktuelle Verbindung gültigen Werte. Geben Sie überhaupt
keine Option an, dann wird SESSION
als
Vorgabe verwendet. LOCAL
ist ein Synonym
für SESSION
.
Sind die Standardwerte ungeeignet, dann können Sie die
meisten dieser Variablen beim Start von
mysqld mit Befehlsoptionen oder zur
Laufzeit mit der SET
-Anweisung einstellen.
Siehe auch Abschnitt 5.2.1, „Befehlsoptionen für mysqld“, und
Abschnitt 13.5.3, „SET
“.
Nachfolgend ist auszugsweise eine Ausgabe aufgelistet. Die Liste der Variablen und ihrer Werte kann auf Ihrem Server anders aussehen. Abschnitt 5.2.2, „Server-Systemvariablen“, beschreibt die Bedeutung der einzelnen Variablen. Informationen zu ihrer Optimierung finden Sie in Abschnitt 7.5.2, „Serverparameter feineinstellen“.
mysql> SHOW VARIABLES;
+---------------------------------+---------------------------+
| Variable_name | Value |
+---------------------------------+---------------------------+
| auto_increment_increment | 1 |
| auto_increment_offset | 1 |
| automatic_sp_privileges | ON |
| back_log | 50 |
| basedir | /home/jon/bin/mysql-5.1/ |
| binlog_cache_size | 32768 |
| bulk_insert_buffer_size | 8388608 |
| character_set_client | latin1 |
| character_set_connection | latin1 |
...
| max_user_connections | 0 |
| max_write_lock_count | 4294967295 |
| multi_range_count | 256 |
| myisam_data_pointer_size | 6 |
| myisam_max_sort_file_size | 2147483647 |
| myisam_recover_options | OFF |
| myisam_repair_threads | 1 |
| myisam_sort_buffer_size | 8388608 |
| ndb_autoincrement_prefetch_sz | 32 |
| ndb_cache_check_time | 0 |
| ndb_force_send | ON |
...
| time_zone | SYSTEM |
| timed_mutexes | OFF |
| tmp_table_size | 33554432 |
| tmpdir | |
| transaction_alloc_block_size | 8192 |
| transaction_prealloc_size | 4096 |
| tx_isolation | REPEATABLE-READ |
| updatable_views_with_limit | YES |
| version | 5.1.6-alpha-log |
| version_comment | Source distribution |
| version_compile_machine | i686 |
| version_compile_os | suse-linux |
| wait_timeout | 28800 |
+---------------------------------+---------------------------+
Mit einer LIKE
-Klausel zeigt die Anweisung
nur die Variablen an, die dem Muster entsprechen:
mysql> SHOW VARIABLES LIKE 'have%';
+-----------------------+----------+
| Variable_name | Value |
+-----------------------+----------+
| have_archive | YES |
| have_bdb | NO |
| have_blackhole_engine | YES |
| have_compress | YES |
| have_crypt | YES |
| have_csv | YES |
| have_example_engine | NO |
| have_federated_engine | NO |
| have_geometry | YES |
| have_innodb | YES |
| have_isam | NO |
| have_ndbcluster | DISABLED |
| have_openssl | NO |
| have_partitioning | YES |
| have_query_cache | YES |
| have_raid | NO |
| have_rtree_keys | YES |
| have_symlink | YES |
+-----------------------+----------+
SHOW WARNINGS [LIMIT [offset
,]row_count
] SHOW COUNT(*) WARNINGS
SHOW WARNINGS
zeigt die Fehler-, Warnungs-
und Hinweismeldungen, die durch die zuletzt abgesetzte
Anweisung ausgegeben wurden. Hat diese Anweisung keine
Meldungen erzeugt, so ist die Ausgabe leer. Die verwandte
Anweisung SHOW ERRORS
zeigt nur die Fehler
an. Siehe auch Abschnitt 13.5.4.10, „SHOW ERRORS
“.
Die Liste der Meldungen wird bei jeder neuen Anweisung, die eine Tabelle verwendet, zurückgesetzt.
Die SHOW COUNT(*) WARNINGS
-Anweisung zeigt
die Gesamtanzahl der Fehler, Warnungen und Hinweise an. Sie
können diese Anzahl auch der Variablen
warning_count
entnehmen:
SHOW COUNT(*) WARNINGS; SELECT @@warning_count;
Der Wert von warning_count
kann größer
sein als die Anzahl der von SHOW WARNINGS
angezeigten Meldungen. Dies liegt dann daran, dass die
Systemvariable max_error_count
so niedrig
angesetzt ist, dass nicht alle Meldungen gespeichert werden.
Ein weiter unten in diesem Anschnitt gezeigtes Beispiel
veranschaulicht, wie dies geschehen kann.
Die LIMIT
-Klausel hat dieselbe Syntax wie
bei der SELECT
-Anweisung. Siehe auch
Abschnitt 13.2.7, „SELECT
“.
Der MySQL Server sendet die Gesamtanzahl der Fehler, Warnungen
und Hinweise zurück, die aufgrund der letzten Anweisung
erzeugt wurden. Wenn Sie die C-API verwenden, lässt sich
dieser Wert durch einen Aufruf von
mysql_warning_count()
ermitteln. Siehe auch
Abschnitt 24.2.3.69, „mysql_warning_count()
“.
Warnungen werden für Anweisungen wie LOAD DATA
INFILE
und DML-Anweisungen wie
INSERT
, UPDATE
,
CREATE TABLE
und ALTER
TABLE
erzeugt.
Die folgende DROP TABLE
-Anweisung erzeugt
einen Hinweis:
mysql>DROP TABLE IF EXISTS no_such_table;
mysql>SHOW WARNINGS;
+-------+------+-------------------------------+ | Level | Code | Message | +-------+------+-------------------------------+ | Note | 1051 | Unknown table 'no_such_table' | +-------+------+-------------------------------+
Es folgt ein einfaches Beispiel, das eine Syntaxwarnung für
CREATE TABLE
und Konvertierungswarnungen
für INSERT
enthält:
mysql>CREATE TABLE t1 (a TINYINT NOT NULL, b CHAR(4)) TYPE=MyISAM;
Query OK, 0 rows affected, 1 warning (0.00 sec) mysql>SHOW WARNINGS\G
*************************** 1. row *************************** Level: Warning Code: 1287 Message: 'TYPE=storage_engine' is deprecated, use 'ENGINE=storage_engine' instead 1 row in set (0.00 sec) mysql>INSERT INTO t1 VALUES(10,'mysql'),(NULL,'test'),
->(300,'Open Source');
Query OK, 3 rows affected, 4 warnings (0.01 sec) Records: 3 Duplicates: 0 Warnings: 4 mysql>SHOW WARNINGS\G
*************************** 1. row *************************** Level: Warning Code: 1265 Message: Data truncated for column 'b' at row 1 *************************** 2. row *************************** Level: Warning Code: 1263 Message: Data truncated, NULL supplied to NOT NULL column 'a' at row 2 *************************** 3. row *************************** Level: Warning Code: 1264 Message: Data truncated, out of range for column 'a' at row 3 *************************** 4. row *************************** Level: Warning Code: 1265 Message: Data truncated for column 'b' at row 3 4 rows in set (0.00 sec)
Die maximale Anzahl zu speichernder Fehler-, Warn- und
Hinweismeldungen wird von der Systemvariablen
max_error_count
gesteuert. Der Standardwert
ist 64. Um die Anzahl der Meldungen, die Sie speichern wollen,
zu ändern, modifizieren Sie den Wert von
max_error_count
. Im folgenden Beispiel
erzeugt die ALTER TABLE
-Anweisung drei
Warnmeldungen, von denen aber nur eine gespeichert wird, weil
max_error_count
zuvor auf 1 gesetzt worden
war:
mysql>SHOW VARIABLES LIKE 'max_error_count';
+-----------------+-------+ | Variable_name | Value | +-----------------+-------+ | max_error_count | 64 | +-----------------+-------+ 1 row in set (0.00 sec) mysql>SET max_error_count=1;
Query OK, 0 rows affected (0.00 sec) mysql>ALTER TABLE t1 MODIFY b CHAR;
Query OK, 3 rows affected, 3 warnings (0.00 sec) Records: 3 Duplicates: 0 Warnings: 3 mysql>SELECT @@warning_count;
+-----------------+ | @@warning_count | +-----------------+ | 3 | +-----------------+ 1 row in set (0.01 sec) mysql>SHOW WARNINGS;
+---------+------+----------------------------------------+ | Level | Code | Message | +---------+------+----------------------------------------+ | Warning | 1263 | Data truncated for column 'b' at row 1 | +---------+------+----------------------------------------+ 1 row in set (0.00 sec)
Um Warnungen zu deaktivieren, setzen Sie
max_error_count
auf 0. In diesem Fall zeigt
warning_count
zwar noch an, wie viele
Warnungen aufgetreten sind, aber keine dieser Meldungen wird
gespeichert.
Sie können die Sitzungsvariable SQL_NOTES
auf 0 setzen, damit Warnungen auf der
Note
-Ebene nicht aufgezeichnet werden.
CACHE INDEXtbl_index_list
[,tbl_index_list
] ... INkey_cache_name
tbl_index_list
:tbl_name
[[INDEX|KEY] (index_name
[,index_name
] ...)]
Die Anweisung CACHE INDEX
weist
Tabellenindizes einem bestimmten Schlüssel-Cache zu. Sie wird
nur bei MyISAM
-Tabellen eingesetzt.
Die folgende Anweisung weist Indizes der Tabellen
t1
, t2
und
t3
dem Schlüssel-Cache namens
hot_cache
zu:
mysql> CACHE INDEX t1, t2, t3 IN hot_cache;
+---------+--------------------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+---------+--------------------+----------+----------+
| test.t1 | assign_to_keycache | status | OK |
| test.t2 | assign_to_keycache | status | OK |
| test.t3 | assign_to_keycache | status | OK |
+---------+--------------------+----------+----------+
Die Syntax von CACHE INDEX
gestattet Ihnen,
anzugeben, dass nur bestimmte Indizes aus einer Tabelle dem
Cache zuzuweisen sind. Die aktuelle Implementierung weist alle
Indizes der Tabelle dem Cache zu, weswegen es keinen Grund
gibt, einen anderen Parameter als den Tabellennamen zu
übergeben.
Der in der CACHE INDEX
-Anweisung
referenzierte Schlüssel-Cache kann erstellt werden, indem
seine Größe mit einer Anweisung zur Parametereinstellung
oder in den Parametereinstellungen des Servers angegeben wird.
Zum Beispiel:
mysql> SET GLOBAL keycache1.key_buffer_size=128*1024;
Parameter eines Schlüssel-Caches lassen sich als Mitglieder einer strukturierten Systemvariablen einstellen. Siehe auch Abschnitt 5.2.3.1, „Strukturierte Systemvariablen“.
Ein Schlüssel-Cache muss bereits vorhanden sein, bevor Sie ihm Indizes zuweisen:
mysql> CACHE INDEX t1 IN non_existent_cache;
ERROR 1284 (HY000): Unknown key cache 'non_existent_cache'
Standardmäßig werden Tabellenindizes dem (vorgabeseitigen) Hauptschlüssel-Cache zugewiesen, der beim Serverstart erstellt wird. Wird ein Schlüssel-Cache zerstört, dann werden alle ihm zugewiesenen Indizes wieder dem Standardschlüssel-Cache zugewiesen.
Die Indexzuweisung wirkt sich global auf den Server aus: Wenn ein Client einem gegebenen Cache einen Index zuweist, wird der Cache für alle Abfragen verwendet, die diesen Index einbeziehen – unabhängig davon, welcher Client die Abfragen absetzt.
FLUSH [LOCAL | NO_WRITE_TO_BINLOG]flush_option
[,flush_option
] ...
Die FLUSH
-Anweisung leert verschiedene
interne Caches, die von MySQL verwendet werden, bzw. lädt
diese neu. Für die Ausführung von FLUSH
benötigen Sie die Berechtigung RELOAD
.
Die Anweisung RESET
ähnelt
FLUSH
. Siehe auch Abschnitt 13.5.5.5, „RESET
“.
flush_option
kann die folgenden
Werte annehmen:
HOSTS
Leert die Cache-Tabellen auf dem Host. Sie sollten die
Hosttabellen leeren, wenn einer Ihrer Hosts die IP-Nummer
wechselt oder Sie die Fehlermeldung Host
'
erhalten. Wenn aufeinander folgend mehr
als host_name
' is
blockedmax_connect_errors
Fehler für
einen gegebenen Host auftreten, während dieser eine
Verbindung mit dem MySQL Server herstellt, dann geht MySQL
davon aus, dass etwas nicht stimmt, und sperrt weitere
Verbindungsanfragen dieses Hosts. Das Synchronisieren der
Hosttabellen gestattet dem Host einen neuen Versuch der
Verbindungsherstellung. Siehe auch
Abschnitt A.2.5, „Host '...' is blocked
-Fehler“.
Sie können mysqld mit
--max_connect_errors=999999999
starten,
um diese Fehlermeldung zu verhindern.
DES_KEY_FILE
Lädt die DES-Schlüssel aus der mit der Option
--des-key-file
beim Serverstart
angegebenen Datei neu.
LOGS
Schließt alle Logdateien und öffnet sie neu. Wenn das
binäre Loggen aktiviert ist, wird die Sequenznummer der
Binärlogdatei relativ zur vorherigen Datei um den Wert 1
erhöht. Unter Unix ist dies das Gleiche wie das Senden
eines SIGHUP
-Signals an den
mysqld-Server. (Ausnahme sind einige
Versionen von Mac OS X 10.3, wo mysqld
SIGHUP
und SIGQUIT
ignoriert.)
Wenn der Server mit der Option
--log-error
gestartet wurde, bewirkt
FLUSH LOGS
, dass das Fehlerlog mit dem
Suffix -old
umbenannt wird und
mysqld eine neue leere Logdatei
erstellt. Wenn die Option --log-error
nicht angegeben wird, erfolgt keine Umbenennung.
PRIVILEGES
Lädt die Berechtigungen aus der Gesamtstruktur in der
mysql
-Datenbank neu.
QUERY CACHE
Defragmentiert den Abfrage-Cache, um seinen Speicher
besser zu nutzen. FLUSH QUERY CACHE
entfernt anders als RESET QUERY CACHE
keine Abfragen aus dem Cache.
STATUS
Setzt die meisten Statusvariablen auf null. Dies ist etwas, das Sie nur beim Debuggen einer Abfrage tun sollten. Siehe auch Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“.
{TABLE | TABLES}
[
tbl_name
[,
tbl_name
] ...]
Wenn keine Tabellen benannt sind, werden alle Tabellen
geschlossen. Das Schließen aller gerade verwendeten
Tabellen wird ebenfalls erzwungen. Ferner wird der
Schlüssel-Cache synchronisiert. Werden ein oder mehrere
Tabellennamen angegeben, dann werden nur die angegebenen
Tabellen synchronisiert. FLUSH TABLES
entfernt ebenso wie RESET QUERY CACHE
zudem alle Abfrageergebnisse aus dem Abfrage-Cache.
TABLES WITH READ LOCK
Schließt alle offenen Tabellen und versieht alle Tabellen
für alle Datenbanken mit einer Lesesperre, bis Sie
UNLOCK TABLES
ausführen. Dies ist eine
recht praktische Möglichkeit der Datensicherung, wenn Sie
ein Dateisystem wie Veritas einsetzen, das rechtzeitig
Schnappschüsse erstellt.
USER_RESOURCES
Setzt alle Benutzerbeschränkungen auf Stundenbasis auf
null. Hierdurch können Clients, bei denen der Grenzwert
für Verbindungen, Abfragen oder Änderungen pro Stunde
erreicht wurde, ihre Aktivitäten direkt wiederaufnehmen.
FLUSH USER_RESOURCES
wirkt sich
allerdings nicht auf die Begrenzung gleichzeitiger
Verbindungen aus. Siehe auch Abschnitt 13.5.1.3, „GRANT
und REVOKE
“.
FLUSH
-Anweisungen werden in das Binärlog
geschrieben, sofern das optionale Schlüsselwort
NO_WRITE_TO_BINLOG
(oder sein Alias
LOCAL
) nicht verwendet wird. Dies wird
gemacht, damit FLUSH
-Anweisungen, die auf
einem MySQL Server verwendet werden, der als
Replikationsmaster agiert, standardmäßig auf den
Replikationsslave repliziert werden.
Hinweis: FLUSH
LOGS
, FLUSH MASTER
,
FLUSH SLAVE
und FLUSH TABLES WITH
READ LOCK
werden keinesfalls geloggt, weil dies bei
der Replikation auf einen Slave Probleme verursachen würde.
Sie können auf einige dieser Anweisungen auch mit dem
Hilfsprogramm mysqladmin zugreifen, indem
Sie die Befehle flush-hosts
,
flush-logs
,
flush-privileges
,
flush-status
oder
flush-tables
verwenden.
Hinweis: Es ist in MySQL
5.1 nicht möglich,
FLUSH
-Anweisungen in gespeicherten
Funktionen oder Triggern abzusetzen. Allerdings können Sie
FLUSH
in gespeicherten Prozeduren benutzen,
solange diese nicht aus gespeicherten Funktionen heraus oder
von Triggern aufgerufen werden. Siehe auch
Abschnitt I.1, „Beschränkungen bei gespeicherten Routinen und Triggern“.
Informationen dazu, wie die RESET
-Anweisung
bei der Replikation verwendet wird, finden Sie in
Abschnitt 13.5.5.5, „RESET
“.
KILL [CONNECTION | QUERY] thread_id
Jede Verbindung mit mysqld wird in einem
separaten Thread ausgeführt. Mit der Anweisung SHOW
PROCESSLIST
können Sie die gerade ausgeführten
Threads auflisten. Die Terminierung eines Threads ist mit der
Anweisung KILL
möglich.
thread_id
KILL
unterstützt die optionalen
Modifizierer CONNECTION
oder
QUERY
:
KILL CONNECTION
entspricht
KILL
ohne Modifizierer: Es terminiert
die Verbindung zur angegebenen Kennung
thread_id
.
KILL QUERY
terminiert die über die
Verbindung aktuell ausgeführte Anweisung, lässt die
Verbindung selbst aber bestehen.
Wenn Sie die Berechtigung PROCESS
haben,
werden alle Threads angezeigt. Wenn Sie die Berechtigung
SUPER
haben, können Sie alle Threads und
Anweisungen terminieren. Andernfalls werden nur Ihre eigenen
Threads und Anweisungen angezeigt und zur Terminierung
freigegeben.
Zur Überprüfung und Terminierung von Threads können Sie auch die Befehle mysqladmin processlist und mysqladmin kill verwenden.
Hinweis: Sie können
KILL
nicht mit der Embedded MySQL
Server-Bibliothek verwenden, da der eingebettete Server nur in
den Threads der Hostanwendung ausgeführt wird – er selbst
erstellt also keine Verbindungs-Threads.
Wenn Sie KILL
verwenden, wird ein
Thread-spezifisches Terminierungs-Flag für den Thread
gesetzt. In den meisten Fällen kann es etwas dauern, bis die
Terminierung des Threads abgeschlossen ist, weil das Flag nur
in bestimmten Abständen überprüft wird:
Bei SELECT
-, ORDER
BY
- und GROUP BY
-Schleifen
wird das Flag nach dem Lesen eines Datensatzblocks
überprüft. Ist das Terminierungs-Flag gesetzt, dann wird
die Anweisung abgebrochen.
Bei ALTER TABLE
wird das
Terminierungs-Flag vor jedem Lesen eines Datensatzblocks
aus der Ursprungstabelle geprüft. Wurde das Flag gesetzt,
dann wird die Anweisung abgebrochen und die
Temporärtabelle gelöscht.
Bei UPDATE
- oder
DELETE
-Operationen wird das Flag nach
jedem gelesenen Block und nach jedem geänderten oder
gelöschten Datensatz überprüft. Ist das
Terminierungs-Flag gesetzt, dann wird die Anweisung
abgebrochen. Beachten Sie, dass, wenn Sie keine
Transaktionen verwenden, bereits erfolgte Änderungen
nicht rückgängig gemacht werden.
GET_LOCK()
führt einen Abbruch aus und
gibt NULL
zurück.
Ein INSERT DELAYED
-Thread
synchronisiert schnell alle Datensätze in seinem Speicher
(d. h., er schreibt sie) und wird dann terminiert.
Wenn der Thread sich im Tabellensperr-Handler befindet
(Zustand Locked
), dann wird die
Tabellensperre umgehend aufgehoben.
Wartet der Thread bei einem Schreibaufruf auf freien Festplattenspeicher, dann wird die Schreiboperation mit der Fehlermeldung „Disk Full“ abgebrochen.
Warnung: Die Terminierung
einer REPAIR TABLE
- oder
OPTIMIZE TABLE
-Operation führt bei
einer MyISAM
-Tabelle zu
Beschädigungen, die die Tabelle unbrauchbar machen. Lese-
oder Schreiboperationen in eine solche Tabelle schlagen
fehl, bis Sie sie – ohne Unterbrechung – wieder
optimieren oder reparieren.
LOAD INDEX INTO CACHEtbl_index_list
[,tbl_index_list
] ...tbl_index_list
:tbl_name
[[INDEX|KEY] (index_name
[,index_name
] ...)] [IGNORE LEAVES]
Die Anweisung LOAD INDEX INTO CACHE
lädt
einen Tabellenindex vorab in den Schlüssel-Cache, dem er
durch eine explizite CACHE INDEX
-Anweisung
zugewiesen wurde, oder aber in den vorgabeseitigen
Schlüssel-Cache. LOAD INDEX INTO CACHE
wird nur bei MyISAM
-Tabellen verwendet.
Der Modifizierer IGNORE LEAVES
bewirkt,
dass nur Blöcke für Indexknoten, die nicht Endknoten
(Blätter) sind, geladen werden.
Die folgende Anweisung lädt Knoten (Indexblöcke) mit Indizes
der Tabellen t1
und t2
:
mysql> LOAD INDEX INTO CACHE t1, t2 IGNORE LEAVES;
+---------+--------------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+---------+--------------+----------+----------+
| test.t1 | preload_keys | status | OK |
| test.t2 | preload_keys | status | OK |
+---------+--------------+----------+----------+
Die Anweisung lädt alle Indexblöcke aus
t1
. Bei t2
werden nur
Blöcke für Nichtendknoten geladen.
Die Syntax von LOAD INDEX INTO CACHE
gestattet Ihnen, anzugeben, dass nur bestimmte Indizes aus
einer Tabelle geladen werden sollen. Die aktuelle
Implementierung lädt alle Indizes der Tabelle in den Cache,
weswegen es keinen Grund gibt, einen anderen Parameter als den
Tabellennamen zu übergeben.
RESETreset_option
[,reset_option
] ...
Die RESET
-Anweisung wird benutzt, um den
Status verschiedener Serveroperationen zu löschen. Sie
benötigen die Berechtigung RELOAD
, um
RESET
ausführen zu können.
RESET
agiert als stärkere Version der
FLUSH
-Anweisung. Siehe auch
Abschnitt 13.5.5.2, „FLUSH
“.
reset_option
kann die folgenden
Werte annehmen:
MASTER
Löscht alle in der Indexdatei aufgeführten Binärlogs,
leert den Binärlogindex und setzt ihn zurück und
erstellt eine neue Binärlogdatei. (Ist als FLUSH
MASTER
in MySQL-Versionen vor 3.23.26 bekannt.)
Siehe auch Abschnitt 13.6.1, „SQL-Anweisungen für die Steuerung von Master-Servern“.
QUERY CACHE
Entfernt alle Abfrageergebnisse aus dem Abfrage-Cache.
SLAVE
Löscht auf dem Slave die Angabe zur Replikationsposition
in den Binärlogs des Masters (d. h., der Slave
„vergisst“ die Position). Setzt außerdem das
Relay-Log zurück, indem alle vorhandenen Relay-Logdateien
gelöscht werden und eine neue Logdatei begonnen wird.
(Ist als FLUSH SLAVE
in MySQL-Versionen
vor 3.23.26 bekannt.) Siehe auch
Abschnitt 13.6.2, „SQL-Anweisungen für die Steuerung von Slave-Servern“.
Dieser Abschnitt beschreibt SQL-Anweisungen, die im Zusammenhang mit der Replikation von Bedeutung sind. Eine Gruppe von Anweisungen wird zur Steuerung der Master-Server verwendet, die andere zur Steuerung der Slave-Server.
Die Replikation kann über die SQL-Schnittstelle gesteuert werden. Dieser Bereich beschreibt die Anweisungen zur Verwaltung der Replikationsmaster-Server. Abschnitt 13.6.2, „SQL-Anweisungen für die Steuerung von Slave-Servern“, beschreibt Anweisungen zur Verwaltung der Slave-Server.
PURGE {MASTER | BINARY} LOGS TO 'log_name
' PURGE {MASTER | BINARY} LOGS BEFORE 'date
'
Löscht alle Binärlogs, die im Logindex vor dem angegebenen Log oder Datum aufgelistet sind. Die Logs werden auch von der Liste entfernt, die in der Logindexdatei aufgezeichnet ist, d. h., das übergebene Log wird zum ersten Log auf der Liste.
Beispiel:
PURGE MASTER LOGS TO 'mysql-bin.010'; PURGE MASTER LOGS BEFORE '2003-04-02 22:46:26';
Das Argument date
der Variante
BEFORE
kann im Format 'YYYY-MM-DD
hh:mm:ss'
angegeben werden.
MASTER
und BINARY
sind
Synonyme.
Diese Anweisung kann auch bei laufender Slave-Replikation sicher ausgeführt werden. Sie müssen die Replikation also nicht anhalten. Wenn ein aktiver Slave gerade eines der Logs ausliest, das Sie löschen wollen, dann hat die Anweisung keine Auswirkungen, sondern schlägt mit einem Fehler fehl. Wenn allerdings ein Slave schläft und Sie eines der Logs löschen, die dieser Slave noch lesen muss, dann wird er nach dem Erwachen nicht mehr zur Replikation in der Lage sein.
Um Logs sicher zu löschen, gehen Sie wie folgt vor:
Sie setzen auf allen Slave-Servern SHOW SLAVE
STATUS
ab, um zu prüfen, welches Log gerade
gelesen wird.
Sie zeigen mit SHOW MASTER LOGS
eine
Liste der Logdateien auf dem Master-Server an.
Ermitteln Sie das zeitlich früheste Log unter allen Slaves. Dies ist das Ziellog. Wenn alle Slaves aktuell sind, muss es das letzte Log auf der Liste sein.
Erstellen Sie eine Kopie aller Logs, die Sie zu löschen beabsichtigen. (Dieser Schritt ist optional, aber stets empfehlenswert.)
Löschen Sie alle Logs bis zum Ziellog (aber nicht das Ziellog selbst).
RESET MASTER
Löscht alle in der Indexdatei aufgeführten Binärlogs, leert den Binärlogindex und setzt ihn zurück und erstellt eine neue Binärlogdatei.
SET SQL_LOG_BIN = {0|1}
Aktiviert oder deaktiviert das binäre Loggen für die
aktuelle Verbindung (SQL_LOG_BIN
ist eine
Sitzungsvariable), sofern der Client die Berechtigung
SUPER
hat. Die Anweisung wird mit einem
Fehler abgewiesen, wenn der Client die Berechtigung nicht hat.
SHOW BINLOG EVENTS [IN 'log_name
'] [FROMpos
] [LIMIT [offset
,]row_count
]
Zeigt die Ereignisse im Binärlog an. Wenn Sie
'
nicht
angeben, wird das erste Binärlog angezeigt.
log_name
'
Die LIMIT
-Klausel hat dieselbe Syntax wie
bei der SELECT
-Anweisung. Siehe auch
Abschnitt 13.2.7, „SELECT
“.
Hinweis: Das Absetzen einer
SHOW BINLOG EVENTS
-Anweisung ohne
LIMIT
-Klausel kann einen sehr zeit- und
ressourcenaufwändigen Prozess starten, weil der Server den
vollständigen Inhalt des Binärlogs an den Client zurückgibt
(dieses Log enthält alle datenändernden Anweisungen, die vom
Server ausgeführt wurden). Als Alternative zu SHOW
BINLOG EVENTS
können Sie das Hilfsprogramm
mysqlbinlog verwenden. Sie können damit
das Binärlog in eine Textdatei speichern und später
untersuchen. Siehe auch Abschnitt 8.8, „mysqlbinlog — Hilfsprogramm für die Verarbeitung binärer Logdateien“.
SHOW MASTER LOGS SHOW BINARY LOGS
Listet die Binärlogdateien auf dem Server auf. Diese
Anweisung wird im Zuge eines Vorgangs benutzt, der in
Abschnitt 13.6.1.1, „PURGE MASTER LOGS
“, beschrieben ist. Dort
wird gezeigt, wie man ermittelt, welche Logdateien gelöscht
werden können.
mysql> SHOW BINARY LOGS;
+---------------+-----------+
| Log_name | File_size |
+---------------+-----------+
| binlog.000015 | 724935 |
| binlog.000016 | 733481 |
+---------------+-----------+
SHOW BINARY LOGS
ist äquivalent mit
SHOW MASTER LOGS
.
SHOW MASTER STATUS
Vermittelt Statusinformationen zu den Binärlogdateien des Masters. Beispiel:
mysql > SHOW MASTER STATUS;
+---------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+---------------+----------+--------------+------------------+
| mysql-bin.003 | 73 | test | manual,mysql |
+---------------+----------+--------------+------------------+
Die Replikation kann über die SQL-Schnittstelle gesteuert werden. Dieser Abschnitt beschreibt die Anweisungen zur Verwaltung der Replikationsslave-Server. Abschnitt 13.6.1, „SQL-Anweisungen für die Steuerung von Master-Servern“, beschreibt Anweisungen zur Verwaltung der Master-Server.
CHANGE MASTER TOmaster_def
[,master_def
] ...master_def
: MASTER_HOST = 'host_name
' | MASTER_USER = 'user_name
' | MASTER_PASSWORD = 'password
' | MASTER_PORT =port_num
| MASTER_CONNECT_RETRY =count
| MASTER_LOG_FILE = 'master_log_name
' | MASTER_LOG_POS =master_log_pos
| RELAY_LOG_FILE = 'relay_log_name
' | RELAY_LOG_POS =relay_log_pos
| MASTER_SSL = {0|1} | MASTER_SSL_CA = 'ca_file_name
' | MASTER_SSL_CAPATH = 'ca_directory_name
' | MASTER_SSL_CERT = 'cert_file_name
' | MASTER_SSL_KEY = 'key_file_name
' | MASTER_SSL_CIPHER = 'cipher_list
'
CHANGE MASTER TO
ändert die Parameter, die
der Slave-Server zur Verbindungsherstellung und Kommunikation
mit dem Master-Server verwendet. Die Anweisung aktualisiert
auch den Inhalt der Dateien master.info
und relay-log.info
.
MASTER_USER
,
MASTER_PASSWORD
,
MASTER_SSL
,
MASTER_SSL_CA
,
MASTER_SSL_CAPATH
,
MASTER_SSL_CERT
,
MASTER_SSL_KEY
und
MASTER_SSL_CIPHER
vermitteln dem Slave
Informationen dazu, wie er Verbindungen mit dem Master
herstellen kann.
Die SSL-Optionen (MASTER_SSL
,
MASTER_SSL_CA
,
MASTER_SSL_CAPATH
,
MASTER_SSL_CERT
,
MASTER_SSL_KEY
und
MASTER_SSL_CIPHER
) können auch auf Slaves
geändert werden, die ohne SSL-Unterstützung kompiliert
wurden. Sie werden in der Datei
master.info
gespeichert, aber ignoriert,
bis Sie einen Server verwenden, auf dem die SSL-Unterstützung
aktiviert ist.
Wenn Sie einen der Parameter nicht angeben, dann behält er in der Regel seinen alten Wert (Ausnahmen entnehmen Sie der nachfolgenden Erläuterung). Wenn sich beispielsweise das Passwort, mit dem die Verbindung zu Ihrem MySQL-Master hergestellt wird, geändert hat, müssen Sie nur die folgenden Anweisungen absetzen, um dem Slave das neue Passwort mitzuteilen:
STOP SLAVE; -- if replication was running CHANGE MASTER TO MASTER_PASSWORD='new3cret'; START SLAVE; -- if you want to restart replication
Es ist nicht notwendig, Parameter anzugeben, die sich nicht ändern (Host, Port, Benutzer usw.).
MASTER_HOST
und
MASTER_PORT
sind der Hostname (oder die
IP-Adresse) des Master-Hosts bzw. sein TCP/IP-Port. Beachten
Sie, dass, wenn MASTER_HOST
gleich
localhost
ist, die Portnummer – wie unter
MySQL bei anderen Gelegenheiten auch – unter Umständen
ignoriert werden kann (dies ist etwa der Fall, wenn
Unix-Socketdateien benutzt werden).
Geben Sie MASTER_HOST
oder
MASTER_PORT
an, dann setzt der Slave
voraus, dass der Master-Server sich vom vorherigen
unterscheidet (und zwar auch dann, wenn Sie einen Host- oder
Portwert angeben, der mit dem aktuellen Wert identisch ist).
In diesem Fall werden die alten Namens- und Positionswerte der
Binärlogdatei auf dem Master-Server als nun ungültig
betrachtet, d. h., wenn Sie
MASTER_LOG_FILE
und
MASTER_LOG_POS
in der Anweisung nicht
angeben, werden stillschweigend
MASTER_LOG_FILE=''
und
MASTER_LOG_POS=4
angehängt.
MASTER_LOG_FILE
und
MASTER_LOG_POS
sind die Koordinaten, bei
denen der Slave-I/O-Thread mit dem Lesen vom Master beginnen
soll, wenn der Thread beim nächsten Mal startet. Wenn Sie
einen dieser Werte angeben, dürfen Sie
RELAY_LOG_FILE
oder
RELAY_LOG_POS
nicht angeben. Wenn weder
MASTER_LOG_FILE
noch
MASTER_LOG_POS
angegeben werden, verwendet
der Slave die letzten Koordinaten des
Slave-SQL-Threads, bevor CHANGE
MASTER
abgesetzt wurde. Hierdurch ist
gewährleistet, dass es bei der Replikation auch dann nicht zu
Unstetigkeiten kommt, wenn der Slave-SQL-Thread sehr spät mit
dem Slave-I/O-Thread verglichen wurde – etwa dann, wenn Sie
beispielsweise nur das zu verwendende Passwort ändern wollen.
CHANGE MASTER
löscht alle
Relay-Logdateien und beginnt eine neue
Relay-Logdatei, sofern Sie nicht
RELAY_LOG_FILE
oder
RELAY_LOG_POS
angeben. In diesem Fall
werden die Relay-Logs behalten, und die globale Variable
relay_log_purge
wird stillschweigend auf 0
gesetzt.
CHANGE MASTER
ist praktisch, wenn es darum
geht, einen Slave zu konfigurieren, und Sie hierfür die
Momentaufnahme des Masters benötigen und Logdatei und Offset
entsprechend aufgezeichnet haben. Nachdem Sie die
Momentaufnahme in den Slave geladen haben, können Sie
CHANGE MASTER TO
MASTER_LOG_FILE='
auf dem Slave ausführen.
log_name_on_master
',
MASTER_LOG_POS=log_offset_on_master
Das folgende Beispiel ändert die Koordinaten des Masters und dessen Binärlogdatei. Dies tut man, wenn man den Slave so konfiguriert, dass er den Master repliziert:
CHANGE MASTER TO MASTER_HOST='master2.mycompany.com', MASTER_USER='replication', MASTER_PASSWORD='bigs3cret', MASTER_PORT=3306, MASTER_LOG_FILE='master2-bin.001', MASTER_LOG_POS=4, MASTER_CONNECT_RETRY=10;
Das nächste Beispiel zeigt eine Operation, die weniger
häufig benötigt wird. Sie wird verwendet, wenn auf dem Slave
Relay-Logs vorhanden sind, die Sie aus irgendeinem Grund
erneut ausführen wollen. Zu diesem Zweck muss der Master
nicht erreichbar sein. Sie müssen lediglich CHANGE
MASTER TO
benutzen und den SQL-Thread mit
START SLAVE SQL_THREAD
starten:
CHANGE MASTER TO RELAY_LOG_FILE='slave-relay-bin.006', RELAY_LOG_POS=4025;
Sie können die zweite Operation sogar in einer
Nicht-Replikations-Konfiguration mit einem eigenständigen
Nicht-Slave-Server benutzen, um nach einem Absturz eine
Wiederherstellung durchzuführen. Angenommen, Ihr Server ist
abgestürzt, und Sie haben eine Sicherung wiederhergestellt.
Nun wollen Sie die eigenen Binärlogs des Servers – nicht
die Relay-Logs, sondern die regulären Binärlogs – namens
(beispielsweise) myhost-bin.*
wieder auf
den Server aufspielen. Zunächst erstellen Sie ein Backup
dieser Binärlogs an einer sicheren Position für den Fall,
dass Sie der nachfolgenden Anleitung nicht exakt folgen und
der Server deswegen die Binärlogs unbeabsichtigt löscht.
Verwenden Sie SET GLOBAL relay_log_purge=0
,
um die Sicherheit zu erhöhen. Danach starten Sie den Server
ohne die Option --log-bin
. Stattdessen geben
Sie die Optionen --replicate-same-server-id
,
--relay-log=myhost-bin
(damit der Server
glaubt, dass es sich bei diesen regulären Logs um Relay-Logs
handelt) und --skip-slave-start
an. Nach dem
Serverstart setzen Sie die folgenden Anweisungen ab:
CHANGE MASTER TO RELAY_LOG_FILE='myhost-bin.153', RELAY_LOG_POS=410, MASTER_HOST='some_dummy_string'; START SLAVE SQL_THREAD;
Der Server liest nun seine eigenen Binärlogs und führt diese
aus. Auf diese Weise erfolgt eine Wiederherstellung der Daten.
Nach deren Abschluss führen Sie STOP SLAVE
aus, fahren den Server herunter, löschen die Dateien
master.info
und
relay-log.info
und starten den Server mit
den ursprünglichen Optionen neu.
Die Angabe der Option MASTER_HOST
(auch mit
einem Pseudowert) ist erforderlich, damit der Server annimmt,
er sei ein Slave.
LOAD DATA FROM MASTER
Diese Anweisung erstellt eine Momentaufnahme des Masters und
kopiert diese auf den Slave. Sie aktualisiert die Werte von
MASTER_LOG_FILE
und
MASTER_LOG_POS
, sodass der Slave die
Replikation an der korrekten Position startet.
Ausschlussregeln für Tabellen und Datenbanken, die mit den
Optionen --replicate-*-do-*
und
--replicate-*-ignore-*
angegeben werden,
werden beachtet. --replicate-rewrite-db
wird
hingegen nicht berücksichtigt, weil ein
Benutzer mit dieser Option eine nichteindeutige Zuordnung wie
--replicate-rewrite-db="db1->db3"
oder
--replicate-rewrite-db="db2->db3"
vornehmen könnte, was den Slave beim Laden der Tabellen vom
Master verwirren würde.
Die Verwendung dieser Anweisung hängt von den folgenden Bedingungen ab:
Sie funktioniert nur bei
MyISAM
-Tabellen. Der Versuch, eine
Tabelle anderen Typs zu laden, führt zu folgendem Fehler:
ERROR 1189 (08S01): Net error reading from master
Sie erwirkt während der Aufzeichnung der Momentaufnahme eine globale Lesesperre auf dem Master, wodurch während des Ladevorgangs Updates auf dem Master unterbunden werden.
Wenn Sie große Tabellen laden, müssen Sie die Werte von
net_read_timeout
und
net_write_timeout
unter Umständen sowohl
auf dem Master- als auch auf den Slave-Servern erhöhen. Siehe
auch Abschnitt 5.2.2, „Server-Systemvariablen“.
Beachten Sie, dass LOAD DATA FROM MASTER
keine Tabellen aus der
mysql
-Datenbank kopiert. Dies erleichtert
die Einrichtung verschiedener Benutzer und Berechtigungen auf
dem Master und dem Slave.
Um LOAD DATA FROM MASTER
verwenden zu
können, benötigt das Replikationskonto, welches zur
Verbindung mit dem Master-Server verwendet wird, die
Berechtigungen RELOAD
und
SUPER
auf dem Master und die Berechtigung
SELECT
für alle Master-Tabellen, die Sie
laden wollen. Alle Master-Tabellen, für die der Benutzer die
Berechtigung SELECT
nicht hat, werden von
LOAD DATA FROM MASTER
ignoriert. Dies liegt
daran, dass der Master sie vor dem Benutzer verbirgt:
LOAD DATA FROM MASTER
ruft SHOW
DATABASES
auf, um die zu ladenden Master-Datenbanken
in Erfahrung zu bringen; SHOW DATABASES
aber gibt nur Datenbanken zurück, für die der Benutzer
Berechtigungen hat. Siehe auch
Abschnitt 13.5.4.7, „SHOW DATABASES
“. Auf der Slave-Seite
benötigt der Benutzer, der LOAD DATA FROM
MASTER
absetzt, Berechtigungen zum Löschen und
Erstellen der Datenbanken und Tabellen, die kopiert werden.
LOAD TABLE tbl_name
FROM MASTER
Überträgt eine Kopie der Tabelle vom Master auf den Slave.
Diese Anweisung wurde in erster Linie zum Debuggen von
LOAD DATA FROM MASTER
-Operationen
implementiert. Um LOAD TABLE
verwenden zu
können, benötigt das Konto, welches zur Verbindung mit dem
Master-Server verwendet wird, die Berechtigungen
RELOAD
und SUPER
auf dem
Master und die Berechtigung SELECT
für die
zu ladende Master-Tabelle. Auf der Slave-Seite benötigt der
Benutzer, der LOAD TABLE FROM MASTER
absetzt, Berechtigungen zum Löschen und Erstellen der
Tabelle.
Die Bedingungen für LOAD DATA FROM MASTER
gelten auch hier. So funktioniert LOAD TABLE FROM
MASTER
beispielsweise nur bei
MyISAM
-Tabellen. Auch die Hinweise zu
Zeitüberschreitungen für LOAD DATA FROM
MASTER
sind anzuwenden.
SELECT MASTER_POS_WAIT('master_log_file
',master_log_pos
)
Dies ist eigentlich eine Funktion und keine Anweisung. Mit ihr kann gewährleistet werden, dass der Slave Ereignisse bis zu einer gegebenen Position im Binärlog des Masters gelesen und ausgeführt hat. Eine vollständige Beschreibung finden Sie in Abschnitt 12.10.4, „Verschiedene Funktionen“.
RESET SLAVE
RESET SLAVE
löscht auf dem Slave die
Angabe zur Replikationsposition in den Binärlogs des Masters
(d. h., der Slave „vergisst“ die Position).
Diese Anweisung ist zur Verwendung für einen sauberen Start
vorgesehen: Sie löscht die Dateien
master.info
und
relay-log.info
und alle Relay-Logs und
beginnt ein neues Relay-Log.
Hinweis: Alle Relay-Logs
werden gelöscht – auch dann, wenn sie nicht vollständig
vom Slave-SQL-Thread ausgeführt wurden. (Dieser Umstand ist
wahrscheinlich auf einem Replikationsslave gegeben, wenn Sie
eine STOP SLAVE
-Anweisung abgesetzt haben
oder der Slave stark belastet ist.)
Verbindungsdaten, die in der Datei
master.info
gespeichert sind, werden
direkt unter Berücksichtigung von Werten zurückgesetzt, die
ggf. mit den entsprechenden Startoptionen angegeben werden. Zu
diesen Daten gehören Werte wie Master-Host, Master-Port,
Master-Benutzer und Master-Passwort. Wenn der Slave-SQL-Thread
gerade mit der Replikation von Temporärtabellen beschäftigt
war, als er angehalten wurde, und RESET
SLAVE
abgesetzt wird, dann werden diese replizierten
Temporärtabellen auf dem Slave gelöscht.
SET GLOBAL SQL_SLAVE_SKIP_COUNTER = N
Diese Anweisung überspringt die nächsten
N
Ereignisse auf dem Master. Dies
ist nützlich, wenn Replikationen wiederhergestellt werden
sollen, die durch eine Anweisung angehalten wurden.
Die Anweisung ist nur gültig, wenn der Slave-Thread nicht ausgeführt wird. Andernfalls erzeugt er einen Fehler.
SHOW SLAVE STATUS
Diese Anweisung vermittelt Statusinformationen zu wesentlichen
Parametern der Slave-Threads. Wenn Sie diese Anweisung mit dem
mysql-Client absetzen, können Sie
\G
statt des Semikolons als
Abschlusszeichen für die Anweisung verwenden, um eine
vertikale Ausgabe zu erhalten, die besser zu lesen ist:
mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: localhost
Master_User: root
Master_Port: 3306
Connect_Retry: 3
Master_Log_File: gbichot-bin.005
Read_Master_Log_Pos: 79
Relay_Log_File: gbichot-relay-bin.005
Relay_Log_Pos: 548
Relay_Master_Log_File: gbichot-bin.005
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 79
Relay_Log_Space: 552
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 8
SHOW SLAVE STATUS
gibt die folgenden Felder
zurück:
Slave_IO_State
Eine Kopie des State
-Felds in der
Ausgabe von SHOW PROCESSLIST
für den
Slave-I/O-Thread. Sie zeigt an, was der Thread gerade tut:
Verbindungsherstellung zum Master, Warten auf vom Master
kommende Ereignisse, Wiederverbindung mit dem Master usw.
Mögliche Zustände sind in
Abschnitt 6.4, „Replikation: Implementationsdetails“,
beschrieben. Bei älteren MySQL-Versionen ist eine
Überprüfung dieses Felds notwendig, denn diese erlaubten
eine fortlaufende Ausführung des Threads auch für den
Fall, dass eine Verbindungsherstellung mit dem Master
nicht möglich war. Wird er ausgeführt, so liegt kein
Problem vor; andernfalls finden Sie den Fehler im Feld
Last_Error
(siehe unten).
Master_Host
Der aktuelle Master-Host.
Master_User
Der aktuelle Benutzer, der mit dem Master verbunden ist.
Master_Port
Der aktuelle Master-Port.
Connect_Retry
Der aktuelle Wert der Option
--master-connect-retry
.
Master_Log_File
Der Name der Master-Binärlogdatei, aus der der I/O-Thread derzeit liest.
Read_Master_Log_Pos
Die Position, bis zu der der I/O-Thread im aktuellen Master-Binärlog gelesen hat.
Relay_Log_File
Der Name der Relay-Logdatei, deren Angaben der SQL-Thread derzeit liest und ausführt.
Relay_Log_Pos
Die Position, bis zu der der SQL-Thread Angaben in der aktuellen Relay-Logdatei gelesen und ausgeführt hat.
Relay_Master_Log_File
Der Name der Master-Binärlogdatei, die das aktuelle Ereignis enthält, welches gerade vom SQL-Thread ausgeführt wird.
Slave_IO_Running
Gibt an, ob der I/O-Thread gestartet wurde und erfolgreich
eine Verbindung mit dem Master herstellen konnte. Bei
älteren MySQL-Versionen (vor 4.1.14 und 5.0.12) hat
Slave_IO_Running
den Wert
YES
, wenn der I/O-Thread gestartet
wurde (und zwar auch dann, wenn noch keine Verbindung zum
Master hergestellt wurde).
Slave_SQL_Running
Gibt an, ob der SQL-Thread gestartet wurde.
Replicate_Do_DB
,
Replicate_Ignore_DB
Liste der Datenbanken, die ggf. mit den Optionen
--replicate-do-db
und
--replicate-ignore-db
angegeben wurden.
Replicate_Do_Table
,
Replicate_Ignore_Table
,
Replicate_Wild_Do_Table
,
Replicate_Wild_Ignore_Table
Liste der Tabellen, die ggf. mit den Optionen
--replicate-do-table
,
--replicate-ignore-table
,
--replicate-wild-do-table
und
--replicate-wild-ignore_table
angegeben
wurden.
Last_Errno
,
Last_Error
Nummer und Meldung des Fehlers, der von der zuletzt
ausgeführten Abfrage zurückgegeben wurde. Die
Fehlernummer 0 und der Leer-String als Meldung haben die
Bedeutung „kein Fehler“. Wenn der Wert
Last_Error
nicht leer ist, erscheint er
auch als Meldung im Fehlerlog des Slaves. Zum Beispiel:
Last_Errno: 1051 Last_Error: error 'Unknown table 'z'' on query 'drop table z'
Die Meldung zeigt an, dass die Tabelle
z
auf dem Master vorhanden war und dort
gelöscht wurde, dass sie aber auf dem Slave nicht
existierte, weswegen die Anweisung DROP
TABLE
dort fehlschlug. (Dies kann beispielsweise
passieren, wenn Sie vergessen, die Tabelle beim Einrichten
der Replikation auf den Slave zu kopieren.)
Skip_Counter
Der zuletzt verwendete Wert von
SQL_SLAVE_SKIP_COUNTER
.
Exec_Master_Log_Pos
Die Position des letzten vom SQL-Thread ausgeführten
Ereignisses aus dem Binärlog des Masters
(Relay_Master_Log_File
).
(Relay_Master_Log_File
,
Exec_Master_Log_Pos
) im Binärlog des
Masters entspricht (Relay_Log_File
,
Relay_Log_Pos
) im Relay-Log.
Relay_Log_Space
Die Gesamtgröße aller vorhandenen Relay-Logs.
Until_Condition
,
Until_Log_File
,
Until_Log_Pos
Der in der UNTIL
-Klausel der
START SLAVE
-Anweisung angegebene Wert.
Until_Condition
kann folgende Werte
haben:
None
, sofern keine
UNTIL
-Klausel angegeben wurde.
Master
, wenn der Slave bis zu einer
angegebenen Position in den Binärlogs des Masters
liest.
Relay
, wenn der Slave bis zu einer
angegebenen Position in seinen Binärlogs liest.
Until_Log_File
und
Until_Log_Pos
geben den Namen der
Logdatei und die Position an. Diese Werte definieren den
Punkt, an dem die Ausführung des SQL-Threads endet.
Master_SSL_Allowed
,
Master_SSL_CA_File
,
Master_SSL_CA_Path
,
Master_SSL_Cert
,
Master_SSL_Cipher
,
Master_SSL_Key
Diese Felder geben (sofern vorhanden) die SSL-Parameter an, die vom Slave zur Verbindung mit dem Master verwendet werden.
Master_SSL_Allowed
kann folgende Werte
haben:
Yes
, wenn eine SSL-Verbindung zum
Master zulässig ist.
No
, wenn keine SSL-Verbindung zum
Master zulässig ist.
Ignored
, wenn eine SSL-Verbindung
zwar zulässig ist, aber am Slave-Server die
SSL-Unterstützung nicht aktiviert ist.
Die Werte der übrigen SSL-spezifischen Felder entsprechen
den Werten der Optionen --master-ca
,
--master-capath
,
--master-cert
,
--master-cipher
und
--master-key
.
Seconds_Behind_Master
Dieses Feld gibt an, wie „verspätet“ der Slave ist:
Wenn der Slave-SQL-Thread aktiv läuft (d. h. Änderungen verarbeitet), dann gibt dieses Feld die Anzahl der Sekunden an, die seit dem Zeitstempel des Ereignisses vergangen sind, das von diesem Thread zuletzt auf dem Master ausgeführt wurde.
Wenn der SQL-Thread den Slave-I/O-Thread eingeholt hat und untätig auf weitere Ereignisse vom I/O-Thread wartet, ist das Feld null.
Im Endeffekt misst das Feld also den zeitlichen Unterschied zwischen dem Slave-SQL-Thread und dem Slave-I/O-Thread.
Ist die Netzwerkverbindung zwischen Master und Slave sehr
schnell, dann liegt der Slave-I/O-Thread recht nah am
Master, d. h., das Feld erlaubt eine recht genaue
Schätzung des zeitlichen Verarbeitungsabstandes zwischen
Slave-SQL-Thread und dem Master. Ist das Netzwerk hingegen
langsam, dann ist der Wert nicht sehr
aussagekräftig: Der Slave-SQL-Thread kann recht häufig
zum langsam lesenden Slave-I/O-Thread aufschließen,
weswegen Seconds_Behind_Master
oft den
Wert 0 anzeigt – und zwar auch dann, wenn der I/O-Thread
im Vergleich zum Master relativ stark verspätet ist.
Anders gesagt, diese Spalte ist nur bei
schnellen Netzwerken aussagekräftig.
Diese Berechnung des zeitlichen Unterschieds funktioniert,
obwohl Master und Slave keine identisch laufenden Uhren
haben (der Unterschied wird ermittelt, wenn der
Slave-I/O-Thread startet; danach wird davon ausgegangen,
dass der Abstand konstant bleibt).
Seconds_Behind_Master
ist
NULL
(d. h. „unbekannt“),
wenn der Slave-SQL-Thread nicht ausgeführt wird oder wenn
der Slave-I/O-Thread nicht läuft oder nicht mit dem
Master verbunden ist. Schläft beispielsweise der
Slave-I/O-Thread für die mit der Option
--master-connect-retry
angegebene Anzahl
von Sekunden, bevor er eine Wiederverbindung versucht,
dann wird NULL
angezeigt, weil der
Slave nicht wissen kann, was der Master tut, und deswegen
auch nicht zuverlässig weiß, wie spät es ist.
Dieses Feld hat eine Einschränkung: Der Zeitstempel wird
bei der Replikation beibehalten, d. h., wenn ein Master
M1 seinerseits ein Slave von M0 ist, dann hat jedes
Ereignis im Binärlog von M1, das der Replikation eines
Ereignisses aus dem Binärlog von M0 entstammt, auch den
Zeitstempel dieses Ereignisses. Dies erlaubt MySQL die
erfolgreiche Replikation von TIMESTAMP
.
Der Nachteil für Seconds_Behind_Master
besteht allerdings darin, dass, wenn M1 auch direkte
Updates von Clients erhält, der Wert wahllos abweicht,
weil das letzte Ereignis auf M1 mal von M0 stammt, mal
aber auch der letzte Zeitstempel eines direkten Updates
ist.
START SLAVE [thread_type
[,thread_type
] ... ] START SLAVE [SQL_THREAD] UNTIL MASTER_LOG_FILE = 'log_name
', MASTER_LOG_POS =log_pos
START SLAVE [SQL_THREAD] UNTIL RELAY_LOG_FILE = 'log_name
', RELAY_LOG_POS =log_pos
thread_type
: IO_THREAD | SQL_THREAD
START SLAVE
startet beide Slave-Threads.
Der I/O-Thread liest Abfragen vom Master-Server und speichert
sie im Relay-Log. Der SQL-Thread liest das Relay-Log und
führt die Abfragen aus. START SLAVE
erfordert die Berechtigung SUPER
.
Wenn START SLAVE
die Slave-Threads
erfolgreich startet, wird kein Fehler zurückgegeben.
Allerdings kann es auch in diesem Fall vorkommen, dass die
Slave-Threads starten und kurz darauf wieder beendet werden
(etwa weil sie keine Verbindung zum Master herstellen oder die
Binärlogs nicht lesen konnten oder aus einem anderen Grund).
START SLAVE
warnt Sie davor nicht. Sie
müssen das Fehlerlog des Slaves auf Fehlermeldungen prüfen,
die von den Slave-Threads erzeugt wurden, oder sich mit
SHOW SLAVE STATUS
vergewissern, dass sie
einwandfrei ausgeführt werden.
Sie können die Optionen IO_THREAD
oder
SQL_THREAD
zur Anweisung hinzufügen, wenn
Sie angeben wollen, welcher der Threads gestartet werden soll.
Eine UNTIL
-Klausel kann hinzugefügt
werden, um anzugeben, dass der Slave starten und laufen soll,
bis der SQL-Thread einen gegebenen Punkt im Master-Binärlog
oder den Slave-Relay-Logs erreicht. Wenn der SQL-Thread diesen
Punkt erreicht, wird er beendet. Wird die Option
SQL_THREAD
in der Anweisung angegeben, dann
startet nur der SQL-Thread. Andernfalls werden beide
Slave-Threads gestartet. Läuft der SQL-Thread bereits, dann
wird die Klausel UNTIL
ignoriert, und eine
Warnung wird ausgegeben.
Für eine UNTIL
-Klausel müssen Sie sowohl
einen Logdateinamen als auch eine Position angeben. Vermischen
Sie die Optionen für Master- und Relay-Logs nicht.
Eine UNTIL
-Bedingung wird von einer
nachfolgenden STOP SLAVE
-Anweisung, einer
START SLAVE
-Anweisung ohne
UNTIL
-Klausel oder einem Serverneustart
zurückgesetzt.
Die UNTIL
-Klausel kann nützlich sein, um
die Replikation zu debuggen oder festzulegen, dass die
Replikation bis genau zu dem Punkt fortfahren soll, an dem ein
Slave eine Anweisung nicht mehr replizieren soll. Wurde
beispielsweise versehentlich eine DROP
TABLE
-Anweisung auf dem Master ausgeführt, dann
können Sie den Slave mit UNTIL
anweisen,
das Log nur bis unmittelbar vor diesem Punkt, aber nicht mehr
weiter auszuführen. Um herauszufinden, was das Ereignis ist,
verwenden Sie mysqlbinlog mit den
Master-Logs oder den Slave-Relay-Logs oder setzen eine
SHOW BINLOG EVENTS
-Anweisung ab.
Wenn Sie UNTIL
verwenden, damit der
Slave-Prozess die Abfragen in Abschnitten repliziert,
empfehlen wir den Start des Slaves mit der Option
--skip-slave-start
, damit der SQL-Thread
nicht ausgeführt wird, wenn der Slave-Server startet. Es ist
wahrscheinlich am besten, diese Option in einer Optionsdatei
statt auf der Befehlszeile zu benutzen, damit die Klausel bei
einem unerwarteten Serverneustart nicht vergessen wird.
Die SHOW SLAVE STATUS
-Anweisung enthält
Ausgabefelder, die die aktuellen Werte der
UNTIL
-Bedingung anzeigen.
In älteren Versionen von MySQL (vor 4.0.5) hieß diese
Anweisung SLAVE START
. Ihre Verwendung in
dieser Form ist zwar in MySQL 5.1 aus
Kompatibilitätsgründen noch akzeptabel, aber veraltet.
STOP SLAVE [thread_type
[,thread_type
] ... ]thread_type
: IO_THREAD | SQL_THREAD
Beendet die Slave-Threads. STOP SLAVE
erfordert die Berechtigung SUPER
.
Wie START SLAVE
kann diese Anweisung mit
den Optionen IO_THREAD
und
SQL_THREAD
verwendet werden, um den oder
die zu beendenden Threads anzugeben.
In älteren Versionen von MySQL (vor 4.0.5) hieß diese
Anweisung SLAVE STOP
. Ihre Verwendung in
dieser Form ist zwar in MySQL 5.1 aus
Kompatibilitätsgründen noch akzeptabel, aber veraltet.
MySQL 5.1 unterstützt serverseitige vorbereitete
Anweisungen. Diese Unterstützung nutzt das effiziente binäre
Client/Server-Protokoll, welches in MySQL 4.1 implementiert wurde.
Voraussetzung hierfür ist, dass Sie eine geeignete
Client-Programmierschnittstelle verwenden. Geeignete
Schnittstellen sind die C-API-Clientbibliothek von MySQL (für
C-Programme), MySQL Connector/J (für Java-Programme) und MySQL
Connector/NET. So bietet etwa die C-API eine Anzahl von
Funktionsaufrufen, die eine API für vorbereitete Anweisungen
darstellen. Siehe auch
Abschnitt 24.2.4, „C-API: Prepared Statements“. Andere
Sprachschnittstellen bieten Unterstützung für vorbereitete
Anweisungen, die das binäre Protokoll verwenden, indem Sie eine
Verbindung in die C-Clientbibliothek herstellen (z. B. die
mysqli
-Erweiterung
in PHP 5.0).
Es gibt auch eine alternative SQL-Schnittstelle für vorbereitete Anweisungen. Diese ist zwar nicht so effizient wie die Verwendung eines binären Protokolls über eine API für vorbereitete Anweisungen, sie erfordert aber auch keine Programmierung, weil sie direkt auf SQL-Ebene verfügbar ist:
Sie können sie verwenden, wenn Ihnen keine Programmierschnittstelle zur Verfügung steht.
Sie können sie aus jedem Programm heraus verwenden, das Ihnen die Übermittlung von SQL-Anweisungen an den Server zur dortigen Ausführung gestattet (dies gilt beispielsweise für das mysql-Clientprogramm).
Sie können es auch dann verwenden, wenn der Client eine alte Version der Clientbibliothek einsetzt. Die einzige Voraussetzung besteht darin, dass Sie eine Verbindung mit einem Server herstellen können müssen, der aktuell genug ist, um die SQL-Syntax für vorbereitete Anweisungen zu unterstützen.
Die SQL-Syntax für vorbereitete Anweisungen ist zur Verwendung in Fällen wie den folgenden vorgesehen:
Sie wollen die Funktion vorbereiteter Anweisungen in Ihrer Anwendung testen, bevor Sie sie einkodieren.
Eine Anwendung hat Probleme mit der Ausführung vorbereiteter Anweisungen, und Sie wollen dem Problem interaktiv auf den Grund gehen.
Sie wollen einen Testfall erstellen, der ein Problem im Zusammenhang mit vorbereiteten Anweisungen beschreibt. Dieser soll als Grundlage eines Fehlerberichts dienen.
Sie müssen vorbereitete Anweisungen verwenden, haben aber keinen Zugang zu einer Programmierschnittstelle, die diese unterstützt.
Die SQL-Syntax für vorbereitete Anweisungen basiert auf drei SQL-Anweisungen:
PREPARE
stmt_name
FROM
preparable_stmt
Die Anweisung PREPARE
bereitet eine
Anweisung vor und weist ihr den Namen
stmt_name
zu, unter dem sie später
referenziert werden kann. Die Groß-/Kleinschreibung wird bei
Anweisungsnamen nicht unterschieden.
preparable_stmt
ist entweder ein
String-Literal oder eine Benutzervariable, die den Text der
Anweisung enthält. Der Text muss eine einzelne SQL-Anweisung
(nicht mehrere Anweisungen) darstellen. In dieser Anweisung
können Fragezeichen (‘?
’) als
Parameterkennzeichen verwendet werden: Sie geben an, wo bei
der späteren Ausführung der Anweisung Datenwerte eingebunden
werden. Fragezeichen sollten auch dann nicht in
Anführungszeichen gesetzt werden, wenn Sie beabsichtigen, sie
an String-Werte anzubinden. Parameterkennzeichen dürfen nur
an Stellen verwendet werden, an denen Datenwerte eingefügt
werden sollen, nicht jedoch für SQL-Schlüsselwörter,
Bezeichner usw.
Wenn eine vorbereitete Anweisung des angegebenen Namens bereits vorhanden ist, wird diese Namenszuweisung implizit aufgehoben, bevor die neue Anweisung vorbereitet wird. Das bedeutet, dass, wenn die neue Anweisung einen Fehler enthält und nicht vorbereitet werden kann, ein Fehler zurückgegeben wird; in diesem Fall gibt es keine Anweisung des betreffenden Namens mehr.
Der Gültigkeitsbereich einer vorbereiteten Anweisung ist die Clientsitzung, innerhalb derer sie erstellt wird. Andere Clients sehen sie nicht.
EXECUTE
stmt_name
[USING
@var_name
[,
@var_name
] ...]
Nach der Vorbereitung einer Anweisung können Sie sie mit
einer EXECUTE
-Anweisung ausführen, die den
Namen der vorbereiteten Anweisung referenziert. Wenn die
vorbereitete Anweisung Parameterkennzeichen enthält, müssen
Sie eine USING
-Klausel angeben, die die
Benutzervariablen mit den Werten auflistet, welche für die
Parameter eingesetzt werden sollen. Parameterwerte können nur
über Benutzervariablen übergeben werden. Die
USING
-Klausel muss so viele Variablen
übergeben, wie Parameterkennzeichen in der Anweisung
vorhanden sind, und alle Variablennamen müssen korrekt sein.
Sie können eine vorbereitete Anweisung mehrfach ausführen und dabei unterschiedliche Variablen übergeben oder die Variablen vor jeder Ausführung auf andere Werte setzen.
{DEALLOCATE | DROP} PREPARE
stmt_name
Um eine vorbereitete Anweisung aufzuheben, verwenden Sie die
Anweisung DEALLOCATE PREPARE
. Wenn Sie eine
vorbereitete Anweisung auszuführen versuchen, nachdem Sie sie
aufgehoben haben, wird ein Fehler erzeugt.
Wenn Sie eine Clientsitzung beenden, ohne eine zuvor vorbereitete Anweisung aufzuheben, dann hebt der Server sie automatisch auf.
In vorbereiteten Anweisungen können die folgenden SQL-Anweisungen
verwendet werden: CREATE TABLE
,
DELETE
, DO
,
INSERT
, REPLACE
,
SELECT
, SET
,
UPDATE
und die meisten
SHOW
-Anweisungen. Andere Anweisungen werden
noch nicht unterstützt.
Die folgenden Beispiele zeigen zwei gleichwertige Arten der Vorbereitung einer Anweisung, die die Hypotenuse eines Dreiecks berechnet, bei dem zwei Seitenlängen gegeben sind.
Das erste Beispiel zeigt, wie man eine vorbereitete Anweisung unter Verwendung eines String-Literals erstellt, um den Text der Anweisung zu übergeben:
mysql>PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
mysql>SET @a = 3;
mysql>SET @b = 4;
mysql>EXECUTE stmt1 USING @a, @b;
+------------+ | hypotenuse | +------------+ | 5 | +------------+ mysql>DEALLOCATE PREPARE stmt1;
Das zweite Beispiel ist ähnlich, übergibt den Text der Anweisung aber als Benutzervariable:
mysql>SET @s = 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
mysql>PREPARE stmt2 FROM @s;
mysql>SET @a = 6;
mysql>SET @b = 8;
mysql>EXECUTE stmt2 USING @a, @b;
+------------+ | hypotenuse | +------------+ | 10 | +------------+ mysql>DEALLOCATE PREPARE stmt2;
Die SQL-Syntax für vorbereitete Anweisungen erlaubt keine
Verschachtelungen: Eine an PREPARE
übergebene
Anweisung darf selbst keine PREPARE
-,
EXECUTE
- oder DEALLOCATE
PREPARE
-Anweisung sein.
Die SQL-Syntax für vorbereitete Anweisungen unterscheidet sich
von der Verwendung von API-Aufrufen für vorbereitete Anweisungen.
So können Sie beispielsweise mit der C-API-Funktion
mysql_stmt_prepare()
keine
PREPARE
-, EXECUTE
- oder
DEALLOCATE PREPARE
-Anweisung vorbereiten.
Die SQL-Syntax für vorbereitete Anweisungen kann in gespeicherten Prozeduren, nicht aber in gespeicherten Funktionen oder Triggern verwendet werden.
Bei der Verwendung vorbereiteter Anweisungen können für die
Argumente der LIMIT
-Klausel Platzhalter
eingesetzt werden. Siehe auch Abschnitt 13.2.7, „SELECT
“.
Inhaltsverzeichnis
MyISAM
-Speicher-EngineInnoDB
-TabellenInnoDB
: Startoptionen und SystemvariablenInnoDB
-Tabellen erzeugenInnoDB
-DatenbankInnoDB
-FehlerbehandlungInnoDB
-TabellenInnoDB
-TroubleshootingMERGE
-Speicher-EngineMEMORY
-Speicher-EngineBDB
-Speicher-EngineEXAMPLE
-Speicher-EngineFEDERATED
-Speicher-EngineARCHIVE
-Speicher-EngineCSV
-Speicher-EngineBLACKHOLE
-Speicher-EngineMySQL unterstützt mehrere Speicher-Engines für die Arbeit mit unterschiedlichen Tabellentypen. MySQL kennt Speicher-Engines sowohl für transaktionssichere als auch für nicht-transaktionssichere Tabellen:
Mit MyISAM
werden nicht-transaktionssichere
Tabellen verwaltet. Dieser Tabellentyp kann Daten sehr schnell
speichern und abrufen und bietet Volltext-Suchfähigkeiten.
MyISAM
wird in allen MySQL-Konfigurationen
unterstützt und ist als Standard-Tabellentyp voreingestellt,
sofern Sie in MySQL keinen anderen Default konfiguriert haben.
Die Speicher-Engine MEMORY
stellt Tabellen im
Arbeitsspeicher zur Verfügung. Mit der Speicher-Egnine
MERGE
lassen sich mehrere identische
MyISAM
-Tabellen wie eine einzige behandeln.
WieMyISAM
verwalten auch die Speicher-Engines
MEMORY
und MERGE
nicht-transaktionssichere Tabellen. Beide sind ebenfalls
standardmäßig in MySQL enthalten.
Note: Die Speicher-Engine
MEMORY
hieß früher HEAP
.
Die Speicher-Engines InnoDB
und
BDB
stellen transaktionssichere Tabellen zur
Verfügung. BDB
ist in den
Binärdistributionen von MySQL-Max für Betriebssysteme, die
dieses unterstützen, enthalten. Außerdem ist
InnoDB
Standardbestandteil aller MySQL
5.1-Binärdistributionen. In Quelldistributionen
können Sie diese Engines aktivieren oder deaktivieren, indem
Sie MySQL nach Ihren Wünschen konfigurieren.
Die Speicher-Engine EXAMPLE
ist ein
„Sockel“-Modul, das eigentlich gar nichts tut. Sie
können mit ihr zwar Tabellen anlegen, aber keine Daten
speichern oder abrufen. Sie soll lediglich im MySQL-Quellcode
als Beispiel zu dienen, um zu zeigen, wie man neue
Speicher-Engines schreibt. Daher ist sie vor allem für
Entwickler von Interesse.
NDB Cluster
wird von MySQL Cluster als
Speicher-Engine zur Implementierung von Tabellen genutzt, die
über viele Computer partitioniert sind. Sie steht in den
MySQL-Max 5.1- Binärdistributionen zur Verfügung.
Dieses Speicher-Engine wird zurzeit nur von Linux, Solaris und
Mac OS X unterstützt. In zukünftigen MySQL-Releases soll sie
auch auf anderen Plattformen, wie etwa Windows, unterstützt
werden.
Die Speicher-Engine ARCHIVE
dient der
Speicherung großer Datenmengen ohne Indizes mit einem sehr
kleinen Speicherverbrauch.
Die Speicher-Engine CSV
speichert Daten in
Textdateien in Form von kommagetrennten Werten.
Die Speicher-Engine BLACKHOLE
nimmt Daten
entgegen, speichert sie jedoch nicht. Abfragen liefern immer
eine leere Menge zurück.
Die Speicher-Engine FEDERATED
speichert Daten
in einer Remote-Datenbank. Gegenwärtig funktioniert sie nur mit
MySQL unter Verwendung der MySQL-C-Client-API. In zukünftigen
Releases soll sie auch mit anderen Datenquellen mit anderen
Treibern oder Client-Verbindungsmethoden funktionieren.
In diesem Kapitel werden die Speicher-Engines von MySQL beschrieben.
Eine Ausnahme bildet die Engine NDB Cluster
, die
in Kapitel 16, MySQL Cluster behandelt wird.
Wenn Sie eine neue Tabelle anlegen, können Sie die zu verwendende
Speicher-Engine angeben, indem Sie der CREATE
TABLE
-Anweisung die Tabellenoption
ENGINE
oder TYPE
hinzufügen:
CREATE TABLE t (i INT) ENGINE = INNODB; CREATE TABLE t (i INT) TYPE = MEMORY;
Der ältere Begriff TYPE
wird aus Gründen der
Abwärtskompatibilität noch als Synonym für
ENGINE
akzeptiert, doch ENGINE
ist der aktuelle Begriff, während TYPE
mittlerweile veraltet ist.
Wenn Sie die Option ENGINE
oder
TYPE
weglassen, wird die Standard-Speicher-Engine
verwendet. Normalerweise ist dies MyISAM
, doch
mit der Server-Startoption --default-storage-engine
oder --default-table-type
oder der Systemvariablen
storage_engine
oder table_type
können Sie auch etwas anderes einstellen.
Wird MySQL unter Windows mit dem MySQL Configuration Wizard
installiert, kann die Speicher-Engine InnoDB
anstelle der standardmäßigen MyISAM
-Engine
gewählt werden. Siehe
Abschnitt 2.3.5.6, „Der Dialog zur Datenbankverwendung“.
Um eine Typkonvertierung von Tabellen vorzunehmen, geben Sie in
einer ALTER TABLE
-Anweisung den neuen Typ an:
ALTER TABLE t ENGINE = MYISAM; ALTER TABLE t TYPE = BDB;
Siehe Abschnitt 13.1.5, „CREATE TABLE
“ und
Abschnitt 13.1.2, „ALTER TABLE
“.
Wenn Sie eine Speicher-Engine zu verwenden versuchen, die entweder
gar nicht kompiliert oder zwar kompiliert, aber deaktiviert ist,
legt MySQL stattdessen mit der Standard-Speicher-Engine eine Tabelle
an, also normalerweise mit MyISAM
. Dieses
Verhalten ist praktisch, wenn Tabellen zwischen MySQL-Servern hin-
und herkopiert werden, die verschiedene Speicher-Engines
unterstützen. (So könnte beispielsweise in einer Replikation Ihr
Masterserver aus Sicherheitsgründen transaktionssichere
Speicher-Engines verwenden, während die Slaveserver aus Gründen
der Schnelligkeit nur nicht-transaktionssichere einsetzen.)
Dass MySQL für Speicher-Engines, die nicht zur Verfügung stehen, automatisch die Standard-Speicher-Engine einsetzt, kann für Neulinge verwirrend sein. Es wird jedoch in einem solchen Fall immer eine Warnung ausgegeben.
Für neue Tabellen legt MySQL immer eine
.frm
-Datei zur Speicherung der Tabellen- und
Spaltendefinitionen an. Der Index und die Daten der Tabelle können
je nach Speicher-Engine in einer oder mehreren Dateien gespeichert
sein. Der Server erstellt die .frm
-Datei über
der Ebene der Speicher-Engine. Einzelne Speicher-Engines legen
zusätzliche Dateien an, die für die von ihnen verwalteten Tabellen
erforderlich sind.
Eine Datenbank kann unterschiedliche Tabellentypen enthalten; die Tabellen müssen also nicht alle mit derselben Speicher-Engine angelegt werden.
Transaktionssichere Tabellen (TSTs) haben gegenüber den nicht-transaktionssicheren (NTSTs) mehrere Vorteile:
Sie sind sicherer. Selbst wenn MySQL abstürzt oder Hardware-Probleme auftreten, bekommen Sie Ihre Daten auf jeden Fall zurück, sei es durch die automatische Wiederherstellung, sei es aus einer Sicherungskopie plus dem Transaktionslog.
Sie können viele Anweisungen miteinander kombinieren und mit
der COMMIT
-Anweisung später alle
gleichzeitig festschreiben (wenn Autocommit deaktiviert wurde).
Sie können Ihre Änderungen mit einem
ROLLBACK
verwerfen (wenn Autocommit
deaktiviert wurde).
Schlägt ein Update fehl, werden alle Ihre Änderungen rückgängig gemacht. (Bei nicht-transaktionssicheren Tabellen sind alle einmal stattgefundenen Änderungen von Dauer.)
Transaktionssichere Speicher-Engines bieten bessere Nebenläufigkeit für Tabellen, in denen gleichzeitig mit Lese-Operationen viele Änderungen stattfinden.
Sie können transaktionssichere und nicht-transaktionssichere
Tabellen in derselben Anweisung verwenden, um aus beiden das Beste
herauszuholen. Allerdings sollten Sie nicht bei ausgeschaltetem
Autocommit verschiedene Speicher-Engines durcheinanderwürfeln, auch
wenn MySQL mehrere transaktionssichere Engines unterstützt, um die
bestmöglichen Ergebnisse zu erzielen. Denn wenn Sie die Engines
vermischen, werden Änderungen an nicht-transaktionssicheren
Tabellen weiterhin festgeschrieben und können nicht mehr
zurückgerollt werden. Informationen zu diesem und anderen
Problemen, die in Transaktionen mit einem Mix von Speicher-Engines
auftreten können, finden Sie unter Abschnitt 13.4.1, „BEGIN/COMMIT/ROLLBACK
“.
Nicht-transaktionssichere Tabellen haben mehrere Vorteile, die alle damit zusammenhängen, dass der Aufwand von Transaktionen entfällt:
Viel schneller
Weniger Speicherbedarf auf der Festplatte
Weniger Arbeitsspeicherbedarf für Updates
MyISAM
ist die Standard-Speicher-Engine. Sie
baut auf dem älteren ISAM
-Code auf, hat aber
viele praktische Erweiterungen. (Beachten Sie, dass MySQL
5.1 ISAM
nicht
mehr unterstützt.)
Jede MyISAM
-Tabelle wird in drei Dateien auf
der Festplatte gespeichert. Die Namen der Dateien beginnen mit dem
Tabellennamen und haben eine Erweiterung, die den Dateityp angibt.
Eine .frm
-Datei speichert das Tabellenformat.
Die Datendatei besitzt die Erweiterung .MYD
(MYData
). Die Indexdatei hat die Erweiterung
.MYI
(MYIndex
).
Um ausdrücklich zu sagen, dass Sie eine
MyISAM
-Tabelle möchten, verwenden Sie die
Tabellenoption ENGINE
:
CREATE TABLE t (i INT) ENGINE = MYISAM;
Der ältere Begriff TYPE
wird aus Gründen der
Abwärtskompatibilität noch als Synonym für
ENGINE
akzeptiert, doch
ENGINE
ist der aktuelle Begriff, während
TYPE
mittlerweile veraltet ist.
Normalerweise ist eine ENGINE
-Angabe für die
MyISAM
-Speicher-Engine unnötig.
MyISAM
ist ohnehin die Standard-Engine, es sei
denn, die Standardeinstellung wurden geändert. Um in solchen
Situationen ganz sicherzugehen, dass MyISAM
verwendet wird, sollten Sie explizit die Option
ENGINE
verwenden.
Zur Prüfung oder Reparatur von MyISAM
-Tabellen
setzen Sie den mysqlcheck-Client oder das
Hilfsprogramm myisamchk ein. Überdies können
Sie MyISAM
-Tabellen mit
myisampack komprimieren, dann belegen sie viel
weniger Speicherplatz. Siehe auch Abschnitt 8.9, „mysqlcheck — Hilfsprogramm für die Wartung und Reparatur von Tabellen“,
Abschnitt 5.10.4.1, „Benutzung von myisamchk
für die Fehlerbeseitigung nach Abstürzen“, und
Abschnitt 8.4, „myisampack — Erzeugung komprimierter, schreibgeschützter MyISAM Tabellen“.
Kennzeichen von MyISAM
-Tabellen:
Alle Daten werden mit dem niederwertigen Byte zuerst gespeichert. Dadurch werden die Daten maschinen- und betriebssystemunabhängig. Die einzigen Voraussetzungen für die binäre Portierbarkeit der Daten sind, dass der Computer vorzeichenbehaftete Integers (Zweierkomplement) und das IEEE-Fließkommaformat verwendet. Diese Voraussetzungen werden von den üblichen Computern meist erfüllt. Nur bei Embedded-Systemen mit ihren manchmal seltsamen Prozessoren ist die Binärkompatibilität nicht immer gegeben.
Die Verarbeitungsgeschwindigkeit leidet nicht sonderlich, wenn das niederwertige Byte zuerst gespeichert wird. Die Bytes in einer Tabellenzeile werden normalerweise nicht ausgerichtet und es macht zeitmäßig kaum einen Unterschied, ob ein unausgerichtetes Byte in der Reihenfolge oder gegen die Reihenfolge gelesen wird. Darüber hinaus ist der Server-Code, der die Spaltenwerte abruft, im Vergleich zu anderem Code nicht zeitkritisch.
Alle numerischen Schlüsselwerte werden mit dem höchstwertigen Byte zuerst gespeichert, um eine bessere Indexkompression zu ermöglichen.
Große Dateien (bis zu 63 Bit Dateilänge) werden für Datei- und Betriebssysteme, auf denen große Dateien möglich sind, unterstützt.
Eine MyISAM
-Tabelle kann maximal 64 Indizes
haben. Dies lässt sich jedoch durch Rekompilieren ändern: Ab
der Version MySQL 5.1.4 können Sie den Build konfigurieren,
indem Sie configure mit der Option
--with-max-indexes=
aufrufen, wobei N
N
die Höchstzahl
der pro MyISAM
-Tabelle zulässigen Indizes
ist. N
muss kleiner oder gleich 128
sein. In älteren Versionen als MySQL 5.1.4 müssen Sie die
Quelle wechseln.
Ein Index darf maximal 16 Spalten haben.
Die Höchstlänge für Schlüssel beträgt 1000 Bytes. Auch dies lässt sich durch Wechseln der Quelle und Rekompilieren ändern. Ist ein Schlüssel länger als 250 Bytes wird ein größerer als der standardmäßig 1024 Bytes große Schlüsselblock verwendet.
Werden Zeilen sortiert eingefügt (wie zum Beispiel mit einer
AUTO_INCREMENT
-Spalte), wird der Indexbaum
aufgespalten, so dass der höchste Knoten nur einen Schlüssel
enthält. So wird der Platz im Indexbaum besser ausgenutzt.
Intern wird eine AUTO_INCREMENT
-Spalte pro
Tabelle unterstützt. MyISAM
aktualisiert
diese Spalte bei INSERT
- und
UPDATE
-Operationen automatisch. Das macht
AUTO_INCREMENT
-Spalten schneller (um
mindestens 10%). Werte am Anfang der Folge werden nach ihrer
Löschung nicht wiederverwendet. (Wenn eine
AUTO_INCREMENT
-Spalte als die letzte Spalte
eines Mehrspalten-Indizes definiert ist, werden gelöschte
Werte vom Anfang einer Folge doch wiederverwendet.) Der
AUTO_INCREMENT
-Wert kann mit ALTER
TABLE
oder myisamchk
zurückgesetzt werden.
Zeilen mit dynamischer Größenanpassung werden bei einer Mischung von Lösch-, Änderungs- und Einfügeoperationen viel weniger stark fragmentiert, da aneinander grenzende gelöschte Blöcke automatisch zusammengefasst und Blöcke, deren Nachbarblock gelöscht werden, automatisch erweitert werden.
Hat eine Tabelle in der Mitte der Datendatei keine freien
Blöcke, können Sie neue Zeilen mit INSERT
einfügen, während gleichzeitig andere Threads die Tabelle
lesen. (Man nennt dies "nebenläufige Einfügeoperationen".)
Wird eine Zeile gelöscht oder werden in eine Zeile
dynamischer Länge mehr Daten geschrieben, als sie zuvor
enthalten hatte, kann ein freier Block entstehen. Wenn alle
freien Blöcke aufgebraucht (ausgefüllt) wurden, werden
zukünftige Einfügeoperationen wieder nebenläufig. Siehe
Abschnitt 7.3.3, „Gleichzeitige Einfügevorgänge“.
Mit den Tabellenoptionen DATA DIRECTORY
und
INDEX DIRECTORY
von CREATE
TABLE
können Sie die Daten- und die Indexdatei in
unterschiedliche Verzeichnisse legen, um mehr Geschwindigkeit
zu erzielen. Siehe Abschnitt 13.1.5, „CREATE TABLE
“.
BLOB
- und TEXT
-Spalten
können indiziert werden.
NULL
-Werte sind in indizierten Spalten
zulässig. Hierfür werden 0 bis 1 Byte pro Schlüssel
gebraucht.
Jede Zeichenspalte kann einen anderen Zeichensatz haben. Siehe Kapitel 10, Zeichensatz-Unterstützung.
In der MyISAM
-Indexdatei gibt es ein Flag,
das anzeigt, ob die Tabelle ordentlich geschlossen wurde. Wenn
mysqld mit der Option
--myisam-recover
gestartet wird, werden
MyISAM
-Tabellen beim Öffnen automatisch
überprüft und repariert, wenn sie nicht richtig geschlossen
wurden.
myisamchk markiert Tabellen als geprüft,
wenn Sie es mit der Option --update-state
ausführen. myisamchk --fast prüft nur
diejenigen Tabellen, die diese Markierung nicht tragen.
myisamchk --analyze speichert Statistikdaten sowohl für Teilschlüssel als auch für vollständige Schlüssel.
myisampack kann BLOB
-
und VARCHAR
-Spalten packen.
MyISAM
unterstützt auch folgende Funktionen:
Unterstützung für einen echten
VARCHAR
-Typ; eine
VARCHAR
-Spalte beginnt mit einer
Längenangabe, die in einem oder zwei Byte(s) gespeichert ist.
Tabellen mit VARCHAR
-Spalten können Zeilen
mit fester oder dynamischer Länge haben.
Die Summe der Längen der VARCHAR
-und
CHAR
-Spalten in einer Tabelle kann bis zu
64KB betragen.
Für UNIQUE
kann ein berechneter Hash-Index
verwendet werden. So ist UNIQUE
für jede
beliebige Spaltenkombination in einer Tabelle zulässig.
(Allerdings können auf einem berechneten
UNIQUE
-Index keine Suchoperationen
durchgeführt werden.)
Ein spezielles Forum für die Speicher-Engine
MyISAM
finden Sie unter
http://forums.mysql.com/list.php?21.
Die folgenden Optionen von mysqld können
verwendet werden, um das Verhalten von
MyISAM
-Tabellen zu ändern. Weitere
Informationen finden Sie unter Abschnitt 5.2.1, „Befehlsoptionen für mysqld“.
--myisam-recover=
mode
Stellt den Modus für die automatische Wiederherstellung von
abgestürzten MyISAM
-Tabellen ein.
--delay-key-write=ALL
Zwischen den Schreibvorgängen werden die Schlüsselpuffer
(Key-Buffer) für MyISAM
-Tabellen nicht
auf die Festplatte zurückgeschrieben.
Note: Wenn Sie dies tun,
sollten Sie auf MyISAM
-Tabellen nicht von
einem anderen Programm aus zugreifen (zum Beispiel von einem
anderen MySQL-Server oder mit myisamchk),
so lange die Tabellen in Gebrauch sind. Sonst riskieren Sie,
dass der Index beschädigt wird. Diese Gefahr wird durch
--external-locking
nicht gebannt.
Die folgenden Systemvariablen beeinflussen das Verhalten von
MyISAM
-Tabellen. Weitere Informationen finden
Sie unter Abschnitt 5.2.2, „Server-Systemvariablen“.
bulk_insert_buffer_size
Die Größe des bei der Optimierung von Massen-Einfügeoperationen verwendeten Tree-Caches. Hinweis: Dieser Wert gilt pro Thread!
myisam_max_sort_file_size
Zur Indexerstellung nicht die schnelle Index-Sortiermethode verwenden, wenn die temporäre Datei dadurch größer als dieser Wert würde. Hinweis: Dieser Parameter wird in Bytes angegeben.
myisam_sort_buffer_size
Stellt die Puffergröße für die Wiederherstellung von Tabellen ein.
Wenn Sie mysqld mit der Option
--myisam-recover
starten, wird die automatische
Wiederherstellung aktiviert. Wenn der Server eine
MyISAM
-Tabelle öffnet, prüft er, ob sie als
abgestürzt gekennzeichnet ist oder die Zählervariable für
Öffnungen von 0 verschieden ist und Sie den Server ohne externe
Sperren betreiben. Trifft eine dieser Bedingungen zu, so
geschieht folgendes:
Der Server überprüft die Tabelle auf Fehler.
Wenn der Server einen Fehler findet, versucht er eine schnelle Tabellenreparatur (mit Sortierung, aber ohne Neuerzeugung der Datendatei).
Scheitert die Reparatur wegen eines Fehlers in der Datendatei (zum Beispiel eines doppelten Schlüssels), versucht der Server erneut eine Reparatur, aber dieses Mal mit Neuerzeugung der Datendatei.
Scheitert auch diese Reparatur, versucht es der Server noch einmal mit der alten Reparaturmethode (zeilenweises Schreiben der Daten ohne Sortierung). Dieses Verfahren müsste in der Lage sein, jeden Fehler zu beheben und braucht nur wenig Festplattenspeicher.
Wenn die Wiederherstellung nicht alle Zeilen aus den zuvor
abgeschlossenen Anweisungen wiederherstellen kann und Sie im
Wert der Option --myisam-recover
nicht
FORCE
angegeben haben, bricht die
automatische Reparatur ab und schreibt folgende Fehlermeldung in
das Fehler-Log:
Error: Couldn't repair table: test.g00pages
Wenn Sie FORCE
angeben, wird stattdessen
folgende Warnung in das Log geschrieben:
Warning: Found 344 of 354 rows when repairing ./test/g00pages
Beachten Sie: Wenn die automatische Wiederherstellung den Wert
BACKUP
enthält, legt der
Wiederherstellungsprozess Dateien an, deren Namen die Form
haben. Sie benötigen ein cron-Skript, das
diese Dateien automatisch von den Datenbankverzeichnissen auf
die Sicherungsmedien verschiebt.
tbl_name-datetime
.BAK
MyISAM
-Tabellen verwenden B-Baum-Indizes. Die
Größe der Indexdatei, summiert über alle Schlüssel, lässt
sich mit der Formel (key_length+4)/0.67
ungefähr berechnen. Das gilt für den ungünstigsten Fall, dass
alle Schlüssel in sortierter Reihenfolge eingefügt wurden und
die Tabelle keine komprimierten Schlüssel besitzt.
String-Indizes werden Leerzeichen-komprimiert. Ist der erste
Teil des Index ein String, so wird dieser zusätzlich
präfixkomprimiert. Durch Leerzeichen-Kompression wird die
Indexdatei kleiner als in den obigen Zahlen für den
ungünstigsten Fall dargestellt, wenn eine Stringspalte viele
Leerzeichen am Ende hat oder eine
VARCHAR
-Spalte ist, die nicht immer in voller
Länge ausgenutzt wird. Eine Präfix-Kompression wird für
Schlüssel eingesetzt, die mit einem String anfangen. Die
Präfix-Kompression ist hilfreich, wenn mehrere Strings mit
identischem Präfix vorhanden sind.
In MyISAM
-Tabellen können Sie auch Zahlen
präfixkomprimieren. Hierzu geben Sie beim Anlegen der Tabelle
die Tabellenoption PACK_KEYS=1
an. Das hilft,
wenn Sie viele Integer-Schlüssel mit identischem Präfix haben,
wenn die Zahlen mit dem höchstwertigen Byte zuerst gespeichert
werden.
MyISAM
unterstützt drei verschiedene
Speicherformate. Zwei davon, das feste und das dynamische
Format, werden automatisch anhand des verwendeten Spaltentyps
gewählt. Das dritte, komprimierte Format kann nur mit der
Utility myisampack angelegt werden.
Wenn Sie CREATE TABLE
oder ALTER
TABLE
für eine Tabelle verwenden, die keine
BLOB
- oder TEXT
-Spalten
besitzt, können Sie mit der Tabellenoption
ROW_FORMAT
ein FIXED
- oder
DYNAMIC
-Format erzwingen.
Um Tabellen zu dekomprimieren, geben Sie
ROW_FORMAT=DEFAULT
mit ALTER
TABLE
zusammen an.
Unter Abschnitt 13.1.5, „CREATE TABLE
“ finden Sie Informationen
über ROW_FORMAT
.
Das statische (Festlängen-) Format ist für
MyISAM
-Tabellen voreingestellt. Es wird
verwendet, wenn die Tabelle keine Spalten mit variabler Länge
(VARCHAR
-, VARBINARY
-,
BLOB
- oder TEXT
-Spalten)
enthält. Jede Zeile wird dann mit einer festgelegten Anzahl
von Bytes gespeichert.
Von den drei Speicherformaten, die MyISAM
unterstützt, ist das statische Format das einfachste und
sicherste (für Schäden am wenigsten anfällige). Außerdem
bietet es wegen der Leichtigkeit, mit der die Zeilen der
Datendatei auf der Festplatte gefunden werden, auch den
schnellsten Festplattenzugriff. Um eine Zeile nach der
Index-Zeilennummer nachzuschlagen, multiplizieren Sie die
Nummer der Zeile mit ihrer Länge, um ihre Position zu
ermitteln. Darüber hinaus ist es beim Durchsuchen einer
Tabelle sehr einfach, mit jedem Festplattenzugriff eine
konstante Anzahl Zeilen zu lesen.
Die Sicherheit erweist sich, wenn Ihr Computer abstürzt,
während der MySQL-Server eine MyISAM
-Datei
mit festgelegtem Format schreibt. In einem solchen Fall kann
myisamchk ganz leicht feststellen, wo die
Zeilen beginnen und enden. Normalerweise ist es dadurch in der
Lage, alle Zeilen außer der einen, die nur teilweise
geschrieben wurde, zurückzugewinnen. Beachten Sie, dass
MyISAM
-Tabellenindizes immer anhand der
Datenzeilen rekonstruiert werden können.
Kennzeichen von statischen Tabellen:
CHAR
-Spalten werden mit Leerzeichen bis
zur Spaltenbreite aufgefüllt.
BINARY
-Spalten werden mit
0x00
-Bytes bis zur Spaltenbreite
aufgefüllt.
Sie sind sehr schnell.
Sie lassen sich leicht zwischenspeichern.
Sie sind nach einem Absturz einfach zu rekonstruieren, da sich die Datensätze an festen Positionen befinden.
Eine Reorganisation der Tabellen ist nicht erforderlich,
es sei denn, Sie löschen sehr viele Zeilen und möchten
dem Betriebssystem den frei gewordenen Speicherplatz
zurückgeben. Hierzu verwenden Sie OPTIMIZE
TABLE
oder myisamchk -r.
Sie belegen normalerweise mehr Speicher als dynamische Tabellen.
Ein dynamisches Speicherformat wird verwendet, wenn eine
MyISAM
-Tabelle Spalten variabler Länge
enthält (VARCHAR
-,
VARBINARY
-, BLOB
- oder
TEXT
-Spalten), oder wenn die Tabelle mit
der Tabellenoption ROW_FORMAT=DYNAMIC
angelegt wurde.
Das dynamische Format ist ein wenig komplizierter als das statische, da jede Zeile einen Header mit einer Längenangabe besitzt. Eine Zeile kann fragmentiert (an nicht-benachbarten Orten gespeichert) werden, wenn sie aufgrund eines Updates länger wird.
Mit OPTIMIZE TABLE
oder myisamchk
-r lassen sich Tabellen defragmentieren. Wenn in
einer Tabelle, die auch Spalten variabler Länge besitzt,
Spalten mit festgelegter Länge vorliegen, die oft
angesprochen oder geändert werden, so empfiehlt es sich, die
Spalten mit variabler Länge in andere Tabellen auszulagern,
um Fragmentierung zu verhindern.
Kennzeichen von dynamischen Tabellen:
Alle String-Spalten sind dynamisch, außer jenen, deren Länge weniger als vier beträgt.
Vor jeder Zeile steht eine Bitmap, die für String-Spalten
angibt, welche Spalten den leeren String enthalten, und
für numerische Spalten, welche Spalten den Wert null
enthalten. Beachten Sie, dass dies keine Spalten mit
NULL
-Werten einbezieht. Wenn eine
String-Spalte nach dem Entfernen angehängter Leerzeichen
die Länge null hat oder eine numerischen Spalte den Wert
Null hat, wird sie in der Bitmap markiert und nicht auf
der Festplatte gespeichert. Nicht-leere Strings werden mit
einem Längen-Byte plus dem String-Inhalt gespeichert.
Sie benötigen normalerweise weniger Festplattenplatz als Festlängen-Tabellen.
Jede Zeile belegt nur so viel Platz wie nötig. Doch wenn
eine Zeile wächst, wird sie aufgespalten, was zu
Fragmentierung führt. Wenn Sie zum Beispiel eine Zeile
mit Daten aktualisieren, die ihre Länge anwachsen lassen,
so wird sie fragmentiert. In diesem Fall kann es
erforderlich sein, gelegentlich OPTIMIZE
TABLE
oder myisamchk -r
auszuführen, um die Leistung zu verbessern.
myisamchk -ei kann Ihnen Statistikdaten
zu Ihrer Tabelle liefern.
Sie sind nach einem Absturz schwerer zu rekonstruieren als Tabellen fester Länge, da die Zeilen unter Umständen in viele Stücke fragmentiert sind und Links (Fragmente) verlorengegangen sein könnten.
Die erwartete Zeilenlänge für dynamische Zeilen wird mit folgendem Ausdruck berechnet:
3 + (number of columns
+ 7) / 8 + (number of char columns
) + (packed size of numeric columns
) + (length of strings
) + (number of NULL columns
+ 7) / 8
Für jeden Link kommen 6 Bytes hinzu. Eine dynamische
Zeile wird immer dann verknüpft (verlinkt), wenn ein
Update sie verlängert. Da jeder neue Link mindestens 20
Bytes hat, passt die nächste Verlängerung wahrscheinlich
noch in denselben Link mit hinein. Wenn nicht, wird ein
neuer Link angelegt. Die Anzahl der Links lässt sich mit
myisamchk -ed feststellen. Alle Links
können mit OPTIMIZE TABLE
oder
myisamchk -r entfernt werden.
Das komprimierte Speicherformat ist ein nur-lesbares Format, das mit myisampack angelegt wird. Komprimierte Tabellen lassen sich mit myisamchk auch wieder dekomprimieren.
Kennzeichen von komprimierten Tabellen:
Sie belegen sehr wenig Platz auf der Festplatte. Dadurch wird der Speicherverbrauch minimiert, was bei der Verwendung langsamer Speichermedien (zum Beispiel CD-ROMs) praktisch ist.
Da jede Zeile separat komprimiert wird, funktioniert der Zugriff mit geringem Aufwand. Der Header für eine Zeile belegt ein bis drei Bytes, abhängig von der längsten Zeile der Tabelle. Jede Spalte wird anders komprimiert und normalerweise gibt es für jede Spalte einen unterschiedlichen Huffman-Baum. Einige der Kompressionsarten sind:
Suffix-Kompression (Komprimierung von Leerzeichen am Ende).
Präfix-Kompression (Komprimierung von Leerzeichen am Anfang).
Zahlen mit dem Wert Null werden in einem Bit gespeichert.
Wenn Werte in einer Integerspalte einen kleinen
Wertebereich haben, wird die Spalte im
kleinstmöglichen Typ gespeichert. So kann zum
Beispiel eine BIGINT
-Spalte (acht
Bytes) als TINYINT
-Spalte (ein
Byte) gespeichert werden, wenn alle ihre Werte
zwischen -128
und
127
betragen.
Hat eine Spalte nur eine kleine Menge möglicher
Werte, wird ihr Datentyp in eine
ENUM
konvertiert.
Eine Spalte kann eine beliebige Kombination der oben beschriebenen Komprimierungen verwenden.
Kann für Spalten fester oder dynamischer Länge verwendet werden.
Zwar wurde das von MySQL für die Datenspeicherung genutzte Dateiformat ausführlich getestet, aber es können immer Umstände auftreten, durch die Datenbanktabellen beschädigt werden. Im Folgenden wird erklärt, wie es dazu kommt und wie man damit umgeht.
Obwohl das Tabellenformat MyISAM
sehr
zuverlässig ist (alle Änderungen, die eine SQL-Anweisung an
einer Tabelle vornimmt, werden geschrieben, ehe die Anweisung
zurückkehrt), können dennoch unter folgenden Umständen
Tabellen beschädigt werden:
Der mysqld-Prozess wird mitten in einem Schreibvorgang abgebrochen.
Der Computer wird unerwartet heruntergefahren (zum Beispiel ausgeschaltet).
Ein Hardware-Versagen.
Während eine Tabelle gerade vom Server modifiziert wird, ändern Sie dieselbe Tabelle mit einem externen Programm (zum Beispiel myisamchk).
Ein Software-Bug im Code von MySQL oder
MyISAM
.
Die folgenden Symptome sind typisch für eine beschädigte Tabelle:
Beim Auswählen von Daten aus der Tabelle bekommen Sie folgende Fehlermeldung:
Incorrect key file for table: '...'. Try to repair it
Anfragen können Zeilen in der Tabelle nicht finden oder liefern unvollständige Ergebnisse zurück.
Mit der CHECK TABLE
-Anweisung können Sie
die Integrität einer MyISAM
-Tabelle
überprüfen und mit REPAIR TABLE
können
Sie sie reparieren, wenn sie beschädigt ist. Wenn
mysqld nicht läuft, können Sie eine
Tabelle auch mit dem Befehlmyisamchk
prüfen oder reparieren Siehe hierzu auch
Abschnitt 13.5.2.3, „CHECK TABLE
“, Abschnitt 13.5.2.6, „REPAIR TABLE
“
und Abschnitt 8.2, „myisamchk — Hilfsprogramm für die Tabellenwartung von MyISAM“.
Werden Ihre Tabellen häufig beschädigt, so sollten Sie nach
den Ursachen forschen. Am wichtigsten ist es, festzustellen,
ob die Tabelle infolge eines Server-Absturzes beschädigt
wurde. Das können Sie leicht daran erkennen, dass im
Fehler-Log eine restarted mysqld
-Nachricht
jüngeren Datums gespeichert ist. Wenn ja, dann wurde die
Tabelle wahrscheinlich durch den Absturz des Servers
beschädigt. Andernfalls kann der Schaden auch im normalen
Betrieb aufgetreten sein. Das wäre dann ein Bug. Versuchen
Sie in diesem Fall, einen reproduzierbaren Testfall zu
erstellen, der das Problem demonstriert. Siehe auch
Abschnitt A.4.2, „Was zu tun ist, wenn MySQL andauernd abstürzt“ und
Abschnitt E.1.6, „Erzeugen eines Testfalls, wenn Sie Tabellenbeschädigung feststellen“.
Jede MyISAM
-Indexdatei
(.MYI
-Datei) besitzt im Header einen
Zähler, an dem sich erkennen lässt, ob eine Tabelle
ordnungsgemäß geschlossen wurde. Liefert CHECK
TABLE
oder myisamchk folgende
Warnung, so bedeutet dies, dass der Zähler nicht mehr
synchron läuft:
clients are using or haven't closed the table properly
Diese Warnung bedeutet zwar nicht unbedingt, dass die Tabelle beschädigt ist, aber Sie sollten zumindest eine Überprüfung vornehmen.
Der Zähler funktioniert folgendermaßen:
Wenn eine Tabelle in MySQL zum ersten Mal geändert wird, wird ein Zähler im Header der Indexdateien inkrementiert.
Bei nachfolgenden Änderungen bleibt der Zähler gleich.
Wenn die letzte Instanz einer Tabelle geschlossen wird
(wegen einer FLUSH TABLES
-Operation
oder weil im Tabellen-Cache kein Platz mehr ist), wird der
Zähler dekrementiert, wenn die Tabelle an irgendeinem
Punkt geändert wurde.
Wenn Sie die Tabelle reparieren oder prüfen und für gut befinden, wird der Zähler wieder auf Null zurückgesetzt.
Um Abstimmungsprobleme mit anderen Prozessen zu verhindern, welche die Tabelle ebenfalls überprüfen, wird der Zähler beim Schließen nicht dekrementiert, wenn er den Wert null hatte.
Anders ausgedrückt: Der Zähler kann unter folgenden Bedingungen nicht mehr synchron sein:
Eine MyISAM
-Tabelle wird ohne
vorheriges LOCK TABLES
und
FLUSH TABLES
kopiert.
MySQL ist zwischen einer Änderung und dem endgültigen Schließen der Tabelle abgestürzt. (Beachten Sie, dass auch in diesem Fall die Tabelle immer noch in Ordnung sein kann, da MySQL zwischen zwei Anweisungen immer alles schreibt.)
Eine Tabelle wurde von myisamchk --recover oder myisamchk --update-state geändert, während sie gleichzeitig von mysqld benutzt wurde.
Mehrere mysqld-Server benutzen die
Tabelle und einer von ihnen hat REPAIR
TABLE
oder CHECK TABLE
auf
ihr ausgeführt, während die anderen Server gerade auf
sie zugriffen. In diesem Fall ist die Verwendung von
CHECK TABLE
sicher, obwohl Sie
vielleicht von anderen Servern eine Warnung bekommen.
REPAIR TABLE
sollten Sie allerdings
vermeiden, denn wenn ein Server die Datendatei durch eine
neue ersetzt, können die anderen Server dies nicht
wissen.
Normalerweise sollte man ein Data Directory nicht mit mehreren Servern gemeinsam nutzen. Weitere Hinweise finden Sie unter Abschnitt 5.13, „Mehrere MySQL-Server auf derselben Maschine laufen lassen“.
InnoDB
: Startoptionen und SystemvariablenInnoDB
-Tabellen erzeugenInnoDB
-DatenbankInnoDB
-FehlerbehandlungInnoDB
-TabellenInnoDB
-Troubleshooting
Mit InnoDB
verfügt MySQL über eine
transaktionssichere (ACID
-konforme)
Speicher-Engine mit Commit-, Rollback- und
Datenwiederherstellungsfähigkeiten. InnoDB
beherrscht sowohl Zeilensperren als auch, ähnlich wie Oracle,
eine konsistente Leseoperation ohne Sperren für
SELECT
-Anweisungen. Diese Features verbessern
die Mehrbenutzertauglichkeit und die Leistung.
InnoDB
benötigt keine Sperreneskalation da
Zeilensperren sehr wenig Platz beanspruchen. Außerdem
unterstützt InnoDB
die FOREIGN
KEY
-Constraints. Sie können
InnoDB
-Tabellen nach Belieben mit Tabellen aus
anderen MySQL-Speicher-Engines mischen, sogar in ein- und
derselben Anweisung.
InnoDB
wurde für maximale Leistung bei der
Verarbeitung großer Datenmengen ausgelegt. Es gibt wohl keine
andere festplattengestützte Speicher-Engine für relationale
Datenbanken, die so effizient mit der CPU umgeht.
Die voll in den MySQL-Server integrierte
InnoDB
-Speicher-Engine hat ihren eigenen
Bufferpool zur Speicherung von Daten und Indizes im Hauptspeicher.
InnoDB
speichert ihre Tabellen und Indizes in
einem Tablespace, der aus mehreren Dateien (oder
Festplattenpartitionen) bestehen kann. Darin unterscheidet sie
sich beispielsweise von MyISAM
, wo jede Tabelle
in separaten Dateien untergebracht wird.
InnoDB
-Tabellen können beliebig groß sein,
selbst auf Betriebssystemen, deren Dateigröße auf 2GB
beschränkt ist.
InnoDB
ist standardmäßig in
Binärdistributionen enthalten. Der Windows Essentials-Installer
macht InnoDB
auf Windows zur
Standard-Speicher-Engine für MySQL.
InnoDB
wird in einer Vielzahl großer
Produktionsdatenbanken eingesetzt, die hohe Anforderungen an die
Leistung stellen. Die bekannte Internet-Newssite Slashdot.org
läuft mit InnoDB
. Mytrix speichert mehr als
1TB Daten in InnoDB
und eine andere Site
verarbeitet durchschnittlich 800 Inserts/Updates pro Sekunde auf
InnoDB
.
InnoDB
unterliegt derselben GNU GPL License
Version 2 (von Juni 1991) wie MySQL. Weitere Informationen über
MySQL-Lizenzen finden Sie unter
http://www.mysql.com/company/legal/licensing/.
Ein spezielles InnoDB
-Forum finden Sie
unter http://forums.mysql.com/list.php?22.
Mit Innobase Oy, dem Produzenten der
InnoDB
-Engine können Sie wie folgt Kontakt
aufnehmen:
Web site: http://www.innodb.com/
Email: <sales@innodb.com>
Phone: +358-9-6969 3250 (office)
+358-40-5617367 (mobile)
Innobase Oy Inc.
World Trade Center Helsinki
Aleksanterinkatu 17
P.O.Box 800
00101 Helsinki
Finland
Die Speicher-Engine InnoDB
ist nach
Voreinstellung aktiv. Wenn Sie keine
InnoDB
-Tabellen verwenden möchten, setzen Sie
die Option skip-innodb
in Ihre
MySQL-Optionsdatei.
Hinweis: Mit
InnoDB
verfügt MySQL über eine
transaktionssichere (ACID
-konforme)
Speicher-Engine mit Commit-, Rollback- und
Datenwiederherstellungsfähigkeiten. Diese
Fähigkeiten stehen jedoch nur dann zur Verfügung, wenn auch das
zugrunde liegende Betriebssystem und die Hardware
vorschriftsgemäß arbeiten.. Viele Betriebssysteme
oder Festplatten-Subsysteme verzögern Schreiboperationen oder
ordnen sie anders an, um die Leistung zu verbessern. Auf manchen
Betriebssystemen kann sogar der Systemaufruf selbst, der
eigentlich warten sollte, bis alle noch ungespeicherten Daten
einer Datei auf die Platte zurückgeschrieben wurden —
fsync()
— bereits zurückkehren, ehe die
Daten in einen dauerhaften Speicher geschrieben wurden. So kann
zum Beispiel ein Betriebssystemabsturz oder ein Stromausfall
Daten, die gerade erst committet wurden, zerstören, oder im
schlimmsten Fall sogar die Datenbank schädigen, indem
Schreiboperationen in die verkehrte Reihenfolge gestellt werden.
Wenn Ihnen an der Integrität Ihrer Daten etwas liegt, sollten Sie
das Verhalten bei Stromausfall testen, ehe Sie etwas in die
Produktionsumgebung einführen. Auf Mac OS X 10.3 und höher
verwendet InnoDB
eine spezielle
fcntl()
-Methode, um Dateien auf die Festplatte
zurückzuschreiben. Unter Linux empfiehlt es sich, den
Write-Back-Cache zu deaktivieren.
Auf ATAPI-Festplatten kann es funktionieren, mit einem Befehl wie
hdparm -W0 /dev/hda
den Write-Back-Cache zu
deaktivieren. Vorsicht! Manche Treiber oder
Festplattencontroller sind nicht in der Lage, den Write-Back-Cache
zu deaktivieren.
Zwei wichtige, von InnoDB
verwalteten
Festplattenressourcen sind die Tablespace-Datendateien und die
Logdateien.
Hinweis: Wenn Sie
Konfigurationsoptionen für InnoDB
angeben,
erzeugt MySQL eine sich selbst erweiternde, 10MB große Datendatei
namens ibdata1
und zwei 5MB große Logdateien
namens ib_logfile0
und
ib_logfile1
im MySQL Data Directory. Um eine
gute Performance zu erzielen, sollten Sie explizit die in den
folgenden Beispielen erwähnten
InnoDB
-Parameter setzen, allerdings natürlich
angepasst an Ihre Hardware und Systemanforderungen.
Die folgenden Beispiele haben nur repräsentativen Charakter. In
Abschnitt 14.2.4, „InnoDB
: Startoptionen und Systemvariablen“ erfahren Sie mehr über die
Konfigurationsparameter für InnoDB
.
Die InnoDB
-Tablespace-Dateien richten Sie ein,
indem Sie die Option innodb_data_file_path
im
[mysqld]
-Abschnitt der Optionsdatei
my.cnf
einstellen. Auf Windows verwenden Sie
stattdessen my.ini
. Der
innodb_data_file_path
sollte eine Liste mit
einer oder mehreren Datendatei-Spezifikationen sein. Mehrere
Datendateien werden durch Semikola
(‘;
’) getrennt:
innodb_data_file_path=datafile_spec1
[;datafile_spec2
]...
Eine Einstellung, die explizit einen Tablespace mit den Standardmerkmalen anlegt, wäre beispielsweise:
[mysqld] innodb_data_file_path=ibdata1:10M:autoextend
Diese Einstellung konfiguriert eine einzige 10MB große Datendatei
namens ibdata1
, die sich selbsttätig
erweitert. Da kein Verzeichnis vorgegeben ist, legt
InnoDB
sie im MySQL Data Directory an.
Größen geben Sie an, indem Sie das Suffix M
für MB oder G
für GB verwenden.
Ein Tablespace mit einer 50MB großen Datendatei fester Größe
namens ibdata1
und einer 50MB großen,
selbsterweiternden Datei namens ibdata2
im
Data Directory kann folgendermaßen konfiguriert werden:
[mysqld] innodb_data_file_path=ibdata1:50M;ibdata2:50M:autoextend
Zur vollständigen Syntax einer Datendateispezifikation gehören Dateiname, Größe und mehrere optionale Attribute:
file_name
:file_size
[:autoextend[:max:max_file_size
]]
autoextend
und die folgenden Attribute können
nur für die letzte Datendatei auf der Zeile
innodb_data_file_path
verwendet werden.
Wenn Sie die Option autoextend
für die letzte
Datendatei angeben, erweitert InnoDB
diese
Datei, sobald sie im Tablespace nicht mehr genug freien Platz hat,
in Inkrementierungsschritten, die auf 8MB voreingestellt sind.
Diese Einstellung kann in der Systemvariablen
innodb_autoextend_increment
geändert werden.
Wenn die Platte vollläuft, müssen Sie eine andere Datendatei oder Festplatte hinzufügen. Eine Anleitung zur Rekonfiguration vorhandener Tablespaces finden Sie in Abschnitt 14.2.7, „Hinzufügen und Entfernen von InnoDB-Daten- und -Logdateien“.
Da InnoDB
die maximale Dateigröße des
Dateisystems nicht kennt, müssen Sie aufpassen, wenn Ihr
Dateisystem nur einen relativ kleinen Wert wie etwa 2GB zulässt.
Eine Maximalgröße für eine selbsterweiternde Datendatei geben
Sie mit dem Attribut max
an. In der folgenden
Konfiguration kann ibdata1
auf bis zu 500MB
anwachsen:
[mysqld] innodb_data_file_path=ibdata1:10M:autoextend:max:500M
InnoDB
legt Ttablespace-Dateien standardmäßig
im MySQL Data Directory an. Um ein anderes Verzeichnis anzugeben,
verwenden Sie die Option innodb_data_home_dir
.
Wenn sie zum Beispiel zwei Dateien namens
ibdata1
und ibdata2
im
Verzeichnis /ibdata
anlegen möchten, müssen
Sie InnoDB
wie folgt konfigurieren:
[mysqld] innodb_data_home_dir = /ibdata innodb_data_file_path=ibdata1:50M;ibdata2:50M:autoextend
Hinweis: Da
InnoDB
keine Verzeichnisse erstellt, müssen
Sie dafür sorgen, dass /ibdata
existiert,
ehe Sie den Server starten. Das gilt auch für
Logdateiverzeichnisse, die Sie konfigurieren. Mit dem Unix- oder
DOS-Befehl mkdir
können Sie alle
erforderlichen Verzeichnisse anlegen.
InnoDB
bildet Verzeichnispfade für
Datendateien, indem es den Wert von
innodb_data_home_dir
mit dem Namen der
Datendatei verkettet, und wenn nötig ein Pfadtrennzeichen
(Schrägstrich oder Backslash) zwischen die Werte setzt. Wenn die
Option innodb_data_home_dir
in
my.cnf
gar nicht auftaucht, ist der
Standardwert das „Punkt“-Verzeichnis
./
, also das MySQL Data Directory. (Der
MySQL-Server macht das Data Directory zum aktuellen
Arbeitsverzeichnis, wenn er seine Arbeit aufnimmt.)
Wenn Sie innodb_data_home_dir
als leeren String
angeben, können Sie absolute Pfade für die Datendateien angeben,
die im Wert von innodb_data_file_path
aufgeführt sind. Das folgende Beispiel ist äquivalent zu dem
vorherigen:
[mysqld] innodb_data_home_dir = innodb_data_file_path=/ibdata/ibdata1:50M;/ibdata/ibdata2:50M:autoextend
Ein einfaches
my.cnf
-Beispiel. Angenommen, Sie
haben einen Computer mit 128MB Arbeitsspeicher und einer
Festplatte. Das folgende Beispiel zeigt mögliche
Konfigurationsparameter in my.cnf
oder
my.ini
für InnoDB
,
einschließlich des autoextend
-Attributs. Das
Beispiel passt zu den meisten Unix- und Windows-Benutzern, die
ihre InnoDB
-Datendateien und -Logdateien nicht
auf mehrere Festplatten verteilen möchten. Es legt eine
selbsterweiternde Datendatei namens ibdata1
und zwei InnoDB
-Logdateien namens
ib_logfile0
und
ib_logfile1
im MySQL Data Directory an.
Außerdem wird die kleine, archivierte
InnoDB
-Logdatei
ib_arch_log_0000000000
, die
InnoDB
automatisch erstellt, ins Data Directory
gespeichert.
[mysqld] # Hier können Sie Ihre übrigen MySQL-Server-Optionen angeben # ... # Datendateien müssen Daten und Indizes speichern können. # Achten Sie auf ausreichend freien Plattenplatz. innodb_data_file_path = ibdata1:10M:autoextend # # Bufferpool-Größe wird auf 50-80% vom Arbeitsspeicher eingestellt innodb_buffer_pool_size=70M innodb_additional_mem_pool_size=10M # # Logdateigröße wird auf 25% der Bufferpool-Größe eingestellt innodb_log_file_size=20M innodb_log_buffer_size=8M # innodb_flush_log_at_trx_commit=1
Achten Sie darauf, dass der MySQL-Server die richtigen Berechtigungen hat, um Dateien im Data Directory anlegen zu können. Generell benötigt der Server Zugriffsrecht auf jedes Verzeichnis, in dem er Daten- oder Logdateien anlegen soll.
Beachten Sie, dass Datendateien in manchen Dateisystemen höchstens 2GB groß sein dürfen. Die kombinierte Größe aller Logdateien muss unter 4GB liegen und die kombinierte Größe der Datendateien mindestens 10MB betragen.
Wenn Sie zum ersten Mal einen InnoDB
-Tablespace
anlegen, starten Sie den MySQL-Server am besten von der
Kommandozeile. Da InnoDB
dann Informationen
über die Datenbankerstellung auf dem Bildschirm ausgibt, können
Sie sehen, was geschieht. Wenn beispielsweise auf Windows
mysqld-max im Verzeichnis C:\Program
Files\MySQL\MySQL Server 5.1\bin
liegt,
können Sie folgendermaßen starten:
C:\> "C:\Program Files\MySQL\MySQL Server 5.1\bin\mysqld-max" --console
Wenn sie keine Serverausgabe an den Bildschirm schicken, müssen
Sie im Fehlerlog nachschauen, welche Meldungen
InnoDB
beim Hochfahren ausgibt.
Unter Abschnitt 14.2.5, „InnoDB-Tablespace erzeugen“ sehen Sie ein Beispiel dafür,
welche Informationen InnoDB
anzeigt.
Die InnoDB
-Optionen können Sie in die
[mysqld]
-Gruppe einer beliebigen Optionsdatei
legen, die Ihr Server beim Hochfahren liest. Speicherorte für
Optionsdateien werden in Abschnitt 4.3.2, „my.cnf-Optionsdateien“
beschrieben.
Wenn Sie MySQL auf Windows mit dem Installations- und
Konfigurationsassistenten installiert haben, liegen die Optionen
in der my.ini
-Datei in Ihrem
MySQL-Installationsverzeichnis. Siehe
Abschnitt 2.3.5.14, „Speicherort der Datei my.ini
“.
Wenn Ihr PC einen Bootloader nutzt und C:
nicht das Bootverzeichnis ist, haben Sie keine andere
Möglichkeit, als die my.ini
-Datei in Ihrem
Windows-Verzeichnis zu benutzen (in der Regel
C:\WINDOWS
oder
C:\WINNT
). Verwenden Sie den Befehl
SET
auf der Kommandozeile eines
Konsolenfensters, um den Wert von WINDIR
auszugeben:
C:\> SET WINDIR
windir=C:\WINDOWS
Wenn Sie sicherstellen möchten, dass
mysqld-Optionen nur aus einer bestimmten Datei
liest, verwenden Sie --defaults-option
beim
Serverstart als erste Option auf der Kommandozeile:
mysqld --defaults-file=your_path_to_my_cnf
Ein
fortgeschrittenesmy.cnf
-Beispiel.
Angenommen, Sie haben einen Linux-Computer mit 2GB RAM und drei
60GB-Festplatten mit den Verzeichnispfaden /
,
/dr2
und /dr3
. Das
folgende Beispiel zeigt, welche Konfigurationsparameter man in
my.cnf
für InnoDB
setzen
könnte.
[mysqld] # Hier können Sie Ihre übrigen MySQL-Server-Optionen angeben # ... innodb_data_home_dir = # # Datendateien müssen Daten und Indizes speichern können. innodb_data_file_path = /ibdata/ibdata1:2000M;/dr2/ibdata/ibdata2:2000M:autoextend # # Setzen Sie die Bufferpool-Größe auf 50-80% des Arbeitsspeichers, # aber achten Sie darauf, dass für Linux x86 die gesamte Speichernutzung < 2GB ist. innodb_buffer_pool_size=1G innodb_additional_mem_pool_size=20M innodb_log_group_home_dir = /dr3/iblogs # innodb_log_files_in_group = 2 # # Setzen Sie die Logdateigröße auf circa 25% der Bufferpool-Größe innodb_log_file_size=250M innodb_log_buffer_size=8M # innodb_flush_log_at_trx_commit=1 innodb_lock_wait_timeout=50 # # Kommentieren Sie die nächsten Zeilen aus, wenn Sie sie nutzen möchten #innodb_thread_concurrency=5
In manchen Fällen steigt die Datenbank-Performance, wenn nicht
alle Daten auf derselben physikalischen Platte liegen. Oft ist es
gut für die Performance, wenn die Logdateien auf einer anderen
Festplatte liegen. Das Beispiel zeigt, wie das geht: Es speichert
zwei Dateien auf verschiedenen Festplatten und legt die Logdateien
auf eine dritte Platte. InnoDB
füllt den
Tablespace beginnend mit der ersten Datendatei. Für einen
schnelleren Zugriff können Sie auch rohe Festplattenpartitionen
(Raw Devices) als InnoDB
-Datendateien
verwenden. Siehe Abschnitt 14.2.3.2, „Verwendung von Raw Devices für den Shared Tablespace“.
Warnung: Auf 32-Bit GNU/Linux x86
dürfen Sie die Arbeitsspeichernutzung nicht zu hoch einstellen.
Wenn glibc
den Prozess-Heap über die
Thread-Stacks hinauswachsen lässt, stürzt der Server ab. Wenn
der Wert des folgenden Ausdrucks 2GB erreicht oder übersteigt,
ist Gefahr in Verzug:
innodb_buffer_pool_size + key_buffer_size + max_connections*(sort_buffer_size+read_buffer_size+binlog_cache_size) + max_connections*2MB
Jeder Thread benutzt einen Stack (oft 2MB, aber in den Binaries
von MySQL AB nur 256KB) und im schlimmsten Fall auch
sort_buffer_size + read_buffer_size
zusätzlichen Arbeitsspeicher.
Indem Sie MySQL selbst kompilieren, können Sie bis zu 64GB
physikalischen Speicher in 32-Bit Windows verwenden. Siehe
Beschreibung von innodb_buffer_pool_awe_mem_mb
in Abschnitt 14.2.4, „InnoDB
: Startoptionen und Systemvariablen“.
Wie werden die anderen mysqld-Serverparameter eingestellt? Die folgenden Werte sind typisch und eignen sich für die meisten Nutzer:
[mysqld]
skip-external-locking
max_connections=200
read_buffer_size=1M
sort_buffer_size=1M
#
# Setzen Sie key_buffer auf 5 - 50% Ihres Arbeitsspeichers, je nachdem, wie
# oft Sie MyISAM-Tabellen benutzen, aber behalten Sie key_buffer_size + InnoDB
# buffer pool size < 80% Ihres Arbeitsspeichers
key_buffer_size=value
Sie können jede InnoDB
-Tabelle und ihre
Indizes in ihrer eigenen Datei speichern. Dieses Feature nennt
man „Multi-Tablespaces“ da im Endeffekt jede
Tabelle ihren eigenen Tablespace bekommt.
Multi-Tablespaces sind praktisch für Benutzer, die bestimmte
Tabellen auf separate physikalische Platten verlagern oder
Backups einzelner Tabellen rasch wiederherstellen möchten, ohne
die Arbeit mit den übrigen InnoDB
-Tabellen
zu unterbrechen.
Aktivieren Sie Multi-Tablespaces mit folgender Zeile im
[mysqld]
-Abschnitt von
my.cnf
:
[mysqld] innodb_file_per_table
Nach dem Server-Neustart speichert InnoDB
jede neu erzeugte Tabelle in einer eigenen Datei
in
dem Datenbankverzeichnis, zu dem die Tabelle gehört. Das
ähnelt dem Vorgehen der
tbl_name
.ibdMyISAM
-Speicher-Engine, doch diese spaltet
die Tabellen in eine Datendatei
und
eine Indexdatei
tbl_name
.MYD
.
Mit tbl_name
.MYIInnoDB
werden Daten und Indizes gemeinsam
in der.ibd
-Datei gespeichert. Die
-Datei
wird wie üblich angelegt.
tbl_name
.frm
Wenn Sie die innodb_file_per_table
-Zeile aus
my.cnf
löschen und den Server neu starten,
erzeugt InnoDB
die Tabellen wieder in Shared
Tablespace-Dateien.
innodb_file_per_table
wirkt sich nur auf eine
einzelne Tabellenerzeugung aus, und beeinflusst nicht den
Zugriff auf bestehende Tabellen. Wenn Sie den Server mit dieser
Option starten, werden neue Tabellen mit
.ibd
-Dateien angelegt, aber alte liegen
immer noch im Shared Tablespace. Entfernen Sie die Option wieder
und starten dann den Server neu, werden die neuen Tabellen im
Shared Tablespace angelegt, aber Tabellen, die mit
Multi-Tablespaces angelegt wurden, bleiben weiterhin
zugänglich.
InnoDB
benötigt immer den Shared Tablespace,
da es sein internes Data Dictionary und seine Undo-Logs dort
speichert. Die .ibd
-Dateien reichen
InnoDB
zum Funktionieren nicht aus.
Hinweis: Sie können
.ibd
-Dateien genau wie
MyISAM
-Tabellendateien nach Belieben zwischen
Datenbankverzeichnissen hin- und herschieben, weil die im Shared
Tablespace von InnoDB
gespeicherte
Tabellendefinition den Datenbanknamen enthält und weil
InnoDB
die Konsistenz von Transaktions-IDs
und Lognummern beibehalten muss.
Um eine .ibd
-Datei und die zugehörige
Tabelle von einer Datenbank in eine andere zu verlagern,
verwenden Sie eine RENAME TABLE
-Anweisung:
RENAME TABLEdb1.tbl_name
TOdb2.tbl_name
;
Wenn Sie über ein „sauberes“ Backup einer
.ibd
-Datei verfügen, können Sie diese in
ihrer angestammten MySQL-Installation folgendermaßen
wiederherstellen:
Geben Sie folgende ALTER TABLE
-Anweisung:
ALTER TABLE tbl_name
DISCARD TABLESPACE;
Vorsicht: Diese Anweisung
löscht die aktuelle .ibd
-Datei.
Speichern Sie die .ibd
-Backup-Datei
zurück in das richtige Datenbankverzeichnis.
Geben Sie folgende ALTER TABLE
-Anweisung:
ALTER TABLE tbl_name
IMPORT TABLESPACE;
Ein „sauberes“ Backup einer
.ibd
-Datei bedeutet in diesem Zusammenhang:
Keine schwebenden Transaktionen in der
.ibd
-Datei.
Keine noch nicht zusammengeführten Insert-Puffer-Einträge
in der .ibd
-Datei.
Purge hat alle zum Löschen vorgemerkten Indexeinträge aus
der .ibd
-Datei entfernt.
mysqld hat alle geänderten Seiten der
.ibd
-Datei aus dem Bufferpool in die
Datei zurückgeschrieben.
Mit folgender Methode können Sie eine saubere
.ibd
-Backup-Datei anlegen:
Beenden Sie alle Aktivitäten des mysqld-Servers und schreiben Sie alle Transaktionen fest.
Warten Sie, bis SHOW ENGINE INNODB STATUS
anzeigt, dass keine Transaktionen mehr in der Datenbank
aktiv sind und der Status des Haupt-Threads von
InnoDB
den Wert Waiting for
server activity
angenommen hat. Dann können Sie
die .ibd
-Datei kopieren.
Eine andere Möglichkeit, an eine saubere Kopie einer
.ibd
-Datei zu kommen, ist die Verwendung
eines kommerziellen InnoDB Hot Backup-Tools:
Legen Sie mit InnoDB Hot Backup ein
Backup der InnoDB
-Installation an.
Starten Sie einen zweiten mysqld-Server
auf dem Backup und lassen Sie ihn die
.ibd
-Dateien im Backup säubern.
Sie können auch rohe Festplattenpartitionen für die Datendateien im Shared Tablespace verwenden. So können sie ungepufferte E/A-Zugriffe ohne Dateisystem-Overhead auf Windows und einigen Unix-Systemen implementieren und die Performance dadurch steigern.
Wenn Sie eine neue Datendatei anlegen, müssen Sie in
innodb_data_file_path
das Schlüsselwort
newraw
direkt hinter die Größe der
Datendatei setzen. Die Partition muss mindestens die angegebene
Größe haben. Beachten Sie, dass 1MB in
InnoDB
1024 × 1024 Bytes sind, während
1MB in Festplattenspezifikationen normalerweise 1.000.000 Bytes
bedeutet.
[mysqld] innodb_data_home_dir= innodb_data_file_path=/dev/hdd1:3Gnewraw;/dev/hdd2:2Gnewraw
Wenn Sie den Server das nächste Mal starten, bemerkt
InnoDB
das Schlüsselwort
newraw
und initialisiert die neue Partition.
Sie dürfen jetzt aber noch keine
InnoDB
-Tabellen ändern oder anlegen, sonst
reinitialisiert InnoDB
beim nächsten
Serverstart die Partition und Ihre Änderungen gehen verloren.
(Als Sicherheitsmaßnahme hindert InnoDB
die
Benutzer daran, irgendwelche Daten zu ändern, wenn eine
Partition mit newraw
definiert wurde.)
Nachdem InnoDB
die neue Partition
initialisiert hat, halten Sie den Server an und ändern
newraw
in der Datendateispezifikation in
raw
um:
[mysqld] innodb_data_home_dir= innodb_data_file_path=/dev/hdd1:5Graw;/dev/hdd2:2Graw
Wenn Sie nun den Server erneut starten, erlaubt
InnoDB
auch Änderungen.
Auf Windows können Sie eine Festplattenpartition folgendermaßen als Datendatei zuweisen:
[mysqld] innodb_data_home_dir= innodb_data_file_path=//./D::10Gnewraw
Das //./
entspricht beim Zugriff auf
physikalische Platten der Windows-Syntax
\\.\
.
Wenn Sie rohe Festplattenpartitionen benutzen, achten Sie bitte darauf, dass ihre Berechtigungseinstellungen dem vom MySQL-Server benutzten Konto auch Lese- und Schreiboperationen gestatten.
Dieser Abschnitt beschreibt die Befehlsoptionen und
Systemvariablen für InnoDB
. Systemvariablen,
die true oder false sein können, werden beim Serverstart entweder
durch Nennung ihres Namens aktiviert oder mit dem Präfix
skip-
deaktiviert. Um beispielsweise
InnoDB
-Prüfsummen ein- oder auszuschalten,
verwenden Sie --innodb_checksums
oder
--skip-innodb_checksums
auf der Kommandozeile,
oder innodb_checksums
oder
skip-innodb_checksums
in einer Optionsdatei.
Systemvariablen, die einen numerischen Wert annehmen, können als
--
auf der Kommandozeile oder als
var_name
=value
in Optionsdateien angegeben werden. Weitere Informationen über
die Angabe von Optionen und Systemvariablen finden Sie unter
Abschnitt 4.3, „Angabe von Programmoptionen“. Viele der Systemvariablen
können zur Laufzeit geändert werden (siehe
Abschnitt 5.2.3.2, „Dynamische Systemvariablen“).
var_name
=value
InnoDB
-Befehlsoptionen:
--innodb
Aktiviert die InnoDB
-Speicher-Engine, wenn
der Server mit InnoDB
-Unterstützung
kompiliert wurde. Mit --skip-innodb
können
Sie InnoDB
deaktivieren.
--innodb_status_file
Veranlasst InnoDB
, eine Datei namens
im MySQL Data Directory anzulegen. <datadir>
/innodb_status.<pid>
InnoDB
schreibt in regelmäßigen Abständen die Ausgabe von
SHOW ENGINE INNODB STATUS
in diese Datei.
InnoDB
-Systemvariablen:
innodb_additional_mem_pool_size
Die Größe des von InnoDB
zum Speichern
von Data Dictionary-Informationen und anderen internen
Datenstrukturen verwendeten Arbeitsspeicherpools in Bytes. Je
mehr Tabellen Ihre Anwendung hat, umso mehr Arbeitsspeicher
müssen Sie hier zuweisen. Wenn InnoDB
in
diesem Pool der Speicher ausgeht, beginnt es, Arbeitsspeicher
vom Betriebssystem abzuzweigen, und gibt Warnmeldungen in das
MySQL-Fehlerlog aus. Der Standardwert beträgt 1MB.
innodb_autoextend_increment
In Inkrementen dieser Größe (in MB) wächst ein selbsterweiternder Tablespace, wenn er vollläuft. Der Standardwert beträgt 8.
innodb_buffer_pool_awe_mem_mb
Die Größe des Bufferpools (in MB), wenn er im AWE-Speicher
liegt. Dies gilt jedoch nur für 32-Bit Windows. Wenn Ihr
32-Bit Windows-Betriebssystem über die so genannten
„Address Windowing Extensions“ mehr als 4GB
Arbeitsspeichergröße unterstützt, können Sie den
InnoDB
-Bufferpool im physikalischen
AWE-Speicher mit dieser Variablen zuweisen. Der
größtmögliche Wert der Variablen beträgt 63000. Ist er
größer als 0, ist innodb_buffer_pool_size
das Fenster im 32-Bit-Adressraum von
mysqld, wobei InnoDB
diesen AWE-Arbeitsspeicher abbildet. Ein guter Wert für
innodb_buffer_pool_size
ist 500MB.
Um den AWE-Speicher nutzen zu können, müssen Sie MySQL neu
kompilieren. Welche Projekteinstellungen derzeit dazu
erforderlich sind, entnehmen Sie bitte der Quelldatei
storage/innobase/os/os0proj.c
.
innodb_buffer_pool_size
Die Größe des Arbeitsspeicherpuffers in Bytes, den
InnoDB
zum Zwischenspeichern der Daten und
Indizes seiner Tabellen benutzt. Je größer Sie diesen Wert
einstellen, umso weniger Festplattenzugriffe sind für den
Zugriff auf die Tabellendaten erforderlich. Für einen
dedizierten Datenbankserver können Sie dies auf 80% des
physikalischen Arbeitsspeichers heraufsetzen. Machen Sie ihn
jedoch nicht zu groß, da ein Wettlauf um den physikalischen
Speicher das Betriebssystem zum Paging veranlassen kann.
innodb_checksums
InnoDB
kann für alle von der Platte
gelesenen Seiten eine Prüfsummenvalidierung verwenden, um
eine zusätzliche Fehlertoleranz gegenüber Schäden an
Hardware oder Datendateien zu gewährleisten. Diese
Validierung ist standardmäßig eingeschaltet. Doch in einigen
wenigen Fällen (zum Beispiel bei der Ausführung von
Benchmarks) ist diese zusätzliche Sicherheitsvorkehrung
überflüssig und kann mit
--skip-innodb-checksums
deaktiviert werden.
innodb_commit_concurrency
Die Anzahl der Threads, die gleichzeitig committen können. Der Wert 0 schaltet die Nebenläufigkeitssteuerung aus.
innodb_concurrency_tickets
Wie viele Threads gleichzeitig auf InnoDB
zugreifen können, hängt von der Einstellung der
innodb_thread_concurrency
-Variablen ab. Ein
Thread wird in eine Schlange gestellt, wenn er auf
InnoDB
zugreifen möchte und das
Nebenläufigkeitslimit bereits erreicht ist. Wenn einem Thread
der Eintritt in InnoDB
erlaubt wird,
bekommt eine Anzahl von „Freifahrscheine“, die
der Anzahl der innodb_concurrency_tickets
entspricht und kann InnoDB
so lange nach
Belieben betreten und verlassen, bis seine Freifahrscheine
aufgebraucht sind. Danach wird der Thread wieder einer
Prüfung unterzogen (und eventuell in die Schlange gestellt),
wenn er das nächste Mal in InnoDB
eintreten möchte.
innodb_data_file_path
Die Pfade und Größen der einzelnen Datendateien. Der
vollständige Verzeichnispfad zu den Datendateien entsteht,
wenn innodb_data_home_dir
mit den
einzelnen, hier angegebenen Pfaden verkettet wird. Die
Dateigrößen werden in MB oder GB (1024MB) durch Anfügen von
M
oder G
an den
Größenwert angegeben. Die Summe der Dateigrößen muss
mindestens 10MB betragen. Wenn Sie keinen
innodb_data_file_path
angeben, wird
standardmäßig eine einzige, selbsterweiternde, 10MB große
Datendatei namens ibdata1
erzeugt. Wie
groß die einzelnen Dateien werden können, entscheidet Ihr
Betriebssystem. Auf Systemen, die große Dateien
unterstützen, können Sie die Dateigröße auf mehr als 4GB
setzen. Sie können auch rohe Festplattenpartitionen als
Datendateien einsetzen. Siehe
Abschnitt 14.2.3.2, „Verwendung von Raw Devices für den Shared Tablespace“.
innodb_data_home_dir
Der gemeinsame Teil des Verzeichnispfads für alle
InnoDB
-Datendateien. Wenn Sie diesen Wert
nicht einstellen, ist das MySQL Data Directory das Ziel. Geben
Sie hier einen leeren String an, so können Sie in
innodb_data_file_path
absolute Dateipfade
verwenden.
innodb_doublewrite
Nach Voreinstellung speichert InnoDB
alle
Daten zweimal, nämlich zuerst in den Doublewrite-Puffer und
dann in die eigentlichen Datendateien. Diese Variable ist
standardmäßig eingeschaltet, kann aber mit der Option
--skip-innodb_doublewrite
ausgeschaltet
werden, wenn Sie Benchmarks ausführen oder Ihnen eine
Top-Performance so wichtig ist, dass Sie sich für
Datenintegrität und mögliche Systemabstürze weniger
interessieren.
innodb_fast_shutdown
Wenn Sie diese Variable auf 0 setzen, führt
InnoDB
vor dem Herunterfahren eine
vollständige Purge-Operation und Verschmelzung der
Insert-Puffer durch. Diese Operationen können Minuten oder im
Extremfall sogar Stunden in Anspruch nehmen. Setzen Sie diese
Variable auf 1, übergeht InnoDB
beim
Herunterfahren diese Operationen. Der Standardwert ist 1. Wenn
Sie ihn auf 2 setzen, leert InnoDB
nur die
Logs und fährt dann kalt herunter, wie bei einem Absturz von
MySQL. Es geht zwar keine committete Transaktion verloren,
aber nach dem nächsten Hochfahren wird eine Wiederherstellung
gefahren. Den Wert 2 können Sie nicht auf NetWare verwenden.
innodb_file_io_threads
Die Anzahl der Dateizugriffs-Threads in
InnoDB
. Normalerweise kann man den
Standardwert 4 beibehalten, aber auf Windows kann eine
größere Zahl die Festplattenzugriffe günstig beeinflussen.
Auf Unix bleibt eine Erhöhung dieses Werts ohne Wirkung, da
InnoDB
immer den Standardwert verwendet.
innodb_file_per_table
Wenn diese Variable eingeschaltet ist, erzeugt
InnoDB
jede neue Tabelle mit ihrer eigenen
.ibd
-Datei zum Speichern von Daten und
Indizes, anstatt im Shared Tablespace. Nach Voreinstellung
werden die Tabellen im Shared Tablespace angelegt. Siehe
Abschnitt 14.2.3.1, „Verwendung von Tabellen-Tablespaces (ein Tablespace pro Tabelle)“.
innodb_flush_log_at_trx_commit
Hat innodb_flush_log_at_trx_commit
den Wert
0, wird einmal pro Sekunde der Logpuffer in die Logdatei
geschrieben und diese auf die Festplatte zurückgespeichert,
doch beim Committen einer Transaktion wird nichts veranlasst.
Ist der Wert 1 (der Standard), wird bei jedem Commit der
Logpuffer in die Logdatei und diese auf die Festplatte
geschrieben. Ist der Wert 2, wird der Puffer bei jedem Commit
in die Datei übertragen, aber diese nicht beim Commit,
sondern einmal pro Sekunde auf die Festplatte
zurückgeschrieben. Beachten Sie jedoch, dass dieser
Schreibvorgang aus Gründen der Prozessplanung in Wirklichkeit
nicht unbedingt exakt einmal pro Sekunde stattfindet.
Der Standardwert dieser Variablen, nämlich 1, ist für die
ACID-Fähigkeit erforderlich. Ein anderer Wert als 1 kann zwar
die Performance steigern, aber um den Preis, dass Sie bei
einem Systemabsturz eine Sekunde an Transaktionen verlieren.
Ist der Wert 0, kann jeder Absturz des
mysqld-Prozesses die Transaktionen der
letzten Sekunde ausradieren. Ist der Wert 2, würde dieser
Datenverlust bei einem Betriebssystemabsturz oder Stromausfall
eintreten. Da allerdings die Wiederherstellungsfunktion von
InnoDB
nicht beeinträchtigt wird, würde
die Crash-Recovery unabhängig vom Wert dieser Variablen
funktionieren. Beachten Sie jedoch, dass viele Betriebssysteme
und einige Festplatten die Flush-to-Disk-Operation
irreführen, indem sie mysqld weismachen,
dass die Daten bereits auf die Festplatte geschrieben wurden,
auch wenn das nicht der Fall ist. Die Dauerhaftigkeit von
Transaktionen ist also selbst mit der Einstellung 1 nicht
gewährleistet, und im schlimmsten Falle kann ein Stromausfall
sogar die InnoDB
-Datenbank beschädigen.
Ein batteriegestützter Festplatten-Cache im
SCSI-Festplattencontroller oder in der Festplatte selbst kann
das Zurückschreiben von Dateien auf die Festplatte
beschleunigen und die Operation sicherer machen. Außerdem
können Sie mit dem Unix-Befehl hdparm das
Caching von Festplatten-Schreibvorgängen in Hardware-Caches
deaktivieren oder einen anderen Hardware-spezifischen Befehl
verwenden.
innodb_flush_method
Die Standardeinstellung fdatasync
sorgt
dafür, dass InnoDB
Daten- und Logdateien
mit fsync()
auf die Festplatte schreibt.
Die Einstellung O_DSYNC
lässt
InnoDB
Logdateien mit
O_SYNC
öffnen und auf die Festplatte
schreiben, aber für Datendateien fsync()
verwenden. Die (auf einigen GNU/Linux-Versionen mögliche)
Einstellung O_DIRECT
veranlasst
InnoDB
, Datendateien mit
O_DIRECT
zu öffnen und Daten- und
Logdateien mit fsync()
auf die Festplatte
schreiben. Beachten Sie, dass InnoDB
die
Funktion fsync()
anstelle von
fdatasync()
benutzt und
O_DSYNC
nicht standardmäßig einsetzt,
weil dies mit vielen Unix-Varianten bereits zu Problemen
geführt hat. Diese Variable ist nur für Unix relevant. Auf
Windows wird immer und unabänderlich
async_unbuffered
zum Zurückschreiben von
Daten auf die Festplatte verwendet.
innodb_force_recovery
Der Crash-Recovery-Modus. Warnung: Diese Variable sollte nur
im Notall, wenn Tabellen aus einer beschädigten Datenbank
gesichert werden sollen, auf 0 gesetzt werden! Die Bedeutung
der möglichen Werte 1 bis 6 wird in
Abschnitt 14.2.8.1, „Erzwingen einer InnoDB
-Wiederherstellung (Recovery)“ erläutert. Als
Sicherheitsmaßnahme verhindert InnoDB
alle
Änderungen an Daten, wenn diese Variable größer als 0 ist.
innodb_lock_wait_timeout
Gibt an, wie viele Sekunden eine
InnoDB
-Transaktion auf eine Sperre wartet,
ehe sie zurückgerollt wird. InnoDB
entdeckt automatisch Transaktions-Deadlocks in seiner eigenen
Sperrentabelle und macht dann die Transaktion rückgängig.
InnoDB
erkennt Sperren, die mit der
LOCK TABLES
-Anweisung gesetzt wurden. Die
Standardeinstellung beträgt 50 Sekunden.
Hinweis: Die größtmögliche Dauerhaftigkeit und Konsistenz
in einer Replikationsumgebung mit InnoDB
und Transaktionen erzielen Sie, wenn Sie in der
my.cnf
-Datei Ihres Masterservers
innodb_flush_log_at_trx_commit=1
und
sync_binlog=1
einstellen.
innodb_locks_unsafe_for_binlog
Diese Variable steuert Next-Key-Locking in
InnoDB
-Suchoperationen und Index-Scans.
Standardmäßig ist diese Variable 0 (deaktiviert) und das
Next-Key-Locking somit eingeschaltet.
Normalerweise benutzt InnoDB
einen
Algorithmus namens Next-Key-Locking.
Zeilensperren funktionieren in InnoDB
folgendermaßen: Wenn ein Tabellenindex durchsucht oder
gescannt wird, errichtet InnoDB
Shared oder
exklusive Sperren auf allen gefundenen Indexeinträgen. Somit
sind die Zeilensperren in Wirklichkeit Sperren auf
Indexeinträgen. Diese Sperren betreffen auch die
„Lücke“, die den Indexeinträgen vorausgeht.
Wenn ein Benutzer eine Shared oder exklusive Sperre auf
Eintrag R eines Index hat, können andere
Benutzer keine neuen Indexeinträge unmittelbar vor
R in diesen Index einfügen. Ist diese
Variable eingeschaltet, wird Next-Key-Locking von
InnoDB
nicht nicht in Suchoperationen oder
Index-Scans verwendet, wohl aber zur Sicherung von
Fremdschlüssel-Constraints und Prüfung auf
Schlüsselduplikate. Das Einschalten dieser Variablen kann
Phantomprobleme verursachen: Angenommen, Sie möchten alle
Kinder der child
-Tabelle, die einen
Identifier-Wert größer 100 haben, lesen und sperren, da Sie
vorhaben, in den ausgewählten Zeilen später eine Spalte zu
ändern:
SELECT * FROM child WHERE id > 100 FOR UPDATE;
Nehmen wir weiterhin an, auf der Spalte id
ist ein Index definiert. Die Anfrage scannt diesen Index ab
dem ersten Eintrag, in dem id
größer als
100 ist. Wenn die auf den Indexeinträgen errichteten Sperren
Einfügungen in den Lücken nicht ausschließen, kann ein
anderer Client eine neue Zeile in die Tabelle einfügen. Wenn
Sie dasselbe SELECT
in derselben
Transaktion ausführen, sehen Sie in der Ergebnismenge eine
neue Zeile. Das führt auch dazu, dass
InnoDB
bei Einfügung neuer Elemente in die
Datenbank keine Serialisierbarkeit garantieren kann. Folglich
gewährleistet InnoDB
bei Einschaltung
dieser Variablen maximal die Isolationsebene READ
COMMITTED
. (Die Konfliktserialisierbarkeit ist aber
nach wie vor garantiert.)
Die Einschaltung dieser Variablen hat noch einen Zusatzeffekt:
InnoDB
sperrt in einem
UPDATE
oder DELETE
nur
die Zeilen, die aktualisiert bzw. gelöscht werden. Dadurch
werden Deadlocks zwar sehr unwahrscheinlich, können aber
immer noch auftreten. Beachten Sie, dass das Einschalten
dieser Variablen nach wie vor nicht erlaubt, dass
UPDATE
andere, ähnliche Operationen (wie
etwa ein anderes UPDATE
) übernimmt, selbst
dann nicht, wenn die beiden Operationen unterschiedliche
Zeilen betreffen. Betrachten Sie das nächste Beispiel, das
mit folgender Tabelle beginnt:
CREATE TABLE A(A INT NOT NULL, B INT) ENGINE = InnoDB; INSERT INTO A VALUES (1,2),(2,3),(3,2),(4,3),(5,2); COMMIT;
Angenommen, ein Client führt folgende Anweisungen aus:
SET AUTOCOMMIT = 0; UPDATE A SET B = 5 WHERE B = 3;
Nehmen wir weiterhin an, dass danach ein anderer Client diese Anweisungen ausführt:
SET AUTOCOMMIT = 0; UPDATE A SET B = 4 WHERE B = 2;
In diesem Fall muss das zweite UPDATE
auf
ein Commit oder Rollback des ersten warten. Das erste
UPDATE
besitzt eine exklusive Sperre auf
Zeile (2,3) und das zweite UPDATE
versucht,
während es die Zeilen scannt, für dieselbe Zeile ebenfalls
eine Sperre zu erwerben, die es jedoch nicht bekommt. Das
liegt daran, dass das zweite UPDATE
zuerst
eine exklusive Sperre auf einer Zeile erwirbt und dann
feststellt ob diese Zeile zur Ergebnismenge gehört. Wenn
nicht, gibt es die überflüssige Sperre wieder frei, sofern
die Variable innodb_locks_unsafe_for_binlog
eingeschaltet ist.
Also führt InnoDB
das
UPDATE
Nummer eins folgendermaßen aus:
x-lock(1,2) unlock(1,2) x-lock(2,3) update(2,3) to (2,5) x-lock(3,2) unlock(3,2) x-lock(4,3) update(4,3) to (4,5) x-lock(5,2) unlock(5,2)
Das zweite UPDATE
führt
InnoDB
so aus:
x-lock(1,2) update(1,2) to (1,4) x-lock(2,3) - wait for query one to commit or rollback
innodb_log_arch_dir
Das Verzeichnis, in dem vollgeschriebene Logdateien archiviert
werden, sofern die Archivierung von Logs eingeschaltet ist.
Wenn ja, so sollte diese Variable auf denselben Wert wie
innodb_log_group_home_dir
gesetzt werden.
Das ist jedoch nicht obligatorisch.
innodb_log_archive
Gibt an, ob InnoDB
-Archivdateien
protokolliert werden sollen. Diese Variable ist nur aus
historischen Gründen noch vorhanden, wird aber nicht benutzt.
Da MySQL die Backup-Recovery anhand seiner eigenen Logdateien
durchführt, gibt es keinen Anlass,
InnoDB
-Logdateien zu archivieren. Die
Variable hat den Standardwert 0.
innodb_log_buffer_size
Gibt in Bytes die Größe des Puffers an, den
InnoDB
benutzt, um Logdateien auf die
Platte zu schreiben. Werte von 1MB bis 8MB sind hier
annehmbar. Der Standardwert ist 1MB. Wenn Sie einen großen
Logpuffer haben, können umfangreiche Transaktionen zuende
laufen, ohne dass das Log vor dem Committen auf die Festplatte
zurückgeschrieben werden muss. In einer Umgebung mit großen
Transaktionen können Sie also Festplattenzugriffe reduzieren,
indem Sie den Logpuffer vergrößern.
innodb_log_file_size
Die Größe jeder Logdatei einer Loggruppe in Bytes. Die
kombinierte Größe der Logdateien muss auf 32-Bit-Rechnren
weniger als 4GB sein. Der Standard ist 5MB. Annehmbar sind
Werte zwischen 1MB und 1/N
-tel der
Größe des Bufferpools, wobei N
die Anzahl der Dateien in einer Loggruppe ist. Je größer der
Wert, umso weniger Checkpoint-Flushing ist im Bufferpool
erforderlich, was wiederum Plattenzugriffe spart. Allerdings
haben große Logdateien auch zur Folge, dass die Recovery nach
einem Absturz langsamer läuft.
innodb_log_files_in_group
Die Anzahl der Logdateien in der Loggruppe.
InnoDB
benutzt die Dateien in zirkulärer
Weise. Der (empfehlenswerte) Standardwert ist 2.
innodb_log_group_home_dir
Der Verzeichnispfad zu den
InnoDB
-Logdateien. Er muss denselben Wert
haben wie innodb_log_arch_dir
. Wenn Sie
keine InnoDB
-Logvariablen angeben, werden
nach Voreinstellung zwei 5MB große Dateien namens
ib_logfile0
und
ib_logfile1
im MySQL Data Directory
angelegt.
innodb_max_dirty_pages_pct
Ein Integer von 0 bis 100. Der Standardwert ist 90. Der
Haupt-Thread in InnoDB
versucht, Seiten aus
dem Bufferpool derart zu schreiben, dass der Prozentsatz von
noch nicht geschriebenen Seiten diesen Wert nicht übersteigt.
innodb_max_purge_lag
Diese Variable gibt an, wie lange INSERT
-,
UPDATE
- und
DELETE
-Operationen aufgeschoben werden,
wenn die Purge-Operationen hinterher hinken (siehe
Abschnitt 14.2.12, „Implementierung der Multiversionierung“). Der Standardwert
ist 0 (keine Verzögerungen).
Das Transaktionssystem von InnoDB
pflegt
eine Liste von Transaktionen, die Indexeinträge anhand von
UPDATE
- oder
DELETE
-Operationen zum Löschen vorgemerkt
haben. Die Länge dieser Liste sei
purge_lag
. Wenn
purge_lag
den Wert
innodb_max_purge_lag
überschreitet, wird
jede INSERT
-, UPDATE
-
und DELETE
-Operation um
((purge_lag
/innodb_max_purge_lag
)×10)–5
Millisekunden aufgeschoben. Diese Verzögerung wird alle zehn
Sekunden am Anfang eines Purge-Batch berechnet. Die
Operationen werden nicht aufgeschoben, wenn Purge nicht laufen
kann, weil eine alte Consistent Read View die zu bereinigenden
Zeilen sehen könnte.
Eine typische Einstellung für eine problematische Arbeitslast wäre 1 Million, wenn die Transaktionen nur etwa 100 Bytes klein sind und wir 100MB unbereinigte Zeilen in unseren Tabellen gestatten können.
innodb_mirrored_log_groups
Gibt an, wie viele identische Kopien von Loggruppen wir für die Datenbank bewahren. Zurzeit sollte dies auf 1 gesetzt werden.
innodb_open_files
Diese Variable ist nur dann von Belang, wenn Sie
Multi-Tablespaces in InnoDB
benutzen. Sie
gibt an, wie viele .ibd
-Dateien
InnoDB
höchstens gleichzeitig offen halten
kann. Der Mindestwert ist 10 und der Standardwert 300.
Die für .ibd
-Dateien verwendeten
Dateideskriptoren sind ausschließlich für
InnoDB
da. Sie haben nichts mit der
Serveroption --open-files-limit
zu tun und
beeinflussen nicht die Arbeit des Tabellen-Caches.
innodb_support_xa
Die Einstellung ON
oder 1 (der Standard)
schaltet die InnoDB
-Unterstützung für
zweiphasigen Commit in XA-Transaktionen ein. Die Aktivierung
von innodb_support_xa
verursacht eine
zusätzliche Schreiboperation auf der Platte zur Vorbereitung
der Transaktion. Wenn Sie sich für XA nicht interessieren,
können Sie diese Variable mit der Einstellung
OFF
oder 0 deaktivieren, was die
Schreibvorgänge auf der Festplatte reduziert und die
InnoDB
-Performance erhöht.
innodb_sync_spin_loops
Gibt an, wie oft ein Thread auf die Freigabe eines
InnoDB
-Mutex wartet, ehe er suspendiert
wird.
innodb_table_locks
InnoDB
beachtet LOCK
TABLES
; MySQL kehrt von LOCK TABLE ..
WRITE
erst zurück, wenn alle anderen Threads alle
ihre Sperren auf der Tabelle freigegeben haben. Der
Standardwert 1 bedeutet, dass LOCK TABLES
InnoDB
veranlasst, eine Tabelle intern zu
sperren. In Anwendungen mit AUTOCOMMIT=1
können die internen Tabellensperren von
InnoDB
Deadlocks verursachen. Sie können
innodb_table_locks=0
in der Datei der
Serveroptionen einstellen, um dieses Problem zu beheben.
innodb_thread_concurrency
InnoDB
versucht, die Anzahl der
nebenläufigen Betriebssystem-Threads innerhalb von
InnoDB
kleiner oder gleich dem in dieser
Variablen festgelegten Höchstwert zu halten. Wenn Sie
Performance-Probleme haben und SHOW ENGINE INNODB
STATUS
zeigt, dass viele Threads auf Semaphoren
warten, haben Sie es vielleicht mit
Thread-„Überlastung“ zu tun. In diesem Fall
setzen sie diese Variable herunter oder herauf. Wenn Ihr
Computer über viele Prozessoren und Festplatten verfügt,
können Sie diesen Wert heraufsetzen, um Ihre Ressourcen
besser auszunutzen. Ein empfehlenswerter Wert ist die Summe
der Prozessoren und Festplatten, über die Ihr System
verfügt. Beträgt der Wert 500 oder mehr, wird die
Nebenläufigkeitsprüfung deaktiviert. Der Standardwert ist 20
und die Nebenläufigkeitsprüfung wird deaktiviert, wenn er
auf größer oder gleich 20 eingestellt wird.
innodb_thread_sleep_delay
Gibt in Mikrosekunden an, wie lange
InnoDB
-Threads schlafen, bevor sie in die
InnoDB
-Schlange eintreten. Der Standardwert
ist 10.000. Der Wert 0 schaltet den Schlaf aus.
sync_binlog
Hat diese Variable einen positiven Wert, synchronisiert der
MySQL-Server sein Binärlog nach jedem
sync_binlog
ten Schreibvorgang mittels
fdatasync()
auf die Festplatte. Im
Autocommit-Modus entsteht pro Anweisung und ansonsten pro
Transaktion ein Eintrag ins Binärlog. Der Standardwert 0
veranlasst keine Festplatten-Synchronisierung. Der Wert 1 ist
am sichersten, da bei einem Absturz nur maximal eine
Anweisung/Transaktion aus dem Binärlog verloren geht. Er ist
aber auch am langsamsten (sofern nicht die Festplatte einen
batteriegestützten Cache hat; dies würde die
Synchronisierung sehr schnell machen).
Angenommen, Sie haben MySQL installiert und die notwendigen
Konfigurationsparameter für InnoDB
in die
Konfigurationsdatei geschrieben. Bevor Sie MySQL nun starten,
müssen Sie überprüfen, ob die Verzeichnisse vorhanden sind, die
Sie für InnoDB
-Daten- und Logdateien angegeben
haben, und ob der MySQL-Server Zugriffsrechte für diese
Verzeichnisse hat. InnoDB
legt keine
Verzeichnisse, sondern nur Dateien an. Prüfen Sie außerdem, ob
Sie genug Platz auf der Festplatte haben, um die Daten- und
Logdateien zu speichern.
Wenn Sie Ihren MySQL-Server mit eingeschaltetem
InnoDB
starten, führen Sie
mysqld am besten auf der Kommandozeile und
nicht mit dem Wrapper mysqld_safe oder als
Windows-Dienst aus. Dann können Sie nämlich die Ausgabe von
mysqld sehen und erkennen, was passiert. Auf
Unix rufen Sie einfach nur mysqld auf und auf
Windows verwenden Sie dafür die
--console
-Option.
Wenn Sie MySQL-Server zum ersten Mal starten, nachdem Sie
InnoDB
in Ihrer Optionsdatei konfiguriert
haben, erzeugt InnoDB
Ihre Daten- und
Logdateien und gibt in etwa folgendes aus:
InnoDB: The first specified datafile /home/heikki/data/ibdata1 did not exist: InnoDB: a new database to be created! InnoDB: Setting file /home/heikki/data/ibdata1 size to 134217728 InnoDB: Database physically writes the file full: wait... InnoDB: datafile /home/heikki/data/ibdata2 did not exist: new to be created InnoDB: Setting file /home/heikki/data/ibdata2 size to 262144000 InnoDB: Database physically writes the file full: wait... InnoDB: Log file /home/heikki/data/logs/ib_logfile0 did not exist: new to be created InnoDB: Setting log file /home/heikki/data/logs/ib_logfile0 size to 5242880 InnoDB: Log file /home/heikki/data/logs/ib_logfile1 did not exist: new to be created InnoDB: Setting log file /home/heikki/data/logs/ib_logfile1 size to 5242880 InnoDB: Doublewrite buffer not found: creating new InnoDB: Doublewrite buffer created InnoDB: Creating foreign key constraint system tables InnoDB: Foreign key constraint system tables created InnoDB: Started mysqld: ready for connections
Jetzt hat InnoDB
seinen Tablespace und seine
Logdateien initialisiert. Sie können mit dem MySQL-Server über
die üblichen MySQL-Clientprogramme wie mysql
Verbindung aufnehmen. Wenn Sie den MySQL-Server mit
mysqladmin shutdown herunterfahren, wird
folgendes ausgegeben:
010321 18:33:34 mysqld: Normal shutdown 010321 18:33:34 mysqld: Shutdown Complete InnoDB: Starting shutdown... InnoDB: Shutdown completed
Sie können die Datendatei und Logverzeichnisse anschauen und die
darin erstellten Dateien erkennen. Das Logverzeichnis enthält
außerdem eine kleine Datei namens
ib_arch_log_0000000000
, die infolge der
Datenbankerstellung entstanden ist, nachdem
InnoDB
die Logarchivierung abgeschaltet hat.
Wenn MySQL erneut gestartet wird, sind die Daten- und Logdateien
bereits vorhanden, sodass die Ausgabe viel knapper ausfällt:
InnoDB: Started mysqld: ready for connections
Wenn Sie die innodb_file_per_table
-Option in
my.cnf
hinzufügen, speichert
InnoDB
jede Tabelle in einer eigenen
.ibd
-Datei in demselben
MySQL-Datenbankverzeichnis, in dem auch die
.frm
-Datei angelegt wurde. Siehe
Abschnitt 14.2.3.1, „Verwendung von Tabellen-Tablespaces (ein Tablespace pro Tabelle)“.
Wenn InnoDB
während einer Dateioperation
einen Betriebssystemfehler ausgibt, hat das Problem in der Regel
eine der folgenden Ursachen:
Sie haben das InnoDB
-Datendatei- oder
Logverzeichnis nicht angelegt.
mysqld verfügt nicht über die notwendigen Berechtigungen, um Dateien in diesen Verzeichnissen anlegen zu können.
mysqld kann die richtige
my.cnf
- oder
my.ini
-Optionsdatei nicht lesen und
weiß deshalb nicht, welche Optionen Sie angegeben haben.
Die Festplatte ist voll oder das Plattenkontingent überschritten.
Da Sie ein Unterverzeichnis angelegt haben, das genauso heißt wie die Datendatei, kann der Name nicht als Dateiname verwendet werden..
Ein Syntaxfehler hat sich in den Wert von
innodb_data_home_dir
oder
innodb_data_file_path
eingeschlichen.
Wenn InnoDB
beim Versuch scheitert, seinen
Tablespace oder seine Logdateien zu initialisieren, sollten Sie
alle von InnoDB
erzeugten Dateien löschen.
Dazu gehören alle ibdata
-Dateien und alle
ib_logfile
-Dateien. Falls Sie bereits
InnoDB
-Tabellen angelegt haben, müssen Sie
auch die .frm
-Dateien (und, wenn Sie
Multi-Tablespaces benutzen, die
.ibd
-Dateien) aus den
MySQL-Datenbankverzeichnissen löschen. Danach können Sie
erneut versuchen, die InnoDB
-Datenbank
anzulegen. Am besten starten Sie den MySQL-Server von einer
Kommandozeile, um erkennen zu können, was geschieht.
Um eine InnoDB
-Tabelle zu erzeugen, müssen Sie
die ENGINE = InnoDB
-Option in der
CREATE TABLE
-Anweisung angeben:
CREATE TABLE customers (a INT, b CHAR (20), INDEX (a)) ENGINE=InnoDB;
Der ältere Begriff TYPE
wird als Synonym für
ENGINE
aus Gründen der Abwärtskompatibilität
zwar weiter unterstützt, aber ENGINE
ist der
bessere Begriff, während TYPE
veraltet ist.
Die Anweisung erzeugt eine Tabelle und einen Index auf der Spalte
a
im InnoDB
-Tablespace, der
aus den in my.cnf
angegebenen Datendateien
besteht. Außerdem legt MySQL die Datei
customers.frm
im Verzeichnis
test
an, das ein Unterverzeichnis des
MySQL-Datenbankverzeichnisses ist. Intern fügt
InnoDB
in das Data Dictionary einen Eintrag
für diese Tabelle ein, der den Datenbanknamen enthält. Wenn
beispielsweise test
die Datenbank ist, in der
die customers
-Tabelle angelegt wurde, heißt
der Eintrag 'test/customers'
. Das bedeutet,
dass Sie in einer anderen Datenbank eine gleichnamige
customers
-Tabelle anlegen können, ohne dass es
in InnoDB
zu Namenskonflikten kommt.
Wieviel Platz im InnoDB
-Tablespace noch frei
ist, sagt Ihnen eine SHOW TABLE
STATUS
-Anweisung für irgendeine
InnoDB
-Tabelle. Der freie Platz im Tablespace
wird im Abschnitt Comment
der Ausgabe von
SHOW TABLE STATUS
angezeigt, beispielsweise:
SHOW TABLE STATUS FROM test LIKE 'customers'
Beachten Sie, dass die Statistikdaten, die SHOW
für InnoDB
-Tabellen anzeigt, nur
Näherungswerte sind. Sie werden für die SQL-Optimierung
eingesetzt. Doch die reservierten Größen für Tabellen und
Indizes in Bytes werden präzise angegeben.
Standardmäßig startet jeder Client, der sich mit dem
MySQL-Server verbindet, mit eingeschaltetem Autocommit-Modus.
Das bedeutet, dass jede SQL-Anweisung direkt bei der Ausführung
automatisch in der Datenbank festgeschrieben wird. Um
Transaktionen zu verwenden, die aus mehreren Anweisungen
bestehen, schalten Sie Autocommit mit der SQL-Anweisung
SET AUTOCOMMIT = 0
aus und verwenden
COMMIT
und ROLLBACK
, um
Ihre Transaktionen zu committen oder zurückzurollen. Wenn Sie
Autocommit eingeschaltet lassen möchten, können Sie Ihre
Transaktionen zwischen START TRANSACTION
und
entweder COMMIT
oder
ROLLBACK
einschließen. Das folgende Beispiel
zeigt zwei Transaktionen: Die erste wird committet und die
zweite zurückgerollt.
shell>mysql test
mysql>CREATE TABLE CUSTOMER (A INT, B CHAR (20), INDEX (A))
->ENGINE=InnoDB;
Query OK, 0 rows affected (0.00 sec) mysql>START TRANSACTION;
Query OK, 0 rows affected (0.00 sec) mysql>INSERT INTO CUSTOMER VALUES (10, 'Heikki');
Query OK, 1 row affected (0.00 sec) mysql>COMMIT;
Query OK, 0 rows affected (0.00 sec) mysql>SET AUTOCOMMIT=0;
Query OK, 0 rows affected (0.00 sec) mysql>INSERT INTO CUSTOMER VALUES (15, 'John');
Query OK, 1 row affected (0.00 sec) mysql>ROLLBACK;
Query OK, 0 rows affected (0.00 sec) mysql>SELECT * FROM CUSTOMER;
+------+--------+ | A | B | +------+--------+ | 10 | Heikki | +------+--------+ 1 row in set (0.00 sec) mysql>
In APIs wie PHP, Perl DBI, JDBC, ODBC oder der
Standardschnittstelle für C-Aufrufe von MySQL können Sie
Anweisungen zur Transaktionssteuerung wie etwa
COMMIT
wie alle anderen SQL-Anweisungen,
beispielsweise SELECT
oder
INSERT
, als Strings an den MySQL-Server
senden. Manche APIs bieten auch eigene, spezielle
Transaktionsfunktionen oder -methoden für Commit und Rollback.
Wichtig: Bitte konvertieren Sie keine Systemtabellen von MySQL
in der mysql
-Datenbank (wie etwa
user
oder host
) in den Typ
InnoDB
. Diese Operation wird nicht
unterstützt. Die Systemtabellen müssen immer den Typ
MyISAM
haben.
Wenn Sie alle Tabellen (außer den Systemtabellen) als
InnoDB
-Tabellen anlegen möchten, fügen Sie
einfach die Zeile
default-storage-engine=innodb
in den
[mysqld]
-Abschnitt Ihrer Serveroptionsdatei
ein.
InnoDB
kennt im Gegensatz zu
MyISAM
keine spezielle Optimierung für eine
separate Indexerstellung. Daher lohnt es sich nicht, zuerst die
Tabellen zu exportieren und importieren und danach die Indizes
anzulegen. Der schnellste Weg, eine Tabelle in
InnoDB
zu ändern, besteht darin, die
Einfügeoperationen direkt auf der
InnoDB
-Tabelle vorzunehmen. Verwenden Sie
also ALTER TABLE … ENGINE=INNODB
oder
erzeugen Sie eine leere InnoDB
-Tabelle mit
denselben Definitionen und fügen Sie darin die Zeilen mit
INSERT INTO … SELECT * FROM …
ein.
Wenn Sie UNIQUE
-Constraints auf
Sekundärschlüsseln haben, können Sie einen Tabellenimport
beschleunigen, indem Sie die Eindeutigkeitsprüfungen während
der Importoperation vorübergehend abschalten:
SET UNIQUE_CHECKS=0;
... import operation ...
SET UNIQUE_CHECKS=1;
Bei großen Tabellen spart das eine Menge Festplattenzugriffe,
da InnoDB
dann seinen Insert-Puffer nutzen
kann, um die Sekundärindexeinträge in einer Batch-Operation zu
schreiben.
Um eine bessere Kontrolle über den Einfügungsprozess zu haben, ist es manchmal besser, Daten einer großen Tabelle in Stücken einzufügen:
INSERT INTO newtable SELECT * FROM oldtable WHERE yourkey > something AND yourkey <= somethingelse;
Wenn alle Datensätze eingefügt wurden, können Sie die Tabellen umbenennen.
Während der Konvertierung großer Tabellen sollten Sie den
InnoDB
-Bufferpool vergrößern, damit weniger
Plattenzugriffe erforderlich sind. Reservieren Sie jedoch nicht
mehr als 80% des physikalischen Arbeitsspeichers. Sie können
auch die InnoDB
-Logdateien vergrößern.
Achten Sie darauf, dass der Tablespace nicht vollläuft:
InnoDB
-Tabellen brauchen auf der Festplatte
viel mehr Speicherplatz als MyISAM
-Tabellen.
Wenn einer ALTER TABLE
-Operation der Platz
ausgeht, startet sie ein Rollback, und das kann Stunden dauern,
wenn es an die Festplatte gebunden ist. Bei Inserts nutzt
InnoDB
den Insert-Puffer, um
Sekundärindexeinträge in Batches mit dem Index
zusammenzuführen. Das spart viele Schreiboperationen auf der
Festplatte. Da für den Rollback kein solcher Mechanismus
existiert, kann dieser 30-mal länger als die
Einfügeoperationen dauern.
Wenn ein Rollback-Prozess außer Kontrolle gerät und Sie keine
wertvollen Daten in Ihrer Datenbank haben, ist es manchmal
ratsam, den Datenbankprozess anzuhalten, anstatt Millionen von
Lese/Schreiboperationen auf der Festplatte abzuwarten. Den
gesamten Vorgang können Sie unter
Abschnitt 14.2.8.1, „Erzwingen einer InnoDB
-Wiederherstellung (Recovery)“ nachlesen.
Wenn Sie eine AUTO_INCREMENT
-Spalte für eine
InnoDB
-Tabelle definieren, enthält der
Tabellen-Handle im InnoDB
-Data Dictionary
einen speziellen Zähler namens Auto-Increment-Zähler, der zur
Zuweisung neuer Werte zu dieser Spalte benutzt wird. Dieser
Zähler wird nur im Arbeitsspeicher und nicht auf der Festplatte
gespeichert.
InnoDB
initialisiert den
Auto-Increment-Zähler für eine Tabelle T
,
die eine AUTO_INCREMENT
-Spalte namens
ai_col
enthält, wie folgt: Nach dem
Serverstart führt InnoDB
für die erste
Einfügung in die Tabelle T
das Äquivalent
folgender Anweisung aus:
SELECT MAX(ai_col) FROM T FOR UPDATE;
InnoDB
inkrementiert den von der Anweisung
abgerufenen Wert um eins und weist ihn der Spalte und dem
Auto-Increment-Zähler für die Tabelle zu. Ist die Tabelle
leer, verwendet InnoDB
den Wert
1
. Wenn ein Benutzer eine SHOW TABLE
STATUS
-Anweisung gibt, die Ausgabe für die Tabelle
T
anzeigt, und der Auto-Increment-Zähler
noch nicht initialisiert wurde, nimmt InnoDB
die Initialisierung vor, inkrementiert aber nicht den Wert und
speichert ihn nicht für spätere Einfügeoperationen. Beachten
Sie, dass für diese Initialisierung eine normale
Schreiboperation mit exklusiver Sperre auf der Tabelle
ausgeführt wird und die Sperre bis zum Ende der Transaktion
aufrecht erhalten bleibt.
Genauso geht InnoDB
vor, wenn ein
Auto-Increment-Zähler für eine neu erzeugte Tabelle
initialisiert wird.
Wenn ein Auto-Increment-Zähler initialisiert wurde und ein
Benutzer nicht ausdrücklich einen Wert für eine
AUTO_INCREMENT
-Spalte angibt, inkrementiert
InnoDB
den Zähler um eins und weist der
Spalte den neuen Wert zu. Wenn der Benutzer eine Zeile einfügt,
die den Spaltenwert explizit angibt, und dieser Wert größer
als der aktuelle Zähler ist, wird der Zähler auf den
angegebenen Spaltenwert gesetzt.
Eventuell treten in der Abfolge der Werte einer
AUTO_INCREMENT
-Spalte Lücken auf, wenn Sie
Transaktionen zurückrollen, die Nummern mithilfe des Zählers
zugewiesen haben.
Wenn der Benutzer in einem INSERT
den Wert
NULL
oder 0
für die
AUTO_INCREMENT
-Spalte angibt, behandelt
InnoDB
die betreffende Zeile, als wäre
überhaupt kein Wert vorhanden, und generiert einen neuen Wert
für sie.
Das Verhalten des Auto-Increment-Mechanismus ist nicht definiert, wenn ein Benutzer der Spalte einen negativen Wert zuweist, oder wenn der Wert die größte Ganzzahl übersteigt, die in dem angegebenen Integertyp gespeichert werden kann.
InnoDB
benutzt für den Zugriff auf den
Auto-Increment-Zähler eine spezielle
AUTO-INC
-Tabellensperre, die bis zum Ende der
laufenden SQL-Anweisung (nicht der Transaktion) gehalten wird.
Die spezielle Strategie zum Aufheben der Sperre wurde
eingefügt, um die Nebenläufigkeit von Einfügeoperationen in
Tabellen mit AUTO_INCREMENT
-Spalten zu
verbessern. Es können nicht zwei Transaktionen zugleich auf
derselben Tabelle eine AUTO-INC
-Sperre
halten.
InnoDB
nutzt den speicherresidenten
Auto-Increment-Zähler so lange, wie der Server läuft. Wird der
Server angehalten und neu gestartet, initialisiert
InnoDB
den Zähler bei der ersten
INSERT
-Operation auf der Tabelle neu, wie
oben bereits beschrieben.
InnoDB
unterstützt die Tabellenoption
AUTO_INCREMENT =
in N
CREATE TABLE
und ALTER
TABLE
-Anweisungen, um den Anfangswert des Zählers
einzustellen oder seinen laufenden Wert zu ändern. Die Wirkung
dieser Option wird durch einen Neustart des Servers aufgehoben,
und zwar aus Gründen, die bereits weiter oben dargestellt
wurden.
InnoDB
unterstützt auch
Fremdschlüssel-Constraints, die in InnoDB
mit folgender Syntax definiert werden:
[CONSTRAINTsymbol
] FOREIGN KEY [id
] (index_col_name
, ...) REFERENCEStbl_name
(index_col_name
, ...) [ON DELETE {RESTRICT | CASCADE | SET NULL | NO ACTION}] [ON UPDATE {RESTRICT | CASCADE | SET NULL | NO ACTION}]
Für Fremdschlüsseldefinitionen gelten folgende Bedingungen:
Beide Tabellen müssen InnoDB
-Tabellen
sein und dürfen keine TEMPORARY
-Tabellen
sein.
In der referenzierenden Tabelle muss ein Index bestehen, in dem die Fremdschlüsselspalten als erste Spalten in derselben Reihenfolge aufgeführt sind. Ein solcher Index wird automatisch auf der referenzierenden Tabelle angelegt, wenn er noch nicht existiert.
In der referenzierten Tabelle muss ein Index bestehen, in dem die referenzierten Spalten als erste Spalten in derselben Reihenfolge aufgeführt sind.
Index-Präfixe auf Fremdschlüsselspalten werden nicht
unterstützt. Dies hat unter anderem zur Folge, dass
BLOB
- und TEXT
-Spalten
nicht in einen Fremdschlüssel eingebunden werden können,
da Indizes auf diesen Spalten immer ein Längenpräfix haben
müssen.
Wenn die CONSTRAINT
-Klausel
verwendet wird, muss der
symbol
symbol
-Wert in der ganzen
Datenbank einzigartig sein. Ist die Klausel nicht angegeben,
erstellt InnoDB
den Namen automatisch.
InnoDB
weist jede INSERT
-
oder UPDATE
-Operation zurück, die versucht,
einen Fremdschlüsselwert in einer Kindtabelle anzulegen, wenn
kein passender Schlüsselwert in der Elterntabelle vorhanden
ist. Was InnoDB
mit einer
INSERT
- oder
UPDATE
-Operation anfängt, die versucht, in
der Elterntabelle einen Schlüsselwert zu ändern oder zu
löschen, zu dem in der Kindtabelle passende Zeilen vorhanden
sind, hängt davon ab, welche
Referenzaktion in den Teilklauseln
ON UPDATE
und ON DELETE
der FOREIGN KEY
-Klausel angegeben ist. Wenn
der Benutzer versucht, in der Elterntabelle eine Zeile zu
ändern oder zu löschen, zu der in der Kindtabelle eine oder
mehr passende Zeilen vorhanden sind, bietet
InnoDB
fünf mögliche Optionen:
CASCADE
: Bei Löschung/Änderung einer
Zeile der Elterntabelle werden automatisch die zugehörigen
Zeilen der Kindtabelle auch gelöscht oder geändert. Es
gibt sowohl ON DELETE CASCADE
als auch
ON UPDATE CASCADE
. Zwischen zwei Tabellen
sollten Sie bitte nicht mehrere ON UPDATE
CASCADE
-Klauseln definieren, die auf derselben
Spalte der Eltern- oder Kindtabelle arbeiten.
SET NULL
: Bei Löschung/Änderung einer
Zeile der Elterntabelle werden automatisch die zugehörigen
Fremdschlüsselspalten der Kindtabelle auf
NULL
gesetzt. Das gilt nur, wenn die
Fremdschlüsselspalten nicht als NOT NULL
definiert sind. Sowohl ON DELETE SET NULL
als auch ON UPDATE SET NULL
wird
unterstützt.
NO ACTION
: Im Standard-SQL bedeutet
NO ACTION
tatsächlich keine
Aktion in dem Sinne, dass jeder Versuch, einen
Primärschlüssel zu löschen oder zu ändern, unterbunden
wird, wenn es dazu einen Fremschlüsselwert in der
referenzierten Tabelle gibt. InnoDB
weist
dann die Lösch- oder Änderungsoperation auf der
Elterntabelle zurück.
RESTRICT
weist die Lösch- oder
Änderungsoperation auf der Elterntabelle zurück.
NO ACTION
und RESTRICT
sind dasselbe wie ein Auslassen der ON
DELETE
- oder ON UPDATE
-Klausel.
(Manche Datenbanksysteme kennen verzögerte Prüfungen
(deferred checks), zu denen auch NO
ACTION
gehört. Da in MySQL
Fremdschlüssel-Constraints jedoch sofort geprüft werden,
sind NO ACTION
und
RESTRICT
hier dasselbe.)
SET DEFAULT
: Diese Aktion wird zwar vom
Parser anerkannt, aber InnoDB
weist
Tabellendefinitionen mit ON DELETE SET
DEFAULT
- oder ON UPDATE SET
DEFAULT
-Klauseln zurück.
Beachten Sie, dass InnoDB
Fremdschlüsselreferenzen in einer Tabelle unterstützt. In
solchen Fällen sind „Datensätze der Kindtabelle“
in Wirklichkeit abhängige Datensätze in derselben Tabelle.
Da InnoDB
Indizes auf Fremdschlüsseln und
referenzierten Schlüsseln verlangt, können
Fremdschlüsselprüfungen schnell durchgeführt werden und
erfordern keinen Tabellen-Scan. Der Index auf den
Fremdschlüsseln wird automatisch angelegt. Das war in manchen
älteren Versionen anders, wo Indizes explizit angelegt werden
mussten, da sonst keine Fremdschlüssel-Constraints angelegt
werden konnten.
Zusammengehörige Spalten im Fremdschlüssel und referenzierten
Schlüssel müssen in InnoDB
ähnliche
Datentypen haben, damit sie sich ohne Typkonvertierung
vergleichen lassen. Die Größe und das Vorzeichen von
Integer-Typen müssen gleich sein. Die Länge von
String-Typen muss nicht unbedingt identisch sein. Wenn Sie
SET NULL
verlangen, dürfen die
Spalten der Kindtabelle nicht als NOT NULL
deklariert sein.
Wenn MySQL die Fehlernummer 1005 aus einer CREATE
TABLE
-Anweisung meldet und die Fehlermeldung sich auf
Fehlernummer 150 bezieht, schlug die Tabellenerstellung fehl,
weil ein Fremdschlüssel-Constraint nicht wohlgeformt war. Wenn
ein ALTER TABLE
scheitert und auf
Fehlernummer 150 verweist, bedeutet dies, dass eine
Fremdschlüsseldefinition für die geänderte Tabelle nicht
korrekt war. Die Anweisung SHOW ENGINE INNODB
STATUS
zeigt eine detaillierte Erklärung des letzten
InnoDB
-Fremdschlüsselfehlers im Server an.
Hinweis:
InnoDB
prüft Fremdschlüssel-Constraints
nicht auf Fremdschlüsseln oder referenzierten Schlüsseln, die
eine NULL
-Spalte enthalten.
Hinweis: Trigger werden von kaskadierenden Fremdschlüsselaktionen derzeit nicht aktiviert.
Abweichung von SQL-Standards:
Wenn mehrere Zeilen in der Elterntabelle denselben
Referenzschlüsselwert haben verhält sich
InnoDB
bei Fremdschlüsselprüfungen so, als
würden die anderen Zeilen der Elterntabelle, also die mit
demselben Schlüsselwert, gar nicht vorhanden. Wenn Sie
beispielsweise einen RESTRICT
-Typ-Constraint
definiert haben und es eine Kindzeile mit mehreren Elternzeilen
gibt, verbietet InnoDB
das Löschen
irgendeiner dieser Elternzeilen.
InnoDB
führt kaskadierende Operationen mit
einem Depth-First-Algorithmus durch, beruhend auf Einträgen in
den Indizes, die zu den Fremdschlüssel-Constraints gehören.
Abweichung von SQL-Standards:
Ein FOREIGN KEY
-Constraint, der einen
Nicht-UNIQUE
-Schlüssel referenziert, ist
nicht Standard-SQL, sondern eine
InnoDB
-Erweiterung dieses Standards.
Abweichung von SQL-Standards:
Wenn ON UPDATE CASCADE
oder ON
UPDATE SET NULL
rekursiv dieselbe
Tabelle ändert, die zuvor während der
kaskadierenden Änderung auch bereits aktualisiert wurde,
verhält es sich wie RESTRICT
. Sie können
also keine rückbezüglichen ON UPDATE
CASCADE
- oder ON UPDATE SET
NULL
-Operationen ausführen. Dadurch sollen
Endlosschleifen wegen kaskadierender Updates verhindert werden.
Andererseits ist ein rückbezügliches ON DELETE SET
NULL
jedoch möglich, nämlich als rückbezügliches
ON DELETE CASCADE
. Die maximale
Schachtelungstiefe von kaskadierenden Operationen beträgt 15
Ebenen.
Abweichung von SQL-Standards:
Wie immer in MySQL prüft InnoDB
für jede
SQL-Anweisung, die viele Zeilen einfügt, löscht oder ändert,
die UNIQUE
- und FOREIGN
KEY
-Constraints zeilenweise. Nach dem SQL-Standard
sollte eigentlich eine verzögerte Prüfung vorgenommen werden,
bei der Constraints erst nach der Verarbeitung der
gesamten SQL-Anweisung geprüft werden. Bis die
verzögerte Constraint-Prüfung auch in
InnoDB
implementiert ist, werden einige Dinge
nicht möglich sein, etwa das Löschen eines Datensatzes, der
sich über einen Fremdschlüssel auf sich selbst bezieht.
In dem folgenden einfachen Beispiel sind
parent
- und child
-Tabellen
über einen Einzelspalten-Fremdschlüssel verbunden:
CREATE TABLE parent (id INT NOT NULL, PRIMARY KEY (id) ) ENGINE=INNODB; CREATE TABLE child (id INT, parent_id INT, INDEX par_ind (parent_id), FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE ) ENGINE=INNODB;
Das folgende, komplexere Beispiel zeigt eine
product_order
-Tabelle, die Fremdschlüssel
für zwei andere Tabellen besitzt. Ein Fremdschlüssel
referenziert einen Zwei-Spalten-Index in der
product
-Tabelle und der andere einen
Ein-Spalten-Index in der customer
-Tabelle:
CREATE TABLE product (category INT NOT NULL, id INT NOT NULL, price DECIMAL, PRIMARY KEY(category, id)) ENGINE=INNODB; CREATE TABLE customer (id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB; CREATE TABLE product_order (no INT NOT NULL AUTO_INCREMENT, product_category INT NOT NULL, product_id INT NOT NULL, customer_id INT NOT NULL, PRIMARY KEY(no), INDEX (product_category, product_id), FOREIGN KEY (product_category, product_id) REFERENCES product(category, id) ON UPDATE CASCADE ON DELETE RESTRICT, INDEX (customer_id), FOREIGN KEY (customer_id) REFERENCES customer(id)) ENGINE=INNODB;
InnoDB
ermöglicht es, mit ALTER
TABLE
einer Tabelle einen Fremdschlüssel-Constraint
hinzuzufügen:
ALTER TABLEtbl_name
ADD [CONSTRAINTsymbol
] FOREIGN KEY [id
] (index_col_name
, ...) REFERENCEStbl_name
(index_col_name
, ...) [ON DELETE {RESTRICT | CASCADE | SET NULL | NO ACTION}] [ON UPDATE {RESTRICT | CASCADE | SET NULL | NO ACTION}]
Bitte legen Sie immer zuerst die
erforderlichen Indizes an. Sie können einer Tabelle
mit ALTER TABLE
auch einen rückbezüglichen
Fremdschlüssel-Constraint hinzufügen.
InnoDB
ermöglicht es überdies, mit
ALTER TABLE
Fremdschlüssel zu löschen:
ALTER TABLEtbl_name
DROP FOREIGN KEYfk_symbol
;
Wenn die FOREIGN KEY
-Klausel bei der
Erzeugung des Fremdschlüssels einen
CONSTRAINT
-Namen enthielt, können Sie beim
Löschen dieses Fremdschlüssels denselben Namen nennen.
Ansonsten wird beim Anlegen des Fremdschlüssels intern ein
fk_symbol
-Wert generiert. Um zum
Löschen eines Fremdschlüssels diesen Symbolwert zu ermitteln,
dient die SHOW CREATE TABLE
-Anweisung. Ein
Beispiel:
mysql>SHOW CREATE TABLE ibtest11c\G
*************************** 1. row *************************** Table: ibtest11c Create Table: CREATE TABLE `ibtest11c` ( `A` int(11) NOT NULL auto_increment, `D` int(11) NOT NULL default '0', `B` varchar(200) NOT NULL default '', `C` varchar(175) default NULL, PRIMARY KEY (`A`,`D`,`B`), KEY `B` (`B`,`C`), KEY `C` (`C`), CONSTRAINT `0_38775` FOREIGN KEY (`A`, `D`) REFERENCES `ibtest11a` (`A`, `D`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `0_38776` FOREIGN KEY (`B`, `C`) REFERENCES `ibtest11a` (`B`, `C`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=INNODB CHARSET=latin1 1 row in set (0.01 sec) mysql>ALTER TABLE ibtest11c DROP FOREIGN KEY `0_38775`;
Sie können einen Fremdschlüssel nicht in separaten Klauseln
derselben ALTER TABLE
-Anweisung anlegen und
löschen. Hierzu sind zwei getrennte Anweisungen erforderlich.
Der Parser von InnoDB
gestattet es, für
Tabellen- und Spaltenbezeichner in einer FOREIGN KEY
… REFERENCES …
-Klausel Backticks als
Anführungszeichen zu verwenden. (Alternativ können doppelte
Anführungszeichen gesetzt werden, wenn der SQL-Modus
ANSI_QUOTES
SQL eingeschaltet ist.) Außerdem
berücksichtigt der InnoDB
-Parser die
Einstellung der Systemvariablen
lower_case_table_names
.
InnoDB
gibt die Fremdschlüsseldefinitionen
einer Tabelle im Rahmen der SHOW CREATE
TABLE
-Anweisung zurück:
SHOW CREATE TABLE tbl_name
;
mysqldump erstellt ebenfalls die korrekten Definitionen der Tabellen in der Dump-Datei und vergisst dabei auch die Fremdschlüssel nicht.
Die Fremdschlüssel-Constraints einer Tabelle können wie folgt angezeigt werden:
SHOW TABLE STATUS FROMdb_name
LIKE 'tbl_name
';
Die Fremdschlüssel-Constraints stehen in der
Comment
-Spalte der Ausgabe.
Bei den Fremdschlüsselprüfungen errichtet
InnoDB
Shared-Sperren auf Zeilenebene auf den
relevanten Datensätzen der Kind- oder Elterntabellen.
InnoDB
prüft die Fremdschlüssel-Constraints
sofort und nicht erst beim Committen der Transaktion.
Damit Dump-Dateien, die Fremdschlüsselbeziehungen haben,
leichter geladen werden können bindet
mysqldump automatisch in die Dump-Ausgabe
eine Anweisung ein, die FOREIGN_KEY_CHECKS
auf 0 setzt. So entstehen keine Probleme mit Tabellen, die beim
Neuladen der Dump-Dateien eigentlich in einer bestimmten
Reihenfolge geladen werden müssen. Diese Variable kann auch
manuell gesetzt werden:
mysql>SET FOREIGN_KEY_CHECKS = 0;
mysql>SOURCE
mysql>dump_file_name
;SET FOREIGN_KEY_CHECKS = 1;
So können Sie die Tabellen in beliebiger Reihenfolge
importieren, wenn die Dump-Datei Tabellen enthält, die
eigentlich gemäß ihrer Fremdschlüssel nicht richtig geordnet
sind. Außerdem wird der Import beschleunigt. Auch in Fällen,
wo Sie Fremdschlüssel-Constraints in LOAD
DATA
- und ALTER TABLE
-Operationen
ignorieren möchten, kann es sinnvoll sein,
FOREIGN_KEY_CHECKS
auf 0 zu setzen.
Mit InnoDB
können Sie eine durch einen
FOREIGN KEY
-Constraint referenzierte Tabelle
nur löschen, wenn SET FOREIGN_KEY_CHECKS=0
eingestellt wurde. Wenn Sie eine Tabelle löschen, werden die in
ihrer Erzeugungsanweisung definierten Constraints mit gelöscht.
Wenn Sie eine gelöschte Tabelle wiederherstellen, muss ihre Definition zu den auf sie bezogenen Fremdschlüssel-Constraints passen. Sie muss die richtigen Spaltennamen und -typen sowie Indizes auf den referenzierten Schlüsseln haben. Ist dies nicht der Fall, gibt MySQL die Fehlernummer 1005 zurück und nennt die Fehlernummer 150 in der Fehlermeldung.
In MySQL funktioniert die Replikation mit
InnoDB
-Tabellen wie mit
MyISAM
-Tabellen. Es sind auch
Replikationsumgebungen möglich, bei denen der Slave eine andere
Speicher-Engine als der Master verwendet. So können Sie
beispielsweise Änderungen, die auf dem Master an einer
InnoDB
-Tabelle vorgenommen werden, in einer
MyISAM
-Tabelle auf dem Slave replizieren.
Um einen neuen Slave für den Master einzurichten, müssen Sie
den InnoDB
-Tablespace und die Logdateien
sowie die .frm
-Dateien der
InnoDB
-Tabellen kopieren und diese Kopien auf
den Slave übertragen. Wenn die Variable
innodb_file_per_table
eingeschaltet ist,
müssen auch die .ibd
-Dateien kopiert
werden. Wie dies genau geht, erfahren Sie unter
Abschnitt 14.2.8, „Sichern und Wiederherstellen einer InnoDB
-Datenbank“.
Wenn Sie den Master oder einen vorhandenen Slave herunterfahren,
können Sie ein kaltes Backup des
InnoDB
-Tablespace und der Logdateien
erstellen und damit einen Slave einrichten. Um einen neuen Slave
aufzusetzen, ohne gleich den Server herunterzufahren, können
Sie das kommerzielle (also kostenpflichtige) Tool
InnoDB
Hot Backup
verwenden.
Die InnoDB
-Replikation wird mit der
LOAD TABLE FROM MASTER
-Anweisung
eingerichtet, die allerdings nur mit
MyISAM
-Tabellen funktioniert. Dafür gibt es
jedoch zwei Workarounds:
Sie können einen Tabellen-Dump auf dem Master vornehmen und die Dump-Datei in den Slave importieren.
Sie können auf dem Master ALTER TABLE
einstellen, bevor Sie die Replikation mit tbl_name
ENGINE=MyISAMLOAD
TABLE
starten, und danach die Master-Tabelle mit
tbl_name
FROM
MASTERALTER TABLE
wieder in
InnoDB
konvertieren. Tun Sie das aber
nicht mit Tabellen, die Fremdschlüsseldefinitionen haben,
da diese Definitionen sonst verlorengehen.
Transaktionen, die auf dem Master scheitern, haben auf die
Replikation keinerlei Auswirkungen. Die Replikation beruht in
MySQL auf dem Binärlog, wo die SQL-Anweisungen, die Daten
modifizieren, festgehalten werden. Eine Transaktion, die
scheitert (beispielsweise wegen Verstoß gegen einen
Fremdschlüssel-Constraint oder weil sie zurückgerollt wird),
gelangt gar nicht ins Binärlog und ergo auch nicht auf die
Slaves. Siehe Abschnitt 13.4.1, „BEGIN/COMMIT/ROLLBACK
“.
Dieser Abschnitt beschreibt, was Sie tun können, wenn Ihr
InnoDB
-Tablespace nicht mehr genug Platz hat
oder Sie die Größe der Logdateien ändern möchten.
Am einfachsten lässt sich der
InnoDB
-Tablespace vergrößern, wenn er von
Anfang an als selbsterweiternd konfiguriert wird. Hierzu geben Sie
das autoextend
-Attribut für die letzte
Datendatei in der Tablespace-Definition an. Dann lässt
InnoDB
diese Datei automatisch in Inkrementen
von 8MB anwachsen, wenn ihr der Platz ausgeht. Die
Inkrement-Größe kann mit der Systemvariablen
innodb_autoextend_increment
in MB eingestellt
werden.
Sie können Ihren Tablespace jedoch auch vergrößern, indem Sie
eine weitere Datendatei hinzufügen. Hierzu müssen sie den
MySQL-Server herunterfahren, der Tablespace-Konfiguration am Ende
von innodb_data_file_path
eine neue Datendatei
hinzufügen, und den Server wieder neu starten.
Wenn die letzte Datendatei mit dem Schlüsselwort
autoextend
definiert worden ist, müssen Sie
bei der Rekonfiguration des Tablespaces berücksichtigen, auf
welches Maß diese letzte Datendatei angewachsen ist. Ermitteln
Sie die Größe der Datendatei, runden Sie sie auf das nächste
Vielfache von 1024 × 1024 bytes (= 1MB) ab und geben Sie
diesen gerundeten Wert explizit in
innodb_data_file_path
an. Dann können Sie eine
weitere Datendatei hinzufügen. Denken Sie daran, dass Sie nur die
letzte Datendatei in innodb_data_file_path
als
selbsterweiternd definieren können.
Nehmen wir beispielsweise an, der Tablespace hat nur eine
selbsterweiternde Datendatei namens ibdata1
:
innodb_data_home_dir = innodb_data_file_path = /ibdata/ibdata1:10M:autoextend
Diese Datei sei nun mit der Zeit auf 988MB angewachsen. Hier sehen Sie die Konfigurationszeile, nachdem die ursprüngliche Datendatei als nicht mehr selbsterweitend definiert und eine neue, selbsterweiternde Datendatei hinzugefügt wurde:
innodb_data_home_dir = innodb_data_file_path = /ibdata/ibdata1:988M;/disk2/ibdata2:50M:autoextend
Wenn Sie der Tablespace-Konfiguration eine neue Datei hinzufügen,
achten Sie darauf, dass diese noch nicht existiert.
InnoDB
wird die Datei erzeugen und
initialisieren, wenn der Server neu gestartet wird.
Gegenwärtig ist es nicht möglich, eine Datendatei aus dem Tablespace zu löschen. Wenn Sie Ihren Tablespace verkleinern möchten, gehen Sie folgendermaßen vor:
Mit mysqldump erstellen Sie einen Dump
aller InnoDB
-Tabellen.
Halten Sie den Server an.
Löschen Sie alle vorhandenen Tablespace-Dateien.
Konfigurieren Sie einen neuen Tablespace.
Starten Sie den Server neu.
Importieren Sie die Dump-Dateien.
Wenn Sie die Anzahl oder Größe Ihrer
InnoDB
-Logdateien ändern möchten, halten Sie
den MySQL-Server an und achten darauf, dass er ohne Fehler
herunterfährt (um zu gewährleisten, dass in den Logs keine Daten
unvollendeter Transaktionen hängen bleiben). Dann kopieren Sie
die Logdateien an einen sicheren Ort, nur für den Fall, dass beim
Herunterfahren etwas schiefgeht und Sie den Tablespace
wiederherstellen müssen. Löschen Sie die alten Logdateien aus
dem Logdateiverzeichnis, ändern Sie die Logdateikonfiguration in
my.cnf
und starten Sie den MySQL-Server neu.
mysqld erkennt beim Hochfahren, dass keine
Logdateien vorhanden sind, und teilt Ihnen mit, dass neue angelegt
werden.
Der Schlüssel zu einem sicheren Datenbankmanagement sind regelmäßige Backups.
InnoDB Hot Backup ist ein Online-Backup-Tool
mit dem Sie eine InnoDB
-Datenbank bei laufendem
Betrieb sichern können. InnoDB Hot Backup
verlangt nicht, dass Sie die Datenbank herunterfahren, setzt keine
Sperren und stört nicht die normale Datenbankverarbeitung.
InnoDB Hot Backup ist ein kostenpflichtiges
(kommerzielles) Add-on, das pro Jahr und pro MySQL-Server-Computer
€390 kostet. Genauere Informationen und Screenshots finden
Sie unter
InnoDB Hot
Backup home page.
Wenn Sie in der Lage sind, Ihren MySQL-Server herunterzufahren,
können Sie auch ein Binär-Backup aller Dateien erstellen, die
InnoDB
zur Verwaltung seiner Tabellen
benötigt. Gehen Sie folgendermaßen vor:
Fahren Sie den MySQL-Server herunter und achten Sie darauf, dass dabei keine Fehler auftreten.
Kopieren Sie alle Datendateien
(ibdata
-Dateien und
.ibd
-Dateien) an einen sicheren Ort.
Kopieren Sie alle ib_logfile
-Dateien an
einen sicheren Ort.
Kopieren Sie Ihre
my.cnf
-Konfigurationsdatei(en) an einen
sicheren Ort.
Kopieren Sie alle .frm
-Dateien für Ihre
InnoDB
-Tabellen an einen sicheren Ort.
Da die Replikation mit InnoDB
-Tabellen
funktioniert, können Sie die Replikationsfähigkeiten von MySQL
nutzen, um in Hochverfügbarkeitsumgebungen eine Kopie Ihrer
Datenbank zu halten.
Zusätzlich zu den Binär-Backups sollten Sie auch regelmäßig
mit mysqldump Dump-Kopien der Tabellen anlegen,
da eine Binärdatei beschädigt werden kann, ohne dass man es
merkt. Dump-Dateien hingegen werde in Textdateien gespeichert, die
für Menschen lesbar sind. So lassen sich Schäden leichter
erkennen. Außerdem ist die Gefahr einer ernsten Datenkorruption
geringer, da das Format einfacher ist.
mysqldump besitzt zudem die
--single-transaction
-Option, mit der Sie
konsistente Snapshots anlegen können, ohne andere Clients
auszusperren.
Um überhaupt in der Lage zu sein, eine
InnoDB
-Datenbank aus dem Binär-Backup
wiederherzustellen, müssen Sie den MySQL-Server mit
eingeschaltetem Binär-Logging betreiben. Dann können Sie das
Binärlog auf die Datenbanksicherung übertragen, um eine
Point-in-Time-Recovery zu fahren:
mysqlbinlog yourhostname
-bin.123 | mysql
Um den MySQL-Server nach einem Absturz wiederherzustellen, müssen
Sie ihn lediglich neu starten. InnoDB
schaut
automatisch in die Logs und versetzt die Datenbank wieder in den
aktuellen Zustand (Roll-forward). InnoDB
rollt
unbestätigte Transaktionen, die zum Zeitpunkt des Absturzes
anhängig waren, automatisch zurück. Während der
Wiederherstellung zeigt mysqld so etwas wie
dieses an:
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 wurde oder Ihre Festplatte abstürzt, müssen Sie ein Backup zur Wiederherstellung verwenden. Sind Schäden aufgetreten, müssen Sie ein Backup suchen, das unbeschädigt ist. Nach der Wiederherstellung der Sicherungsdateien aus dem Backup müssen Sie mit mysqlbinlog und mysql die Änderungen, die nach dem Backup eingetreten sind, aus den Binärlogs anwenden.
In manchen Fällen, in denen Daten beschädigt wurden, reicht es
aus, die beschädigten Tabellen zu dumpen, zu löschen und neu zu
erzeugen. Mit der SQL-Anweisung CHECK TABLE
finden Sie die meisten Schäden heraus, allerdings nicht jede nur
denkbare Art von Datenkorruption. Der
innodb_tablespace_monitor
prüft die
Integrität des Dateiraum-Managements in den Tablespace-Dateien.
Manchmal ist ein scheinbarer Datenbankschaden in Wirklichkeit ein Schaden, den das Betriebssystem an seinem eigenen Datei-Cache verursacht hat, während die Daten auf der Festplatte nach wie vor in Ordnung sind. Am besten versuchen Sie als Erstes, den Computer neu zu starten. So können Sie Fehler eliminieren, die nur scheinbar einen Schaden an Datenbankseiten verursachten.
Wenn Schäden an Datenbankseiten vorhanden sind, sollten Sie
Ihre Tabellen mit SELECT INTO OUTFILE
dumpen.
Normalerweise sind die meisten auf diese Weise geretteten Daten
intakt. Trotzdem kann der Schaden dazu führen, dass
SELECT * FROM
-Anweisungen oder
tbl_name
InnoDB
-Hintergrundoperationen abstürzen oder
sich durchsetzen oder gar die Roll-forward-Recovery von
InnoDB
abstürzen lassen. Sie können einen
Neustart von InnoDB
erzwingen und
gleichzeitig die Hintergrundoperationen anhalten, sodass ein
Tabellen-Dump möglich ist. Zum Beispiel könnten Sie dem
Abschnitt [mysqld]
Ihrer Optionsdatei vor dem
Server-Neustart folgende Zeile hinzufügen:
[mysqld] innodb_force_recovery = 4
Weiter unten erfahren Sie, welche von null verschiedenen Werte
innodb_force_recovery
annehmen kann.
Größere Werte schließen alle Sicherheitsmaßnahmen der
kleineren Werte mit ein. Wenn Sie in der Lage sind, Ihre
Tabellen mit einem Optionswert von höchstens 4 zu dumpen,
können Sie davon ausgehen, dass nur wenige Daten auf einzelnen
beschädigten Seiten verloren gegangen sind. Der Wert 6 ist
schon drastischer: Hier bleiben Datenbankseiten in einem
obsoleten Zustand zurück, was zu zusätzlichen Schäden in
B-Bäumen und anderen Datenbankstrukturen führen kann.
1
(SRV_FORCE_IGNORE_CORRUPT
)
Server soll auch dann weiter laufen, wenn er eine
beschädigte Seite entdeckt. Versuchen Sie, SELECT
* FROM
beschädigte Indexeinträge und Seiten überspringen zu
lassen, da dies den Tabellen-Dump erleichtert.
tbl_name
2
(SRV_FORCE_NO_BACKGROUND
)
Unterbindet den Haupt-Thread. Wenn während der Purge-Operation ein Absturz passiert, wird dieser Recovery-Wert das verhindern.
3
(SRV_FORCE_NO_TRX_UNDO
)
Nach der Recovery keine Transaktionen zurückrollen.
4
(SRV_FORCE_NO_IBUF_MERGE
)
Verhindert auch Merge-Operationen auf Insert-Puffern. Wenn diese einen Absturz herbeiführen würden werden sie nicht durchgeführt. Es wird keine Tabellenstatistik berechnet.
5
(SRV_FORCE_NO_UNDO_LOG_SCAN
)
Beim Starten der Datenbank nicht in die Undo-Logs schauen:
InnoDB
behandelt dann auch
unvollständige Transaktionen als abgeschlossen.
6
(SRV_FORCE_NO_LOG_REDO
)
Keinen Roll-forward der Logs in Verbindung mit der Recovery durchführen.
Selbst bei einer erzwungenen Recovery können Sie Tabellen mit
SELECT
dumpen oder sie mit
DROP
löschen oder mit
CREATE
anlegen. Wenn Sie wissen, dass eine
bestimmte Tabelle beim Zurückrollen einen Absturz verursacht,
können Sie sie löschen. Oder Sie verwenden diese Option, um
ein Rollback anzuhalten, das wegen eines gescheiterten
Massen-Imports oder einer fehlgeschlagenen ALTER
TABLE
-Operation außer Kontrolle geraten ist. Sie
können den mysqld-Prozess anhalten und
innodb_force_recovery
auf
3
setzen, um die Datenbank ohne den Rollback
wieder ans Laufen zu bringen, und dann mit
DROP
die Tabelle löschen, die den
Endlos-Rollback verursacht hatte.
Die Datenbank darf auf keine andere Weise mit einem
von null verschiedenen
innodb_force_recovery
-Wert benutzt
werden. Zur Sicherheit hindert
InnoDB
die Benutzer an
INSERT
-, UPDATE
- und
DELETE
-Operationen, wenn
innodb_force_recovery
größer als 0 ist.
InnoDB
implementiert einen
„fuzzy“ Checkpoint-Mechanismus.
InnoDB
schreibt Datenbankseiten, die
geändert wurden, in kleinen Batches aus dem Bufferpool auf die
Platte. Es ist nicht nötig, den Bufferpool in einem einzigen,
großen Batch auf die Platte zu schreiben, da dies in der Praxis
dazu führen würde, dass Benutzer während des
Checkpointing-Prozesses keine SQL-Anweisungen erteilen können.
Bei einer Recovery sucht InnoDB
ein
Checkpoint-Label in den Logdateien, da es weiß, dass alle
Datenbankmodifikationen, die diesem Label vorausgingen, im
Disk-Image der Datenbank vorhanden sind. Dann scannt
InnoDB
die Logdateien von dem Checkpoint aus
nach vorne durch und wendet die dort protokollierten
Modifikationen auf die Datenbank an.
InnoDB
schreibt Daten in rotierender Weise in
seine Logdateien. Alle committeten Modifikationen, die dazu
führen, dass Datenbankseiten im Bufferpool von den Images auf
der Festplatte abweichen, müssen in den Logdateien vorhanden
sein, falls InnoDB
einmal eine Recovery
durchführen muss. Wenn InnoDB
eine Logdatei
benutzt, muss es also dafür sorgen, dass die
Datenbankseiten-Images auf der Platte die in der für die
Recovery verwendeten Logdatei protokollierten Modifikationen
enthalten. Mit anderen Worten muss InnoDB
einen Checkpoint anlegen, wozu häufig modifizierte
Datenbankseiten auf die Platte zurückgeschrieben werden
müssen.
Dies erklärt auch, warum sehr große Logdateien die Plattenzugriffe beim Checkpointing reduzieren. Oft ist es sinnvoll, die Gesamtgröße der Logdateien auf die Größe des Bufferpools oder sogar einen noch höheren Wert einzustellen. Der Nachteil großer Logdateien: Die Recovery kann dann länger dauern, da mehr Informationen in die Datenbank eingebracht werden müssen.
Auf Windows speichert InnoDB
die Namen von
Datenbanken und Tabellen intern immer in Kleinbuchstaben. Um
Datenbanken in einem Binärformat von Unix auf Windows oder von
Windows auf Unix zu verlagern, sollten Sie alle Tabellen- und
Datenbanknamen auf Kleinschrift umstellen. Dies können Sie ganz
bequem erreichen, indem Sie dem
[mysqld]
-Abschnitt Ihrer
my.cnf
- oder
my.ini
-Datei folgende Zeile hinzufügen,
bevor Sie irgendwelche Datenbanken oder Tabellen erzeugen:
[mysqld] lower_case_table_names=1
Wie MyISAM
-Datendateien sind auch die Daten-
und Logdateien von InnoDB
auf allen
Plattformen, die dasselbe Fließkommazahlenformat haben, binär
kompatibel. Sie können eine InnoDB
-Datenbank
einfach verschieben, indem Sie alle in
Abschnitt 14.2.8, „Sichern und Wiederherstellen einer InnoDB
-Datenbank“ aufgelisteten relevanten Dateien
kopieren. Wenn die Fließkommaformate unterschiedlich sind, aber
keine FLOAT
- oder
DOUBLE
-Datentypen in den Tabellen verwendet
werden, ist die Prozedur dieselbe: Kopieren Sie einfach die
relevanten Dateien. Sind aber sowohl die Formate unterschiedlich,
als auch Fließkommawerte in den Tabellen vorhanden, so müssen
Sie Ihre Tabellen mit mysqldump auf der einen
Maschine dumpen und dann diese Dump-Dateien auf die andere
Maschine übertragen.
Eine bessere Performance erzielen Sie, wenn Sie den Autocommit-Modus beim Datenimport abschalten, immer vorausgesetzt, der Tablespace hat genug Platz für das große Rollback-Segment, das Import-Transaktionen generieren. Den Commit-Befehl geben Sie nachträglich, wenn Sie eine Tabelle oder ein Tabellensegment importiert haben.
InnoDB
-SperrmodiInnoDB
und AUTOCOMMIT
InnoDB
und TRANSACTION ISOLATION
LEVEL
Das Transaktionsmodell von InnoDB
soll die
besten Eigenschaften einer Multiversionierungsdatenbank mit dem
traditionellen zweiphasigen Sperren verbinden.
InnoDB
errichtet Sperren auf Zeilenebene und
führt Anfragen standardmäßig als nicht-sperrende, konsistente
Leseoperationen nach Art von Oracle aus. Die Sperrentabelle in
InnoDB
wird so platzsparend gespeichert, dass
keine Sperreneskalation erforderlich ist: Einzelne Zeilen oder
beliebige Teile der Zeilen in der Datenbank können von mehreren
Benutzern gesperrt werden, ohne dass InnoDB
der
Speicherplatz ausgeht.
InnoDB
implementiert zwei Arten von
Standard-Zeilensperren:
Eine Shared-Sperre (S
) erlaubt
einer Transaktion, eine Zeile (ein Tupel) zu lesen.
Eine exklusive (X
) Sperre erlaubt
einer Transaktion, eine Zeile zu ändern oder zu löschen.
Wenn die Transaktion T1
eine Shared-Sperre
(S
) auf dem Tupel
t
hält, dann
kann einer Forderung einer anderen Transaktion
T2
nach einer
S
-Sperre auf t
sofort stattgegeben werden. Danach halten sowohl
T1
als auch T2
eine
S
-Sperre auf
t
.
kann einer Forderung einer anderen Transaktion
T2
nach einer
X
-Sperre auf t
nicht sofort stattgegeben werden.
Wenn eine Transaktion T1
eine exklusive
(X
) Sperre auf Tupel
t
hält, kann einer Forderung einer anderen
Transaktion T2
nach einer Sperre egal welchen
Typs auf t
nicht sofort stattgegeben werden.
Transaktion T2
muss warten, bis Transaktion
T1
ihre Sperre auf Tupel t
wieder freigegeben hat.
Außerdem unterstützt InnoDB
Multigranuläre Sperren: So können Zeilen
und Tabellensperren koexistieren. Um Sperren auf mehreren
Granularitätsebenen in die Praxis umzusetzen, gibt es die so
genannten Intention Locks. Mithilfe dieser
intendierten Sperren kann eine Transaktion anzeigen, welchen
Sperrentyp (Shared oder exklusiv) sie später auf einer Zeile
einer Tabelle benötigt. In InnoDB
werden
zwei Arten von Intention Locks verwendet (wir gehen davon aus,
dass Transaktion T
eine Sperre des
angegebenen Typs auf Tabelle R
) angefordert
hat:
Intention Shared (IS
):
Transaktion T
will
S
-Sperren einzelner Zeilen von
Tabelle R
erwerben.
Intention Exclusive (IX
):
Transaktion T
will
X
-Sperren auf diesen Zeilen
erwerben.
Das Protokoll für Intention Locking ist wie folgt:
Bevor eine Transaktion eine
S
-Sperre auf einer gegebenen
Zeile errichten kann, muss sie eine
IS
- oder stärkere Sperre auf der
Tabelle, zu der die Zeile gehört, erwerben.
Bevor eine Transaktion eine
X
-Sperre auf einer gegebenen
Zeile errichten kann, muss sie eine
IX
-Sperre auf der Tabelle, zu der
die Zeile gehört, erwerben.
Diese Regeln lassen sich gut in einer Matrix der Sperrtypenkompatibilität zusammenfassen:
X | IX | S | IS | |
X | Konflikt | Konflikt | Konflikt | Konflikt |
IX | Konflikt | Kompatibel | Konflikt | Kompatibel |
S | Konflikt | Konflikt | Kompatibel | Kompatibel |
IS | Konflikt | Kompatibel | Kompatibel | Kompatibel |
Der Sperranforderung einer Transaktion wird stattgegeben, wenn die Sperre mit den bereits vorhandenen Sperren kompatibel ist. Ihr wird nicht stattgegeben, wenn die Sperre mit den vorhandenen in Konflikt treten würde. Dann muss die Transaktion abwarten, bis die andere Sperre, die den Konflikt verursachen würde, freigegeben wurde. Wenn eine Sperranforderung mit einer vorhandenen Sperre in Konflikt tritt und nicht gewährt werden kann, weil sie einen Deadlock verursachen würde, wird ein Fehler ausgelöst.
Somit können Intention Locks nichts blockieren, außer
vielleicht Sperranforderungen für ganze Tabellen
(beispielsweise LOCK TABLES … WRITE
).
IX
und IS
sollen vor allem anzeigen, dass jemand eine Tabellenzeile sperrt
oder sperren wird.
Das folgende Beispiel zeigt, wie ein Fehler ausgelöst wird, wenn eine Sperranforderung einen Deadlock zur Folge haben würde. An dem Beispiel sind zwei Clients beteiligt, nämlich A und B.
Zuerst legt Client A eine Tabelle mit einer Zeile an und beginnt
dann eine Transaktion. Inmitten der Transaktion erwirbt A eine
S
-Sperre auf der Zeile, indem er im
Shared-Modus ein Select auf ihr ausführt:
mysql>CREATE TABLE t (i INT) ENGINE = InnoDB;
Query OK, 0 rows affected (1.07 sec) mysql>INSERT INTO t (i) VALUES(1);
Query OK, 1 row affected (0.09 sec) mysql>START TRANSACTION;
Query OK, 0 rows affected (0.00 sec) mysql>SELECT * FROM t WHERE i = 1 LOCK IN SHARE MODE;
+------+ | i | +------+ | 1 | +------+ 1 row in set (0.10 sec)
Dann beginnt Client B eine Transaktion und versucht, die Zeile aus der Tabelle zu löschen:
mysql>START TRANSACTION;
Query OK, 0 rows affected (0.00 sec) mysql>DELETE FROM t WHERE i = 1;
Die Löschoperation macht eine
X
-Sperre erforderlich. Diese kann
jedoch nicht erteilt werden, da sie mit der
S
-Sperre von Client A inkompatibel
ist. So wird der Request in die Schlange der Sperranforderungen
auf diese Zeile gestellt und Client B wird blockiert.
Endlich versucht Client A ebenfalls, die Zeile aus der Tabelle zu löschen:
mysql> DELETE FROM t WHERE i = 1;
ERROR 1213 (40001): Deadlock found when trying to get lock;
try restarting transaction
Hier tritt der Deadlock auf, da Client A eine
X
-Sperre benötigt, um die Zeile
sperren zu können. Diese Sperre kann jedoch nicht gewährt
werden, da Client B schon vorher eine
X
-Sperre angefordert hatte, und nur
noch darauf wartet, dass A seine
S
-Sperre freigibt. Doch auch die
S
-Sperre von A kann nicht auf eine
X
-Sperre hochgesetzt werden, da B
schon vorher eine X
-Sperre
angefordert hatte. Infolgedessen meldet
InnoDB
dem Client A einen Fehler und gibt
dessen Sperre frei. Jetzt kann der Sperranforderung von Client B
stattgegeben werden und B löscht die Zeile aus der Tabelle.
In InnoDB
findet jegliche Benutzeraktivität
in einer Transaktion statt. Wenn der Autocommit-Modus
eingeschaltet ist, bildet jede SQL-Anweisung eine eigene
Transaktion. Standardmäßig ist dieser Modus immer aktiv, wenn
MySQL hochfährt.
Wird Autocommit mit SET AUTOCOMMIT = 0
ausgeschaltet, gehen wir davon aus, dass der Benutzer immer eine
Transaktion offen hat. Eine COMMIT
- oder
ROLLBACK
-Anweisung beendet die laufende
Transaktion und eine neue beginnt. COMMIT
bedeutet, dass die Änderungen, die in der aktuellen Transaktion
vorgenommen wurden, in der Datenbank dauerhaft festgeschrieben
und für andere Benutzer sichtbar gemacht werden. Eine
ROLLBACK
-Anweisung hingegen macht alle
Änderungen in der aktuellen Transaktion rückgängig. Beide
Anweisungen geben auch alle InnoDB
-Sperren
frei, die in der Transaktion gesetzt wurden.
Wenn auf einer Verbindung Autocommit eingeschaltet ist, kann der
Benutzer dennoch Transaktionen aus mehreren Anweisungen
ausführen, wenn er sie mit einem expliziten START
TRANSACTION
oder BEGIN
einleitet
und mit COMMIT
oder
ROLLBACK
beendet.
Was die Transaktionsisolationsebenen von SQL:1992 angeht, so hat
InnoDB
die Standardeinstellung
REPEATABLE READ
. InnoDB
bietet alle vier Transaktionsisolationsebenen des SQL-Standards.
Die Standardisolationsebene können Sie mit der
--transaction-isolation
-Option auf der
Kommandozeile oder in einer Optionsdatei einstellen. So können
Sie beispielsweise im [mysqld]
-Abschnitt
einer Optionsdatei folgendes eintragen:
[mysqld] transaction-isolation = {READ-UNCOMMITTED | READ-COMMITTED | REPEATABLE-READ | SERIALIZABLE}
Ein Benutzer kann die Isolationsebene für eine einzelne Session
oder alle neuen Verbindungen mit der SET
TRANSACTION
-Anweisung einstellen, die folgende Syntax
hat:
SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}
Beachten Sie, dass in den Namen der Ebenen in der
--transaction-isolation
-Option Bindestriche
verwendet werden, aber nicht in der SET
TRANSACTION
-Anweisung.
Standardmäßig wird die Isolationsebene immer für die nächste
(noch nicht begonnene) Transaktion eingestellt. Mit dem
Schlüsselwort GLOBAL
stellt die Anweisung
die Standard-Transaktionsebene global für alle neuen
Verbindungen ein, die ab diesem Punkt aufgebaut werden (aber
nicht für die schon bestehenden Verbindungen). Um dies zu tun,
benötigen Sie die SUPER
-Berechtigung. Das
Schlüsselwort SESSION
stellt die
Standard-Transaktionsebene für alle zukünftigen Transaktionen
auf aktuellen Verbindung ein.
Jeder Client kann die Session-Isolationsebene (sogar inmitten einer Transaktion), oder die Isolationsebene der nächsten Transaktion haben.
Ob die Transaktionsisolationsebene global oder für die einzelne
Session eingestellt wurde, können Sie anhand der
Systemvariablen tx_isolation
mit folgenden
Anweisungen ermitteln:
SELECT @@global.tx_isolation; SELECT @@tx_isolation;
Für Zeilensperren verwendet InnoDB
Next-Key-Locking. Das bedeutet, dass InnoDB
zusätzlich zu den Indexeinträgen auch die
„Lücke“ vor einem Indexeintrag sperrt, um zu
verhindern, dass andere Benutzer gerade dort etwas einfügen.
Eine Next-Key-Sperre ist eine Sperre, die nicht nur den
Indexeintrag, sondern auch die Lücke vor diesem blockiert. Eine
Gap-Sperre ist eine Sperre, die lediglich die Lücke vor einem
Indexeintrag betrifft.
Im Folgenden werden die Isolationsebenen in
InnoDB
genauer erläutert:
READ UNCOMMITTED
SELECT
-Anweisungen werden ohne Sperren
ausgeführt, wobei es jedoch möglich ist, dass eine ältere
Version eines Eintrags verwendet wird. Also sind
Leseoperationen mit dieser Isolationsebene nicht konsistent
(man bezeichnet dies auch als „Dirty Read“).
Ansonsten funktioniert diese Isolationsebene wie
READ COMMITTED
.
READ COMMITTED
Eine Oracle-ähnliche Isolationsebene. Alle SELECT
… FOR UPDATE
- und SELECT …
LOCK IN SHARE MODE
-Anweisungen sperren nur die
Indexeinträge und nicht die Lücken davor. So können neben
den gesperrten Einträgen nach Belieben neue Datensätze
eingefügt werden. UPDATE
- und
DELETE
-Anweisungen, die einen eindeutigen
Index mit einer eindeutigen Suchbedingung verwenden, können
nur den gefundenen Indexeintrag, aber nicht die Lücke
davor, sperren. In Bereichs-UPDATE
s und
DELETE
s muss InnoDB
Next-Key- oder Gap-Sperren setzen und Einfügungen anderer
Benutzer in die Lücken, die in dem Bereich liegen,
blockieren. Dies ist erforderlich, da die Replikation und
Recovery von MysQL nur funktioniert, wenn keine
„Phantomzeilen“ vorhanden sind.
Konsistente Leseoperationen verhalten sich wie in Oracle: Jede konsistente Leseoperation, sogar innerhalb derselben Transaktion, setzt und liest ihren eigenen, frischen Snapshot. Siehe Abschnitt 14.2.10.4, „Konsistentes Lesen“.
REPEATABLE READ
Die Standardisolationsebene von InnoDB
.
SELECT … FOR UPDATE
-,
SELECT … LOCK IN SHARE MODE
-,
UPDATE
- und
DELETE
-Anweisungen, die einen eindeutigen
Index mit einer eindeutigen Suchbedingung verwenden, sperren
nur den gefundenen Indexeintrag, aber nicht die Lücke
davor. Für andere Suchbedingungen setzen diese Operationen
Next-Key-Locking ein oder sperren den durchsuchten
Indexbereich mit Next-Key- oder Gap-Sperren und blockieren
dadurch Einfügungen anderer Benutzer.
In konsistenten Leseoperationen gibt es einen wichtigen
Unterschied zur Isolationsebene READ
COMMITTED
: Alle konsistenten Leseoperationen
innerhalb derselben Transaktion lesen denselben Snapshot,
der von der ersten Leseoperation eingerichtet wurde. Daraus
folgt: Wenn Sie mehrere einfache
SELECT
-Anweisungen innerhalb derselben
Transaktion erteilen, sind diese
SELECT
-Anweisungen auch untereinander
konsistent. Siehe Abschnitt 14.2.10.4, „Konsistentes Lesen“.
SERIALIZABLE
Wie REPEATABLE READ
, nur dass
InnoDB
implizit alle einfachen
SELECT
-Anweisungen zu SELECT
… LOCK IN SHARE MODE
committet.
Bei einer konsistenten Leseoperation verwendet
InnoDB
Multiversionierung, um einer Anfrage
einen Snapshot der Datenbank für einen bestimmten Zeitpunkt
(Point-in-Time) zu präsentieren. Die Anfrage erkennt die
Änderungen, die Transaktionen vor diesem Zeitpunkt vorgenommen
hatten, aber keine Änderungen späterer oder noch unvollendeter
Transaktionen. Die Ausnahme: Änderungen von früheren
Anweisungen in derselben Transaktion sind für die Anweisung
sichtbar.
Wenn Sie die Standardisolationsebene REPEATABLE
READ
benutzen, lesen alle konsistenten Leseoperationen
innerhalb derselben Transaktion den Snapshot, der durch die
erste Leseoperation in dieser Transaktion erzeugt wurde. Einen
frischeren Snapshot für Ihre Anfragen erhalten Sie, indem Sie
die laufende Transaktion committen und danach neue Anfragen
absetzen.
Konsistentes Lesen ist der Standardmodus, in dem
InnoDB
SELECT
-Anfragen auf
den Isolationsebenenen READ COMMITTED
und
REPEATABLE READ
verarbeitet. Konsistentes
Lesen errichtet keine Sperren auf den benutzten Tabellen, sodass
andere Benutzer diese Tabellen nach Belieben modifizieren
können, während eine konsistente Leseoperation auf ihnen
abläuft.
Beachten Sie, dass konsistente Leseoperationen nicht mit
DROP TABLE
und ALTER TABLE
funktionieren. Mit DROP TABLE
nicht, weil
MySQL eine Tabelle, die gelöscht wurde, nicht mehr benutzen
kann und InnoDB
sie zerstört, und mit
ALTER TABLE
nicht, weil dieser Befehl
innerhalb einer Transaktion ausgeführt wird, die eine neue
Tabelle anlegt und Zeilen aus der alten Tabelle in sie einfügt.
Wenn Sie die konsistente Leseoperation neu ausführen, kann sie
die Zeilen der neuen Tabelle nicht erkennen, da sie in einer
Transaktion eingefügt wurden, die in dem von der konsistenten
Leseoperation verwendeten Snapshot nicht sichtbar war.
In manchen Fällen ist eine konsistente Leseoperation nicht das
Richtige. Vielleicht möchten Sie ja eine neue Zeile in Ihre
child
-Tabelle einfügen und dabei
sicherstellen, dass das Kind in der Tabelle
parent
auch wirklich ein Elternteil hat. Das
folgende Beispiel zeigt, wie Sie referenzielle Integrität in
Ihren Anwendungscode implementieren können.
Angenommen, Sie verwenden eine konsistente Leseoperation, um die
Tabelle parent
zu lesen, und sehen auch
tatsächlich die Elternzeile des Kindes in der Tabelle. Können
Sie die Kindzeile nun auch beruhigt in die Tabelle
child
einfügen? Nein, denn es kann ja sein,
dass irgendein anderer Benutzer zwischenzeitlich die Elternzeile
aus der Tabelle parent
gelöscht hat, ohne
dass Sie es merkten.
Die Lösung: Sie führen das SELECT
in dem
Sperrmodus LOCK IN SHARE MODE
aus:
SELECT * FROM parent WHERE NAME = 'Jones' LOCK IN SHARE MODE;
Wird eine Leseoperation im Share-Modus ausgeführt, so liest sie
die aktuellsten verfügbaren Daten und errichtet eine
Shared-Sperre auf den Zeilen, die sie liest. Diese verhindert,
dass andere Benutzer die Zeile ändern oder löschen. Wenn die
Daten zu einer noch unvollendeten Transaktion einer anderen
Clientverbindung gehören, warten wir, bis die Transaktion
committet ist. wenn wir gesehen haben, dass die obige Anfrage
den Parent 'Jones'
zurückgibt, können wir
unseren Eintrag beruhigt in die child
-Tabelle
einfügen und unsere Transaktion committen.
Betrachten wir ein anderes Beispiel: Wir haben in der Tabelle
child_codes
ein Zählerfeld eines
Integer-Typs, das wir dazu benutzen, jedem Kind, das der
child
-Tabelle hinzugefügt wird, eine
eindeutige Kennnummer zu geben. Da wäre es natürlich keine
gute Idee, den Wert des Zählers mit einer konsistenten
Leseoperation oder im Shared-Modus zu lesen, da zwei
Datenbanknutzer dann vielleicht denselben Zählerwert sehen und
einen Fehler wegen Schlüsselduplikaten auslösen, sofern sie
versuchen, Kindeinträge mit derselben Nummer in die Tabelle
einzufügen.
Hier ist LOCK IN SHARE MODE
keine gute
Lösung. Denn wenn zwei Benutzer gleichzeitig den Zähler lesen,
könnte mindestens einer von ihnen in einen Deadlock geraten,
wenn er versucht, den Zähler zu aktualisieren.
Hier haben Sie zwei gute Möglichkeiten, das Lesen und
Inkrementieren des Zählers zu implementieren: (1) Sie
inkrementierten zuerst den Zähler um 1 und führen erst dann
die Leseoperation durch, oder (2) Sie lesen den Zähler zuerst
im Sperrmodus FOR UPDATE
und inkrementieren
ihn danach. Der zweite Ansatz kann folgendermaßen implementiert
werden:
SELECT counter_field FROM child_codes FOR UPDATE; UPDATE child_codes SET counter_field = counter_field + 1;
Ein SELECT … FOR UPDATE
liest die
neuesten verfügbaren Daten und errichtet eine exklusive Sperre
auf jeder Zeile, die es liest. Somit setzt es dieselben Sperren,
die auch ein Searched SQL UPDATE
auf den
Zeilen erwerben würde.
Die obige Beschreibung ist nur ein Beispiel dafür, wie
SELECT … FOR UPDATE
funktioniert. In
MySQL können Sie einen eindeutigen Identifier grundsätzlich
mit nur einem einzigen Tabellenzugriff generieren:
UPDATE child_codes SET counter_field = LAST_INSERT_ID(counter_field + 1); SELECT LAST_INSERT_ID();
Die SELECT
-Anweisung ruft nur die
Identifier-Information ab (die für die aktuelle Verbindung
spezifisch ist). Sie greift auf keine Tabellen zu.
Sperren von IN SHARE MODE
- und FOR
UPDATE
-Leseoperationen werden freigegeben, wenn die
Transaktion committet oder zurückgerollt wird.
In Zeilensperren verwendet InnoDB
einen
Algorithmus namens Next-Key-Locking.
InnoDB
sperrt Zeilen so, dass es beim
Durchsuchen oder Scannen eines Tabellenindex Shared- oder
exklusive Sperren auf den gefundenen Indexeinträgen errichtet.
Also sind die Zeilensperren in Wirklichkeit
Indexeintragssperren.
Die Sperren, die InnoDB
auf Indexeinträgen
errichtet, betreffen auch die „Lücke“ vor den
Einträgen. Wenn ein Benutzer eine Shared- oder exklusive Sperre
auf Eintrag R
eines Index hält, kann kein
anderer Benutzer unmittelbar vor R
einen
Eintrag in die Indexreihenfolge einfügen. Durch dieses so
genannte „Gap-Locking“ wird das
„Phantom-Problem“ gelöst. Angenommen, Sie wollten
alle Kinder der child
-Tabelle lesen und
sperren, deren Identifier-Wert größer als 100 ist, um später
eine Spalte in den ausgewählten Zeilen zu ändern:
SELECT * FROM child WHERE id > 100 FOR UPDATE;
Angenommen, Sie haben einen Index auf der Spalte
id
. Die Anfrage scannt diesen Index ab dem
ersten Eintrag, dessen id
größer als 100
ist. Wenn die Sperren auf den Indexeinträgen Einfügungen in
die Lücken nicht verhindern würden, könnte in der
Zwischenzeit eine neue Zeile in die Tabelle eingefügt werden.
Wenn Sie dasselbe SELECT
in derselben
Transaktion ein zweites Mal ausführten, hätten Sie plötzlich
eine zusätzliche Zeile in der Ergebnismenge. Das verstößt
aber gegen das Isolationsprinzip von Transaktionen: Eine
Transaktion muss so ablaufen, dass sich die Daten, die sie
liest, während ihrer Laufzeit nicht ändern können. Wenn wir
eine Zeilenmenge als ein Datenelement betrachten, würde die
neue „Phantomzeile“ dieses Isolationsprinzip
verletzen.
Wenn InnoDB
einen Index scannt, kann es auch
die Lücke hinter dem letzten Eintrag im Index sperren. Genau
dies geschieht auch im obigen Beispiel: Die von
InnoDB
gesetzten Sperren verhindern jede
Einfügung in die Tabelle an Stellen, deren
id
größer als 100 ist.
Mit Next-Key-Locking können Sie eine Eindeutigkeitsprüfung in Ihrer Anwendung implementieren. Wenn Sie Ihre Daten im Share-Modus lesen und kein Duplikat der Zeile sehen, die Sie einfügen möchten, dann können Sie die Einfügung beruhigt ausführen und wissen, dass die Next-Key-Sperre auf dem Nachfolger Ihrer Zeile verhindert, dass in der Zwischenzeit jemand anders ein Duplikat Ihrer Zeile einfügt.
Angenommen, Sie verwenden die Standardisolationsebene
REPEATABLE READ
. Wenn Sie eine konsistente
Leseoperation ausführen (also eine normale
SELECT
-Anweisung), weist
InnoDB
Ihrer Transaktion einen Zeitpunkt zu,
an dem Ihre Anfrage die Datenbank sieht. Wenn eine andere
Transaktion nach diesem Zeitpunkt eine Zeile löscht und
committet, können Sie dies nicht sehen. Einfügungen und
Änderungen werden genauso behandelt.
Sie können Ihren Zeitpunkt aktualisieren, indem Sie Ihre
Transaktion committen und eine neue
SELECT
-Anfrage starten.
Dies bezeichnet man als Nebenläufigkeitssteuerung mit Multiversionierung.
User A User B SET AUTOCOMMIT=0; SET AUTOCOMMIT=0; time | 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 | --------------------- 1 row in set
In diesem Beispiel sieht Benutzer A die von Benutzer B eingefügte Zeile erst dann, wenn sowohl B als auch A ihre Operationen committet haben, sodass der Zeitpunkt sich auf die Zeit nach dem Commit von B verschiebt.
Wenn Sie den „frischsten“ Zustand der Datenbank
sehen möchten, stellen Sie entweder die Isolationsebene
READ COMMITTED
oder einen Locking-Read ein:
SELECT * FROM t LOCK IN SHARE MODE;
Ein Locking Read, ein UPDATE
oder ein
DELETE
errichten normalerweise Zeilensperren
auf jedem Indexeintrag, der bei der Verarbeitung der SQL-Anfrage
gescannt wird. Ob irgendwelche
WHERE
-Bedingungen in der Anfrage die Zeile
eigentlich ausschließen würden, spielt keine Rolle.
InnoDB
merkt sich nicht die genaue
WHERE
-Bedigungn, sondern weiß nur, welche
Indexbereiche gescannt werden. Die Sperren auf den Einträgen
sind normalerweise Next-Key-Sperren, die auch Einfügungen in
die „Lücke“ vor dem Eintrag blockieren.
Wenn exklusive Sperren errichtet werden, ruft
InnoDB
immer auch den geclusterten
Indexeintrag ab und sperrt ihn.
Wenn Sie nicht die geeigneten Indizes für Ihre Anweisung haben und MySQL die gesamte Tabelle scannen muss, um die Anfrage zu verarbeiten, werden alle Tabellenzeilen und somit auch alle Einfügeoperationen anderer Benutzer auf der Tabelle gesperrt. Es ist also wichtig, gute Indizes anzulegen, damit Ihre Anfragen nicht unnötig viele Zeilen scannen müssen.
InnoDB
setzt bestimmte Arten von Sperren wie
folgt:
SELECT … FROM
ist ein konsistenter
Lesevorgang, der einen Snapshot der Datenbank betrachtet und
nur dann Sperren errichtet, wenn die
Transaktionsisolationsebene SERIALIZABLE
ist. In diesem Fall werden Shared Next-Key-Sperren auf die
gefundenen Indexeinträge gesetzt.
SELECT … FROM … LOCK IN SHARE
MODE
setzt Shared Next-Key-Sperren auf alle
Indexeinträge, die der Lesevorgang findet.
SELECT … FROM … FOR UPDATE
setzt exklusive Next-Key-Sperren auf alle Indexeinträge,
die der Lesevorgang findet.
INSERT INTO … VALUES (…)
setzt eine exklusive Sperre auf die eingefügte Zeile.
Beachten Sie, dass diese Sperre keine Next-Key-Sperre ist
und daher andere Benutzer nicht daran hindert, in die Lücke
vor der neuen Zeile etwas einzufügen. Wenn ein Fehler wegen
Schlüsselduplikaten auftritt, wird eine Shared-Sperre auf
dem Duplikat-Indexeintrag gesetzt.
Bei der Initialisierung einer zuvor angegebenen
AUTO_INCREMENT
-Spalte auf einer Tabelle
setzt InnoDB
eine exklusive Sperre auf
das Ende des mit dieser
AUTO_INCREMENT
-Spalte verbundenen Index.
Für den Zugriff auf den Auto-Increment-Zähler nutzt
InnoDB
einen bestimmten
Tabellensperrmodus namens AUTO-INC
, mit
dem die Sperre nur bis zum Ende der aktuellen SQL-Anweisung
und nicht der gesamten Transaktion aufrecht erhalten bleibt.
Siehe Abschnitt 14.2.10.2, „InnoDB
und AUTOCOMMIT
“.
InnoDB
ruft den Wert einer
initialisierten AUTO_INCREMENT
-Spalte ab,
ohne Sperren zu setzen.
INSERT INTO T SELECT … FROM S WHERE
…
errichtet eine exklusive Sperre (keine
Next-Key-Sperre) auf jeder in T
eingefügten Zeile. InnoDB
erwirbt Shared
Next-Key-Sperren auf S
, wenn nicht
innodb_locks_unsafe_for_binlog
aktiviert
ist. In diesem Fall durchsucht es S
mit
einer konsistenten Leseoperation. InnoDB
muss im zweiten Fall Sperren setzen: Bei einer
Roll-forward-Recovery von einem Backup muss jede
SQL-Anweisung in genau derselben Weise wie ursprünglich
ausgeführt werden.
CREATE TABLE … SELECT …
führt das SELECT
als konsistente
Leseoperation oder mit Shared-Sperren durch, wie oben
beschrieben.
REPLACE
wird wie ein Insert ausgeführt,
wenn keine Konflikte auf einem eindeutigen Schlüssel
entstehen. Andernfalls wird eine exklusive Next-Key-Sperre
auf der zu aktualisierenden Zeile errichtet.
UPDATE … WHERE …
setzt eine
exklusive Next-Key-Sperre auf jeden bei der Suche gefundenen
Datensatz.
DELETE FROM … WHERE …
setzt
eine exklusive Next-Key-Sperre auf jeden bei der Suche
gefundenen Datensatz.
Wenn ein FOREIGN KEY
-Constraint auf einer
Tabelle definiert ist, setzt jedes Insert, Update oder
Delete, bei dem die Constraint-Bedingung geprüft werden
muss, Shared-Zeilensperren auf die betrachteten Datensätze,
um den Constraint zu überprüfen. InnoDB
setzt diese Sperren auch dann, wenn der Constraint versagt.
LOCK TABLES
setzt Tabellensperren,
allerdings auf der MySQL-Ebene, die höher als die
InnoDB
-Ebene liegt.
InnoDB
weiß von den Tabellensperren,
wenn innodb_table_locks=1
(die
Standardeinstellung) und AUTOCOMMIT=0
eingestellt ist, und die MySQL-Ebene oberhalb von
InnoDB
weiß ebenso von den
Zeilensperren. Sonst kann die automatische
Deadlock-Erkennung von InnoDB
keine
Deadlocks erkennen, an denen solche Tabellensperren
beteiligt sind. Außerdem wäre es dann möglich, eine
Tabellensperre auf einer Tabelle zu errichten, in der ein
anderer Benutzer gleichzeitig Zeilensperren hält, weil die
höhere MySQL-Ebene diese Zeilensperren nicht kennt. Dies
bedroht allerdings nicht die Transaktionsintegrität, wie in
Abschnitt 14.2.10.10, „Blockierungserkennung und Rollback“ erläutert.
Siehe auch Abschnitt 14.2.16, „Beschränkungen von InnoDB
-Tabellen“.
Nach Voreinstellung beginnt MySQL jede Clientverbindung mit
eingeschaltetem Autocommit. Dabei wird nach jeder fehlerfrei
gelaufenen SQL-Anweisung ein Commit durchgeführt. Gibt die
Anweisung einen Fehler zurück, so entscheidet die Art des
Fehlers darüber, ob ein Commit oder ein Rollback ausgeführt
wird. Siehe Abschnitt 14.2.15, „InnoDB
-Fehlerbehandlung“.
Wenn Sie Autocommit ausgeschaltet haben und eine Verbindung schließen, ohne explizit die letzte Transaktion zu committen, rollt MySQL diese Transaktion zurück.
Jede der folgenden Anweisungen (und ihre Synonyme) beendet
implizit eine Transaktion, als hätten Sie
COMMIT
gesagt:
ALTER FUNCTION
, ALTER
PROCEDURE
, ALTER TABLE
,
BEGIN
, CREATE
DATABASE
, CREATE FUNCTION
,
CREATE INDEX
, CREATE
PROCEDURE
, CREATE TABLE
,
DROP DATABASE
, DROP
FUNCTION
, DROP INDEX
,
DROP PROCEDURE
, DROP
TABLE
, LOAD MASTER DATA
,
LOCK TABLES
, RENAME
TABLE
, SET AUTOCOMMIT=1
,
START TRANSACTION
,
TRUNCATE
, UNLOCK
TABLES
.
UNLOCK TABLES
committet eine Transaktion
nur dann, wenn Tabellen gesperrt sind.
Die CREATE TABLE
-Anweisung in
InnoDB
wird als eine einzelne Transaktion
ausgeführt. Dies bedeutet, dass ein
ROLLBACK
vom Benutzer nicht die im Lauf
der Transaktion erteilten CREATE
TABLE
-Anweisungen rückgängig macht.
Transaktionen können nicht geschachtelt werden. Dies ist eine
Konsequenz des impliziten COMMIT
, das jede
laufende Transaktion ausführt, wenn Sie eine START
TRANSACTION
-Anweisung oder ein Synonym erteilen.
InnoDB
erkennt automatisch einen Deadlock von
Transaktionen und rollt eine oder mehrere Transaktion(en)
zurück, um den Deadlock aufzulösen. InnoDB
versucht, für den Rollback kleine Transaktionen herauszusuchen,
wobei die Größe einer Transaktion anhand der Anzahl der Zeilen
bestimmt wird, die sie einfügt, ändert oder löscht.
InnoDB
weiß von Tabellensperren, wenn
innodb_table_locks=1
(die
Standardeinstellung) und AUTOCOMMIT=0
eingestellt ist, und die MySQL-Ebene oberhalb von
InnoDB
weiß ebenso von den Zeilensperren.
Sonst kann die automatische Deadlock-Erkennung von
InnoDB
keine Deadlocks erkennen, wenn eine
von der MySQL-Anweisung LOCK TABLES
gesetzte
Tabellensperre oder eine von einer anderen Speicher-Engine als
InnoDB
gesetzte Sperre beteiligt ist. Solche
Situationen müssen Sie durch Einstellen der Systemvariablen
innodb_lock_wait_timeout
beherrschen.
Wenn InnoDB
eine Transaktion vollständig
zurückrollt, werden alle von ihr gehaltenen Sperren
freigegeben. Wird jedoch nur eine einzige SQL-Anweisung infolge
eines Fehlers zurückgerollt, bleiben manche von ihr errichteten
Sperren eventuell erhalten, da InnoDB
Zeilensperren in einem Format speichert, an dem es später nicht
mehr erkennen kann, welche Anweisung welche Sperren gesetzt hat.
Deadlocks in Transaktionsdatenbanken sind ein klassisches Problem. Gefährlich werden sie aber erst dann, wenn sie so häufig auftreten, dass bestimmte Transaktionen nicht mehr möglich sind. Normalerweise müssen Sie Ihre Anwendungen so erstellen, dass sie immer bereit sind, eine Transaktion neu zu starten, wenn sie wegen eines Deadlocks zurückgerollt wurde.
InnoDB
benutzt automatische Zeilensperren.
Deadlocks können sogar bei Transaktionen auftreten, die nur
eine einzige Zeile einfügen oder löschen. Da diese Operationen
nicht wirklich „atomar“ sind, errichten sie
automatisch Sperren auf den (vielleicht mehreren)
Indexeinträgen der eingefügten oder gelöschten Zeile.
Folgende Techniken helfen Ihnen, mit Deadlocks fertigzuwerden und ihre Zahl zu reduzieren:
SHOW ENGINE INNODB STATUS
verrät Ihnen
den Grund des letzten Deadlocks. Dies kann Ihnen helfen,
Ihre Anwendung so zu tunen, dass Deadlocks vermieden werden.
Seien Sie immer bereit, eine Transaktion, die wegen eines Deadlocks scheiterte, neu zu starten. Deadlocks sind nichts Schlimmes. Versuchen Sie es einfach noch einmal.
Committen Sie Ihre Transaktionen oft. Kleine Transaktionen sind nicht so konfliktanfällig.
Wenn Sie Lesesperren (SELECT … FOR
UPDATE
oder … LOCK IN SHARE
MODE
) setzen, versuchen Sie, eine niedrigere
Isolationsebene einzustellen, beispielsweise READ
COMMITTED
.
Greifen Sie in einer festgelegten Reihenfolge auf Ihre Tabellen und Zeilen zu. Dann bilden die Transaktionen ordentliche Schlangen und können sich nicht gegenseitig blockieren.
Versehen Sie Ihre Tabellen mit guten Indizes. Dann müssen
Ihre Anfragen weniger Indexeinträge scannen und folglich
auch weniger Sperren setzen. Mit EXPLAIN
SELECT
können Sie feststellen, welche Indizes
nach Ansicht Ihres MySQL-Servers für Ihre Anfragen die
besten sind.
Sperren Sie nicht so viel. Wenn Sie es sich leisten können,
dass ein SELECT
Daten aus einem älteren
Snapshot zurückgibt, verzichten Sie auf die Klausel
FOR UPDATE
oder LOCK IN SHARE
MODE
. Die Isolationsebene READ
COMMITTED
ist gut geeignet, da jede konsistente
Leseoperation innerhalb derselben Transaktion Daten aus
einem eigenen, frischen Snapshot liest.
Wenn sonst nichts hilft, serialisieren Sie Ihre
Transaktionen mit Tabellensperren. Um LOCK
TABLES
mit Transaktionstabellen wie etwa
InnoDB
-Tabellen zu verwenden, setzen Sie
AUTOCOMMIT = 0
und rufen UNLOCK
TABLES
erst auf, nachdem Sie die Transaktion
explizit committet haben. Wenn Sie beispielsweise in die
Tabelle t1
schreiben und aus der Tabelle
t2
lesen möchten, tun Sie dies wie
folgt:
SET AUTOCOMMIT=0;
LOCK TABLES t1 WRITE, t2 READ, ...;
... do something with tables t1 and t2 here ...
COMMIT;
UNLOCK TABLES;
Tabellensperren sorgen dafür, dass Ihre Transaktions brav Schlange stehen und Deadlocks vermieden werden.
Sie können Transaktionen auch serialisieren, indem Sie eine
„Semaphoren“-Hilfstabelle mit nur einer
einzigen Zeile anlegen. Sorgen Sie dafür, dass jede
Transaktion diese Zeile aktualsieren muss, ehe sie auf
andere Tabellen zugreifen darf. Auf diese Weise laufen alle
Transaktionen nacheinander ab. Beachten Sie, dass der
Deadlock-Erkennungsalgorithmus von InnoDB
auch in diesem Falle funktioniert, da die serialisierende
Sperre auf Zeilenebene arbeitet. Bei MySQL-Tabellensperren
muss die Timeout-Methode eingesetzt werden, um Deadlocks
aufzulösen.
In Anwendungen, die den LOCK
TABLES
-Befehl verwenden errichtet MySQL keine
InnoDB
-Tabellensperren, wenn
AUTOCOMMIT=1
.
Wenn das Unix-Tool top
oder der Windows
Task Manager zeigt, dass die CPU-Last unter 70% liegt, läuft
Ihre Arbeit wahrscheinlich festplattengebunden ab. Vielleicht
committen Sie zu oft Transaktionen oder Ihr Bufferpool ist zu
klein. Diesen zu vergrößern könnte helfen, aber stellen sie
ihn nicht auf 80% des physikalischen Speichers oder gar mehr
ein.
Verpacken Sie mehrere Modifikationen in eine einzige
Transaktion. InnoDB
muss bei jedem Committ
einer Transaktion, die etwas an der Datenbank änderte, die
Logs auf die Festplatte zurückschreiben. Da diese meist mit
einer Geschwindigkeit von höchstens 167 Umdrehungen/Sekunde
rotiert, ist diese 167tel Sekunde auch für Committs die
Obergrenze, wenn die Festplatte es nicht schafft, das
Betriebssystem zu „überlisten“.
Wenn Sie es sich leisten können, im Falle eines Absturzes
einige Ihrer zuletzt committeten Transaktionen zu verlieren,
können Sie den
innodb_flush_log_at_trx_commit
-Parameter
auf 0 setzen. InnoDB
versucht ohnehin, das
Log einmal pro Sekunde auf die Platte zu schreiben, auch wenn
dies nicht immer klappt.
Machen Sie Ihre Logdateien groß, vielleicht genauso groß wie
den Bufferpool. Wenn InnoDB
die Logdateien
vollgeschrieben hat, muss es den neuen Inhalt des Bufferpools
in einem Checkpoint auf die Platte schreiben. Kleine
Logdateien verursachen viele überflüssige Schreibvorgänge
auf der Festplatte. Der Nachteil großer Logdateien ist die
längere Recovery-Zeit.
Machen Sie auch den Logpuffer recht groß (etwa 8MB).
Verwenden Sie zur Speicherung von Strings variabler Länge
oder wenn die Spalte NULL
-Werte enthalten
kann, VARCHAR
statt CHAR
als Datentyp. Eine
CHAR(
-Spalte
speichert immer N
)N
Zeichen, selbst
wenn der String kürzer oder sein Wert NULL
ist. Kleinere Tabellen passen besser in den Bufferpool und
reduzieren die Schreibvorgänge auf der Festplatte.
Wenn Sie die Standardeinstellung
row_format=compact
für das Datensatzformat
von MySQL 5.1 Zeichensätze variabler Länge wie
etwa utf8
oder sjis
verwenden, belegt
CHAR(
eine
variable Menge Speicherplatz, allerdings mindestens
N
)N
Bytes.
In manchen Versionen von GNU/Linux und Unix geht es
erstaunlich langsam, Daten mit dem Unix-Aufruf
fsync()
(den InnoDB
standardmäßig verwendet) und anderen, ähnlichen Methoden
auf die Platte zu schreiben. Wenn Sie mit der Schreibleistung
Ihrer Datenbank unzufrieden sind, setzen Sie den
innodb_flush_method
-Parameter auf
O_DSYNC
. Zwar scheint
O_DSYNC
auf den meisten Systemen die
langsamere Variante zu sein, aber vielleicht ist es gerade auf
Ihrem schneller.
Wenn Sie InnoDB
auf Solaris 10 for x86_64
(AMD Opteron) einsetzen, ist es wichtig, alle zum Speichern
von InnoDB
-Dateien verwendeten Dateisysteme
mit der forcedirectio
-Option zu mounten
(die standardmäßig auf Solaris 10/x86_64
nicht benutzt wird). Wenn Sie dies nicht
tun, läuft InnoDB
auf dieser Plattform
sehr viel langsamer und hat eine geringere Performance.
Wenn Sie InnoDB
mit einem großen
innodb_buffer_pool_size
-Wert auf Solaris
2.6 und höher auf einer beliebigen Plattform
(sparc/x86/x64/amd64) einsetzen, können Sie die Performance
massiv steigern, indem Sie die
InnoDB
-Daten- und -Logdateien auf Raw
Devices oder einem separaten UFS-Dateisystem mit Direkt-E/A
speichern (und zwar mit der Mount-Option
forcedirectio
, siehe
mount_ufs(1M)
). Wer das Veritas-Dateisystem
VxFS hat, sollte die Mount-Option
convosync=direct
setzen.
Andere MySQL-Datendateien, wie etwa die für
MyISAM
-Tabellen, sollten nicht in einem
Dateisystem mit Direkt-E/A abgelegt werden. Executables oder
Bibliotheken dürfen niemals in einem
Dateisystem mit Direkt-E/A abgelegt werden
Beim Datenimport in InnoDB
müssen Sie
darauf achten, dass MySQL nicht im Autocommit-Modus läuft, da
dieser bei jedem Insert die Logs auf die Festplatte
zurückschreibt. Um während der Import-Operation Autocommit
auszuschalten, schließen Sie die Operation in SET
AUTOCOMMIT
und COMMIT
-Anweisungen
ein:
SET AUTOCOMMIT=0;
... SQL import statements ...
COMMIT;
Mit der mysqldump-Option
--opt
erhalten Sie Dump-Dateien, die sich in
eine InnoDB
-Tabelle ganz schnell
importieren lassen, selbst ohne den Import in die Anweisungen
SET AUTOCOMMIT
und
COMMIT
zu verpacken.
Hüten Sie sich vor umfangreichen Rollbacks von
Masseneinfügeoperationen: InnoDB
benutzt
den Insert-Puffer zwar bei den Einfügungen, um
Schreibvorgänge zu minimieren, aber nicht bei den
zugehörigen Rollbacks. Ein festplattengebundener Rollback
kann 30-mal so lange wie der zugehörige Insert brauchen.
Dabei hilft es auch nichts, den Datenbankprozess anzuhalten,
da der Rollback beim Hochfahren des Servers wieder von vorne
beginnt. Die einzige Möglichkeit, einen außer Kontrolle
geratenen Rollback aufzuhalten, besteht darin, den Bufferpool
so groß anzusetzen, dass der Rollback CPU-gebunden und somit
schneller läuft, oder eine spezielle Prozedur einzusetzen.
Siehe Abschnitt 14.2.8.1, „Erzwingen einer InnoDB
-Wiederherstellung (Recovery)“.
Hüten Sie sich auch vor anderen umfangreichen
festplattengebundenen Operationen. Verwenden Sie zum Leeren
einer Tabelle DROP TABLE
und
CREATE TABLE
, aber nicht DELETE
FROM
.
tbl_name
Mit dem mehrzeiligen INSERT
können Sie den
Kommunikationsaufwand zwischen Client und Server minimieren,
wenn Sie viele Zeilen einfügen müssen:
INSERT INTO yourtable VALUES (1,2), (5,5), ...;
Dieser Tipp gilt übrigens für Einfügungen in alle
möglichen Tabellen, nicht nur in
InnoDB
-Tabellen.
Wenn Sie UNIQUE
-Constraints auf
Sekundärschlüsseln haben, können Sie Tabellenimporte
beschleunigen, indem Sie die Eindeutigkeitsprüfung während
der Import-Session vorübergehend abschalten:
SET UNIQUE_CHECKS=0;
... import operation ...
SET UNIQUE_CHECKS=1;
Bei großen Tabellen spart dies eine Menge Plattenzugriffe, da
InnoDB
seine Insert-Puffer dazu benutzen
kann, Sekundärindexeinträge als Batch zu verarbeiten.
Wenn Ihre Tabellen FOREIGN KEY
-Constraints
haben, können Sie Tabellenimporte beschleunigen, indem Sie
für die Dauer der Import-Session die Fremschlüsselprüfungen
abschalten:
SET FOREIGN_KEY_CHECKS=0;
... import operation ...
SET FOREIGN_KEY_CHECKS=1;
Bei großen Tabellen spart dies eine Menge Plattenzugriffe.
Wenn Sie oft wiederkehrende Anfragen auf Tabellen haben, die sich nur selten ändern, nutzen Sie den Query-Cache:
[mysqld] query_cache_type = ON query_cache_size = 10M
InnoDB
hat Monitore, die Informationen über
den internen Zustand von InnoDB
ausgeben. Sie
können jederzeit eine SHOW ENGINE INNODB
STATUS
-Anweisung erteilen, um die Ausgabe des
InnoDB
-Standardmonitors in Ihren SQL-Client
zu holen. Diese Informationen sind nützlich für das
Performance-Tuning. (Wenn Sie den interaktiven SQL-Client
mysql benutzen, ist die Ausgabe einfacher zu
lesen, wenn Sie das übliche Semikolon am Ende von Anweisungen
durch \G
ersetzen.) Die Sperrmodi von
InnoDB
werden in
Abschnitt 14.2.10.1, „InnoDB
-Sperrmodi“ erklärt.
mysql> SHOW ENGINE INNODB STATUS\G
Eine andere Möglichkeit, InnoDB
-Monitore zu
nutzen, besteht darin, sie in regelmäßigen Abständen Daten in
die Standardausgabe des mysqld-Servers
schreiben zu lassen. In diesem Fall wird keine Ausgabe an die
Clients gesandt. Wenn sie eingeschaltet sind, geben
InnoDB
-Monitore etwa alle 15 Sekunden Daten
aus. Die Server-Ausgabe wird normalerweise an das
.err
-Log im MySQL Data Directory geschickt.
Diese Daten sind nützlich für das Performance-Tuning. Auf
Windows müssen Sie den Server von einer Eingabeaufforderung in
einem Konsolenfenster mit der --console
-Option
starten, wenn Sie die Ausgabe an das Fenster statt in das
Fehlerlog schicken wollen.
Die Monitorausgabe enthält folgende Informationen:
Tabellen- und Zeilensperren, die von den aktiven Transaktionen gehalten werden
Wartende Sperranforderungen von Transaktionen (Lock Waits)
Auf Semaphoren wartende Threads
Noch schwebende E/A-Requests
Statistikdaten über den Bufferpool
Aktivitäten des InnoDB
-Haupt-Threads zur
Verschmelzung von Purge- und Insert-Puffern
Damit der InnoDB
-Standardmonitor seine Daten
an die Standardausgabe von mysqld sendet,
geben Sie folgende SQL-Anweisung:
CREATE TABLE innodb_monitor (a INT) ENGINE=INNODB;
Folgende Anweisung hält den Monitor an:
DROP TABLE innodb_monitor;
Die CREATE TABLE
-Syntax ist nur eine
Möglichkeit, über den SQL-Parser von MySQL einen Befehl an
InnoDB
zu übergeben. Es ist nur wichtig,
dass der Tabellenname innodb_monitor
und der
Tabellentyp InnoDB
ist. Die Tabellenstruktur
ist für den InnoDB
-Monitor nicht von Belang.
(Diese Syntax kann beim Herunterfahren des Servers wichtig sein,
der Monitor fährt bei einem Neustart des Servers nicht
automatisch wieder hoch. Sie müssen die Monitortabelle löschen
und eine neue CREATE TABLE
-Anweisung geben,
um den Monitor zu starten. Das kann sich in einem künftigen
Release noch ändern.)
innodb_lock_monitor
kann ähnlich eingesetzt
werden. Dieser gleicht dem innodb_monitor
,
nur dass er außerdem viele Sperrinformationen gibt. Ein
separater innodb_tablespace_monitor
gibt eine
Liste der angelegten Dateisegmente im Tablespace aus und
validiert die Zuweisung der Datenstrukturen im Tablespace.
Zusätzlich gibt es den innodb_table_monitor
,
mit dem Sie den Inhalt des internen Data Dictionary von
InnoDB
ausgeben können.
Hier sehen Sie eine Beispielausgabe des
InnoDB
-Monitors:
mysql> SHOW ENGINE INNODB STATUS\G
*************************** 1. row ***************************
Status:
=====================================
030709 13:00:59 INNODB MONITOR OUTPUT
=====================================
Per second averages calculated from the last 18 seconds
----------
SEMAPHORES
----------
OS WAIT ARRAY INFO: reservation count 413452, signal count 378357
--Thread 32782 has waited at btr0sea.c line 1477 for 0.00 seconds the
semaphore: X-lock on RW-latch at 41a28668 created in file btr0sea.c line 135
a writer (thread id 32782) has reserved it in mode wait exclusive
number of readers 1, waiters flag 1
Last time read locked in file btr0sea.c line 731
Last time write locked in file btr0sea.c line 1347
Mutex spin waits 0, rounds 0, OS waits 0
RW-shared spins 108462, OS waits 37964; RW-excl spins 681824, OS waits
375485
------------------------
LATEST FOREIGN KEY ERROR
------------------------
030709 13:00:59 Transaction:
TRANSACTION 0 290328284, ACTIVE 0 sec, process no 3195, OS thread id 34831
inserting
15 lock struct(s), heap size 2496, undo log entries 9
MySQL thread id 25, query id 4668733 localhost heikki update
insert into ibtest11a (D, B, C) values (5, 'khDk' ,'khDk')
Foreign key constraint fails for table test/ibtest11a:
,
CONSTRAINT `0_219242` FOREIGN KEY (`A`, `D`) REFERENCES `ibtest11b` (`A`,
`D`) ON DELETE CASCADE ON UPDATE CASCADE
Trying to add in child table, in index PRIMARY tuple:
0: len 4; hex 80000101; asc ....;; 1: len 4; hex 80000005; asc ....;; 2:
len 4; hex 6b68446b; asc khDk;; 3: len 6; hex 0000114e0edc; asc ...N..;; 4:
len 7; hex 00000000c3e0a7; asc .......;; 5: len 4; hex 6b68446b; asc khDk;;
But in parent table test/ibtest11b, in index PRIMARY,
the closest match we can find is record:
RECORD: info bits 0 0: len 4; hex 8000015b; asc ...[;; 1: len 4; hex
80000005; asc ....;; 2: len 3; hex 6b6864; asc khd;; 3: len 6; hex
0000111ef3eb; asc ......;; 4: len 7; hex 800001001e0084; asc .......;; 5:
len 3; hex 6b6864; asc khd;;
------------------------
LATEST DETECTED DEADLOCK
------------------------
030709 12:59:58
*** (1) TRANSACTION:
TRANSACTION 0 290252780, ACTIVE 1 sec, process no 3185, OS thread id 30733
inserting
LOCK WAIT 3 lock struct(s), heap size 320, undo log entries 146
MySQL thread id 21, query id 4553379 localhost heikki update
INSERT INTO alex1 VALUES(86, 86, 794,'aA35818','bb','c79166','d4766t',
'e187358f','g84586','h794',date_format('2001-04-03 12:54:22','%Y-%m-%d
%H:%i'),7
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 48310 n bits 568 table test/alex1 index
symbole trx id 0 290252780 lock mode S waiting
Record lock, heap no 324 RECORD: info bits 0 0: len 7; hex 61613335383138;
asc aa35818;; 1:
*** (2) TRANSACTION:
TRANSACTION 0 290251546, ACTIVE 2 sec, process no 3190, OS thread id 32782
inserting
130 lock struct(s), heap size 11584, undo log entries 437
MySQL thread id 23, query id 4554396 localhost heikki update
REPLACE INTO alex1 VALUES(NULL, 32, NULL,'aa3572','','c3572','d6012t','',
NULL,'h396', NULL, NULL, 7.31,7.31,7.31,200)
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 0 page no 48310 n bits 568 table test/alex1 index
symbole trx id 0 290251546 lock_mode X locks rec but not gap
Record lock, heap no 324 RECORD: info bits 0 0: len 7; hex 61613335383138;
asc aa35818;; 1:
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 48310 n bits 568 table test/alex1 index
symbole trx id 0 290251546 lock_mode X locks gap before rec insert intention
waiting
Record lock, heap no 82 RECORD: info bits 0 0: len 7; hex 61613335373230;
asc aa35720;; 1:
*** WE ROLL BACK TRANSACTION (1)
------------
TRANSACTIONS
------------
Trx id counter 0 290328385
Purge done for trx's n:o < 0 290315608 undo n:o < 0 17
Total number of lock structs in row lock hash table 70
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 0 0, not started, process no 3491, OS thread id 42002
MySQL thread id 32, query id 4668737 localhost heikki
show innodb status
---TRANSACTION 0 290328384, ACTIVE 0 sec, process no 3205, OS thread id
38929 inserting
1 lock struct(s), heap size 320
MySQL thread id 29, query id 4668736 localhost heikki update
insert into speedc values (1519229,1, 'hgjhjgghggjgjgjgjgjggjgjgjgjgjgggjgjg
jlhhgghggggghhjhghgggggghjhghghghghghhhhghghghjhhjghjghjkghjghjghjghjfhjfh
---TRANSACTION 0 290328383, ACTIVE 0 sec, process no 3180, OS thread id
28684 committing
1 lock struct(s), heap size 320, undo log entries 1
MySQL thread id 19, query id 4668734 localhost heikki update
insert into speedcm values (1603393,1, 'hgjhjgghggjgjgjgjgjggjgjgjgjgjgggjgj
gjlhhgghggggghhjhghgggggghjhghghghghghhhhghghghjhhjghjghjkghjghjghjghjfhjf
---TRANSACTION 0 290328327, ACTIVE 0 sec, process no 3200, OS thread id
36880 starting index read
LOCK WAIT 2 lock struct(s), heap size 320
MySQL thread id 27, query id 4668644 localhost heikki Searching rows for
update
update ibtest11a set B = 'kHdkkkk' where A = 89572
------- TRX HAS BEEN WAITING 0 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 65556 n bits 232 table test/ibtest11a index
PRIMARY trx id 0 290328327 lock_mode X waiting
Record lock, heap no 1 RECORD: info bits 0 0: len 9; hex 73757072656d756d00;
asc supremum.;;
------------------
---TRANSACTION 0 290328284, ACTIVE 0 sec, process no 3195, OS thread id
34831 rollback of SQL statement
ROLLING BACK 14 lock struct(s), heap size 2496, undo log entries 9
MySQL thread id 25, query id 4668733 localhost heikki update
insert into ibtest11a (D, B, C) values (5, 'khDk' ,'khDk')
---TRANSACTION 0 290327208, ACTIVE 1 sec, process no 3190, OS thread id
32782
58 lock struct(s), heap size 5504, undo log entries 159
MySQL thread id 23, query id 4668732 localhost heikki update
REPLACE INTO alex1 VALUES(86, 46, 538,'aa95666','bb','c95666','d9486t',
'e200498f','g86814','h538',date_format('2001-04-03 12:54:22','%Y-%m-%d
%H:%i'),
---TRANSACTION 0 290323325, ACTIVE 3 sec, process no 3185, OS thread id
30733 inserting
4 lock struct(s), heap size 1024, undo log entries 165
MySQL thread id 21, query id 4668735 localhost heikki update
INSERT INTO alex1 VALUES(NULL, 49, NULL,'aa42837','','c56319','d1719t','',
NULL,'h321', NULL, NULL, 7.31,7.31,7.31,200)
--------
FILE I/O
--------
I/O thread 0 state: waiting for i/o request (insert buffer thread)
I/O thread 1 state: waiting for i/o request (log thread)
I/O thread 2 state: waiting for i/o request (read thread)
I/O thread 3 state: waiting for i/o request (write thread)
Pending normal aio reads: 0, aio writes: 0,
ibuf aio reads: 0, log i/o's: 0, sync i/o's: 0
Pending flushes (fsync) log: 0; buffer pool: 0
151671 OS file reads, 94747 OS file writes, 8750 OS fsyncs
25.44 reads/s, 18494 avg bytes/read, 17.55 writes/s, 2.33 fsyncs/s
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf for space 0: size 1, free list len 19, seg size 21,
85004 inserts, 85004 merged recs, 26669 merges
Hash table size 207619, used cells 14461, node heap has 16 buffer(s)
1877.67 hash searches/s, 5121.10 non-hash searches/s
---
LOG
---
Log sequence number 18 1212842764
Log flushed up to 18 1212665295
Last checkpoint at 18 1135877290
0 pending log writes, 0 pending chkp writes
4341 log i/o's done, 1.22 log i/o's/second
----------------------
BUFFER POOL AND MEMORY
----------------------
Total memory allocated 84966343; in additional pool allocated 1402624
Buffer pool size 3200
Free buffers 110
Database pages 3074
Modified db pages 2674
Pending reads 0
Pending writes: LRU 0, flush list 0, single page 0
Pages read 171380, created 51968, written 194688
28.72 reads/s, 20.72 creates/s, 47.55 writes/s
Buffer pool hit rate 999 / 1000
--------------
ROW OPERATIONS
--------------
0 queries inside InnoDB, 0 queries in queue
Main thread process no. 3004, id 7176, state: purging
Number of rows inserted 3738558, updated 127415, deleted 33707, read 755779
1586.13 inserts/s, 50.89 updates/s, 28.44 deletes/s, 107.88 reads/s
----------------------------
END OF INNODB MONITOR OUTPUT
============================
Einige Hinweise zu dieser Ausgabe:
Wenn der TRANSACTIONS
-Teil Lock Waits
meldet, ist Ihre Anwendung vielleicht durch Sperren
blockiert. Die Ausgabe kann auch helfen, die Gründe für
Transaktions-Deadlocks festzustellen.
Der SEMAPHORES
-Teil meldet Threads, die
auf Semaphoren warten, und Statistikdaten darüber, wie oft
Threads einen Spin oder Wait auf einen Mutex oder eine
Semaphpre einer Lese/Schreib-Sperre benötigt haben. Wenn
viele Threads auf Semaphoren warten, kann dies am
Festplatten-E/A liegen, oder auch an Verstopfungsproblemen
in InnoDB
. Verstopfungen können durch
viele parallele Anfragen oder Probleme im Thread-Management
des Betriebssystems bedingt sein. In solchen Situationen
kann es helfen, innodb_thread_concurrency
auf einen kleineren als den Standardwert zu setzen.
Der Abschnitt BUFFER POOL AND MEMORY
verrät Ihnen, wie viele Seiten gelesen und geschrieben
werden. Aus diesen Zahlen können Sie berechnen, wie viele
Datendateizugriffe Ihre Anfragen gerade ausführen.
Der Abschnitt ROW OPERATIONS
zeigt, was
der Haupt-Thread gerade tut.
InnoDB
sendet Diagnose-Ausgabe an
stderr
oder an Dateien anstatt an die
stdout
-Ausgabe oder Arbeitsspeicherpuffer
fester Größe, um Puffer-Überläufe zu verhindern. Als
Nebeneffekt wird die Ausgabe von SHOW ENGINE INNODB
STATUS
alle 15 Sekunden in eine Statusdatei im MySQL
Data Directory geschrieben. Diese Datei heißt
innodb_status.
,
wobei pid
pid
die Server-Prozess-ID ist.
InnoDB
entfernt diese Datei bei einem
normalen Shutdown. Bei einem unnormalen Shutdown können
Instanzen dieser Statusdateien überleben und müssen manuell
gelöscht werden. Bevor Sie dies tun, sollten Sie allerdings
hineinschauen, um zu sehen ob sie irgendwelche Hinweise auf die
Ursache der unnormalen Shutdowns enthalten. Die Datei
innodb_status.
wird nur angelegt, wenn die Konfigurationsoption
pid
innodb_status_file=1
gesetzt ist.
Da InnoDB
eine Speicher-Engine mit
Multiversionierung ist, muss sie Informationen über ältere
Versionen der Zeilen im Tablespace bewahren. Diese Informationen
werden in einer Datenstruktur gespeichert, die wie in Oracle
Rollback-Segment heißt.
Internally fügt InnoDB
jeder Zeile, die in der
Datenbank gespeichert wird, zwei Felder hinzu: ein 6 Byte großes
Feld mit dem Transaktions-Identifier der letzten Transaktion, mit
der die Zeile eingefügt oder geändert worden ist (eine Löschung
wird intern wie eine Änderung behandelt, bei der ein bestimmtes
Bit in der Zeile gesetzt wird, um sie als gelöscht zu
kennzeichnen), und ein 7-Byte-Feld namens Rollpointer. Dieser
zeigt auf einen Undo-Logeintrag, der in das Rollback-Segment
geschrieben wurde. Wenn die Zeile geändert wurde, enthält dieser
Undo-Logeintrag die Daten, die erforderlich sind, um ihren Inhalt
von vor der Änderung wiederherzustellen.
InnoDB
benutzt die Informationen aus dem
Rollback-Segment, um die für ein Transaktions-Rollback
erforderlichen Wiederherstellungsoperationen auszuführen.
Außerdem dienen die Informationen der Erstellung älterer
Versionen einer Zeile für eine konsistente Leseoperation.
Undo-Logs im Rollback-Segment sind in Insert- und Update-Undo-Logs
getrennt. Insert-Undo-Logs werden nur für das
Transaktions-Rollback gebraucht und können gelöscht werden,
sobald die Transaktion committet wird. Update-Undo-Logs werden
auch für konsistente Leseoperationen benutzt, können aber
verworfen werden, wenn keine Transaktion mehr läuft, für die
InnoDB
einen Snapshot zugewiesen hat, der für
eine konsistente Leseoperation die Daten des Update-Undo-Logs
benötigen könnte, um eine ältere Version der Datenbankzeile
wiederherzustellen.
Bitte denken Sie daran, Ihre Transaktionen regelmäßig zu
committen, einschließlich derjenigen Transaktionen, die nur
konsistente Leseoperationen ausgeben. Andernfalls kann
InnoDB
die Daten aus dem Update-Undo-Log nicht
verwerfen und das Rollback-Segment kann so stark anwachsen, dass
es Ihren Tablespace ganz ausfüllt.
Die physikalische Größe eines Undo-Logeintrags im Rollback-Segment ist normalerweise kleiner als die zugehörige eingefügte oder geänderte Zeile. Mit diesen Informationen können Sie berechnen, wie viel Platz für Ihr Rollback-Segment erforderlich ist.
In der Multiversionierung von InnoDB
wird eine
Zeile nicht sofort physikalisch aus der Datenbank entfernt, wenn
Sie sie mit einer SQL-Anweisung löschen. Erst wenn
InnoDB
den für die Löschung erstellten
Update-Undo-Logeintrag entfernen kann, kann es auch die Zeile und
ihre Indexeinträge physikalisch aus der Datenbank entfernen.
Diese Löschoperation bezeichnet man als Purge. Sie läuft sehr
schnell, ungefähr genauso schnell wie die SQL-Löschanweisung.
In einem Szenario, in dem der Benutzer Zeilen in kleinen,
ungefähr gleichen Batches aus der Tabelle löscht, kann es
passieren, dass der Purge-Thread beginnt, hinterherzuhinken, und
die Tabelle immer größer wird, wodurch sich alle
Festplattenoperationen stark verlangsamen. Selbst Tabellen, die
nur 10MB an brauchbaren Daten aufweisen, können mit allen
„toten“ Zeilen auf 10GB anwachsen. In solchen Fällen
wäre es gut, neue Zeilenoperationen zurückzufahren und dem
Purge-Thread mehr Ressourcen zuzuweisen. Genau zu diesem Zweck
gibt es die Systemvariable
innodb_max_purge_lag
. Weitere Informationen
finden Sie unter Abschnitt 14.2.4, „InnoDB
: Startoptionen und Systemvariablen“.
MySQL speichert seine Data Dictionary-Informationen über Tabellen
in .frm
-Dateien in Datenbankverzeichnissen.
Das gilt für alle Speicher-Engines von MySQL. Doch jede
InnoDB
-Tabelle hat auch einen eigenen Eintrag
im internen InnoDB
-Data Dictionary innerhalb
des Tablespace. Wenn MySQL eine Tabelle oder Datenbank löscht,
muss es sowohl die .frm
-Datei(en) als auch
die zugehörigen Einträge im InnoDB
-Data
Dictionary löschen. Daher dürfen Sie auch
InnoDB
-Tabellen nicht einfach durch Verschieben
der .frm
-Dateien von einer Datenbank in die
andere übertragen.
Jede InnoDB
-Tabelle besitzt einen speziellen,
so genannten geclusterten Index, der die
Daten über die Zeilen speichert. Wenn Sie einen PRIMARY
KEY
auf Ihrer Tabelle definieren, ist der Index dieses
Primärschlüssels der geclusterte Index.
Wenn Sie keinen PRIMARY KEY
für Ihre Tabelle
definieren, wählt MySQL den ersten
UNIQUE
-Index, der nur NOT
NULL
-Spalten hat, als Primärschlüssel aus, und
InnoDB
verwendet diesen als geclusterten Index.
Wenn die Tabelle keinen solchen Index besitzt, wird intern von
InnoDB
ein geclusterter Index generiert, in dem
die Zeilen nach der Zeilen-ID geordnet sind, die
InnoDB
den Zeilen derartiger Tabellen zuweist.
Die Zeilen-ID ist ein 6-Byte-Feld, das monoton wächst, wenn neue
Zeilen eingefügt werden. Somit stehen die nach Zeilen-ID
geordneten Zeilen physikalisch in der Reihenfolge ihrer
Einfügung.
Über einen geclusterten Index ist eine Zeile schnell zu erreichen, da die Zeilendaten auf derselben Seite liegen, zu der die Indexsuche hinführt. Wenn eine Tabelle groß ist, speichert die Clustered-Index-Architektur im Vergleich zu der traditionellen Lösung oft Plattenzugriffe. (In vielen Datenbanksystemen sind die Daten auf einer anderen Seite gespeichert als der Indexeintrag.)
In InnoDB
enthalten die Datensätze in
nicht-geclusterten Indizes (auch Sekundärindizes genannt) den
Primärschlüsselwert für die Zeile. InnoDB
benutzt diesen Primärschlüsselwert, um die Zeile in dem
geclusterten Index zu suchen. Beachten Sie: Wenn der
Primärschlüssel lang ist, brauchen die Sekundärindizes mehr
Platz.
InnoDB
vergleicht unterschiedlich lange
CHAR
- und VARCHAR
-Strings,
indem es die Längendifferenz im kürzeren String als mit
Leerzeichen ausgefüllt betrachtet.
Alle InnoDB
-Indizes sind B-Trees, wobei die
Indexeinträge in den Blattseiten des Baums gespeichert werden.
Die Standardgröße einer Indexseite beträgt 16KB. Wenn neue
Einträge eingefügt werden, versucht InnoDB
,
1/16 der Seite für zukünftige Einfügungen und Änderungen der
Indexeinträge frei zu halten.
Wenn Indexeinträge in (auf- oder absteigender) sequenzieller
Reihenfolge eingefügt werden, werden die Indexseiten zu 15/16
voll. Werden die Einträge in zufälliger Reihenfolge
eingefügt, werden die Seiten nur zu 1/2 bis 15/16 voll. Wenn
der Füllstand einer Indexseite unter 1/2 fällt, versucht
InnoDB
mit dem Indexbaum zu vereinbaren, dass
die Seite freigegeben wird.
In Datenbankanwendungen kommt es häufig vor, dass ein Primärschlüssel ein eindeutiger Identifier ist und neue Zeilen in der aufsteigenden Reihenfolge des Primärschlüssels eingefügt werden. So sind für Einfügungen in den geclusterten Index keine willkürlichen Lesezugriffe auf eine Festplatte erforderlich.
Dagegen sind Sekundärindizes normalerweise nicht-eindeutig und
Einfügungen in sie finden in relativ willkürlicher Reihenfolge
statt. Dies würde eine Menge willkürlicher E/A-Operationen auf
der Festplatte erfordern, wenn es in InnoDB
nicht einen speziellen Mechanismus gäbe.
Wenn ein Indexeintrag in einen nicht-eindeutigen Sekundärindex
eingefügt werden soll, prüft InnoDB
, ob
dieser Sekundärindex im Bufferpool liegt. Wenn ja, führt
InnoDB
die Einfügung direkt auf der
Indexseite durch. Wenn nicht, fügt InnoDB
den Eintrag in eine spezielle Insert-Puffer-Struktur ein. Der
Insert-Puffer wird so klein gehalten, dass er komplett in den
Bufferpool passt und Einfügungen sehr schnell erledigt werden
können.
Dieser Insert-Puffer wird regelmäßig mit den Sekundärindexbäumen in der Datenbank zusammengeführt. Oft können mehrere Einfügeoperationen auf derselben Seite des Indexbaums gleichzeitig zusammengeführt werden, was Festplattenzugriffe spart. Messungen haben ergeben, dass der Insert-Puffer Einfügungen in eine Tabelle bis zu 15-mal schneller laufen lässt.
Das Zusammenführen von Insert-Puffer-Daten kann auch dann
weitergehen, nachdem die einfügende
Transaktion committet wurde, ja sogar nach dem Herunterfahren
und Neustart des Servers (siehe
Abschnitt 14.2.8.1, „Erzwingen einer InnoDB
-Wiederherstellung (Recovery)“).
Das Zusammenführen von Insert-Puffer-Daten kann viele Stunden dauern, wenn viele Sekundärindizes aktualisiert werden müssen und viele Zeilen eingefügt wurden. In dieser Zeit erhöht sich die E/A-Aktivität, sodass festplattengebundene Anfragen eventuell viel langsamer laufen. Eine andere, wichtige E/A-Hintergrundoperation ist der Purge-Thread (siehe Abschnitt 14.2.12, „Implementierung der Multiversionierung“).
Wenn eine Tabelle fast komplett in den Hauptspeicher passt, sind
Hash-Indizes das schnellste Mittel, um Anfragen auszuführen.
InnoDB
hat einen Mechanismus, der
Index-Suchen auf den Indizes einer Tabelle beobachtet. Wenn
InnoDB
bemerkt, dass Anfragen von einem
Hash-Index profitieren könnten, baut es automatisch einen auf.
Beachten Sie, dass der Hash-Index immer auf einem vorhandenen
B-Baum-Index der Tabelle aufbaut. InnoDB
kann
einen Hash-Index auf einem beliebig langen Präfix des für den
B-Baum definierten Schlüssels aufbauen, je nachdem, welches
Suchmuster InnoDB
für den B-Baum-Index
beachtet. Ein Hash-Index kann auch partiell sein: Es ist nicht
notwendig, den gesamten B-Baum-Index im Bufferpool zu cachen.
InnoDB
baut Hash-Indizes nach Bedarf für
diejenigen Indexseiten auf, die oft angesprochen werden.
In gewissem Sinne legt sich InnoDB
durch den
anpassungsfähigen Hash-Index-Mechanismus selbst auf einen
großen Arbeitsspeicher hin aus und kommt dadurch der
Architektur von Hauptspeicher-Datenbanken näher.
Datensätze von InnoDB
-Tabellen haben
folgende Merkmale:
Jeder Indexeintrag hat einen sechs Bytes großen Header, der benutzt wird, um aufeinanderfolgende Datensätze zu verknüpfen, und auch in Zeilensperren zum Einsatz kommt.
Einträge im geclusterten Index enthalten Felder für alle benutzerdefinierten Spalten. Zusätzlich gibt es ein sechs Bytes großes Feld für die Transaktions-ID und ein sieben Bytes großes für den Rollpointer.
Wenn für eine Tabelle kein Primärschlüssel definiert wurde, enhält jeder geclusterte Indexeintrag auch ein sechs Bytes großes Feld mit der Zeilen-ID.
Jeder Sekundärindexeintrag enthält auch alle Felder, die für den geclusterten Indexschlüssel definiert worden sind.
Ein Datensatz enthält auch einen Zeiger auf die einzelnen Felder des Datensatzes. Wenn deren Gesamtlänge 128 Bytes nicht übersteigt, ist der Zeiger ein Byte, ansonsten zwei Bytes groß. Das Array dieser Zeiger bezeichnet man als Record Directory. Der Bereich, auf den sie zeigen, ist der Datenteil des Datensatzes.
Intern speichert InnoDB
Zeichenspalten
fester Breite, wie beispielsweise
CHAR(10)
, in einem Format mit fester
Länge. InnoDB
kappt Leerzeichen am Ende
von VARCHAR
-Spalten.
Ein SQL-NULL
-Wert reserviert 1 oder 2
Bytes im Record Directory und null Bytes im Datenteil des
Eintrags, wenn er in einer Spalte mit variabler Länge
gespeichert ist. In einer Spalte fester Länge reserviert er
diese festgelegte Länge auch für
NULL
-Werte, damit eine Aktualisierung,
die die Spalte von NULL
auf einen anderen
Wert setzt, vor Ort ohne Fragmentierung der Indexseite
ausgeführt werden kann.
InnoDB
verwendet simulierte, asynchrone
Festplattenein- und -ausgaben (E/A) und erzeugt mehrere Threads
für E/A-Operationen wie beispielsweise Read-ahead.
Es gibt zwei Read-ahead-Heuristiken in
InnoDB
:
Beim sequenziellen Read-ahead schickt
InnoDB
, wenn es bemerkt, dass ein Segment
im Tablespace ein sequenzielles Zugriffsmuster aufweist, im
Voraus einen Batch Leseoperationen auf Datenbankseiten an
das E/A-System.
Beim willkürlichen Read-ahead schickt
InnoDB
, wenn es bemerkt, dass ein Bereich
im Tablespace im Begriff ist, vollständig in den Bufferpool
eingelesen zu werden, die restlichen Leseoperationen an das
E/A-System.
InnoDB
verwendet eine neue Technik namens
Doublewrite, um Dateien auf die
Festplatte zurückzuschreiben. Dadurch wird die Recovery nach
einem Betriebssystemabsturz oder einem Stromausfall sicherer und
die Leistung der meisten Unix-Varianten besser, da nicht mehr so
viele fsync()
-Operationen nötig sind.
Doublewrite sorgt dafür, dass InnoDB
Seiten
nicht gleich in die Datendatei, sondern zuerst in einen
zusammenhängenden Tablespace-Bereich namens Doublewrite-Puffer
schreibt. Erst wenn dieser Vorgang abgeschlossen ist, werden die
Seiten in ihre angestammten Plätze in der Datendatei
geschrieben. Stürzt das Betriebssystem mitten im Schreiben
einer Seite ab, kann InnoDB
später bei der
Recovery eine gute Kopie der Seite im Doublewrite-Puffer finden.
Die in der Konfigurationsdatei definierten Datendateien bilden
den Tablespace von InnoDB
. Die Dateien werden
einfach aneinander gehängt, um diesen Tablespace zu bilden. Es
wird kein Striping verwendet. Zurzeit können Sie noch nicht
bestimmen, an welche Stelle des Tablespaces Ihre Tabellen
zugewiesen werden. Doch in einem neuen Tablespace wird der Platz
beginnend mit der ersten Datendatei zugewiesen.
Der Tablespace besteht aus Datenbankseiten mit einer
Standardgröße von 16KB. Die Seiten werden zu Extents von 64
aufeinander folgenden Seiten zusammengefasst. Die
„Dateien“ eines Tablespace nennt man in
InnoDB
Segmente. Der
Begriff „Rollback-Segment“ ist etwas irreführend,
da er in Wirklichkeit viele Tablespace-Segmente umfasst.
Für jeden Index in InnoDB
werden zwei
Segmente zugewiesen. eines für Nicht-Blattknoten und das andere
für Blattknoten des B-Baums. Dadurch wird eine bessere Abfolge
der Blattknoten, die die eigentlichen Daten enthalten, erreicht.
Wenn ein Segment im Tablespace anwächst, weist ihm
InnoDB
die ersten 32 Seiten einzeln zu, und
danach nur noch vollständige Extents. InnoDB
kann einem großen Segment bis zu 4 Extents zugleich zuweisen,
um eine gute Datensequenzialität zu gewährleisten.
Da manche Seiten im Tablespace Bitmaps anderer Seiten enthalten,
können einige Extents eines
InnoDB
-Tablespace den Segmenten nicht als
Ganzes, sondern nur in Form einzelner Seiten zugewiesen werden.
Wenn Sie mit einer SHOW TABLE
STATUS
-Anweisung fragen, wie viel Platz in einem
Tablespace noch frei ist, meldet InnoDB
nur
die Extents, die darin definitiv noch nicht belegt sind.
InnoDB
reserviert immer einige Extents für
die Reinigungsaufgaben und andere interne Zwecke. Diese
reservierten Extents sind in dem freien Platz nicht inbegriffen.
Wenn Sie Daten aus einer Tabelle löschen, kontrahiert
InnoDB
die entsprechenden B-Baum-Indizes. Ob
der frei gewordene Platz für ander Benutzer verfügbar wird,
hängt davon ab, ob das Löschungsmuster einzelne Seiten oder
ganze Extents des Tablespace freigibt. Wenn Sie eine Tabelle
oder alle in ihr befindlichen Zeilen löschen, dann wird
garantiert der Platz für andere Benutzer freigegeben, aber
vergessen Sie nicht, dass gelöschte Zeilen physikalisch erst in
einer (automatischen) Purge-Operation entfernt werden, wenn sie
auch für Transaktions-Rollbacks und konsistente Leseoperationen
nicht mehr gebraucht werden. (Siehe
Abschnitt 14.2.12, „Implementierung der Multiversionierung“.)
Wenn willkürliche Einfügungen oder Löschungen in den Indizes einer Tabelle vorgenommen werden, können diese Indizes fragmentiert werden. Fragmentierung bedeutet, dass die physikalische Reihenfolge der Indexseiten auf der Platte nicht der Reihenfolge des Index für die Datensätze der Seiten entspricht, oder dass viele ungenutzte Seiten in den 64-Seiten-Blöcken vorhanden sind, die dem Index zugewiesen wurden.
Ein Fragmentierungssymptom liegt vor, wenn eine Tabelle mehr
Platz belegt, als sie „sollte“. Wieviel mehr, das
ist in der Praxis schwer zu sagen. Alle
InnoDB
-Daten und -Indizes werden in B-Bäumen
gespeichert und ihr Füllfaktor kann zwischen 50% und 100%
variieren. Ein anderes Symptom für Fragmentierung wäre es,
wenn ein Tabellenscan wie dieser mehr Zeit braucht, als er
„sollte“:
SELECT COUNT(*) FROM t WHERE a_non_indexed_column <> 12345;
(In der obigen Anfrage „überlisten“ wir die SQL-Optimierung, damit sie statt des Sekundärindex den geclusterten Index durchsucht.) Die meisten Festplatten können 10 bis 50MB/s lesen. Anhand dieses Werts können sie einschätzen, wie schnell ein Tabellenscan eigentlich laufen sollte.
Index-Scans können schneller laufen, wenn Sie regelmäßig eine
„Null“-ALTER TABLE
-Operation
durchführen:
ALTER TABLE tbl_name
ENGINE=INNODB
Dies veranlasst MySQL, die Tabelle neu zu erstellen. Eine andere Möglichkeit für eine Defragmentierungsoperation wäre es, die Tabelle mit mysqldump in eine Textdatei zu dumpen, zu löschen und aus der Dump-Datei neu zu laden.
Wenn die Einfügungen in einen Index immer in aufsteigender
Reihenfolge und Löschungen nur an seinem Ende stattfinden,
garantiert der Dateiraumverwaltungs-Algorithmus von
InnoDB
, dass keine Fragmentierung in diesem
Index auftreten kann.
Die Fehlerbehandlung in InnoDB
entspricht nicht
immer dem SQL-Standard. Nach dem Standard müsste jeder Fehler,
der während einer SQL-Anweisung auftritt, den Rollback dieser
Anweisung zur Folge haben. InnoDB
rollt jedoch
manchmal nur einen Teil der Anweisung zurück, oder aber auch die
ganze Transaktion. Die folgenden Einträge beschreiben die
Fehlerbehandlung von InnoDB
:
Wenn Ihr Tablespace vollläuft, tritt ein MySQL Table
is full
-Fehler auf und InnoDB
rollt die SQL-Anweisung zurück.
Ein Transaktions-Deadlock lässt InnoDB
die
gesamte Transaktion zurückrollen. Im Fall eines Lock Wait
Timeout rollt InnoDB
nur die letzte
SQL-Anweisung zurück.
Wenn wegen eines Deadlocks oder Lock Wait Timeouts eine
Transaktion zurückgerollt wird, so werden die in dieser
Transaktion ausgeführten Anweisungen wirkungslos. Wenn jedoch
die Startanweisung der Transaktion START
TRANSACTION
oder BEGIN
war, so
wird die Anweisung durch den Rollback nicht betroffen. Weitere
SQL-Anweisungen werden dann zu einem Teil der Transaktion, bis
ein COMMIT
, ROLLBACK
oder eine andere SQL-Anweisung eintritt, die einen impliziten
Commit verursacht.
Ein Schlüsselduplikat-Fehler rollt die SQL-Anweisung zurück,
wenn Sie nicht die IGNORE
-Option in der
Anweisung angegeben haben.
Ein row too long error
rollt die
SQL-Anweisung zurück.
Andere Fehler werden zumeist auf der MySQL-Ebene erkannt (also
oberhalb der Ebene von InnoDB
), und rollen
die zugehörige SQL-Anweisung zurück. Sperren werden bei
einem Rollback einer einzelnen SQL-Anweisung nicht
freigegeben.
Während eines impliziten Rollback und während der Ausführung
eines expliziten ROLLBACK
-Befehls von SQL zeigt
SHOW PROCESSLIST
den Wert Rolling
back
in der State
-Spalte der
betreffenden Verbindung an.
Es folgt eine (nicht vollständige) Liste häufiger
InnoDB
-spezifischer Fehler, einschließlich
ihrer Ursachen und Lösungsmöglichkeiten.
1005 (ER_CANT_CREATE_TABLE)
Tabelle kann nicht angelegt werden. Wenn die Fehlermeldung
auf errno
150 verweist, schlug die
Tabellenerzeugung fehl, weil ein Fremdschlüssel-Constraint
nicht richtig gebildet wurde.
1016 (ER_CANT_OPEN_FILE)
Die InnoDB
-Tabelle kann in den
InnoDB
-Datendateien nicht gefunden
werden, obwohl die .frm
-Datei für die
Tabelle existiert. Siehe
Abschnitt 14.2.17.1, „Troubleshooting von InnoDB
bei Data
Dictionary-Operationen“.
1114 (ER_RECORD_FILE_FULL)
InnoDB
hat keine Platz im Tablespace mehr
frei. Rekonfigurieren Sie den Tablespace, indem Sie eine
neue Datendatei hinzufügen.
1205 (ER_LOCK_WAIT_TIMEOUT)
Lock Wait Timeout ist abgelaufen. Transaktion wurde zurückgerollt.
1213 (ER_LOCK_DEADLOCK)
Transaktions-Deadlock. Führen Sie die Transaktion erneut aus.
1216 (ER_NO_REFERENCED_ROW)
Sie versuchen, eine neue Zeile einzufügen, aber da es keine Elternzeile gibt, wird ein Fremdschlüssel-Constraint verletzt. Fügen Sie als Erstes die Elternzeile ein.
1217 (ER_ROW_IS_REFERENCED)
Sie versuchen, eine Elternzeile zu löschen, die Kinder hat, wodurch ein Fremdschlüssel-Constraint verletzt wird. Löschen Sie zuerst die Kinder.
Die Bedeutung einer Betriebssystem-Fehlernummer können Sie mit dem Programm perror ermitteln, das zur MySQL-Distribution gehört.
Die folgende Tabelle enthält eine Liste der häufigsten Systemfehlercodes von Linux. Eine vollständigere Aufstellung finden Sie unter Linux-Quellcode.
1 (EPERM)
Operation nicht gestattet
2 (ENOENT)
Datei oder Verzeichnis nicht vorhanden
3 (ESRCH)
Prozess nicht vorhanden
4 (EINTR)
Unterbrochener Systemaufruf
5 (EIO)
E/A-Fehler
6 (ENXIO)
Device oder Adresse nicht vorhanden
7 (E2BIG)
Argumenteliste zu lang
8 (ENOEXEC)
Exec-Format-Fehler
9 (EBADF)
Dateinummer stimmt nicht
10 (ECHILD)
Kein Kindprozess
11 (EAGAIN)
Versuchen Sie es erneut
12 (ENOMEM)
Kein Arbeitsspeicher mehr frei
13 (EACCES)
Berechtigung verweigert
14 (EFAULT)
Adresse stimmt nicht
15 (ENOTBLK)
Block-Device erforderlich
16 (EBUSY)
Device oder Ressource ist belegt
17 (EEXIST)
Datei vorhanden
18 (EXDEV)
Cross-Device-Link
19 (ENODEV)
Device nicht vorhanden
20 (ENOTDIR)
Ist kein Verzeichnis
21 (EISDIR)
Ist ein Verzeichnis
22 (EINVAL)
Ungültiges Argument
23 (ENFILE)
Dateitabellenüberlauf
24 (EMFILE)
Zu viele geöffnete Dateien
25 (ENOTTY)
Unpassender ioctl für Device
26 (ETXTBSY)
Textdatei belegt
27 (EFBIG)
Datei zu groß
28 (ENOSPC)
Device hat keinen Platz mehr frei
29 (ESPIPE)
Unzulässige Suche
30 (EROFS)
Schreibgeschütztes Dateisystem
31 (EMLINK)
Zu viele Links
Die folgende Tabelle enthält eine Liste häufiger Windows-Systemfehlercodes. Eine vollständigere Aufstellung finden Sie auf der Website von Microsoft.
1 (ERROR_INVALID_FUNCTION)
Funktion nicht korrekt
2 (ERROR_FILE_NOT_FOUND)
System kann die Datei nicht finden
3 (ERROR_PATH_NOT_FOUND)
System kann den Pfad nicht finden
4 (ERROR_TOO_MANY_OPEN_FILES)
System kann die Datei nicht öffnen
5 (ERROR_ACCESS_DENIED)
Zugriff verweigert
6 (ERROR_INVALID_HANDLE)
Ungültiger Handle
7 (ERROR_ARENA_TRASHED)
Speichersteuerungsblöcke wurden zerstört
8 (ERROR_NOT_ENOUGH_MEMORY)
Zu wenig Speicher, um diesen Befehl zu verarbeiten
9 (ERROR_INVALID_BLOCK)
Speichersteuerungsblock-Adresse ist ungültig
10 (ERROR_BAD_ENVIRONMENT)
Die Umgebung ist nicht korrekt
11 (ERROR_BAD_FORMAT)
Versuch, ein Programm mit einem unzulässigen Format zu laden
12 (ERROR_INVALID_ACCESS)
Zugriffscode ist ungültig
13 (ERROR_INVALID_DATA)
Daten sind ungültig
14 (ERROR_OUTOFMEMORY)
Nicht genug Speicher vorhanden, um die Operation auszuführen
15 (ERROR_INVALID_DRIVE)
System kann das angegebene Laufwerk nicht finden
16 (ERROR_CURRENT_DIRECTORY)
Verzeichnis kann nicht entfernt werden
17 (ERROR_NOT_SAME_DEVICE)
System kann die Datei nicht auf ein anderes Festplattenlaufwerk verlagern
18 (ERROR_NO_MORE_FILES)
Keine weiteren Dateien vorhanden
19 (ERROR_WRITE_PROTECT)
Schreibgeschütztes Speichermedium
20 (ERROR_BAD_UNIT)
System kann das angegebene Gerät nicht finden
21 (ERROR_NOT_READY)
Gerät ist nicht bereit
22 (ERROR_BAD_COMMAND)
Gerät erkennt den Befehl nicht
23 (ERROR_CRC)
Datenfehler (zyklische Redundanzprüfung)
24 (ERROR_BAD_LENGTH)
Das Programm hat einen Befehl gegeben, dessen Länge nicht stimmt
25 (ERROR_SEEK)
Das Laufwerk konnte einen bestimmten Bereich oder Track auf der Festplatte nicht finden
26 (ERROR_NOT_DOS_DISK)
Kein Zugriff auf die Platte oder Diskette
27 (ERROR_SECTOR_NOT_FOUND)
Das Laufwerk kann den angeforderten Sektor nicht finden
28 (ERROR_OUT_OF_PAPER)
Kein Papier im Drucker
29 (ERROR_WRITE_FAULT)
System kann auf das angegebene Gerät nicht schreiben
30 (ERROR_READ_FAULT)
System kann von dem angegebenen Gerät nicht lesen
31 (ERROR_GEN_FAILURE)
Ein mit dem System verbundenes Gerät funktioniert nicht
32 (ERROR_SHARING_VIOLATION)
Der Prozess kann nicht auf die Datei zugreifen, da sie von einem anderen Prozess benutzt wird
33 (ERROR_LOCK_VIOLATION)
Der Prozess kann nicht auf die Datei zugreifen, da sie von einem anderen Prozess teilweise gesperrt wurde
34 (ERROR_WRONG_DISK)
Verkehrte Diskette im Laufwerk. Legen Sie %2 (Volume-Seriennummer: %3) in Laufwerk %1 ein
36 (ERROR_SHARING_BUFFER_EXCEEDED)
Zu viele Dateien für gemeinsame Nutzung geöffnet
38 (ERROR_HANDLE_EOF)
Dateiende erreicht
39 (ERROR_HANDLE_DISK_FULL)
Festplatte ist voll
87 (ERROR_INVALID_PARAMETER)
Der Parameter ist verkehrt. (Wenn auf Windows dieser Fehler
auftritt und innodb_file_per_table
in
einer Serveroptionsdatei eingeschaltet wurde, fügen Sie der
Datei zusätzlich die Zeile
innodb_flush_method=unbuffered
hinzu.)
112 (ERROR_DISK_FULL)
Festplatte ist voll
123 (ERROR_INVALID_NAME)
Dateiname oder Verzeichnisname oder Volume-Label-Syntax ist verkehrt
1450 (ERROR_NO_SYSTEM_RESOURCES)
Systemressourcen reichen nicht, um den angefragten Service abzuschließen
Warnung: Konvertieren Sie
niemals MySQL-Systemtabellen in der
mysql
-Datenbank aus dem
MyISAM
- in das
InnoDB
-Format! Diese Operation wird nicht
unterstützt. Wenn Sie dies tun, kann MySQL erst dann wieder
gestartet werden, wenn Sie die alten Systemtabellen aus einem
Backup wiederhergestellt oder mit dem Skript
mysql_install_db neu generiert haben.
Eine Tabelle darf nicht mehr als 1000 Spalten haben.
Die interne maximale Schlüssellänge beträgt 3500 Bytes, aber MySQL selbst schränkt dies auf 1024 Bytes ein.
Die maximale Zeilenlänge beträgt (außer bei
VARCHAR
-, BLOB
- und
TEXT
-Spalten) etwas weniger als die Hälfte
einer Datenbankseite, also rund 8000 Bytes.
LONGBLOB
- und
LONGTEXT
-Spalten müssen kleiner als 4GB
und die maximale Länge einer Zeile (auch bei
BLOB
- und TEXT
-Spalten)
muss kleiner als 4GB sein. InnoDB
speichert
die ersten 768 Bytes einer VARCHAR
-,
BLOB
- oder TEXT
-Spalte
in der Zeile und den Rest in separaten Seiten.
Obwohl InnoDB
intern auch Zeilen von mehr
als 65535 unterstützt, können Sie keine Zeile definieren,
die VARCHAR
-Spalten mit einer kombinierten
Größe von mehr als 65535 enthält:
mysql>CREATE TABLE t (a VARCHAR(8000), b VARCHAR(10000),
->c VARCHAR(10000), d VARCHAR(10000), e VARCHAR(10000),
->f VARCHAR(10000), g VARCHAR(10000)) ENGINE=InnoDB;
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs
Auf manchen älteren Betriebssystemen müssen Dateien kleiner
als 2GB sein. Das ist zwar keine
InnoDB
-spezifische Beschränkung, aber wenn
Sie einen großen Tablespace benötigen, müssen Sie diesen so
konfigurieren, dass er mehrere kleine statt einer großen
Datendatei enthält.
Die kombinierte Größe aller
InnoDB
-Logdateien muss unter 4GB liegen.
Die Mindestgröße eines Tablespace beträgt 10MB und seine Höchstgröße vier Milliarden Datenbankseiten (64TB). Dies ist auch die Maximalgröße für eine Tabelle.
InnoDB
-Tabellen unterstützen keine
FULLTEXT
-Indizes.
ANALYZE TABLE
ermittelt die
Indexkardinalität (anhand der
Cardinality
-Spalte der Ausgabe von
SHOW INDEX
), indem er acht Zufallssprünge
in jeden der Indexbäume unternimmt und die Schätzungen der
Indexkardinalität entsprechend aktualisiert. Da dies nur
Schätzungen sind, können unterschiedliche Ausführungen von
ANALYZE TABLE
unterschiedliche Zahlen
ergeben. Dadurch läuft ANALYZE TABLE
auf
InnoDB
-Tabellen zwar schnell, aber nicht zu
100% präzise, da es nicht alle Zeilen berücksichtigt.
MySQL verwendet die Indexkardinalitäts-Schätzungen nur in
der Optimierung von Joins. Ist ein Join nicht richtig
optimiert, können Sie es mit ANALYZE TABLE
versuchen. In den seltenen Fällen, da ANALYZE
TABLE
für Ihre Tabellen keine ausreichend guten
Werte produziert, können Sie Ihre Anfragen mit FORCE
INDEX
ausführen und ihnen damit einen bestimmten
Index aufzwingen, oder die Systemvariable
max_seeks_for_key
setzen, damit MySQL eher
im Index nachschaut, als Tabellen zu scannen. Siehe
Abschnitt 5.2.2, „Server-Systemvariablen“ und
Abschnitt A.6, „Probleme im Zusammenhang mit dem Optimierer“.
SHOW TABLE STATUS
zeigt keine präzisen
Statistikdaten über InnoDB
-Tabellen an,
wenn man von der physikalischen Größe absieht, die für sie
reserviert ist. Die Zeilenzahl ist nur eine grobe Schätzung,
die für die SQL-Optimierung genutzt wird.
InnoDB
pflegt keinen internen Zähler für
die Anzahl der Zeilen in einer Tabelle. (In der Praxis wäre
das wegen der Multiversionierung auch etwas kompliziert.) Um
eine SELECT COUNT(*) FROM t
-Anweisung zu
verarbeiten, muss InnoDB
einen Index der
Tabelle scannen. Das braucht Zeit, wenn der Index nicht
komplett im Bufferpool liegt. Um schneller eine Zahl zu
erhalten, müssen Sie selbst eine Zählertabelle erstellen und
dafür sorgen, dass Ihre Anwendung sie bei Einfügungen und
Löschungen aktualisiert. Wenn sich Ihre Tabelle nicht oft
ändert, ist der MySQL-Anfragecache eine gute Lösung.
SHOW TABLE STATUS
kann ebenfalls eingesetzt
werden, wenn Ihnen ein Näherungswert genügt. Siehe
Abschnitt 14.2.11, „Tipps zur Leistungssteigerung“.
Auf Windows speichert InnoDB
Datenbank- und
Tabellennamen intern immer in Kleinbuchstaben. Um Datenbanken
im Binärformat von Unix auf Windows oder umgekehrt zu
übertragen, sollten Sie immer explizit klein geschriebene
Namen für Datenbanken und Tabellen verwenden.
Für eine AUTO_INCREMENT
-Spalte müssen Sie
immer einen Index für die Tabelle definieren, der nur diese
AUTO_INCREMENT
-Spalte enthält. In
MyISAM
-Tabellen kann die
AUTO_INCREMENT
-Spalte auch Teil eines
Mehrspaltenindex sein.
Wenn Sie den MySQL-Server neu starten, kann
InnoDB
einen alten Wert wiederverwenden,
der für eine AUTO_INCREMENT
-Spalte zwar
angelegt, aber nie gespeichert wurde (also einen Wert, der
während einer älteren Transaktion generiert wurde, die
zurückgerollt worden ist).
Wenn einer AUTO_INCREMENT
-Spalte die Werte
ausgehen, bricht InnoDB
einen
BIGINT
auf
-9223372036854775808
und BIGINT
UNSIGNED
auf 1
um. Da jedoch
BIGINT
-Werte 64 Bits haben, würde es,
selbst wenn Sie eine Million Zeilen pro Sekunde einfügten,
immer noch fast dreihunderttausend Jahre dauern, bis
BIGINT
an seine Grenze stößt. Bei allen
anderen Integerspalten würde ein Fehler wegen
Schlüsselduplikat die Folge sein. MyISAM
funktioniert ähnlich, da dies im Wesentlichen dem normalen
MySQL-Verhalten und nicht dem einer bestimmten Speicher-Engine
entspricht.
DELETE FROM
generiert die
Tabelle nicht neu, sondern löscht eine nach der anderen alle
Zeilen.
tbl_name
Unter bestimmten Gegebenheiten wird TRUNCATE
für eine
tbl_name
InnoDB
-Tabelle wie DELETE FROM
behandelt und
setzt nicht den tbl_name
AUTO_INCREMENT
-Zähler
zurück. Siehe Abschnitt 13.2.9, „TRUNCATE
“.
In MySQL 5.1, erwirbt die MySQL-Operation
LOCK TABLES
zwei Sperren auf jeder Tabelle,
wenn innodb_table_locks=1
(die
Standardeinstellung). Zusätzlich zu einer Tabellensperre auf
der MySQL-Ebene, errichtet es auch eine
InnoDB
-Tabellensperre. Ältere
MySQL-Versionen errichteten keine
InnoDB
-Tabellensperren. Dieses alte
Verhalten kann mit innodb_table_locks=0
eingestellt werden. Wenn keine
InnoDB
-Tabellensperre erworben wird, läuft
LOCK TABLES
auch dann, wenn einige
Datensätze der Tabellen von anderen Transaktionen gesperrt
sind.
Alle InnoDB
-Sperren, die eine Transaktion
hält, werden freigegeben, wenn die Transaktion committet oder
abgebrochen wird. Also hat es wenig Sinn LOCK
TABLES
auf InnoDB
-Tabellen im
AUTOCOMMIT=1
-Modus aufzurufen, da die
InnoDB
-Tabellensperren sofort freigegeben
würden.
Manchmal wäre es nützlich, im Laufe einer Transaktion noch
weitere Tabellen zu sperren. Doch leider führt LOCK
TABLES
in MySQL ein implizites
COMMIT
und UNLOCK TABLES
aus. Es ist eine InnoDB
-Variante von
LOCK TABLES
geplant, die auch inmitten
einer Transaktion ausgeführt werden kann.
Die LOAD TABLE FROM MASTER
-Anweisung zum
Einrichten eines Slaveservers für die Replikation
funktioniert noch nicht mit
InnoDB
-Tabellen. Als Workaround können Sie
die Tabelle auf dem Master in MyISAM
konvertieren, dann laden und hinterher die Mastertabelle
wieder auf InnoDB
umstellen. Dies geht
jedoch nicht mit Tabellen, die
InnoDB
-spezifische Features wie etwa
Fremdschlüssel verwenden.
Die Standardgröße für Datenbankseiten in
InnoDB
beträgt 16KB. Indem Sie den Code
rekompilieren, können Sie Werte zwischen 8KB und 64KB
einstellen. Sie müssen dazu die Werte von
UNIV_PAGE_SIZE
und
UNIV_PAGE_SIZE_SHIFT
in der Quelldatei
univ.i
ändern.
Trigger werden zurzeit noch nicht durch kaskadierende Fremdschlüsselaktionen aktiviert.
Die folgenden allgemeinen Richtlinien gelten für die Behebung von
InnoDB
-Problemen:
Wenn eine Operation scheitert oder Sie einen Bug vermuten,
schauen Sie in das Fehlerlog des MySQL-Servers. es ist die
Datei im Data Directory, die das Suffix
.err
trägt.
Für die Problembehebung führen Sie MySQL am besten an der
Eingabeaufforderung aus, anstatt durch den
mysqld_safe-Wrapper oder als
Windows-Dienst. Dann können Sie erkennen, was
mysqld auf die Konsole ausgibt, und
verstehen besser, was vor sich geht. Auf Windows müssen Sie
den Server mit der --console
-Option
starten, um die Ausgabe ans Konsolenfenster zu schicken.
Nutzen Sie die InnoDB
-Monitore, um
Informationen über ein Problem einzuholen (siehe
Abschnitt 14.2.11.1, „Der InnoDB-Monitor“). Wenn es sich um ein
Leistungsproblem handelt oder Ihr Server sich anscheinend
aufgehängt hat, geben Sie mithilfe von
innodb_monitor
Informationen über den
internen Zustand von InnoDB
aus. Handelt es
sich um ein Sperrenproblem, verwenden Sie
innodb_lock_monitor
. Hat das Problem mit
der Erzeugung von Tabellen oder mit anderen Data
Dictionary-Operationen zu tun, geben Sie mithilfe von
innodb_table_monitor
den Inhalt des
InnoDB
-internen Data Dictionary aus.
Wenn Sie Tabellenschäden vermuten, führen Sie auf der
betreffenden Tabelle CHECK TABLE
aus.
Ein besonderes Problem mit Tabellen besteht darin, dass der
MySQL-Server Data Dictionary-Informationen in
.frm
-Dateien in Datenbankverzeichnissen
ablegt, während InnoDB
die Informationen
auch in sein eigenes Data Dictionary innerhalb der
Tablespace-Dateien speichert. Wenn Sie
.frm
-Dateien verschieben oder der Server
inmitten einer Data Dictionary-Operation abstürzt, kann es
geschehen, dass die Speicherorte der
.frm
-Dateien hinterher nicht mehr zu den
Angaben im InnoDB
-internen Data Dictionary
passen.
Eine gescheiterte CREATE TABLE
-Anweisung ist
ein Symptom für ein nicht mehr synchrones Data Dictionary. Wenn
dies passiert, schauen Sie im Fehlerlog des Servers nach. Wird
dort behauptet, dass die Tabelle im
InnoDB
-internen Data Dictionary bereits
existiert, so haben Sie in den
InnoDB
-Tablespace-Dateien, eine verwaiste
Tabelle, zu der keine .frm
-Datei gehört.
Die Fehlermeldung sieht wie folgt aus:
InnoDB: Error: table test/parent already exists in InnoDB internal InnoDB: data dictionary. Have you deleted the .frm file InnoDB: and not used DROP TABLE? Have you used DROP DATABASE InnoDB: for InnoDB tables in MySQL version <= 3.23.43? InnoDB: See the Restrictions section of the InnoDB manual. InnoDB: You can drop the orphaned table inside InnoDB by InnoDB: creating an InnoDB table with the same name in another InnoDB: database and moving the .frm file to the current database. InnoDB: Then MySQL thinks the table exists, and DROP TABLE will InnoDB: succeed.
Nach den Instruktionen der Fehlermeldung können Sie die
verwaiste Tabelle löschen. Wenn Sie DROP
TABLE
immer noch nicht ausführen können, kann das
Problem auch an der AutoVervollständigung von Namen durch den
mysql-Client liegen. Um dieses zu verhindern,
starten Sie den mysql-Client mit der
--disable-auto-rehash
-Option und versuchen noch
einmal Ihr DROP TABLE
. (Bei eingeschalteter
Namensvervollständigung versucht mysql eine
Liste von Tabellennamen zu erstellen. Das scheitert, wenn ein
Problem wie das oben beschriebene auftritt.)
Ein anderes Symptom für ein nicht mehr synchrones Data
Dictionary liegt vor, wenn MySQL meldet, dass eine
.InnoDB
-Datei nicht geöffnet werden kann:
ERROR 1016: Can't open file: 'child2.InnoDB'. (errno: 1)
Im Fehlerlog können Sie dann eine Nachricht wie diese vorfinden:
InnoDB: Cannot find table test/child2 from the internal data dictionary InnoDB: of InnoDB though the .frm file for the table exists. Maybe you InnoDB: have deleted and recreated InnoDB data files but have forgotten InnoDB: to delete the corresponding .frm files of InnoDB tables?
Dies bedeutet, dass Sie eine verwaiste
.frm
-Datei haben, zu der es in
InnoDB
keine Tabelle gibt. Die verwaiste
.frm
-Datei können Sie dann manuell
löschen.
Wenn MySQL mitten in einer ALTER
TABLE
-Operation abstürzt, haben Sie hinterher
vielleicht eine verwaiste temporäre Tabelle im
InnoDB
-Tablespace. Mit
innodb_table_monitor
sehen Sie dann eine
Tabelle namens #sql-...
aufgeführt. Sie
können SQL-Anweisungen auf Tabellen ausführen, deren Name das
Zeichen ‘#
’ enthält, wenn Sie
den Namen in Backticks setzen. So können Sie die verwaiste
Tabelle wie jede andere auch mit den zuvor beschriebenen
Methoden löschen. Achtung: Um eine Datei in der Unix-Shell zu
kopieren oder umzubenennen, müssen Sie den Dateinamen, wenn er
‘#
’ enthält, in doppelte
Anführungszeichen setzen.
Eine MERGE
-Tabelle, auch bekannt als
MRG_MyISAM
, ist eine Sammlung identischer
MyISAM
-Tabellen, die als eine einzige Tabelle
verwendet werden können. „Identisch“ bedeutet, dass
alle Tabellen dieselben Spalten- und Indexdaten haben. Sie können
keine MyISAM
-Tabellen zusammenführen
(„mergen“) , in denen die Spalten oder Indizes in
einer unterschiedlichen Reihenfolge stehen, oder die nicht genau
gleich viele Spalten haben. Allerdings können alle
MyISAM
-Tabellen mit
myisampack komprimiert werden. Siehe
Abschnitt 8.4, „myisampack — Erzeugung komprimierter, schreibgeschützter MyISAM Tabellen“. Unterschiede in den
Tabellenoptionen, wie beispielsweise
AVG_ROW_LENGTH
, MAX_ROWS
oder PACK_KEYS
spielen keine Rolle.
Wenn Sie eine MERGE
-Tabelle anlegen, erzeugt
MySQL auf der Festplatte zwei Dateien, deren Namen jeweils mit dem
Tabellennamen beginnen und Erweiterungen haben, die den Dateityp
angeben. Eine .frm
-Datei speichert das
Tabellenformat und eine .MRG
-Datei enthält
die Namen der Tabellen, die wie eine einzige benutzt werden
sollen. Die Tabellen müssen nicht in derselben Datenbank
vorliegen wie die MERGE
-Tabelle selbst.
Mit MERGE
-Tabellen können Sie die Anweisungen
SELECT
, DELETE
,
UPDATE
und INSERT
verwenden.
Sie benötigen SELECT
-,
UPDATE
- und DELETE
-Rechte
für die MyISAM
-Tabellen, die Sie einer
MERGE
-Tabelle zuordnen möchten.
Wenn Sie die MERGE
-Tabelle mit
DROP
löschen, löschen Sie damit nur die
MERGE
-Spezifikation. Die zugrunde liegenden
Tabellen sind davon nicht betroffen.
Um eine MERGE
-Tabelle anzulegen, müssen Sie in
einer
UNION=(
-Klausel angeben, welche list-of-tables
)MyISAM
-Tabellen Sie
als eine einzige benutzen möchten. Optional können Sie mit der
Option INSERT_METHOD
erreichen, dass
Einfügeoperationen in der MERGE
-Tabelle auf
der ersten oder der letzten Tabelle der
UNION
-Liste stattfinden. Wenn Sie den Wert
FIRST
einsetzen, geschieht die Einfügung in
der ersten, wenn Sie LAST
einsetzen, in der
letzten Tabelle. Wenn Sie die
INSERT_METHOD
-Option nicht oder nur mit dem
Wert NO
angeben, zieht jeder Versuch, Zeilen in
die MERGE
-Tabelle einzufügen, eine
Fehlermeldung nach sich.
Das folgende Beispiel zeigt, wie eine
MERGE
-Tabelle angelegt wird:
mysql>CREATE TABLE t1 (
->a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
->message CHAR(20)) ENGINE=MyISAM;
mysql>CREATE TABLE t2 (
->a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
->message CHAR(20)) ENGINE=MyISAM;
mysql>INSERT INTO t1 (message) VALUES ('Testing'),('table'),('t1');
mysql>INSERT INTO t2 (message) VALUES ('Testing'),('table'),('t2');
mysql>CREATE TABLE total (
->a INT NOT NULL AUTO_INCREMENT,
->message CHAR(20), INDEX(a))
->ENGINE=MERGE UNION=(t1,t2) INSERT_METHOD=LAST;
Der ältere Begriff TYPE
wird aus Gründen der
Abwärtskompatibilität noch als Synonym für
ENGINE
akzeptiert, doch
ENGINE
ist der aktuelle Begriff, während
TYPE
mittlerweile veraltet ist.
Beachten Sie, dass die Spalte a
in den zugrunde
liegenden MyISAM
-Tabellen ein PRIMARY
KEY
ist, aber nicht in der
MERGE
-Tabelle. Dort ist diese Spalte zwar auch
indiziert, aber nicht als PRIMARY KEY
, da eine
MERGE
-Tabelle für die ihr zugrunde liegenden
Tabellen keine Eindeutigkeit erzwingen kann.
Nachdem Sie die MERGE
-Tabelle angelegt haben,
können Sie Anfragen schreiben, die auf der Tabellengruppe als
Ganzes operieren:
mysql> SELECT * FROM total;
+---+---------+
| a | message |
+---+---------+
| 1 | Testing |
| 2 | table |
| 3 | t1 |
| 1 | Testing |
| 2 | table |
| 3 | t2 |
+---+---------+
Beachten Sie, dass sich die .MRG
-Datei direkt
von außerhalb des MySQL-Servers bearbeiten lässt:
shell>cd /
shell>mysql-data-directory
/current-database
ls -1 t1 t2 > total.MRG
shell>mysqladmin flush-tables
Um eine Neuzuordnung einer MERGE
-Tabelle zu
einer anderen Gruppe von MyISAM
-Tabellen zu
erzielen, gibt es folgende Methoden:
Sie löschen die MERGE
-Tabelle mit
DROP
und erstellen sie neu.
Sie ändern die Liste der zugrunde liegenden Tabellen mit
ALTER TABLE
.
tbl_name
UNION=(...)
Sie ändern die .MRG
-Datei und geben eine
FLUSH TABLE
-Anweisung für die
MERGE
-Tabelle und alle zugrunde liegenden
Tabellen aus, damit die Speicher-Engine die neue
Definitionsdatei lesen muss.
MERGE
-Tabellen können bei der Lösung
folgender Probleme behilflich sein:
Einfache Verwaltung einer Menge von Logtabellen. So können
Sie zum Beispiel Daten verschiedener Monate in getrennte
Tabellen laden, einige davon mit myisampack
komprimieren und dann eine MERGE
-Tabelle
anlegen, um das Ganze als ein einziges Log zu verwenden.
Mehr Schnelligkeit. Sie können eine große,
schreibgeschützte Tabelle nach bestimmten Kriterien
aufspalten und die entstehenden Tabellen auf verschiedene
Festplatten speichern. Mit einer
MERGE
-Tabelle aus diesen Einzeltabellen
haben Sie schnelleren Zugriff als mit der großen
Ursprungstabelle.
Effizienteres Suchen. Wenn Sie genau wissen, was Sie wollen,
können Sie für manche Anfragen eine einzelne der
aufgespaltenen Tabellen und für andere die
MERGE
- Tabelle benutzen. Sie können sogar
eine Vielzahl verschiedener MERGE
-Tabellen
bilden, die zum Teil dieselben Einzeltabellen benutzen.
Reparaturen werden effizienter. Es ist einfacher, kleinere
Tabellen zu reparieren, die einer
MERGE
-Tabelle zugeordnet sind, als eine
einzige große Tabelle.
Viele Tabellen können wie eine einzige sofort zugeordnet
werden. Eine MERGE
-Tabelle benötigt keinen
eigenen Index, da sie die Indizes der Einzeltabellen
verwendet. Infolgedessen lassen sich Sammlungen von
MERGE
-Tabellen sehr
schnell erstellen oder neu zuordnen. (Beachten Sie, dass Sie
trotzdem bei der Erstellung einer
MERGE
-Tabelle die Indexdefinitionen angeben
müssen auch wenn keine Indizes angelegt werden.)
Wenn Sie aus mehreren Tabellen nach Bedarf eine einzige,
große Tabelle erstellen müssen, ist es günstiger,
stattdessen eine MERGE
-Tabelle anzulegen.
Diese ist viel schneller und spart eine Menge Speicherplatz.
Mit MERGE
-Tabellen können Sie die
Dateigrößenbeschränkung Ihres Betriebssystems umgehen. Eine
einzelne, große MyISAM
-Tabelle würde
durch dieses Limit begrenzt, aber eine Sammlung von kleineren
MyISAM
-Tabellen nicht.
Sie können einen Alias oder ein Synonym für eine
MyISAM
-Tabelle anlegen, indem Sie eine
MERGE
-Tabelle definieren, der nur diese
eine Tabelle zugeordnet ist. Der Einfluss auf die Leistung
dürfte kaum spürbar sein (nur ein paar indirekte Aufrufe und
memcpy()
-Aufrufe für jede Leseoperation).
Die Nachteile von MERGE
-Tabellen sind:
Es dürfen nur identische MyISAM
-Tabellen
für eine MERGE
-Tabelle benutzt werden.
Eine Reihe von MyISAM
-Features steht für
MERGE
-Tabellen nicht zur Verfügung. Sie
können zum Beispiel keine FULLTEXT
-Indizes
auf ihnen anlegen. (Es bleibt Ihnen natürlich unbenommen,
FULLTEXT
-Indizes auf den zugrunde liegenden
MyISAM
-Tabellen anzulegen, doch aber auf
der MERGE
-Tabelle können Sie keine
Volltextsuche ausführen.)
Wenn die MERGE
-Tabelle nicht-temporär ist,
müssen auch die zugrunde liegenden
MyISAM
-Tabellen nicht-temporär sein. Ist
die MERGE
-Tabelle hingegen temporär,
können die MyISAM
-Tabellen eine beliebige
Mixtur aus temporären und nicht-temporären Tabellen sein.
MERGE
-Tabellen verwenden mehr
Dateideskriptoren. Wenn 10 Clients eine
MERGE
-Tabelle ansprechen, die ihrerseits 10
Tabellen abbildet, benutzt der Server (10 × 10) + 10
Dateideskriptoren. (10 Datendateideskriptoren für jeden der
10 Clients und 10 Indexdateideskriptoren, die von den Clients
gemeinsam genutzt werden.)
Lesevorgänge von Schlüsseln sind langsamer. Wenn Sie einen
Schlüssel lesen, muss die
MERGE
-Speicher-Engine eine Leseoperation
auf allen zugrunde liegenden Tabellen ausführen, um
festzustellen, welche dem gegebenen Schlüssel am besten
entspricht. Um den nächsten Schlüssel zu lesen, muss die
MERGE
-Speicher-Engine die Lesepuffer nach
ihm durchsuchen. Erst wenn ein Schlüsselpuffer aufgebraucht
ist, muss die Speicher-Engine den nächsten Schlüsselblock
lesen. Das macht MERGE
-Schlüssel in
eq_ref
-Suchen viel langsamer, aber nicht in
ref
-Suchen. Unter Abschnitt 7.2.1, „EXPLAIN
-Syntax (Informationen über ein
SELECT
erhalten)“
finden Sie weitere Informationen über
eq_ref
und ref
.
Ein spezielles Forum zur Speicher-Engine
MERGE
finden Sie unter
http://forums.mysql.com/list.php?93.
Folgende Probleme mit MERGE
-Tabellen sind
bekannt:
Wenn Sie mit ALTER TABLE
versuchen, eine
MERGE
-Tabelle in eine andere
Speicher-Engine umzuwandeln, geht die Zuordnung der zugrunde
liegenden Tabellen verloren. Stattdessen werden die Zeilen
der zugrunde liegenden MyISAM
-Tabellen in
die geänderte Tabelle kopiert, die dann die neue
Speicher-Engine verwendet.
REPLACE
funktioniert nicht.
DROP TABLE
, ALTER
TABLE
, DELETE
ohne
WHERE
-Klausel, REPAIR
TABLE
, TRUNCATE TABLE
,
OPTIMIZE TABLE
oder ANALYZE
TABLE
dürfen auf keine Tabelle angewendet werden,
die einer offenen MERGE
-Tabelle
zugeordnet ist. Wenn Sie dies tun, verweist die
MERGE
-Tabelle später weiterhin auf die
Originaltabelle, was zu unerwarteten Ergebnissen führen
kann. Am einfachsten können Sie dieses Problem umgehen,
indem Sie mit einer FLUSH
TABLES
-Anweisung vor diesen Operationen dafür
sorgen, dass keine MERGE
-Tabellen offen
bleiben.
Unter Windows funktioniert kein DROP
TABLE
auf einer Tabelle, die gerade von einer
MERGE
-Tabelle benutzt wird, da die
Tabellenzuordnung der Speicher-Engine
MERGE
vor der oberen Schicht von MySQL
verborgen wird. Da Windows das Löschen geöffneter Dateien
nicht gestattet, müssen Sie zuerst alle
MERGE
-Tabellen auf die Festplatte
zurückschreiben (mit FLUSH TABLES
) oder
die MERGE
-Tabelle vor der anderen Tabelle
löschen.
Eine MERGE
-Tabelle kann keine Uniqueness
Constraints über die gesamte Tabelle hinweg aufrecht
erhalten. Wenn Sie ein INSERT
ausführen,
werden die Daten in die erste oder letzte der
MyISAM
-Tabellen geladen (je nach dem Wert
der Option INSERT_METHOD
). MySQL
gewährleistet die Eindeutigkeit von Unique-Keys innerhalb
dieser einen MyISAM
-Tabelle, aber nicht
für die gesamte Tabellengruppe.
Beim Anlegen einer MERGE
-Tabelle wird
nicht geprüft, ob die zugrunde liegenden Tabellen
existieren und gleich strukturiert sind. Wenn die
MERGE
-Tabelle verwendet wird, prüft
MySQL, ob alle zugeordneten Tabellen gleich lange Zeilen
haben, aber narrensicher ist diese Überprüfung nicht.
Legen Sie eine MERGE
-Tabelle aus
ungleichen MyISAM
-Tabellen an, so müssen
Sie sich auf ein paar seltsame Probleme gefasst machen.
Die Reihenfolge der Indizes in der
MERGE
-Tabelle und den ihr zugrunde
liegenden Tabellen sollte gleich sein. Wenn Sie mit
ALTER TABLE
einer Tabelle, die in einer
MERGE
-Tabelle benutzt wird, einen
UNIQUE
-Index hinzufügen, und dann mit
einem weiteren ALTER TABLE
der
MERGE
-Tabelle einen nicht-eindeutigen
Index geben, ist die Reihenfolge der Indizes
unterschiedlich, wenn auch die zugrunde liegende Tabelle
zuvor bereits einen nicht-eindeutigen Index hatte. (Dazu
kommt es, weil ALTER TABLE
UNIQUE
-Indizes vor nicht-eindeutige
Indizes setzt, um das schnelle Auffinden doppelter
Schlüsselwerte zu erleichtern.) Infolgedessen können
Anfragen von Tabellen mit solchen Indizes unerwartete
Ergebnisse liefern.
Die Speicher-Engine MEMORY
legt Tabellen mit
Inhalten an, die im Arbeitsspeicher gespeichert sind. Früher
wurden sie als HEAP
-Tabellen bezeichnet. Heute
ist MEMORY
der bevorzugte Ausdruck, auch wenn
HEAP
aus Gründen der Abwärtskompatibilität
weiter unterstützt wird.
Zu jeder MEMORY
-Tabelle gehört eine
Festplattendatei. Der Dateiname beginnt mit dem Tabellennamen und
hat die Erweiterung .frm
, um anzuzeigen, dass
hier die Tabellendefinition (frm = form) gespeichert ist.
Um explizit eine MEMORY
-Tabelle anzulegen,
geben Sie dies in der Tabellenoption ENGINE
an:
CREATE TABLE t (i INT) ENGINE = MEMORY;
Der ältere Begriff TYPE
wird aus Gründen der
Abwärtskompatibilität noch als Synonym für
ENGINE
akzeptiert, doch
ENGINE
ist der aktuelle Begriff, während
TYPE
mittlerweile veraltet ist.
Wie der Name schon sagt, werden MEMORY
-Tabellen
im Arbeitsspeicher gespeichert und sie benutzen nach
Voreinstellung einen gehashten Index. Das macht sie sehr schnell
und nützlich für temporäre Tabellen. Wenn allerdings der Server
abstürzt, gehen alle in MEMORY
-Tabellen
gespeicherten Daten verloren. Die Tabellen selbst bestehen weiter,
da ihre Definitionen in .frm
-Dateien auf der
Festplatte gespeichert sind, doch ihre Daten sind fort, wenn der
Server wieder hochfährt.
Das folgende Beispiel zeigt, wie eine
MEMORY
-Tabelle erzeugt, benutzt und gelöscht
wird:
mysql>CREATE TABLE test ENGINE=MEMORY
->SELECT ip,SUM(downloads) AS down
->FROM log_table GROUP BY ip;
mysql>SELECT COUNT(ip),AVG(down) FROM test;
mysql>DROP TABLE test;
Kennzeichen von MEMORY
-Tabellen:
Speicherplatz für MEMORY
-Tabellen wird in
kleinen Blöcken zugewiesen. Die Tabellen verwenden 100%
dynamisches Hashing für Einfügeoperationen. Es werden keine
Overflow- Bereiche und kein zusätzlicher Platz für
Schlüssel oder für Freelists benötigt. Gelöschte Zeilen
werden in eine verkettete Liste geschrieben und
wiederverwendet, wenn neue Daten in die Tabelle eingefügt
werden. MEMORY
-Tabellen haben auch keine
Probleme mit Löschen plus Einfügen, was normalerweise bei
gehashten Tabellen häufig vorkommt.
MEMORY
-Tabellen können bis zu 32 Indizes
mit jeweils bis zu 16 Spalten und einer maximalen
Schlüssellänge von 500 Bytes haben.
Die Speicher-Engine MEMORY
implementiert
sowohl HASH
- als auch
BTREE
-Indizes. Mit einer
USING
-Klausel können Sie angeben, welchen
von beiden Sie wünschen:
CREATE TABLE lookup (id INT, INDEX USING HASH (id)) ENGINE = MEMORY; CREATE TABLE lookup (id INT, INDEX USING BTREE (id)) ENGINE = MEMORY;
Die allgemeinen Merkmale von B-Baum- und Hash-Indizes werden in Abschnitt 7.4.5, „Wie MySQL Indizes benutzt“ beschrieben.
Es darf keine nicht-eindeutigen Schlüssel auf eine
MEMORY
-Tabelle geben. (Dies ist
ungebräuchlich für Implementierungen von Hash-Indizes.)
Wenn Sie einen Hash-Index auf einer
MEMORY
-Tabelle mit sehr vielen doppelten
Schlüsseln haben (viele Indexeinträge enthalten denselben
Wert), dann laufen Updates, die Schlüsselwerte betreffen,
sowie sämtliche Löschoperationen deutlich langsamer. Wie
viel langsamer, hängt von dem Ausmaß der
Schlüsselduplikation ab (umgekehrt proportional zur
Indexkardinalität). Um dieses Problem zu vermeiden, verwenden
Sie einen BTREE
-Index.
Indizierte Spalten können NULL
-Werte
enthalten.
MEMORY
-Tabellen verwenden ein
Speicherformat mit fester Zeilenlänge.
MEMORY
-Tabellen dürfen keine
BLOB
- oder TEXT
-Spalten
enthalten.
MEMORY
unterstützt
AUTO_INCREMENT
-Spalten.
INSERT DELAYED
kann mit
MEMORY
-Tabellen verwendet werden. Siehe
Abschnitt 13.2.4.2, „INSERT DELAYED
“.
MEMORY
-Tabellen werden von allen Clients
gemeinsam genutzt (wie jede andere
nicht-TEMPORARY
-Tabelle).
MEMORY
-Tabellen speichern ihren Inhalt im
Arbeitsspeicher, eine Eigenschaft, die sie mit internen
Tabellen gemeinsam haben, die der Server bei der Verarbeitung
von Anfragen nebenbei anlegt. Die beiden Tabellentypen
unterscheiden sich jedoch darin, dass
MEMORY
-Tabellen im Gegensatz zu den
internen Tabellen nicht von Speicherkonvertierung betroffen
sind:
Wenn eine interne Tabelle zu groß wird, konvertiert der
Server sie automatisch in eine Festplattentabelle. Deren
maximale Größe wird durch die Systemvariable
tmp_table_size
festgelegt.
MEMORY
-Tabellen werden nie in
Festplattentabellen konvertiert. Um sicherzustellen, dass
Sie nicht versehentlich den gesamten Arbeitsspeicher
benutzen, können Sie die Systemvariable
max_heap_table_size
so einstellen, dass
auch MEMORY
-Tabellen einem
Größenlimit unterliegen. Für einzelne Tabellen können
Sie auch in der CREATE TABLE
-Anweisung
die Tabellenoption MAX_ROWS
-Tabelle
setzen.
Der Server benötigt genug Arbeitsspeicher, um alle
MEMORY
-Tabellen zu pflegen, die zur selben
Zeit gebraucht werden.
Um den von einer MEMORY
-Tabelle belegten
Speicher wieder freizugeben, wenn sie nicht länger benötigt
wird, führen Sie DELETE
oder
TRUNCATE TABLE
aus oder löschen die
Tabelle mit DROP TABLE
.
Möchten Sie beim Starten des MySQL-Servers Daten in eine
MEMORY
-Tabelle laden, so können Sie die
Option --init-file
nutzen. In diese Datei
können Sie Anweisungen wie INSERT INTO ...
SELECT
oder LOAD DATA INFILE
setzen, um die Tabelle aus einer persistenten Datenquelle zu
laden. Siehe Abschnitt 5.2.1, „Befehlsoptionen für mysqld“, and
Abschnitt 13.2.5, „LOAD DATA INFILE
“.
Wenn Sie Replikation benutzen, werden die
MEMORY
-Tabellen auf dem Masterserver auf
Platte geschrieben, wenn dieser heruntergefahren und neu
gestartet wird. Ein Slave merkt allerdings nicht, dass die
Tabellen inzwischen leer sind, und gibt ihren alten Inhalt
zurück, wenn Sie Daten von ihm abfragen. Wird eine
MEMORY
-Tabelle auf einem Master nach einem
Neustart erstmals wieder genutzt, so wird automatisch eine
DELETE
-Anweisung in sein Binärlog
geschrieben, um den Slave wieder mit ihm zu synchronisieren.
Doch Vorsicht: Auch bei dieser Strategie hat der Slave in dem
Zeitraum zwischen dem Neustart des Masters und seinem ersten
Zugriff auf die Tabelle veraltete Daten im Speicher. Wenn Sie
jedoch die MEMORY
-Tabelle gleich beim
Hochfahren des Masters mithilfe der Option
--init-file
wieder mit Inhalt füllen, ist
gewährleistet, dass dieser Zeitraum auf Null schrumpft.
Der für eine Zeile in einer MEMORY
-Tabelle
benötigte Speicher lässt sich mit folgendem Ausdruck
berechnen:
SUM_OVER_ALL_BTREE_KEYS(max_length_of_key
+ sizeof(char*) × 4) + SUM_OVER_ALL_HASH_KEYS(sizeof(char*) × 2) + ALIGN(length_of_row
+1, sizeof(char*))
ALIGN()
ist ein Rundungsfaktor, der
gewährleisten soll, dass die Zeilenlänge ein Vielfaches der
char
-Pointergröße ist.
sizeof(char*)
ist auf 32-Bit-Rechnern
gleich 4 und auf 64-Bit-Rechnern gleich 8.
Ein spezielles Forum zur Speicher-Engine
MEMORY
finden Sie unter
http://forums.mysql.com/list.php?92.
Sleepycat Software hat für MySQL die transaktionssichere
Speicher-Engine Berkeley DB, kurz BDB
,
bereitgestellt. BDB
-Tabellen haben bessere
Chancen, einen Absturz zu überstehen, und können darüber hinaus
COMMIT
- und
ROLLBACK
-Operationen auf Transaktionen
durchführen.
BDB
-Support ist in MySQL Quelldistributionen
enthalten und in MySQL-Max-Binärdistributionen aktiviert. Die
MySQL-Quelldistribution wird mit einer
BDB
-Distribution ausgeliefert, die durch einen
Patch auf MySQL zugeschnitten ist. Für MySQL kann keine
nicht-gepatchte Version von BDB
verwendet
werden.
MySQL AB arbeitet eng mit Sleepycat zusammen, um eine hochwertige MySQL/BDB-Schnittstelle zu gewährleisten. (Obgleich Berkeley DB selbst gründlich getestet und sehr zuverlässig ist, hat die MySQL-Schnittstelle immer noch Gamma-Qualität. Wir arbeiten weiter an ihrer Verbesserung und Optimierung.)
Wenn Probleme mit BDB
-Tabellen auftreten, sind
wir bestrebt, unseren Benutzern beim Isolieren des Problems zu
helfen und reproduzierbare Testfälle zu erstellen. Alle
derartigen Testfälle werden an Sleepycat weitergeleitet, wo man
uns wiederum hilft, die Probleme zu finden und zu beheben. Da
dieser Vorgang in zwei Phasen abläuft, kann die Behebung von
Problemen mit BDB
-Tabellen etwas länger dauern
als bei anderen Speicher-Engines. Wir denken jedoch nicht, dass es
mit diesem Vorgehen besondere Schwierigkeiten gibt, da der
Berkeley DB-Code selbst noch in vielen anderen Anwendungen als
MySQL läuft.
Allgemeine Informationen über Berkeley DB finden Sie auf der Sleepycat-Website http://www.sleepycat.com/.
Nach unserem derzeitigen Kenntnisstand funktioniert
BDB
mit folgenden Betriebssystemen:
Linux 2.x Intel
Sun Solaris (SPARC und x86)
FreeBSD 4.x/5.x (x86, sparc64)
IBM AIX 4.3.x
SCO OpenServer
SCO UnixWare 7.1.x
Windows NT/2000/XP
Die Speicher-Engine BDB
funktioniert
nicht auf folgenden Betriebssystemen:
Linux 2.x Alpha
Linux 2.x AMD64
Linux 2.x IA-64
Linux 2.x s390
Mac OS X
Hinweis: Diese Listen sind nicht vollständig. Sie werden bei Eintreffen neuer Informationen aktualisiert.
Wenn Sie MySQL aus der Quelle mit Unterstützung für
BDB
-Tabellen erstellen, aber beim Starten mit
mysqld folgender Fehler auftritt, so bedeutet
dies, dass Ihre Rechnerarchitektur die
BDB
-Speicher-Engine nicht unterstützt:
bdb: architecture lacks fast mutexes: applications cannot be threaded Can't init databases
In diesem Fall müssen Sie MySQL ohne
BDB
-Unterstützung bauen oder den Server mit
der Option --skip-bdb
starten.
Wenn Sie eine Binärversion von MySQL heruntergeladen haben, die
Unterstützung für Berkeley DB bietet, befolgen Sie einfach die
üblichen Installationsanweisungen für Binärdistributionen.
(MySQL-Max-Distributionen umfassen
BDB
-Support.)
Erstellen Sie MySQL aus einer Quelldistribution, so können Sie
BDB
-Unterstützung aktivieren, indem Sie beim
Aufruf von configure zusätzlich zu den
anderen Optionen, die Sie normalerweise verwenden, die Option
--with-berkeley-db
einschalten. Laden Sie eine
MySQL-Distribution der Version 5.1 herunter, gehen
Sie in das oberste Verzeichnis und führen Sie folgenden Befehl
aus:
shell> ./configure --with-berkeley-db [other-options
]
Weitere Informationen, Abschnitt 5.3, „mysqld-max, ein erweiterter mysqld-Server“, siehe Abschnitt 2.7, „Installation von MySQL auf anderen Unix-ähnlichen Systemen“ und Abschnitt 2.8, „Installation der Quelldistribution“.
Mit den folgenden mysqld-Optionen lässt sich
das Verhalten der Speicher-Engine BDB
ändern. Weitere Informationen siehe
Abschnitt 5.2.1, „Befehlsoptionen für mysqld“.
--bdb-data-direct
Schaltet für BDB
-Datenbankdateien den
Systempuffer aus, um doppeltes Cachen zu verhindern. Diese
Option wurde in MySQL 5.1.4 hinzugefügt.
--bdb-home=
path
Das Basisverzeichnis für BDB
-Tabellen.
Es sollte dasselbe Verzeichnis sein, das auch für die
--datadir
-Option verwendet wird.
--bdb-lock-detect=
method
Die BDB
-Methode zur Erkennung von
Sperren. Der Wert der Option ist DEFAULT
,
OLDEST
, RANDOM
,
YOUNGEST
, MAXLOCKS
,
MINLOCKS
, MAXWRITE
oder MINWRITE
.
--bdb-log-direct
Schaltet für BDB
-Datenbankdateien den
Systempuffer aus, um doppeltes Cachen zu verhindern. Diese
Option wurde in MySQL 5.1.4 hinzugefügt.
--bdb-logdir=
file_name
Das Verzeichnis für BDB
-Logdateien.
--bdb-no-recover
Berkeley DB nicht im Wiederherstellungsmodus starten.
--bdb-no-sync
BDB
-Logs nicht synchronisieren. Diese
Option ist veraltet; bitte verwenden Sie stattdessen
--skip-sync-bdb-logs
(siehe Beschreibung
von --sync-bdb-logs
).
--bdb-shared-data
Berkeley DB im Multi-Prozess-Modus starten. (Nicht beim
Initialisieren von Berkeley DB DB_PRIVATE
benutzen.)
--bdb-tmpdir=
path
Name des temporären Dateiverzeichnisses von
BDB
.
--skip-bdb
BDB
-Speicher-Engine nicht benutzen.
--sync-bdb-logs
BDB
-Logs synchronisieren. Diese Option
ist standardmäßig aktiviert und kann mit
--skip-sync-bdb-logs
deaktiviert werden.
Mit --skip-bdb
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. Versuchen Sie
dennoch, eine BDB
-Tabelle anzulegen, so
verwendet MySQL stattdessen die Standard-Speicher-Engine.
Normalerweise sollten Sie mysqld ohne die
Option --bdb-no-recover
starten, wenn Sie
BDB
-Tabellen benutzen möchten. Das kann
jedoch Probleme verursachen, wenn Sie mysqld
starten und die BDB
-Logdateien beschädigt
sind. Siehe Abschnitt 2.9.2.3, „Probleme mit dem Start des MySQL Servers“.
Mit der Variablen bdb_max_lock
können Sie
angeben, wie viele Sperren auf einer
BDB
-Tabelle höchstens aktiv sein dürfen.
Der Standardwert beträgt 10.000. Sie können ihn heraufsetzen,
wenn Fehler wie der folgende bei langen Transaktionen auftreten,
oder wenn mysqld viele Zeilen betrachten
muss, um eine Anfrage auszuführen:
bdb: Lock table is out of available locks Got error 12 from ...
Außerdem sollten Sie die Variablen
binlog_cache_size
und
max_binlog_cache_size
ändern, wenn Sie
große, aus mehreren Anweisungen bestehende Transaktionen
ausführen. Siehe Abschnitt 5.12.3, „Die binäre Update-Logdatei“.
Jede BDB
-Tabelle wird in zwei Dateien auf der
Festplatte gespeichert. Die Namen dieser Dateien setzen sich aus
dem Namen der Tabelle und einer Dateityperweiterung zusammen.
Eine .frm
-Datei speichert das Format und
eine .db
-Datei den Inhalt und die Indizes
der Tabelle.
Um explizit deutlich zu machen, dass Sie eine
BDB
-Tabelle benötigen, verwenden Sie die
Tabellenoption ENGINE
:
CREATE TABLE t (i INT) ENGINE = BDB;
Der ältere Begriff TYPE
wird aus Gründen
der Abwärtskompatibilität noch als Synonym für
ENGINE
akzeptiert, doch
ENGINE
ist der aktuelle Begriff, während
TYPE
mittlerweile veraltet ist.
BerkeleyDB
ist ein Synonym für
BDB
in der Tabellenoption
ENGINE
.
Die Speicher-Engine BDB
ermöglicht
transaktionssichere Tabellen. Wie diese benutzt werden, hängt
vom Autocommit-Modus ab:
Arbeiten Sie mit eingeschaltetem Autocommit (der Standard),
werden Änderungen an BDB
-Tabellen sofort
festgeschrieben (commit) und können nicht zurückgerollt
werden.
Arbeiten Sie mit ausgeschaltetem Autocommit, werden die
Änderungen erst permanent, nachdem Sie eine
COMMIT
-Anweisung ausgeführt haben.
Stattdessen können Sie jedoch auch ein
ROLLBACK
ausführen, um die Änderungen
zu widerrufen.
Eine Transaktion wird mit START
TRANSACTION
oder BEGIN
gestartet, um den Autocommit-Modus implizit auszusetzen,
oder mit SET AUTOCOMMIT=0
, um den
Autocommit-Modus explizit auszuschalten.
Weitere Informationen über Transaktionen finden Sie unter
Abschnitt 13.4.1, „BEGIN/COMMIT/ROLLBACK
“.
Die BDB
-Speicher-Engine hat folgende
Merkmale:
BDB
-Tabellen können bis zu 31 Indizes
pro Tabelle, 16 Spalten pro Index und 1024 Bytes pro
Schlüssel haben.
MySQL erfordert einen Primärschlüssel in jeder
BDB
-Tabelle, um auf jede Zeile eindeutig
verweisen zu können. Wenn Sie nicht explizit
einenPRIMARY KEY
deklarieren, erzeugt und
wartet MySQL einen verborgenen Primärschlüssel. Dieser hat
eine Länge von 5 Bytes und wird bei jedem Einfügeversuch
um eins inkrementiert. Der Schlüssel erscheint nicht in der
Ausgabe von SHOW CREATE TABLE
oder
DESCRIBE
.
Der Primärschlüssel ist schneller als jeder andere Index, da er zusammen mit den Zeilendaten gespeichert wird. Da die anderen Indizes als Schlüsseldaten plus Primärschlüssel gespeichert werden, ist es wichtig, den Primärschlüssel möglichst kurz zu halten, um Plattenplatz zu sparen und eine höhere Geschwindigkeit zu erzielen.
Dieses Verhalten ist ähnlich wie das von
InnoDB
, wo kürzere Primärschlüssel
nicht nur im Primärindex, sondern auch in den
Sekundärindizes Platz sparen.
Wenn alle Spalten, auf die Sie in einer
BDB
-Tabelle zugreifen, zu demselben Index
oder zum Primärschlüssel gehören, kann MySQL die Anfrage
ausführen, ohne auf die eigentliche Zeile zugreifen zu
müssen. In einer MyISAM
-Tabelle ist dies
nur möglich, wenn die Spalten zu demselben Index gehören.
Sequenzielles Scannen ist bei
BDB
-Tabellen langsamer als bei
MyISAM
-Tabellen, da die Daten in
BDB
-Tabellen in B-Bäumen und nicht in
einer separaten Datendatei gespeichert werden.
Schlüsselwerte werden nicht Präfix- oder
Suffix-komprimiert wie Schlüsselwerte in
MyISAM
-Tabellen. Mit anderen Worten: Die
Schlüsselinformationen benötigen in
BDB
-Tabellen etwas mehr Platz als in
MyISAM
-Tabellen.
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.
SELECT COUNT(*) FROM
ist bei
tbl_name
BDB
-Tabellen langsam, da in der Tabelle
kein Zeilenzähler gepflegt wird.
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
-Anweisungen ausführen, sollte
diese Zahl ausreichend genau für den MySQL-Optimierer sein.
Da MySQL die Zahl nur beim Schließen speichert, kann sie
falsch sein, wenn MySQL unerwartet beendet wird. Das sollte
kein schwerer Fehler sein, selbst wenn die Zahl nicht zu
100% korrekt ist. Man kann die Anzahl von Zeilen
aktualisieren, indem man ANALYZE TABLE
oder OPTIMIZE TABLE
ausführt. Siehe
Abschnitt 13.5.2.1, „ANALYZE TABLE
“ und
Abschnitt 13.5.2.5, „OPTIMIZE TABLE
“
Internes Sperren in BDB
-Tabellen wird auf
Seitenebene durchgeführt (page locking).
LOCK TABLES
funktioniert bei
BDB
-Tabellen wie bei anderen Tabellen.
Wenn Sie LOCK TABLES
nicht benutzen,
errichtet MySQL eine interne Sperre für
Mehrfach-Schreibvorgänge auf der Tabelle (eine Sperre, die
andere Schreibvorgänge nicht blockiert), um
sicherzustellen, dass die Tabelle korrekt gesperrt ist, wenn
ein anderer Thread eine Tabellensperre ausführt.
Um Transaktionen zurückrollen zu können, unterhält die
BDB
-Speicher-Engine Logdateien. Um
maximale Performance zu erzielen, sollten Sie diese auf
andere Festplatten platzieren als Ihre Datenbanken, indem
Sie die Option --bdb-logdir
verwenden.
MySQL macht jedes Mal, wenn eine neue
BDB
-Logdatei gestartet wird, einen
Checkpoint und entfernt alle
BDB
-Logdateien, die nicht für aktuelle
Transaktionen benötigt werden. Sie können auch jederzeit
FLUSH LOGS
laufen lassen, um einen
Checkpoint für die Berkeley DB-Tabellen anzulegen.
Für die Wiederherstellung nach Abstürzen sollten Sie Datensicherungen der Tabellen plus das Binärlog von MySQL benutzen. Siehe Abschnitt 5.10.1, „Datenbank-Datensicherungen“.
Achtung: Wenn Sie alte
Logdateien löschen, die noch in Gebrauch sind, ist
BDB
nicht in der Lage,
Wiederherstellungen durchzuführen, und Sie könnten Daten
verlieren, wenn etwas schief geht.
Die Anwendung 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 Deadlock auftritt.
Wenn die Platte bei einer BDB
-Tabelle
voll wird, wird ein Fehler gemeldet (wahrscheinlich Fehler
28) und die Transaktion sollte zurückgerollt werden. Im
Gegensatz dazu wartet bei MyISAM
-Tabellen
der Server darauf, dass genügend Plattenplatz frei ist, ehe
er fortfährt.
Im Folgenden werden Einschränkungen aufgeführt, die Sie bei
der Verwendung von BDB
-Tabellen beachten
müssen:
Jede BDB
-Tabelle speichert in ihrer
.db
-Datei den Pfad, mit dem sie
angelegt wurde. Dies wird getan, um die Erkennung von
Sperren in Mehrbenutzerumgebungen zu ermöglichen, in denen
Symlinks unterstützt werden. Infolgedessen ist es nicht
möglich, BDB
-Tabellendateien von einem
Datenbankverzeichnis in ein anderes zu verlagern.
Wenn Sie BDB
-Tabellen sichern, müssen
Sie entweder mysqldump verwenden oder
eine Sicherung anlegen, die Dateien für jede
BDB
-Tabelle (also die
.frm
- und die
.db
-Dateien) sowie die
BDB
-Logdateien speichert. Die
Speicher-Engine BDB
speichert
unvollendete Transaktionen in ihren Logdateien und
erfordert, dass diese beim Starten von
mysqld präsent sind. Die
BDB
-Logs sind die Dateien im Data
Directory, deren Namen die Form
log.
haben (zehn Ziffern).
NNNNNNNNNN
Wenn eine Spalte, die NULL
-Werte
zulässt, einen eindeutigen Index hat, darf nur ein einziger
NULL
-Wert vorhanden sein. Im Gegensatz
dazu erlauben andere Speicher-Engines auch mehrere
NULL
-Werte in Unique-Indizes.
Wenn Sie mysqld nach einem Upgrade
starten und folgenden Fehler erhalten, so bedeutet dies,
dass die neue Version von BDB
das alte
Logdateiformat nicht mehr unterstützt:
bdb: Ignoring log file: .../log.NNNNNNNNNN
:
unsupported log version #
In diesem Fall müssen Sie alle BDB
-Logs
aus Ihrem Datenverzeichnis löschen (also die Dateien, deren
Namen die Form
log.
haben) und mysqld neu starten. Außerdem
sollten Sie mit mysqldump --opt Ihre
NNNNNNNNNN
BDB
-Tabellen dumpen, löschen und dann
aus der Dump-Datei rekonstruieren.
Wenn Sie bei ausgeschaltetem Autocommit eine
BDB
-Tabelle löschen, die in einer
anderen Transaktion verwendet wird, wird vielleicht eine
Fehlermeldung wie die folgende in Ihr MySQL-Fehlerlog
geschrieben:
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 zwar nicht fatal, lässt sich aber auch nicht ganz
einfach beheben. So lange dieses Problem noch nicht behoben
ist, raten wir Ihnen, BDB
-Tabellen nur
bei eingeschaltetem Autocommit zu löschen.
Die Speicher-Engine EXAMPLE
ist eine
Sockel-Engine, die eigentlich gar nichts tut, sondern einzig als
Beispiel im MySQL-Quellcode dienen soll, um zu veranschaulichen,
wie man neue Speicher-Engines erstellt. Sie ist vor allem für
Entwickler von Interesse.
Die Speicher-Engine EXAMPLE
ist in den
MySQL-Max-Binärdistributionen enthalten. Wenn Sie MySQL von der
Quelldistribution bauen, können Sie diese Speicher-Engine
aktivieren, indem Sie configure mit der Option
--with-example-storage-engine
aufrufen.
Die Quelle für die EXAMPLE
-Engine finden Sie
im Verzeichnis storage/example
der
MySQL-Quelldistribution.
Wenn Sie eine EXAMPLE
-Tabelle anlegen, erstellt
der Server eine Tabellen-Formatdatei im Datenbankverzeichnis. Die
Datei beginnt mit dem Tabellennamen und hat die Erweiterung
.frm
. Andere Dateien werden nicht erzeugt und
Daten können in der Tabelle auch nicht gespeichert werden.
Anfragen geben eine leere Ergebnismenge zurück.
mysql>CREATE TABLE test (i INT) ENGINE = EXAMPLE;
Query OK, 0 rows affected (0.78 sec) mysql>INSERT INTO test VALUES(1),(2),(3);
ERROR 1031 (HY000): Table Speicher-Engine for 'test' doesn't have this option mysql>SELECT * FROM test;
Empty set (0.31 sec)
Die Speicher-Engine EXAMPLE
unterstützt keine
Indizierung.
Die Speicher-Engine FEDERATED
greift auf Daten
in entfernten Datenbanktabellen (auf anderen Hosts) zu, nicht in
lokalen Tabellen.
Die Speicher-Engine FEDERATED
ist in
MySQL-Max-Binärdistributionen enthalten. Wenn Sie MySQL von der
Quelldistribution bauen, können Sie diese Speicher-Engine
aktivieren, indem Sie configure mit der Option
--with-federated-storage-engine
aufrufen.
Die Quelle für die FEDERATED
-Engine finden Sie
im Verzeichnis sql
einer
MySQL-Quelldistribution.
Ein spezielles Forum zur Speicher-Engine
FEDERATED
finden Sie unter
http://forums.mysql.com/list.php?105.
Wenn Sie eine FEDERATED
-Tabelle anlegen,
erzeugt der Server eine Tabellen-Formatdatei im
Datenbankverzeichnis. Die Datei beginnt mit dem Tabellennamen
und hat die Erweiterung .frm
. Andere
Dateien werden nicht angelegt, da die eigentlichen Daten in
einer Remote-Tabelle vorliegen. Das steht im Gegensatz zu den
Speicher-Engines für lokale Tabellen.
Für lokale Datenbanktabellen liegen auch die Datendateien lokal
vor. Wenn Sie beispielsweise eine
MyISAM
-Tabelle namens
users
anlegen, erzeugt der
MyISAM
-Handler eine Datendatei namens
users.MYD
. Ein Handler für lokale Tabellen
liest, ergänzt, löscht und aktualisiert Daten in lokalen
Datendateien und die Zeilen werden in einem für den Handler
spezifischen Format gespeichert. Um Datenzeilen zu lesen, muss
der Handler die Daten in Spalten parsen, und um Zeilen zu
schreiben, müssen die Spaltenwerte in das vom Handler benutzte
Zeilenformat umgewandelt und in die lokale Datendatei
geschrieben werden.
Doch bei der MySQL-Speicher-Engine FEDERATED
existieren lokal keine Datendateien für eine Tabelle (es gibt
beispielsweise keine .MYD
-Datei).
Stattdessen speichert eine entfernte Datenbank die Daten, die
normalerweise in der Tabelle vorliegen würden. Der lokale
Server verbindet sich mit einem entfernten Server und liest,
löscht, aktualisiert und ergänzt die Daten in der entfernten
Tabelle über eine MySQL-API. Abgefragt werden die Daten mit
einer SELECT * FROM
-SQL-Anweisung. Um
das Ergebnis zu lesen, werden die Zeilen eine nach der anderen
mit der C-API-Funktion tbl_name
mysql_fetch_row()
abgeholt. Danach werden die Spalten der
SELECT
-Ergebnismenge in das vom
FEDERATED
-Handler erwartete Format
umgewandelt.
Der Informationsfluss ist wie folgt:
Lokaler SQL-Aufruf
MySQL-Handler-API (Daten im Format des Handlers)
MySQL-Client-API (Daten werden in SQL-Aufrufe konvertiert)
Remote-Datenbank -> MySQL-Client-API
Ergebnismengen (sofern vorhanden) werden in Handler-Format konvertiert
Handler-API -> Ergebniszeilen oder Zahl der betroffenen Zeilen werden lokal angegeben
Das Verfahren zur Benutzung der
FEDERATED
-Tabellen ist sehr einfach.
Normalerweise betreiben Sie zwei Server, entweder auf demselben
oder auf verschiedenen Hosts. (Es ist möglich, allerdings nicht
sehr sinnvoll, dass eine FEDERATED
-Tabelle
eine andere Tabelle verwendet, die von demselben Server
verwaltet wird.)
Zuerst muss auf dem Remote-Server eine Tabelle liegen, auf die
Sie mit einer FEDERATED
-Tabelle zugreifen
möchten. Angenommen, die entfernte Tabelle liegt in der
Datenbank federated
und ist folgendermaßen
definiert:
CREATE TABLE test_table ( id INT(20) NOT NULL AUTO_INCREMENT, name VARCHAR(32) NOT NULL DEFAULT '', other INT(20) NOT NULL DEFAULT '0', PRIMARY KEY (id), INDEX name (name), INDEX other_key (other) ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
Im Beispiel wird eine MyISAM
-Tabelle
verwendet, aber es könnte auch eine andere Speicher-Engine
benutzt werden.
Nun erstellen Sie eine FEDERATED
-Tabelle auf
dem lokalen Server, um auf die entfernte Tabelle zuzugreifen:
CREATE TABLE federated_table ( id INT(20) NOT NULL AUTO_INCREMENT, name VARCHAR(32) NOT NULL DEFAULT '', other INT(20) NOT NULL DEFAULT '0', PRIMARY KEY (id), INDEX name (name), INDEX other_key (other) ) ENGINE=FEDERATED DEFAULT CHARSET=latin1 CONNECTION='mysql://root@remote_host:9306/federated/test_table';
(Hinweis:
CONNECTION
ersetzt
COMMENT
, was in früheren MySQL-Versionen
verwendet wurde.)
Die Struktur dieser Tabelle muss der Struktur der entfernten
Tabelle genau entsprechen, nur die Tabellenoption
ENGINE
ist FEDERATED
und
die Tabellenoption CONNECTION
ist ein
Verbindungsstring, welcher der
FEDERATED
-Engine sagt, wie sie sich mit dem
entfernten Server verbinden kann.
Die FEDERATED
-Engine erzeugt in der
federated
-Datenbank nur die
test_table.frm
-Datei.
Die Remote-Host-Daten geben an, mit welchem entfernten Server
sich Ihr lokaler Server verbindet, und die Datenbank- und
Tabelleninformationen geben an, welche entfernte Tabelle als
Datenquelle verwendet werden soll. Da im vorliegenden Beispiel
der entfernte Server als remote_host
auf Port
9306 definiert ist, muss ein MySQL-Server auf dem Remote-Host
laufen und auf Port 9306 lauschen.
Die allgemeine Form eines Verbindungsstrings in der Option
CONNECTION
ist:
scheme
://user_name
[:password
]@host_name
[:port_num
]/db_name
/tbl_name
Vorläufig wird nur mysql
als Wert für
scheme
akzeptiert. Das Passwort und
die Port-Nummer sind optional.
Im Folgenden sehen Sie einige Beispiele für Verbindungsstrings:
CONNECTION='mysql://username:password@hostname:port/database/tablename' CONNECTION='mysql://username@hostname/database/tablename' CONNECTION='mysql://username:password@hostname/database/tablename'
CONNECTION
ist für die Angabe des
Verbindungsstrings nicht optimal geeignet und wird
wahrscheinlich irgendwann ersetzt. Für Anwendungen mit
FEDERATED
-Tabellen müssen Sie sich daher
merken, dass diese Anwendungen modifiziert werden müssen, wenn
sich das Format für die Verbindungsinformationen eines Tages
ändert.
Da jedes Passwort, das Sie im Verbindungsstring angeben, als
einfacher Text gespeichert wird, ist es für jeden Benutzer
ersichtlich, der SHOW CREATE TABLE
oder
SHOW TABLE STATUS
für die
FEDERATED
-Tabelle ausführen oder die
TABLES
-Tabelle in der
INFORMATION_SCHEMA
-Datenbank abfragen darf.
Die folgenden Features werden von der Speicher-Engine
FEDERATED
unterstützt bzw. nicht
unterstützt:
In der vorliegenden Version muss der entfernte Server ein
MySQL-Server sein. In Zukunft wird
FEDERATED
möglicherweise auch andere
Datenbank-Engines unterstützen.
Die entfernte Tabelle, die von einer
FEDERATED
-Tabelle benutzt wird,
muss vorhanden sein, bevor Sie mit
FEDERATED
versuchen, auf sie zuzugreifen.
Es ist möglich, mit einer
FEDERATED
-Tabelle auf eine andere zu
verweisen, aber bitte achten Sie darauf, keine
Endlosschleife zu erzeugen.
FEDERATED
unterstützt keine
Transaktionen.
Die FEDERATED
-Engine kann nicht wissen,
ob die entfernte Tabelle sich geändert hat. Der Grund
dafür: Diese Tabelle muss wie eine Datendatei
funktionieren, in die niemand anders als die Datenbank
schreiben kann. Die Datenintegrität in der lokalen Tabelle
könnte beschädigt werden, wenn sich in der entfernten
Datenbank etwas ändert.
Die FEDERATED
-Speicher-Engine
unterstützt SELECT
,
INSERT
, UPDATE
,
DELETE
und Indizes. Nicht unterstützt
werden ALTER TABLE
, DROP
TABLE
oder andere Data Definition
Language-Anweisungen. Die aktuelle Implementierung verwendet
keine vorbereiteten Anweisungen (Prepared-Statements).
Die Implementierung verwendet SELECT
,
INSERT
, UPDATE
und
DELETE
, aber nicht
HANDLER
.
FEDERATED
-Tabellen arbeiten nicht mit dem
Anfragen-Cache.
Manche dieser Beschränkungen werden vielleicht in künftigen
Versionen des FEDERATED
-Handlers entfallen.
Die Speicher-Engine ARCHIVE
dient der
Speicherung großer Datenmengen ohne Indizes mit einem sehr
kleinen Speicherbedarf.
Die Speicher-Engine ARCHIVE
ist in den
Binärdistributionen von MySQL enthalten. Wenn Sie MySQL aus der
Quelldistribution bauen, aktivieren Sie diese Speicher-Engine,
indem Sie configure mit der Option
--with-archive-storage-engine
aufrufen.
Die Quelle für die ARCHIVE
-Engine finden Sie
im Verzeichnis storage/archive
der
MySQL-Quelldistribution.
Ob die ARCHIVE
-Engine zur Verfügung steht,
prüfen Sie mit folgender Anweisung:
mysql> SHOW VARIABLES LIKE 'have_archive';
Wenn Sie eine ARCHIVE
-Tabelle anlegen, erzeugt
der Server eine Tabellen-Formatdatei im Datenbankverzeichnis. Die
Datei beginnt mit dem Tabellennamen und hat die
Erweiterung.frm
. Die Speicher-Engine legt
noch weitere Dateien an, deren Namen alle mit dem Tabellennamen
anfangen. Die Datendateien haben die Erweiterung
.ARZ
und die Metadatendateien die Erweiterung
.ARM
. Eine .ARN
-Datei
kann bei Optimierungsoperationen erscheinen.
Die ARCHIVE
-Engine unterstützt
INSERT
und SELECT
, aber
nicht DELETE
, REPLACE
oder
UPDATE
. Sie unterstützt ORDER
BY
-Operationen, BLOB
-Spalten und im
Grunde alle Datentypen außer den raumbezogenen (Spatial-Daten)
(siehe Abschnitt 18.4.1, „Raumbezogene Datentypen in MySQL“). Außerdem nutzt
ARCHIVE
Zeilensperren.
Seit MySQL 5.1.6 unterstützt ARCHIVE
das
AUTO_INCREMENT
-Spaltenattribut. Die
AUTO_INCREMENT
-Spalten können einen
eindeutigen oder einen nicht-eindeutigen Index haben. Der Versuch,
einen Index auf einer anderen Spalte anzulegen, führt zu einem
Fehler. Außerdem unterstützt ARCHIVE
die
Tabellenoption AUTO_INCREMENT
in
CREATE TABLE
- und ALTER
TABLE
-Anweisungen. So kann der erste Wert der Folge für
eine neue Tabelle angegeben oder für eine vorhandene Tabelle
zurückgesetzt werden.
Seit MySQL 5.1.6 ignoriert die ARCHIVE
-Engine
BLOB
-Spalten, wenn diese nicht angefordert
werden, und übergeht sie beim Lesen. Früher bedeuteten die
folgenden beiden Anweisungen denselben Aufwand, doch seit der
Version 5.1.6 ist die zweite viel effizienter als die erste:
SELECT a, b, blob_col FROM archive_table; SELECT a, b FROM archive_table;
Speicherung: Zeilen werden beim
Einfügen komprimiert. ARCHIVE
verwendet
verlustfreie zlib
-Datenkompression (siehe
http://www.zlib.net/). Mit OPTIMIZE
TABLE
können Sie die Tabelle analysieren und in ein
kleineres Format packen (einen Grund zur Verwendung von
OPTIMIZE TABLE
finden Sie weiter unten in
diesem Abschnitt). Außerdem unterstützt diese Engine
CHECK TABLE
. Mehrere verschiedene Arten von
Einfügungen sind möglich:
Eine INSERT
-Anweisung schiebt die Zeilen
einfach in einen Kompressionspuffer, der nach Bedarf auf die
Platte zurückgeschrieben wird. Die Einfügung von Daten in
den Puffer ist durch eine Sperre geschützt. Mit
SELECT
wird das Schreiben auf die
Festplatte erzwungen, sofern nicht nur INSERT
DELAYED
-Einfügungen vorgekommen waren (diese werden
nur nach Bedarf auf die Platte geschrieben). Siehe
Abschnitt 13.2.4.2, „INSERT DELAYED
“.
Eine Massen-Einfügeoperation (bulk insert) wird erst nach
ihrem Abschluss sichtbar, wenn nicht gleichzeitig andere
Einfügungen auftreten: In diesem Fall wird sie teilweise
sichtbar. Ein SELECT
hat normalerweise
nicht zur Folge, dass eine Massen-Einfügeoperation auf die
Festplatte geschrieben wird, es sei denn, eine normale
Einfügeoperation tritt auf, während die andere gerade
geladen wird..
Anfragen: Bei Anfragen werden die
Zeilen nach Bedarf dekomprimiert; es gibt keinen Zeilen-Cache.
Eine SELECT
-Operation führt einen kompletten
Tabellen-Scan durch: Wenn ein SELECT
auftritt,
stellt es fest, wie viele Zeilen gerade zur Verfügung stehen und
liest diese Anzahl Zeilen. SELECT
wird als
konsistente Leseoperation durchgeführt. Beachten Sie, dass viele
SELECT
-Anweisungen während einer
Einfügeoperation die Datenkompression schwächt, es sei denn, Sie
verwenden nur Massen- oder verzögerte Einfügungen. Eine bessere
Kompression können Sie mit OPTIMIZE TABLE
oder
REPAIR TABLE
erzielen. Die Anzahl der Zeilen,
die SHOW TABLE STATUS
für
ARCHIVE
-Tabellen meldet, ist immer korrekt.
Siehe Abschnitt 13.5.2.5, „OPTIMIZE TABLE
“,
Abschnitt 13.5.2.6, „REPAIR TABLE
“ und
Abschnitt 13.5.4.21, „SHOW TABLE STATUS
“.
Ein spezielles Forum zur Speicher-Engine
ARCHIVE
finden Sie unter
http://forums.mysql.com/list.php?112.
Die CSV
-Speicher-Engine speichert Daten in
Textdateien im Format von kommagetrennten Werten (Comma Separated
Values, CSV).
Um diese Speicher-Engine zu aktivieren, verwenden Sie
configure mit der Option
--with-csv-storage-engine
, wenn Sie MySQL bauen.
Die Speicher-Engine CSV
ist in MySQL-Max-
Binärdistributionen enthalten. Wenn Sie MySQL von einer
Quelldistribution bauen, können Sie sie aktivieren, indem Sie
configure mit der Option
--with-csv-storage-engine
aufrufen.
Die Quelle für die CSV
-Engine finden Sie im
Verzeichnis storage/csv
einer MySQL-
Quelldistribution.
Wenn Sie eine CSV
-Tabelle anlegen, erstellt der
Server eine Tabellen-Formatdatei im Datenbankverzeichnis. Die
Datei beginnt mit dem Tabellennamen und hat die Erweiterung
.frm
. Außerdem legt die Speicher-Engine eine
Datendatei an, deren Name mit dem Tabellennamen anfängt und die
Erweiterung .CSV
hat. Die Datendatei ist eine
einfache Textdatei. Wenn Sie Daten in der Tabelle speichern,
schreibt die Engine sie im CVS-Format in die Datei.
mysql>CREATE TABLE test(i INT, c CHAR(10)) ENGINE = CSV;
Query OK, 0 rows affected (0.12 sec) mysql>INSERT INTO test VALUES(1,'record one'),(2,'record two');
Query OK, 2 rows affected (0.00 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql>SELECT * FROM test;
+------+------------+ | i | c | +------+------------+ | 1 | record one | | 2 | record two | +------+------------+ 2 rows in set (0.00 sec)
Wenn Sie die mit der obigen Anweisung im Datenbankverzeichnis
erzeugte Datei test.CSV
anschauen, müsste
sie folgenden Inhalt haben:
"1","record one" "2","record two"
Die Speicher-Engine CSV
unterstützt keine
Indizierung.
Die Speicher-Engine BLACKHOLE
ist wie ein
„Schwarzes Loch“, das Daten zwar entgegennimmt, aber
nicht speichert. Anfragen geben immer eine leere Ergebnismenge
zurück:
mysql>CREATE TABLE test(i INT, c CHAR(10)) ENGINE = BLACKHOLE;
Query OK, 0 rows affected (0.03 sec) mysql>INSERT INTO test VALUES(1,'record one'),(2,'record two');
Query OK, 2 rows affected (0.00 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql>SELECT * FROM test;
Empty set (0.00 sec)
Die Speicher-Engine BLACKHOLE
ist in MySQL-Max-
Binärdistributionen enthalten. Wenn Sie MySQL von einer
Quelldistribution bauen, können Sie sie aktivieren, indem Sie
configure mit der Option
--with-blackhole-storage-engine
aufrufen.
Die Quelle für die BLACKHOLE
-Engine finden Sie
im Verzeichnis sql
einer MySQL-
Quelldistribution.
Wenn Sie eine BLACKHOLE
-Tabelle anlegen,
erstellt der Server eine Tabellen-Formatdatei im
Datenbankverzeichnis. Die Datei beginnt mit dem Tabellennamen und
hat die Erweiterung .frm
. Andere Dateien
werden mit der Tabelle nicht verknüpft.
Die BLACKHOLE
-Speicher-Engine unterstützt alle
Arten von Indizes. Das bedeutet, dass Sie Indexdeklarationen in
die Tabellendefinition aufnehmen können.
Ob BLACKHOLE
zur Verfügung steht, prüfen Sie
mit folgender Anweisung:
mysql> SHOW VARIABLES LIKE 'have_blackhole_engine';
Bei Einfügungen in eine BLACKHOLE
-Tabelle
werden keine Daten gespeichert, doch wenn das Binärlog aktiviert
ist, werden die SQL-Anweisungen protokolliert (und auf die
Slaveserver repliziert). Das kann als Wiederholungs- oder
Filtermechanismus ganz nützlich sein. Nehmen wir zum Beispiel an,
Ihre Anwendung benötigt Filterregeln auf der Slave-Seite, aber
eine Übertragung sämtlicher Logdaten auf den Slave würde zu
viel Traffic verursachen. In solchen Fällen kann auf dem
Master-Host ein „Dummy“-Slave-Prozess mit
BLACKHOLE
als Speicher-Engine eingerichtet
werden:
Der Master schreibt in sein Binärlog und der als Slave
fungierende „Dummy“-mysqld-Prozess
wendet die gewünschte Kombination von
replicate-do-*
- und
replicate-ignore-*
-Regeln an und schreibt ein
eigenes gefiltertes Binärlog. (Siehe
Abschnitt 6.9, „Replikationsoptionen in my.cnf“.) Dieses gefilterte Log wird
dann dem Slave zur Verfügung gestellt.
Da der Dummy-Prozess selbst gar keine Daten speichert, entsteht durch den zusätzlichen mysqld-Prozess auf dem Replikations-Master-Host kaum Verarbeitungs-Overhead. Dieser Mechanismus kann mit weiteren Replikations-Slaves wiederholt werden.
Andere mögliche Einsatzgebiete für BLACKHOLE
sind:
Syntaxprüfung für Dump-Dateien.
Sie können den Overhead für Binärlogs messen, indem Sie die
Performance eines BLACKHOLE
s mit und ohne
Binärlog vergleichen.
Da BLACKHOLE
im Grunde eine
„leere“ Speicher-Engine ist, könnte sie
eingesetzt werden, um Leistungsengpässe ausfindig zu machen,
die nicht mit der Speicher-Engine selbst zusammenhängen.
Seit MySQL 5.1.4 kann die BLACKHOLE
-Engine mit
Transaktionen umgehen, und zwar in dem Sinne, dass sie bestätigte
Transaktionen in das Binärlog schreibt und zurückgerollte nicht.
Inhaltsverzeichnis
Handlerton
INSERT
-Unterstützung für Speicher-EnginesUPDATE
-Unterstützung für Speicher-EnginesDELETE
-Unterstützung für Speicher-EnginesCREATE TABLE
-Operationen
erhaltenindex_init()
index_end()
index_read()
index_read_idx()
index_next()
index_prev()
index_first()
index_last()
Mit MySQL 5.1 hat die Firma MySQL AB eine Architektur für eine Pluggable Storage Engine eingeführt. Dadurch ist es jetzt möglich, neue Speicher-Engines zu erstellen und einem laufenden MySQL Server hinzuzufügen, ohne den Server selbst neu kompilieren zu müssen.
Durch diese Architektur wird es leichter, neue Speicher-Engines für MySQL zu entwickeln und einzusetzen.
Dieses Kapitel soll Ihnen als Leitfaden dienen und bei der Entwicklung einer Speicher-Engine für die neue Pluggable Storage Engine-Architektur helfen.
Ein spezielles Forum zu Speicher-Engines finden Sie unter http://forums.mysql.com/list.php?94.
Der MySQL Server ist modular aufgebaut:
Die Speicher-Engines übernehmen die Datenspeicherung und die Indexverwaltung für MySQL. Der MySQL Server kommuniziert mit den Speicher-Engines über eine klar definierte API.
Jede Speicher-Engine ist eine Klasse und jede Instanz dieser
Klasse kommuniziert mit dem MySQL Server über ein spezielles
Handler
-Interface.
Für jeden Thread, der mit einer bestimmten Tabelle arbeiten muss, wird ein Handler angelegt. Zum Beispiel: Wenn drei Verbindungen alle mit derselben Tabelle zu arbeiten beginnen, müssen drei Handler-Instanzen erzeugt werden.
Sobald eine Handler-Instanz erzeugt wurde, erteilt der MySQL Server dem Handler Befehle, damit dieser Datenspeicherungs- und Abrufoperationen ausführt, wie beispielsweise eine Tabelle öffnen, Datensätze ändern und Indizes verwalten.
Selbst erstellte Speicher-Engines können progressiv aufgebaut
werden: So könnte ein Entwickler mit einer nur-lesenden Engine
beginnen und später Unterstützung für
INSERT
-, UPDATE
- und
DELETE
-Operationen hinzufügen, um noch ein
wenig später Indizierung, Transaktionen und andere
fortgeschrittene Operationen zu implementieren.
Der einfachste Weg zur Implementierung einer neuen Speicher-Engine
besteht darin, die EXAMPLE
-Engine zu kopieren
und zu modifizieren. Die Dateien
ha_example.cc
und
ha_example.h
liegen im Verzeichnis
storage/example
des MySQL 5.1-Quellbaums. Wie
Sie an den Quellbaum von MySQL 5.1 gelangen, erfahren Sie unter
Abschnitt 2.8.3, „Installation vom Entwicklungs-Source-Tree“.
Beim Kopieren der Dateien ändern Sie deren Namen von
ha_example.cc
und
ha_example.h
in etwas für Ihre Speicher-Engine
Passenderes ab, wie etwa ha_foo.cc
und
ha_foo.h
.
Nach dem Kopieren und Umbenennen der Dateien müssen Sie
EXAMPLE
und example
jeweils
durch den Namen Ihrer Speicher-Engine ersetzen. Wenn Sie mit
sed
vertraut sind, können diese Schritte
automatisch ausgeführt werden (in diesem Beispiel lautet der Name
der Speicher-Engine „FOO“):
sed s/EXAMPLE/FOO/g ha_example.h | sed s/example/foo/g ha_foo.h sed s/EXAMPLE/FOO/g ha_example.cc | sed s/example/foo/g ha_foo.cc
Der Handlerton
(eine Abkürzung für
„Handler Singleton“) definiert die Speicher-Engine
und enthält Funktionszeiger auf diejenigen Funktionen, die für
die Speicher-Engine als Ganzes gelten, im Gegensatz zu jenen
Funktionen, die auf Tabellenebene arbeiten. Dazu gehören
beispielsweise die Transaktionsfunktionen für Commits und
Rollbacks.
Hier sehen Sie ein Beispiel aus der Speicher-Engine
EXAMPLE
.
handlerton example_hton= { "EXAMPLE", SHOW_OPTION_YES, "Example storage engine", DB_TYPE_EXAMPLE_DB, NULL, /* Initialisierung */ 0, /* Slot */ 0, /* Savepoint-Größe */ NULL, /* close_connection */ NULL, /* Savepoint */ NULL, /* Rollback zum Savepoint */ NULL, /* Savepoint freigeben */ NULL, /* Commit */ NULL, /* Rollback */ NULL, /* Prepare */ NULL, /* Recover */ NULL, /* commit_by_xid */ NULL, /* rollback_by_xid */ NULL, /* create_cursor_read_view */ NULL, /* set_cursor_read_view */ NULL, /* close_cursor_read_view */ example_create_handler, /* Neuen Handler anlegen */ NULL, /* Eine Datenbank löschen */ NULL, /* Panik-Aufruf */ NULL, /* Temporäre Latches freigeben */ NULL, /* Statistik aktualisieren */ NULL, /* Konsistenten Snapshot starten */ NULL, /* Logs auf die Platte schreiben */ NULL, /* Status anzeigen */ NULL, /* Replication Report Sent Binlog */ HTON_CAN_RECREATE };
Es folgt die Definition des Handlerton
aus
handler.h
:
typedef struct { const char *name; SHOW_COMP_OPTION state; const char *comment; enum db_type db_type; bool (*init)(); uint slot; uint savepoint_offset; int (*close_connection)(THD *thd); int (*savepoint_set)(THD *thd, void *sv); int (*savepoint_rollback)(THD *thd, void *sv); int (*savepoint_release)(THD *thd, void *sv); int (*commit)(THD *thd, bool all); int (*rollback)(THD *thd, bool all); int (*prepare)(THD *thd, bool all); int (*recover)(XID *xid_list, uint len); int (*commit_by_xid)(XID *xid); int (*rollback_by_xid)(XID *xid); void *(*create_cursor_read_view)(); void (*set_cursor_read_view)(void *); void (*close_cursor_read_view)(void *); handler *(*create)(TABLE *table); void (*drop_database)(char* path); int (*panic)(enum ha_panic_function flag); int (*release_temporary_latches)(THD *thd); int (*update_statistics)(); int (*start_consistent_snapshot)(THD *thd); bool (*flush_logs)(); bool (*show_status)(THD *thd, stat_print_fn *print, enum ha_stat_type stat); int (*repl_report_sent_binlog)(THD *thd, char *log_file_name, my_off_t end_offset); uint32 flags; } handlerton;
Es gibt insgesamt 30 Handlerton-Elemente, von denen aber nur
wenige obligatorisch sind (insbesondere die ersten vier Elemente
und die create()
-Funktion).
Der Name der Speicher-Engine. Dieser Name wird beim Anlegen
von Tabellen verwendet (CREATE TABLE ... ENGINE =
).
FOO
;
Der Wert, der im Status
-Feld angezeigt
wird, wenn ein Benutzer den Befehl SHOW STORAGE
ENGINES
eingibt.
Der Kommentar zur Speicher-Engine, eine Beschreibung, die
durch den Befehl SHOW STORAGE ENGINES
angezeigt wird.
Ein Integer, der die Speicher-Engine im MySQL Server eindeutig
bezeichnet. Die von den eingebauten Speicher-Engines benutzten
Konstanten werden in der Datei handler.h
definiert. Selbst erstellte Engines sollten
DB_TYPE_CUSTOM
verwenden.
Ein Funktionszeiger auf die Initialisierungsfunktion der Speicher-Engine. Diese Funktion wird nur ein einziges Mal beim Starten des Servers aufgerufen, damit die Speicher-Engine-Klasse vor der Instanziierung der Handler die notwendigen Aufräumarbeiten erledigen kann.
Der Slot. Jede Speicher-Engine hat ihren eigenen
Speicherbereich (in Wirklichkeit ein Zeiger) im
thd
zur Speicherung von Verbindungsdaten
für jede Verbindung. Angesprochen wird er mit
thd->ha_data[
.
Die Slot-Nummer wird von MySQL nach dem Aufruf von
foo
_hton.slot]
initialisiert. Weitere Informationen über
foo
_init()thd
finden Sie unter
Abschnitt 15.16.3, „Implementierung von ROLLBACK“.
Der Savepoint-Offset. Um Daten pro Savepoint speichern zu
können, besitzt die Speicher-Engine einen Speicherbereich in
der angeforderten Größe (0
, wenn kein
Savepoint-Speicher notwendig ist).
Der Savepoint-Offset muss als fester Wert mit der Größe des
benötigten Speichers initialisiert werden, um Daten pro
Savepoint speichern zu können. Nach
wird er
auf einen Offset des Savepoint-Speicherbereichs umgestellt und
muss nicht mehr von der Speicher-Engine verwendet werden.
foo
_init
Mehr zum Thema unter Abschnitt 15.16.5.1, „Den Savepoint-Offset angeben“.
Transaktionssichere Speicher-Engines bereinigen den ihrem Slot zugewiesenen Speicher.
Ein Funktionszeiger auf die Handler-Funktion
savepoint_set()
. Dieser wird genutzt, um
einen Savepoint anzulegen und in dem entsprechend großen
zugewiesenen Arbeitsspeicherbereich abzulegen.
Mehr zum Thema unter
Abschnitt 15.16.5.2, „Implementierung der Funktion savepoint_set
“.
Ein Funktionszeiger auf die Handler-Funktion
rollback_to_savepoint()
. Dieser wird
verwendet, um während einer Transaktion zu einem Savepoint
zurückzukehren. Er wird nur für Speicher-Engines angelegt,
die Savepoints unterstützen.
Mehr zum Thema unter
Abschnitt 15.16.5.3, „Implementierung der Funktion savepoint_rollback()
“.
Ein Funktionszeiger auf die Handler-Funktion
release_savepoint()
. Er wird verwendet,
um die Ressourcen eines Savepoints während einer Transaktion
freizugeben. Der Zeiger wird optional für Speicher-Engines,
die Savepoints unterstützen, angelegt.
Mehr zum Thema unter
Abschnitt 15.16.5.4, „Implementierung der Funktion savepoint_release()
“.
Ein Funktionszeiger auf die Handler-Funktion
commit()
. Wird verwendet, um eine
Transaktion festzuschreiben. Er wird nur für Speicher-Engines
angelegt, die Savepoints unterstützen.
Mehr zum Thema unter Abschnitt 15.16.4, „Implementierung von COMMIT“.
Ein Funktionszeiger auf die Handler-Funktion
rollback()
. Wird verwendet, um eine
Transaktion zurückzurollen. Er wird nur für Speicher-Engines
angelegt, die Savepoints unterstützen.
Mehr zum Thema unter Abschnitt 15.16.3, „Implementierung von ROLLBACK“.
Erforderlich für transaktionssichere XA-Speicher-Engines. Bereitet eine Transaktion auf das Commit vor.
Erforderlich für transaktionssichere XA-Speicher-Engines. Gibt eine Liste von Transaktionen zurück, die sich im vorbereiteten Zustand befinden.
Erforderlich für transaktionssichere XA-Speicher-Engines. Schreibt die Transaktion XID fest.
Erforderlich für transaktionssichere XA-Speicher-Engines. Rollt die Transaktion XID zurück.
Wird beim Anlegen eines Cursors aufgerufen, damit die Speicher-Engine eine konsistente Read-View erzeugen kann.
Wird aufgerufen, um auf eine bestimmte konsistente Read-View umzustellen.
Wird aufgerufen, um eine bestimmte Read-View zu schließen.
OBLIGATORISCH . Erzeugt eine Handler-Instanz und gibt sie zurück.
Mehr zum Thema unter Abschnitt 15.5, „Die Erzeugung von Handlern“.
Wird verwendet, wenn die Speicher-Engine beim Löschen eines Schemas besondere Maßnahmen ergreifen muss (wie zum Beispiel eine Speicher-Engine, die Tablespaces verwendet).
Bereinigungsfunktion, die nach dem Herunterfahren oder Abstürzen eines Servers aufgerufen wird.
InnoDB
-spezifische Funktion.
InnoDB
-spezifische Funktion, die beim Start
von SHOW ENGINE InnoDB STATUS
aufgerufen
wird.
Funktion, die aufgerufen wird, um einen konsistenten Read zu beginnen.
Wird aufgerufen, um anzuzeigen, dass die Logs auf einem zuverlässigen Speichermedium gespeichert werden sollen.
Liefert für Menschen lesbare Statusinformationen über die
Speicher-Engine für SHOW ENGINE
.
foo
STATUS
InnoDB
-spezifische Funktion, die zur
Replikation verwendet wird.
Handlerton-Flags, welche die Fähigkeiten der Speicher-Engine
anzeigen. Die möglichen Werte sind in
sql/handler.h
definiert und werden hier
noch einmal aufgeführt:
#define HTON_NO_FLAGS 0 #define HTON_CLOSE_CURSORS_AT_COMMIT (1 << 0) #define HTON_ALTER_NOT_SUPPORTED (1 << 1) #define HTON_CAN_RECREATE (1 << 2) #define HTON_FLUSH_AFTER_RENAME (1 << 3) #define HTON_NOT_USER_SELECTABLE (1 << 4)
HTON_ALTER_NOT_SUPPORTED
zeigt an, dass die
Speicher-Engine keine ALTER
TABLE
-Anweisungen annehmen kann. Die
FEDERATED
-Speicher-Engine ist ein Beispiel
dafür.
HTON_FLUSH_AFTER_RENAME
zeigt an, dass
FLUSH LOGS
nach der Umbenennung einer
Tabelle aufgerufen werden muss.
HTON_NOT_USER_SELECTABLE
bedeutet, dass die
Speicher-Engine nicht angezeigt werden darf, wenn ein Benutzer
SHOW STORAGE ENGINES
aufruft. Wird für
System-Speicher-Engines wie zum Beispiel die Dummy-Engine für
Binärlogs verwendet.
Als Erstes muss die Speicher-Engine den Methodenaufruf zur Erzeugung einer neuen Handler-Instanz unterstützen.
Vor dem Handlerton
muss in der Quelldatei der
Speicher-Engine ein Funktions-Header für die
Instanziierungsfunktion definiert werden. Hier ist ein Beispiel
aus der CSV
-Engine:
static handler* tina_create_handler(TABLE *table);
Wie Sie sehen, nimmt die Funktion einen Zeiger auf die Tabelle entgegen, welche der Handler verwalten soll, und liefert das Handler-Objekt zurück.
Wenn der Funktions-Header definiert ist, wird die Funktion durch
einen Funktionszeiger im
create()
-handlerton
-Element
angesprochen, um anzuzeigen, dass sie für die Erzeugung neuer
Handler-Instanzen zuständig ist.
Das folgende Beispiel zeigt die Instanziierungsfunktion der
Speicher-Engine MyISAM
:
static handler *myisam_create_handler(TABLE *table) { return new ha_myisam(table); }
Dieser Aufruf arbeitet mit dem Konstruktor der Speicher-Engine.
Das folgende Beispiel stammt von der Storage-Engine
FEDERATED
:
ha_federated::ha_federated(TABLE *table_arg) :handler(&federated_hton, table_arg), mysql(0), stored_result(0), scan_flag(0), ref_length(sizeof(MYSQL_ROW_OFFSET)), current_position(0) {}
Und hier ist ein weiteres Beispiel mit der Storage-Engine
EXAMPLE
:
ha_example::ha_example(TABLE *table_arg) :handler(&example_hton, table_arg) {}
Die zusätzlichen Elemente im
FEDERATED
-Beispiel sind
Handler-Initialisierungen. Die erforderliche
Minimalimplementierung ist die
handler()
-Initialisierung aus dem
EXAMPLE
-Beispiel.
Die Speicher-Engines sind notwendig, damit der MySQL Server eine Liste von Erweiterungen bekommt, die von der betreffenden Engine für eine gegebene Tabelle sowie ihre Daten und Indizes benutzt werden können.
Erweiterungen werden in Form eines mit Null endenden String-Arrays
erwartet. Das folgende Array wird von der
CSV
-Engine verwendet:
static const char *ha_tina_exts[] = { ".CSV", NullS };
Dieses Array wird zurückgegeben, wenn die Funktion
bas_ext()
aufgerufen wird:
const char **ha_tina::bas_ext() const { return ha_tina_exts; }
Wenn Sie MySQL über die verwendeten Erweiterungen informieren,
müssen Sie keine DROP TABLE
-Funktionalität
implementieren. Der MySQL Server nimmt Ihnen dies ab, indem er die
Tabelle schließt und alle Dateien mit den von Ihnen angegebenen
Erweiterungen löscht.
Wenn Sie einen Handler erzeugt haben, werden Sie normalerweise als Nächstes eine Tabelle anlegen.
Hierzu muss Ihre Speicher-Engine die virtuelle Funktion
create()
implementieren:
virtual int create(const char *name, TABLE *form, HA_CREATE_INFO *info)=0;
Diese Funktion sollte alle notwendigen Dateien erzeugen, muss jedoch nicht die Tabelle öffnen. Darum wird sich später der MySQL Server kümmern.
Der Parameter *name
ist der Tabellenname und
der Parameter *form
ist eine
TABLE
-Struktur, welche die Tabelle definiert
und den Inhalt der zuvor bereits vom MySQL Server angelegten
-Datei
vergleicht. Die Datei
tablename
.frm
darf
nicht von Speicher-Engines geändert werden.
tablename
.frm
Der Parameter *info
ist eine Struktur, die
Informationen über die CREATE TABLE
-Anweisung
enthält, mit welcher die Tabelle angelegt wurde. Diese in
handler.h
definierte Struktur geben wir hier
für Sie wieder:
typedef struct st_ha_create_information { CHARSET_INFO *table_charset, *default_table_charset; LEX_STRING connect_string; const char *comment,*password; const char *data_file_name, *index_file_name; const char *alias; ulonglong max_rows,min_rows; ulonglong auto_increment_value; ulong table_options; ulong avg_row_length; ulong raid_chunksize; ulong used_fields; SQL_LIST merge_list; enum db_type db_type; enum row_type row_type; uint null_bits; /* NULL-Bits am Anfang des Datensatzes */ uint options; /* OR von HA_CREATE_-Optionen */ uint raid_type,raid_chunks; uint merge_insert_method; uint extra_size; /* Länge des zusätzlichen Datensegments */ bool table_existed; /* 1 in create, falls Tabelle bereits vorhanden */ bool frm_only; /* 1, wenn kein ha_create_table() */ bool varchar; /* 1, wenn die Tabelle eine VARCHAR-Spalte hat */ } HA_CREATE_INFO;
Eine einfache Speicher-Engine kann den Inhalt von
*form
and *info
ignorieren,
denn im Grunde genügt es, die von der Speicher-Engine benutzten
Datendateien anzulegen und gegebenenfalls zu initialisieren
(vorausgesetzt, die Speicher-Engine arbeitet mit Dateien).
Das folgende Beispiel zeigt die Implementierung der
Speicher-Engine CSV
:
int ha_tina::create(const char *name, TABLE *table_arg, HA_CREATE_INFO *create_info) { char name_buff[FN_REFLEN]; File create_file; DBUG_ENTER("ha_tina::create"); if ((create_file= my_create(fn_format(name_buff, name, "", ".CSV", MY_REPLACE_EXT|MY_UNPACK_FILENAME),0, O_RDWR | O_TRUNC,MYF(MY_WME))) < 0) DBUG_RETURN(-1); my_close(create_file,MYF(0)); DBUG_RETURN(0); }
Im obigen Beispiel kümmert sich die CSV
-Engine
gar nicht um die *table_arg
- oder
*create_info
-Parameter, sondern legt einfach
die erforderlichen Datendateien an, schließt sie wieder und kehrt
zurück.
Die Funktionen my_create
und
my_close
sind Hilfsfunktionen. Ihre Definition
steht in src/include/my_sys.h
.
Ehe auf der Tabelle irgendwelche Lese- oder Schreiboperationen ausgeführt werden, ruft der MySQL Server die Methode handler::open() auf, um die Datendateien und (sofern vorhanden) die Indexdateien der Tabelle zu öffnen.
int open(const char *name, int mode, int test_if_locked);
Der erste Parameter ist der Name der zu öffnenden Tabelle und der
zweite legt fest, welche Datei geöffnet oder welche Operation
ausgeführt werden soll. Die Werte sind in
handler.h
definiert und werden hier noch
einmal wiedergegeben:
O_RDONLY - Mit nur-lesendem Zugriff öffnen O_RDWR - Mit Lese-/Schreibzugriff öffnen
Die letzte Option legt fest, ob der Handler auf eine Tabellensperre achten soll, bevor er die Tabelle öffnet. Folgende Möglichkeiten stehen zur Verfügung:
#define HA_OPEN_ABORT_IF_LOCKED 0 /* der Default */ #define HA_OPEN_WAIT_IF_LOCKED 1 #define HA_OPEN_IGNORE_IF_LOCKED 2 #define HA_OPEN_TMP_TABLE 4 /* es ist eine temporäre Tabelle */ #define HA_OPEN_DELAY_KEY_WRITE 8 /* nicht den Index aktualisieren */ #define HA_OPEN_ABORT_IF_CRASHED 16 #define HA_OPEN_FOR_REPAIR 32 /* auch öffnen, wenn sie abgestürzt ist */
Die Speicher-Engine muss in der Regel irgendeine Art von
Zugriffskontrolle implementieren, um in einer Multithread-Umgebung
Schäden an der Tabelle zu verhüten. Ein Beispiel für die
Implementierung von Dateisperren finden Sie in den Methoden
get_share()
und
free_share()
von
sql/examples/ha_tina.cc
.
Die simpelsten Speicher-Engines implementieren nur-lesende Tabellenscans. Solche Engines können eingesetzt werden, um SQL-Anfragen auf Logs oder anderen Datendateien zu unterstützen, die außerhalb von MySQL mit Daten gefüllt werden.
Die Implementierung der Methoden in diesem Absatz ist der erste Schritt zu anspruchsvolleren Speicher-Engines.
Im Folgenden sehen Sie, welche Methoden beim Scan einer
neunzeiligen Tabelle der CSV
-Engine aufgerufen
werden:
ha_tina::store_lock ha_tina::external_lock ha_tina::info ha_tina::rnd_init ha_tina::extra - ENUM HA_EXTRA_CACHE Cache record in HA_rrnd() ha_tina::rnd_next ha_tina::rnd_next ha_tina::rnd_next ha_tina::rnd_next ha_tina::rnd_next ha_tina::rnd_next ha_tina::rnd_next ha_tina::rnd_next ha_tina::rnd_next ha_tina::extra - ENUM HA_EXTRA_NO_CACHE End caching of records (def) ha_tina::external_lock ha_tina::extra - ENUM HA_EXTRA_RESET Reset database to after open
Die Funktion
store_lock()
wird vor allen Lese- und Schreibvorgängen aufgerufen.
Bevor die Sperre dem Tabellensperren-Handler hinzugefügt wird,
ruft mysqld die Funktion
store_lock()
mit den erforderlichen Sperren
auf. Die Funktion kann das Ausmaß der Sperrung ändern, also
beispielsweise eine blockierende Schreibsperre in eine
nichtblockierende umwandeln, die Sperre ignorieren (wenn keine
MySQL-Tabellensperren benutzt werden sollen) oder Sperren für
viele Tabellen hinzufügen (wie es bei Verwendung eines
MERGE-Handlers getan wird).
Berkeley DB stuft beispielsweise blockierende Tabellensperren
vom Typ TL_WRITE
zu nichtblockierenden
TL_WRITE_ALLOW_WRITE
-Sperren herab (ein
Hinweis darauf, dass zwar WRITE
-Operationen
stattfinden, aber dennoch andere lesende und schreibende Prozesse
zugelassen sind).
Auch beim Aufheben von Sperren wird
store_lock()
aufgerufen. In diesem Fall
muss in der Regel nichts weiter veranlasst werden.
Wenn store_lock
das Argument
TL_IGNORE
bekommt, bedeutet das, dass MySQL
vom Handler verlangt, dasselbe Ausmaß der Sperrung wie beim
letzten Mal zu speichern.
Die möglichen Sperrentypen sind in
includes/thr_lock.h
definiert und werden
hier noch einmal aufgeführt:
enum thr_lock_type { TL_IGNORE=-1, TL_UNLOCK, /* SPERREN AUFHEBEN */ TL_READ, /* Lesesperre */ TL_READ_WITH_SHARED_LOCKS, TL_READ_HIGH_PRIORITY, /* Hat Priorität vor TL_WRITE. Nebenläufige Einfügeoperationen zulässig*/ TL_READ_NO_INSERT, /* READ, nebenläufige Einfügeoperationen unzulässig */ TL_WRITE_ALLOW_WRITE, /* Schreibsperre, aber andere Threads dürfen lesen/schreiben. */ TL_WRITE_ALLOW_READ, /* Schreibsperre, aber andere Threads dürfen lesen/schreiben. */ TL_WRITE_CONCURRENT_INSERT, /* WRITE-Sperre, die von nebenläufigen Einfügeoperationen benutzt wird. */ TL_WRITE_DELAYED, /* Schreibvorgang, der von INSERT DELAYED verwendet wird. READ-Sperren zulässig */ TL_WRITE_LOW_PRIORITY, /* WRITE-Sperre mit geringerer Priorität als TL_READ */ TL_WRITE, /* Normale WRITE-Sperre */ TL_WRITE_ONLY /* Jede neue Sperranforderung wird mit einem Fehler abgebrochen*/ };
Der tatsächliche Umgang mit Sperren hängt von der Implementierung Ihrer Sperren ab. Sie können alle, einige oder gar keine der geforderten Sperrentypen implementieren und eigene Methoden verwenden, wo es Ihnen passend erscheint. Im Folgenden sehen Sie eine Minimalimplementierung für eine Speicher-Engine, die keine Sperren herabstufen muss:
THR_LOCK_DATA **ha_tina::store_lock(THD *thd, THR_LOCK_DATA **to, enum thr_lock_type lock_type) { if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) lock.type=lock_type; *to++= &lock; return to; }
Eine komplexere Implementierung finden Sie unter
ha_berkeley::store_lock()
und
ha_myisammrg::store_lock()
.
Die Funktion
external_lock()
wird am Anfang einer Anweisung und bei jedem LOCK
TABLES
aufgerufen.
Beispiele für die Verwendung der Funktion
external_lock()
finden Sie in den Dateien
sql/ha_innodb.cc
und
sql/ha_berkeley.cc
, doch die meisten
Speicher-Engines können auch einfach 0
zurückgeben, wie es auch die Speicher-Engine
EXAMPLE
tut:
int ha_example::external_lock(THD *thd, int lock_type) { DBUG_ENTER("ha_example::external_lock"); DBUG_RETURN(0); }
Die Funktion, die vor jedem Tabellenscan aufgerufen wird, ist
rnd_init()
.
Sie wird verwendet, um einen Tabellenscan vorzubereiten, indem
sie Zähler und Zeiger wieder auf den Anfang der Tabelle
zurücksetzt.
Das folgende Beispiel verwendet die Speicher-Engine
CSV
:
int ha_tina::rnd_init(bool scan) { DBUG_ENTER("ha_tina::rnd_init"); current_position= next_position= 0; records= 0; chain_ptr= chain; DBUG_RETURN(0); }
Hat der Parameter scan
den Wert
true
, durchsucht MySQL die Tabelle
sequenziell; hat er den Wert false
, werden
willkürliche Leseoperationen auf Zufallspositionen
durchgeführt.
Vor einem Tabellenscan wird die Funktion
info()
aufgerufen, um zusätzliche Tabelleninformationen für den
Optimierer zu beschaffen.
Diese Informationen werden dem Optimierer nicht über
Rückgabewerte geliefert, sondern durch Zuweisung bestimmter
Eigenschaften der Klasse der Speicher-Engine. Diese
Eigenschaften liest der Optimierer, bevor der Aufruf von
info()
zurückkehrt.
Viele der von info()
gesetzten Werte werden
nicht nur vom Optimierer genutzt, sondern auch von der
SHOW TABLE STATUS
-Anweisung.
In sql/handler.h
werden alle öffentlichen
Eigenschaften vollständig aufgeführt. Einige der
gebräuchlichsten werden hier noch einmal wiedergegeben:
ulonglong data_file_length; /* Länge der Datendatei */ ulonglong max_data_file_length; /* Länge der Datendatei */ ulonglong index_file_length; ulonglong max_index_file_length; ulonglong delete_length; /* Freie Bytes */ ulonglong auto_increment_value; ha_rows records; /* Datensätze in der Tabelle */ ha_rows deleted; /* Gelöschte Datensätze */ ulong raid_chunksize; ulong mean_rec_length; /* Physikalische Länge der Datensätze */ time_t create_time; /* Erstellungszeitpunkt der Tabelle */ time_t check_time; time_t update_time;
Die für einen Tabellenscan wichtigste Eigenschaft ist
records
: Sie gibt an, wie viele Datensätze
die Tabelle hat. Zeigt die Speicher-Engine null oder eine Zeile
in der Tabelle an, verhält sich der Optimierer anders, als wenn
die Tabelle zwei oder mehr Zeilen hat. Daher ist es wichtig, vor
einem Scan von Tabellen, deren Größe nicht genau bekannt ist
(wie zum Beispiel in Fällen, wo die Daten aus einer externen
Quelle kommen), einen Wert größer gleich zwei zurückzugeben.
Vor manchen Operationen wird die Funktion
extra()
aufgerufen, um der Speicher-Engine zusätzliche Hinweise zu
geben, wie sie bestimmte Operationen auszuführen hat.
Die Implementierung der Hinweise im Aufruf von
extra
ist nicht obligatorisch. Die meisten
Speicher-Engines geben hier 0
zurück:
int ha_tina::extra(enum ha_extra_function operation) { DBUG_ENTER("ha_tina::extra"); DBUG_RETURN(0); }
Nach der Tabelleninitialisierung ruft der MySQL Server die
Handler-Funktion
rnd_next()
für jede zu untersuchende Zeile einmal auf, bis seine
Suchbedingung erfüllt oder das Ende der Datei erreicht ist. Im
letzteren Fall gibt er HA_ERR_END_OF_FILE
zurück.
Die Funktion rnd_next()
nimmt einen
Byte-Array-Parameter namens *buf
entgegen.
Dieser *buf
-Parameter muss mit dem Inhalt der
Tabellenzeile im internen Format von MySQL gefüllt sein.
Der Server verwendet drei Datenformate: Zeilen mit fester
Länge, Zeilen mit variabler Länge und variabel lange Zeilen
mit BLOB-Zeigern. In jedem der Formate erscheinen die Spalten in
derselben Reihenfolge wie in der CREATE TABLE-Anweisung. (Die
Tabellendefinition wird in der .frm
-Datei
gespeichert und Optimierer und Handler können beide die
Metadaten der Tabelle aus derselben Quelle holen, nämlich aus
ihrer TABLE
-Struktur.)
Jedes Format beginnt mit einer „NULL-Bitmap“, die für jede nullfähige Spalte ein Bit enthält. Eine Tabelle mit 8 nullfähigen Spalten hat somit eine 1 Byte große Bitmap, während eine Tabelle mit 9 bis 16 nullfähigen Spalten eine 2 Byte große Bitmap besitzt, und so weiter. Eine Ausnahme bilden die Tabellen mit fester Breite: Da sie ein zusätzliches Startbit haben, würde eine solche Tabelle mit 8 nullfähigen Spalten dennoch eine 2 Byte große Bitmap aufweisen.
Hinter der NULL-Bitmap kommen nacheinander die Spalten an die
Reihe. Jede Spalte hat die in Kapitel 11, Datentypen,
angegebene Größe. Im Server sind die Spaltendatentypen in der
Datei sql/field.cc
definiert. In einem
Format mit fester Zeilenbreite werden die Spalten einfach
nacheinander angeordnet. In einem Format mit variabler
Zeilenlänge werden die VARCHAR
-Spalten mit
einer Länge von 1 oder 2 Byte, gefolgt von einem
Zeichen-String, kodiert. In einer variabel langen Zeile mit
BLOB
-Spalten wird jeder BLOB in zwei Teilen
dargestellt: Zuerst kommt ein Integer, der die tatsächliche
Länge des BLOB
darstellt, und dann ein
Zeiger auf den Speicherplatz des BLOB
.
Beispiele für die Konvertierung (oder das
„Packen“) von Zeilen finden Sie ab der Funktion
rnd_next()
in jedem Tabellen-Handler. So
zeigt beispielsweise in ha_tina.cc
der Code
von find_current_row()
, wie die
TABLE
-Struktur (auf welche die Tabelle
verweist) und ein String-Objekt namens Buffer genutzt werden
können, um Zeichendaten aus einer CSV-Datei zu packen. Um eine
Zeile auf die Platte zurückzuspeichern, ist die umgekehrte
Konvertierung erforderlich: Die Zeilen müssen dann aus dem
internen Format wieder zurückkonvertiert werden.
Das folgende Beispiel stammt wieder aus der Speicher-Engine
CSV
:
int ha_tina::rnd_next(byte *buf) { DBUG_ENTER("ha_tina::rnd_next"); statistic_increment(table->in_use->status_var.ha_read_rnd_next_count, &LOCK_status); current_position= next_position; if (!share->mapped_file) DBUG_RETURN(HA_ERR_END_OF_FILE); if (HA_ERR_END_OF_FILE == find_current_row(buf) ) DBUG_RETURN(HA_ERR_END_OF_FILE); records++; DBUG_RETURN(0); }
Die Funktion find_current_row()
übernimmt
die Konvertierung aus dem internen Zeilenformat in ein
CSV-Zeilenformat:
int ha_tina::find_current_row(byte *buf) { byte *mapped_ptr= (byte *)share->mapped_file + current_position; byte *end_ptr; DBUG_ENTER("ha_tina::find_current_row"); /* EOF soll als Newline gelten*/ if ((end_ptr= find_eoln(share->mapped_file, current_position, share->file_stat.st_size)) == 0) DBUG_RETURN(HA_ERR_END_OF_FILE); for (Field **field=table->field ; *field ; field++) { buffer.length(0); mapped_ptr++; // Inkrementiere hinter dem ersten Anführungszeichen for(;mapped_ptr != end_ptr; mapped_ptr++) { // Ist notwendig, um Zeilenvorschübe zu konvertieren! if (*mapped_ptr == '"' && (((mapped_ptr[1] == ',') && (mapped_ptr[2] == '"')) || (mapped_ptr == end_ptr -1 ))) { mapped_ptr += 2; // Gehe hinter das , und das " break; } if (*mapped_ptr == '\\' && mapped_ptr != (end_ptr - 1)) { mapped_ptr++; if (*mapped_ptr == 'r') buffer.append('\r'); else if (*mapped_ptr == 'n' ) buffer.append('\n'); else if ((*mapped_ptr == '\\') || (*mapped_ptr == '"')) buffer.append(*mapped_ptr); else /* Dies kann nur bei einer extern erzeugten Datei passieren */ { buffer.append('\\'); buffer.append(*mapped_ptr); } } else buffer.append(*mapped_ptr); } (*field)->store(buffer.ptr(), buffer.length(), system_charset_info); } next_position= (end_ptr - share->mapped_file)+1; /* Vielleicht \N für null verwenden? */ memset(buf, 0, table->s->null_bytes); /* Nullen werden nicht implementiert! */ DBUG_RETURN(0); }
Wenn der MySQL Server eine Tabelle nicht mehr benötigt, ruft er die Methode close() auf, um Zeiger auf Dateien zu schließen und andere Ressourcen freizugeben.
Speicher-Engines, die Methoden für einen gemeinsamen Zugriff
verwenden, wie sie in CSV
und anderen
Beispiel-Engines vorkommen, müssen sich selbst aus der
share
-Struktur entfernen:
int ha_tina::close(void) { DBUG_ENTER("ha_tina::close"); DBUG_RETURN(free_share(share)); }
Speicher-Engines mit eigenem Share Management-System sollten alle notwendigen Methoden einsetzen, um die Handler-Instanz aus der Freigabe (Share) für die Tabelle zu entfernen, die in ihrem Handler geöffnet ist.
Wenn Ihre Speicher-Engine Lesefähigkeiten bekommen hat, ist als
Nächstes die Unterstützung für
INSERT
-Anweisungen an der Reihe. Beherrscht
Ihre Speicher-Engine INSERT
, so kann sie auch
mit WORM(write once, read many)-Anwendungen wie etwa dem
Protokollieren und Archivieren von Daten zur späteren Analyse
umgehen.
Alle INSERT
-Operationen werden von der Funktion
write_row()
erledigt:
int ha_foo::write_row(byte *buf)
Der Parameter *buf
enthält die einzufügende
Zeile im internen Format von MySQL. Eine simple Speicher-Engine
könnte einfach an das Ende der Datendatei gehen und den Inhalt
des Puffers direkt dort anfügen (das würde auch das Lesen von
Zeilen vereinfachen, da man die Zeile lesen und direkt an den
Puffer-Parameter der Funktion rnd_next()
übergeben könnte).
Der Prozess zum Schreiben einer Zeile ist genau das Gegenteil vom
Leseprozess: Er nimmt die Daten im internen Zeilenformat von MySQL
und schreibt sie in die Datendatei. Das folgende Beispiel stammt
von der Speicher-Engine MyISAM
:
int ha_myisam::write_row(byte * buf) { statistic_increment(table->in_use->status_var.ha_write_count,&LOCK_status); /* Zeitstempel-Spalte, falls vorhanden, auf die aktuelle Zeit setzen */ if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) table->timestamp_field->set_time(); /* Wenn eine auto_increment-Spalte vorhanden ist und wir eine geänderte oder neue Zeile laden, muss der auto_increment-Wert im Datensatz aktualisiert werden. */ if (table->next_number_field && buf == table->record[0]) update_auto_increment(); return mi_write(file,buf); }
Im obigen Beispiel sind drei Dinge bemerkenswert: Die
Tabellenstatistik für Schreiboperationen wird aktualisiert, der
Zeitstempel wird vor dem eigentlichen Schreibvorgang aktualisiert
und die AUTO_INCREMENT
-Werte werden
hochgesetzt.
Der MySQL Server führt UPDATE
-Anweisungen aus,
indem er so lange (Tabelle, Index, Bereich usw.) scannt, bis er
eine Zeile findet, die zu der WHERE
-Klausel der
UPDATE
-Anweisung passt. Dann ruft er die
Funktion
update_row()
auf:
int ha_foo::update_row(const byte *old_data, byte *new_data)
Der Parameter *old_data
enthält die Daten, die
vor dem Update in der Zeile gespeichert waren, während der
Parameter *new_data
den neuen Zeileninhalt
enthält (im internen Zeilenformat von MySQL).
Wie ein Update durchgeführt wird, hängt vom Zeilenformat und der Speicherimplementierung ab. Manche Speicher-Engines ersetzen Daten direkt, während andere Implementierungen die vorhandene Zeile löschen und die neue Zeile am Ende der Datendatei anfügen.
Speicher-Engines ohne Indizierung können den Inhalt des
Parameters *old_data
ignorieren und müssen
sich nur mit dem Pufferinhalt *new_data
abgeben. Engines mit Transaktionsunterstützung müssen unter
Umständen die Puffer vergleichen, um für ein mögliches
späteres Rollback herauszufinden, welche Änderungen vorgenommen
wurden.
Enthält die zu ändernde Tabelle Zeitstempelspalten, muss die
Funktion update_row()
auch diese Zeitstempel
aktualisieren. Das folgende Beispiel stammt von der
Speicher-Engine CSV
:
int ha_tina::update_row(const byte * old_data, byte * new_data) { int size; DBUG_ENTER("ha_tina::update_row"); statistic_increment(table->in_use->status_var.ha_read_rnd_next_count, &LOCK_status); if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) table->timestamp_field->set_time(); size= encode_quote(new_data); if (chain_append()) DBUG_RETURN(-1); if (my_write(share->data_file, buffer.ptr(), size, MYF(MY_WME | MY_NABP))) DBUG_RETURN(-1); DBUG_RETURN(0); }
Beachten Sie, wie in diesem Beispiel der Zeitstempel eingestellt wurde.
Der MySQL Server verwendet für
DELETE
-Anweisungen denselben Ansatz wie für
UPDATE
-Anweisungen: Er geht mithilfe der
Funktion rnd_next()
zu der Zeile, die
gelöscht werden soll, und ruft dann die Funktion
delete_row()
auf:
int ha_foo::delete_row(const byte *buf)
Der Parameter *buf
enthält den Inhalt der zu
löschenden Zeile. Speicher-Engines ohne Indizierung können
diesen Parameter ignorieren, aber Speicher-Engines mit
Transaktionsunterstützung müssen die gelöschten Daten für ein
späteres Rollback speichern.
Das folgende Beispiel stammt von der
CSV
-Engine:
int ha_tina::delete_row(const byte * buf) { DBUG_ENTER("ha_tina::delete_row"); statistic_increment(table->in_use->status_var.ha_delete_count, &LOCK_status); if (chain_append()) DBUG_RETURN(-1); --records; DBUG_RETURN(0); }
Das Wichtige an diesem Beispiel sind die Aktualisierung der
delete_count
-Statistik und die Zeilenzählung.
Speicher-Engines können nicht nur Tabellenscanning implementieren, sondern auch Funktionen für ein nichtsequenzielles Lesen. Der MySQL Server nutzt diese Funktionen für bestimmte Sortieroperationen.
Die Funktion
position()
wird nach jedem rnd_next()
-Aufruf
benötigt, wenn die Daten neu geordnet werden müssen:
void ha_foo::position(const byte *record)
Der Inhalt von *record
ist Ihre Sache; was
Sie auch immer als Inhalt einsetzen, wird in einem späteren
Abruf der Zeile zurückgeliefert. Die meisten Speicher-Engines
speichern irgendeine Art von Offset oder Primärschlüsselwert.
Die Funktion
rnd_pos()
verhält sich ähnlich wie rnd_next()
, hat
aber einen zusätzlichen Parameter:
int ha_foo::rnd_pos(byte * buf, byte *pos)
Dieser *pos
-Parameter enthält die Position,
die zuvor mit der Funktion position()
ermittelt wurde.
Eine Speicher-Engine muss die Zeile an der angegebenen Position
ausfindig machen und durch *buf
im internen
Zeilenformat von MySQL zurückgeben.
CREATE TABLE
-Operationen
erhaltenindex_init()
index_end()
index_read()
index_read_idx()
index_next()
index_prev()
index_first()
index_last()
Sobald eine Engine über einfache Lese- und Schreiboperationen verfügt, muss als Nächstes Unterstützung für Indizes her. Ohne Indizes ist die Leistung einer Speicher-Engine äußerst mager.
Dieser Abschnitt beschreibt, welche Methoden implementiert werden müssen, damit eine Speicher-Engine Indizes unterstützt.
Indexunterstützung für eine Speicher-Engine bedeutet zweierlei: Informationen an den Optimierer zu geben und indexbezogene Methoden zu implementieren. Die Informationen, die der Optimierer erhält, helfen ihm zu entscheiden, welchen Index er verwenden soll oder ob er die Indizierung beiseite lassen und stattdessen einen Tabellenscan durchführen soll.
Die Indexmethoden lesen entweder Zeilen, die zu einem Schlüssel passen, scannen eine Zeilenmenge in der Reihenfolge ihrer Indizes oder lesen Informationen direkt aus dem Index.
Das folgende Beispiel zeigt die Funktionsaufrufe während einer
UPDATE
-Anfrage, die einen Index nutzt, wie
beispielsweise in UPDATE foo SET ts = now() WHERE id =
1
:
ha_foo::index_init ha_foo::index_read ha_foo::index_read_idx ha_foo::rnd_next ha_foo::update_row
Zusätzlich zu Methoden, die Indizes lesen, benötigt Ihre Speicher-Engine auch Methoden, die neue Indizes erstellen und Tabellenindizes auf dem Laufenden halten, wenn Zeilen hinzugefügt, modifiziert oder entfernt werden.
Speicher-Engines mit Indexunterstützung sollten die
Indexinformationen möglichst während einer CREATE
TABLE
-Operation beschaffen und zur späteren
Verwendung speichern. Der Grund: Die Indexinformationen sind
beim Anlegen der Tabelle und des Indexes am einfachsten zu
bekommen und lassen sich später nicht mehr so leicht abrufen.
Die Daten des Tabellenindexes liegen in der
key_info
-Struktur des
TABLE
-Arguments der
create()
-Funktion vor.
In der key_info
-Struktur gibt es ein
flag
, welches das Verhalten des Indexes
definiert:
#define HA_NOSAME 1 /* Keine Doppeleinträge vorhanden */ #define HA_PACK_KEY 2 /* String zu vorigem Schlüssel packen */ #define HA_AUTO_KEY 16 #define HA_BINARY_PACK_KEY 32 /* Alle Schlüssel zu vorigem Schlüssel packen */ #define HA_FULLTEXT 128 /* Volltextsuche */ #define HA_UNIQUE_CHECK 256 /* Schlüssel auf Eindeutigkeit prüfen */ #define HA_SPATIAL 1024 /* Raumbezogene Suche */ #define HA_NULL_ARE_EQUAL 2048 /* Gleichheitsvergleich für NULL in Schlüssel möglich */ #define HA_GENERATED_KEY 8192 /* Automatisch generierter Schlüssel */
Zusätzlich zum flag
ist ein Enumerator
namens algorithm
vorhanden, der den
gewünschten Indextyp angibt:
enum ha_key_alg { HA_KEY_ALG_UNDEF= 0, /* Nicht angegeben (alte Datei) */ HA_KEY_ALG_BTREE= 1, /* B-Tree, ist der Standard */ HA_KEY_ALG_RTREE= 2, /* R-Tree, für raumbezogenes Suchen */ HA_KEY_ALG_HASH= 3, /* HASH-Schlüssel (HEAP-Tabellen) */ HA_KEY_ALG_FULLTEXT= 4 /* FULLTEXT (MyISAM-Tabellen) */ };
Zusätzlich zum flag
und
algorithm
ist ein Array von
key_part
-Elementen vorhanden, welche die
einzelnen Teile eines zusammengesetzten Schlüssels beschreiben.
Diese Schlüsselteile definieren das zu dem jeweiligen Teil
gehörende Feld, geben an, ob der Schlüssel gepackt werden
soll, und verraten den Datentyp und die Länge des Indexteils.
Unter ha_myisam.cc
finden Sie ein Beispiel
dafür, wie diese Daten geparst werden.
Als Alternative kann eine Speicher-Engine auch dem Beispiel von
ha_berkeley.cc
folgen und bei jeder
Operation Indexinformationen aus der
TABLE
-Struktur des Handlers lesen.
Bei jeder Schreiboperation auf Tabellen
(INSERT
, UPDATE
,
DELETE
) muss die Speicher-Engine ihre
internen Indexdaten aktualisieren.
Die hierzu verwendete Methode variiert von Engine zu Engine und hängt davon ab, welche Methode zum Speichern des Indexes verwendet wird.
Im Allgemeinen muss die Speicher-Engine die in Funktionen wie
write_row()
,
delete_row()
und
update_row()
übergebenen Zeilendaten mit den Indexinformationen der Tabelle
kombinieren, um festzustellen, welche Indexdaten geändert
werden müssen, und die notwendigen Modifikationen vorzunehmen.
Mit welcher Methode Zeile und Index zusammengebracht werden,
hängt von dem Ansatz Ihrer Speicherung ab. Die Speicher-Engine
BerkeleyDB
speichert den Primärschlüssel
der Zeile im Index, während andere Engines oft nur den
Zeilen-Offset speichern.
Viele der Indexmethoden übergeben ein Byte-Array namens
*key
, welches den zu lesenden Indexeintrag in
einem Standardformat angibt. Ihre Speicher-Engine muss die
Informationen des Schlüssels extrahieren und in ihr internes
Indexformat übersetzen, um die zum Index gehörige Zeile zu
ermitteln.
Die im Schlüssel vorliegenden Daten werden mit einer Iteration
durch den Schlüssel beschafft. Ihr Format ist so, wie es in
table->key_info[
definiert wurde. Das folgende Beispiel aus
index
]->key_part[part_num
]ha_berkeley.cc
zeigt, wie die
Speicher-Engine BerkeleyDB
einen in
*key
definierten Schlüssel in ihr internes
Format konvertiert:
/* Erzeuge aus einem ungepackten MySQL-Schlüssel (wie dem, der von index_read() übermittelt wird) einen gepackten. Anhand dieses Schlüssels wird eine Zeile gelesen */ DBT *ha_berkeley::pack_key(DBT *key, uint keynr, char *buff, const byte *key_ptr, uint key_length) { KEY *key_info=table->key_info+keynr; KEY_PART_INFO *key_part=key_info->key_part; KEY_PART_INFO *end=key_part+key_info->key_parts; DBUG_ENTER("bdb:pack_key"); bzero((char*) key,sizeof(*key)); key->data=buff; key->app_private= (void*) key_info; for (; key_part != end && (int) key_length > 0 ; key_part++) { uint offset=0; if (key_part->null_bit) { if (!(*buff++ = (*key_ptr == 0))) // Für NULL wird 0 gespeichert { key_length-= key_part->store_length; key_ptr+= key_part->store_length; key->flags|=DB_DBT_DUPOK; continue; } offset=1; // Daten liegen unter key_ptr+1 } buff=key_part->field->pack_key_from_key_image(buff,(char*) key_ptr+offset, key_part->length); key_ptr+=key_part->store_length; key_length-=key_part->store_length; } key->size= (buff - (char*) key->data); DBUG_DUMP("key",(char*) key->data, key->size); DBUG_RETURN(key); }
Damit die Indizierung wirkungsvoll eingesetzt wird, müssen Speicher-Engines dem Optimierer Informationen über die Tabelle und ihre Indizes liefern. Anhand dieser Informationen wird entschieden, ob und, wenn ja, welcher Index genutzt werden soll.
Durch Aufruf der Funktion
handler::info()
fordert der Optimierer die Aktualisierung der Tabellendaten
an. Die Funktion info()
hat keinen
Rückgabewert; stattdessen wird erwartet, dass die
Speicher-Engine eine Reihe von öffentlichen Variablen setzt,
die der Server dann nach Bedarf auslesen kann. Diese Werte
werden auch für bestimmte SHOW
-Ausgaben
wie beispielsweise SHOW TABLE STATUS
und
für INFORMATION_SCHEMA
eingesetzt.
Alle Variablen sind optional, sollten aber nach Möglichkeit ausgefüllt werden:
records
– Die Anzahl der Zeilen in der
Tabelle. Wenn Sie nicht schnell eine genaue Zahl liefern
können, sollten Sie diesen Wert auf größer als 1 setzen,
damit der Optimierer nicht für Tabellen mit null oder
einer Zeile in Aktion treten muss.
deleted
– Die Anzahl der gelöschten
Zeilen in der Tabelle. Dient der Ermittlung von
Tabellenfragmentation, wo sie vorliegt.
data_file_length
– Die Größe der
Datendatei in Bytes. Hilft dem Optimierer, den Aufwand von
Leseoperationen zu berechnen.
index_file_length
– Die Größe der
Indexdatei in Bytes. Hilft dem Optimierer, den Aufwand von
Leseoperationen zu berechnen.
mean_rec_length
– Die
Durchschnittslänge einer einzelnen Zeile in Bytes.
scan_time
– I/O-Aufwand für den
Versuch eines vollständigen Tabellenscans.
delete_length
–
(keine Beschreibung verfügbar)
check_time
–
(keine Beschreibung verfügbar)
Bei der Berechnung von Werten geht Geschwindigkeit vor Genauigkeit, da es keinen Sinn hat, viel Zeit zu vertrödeln, um dem Optimierer den schnellsten Weg aufzuzeigen. Schätzungen innerhalb einer Größenordnung sind normalerweise ausreichend.
Die Funktion
records_in_range()
wird vom Optimierer aufgerufen, um besser entscheiden zu
können, welcher Index einer Tabelle für eine Anfrage oder
einen Join benutzt werden soll. Sie ist folgendermaßen
definiert:
ha_rows ha_foo::records_in_range(uint inx, key_range *min_key, key_range *max_key)
Der Parameter inx
ist der zu prüfende
Index. Der Parameter *min_key
gibt das
untere und der Parameter *max_key
das obere
Ende des Bereichs an.
min_key.flag
kann einen der folgenden Werte
haben:
HA_READ_KEY_EXACT
- Schlüssel in den
Bereich einbeziehen
HA_READ_AFTER_KEY
- Schlüssel nicht in
den Bereich einbeziehen
max_key.flag
kann einen der folgenden Werte
haben:
HA_READ_BEFORE_KEY
- Schlüssel nicht
in den Bereich einbeziehen
HA_READ_AFTER_KEY
- Alle
'end_key'-Werte in den Bereich einbeziehen
Folgende Rückgabewerte sind zulässig:
0
- Keine passenden Schlüssel im
gegebenen Bereich vorhanden
number > 0
- Es gibt ungefähr
number
passende Zeilen im
Bereich
HA_POS_ERROR
- Fehler im Indexbaum
Bei der Berechnung der Werte geht Geschwindigkeit vor Genauigkeit.
Die Funktion
index_init()
wird vor Benutzung eines Indexes aufgerufen, damit die
Speicher-Engine die notwendigen Vorbereitungen oder
Optimierungen vornehmen kann:
int ha_foo::index_init(uint keynr, bool sorted)
Da die meisten Speicher-Engines keine besonderen Vorbereitungen treffen, wird in diesem Fall eine Standardimplementierung verwendet, wenn die Methode nicht explizit in der Engine implementiert ist:
int handler::index_init(uint idx) { active_index=idx; return 0; }
Die Funktion
index_end()
ist das Gegenstück zu index_init()
. Ihre
Aufgabe ist es, hinter index_init()
wieder
aufzuräumen.
Wenn eine Speicher-Engine index_init()
nicht implementiert, muss sie auch
index_end()
nicht implementieren.
Die Funktion
index_read()
wird verwendet, um eine Zeile anhand eines Schlüssels
abzufragen:
int ha_foo::index_read(byte * buf, const byte * key, uint key_len, enum ha_rkey_function find_flag)
Der Parameter *buf
ist ein Byte-Array, in dem
die Speicher-Engine die Zeile speichert, die zu dem
Indexschlüssel *key
gehört. Der Parameter
key_len
gibt bei Präfixvergleichen die
Länge des Präfixes an und find_flag
ist ein
Enumerator, der das Suchverhalten bestimmt.
Der zu verwendende Index wird vorher im Aufruf von
index_init()
festgelegt und dann in der Handler-Variablen
active_index
gespeichert.
Folgende Werte sind für find_flag
zulässig:
HA_READ_KEY_EXACT HA_READ_KEY_OR_NEXT HA_READ_PREFIX_LAST HA_READ_PREFIX_LAST_OR_PREV HA_READ_BEFORE_KEY HA_READ_AFTER_KEY HA_READ_KEY_OR_NEXT HA_READ_KEY_OR_PREV
Speicher-Engines müssen den Parameter *key
in ihr spezifisches Format konvertieren. Danach verwenden sie
ihn, um anhand von find_flag
die passende
Zeile zu finden und im internen Zeilenformat von MySQL in
*buf
zu speichern. Weitere Informationen
über das interne Zeilenformat finden Sie unter
Abschnitt 15.9.6, „Implementierung der Funktion rnd_next()
“.
Die Speicher-Engine muss nicht nur die passende Zeile zurückgeben, sondern auch einen Cursor setzen, um sequenzielle Index-Reads zu unterstützen.
Ist der Parameter *key
null, liest die
Speicher-Engine den ersten Schlüssel im Index.
Die Funktion
index_read_idx()
gleicht
index_read()
mit dem Unterschied, dass index_read_idx()
noch einen weiteren keynr
-Parameter
akzeptiert:
int ha_foo::index_read_idx(byte * buf, uint keynr, const byte * key, uint key_len, enum ha_rkey_function find_flag)
Der Parameter keynr
gibt den zu lesenden
Index an, während bei index_read
der Index
bereits eingestellt ist.
Wie mit index_read()
muss auch hier die
Speicher-Engine die zum Schlüssel gehörige Zeile gemäß dem
find_flag
zurückgeben und für zukünftige
Leseoperationen einen Cursor setzen.
Die Funktion
index_next()
wird zum Durchsuchen des Indexes benutzt:
int ha_foo::index_next(byte * buf)
Im Parameter *buf
wird die Zeile gespeichert,
die entsprechend dem internen Cursor, den die Speicher-Engine
bei Operationen wie index_read()
und
index_first()
gesetzt hatte, dem nächsten
passenden Schlüsselwert entspricht.
Die Funktion
index_prev()
wird für umgekehrtes Indexscanning verwendet:
int ha_foo::index_prev(byte * buf)
Im Parameter *buf
wird die Zeile gespeichert,
die entsprechend dem internen Cursor, den die Speicher-Engine
bei Operationen wie index_read()
und
index_last()
gesetzt hatte, dem vorherigen
passenden Schlüsselwert entspricht.
Die Funktion
index_first()
wird für das Indexscanning verwendet:
int ha_foo::index_first(byte * buf)
Im Parameter *buf
wird die Zeile gespeichert,
die dem ersten Schlüsselwert im Index entspricht.
Die Funktion
index_last()
wird für das umgekehrte Indexscanning verwendet:
int ha_foo::index_last(byte * buf)
Im Parameter *buf
wird die Zeile gespeichert,
die dem letzten Schlüsselwert im Index entspricht.
In diesem Abschnitt sind Methoden beschrieben, die implementiert werden müssen, damit eine Speicher-Engine Transaktionen unterstützen kann.
Bitte beachten Sie, dass das Transaktionsmanagement eine
komplizierte Sache sein kann, zu der auch Methoden zur
Zeilenversionierung und Redo-Logs gehören, die den Rahmen dieser
Dokumentation sprengen würden. Hier wird lediglich beschrieben,
welche Methoden notwendig sind, und nicht, wie diese implementiert
werden. Implementierungsbeispiele finden Sie in
ha_innodb.cc
und
ha_berkeley.cc
.
Transaktionen werden nicht explizit auf der Ebene der
Speicher-Engines, sondern implizit durch Aufrufe der Funktion
start_stmt()
oder
external_lock()
gestartet. Falls bei Aufruf
dieser Funktionen bereits eine Transaktion läuft, wird diese
nicht ersetzt.
Die Speicher-Engine speichert Transaktionsinformationen in ihrem
pro Verbindung zugewiesenen Arbeitsspeicher und registriert die
Transaktion beim MySQL Server, damit dieser später
COMMIT
- und
ROLLBACK
-Operationen ausführen kann.
Die Speicher-Engine muss irgendeine Art von Versionierung oder Protokollierung implementieren, damit alle Operationen, die im Rahmen der Transaktion ausgeführt werden, wieder zurückgerollt werden können.
Nach getaner Arbeit ruft der MySQL Server entweder die
commit()
-Funktion oder die im Handlerton
der Speicher-Engine definierte
rollback()
-Funktion auf.
Die Speicher-Engine startet eine Transaktion, wenn die Funktion
start_stmt()
oder
external_lock()
aufgerufen wird.
Ist noch keine Transaktion aktiv, muss die Speicher-Engine eine
neue beginnen und beim MySQL Server registrieren, damit später
ROLLBACK
oder COMMIT
aufgerufen werden kann.
Die erste Funktion, die eine Transaktion beginnen kann, ist
start_stmt()
.
Das folgende Beispiel zeigt, wie eine Speicher-Engine eine Transaktion registrieren könnte:
int my_handler::start_stmt(THD *thd, thr_lock_type lock_type) { int error= 0; my_txn *txn= (my_txn *) thd->ha_data[my_handler_hton.slot]; if (txn == NULL) { thd->ha_data[my_handler_hton.slot]= txn= new my_txn; } if (txn->stmt == NULL && !(error= txn->tx_begin())) { txn->stmt= txn->new_savepoint(); trans_register_ha(thd, FALSE, &my_handler_hton); } return error; }
THD
ist die aktuelle Clientverbindung. Sie
speichert zustandsrelevante Daten für den aktuellen Client,
wie beispielsweise seine Identität, Netzwerkverbindung und
andere Verbindungsdaten.
thd->ha_data[my_handler_hton.slot]
ist ein
Zeiger in thd
auf die
verbindungsspezifischen Daten dieser Speicher-Engine. In
diesem Beispiel wird er verwendet, um den Transaktionskontext
zu speichern.
Ein weiteres Beispiel für die Implementierung von
start_stmt()
finden Sie in
ha_innodb.cc
.
MySQL ruft zu Beginn jeder Anweisung für jede zu verwendende
Tabelle
handler::external_lock()
auf. Somit wird immer dann, wenn eine Tabelle zum ersten Mal
angesprochen wird, implizit eine Transaktion gestartet.
Da noch keine Sperren vorhanden sind, werden alle Tabellen,
die möglicherweise zwischen dem Anfang und dem Ende einer
Anweisung verwendet werden könnten, gesperrt, bevor die
Ausführung der Anweisung beginnt. Für alle diese Tabellen
wird handler::external_lock()
aufgerufen.
Wenn also ein INSERT
einen Trigger
abfeuert, der eine gespeicherte Prozedur aufruft, die eine
gespeicherte Funktion aufruft usw., werden alle von Trigger,
gespeicherter Prozedur, Funktion usw. verwendeten Tabellen
schon zu Beginn des INSERT
gesperrt. Und
wenn ein Konstrukt wie das folgende vorliegt, dann werden beide Tabellen gesperrt:
IF .. verwende eine Tabelle ELSE .. verwende eine andere Tabelle
Außerdem gilt: Wenn ein Benutzer LOCK
TABLES
eingibt, ruft MySQL
handler::external_lock
nur ein einziges
Mal auf. In diesem Fall führt MySQL
handler::start_stmt()
zu Beginn der
Anweisung aus.
Das folgende Beispiel zeigt, wie eine Speicher-Engine eine Transaktion starten und Sperranforderungen dabei berücksichtigen kann:
int my_handler::external_lock(THD *thd, int lock_type) { int error= 0; my_txn *txn= (my_txn *) thd->ha_data[my_handler_hton.slot]; if (txn == NULL) { thd->ha_data[my_handler_hton.slot]= txn= new my_txn; } if (lock_type != F_UNLCK) { bool all_tx= 0; if (txn->lock_count == 0) { txn->lock_count= 1; txn->tx_isolation= thd->variables.tx_isolation; all_tx= test(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN | OPTION_TABLE_LOCK)); } if (all_tx) { txn->tx_begin(); trans_register_ha(thd, TRUE, &my_handler_hton); } else if (txn->stmt == 0) { txn->stmt= txn->new_savepoint(); trans_register_ha(thd, FALSE, &my_handler_hton); } } else { if (txn->stmt != NULL) { /* Schreibe Transaktion fest, wenn Autocommit-Modus eingeschaltet */ my_handler_commit(thd, FALSE); delete txn->stmt; // Lösche Savepoint txn->stmt= NULL; } } return error; }
Jede Speicher-Engine muss immer zu Beginn einer Transaktion
trans_register_ha()
aufrufen. Die
Funktion trans_register_ha()
registriert
eine Transaktion beim MySQL Server, um spätere
COMMIT
- und
ROLLBACK
-Operationen möglich zu machen.
Ein weiteres Implementierungsbeispiel für
external_lock()
finden Sie in
ha_innodb.cc
.
Von den beiden wichtigsten Transaktionsoperationen ist
ROLLBACK
am schwierigsten zu
implementieren. Alle Operationen, die während der Transaktion
auftraten, müssen rückgängig gemacht werden, damit sämtliche
Zeilen wieder den unveränderten Zustand vor der Transaktion
zurückerhalten.
Um ROLLBACK
zu unterstützen, benötigen Sie
eine Funktion, die folgender Definition entspricht:
int (*rollback)(THD *thd, bool all);
Der Name dieser Funktion wird dann im
rollback
-Eintrag (dem 13.) des
Handlerton
aufgeführt.
Der Parameter THD
zeigt an, welche
Transaktion zurückgerollt werden soll, und bool
all
legt fest, ob die gesamte Transaktion oder nur die
letzte Anweisung rückgängig gemacht werden soll.
Die Implementierungsdetails von ROLLBACK
sind
von Engine zu Engine unterschiedlich. Beispiele finden Sie in
ha_innodb.cc
und
ha_berkeley.cc
.
Bei einer Commit-Operation werden alle während einer Transaktion vorgenommenen Änderungen festgeschrieben, sodass eine Rollback-Operation danach nicht mehr möglich ist. Je nachdem, welche Transaktionsisolation verwendet wurde, werden die Änderungen dann zum ersten Mal für andere Threads sichtbar.
Zur Unterstützung von COMMIT
benötigen Sie
eine Funktion, die wie folgt definiert ist:
int (*commit)(THD *thd, bool all);
Der Name dieser Funktion wird dann im
commit
-Eintrag (dem 12.) des
Handlerton
aufgeführt.
Der Parameter THD
zeigt an, welche
Transaktion festgeschrieben werden soll, und bool
all
legt fest, ob dies ein kompletter Commit ist oder
nur das Ende einer zu einer Transaktion gehörenden Anweisung.
Die Implementierungsdetails von COMMIT
sind
von Engine zu Engine unterschiedlich. Beispiele finden Sie in
ha_innodb.cc
and
ha_berkeley.cc
.
Läuft der Server im Autocommit-Modus, so müsste die
Speicher-Engine automatisch alle nur-lesenden Anweisungen wie
beispielsweise SELECT
festschreiben.
Das "Autocommitten" in einer Speicher-Engine funktioniert durch
Zählen von Sperren. Jeder Aufruf von
external_lock()
inkrementiert den Zähler
und jeder Aufruf von external_lock()
mit
dem Argument F_UNLCK
dekrementiert ihn.
Fällt die Anzahl der Sperren auf null, wird ein Commit
ausgelöst.
Zuerst sollte der Implementierer wissen, wie viele Bytes erforderlich sind, um die Savepoint-Daten zu speichern. Diese Anzahl sollte eine feste Größe und möglichst nicht zu groß sein, da der MySQL Server Platz zum Speichern des Savepoints für alle Speicher-Engines und jeden benannten Savepoint zuweisen muss.
Der Implementierer sollte die Daten in dem von mysqld zuvor zugewiesenen Platz speichern und den Inhalt dieses zugewiesenen Speichers auch nutzen, um Rollback- oder Savepoint-Freigabeoperationen auszuführen.
Wenn ein COMMIT
oder
ROLLBACK
eintritt (wobei bool
all
auf true
gesetzt ist), werden
alle Savepoints freigegeben. Wenn die Speicher-Engine Ressourcen
für Savepoints zuweist, sollte sie diese freigeben.
Die folgenden Handlerton-Elemente müssen implementiert werden, damit Savepoints unterstützt werden können (es sind die Elemente 7, 9, 10 und 11):
uint savepoint_offset; int (*savepoint_set)(THD *thd, void *sv); int (*savepoint_rollback)(THD *thd, void *sv); int (*savepoint_release)(THD *thd, void *sv);
Das siebte Element des Handlertons ist der
savepoint_offset
:
uint savepoint_offset;
Der savepoint_offset
muss mit einer festen
Größe initialisiert werden, die ausreicht, um die Savepoint
zu speichernden Informationen aufzunehmen.
Die Funktion savepoint_set()
wird immer
dann aufgerufen, wenn ein Benutzer den Befehl
SAVEPOINT
gibt:
int (*savepoint_set)(THD *thd, void *sv);
Der Parameter *sv
verweist auf einen
uninitialisierten Speicherbereich, dessen Größe in
savepoint_offset
definiert wurde.
Wenn savepoint_set()
aufgerufen wird,
muss die Speicher-Engine Savepoint-Informationen in
sv
speichern, damit der Server die
Transaktion später bis zu dem Savepoint zurückrollen oder
die Ressourcen des Savepoints wieder freigeben kann.
Die Funktion savepoint_rollback()
wird
immer dann aufgerufen, wenn ein Benutzer die ROLLBACK
TO SAVEPOINT
-Anweisung erteilt:
int (*savepoint_rollback) (THD *thd, void *sv);
Der Parameter *sv
verweist auf den
Speicherbereich, der zuvor an die Funktion
savepoint_set()
übergeben wurde.
Die Funktion savepoint_release()
wird
immer dann aufgerufen, wenn ein Benutzer die Anweisung
RELEASE SAVEPOINT
verwendet:
int (*savepoint_release) (THD *thd, void *sv);
Der Parameter *sv
verweist auf den
Speicherbereich, der zuvor an die Funktion
savepoint_set()
übergeben wurde.
Definiert die von der Speicher-Engine verwendeten Dateierweiterungen.
virtual const char ** bas_ext
( | ) ; |
; |
Dies ist die Methode bas_ext
. Sie wird
aufgerufen, um dem MySQL Server die Liste der von der
Speicher-Engine verwendeten Dateierweiterungen in Form eines mit
null endenden String-Arrays mitzuteilen.
Indem sie eine Liste der Dateierweiterungen angeben, können
Speicher-Engines in vielen Fällen auf die Funktion
delete_table()
verzichten, da der MySQL Server alle Verweise auf die Tabelle
schließt und alle Dateien mit den angegebenen Erweiterungen
löscht.
Diese Funktion hat keine Parameter.
Der Rückgabewert ist ein auf null endendes String-Array mit
den Dateierweiterungen der Speicher-Engine. Das folgende
Beispiel stammt von der Engine CSV
:
static const char *ha_tina_exts[] = { ".CSV", NullS };
static const char *ha_tina_exts[] = { ".CSV", NullS }; const char **ha_tina::bas_ext() const { return ha_tina_exts; }
static const char *ha_example_exts[] = { NullS }; const char **ha_example::bas_ext() const { return ha_example_exts; }
Schließt eine geöffnete Tabelle.
virtual int close
( | void) ; |
void ; |
Dies ist die Methode close
.
Schließt eine Tabelle. Ein guter Zeitpunkt, um die zugewiesenen Ressourcen wieder freizugeben.
Wird von sql_base.cc
,
sql_select.cc
und table.cc
aufgerufen. In sql_select.cc
wird diese
Methode nur zum Schließen temporärer Tabellen oder bei der
Konvertierung einer temporären in eine
MyISAM
-Tabelle verwendet. Wegen
sql_base.cc
schauen Sie unter
close_data_tables()
nach.
void
Keine Rückgabewerte.
Ein Beispiel von der CSV
-Engine:
int ha_example::close(void) { DBUG_ENTER("ha_example::close"); DBUG_RETURN(free_share(share)); }
Legt eine neue Tabelle an.
virtual int create
( | name, | |
form, | ||
info) ; |
const char * | name ; |
TABLE * | form ; |
HA_CREATE_INFO * | info ; |
Dies ist die Methode create
.
create()
wird aufgerufen, um eine Tabelle
anzulegen. Der Variablenname ist dann der Name der Tabelle. Wenn
Sie create()
aufrufen, brauchen Sie die
Tabelle nicht zu öffnen. Auch die
.frm
-Datei ist dann bereits angelegt,
sodass ein Aufruf von adjusting create_info
nicht mehr zu empfehlen ist.
Wird von handler.cc
in Form von
ha_create_table()
aufgerufen.
name
form
info
Keine Rückgabewerte.
Beispiel von der Speicher-Engine CSV
:
int ha_tina::create(const char *name, TABLE *table_arg, HA_CREATE_INFO *create_info) { char name_buff[FN_REFLEN]; File create_file; DBUG_ENTER("ha_tina::create"); if ((create_file= my_create(fn_format(name_buff, name, "", ".CSV", MY_REPLACE_EXT|MY_UNPACK_FILENAME),0, O_RDWR | O_TRUNC,MYF(MY_WME))) < 0) DBUG_RETURN(-1); my_close(create_file,MYF(0)); DBUG_RETURN(0); }
Löscht eine Zeile.
virtual int delete_row
( | buf) ; |
const byte * | buf ; |
Dies ist die Methode delete_row
.
buf
enthält eine Kopie der zu löschenden Zeile. Der Server
verwendet diese Funktion, unmittelbar nachdem die aktuelle Zeile
aufgerufen wurde (von einer vorangegangenen
rnd_next()
-Funktion oder einem
Indexaufruf). Wenn Sie einen Zeiger auf die letzte Zeile
bewahren oder auf einen Primärschlüssel zugreifen können,
wird das Löschen viel einfacher. Denken Sie daran, dass der
Server aufeinander folgende Löschungen nicht garantiert.
ORDER BY
-Klauseln können verwendet werden.
Wird in sql_acl.cc
und
sql_udf.cc
aufgerufen, um interne
Tabelleninformationen zu verwalten. Wird auch in
sql_delete.cc
,
sql_insert.cc
und
sql_select.cc
benutzt. In
sql_select
wird diese Funktion zum Entfernen
von Duplikaten eingesetzt, während sie in
insert
für
REPLACE
-Aufrufe verwendet wird.
buf
Keine Rückgabewerte.
(kein Beispiel verfügbar)
{ return HA_ERR_WRONG_COMMAND; }
Alle Dateien löschen, die eine von
bas_ext()
gemeldete Erweiterung haben.
virtual int delete_table
( | name) ; |
const char * | name ; |
Dies ist die Methode delete_table
.
Dient dem Löschen einer Tabelle. Wenn
delete_table()
aufgerufen wird, sind alle
offenen Verweise auf diese Tabelle geschlossen (und auch Ihre
globalen, gemeinsam genutzten Verweise freigegeben) worden. Der
Variablenname ist der Name der Tabelle. Zuvor angelegte Dateien
müssen an diesem Punkt gelöscht werden.
Wenn Sie diese Funktion nicht implementieren, wird die
Standardfunktion delete_table()
von
handler.cc
aufgerufen, die alle Dateien mit
den von bas_ext()
zurückgegebenen
Erweiterungen löscht. Man kann davon ausgehen, dass der Handler
unter Umständen mehr Erweiterungen zurückgibt, als für die
Datei tatsächlich verwendet wurden.
Wird von handler.cc
durch
delete_table
und
ha_create_table()
aufgerufen. Wird beim
Erzeugen einer Tabelle nur dann eingesetzt, wenn das
table_flag
HA_DROP_BEFORE_CREATE
für die
Speicher-Engine angegeben wurde.
name
: Basisname der Tabelle
0
, wenn mindestens eine Datei von
base_ext
erfolgreich gelöscht und keine
anderen Fehler als ENOENT
gemeldet
wurden.
#
: Fehler
Die meisten Speicher-Engines brauchen diese Funktion nicht zu implementieren.
Sorgt bei Transaktionen für das Sperren der Tabellen.
virtual int external_lock
( | thd, | |
lock_type) ; |
THD * | thd ; |
int | lock_type ; |
Dies ist die Methode external_lock
.
Im Abschnitt „locking functions for mysql“ in
lock.cc
finden Sie weitere lesenswerte
Hinweise zu diesem Thema.
Sperrt eine Tabelle. Wenn Sie eine Speicher-Engine
implementieren, die mit Transaktionen umgehen kann, schauen Sie
in ha_berkely.cc
nach, wie Sie am besten
vorgehen. Ansonsten können Sie hier auch einen Aufruf von
flock()
in Erwägung ziehen.
Wird von lock.cc
durch
lock_external()
und
unlock_external()
sowie von
sql_table.cc
durch
copy_data_between_tables()
aufgerufen.
thd
lock_type
Keine Rückgabewerte.
{ return 0; }
Übergibt Hinweise („Hints“) vom Server an die Speicher-Engine.
virtual int extra
( | operation) ; |
enum ha_extra_function | operation ; |
Dies ist die Methode extra
.
extra()
wird aufgerufen, wenn der Server
einen Hinweis an die Speicher-Engine senden will. Die Engine
MyISAM
implementiert die meisten Hinweise.
ha_innodb.cc
enthält die vollständigste
Liste dieser Hinweise.
operation
Keine Rückgabewerte.
Die meisten Speicher-Engines geben einfach 0
zurück.
{ return 0; }
Sie können Ihrer Speicher-Engine auch die Standardeinstellung geben, keinen dieser Hinweise zu implementieren.
{ return 0; }
Zeigt das Ende eines Indexscans an und gibt die hierfür belegten Ressourcen frei.
virtual int index_end
( | ) ; |
; |
Dies ist die Methode index_end
, die
normalerweise als Gegenstück zu index_init
verwendet wird und alle für den Indexscan verwendeten
Ressourcen wieder freigibt.
Diese Funktion hat keine Parameter.
Diese Funktion hat keine Rückgabewerte.
Gibt alle zugewiesenen Ressourcen frei und liefert 0 zurück.
{ active_index=MAX_KEY; return 0; }
Fragt die erste Zeile eines Indexes ab und gibt sie zurück.
virtual int index_first
( | buf) ; |
byte * | buf ; |
Dies ist die Methode index_first
.
index_first()
fragt nach dem ersten
Schlüssel im Index.
Wird von opt_range.cc
,
opt_sum.cc
, sql_handler.cc
und sql_select.cc
aufgerufen.
buf
- Ein Byte-Array, in welches die
Zeile geladen wird.
Keine Rückgabewerte.
Die Implementierung hängt von der verwendeten Indexmethode ab.
{ return HA_ERR_WRONG_COMMAND; }
Teilt der Speicher-Engine mit, dass ein Indexscan bevorsteht, damit diese die benötigten Ressourcen zuweist.
virtual int index_init
( | idx, | |
sorted) ; |
uint | idx ; |
bool | sorted ; |
Dies ist die Methode index_init
. Diese
Funktion wird vor einem Indexscan aufgerufen, damit die
Speicher-Engine Gelegenheit hat, Ressourcen zuzuweisen und
Vorbereitungen zu treffen.
idx
sorted
(nicht verfügbar)
Diese Funktion kann 0 zurückgeben, wenn keine Vorbereitung erforderlich ist.
{ active_index=idx; return 0; }
Gibt die letzte Zeile des Indexes zurück.
virtual int index_last
( | buf) ; |
byte * | buf ; |
Dies ist die Methode index_last
.
index_last()
fragt nach dem letzten
Schlüssel im Index.
Wird von opt_range.cc
,
opt_sum.cc
, sql_handler.cc
und sql_select.cc
aufgerufen.
buf
- Ein Byte-Array, in welches die
zugehörige Zeile geladen wird.
Diese Funktion hat keine Rückgabewerte.
Geht zur letzten Zeile im Index und lädt den zugehörigen Datensatz in den Puffer.
{ return HA_ERR_WRONG_COMMAND; }
Gibt die nächste Zeile im Index zurück.
virtual int index_next
( | buf) ; |
byte * | buf ; |
Dies ist die Methode index_next
.
Wird verwendet, um sich im Index nach vorne zu arbeiten.
buf
Diese Funktion hat keine Rückgabewerte.
Geht mithilfe eines Zeigers oder Cursors immer zum nächsten Index weiter und schreibt die zugehörige Zeile in den Puffer.
{ return HA_ERR_WRONG_COMMAND; }
Geht zur vorherigen Zeile im Index.
virtual int index_prev
( | buf) ; |
byte * | buf ; |
Dies ist die Methode index_prev
.
Wird verwendet, um sich rückwärts durch den Index zu arbeiten.
buf
Diese Funktion hat keine Rückgabewerte.
Geht zur vorigen Zeile im Index und schreibt diese in den Puffer.
{ return HA_ERR_WRONG_COMMAND; }
Sucht anhand eines Schlüssels eine Zeile und schreibt sie in den Puffer.
virtual int index_read_idx
( | buf, | |
index, | ||
key, | ||
key_len, | ||
find_flag) ; |
byte * | buf ; |
uint | index ; |
const byte * | key ; |
uint | key_len ; |
enum ha_rkey_function | find_flag ; |
Dies ist die Methode index_read_idx
.
Setzt einen Indexcursor auf den im Schlüssel angegebenen Indexwert und holt, sofern vorhanden, die zugehörige Zeile ab. Wird nur verwendet, um ganze Schlüssel zu lesen.
buf
index
key
key_len
find_flag
Diese Funktion hat keine Rückgabewerte.
Findet die zum Schlüssel gehörige Zeile und gibt sie in den bereitgestellten Puffer zurück.
Sucht anhand eines Schlüssels eine Zeile und kehrt zurück.
virtual int index_read
( | buf, | |
key, | ||
key_len, | ||
find_flag) ; |
byte * | buf ; |
const byte * | key ; |
uint | key_len ; |
enum ha_rkey_function | find_flag ; |
Dies ist die Methode index_read
.
Setzt einen Indexcursor auf den im Handle angegebenen Indexwert und holt, sofern vorhanden, die zugehörige Zeile ab. Ist der Schlüsselwert null, beginnt die Funktion beim ersten Schlüssel des Indexes.
buf
key
key_len
find_flag
Diese Funktion hat keine Rückgabewerte.
(kein Beispiel verfügbar)
{ return HA_ERR_WRONG_COMMAND; }
Lässt die Speicher-Engine Statistikdaten ausgeben.
virtual void info
( | uint) ; |
uint ; |
Dies ist die Methode info
.
::info()
gibt Informationen an den Optimierer
zurück. Zurzeit implementiert dieser Tabellen-Handler die
meisten erforderlichen Felder noch nicht. Auch
SHOW
nutzt diese Daten. Ein weiterer Hinweis
ist der, dass Sie voraussichtlich Folgendes in Ihren Code
schreiben müssen: if (records < 2) records =
2;
. Denn sonst führt der Server auch in Fällen, wo
nur ein einziger Datensatz vorhanden ist, Optimierungen durch.
Wenn Sie die Anzahl der Datensätze bei einem Tabellenscan nicht
kennen, sollten Sie records
auf zwei
einstellen, damit Sie so viele Datensätze zurückgeben können,
wie Sie benötigen. Neben records
gibt es
noch einige weitere Variablen einzustellen, nämlich:
deleted data_file_length
,
index_file_length
, delete_length
check_time
. Weitere Informationen finden Sie unter den
öffentlichen Variablen in handler.h
.
Wird in filesort.cc
,
ha_heap.cc
, item_sum.cc
,
opt_sum.cc
, sql_delete.cc
,
sql_delete.cc
,
sql_derived.cc
,
sql_select.cc
,
sql_select.cc
,
sql_select.cc
,
sql_select.cc
,
sql_select.cc
,
sql_show.cc
,
sql_show.cc
sql_show.cc
,
sql_show.cc
, sql_table.cc
,
sql_union.cc
und
sql_update.cc
aufgerufen.
uint
Keine Rückgabewerte.
Dieses Beispiel stammt von der Speicher-Engine
CSV
:
void ha_tina::info(uint flag) { DBUG_ENTER("ha_tina::info"); /* Ist zwar gelogen, aber der Optimierer soll keine mit null oder 1 Datensatz anfassen */ if (records < 2) records= 2; DBUG_VOID_RETURN; }
Öffnet eine Tabelle.
virtual int open
( | name, | |
mode, | ||
test_if_locked) ; |
const char * | name ; |
int | mode ; |
uint | test_if_locked ; |
Dies ist die Methode open
.
Wird zum Öffnen von Tabellen verwendet. Der Name ist der Name der Datei. Eine Tabelle wird dann geöffnet, wenn es nötig ist, zum Beispiel, wenn eine SELECT-Anfrage für die Tabelle eintrifft. (Die Tabellen werden jedoch nicht für jede Anfrage geöffnet und geschlossen, sondern zwischenzeitlich im Cache gelagert.)
Wird von handler.cc
durch
handler::ha_open()
aufgerufen. Der Server
öffnet alle Tabellen mit einem Aufruf der Funktion
ha_open()
, die dann die Handler-spezifische
open()
-Funktion aufruft.
Ein Handler-Objekt wird im Rahmen seiner Initialisierung geöffnet, bevor es für normale Anfragen verwendet wird (nicht immer vor Metadatenänderungen.) Wenn das Objekt geöffnet wurde, wird es auch vor dem Löschen wieder geschlossen.
Dies ist die Methode open
. Sie wird
aufgerufen, um eine Datenbanktabelle zu öffnen.
Der erste Parameter ist der Name der zu öffnenden Tabelle und
der zweite legt fest, welche Datei geöffnet oder welche
Operation ausgeführt werden soll. Die Werte sind in
handler.h
definiert und werden hier für
Sie noch einmal aufgeführt:
#define HA_OPEN_KEYFILE 1 #define HA_OPEN_RNDFILE 2 #define HA_GET_INDEX 4 #define HA_GET_INFO 8 /* nach dem Öffnen ha_info() aufrufen */ #define HA_READ_ONLY 16 /* Datei schreibgeschützt öffnen */ #define HA_TRY_READ_ONLY 32 /* Wenn Schreibzugriff nicht möglich, schreibgeschützten versuchen */ #define HA_WAIT_IF_LOCKED 64 /* Bei vorhandener Sperre mit dem Öffnen warten */ #define HA_ABORT_IF_LOCKED 128 /* Bei vorhandener Sperre das Öffnen überspringen*/ #define HA_BLOCK_LOCK 256 /* Entsperren, wenn einige Datensätze gelesen werden */ #define HA_OPEN_TEMPORARY 512
Die letzte Option gibt an, ob der Handler auf Sperren auf der Tabelle achten soll, ehe er sie öffnet.
In der Regel wird Ihre Speicher-Engine auch irgendeine Form von
Zugriffskontrolle implementieren müssen, damit in einer
Multithread-Umgebung keine Dateien beschädigt werden. Ein
Beispiel für die Implementierung von Dateisperren finden Sie in
den Methoden get_share()
und
free_share()
von
sql/examples/ha_tina.cc
.
name
mode
test_if_locked
Keine Rückgabewerte.
Dieses Beispiel stammt von der Speicher-Engine
CSV
:
int ha_tina::open(const char *name, int mode, uint test_if_locked) { DBUG_ENTER("ha_tina::open"); if (!(share= get_share(name, table))) DBUG_RETURN(1); thr_lock_data_init(&share->lock,&lock,NULL); ref_length=sizeof(off_t); DBUG_RETURN(0); }
Liefert dem MySQL Server die Position/den Offset der zuletzt gelesenen Zeile.
virtual void position
( | record) ; |
const byte * | record ; |
Dies ist die Methode position
.
position()
wird nach jedem
rnd_next()
aufgerufen, wenn die Daten
geordnet werden müssen. Um die Position zu speichern, können
Sie so etwas wie das Folgende tun: my_store_ptr(ref,
ref_length, current_position)
;
Der Server benutzt ref
zum Speichern von
Daten. In den obigen Fällen ist ref_length
die Größe, die erforderlich ist, um die
current_position
zu speichern.
ref
ist nur ein Byte-Array, das vom Server
gepflegt wird. Wenn Sie Offsets verwenden, um Zeilen zu
kennzeichnen, dann sollte current_position
der Offset sein. Wenn ein Primärschlüssel verwendet wird, wie
in BDB
, dann muss
current_position
ein Primärschlüssel sein.
Wird aufgerufen von filesort.cc
,
sql_select.cc
,
sql_delete.cc
und
sql_update.cc
.
record
Diese Funktion hat keine Rückgabewerte.
Gibt für die letzte Zeile einen Offset oder einen Schlüssel für den Datenabruf zurück.
Gibt eine Einschätzung, wie viele Datensätze in dem angegebenen Bereich liegen.
virtual ha_rows records_in_range
( | inx, | |
min_key, | ||
max_key) ; |
uint | inx ; |
key_range * | min_key ; |
key_range * | max_key ; |
Dies ist die Methode records_in_range
.
Wenn Sie dieser Funktion einen Start- und einen End-Schlüssel
übergeben, schätzt sie ein, wie viele Zeilen zwischen diesen
beiden Schlüsseln liegen. end_key
kann auch
leer sein; in diesem Fall wird ermittelt, ob
start_key
irgendwelchen Zeilen entspricht.
Wird vom Optimierer genutzt, um den Aufwand zu ermitteln, den die Benutzung eines bestimmten Indexes verursachen würde.
Wird von opt_range.cc
durch
check_quick_keys()
aufgerufen.
inx
min_key
max_key
Gibt die ungefähre Anzahl der Zeilen zurück.
Ermittelt näherungsweise die Anzahl der Zeilen zwischen den beiden Schlüsselwerten und kehrt zurück.
{ return (ha_rows) 10; }
Initialisiert einen Handler für den Tabellenscan.
virtual int rnd_init
( | scan) ; |
bool | scan ; |
Dies ist die Methode rnd_init
.
rnd_init()
wird aufgerufen, wenn das System
von der Speicher-Engine einen Tabellenscan verlangt.
Anders als index_init()
kann
rnd_init()
zweimal aufgerufen werden, ohne
dass zwischendurch rnd_end()
erforderlich
ist (macht nur Sinn, wenn scan=1). Der zweite Aufruf sollte dann
den neuen Tabellenscan vorbereiten (wenn z. B.
rnd_init()
den Cursor zuweist, sollte der
zweite Aufruf diesen an den Tabellenanfang setzen; so muss er
nicht erneut freigegeben und wieder zugewiesen werden).
Wird von filesort.cc
,
records.cc
,
sql_handler.cc
,
sql_select.cc
,
sql_table.cc
und
sql_update.cc
aufgerufen.
scan
Keine Rückgabewerte.
Dieses Beispiel stammt von der Speicher-Engine
CSV
:
int ha_tina::rnd_init(bool scan) { DBUG_ENTER("ha_tina::rnd_init"); current_position= next_position= 0; records= 0; chain_ptr= chain; DBUG_RETURN(0); }
Liest die nächste Zeile einer Tabelle und gibt sie an den Server zurück.
virtual int rnd_next
( | buf) ; |
byte * | buf ; |
Dies ist die Methode rnd_next
.
Diese Methode wird für jede Zeile des Tabellenscans aufgerufen.
Am Ende der Datensätze sollten Sie HA_ERR_END_OF_FILE
zurückgeben. Die Zeilendaten werden in den Puffer geladen. Die
Feldstruktur für die Tabelle ist der Schlüssel, um Daten so in
den Puffer zu schreiben, dass der Server sie verstehen kann.
Wird von filesort.cc
,
records.cc
,
sql_handler.cc
,
sql_select.cc
,
sql_table.cc
und
sql_update.cc
aufgerufen.
buf
Keine Rückgabewerte.
Dieses Beispiel stammt von der Speicher-Engine
ARCHIVE
:
int ha_archive::rnd_next(byte *buf) { int rc; DBUG_ENTER("ha_archive::rnd_next"); if (share->crashed) DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE); if (!scan_rows) DBUG_RETURN(HA_ERR_END_OF_FILE); scan_rows--; statistic_increment(table->in_use->status_var.ha_read_rnd_next_count, &LOCK_status); current_position= gztell(archive); rc= get_row(archive, buf); if (rc != HA_ERR_END_OF_FILE) records++; DBUG_RETURN(rc); }
Gibt eine Zeile anhand ihrer Position zurück.
virtual int rnd_pos
( | buf, | |
pos) ; |
byte * | buf ; |
byte * | pos ; |
Dies ist die Methode rnd_pos
.
Diese Methode findet Zeilen, die zuvor anhand ihrer Position gekennzeichnet wurden. Ist nützlich für große Sortieraufgaben.
Ähnlich wie rnd_next
, liefert jedoch eine
Position zurück, um die Zeile zu ermitteln. Die Position hat
den in ref
gespeicherten Typ. Mit
ha_get_ptr(pos,ref_length)
können Sie den
Schlüssel oder den Positionswert abrufen, den Sie beim Aufruf
von position()
gespeichert hatten. Wird von
filesort.cc
, records.cc
,
sql_insert.cc
,
sql_select.cc
und
sql_update.cc
aufgerufen.
buf
pos
Diese Funktion hat keine Rückgabewerte.
Findet die Zeile anhand eines Positionswerts und schreibt sie in den bereitgestellten Puffer.
Wird zu Beginn einer Anweisung für Transaktionszwecke aufgerufen.
virtual int start_stmt
( | thd, | |
lock_type) ; |
THD * | thd ; |
thr_lock_type | lock_type ; |
Dies ist die Methode start_stmt
.
Wenn eine Tabelle gesperrt wird, wird eine Anweisung gestartet,
indem start_stmt
anstelle von
external_lock
aufgerufen wird.
thd
lock_type
Diese Funktion hat keine Rückgabewerte.
Falls nicht bereits eine Transaktion läuft, werden durch diese Funktion die Vorkehrungen für den Beginn einer Transaktion getroffen.
{return 0;}
Dient dem Errichten und Freigeben von Tabellensperren.
virtual THR_LOCK_DATA **
store_lock
( | thd, | |
to, | ||
lock_type) ; |
THD * | thd ; |
THR_LOCK_DATA ** | to ; |
enum thr_lock_type | lock_type ; |
Dies ist die Methode store_lock
.
Der Methode handler::store_lock()
liegt
folgende Idee zugrunde:
Die Anweisung entscheidet darüber, welche Sperren auf einer Tabelle erforderlich sind. Für Updates/Deletes/Inserts bekommen wir WRITE-Sperren und für SELECTs usw. Lesesperren.
Bevor die Sperre dem Tabellensperren-Handler übergeben wird,
ruft mysqld die Funktion
store_lock
mit den erforderlichen Sperren
auf. Diese Funktion kann die Sperrebene modifizieren, etwa den
blockierenden Schreibmodus in einen nichtblockierenden
umwandeln, die Sperre ignorieren (wenn wir die
MySQL-Tabellensperren gar nicht einsetzen möchten) oder Sperren
für viele Tabellen hinzufügen (zum Beispiel bei Verwendung
eines MERGE-Handlers).
Berkeley DB stuft beispielsweise blockierende Tabellensperren vom Typ TL_WRITE zu nichtblockierenden TL_WRITE_ALLOW_WRITE-Sperren herab (ein Zeichen dafür, dass wir zwar Schreiboperationen vornehmen, aber dennoch andere Lese- und Schreibvorgänge zulassen).
store_lock()
wird auch bei der Freigabe von
Sperren aufgerufen. In diesem Fall muss normalerweise nichts
weiter getan werden.
Wenn store_lock()
das Argument
TL_IGNORE
bekommt, so bedeutet dies, dass
MySQL den Handler dasselbe Ausmaß der Sperrung wie beim letzten
Mal speichern lässt.
Wird von lock.cc
durch
get_lock_data()
aufgerufen.
thd
to
lock_type
Keine Rückgabewerte.
Das folgende Beispiel stammt von der Speicher-Engine
ARCHIVE
:
/* Das folgende Beispiel zeigt die Einrichtung von Zeilensperren. */ THR_LOCK_DATA **ha_archive::store_lock(THD *thd, THR_LOCK_DATA **to, enum thr_lock_type lock_type) { if (lock_type == TL_WRITE_DELAYED) delayed_insert= TRUE; else delayed_insert= FALSE; if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) { /* Hier kommen wir zum Kern der Zeilensperre. Wenn TL_UNLOCK gesetzt ist Wenn kein LOCK TABLE oder DISCARD/IMPORT TABLESPACE erfolgt, dann sollen mehrere Schreib-Threads zulässig sein */ if ((lock_type >= TL_WRITE_CONCURRENT_INSERT && lock_type <= TL_WRITE) && !thd->in_lock_tables && !thd->tablespace_op) lock_type = TL_WRITE_ALLOW_WRITE; /* In Anfragen wie INSERT INTO t1 SELECT ... FROM t2 ... würde MySQL die Sperre TL_READ_NO_INSERT für t2 verwenden und dies würde mit der Sperre TL_WRITE_ALLOW_WRITE in Konflikt treten, da alle Inserts in t2 blockiert werden. Also konvertieren wir die Sperre in eine normale Lesesperre, um nebenläufige Einfügungen in t2 zuzulassen. */ if (lock_type == TL_READ_NO_INSERT && !thd->in_lock_tables) lock_type = TL_READ; lock.type=lock_type; } *to++= &lock; return to; }
Im Folgenden sehen Sie die Minimalimplementierung für eine Speicher-Engine, die keine Sperren herabstufen muss:
THR_LOCK_DATA **ha_tina::store_lock(THD *thd, THR_LOCK_DATA **to, enum thr_lock_type lock_type) { /* Achtung: Wenn die Sperre den Typ TL_IGNORE hat, wird lock.type nicht aktualisiert, sondern die vorherige Ebene beibehalten*/ if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) lock.type=lock_type; /* Das Herz der Methode store_lock() und ihr Daseinszweck: das (möglicherweise geänderte) Ausmaß der Sperrung im zugewiesenen Speicher festzuhalten */ *to++= &lock; return to; }
Komplexere Implementierungen finden Sie unter
ha_berkeley::store_lock()
und
ha_myisammrg::store_lock()
.
Ändert den Inhalt einer vorhandenen Zeile.
virtual int update_row
( | old_data, | |
new_data) ; |
const byte * | old_data ; |
byte * | new_data ; |
Dies ist die Methode update_row
.
old_data
speichert den alten und
new_data
den neuen Datensatz der Zeile.
Der Server kann Änderungen anhand einer Reihenfolge vornehmen,
wenn eine ORDER BY
-Klausel verwendet wurde. Eine
aufeinander folgende Ordnung ist nicht garantiert.
Zurzeit kann
new_data
keine aktualisierten auto_increment
- oder
timestamp
-Felder aufnehmen. Dies können Sie
jedoch zum Beispiel folgendermaßen erreichen: if
(table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
table->timestamp_field->set_time(); if (table->next_number_field
&& record == table->record[0])
update_auto_increment();
.
Wird von sql_select.cc
,
sql_acl.cc
, sql_update.cc
und sql_insert.cc
aufgerufen.
old_data
new_data
Keine Rückgabewerte.
(kein Beispiel verfügbar)
{ return HA_ERR_WRONG_COMMAND; }
Fügt einer Tabelle eine neue Zeile hinzu.
virtual int write_row
( | buf) ; |
byte * | buf ; |
Dies ist die Methode write_row
.
write_row()
fügt eine Zeile ein.
Gegenwärtig wird bei Massenladeoperationen kein
extra()
-Hinweis
gegeben.
buf
ist ein Byte-Array mit Daten und hat die Länge
table->s->reclength
Mithilfe der Feldinformationen können Sie die Daten aus dem nativen Byte-Array-Typ extrahieren, zum Beispiel wie in: for (Field **field=table->field ; *field ; field++) { ... }.
BLOBs erfordern eine Sonderbehandlung:
for (ptr= table->s->blob_field, end= ptr + table->s->blob_fields ; ptr != end ; ptr++) { char *data_ptr; uint32 size= ((Field_blob*)table->field[*ptr])->get_length(); ((Field_blob*)table->field[*ptr])->get_ptr(&data_ptr); ... }
In ha_tina.cc
wird gezeigt, wie alle Daten
als Strings extrahiert werden. In
ha_berkeley.cc
finden Sie ein Beispiel, wie
die Daten intakt gespeichert werden, indem man sie für den
Berkeley-eigenen nativen Speichermechanismus "verpackt".
Siehe Hinweis zu update_row()
über
auto_increments
und
timestamps
. Dieser Fall lässt sich auch auf
write_row()
übertragen.
Wird von item_sum.cc
,
item_sum.cc
, sql_acl.cc
,
sql_insert.cc
,
sql_insert.cc
,
sql_select.cc
,
sql_table.cc
, sql_udf.cc
und sql_update.cc
verwendet.
buf
- Ein Byte-Array mit Daten
Keine Rückgabewerte.
(kein Beispiel verfügbar)
{ return HA_ERR_WRONG_COMMAND; }
Inhaltsverzeichnis
MySQL Cluster ist eine hochverfügbare und hochredundante Version
von MySQL, die für verteilte Umgebungen geschaffen wurde. Die
Speicher-Engine NDB Cluster
ermöglicht den
Betrieb mehrerer MySQL Server in einem Cluster. Diese
Speicher-Engine ist in den Binär-Releases von MySQL
5.1 und in den RPMs verfügbar, die mit den meisten
modernen Linux-Distributionen kompatibel sind. (Wenn Sie RPM-Dateien
installieren, müssen Sie darauf achten, sowohl die
mysql-server
- als auch die
mysql-max
-RPMs zu installieren, um MySQL Cluster
zu ermöglichen.)
Gegenwärtig ist MySQL Cluster für Linux, Mac OS X und Solaris verfügbar. (Manche Anwender haben MySQL Cluster auch auf FreeBSD mit Erfolg installieren können, doch dieses System wird von der MySQL AB noch nicht offiziell unterstützt.) Wir arbeiten daran, Cluster auf allen von MySQL unterstützten Betriebssystemen einschließlich Windows lauffähig zu machen, und werden diese Seite aktualisieren, wenn ein neues Betriebssystem hinzukommt.
Dieses Kapitel ändert sich noch laufend; sein Inhalt wird immer wieder an den aktuellen Stand von MySQL Cluster angepasst. Weitere Informationen über MySQL Cluster finden Sie auf der Website von MySQL AB unter http://www.mysql.com/products/cluster/.
Antworten auf häufig gestellte Fragen zum Thema Cluster finden Sie unter Abschnitt 16.10, „MySQL Cluster: FAQ“.
Die Mailingliste zu MySQL Cluster: http://lists.mysql.com/cluster.
Das MySQL Cluster-Forum: http://forums.mysql.com/list.php?25.
Wenn Sie MySQL Cluster noch nicht kennen, ist eventuell der folgende Artikel aus unserer Developer Zone für Sie interessant: How to set up a MySQL Cluster for two servers.
MySQL Cluster ist eine Technologie für das Clustering von speicherresidenten Datenbanken in einem Share-Nothing-System. Mit der Share-Nothing-Architektur kann das System auf sehr preiswerter Hardware laufen und es gibt keine besonderen Anforderungen an Hardware oder Software. Überdies ist kein Single Point of Failure vorhanden, da jede Komponente ihren eigenen Arbeitsspeicher und ihre Festplatte hat.
MySQL Cluster integriert den normalen MySQL Server in eine
speicherresidente geclusterte Speicher-Engine namens
NDB
. In unserer Dokumentation bezeichnet der
Begriff NDB
den Teil des Setups, der für die
jeweilige Speicher-Engine spezifisch ist, während mit
„MySQL Cluster“ die Kombination aus MySQL und der
Speicher-Engine NDB
gemeint ist.
Ein MySQL Cluster besteht aus mehreren Computern, auf denen jeweils eine Anzahl Prozesse laufen, darunter MySQL Server, Datenknoten für NDB Cluster, Management-Server und (möglicherweise) besondere Programme für den Datenzugriff. Im Folgenden wird gezeigt, wie diese Komponenten in einem Cluster zueinander in Beziehung stehen:
Alle diese Programme arbeiten zusammen, um ein MySQL Cluster zu
bilden. Wenn in der Speicher-Engine NDB Cluster
Daten gespeichert werden, werden die Tabellen in den Datenknoten
untergebracht. Auf solche Tabellen können alle anderen MySQL
Server im Cluster direkt zugreifen. Wenn also beispielsweise ein
Gehaltsabrechnungsprogramm Daten in einem Cluster speichert und
eine Anwendung das Gehalt eines Mitarbeiters ändert, können alle
anderen MySQL Server, die diese Daten abfragen, sofort die
Änderung erkennen.
Die in den Datenknoten für MySQL Cluster abgelegten Daten können gespiegelt werden. Der Cluster kann also mit Fehlern in einzelnen Datenknoten gut umgehen; die einzige Auswirkung wäre die, dass einige wenige Transaktionen abbrechen, weil sie ihren Transaktionsstatus verlieren. Da Anwendungen, die Transaktionen vornehmen, auch mit dem Scheitern einer Transaktion umgehen können, dürfte dies kein Problem sein.
Mit der Einführung von MySQL Cluster in die Open-Source-Szene stellt die MySQL AB jedem, der es benötigt, eine hochverfügbare, leistungsfähige und skalierbare geclusterte Datenverwaltung zur Verfügung.
NDB ist eine hochverfügbare speicherresidente Speicher-Engine mit Fähigkeiten für die Datenpersistenz.
Die Speicher-Engine NDB kann mit mehreren Optionen für Ausfallsicherung und Lastverteilung konfiguriert werden, doch am einfachsten ist es, das System mit der Speicher-Engine auf der Cluster-Ebene zu starten. Die Speicher-Engine NDB von MySQL Cluster enthält vollständige Daten, deren Abhängigkeiten sich lediglich auf andere Daten in demselben Cluster beziehen.
Im Folgenden erfahren Sie, wie man einen MySQL Cluster einrichtet, der aus der Speicher-Engine NDB und einigen MySQL Servern besteht.
Der Cluster-Teil von MySQL Cluster ist gegenwärtig unabhängig von den MySQL Servern konfiguriert. In MySQL Cluster wird jeder Teil des Clusters als ein Knoten betrachtet.
Hinweis: In vielen Zusammenhängen wird der Begriff „Knoten“ für einen Computer verwendet, doch im Zusammenhang mit MySQL Cluster ist damit ein Prozess gemeint. Auf einem einzigen Computer, dem so genannten Cluster-Host, können also beliebig viele Knoten existieren.
Es gibt drei Arten von Cluster-Knoten und eine Minimalkonfiguration von MySQL besteht aus drei Knoten, je einem von jeder Art:
dem Management-Knoten (MGM-Knoten): Dieser verwaltet andere Knoten im MySQL Cluster, indem er zum Beispiel Konfigurationsdaten zur Verfügung stellt, Knoten startet und anhält, eine Sicherung ausführt usw. Da dieser Knotentyp die Konfiguration der anderen Knoten managt, sollten Knoten dieses Typs immer als Erste, vor allen anderen Knoten, gestartet werden. Ein MGM-Knoten wird mit dem Befehl ndb_mgmd gestartet.
dem Datenknoten: Dies ist der Knotentyp, der die Daten des Clusters speichert. Die Anzahl der Datenknoten beträgt Replikas mal Anzahl Fragmente. Wenn Sie beispielsweise zwei Replikas mit je zwei Fragmenten haben, benötigen Sie vier Datenknoten. Noch mehr Replikas sind nicht notwendig. Ein Datenknoten wird mit dem Befehl ndbd gestartet.
dem SQL-Knoten: Mit diesem
Knotentyp wird auf die Cluster-Daten zugegriffen. In MySQL
Cluster ist ein Client-Knoten ein traditioneller MySQL Server,
der die Speicher-Engine NDB Cluster
nutzt.
Ein SQL-Knoten wird normalerweise mit dem Befehl
mysqld --ndbcluster gestartet, oder auch
mit mysqld und der Option
ndbcluster
in der
my.cnf
-Datei.
Eine kurze Einführung in die Beziehungen zwischen Knoten, Knotengruppen, Replikas und Partitionen in MySQL Cluster finden Sie in Abschnitt 16.2.1, „MySQL Cluster: Knoten, Knotengruppen, Repliken und Partitionen“.
Um einen Cluster zu konfigurieren, müssen Sie jeden Einzelnen seiner Knoten konfigurieren und individuelle Kommunikationsverbindungen zwischen den Knoten einrichten. Der Entwurf von MySQL Cluster zielt gegenwärtig darauf ab, dass die Speicherknoten alle denselben Bedarf an Prozessorleistung, Speicherplatz und Bandbreite haben. Um überdies nur an einer einzigen Stelle konfigurieren zu müssen, liegen sämtliche Konfigurationen für den gesamten Cluster in nur einer Konfigurationsdatei.
Der Management-Server (MGM-Knoten) verwaltet die Konfigurationsdatei und das Log für den Cluster. Da sich jeder Knoten im Cluster seine Konfigurationsdaten vom Management-Server holt, muss der Knoten feststellen können, wo der Management-Server zu finden ist. Wenn interessante Ereignisse in den Datenknoten eintreten, übermitteln die Knoten Informationen über diese Ereignisse an den Management-Server, der diese Daten dann an das Cluster-Log überträgt.
Darüber hinaus können beliebig viele Cluster-Clientprozesse oder -anwendungen ablaufen. Von diesen gibt es zwei Arten:
Standard-MySQL-Clients: Diese unterscheiden sich von MySQL Cluster nur insofern, als sie eben nicht geclustert sind. Also können Sie auch von vorhandenen MySQL-Anwendungen, die in PHP, Perl, C, C++, Java, Python, Ruby usw. geschrieben wurden, auf MySQL Cluster zugreifen.
Management-Clients: Diese Clients verbinden sich mit dem Management-Server und kennen Befehle, um Knoten elegant zu starten oder abzubrechen, das Message-Tracing ein- und auszuschalten (nur in den Debugversionen), Knotenversionen und -status anzuzeigen, Sicherungen zu starten oder anzuhalten usw.
In diesem Abschnitt wird beschrieben, wie MySQL Cluster mehrfach vorhandene Daten für die Speicherung aufteilt.
Die Konzepte, die im Folgenden mit kurzen Definitionen aufgelistet werden, sind für das Verständnis dieses Themas unerlässlich:
(Daten-)Knoten: Ein ndbd-Prozess, der eine Replik speichert, also eine Kopie der Partition (siehe unten), die der Knotengruppe, zu welcher dieser Knoten gehört, zugewiesen wurde.
Normalerweise liegt jeder Datenknoten auf einem anderen Computer. Es ist jedoch möglich, mehrere Datenknoten auf einem einzigen Computer unterzubringen, wenn dieser über mehrere Prozessoren verfügt. In solchen Fällen kann pro physikalische CPU eine ndbd-Instanz laufen. (Beachten Sie, dass ein Prozessor mit mehreren Zentraleinheiten immer noch ein einzelner Prozessor ist.)
Die Begriffe „Knoten“ und „Datenknoten“ werden im Zusammenhang mit ndbd-Prozessen synonym verwendet. Wenn Management-Knoten (ndb_mgmd -Prozesse) und SQL-Knoten (mysqld-Prozesse) gemeint sind, wird dies im Text ausdrücklich gesagt.
Knotengruppe: Eine Knotengruppe besteht aus einem oder mehreren Knoten und speichert eine Partition oder eine Menge von Replikas (siehe nächster Eintrag).
Hinweis: Gegenwärtig müssen alle Gruppen in einem Cluster gleich viele Knoten haben.
Partition: Ein Teil der in einem Cluster gespeicherten Daten. Es gibt so viele Cluster-Partitionen, wie Knotengruppen im Cluster vorliegen, und jede Knotengruppe ist dafür verantwortlich, mindestens eine Kopie der ihr zugewiesenen Partition (also mindestens eine Replik) aufzubewahren, die dem Cluster zur Verfügung steht.
Replik: Eine Kopie einer Cluster-Partition. Jeder Knoten in einer Knotengruppe speichert eine Replik. Wird gelegentlich auch als Partitionsreplik bezeichnet.
Das folgende Diagramm zeigt einen MySQL Cluster mit vier Datenknoten in zwei Knotengruppen zu je zwei Knoten. Beachten Sie, dass hier nur die Datenknoten gezeigt werden, obwohl ein funktionierender Cluster einen ndb_mgm-Prozess für das Cluster-Management und mindestens einen SQL-Knoten für den Zugriff auf die im Cluster gespeicherten Daten benötigt.
Die in diesem Cluster gespeicherten Daten sind auf vier Partitionen verteilt, die mit 0, 1, 2 und 3 nummeriert sind. Jede Partition wird – in mehrfachen Kopien – in derselben Knotengruppe gespeichert. Partitionen werden auf unterschiedlichen Knotengruppen gespeichert:
Partition 0 wird in Knotengruppe 0 gespeichert; eine primäre Replik (oder primäre Kopie) wird auf Knoten 1 gespeichert, und eine Backup-Replik (Backup-Kopie der Partition) auf Knoten 2.
Partition 1 wird auf der anderen Knotengruppe gespeichert (Knotengruppe 1); die primäre Replik dieser Partition ist auf Knoten 3 und die Backup-Repli befindet sich auf Knoten 4.
Partition 2 wird auf Knotengruppe 0 gespeichert. Die Platzierung ihrer beiden Repliken ist jedoch genau umgekehrt wie bei Partition 0: Bei Partition 2 wird die primäre Replik auf Knoten 2 und die Backup-Replik auf Knoten 1 gespeichert.
Partition 3 wird auf Knotengruppe 1 gespeichert, und die Platzierung ihrer beiden Repliken ist umgekehrt wie bei Partition 1. Mit anderen Worten befindet sich ihre primäre Replik auf Knoten 4 und die Backup-Replik auf Knoten 3.
Für den Dauerbetrieb eines MySQL Clusters bedeutet dies: Solange jede Knotengruppe des Clusters mindestens einen funktionierenden Knoten hat, ist der Cluster im Besitz einer vollständigen Kopie sämtlicher Daten und bleibt funktionstüchtig. Dies wird im nächsten Diagramm veranschaulicht.
In diesem Beispiel, in dem der Cluster aus zwei Knotengruppen mit je zwei Knoten besteht, genügt eine beliebige Kombination mindestens eines Knotens aus Gruppe A und mindestens eines weiteren Knotens aus Gruppe B, um den Cluster „am Leben“ zu halten (wie es die Pfeile im Diagramm zeigen). Wenn jedoch beide Knoten einer Knotengruppe versagen, genügen die verbleibenden beiden Knoten nicht, um den Betrieb aufrechtzuerhalten (dies zeigen die mit X markierten Pfeile). In beiden Fällen hat der Cluster eine vollständige Partition verloren und kann somit nicht mehr auf alle Cluster-Daten Zugriff geben.
Dieser Abschnitt ist eine „Anleitung“, welche in Grundzügen beschreibt, wie man einen MySQL Cluster plant, installiert, konfiguriert und ausführt. Die Beispiele in Abschnitt 16.4, „MySQL Cluster: Konfiguration“, bieten zwar ausführlichere Informationen über verschiedene Cluster-Optionen und Konfigurationen, aber auch mit dem hier gezeigten Verfahren erhalten Sie einen brauchbaren MySQL Cluster, der ein Minimum an Verfügbarkeit und Datensicherheit bietet.
Dieser Abschnitt behandelt Hardware- und Softwarevoraussetzungen, Netzwerkfragen, die Installation eines MySQL Clusters, die Konfiguration, das Starten, Anhalten und Neustarten eines Clusters, das Laden einer Beispieldatenbank sowie die Ausführung von Anfragen.
Grundvoraussetzungen
Diese Anleitung setzt Folgendes voraus:
Der Cluster hat vier Knoten, von denen jeder auf einem separaten Host residiert und eine feste Netzwerkadresse in einem typischen Ethernet besitzt, wie es hier gezeigt wird:
Knoten | IP-Adresse |
Management(MGM)-Knoten | 192.168.0.10 |
MySQL Server(SQL)-Knoten | 192.168.0.20 |
Datenknoten (NDBD-Knoten) "A" | 192.168.0.30 |
Datenknoten (NDBD-Knoten) "B" | 192.168.0.40 |
Dies wird möglicherweise im nachfolgenden Diagramm klarer:
Hinweis: Im Interesse der
Einfachheit (und Zuverlässigkeit) verwendet diese Anleitung
nur numerische IP-Adressen. Wenn jedoch in Ihrem Netzwerk
DNS-Namensauflösung verfügbar ist, können Sie anstelle von
IP-Adressen in der Cluster-Konfiguration auch Hostnamen
verwenden. Alternativ können Sie in der Datei
/etc/hosts
oder der in Ihrem
Betriebssystem verwendeten Entsprechung eine andere
Möglichkeit für das Host-Lookup einrichten (soweit
verfügbar).
Jeder Host in unserem Szenario ist ein Intel-PC, auf dem eine normale generische Linux-Distribution in einer Standardkonfiguration auf der Festplatte installiert ist und keine unnötigen Dienste laufen. Das Kernbetriebssystem mit seinen Standard-TCP/IP-Netzwerkfähigkeiten müsste ausreichen. Der Einfachheit halber setzen wir des Weiteren voraus, dass die Dateisysteme auf allen Hosts gleich eingerichtet sind. Anderenfalls müssen Sie diese Anleitungen entsprechend anpassen.
Auf jedem Computer sind Standard-Ethernet-Karten mit 100 Mbps oder 1 Gigabit samt Treibern installiert und alle vier Hosts sind durch eine Standardvorrichtung für Ethernet-Netzwerke, wie beispielsweise einen Switch, miteinander verbunden. (Alle Computer sollten Netzwerkkarten mit demselben Datendurchsatz verwenden, d. h., die vier Computer haben entweder 100-Mbps-Karten oder 1-Gbps-Karten.) MySQL Cluster funktioniert zwar auch in einem 100-Mbps-Netzwerk, aber ein 1-Gigabit-Ethernet bietet deutlich mehr Leistung.
Beachten Sie, dass MySQL Cluster nicht für den Einsatz in einem Netzwerk mit weniger als 100 Mbps Datendurchsatz gedacht ist. Aus diesem und anderen Gründen werden Sie keinen Erfolg haben, wenn Sie versuchen, einen MySQL Cluster in einem öffentlichen Netzwerk wie dem Internet zu betreiben. Das ist auch nicht empfehlenswert.
Für unsere Beispieldaten verwenden wir die Datenbank
world
, die Sie von der Website der MySQL AB
herunterladen können. Da diese Datenbank relativ wenig
Speicherplatz belegt, gehen wir davon aus, dass jeder Computer
256 Mbyte RAM besitzt. Dies dürfte ausreichen, um das
Betriebssystem auszuführen, den NDB-Prozess zu hosten und die
Datenbank (die Datenknoten) zu speichern.
Auch wenn wir uns in dieser Anleitung auf ein Linux-Betriebssystem beziehen, lassen sich die hier geschilderten Instruktionen und Verfahren auch auf Solaris oder Mac OS X leicht übertragen. Außerdem setzen wir voraus, dass Sie bereits wissen, wie man eine Minimalinstallation durchführt und das Betriebssystem für den Netzwerkbetrieb konfiguriert, oder dass Sie sich in diesen Fragen notfalls an anderer Stelle kundig machen können.
Im nächsten Abschnitt werden Hardware-, Software- und Netzwerkvoraussetzungen für MySQL Cluster etwas eingehender behandelt. (Siehe Abschnitt 16.3.1, „Hardware, Software und Netzwerk“.)
Eine Stärke von MySQL Cluster besteht darin, dass das System auf handelsüblicher Hardware läuft und in dieser Hinsicht keine besonderen Ansprüche stellt – abgesehen von einem großen Arbeitsspeicher, da im Betrieb sämtliche Daten dort gespeichert werden. (Dies wird sich allerdings noch ändern, da in einem künftigen Release von MySQL Cluster eine Datenspeicherung auf Festplatte angestrebt wird.) Natürlich wird die Leistung umso besser, je mehr und je schnellere CPUs eingesetzt werden. Der Speicherbedarf für Cluster-Prozesse ist relativ gering.
Auch an die Software stellt Cluster eher geringe Anforderungen.
Die Host-Betriebssysteme benötigen keine ungewöhnlichen
Module, Dienste, Anwendungen oder Konfigurationen, um MySQL
Cluster zu unterstützen. Für Mac OS X oder Solaris reicht
sogar die Standardinstallation völlig aus. Für Linux dürfte
gleichfalls die Standardinstallation hinreichend sein. Die
Anforderungen an MySQL-Software lassen sich ebenfalls leicht
erfüllen: Sie benötigen lediglich einen Produktions-Release
von MySQL-max 5.1. Um Cluster-Unterstützung zu
bekommen, müssen Sie die
-max
-Version von
MySQL einsetzen, brauchen MySQL jedoch nicht selbst zu
kompilieren. In dieser Anleitung setzen wir voraus, dass Sie die
passende -max
-Binärversion zu Ihrem
Betriebssystem Linux, Solaris oder Mac OS X verwenden, die unter
den Softwaredownloads von MySQL unter
http://dev.mysql.com/downloads/ erhältlich ist.
Für die Kommunikation zwischen den Knoten unterstützt Cluster TCP/IP-Netzwerke in einer beliebigen Standardtopologie, wofür jeder Host als Minimum eine Standard-Ethernet-Karte mit 100 Mbps plus Switch, Hub oder Router benötigt, um die Netzwerkkonnektivität für den Cluster als Ganzes herzustellen. Wir raten Ihnen dringend, MySQL Cluster in einem eigenen Subnetz zu betreiben, auf das keine Computer zugreifen, die nicht an dem Cluster partizipieren. Dafür gibt es folgende Gründe:
Sicherheit: Die Kommunikation zwischen Cluster-Knoten ist in keiner Weise verschlüsselt oder abgeschirmt. Die einzige Möglichkeit, Datenübertragungen in einem MySQL Cluster zu schützen, besteht darin, den Cluster in einem geschützten Netzwerk auszuführen. Wenn Sie MySQL Cluster für Webanwendungen nutzen möchten, muss der Cluster unbedingt hinter Ihrer Firewall sitzen und nicht etwa in der demilitarisierten Zone Ihres Netzwerks (DMZ) oder an einer anderen Stelle.
Effizienz: Wenn Sie einen MySQL Cluster in einem privaten oder geschützten Netzwerk einrichten, kann er über die Bandbreite zwischen den Cluster-Hosts alleine verfügen. Indem Sie für Ihren MySQL Cluster einen getrennten Switch verwenden, schützen Sie die Cluster-Daten vor unbefugtem Zugriff und gewährleisten überdies, dass die Cluster-Knoten von den Interferenzen durch Datenübertragungen zwischen anderen Computern im Netzwerk verschont bleiben. Die Zuverlässigkeit können Sie durch doppelte Switches und doppelte Karten erhöhen; so scheidet das Netzwerk als Single Point of Failure aus. Viele Gerätetreiber unterstützen eine Ausfallsicherung für solche Kommunikationsverbindungen.
Es ist auch möglich, das sehr schnelle Scalable Coherent Interface (SCI) mit MySQL Cluster zu kombinieren, aber obligatorisch ist es nicht. Unter Abschnitt 16.7, „Verwendung von Hochgeschwindigkeits-Interconnects mit MySQL Cluster“, erfahren Sie mehr über dieses Protokoll und seine Verwendung mit MySQL Cluster.
Auf jedem Hostcomputer für MySQL Cluster, der Speicher- oder SQL-Knoten ausführt, muss MySQL als -max-Binärversion installiert sein. Für Management-Knoten muss zwar nicht die Binärversion von MySQL Server installiert werden, wohl aber die Binärversionen von MGM Server Daemon und vom Client (ndb_mgmd und ndb_mgm). In diesem Abschnitt erfahren Sie alles Notwendige, um für jede Art von Cluster-Knoten die richtige Binärversion zu installieren.
MySQL AB bietet vorkompilierte Binärversionen, die Cluster
unterstützen und die Sie generell nicht selbst kompilieren
müssen. Der erste Schritt zur Installation jedes Cluster-Hosts
besteht also darin, die Datei
mysql-max-5.1.5-alpha-pc-linux-gnu-i686.tar.gz
aus dem
MySQL-Downloadbereich
herunterzuladen. Wir gehen davon aus, dass Sie diese Datei in
das Verzeichnis /var/tmp
jedes Computers
legen. (Sollten Sie doch eine maßgeschneiderte Binärversion
benötigen, schauen Sie bitte unter
Abschnitt 2.8.3, „Installation vom Entwicklungs-Source-Tree“, nach.)
RPMs gibt es auch für 32-Bit- und 64-Bit-Linux-Systeme. Die von
den RPMs installierten -max
-Binaries
unterstützen die Speicher-Engine NDBCluster
.
Wenn Sie diese anstelle der Binärdateien einsetzen möchten,
müssen Sie allerdings beide Packages -
-server
und -max
- auf
allen Computern installieren, die Cluster-Knoten hosten sollen.
(Unter Abschnitt 2.4, „MySQL unter Linux installieren“, erfahren Sie mehr darüber,
wie man MySQL mithilfe der RPMs installiert.) Nach der
Installation von RPM müssen Sie noch den Cluster konfigurieren,
wie in Abschnitt 16.3.3, „Konfiguration im Mehrcomputerbetrieb“, beschrieben.
Hinweis: Nach Abschluss der Installation dürfen Sie noch nicht die Binaries starten. Wie Sie das tun, zeigen wir Ihnen, nachdem sämtliche Knoten konfiguriert sind.
Speicherung und Installation des SQL-Knotens
Auf allen drei Computern, die Speicher- oder SQL-Knoten hosten
sollen, müssen Sie als root
-User folgende
Schritte ausführen:
Sie müssen in den Dateien /etc/passwd
und /etc/group
nachschauen (oder die
Tools nutzen, die Ihr Betriebssystem zur Verwaltung von
Benutzern und Gruppen zur Verfügung stellt), um
festzustellen, ob auf dem System bereits eine
mysql
-Gruppe und ein
mysql
-Benutzer vorhanden ist. Manche
Betriebssystem-Distributionen legen diese bei ihrer
Installation bereits an. Wenn sie noch nicht vorhanden sind,
legen Sie eine neue mysql
-Benutzergruppe
an und fügen dieser dann einen
mysql
-Benutzer hinzu:
shell>groupadd mysql
shell>useradd -g mysql mysql
Die Syntax für useradd und groupadd kann auf verschiedenen Unix-Versionen etwas abweichen. Es ist auch möglich, dass die Befehle etwas andere Namen haben, wie etwa adduser und addgroup.
Dann wechseln Sie in das Verzeichnis mit der heruntergeladenen Datei, packen das Archiv aus und erzeugen einen Symlink auf die Executable mysql-max. Beachten Sie, dass die tatsächlichen Datei- und Verzeichnisnamen je nach MySQL-Version unterschiedlich sind.
shell>cd /var/tmp
shell>tar -xzvf -C /usr/local/bin mysql-max-5.1.5-alpha-pc-linux-gnu-i686.tar.gz
shell>ln -s /usr/local/bin/mysql-max-5.1.5-alpha-pc-linux-gnu-i686 mysql
Nun gehen Sie in das Verzeichnis mysql
und führen das mitgelieferte Skript aus, das die
Systemdatenbanken anlegt:
shell>cd mysql
shell>scripts/mysql_install_db --user=mysql
Nun stellen Sie die Berechtigungen für den MySQL Server und die Datenverzeichnisse ein:
shell>chown -R root .
shell>chown -R mysql data
shell>chgrp -R mysql .
Beachten Sie, dass das Datenverzeichnis auf jedem Computer,
auf dem ein Datenknoten residiert, unter
/usr/local/mysql/data
liegt. Dieses
Wissen werden wir nutzen, wenn wir den Management-Knoten
konfigurieren. (Siehe Abschnitt 16.3.3, „Konfiguration im Mehrcomputerbetrieb“.)
Kopieren Sie das MySQL-Startskript in das passende Verzeichnis, sorgen Sie dafür, dass es ausführbar ist, und stellen Sie ein, dass es beim Hochfahren des Betriebssystems läuft:
shell>cp support-files/mysql.server /etc/rc.d/init.d/
shell>chmod +x /etc/rc.d/init.d/mysql.server
shell>chkconfig --add mysql.server
Hier legen wir die Verknüpfungen zu den Startskripten mit dem Befehl chkconfig von Red Hat an. Bitte wählen Sie das für Ihr Betriebssystem jeweils passende Mittel aus, etwa update-rc.d für Debian.
Die obigen Schritte müssen auf jedem Computer, der einen Speicher- oder SQL-Knoten hostet, separat ausgeführt werden.
Installation des Management-Knotens
Um den Management(MGM)-Knoten installieren zu können, muss die
mysqld-Binary nicht installiert sein. Nur die
Binärversionen für den MGM-Server und -Client sind
erforderlich. Diese finden Sie im heruntergeladenen
-max
-Archiv. Wir gehen wieder davon aus, dass
Sie die Datei in das Verzeichnis /var/tmp
gespeichert haben.
Die folgenden Schritte müssen Sie als
root
-User Ihres Systems ausführen (das
heißt nach Ausführung von sudo, su
root oder dem für Ihr System passenden Befehl zur
vorübergehenden Einrichtung von Administratorrechten). Dann
installieren Sie auf dem Host des Cluster-Management-Knotens
ndb_mgmd und ndb_mgm wie
folgt:
Gehen Sie in das Verzeichnis /var/tmp
und extrahieren Sie ndb_mgm und
ndb_mgmd aus dem Archiv in ein passendes
Verzeichnis wie beispielsweise
/usr/local/bin
:
shell>cd /var/tmp
shell>tar -zxvf mysql-max-5.1.5-alpha-pc-linux-gnu-i686.tar.gz \
/usr/local/bin '*/bin/ndb_mgm*'
Gehen Sie in das Verzeichnis, in das Sie die Dateien entpackt haben, und machen Sie beide ausführbar:
shell>cd /usr/local/bin
shell>chmod +x ndb_mgm*
In Abschnitt 16.3.3, „Konfiguration im Mehrcomputerbetrieb“, werden wir Konfigurationsdateien für alle Knoten unseres Beispiel-Clusters erstellen und schreiben.
Für unseren MySQL Cluster mit vier Knoten und vier Hosts müssen wir vier Konfigurationsdateien schreiben, je eine pro Knoten/Host.
Jeder Datenknoten oder SQL-Knoten benötigt eine
my.cnf
-Datei, die zwei Informationen
liefert: einen
connectstring, der dem
Knoten sagt, wo er den MGM-Knoten findet, und eine Leitung,
die den MySQL Server auf diesem Host (dem Computer mit dem
Datenknoten) anweist, im NDB-Modus zu laufen.
Mehr zum Thema Verbindungs-Strings erfahren Sie unter
Abschnitt 16.4.4.2, „MySQL Cluster: connectstring
“.
Der Management-Knoten benötigt eine
config.ini
-Datei, die ihm sagt, wie
viele Replikas er pflegen soll, wie viel Speicher er für
die Daten und Indizes auf jedem Datenknoten reservieren
soll, wo er die Datenknoten suchen soll, wo er die Daten
für jeden Datenknoten auf Platte speichern soll und wo er
SQL-Knoten finden kann.
Konfiguration der Speicher- und SQL-Knoten
Die für die Datenknoten erforderliche
my.cnf
-Datei ist ganz einfach. Diese
Konfigurationsdatei sollte im Verzeichnis
/etc
liegen und kann mit jedem Editor
bearbeitet werden. (Wenn die Datei noch nicht existiert, legen
Sie sie bitte an.) Zum Beispiel:
shell> vi /etc/my.cnf
Hier legen wir die Datei zwar mit vi an, aber Sie können auch jeden anderen Editor benutzen.
Für jeden Daten- und SQL-Knoten in unserem Beispiel-Cluster
sollte die my.cnf
-Datei folgendermaßen
aussehen:
# Optionen für den mysqld-Prozess: [MYSQLD] ndbcluster # NDB-Engine ausführen ndb-connectstring=192.168.0.10 # Speicherort des MGM-Knotens # Optionen für den ndbd-Prozess: [MYSQL_CLUSTER] ndb-connectstring=192.168.0.10 # Speicherort des MGM-Knotens
Wenn Sie diese Daten eingegeben haben, speichern Sie die Datei und schließen den Editor. Dies tun Sie für die Hosts der Datenknoten „A“ und „B“ sowie für den Host des SQL-Knotens.
Konfiguration des Management-Knotens
Der erste Schritt zur Konfiguration des MGM-Knotens besteht
darin, das Verzeichnis für die Konfigurationsdatei und dann die
Datei selbst anzulegen. Zum Beispiel (immer als
root
-User):
shell>mkdir /var/lib/mysql-cluster
shell>cd /var/lib/mysql-cluster
shell>vi config.ini
Für unseren Beispiel-Cluster sieht die
config.ini
-Datei folgendermaßen aus:
# Optionen, die ndbd-Prozesse auf allen Datenknoten betreffen: [NDBD DEFAULT] NoOfReplicas=2 # Anzahl der Replikas DataMemory=80M # So viel Speicher wird für Datenknoten reserviert IndexMemory=18M # So viel Speicher wird für Indizes reserviert # Für DataMemory und IndexMemory haben wir die Standardwerte # eingesetzt. Da die "world"-Datenbank nur # circa 500 Kbyte belegt, dürfte dies für unseren Beispiel-Cluster # mehr als ausreichend sein. # TCP/IP options: [TCP DEFAULT] portnumber=2202 # Dies ist der Standardwert. Sie können jedoch # jeden Port benutzen, der auf allen Hosts im Cluster frei ist. # Hinweis: Ab MySQL 5.0 ist es ratsam, keine # Portnummer anzugeben, sondern einfach # die Verwendung des Standardwerts zu gestatten # Optionen für den Management-Prozess: [NDB_MGMD] hostname=192.168.0.10 # Hostname oder IP-Adresse des MGM-Knotens datadir=/var/lib/mysql-cluster # Verzeichnis der Logdateien für MGM-Knoten # Optionen für Datenknoten "A": [NDBD] # (ein [NDBD]-Abschnitt pro Datenknoten) hostname=192.168.0.30 # Hostname oder IP-Adresse datadir=/usr/local/mysql/data # Verzeichnis für die Datendateien dieses Knotens # Optionen für Datenknoten "B": [NDBD] hostname=192.168.0.40 # Hostname oder IP-Adresse datadir=/usr/local/mysql/data # Verzeichnis für die Datendateien dieses Knotens # Optionen für SQL-knoten: [MYSQLD] hostname=192.168.0.20 # Hostname oder IP-Adresse # (Weitere mysqld-Verbindungen können # für diverse Zwecke, z. B. Ausführung von # ndb_restore, für diesen Knoten angegeben werden.)
(Hinweis: Die Datenbank
world
kann von http://dev.mysql.com/doc/
heruntergeladen werden, wo sie unter „Examples.“
aufgeführt ist.)
Wenn alle Konfigurationsdateien angelegt und diese minimalen Optionen angegeben sind, können Sie den Cluster starten und sich vergewissern, dass alle Prozesse laufen. Wie das geht, erfahren Sie in Abschnitt 16.3.4, „Erster Start“.
Detailliertere Informationen über die verfügbaren Konfigurationsparameter von MySQL Cluster und ihre Verwendung finden Sie unter Abschnitt 16.4.4, „Konfigurationsdatei“, und Abschnitt 16.4, „MySQL Cluster: Konfiguration“. Wie Sie MySQL Cluster für die Erstellung von Datensicherungen konfigurieren, erfahren Sie unter Abschnitt 16.6.5.4, „Konfiguration für Cluster-Backup“.
Hinweis: Der Standardport für Cluster-Management-Knoten ist 1186 und der Standardport für Datenknoten ist 2202. Seit MySQL 5.0.3 wurde diese Einschränkung aufgehoben und der Cluster weist automatisch Ports für Datenknoten aus dem Vorrat der freien Ports zu.
Den Cluster nach erfolgter Konfiguration zu starten ist nicht schwer. Jeder Cluster-Knoten-Prozess muss separat und auf dem Knoten-Host gestartet werden. Zwar können die Knoten in beliebiger Reihenfolge gestartet werden, aber es empfiehlt sich, als Erstes den Management-Knoten, dann die Speicherknoten und zum Schluss die SQL-Knoten zu starten:
Auf dem Management-Host setzen Sie folgenden Befehl in der System-Shell ab, um den MGM-Knoten-Prozess zu starten:
shell> ndb_mgmd -f /var/lib/mysql-cluster/config.ini
Beachten Sie, dass Sie ndb_mgmd mithilfe
der Option -f
oder
--config-file
mitteilen müssen, wo er
seine Konfigurationsdatei finden kann. (Einzelheiten siehe
Abschnitt 16.5.3, „ndb_mgmd, der Management-Server-Prozess“.)
Auf jedem Datenknoten-Host geben Sie folgenden Befehl, um den ndbd-Prozess zum ersten Mal zu starten:
shell> ndbd --initial
Es ist äußerst wichtig, dass der Parameter
--initial
nur beim
ersten Start von ndbd oder bei einem
Neustart nach einer Sicherungs-/Wiederherstellungsoperation
oder einer Konfigurationsänderung verwendet wird. Denn die
Option --initial
veranlasst den Knoten,
alle für die Wiederherstellung erforderlichen Dateien zu
löschen, die von vorherigen
ndbd-Instanzen angelegt wurden,
einschließlich der Dateien des Redo-Logs.
Wenn Sie MySQL auf dem Cluster-Host, wo der SQL-Knoten
residieren soll, von RPM-Dateien installiert haben, können
(und sollten) Sie das in /etc/init.d
installierte Startskript nutzen, um den MySQL Server-Prozess
auf dem SQL-Knoten zu starten. Beachten Sie, dass Sie die
-max
-Server-RPM zusätzlich
zur Standardserver-RPM installieren müssen, um
die Binärversion von -max
-Server
ausführen zu können.
Wenn alles geklappt hat und der Cluster korrekt eingerichtet wurde, sollte er nun funktionsbereit sein. Dies können Sie testen, indem Sie den Management-Knoten-Client ndb_mgm aufrufen. Die Ausgabe sollte ungefähr dem Folgenden entsprechen, wobei jedoch je nach der verwendeten MySQL-Version kleinere Abweichungen möglich sind:
shell>ndb_mgm
-- NDB Cluster -- Management Client -- ndb_mgm>SHOW
Connected to Management Server at: localhost:1186 Cluster Configuration --------------------- [ndbd(NDB)] 2 node(s) id=2 @192.168.0.30 (Version: 5.1.5-alpha, Nodegroup: 0, Master) id=3 @192.168.0.40 (Version: 5.1.5-alpha, Nodegroup: 0) [ndb_mgmd(MGM)] 1 node(s) id=1 @192.168.0.10 (Version: 5.1.5-alpha) [mysqld(SQL)] 1 node(s) id=4 (Version: 5.1.5-alpha)
Hinweis: Wenn Sie eine ältere
Version von MySQL verwenden, wird der SQL-Knoten möglicherweise
als [mysqld(API)]
bezeichnet. Das ist eine
ältere Lesart, die mittlerweile abgeschafft wurde.
Nun können Sie im MySQL Cluster mit Datenbanken, Tabellen und Daten arbeiten. Unter Abschnitt 16.3.5, „Beispieldaten einladen und Abfragen ausführen“, finden Sie eine kurze Beschreibung.
Der Umgang mit Daten im MySQL Cluster ist ganz ähnlich wie in einer MySQL-Konfiguration ohne Cluster. Nur auf zwei Dinge muss man achten:
Damit eine Tabelle im Cluster repliziert wird, muss die
Speicher-Engine NDB Cluster
mit der
Option ENGINE=NDB
oder der Tabellenoption
ENGINE=NDBCLUSTER
eingeschaltet sein. Dies
können Sie tun, wenn Sie die Tabelle anlegen:
CREATE TABLE tbl_name
( ... ) ENGINE=NDBCLUSTER;
Alternativ können Sie eine bereits vorhandene Tabelle, die
eine andere Speicher-Engine verwendet, mit ALTER
TABLE
auf NDB Cluster
umstellen:
ALTER TABLE tbl_name
ENGINE=NDBCLUSTER;
Jede NDB
-Tabelle
muss einen Primärschlüssel haben.
Wenn der Benutzer beim Anlegen der Tabelle keinen definiert,
wird von der Speicher-Engine NDB Cluster
automatisch ein verborgener Primärschlüssel generiert.
(Hinweis: Dieser verborgene
Schlüssel belegt Platz wie jeder andere Tabellenindex auch.
Nicht selten treten Speicherplatzprobleme auf, wenn diese
automatisch angelegten Indizes untergebracht werden
müssen.)
Wenn Sie aus der Ausgabe von mysqldump
Tabellen aus einer vorhandenen Datenbank importieren, können
Sie das SQL-Skript mit einem Editor öffnen und die Option
ENGINE
für alle Anweisungen einstellen, in
denen Tabellen angelegt werden, oder eine eventuell vorhandene
ENGINE
- (oder TYPE
-)Option
ersetzen. Nehmen wir an, Sie haben die Beispieldatenbank
world
auf einem anderen MySQL Server liegen,
der MySQL Cluster nicht unterstützt, und Sie möchten die
Tabelle City
exportieren:
shell> mysqldump --add-drop-table world City > city_table.sql
Die resultierende city_table.sql
-Datei
enthält die folgende Anweisung zur Erzeugung einer Tabelle (und
die notwendigen INSERT
-Anweisungen, um die
Tabellendaten zu importieren):
DROP TABLE IF EXISTS `City`;
CREATE TABLE `City` (
`ID` int(11) NOT NULL auto_increment,
`Name` char(35) NOT NULL default '',
`CountryCode` char(3) NOT NULL default '',
`District` char(20) NOT NULL default '',
`Population` int(11) NOT NULL default '0',
PRIMARY KEY (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO `City` VALUES (1,'Kabul','AFG','Kabol',1780000);
INSERT INTO `City` VALUES (2,'Qandahar','AFG','Qandahar',237500);
INSERT INTO `City` VALUES (3,'Herat','AFG','Herat',186800);
(restliche INSERT-Anweisungen ausgelassen)
Sie müssen gewährleisten, dass MySQL die Speicher-Engine NDB
für diese Tabelle verwendet. Dazu ändern Sie die Tabellendefinition
vor dem Import in die Cluster-Datenbank.
Die Definition der Tabelle City
würde zum
Beispiel folgendermaßen modifiziert:
DROP TABLE IF EXISTS `City`;
CREATE TABLE `City` (
`ID` int(11) NOT NULL auto_increment,
`Name` char(35) NOT NULL default '',
`CountryCode` char(3) NOT NULL default '',
`District` char(20) NOT NULL default '',
`Population` int(11) NOT NULL default '0',
PRIMARY KEY (`ID`)
) ENGINE=NDBCLUSTER DEFAULT CHARSET=latin1;
INSERT INTO `City` VALUES (1,'Kabul','AFG','Kabol',1780000);
INSERT INTO `City` VALUES (2,'Qandahar','AFG','Qandahar',237500);
INSERT INTO `City` VALUES (3,'Herat','AFG','Herat',186800);
(remaining INSERT statements omitted)
Dies müssen Sie mit der Definition jeder Tabelle tun, die in
die geclusterte Datenbank importiert werden soll. Am einfachsten
erreichen Sie dies, indem Sie in der Datei mit den
Tabellendefinitionen alle Vorkommen von
TYPE=MyISAM
oder
ENGINE=MyISAM
durch
ENGINE=NDBCLUSTER
ersetzen. Wenn Sie die
Datei nicht ändern möchten, können Sie die Tabellen auch mit
der unveränderten Datei anlegen und dann ihren Typ mit
ALTER TABLE
ändern. Die Einzelheiten
erfahren Sie in einem späteren Abschnitt.
Wenn wir davon ausgehen, dass Sie bereits eine Datenbank namens
world
auf dem SQL-Knoten des Clusters
angelegt haben, können Sie nun
city_table.sql
mit dem
Kommandozeilen-Client mysql lesen und die
entsprechende Tabelle in der üblichen Weise mit Daten füllen:
shell> mysql world < city_table.sql
Dieser Befehl muss unbedingt auf dem Host ausgeführt werden,
auf welchem der SQL-Knoten läuft (in diesem Fall auf der
Maschine mit der IP-Adresse 192.168.0.20
).
Um eine Kopie der gesamten world
-Datenbank
auf dem SQL-Knoten anzulegen, führen Sie
mysqldump auf dem ungeclusterten Server aus,
um die Datenbank in die Datei world.sql
im
Verzeichnis /usr/local/mysql/data
zu
exportieren. Danach importieren Sie diese Datei folgendermaßen
in den SQL-Knoten des Clusters:
shell>cd /usr/local/mysql/data
shell>mysql world < world.sql
Wenn Sie die Datei an einer anderen Stelle speichern, müssen Sie die obigen Anleitungen entsprechend abändern.
Sie müssen wissen, dass NDB Cluster
in MySQL
5.1 nicht die selbstständige Erkennung von
Datenbanken unterstützt (siehe
Abschnitt 16.8, „Bekannte Beschränkungen von MySQL Cluster“). Mit anderen
Worten: Sobald Sie die Datenbank world
und
ihre Tabellen auf einem Datenknoten angelegt haben, müssen Sie
die Anweisung CREATE SCHEMA world
mit
nachfolgendem FLUSH TABLES
auf jedem
SQL-Knoten im Cluster erteilen. Nur dann kann der Knoten die
Datenbank erkennen und ihre Tabellendefinitionen lesen.
SELECT
-Anfragen werden auf dem SQL-Knoten
genau wie auf jedem anderen MySQL Server ausgeführt. Um
Anfragen auf der Kommandozeile auszuführen, müssen Sie sich
zuerst wie üblich in den MySQL Monitor einloggen (das Passwort
von root
am Enter
password:
-Prompt eingeben):
shell> mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1 to server version: 5.1.5-alpha
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql>
Wir verwenden einfach das root
-Konto des
MySQL Servers und gehen davon aus, dass Sie bei der Installation
des MySQL Servers die Standardsicherheitsvorkehrungen getroffen
und ein starkes root
-Passwort eingerichtet
haben. Mehr darüber lesen Sie unter
Abschnitt 2.9.3, „Einrichtung der anfänglichen MySQL-Berechtigungen“.
Bitte achten Sie darauf, dass Cluster-Knoten, wenn sie
aufeinander zugreifen, nicht von dem MySQL-Berechtigungssystem
Gebrauch machen. Die Einrichtung oder Änderung von
MySQL-Benutzerkonten (einschließlich root
)
wirkt sich nur auf Anwendungen aus, die auf den SQL-Knoten
zugreifen, aber nicht auf die Interaktion zwischen den Knoten.
Wenn Sie die ENGINE
-Klauseln in den
Tabellendefinitionen vor dem Import des SQL-Skripts nicht
geändert hatten, sollten Sie nun folgende Anweisungen
ausführen:
mysql>USE world;
mysql>ALTER TABLE City ENGINE=NDBCLUSTER;
mysql>ALTER TABLE Country ENGINE=NDBCLUSTER;
mysql>ALTER TABLE CountryLanguage ENGINE=NDBCLUSTER;
Auch die Auswahl einer Datenbank und die Ausführung einer SELECT-Anfrage auf einer Tabelle dieser Datenbank sowie das Schließen des MySQL Monitors funktionieren wie üblich:
mysql>USE world;
mysql>SELECT Name, Population FROM City ORDER BY Population DESC LIMIT 5;
+-----------+------------+ | Name | Population | +-----------+------------+ | Bombay | 10500000 | | Seoul | 9981619 | | São Paulo | 9968485 | | Shanghai | 9696300 | | Jakarta | 9604900 | +-----------+------------+ 5 rows in set (0.34 sec) mysql>\q
Bye shell>
Anwendungen, die MySQL nutzen, können ihre Standard-APIs auch
für den Zugriff auf NDB-Tabellen verwenden. Bitte denken Sie
jedoch daran, dass Ihre Anwendung auf den SQL-Knoten zugreifen
muss, und nicht auf den MGM- oder die Speicherknoten. Das
folgende kleine Beispiel zeigt, wie die obige
SELECT
-Anweisung mithilfe der
mysqli
-Erweiterung von PHP 5 ausgeführt
wird, die auf einem Webserver irgendwo anders im Netzwerk
läuft:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<title>SIMPLE mysqli SELECT</title>
</head>
<body>
<?php
# Verbindung zum SQL-Knoten:
$link = new mysqli('192.168.0.20', 'root', 'root_password
', 'world');
# Die Parameter für den mysqli-Konstruktor sind:
# Host, User, Passwort, Datenbank
if( mysqli_connect_errno() )
die("Connect failed: " . mysqli_connect_error());
$query = "SELECT Name, Population
FROM City
ORDER BY Population DESC
LIMIT 5";
# wenn keine Fehler auftreten...
if( $result = $link->query($query) )
{
?>
<table border="1" width="40%" cellpadding="4" cellspacing ="1">
<tbody>
<tr>
<th width="10%">City</th>
<th>Population</th>
</tr>
<?
# dann zeige Ergebnisse an...
while($row = $result->fetch_object())
printf(<tr>\n <td align=\"center\">%s</td><td>%d</td>\n</tr>\n",
$row->Name, $row->Population);
?>
</tbody
</table>
<?
# ...und prüfe, wie viele Zeilen abgerufen wurden
printf("<p>Affected rows: %d</p>\n", $link->affected_rows);
}
else
# anderenfalls sag uns, was schief gegangen ist
echo mysqli_error();
# gib die Ergebnismenge und das mysqli-Verbindungsobjekt frei
$result->close();
$link->close();
?>
</body>
</html>
Wir setzen voraus, dass der Prozess, der auf dem Webserver läuft, die IP-Adresse des SQL-Knotens erreichen kann.
In gleicher Weise können Sie die MySQL C-API, Perl-DBI, Python-mysql oder die eigenen Connectors der MySQL AB einsetzen, um die Aufgaben der Datendefinition und Datenbearbeitung genau so zu erledigen, wie Sie es auch normalerweise mit MySQL tun.
Um den Cluster herunterzufahren, geben Sie folgenden Befehl in eine Shell auf dem Host des MGM-Knotens ein:
shell> ndb_mgm -e shutdown
Hier wird die Option -e
verwendet, um einen
Befehl von der Shell an den ndb_mgm-Client zu
übergeben. Siehe auch Abschnitt 4.3.1, „Befehlszeilenoptionen für mysqld“.
Mit diesem Befehl werden ndb_mgm,
ndb_mgmd und alle eventuell laufenden
ndbd-Prozesse geräuschlos beendet.
SQL-Knoten können mit mysqladmin shutdown
und anderen Methoden heruntergefahren werden.
Folgende Befehle starten den Cluster neu:
Auf dem Management-Host (in unserem Beispiel
192.168.0.10
):
shell> ndb_mgmd -f /var/lib/mysql-cluster/config.ini
Auf jedem der Daten-Hosts (192.168.0.30
und 192.168.0.40
):
shell> ndbd
Denken Sie daran, dass Sie diesen Befehl
nicht mit der Option
--initial
aufrufen dürfen, wenn Sie einen
NDBD-Knoten ganz normal neu starten.
Auf dem SQL-Host (192.168.0.20
):
shell> mysqld &
Mehr über Datensicherungen im Cluster erfahren Sie unter Abschnitt 16.6.5.2, „Verwendung des Management-Servers zur Erzeugung von Backups“.
Um den Cluster aus einer Datensicherung wiederherzustellen, benötigen Sie den Befehl ndb_restore, der in Abschnitt 16.6.5.3, „Wiederherstellung aus einem Cluster-Backup“, erklärt wird.
Weitere Informationen über die Konfiguration von MySQL Cluster finden Sie unter Abschnitt 16.4, „MySQL Cluster: Konfiguration“.
Ein MySQL Server in einem MySQL Cluster unterscheidet sich nur in
einer Hinsicht von einem normalen (ungeclusterten) MySQL Server:
Er verwendet die Speicher-Engine NDB Cluster
.
Diese Engine wird auch einfach als NDB
bezeichnet, beide Namen sind synonym.
Um nicht überflüssig Ressourcen zu reservieren, ist die
NDB
-Engine in der Standardkonfiguration des
Servers ausgeschaltet. Um sie einzuschalten, müssen Sie die
Serverkonfigurationsdatei my.cnf
ändern oder
den Server mit der Option --ndbcluster
hochfahren.
Da der MySQL Server Teil des Clusters ist, muss auch er wissen,
wie er einen MGM-Knoten erreicht, von dem er sich die
Cluster-Konfigurationsdaten besorgen kann. Nach Voreinstellung
sucht er den MGM-Knoten auf dem localhost
. Wenn
Sie jedoch einen anderen Ort angeben müssen, so können Sie dies
in der Datei my.cnf
oder auf der
Kommandozeile des MySQL Servers tun. Bevor die Speicher-Engine
NDB
genutzt werden kann, müssen mindestens ein
MGM-Knoten sowie die erforderlichen Datenknoten funktionieren.
Die Speicher-Engine NDB
für den
Cluster-Betrieb ist als Binärdistribution für Linux, Mac OS X
und Solaris erhältlich. Wir arbeiten daran, Cluster auf allen
von MySQL unterstützten Betriebssystemen einschließlich
Windows funktionsfähig zu machen.
Wenn Sie einen Build von einem Source Tarball oder dem MySQL
5.1 BitKeeper Tree bevorzugen, achten Sie darauf,
configure mit der Option
--with-ndbcluster
auszuführen. Sie können
jedoch auch das Build-Skript
BUILD/compile-pentium-max laufen lassen.
Beachten Sie, dass dieses Skript OpenSSL enthält: Damit der
Build fehlerfrei läuft, müssen Sie also entweder OpenSSL
besitzen oder sich besorgen oder
compile-pentium-max umkonfigurieren, um
dieses Erfordernis herauszunehmen. Sie können natürlich auch
einfach die Standardinstruktionen für das Kompilieren Ihrer
eigenen Binaries befolgen und dann die üblichen Tests und
Installationsprozeduren durchführen. Siehe
Abschnitt 2.8.3, „Installation vom Entwicklungs-Source-Tree“.
In den folgenden Abschnitten wird vorausgesetzt, dass Sie mit der Installation von MySQL bereits vertraut sind. Daher behandeln wir hier nur die Unterschiede zwischen der Konfiguration eines geclusterten und eines ungeclusterten MySQL Servers. (Wenn Sie genauere Informationen benötigen, schauen Sie unter Kapitel 2, Installation von MySQL, nach.)
Am einfachsten ist die Cluster-Konfiguration, wenn alle
Management- und Datenknoten bereits laufen. Dies ist wohl der
langwierigste Teil der Konfiguration. Dagegen ist die
Bearbeitung der Datei my.cnf
ziemlich
einfach und dieser Abschnitt wird lediglich beschreiben, wo die
Konfiguration von der des ungeclusterten MySQL Servers abweicht.
Um sich mit den Grundlagen vertraut zu machen, beschreiben wir zuerst die denkbar einfachste Konfiguration eines funktionsfähigen MySQL Clusters. Danach müssten Sie in der Lage sein, die von Ihnen gewünschte Startkonfiguration aus den Informationen der anderen zum Thema gehörenden Teile dieses Kapitels zu erschließen.
Zuerst müssen Sie ein Konfigurationsverzeichnis wie
beispielsweise /var/lib/mysql-cluster
anlegen, indem Sie folgenden Befehl als
System-root
-User ausführen:
shell> mkdir /var/lib/mysql-cluster
In diesem Verzeichnis legen Sie eine Datei namens
config.ini
an, die folgende Daten enthält.
Bitte setzen Sie für HostName
und
DataDir
die für Ihr System passenden Werte
ein.
# Die Datei "config.ini" zeigt eine Minimalkonfiguration, bestehend aus 1 Datenknoten, # 1 Management-Server und 3 MySQL Servern. # Die leeren Default-Abschnitte sind nicht erforderlich und werden nur der # Vollständigkeit halber gezeigt. # Die Datenknoten müssen einen Hostnamen angeben, nicht aber die MySQL Server. # Wenn Sie den Hostnamen Ihres Computers nicht wissen, verwenden Sie localhost. # Der Parameter DataDir hat ebenfalls einen Standardwert, sollte aber besser # explizit gesetzt werden. # Hinweis: DB, API und MGM sind Aliase für NDBD, MYSQLD und NDB_MGMD # DB und API sind veraltet und sollten in neuen # Installationen nicht mehr benutzt werden. [NDBD DEFAULT] NoOfReplicas= 1 [MYSQLD DEFAULT] [NDB_MGMD DEFAULT] [TCP DEFAULT] [NDB_MGMD] HostName= myhost.example.com [NDBD] HostName= myhost.example.com DataDir= /var/lib/mysql-cluster [MYSQLD] [MYSQLD] [MYSQLD]
Sie können jetzt den Management-Server
ndb_mgmd starten. Da dieser standardmäßig
versucht, die Datei config.ini
in seinem
aktuellen Arbeitsverzeichnis zu lesen, müssen Sie in das
Verzeichnis wechseln, in dem die Datei sich befindet, und dann
ndb_mgmd aufrufen:
shell>cd /var/lib/mysql-cluster
shell>ndb_mgmd
Danach starten Sie einen einzelnen DB-Knoten mit dem Befehl
ndbd. Wenn Sie ndbd zum
allerersten Mal für einen DB-Knoten starten, müssen Sie die
Option --initial
einsetzen:
shell> ndbd --initial
Bei allen weiteren Starts von ndbd müssen
Sie die --initial
-Option unbedingt
weglassen:
shell> ndbd
Der Grund, weshalb die Option --initial
bei
weiteren Neustarts nicht wieder benutzt werden darf, ist der,
dass sie ndbd veranlasst, alle vorhandenen
Daten- und Logdateien (und alle Metadaten für Tabellen) dieses
Datenknotens zu löschen und neu zu erzeugen. Die einzige
Ausnahme von dieser Regel, --initial
nur für
den allerersten Aufruf von ndbd zu verwenden,
tritt dann ein, wenn der Cluster neu gestartet und nach dem
Hinzufügen neuer Datenknoten aus den Sicherungsdateien
wiederhergestellt wird.
Nach Voreinstellung sucht ndbd den
Management-Server auf localhost
am Port 1186.
Hinweis: Wenn Sie MySQL von
einem Binary Tarball installiert haben, müssen Sie den Pfad der
ndb_mgmd- und ndbd-Server
explizit angeben. (Normalerweise befinden sich die beiden in
/usr/local/mysql/bin
.)
Zum Schluss gehen Sie in das MySQL-Datenverzeichnis
(normalerweise /var/lib/mysql
oder
/usr/local/mysql/data
) und sorgen dafür,
dass die Datei my.cnf
die Option enthält,
die zur Aktivierung der Speicher-Engine NDB erforderlich ist:
[mysqld] ndbcluster
Jetzt können Sie den MySQL Server wie gewöhnlich starten:
shell> mysqld_safe --user=mysql &
Warten Sie einen Augenblick, um sich zu vergewissern, dass der
MySQL Server richtig läuft. Wenn Sie die Meldung mysql
ended
sehen, schauen Sie in die
.err
-Datei des Servers, um den Fehler zu
finden.
Wenn so weit alles geklappt hat, können Sie den Server nun
geclustert starten. Verbinden Sie sich mit dem Server und
schauen Sie nach, ob die Speicher-Engine
NDBCLUSTER
aktiviert ist:
shell>mysql
Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1 to server version: 5.1.5-alpha-Max Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql>SHOW ENGINES\G
... *************************** 12. row *************************** Engine: NDBCLUSTER Support: YES Comment: Clustered, fault-tolerant, memory-based tables *************************** 13. row *************************** Engine: NDB Support: YES Comment: Alias for NDBCLUSTER ...
Die Zeilennummern der obigen Ausgabe können auf Ihrem System je nach Ihrer Serverkonfiguration abweichen.
Versuchen Sie nun, eine NDBCLUSTER
-Tabelle
anzulegen:
shell>mysql
mysql>USE test;
Database changed mysql>CREATE TABLE ctest (i INT) ENGINE=NDBCLUSTER;
Query OK, 0 rows affected (0.09 sec) mysql>SHOW CREATE TABLE ctest \G
*************************** 1. row *************************** Table: ctest Create Table: CREATE TABLE `ctest` ( `i` int(11) default NULL ) ENGINE=ndbcluster DEFAULT CHARSET=latin1 1 row in set (0.00 sec)
Um zu prüfen, ob Ihre Knoten richtig eingerichtet sind, starten Sie den Management-Client:
shell> ndb_mgm
Innerhalb des Management-Clients geben Sie den Befehl SHOW ein, um einen Statusbericht über den Cluster zu erhalten:
NDB> SHOW
Cluster Configuration
---------------------
[ndbd(NDB)] 1 node(s)
id=2 @127.0.0.1 (Version: 3.5.3, Nodegroup: 0, Master)
[ndb_mgmd(MGM)] 1 node(s)
id=1 @127.0.0.1 (Version: 3.5.3)
[mysqld(API)] 3 node(s)
id=3 @127.0.0.1 (Version: 3.5.3)
id=4 (not connected, accepting connect from any host)
id=5 (not connected, accepting connect from any host)
Nun haben Sie mit Erfolg einen funktionierenden MySQL Cluster
eingerichtet. In diesen Cluster können Sie jetzt aus jeder
Tabelle, die mit ENGINE=NDBCLUSTER
oder
seinem Alias ENGINE=NDB
angelegt wurde, Daten
laden.
connectstring
Um MySQL Cluster zu konfigurieren, müssen Sie mit zwei Dateien arbeiten:
my.cnf
: Hier sind Optionen für alle
Executables im MySQL Cluster angegeben. Diese Datei, die
Ihnen aus der früheren Arbeit mit MySQL bereits vertraut
sein dürfte, muss jeder ausführbaren Datei im Cluster
zugänglich sein.
config.ini
: Diese Datei wird nur vom
Management-Server im MySQL Cluster gelesen, der dann die in
ihr enthaltenen Informationen an alle Prozesse im Cluster
weiterleitet. config.ini
enthält eine
Beschreibung für jeden am Cluster beteiligten Knoten. Dazu
gehören Konfigurationsparameter für Datenknoten sowie
Konfigurationsparameter für Verbindungen zwischen
sämtlichen Knoten im Cluster.
Wir arbeiten permanent daran, die Cluster-Konfiguration zu verbessern und diesen Prozess zu vereinfachen. Auch wenn wir uns dabei um Abwärtskompatibilität bemühen, können auch gelegentlich inkompatible Änderungen vorkommen. In solchen Fällen teilen wir den Benutzern von Cluster im Voraus mit, wenn eine Änderung nicht abwärtskompatibel ist. Wenn Sie auf eine noch undokumentierte Änderung dieser Art stoßen sollten, melden Sie sie bitte der MySQL-Bugs-Datenbank nach dem in Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“, beschriebenen Verfahren.
Um MySQL Cluster zu unterstützen, müssen Sie die Datei
my.cnf
so ändern, wie es im folgenden
Beispiel gezeigt wird. Bitte verwechseln Sie die hier
angegebenen Optionen nicht mit denen aus den
config.ini
-Dateien. Sie können diese
Parameter auch auf der Kommandozeile angeben, wenn Sie die
Executables aufrufen.
# my.cnf # Beispiel für Ergänzungen der my.cnf für MySQL Cluster # (gilt für MySQL 5.1) # ndbcluster-Speicher-Engine aktivieren und Verbindungs-String für # Management-Server-Host anlegen (Standardport ist 1186) [mysqld] ndbcluster ndb-connectstring=ndb_mgmd.mysql.com # Verbindungs-String für Management-Server-Host anlegen (Standardport ist 1186) [ndbd] connect-string=ndb_mgmd.mysql.com # Verbindungs-String für Management-Server-Host anlegen (Standardport ist 1186) [ndb_mgm] connect-string=ndb_mgmd.mysql.com # Speicherort für Cluster-Konfigurationsdatei [ndb_mgmd] config-file=/etc/config.ini
(Weitere Informationen über Connectstrings finden Sie unter
Abschnitt 16.4.4.2, „MySQL Cluster: connectstring
“.)
# my.cnf # Beispiel für Ergänzungen der my.cnf für MySQL Cluster # (funktioniert auf allen Versionen) # ndbcluster-Speicher-Engine aktivieren und Verbindungs-String für # Management-Server-Host anlegen (Standardport ist 1186 [mysqld] ndbcluster ndb-connectstring=ndb_mgmd.mysql.com:1186
Sie können in der Cluster-my.cnf
-Datei
auch einen separaten
[mysql_cluster]
-Abschnitt für
Einstellungen einrichten, die von allen Executables gelesen
und benutzt werden:
# Cluster-spezifische Einstellungen [mysql_cluster] ndb-connectstring=ndb_mgmd.mysql.com:1186
Die Konfigurationsdatei heißt nach Voreinstellung
config.ini
. Sie wird von
ndb_mgmd beim Starten gelesen und kann an
jedem beliebigen Ort gespeichert sein. Ihr Speicherort und ihr
Name werden mit
--config-file=
auf der Kommandozeile für ndb_mgmd
angegeben. Wenn die Konfigurationsdatei nicht angegeben wurde,
versucht ndb_mgmd nach Voreinstellung, eine
Datei namens path_name
config.ini
im aktuellen
Arbeitsverzeichnis zu lesen.
Gegenwärtig hat die Konfiguration ein INI-Format: Sie besteht
also aus Abschnitten mit Abschnittsüberschriften (in eckigen
Klammern), gefolgt von den jeweiligen Parameternamen und
-werten. Sie weicht insofern vom Standard-INI-Format ab, als
der Name und Wert eines Parameters auch durch einen
Doppelpunkt (‘:
’) und nicht nur
durch das Gleichheitszeichen
(‘=
’) getrennt sein können und
die Abschnitte nicht eindeutig durch einen Abschnittsnamen
identifiziert sind. Stattdessen werden eindeutige Abschnitte
(wie zum Beispiel zwei verschiedene Knoten desselben Typs)
durch eine eindeutige ID gekennzeichnet, die innerhalb des
Abschnitts als Parameter angegeben ist.
Für die meisten Parameter sind Standardwerte definiert. Diese
können auch in config.ini
angegeben
sein. Um einen Abschnitt für Standardwerte anzulegen, fügen
Sie dem Abschnittsnamen einfach DEFAULT
hinzu. Zum Beispiel enthält ein
[NDBD]
-Abschnitt Parameter für einen
bestimmten Datenknoten, während ein[NDBD
DEFAULT]
-Abschnitt Parameter enthält, die für
sämtliche Datenknoten gelten. Wir nehmen an, dass alle
Datenknoten denselben Speicherplatz belegen. Um sie alle zu
konfigurieren, legen Sie also einen [NDBD
DEFAULT]
-Abschnitt mit einer
DataMemory
-Zeile an, in welcher der
Speicherplatz für die Datenknoten angegeben ist.
Die Konfigurationsdatei muss mindestens die Computer und Knoten eines Clusters aufführen und sagen, auf welchem Computer welcher Knoten residiert. Im Folgenden sehen Sie ein Beispiel einer einfachen Konfigurationsdatei für einen Cluster, der aus einem Management-Server, zwei Datenknoten und zwei MySQL Servern besteht:
# Datei "config.ini" - 2 Datenknoten und 2 SQL-Knoten # Diese Datei wird in das Startverzeichnis von ndb_mgmd (dem # Management-Server gelegt.) # Der erste MySQL Server kann von jedem Host gestartet werden, der zweite # nur vom Host mysqld_5.mysql.com [NDBD DEFAULT] NoOfReplicas= 2 DataDir= /var/lib/mysql-cluster [NDB_MGMD] Hostname= ndb_mgmd.mysql.com DataDir= /var/lib/mysql-cluster [NDBD] HostName= ndbd_2.mysql.com [NDBD] HostName= ndbd_3.mysql.com [MYSQLD] [MYSQLD] HostName= mysqld_5.mysql.com
Beachten Sie, dass jeder Knoten seinen eigenen Abschnitt in
config.ini
hat. Da der vorliegende
Cluster zwei Datenknoten hat, enthält die Konfigurationsdatei
zwei [NDBD]
-Abschnitte, in denen diese
Knoten definiert sind.
In der config.ini
-Konfigurationsdatei
können sechs verschiedene Abschnitte benutzt werden:
[COMPUTER]
: Definiert die
Cluster-Hosts.
[NDBD]
: Definiert die Daten des
Clusters nodes.
[MYSQLD]
: Definiert die MySQL
Server-Knoten des Clusters server nodes.
[MGM]
or [NDB_MGMD]
:
Definiert den Management-Server-Knoten des Clusters.
[TCP]
: Definiert die
TCP/IP-Verbindungen zwischen den Knoten im Cluster, wobei
TCP/IP das Standardverbindungsprotokoll ist.
[SHM]
: Definiert
Shared-Memory-Verbindungen zwischen Knoten. Früher stand
dieser Verbindungtyp nur in Binaries zur Verfügung, die
mit der Option --with-ndb-shm
gebaut
wurden. In MySQL 5.1-Max
ist er nach Voreinstellung eingeschaltet, allerdings
befindet sich diese Lösung noch in der Erprobungsphase.
Für jeden Abschnitt können Sie auch
DEFAULT
-Werte definieren.
Cluster-Parameternamen unterscheiden im Gegensatz zu den
Parametern in my.cnf
oder
my.ini
nicht zwischen Groß- und
Kleinschreibung.
Mit Ausnahme des MySQL Cluster-Management-Servers (ndb_mgmd) benötigt jeder zu einem MySQL Cluster gehörige Knoten einen Verbindungs-String (Connectstring), der auf den Standort des Management-Servers verweist. Dieser Verbindungs-String wird zum Einrichten einer Verbindung mit dem Management-Server und, je nach der Rolle des Knotens im Cluster, auch für die Erfüllung anderer Aufgaben benötigt. Ein Verbindungs-String hat folgende Syntax:
<connectstring> := [<nodeid-specification>,]<host-specification>[,<host-specification>] <nodeid-specification> :=node_id
<host-specification> :=host_name
[:port_num
]
node_id
ist ein Integer größer 1, der
einen Knoten in config.ini
bezeichnet.
host_name
ist ein String, der einen
gültigen Internethostnamen oder eine IP-Adresse angibt.
port_num
ist ein Integer, der auf
eine TCP/IP-Portnummer verweist.
example 1 (long): "nodeid=2,myhost1:1100,myhost2:1100,192.168.0.3:1200" example 2 (short): "myhost1"
Alle Knoten verwenden localhost:1186
als
Standardwert für den Verbindungs-String, wenn kein anderer
angegeben wird. Wenn port_num
aus
dem Verbindungs-String weggelassen wird, ist 1186 der
Standardport. Dieser sollte im Netzwerk immer frei sein, da er
von der IANA genau diesen Zweck zugewiesen bekam (siehe
http://www.iana.org/assignments/port-numbers
for details).
Durch Auflistung mehrerer
<host-specification>
-Werte können
Sie redundante Management-Server angeben. Ein Cluster-Knoten
wird dann versuchen, der Reihe nach mehrere Management-Server
auf jedem Host zu kontaktieren, bis er eine Verbindung
einrichten kann.
Der Verbindungs-String kann auf verschiedene Weisen angegeben werden:
Jede Executable hat ihre eigene Kommandozeilenoption, um den Management-Server beim Starten anzugeben. (In der Dokumentation finden Sie die jeweilige Executable.)
Sie können auch die Verbindungs-Strings für alle Knoten
des Clusters zugleich einrichten, indem Sie sie in den
[mysql_cluster]
-Abschnitt der
my.cnf
-Datei des Management-Servers
schreiben.
Aus Gründen der Abwärtskompatibilität stehen auch zwei weitere Optionen mit gleicher Syntax zur Verfügung:
Sie können die Umgebungsvariable
NDB_CONNECTSTRING
auf den
Verbindungs-String einstellen.
Sie können den Verbindungs-String für jede
Executable in eine Textdatei namens
Ndb.cfg
schreiben und diese Datei
in das Startverzeichnis der Executable legen.
Diese beiden Möglichkeiten sind jedoch inzwischen veraltet und sollten für neuere Installationen nicht mehr verwendet werden.
Wir empfehlen, den Verbindungs-String entweder auf der
Kommandozeile oder in der Datei my.cnf
für jede Executable anzugeben.
Die einzige Bedeutung des Abschnitts
[COMPUTER]
besteht darin, nicht für jeden
Knoten im System Hostnamen definieren zu müssen. Alle hier
angegebenen Parameter sind obligatorisch.
Id
Ein Integer-Wert, der auf einen anderswo in der Konfigurationsdatei angegebenen Hostcomputer verweist.
HostName
Der Hostname oder die IP-Adresse des Computers.
Im Abschnitt [NDB_MGMD]
wird das Verhalten
des Management-Servers konfiguriert. [MGM]
kann auch als Alias verwendet werden; beide Abschnittsnamen
sind äquivalent. Alle Parameter in der folgenden Liste sind
optional; wenn man sie weglässt, werden Standardwerte
verwendet. Hinweis: Wenn
weder der Parameter ExecuteOnComputer
noch
ein HostName
angegeben ist, wird
localhost
für beide als Default
eingesetzt.
Id
Jeder Knoten im Cluster hat eine eindeutige Identität, die durch einen Integer-Wert zwischen 1 und 63 (einschließlich) dargestellt wird. Alle Nachrichten im Cluster sprechen den Knoten mit dieser ID an.
ExecuteOnComputer
Bezieht sich auf einen der im Abschnitt
[COMPUTER]
aufgeführten Computer.
PortNumber
Die Nummer des Ports, auf welchem der Management-Server auf Konfigurationsanforderungen und Management-Befehle lauscht.
LogDestination
Dieser Parameter gibt an, wohin die Logdaten für den
Cluster gesandt werden: an CONSOLE
,
SYSLOG
oder FILE
:
CONSOLE
gibt das Log an
stdout
aus:
CONSOLE
SYSLOG
sendet das Log an
syslog
, wobei einer der folgenden
Werte verwendet wird: auth
,
authpriv
, cron
,
daemon
, ftp
,
kern
, lpr
,
mail
, news
,
syslog
, user
,
uucp
, local0
,
local1
, local2
,
local3
, local4
,
local5
, local6
oder local7
.
Hinweis: Nicht jedes Betriebssystem unterstützt alle diese Werte.
SYSLOG:facility=syslog
FILE
sendet die Ausgabe des
Cluster-Logs an eine normale Datei auf demselben
Computer. Folgende Werte können angegeben werden:
filename
: Der Name der
Logdatei.
maxsize
: Die Maximalgröße (in
Bytes), auf welche die Datei anwachsen kann, ehe
das Log in einer neuen Datei fortgesetzt wird.
Wenn dies geschieht, wird die alte Logdatei
umbenannt, indem ein .N
an ihren Dateinamen angefügt wird, wobei
N
die nächste laufende
Nummer ist, die noch nicht für diesen Dateinamen
eingesetzt wurde.
maxfiles
: Die maximale Anzahl
der Logdateien.
FILE:filename=cluster.log,maxsize=1000000,maxfiles=6
In der folgenden Form können auch mehrere Logdestinationen, jeweils durch Semikola getrennt, angegeben werden:
CONSOLE;SYSLOG:facility=local0;FILE:filename=/var/log/mgmd
Der Parameter FILE
hat folgenden
Standardwert:
FILE:filename=ndb_
.
node_id
_cluster.log,maxsize=1000000,maxfiles=6node_id
ist dabei die ID
des Knotens.
ArbitrationRank
Mit diesem Parameter wird angegeben, welche Knoten als
Arbitrator fungieren können. Nur MGM- und SQL-Knoten
können Arbitrator sein. Der
ArbitrationRank
can take ist einer der folgenden Werte:
0
: Dieser Knoten wird nie als
Arbitrator eingesetzt.
1
: Da dieser Knoten eine hohe
Priorität hat, wird er eher als Knoten mit niedriger
Priorität als Arbitrator eingesetzt.
2
: Ein Knoten mit niedriger
Priorität, der als Arbitrator nur eingesetzt wird,
wenn kein Knoten mit höherer Priorität für diesen
Zweck verfügbar ist.
Normalerweise sollte der Management-Server als Arbitrator
konfiguriert werden, indem sein
ArbitrationRank
auf 1 (den Default) und
der Rang aller SQL-Knoten auf 0 gesetzt wird.
ArbitrationDelay
Ein Integer-Wert, der angibt, um wie viele Millisekunden die Antworten des Management-Servers auf Arbitration-Requests verzögert werden. Der Standardwert 0 muss normalerweise nicht geändert werden.
DataDir
Das Verzeichnis, in dem die Ausgabedateien des
Management-Servers gespeichert werden. Dazu gehören die
Cluster-Logdateien, die Prozess-Ausgabedateien und die
Prozess-ID (PID)-Datei des Daemons. (Für die Logdateien
können Sie auch einen anderen Speicherort einstellen,
indem Sie, wie weiter oben in diesem Abschnitt
beschrieben, den Parameter FILE
für
die LogDestination
einstellen.)
Im Abschnitt [NDBD]
wird das Verhalten der
Datenknoten des Clusters konfiguriert. Es gibt eine Vielzahl
Parameter für die Größen von Puffern und Pools, für
Timeout-Werte und so weiter. Die einzigen obligatorischen
Parameter sind:
entweder ExecuteOnComputer
oder
HostName
der Parameter NoOfReplicas
Diese obligatorischen Parameter müssen im Abschnitt
[NDBD DEFAULT]
definiert werden.
Die meisten Parameter für Datenknoten werden im Abschnitt
[NDBD DEFAULT]
gesetzt. Nur die Parameter,
von denen explizit gesagt wird, dass sie lokale Werte
einstellen können, dürfen im
[NDBD]
-Abschnitt geändert werden.
HostName
, Id
und
ExecuteOnComputer
müssen
unbedingt im lokalen
[NDBD]
-Abschnitt definiert sein.
Datenknoten identifizieren
Der Wert Id
(der Datenknoten-Bezeichner)
kann entweder auf der Kommandozeile beim Starten des Knotens
oder in der Konfigurationsdatei zugewiesen werden.
An jeden Parameter kann als Suffix K
,
M
oder G
angehängt
werden, um Einheiten von 1.024, 1.024 × 1.024 oder 1.024
× 1.024 × 1.024 anzugeben. (So bedeutet
beispielsweise 100K
100 × 1.024 =
102.400.) In Parameternamen und -werten wird zwischen Groß-
und Kleinschreibung unterschieden.
Id
Diese Knoten-ID ist die Adresse des Knotens für alle internen Nachrichten im Cluster. Sie ist ein Integer zwischen 1 und 63 einschließlich. Jeder Knoten im Cluster muss eine eindeutige Identität haben.
ExecuteOnComputer
Bezieht sich auf einen der Computer (Hosts), die im
Abschnitt COMPUTER
definiert sind.
HostName
Die Angabe dieses Parameters wirkt sich ähnlich wie die
Angabe von ExecuteOnComputer
aus: Er
definiert den Hostnamen des Computers, auf dem der
Speicherknoten liegen soll. Wenn Sie einen anderen
Hostnamen als localhost
angeben
möchten, müssen Sie entweder diesen Parameter oder
ExecuteOnComputer
verwenden.
ServerPort
(OBSOLETE)
Jeder Knoten im Cluster verbindet sich mit anderen Computern über einen Port. Dieser Port wird beim Einrichten der Verbindung auch für Nicht-TCP-Transporter verwendet. Der Standardport wird dynamisch in einer Weise zugewiesen, die gewährleistet, dass keine zwei Knoten auf demselben Computer die gleiche Portnummer bekommen. Daher dürfte es sich normalerweise erübrigen, einen Wert für diesen Parameter zu setzen.
NoOfReplicas
Dieser globale Parameter kann nur im Abschnitt
[NDBD DEFAULT]
eingestellt werden und
definiert, wie viele Replikas jeder Tabelle im Cluster
gespeichert werden. Außerdem gibt dieser Parameter die
Größe der Knotengruppen an. Eine Knotengruppe ist eine
Menge von Knoten, die alle dieselben Informationen
speichern.
Knotengruppen werden implizit gebildet. Die erste
Knotengruppe besteht aus der Menge der Datenknoten mit den
niedrigsten Knoten-IDs, die nächste aus der Menge der
Datenknoten mit den zweitniedrigsten IDs und so weiter.
Nehmen wir als Beispiel an, wir hätten 4 Datenknoten und
die NoOfReplicas
wurde auf 2 gesetzt.
Die vier Datenknoten haben die IDs 2, 3, 4 und 5. Dann
besteht die erste Gruppe aus den Knoten 2 und 3 und die
zweite Gruppe aus den Knoten 4 und 5. Es ist wichtig, den
Cluster so zu konfigurieren, dass Knoten derselben Gruppe
nicht auf demselben Computer liegen, da ein einziger
Hardwareabsturz dann den gesamten Cluster zerstören
würde.
Wenn keine Knoten-IDs angegeben werden, entscheidet die
Reihenfolge der Datenknoten über ihre Zugehörigkeit zu
einer Knotengruppe. Egal ob explizit zugewiesen oder
nicht, die SHOW
-Ausgabe auf dem
Management-Client zeigt die Knotengruppen an.
NoOfReplicas
hat keinen Standardwert,
der größtmögliche Wert beträgt 4.
DataDir
Dieser Parameter gibt das Verzeichnis für die Trace-Dateien, Logdateien, PID-Dateien und Fehlerlogs an.
FileSystemPath
Dieser Parameter gibt an, in welchem Verzeichnis alle
Dateien gespeichert werden, die für Metadaten, REDO-Logs,
UNDO-Logs und Datendateien angelegt werden. Nach
Voreinstellung ist dies das in DataDir
angegebene Verzeichnis.
Hinweis: Dieses
Verzeichnis muss existieren, bevor der
ndbd-Prozess gestartet wird.
Die empfohlene Verzeichnishierarchie für MySQL Cluster
beginnt mit dem Verzeichnis
/var/lib/mysql-cluster
, unter dem
dann ein Verzeichnis für das Dateisystem des Knotens
angelegt wird. Der Name dieses Unterverzeichnisses
enthält die Knoten-ID. Wenn beispielsweise die Knoten-ID
die 2 ist, heißt das Unterverzeichnis
ndb_2_fs
.
BackupDataDir
Dieser Parameter sagt, in welches Verzeichnis die
Sicherungsdateien gespeichert werden. Wird nichts
angegeben, ist ein Verzeichnis namens
BACKUP
unter dem im Parameter
FileSystemPath
angegebenen Speicherort
das Standardverzeichnis (siehe oben.)
Data Memory und Index Memory
DataMemory
und
IndexMemory
sind
[NDBD]
-Parameter, in denen die Größe der
Speichersegmente festgelegt wird, welche die tatsächlichen
Datensätze und ihre Indizes speichern. Für die Einstellung
dieser Parameter müssen Sie unbedingt wissen, wie
DataMemory
und
IndexMemory
verwendet werden, da diese
Werte normalerweise an die tatsächliche Speichernutzung des
Clusters angepasst werden müssen:
DataMemory
Dieser Parameter besagt, wie viel Speicherplatz (in Bytes) für die Speicherung der Datenbankeinträge zur Verfügung stehen muss. Da im Arbeitsspeicher der gesamte hier angegebene Speicherplatz zugewiesen wird, ist es extrem wichtig, dass der physikalische Arbeitsspeicher des Computers groß genug ist, um diesen auch unterbringen zu können.
Der durch DataMemory
zugewiesene
Speicher wird sowohl für die Datensätze als auch für
ihre Indizes verwendet. Jeder Datensatz hat zurzeit noch
eine feste Größe (sogar
VARCHAR
-Spalten werden als Spalten
fester Breite gespeichert). Für jeden Datensatz gibt es
einen Overhead von 16 Byte. Zusätzlich wird noch weiterer
Platz für jeden Datensatz zugewiesen, da er in einer
32-Kbyte-Seite mit 128 Byte Seiten-Overhead gespeichert
wird (siehe unten). Zudem wird für jede Seite ein wenig
Platz verschwendet, da jeder Datensatz in ein- und
derselben Seite gespeichert werden muss. Die
Maximalgröße eines Datensatzes beträgt gegenwärtig
8.052 Byte.
Der in DataMemory
definierte
Speicherplatz wird auch zur Unterbringung von Indizes
genutzt, die rund 10 Byte pro Datensatz belegen. Jede
Tabellenzeile wird im geordneten Index dargestellt. Oft
nehmen Anwender fälschlich an, dass alle Indizes in dem
Speicher des IndexMemory
abgelegt
werden, doch dies ist nicht der Fall: Nur
Primärschlüssel und eindeutige Hash-Indizes nutzen
diesen Speicher, während geordnete Indizes den von
DataMemory
zugewiesenen Speicher
belegen. Wenn Sie jedoch einen Primärschlüssel oder
einen eindeutigen Hash-Index anlegen, wird zugleich auf
denselben Schlüsseln auch ein geordneter Index erzeugt,
sofern Sie nicht in der Indexanweisung USING
HASH
gesagt haben. Dies können Sie prüfen,
indem Sie ndb_desc -d
db_name
table_name
im
Management-Client ausführen.
Der für das DataMemory
zugewiesene
Speicherplatz besteht aus 32-Kbyte-Seiten, die den
Tabellenfragmenten zugeordnet werden. Jede Tabelle wird
normalerweise in ebenso viele Fragmente partitioniert, wie
der Cluster Datenknoten hat. Also sind für jeden Knoten
so viele Fragmente vorhanden, wie in
NoOfReplicas
eingestellt sind.
Gegenwärtig ist es nicht möglich, eine einmal
zugewiesene Seite dem Pool der freien Seiten
zurückzugeben, außer man löscht die Tabelle. Auch durch
eine Knotenwiederherstellung wird die Partition kleiner,
da alle Datensätze in leere Partitionen anderer
Live-Knoten geschrieben werden.
Der Speicherplatz im DataMemory
enthält auch UNDO-Informationen: Bei jedem Update wird
eine Kopie des unveränderten Datensatzes in das
DataMemory
geschrieben. Außerdem wird
jede Kopie in den geordneten Tabellenindizes referenziert.
Eindeutige Hash-Indizes werden nur aktualisiert, wenn die
eindeutigen Indexspalten sich ändern. In diesem Fall wird
ein neuer Eintrag in die Indextabelle eingefügt und der
alte beim Committen gelöscht. Aus diesem Grunde ist es
auch notwendig, genug Speicherplatz zu reservieren, um
selbst die größten Transaktionen von Anwendungen, die
diesen Cluster nutzen, noch behandeln zu können. Wenige
große Transaktionen auszuführen ist jedenfalls nicht
besser, als viele kleine zu verwenden. Dafür gibt es
folgende Gründe:
Große Transaktionen sind nicht schneller als kleinere.
Wenn eine Transaktion scheitert, müssen bei großen Transaktionen mehr Operationen wiederholt werden, weil sie verloren gegangen sind.
Große Transaktionen belegen mehr Speicherplatz.
Der Standardwert für das DataMemory
beträgt 80 Mbyte und der Mindestwert 1 Mbyte. Es gibt
keinen Höchstwert, aber in der Praxis muss die
Maximalgröße natürlich so angepasst werden, dass der
Prozess nicht anfängt, auf die Platte zu schreiben, wenn
das Limit erreicht wird. Dieses Limit hängt von der
Größe des auf dem Computer verfügbaren physikalischen
Arbeitsspeichers ab sowie von der Frage, wie viel Speicher
das Betriebssystem einem einzelnen Prozess zuweisen kann.
32-Bit-Betriebssysteme sind generell auf 2 bis 4 Gbyte pro
Prozess beschränkt, während 64-Bit-Betriebssysteme mehr
Speicher verwenden können. Aus diesem Grunde eignen sich
64-Bit-Systeme für große Datenbanken besser. Überdies
ist es möglich, mehrere ndbd-Prozesse
pro Computer auszuführen. Dies kann bei Maschinen mit
mehreren CPUs Vorteile bringen.
IndexMemory
Dieser Parameter gibt an, wie viel Speicher für Hash-Indizes in MySQL Cluster benutzt wird. Hash-Indizes werden immer für Primärschlüsselindizes, eindeutige Indizes und Unique-Constraints verwendet. Achtung: Wenn Sie einen Primärschlüssel und einen eindeutigen Index definieren, werden zwei Indizes angelegt, von denen einer ein Hash-Index ist, der für alle Tupel-Zugriffe, für die Sperren und für die Durchsetzung von Unique-Constraints verwendet wird.
Die Größe des Hash-Indexes beträgt 25 Byte pro Datensatz plus die Größe des Primärschlüssels. Für Primärschlüssel, die mehr als 32 Byte belegen, werden weitere 8 Byte addiert.
Der Standardwert für IndexMemory
beträgt 18 Mbyte, der Mindestwert 1 Mbyte.
Das folgende Beispiel zeigt, wie Speicher für eine Tabelle zugewiesen wird. Betrachten Sie folgende Tabellendefinition:
CREATE TABLE example ( a INT NOT NULL, b INT NOT NULL, c INT NOT NULL, PRIMARY KEY(a), UNIQUE(b) ) ENGINE=NDBCLUSTER;
Für jeden Datensatz sind 12 Byte Daten plus 12 Byte Overhead
zugewiesen. Wenn keine Spalten dabei sind, die Nullwerte
annehmen können, so spart dies 4 Byte Overhead. Außerdem
gibt es auf den Spalten a
und
b
zwei geordnete Indizes, die jeweils
ungefähr 10 Byte pro Datensatz belegen. Auf der Basistabelle
ist ein Primärschlüssel-Hash-Index definiert, der rund 29
Byte pro Datensatz beansprucht. Der Unique-Constraint ist
durch eine separate Tabelle implementiert, die
b
als Primärschlüssel und
a
als eine Spalte verwendet. Diese andere
Tabelle belegt weitere 29 Byte Indexspeicher pro Datensatz in
der example
-Tabelle zuzüglich 8 Byte für
die Datensatzdaten und 12 Byte für den Overhead.
Also benötigen wir für eine Million Datensätze 58 Mbyte für den Indexspeicher, um die Hash-Indizes für den Primärschlüssel und den Unique-Constraint unterbringen zu können. Außerdem benötigen wir 64 Mbyte für die Datensätze der Basistabelle und die Tabelle mit dem eindeutigen Index plus die beiden Tabellen mit dem geordneten Index.
Wie Sie sehen, belegen Hash-Indizes nicht eben wenig Speicherplatz, bieten aber als Ausgleich einen sehr schnellen Datenzugriff. In MySQL Cluster werden sie außerdem für Unique-Constraints verwendet.
Gegenwärtig ist Hashing der einzige Partitionierungsalgorithmus und geordnete Indizes sind lokal für jeden Knoten. Also können geordnete Indizes im Allgemeinen nicht für die Handhabung von Unique-Constraints eingesetzt werden.
Ein wichtiger Punkt sowohl für das
IndexMemory
als auch für das
DataMemory
ist der, dass die Gesamtgröße
der Datenbank die Summe sämtlicher Daten- und Indexspeicher
für jede Knotengruppe ist. Da alle Knotengruppen verwendet
werden, um replizierte Informationen zu speichern, kommen bei
vier Knoten mit zwei Replikas zwei Knotengruppen zustande.
Also stehen jedem Datenknoten insgesamt 2 ×
DataMemory
an Datenspeicher zur Verfügung.
Das DataMemory
und das
IndexMemory
sollten unbedingt für alle
Knoten auf denselben Wert eingestellt werden. Da die Daten
über alle Knoten im Cluster gleichmäßig verteilt sind, kann
für jeden Knoten im Cluster maximal nur so viel Speicher zur
Verfügung stehen wie für den kleinsten Knoten im Cluster.
Die Werte für DataMemory
und
IndexMemory
können zwar geändert werden,
doch ist es riskant, einen von beiden herunterzusetzen: Wenn
Sie dies tun, kann es leicht passieren, dass ein Knoten oder
sogar der gesamte MySQL Cluster aus Mangel an Arbeitsspeicher
nicht mehr starten kann. Das Heraufsetzen dieser Werte ist
zwar schon eher akzeptabel, aber solche Upgrades sollten
ebenso wie jeder Softwareupgrade durchgeführt werden: Zuerst
wird die Konfigurationdatei geändert, dann der
Management-Server neu hochgefahren und zum Schluss werden
nacheinander alle Datenknoten gestartet.
Durch Updates wird nicht mehr Indexspeicherplatz belegt. Einfügungen treten sofort in Kraft, aber Löschungen von Zeilen werden erst dann tatsächlich wirksam, wenn die Transaktion committed wird.
Transaktionsparameter
Die nächsten drei [NDBD]
-Parameter sind
wichtig, weil sie die Anzahl der Paralleltransaktionen und die
Größe der Transaktionen festlegen, die das System
bewältigen kann.
MaxNoOfConcurrentTransactions
stellt ein,
wie viele parallele Transaktionen in einem Knoten möglich
sind. MaxNoOfConcurrentOperations
sagt, wie
viele Datensätze gleichzeitig geändert oder gesperrt werden
können.
Beide Parameter (besonders
MaxNoOfConcurrentOperations
) werden von den
meisten Anwendern an ihre spezifischen Anforderungen angepasst
und nicht auf den Standardwerten belassen. Der Standardwert
ist auf Systeme ausgelegt, die nur kleine Transaktionen
fahren, um zu gewährleisten, dass diese nicht übermäßig
Speicher belegen.
MaxNoOfConcurrentTransactions
Für jede aktive Transaktion im Cluster muss ein Datensatz in einem der Cluster-Knoten stehen. Die Aufgabe, Transaktionen zu koordinieren, teilen sich die Knoten untereinander auf. Die Gesamtzahl der Transaktionsdatensätze im Cluster ist gleich der Anzahl der Transaktionen in einem gegebenen Knoten mal der Anzahl der Knoten im Cluster.
Transaktionsdatensätze werden einzelnen MySQL Servern zugewiesen. Normalerweise ist pro Verbindung mindestens ein Transaktionsdatensatz zugewiesen, der eine beliebige Tabelle in dem Cluster benutzen kann. Daher sollten Sie dafür sorgen, dass in einem Cluster mehr Transaktionsdatensätze als nebenläufige Verbindungen zu allen MySQL Servern im Cluster vorhanden sind.
Dieser Parameter muss für alle Cluster-Knoten auf denselben Wert gesetzt werden.
Dieser Parameter sollte nie geändert werden, da dadurch ein Cluster abstürzen kann. Wenn ein Knoten abstürzt, erstellt ein anderer Knoten (nämlich der älteste überlebende) den Status aller Transaktionen, die im Augenblick des Crashs in dem abgestürzten Knoten abliefen. Daher ist es wichtig, dass dieser Knoten so viele Transaktionsdatensätze wie der abgestürzte Knoten hat.
Der Standardwert ist 4096.
MaxNoOfConcurrentOperations
Diesen Parameter sollte man immer an die Größe und Anzahl der Transaktionen anpassen. Wenn Ihre Transaktionen immer nur wenige Operationen ausführen und nicht viele Datensätze betreffen, besteht kein Anlass, diesen Parameter auf einen hohen Wert zu setzen. Doch für große Transaktionen mit vielen Datensätzen sollten Sie ihn heraufsetzen.
Für jede Transaktion, die Cluster-Daten ändert, werden sowohl im Transaktionskoordinator als auch in den Knoten, wo die eigentlichen Änderungen eintreten, Aufzeichnungen gemacht. Diese Einträge enthalten Statusinformationen, die erforderlich sind, um die UNDO-Datensätze für Rollback, Lock Queues und andere Sätze zu erhalten.
Dieser Parameter sollte auf die Anzahl der in Transaktionen gleichzeitig zu ändernden Datensätze, dividiert durch die Anzahl der Datenknoten im Cluster, gesetzt werden. In einem Cluster, der 4 Datenknoten hat und 1.000.000 nebenläufige Updates bewältigen soll, beträgt dieser Wert 1.000.000 / 4 = 250.000.
Auch durch Leseanfragen, die Sperren setzen, werden Operationseinträge erzeugt. Für diese wird in den einzelnen Knoten etwas mehr Speicherplatz reserviert, um mit Fällen umgehen zu können, in denen die Verteilung über die Knoten nicht perfekt ist.
Wenn Abfragen den eindeutigen Hash-Index verwenden, gibt es sogar zwei Operationseinträge pro Transaktionsdatensatz. Der erste stellt den Lesevorgang in der Indextabelle dar und der zweite betrifft die Operation auf der Basistabelle.
Der Standardwert ist 32768.
Dieser Parameter steuert in Wirklichkeit zwei separat konfigurierbare Werte. Der erste gibt an, wie viele Operationseinträge mit dem Transaktionskoordinator gesetzt werden, und der zweite, wie viele Operationseinträge lokal in der Datenbank gemacht werden.
Eine sehr große Transaktion auf einem Cluster mit 8
Knoten erfordert im Transaktionskoordinator so viele
Operationseinträge, wie es Lese-, Änderungs- und
Einfügungsoperationen in der Transaktion gibt. Dabei
werden die Operationseinträge allerdings über alle 8
Knoten verteilt. Also sollten die beiden Teile getrennt
konfiguriert werden, wenn das System auf eine einzelne
sehr große Transaktion vorbereitet werden soll. Anhand
von MaxNoOfConcurrentOperations
wird
immer berechnet, wie viele Operationseinträge es in dem
Teil des Knotens gibt, wo der Transaktionskoordinator
sitzt.
Zudem ist es wichtig, eine ungefähre Vorstellung des Speicherbedarfs für die Operationseinträge zu haben: Diese belegen pro Eintrag ungefähr 1 Kbyte.
MaxNoOfLocalOperations
Nach Voreinstellung wird dieser Parameter zu 1,1 ×
MaxNoOfConcurrentOperations
berechnet.
Dies eignet sich für Systeme mit vielen simultanen
Transaktionen, die jedoch alle nicht sehr umfangreich
sind. Wenn Sie immer nur eine einzige, dafür aber sehr
große Transaktion und zudem viele Knoten haben, sollten
Sie den Standardwert dieses Parameters mit einem
geeigneteren überschreiben.
Temporärer Speicher für Transaktionen
Die nächste Gruppe von [NDBD]
-Parametern
entscheidet über die temporäre Speicherung, die zur
Ausführung einer Anweisung in einer Cluster-Transaktion
verwendet wird. Alle Datensätze werden freigegeben, wenn die
Anweisung abgeschlossen ist und der Cluster auf den Commit-
oder Rollback-Befehl wartet.
Die Standardwerte für diese Parameter sind für die meisten Situationen passend. Wenn Sie jedoch Transaktionen auf sehr vielen Zeilen oder mit sehr vielen Operationen ausführen müssen, müssen Sie diese Werte eventuell heraufsetzen, um eine bessere Parallelverarbeitung im System zu ermöglichen. Sollten Ihre Transaktionen dagegen relativ klein sein, so können Sie durch Reduzieren dieser Werte Speicherplatz sparen.
MaxNoOfConcurrentIndexOperations
Für Anfragen, die einen eindeutigen Hash-Index verwenden,
wird während der Ausführungsphase eine weitere Gruppe
von Operationseinträgen erstellt. Dieser Parameter stellt
die Größe dieses Pools an Einträgen ein. Also wird
dieser Eintrag nur während der Ausführung eines Teils
einer Anfrage zugewiesen. Sobald dieser Teil abgeschlossen
ist, wird der Eintrag wieder freigegeben. Der Zustand, in
dem Transaktionen abgebrochen oder committet werden, wird
von den normalen Operationseinträgen behandelt, deren
Pool-Größe durch den Parameter
MaxNoOfConcurrentOperations
eingestellt
wird.
Dieser Parameter hat den Standardwert 8192. Nur in seltenen Fällen, in denen extrem hoher Parallelismus auftritt und eindeutige Hash-Indizes verwendet werden, kann es erforderlich sein, diesen Wert zu erhöhen. Auch ein kleinerer Wert ist möglich und kann Speicherplatz sparen, wenn der DBA sich sicher ist, dass für den Cluster kein besonders hoher Parallelismus erforderlich ist.
MaxNoOfFiredTriggers
Der Standardwert von
MaxNoOfFiredTriggers
ist 4000 und
dürfte für die meisten Situationen ausreichen. In
manchen Fällen kann er sogar heruntergesetzt werden, wenn
der DBA sich sicher ist, dass in dem Cluster kein
besonderer Parallelismus auftritt.
Wenn eine Operation ausgeführt wird, wird ein Datensatz angelegt, der einen eindeutigen Hash-Index beeinflusst. Eine Einfügung oder Löschung eines Eintrags in einer Tabelle mit eindeutigen Hash-Indizes oder eine Aktualisierung einer Spalte, die Teil eines eindeutigen Hash-Indexes ist, löst eine entsprechende Einfügung oder Löschung in der Indextabelle aus. Der resultierende Eintrag wird verwendet, um diese Indextabellenoperation zu repräsentieren, so lange die Originaloperation, die ihn veranlasste, noch nicht abgeschlossen ist. Diese Operation ist zwar kurzlebig, kann aber dennoch viele Einträge in ihrem Pool benötigen, wenn viele parallele Schreiboperationen auf einer Basistabelle stattfinden, die eine Reihe von eindeutigen Hash-Indizes enthält.
TransactionBufferMemory
Dieser Parameter betrifft den Speicher zum Nachvollziehen von Operationen, die bei der Aktualisierung von Indextabellen und beim Lesen von eindeutigen Indizes auftreten. In diesem Arbeitsspeicherbereich werden die Schlüssel- und Spalteninformationen für diese Operationen gespeichert. Nur in seltenen Fällen muss dieser Parameter auf einen anderen als seinen Standardwert gesetzt werden.
Normale Lese- und Schreiboperationen nutzen einen
ähnlichen Puffer, der sogar noch kurzfristiger arbeitet.
Der zur Übersetzungszeit benutzte Parameter
ZATTRBUF_FILESIZE
(aus
ndb/src/kernel/blocks/Dbtc/Dbtc.hpp
)
ist auf 4.000 × 128 Byte (500 Kbyte) eingestellt.
Ein ähnlicher Puffer für die Schlüsselinformationen,
nämlich ZDATABUF_FILESIZE
(ebenfalls
in Dbtc.hpp
), bietet 4.000 × 16
= 62,5 Kbyte Speicherplatz. Dbtc
ist
das Modul, welches sich um die Transaktionskoordination
kümmert.
Scans und Datenpuffer
Das Modul Dblqh
hat noch weitere
[NDBD]
-Parameter (in
ndb/src/kernel/blocks/Dblqh/Dblqh.hpp
),
die sich auf Lese- und Änderungsoperationen auswirken.
Hierzu gehören die ZATTRINBUF_FILESIZE
,
die auf 10.000 × 128 Byte (1250 Kbyte) voreingestellt
ist, und ZDATABUF_FILE_SIZE
mit dem
Standardwert 10.000 * 16 Byte (rund 156 Kbyte) Speicherplatz
im Puffer. Bisher haben weder Anwender noch die Ergebnisse
unserer umfangreichen Tests je eine Erhöhung dieser
Compile-Time-Limits nahe gelegt.
Der Standardwert für
TransactionBufferMemory
ist 1 Mbyte.
MaxNoOfConcurrentScans
Dieser Parameter stellt ein, wie viele parallele Scans im
Cluster ausgeführt werden können. Jeder
Transaktionskoordinator kann so viele parallele Scans
bewältigen, wie dieser Parameter festlegt. Jede
Scananfrage wird durch paralleles Scannen aller
Partitionen ausgeführt. Jeder Partitionsscan verwendet
einen Scandatensatz in dem Knoten, auf dem sich die
Partition befindet, wobei die Anzahl der Einträge der
Wert dieses Parameters mal die Anzahl der Knoten ist. Der
Cluster sollte in der Lage sein,
MaxNoOfConcurrentScans
nebenläufige
Scans auf allen Knoten im Cluster zu bewältigen.
Scans werden tatsächlich in zwei Fällen ausgeführt: erstens wenn kein Hash-Index oder geordneter Index für die Ausführung der Anfrage vorliegt; in diesem Fall wird die Anfrage mithilfe eines vollständigen Tabellenscans ausgeführt. Zweitens, wenn für die Anfrage zwar kein Hash-Index, aber ein geordneter Index vorhanden ist, denn die Verwendung eines geordneten Indexes erfordert zusätzlich einen parallelen Bereichsscan. Da die Reihenfolge nur auf den lokalen Partitionen beibehalten wird, muss der Indexscan auf allen Partitionen ausgeführt werden.
Der Standardwert von
MaxNoOfConcurrentScans
ist 256 und der
Höchstwert beträgt 500.
Dieser Parameter gibt an, wie viele Scans im
Transaktionskoordinator möglich sind. Wenn keine Anzahl
für lokale Scandatensätze vorgegeben ist, wird sie als
MaxNoOfConcurrentScans
mal der Anzahl
der Datenknoten im System berechnet.
MaxNoOfLocalScans
Gibt die Anzahl der lokalen Scandatensätze an, wenn viele Scans nicht vollständig parallelisiert sind.
BatchSizePerLocalScan
Dieser Parameter wird genutzt, um zu berechnen, wie viele Sperrdatensätze erforderlich sind, um viele nebenläufige Scanoperationen zu handhaben.
Der Standardwert beträgt 64; dieser Wert steht in enger
Verbindung zur in den SQL-Knoten definierten
ScanBatchSize
.
LongMessageBuffer
Dies ist ein interner Puffer für die Weitergabe von Nachrichten in oder zwischen Knoten. Der Wert muss zwar wahrscheinlich nie geändert werden, ist aber dennoch konfigurierbar. Sein Standardwert beträgt 1 Mbyte.
Logging und Checkpointing
Die folgenden [NDBD]
-Paramater steuern das
Verhalten in Bezug auf Logs und Checkpoints.
NoOfFragmentLogFiles
Dieser Parameter stellt die Größe der REDO-Logdateien des Knotens ein. REDO-Logdateien sind ringförmig organisiert, wobei es außerordentlich wichtig ist, dass die erste und die letzte Logdatei (auch „Head“ und „Tail“ genannt) nicht aufeinander treffen. Wenn sich diese beiden zu stark annähern, fängt der Knoten an, alle Transaktionen abzubrechen, in denen Updates vorkommen, da kein Platz für neue Logeinträge mehr vorhanden ist.
Ein REDO-Logeintrag wird erst gelöscht, wenn seit seiner Einfügung drei lokale Checkpoints erreicht wurden. Die Häufigkeit der Checkpoints wird durch eigene Konfigurationsparameter festgelegt, die an anderer Stelle in diesem Kapitel beschrieben werden.
Der Standardparameterwert beträgt 8, also 8 mal 4
16-Mbyte-Dateien oder insgesamt 512 Mbyte. Mit anderen
Worten: Der Speicher für die REDO-Logs muss in Blöcken
zu 64 Mbyte zugewiesen werden. In Szenarien, in denen
viele Updates erforderlich sind, kann es erforderlich
werden, den Wert von
NoOfFragmentLogFiles
sogar auf 300 oder
noch mehr zu setzen, um genügend Platz für die REDO-Logs
zu schaffen.
Wenn das Checkpointing zu langsam läuft und so viele
Schreibvorgänge in der Datenbank stattfinden, dass die
Logdateien voll laufen und der Logtail nicht abgetrennt
werden kann, ohne die Wiederherstellung zu gefährden,
können Änderungstransaktionen mit dem internen
Fehlercode 410 (Out of log file space
temporarily
) abgebrochen werden. Dies dauert so
lange, bis ein Checkpoint abgeschlossen ist und der
Logtail vorrücken kann.
MaxNoOfSavedMessages
Dieser Parameter stellt ein, wie viele Trace-Dateien maximal gespeichert werden, ehe die alten überschrieben werden. Trace-Dateien werden angelegt, wenn der Knoten aus irgendeinem Grund abstürzt.
Der Standardwert sind 25 Trace-Dateien.
Metadatenobjekte
Die folgenden [NDBD]
-Parameter legen die
Größen der Pools für Metadatenobjekte fest, also wie viele
Attribute, Tabellen, Indizes und Trigger-Objekte maximal für
die Indizes, Ereignisse und Replikation zwischen Clustern zur
Verfügung stehen. Beachten Sie, dass diese Werte lediglich
„Richtwerte“ für den Cluster sind. Werden sie
nicht gesetzt, so treten die unten angegebenen Standardwerte
in Kraft.
MaxNoOfAttributes
Gibt an, wie viele Attribute im Cluster definiert werden können.
Der Standardwert beträgt 1.000 und der kleinstmögliche Wert 32. Einen Höchstwert gibt es nicht. Jedes Attribut belegt rund 200 Byte Speicherplatz pro Knoten, da alle Metadaten vollständig auf den Servern repliziert werden.
Bei der Einstellung von
MaxNoOfAttributes
müssen Sie sich
schon im Voraus klar machen, wie viele ALTER
TABLE
-Anweisungen Sie wohl in Zukunft ausführen
möchten. Denn wenn Sie ALTER TABLE
auf
einer Cluster-Tabelle ausführen, werden dreimal so viele
Attribute wie in der Originaltabelle verwendet. Wenn eine
Tabelle beispielsweise 100 Attribute benötigt und Sie in
der Lage sein möchten, diese Tabelle später noch zu
ändern, müssen Sie den Wert von
MaxNoOfAttributes
auf 300 setzen. Wenn
wir voraussetzen, dass Sie alle gewünschten Tabellen ohne
irgendwelche Probleme anlegen können, sollten Sie
MaxNoOfAttributes
sicherheitshalber
doppelt so viele Attribute hinzufügen, wie die größte
Tabelle besitzt. Außerdem sollten Sie nach der
Konfiguration des Parameters mit einem echten
ALTER TABLE
prüfen, ob diese Zahl
ausreicht. Wenn die Anweisung scheitert, müssen Sie
MaxNoOfAttributes
um ein anderes
Vielfaches des ursprünglichen Werts erhöhen und erneut
testen.
MaxNoOfTables
Für jede Tabelle, jeden eindeutigen Hash-Index und jeden geordneten Index wird ein Tabellenobjekt zugewiesen. Dieser Parameter stellt ein, wie viele Tabellenobjekte der Cluster insgesamt maximal haben kann.
Für jedes Attribut vom Typ BLOB
wird
eine zusätzliche Tabelle verwendet, um einen Großteil
der BLOB
-Daten zu speichern. Auch diese
Tabellen müssen beim Festlegen der Gesamtzahl der
Tabellen berücksichtigt werden.
Dieser Parameter ist standardmäßig auf 128 eingestellt. Sein Mindestwert beträgt 8 und sein Höchstwert 1600. Jedes Tabellenobjekt belegt rund 20 Kbyte pro Knoten.
MaxNoOfOrderedIndexes
Für jeden geordneten Index im Cluster wird ein Objekt zugewiesen, das beschreibt, was hier indiziert wird und in welchen Speichersegmenten. Nach Voreinstellung ist jeder so definierte Index ein geordneter Index. Jeder eindeutige Index und jeder Primärschlüssel besitzt sowohl einen geordneten als auch einen Hash-Index.
Dieser Parameter hat den Standardwert 128. Jedes Objekt belegt ungefähr 10 Kbyte pro Knoten.
MaxNoOfUniqueHashIndexes
Für jeden eindeutigen Index, der kein Primärschlüssel
ist, wird eine spezielle Tabelle zugewiesen, die den
eindeutigen Schlüssel auf den Primärschlüssel der
indizierten Tabelle abbildet. Nach Voreinstellung wird
außerdem für jeden eindeutigen Index ein geordneter
Index definiert. Wenn Sie dies verhindern möchten,
müssen Sie beim Definieren des eindeutigen Indexes die
Option USING HASH
angeben.
Der Standardwert ist 64. Jeder Index belegt ungefähr 15 Kbyte pro Knoten.
MaxNoOfTriggers
Für jeden eindeutigen Hash-Index werden interne Update-, Insert- und Delete-Trigger zugewiesen. (Das bedeutet, dass für jeden solchen Index drei Trigger erzeugt werden.) Ein geordneter Index erfordert dagegen nur ein einziges Trigger-Objekt. Auch Datensicherungen benötigen drei Trigger-Objekte für jede normale Tabelle im Cluster.
Hinweis: Wenn Replikation zwischen Clustern unterstützt wird, sind auch dafür interne Trigger erforderlich.
Dieser Parameter stellt die Höchstzahl der Trigger-Objekte im Cluster ein.
Der Standardwert ist 768.
MaxNoOfIndexes
Dieser Parameter ist in MySQL 5.1 veraltet.
Bitte verwenden Sie stattdessen
MaxNoOfOrderedIndexes
und
MaxNoOfUniqueHashIndexes
.
Dieser Parameter wird nur von eindeutigen Hash-Indizes verwendet. Für jeden derartigen Index, der im Cluster definiert ist, muss ein Datensatz in diesem Pool vorhanden sein.
Der Standardwert dieses Parameters ist 128.
Boolesche Parameter
Das Verhalten der Datenknoten hängt auch von einigen
booleschen [NDBD]
-Parametern ab. Um diese
Parameter auf TRUE
einzustellen, setzen Sie
sie auf 1
oder Y
, und um
sie auf FALSE
einzustellen, setzen Sie sie
auf 0
oder N
.
LockPagesInMainMemory
Viele Betriebssysteme, darunter auch Solaris und Linux, können einen Prozess im Arbeitsspeicher sperren und dadurch verhindern, dass er auf die Festplatte schreibt. Das kann dabei helfen, die Echtzeitfähigkeiten eines Clusters zu bewahren.
Dieses Feature ist nach Voreinstellung deaktiviert.
StopOnError
Dieser Parameter zeigt an, ob ein ndbd-Prozess anhalten oder automatisch neu starten soll, wenn eine Fehlerbedingung auftritt.
Dieses Feature ist nach Voreinstellung aktiviert.
Diskless
Wenn Tabellen im MySQL Cluster als diskless definiert werden, werden für sie weder Checkpoints auf der Festplatte noch Logeinträge erstellt. Solche Tabellen existieren nur im Hauptspeicher. Infolgedessen überleben weder die Tabellen selbst noch die in ihnen enthaltenen Datensätze einen Absturz. Allerdings können Sie im Diskless-Modus ndbd auch auf einem Computer ohne Festplatte ausführen.
Wichtig: Dieses Feature lässt den gesamten Cluster im Diskless-Modus laufen.
Wenn dieses Feature aktiviert ist, werden zwar Datensicherungen ausgeführt, aber keine wirklichen Sicherungsdaten gespeichert.
Diskless
ist nach Voreinstellung
deaktiviert.
RestartOnErrorInsert
Dieses Feature ist nur beim Bauen der Debugversion zugänglich, wo es möglich ist, zu Testzwecken Fehler in die Ausführung einzelner Codeblöcke einzubauen.
Dieses Feature ist nach Voreinstellung deaktiviert.
Timeouts, Intervalle und Auslagerung von Daten auf die Festplatte
Mehrere [NDBD]
-Parameter stehen zur
Verfügung, um Timeouts und Intervalle zwischen verschiedenen
Aktionen in Cluster-Datenknoten festzulegen. Die Timeout-Werte
werden, sofern nicht explizit etwas anderes gesagt wird, in
Millisekunden angegeben.
TimeBetweenWatchDogCheck
Damit der Haupt-Thread nicht in einer Endlosschleife gefangen bleiben kann, wird er durch einen so genannten „Wachhund“ (engl. Watchdog) überprüft. Dieser Parameter gibt an, wie viele Millisekunden zwischen den Prüfungen verstreichen. Wenn der Prozess nach drei Prüfungen immer noch in demselben Zustand verharrt, wird er vom Watchdog-Thread beendet.
Dieser Parameter lässt sich leicht ändern, sei es zu experimentellen Zwecken oder um ihn an die lokalen Bedingungen anzupassen. Er kann auch für jeden Knoten separat gesetzt werden, wofür es allerdings keinen vernünftigen Grund gibt.
Der Standard-Timeout-Wert beträgt 4.000 Millisekunden (4 Sekunden).
StartPartialTimeout
Dieser Parameter legt fest, wie lange der Cluster auf das Hochfahren aller Speicherknoten wartet, bevor die Initialisierungsroutine für den Cluster aufgerufen wird. Dieser Timeout-Wert soll nach Möglichkeit verhindern, dass ein Cluster nur teilweise hochgefahren wird.
Der Standardwert beträgt 30.000 Millisekunden (30 Sekunden). Mit 0 wird der Timeout ausgeschaltet, sodass der Cluster nur starten kann, wenn alle Knoten zur Verfügung stehen.
StartPartitionedTimeout
Wenn der Cluster nach dem Abwarten von
StartPartialTimeout
Millisekunden
startbereit ist, sich aber möglicherweise immer noch in
einem partitionierten Zustand befindet, wartet er ab, bis
auch dieser Timeout verstrichen ist.
Der Standardwert für diesen Timeout beträgt 60.000 Millisekunden (60 Sekunden).
StartFailureTimeout
Wenn ein Datenknoten seine Startsequenz in der durch diesen Parameter gesetzten Zeit nicht abgeschlossen hat, scheitert sein Start. Wenn Sie den Parameter auf 0 setzen, gibt es keinen Timeout für den Datenknoten.
Der Standardwert beträgt 60.000 Millisekunden (60 Sekunden). Für Datenknoten mit extrem großen Datenmengen sollten Sie diesen Parameter heraufsetzen. Wenn ein Speicherknoten beispielsweise mehrere Gigabytes an Daten enthält, könnten sogar 10 bis 15 Minuten (600.000 bis 1.000.000 Millisekunden) für einen Neustart des Knotens erforderlich sein.
HeartbeatIntervalDbDb
Heartbeats (Herzschläge) sind eines der wichtigsten Mittel, um herauszufinden, ob Knoten abgestürzt sind. Dieser Parameter zeigt an, wie oft Heartbeat-Signale gesandt und empfangen werden sollten. Wenn drei aufeinander folgende Heartbeats ausgefallen sind, wird der Knoten für tot erklärt. Also beträgt die maximale Zeitspanne für die Entdeckung eines Scheiterns mit dem Heartbeat-Mechanismus das Vierfache des Heartbeat-Intervalls.
Das Standardintervall für Heartbeats dauert 1.500 Millisekunden (1,5 Sekunden). Dieser Parameter darf nicht drastisch verändert werden und sollte für alle Knoten ähnlich eingestellt werden. Wenn ein Knoten 5.000-Millisekunden-Intervalle und der beobachtende Knoten 1.000 Millisekunden verwendet, wird der mit den längeren Intervallen natürlich sehr schnell für tot erklärt. Dieser Parameter kann während eines Online-Softwareupgrades geändert werden, allerdings nur in kleinen Inkrementen.
HeartbeatIntervalDbApi
Jeder Datenknoten sendet Heartbeat-Signale an jeden MySQL
Server (SQL-Knoten), um sich zu vergewissern, dass der
Kontakt noch besteht. Wenn ein MySQL Server seinen
Heartbeat nicht rechtzeitig absendet, wird er als
„tot“ erklärt und alle seine laufenden
Transaktionen werden beendet und seine Ressourcen
freigegeben. Ein SQL-Knoten kann sich erst wieder
verbinden, wenn alle von der vorherigen MySQL-Instanz
angestoßenen Aktivitäten abgeschlossen wurden. Es gilt
dasselbe Kriterium der drei Heartbeats wie unter
HeartbeatIntervalDbDb
beschrieben.
Das Standardintervall beträgt 1.500 Millisekunden (1,5 Sekunden). Dieses Intervall kann zwischen einzelnen Datenknoten variieren, da jeder Speicherknoten die mit ihm verbundenen MySQL Server unabhängig von allen anderen Datenknoten beobachtet.
TimeBetweenLocalCheckpoints
Dieser Parameter ist insofern eine Ausnahmeerscheinung, als er nicht eine Wartezeit vor dem Starten eines neuen lokalen Checkpoints angibt, sondern gewährleisten soll, dass keine lokalen Checkpoints in einem Cluster ausgeführt werden, in dem nur relativ wenige Updates auftreten. In den meisten Clustern mit hohen Update-Raten wird ein neuer lokaler Checkpoint normalerweise unmittelbar nach Abschluss des vorherigen gestartet.
Der Umfang aller seit dem Start des vorherigen lokalen Checkpoints ausgeführten Schreiboperationen wird addiert. Dieser Parameter ist ebenfalls außergewöhnlich, da er als Basis-2-Logarithmus der Anzahl der 4-Byte-Wörter spezifiziert ist. Der Standardwert von 20 bedeutet also Schreiboperationen im Umfang von 4 Mbyte (4 × 220), 21 würde 8 Mbyte bedeuten, und so weiter bis zum Maximalwert 31, der 8 Gbyte Schreiboperationen entsprechen würde.
Alle Schreiboperationen im Cluster werden addiert. Wenn
TimeBetweenLocalCheckpoints
auf 6 oder
weniger gesetzt wird, bedeutet dies, dass pausenlos lokale
Checkpoints ausgeführt werden, unabhängig von der
Arbeitslast des Clusters.
TimeBetweenGlobalCheckpoints
Wenn eine Transaktion committet wird, dann im Hauptspeicher in allen Knoten, auf denen die Daten gespiegelt werden. Doch die Transaktionslog-Einträge werden durch den Commit-Befehl nicht auf die Platte zurückgeschrieben. Denn wenn die Transaktion auf mindestens zwei autonomen Hostcomputern sicher committet wurde, müsste dies ausreichen, um die Haltbarkeit der Daten zu gewährleisten.
Wichtig ist außerdem, dass das System auch im schlimmsten Fall, nämlich dem Absturz eines kompletten Clusters, die Oberhand behält. Um das zu gewährleisten, werden alle Transaktionen, die in einem gegebenen Zeitraum stattfinden, in einen globalen Checkpoint geladen. Diesen kann man sich als eine Menge von committeten und auf die Festplatte geschriebenen Transaktionen vorstellen. Mit anderen Worten: Transaktionen werden im Rahmen des Commit-Prozesses in eine globale Checkpoint-Gruppe gelegt. Später werden die Logeinträge dieser Gruppe auf die Festplatte zurückgeschrieben und die gesamte Transaktionsgruppe auf allen Computern im Cluster sicher auf die Festplatte geschrieben.
Dieser Parameter legt das Zeitintervall zwischen den globalen Checkpoints fest. Der Standardwert beträgt 2.000 Millisekunden.
TimeBetweenInactiveTransactionAbortCheck
Um Timeouts zu behandeln, wird für jede Transaktion einmal pro in diesem Parameter angegebenem Intervall ein Timer nachgeschaut. Wenn also dieser Parameter auf 1.000 Millisekunden gesetzt ist, wird einmal pro Sekunde jede Transaktion auf einen Timeout überprüft.
Der Standardwert beträgt 1.000 Millisekunden (1 Sekunde).
TransactionInactiveTimeout
Dieser Parameter gibt an, wie viel Zeit maximal zwischen zwei Operationen einer Transaktion verstreichen darf, ehe die Transaktion abgebrochen wird.
Der Standardwert dieses Parameters ist null (kein Timeout). Für eine Echtzeitdatenbank, die gewährleisten muss, dass keine Transaktion irgendwelche Sperren zu lange aufrechterhält, sollte dieser Parameter auf einen sehr kleinen Wert gesetzt werden. Die Maßeinheit sind Millisekunden.
TransactionDeadlockDetectionTimeout
Wenn ein Knoten eine Abfrage ausführt, zu der eine Transaktion gehört, wartet er auf Antwort von den anderen Knoten des Clusters, ehe er fortfährt. Bleibt eine Antwort aus, kann das folgende Gründe haben:
Der Knoten ist „tot“.
Die Operation steckt in einer Warteschlange von Sperranforderungen.
Der Knoten, der die Aktion ausführen sollte, könnte heftig überlastet sein.
Dieser Timeout-Parameter legt fest, wie lange der Transaktionskoordinator darauf wartet, dass ein anderer Knoten die Anfrage ausführt, ehe er die Transaktion abbricht. Er ist wichtig, um den Absturz eines Knotens behandeln oder Deadlocks feststellen zu können. Wenn Sie ihn zu hoch setzen, können Situationen mit gescheiterten Knoten oder Deadlocks unangenehme Konsequenzen haben.
Der Standardwert für den Timeout beträgt 1.200 Millisekunden (1,2 Sekunden).
NoOfDiskPagesToDiskAfterRestartTUP
Wenn ein lokaler Checkpoint ausgeführt wird, schreibt der
Algorithmus alle Datenseiten auf die Festplatte zurück.
Wenn Sie dies aber einfach ohne irgendwelche Moderation so
rasch wie möglich tun, riskieren Sie eine Überlastung
von Prozessoren, Netzwerken und Platten. Um die
Schreibgeschwindigkeit zu steuern, gibt dieser Parameter
an, wie viele Seiten pro 100 Millisekunden geschrieben
werden dürfen. In diesem Zusammenhang ist eine
„Seite“ als 8 Kbyte definiert. Dieser
Parameter wird in Einheiten von 80 Kbyte pro Sekunde
angegeben; wenn Sie also
NoOfDiskPagesToDiskAfterRestartTUP
auf
den Wert 20
setzen, werden bei einem
lokalen Checkpoint 1,6 Mbyte an Datenseiten pro Sekunde
auf die Platte geschrieben. Dieser Wert umfasst auch die
Erstellung der UNDO-Logs für die Datenseiten. Folglich
setzt dieser Parameter die Obergrenze für
Schreibvorgänge aus dem Data Memory. Für die
UNDO-Logeinträge für Indexseiten ist der Parameter
NoOfDiskPagesToDiskAfterRestartACC
da.
(Mehr über Indexseiten können Sie im Eintrag
IndexMemory
nachlesen.)
Kurz: Dieser Parameter gibt an, wie schnell lokale
Checkpoints ausgeführt werden. Er arbeitet zusammen mit
NoOfFragmentLogFiles
,
DataMemory
und
IndexMemory
.
Der Standardwert ist 40 (3,2 Mbyte Datenseiten pro Sekunde).
NoOfDiskPagesToDiskAfterRestartACC
Dieser Parameter verwendet dieselbe Maßeinheit wie
NoOfDiskPagesToDiskAfterRestartTUP
und
verhält sich auch ganz ähnlich, setzt jedoch die
Obergrenze für das Schreiben von Indexseiten aus dem
Index Memory.
Der Standardwert dieses Parameters beträgt 20 (1,6 Mbyte Index Memory pro Sekunde).
NoOfDiskPagesToDiskDuringRestartTUP
Dieser Parameter funktioniert ähnlich wie
NoOfDiskPagesToDiskAfterRestartTUP
und
NoOfDiskPagesToDiskAfterRestartACC
,
allerdings im Hinblick auf lokale Checkpoints, die in
einem Knoten bei dessen Neustart ausgeführt werden. Ein
lokaler Checkpoint wird immer bei jeglichem Neustart eines
Knotens ausgeführt. Während eines Knoten-Neustarts
können Daten schneller als in anderen Situationen auf die
Platte geschrieben werden, da zu diesem Zeitpunkt im
Knoten noch weniger andere Aktivitäten stattfinden.
Dieser Parameter bezieht sich auf die Seiten, die aus dem Data Memory geschrieben werden.
Der Standardwert beträgt 40 (3,2 Mbyte pro Sekunde).
NoOfDiskPagesToDiskDuringRestartACC
Gibt an, wie viele Seiten des Index Memorys während des lokalen Checkpointings beim Neustart eines Knotens auf die Festplatte geschrieben werden können.
Wie bei
NoOfDiskPagesToDiskAfterRestartTUP
und
NoOfDiskPagesToDiskAfterRestartACC
werden auch für diesen Parameter die Werte als
8-Kbyte-Seiten angegeben, die pro 100 Millisekunden
geschrieben werden (80 Kbyte/Sekunde).
Der Standardwert beträgt 20 (1,6 Mbyte pro Sekunde).
ArbitrationTimeout
Dieser Parameter legt fest, wie lange Datenknoten darauf warten sollen, dass der Arbitrator auf eine Arbitration-Nachricht antwortet. Wird dieser Wert überschritten, kann man davon ausgehen, dass sich das Netzwerk aufgespalten hat.
Der Standardwert beträgt 1000 Millisekunden (1 Sekunde).
Buffering und Logging
Es stehen auch mehrere
[NDBD]
-Konfigurationsparameter zur
Verfügung, die den früheren Compile-Time-Parametern
entsprechen. Mit ihnen kann der fortgeschrittene Anwender die
von Knotenprozessen genutzten Ressourcen besser steuern und
diverse Puffergrößen seinen Bedürfnissen anpassen.
Diese Puffer werden als Frontends für das Dateisystem
verwendet, wenn Logeinträge auf die Platte geschrieben
werden. Wenn der Knoten im Diskless-Modus läuft, können
diese Parameter ungestraft auf ihre Mindestwerte gesetzt
werden, da die Dateisystem-Abstraktionsschicht der
Speicher-Engine NDB
das Schreiben auf der
Festplatte „vorgaukelt“.
UndoIndexBuffer
Der UNDO-Indexpuffer, dessen Größe mit diesem Parameter
eingestellt wird, wird während eines lokalen Checkpoints
benutzt. Das Recovery-Schema der Speicher-Engine
NDB
beruht auf der Konsistenz der
Checkpoints und einem funktionierenden REDO-Log. Um einen
konsistenten Checkpoint zu erhalten, ohne gleich
sämtliche Schreibvorgänge im System zu blockieren, ist
während der Erstellung des lokalen Checkpoints das
UNDO-Logging eingeschaltet. UNDO-Logging wird immer nur
auf einem einzigen Tabellenfragment eingeschaltet. Diese
Optimierung ist möglich, da die Tabellen vollständig im
Hauptspeicher liegen.
Der UNDO-Indexpuffer wird für die Änderungen am Primärschlüssel-Hash-Index benutzt. Einfügungen und Löschungen führen zu Umstellungen im Hash-Index. Die Speicher-Engine NDB schreibt UNDO-Logeinträge, die alle physikalischen Änderungen einer Indexseite zuordnen, sodass sie beim Systemstart rückgängig gemacht werden können. Außerdem protokolliert sie zu Beginn eines lokalen Checkpoints alle aktiven Einfügeoperationen für jedes Fragment.
Lese- und Änderungsoperationen setzen Sperrbits und aktualisieren einen Header im Hash-Indexeintrag. Diese Änderungen behandelt der Page-Writing-Algorithmus so, dass sichergestellt ist, dass diese Operationen kein UNDO-Logging benötigen.
Dieser Puffer ist nach Voreinstellung auf 2 Mbyte gesetzt.
Sein Mindestwert 1 Mbyte dürfte für die meisten
Anwendungen ausreichen. Für Anwendungen, die besonders
große oder zahlreiche Einfüge- und Löschoperationen in
Verbindung mit großen Transaktionen und umfangreichen
Primärschlüsseln vornehmen, kann es erforderlich sein,
diesen Puffer zu vergrößern. Wenn er zu klein ist,
meldet die Speicher-Engine NDB den internen Fehlercode 677
(Index UNDO buffers overloaded
).
UndoDataBuffer
Dieser Parameter stellt die Größe des UNDO-Datenpuffers ein, der ähnlich wie der UNDO-Indexpuffer funktioniert, aber für das Data Memory statt des Index Memorys verwendet wird. Dieser Puffer wird in der lokalen Checkpoint-Phase eines Fragments für Einfüge-, Lösch- und Änderungsoperationen benötigt.
Da UNDO-Logeinträge immer größer werden, je mehr Operationen protokolliert werden, ist auch dieser Puffer größer als sein Gegenstück für das Index Memory, nämlich nach Voreinstellung 16 Mbyte.
Dieser Speicher kann für manche Anwendungen unnötig groß sein. In solchen Fällen können Sie den Wert bis auf das Minimum von 1 Mbyte heruntersetzen.
Es ist nur selten erforderlich, diesen Puffer zu vergrößern. Wenn es dennoch einmal getan werden muss, so sollten Sie vorher prüfen, ob Ihre Festplatten die Last der Updates in der Datenbank überhaupt bewältigen können. Wenn nicht genügend Platz auf der Festplatte vorhanden ist, können Sie dies auch durch das Vergrößern dieses Puffers nicht ändern.
Wenn dieser Puffer zu klein ist und verstopft, meldet die Speicher-Engine NDB den internen Fehlercode 891 (Data UNDO buffers overloaded).
RedoBuffer
Auch alle Update-Aktivitäten müssen protokolliert werden. Das REDO-Log ermöglicht es, die Updates bei einem späteren Neustart des Systems erneut laufen zu lassen. Der Recovery-Algorithmus von NDB verwendet einen „Fuzzy“-Checkpoint der Daten in Verbindung mit dem UNDO-Log und wendet dann das REDO-Log an, um alle Änderungen bis zum Wiederherstellungspunkt erneut aufzuspielen.
RedoBuffer
stellt die Größe des
Puffers ein, in den das REDO-Log geschrieben wird, und hat
den Standardwert 8 Mbyte. Sein Mindestwert beträgt 1
Mbyte.
Ist dieser Puffer zu klein, meldet die Speicher-Engine NDB
den Fehlercode 1221 (REDO log buffers
overloaded
).
Für das Cluster-Management ist es sehr wichtig, die Anzahl
der Logmeldungen steuern zu können, die für verschiedene
Ereignistypen an stdout
gesandt werden.
Für jede Art von Ereignis gibt es 16 mögliche Berichtsebenen
(mit den Nummern 0 bis 15). Wird die Berichtsebene für eine
gegebene Ereigniskategorie auf 15 gesetzt, so bedeutet dies,
dass alle Ereignisberichte dieser Kategorie an
stdout
geschickt werden; wird es auf 0
gesetzt, so werden in dieser Kategorie keine Ereignisse
gemeldet.
Nach Voreinstellung wird nur die Startnachricht an
stdout
geschickt, während die übrigen
Ereignisberichtsebenen auf 0 gesetzt sind. Der Grund: Diese
Meldungen werden auch an das Cluster-Log des
Management-Servers geschickt.
Dieselben Ebenen können Sie auch für den Management-Client einstellen, um festzulegen, welche Ereignisebenen im Cluster-Log protokolliert werden.
LogLevelStartup
Die Berichtsebene für Ereignisse, die beim Starten des Prozesses eintreten.
Die Standardebene ist 1.
LogLevelShutdown
Die Berichtsebene für Ereignisse, die beim sanften Herunterfahren eines Knotens gemeldet werden.
Die Standardebene ist 0.
LogLevelStatistic
Die Berichtsebene für statistische Ereignisse wie beispielsweise die Anzahl der Lesevorgänge auf Primärschlüsseln, die Anzahl der Änderungen oder Einfügungen, Informationen über die Pufferausnutzung und so weiter.
Die Standardebene ist 0.
LogLevelCheckpoint
Die Berichtsebene für Ereignisse, die bei lokalen und globalen Checkpoints generiert werden.
Die Standardebene ist 0.
LogLevelNodeRestart
Die Berichtsebene für Ereignisse, die beim Neustart eines Knotens generiert werden.
Die Standardebene ist 0.
LogLevelConnection
Die Berichtsebene für Ereignisse, die von Verbindungen zwischen Cluster-Knoten generiert werden.
Die Standardebene ist 0.
LogLevelError
Die Berichtsebene für Ereignisse, die von Fehlern und Warnungen vom Cluster insgesamt generiert werden. Diese Fehler bringen zwar nicht gleich einen Knoten zum Absturz, sind es aber dennoch wert, gemeldet zu werden.
Die Standardebene ist 0.
LogLevelInfo
Die Berichtsebene für Ereignisse, die zur Information über den Allgemeinzustand des Clusters generiert werden.
Die Standardebene ist 0.
Sicherungsparameter
In diesem Abschnitt geht es um
[NDBD]
-Parameter zur Definition von
Speicherpuffern für die Ausführung von Online-Sicherungen.
BackupDataBufferSize
Bei der Erstellung einer Datensicherung werden zwei Puffer
verwendet, um die Daten auf die Festplatte zu schreiben:
Der Puffer für Sicherungsdaten (Backup Data-Puffer) nimmt
Daten auf, die beim Scannen der Tabellen eines Knotens
aufgezeichnet wurden. Wenn dieser Puffer bis zu dem in
BackupWriteSize
(siehe unten)
angegebenen Stand gefüllt ist, werden die Seiten auf die
Festplatte geschrieben. Während Daten auf die Platte
zurückgeschrieben werden, kann der Datensicherungsprozess
weiter diesen Puffer mit Daten füllen, bis ihm der Platz
ausgeht. Wenn dies geschieht, macht der Sicherungsprozess
eine Pause mit seinen Scans, bis einige Schreibvorgänge
auf der Platte so weit abgeschlossen sind, dass Speicher
freigegeben wurde und das Scannen fortgesetzt werden kann.
Der Standardwert ist 2 Mbyte.
BackupLogBufferSize
Der Backup Log-Puffer spielt eine ähnliche Rolle wie der Backup Data-Puffer, wird jedoch verwendet, um ein Log aller während einer Datensicherung ausgeführten Schreibvorgänge auf Tabellen zu generieren. Diese Seiten werden nach demselben Prinzip wie bei der Datensicherung „Datenpuffer“ geschrieben, nur dass hier die Sicherung scheitert, wenn der Platz im Backup Log-Puffer ausgeht. Aus diesem Grund muss der Backup Log-Puffer unbedingt groß genug sein, um die von Schreibaktivitäten während der Datensicherung verursachte Belastung aushalten zu können. Siehe auch Abschnitt 16.6.5.4, „Konfiguration für Cluster-Backup“.
Der Standardwert dieses Parameters müsste für die meisten Anwendungen ausreichen. Eine Sicherung scheitert eher schon einmal durch zu langsame Schreibvorgänge auf der Platte als durch einen vollen Backup Log-Puffer. Wenn das Festplatten-Teilsystem für die Last der von Anwendungen verursachten Schreibvorgänge unzureichend konfiguriert ist, kann auch der Cluster die gewünschten Operationen nicht ausführen.
Cluster-Knoten sollten so konfiguriert werden, dass der Engpass eher im Prozessor liegt als in den Festplatten oder Netzwerkverbindungen.
Der Standardwert ist 2 Mbyte.
BackupMemory
Dieser Parameter ist einfach die Summe von
BackupDataBufferSize
und
BackupLogBufferSize
.
Der Standardwert ist 2 Mbyte + 2 Mbyte = 4 Mbyte.
BackupWriteSize
Dieser Parameter spezifiziert die Größe der Meldungen, die von den Backup Log- und Backup Data-Puffern auf die Festplatte geschrieben werden.
Der Standardwert ist 32 Kbyte.
Die [MYSQLD]
-Abschnitte in der
config.ini
-Datei definieren das Verhalten
der MySQL Server (SQL-Knoten), die für den Zugriff auf
Cluster-Daten eingesetzt werden. Keiner dieser Parameter ist
obligatorisch. Wenn kein Computer- oder Hostname angegeben
ist, kann jeder Host diesen SQL-Knoten benutzen.
Id
Der Wert Id
wird verwendet, um den
Knoten in allen Cluster-internen Nachrichten zu
identifizieren. Es ist ein Integer zwischen 1 und 63
einschließlich, der unter allen Knoten-IDs im Cluster
einzigartig sein muss.
ExecuteOnComputer
Bezieht sich auf einen der Computer (Hosts), die in einem
[COMPUTER]
-Abschnitt der
Konfigurationsdatei genannt sind.
ArbitrationRank
Dieser Parameter gibt an, welche Knoten als Arbitrator
fungieren können. Sowohl MGM- als auch SQL-Knoten können
Arbitrator sein. Der Wert 0 bedeutet, dass der betreffende
Knoten nie Arbitrator sein kann, 1 gibt ihm die höchste
Priorität als Arbitrator und 2 verleiht ihm eine niedrige
Priorität. In einer normalen Konfiguration wird der
Management-Server als Arbitrator eingesetzt, indem sein
ArbitrationRank
auf 1 (den Default) und
die der SQL-Knoten auf 0 gesetzt werden.
ArbitrationDelay
Wird dieser Parameter auf irgendeinen anderen Wert als 0 (den Standardwert) gesetzt, so werden die Antworten des Arbitrators auf Arbitration-Requests um diese Anzahl Millisekunden verzögert. Normalerweise ist es nicht nötig, diesen Wert zu ändern.
BatchByteSize
Für Anfragen, die in vollständige Tabellenscans oder
Indexbereichsscans übersetzt werden, ist es aus
Performancegründen wichtig, die Datensätze in Stapeln
(Batches) der richtigen Größe abzuholen. Diese richtige
Größe kann man sowohl als eine Anzahl von Datensätzen
(BatchSize
) als auch in Bytes
(BatchByteSize
) einstellen. Die
tatsächliche Batch-Größe wird von beiden Parametern
eingeschränkt.
Je nachdem, wie dieser Parameter eingestellt ist, kann die Geschwindigkeit von Anfragen um 40 Prozent variieren. In künftigen Releases wird MySQL Server anhand des Anfragetyps fundierte Annahmen über die Batch-Größe treffen.
Dieser Parameter wird in Bytes angegeben und hat den Standardwert 32 Kbyte.
BatchSize
Dieser Parameter wird als Anzahl von Datensätzen angegeben und ist standardmäßig auf 64 eingestellt. Seine Maximalgröße beträgt 992.
MaxScanBatchSize
Die Batch-Größe ist die Größe jedes Batchs von jedem Datenknoten. Die meisten Scans werden parallel ausgeführt, damit der MySQL Server nicht von vielen Knoten parallel zu viele Daten übermittelt bekommt. Dieser Parameter setzt eine Obergrenze der gesamten Batch-Größe quer über alle Knoten.
Standardmäßig ist dieser Parameter auf 256 Kbyte eingestellt; seine Maximalgröße beträgt 16 Mbyte.
TCP/IP ist der Standardtransportmechanismus zur Einrichtung
von Verbindungen in MySQL Cluster. Normalerweise ist es nicht
nötig, Verbindungen zu definieren, da Cluster automatisch
zwischen allen Datenknoten untereinander, zwischen allen
Datenknoten und allen MySQL Server-Knoten sowie zwischen allen
Datenknoten und dem Management-Server Verbindungen einrichtet.
(Die einzige Ausnahme von dieser Regel wird unter
Abschnitt 16.4.4.8, „MySQL Cluster: TCP/IP-Verbindungen mittels direkter Verbindungen“,
beschrieben.) [TCP]
-Abschnitte in der
config.ini
-Datei definieren explizit
TCP/IP-Verbindungen zwischen Knoten im Cluster.
Es ist nur dann notwendig, eine Verbindung zu definieren, wenn
die Standardverbindungsparameter außer Kraft gesetzt werden
sollen. In diesem Fall müssen mindestens
NodeId1
, NodeId2
und die
zu ändernden Parameter angegeben werden.
Die Standardwerte dieser Parameter können Sie auch ändern,
indem Sie sie im [TCP DEFAULT]
-Abschnitt
setzen.
NodeId1
, NodeId2
Um eine Verbindung zwischen zwei Knoten zu identifizieren,
müssen ihre Knoten-IDs im
[TCP]
-Abschnitt der Konfigurationsdatei
angegeben werden. Dabei handelt es sich um dieselben
eindeutigen Id
-Werte für einzelne
Knoten, wie in
Abschnitt 16.4.4.6, „Festlegung von SQL-Nodes in einem MySQL Cluster“,
beschrieben.
SendBufferMemory
TCP-Transporter speichern alle Nachrichten in einem Puffer, ehe sie den Sendeaufruf an das Betriebssystem starten. Wenn dieser Puffer 64 Kbyte erreicht, wird sein Inhalt übersandt; das Gleiche geschieht, wenn eine Runde Nachrichten ausgeführt worden ist. Um mit vorübergehenden Überlastungen umgehen zu können, ist es auch möglich, einen größeren Send-Puffer zu definieren. Seine Standardgröße beträgt 256 Kbyte.
SendSignalId
Um ein Diagramm mit verteilten Nachrichen nachvollziehen
zu können, muss jede Nachricht genau identifiziert sein.
Wenn dieser Parameter Y
ist, werden die
Message-IDs über das Netzwerk transportiert. In der
Standardeinstellung ist dieses Feature ausgeschaltet.
Checksum
Dieser boolesche Parameter ist standardmäßig
deaktiviert. (Um ihn zu aktivieren, setzen Sie ihn auf
Y
oder 1
, um ihn zu
deaktivieren, auf N
oder
0
.) Wird er aktiviert, so werden für
alle Nachrichten, ehe sie in den Send-Puffer geladen
werden, Prüfsummen berechnet. Dadurch wird
gewährleistet, dass die Nachrichten nicht durch den
Transportmechanismus oder beim Warten im Send-Puffer
geschädigt werden.
PortNumber
(OBSOLET)
Dieser Parameter gab früher einmal die Nummer des Ports an, auf dem das System nach Verbindungen anderer Knoten lauschte. Der Parameter sollte nicht mehr benutzt werden.
ReceiveBufferMemory
Gibt die Größe des Puffers zum Empfangen von Daten von dem TCP/IP-Socket an. Es ist kaum jemals erforderlich, den Standardwert von 64 Kbyte zu ändern, es sei denn, um Speicher zu sparen.
Um einen Cluster mit Direktverbindungen zwischen den
Datenknoten einzurichten, müssen Sie explizit die
Crossover-IP-Adressen der Datenknoten angeben, die so im
[TCP]
-Abschnitt der
config.ini
-Datei des Clusters verbunden
werden.
Im folgenden Beispiel planen wir einen Cluster mit mindestens
vier Hosts, nämlich einem Management-Server, einem SQL-Knoten
und zwei Datenknoten. Der Cluster als Ganzes residiert im
Subnetz 172.23.72.*
eines LANs. Zusätzlich
zu den normalen Netzwerkverbindungen existiert eine
Direktverbindung zwischen den beiden Datenknoten über ein
standardmäßiges Crossover-Kabel. Die beiden können direkt
über IP-Adressen im Adressbereich 1.1.0.*
miteinander kommunizieren:
# Management-Server [NDB_MGMD] Id=1 HostName=172.23.72.20 # SQL-Knoten [MYSQLD] Id=2 HostName=172.23.72.21 # Datenknoten [NDBD] Id=3 HostName=172.23.72.22 [NDBD] Id=4 HostName=172.23.72.23 # TCP/IP-Verbindungen [TCP] NodeId1=3 NodeId2=4 HostName1=1.1.0.1 HostName2=1.1.0.2
Direktverbindungen zwischen Datenknoten können die Gesamtleistung des Clusters steigern, da die Datenknoten auf diese Weise ein Ethernet-Gerät wie etwa einen Switch, Hub oder Router umgehen können, was die Latenzzeit im Cluster reduziert. Wichtig: Um von solchen Direktverbindungen zwischen mehr als zwei Datenknoten maximal zu profitieren, benötigen Sie eine Direktverbindung jedes Datenknotens mit jedem anderen Datenknoten derselben Knotengruppe.
MySQL Cluster versucht, den Shared Memory Transporter zu
nutzen und wenn möglich automatisch zu konfigurieren, vor
allem, wenn mehrere Knoten gleichzeitig auf demselben
CLuster-Host laufen. (In sehr frühen Versionen von MySQL
Cluster funktionierten Shared Memory-Segmente nur, wenn die
-max
-Binärversion mit der Option
--with-ndb-shm
gebaut wurde.) In den
[SHM]
-Abschnitten der
config.ini
-Datei werden Shared
Memory-Verbindungen zwischen Knoten im Cluster explizit
definiert. Wenn explizit Shared Memory als Verbindungsmethode
konfiguriert ist, müssen mindestens auch
NodeId1
, NodeId2
und
ShmKey
definiert sein. Alle anderen
Parameter müssten mit ihren Standardeinstellungen im
Normalfall gut funktionieren.
Wichtig: Die Funktionalität von SHM befindet sich noch im Experimentierstadium. Sie wird offiziell von keinem MySQL-Release bis einschließlich 5.1 unterstützt. Sie müssen also entweder nach eigenem Ermessen oder anhand von Informationen aus unseren kostenlosen Ressourcen (Foren, Mailinglisten) entscheiden, ob dieses Feature in Ihrem speziellen Fall richtig ans Laufen gebracht werden kann.
NodeId1
, NodeId2
Um eine Verbindung zwischen zwei Knoten identifizieren zu
können, müssen Sie für jeden von ihnen einen
Knotenbezeichner verwenden, etwa
NodeId1
und NodeId2
.
ShmKey
Bei der Einrichtung von Shared Memory-Segmenten wird das für die Kommunikation zu verwendende Segment durch eine Knoten-ID (einen Integer) eindeutig identifiziert. Einen Standardwert gibt es nicht.
ShmSize
Jede SHM-Verbindung hat ein Shared Memory-Segment, in
welchem die Nachrichten zwischen den Knoten vom Absender
gespeichert und vom Empfänger gelesen werden. Die Größe
dieses Segments wird durch ShmSize
festgelegt und beträgt nach Voreinstellung 1 Mbyte.
SendSignalId
Um den Pfad einer verteilten Nachricht zurückverfolgen zu
können, benötigt jede Nachricht einen eindeutigen
Bezeichner. Wird dieser Parameter auf Y
gesetzt, werden auch Message-IDs über das Netzwerk
transportiert. Nach Voreinstellung ist dieses Feature
deaktiviert.
Checksum
Dieser boolesche Parameter ist standardmäßig
ausgeschaltet (er kann Y
oder
N
sein). Wird er eingeschaltet, werden
für alle Nachrichten Prüfsummen berechnet, ehe sie in
den Puffer gelegt werden.
Dieses Feature verhindert, dass Nachrichten beschädigt werden, während sie im Puffer warten. Außerdem wirkt es als Versicherung gegen Datenkorruption auf dem Transportweg.
In [SCI]
-Abschnitten der
config.ini
-Datei werden explizit SCI
(Scalable Coherent Interface)-Verbindungen zwischen
Cluster-Knoten definiert. Die Verwendung von SCI Transportern
in MySQL Cluster wird nur dann unterstützt, wenn die
MySQL-Max-Binaries mit der Option
--with-ndb-sci=
gebaut wurden. Der /your/path/to/SCI
path
sollte auf
ein Verzeichnis verweisen, das zumindest
lib
- und
include
-Verzeichnisse mit
SISCI-Bibliotheken und Header-Dateien enthält. (Mehr zum
Thema SCI finden Sie unter
Abschnitt 16.7, „Verwendung von Hochgeschwindigkeits-Interconnects mit MySQL Cluster“.)
Darüber hinaus erfordert SCI spezielle Hardware.
Wir raten Ihnen dringend, SCI Transporter nur für die Kommunikation zwischen ndbd-Prozessen zu verwenden. Beachten Sie bitte auch, dass SCI Transporter dazu führen, dass die ndbd-Prozesse niemals schlafen. Aus diesem Grund sollten SCI Transporter nur auf Computern eingesetzt werden, die mindestens zwei CPUs ausschließlich für ndbd-Prozesse reserviert haben. Es muss mindestens eine CPU pro ndbd-Prozess vorhanden sein, und mindestens eine CPU muss für die Betriebssystemaktivitäten übrig bleiben.
NodeId1
, NodeId2
Um eine Verbindung zwischen zwei Knoten genau
identifizieren zu können, müssen beide Knoten einen
Bezeichner haben, etwa NodeId1
und
NodeId2
.
Host1SciId0
Die SCI-Knoten-ID für den ersten Cluster-Knoten (den mit
der Bezeichnung NodeId1
).
Host1SciId1
Man kann SCI Transporter zur Ausfallsicherung zwischen zwei SCI-Karten einsetzen, die dann allerdings separate Netzwerke zwischen den Knoten verwenden sollten. Dieser Parameter definiert die Knoten-ID und die zweite SCI-Karte für den ersten Knoten.
Host2SciId0
Dieser Parameter identifiziert die SCI-Knoten-ID für den
zweiten Cluster-Knoten (den mit der Bezeichnung
NodeId2
).
Host2SciId1
Wenn zur Ausfallsicherung zwei SCI-Karten eingesetzt werden, identifiziert dieser Parameter die zweite SCI-Karte für den zweiten Knoten.
SharedBufferSize
Jeder SCI Transporter hat ein Shared Memory-Segment für die Kommunikation zwischen den Knoten. Für die meisten Anwendungen müsste es ausreichen, die Größe dieses Segments auf dem Standardwert 1 Mbyte zu belassen. Ein kleinerer Wert kann bei vielen parallelen Einfügeoperationen Probleme verursachen; wenn der Shared Buffer zu klein ist, kann überdies der gesamte ndbd-Prozess abstürzen.
SendLimit
Ein kleiner Puffer vor den SCI-Medien speichert Nachrichten, ehe sie über das SCI-Netzwerk verschickt werden. Nach Voreinstellung ist er 8 Kbyte groß. Unsere Benchmarks weisen zwar die beste Performance bei 64 Kbyte aus, aber 16 Kbyte kommen schon bis auf wenige Prozente an diesen Höchstwert heran, und es gibt wenig Anlass, über den Wert von 8 Kbyte hinauszugehen.
SendSignalId
Um eine verteilte Nachricht zurückverfolgen zu können,
benötigt jede Nachricht einen eindeutigen Bezeichner.
Wird dieser Parameter auf Y
gesetzt,
werden auch Message-IDs über das Netzwerk transportiert.
Nach Voreinstellung ist dieses Feature deaktiviert.
Checksum
Dieser boolesche Parameter ist standardmäßig
deaktiviert. Wird Checksum
aktiviert,
so werden für alle Nachrichten, ehe sie in den
Send-Puffer geladen werden, Prüfsummen berechnet. Dadurch
wird gewährleistet, dass die Nachrichten nicht durch den
Transportmechanismus oder beim Warten im Send-Puffer
geschädigt werden.
Um die Verwaltung von MySQL Cluster zu verstehen, müssen Sie vier wichtige Prozesse kennen: In den folgenden Abschnitten dieses Kapitels werden wir feststellen, welche Rollen diese Prozesse in einem Cluster spielen, wie sie benutzt werden und welche Startoptionen für sie zur Verfügung stehen:
mysqld ist der traditionelle MySQL
Server-Prozess. Um ihn mit MySQL Cluster zu verwenden, muss
mysqld mit Unterstützung für die
Speicher-Engine NDB Cluster
gebaut werden,
wie sie in den -max
-Binaries von
http://dev.mysql.com/downloads/ bereits vorkompiliert ist.
Wenn Sie MySQL von der Quellversion bauen, müssen Sie
configure mit der Option
--with-ndbcluster
aufrufen, um NDB
Cluster
-Unterstützung zu erhalten.
Wenn die mysqld-Binary mit
Cluster-Unterstützung erstellt wurde, ist die Speicher-Engine
NDB Cluster
nach Voreinstellung immer noch
ausgeschaltet. Um sie zu aktivieren, haben Sie zwei
Möglichkeiten:
Sie können --ndbcluster
als Startoption
auf der Kommandozeile setzen, wenn Sie
mysqld starten.
Sie können in den Abschnitt [mysqld]
Ihrer my.cnf
-Datei eine Zeile mit dem
Eintrag ndbcluster
einsetzen.
Eine einfache Möglichkeit, zu überprüfen, ob Ihr Server mit
der Speicher-Engine NDB Cluster
läuft,
besteht darin, im MySQL Monitor (mysql) die
SHOW ENGINES
-Anweisung zu geben. Dann müsste
der Wert YES
als
Support
-Wert in der Zeile für
NDBCLUSTER
stehen. Steht dort ein
NO
oder ist diese Zeile in der Ausgabe gar
nicht vorhanden, so ist Ihre laufende MySQL-Version nicht
NDB
-fähig. Wenn in dieser Zeile der Wert
DISABLED
steht, müssen Sie die
NDB
-Unterstützung in einer der beiden oben
beschriebenen Weisen aktivieren.
Um Cluster-Konfigurationsdaten lesen zu können, benötigt der MySQL Server mindestens drei Informationen:
die eigene Cluster-Knoten-ID des MySQL Servers
den Hostnamen oder die IP-Adresse für den Management-Server (MGM-Knoten)
die Nummer des TCP/IP-Ports, auf dem er sich mit dem Management-Server verbinden kann
Da Knoten-IDs dynamisch zugewiesen werden können, müssen sie nicht unbedingt explizit angegeben werden.
Der mysqld-Parameter
ndb-connectstring
gibt den Verbindungs-String
an, entweder auf der Kommandozeile beim Starten von
mysqld oder in der Datei
my.cnf
. Der Verbindungs-String enthält den
Hostnamen oder die IP-Adresse, unter der der Management-Server
zu erreichen ist, sowie den verwendeten TCP/IP-Port.
Im folgenden Beispiel ist ndb_mgmd.mysql.com
der Management-Server-Host und 1186 der Port, auf dem dieser auf
Cluster-Nachrichten lauscht:
shell> mysqld --ndb-connectstring=ndb_mgmd.mysql.com:1186
Mehr über Verbindungs-Strings erfahren Sie unter
Abschnitt 16.4.4.2, „MySQL Cluster: connectstring
“.
Mit diesen Informationen wird der MySQL Server zum vollwertigen Mitglied des Clusters. (Manchmal bezeichnen wir einen mysqld-Prozess, der auf diese Weise ausgeführt wird, auch als SQL-Knoten.) Er kennt dann alle Cluster-Datenknoten und ihren Status und wird Verbindungen zu ihnen einrichten. In diesem Fall ist er in der Lage, jeden Datenknoten als Transaktionskoordinator zu benutzen und Knotendaten zu lesen und zu ändern.
ndbd ist der Prozess, der alle Tabellendaten behandelt, die mit der Speicher-Engine NDB Cluster gespeichert sind. Dieser Prozess kann einen Speicherknoten auch in die Lage versetzen, verteilte Transaktionen, Knoten-Recovery, Checkpointing auf der Festplatte, Online-Sicherung und ähnliche Aufgaben zu erfüllen.
In einem MySQL Cluster kümmern sich mehrere ndbd-Prozesse gemeinsam um die Behandlung der Daten. Diese Prozesse können auf demselben Computer/Host oder auf verschiedenen Computern ausgeführt werden. Die Beziehungen zwischen Datenknoten und Cluster-Hosts ist komplett konfigurierbar.
ndbd generiert einige Logdateien, die in
einem im DataDir
-Abschnitt der
Konfigurationsdatei config.ini
genannten
Verzeichnis abgelegt werden. Diese Logdateien sind unten
aufgeführt. Beachten Sie, dass
node_id
der eindeutige Bezeichner des
Knotens ist. So ist beispielsweise
ndb_2_error.log
das Fehlerlog, das der
Speicherknoten mit der Knoten-ID 2
generiert.
ndb_
ist eine Datei mit Aufzeichnungen aller Crashes, die dem
angegebenen ndbd-Prozess begegnet sind.
Jeder Datensatz in dieser Datei enthält einen kurzen
Fehler-String und eine Referenz auf eine Trace-Datei für
den betreffenden Crash. Ein typischer Eintrag könnte
folgendermaßen aussehen:
node_id
_error.log
Date/Time: Saturday 30 July 2004 - 00:20:01 Type of error: error Message: Internal program error (failed ndbrequire) Fault ID: 2341 Problem data: DbtupFixAlloc.cpp Object of reference: DBTUP (Line: 173) ProgramName: NDB Kernel ProcessID: 14909 TraceFile: ndb_2_trace.log.2 ***EOM***
Hinweis: Sie
müssen immer daran denken, dass der letzte Eintrag in der
Fehlerlogdatei nicht unbedingt der neueste ist
(das wäre sogar höchst unwahrscheinlich). Eintragungen im
Fehlerlog sind nicht chronologisch,
sondern spiegeln die Reihenfolge der Trace-Dateien wider,
wie sie in der Datei
ndb_
(siehe unten) festgelegt ist. Daher werden
Fehlerlogeinträge zyklisch und nicht sequenziell
überschrieben.
node_id
_trace.log.next
ndb_
ist eine Trace-Datei, die genau beschreibt, was unmittelbar
vor Eintreten des Fehlers geschah. Diese Information ist
nützlich für die Analysen des MySQL
Cluster-Entwicklungsteams.
node_id
_trace.log.trace_id
Sie können konfigurieren, wie viele von diesen
Trace-Dateien erzeugt werden, ehe die alten überschrieben
werden. trace_id
ist eine Zahl,
die mit jeder sukzessiven Trace-Datei um eins erhöht wird.
Die Datei
ndb_
behält im Auge, welche Trace-Datei-Nummer als Nächste
zugewiesen wird.
node_id
_trace.log.next
Die Datei
ndb_
enthält die Datenausgabe des
ndbd-Prozesses. Diese Datei wird nur
angelegt, wenn ndbd als Daemon gestartet
wird.
node_id
_out.log
Die Datei
ndb_
enthält die Prozess-ID des
ndbd-Prozesses, wenn dieser als Daemon
gestartet wird. Sie fungiert auch als Sperrdatei, damit
keine Knoten mit demselben Bezeichner gestartet werden.
node_id
.pid
Die Datei
ndb_
ist nur in Debugversionen von ndbd
vorhanden, wo es möglich ist, alle ein- und ausgehenden
sowie internen Nachrichten mit ihren Daten im
ndbd-Prozess nachzuvollziehen.
node_id
_signal.log
Bitte verwenden Sie kein mit NFS gemountetes Verzeichnis, da
dies in manchen Umgebungen Probleme verursachen kann, wobei die
Sperre auf der .pid
-Datei auch nach dem
Ende des Prozesses in Kraft bleibt.
Um ndbd starten zu können, ist es unter Umständen notwendig, den Hostnamen des Management-Servers und den Port anzugeben, auf dem er lauscht. Optional können Sie auch die ID des Knotens angeben, den der Prozess benutzen soll.
shell> ndbd --connect-string="nodeid=2;host=ndb_mgmd.mysql.com:1186"
Mehr zu diesem Thema finden Sie unter
Abschnitt 16.4.4.2, „MySQL Cluster: connectstring
“.
Abschnitt 16.5.5, „Befehlsoptionen für MySQL Cluster-Prozesse“, beschreibt
weitere Optionen für ndbd.
Wenn der ndbd-Prozess startet, werden in Wirklichkeit zwei Prozesse initiiert: Der erste heißt „Engelprozess“ und hat nur die Aufgabe, zu entdecken, wenn die Ausführung des Prozesses beendet ist, und dann den ndbd-Prozess neu zu starten, wenn er so konfiguriert ist. Wenn Sie also versuchen, ndbd mit dem Unix-Befehl kill anzuhalten, müssen Sie beide Prozesse anhalten, und zwar den Engelprozess als ersten. Einen ndbd-Prozess stoppen Sie am besten, indem Sie den Management-Client benutzen, um den Prozess von dort aus anzuhalten.
Der Ausführungsprozess verwendet nur einen einzigen Thread für das Lesen, Schreiben und Scannen der Daten sowie alle anderen Aktivitäten. Dieser Thread ist asynchron implementiert, damit er Tausende von nebenläufigen Aktivitäten leicht bewältigen kann. Zusätzlich überwacht ein Wachhund-Thread diesen Ausführungs-Thread, um sicherzustellen, dass dieser nicht in einer Endlosschleife stecken bleibt. Ein Pool von Threads kümmert sich um die Dateiein- und -ausgaben, wobei jeder Thread für eine geöffnete Datei zuständig ist. Auch die Transporter im ndbd-Prozess können für ihre Transporterverbindungen Threads nutzen. In einem System, das viele Operationen - darunter auch Updates - ausführt, kann der ndbd-Prozess bis zu 2 CPUs mit Beschlag belegen, wenn ihm dies erlaubt ist. Auf einem Mehrprozessorcomputer ist es empfehlenswert, mehrere ndbd-Prozesse für die verschiedenen Knotengruppen zu verwenden.
Der Management-Server ist der Prozess, der die Cluster-Konfigurationsdatei liest und diese Informationen auf alle Knoten im Cluster verteilt, die nach ihnen fragen. Außerdem pflegt er ein Log der Cluster-Aktivitäten. Management-Clients können sich mit dem Management-Server verbinden und den Status des Clusters überprüfen.
Es ist nicht unbedingt erforderlich, beim Start des Management-Servers einen Verbindungs-String anzugeben. Wenn Sie allerdings mehrere Management-Server einsetzen, ist ein solcher String notwendig und jeder Knoten im Cluster muss explizit seine Knoten-ID angeben.
Weitere Informationen über die Verwendung von
Verbindungs-Strings finden Sie unter
Abschnitt 16.4.4.2, „MySQL Cluster: connectstring
“.
Abschnitt 16.5.5, „Befehlsoptionen für MySQL Cluster-Prozesse“, beschreibt
andere Optionen für ndb_mgmd.
Die folgenden Dateien werden von ndb_mgmd in
seinem Startverzeichnis angelegt oder benutzt, und sie werden
gemäß den Angaben in der Konfigurationsdatei
config.ini
in das
DataDir
übernommen. In der nachfolgenden
Liste ist node_id
der eindeutige
Knotenbezeichner.
config.ini
ist die Konfigurationsdatei
für den Cluster insgesamt. Diese Datei wird vom Benutzer
angelegt und vom Management-Server gelesen. In
Abschnitt 16.4, „MySQL Cluster: Konfiguration“, ist die
Einrichtung dieser Datei beschrieben.
Das Ereignislog des Clusters ist
ndb_
.
Dort werden Ereignisse festgehalten, die beispielsweise beim
Starten und Beenden von Checkpoints, beim Starten von Knoten
oder beim Absturz eines Knotens auftreten, und es wird das
Ausmaß der Arbeitsspeichernutzung protokolliert. Eine
vollständige Liste der Cluster-Ereignisse samt
Beschreibungen finden Sie unter
Abschnitt 16.6, „Management von MySQL Cluster“.
node_id
_cluster.log
Wenn das Cluster-Log auf eine Million Byte angewachsen ist,
wird die Datei in
ndb_
umbenannt, wobei node_id
_cluster.log.seq_id
seq_id
die
laufende Nummer der Cluster-Logdatei ist. (Ein Beispiel:
Sind bereits Dateien mit den laufenden Nummern 1, 2 und 3
vorhanden, bekommt die nächste Logdatei die Nummer
4
.)
Die Datei
ndb_
wird für node_id
_out.logstdout
und
stderr
genutzt, wenn der
Management-Server als Daemon läuft.
ndb_
ist die Prozess-ID-Datei, wenn der Management-Server als
Daemon läuft.
node_id
.pid
Der Management-Client-Prozess ist eigentlich nicht erforderlich, um den Cluster zu betreiben. Sein Wert liegt in der Bereitstellung von Befehlen zur Überprüfung des Cluster-Status, zum Starten von Datensicherungen und zur Ausführung anderer administrativer Funktionen. Der Management-Client greift über eine C-API auf den Management-Server zu. Fortgeschrittene Benutzer können über diese API auch dedizierte Management-Prozesse programmieren, die sich um ähnliche Aufgaben kümmern wie ndb_mgm.
Um den Management-Client zu starten, müssen Sie den Hostnamen und die Portnummer des Management-Servers angeben:
shell> ndb_mgm [host_name
[port_num
]]
Ein Beispiel:
shell> ndb_mgm ndb_mgmd.mysql.com 1186
Der Standardhostname ist localhost
und der
Standardport ist 1186.
Mehr über die Verwendung von ndb_mgm lesen Sie unter Abschnitt 16.5.5.4, „Befehlsoptionen für ndb_mgm“, und Abschnitt 16.6.2, „Befehle des Management-Clients“.
Alle MySQL Cluster-Executables (außer
mysqld) nehmen die in diesem Abschnitt
aufgeführten Optionen entgegen. Benutzer älterer Versionen von
MySQL Cluster sollten berücksichtigen, dass einige dieser
Optionen gegenüber MySQL 4.1 Cluster geändert wurden, um sie
miteinander und mit mysqld zu
vereinheitlichen. Die Option --help
zeigt Ihnen
die Liste der unterstützten Optionen an.
Die folgenden Abschnitte beschreiben Optionen, die für einzelne NDB-Programme spezifisch sind.
--help
--usage
,
-?
Gibt eine kurze Liste mit Beschreibungen der verfügbaren Befehlsoptionen aus.
--connect-string=
,
connect_string
-c
connect_string
connect_string
stellt den
Verbindungs-String für den Management-Server als
Befehlsoption ein.
shell> ndbd --connect-string="nodeid=2;host=ndb_mgmd.mysql.com:1186"
--debug[=
options
]
Diese Option kann nur für Versionen verwendet werden, die mit Debugging kompiliert wurden. Sie aktiviert die Ausgabe von Debugaufrufen in derselben Weise wie für den mysqld-Prozess.
--execute=
command
-e
command
Kann einen Befehl von der System-Shell an die Cluster-Executable schicken. Die beiden folgenden Befehle:
shell> ndb_mgm -e show
oder
shell> ndb_mgm --execute="SHOW"
sind äquivalent zu
NDB> SHOW;
Analog funktionieren die Optionen --execute
und -e
mit dem Kommandozeilen-Client von
mysql. Siehe auch
Abschnitt 4.3.1, „Befehlszeilenoptionen für mysqld“.
--version
, -V
Gibt die Versionsnummer des ndbd-Prozesses aus. Dabei handelt es sich um die Nummer der MySQL Cluster-Version. Diese ist wichtig, da nicht alle Versionen zusammen benutzt werden können. Der MySQL Cluster-Prozess prüft beim Hochfahren, ob die Versionen der verwendeten Binaries überhaupt in demselben Cluster nebeneinander existieren können. Das ist auch beim Online-Softwareupgrade von MySQL Cluster von Bedeutung.
--ndb-connectstring=
connect_string
Wenn die Speicher-Engine NDB Cluster
benutzt wird, gibt diese Option an, welcher
Management-Server die Daten für die Cluster-Konfiguration
verteilt.
--ndbcluster
Die Speicher-Engine NDB Cluster
ist
für die Benutzung von MySQL Cluster erforderlich. Wenn
eine mysqld-Binary die Speicher-Engine
NDB Cluster
unterstützt, ist diese
Engine nach Voreinstellung deaktiviert. Mit der Option
--ndbcluster
wird sie aktiviert und mit
--skip-ndbcluster
explizit deaktiviert.
Optionen für alle NDB-Programme finden Sie unter Abschnitt 16.5.5, „Befehlsoptionen für MySQL Cluster-Prozesse“.
--daemon
, -d
Lässt ndbd als Daemon-Prozess laufen.
Dies ist das Standardverhalten. Die Option
--nodaemon
kann verwendet werden, wenn
der Prozess nicht als Daemon laufen soll.
--initial
Lässt ndbd einen Initialstart durchführen. Beim Initialstart werden alle Dateien gelöscht, die von früheren ndbd-Instanzen zu Wiederherstellungszwecken angelegt wurden. Außerdem rekonstruiert diese Option die Recovery-Logdateien. Beachten Sie, dass dieser Prozess auf manchen Betriebssystemen viel Zeit braucht.
Ein --initial
-Start soll nur beim
allerersten Hochfahren des
ndbd-Prozesses ausgeführt werden, da
er alle Dateien aus dem Cluster-Dateisystem löscht und
alle Recovery-Logdateien wiederherstellt. Von dieser Regel
gibt es zwei Ausnahmen:
Ein Softwareupgrade, bei dem Dateiinhalte geändert worden sind.
Der Neustart eines Knotens mit einer neuen Version von ndbd.
Als letztes Mittel, wenn aus irgendeinem Grund der Neustart eines Knotens oder des Systems immer wieder scheitert. In diesem Fall müssen Sie jedoch berücksichtigen, dass der Knoten nun nicht mehr zur Wiederherstellung von Daten taugt, da seine Datendateien zerstört wurden.
Diese Option wirkt sich auf keine Sicherungsdateien aus, die von dem betroffenen Knoten bereits erzeugt worden sind.
--nodaemon
Veranlasst, dass ndbd nicht als Daemon-Prozess startet. Dies ist nützlich, wenn Sie ndbd debuggen und die Ausgabe auf den Bildschirm umleiten möchten.
--nostart
Lässt ndbd nicht automatisch starten. Wenn diese Option benutzt wird, verbindet sich ndbd mit dem Management-Server, holt sich von diesem Konfigurationsdaten und initialisiert Kommunikationsobjekte. Die Ausführung wird jedoch erst dann gestartet, wenn der Management-Server es ausdrücklich verlangt, indem er dem Management-Client einen ausdrücklichen Befehl dafür gibt.
Optionen, die allen NDB-Programmen gemeinsam sind, finden Sie unter Abschnitt 16.5.5, „Befehlsoptionen für MySQL Cluster-Prozesse“.
--config-file=
,
file_name
-f
,
file_name
Sagt dem Management-Server, welches seine
Konfigurationsdatei ist. Diese Option muss gesetzt werden;
ihr Standardwert ist config.ini
.
Achtung: Diese Option kann auch als -c
angegeben
werden, aber diese Abkürzung ist veraltet und soll
nicht in neueren Installationen
verwendet werden.
file_name
--daemon
, -d
Lässt ndb_mgmd als Daemon-Prozess starten. Dies ist das Standardverhalten.
--nodaemon
Lässt ndb_mgmd nicht als Daemon-Prozess starten.
Optionen, die allen NDB-Programmen gemeinsam sind, finden Sie unter Abschnitt 16.5.5, „Befehlsoptionen für MySQL Cluster-Prozesse“.
--try-reconnect=
number
Wenn die Verbindung zum Management-Server abbricht,
versucht der Knoten alle 5 Sekunden, sich erneut zu
verbinden, bis er damit Erfolg hat. Mit dieser Option
können Sie die Anzahl der Verbindungsversuche auf
number
begrenzen. Danach gibt
der Knoten auf und meldet einen Fehler.
Zur Verwaltung eines MySQL Clusters gehören diverse Aufgaben, darunter an erster Stelle das Konfigurieren und Starten von MySQL Cluster. Dies wird in Abschnitt 16.4, „MySQL Cluster: Konfiguration“ und Abschnitt 16.5, „Prozessverwaltung in MySQL Cluster“, beschrieben.
In den folgenden Abschnitten wird beschrieben, wie man einen laufenden MySQL Cluster verwaltet.
Im Wesentlichen gibt es zwei Methoden, um einen laufenden MySQL
Cluster aktiv zu verwalten. Die erste: Sie können Befehle in den
Management-Client eingeben, um den Cluster-Status zu prüfen, die
Logebenen zu ändern, Datensicherungen zu starten und anzuhalten
und Knoten hoch- oder herunterzufahren. Die zweite Methode: Sie
prüfen den Inhalt des Cluster-Logs
ndb_
im node_id
_cluster.logDataDir
-Verzeichnis des Management-Servers.
(Denken Sie daran, dass node_id
der
eindeutige Bezeichner des Knotens ist, dessen Aktivität
protokolliert wird.) Das Cluster-Log enthält Ereignisberichte,
die von ndbd generiert wurden. Es ist auch
möglich, Cluster-Logeinträge an ein Unix-Systemlog zu senden.
Dieser Abschnitt beschreibt die Schritte zum Starten eines Clusters.
Wie Sie hier sehen, gibt es mehrere Starttypen und -modi:
Initialstart: Der Cluster
startet mit einem sauberen Dateisystem auf allen Knoten.
Dies geschieht entweder, wenn der Cluster zum allerersten
Mal gestartet wird, oder wenn er mit der Option
--initial
neu gestartet wird.
Neustart des Systems: Der Cluster startet und liest die in den Datenknoten gespeicherten Daten. Dies geschieht, wenn der Cluster, nachdem er nach Benutzung heruntergefahren wurde, den Betrieb an dem Punkt wieder aufnehmen soll, an dem er sich verabschiedet hatte.
Neustart eines Knotens: Dies ist der Online-Neustart eines Cluster-Knotens, während der Cluster selbst noch läuft.
Initialer Knoten-Neustart: Dies ist im Grunde dasselbe wie der Neustart eines Knotens, nur dass der Knoten hier neu initialisiert und mit einem sauberen Dateisystem hochgefahren wird.
Vor dem Starten muss jeder Datenknoten
(ndbd
-Prozess) initialisiert werden. Hierzu
gehören folgende Schritte:
eine Knoten-ID besorgen
die Konfigurationsdaten beschaffen
die Ports für die Kommunikation zwischen den Knoten zuweisen
Hauptspeicher gemäß den Vorgaben der Konfigurationsdatei reservieren
Nachdem die Datenknoten initialisiert sind, kann der Startprozess des Clusters fortfahren. Dabei macht der Cluster folgende Stadien durch:
Stadium 0
Das Dateisystem des Clusters wird geleert. Dieses Stadium
tritt nur dann ein, wenn der Cluster
mit der Option --initial
gestartet wurde.
Stadium 1
Nun werden die Cluster-Verbindungen eingerichtet, die Kommunikationskanäle zwischen den Knoten zugewiesen und die Heartbeats des Clusters gestartet.
Stadium 2
Der Arbitratorknoten wird ausgewählt. Wenn es sich um einen Neustart des Systems handelt, ermittelt der Cluster den letzten wiederherstellbaren globalen Checkpoint.
Stadium 3
Eine Reihe von internen Cluster-Variablen wird initialisiert.
Stadium 4
Für einen Initialstart oder initialen Knoten-Neustart
werden die Redo-Logdateien angelegt. Die Anzahl dieser
Dateien ist gleich NoOfFragmentLogFiles
.
Bei einem System-Neustart:
werden das oder die Schema(ta) gelesen,
werden die Daten aus dem lokalen Checkpoint und den Redo-Logs gelesen,
werden alle Redo-Informationen angewendet, bis der letzte wiederherstellbare globale Checkpoint erreicht wurde.
Für einen Knoten-Neustart muss der Logtail des Redo-Logs gefunden werden.
Stadium 5
Wenn es sich um einen Initialstart handelt, werden die
internen Systemtabellen SYSTAB_0
und
NDB$EVENTS
angelegt.
Bei einem Knoten-Neustart oder initialen Knoten-Neustart:
wird der Knoten in die Transaktions-Behandlungsoperationen einbezogen.
wird das Knotenschema mit dem des Masters verglichen und synchronisiert,
werden die in INSERT
-Form von den
anderen Datenknoten der Knotengruppe dieses Knotens
empfangenen Daten synchronisiert.
In allen Fällen wird gewartet, bis der Arbitrator bestimmt, dass ein lokaler Checkpoint vollständig ist.
Stadium 6
Interne Variablen werden aktualisiert.
Stadium 7
Interne Variablen werden aktualisiert.
Stadium 8
Bei einem Neustart eines Systems werden alle Indizes neu aufgebaut.
Stadium 9
Interne Variablen werden aktualisiert.
Stadium 10
Bei einem Knoten-Neustart oder initialen Knoten-Neustart können sich an diesem Punkt APIs mit dem Knoten verbinden und Ereignisse empfangen.
Stadium 11
Bei einem Knoten-Neustart oder initialen Knoten-Neustart wird an diesem Punkt die Lieferung von Ereignissen an den Knoten übergeben, der dem Cluster beitritt. Dieser neue Knoten übernimmt dann die Verantwortung für die Lieferung seiner primären Daten an die Abonnenten.
Nachdem dieser Prozess für einen Initialstart oder Neustart eines Systems abgeschlossen ist, wird die Transaktionsunterstützung aktiviert. Bei einem Knoten-Neustart oder initialen Knoten-Neustart bedeutet das Ende des Startprozesses, dass der Knoten nun als Transaktionskoordinator fungieren kann.
Ein Cluster kann nicht nur durch die zentrale Konfigurationsdatei, sondern auch über eine Kommandozeilenschnittstelle kontrolliert werden, die im Management-Client ndb_mgm zur Verfügung steht. Diese ist die wichtigste Administrationsschnittstelle für den Betrieb eines Clusters.
Befehle für die Ereignislogs stehen in Abschnitt 16.6.3, „Ereignisberichte, die MySQL Cluster erzeugt“, und Befehle für die Erstellung von Datensicherungen und die Wiederherstellung aus Datensicherungen in Abschnitt 16.6.5, „Online-Backup eines MySQL Clusters“.
Der Management-Client kennt folgende Grundbefehle. In der
nachfolgenden Liste steht node_id
entweder für eine Datenbankknoten-ID oder für das
Schlüsselwort ALL
, das bedeutet, dass der
Befehl für alle Datenknoten des Clusters gilt.
HELP
Zeigt Informationen über die verfügbaren Befehle an.
SHOW
Zeigt Informationen über den Cluster-Status an.
Achtung: In einem Cluster, in dem mehrere Management-Knoten in Gebrauch sind, zeigt dieser Befehl nur über diejenigen Datenknoten Informationen an, die gerade mit dem aktuellen Management-Server verbunden sind.
node_id
START
Startet den Datenknoten, der durch die
node_id
identifiziert ist (oder
alle Datenknoten).
node_id
STOP
Stoppt den Datenknoten, der durch die
node_id
identifiziert ist (oder
alle Datenknoten).
node_id
RESTART [-N]
[-I]
Startet den Datenknoten neu, der durch die
node_id
identifiziert ist (oder
alle Datenknoten).
node_id
STATUS
Zeigt Statusinformationen über den Datenknoten an, der
durch die node_id
identifiziert
ist (oder über alle Datenknoten).
ENTER SINGLE USER MODE
node_id
Geht in den Einbenutzermodus, wobei nur der MySQL Server,
der durch die Knoten-ID node_id
identifiziert ist, auf die Datenbank zugreifen darf.
EXIT SINGLE USER MODE
Verlässt den Einbenutzermodus, sodass alle SQL-Knoten (also alle laufenden mysqld-Prozesse) auf die Datenbank zugreifen können.
QUIT
Beendet den Management-Client.
SHUTDOWN
Fährt alle Cluster-Knoten außer den SQL-Knoten herunter und beendet den Management-Client.
In diesem Abschnitt geht es um die Ereignislog-Typen, die MySQL Cluster zur Verfügung stellt, und um die darin protokollierten Ereignisarten.
MySQL Cluster stellt zwei Typen von Ereignislogs zur Verfügung: das Cluster-Log mit Ereignissen, die von allen Cluster-Knoten generiert werden, und die Knoten-Logs, die lokal für die einzelnen Datenknoten geführt werden.
Die vom Cluster-Ereignislogging generierte Ausgabe kann mehrere
Ziele haben: eine Datei, die Konsole des Management-Servers oder
auch syslog
. Die Ausgabe des
Knoten-Ereignisloggings wird in das Konsolenfenster des
Datenknotens geschrieben.
Beide Typen von Ereignislogs können auf die Protokollierung verschiedener Ereignisse eingestellt werden.
Hinweis: Das Cluster-Log ist das Log, das für die meisten Anwendungen empfohlen wird, da es Informationen über einen ganzen Cluster in einer einzigen Datei zur Verfügung stellt. Die Knoten-Logs sind nur für die Anwendungsentwicklung oder für das Debugging von Anwendungscode gedacht.
Protokollierbare Ereignisse können nach drei verschiedenen Kriterien unterschieden werden:
Kategorie (Category): Diese kann einer
der folgenden Werte sein: STARTUP
,
SHUTDOWN
, STATISTICS
,
CHECKPOINT
,
NODERESTART
,
CONNECTION
, ERROR
oder
INFO
.
Priorität (Priority): Diese wird in Ganzzahlen von 1 bis 15 einschließlich angegeben, wobei 1 „am wichtigsten“ und 15 „am unwichtigsten“ bedeutet.
Ernsthaftigkeit (Severity Level): Dies
kann einer der folgenden Werte sein:
ALERT
, CRITICAL
,
ERROR
, WARNING
,
INFO
oder DEBUG
.
Sowohl Cluster- als auch Knoten-Log können anhand dieser Eigenschaften gefiltert werden.
Die folgenden Management-Befehle beziehen sich auf das Cluster-Log:
CLUSTERLOG ON
Schaltet das Cluster-Log ein.
CLUSTERLOG OFF
Schaltet das Cluster-Log aus.
CLUSTERLOG INFO
Gibt Informationen über die Einstellungen des Cluster-Logs.
node_id
CLUSTERLOG
category
=threshold
Protokolliert
category
-Ereignisse mit einer
Priorität kleiner oder gleich
threshold
im Cluster-Log.
CLUSTERLOG FILTER
severity_level
Schaltet Cluster-Logging von Ereignissen des angegebenen
severity_level
ein oder aus.
Die folgende Tabelle beschreibt die Standardeinstellung (für alle Datenknoten) für den Kategorie-Schwellenwert des Cluster-Logs. Ist die Priorität eines Ereignisses kleiner oder gleich dem Prioritäts-Schwellenwert, wird es in das Cluster-Log aufgenommen.
Beachten Sie, dass die Ereignisse pro Datenknoten gemeldet werden und dass der Schwellenwert (Threshold) für verschiedene Knoten unterschiedlich eingestellt werden kann.
Kategorie | Standardschwellenwert (alle Datenknoten) |
STARTUP | 7 |
SHUTDOWN | 7 |
STATISTICS | 7 |
CHECKPOINT | 7 |
NODERESTART | 7 |
CONNECTION | 7 |
ERROR | 15 |
INFO | 7 |
Die Schwellenwerte dienen dazu, die Ereignisse innerhalb der
Kategorien zu filtern. So wird beispielsweise ein
STARTUP
-Ereignis mit der Priorität 3 erst
protokolliert, wenn der Schwellenwert für
STARTUP
auf 3 oder noch niedriger
eingestellt wird. Ist der Schwellenwert 3, werden nur
Ereignisse mit der Prioritätszahl drei oder kleiner als drei
protokolliert.
Die folgende Tabelle zeigt die Ernsthaftigkeit (den
Severity-Level) von Ereignissen.
(Hinweis: Diese Abstufungen
entsprechen den Ebenen des Unix-syslog
, mit
Ausnahme von LOG_EMERG
und
LOG_NOTICE
, die nicht verwendet bzw.
zugeordnet werden.)
1 | ALERT | Eine Bedingung, die unverzüglich behoben werden muss, wie beispielsweise eine beschädigte Systemdatenbank |
2 | CRITICAL | Kritische Bedingungen, wie beispielsweise Gerätefehler oder unzureichende Ressourcen |
3 | ERROR | Bedingungen, die korrigiert werden sollten, wie beispielsweise Konfigurationsfehler |
4 | WARNING | Bedingungen, die zwar keine Fehler darstellen, aber eine Sonderbehandlung erfordern könnten |
5 | INFO | Meldungen zu Informationszwecken |
6 | DEBUG | Debugging-Meldungen, die für die Entwicklung von NDB
Cluster verwendet werden |
Die Ernsthaftigkeitsebenen für Ereignisse können ein- oder
ausgeschaltet werden (mit CLUSTERLOG
FILTER
, siehe oben). Wenn eine Ernsthaftigkeitsebene
eingeschaltet ist, werden alle Ereignisse, deren Priorität
kleiner oder gleich dem Schwellenwert für die betreffende
Kategorie ist, protokolliert. Wenn die Ernsthaftigkeitsebene
ausgeschaltet ist, werden Ereignisse, die auf dieser Ebene
liegen, nicht protokolliert.
Ein Ereignisbericht in den Ereignislogs hat folgendes Format:
datetime
[string
]severity
--message
Zum Beispiel:
09:19:30 2005-07-24 [NDB] INFO -- Node 4 Start phase 4 completed
Der folgende Abschnitt beschreibt alle Ereignisse, die gemeldet werden können, geordnet nach Kategorien und innerhalb der Kategorie nach Ernsthaftigkeit.
GCP und LCP bedeuten in den Ereignisbeschreibungen „Global Checkpoint“ und „Local Checkpoint“.
CONNECTION
-Ereignisse
Diese Ereignisse hängen mit Verbindungen zwischen Cluster-Knoten zusammen.
Ereignis | Priorität | Ernsthaftigkeit | Beschreibung |
DB nodes connected | 8 | INFO | Datenknoten verbunden |
DB nodes disconnected | 8 | INFO | Verbindung zum Datenknoten getrennt |
Communication closed | 8 | INFO | SQL-Knoten oder Datenknoten-Verbindung geschlossen |
Communication opened | 8 | INFO | Verbindung zum SQL- oder Datenknoten geöffnet |
CHECKPOINT
-Ereignisse
Die folgenden Logmeldungen hängen mit Checkpoints zusammen.
Ereignis | Priorität | Ernsthaftigkeit | Beschreibung |
LCP stopped in calc keep GCI | 0 | ALERT | LCP gestoppt |
Local checkpoint fragment completed | 11 | INFO | LCP auf einem Fragment abgeschlossen |
Global checkpoint completed | 10 | INFO | GCP fertig |
Global checkpoint started | 9 | INFO | Start eines GCP: REDO-Log wird auf Platte geschrieben |
Local checkpoint completed | 8 | INFO | LCP normal abgeschlossen |
Local checkpoint started | 7 | INFO | Start eines LCP: Daten auf Platte geschrieben |
Report undo log blocked | 7 | INFO | UNDO-Logging blockiert; Puffer läuft fast über |
STARTUP
-Ereignisse
Die folgenden Ereignisse werden als Reaktion auf den Erfolg oder Misserfolg beim Starten eines Knotens oder des Clusters generiert. Außerdem geben sie Informationen über den Fortschritt des Startprozesses einschließlich Informationen über Logging-Aktivitäten.
Ereignis | Priorität | Ernsthaftigkeit | Beschreibung |
Internal start signal received STTORRY | 15 | INFO | Blöcke, die nach Ende des Neustarts empfangen wurden |
Undo records executed | 15 | INFO | (Beschreibung nicht verfügbar) |
New REDO log started | 10 | INFO | GCI behält X , neuester wiederherstellbarer
GCI Y |
New log started | 10 | INFO | Log-Teil X , Beginn bei MB
Y , Ende bei MB
Z |
Node has been refused for inclusion in the cluster | 8 | INFO | Knoten kann wegen eines Konfigurationsfehlers nicht in den Cluster einbezogen werden, Kommunikation kann nicht hergestellt werden oder anderes Problem |
DB node neighbors | 8 | INFO | Zeigt benachbarte Datenknoten |
DB node start phase | 4 | INFO | Eine Startphase eines Datenknotens ist abgeschlossen |
Node has been successfully included into the cluster | 3 | INFO | Zeigt den Knoten, Manager-Knoten und dynamische ID an |
DB node start phases initiated | 1 | INFO | NDB Cluster-Knoten starten |
DB node all start phases completed | 1 | INFO | Gestartete NDB Cluster-Knoten |
DB node shutdown initiated | 1 | INFO | Herunterfahren des Datenknotens hat begonnen |
DB node shutdown aborted | 1 | INFO | Datenknoten kann nicht normal heruntergefahren werden |
NODERESTART
-Ereignisse
Die folgenden Ereignisse werden beim Neustart eines Knotens generiert und geben Aufschluss über den Erfolg oder Misserfolg des Neustart-Prozesses.
Ereignis | Priorität | Ernsthaftigkeit | Beschreibung |
Node failure phase completed | 8 | ALERT | Meldet den Abschluss von Node Failure-Phasen |
Node has failed, node state was | 8 | ALERT | Meldet das Scheitern eines Knotens |
Report arbitrator results | 2 | ALERT | Arbitration-Versuche können 8 mögliche Ergebnisse haben:
|
Completed copying a fragment | 10 | INFO | |
Completed copying of dictionary information | 8 | INFO | |
Completed copying distribution information | 8 | INFO | |
Starting to copy fragments | 8 | INFO | |
Completed copying all fragments | 8 | INFO | |
GCP takeover started | 7 | INFO | |
GCP takeover completed | 7 | INFO | |
LCP takeover started | 7 | INFO | |
LCP takeover completed (state = | 7 | INFO | |
Report whether an arbitrator is found or not | 6 | INFO | Die Suche nach einem Arbitrator kann 7 mögliche Ergebnisse haben:
|
STATISTICS
-Ereignisse
Die folgenden Ereignisse sind statistischer Natur. Sie melden beispielsweise die Anzahl der Transaktionen oder anderer Operationen, die Datenmengen, die von einzelnen Knoten gesendet oder empfangen wurden, oder die Speicherauslastung.
Ereignis | Priorität | Ernsthaftigkeit | Beschreibung |
Report job scheduling statistics | 9 | INFO | Mittelwerte der internen Job-Planungsstatistik |
Sent | 9 | INFO | Durchschnittliche Anzahl der an Knoten X
gesandten Bytes |
Received | 9 | INFO | Durchschnittliche Anzahl der von Knoten X
empfangenen Bytes |
Report transaction statistics | 8 | INFO | Anzahl von Transaktionen, Commits, Leseoperationen, Simple Reads, Schreiboperationen, nebenläufigen Operationen, Attributinformationen und Abbrüchen |
Report operations | 8 | INFO | Anzahl der Operationen |
Report table create | 7 | INFO | |
Memory usage | 5 | INFO | Ausnutzung von Data und Index Memory (80 %, 90 % und 100 %) |
ERROR
-Ereignisse
Diese Ereignisse betreffen Fehler und Warnungen im Cluster. Ihr Auftreten ist ein Hinweis auf eine größere Fehlfunktion oder ein Versagen.
Ereignis | Priorität | Ernsthaftigkeit | Beschreibung |
Dead due to missed heartbeat | 8 | ALERT | Der Knoten X wird für „tot“
erklärt, weil kein Heartbeat empfangen wurde |
Transporter errors | 2 | ERROR | |
Transporter warnings | 8 | WARNING | |
Missed heartbeats | 8 | WARNING | Beim Knoten X sind
Y Heartbeats ausgefallen |
General warning events | 2 | WARNING |
INFO
-Ereignisse
Diese Ereignisse liefern allgemeine Informationen über den Zustand des Clusters und die mit seiner Wartung zusammenhängenden Aktivitäten, wie beispielsweise Logging und die Übermittlung von Heartbeats.
Ereignis | Priorität | Ernsthaftigkeit | Beschreibung |
Sent heartbeat | 12 | INFO | Heartbeat, der an den Knoten X gesandt wurde |
Create log bytes | 11 | INFO | Logteil, Logdatei, MB |
General information events | 2 | INFO |
Im Einbenutzermodus kann der Datenbankadministrator den Zugriff auf das Datenbanksystem auf einen einzigen MySQL Server (SQL-Knoten) beschränken. Beim Eintritt in den Einbenutzermodus werden alle Verbindungen zu allen anderen MySQL Servern geräuschlos geschlossen und alle laufenden Transaktionen abgebrochen. Es dürfen keine neuen Transaktionen gestartet werden.
Sobald der Cluster im Einbenutzermodus läuft, hat nur noch der eine angegebene SQL-Knoten Zugriff auf die Datenbank.
Mit dem Befehl ALL STATUS können Sie sehen, wann der Cluster in den Einbenutzermodus gegangen ist.
Beispiel:
ndb_mgm> ENTER SINGLE USER MODE 5
Wenn dieser Befehl ausgeführt worden und der Cluster in den
Einbenutzermodus eingetreten ist, ist der SQL-Knoten mit der ID
5
der einzige zugelassene Benutzer des
Clusters.
Der im obigen Befehl angegebene Knoten muss ein MySQL Server-Knoten sein. Jeder Versuch, einen anderen Knotentyp anzugeben, wird zurückgewiesen.
Hinweis: Wenn der obige Befehl aufgerufen wird, werden alle auf dem angegebenen Knoten laufenden Transaktionen abgebrochen, die Verbindung wird geschlossen und der Server muss neu gestartet werden.
Der Befehl EXIT SINGLE USER MODE stellt den Status der Datenknoten des Clusters vom Einbenutzer- auf den normalen Modus um. MySQL Server, die auf eine Verbindung mit dem Cluster warten (d. h. darauf, dass der Cluster bereit ist und wieder zur Verfügung steht), erhalten wieder die Erlaubnis, eine Verbindung herzustellen. Der als Einbenutzer-SQL-Knoten gekennzeichnete MySQL Server läuft während und nach der Zustandsänderung weiter (sofern er immer noch verbunden ist).
Beispiel:
NDB> EXIT SINGLE USER MODE
Im Einbenutzermodus gibt es zwei empfohlene Vorgehensweisen für den Umgang mit einem Knoten-Absturz:
Methode 1:
Sie beenden alle Einbenutzertransaktionen.
Sie geben den Befehl EXIT SINGLE USER MODE ein.
Sie starten die Datenknoten des Clusters neu.
Methode 2:
Sie starten die Datenbankknoten neu, bevor Sie in den Einbenutzermodus gehen.
Dieser Abschnitt beschreibt, wie eine Datenbanksicherung erstellt und wie die Datenbank später aus einer Sicherung wiederhergestellt wird.
Eine Datensicherung ist eine Momentaufnahme der Datenbank zu einem gegebenen Zeitpunkt. Sie besteht aus drei Hauptteilen:
Metadaten: die Namen und Definitionen aller Datenbanktabellen
Tabellendatensätze: die Daten, die in den Datenbanktabellen zum Zeitpunkt der Datensicherung tatsächlich gespeichert waren
Transaktionslog: ein sequenzieller Logeintrag, der Ihnen sagt, wie und wann Daten in der Datenbank gespeichert wurden
Jeder dieser Teile wird auf allen Knoten gespeichert, deren Daten gesichert werden. Während der Datensicherung speichert jeder Knoten diese drei Teile in drei Dateien auf der Festplatte:
BACKUP-
backup_id
.node_id
.ctl
Eine Steuerungsdatei mit Steuerungsinformationen und Metadaten. Jeder Knoten speichert dieselben Tabellendefinitionen (für alle Tabellen im Cluster) in seiner eigenen Version dieser Datei.
BACKUP-
backup_id
-0.node_id
.data
Eine Datendatei mit den Tabellendaten, die pro Fragment gespeichert werden. Das bedeutet, dass verschiedene Knoten während der Datensicherung verschiedene Fragmente speichern. Die Datei eines Knotens fängt immer mit einem Header an, auf dem die Tabelle steht, zu welcher die Datensätze gehören. Nach der Liste der Datensätze folgt ein Footer mit einer Prüfsumme für alle Datensätze.
BACKUP-
backup_id
.node_id
.log
Eine Logdatei mit Datensätzen von committeten Transaktionen. Nur Transaktionen auf Tabellen, die in der Sicherung gespeichert sind, werden im Log festgehalten. Die gesicherten Knoten speichern unterschiedliche Datensätze, da unterschiedliche Knoten unterschiedliche Datenbankfragmente hosten.
Im obigen Listing ist backup_id
der
Bezeichner für die Sicherung und
node_id
der eindeutige Bezeichner
für den Knoten, welcher die Datei anlegt.
Ehe Sie eine Datensicherung starten, müssen Sie sich vergewissern, dass der Cluster dafür richtig konfiguriert ist. (Siehe Abschnitt 16.6.5.4, „Konfiguration für Cluster-Backup“.)
Um mit dem Management-Server eine Sicherung vorzunehmen, tun Sie Folgendes:
Sie starten den Management-Server (ndb_mgm).
Sie führen den Befehl START BACKUP
aus.
Der Management-Server wird mit der Nachricht
Start of backup ordered
antworten. Dies
bedeutet, dass er den Request an den Cluster übermittelt,
aber noch keine Reaktion empfangen hat.
Der Management-Server antwortet mit Backup
,
wobei backup_id
startedbackup_id
wieder der
eindeutige Bezeichner für diese Sicherung ist. (Dieser
Bezeichner wird auch im Cluster-Log gespeichert, wenn
nichts anderes konfiguriert wurde.) Dies bedeutet, dass
der Cluster den Backup-Request empfangen und verarbeitet
hat. Es bedeutet jedoch nicht, dass
die Sicherung abgeschlossen ist.
Der Management-Server signalisiert durch die Nachricht
Backup
, dass die Datensicherung abgeschlossen
ist.
backup_id
completed
Um eine laufende Sicherung abzubrechen, gehen Sie folgendermaßen vor:
Sie starten den Management-Server.
Sie führen den Befehl ABORT BACKUP
aus. Die
Zahl backup_id
backup_id
ist der
Backup-Bezeichner, der in der Antwort des
Management-Servers beim Starten der Datensicherung
angegeben wurde (in der Nachricht Backup
).
backup_id
started
Der Management-Server quittiert den Abbruchbefehl mit
einem Abort of backup
.
Beachten Sie, dass er bisher noch keine wirkliche Antwort
auf diesen Request erhalten hat.
backup_id
ordered
Nach dem Abbruch der Datensicherung meldet der
Management-Server Backup
. Dies
bedeutet, dass der Cluster die Datensicherung beendet hat
und alle mit ihr verbundenen Dateien aus dem Dateisystem
des Clusters gelöscht wurden.
backup_id
has been aborted for
reason XYZ
Es ist auch möglich, eine laufende Datensicherung von der System-Shell aus mit folgendem Befehl abzubrechen:
shell> ndb_mgm -e "ABORT BACKUP backup_id
"
Hinweis: Wenn zum Zeitpunkt
des Abbruchbefehls keine Sicherung mit der
backup_id
läuft, erstattet der
Management-Server darüber keine explizite Meldung. Immerhin
wird der ungültige Abbruchbefehl jedoch im Cluster-Log
erwähnt.
Das Programm zur Cluster-Wiederherstellung ist als separate Kommandozeilen-Utility namens ndb_restore implementiert. Es liest die angelegten Sicherungsdateien und fügt die darin gespeicherten Informationen in die Datenbank ein. Das Wiederherstellungsprogramm muss für jeden Satz von Sicherungsdateien einmal ausgeführt werden, also so viele Male, wie Datenbankknoten zum Zeitpunkt der Datensicherung ausgeführt wurden.
Wenn Sie das Wiederherstellungsprogramm
ndb_restore erstmals ausführen, müssen
Sie auch die Metadaten rekonstruieren. Mit anderen Worten: Sie
müssen die Datenbanktabellen wiederherstellen. (Beachten Sie,
dass der Cluster eine leere Datenbank haben müsste, wenn die
Wiederherstellung der Sicherung beginnt.) Das
Wiederherstellungsprogramm fungiert als API zum Cluster und
erfordert daher eine freie Verbindung zum Cluster. Ob diese
vorhanden ist, sagt Ihnen der
ndb_mgm-Befehl SHOW (den
Sie mit ndb_mgm -e SHOW auf der
System-Shell absetzen können). Mit der Option -c
können Sie
den MGM-Knoten angeben (mehr zu Verbindungs-Strings erfahren
Sie unter Abschnitt 16.4.4.2, „MySQL Cluster: connectstring
connectstring
“). Die
Sicherungsdateien müssen in dem Verzeichnis liegen, welches
dem Wiederherstellungsprogramm als Argument übergeben wird.
Es ist möglich, eine Datenbanksicherung mit einer anderen
Konfiguration als die Erzeugung der Datenbank zu fahren.
Nehmen wir beispielsweise an, dass eine Sicherung mit der ID
12
, die in einem Cluster mit zwei
Datenbankknoten mit den Knoten-IDs 2
und
3
angelegt wurde, in einem Cluster mit vier
Knoten wiederhergestellt werden soll. Dazu muss der Befehl
ndb_restore zweimal ausgeführt werden:
einmal für jeden Datenbankknoten in dem Cluster, in dem die
Sicherung durchgeführt wurde.
Hinweis: Schneller geht die Wiederherstellung, wenn sie parallel ausgeführt wird, vorausgesetzt, es stehen genügend Cluster-Verbindungen zur Verfügung. Allerdings müssen die Datendateien immer vor den Logs angewendet werden.
Vier Konfigurationsparameter sind für die Datensicherung äußerst wichtig:
BackupDataBufferSize
Gibt an, wie viel Arbeitsspeicher für das Puffern von Daten zur Verfügung steht, ehe diese auf die Platte geschrieben werden.
BackupLogBufferSize
Gibt an, wie viel Arbeitsspeicher für das Puffern von Logeinträgen zur Verfügung steht, ehe diese auf die Platte geschrieben werden.
BackupMemory
Gibt an, wie viel Arbeitsspeicher in einem Datenbankknoten insgesamt für Datensicherungen reserviert ist. Dieser Wert sollte die Summe des zugewiesenen Speichers für Backup-Datenpuffer plus Backup-Logpuffer sein.
BackupWriteSize
Die Blockgröße, in der Daten auf die Platte geschrieben werden. Gilt sowohl für Backup-Datenpuffer als auch für Backup-Logpuffer.
Genauere Einzelheiten über diese Parameter finden Sie unter Abschnitt 16.4, „MySQL Cluster: Konfiguration“.
Wenn auf einen Backup-Request ein Fehlercode zurückgegeben wird, liegt dies wahrscheinlich an unzureichendem Arbeits- oder Festplattenspeicher. Sie sollten sich vergewissern, dass für die Datensicherung genügend Hauptspeicher zur Verfügung steht und dass auch auf der Festplattenpartition, die von der Datensicherung genutzt wird, ausreichend Platz ist.
NDB
unterstützt keine Repeatable Reads,
was zu Problemen mit dem Wiederherstellungsprozess führen
kann. Zwar ist der Sicherungsprozess selbst
„heiß“, aber die Wiederherstellung eines MySQL
Clusters aus einer Datensicherung ist eben nicht zu 100 % ein
„heißer“ Prozess. Dies liegt daran, dass für
die Dauer des Wiederherstellungsprozesses laufende
Transaktionen Non-Repeatable Reads von der rekonstruierten
Datenbank erhalten. Das bedeutet, dass der Zustand der Daten
inkonsistent ist, während die Wiederherstellung noch läuft.
Schon bevor im Jahre 1996 mit dem Entwurf von NDB
Cluster
begonnen wurde, war offensichtlich, dass die Kommunikation
zwischen Knoten im Netzwerk eines der Hauptprobleme in der
Konstruktion von parallelen Datenbanken sein würde. Daher wurde
NDB Cluster
schon von Anfang an für mehrere
verschiedene Datentransportmechanismen ausgelegt. In diesem Manual
verwenden wir für diese den Oberbegriff
Transporter.
Zurzeit unterstützt die MySQL Cluster-Codebasis vier verschiedene Transporter. Die meisten Anwender nutzen heutzutage TCP/IP über Ethernet, da diese Technik allgegenwärtig ist. Zudem ist TCP/IP der mit Abstand am besten getestete Transporter in MySQL Cluster.
Wir arbeiten daran, sicherzustellen, dass die Kommunikation mit dem ndbd-Prozess in möglichst großen „Happen“ abgewickelt wird, da dies für alle Arten der Datenübermittlung nur vorteilhaft ist.
Wer es wünscht, kann die Leistung sogar noch stärker steigern, indem er Direktverbindungen zwischen Clustern (Interconnects) verwendet. Es gibt zwei Möglichkeiten, diese zu errichten: entweder mit einem selbst definierten Transporter oder mit Socketimplementierungen, die den TCP/IP-Stapel bis zu einem gewissen Grade umgehen. Wir haben beide Techniken mit der SCI(Scalable Coherent Interface)-Technologie von Dolphin ausprobiert.
In diesem Abschnitt zeigen wir, wie man einen Cluster, der für normale TCP/IP-Kommunikation konfiguriert ist, auf SCI Sockets umstellt. Diese Dokumentation beruht auf der SCI Sockets-Version 2.3.0 auf dem Stand vom 1. Oktober 2004.
Voraussetzungen:
Alle Computer, die SCI Sockets nutzen sollen, müssen mit SCI-Karten ausgerüstet sein.
SCI Sockets können mit jeder beliebigen Version von MySQL Cluster benutzt werden. Es sind keine besonderen Builds erforderlich, da diese Technologie die ganz normalen Socketaufrufe verwendet, die in MySQL Cluster bereits zur Verfügung stehen. Allerdings werden SCI Sockets zurzeit nur von den Linux-Kernels 2.4 und 2.6 unterstützt. SCI Transporter wurden erfolgreich auch auf anderen Betriebssystemen getestet; wir selbst haben sie bisher allerdings nur auf Linux 2.4 erprobt.
Für SCI Sockets sind im Wesentlichen vier Dinge erforderlich:
Sie müssen die SCI Socket-Bibliotheken erstellen.
Sie müssen die Kernel-Bibliotheken von SCI Socket installieren.
Sie müssen eine oder zwei Konfigurationsdateien installieren.
Die Kernel-Bibliothek von SCI Socket muss entweder für den gesamten Computer oder für die Shell, in der MySQL Cluster-Prozesse gestartet werden, aktiviert sein.
Dieser Prozess muss für jeden Computer im Cluster wiederholt werden, auf dem SCI Sockets für die Kommunikation zwischen Knoten eigesetzt werden sollen.
Um SCI Sockets einsetzen zu können, müssen Sie zwei Packages beschaffen:
das Quellcode-Package mit den DIS-Support-Bibliotheken für die SCI Sockets-Bibliotheken
das Quellcode-Package für die SCI Socket-Bibliotheken selbst
Diese stehen gegenwärtig nur im Quellcodeformat zur Verfügung.
Die neuesten Versionen dieser Packages (zu dem Zeitpunkt, da
dies geschrieben wurde) sind
DIS_GPL_2_5_0_SEP_10_2004.tar.gz
und
SCI_SOCKET_2_3_0_OKT_01_2004.tar.gz
. Diese
oder neuere Versionen finden Sie unter
http://www.dolphinics.no/support/downloads.html.
Installation der Packages
Wenn Sie die Bibliotheks-Packages bekommen haben, müssen Sie sie als Erstes in die passenden Verzeichnisse entpacken, wobei die SCI Sockets-Bibliotheken in ein Verzeichnis unterhalb des DIS-Codes gelegt werden müssen. Als Nächstes müssen Sie die Bibliotheken erstellen. Das folgende Beispiel zeigt, mit welchen Befehlen dies auf Linux/x86 getan wird:
shell>tar xzf DIS_GPL_2_5_0_SEP_10_2004.tar.gz
shell>cd DIS_GPL_2_5_0_SEP_10_2004/src/
shell>tar xzf ../../SCI_SOCKET_2_3_0_OKT_01_2004.tar.gz
shell>cd ../adm/bin/Linux_pkgs
shell>./make_PSB_66_release
Diese Bibliotheken können auch für einige 64-Bit-Prozessoren erstellt werden. Um sie für Opteron-CPUs mit den 64-Bit-Erweiterungen einzurichten, führen Sie make_PSB_66_X86_64_release statt make_PSB_66_release aus. Wird der Build auf einem Itanium-Computer ausgeführt, verwenden Sie den Befehl make_PSB_66_IA64_release. Die X86-64-Variante müsste auf Intel EM64T-Architekturen funktionieren, wurde aber (unseres Wissens) noch nicht getestet.
Wenn der Build-Prozess abgeschlossen ist, liegen die
kompilierten Bibliotheken in einer gezippten tar-Datei namens
DIS-
.
Nun muss das Package noch am richtigen Ort installiert werden.
In diesem Beispiel legen wir die Installation in das Verzeichnis
<operating-system>
-time
-date
/opt/DIS
.
(Hinweis: Wahrscheinlich
müssen Sie die Anweisungen als Systembenutzer
root
ausführen.)
shell>cp DIS_Linux_2.4.20-8_181004.tar.gz /opt/
shell>cd /opt
shell>tar xzf DIS_Linux_2.4.20-8_181004.tar.gz
shell>mv DIS_Linux_2.4.20-8_181004 DIS
Netzwerkkonfiguration
Nun, da alle Bibliotheken und Binaries am richtigen Platz sind, müssen Sie noch dafür sorgen, dass die SCI-Karten die richtigen Knoten-IDs im SCI-Adressraum haben.
Außerdem müssen Sie eine Entscheidung über die Netzwerkstruktur treffen, ehe Sie fortfahren. In diesem Zusammenhang sind drei Arten von Netzwerkstrukturen möglich:
ein einfacher, eindimensionaler Ring
ein oder mehrere SCI-Switches mt einem Ring pro Switch-Port
ein zwei- oder dreidimensionaler Torus
Jede dieser Netzwerktopologien hat ihre eigene Methode, um Knoten-IDs zu liefern. Alle diese Methoden werden im Folgenden kurz erklärt.
Ein einfacher Ring verwendet IDs, die von Null verschiedene Vielfache von 4 sind: 4, 8, 12, ...
Die nächste Möglichkeit verwendet SCI-Switches. Ein SCI-Switch hat 8 Ports, von denen jeder einen Ring unterstützen kann. Sie müssen dafür sorgen, dass verschiedene Ringe verschiedene ID-Räume benutzen. In einer typischen Konfiguration nutzt der erste Port Knoten-IDs unter 64 (4 – 60), der nächste Port die nächsten 64 Knoten-IDs (68–124), und so weiter, sodass die Knoten-IDs 452–508 dem 8. Port zugewiesen werden.
Zwei- und dreidimensionale Torus-Netzwerktopologien nehmen Rücksicht darauf, wo der einzelne Knoten in welcher Dimension angesiedelt ist, indem sie für jeden Knoten in der ersten Dimension um 4 hochzählen, für jeden in der zweiten Dimension um 64 und (wenn vorhanden) für jeden in der dritten Dimension um 1024. Auf der Website von Dolphin finden Sie Genaueres zum Thema.
In unseren Tests haben wir Switches verwendet, obwohl die meisten großen Cluster-Installationen 2- oder 3-dimensionale Torusstrukturen verwenden. Switches haben den Vorteil, dass man mit dualen SCI-Karten und dualen Switches relativ einfach ein redundantes Netzwerk aufbauen kann, wobei die durchschnittlichen Ausfallzeiten im SCI-Netzwerk im Bereich von 100 Mikrosekunden liegen. Dies wird von dem SCI Transporter in MySQL Cluster unterstützt und auch für die SCI Socket-Implementierung zurzeit entwickelt.
Auch für den 2D-/3D-Torus ist eine Ausfallsicherung möglich, doch hierfür ist es erforderlich, an alle Knoten neue Routing-Indizes auszusenden. Dies nimmt allerdings nur circa 100 Millisekunden Zeit in Anspruch, was für die meisten Hochverfügbarkeitssysteme noch akzeptabel sein dürfte.
Indem Sie die Cluster-Datenknoten in der geswitchten Architektur sorgfältig platzieren, können Sie mit 2 Switches eine Struktur aufbauen, in der 16 Computer miteinander verbunden sind und nie mehr als einer von ihnen durch einen einzelnen Fehler ausfallen kann. Mit 32 Computern und 2 Switches können Sie den Cluster so konfigurieren, dass ein einzelner Absturz nie mehr als 2 Knoten betreffen kann und dass darüber hinaus bekannt wird, um welches Knotenpaar es sich handelt. Indem Sie diese beiden Knoten dann in separate Knotengruppen verlegen, können Sie sogar eine „sichere“ MySQL Cluster-Installation bekommen.
Um die Knoten-ID für eine SCI-Karte zu setzen, geben Sie
folgenden Befehl im Verzeichnis
/opt/DIS/sbin
ein. In diesem Beispiel ist
-c 1
die Nummer der SCI-Karte (diese ist immer
1, wenn nur eine Karte in den Computer eingebaut ist),
-a 0
ist der Adapter 0 und
68
ist die Knoten-ID:
shell> ./sciconfig -c 1 -a 0 -n 68
Wenn mehrere SCI-Karten in demselben Computer eingebaut sind,
können Sie mit folgendem Befehl ermitteln, welche Karte welchen
Steckplatz hat (wir gehen wieder davon aus, dass
/opt/DIS/sbin
das aktuelle
Arbeitsverzeichnis ist):
shell> ./sciconfig -c 1 -gsn
So erhalten Sie die Seriennummer der SCI-Karte. Diesen Vorgang
wiederholen Sie dann mit -c 2
und so weiter
für jede Karte im Computer. Sobald Sie jede Karte einem
Steckplatz zugeordnet haben, können Sie für alle Karten
Knoten-IDs einrichten.
Sobald die notwendigen Bibliotheken und Binaries installiert und
die SCI-Knoten-IDs gesetzt sind, ordnen Sie als Nächstes die
Hostnamen oder IP-Adressen den SCI-Knoten-IDs zu. Dies tun Sie
in der Konfigurationsdatei für SCI Sockets, die normalerweise
unter /etc/sci/scisock.conf
gespeichert
sein müsste.
In dieser Datei ist jeder SCI-Knoten-ID über die jeweilige
SCI-Karte der Hostname oder die IP-Adresse zugeordnet, mit der
sie kommunizieren soll. Hier sehen Sie ein sehr einfaches
Beispiel für eine solche Konfigurationsdatei:
#host #nodeId alpha 8 beta 12 192.168.10.20 16
Sie können die Konfiguration auch so einschränken, dass sie
nur für einen Teil der verfügbaren Ports für diese Hosts
gilt. Hierfür können Sie eine zusätzliche Konfigurationsdatei
namens /etc/sci/scisock_opt.conf
verwenden:
#-key -type -values EnablePortsByDefault yes EnablePort tcp 2200 DisablePort tcp 2201 EnablePortRange tcp 2202 2219 DisablePortRange tcp 2220 2231
Treiberinstallation
Wenn die Konfigurationsdateien eingerichtet sind, können die Treiber installiert werden.
Als Erstes installieren Sie die Treiber der unteren Ebene und dann den SCI Socket-Treiber:
shell>cd DIS/sbin/
shell>./drv-install add PSB66
shell>./scisocket-install add
Auf Wunsch kann die Installation mit einem Skript überprüft werden, das nachschaut, ob auf alle Knoten in den SCI Socket-Konfigurationsdateien Zugriff besteht:
shell>cd /opt/DIS/sbin/
shell>./status.sh
Wenn Sie auf einen Fehler stoßen und die SCI Socket-Konfiguration ändern müssen, so tun Sie dies mit ksocketconfig:
shell>cd /opt/DIS/util
shell>./ksocketconfig -f
Das Setup testen
Mit dem Testprogramm latency_bench können
Sie sich vergewissern, dass auch tatsächlich die SCI Sockets
benutzt werden. Mit der Serverkomponente dieses Dienstprogramms
können sich die Clients mit dem Server verbinden, um die
Verbindungslatenz zu überprüfen. Wenn Sie die Latenz
beobachten, haben Sie schnell heraus, ob SCI aktiviert ist oder
nicht. (Hinweis: Bevor Sie
latency_bench sagen, müssen Sie die
Umgebungsvariable LD_PRELOAD
so einstellen,
wie es weiter unten in diesem Abschnitt gezeigt wird.)
Um einen Server einzurichten, tun Sie Folgendes:
shell>cd /opt/DIS/bin/socket
shell>./latency_bench -server
Um einen Client zu betreiben, führen Sie
latency_bench erneut aus, diesmal allerdings
mit der Option -client
:
shell>cd /opt/DIS/bin/socket
shell>./latency_bench -client
server_hostname
Die SCI Socket-Konfiguration sollte nun abgeschlossen und MySQL Cluster bereit für die Nutzung von SCI Sockets und SCI Transporter sein (siehe Abschnitt 16.4.4.10, „MySQL Cluster: SCI-Transportverbindungen“).
Den Cluster starten
Der nächste Schritt besteht darin, MySQL Cluster zu starten. Um
SCI Sockets einzuschalten, müssen Sie die Umgebungsvariable
LD_PRELOAD
einstellen, bevor Sie
ndbd, mysqld und
ndb_mgmd laufen lassen. Diese Variable sollte
auf die Kernel-Bibliothek von SCI Sockets verweisen.
Folgendermaßen wird ndbd in einer Bash-Shell gestartet:
bash-shell>export LD_PRELOAD=/opt/DIS/lib/libkscisock.so
bash-shell>ndbd
In einer tcsh-Umgebung erreichen Sie dasselbe mit:
tcsh-shell>setenv LD_PRELOAD=/opt/DIS/lib/libkscisock.so
tcsh-shell>ndbd
Hinweis: MySQL Cluster kann nur die Kernel-Variante von SCI Sockets nutzen.
Der ndbd-Prozess hat eine Reihe von einfachen Konstrukten, um auf die Daten in einem MySQL Cluster zuzugreifen. Wir haben eine ganz einfache Benchmark erstellt, um die jeweilige Leistung dieser Konstrukte zu testen und herauszufinden, wie sich die verschiedenen Verbindungen zwischen den Knoten auf diese Leistung auswirken.
Es gibt vier Zugriffsmethoden:
Zugriff über Primärschlüssel
Das ist der Zugriff auf einen Datensatz über seinen Primärschlüssel. Im einfachsten Fall wird immer nur auf einen einzigen Datensatz zugegriffen, was bedeutet, dass dieser eine einzige Request den vollen Aufwand verursacht, der erforderlich ist, um mehrere TCP/IP-Nachrichten und Kontextwechsel zu bewältigen. Wenn dagegen mehrere Primärschlüsselzugriffe in einem Stapel versandt werden, teilen sich diese Zugriffe die Kosten der notwendigen TCP/IP-Nachrichten und Kontextwechsel. Wenn die TCP/IP-Nachrichten an verschiedene Ziele gehen, müssen allerdings zusätzliche TCP/IP-Nachrichten eingerichtet werden.
Zugriff über eindeutigen Schlüssel
Zugriffe über eindeutige (unique) Schlüssel ähneln den Primärschlüsselzugriffen, allerdings mit dem Unterschied, dass sie als Leseoperation auf einer Indextabelle mit nachgeschaltetem Primärschlüsselzugriff auf die Tabelle funktionieren. Allerdings wird nur ein einziger Request vom MySQL Server abgeschickt und der Lesevorgang auf der Indextabelle wird von ndbd ausgeführt. Auch diese Art von Requests profitiert von der Stapelverarbeitung.
Vollständiger Tabellenscan
Wenn für einen Tabellen-Lookup keine Indizes vorhanden sind, wird ein vollständiger Tabellenscan ausgeführt. Dieser wird als ein einziger Request an den ndbd-Prozess gesandt, der dann den Tabellenscan in eine Menge von parallelen Scans auf alle ndbd-Prozesse im Cluster verteilt. In künftigen Versionen von MySQL Cluster wird ein SQL-Knoten in der Lage sein, manche dieser Scans herauszufiltern.
Bereichsscan mit geordnetem Index
Wenn ein geordneter Index verwendet wird, führt dieser eine Art vollständigen Tabellenscan aus, scannt aber nur die Datensätze in dem Intervall, welches die vom MySQL Server (SQL-Knoten) übermittelte Anfrage angibt. Alle Partitionen werden parallel gescannt, wenn alle gebundenen Indexattribute alle Attribute im Partitionierungsschlüssel enthalten.
Um die Grundleistung dieser Zugriffsmethoden testen zu können, haben wir eine Reihe von Benchmarks entwickelt. Eine davon, nämlich testReadPerf, testet einzeln und im Stapel übersandte Zugriffe über Primärschlüssel oder eindeutige Schlüssel. Diese Benchmark misst auch den Setup-Aufwand von Bereichsscans, indem sie Scans ausführt, die einen einzelnen Datensatz zurückliefern. Eine andere Variante dieser Benchmark holt mit einem Bereichsscan eine Menge von Datensätzen ab.
So können wir die Kosten eines einzelnen Schlüsselzugriffs und eines einzelnen Datensatzscans ermitteln und zusätzlich festellen, wie sich die Kommunikationsmedien bei welcher Zugriffsmethode auswirken.
In unseren Tests haben wir die Basis-Benchmarks sowohl für einen normalen Transporter mit TCP/IP-Sockets als auch für eine ähnliche Umgebung mit SCI Sockets ermittelt. Die Zahlen in der folgenden Tabelle gelten für kleinere Abfragen mit 20 Datensätzen pro Zugriff. Die Differenz zwischen seriellem und Stapelzugriff access schrumpft um den Faktor 3 bis 4, wenn stattdessen 2-Kbyte-Datensätze verwendet werden. SCI Sockets wurden nicht mit 2-Kbyte-Datensätzen getestet. Die Tests wurden auf einem Cluster mit 2 Datenknoten gefahren, der auf zwei Computern mit je zwei CPUs (AMD MP1900+-Prozessoren) residiert.
Zugriffsart | TCP/IP-Sockets | SCI Socket |
Serieller Primärschlüsselzugriff | 400 Mikrosekunden | 160 Mikrosekunden |
Primärschlüsselzugriff im Stapel | 28 Mikrosekunden | 22 Mikrosekunden |
Serieller Zugriff auf eindeutigen Schlüssel | 500 Mikrosekunden | 250 Mikrosekunden |
Stapelzugriff auf eindeutigen Schlüssel | 70 Mikrosekunden | 36 Mikrosekunden |
Indizierter eq-bound | 1.250 Mikrosekunden | 750 Mikrosekunden |
Indexbereich | 24 Mikrosekunden | 12 Mikrosekunden |
In einer anderen Testreihe haben wir die Leistung der SCI Sockets der des SCI Transporters und diese beiden wiederum der Leistung eines TCP/IP-Transporters gegenübergestellt. Alle diese Tests verwendeten Primärschlüsselzugriffe, entweder seriell und mit mehreren Threads oder mit mehreren Threads und im Stapel.
Die Tests haben gezeigt, dass SCI Sockets um rund 100 % schneller waren als TCP/IP. Der SCI Transporter war in den meisten Fällen schneller als SCI Sockets. Ein bemerkenswerter Fall trat bei einem Testprogramm mit vielen Threads auf: Hier zeigte sich, dass der SCI Transporter keine gute Leistung brachte, wenn er für den mysqld-Prozess benutzt wird.
Insgesamt zeigen unsere Tests, dass SCI Sockets in den meisten Benchmarks rund 100 % schneller sind als TCP/IP, außer in seltenen Fällen, in denen es nicht auf die Geschwindigkeit der Kommunikation ankommt. Dies kann der Fall sein, wenn die meiste Verarbeitungszeit für Scanfilter verbraucht wird oder wenn sehr große Stapel von Primärschlüsselzugriffen zustande kommen. In diesem Fall macht die CPU-Last der ndbd-Prozesse einen großen Teil des Aufwands aus.
Eine Verwendung des SCI Transporters anstelle von SCI Sockets ist nur für die Kommunikation zwischen ndbd-Prozessen interessant. Der SCI Transporter ist jedoch auch eine Option, wenn eine CPU für den ndbd-Prozess dediziert werden kann, da der SCI Transporter dafür sorgen kann, dass dieser Prozess niemals schläft. Außerdem ist es wichtig, zu gewährleisten, dass die Priorität des ndbd-Prozesses so eingestellt wird, dass er auch nach langem Laufen seine Priorität nicht einbüßt. Dies kann in Linux 2.6 durch das Sperren von Prozessen in CPUs getan werden. Wenn eine solche Konfiguration machbar ist, legt der ndbd-Prozess im Vergleich zu einer Lösung mit SCI Sockets um 10 bis 70 % zu. (Die größeren Zahlen kommen bei Updates und möglicherweise auch bei Parallelscans zustande.)
Es gibt noch mehrere andere optimierte Socketimplementierungen für Computer-Cluster, darunter Myrinet, Gigabit Ethernet, Infiniband und die VIA-Schnittstelle. Wir haben MySQL Cluster bisher jedoch nur mit SCI Sockets getestet. Unter Abschnitt 16.7.1, „Konfiguration von MySQL Cluster für SCI Sockets“, erfahren Sie, wie Sie SCI Sockets mit normalem TCP/IP für MySQL Cluster einrichten.
In diesem Abschnitt finden Sie eine Liste bekannter
Einschränkungen in den MySQL Cluster-Releases der
5.1.x-Serie im Vergleich zu den Features, die beim
Einsatz der Speicher-Engines MyISAM
und
InnoDB
zur Verfügung stehen. Es ist zurzeit
nicht geplant, diese Einschränkungen in den nächsten Releases
von MySQL 5.1 zu beseitigen, aber wir werden
versuchen, in der darauf folgenden Serie von Releases Lösungen
für diese Probleme zu finden. Wenn Sie in der
MySQL-Bugs-Datenbank http://bugs.mysql.com unter
der Kategorie „Cluster“ nachschauen, erfahren Sie,
welche bekannten Bugs (soweit sie mit
„5.1“ markiert sind) in den nächsten
Releases von MySQL 5.1 behoben werden sollen.
Die hier aufgeführte Liste sollte unter den soeben genannten Bedingungen komplett sein. Falls Ihnen irgendwelche Diskrepanzen auffallen, können Sie diese an die MySQL-Bugs-Datenbank melden, wie es unter Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“, beschrieben ist. Wenn wir nicht planen, das Problem in MySQL 5.1 zu beheben, werden wir es mit auf die Liste setzen.
Nichtkonforme Syntax (führt zu Fehlern bei der Ausführung vorhandener Anwendungen):
Textindizes werden nicht unterstützt.
Geometrische Datentypen (WKT
und
WKB
) werden in
NDB
-Tabellen in MySQL 5.1
unterstützt, aber raumbezogene (spatial) Indizes nicht.
Es ist nicht möglich, Partitionen von
NDB
-Tabellen mit ALTER TABLE
... DROP PARTITION
zu löschen. Die anderen
Partitionierungserweiterungen für ALTER
TABLE
, nämlich ADD
PARTITION
, REORGANIZE
PARTITION
und COALESCE
PARTITION
, werden für Cluster-Tabellen
unterstützt, aber Kopieren usw. ist nicht optimiert.
Siehe auch
Abschnitt 17.3.1, „Verwaltung von RANGE
- und
LIST
-Partitionen“, und
Abschnitt 13.1.2, „ALTER TABLE
“.
Seit MySQL 5.1.6 werden alle Cluster-Tabellen
standardmäßig nach KEY
partitioniert,
wobei der Primärschlüssel der Tabelle als
Partitionierungsschlüssel verwendet wird. Ist für die
Tabelle nicht explizit ein Primärschlüssel definiert,
wird automatisch von der Speicher-Engine
NDB
ein „verborgener“
Primärschlüssel erzeugt und benutzt. Mehr zu diesem und
verwandten Themen finden Sie unter
Abschnitt 17.2.4, „KEY
-Partitionierung“.
Nichtkonforme Grenzwerte oder Verhalten (kann bei der Ausführung vorhandener Anwendungen zu Fehlern führen):
Transaktionsbehandlung:
NDB Cluster
unterstützt als
einzige Ebene der Transaktionsisolation READ
COMMITTED
.
Ein teilweises Zurückrollen von Transaktionen ist nicht möglich. Ein Fehler wegen eines doppelten Schlüssels oder etwas Ähnlichem führt dazu, dass die gesamte Transaktion zurückgerollt wird.
Wichtig: Wenn ein
SELECT
auf einer Cluster-Tabelle
eine Spalte des Typs BLOB
,
TEXT
oder
VARCHAR
enthält, wird die
Transaktionsisolationsebene READ
COMMITTED
in einen Lesevorgang mit
Lesesperre umgewandelt. Dies wird getan, um die
Konsistenz zu garantieren, da Teile der in solchen
Spalten gespeicherten Werte in Wirklichkeit aus einer
anderen Tabelle gelesen werden.
Es gibt eine Reihe von harten Grenzwerten, die konfigurierbar sind, aber der im Cluster verfügbare Hauptspeicher setzt auf jeden Fall Grenzen. Die vollständige Liste der Konfigurationsparameter finden Sie in Abschnitt 16.4.4, „Konfigurationsdatei“. Die meisten dieser Parameter können online aktualisiert werden. Die erwähnten festen Grenzen sind:
Jeweiliger Arbeitsspeicher für Datenbank und Index
(DataMemory
und
IndexMemory
).
Wie viele Transaktionen höchstens ausgeführt werden
können, ist im Konfigurationsparameter
MaxNoOfConcurrentOperations
festgelegt. Beachten Sie, das Massenladeoperationen,
TRUNCATE TABLE
, und ALTER
TABLE
als Sonderfälle mit mehreren
Transaktionen abgearbeitet werden und daher nicht
dieser Einschränkung unterliegen.
Verschiedene Grenzwerte für Tabellen und Indizes. So
wird beispielsweise die Höchstzahl der geordneten
Indizes pro Tabelle durch
MaxNoOfOrderedIndexes
festgesetzt.
Datenbank-, Tabellen- und Attributnamen dürfen in
NDB
-Tabellen nicht so lang sein wie bei
anderen Tabellen-Handlern. Attributnamen werden auf 31
Zeichen gekappt. Wenn sie dann nicht mehr eindeutig sind,
gibt es einen Fehler. Datenbank- und Tabellennamen können
insgesamt 122 Zeichen lang sein. (Das bedeutet, dass ein
Name einer NDB Cluster
-Tabelle maximal
122 Zeichen minus die Länge des Namens der Datenbank
haben kann, zu welcher die Tabelle gehört.)
Alle Zeilen von Cluster-Tabellen haben eine feste Länge.
Wenn also (zum Beispiel) eine Tabelle ein oder mehrere
VARCHAR
-Felder mit relativ kleinen
Werten hat, brauchen diese bei der Speicher-Engine
NDB
mehr Speicherplatz als bei der
Speicher-Engine MyISAM
. (Mit anderen
Worten, eine VARCHAR
-Spalte belegt
beispielsweise ebenso viel Speicher wie eine gleich große
CHAR
-Spalte.)
Die Höchstzahl der Tabellen in einer Cluster-Datenbank ist auf 1.792 beschränkt.
Die Höchstzahl der Attribute pro Tabelle ist auf 128 beschränkt.
Die maximal zulässige Größe einer Zeile ist 8 Kbyte,
nicht inbegriffen die in
BLOB
-Spalten gespeicherten
Daten.
Die Höchstzahl der Attribute pro Schlüssel beträgt 32.
Nicht unterstützte Features (verursachen keinen Fehler, werden aber nicht unterstützt oder verlangt):
Das Fremdschlüsselkonstrukt wird, genau wie in
MyISAM
-Tabellen, ignoriert.
Savepoints und Rollbacks zu Savepoints werden, genau wie
in MyISAM
-Tabellen, ignoriert.
Probleme im Zusammenhang mit Leistung und Einschränkungen:
Aufgrund des sequenziellen Zugriffs hat die
NDB
-Speicher-Engine Leistungsprobleme
mit Anfragen. Auch ist es aufwändiger als mit
MyISAM
oder InnoDB
,
viele Bereichsscans auszuführen.
Die Records in range
-Statistik wird
nicht unterstützt, sodass sich in einigen Fällen
ungünstige Anfragenpläne ergeben. Als Workaround
empfehlen sich USE INDEX
oder
FORCE INDEX
.
Sie können keine mit USING HASH
erzeugten eindeutigen Hash-Indizes für den Zugriff auf
eine Tabelle verwenden, wenn NULL
als
Teil des Schlüssels angegeben ist.
MySQL Cluster unterstützt keine permanenten Commits auf der Platte. Commits werden repliziert, aber es gibt keine Garantie dafür, dass die Logs beim Committen auf die Platte zurückgeschrieben werden.
Fehlende Features:
Die einzige Isolationsebene, die unterstützt wird, ist
READ COMMITTED
. (InnoDB unterstützt
READ COMMITTED
, READ
COMMITTED
, REPEATABLE READ
und SERIALIZABLE
.) Unter
Abschnitt 16.6.5.5, „Backup: Troubleshooting“,
können Sie nachlesen, wie sich dies auf die Sicherung und
Wiederherstellung von Cluster-Datenbanken auswirkt.
Es gibt keine dauerhaften Commits auf der Platte. Die Commits werden repliziert, aber es gibt keine Garantie dafür, dass die Logs beim Committen auf die Platte zurückgeschrieben werden.
Probleme mit mehreren MySQL Servern
(betreffen nicht MyISAM
oder
InnoDB
):
ALTER TABLE
sperrt nicht vollständig,
wenn mehrere MySQL Server betrieben werden (keine
verteilte Tabellensperre).
MySQL-Replikation funktioniert nicht richtig, wenn Updates auf mehreren MySQL Servern ausgeführt werden. Wenn jedoch das Datenbank-Partitionierungsschema auf Anwendungsebene durchgeführt wird und keine Transaktionen über diese Partitionen hinweg stattfinden, kann die Replikation funktionieren.
Das selbstständige Erkennen von Datenbanken wird nicht
für mehrere MySQL Server unterstützt, die auf denselben
MySQL Cluster zugreifen. Die selbstständige Erkennung von
Tabellen wird dagegen in diesen Fälllen unterstützt.
Wenn also eine Datenbank namens
db_name
mit einem einzigen
MySQL Server angelegt oder importiert wurde, müssen Sie
für jeden weiteren Server, der auf denselben MySQL
Cluster zugreift, eine CREATE SCHEMA
-Anweisung
erteilen. Wenn dies für einen gegebenen MySQL Server
erledigt ist, müsste dieser in der Lage sein, die
Datenbanktabellen ohne Fehler zu erkennen.
db_name
Probleme, die ausschließlich MySQL
Cluster betreffen (nicht MyISAM
oder InnoDB
):
Alle Cluster-Computer müssen dieselbe Architektur haben. Das bedeutet, dass alle Knoten-Hosts konsistent entweder big-endian oder little-endian sein müssen. Beispielsweise darf es keinen Management-Knoten auf einem Power-PC geben, der einen Datenknoten auf einer x86-Maschine regelt. Diese Einschränkung gilt nicht für Computer, die einfach nur mysql ausführen, oder andere Clients, die vielleicht auf die SQL-Knoten des Clusters zugreifen.
Es sind keine Online-Schemaänderungen mit ALTER
TABLE
oder CREATE INDEX
möglich, da NDB Cluster
nicht die
selbstständige Erkennung solcher Änderungen
unterstützt. (Sie können jedoch eine Tabelle importieren
oder anlegen, die eine andere Speicher-Engine nutzt, und
diese dann mit ALTER TABLE
in eine
tbl_name
ENGINE=NDBCLUSTERNDB
-Tabelle umwandeln. In solchen
Fällen müssen Sie eine FLUSH
TABLES
-Anweisung geben, um den Cluster zu
zwingen, die Änderung aufzugreifen.)
Es ist nicht möglich, Knoten online hinzuzufügen oder zu löschen (der Cluster muss in solchen Fällen neu gestartet werden).
Wenn mehrere Management-Server verwendet werden, gelten folgende Regeln:
Sie müssen den Knoten in Verbindungs-Strings explizite IDs geben, da die automatische Zuweisung von Knoten-IDs nicht über mehrere Management-Server hinweg funktioniert.
Sie müssen genau darauf achten, dass alle Management-Server gleich konfiguriert sind. Der Cluster wird dies nicht extra prüfen.
Damit die Management-Knoten voneinander wissen, müssen Sie alle Datenknoten neu starten, nachdem der Cluster eingerichtet ist. (Genaue Erläuterungen finden Sie unter Bug#13070.)
Einige Netzwerkschnittstellen für Datenknoten werden nicht unterstützt. Wenn Sie diese verwenden, bekommen Sie Probleme: Wenn ein Datenknoten abstürzt, wartet ein SQL-Knoten auf die Bestätigung, dass der Datenknoten nicht mehr läuft, bekommt aber keine, da eine andere Route zu dem betroffenen Datenknoten weiterhin offen bleibt. Im Endeffekt kann dies den ganzen Cluster unbenutzbar machen.
Die Höchstzahl der Datenknoten beträgt 48.
Die Gesamtzahl aller Knoten in einem MySQL Cluster beträgt 63. Das umfasst sämtliche MySQL Server (SQL-Knoten), Datenknoten und Management-Server.
Die Höchstzahl der Metadatenobjekte in MySQL 5.1 Cluster beträgt 20.320. Diese Obergrenze ist fest eingegeben.
In diesem Abschnitt geht es um Änderungen an der Implementierung von MySQL Cluster in MySQL 5.1 im Vergleich zu MySQL 5.0. Außerdem werden wir unseren Fahrplan für künftige Verbesserungen an MySQL Cluster vorstellen, wie sie gegenwärtig für MySQL 5.2 vorgesehen sind.
Es gibt relativ wenig Änderungen zwischen der Implementierung von NDB Cluster in MySQL 5.0 und in 5.1, sodass der Upgrade relativ schnell und schmerzlos vonstatten gehen sollte.
Alle bedeutenden neuen Features, die für MySQL Cluster entwickelt werden sollen, kommen in den Baum von MySQL 5.1. Außerdem weisen wir weiter unten in diesem Abschnitt (siehe Abschnitt 16.9.2, „MySQL 5.1 Roadmap für die Entwicklung von MySQL Cluster“) darauf hin, was die Cluster in MySQL 5.1 voraussichtlich alles enthalten werden.
MySQL Cluster enthält in den Versionen 5.0.3-beta und folgende eine Reihe von neuen Features, die sicherlich interessant sein werden:
Pushdown-Bedingungen: Betrachten Sie folgende Anfrage:
SELECT * FROM t1 WHERE non_indexed_attribute = 1;
Diese Anfrage wird einen vollständigen Tabellenscan
ausführen und die Bedingung wird in den Datenknoten des
Clusters ausgewertet. Daher ist es nicht nötig, die
Datensätze zur Auswertung durchs Netzwerk zu schicken. (Es
werden also Funktionen und nicht Daten transportiert.) Bitte
beachten Sie, dass dieses Feature gegenwärtig nach
Voreinstellung deaktiviert ist (da die gründlicheren Tests
noch nicht abgeschlossen sind), aber in den meisten Fällen
bereits funktionieren müsste. Dieses Feature kann mit der
Anweisung SET engine_condition_pushdown =
On
aktiviert werden. Alternativ können Sie
mysqld so laufen lassen, dass das Feature
eingeschaltet wird, indem Sie den MySQL Server mit der
Option --engine-condition-pushdown
starten.
Ein Hauptvorteil dieser Änderung besteht darin, dass Anfragen parallel ausgeführt werden können. So laufen Anfragen auf nichtindizierten Spalten unter Umständen fünf- bis zehnmal schneller als zuvor, und dies mal der Anzahl der Datenknoten, da mehrere CPUs die Anfrage parallel bearbeiten können.
Mit dem Befehl EXPLAIN
können Sie
ermitteln, wann Pushdown-Bedingungen verwendet werden. Siehe
auch Abschnitt 7.2.1, „EXPLAIN
-Syntax (Informationen über ein
SELECT
erhalten)“.
Weniger Platzbedarf
IndexMemory
: In MySQL
5.1 belegt jeder Datensatz ungefähr 25 Byte
Index Memory und jeder eindeutige Index 25 Byte pro
Datensatz (und zusätzlich noch einigen Platz im Data
Memory, da diese Datensätze in einer separaten Tabelle
gespeichert werden). Das liegt daran, dass der
Primärschlüssel nun nicht mehr im Index Memory gespeichert
wird.
Der Anfragen-Cache ist für MySQL Cluster aktiviert: Mehr über die Konfiguration und Nutzung des Anfragen-Caches erfahren Sie unter Abschnitt 5.14, „MySQL-Anfragen-Cache“.
Neue Optimierungen: Eine Optimierung verdient eine gesonderte Erwähnung: Nämlich die, dass nun in manchen Anfragen ein Batched Read Interface verwendet wird. Betrachten Sie zum Beispiel folgende Anfrage:
SELECT * FROM t1 WHERE primary_key
IN (1,2,3,4,5,6,7,8,9,10);
Diese Anfrage wird zwei- bis dreimal schneller bearbeitet als in den früheren Versionen von MySQL Cluster, da alle zehn Schlüssel-Lookups in einem einzigen Schwung statt immer nacheinander übersandt werden.
Obergrenze für einige
Metadatenobjekte: In MySQL 5.1 kann jede
Cluster-Datenbank bis zu 20.320 Metadatenobjekte enthalten,
einschließlich Datenbanktabellen, Systemtabellen, Indizes
und BLOB
s.
Das Folgende ist ein Zustandsbericht über die neuesten Commits im MySQL 5.1-Quellbaum. Bitte beachten Sie, dass alle Entwicklungen an 5.1 sich noch laufend ändern können.
Gegenwärtig werden vier wichtige neue Features für MySQL 5.1 entwickelt:
Integration von MySQL Cluster in die MySQL-Replikation: Dadurch wird es möglich, von jedem beliebigen MySQL Server im Cluster Updates zu veranlassen und dennoch weiterhin die MySQL-Replikation von einem der MySQL Server im Cluster erledigen zu lassen, wobei der Status auf der Slave-Seite immer mit dem Cluster konsistent bleibt, der als Master fungiert.
Unterstützung für festplattenbasierte Datensätze: Datensätze auf Platte werden künftig unterstützt. Indizierte Felder mit Primärschlüssel-Hash-Index müssen zwar weiterhin im RAM gespeichert werden, aber alle anderen Felder können auf der Festplatte liegen.
Datensätze variabler
Länge: Eine
VARCHAR(255)
-Spalte belegt zurzeit
unabhängig von dem tatsächlichen Inhalt des Datensatzes
immer 260 Byte. In MySQL 5.1 Cluster-Tabellen wird nur der
Teil der Spalte gespeichert, der tatsächlich von
Datensatzdaten belegt ist. Dadurch kann der
Speicherplatzbedarf für solche Spalten in vielen Fällen um
maximal das Fünffache schrumpfen.
Benutzerdefinierte
Partitionierung: Die Benutzer können nun
Partitionen anhand von Spalten definieren, die Teil des
Primärschlüssels sind. Der MySQL Server kann feststellen,
ob es möglich ist, einige der Partitionen aus der
WHERE
-Klausel auszuschließen. Eine
Partitionierung anhand der KEY
-,
HASH
-, RANGE
- und
LIST
-Handler wird nun ebenso wie eine
Teilpartitionierung möglich sein. Dieses Feature sollte
auch für viele andere Handler und nicht nur für
NDB Cluster
zur Verfügung stehen.
Zusätzlich arbeiten wir daran, das 8-Kbyte-Limit auch für
Zeilen in Cluster-Tabellen heraufzusetzen, die andere
Spaltentypen als BLOB
oder
TEXT
enthalten. Denn gegenwärtig sind die
Zeilen noch auf diese Größe festgelegt und die Seitengröße
beträgt 32.768 Byte (minus 128 Byte für den Zeilen-Header).
Wenn wir also mehr als 8 Kbyte pro Datensatz gestatten, würde
daher der übrige Platz (bis zu ungefähr 14.000 Byte) leer
bleiben. In MySQL 5.1 wollen wir diese Einschränkung
beseitigen, sodass nicht mehr der ganze Rest der Seite
verschwendet wird, wenn mehr als 8 Kbyte für eine Zeile
benötigt werden.
In diesem Abschnitt werden häufig gestellte Fragen über MySQL Cluster beantwortet.
Was ist „NDB“?
Dies steht für „Network DataBase“.
Was macht es für einen Unterschied, ob ich Cluster oder Replikation nutze?
Bei einer Replikation aktualisiert ein MySQL-Master-Server
einen oder mehrere Slaves. Transaktionen werden nacheinander
committet und eine langsame Transaktion kann dazu führen,
dass der Slave hinter dem Master zurückbleibt. Das bedeutet:
Wenn der Master abstürzt, kann es dazu kommen, dass der Slave
die letzten paar Transaktionen nicht mitbekommen hat. Wird
eine transaktionssichere Engine wie InnoDB
benutzt, so wird eine Transaktion auf dem Slave entweder
abgeschlossen oder gar nicht angewendet. Bei der Replikation
ist jedoch nicht garantiert, dass alle Daten auf dem Master
und dem Slave zu jedem Zeitpunkt konsistent sind. In MySQL
Cluster hingegen sind immer alle Datenknoten synchron und eine
Transaktion, die von irgendeinem Datenknoten committet wird,
wird für alle Datenknoten committet. Wenn ein Datenknoten
abstürzt, bleiben alle übrigen Datenknoten in einem
konsistenten Zustand zurück.
Kurz: Während die MySQL-Replikation standardmäßig asynchron ist, ist MySQL Cluster synchron.
Wir planen, eine (asynchrone) Replikation für Cluster in MySQL 5.1 einzuführen. Dazu gehört auch die Fähigkeit, sowohl zwischen zwei Clustern als auch zwischen einem geclusterten und einem nichtgeclusterten MySQL Server zu replizieren.
Benötige ich ein spezielles Netzwerk für Cluster? (Wie kommunizieren Computer in einem Cluster?)
MySQL Cluster ist für die Benutzung in einer Umgebung mit großer Bandbreite und über TCP/IP verbundene Computer ausgelegt. Die Leistung des Clusters hängt direkt von der Schnelligkeit der Verbindungen zwischen den Cluster-Computern ab. Die Mindestanforderung für die Konnektivität in einem Cluster ist ein typisches 100-Megabit-Ethernet-Netzwerk oder etwas Entsprechendes. Wir empfehlen Ihnen, nach Möglichkeit ein 1-Gigabit-Ethernet einzusetzen.
Das schnellere SCI-Protokoll wird ebenfalls unterstützt, benötigt jedoch eine spezielle Hardware. Weitere Informationen über SCI finden Sie unter Abschnitt 16.7, „Verwendung von Hochgeschwindigkeits-Interconnects mit MySQL Cluster“.
Wie viele Computer sind für einen Cluster erforderlich und warum?
Für einen benutzbaren Cluster sind mindestens drei Computer notwendig. Empfohlen werden jedoch mindestens vier: je einer für den Management- und den SQL-Knoten und zwei, die als Speicherknoten dienen. Zwei Datenknoten sind wegen der Redundanz ratsam und der Management-Knoten muss auf einem eigenen Computer laufen, um auch beim Absturz eines Datenknotens weiterhin die Arbitrator-Funktion aufrechterhalten zu können.
Was tun die verschiedenen Computer in einem Cluster?
Ein MySQL Cluster hat sowohl eine physikalische als auch eine logische Struktur, wobei die Computer die physikalischen Elemente sind. Die logischen oder funktionalen Elemente eines Clusters werden als Knoten bezeichnet und ein Computer, auf dem ein Cluster-Knoten läuft, wird Cluster-Host genannt. Im Idealfall gibt es einen Knoten pro Cluster-Host, allerdings können auf einem einzelnen Host auch mehrere Knoten laufen. Es gibt drei Knotentypen, von denen jeder im Cluster eine bestimmte Rolle spielt:
Management-Knoten (MGM-Knoten): Leistet Management-Dienste für den Cluster als Ganzes, darunter Hochfahren, Herunterfahren, Datensicherungen und Bereitstellung von Konfigurationsdaten für die anderen Knoten. Der Management-Knoten-Server ist in Form der Anwendung ndb_mgmd implementiert, und der Management-Client, der den MySQL Cluster über den MGM-Knoten kontrolliert, ist ndb_mgm.
Datenknoten: Speichert und repliziert Daten. Seine Funktionalität erhält der Datenknoten von einer Instanz des NDB-Datenknotenprozesses ndbd.
SQL-Knoten: Dieser ist
einfach eine Instanz von MySQL Server
(mysqld), die mit Unterstützung für
die Speicher-Engine NDB Cluster
gebaut
und mit der Option --ndb-cluster
gestartet wurde, welche die Engine aktiviert.
Mit welchen Betriebssystemen kann ich Cluster benutzen?
MySQL Cluster wird offiziell für Linux, Mac OS X und Solaris unterstützt. Wir arbeiten daran, Cluster auch auf anderen Plattformen zu ermöglichen (einschließlich Windows), und haben uns das Ziel gesetzt, MySQL Cluster irgendwann auf allen Plattformen zu unterstützen, auf denen auch MySQL selbst läuft.
Es könnte möglich sein, Cluster-Prozesse auch auf anderen Betriebssystemen auszuführen. Einige Anwender berichten, Cluster bereits erfolgreich auf FreeBSD betrieben zu haben. Allerdings können Cluster auf anderen als den hier erwähnten drei Betriebssystemen bestenfalls als Alpha-Software gelten. Ihre Zuverlässigkeit in einer Produktionsumgebung kann nicht garantiert werden und wird nicht von MySQL AB unterstützt.
Welche Hardwareanforderungen stellt MySQL Cluster?
Cluster müssten auf jeder Plattform laufen, für die NDB-fähige Binaries zur Verfügung stehen. Natürlich wird die Leistung mit schnelleren CPUs und größerem Arbeitsspeicher besser, und 64-Bit-CPUs sind schneller als 32-Bit-Prozessoren. Die als Datenknoten verwendeten Computer müssen genug Arbeitsspeicher haben, um den Teil der Datenbank zu speichern, der auf diesem Datenknoten liegt (weitere Informationen siehe Wie viel RAM brauche ich?). Die Knoten können über ein normales TCP/IP-Netzwerk mit Standardhardware kommunizieren. Für die SCI-Unterstützung ist spezielle Netzwerkhardware erforderlich.
Wie viel RAM brauche ich? Kann überhaupt Festplattenspeicher benutzt werden?
Zurzeit sind Cluster lediglich arbeitsspeicherresident, sodass alle Tabellendaten (einschließlich Indizes) im Arbeitsspeicher abgelegt werden. Wenn Ihre Daten 1 Gbyte Platz benötigen und Sie sie einmal im Cluster replizieren möchten, benötigen Sie dafür folglich 2 Gbyte Hauptspeicher. Hinzu kommt der Arbeitsspeicher, den das Betriebssystem und irgendwelche sonstigen Anwendungen belegen, die auf den Cluster-Computern laufen.
Die folgende Formel liefert eine grobe Schätzung des für jeden Datenknoten im Cluster benötigten Arbeitsspeicherbedarfs:
(SizeofDatabase × NumberOfReplicas × 1.1 ) / NumberOfDataNodes
Um den Speicherbedarf genauer zu berechnen, müssen Sie für jede Tabelle in der Cluster-Datenbank den pro Zeile erforderlichen Speicher ermitteln (Einzelheiten siehe Abschnitt 11.5, „Speicherbedarf von Spaltentypen“) und diesen Wert mit der Zeilenzahl multiplizieren. Außerdem müssen Sie die Spaltenindizes wie folgt mit einkalkulieren:
Jeder Primärschlüssel oder Hash-Index auf einer
NDBCluster
-Tabelle benötigt
21–25 Byte pro Datensatz. Diese Indizes nutzen das
IndexMemory
.
Jeder geordnete Index belegt pro Datensatz 10 Byte
Speicher im DataMemory
.
Jeder Primärschlüssel oder eindeutige Schlüsselindex
erzeugt auch einen geordneten Index, wenn er nicht mit
USING HASH
angelegt wurde. Mit anderen
Worten: Ein ohne USING HASH
angelegter
Primärschlüssel oder eindeutiger Index auf einer
Cluster-Tabelle belegt in MySQL 5.1
31–35 Byte Speicher pro Datensatz.
Beachten Sie, dass Tabellenänderungen generell schneller
laufen, wenn alle Primärschlüssel und eindeutigen
Indizes auf MySQL Cluster-Tabellen mit USING
HASH
angelegt werden, da dann weniger
Arbeitsspeicher erforderlich ist (weil keine geordneten
Indizes erzeugt werden) und auch die Belastung der CPU
geringer ist (weil weniger Indizes gelesen und womöglich
geändert werden müssen).
Sehr wichtig: Bitte denken Sie daran, dass jede
MySQL Cluster-Tabelle einen Primärschlüssel haben
muss. Die Speicher-Engine NDB
legt automatisch einen Primärschlüssel an, wenn nicht
bereits einer definiert wurde, und dieser Primärschlüssel
wird ohne USING HASH
erzeugt.
Es gibt kein einfaches Mittel, um genau festzustellen, wann
wie viel Arbeitsspeicher von Cluster-Indizes belegt wird, aber
wenn 80 % des verfügbaren DataMemory
oder
IndexMemory
voll sind, wird eine Warnung in
das Cluster-Log geschrieben. Weitere Warnungen gibt es, wenn
85 %, 90 % usw. erreicht werden.
Oft erreichen uns Fragen von Anwendern, die berichten, dass der Ladeprozess beim Laden von Daten in eine Cluster-Datenbank vorzeitig mit einer Fehlermeldung wie dieser abbricht:
ERROR 1114: The table 'my_cluster_table' is full
Wenn dies geschieht, haben Sie höchstwahrscheinlich nicht
genügend RAM für alle Datentabellen und Indizes
einschließlich des von der Speicher-Engine
NDB
geforderten Primärschlüssels, der
automatisch erzeugt wird, wenn er in der Tabellendefinition
fehlt.
Außerdem müssen Sie berücksichtigen, dass alle Datenknoten gleich viel RAM haben sollten, da in einem Cluster kein Datenknoten mehr Speicher übrig hat als der an Speicher ärmste Datenknoten des Clusters. Mit anderen Worten: Wenn drei Computer Cluster-Datenknoten hosten und zwei davon 3 Gbyte RAM für Cluster-Daten übrig haben, während dem dritten nur 1 Gbyte verbleibt, können alle drei Datenknoten nur noch 1 Gbyte Speicher für den Cluster verwenden.
Da MySQL Cluster mit TCP/IP arbeitet: Bedeutet dies, dass ich den Cluster im Internet betreiben und einen oder mehrere Knoten remote halten kann?
Es ist mehr als zweifelhaft, dass ein Cluster unter solchen Bedingungen noch eine zuverlässige Leistung bringen könnte, da MySQL Cluster unter der Grundannahme entworfen und implementiert wurde, dass der Cluster eine Hochgeschwindigkeitsverbindung wie in einem LAN mit 100 Mbps oder einem Gigabit-Ethernet (vorzugsweise Letzterem) nutzen kann. Die Leistung mit einer langsameren Verbindung werden wir weder testen noch irgendwie gewährleisten.
Außerdem ist es außerordentlich wichtig, immer daran zu denken, dass die Kommunikation zwischen Knoten in einem MySQL Cluster nicht sicher ist. Die Datenübermittlungen werden weder verschlüsselt noch durch irgendeinen anderen Schutzmechanismus abgesichert. Die sicherste Konfiguration für einen Cluster ist ein privates Netzwerk hinter einer Firewall, ohne direkten Zugriff von außerhalb auf irgendwelche Cluster-Daten oder Management-Knoten. (Für SQL-Knoten sollten Sie dieselben Vorkehrungen treffen wie für jede andere Instanz des MySQL Servers.)
Muss ich für Cluster eine neue Programmiersprache oder Datenbank-Abfragesprache lernen?
Nein. Für die Verwaltung und Konfiguration des Clusters selbst werden zwar einige spezielle Befehle benötigt, aber für die folgenden Operationen sind nur (My)SQL-Standardabfragen und Standardbefehle erforderlich:
Tabellen anlegen, ändern und löschen
Tabellendaten einfügen, ändern und löschen
Primärschlüssel oder eindeutige Indizes anlegen, ändern und löschen
SQL-Knoten (MySQL Server) konfigurieren und verwalten.
Wie kann ich herausfinden, was eine Fehlermeldung oder Warnung bedeutet, wenn ich Cluster benutze?
Dafür gibt es zwei Möglichkeiten:
Sie können im mysql-Client direkt nachdem Sie den Fehler oder die Warnung bekommen haben, SHOW ERRORS oder SHOW WARNINGS aufrufen. Fehler und Warnungen werden auch im MySQL Query Browser angezeigt.
Sie können an einem Prompt der System-Shell
perror --ndb
error_code
ausführen.
Ist MySQL Cluster transaktionssicher? Welche Isolationsebenen werden unterstützt?
Ja. Für Tabellen, die mit der Speicher-Engine
NDB
angelegt wurden, werden Transaktionen
unterstützt. In MySQL 5.1 kennen Cluster
allerdings als einzige Ebene der Transaktionsisolation
READ COMMITTED
.
Welche Speicher-Engines unterstützt MySQL Cluster?
Clustering wird in MySQL nur von der Speicher-Engine
NDB
unterstützt. Um eine Tabelle für
Cluster-Knoten tauglich zu machen, muss sie also mit
ENGINE=NDB
(oder dem Äquivalent
ENGINE=NDBCLUSTER
) angelegt werden.
(Es ist möglich, Tabellen mit anderen Speicher-Engines wie
etwa MyISAM
oder InnoDB
auf einem MySQL Server anzulegen, der für Clustering
verwendet wird, doch diese
Nicht-NDB
-Tabellen können
nicht an dem Cluster
beteiligt sein.)
Welche Versionen von MySQL unterstützen Cluster? Muss ich die Quellversionen kompilieren?
Cluster wird in allen MySQL-max-Binaries der Release-Serie
5.1 unterstützt, mit den im folgenden Absatz
genannten Ausnahmen. Ob Ihr Server NDB unterstützt, können
Sie mit SHOW VARIABLES LIKE 'have_%'
oder
SHOW ENGINES
herausfinden. (Mehr
Informationen finden Sie unter Abschnitt 5.3, „mysqld-max, ein erweiterter mysqld-Server“.)
Linux-Benutzer müssen wissen, dass NDB
nicht in den Standard-RPMs für MySQL
Server enthalten ist. Es gibt auch separate RPM-Packages für
die Speicher-Engine NDB und die zugehörigen Management- und
anderen Tools. Downloadsites für diese RPMs sind im Abschnitt
für NDB RPM-Downloads der MySQL
5.1-Downloadseite angegeben. (Früher musste man
die -max
-Binaries verwenden, die als
.tar.gz
-Archive geliefert wurden. Auch
dies ist immer noch möglich, aber nicht mehr nötig; heute
können Sie den RPM-Manager Ihrer Linux-Distribution nutzen,
wenn Sie es möchten.) NDB-Unterstützung bekommen Sie auch,
indem Sie die -max
-Binaries von der Quelle
kompilieren, doch bloß um MySQL Cluster-Unterstützung zu
bekommen, ist das nicht erforderlich. Um die neueste Binary,
RPM oder Quelldistribution der MySQL 5.1-Serie
herunterzuladen, gehen Sie zu
http://dev.mysql.com/downloads/mysql/5.1.html.
Würde ich im Katastrophenfall, etwa wenn die ganze Stadt einen Stromausfall hat und zusätzlich meine unterbrechungsfreie Stromversorgung versagt, alle meine Daten verlieren?
Da alle committeten Transaktionen protokolliert werden, ist es zwar möglich, dass einige Daten in einem solchen Katastrophenfall verloren gehen könnten, aber der Verlust dürfte sich in Grenzen halten. Der Datenverlust kann zusätzlich begrenzt werden, indem Sie die Anzahl der Operationen pro Transaktion reduzieren. (Es ist immer schlecht, zu viele Operationen in einer einzigen Transaktion auszuführen.)
Kann man in einem Cluster
FULLTEXT
-Indizes benutzen?
FULLTEXT
-Indizes werden zurzeit weder von
NDB
noch von irgendeiner anderen
Speicher-Engine außer MyISAM
unterstützt.
Wir arbeiten daran, diese Fähigkeit in einem künftigen
Release hinzuzufügen.
Kann ich mehrere Knoten auf einem einzigen Computer laufen lassen?
Das ist möglich, aber nicht ratsam. Einer der Hauptgründe für ein Cluster ist die Redundanz. Um jedoch alle Vorteile der Redundanz zu gewährleisten, sollte jeder Knoten auf einem eigenen Computer laufen. Wenn Sie mehrere Knoten auf einem einzigen Computer betreiben und dieser abstürzt, verlieren Sie alle diese Knoten. Wenn man bedenkt, dass MySQL Cluster auf Standardhardware mit einem billigen (oder sogar kostenlosen) Betriebssystem laufen kann, dann lohnt es sich wohl, ein oder zwei zusätzliche Rechner anzuschaffen, um missionskritische Daten zu sichern. Überdies sind die Anforderungen an einen Cluster-Host, auf dem ein Management-Knoten läuft, minimal: Diese Aufgabe kann schon ein 200-MHz-Pentium bewältigen, wenn er genügend RAM für das Betriebssystem plus einen geringen Overhead für die ndb_mgmd- und ndb_mgm-Prozesse hat.
Kann ich einem Cluster Knoten hinzufügen, ohne ihn neu starten zu müssen?
Zurzeit noch nicht. Allerdings ist ein Neustart alles, was Sie tun müssen, um einem Cluster neue MGM- oder SQL-Knoten hinzuzufügen. Wenn Sie Datenknoten hinzufügen, liegen die Dinge etwas komplizierter; dafür sind folgende Schritte nötig:
Sie sichern alle Cluster-Daten.
Sie fahren den Cluster und alle Cluster-Knoten-Prozesse vollständig herunter.
Sie starten den Cluster mit der Startoption
--initial
neu.
Sie stellen alle Cluster-Daten aus den Sicherungsdateien wieder her.
In einer künftigen Release-Serie von MySQL Cluster hoffen wir, MySQL Cluster eine „heiße“ Rekonfigurationsfähigkeit implementieren zu können, um die Anforderungen an den Neustart des Clusters nach dem Hinzufügen neuer Knoten zu minimieren (wenn nicht gar zu eliminieren).
Muss ich irgendwelche Einschränkungen berücksichtigen, wenn ich Cluster benutze?
Für NDB
-Tabellen gelten in MySQL folgende
Einschränkungen:
Sie unterstützen nicht alle Zeichensätze und Kollationen.
Sie unterstützen keine
FULLTEXT
-Indizes und Indexpräfixe. Nur
vollständige Spalten können indiziert werden.
Sie unterstützen keine raumbezogenen Datentypen. Siehe auch Kapitel 18, Raumbezogene Erweiterungen in MySQL.
Sie unterstützen nur vollständige Rollbacks von Transaktionen. Teilweise Rollbacks und Rollbacks zu Savepoints werden nicht unterstützt.
Pro Tabelle dürfen maximal 128 Attribute verwendet werden und die Attributnamen dürfen nicht länger als 31 Zeichen sein. Für jede Tabelle beträgt die Höchstlänge für den Tabellen- plus Datenbanknamen 122 Zeichen.
Eine Tabellenzeile darf maximal 8 Kbyte lang sein,
BLOB
s nicht inbegriffen. Für die
Zeilenzahl pro Tabelle gibt es keine festgesetzte
Obergrenze. Die Größenbeschränkungen für Tabellen
hängen von mehreren Faktoren ab, besonders von dem für
jeden Datenknoten verfügbaren Arbeitsspeicher.
Die NDB
-Engine unterstützt keine
Fremdschlüssel-Constraints. Diese werden wie in
MyISAM
ignoriert.
Query-Caching wird nicht unterstützt.
Weitere Informationen über Beschränkungen in Clustern finden Sie unter Abschnitt 16.8, „Bekannte Beschränkungen von MySQL Cluster“.
Wie importiere ich eine vorhandene MySQL-Datenbank in einen Cluster?
Wie in jede andere Version von MySQL können Sie auch in MySQL
Cluster Datenbanken importieren. Außer den im obigen Absatz
erwähnten Beschränkungen gibt es nur eine einzige weitere
Sonderbedingung: Alle Tabellen, die in den Cluster eingebracht
werden sollen, müssen die Speicher-Engine
NDB
verwenden. Das bedeutet, dass die
Tabellen mit ENGINE=NDB
oder
ENGINE=NDBCLUSTER
angelegt werden müssen.
Es ist auch möglich, bestehende Tabellen, die andere
Speicher-Engines nutzen, mit ALTER TABLE
in
NDB Cluster
zu konvertieren, aber dafür
ist ein zusätzlicher Workaround notwendig. Einzelheiten siehe
Abschnitt 16.8, „Bekannte Beschränkungen von MySQL Cluster“.
Wie kommunizieren Cluster-Knoten?
Cluster-Knoten können über drei Protokolle miteinander kommunizieren: TCP/IP, SHM (Shared Memory) und SCI (Scalable Coherent Interface). Wo es zur Verfügung steht, wird nach Voreinstellung SHM für Knoten benutzt, die auf demselben Cluster-Host residieren. SCI ist ein sehr schnelles (1 Gigabit pro Sekunde und mehr) und hochverfügbares Protokoll, das beim Aufbau skalierbarer Mehrprozessorsysteme zum Einsatz kommt. Es erfordert spezielle Hardware und Treiber. Unter Abschnitt 16.7, „Verwendung von Hochgeschwindigkeits-Interconnects mit MySQL Cluster“, erfahren Sie mehr über SCI als Transportmechanismus in MySQL Cluster.
Was ist ein „Arbitrator“?
Wenn ein oder mehrere Cluster-Knoten abstürzen, ist es möglich, dass nicht mehr alle Cluster-Knoten einander „sehen“ können. Es kann sogar passieren, dass zwei Knotenmengen durch eine Netzwerkpartitionierung voneinander isoliert werden, die man auch als „Split Brain“-Szenario bezeichnet. Eine solche Situation ist nicht wünschenswert, da jede der beiden Knotenmengen versuchen würde, den gesamten Cluster darzustellen.
Wenn Cluster-Knoten abstürzen, gibt es zwei Möglichkeiten: Wenn mehr als 50 % der verbleibenden Knoten miteinander kommunizieren können, haben wir eine so genannte „Majority Rules“-Situation („die Mehrheit regiert“), und diese Knotenmenge wird dann als der Cluster betrachtet. Der Arbitrator kommt ins Spiel, wenn es einen Gleichstand zwischen den Knoten gibt: In solchen Fällen wird die Knotenmenge, zu welcher der Arbitrator gehört, als der Cluster betrachtet, und die anderen Knoten werden heruntergefahren.
Diese Darstellung ist etwas vereinfachend. Eine genauere Erkärung, die auch Knotengruppen berücksichtigt, folgt:
Wenn alle Knoten in mindestens einer Knotengruppe am Leben
sind, entstehen keine Probleme mit Netzwerkpartitionierung, da
kein einzelner Teil des Clusters einen funktionsfähigen
Cluster bilden kann. Das eigentliche Problem entsteht, wenn in
keiner Knotengruppe alle Knoten mehr am Leben sind. In diesem
Fall wird eine Netzwerkpartitionierung, das so genannte
„Split-Brain“-Szenario, möglich. Dann ist ein
Arbitrator (engl. für „Schiedsrichter“)
gefordert. Alle Cluster-Knoten betrachten denselben Knoten,
normalerweise den Management-Knoten, als Arbitrator. Es ist
jedoch möglich, stattdessen einen der MySQL Server im Cluster
als Arbitrator zu konfigurieren. Der Arbitrator gestattet,
dass die erste Knotenmenge mit ihm Kontakt aufnimmt, und
fährt die andere Knotenmenge herunter. Die Wahl des
Arbitrators wird durch den Konfigurationsparameter
ArbitrationRank
für MySQL Server- und
Management-Server-Knoten gesteuert. (Einzelheiten siehe
Abschnitt 16.4.4.4, „Festlegung des MySQL Cluster-Management-Servers“.) Beachten Sie
außerdem, dass der Arbitrator an sich keine großen
Anforderungen an den als Arbitrator ausgewählten Host stellt,
er muss also nicht besonders schnell sein oder einen besonders
großen Arbeitsspeicher haben, um für diese Aufgabe geeignet
zu sein.
Welche Datentypen unterstützt MySQL Cluster?
MySQL Cluster unterstützt alle üblichen MySQL-Datentypen,
ausgenommen die raumbezogenen, die zur Spatial-Erweiterung von
MySQL gehören. (Siehe Kapitel 18, Raumbezogene Erweiterungen in MySQL.)
Darüber hinaus gibt es bei NDB
-Tabellen
einige Abweichungen im Hinblick auf Indizes.
Hinweis: MySQL
Cluster-Tabellen (also Tabellen, die mit
ENGINE=NDBCLUSTER
angelegt wurden) haben
nur Zeilen mit fester Breite. Das bedeutet beispielsweise,
dass ein Datensatz mit einer
VARCHAR(255)
-Spalte Speicher für 255
Zeichen belegt (wie Zeichensatz und die Kollation der Tabelle
es erfordern), unabhängig davon, wie viele Zeichen
tatsächlich in der Spalte gespeichert sind. Dieses Problem
soll in einer künftigen Release-Serie von MySQL behoben
werden.
Mehr zu diesen Fragen lesen Sie unter Abschnitt 16.8, „Bekannte Beschränkungen von MySQL Cluster“.
Wie kann ich MySQL Cluster starten und anhalten?
Jeder Knoten im Cluster muss separat gestartet werden, und zwar in folgender Reihenfolge:
Sie starten den Management-Knoten mit dem Befehl ndb_mgmd.
Sie starten jeden Datenknoten mit dem Befehl ndbd.
Sie starten jeden MySQL Server (SQL-Knoten) mit dem Befehl mysqld_safe --user=mysql &.
Jeder dieser Befehle muss in der System-Shell des Computers ausgeführt werden, auf dem der betreffende Knoten ausgeführt wird. Ob der Cluster läuft, können Sie prüfen, indem Sie den MGM-Management-Client ndb_mgm auf dem Computer aufrufen, auf dem der MGM-Knoten läuft.
Was passiert mit den Cluster-Daten, wenn der Cluster heruntergefahren wird?
Die Daten, die in den Datenknoten des Clusters im Arbeitsspeicher liegen, werden auf die Platte geschrieben und beim nächsten Start des Clusters wieder in den Arbeitsspeicher geladen.
Um den Cluster herunterzufahren, geben Sie folgenden Befehl in die Shell des MGM-Knoten-Hosts ein:
shell> ndb_mgm -e shutdown
Das beendet geräuschlos ndb_mgm, ndb_mgm und alle ndbd-Prozesse. MySQL Server, die als SQL-Knoten eines Clusters laufen, können mit mysqladmin shutdown angehalten werden.
Weitere Informationen finden Sie unter Abschnitt 16.6.2, „Befehle des Management-Clients“, und Abschnitt 16.3.6, „Sicheres Herunterfahren und Neustarten“.
Ist es nützlich, mehr als einen Management-Knoten im Cluster zu haben?
Das kann als Ausfallsicherung hilfreich sein. Zwar wird der Cluster immer nur von einem MGM-Knoten gesteuert, aber es ist möglich, einen MGM als Primärknoten und andere als Ausfallsicherung zu konfigurieren, für den Fall, dass der Primär-MGM-Knoten abstürzt.
Kann ich in einem Cluster unterschiedliche Hardware und Betriebssysteme mixen?
Ja, aber nur wenn alle Computer und Betriebssysteme dieselbe "Endianness" haben (also entweder alle big-endian oder alle little-endian sind). Es ist auch möglich, auf verschiedenen Knoten verschiedene Releases von MySQL Cluster zu benutzen. Dies können wir jedoch nur im Rahmen einer laufenden Upgrade-Prozedur empfehlen.
Kann ich zwei Datenknoten auf einem einzigen Host betreiben? Oder zwei SQL-Knoten?
Ja, möglich wäre das schon. Wenn Sie mehrere Datenknoten haben, muss jeder Knoten ein anderes Data Directory benutzen. Wenn Sie mehrere SQL-Knoten auf derselben Maschine laufen lassen wollen, muss jede mysqld-Instanz einen anderen TCP/IP-Port benutzen.
Kann ich Hostnamen mit MySQL Cluster benutzen?
Ja, Sie können DNS und DHCP für Cluster-Hosts benutzen. Wenn Ihre Anwendung jedoch eine Verfügbarkeit von 99,999 Prozent benötigt, empfehlen wir feste IP-Adressen. Wenn Sie die Kommunikation zwischen Cluster-Hosts von Diensten wie DNS und DHCP abhängig machen, führen Sie damit zusätzliche Points of Failure ein. Je weniger es davon gibt, desto besser.
Die folgenden Begriffe sind wichtig für das Verständnis von MySQL Cluster oder haben in diesem Zusammenhang eine spezielle Bedeutung.
Cluster:
Im generischen Sinne ist ein Cluster eine Menge von Computern, die als Einheit funktionieren und zusammenarbeiten, um eine einzelne Aufgabe zu erfüllen.
NDB
Cluster
:
Dies ist die Speicher-Engine, mit der MySQL eine auf mehrere Computer verteilte Implementierung von Datenspeicherung, -abruf und -verwaltung implementiert.
MySQL Cluster:
Eine Gruppe von Computern, die zusammenarbeiten und die
Speicher-Engine NDB
verwenden, um eine
verteilte MySQL-Datenbank in einer
Share-Nothing-Architektur mit
arbeitsspeicherresidenter Speicherung zu
ermöglichen.
Konfigurationsdateien:
Textdateien mit Anweisungen und Informationen über den Cluster, seine Hosts und seine Knoten. Diese werden beim Hochfahren des Clusters von dessen Management-Knoten gelesen. Einzelheiten siehe Abschnitt 16.4.4, „Konfigurationsdatei“.
Datensicherung (Backup):
Eine vollständige Kopie aller Cluster-Daten, Transaktionen und Logs, die auf der Festplatte oder einem anderen Langzeitspeicher abgelegt wird.
Wiederherstellung (Restore):
Den Cluster in den Zustand zurückversetzen, der in der Datensicherung gespeichert ist.
Checkpoint:
Im Allgemeinen: Wenn die Daten auf der Festplatte gespeichert
werden, sagt man, dass ein Checkpoint erreicht wurde. Eher
Cluster-spezifisch ausgedrückt, ein Checkpoint ist ein
Zeitpunkt, zu dem alle committeten Transaktionen auf der
Festplatte gespeichert werden. Im Hinblick auf die
Speicher-Engine NDB
gibt es zwei Arten von
Checkpoints, die zusammen gewährleisten, dass eine
konsistente View der Cluster-Daten bewahrt bleibt:
Lokaler Checkpoint (LCP):
Dieser Checkpoint ist für einen einzelnen Knoten spezifisch; allerdings können LCPs mehr oder weniger nebenläufig in allen Knoten im Cluster stattfinden. Bei einem LCP, der normalerweise alle paar Minuten eintritt, werden alle Daten eines Knotens auf der Platte gespeichert. Das genaue Intervall variiert ebenso wie die vom Knoten gespeicherte Datenmenge, der Grad der Cluster-Aktivität und andere Faktoren.
Globaler Checkpoint (GCP):
Ein GCP tritt alle paar Sekunden auf, wenn Transaktionen für alle Knoten synchronisiert werden und das Redo-Log auf die Festplatte geschrieben wird.
Cluster-Host:
Ein Computer, der einen Teil eines MySQL Clusters bildet. Ein Cluster hat sowohl eine physikalische als auch eine logische Struktur. Physikalisch besteht er aus einigen Computern, den so genannten Cluster-Hosts (oder einfach nur Hosts). Siehe auch Knoten und Knotengruppe weiter unten.
Knoten:
Eine logische oder funktionale Einheit eines MySQL Clusters, die machmal auch Cluster-Knoten genannt wird. Im Zusammenhang mit MySQL Cluster ist „Knoten“ eher ein Prozess als eine physikalische Komponente des Clusters. Für einen funktionierenden MySQL Cluster sind drei Arten von Knoten erforderlich:
Management(MGM)-Knoten:
Verwaltet die anderen Knoten im MySQL Cluster. Er liefert die Konfigurationsdaten an andere Knoten, startet und stoppt sie, kümmert sich um Netzwerkpartitionierung, legt Sicherungen an und stellt Daten aus Sicherungen wieder her usw.
SQL-Knoten (MySQL Server):
Instanzen des MySQL Servers, die als Frontend für Daten dienen, welche in den Datenknoten des Clusters liegen. Clients, die Daten speichern, abrufen oder ändern wollen, können auf einen SQL-Knoten wie auf jeden gewöhnlichen MySQL Server zugreifen, mit den üblichen Authentifizierungsmethoden und APIs. Die darunter liegende Verteilung der Daten auf Knotengruppen ist für Benutzer und Anwendungen nicht erkennbar. SQL-Knoten greifen auf die Datenbanken des Clusters als Ganzes zu, ohne sich um die Verteilung der Daten auf verschiedene Datenknoten oder Cluster-Hosts zu kümmern.
Datenknoten:
Diese Knoten speichern die tatsächlichen Daten. Tabellendatenfragmente werden in einer Menge von Knotengruppen gespeichert, wobei jede Knotengruppe eine andere Teilmenge der Tabellendaten speichert. Jeder Knoten, der zu einer Knotengruppe gehört, speichert eine Replik des Fragments, für das die Knotengruppe zuständig ist. Zurzeit kann ein einzelner Cluster insgesamt bis zu 48 Datenknoten unterstützen.
Mehrere Knoten können auf demselben Computer koexistieren. (Es ist sogar möglich, einen kompletten Cluster auf einer einzigen Maschine einzurichten, doch niemand würde dies in einer Produktionsumgebung tun.) Bitte merken Sie sich, dass sich der Begriff Host im Zusammenhang mit MySQL Cluster auf eine physikalische Komponente des Clusters bezieht, während mit Knoten eine logische oder funktionale Komponente (ein Prozess) gemeint ist.
Hinweis auf veraltete Begriffe: In älteren Versionen der Dokumentation zu MySQL Cluster wurden Datenknoten manchmal als „Datenbankknoten“, „DB-Knoten“ oder „Speicherknoten“ und SQL-Knoten als „Client-Knoten“ oder „API-Knoten“ bezeichnet. Diese ältere Terminologie wurde verworfen, um keine Verwirrung zu stiften, und sollte daher nicht mehr benutzt werden.
Knotengruppe:
Eine Menge von Datenknoten. Alle Datenknoten in einer Knotengruppe enthalten dieselben Daten (Fragmente) und alle Knoten einer Gruppe sollten auf verschiedenen Hosts residieren. Es ist möglich, zu steuern, welche Knoten zu welchen Gruppen gehören.
Knoten-Absturz:
MySQL Cluster ist nicht darauf angewiesen, dass jeder einzelne Knoten im Cluster funktioniert. Der Cluster kann auch dann weiterlaufen, wenn ein oder mehrere Knoten abstürzen. Wie viele abgestürzte Knoten ein Cluster im Einzelfall verträgt, hängt von der Anzahl der Knoten und der Konfiguration des Clusters ab.
Knoten-Neustart:
Der Prozess, einen abgestürzten Knoten wieder ans Laufen zu bringen.
Initialer Knoten-Neustart:
Der Prozess, einen Cluster-Knoten zu starten, dessen Dateisystem entfernt wurde. Dies wird manchmal bei Softwareupgrades oder unter anderen Sonderbedingungen getan.
System-Crash (oder Systemabsturz):
Dieser kann auftreten, wenn so viele Cluster-Knoten abgestürzt sind, dass der konsistente Zustand des Clusters nicht mehr garantiert werden kann.
System-Neustart:
Der Neustart eines Clusters samt Reinitialisierung seines Zustands aus den Festplatten-Logs und Checkpoints. Ist nach einem geplanten oder außerplanmäßigen Shutdown des Clusters erforderlich.
Fragment:
Ein Teil einer Datenbanktabelle. In der Speicher-Engine
NDB
wird eine Tabelle in Fragmente zerlegt
und so gespeichert. Ein Fragment wird manchmal auch
„Partition“ genannt, doch „Fragment“
ist der bessere Begriff. Tabellen werden in MySQL Cluster
fragmentiert, um die Lastverteilung zwischen Computern und
Knoten zu erleichtern.
Replik:
Unter der Speicher-Engine NDB
hat jedes
Tabellenfragment eine Reihe von Replikas, die aus
Redundanzgründen auf anderen Datenknoten gespeichert werden.
Gegenwärtig kann es bis zu vier Replikas pro Fragment geben.
Transporter:
Ein Protokoll für die Datenübermittlung zwischen Knoten. MySQL Cluster unterstützt zurzeit vier verschiedene Arten von Transporter-Verbindungen:
TCP/IP
Dies ist natürlich das vertraute Netzwerkprotokoll, das auch die Grundlage von HTTP, FTP (usw.) im Internet bildet. TCP/IP kann sowohl für lokale als auch für Remote-Verbindungen eingesetzt werden.
SCI
Scalable Coherent Interface ist ein Hochgeschwindigkeitsprotokoll, das zur Erstellung von Mehrprozessorsystemen und Anwendungen für die Parallelverarbeitung benutzt wird. Die Verwendung von SCI mit MySQL Cluster erfordert spezielle Hardware, wie in Abschnitt 16.7.1, „Konfiguration von MySQL Cluster für SCI Sockets“, beschrieben. Eine grundlegende Einführung in SCI finden Sie unter http://www.dolphinics.com/corporate/scitech.html.
SHM
Shared
memory-Segmente wie bei
Unix. Wenn SHM unterstützt wird, wird es automatisch für
die Verbindung von Knoten auf demselben Host verwendet.
Wenn Sie mehr über dieses Thema erfahren möchten,
lesen Sie am besten auf der
Unix-Manpage
fürshmop(2)
nach.
Hinweis: Der Cluster-Transporter ist für den Cluster intern. Anwendungen, die MySQL Cluster nutzen, kommunizieren mit SQL-Knoten wie mit jeder anderen Version von MySQL Server (über TCP/IP oder mittels Unix-Socketdateien oder der Named Pipes von Windows). Über die Standardclient-APIs von MySQL können Anfragen gesandt und Antworten abgerufen werden.
NDB
:
Die Abkürzung für Network Database, also die Speicher-Engine, mit der MySQL Cluster eingeschaltet wird. Diese Speicher-Engine unterstützt alle üblichen MySQL-Datentypen und SQL-Anweisungen und ist ACID-fähig. Außerdem bietet sie volle Transaktionsunterstützung (Commits und Rollbacks).
Share-Nothing-Architektur:
Die ideale Architektur für einen MySQL Cluster. In einer richtigen Share-Nothing-Umgebung läuft jeder Knoten auf einem separaten Host. Das hat den Vorteil, dass ein einzelner Host oder Knoten kein Single Point of Failure oder Leistungsengpass für das Gesamtsystem sein kann.
Speicherresident:
Alle Daten, die in den Datenknoten gespeichert sind, hält der Hostcomputer dieses Knotens im Arbeitsspeicher. Für jeden Datenknoten im Cluster muss daher RAM in der Größenordnung Datenbankgröße mal Anzahl Replikas geteilt durch Anzahl der Datenknoten vorgehalten werden. Wenn also die Datenbank 1 Gbyte belegt und Sie den Cluster mit vier Replikas und acht Datenknoten einrichten möchten, ist pro Knoten mindestens 500 Mbyte Arbeitsspeicher erforderlich. Beachten Sie, dass dazu noch der Speicherbedarf für das Betriebssystem und die anderen Anwendungen kommt, die vielleicht auf dem Host laufen.
Tabelle:
Wie es bei relationalen Datenbanken üblich ist, ist eine „Tabelle“ eine Menge identisch strukturierter Datensätze. In MySQL Cluster wird eine Datenbanktabelle auf einem Datenknoten in Form einer Reihe von Fragmenten gespeichert, wobei jedes Fragment auf anderen Datenknoten repliziert wird. Die Menge der Datenknoten, welche dieselben Fragmente replizieren, nennt man Knotengruppe.
Cluster-Programme:
Kommandozeilenprogramme, die zum Ausführen, Konfigurieren und Administrieren von MySQL Cluster erforderlich sind. Hierzu gehören beide Server-Daemons:
ndbd:
Der Datenknoten-Daemon (führt einen Datenknoten-Prozess aus)
ndb_mgmd:
Der Management-Server-Daemon (führt einen Management-Server-Prozess aus)
und Clientprogramme:
ndb_mgm:
Der Management-Client (stellt die Schnittstelle zur Ausführung von Management-Befehlen zur Verfügung)
ndb_waiter:
Prüft den Status aller Knoten in einem Cluster
ndb_restore:
Stellt Cluster-Daten aus einer Datensicherung wieder her
Mehr über diese Programme und ihre Verwendung erfahren Sie unter Abschnitt 16.5, „Prozessverwaltung in MySQL Cluster“.
Ereignislog:
MySQL Cluster protokolliert Ereignisse nach Kategorie (Starten, Herunterfahren, Fehler, Checkpoints usw.), Priorität und Ernsthaftigkeit. Eine vollständige Liste aller protokollierungsfähigen Ereignisse finden Sie unter Abschnitt 16.6.3, „Ereignisberichte, die MySQL Cluster erzeugt“. Es gibt zwei Arten von Ereignislogs:
Cluster-Log:
Zeichnet alle gewünschten protokollierbaren Ereignisse für den Cluster als Ganzes auf.
Knoten-Log:
Ein separates Log, das für jeden einzelnen Knoten gepflegt wird.
Unter normalen Umständen ist es notwendig und hinreichend, nur das Cluster-Log zu pflegen und zu untersuchen. In die Knoten-Logs schauen Sie nur bei der Anwendungsentwicklung und beim Debuggen hinein.
Inhaltsverzeichnis
In diesem Kapitel geht es um die in MySQL 5.1 implementierten Formen der Partitionierung. Eine Einführung in Partitionierung und Partitionierungskonzepte finden Sie in Abschnitt 17.1, „Überblick über die Partitionierung in MySQL“. MySQL 5.1 unterstützt mehrere Formen der Partitionierung, die in Abschnitt 17.2, „Partitionstypen“, beschrieben werden, sowie der Teilpartitionierung (auch als zusammengesetzte Partitionierung bezeichnet), die in Abschnitt 17.2.5, „Unterpartitionen“, beschrieben werden. Wie Partitionen in partitionierten Tabellen hinzugefügt, entfernt oder geändert werden, erfahren Sie in Abschnitt 17.3, „Partitionsverwaltung“. Tabellenwartungsbefehle für partitionierte Tabellen behandeln wir in Abschnitt 17.3.3, „Wartung von Partitionen“.
Wichtig: Partitionierte Tabellen,
die mit den MySQL-Versionen vor 5.1.6 angelegt wurden, können von
einem MySQL Server der Version 5.1.6 oder höher nicht gelesen
werden. Außerdem kann die
INFORMATION_SCHEMA.TABLES
-Tabelle nicht benutzt
werden, wenn solche Tabellen auf einem Server liegen, der mit der
Version 5.1.6 oder höher betrieben wird. Wenn Sie partitionierte
Tabellen haben, die mit MySQL 5.1.5 oder früher angelegt wurden,
lesen Sie unbedingt die Zusatzinformationen und empfohlenen
Workarounds in Abschnitt D.1.1, „Änderungen in Release 5.1.6 (Noch nicht veröffentlicht)“, nach,
bevor Sie auf MySQL 5.1.6 oder höher
aufrüsten.
Die Partitionierungsimplementierung in MySQL 5.1 befindet sich noch
in der Entwicklung und ist noch nicht bereit für
Produktionsumgebungen. Etwas Ähnliches gilt für den Inhalt dieses
Kapitels: Manche der hier beschriebenen Features sind in
Wirklichkeit noch gar nicht implementiert, und andere funktionieren
noch nicht ganz so wie beschrieben (beispielsweise die Optionen
DATA DIRECTORY
und INDEX
DIRECTORY
für Partitionen, die noch unter dem Bug#13520
leiden). Wir haben versucht, diese Abweichungen im vorliegenden
Kapitel kenntlich zu machen. Bitte schauen Sie in folgende Quellen
hinein, bevor Sie uns Bugreports schicken:
Dies ist das offizielle Diskussionsforum für alle, die sich für die Partitionierungstechnologie von MySQL interessieren oder damit arbeiten. Hier finden Sie Ankündigungen und Aktualisierungen von MySQL-Entwicklern und anderen. Das Forum wird von den Mitgliedern des Partitioning Development and Documentation-Teams geleitet.
Eine Liste aller Partitionierungs-Bugs, die an unser Bugs-System gemeldet wurden, unabhängig von Alter, Ernsthaftigkeit und aktuellem Status. Es ist möglich, diese Liste nach diversen Kritierien zu filtern. Eventuell können Sie auch auf die MySQL Bugs System Home Page gehen und nach Bugs fahnden, die für Sie von besonderem Interesse sind.
Der MySQL Partitioning Architect und Lead Developer Mikael Ronström stellt hier häufig Artikel ein, die seine Arbeit mit MySQL Partitioning und MySQL Cluster betreffen.
Eine News-Site über MySQL mit Blogs, die für jeden MySQL-Nutzer interessant sein dürften. Wir raten Ihnen, hier Links zu den Blogs der Nutzer herauszusuchen, die mit der Partitionierung in MySQL arbeiten, oder Ihr eigenes Blog eintragen zu lassen.
Die Alpha-Binaries von MySQL 5.1 stehen nun unter
http://dev.mysql.com/downloads/mysql/5.1.html zum
Herunterladen zur Verfügung. Die Quelle für die aktuellsten
Bugfixes und neuen Features im Zusammenhang mit Partitionierung
finden Sie allerdings in unserem BitKeeper-Repository. Um
Partitionierung zu ermöglichen, müssen Sie den Server mit der
Option --with-partition
kompilieren. Weitere
Informationen über den MySQL-Build finden Sie unter
Abschnitt 2.8, „Installation der Quelldistribution“. Wenn Sie Probleme mit dem
Kompilieren eines partitionierungsfähigen MySQL 5.1-Build haben,
schauen Sie in das MySQL
Partitioning Forum und fragen Sie dort um Hilfe, falls nicht
bereits eine Lösung für Ihr Problem veröffentlicht wurde.
Dieser Abschnitt gibt einen Überblick über Partitionierungskonzepte in MySQL 5.1.
Beschränkungen der Partitionierung und die Grenzen des Features erfahren Sie unter Abschnitt 17.4, „Beschränkungen und Grenzen der Partitionierung“.
Der SQL-Standard enthält kaum Anleitungen in Bezug auf die
physikalischen Aspekte der Datenspeicherung. Die Sprache SQL ist
dafür ausgelegt, unabhängig von Datenstrukturen, Medien sowie
den einem Schema zugrunde liegenden Tabellen, Zeilen oder Spalten
zu funktionieren. Allerdings haben die meisten modernen
Datenbankmanagementsysteme auch irgendwelche Möglichkeiten
entwickelt, um festzustellen, an welchem Ort (Dateisystem,
Hardware oder beides) bestimmte Daten physikalisch gespeichert
werden. In MySQL unterstützte die Speicher-Engine
InnoDB
lange Zeit Tablespaces und der MySQL
Server konnte schon vor der Einführung von Partitionierung so
konfiguriert werden, dass er für die Speicherung
unterschiedlicher Datenbanken verschiedene physikalische
Verzeichnisse verwendete (unter Abschnitt 7.6.1, „Symbolische Verknüpfungen“,
werden die Gründe dafür erklärt).
Mit der Partitionierung wird dieses Konzept
noch einen Schritt weitergeführt: Hiermit können Sie
verschiedene Teile einzelner Tabellen über ein Dateisystem
verteilen, und zwar nach Regeln, die Sie im Großen und Ganzen
nach Ihren Bedürfnissen festlegen. So werden verschiedene Teile
einer Tabelle im Endeffekt als getrennte Tabellen an verschiedenen
Stellen gespeichert. Die vom Benutzer gewählte Regel, nach
welcher die Daten aufgeteilt werden, bezeichnet man als
Partitionierungsfunktion. Diese kann in
MySQL der Modulus sein, ein einfacher Vergleich mit einer Menge
von Wertebereichen oder Wertelisten, oder auch eine interne oder
lineare Hash-Funktion. Die Funktion wird je nach dem vom Benutzer
angegebenen Partitionierungstyp ausgewählt und nimmt den Wert
eines ebenfalls vom Benutzer gelieferten Ausdrucks als Parameter
entgegen. Dieser Ausdruck kann der Wert einer Integer-Spalte sein
oder auch eine Funktion, die auf einer oder mehreren Spalten
arbeitet und einen Integer zurückgibt. Der Wert dieses Ausdrucks
wird an die Partitionierungsfunktion übergeben, die ihrerseits
die Nummer der Partition, in welcher dieser spezielle Datensatz
gespeichert werden soll, als Integer zurückgibt. Diese Funktion
muss nichtkonstant und nichtzufällig sein. Sie darf keine
Anfragen enthalten, kann aber jedweden in MySQL zulässigen
SQL-Ausdruck enthalten, wenn dieser nur einen positiven Integer
kleiner MAXVALUE
zurückgibt (dies ist der
größtmögliche positive Integer). Beispiele für
Partitionierungsfunktionen finden Sie in den Abschnitten über
Partitionierungstypen weiter unten in diesem Kapitel (siehe
Abschnitt 17.2, „Partitionstypen“) sowie in den Beschreibungen
zur Partitionierungssyntax in Abschnitt 13.1.5, „CREATE TABLE
“.
Dies bezeichnet man als horizontale Partitionierung: Verschiedene Zeilen einer Tabelle können unterschiedlichen physikalischen Partitionen zugewiesen werden. MySQL 5.1 kennt keine vertikale Partitionierung, bei der verschiedene Tabellenspalten auf verschiedene physikalische Partitionen gespeichert würden. Es gibt auch noch keinerlei Pläne, vertikale Partitionierung in MySQL 5.1 einzuführen.
Partitionierungsunterstützung ist in den
-max
-Releases von MySQL 5.1
enthalten (d. h., dass die 5.1--max
-Binaries
mit der Option --with-partition
erstellt werden).
Wenn die MySQL-Binary mit Partitionierungsunterstützung gebaut
wird, muss nichts weiter unternommen werden, um diese zu
aktivieren (es sind beispielsweise keine speziellen Einträge in
der my.cnf
-Datei erforderlich). Ob Ihr MySQL
Server Partitionierung unterstützt, verrät Ihnen der Befehl
SHOW VARIABLES
:
mysql> SHOW VARIABLES LIKE '%partition%';
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| have_partitioning | YES |
+-------------------+-------+
1 row in set (0.00 sec)
Wenn Sie in der Ausgabe Ihres ensprechenden SHOW
VARIABLES
-Befehls nicht wie hier eine
have_partitioning
-Variable mit dem Wert
YES
zu sehen bekommen, dann unterstützt Ihre
MySQL-Version keine Partitionierung.
Vor MySQL 5.1.6 hieß diese Variable
have_partition_engine
(Bug#16718).
Um partitionierte Tabellen zu erstellen, können Sie jede vom
MySQL Server unterstützte Speicher-Engine einsetzen; die
MySQL-Partitionierungs-Engine läuft in ihrer eigenen Schicht und
kann mit allen diesen Speicher-Engines umgehen. In MySQL
5.1 müssen alle Partitionen derselben
partitionierten Tabelle auch dieselbe Speicher-Engine benutzen.
Sie können beispielsweise nicht für die eine Partition
MyISAM
und für die andere
InnoDB
benutzen. Allerdings hindert nichts Sie
daran, verschiedene Speicher-Engines für verschiedene
partitionierte Tabellen auf demselben MySQL Server oder sogar in
derselben Datenbank zu benutzen.
Um eine bestimmte Speicher-Engine für eine partitionierte Tabelle
zu verwenden, müssen Sie lediglich die passende
[STORAGE] ENGINE
-Option einstellen, wie Sie es
auch bei einer nichtpartitionierten Tabelle tun würden.
Allerdings müssen Sie daran denken, dass [STORAGE]
ENGINE
(und andere Tabellenoptionen) in einer
CREATE TABLE
-Anweisung vor
den Partitionierungsoptionen stehen müssen. Das folgende Beispiel
zeigt, wie man eine Tabelle anlegt, die per Hash in 6 Partitionen
zerlegt wird und die Speicher-Engine InnoDB
verwendet:
CREATE TABLE ti (id INT, amount DECIMAL(7,2), tr_date DATE) ENGINE=INNODB PARTITION BY HASH(MONTH(tr_date)) PARTITIONS 6;
(Beachten Sie, dass jede PARTITION
-Klausel auch
eine [STORAGE] ENGINE
-Option enthalten kann,
die jedoch in MySQL 5.1 wirkungslos bleibt.)
Es ist durchaus möglich, auch partitionierte temporäre Tabellen zu erstellen, doch diese haben nur so lange wie die aktuelle MySQL-Session Bestand. Dasselbe gilt für nichtpartitionierte temporäre Tabellen.
Hinweis: Eine Partitionierung betrifft alle Daten und Indizes einer Tabelle. Sie können weder die Daten ohne ihre Indizes partitionieren noch die Indizes ohne die Daten, ebenso wenig, wie Sie nur einen Teil einer Tabelle partitionieren können.
Die Daten und Indizes jeder Partition können mit den Optionen
DATA DIRECTORY
und INDEX
DIRECTORY
der PARTITION
-Klausel der
CREATE TABLE
-Anweisung, mit der die
partitionierte Tabelle angelegt wird, einem bestimmten Verzeichnis
zugewiesen werden. Überdies können Sie mit
MAX_ROWS
und MIN_ROWS
festlegen, wie viele Zeilen höchstens bzw. mindestens in jeder
Partition gespeichert werden dürfen. Genaueres über diese
Optionen erfahren Sie unter
Abschnitt 17.3, „Partitionsverwaltung“.
Hinweis: Dieses Feature läuft
zurzeit wegen Bug#13250 nicht; dies dürfte jedoch behoben sein,
wenn die ersten 5.1-Binaries zur Verfügung gestellt werden.
Eine Partitionierung hat folgende Vorteile:
In einer einzigen Tabelle können mehr Daten gespeichert werden, als auf eine einzelne Festplatte oder Dateisystempartition passen.
Unnütz gewordene Daten lassen sich oft einfacher aus der Tabelle entfernen, wenn man nur eine Partition löschen muss, die ebendiese Daten enthält. Umgekehrt lassen sich in einigen Fällen Daten auch einfacher hinzufügen, indem man einfach eine neue Partition speziell für diese Daten erschafft.
Normalerweise bietet eine Partitionierung auch noch die in der folgenden Liste aufgeführten Vorteile. Diese Features sind zwar in MySQL Partitioning noch nicht implementiert, stehen aber ganz oben auf unserer Prioritätenliste. Wir hoffen, sie im Produktionsrelease der Version 5.1 bereits einbringen zu können.
Manche Anfragen lassen sich dadurch optimieren, dass die
Daten, die auf eine WHERE
-Klausel
zutreffen, auf bestimmten Partitionen gespeichert werden
können, wodurch die restlichen Partitionen von der Suche
ausgeschlossen bleiben. Da Partitionen nach der Erstellung
einer partitionierten Tabelle geändert werden können, sind
Sie in der Lage, Ihre Daten so zu reorganisieren, dass
häufige Anfragen schneller verarbeitet werden, als es im
ursprünglichen Partitionierungsschema der Fall war.
Anfragen mit Aggregatfunktionen wie SUM()
und COUNT()
lassen sich leicht
parallelisieren. Ein einfaches Beispiel einer solchen Anfrage
wäre SELECT salesperson_id, COUNT(orders) as
order_total FROM sales GROUP BY salesperson_id;
. Mit
„parallelisieren“ ist gemeint, dass die Anfrage
auf allen Partitionen gleichzeitig ausgeführt werden kann und
das Endergebnis dann die Summe der Resultate der einzelnen
Partitionen ist.
Da Suchoperationen auf mehrere Festplatten verteilt werden können, wird ein größerer Durchsatz an Anfragen erzielt.
Bitte schauen Sie regelmäßig im englischsprachingen Handbuch, Kapitel „Partitions“, nach aktuellen Entwicklungen in der Implementierung der Partitionierung in MySQL 5.1, da diese Entwicklung noch nicht abgeschlossen ist.
Dieser Abschnitt beschreibt die in MySQL 5.1 verfügbaren Arten der Partitionierung, nämlich:
RANGE
-Partitionierung
(Bereichspartitionierung): Weist den Partitionen Zeilen zu, je
nachdem, ob ihre Spaltenwerte in einen bestimmten Wertebereich
fallen. Siehe Abschnitt 17.2.1, „RANGE
-Partitionierung“.
LIST
-Partitionierung
(Listenpartitionierung): Ähnelt der Bereichspartitionierung,
nur dass hier die Partition anhand der Frage ausgewählt wird,
ob sich die Spaltenwerte in einer Menge eigenständiger Werte
wiederfinden. Siehe Abschnitt 17.2.2, „LIST
-Partitionierung“.
HASH
-Partitionierung:
Hierbei wird eine Partition anhand des Rückgabewerts eines
benutzerdefinierten Ausdrucks ausgewählt, der auf
Spaltenwerten der Zeilen operiert, die in die Tabelle
eingefügt werden sollen. Die Funktion kann jeden in MySQL
zulässigen Ausdruck enthalten, der einen nichtnegativen
Integer ergibt. Siehe Abschnitt 17.2.3, „HASH
-Partitionierung“.
KEY
-Partitionierung
(Schlüsselpartitionierung): Ähnelt der Hash-Partitionierung,
aber mit dem Unterschied, dass nur bestimmte auszuwertende
Spalten übergeben werden und der MySQL Server seine eigene
Hash-Funktion liefert. Die Spalte(n) dürfen nur Integer-Werte
enthalten. Siehe Abschnitt 17.2.4, „KEY
-Partitionierung“.
Bitte vergessen Sie nicht: Egal welche Art von Partitionierung Sie
verwenden, Partitionen werden immer automatisch der Reihe nach bei
ihrer Erstellung durchnummeriert, und zwar beginnend mit
0
. Wenn eine neue Zeile in eine partitionierte
Tabelle eingefügt wird, wird die richtige Partition anhand dieser
laufenden Nummern gefunden. Wenn beispielsweise Ihre Tabellen 4
Partitionen nutzen, so habe diese Partitionen die Nummern
0
, 1
, 2
und 3
. Bei einer RANGE
- oder
LIST
-Partitionierung müssen Sie
gewährleisten, dass für jede Partitionsnummer auch eine
Partition definiert ist. Bei einer
HASH
-Partitionierung muss die verwendete
benutzerdefinierte Funktion einen Integer größer
0
zurückgeben. Bei einer
KEY
-Partitionierung wird dieses Problem
automatisch von der Hash-Funktion gelöst, die der MySQL Server
intern einsetzt.
Partitionsnamen halten sich generell an dieselben Regeln, die auch
für andere MySQL-Bezeichner gelten, wie beispielsweise die für
Tabellen und Datenbanken. Allerdings müssen Sie daran denken,
dass Partitionsnamen nicht zwischen Groß- und Kleinschreibung
unterscheiden. So würde beispielsweise die folgende
CREATE TABLE
-Anweisung scheitern:
mysql>CREATE TABLE t2 (val INT)
->PARTITION BY LIST(val)(
->PARTITION mypart VALUES IN (1,3,5),
->PARTITION MyPart VALUES IN (2,4,6)
->);
ERROR 1488 (HY000): All partitions must have unique names in the table
Der Fehler liegt daran, dass MySQL keinen Unterschied zwischen den
Partitionsnamen mypart
und
MyPart
erkennen kann.
In den folgenden Abschnitten geben wir nicht immer alle nur
denkbaren Syntaxvarianten zur Erstellung der Partitionstypen an.
Diese Informationen können Sie unter
Abschnitt 13.1.5, „CREATE TABLE
“, nachschlagen.
Wenn eine Tabelle nach Wertebereichen partitioniert wird,
enthält später jede Partition die Zeilen, für die der
Partitionierungsausdruck einen Wert hat, der in einem bestimmten
Wertebereich liegt. Die Wertebereiche sollten aneinander
grenzen, aber sich nicht überschneiden, und sie sollten mit dem
VALUES LESS THAN
-Operator definiert werden.
Bei den nächsten Beispielen gehen wir davon aus, dass wie unten
beschrieben eine Tabelle für die Personaldaten einer Kette von
20 Videotheken (mit den Nummern 1 bis 20) eingerichtet wird:
CREATE TABLE employees ( id INT NOT NULL, fname VARCHAR(30), lname VARCHAR(30), hired DATE NOT NULL DEFAULT '1970-01-01', separated DATE NOT NULL DEFAULT '9999-12-31', job_code INT NOT NULL, store_id INT NOT NULL );
Diese Tabelle kann je nach Bedarf auf unterschiedliche Weise
nach Bereichen partitioniert werden. Eine Möglichkeit wäre es,
die store_id
-Spalte zu verwenden. Sie
könnten die Tabelle beispielsweise mit einer PARTITION
BY RANGE
-Klausel auf 4 Partitionen verteilen:
CREATE TABLE employees ( id INT NOT NULL, fname VARCHAR(30), lname VARCHAR(30), hired DATE NOT NULL DEFAULT '1970-01-01', separated DATE NOT NULL DEFAULT '9999-12-31', job_code INT NOT NULL, store_id INT NOT NULL ) PARTITION BY RANGE (store_id) ( PARTITION p0 VALUES LESS THAN (6), PARTITION p1 VALUES LESS THAN (11), PARTITION p2 VALUES LESS THAN (16), PARTITION p3 VALUES LESS THAN (21) );
In diesem Partitionierungsschema werden die Angestelltendaten
der Zweigstellen 1 bis 5 in Partition p0
gespeichert, die Angestelltendaten der Zweigstellen 6 bis 10 in
Partition p1
und so weiter. Beachten Sie,
dass die Partitionen der Reihe nach von der niedrigsten bis zur
höchsten Nummer definiert werden. Dies verlangt die Syntax von
PARTITION BY RANGE
, die in dieser Hinsicht
einer switch ... case
-Anweisung in C oder
Java ähnelt.
Es ist einfach, festzustellen, dass eine neue Zeile mit den
Daten (72, 'Michael', 'Widenius', '1998-06-25', NULL,
13)
in die Partition p2
eingefügt
wurde, doch was geschieht, wenn die Videothekenkette eine 21.
Zweigstelle eröffnen möchte? In dem vorliegenden Schema gibt
es keine Regeln für Zeilen mit einer
store_id
größer 20. Daher wird ein Fehler
gemeldet, weil der Server nicht weiß, wohin damit. Dieses
Verhalten können Sie mit einem so genannten
„Catchall“ verhindern: einer VALUES LESS
THAN
-Klausel in der CREATE
TABLE
-Anweisung, die für alle Werte Vorsorge trifft,
die den größten explizit angegebenen Wert übersteigen:
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT NOT NULL,
store_id INT NOT NULL
)
PARTITION BY RANGE (store_id) (
PARTITION p0 VALUES LESS THAN (6),
PARTITION p1 VALUES LESS THAN (11),
PARTITION p2 VALUES LESS THAN (16),
PARTITION p3 VALUES LESS THAN MAXVALUE
);
MAXVALUE
ist der größte mögliche
Integer-Wert. Nun werden alle Zeilen, deren
store_id
-Spaltenwert größer oder gleich dem
größten definierten Wert 16 ist, in Partition
p3
gespeichert. Irgendwann einmal, wenn die
Anzahl der Zweigstellen auf 25, 30 oder mehr angewachsen ist,
können Sie mit einer ALTER TABLE
-Anweisung
neue Partitionen für die Zweigstellen 21 bis 25, 26 bis 30 und
so weiter hinzufügen (Einzelheiten zur Vorgehensweise finden
Sie unter Abschnitt 17.3, „Partitionsverwaltung“.)
In ähnlicher Weise können Sie die Tabelle auf der Grundlage
von Job-Codes partitionieren, d. h. anhand der Werte der Spalte
job_code
. Nehmen wir beispielsweise an,
reguläre (in der Filiale arbeitende) Angestellte haben einen
zweistelligen Job-Code, Büro- und Support-Mitarbeiter einen
dreistelligen und Manager einen vierstelligen. Dann könnten Sie
Ihre partitionierte Tabelle folgendermaßen definieren:
CREATE TABLE employees ( id INT NOT NULL, fname VARCHAR(30), lname VARCHAR(30), hired DATE NOT NULL DEFAULT '1970-01-01', separated DATE NOT NULL DEFAULT '9999-12-31', job_code INT NOT NULL, store_id INT NOT NULL ) PARTITION BY RANGE (job_code) ( PARTITION p0 VALUES LESS THAN (100), PARTITION p1 VALUES LESS THAN (1000), PARTITION p2 VALUES LESS THAN (10000) );
In diesem Beispiel würden die Daten der Filialmitarbeiter in
der Partition p0
, die der Büro- und
Support-Mitarbeiter in der Partition p1
und
die der Manager in der Partition p2
gespeichert.
In VALUES LESS THAN
-Klauseln kann auch ein
Ausdruck verwendet werden, allerdings nur mit der Maßgabe, dass
MySQL in der Lage sein muss, den Rückgabewert dieses Ausdrucks
in einem LESS THAN
(<
)-Vergleich auszuwerten; der Wert des
Ausdrucks darf also nicht NULL
sein. Dies ist
der Grund, weshalb die Spalten hired
,
separated
, job_code
und
store_id
der Tabelle
employees
als NOT NULL
definiert wurden.
Anstatt die Tabellendaten anhand der Zweigstellennummer zu
verteilen, können Sie auch einen Ausdruck verwenden, der auf
den beiden DATE
-Spalten basiert. Nehmen wir
beispielsweise an, Sie möchten die Tabelle nach dem Jahr
partitionieren, in welchem die Mitarbeiter das Unternehmen
verlassen, also nach dem Wert der Spalte
YEAR(separated)
. Folgende CREATE
TABLE
-Anweisung würde ein solches
Partitionierungsschema implementieren:
CREATE TABLE employees ( id INT NOT NULL, fname VARCHAR(30), lname VARCHAR(30), hired DATE NOT NULL DEFAULT '1970-01-01', separated DATE NOT NULL DEFAULT '9999-12-31', job_code INT, store_id INT ) PARTITION BY RANGE ( YEAR(separated) ) ( PARTITION p0 VALUES LESS THAN (1991), PARTITION p1 VALUES LESS THAN (1996), PARTITION p2 VALUES LESS THAN (2001), PARTITION p3 VALUES LESS THAN MAXVALUE );
In diesem Schema werden die Daten der Mitarbeiter, die das
Unternehmen vor 1991 verließen, in der Partition
p0
gespeichert, die Daten derjenigen, die
zwischen 1991 und 1995 gingen, in Partition
p1
, die Daten derjenigen, die zwischen 1996
und 2000 gingen, in Partition p2
und die
Daten derjenigen, die nach 2000 gingen, in Partition
p3
.
Eine Bereichspartitionierung ist in folgenden Fällen besonders nützlich:
Sie möchten oder müssen „alte“ Daten
löschen. Wenn Sie das soeben gezeigte
Partitionierungsschema umsetzen, brauchen Sie nur noch
ALTER TABLE employees DROP PARTITION p0;
aufzurufen, um alle Datensätze der Angestellten zu
löschen, die vor 1991 das Unternehmen verlassen haben.
(Weitere Informationen finden Sie unter
Abschnitt 13.1.2, „ALTER TABLE
“, und
Abschnitt 17.3, „Partitionsverwaltung“.) Wenn Sie eine
Tabelle mit sehr vielen Zeilen haben, kann diese
Vorgehensweise sehr viel effizienter als eine
DELETE
-Anfrage wie etwa DELETE
FROM employees WHERE YEAR(separated) <= 1990;
sein.
Sie möchten eine Spalte benutzen, die Datums- oder Uhrzeitwerte oder Werte aus einer anderen Wertfolge enthält.
Es werden oft Anfragen ausgeführt, die direkt von einer
für die Partitionierung der Tabelle verwendeten Spalte
abhängen. So kann MySQL beispielsweise bei einer Anfrage
wie SELECT COUNT(*) FROM employees WHERE
YEAR(separated) = 2000 GROUP BY store_id;
ganz
schnell herausfinden, dass nur die Partition
p2
durchsucht werden muss, da die
restlichen Partitionen gar keine zu der
WHERE
-Klausel passenden Einträge
enthalten können. Hinweis:
Dies Optimierung wurde in den Quelldateien von MySQL 5.1
zwar noch nicht aktiviert, aber wir arbeiten daran.
Die Listenpartitionierung in MySQL ähnelt in vieler Hinsicht
der Bereichspartitionierung. Wie bei dieser muss jede Partition
explizit definiert werden. Der Hauptunterschied besteht darin,
dass bei einer Listenpartitionierung die einzelnen Partitionen
anhand der Frage gebildet werden, ob ein Spaltenwert in einer
von mehreren Wertelisten vorkommt, während
bei der Bereichspartitionierung gefragt wird, ob er in einer von
mehreren Wertefolgen vorkommt. Diese Form
der Partitionierung nehmen Sie mit PARTITION BY
LIST(
vor, wobei
expr
)expr
ein Spaltenwert oder ein auf
einem Spaltenwert basierender Ausdruck ist, der einen Integer
zurückgibt. Die einzelnen Partitionen werden sodann durch
VALUES IN
(
definiert,
wobei value_list
)value_list
eine kommagetrennte
Liste von Integern ist.
Hinweis: In MySQL
5.1 kann der Spaltenwert bei einer
LIST
-Partitionierung nur mit einer
Integer-Liste verglichen werden.
Im Gegensatz zu Bereichspartitionen müssen Listenpartitionen
nicht in einer bestimmten Reihenfolge definiert werden. Genauere
Hinweise zur Syntax finden Sie unter
Abschnitt 13.1.5, „CREATE TABLE
“.
In den nachfolgenden Beispielen gehen wir davon aus, dass die
Grunddefinition der zu partitionierenden Tabelle die der
nachfolgenden CREATE TABLE
-Anweisung ist:
CREATE TABLE employees ( id INT NOT NULL, fname VARCHAR(30), lname VARCHAR(30), hired DATE NOT NULL DEFAULT '1970-01-01', separated DATE NOT NULL DEFAULT '9999-12-31', job_code INT, store_id INT );
(Dies ist dieselbe Tabelle, die auch als Grundlage der Beispiele
in Abschnitt 17.2.1, „RANGE
-Partitionierung“, diente.)
Angenommen, wir haben eine Kette von 20 Videotheken, die auf 4 Franchisenehmer verteilt ist, wie in der folgenden Tabelle gezeigt:
Region | Store ID Numbers |
North | 3, 5, 6, 9, 17 |
East | 1, 2, 10, 11, 19, 20 |
West | 4, 12, 13, 14, 18 |
Central | 7, 8, 15, 16 |
Um diese Tabelle so zu partitionieren, dass jeweils die
Zweigstellen einer Region zusammenhängend gespeichert werden,
könnten Sie die folgende CREATE
TABLE
-Anweisung einsetzen:
CREATE TABLE employees ( id INT NOT NULL, fname VARCHAR(30), lname VARCHAR(30), hired DATE NOT NULL DEFAULT '1970-01-01', separated DATE NOT NULL DEFAULT '9999-12-31', job_code INT, store_id INT ) PARTITION BY LIST(store_id) ( PARTITION pNorth VALUES IN (3,5,6,9,17), PARTITION pEast VALUES IN (1,2,10,11,19,20), PARTITION pWest VALUES IN (4,12,13,14,18), PARTITION pCentral VALUES IN (7,8,15,16) );
Nun ist es ganz einfach, regionale Angestelltendaten in die
Tabelle zu laden oder aus ihr zu löschen. Nehmen wir
beispielsweise an, alle Zweigstellen der Region West werden an
ein anderes Unternehmen verkauft. Dann könnten alle
Angestelltendaten der Zweigstellen dieser Region mit der Anfrage
ALTER TABLE employees DROP PARTITION pWest;
gelöscht werden, die viel schneller als die entsprechende
DELETE
-Anfrage DELETE FROM employees
WHERE store_id IN (4,12,13,14,18);
ausgeführt wird.
Wichtig: Wenn Sie versuchen,
eine Zeile einzufügen, deren Spaltenwert (oder Rückgabewert
für den Partitionierungsausdruck) in den Listen mit den
Partitionierungswerten nicht vorkommt, scheitert die
INSERT
-Anfrage mit einer Fehlermeldung. So
würde beispielsweise die folgende Anfrage bei dem oben
skizzierten Schema einer LIST
-Partitionierung
fehlschlagen:
INSERT INTO employees VALUES (224, 'Linus', 'Torvalds', '2002-05-01', '2004-10-12', 42, 21);
Dieser Fehler tritt ein, da der
store_id
-Spaltenwert 21
in
keiner der Wertelisten auftritt, die zur Definition der
Partitionen pNorth
, pEast
,
pWest
und pCentral
angegeben wurden. Es ist wichtig zu wissen, dass für
Listenpartitionen keine „Catchall“-Definition wie
VALUES LESS THAN MAXVALUE
existiert, um Werte
unterzubringen, die in keiner der Wertelisten auftauchen. Mit
anderen Worten: Jeder Partitionierungswert muss in
einer der Wertelisten vorhanden sein.
Wie die RANGE
-Partitionierung kann auch die
LIST
-Partitionierung mit einer Hash- oder
Schlüsselpartitionierung kombiniert werden, um eine
zusammengesetzte Partitionierung (Teilpartitionierung) zu
bilden. Siehe Abschnitt 17.2.5, „Unterpartitionen“.
Eine Partitionierung nach HASH
wird
hauptsächlich eingesetzt, um eine gleichmäßige Verteilung der
Daten auf eine im Voraus festgelegte Anzahl von Partitionen zu
erzielen. Bei einer Bereichs- oder Listenpartitionierung müssen
Sie explizit angeben, in welcher Partition Spaltenwerte
gespeichert werden sollen, während MySQL Ihnen dies bei einer
Hash-Partitionierung abnimmt. Hier müssen Sie lediglich einen
Spaltenwert oder einen auf einem Spaltenwert basierenden
Ausdruck für den Hash angeben und sagen, auf wie viele
Partitionen die partitionierte Tabelle verteilt werden soll.
Um eine Tabelle mit einer
HASH
-Partitionierung aufzuteilen, müssen Sie
an die CREATE TABLE
-Anweisung eine
PARTITION BY HASH
(
-Klausel anfügen,
wobei expr
)expr
ein Ausdruck ist, der
einen Integer zurückgibt. Das kann auch einfach der Name einer
Spalte sein, die einen der Integer-Typen von MySQL hat.
Zusätzlich wird normalerweise noch eine PARTITIONS
-Klausel angefügt,
wobei num
num
ein nichtnegativer Integer
ist und angibt, auf wie viele Partitionen die Tabelle verteilt
werden soll.
Die folgende Anweisung erzeugt beispielsweise eine Tabelle, die
einen Hash der Spalte store_id
verwendet und
auf 4 Partitionen verteilt wird:
CREATE TABLE employees ( id INT NOT NULL, fname VARCHAR(30), lname VARCHAR(30), hired DATE NOT NULL DEFAULT '1970-01-01', separated DATE NOT NULL DEFAULT '9999-12-31', job_code INT, store_id INT ) PARTITION BY HASH(store_id) PARTITIONS 4;
Wenn Sie keine PARTITIONS
-Klausel verwenden,
ist die Anzahl der Partitionen nach Voreinstellung
1
. Ausnahme:
Bei NDB Cluster
-Tabellen ist die vorgegebene
Anzahl der Partitionen gleich der Anzahl der Datenknoten im
Cluster, eventuell berichtigt um eine
MAX_ROWS
-Einstellung, um zu gewährleisten,
dass alle Zeilen in die Partitionen hineinpassen. (Siehe
Kapitel 16, MySQL Cluster.)
Wenn Sie das Schlüsselwort PARTITIONS
ohne
darauf folgende Zahlenangabe verwenden, wird ein Syntaxfehler
ausgelöst.
Sie können für expr
auch einen
SQL-Ausdruck einsetzen, der einen Integer zurückliefert. Wenn
Sie Ihre Tabelle beispielsweise anhand des Einstellungsjahres
der Angestellten partitionieren möchten, gehen Sie
folgendermaßen vor:
CREATE TABLE employees ( id INT NOT NULL, fname VARCHAR(30), lname VARCHAR(30), hired DATE NOT NULL DEFAULT '1970-01-01', separated DATE NOT NULL DEFAULT '9999-12-31', job_code INT, store_id INT ) PARTITION BY HASH( YEAR(hired) ) PARTITIONS 4;
Sie können für expr
alle Funktionen
und Ausdrücke verwenden, die in MySQL zulässig sind,
vorausgesetzt, der Rückgabewert ist ein nichtkonstanter,
nichtzufälliger Integer. (Mit anderen Worten: Der Wert soll
variieren, aber deterministisch sein.) Sie müssen allerdings
daran denken, dass dieser Ausdruck jedes Mal, wenn eine Zeile
eingefügt, aktualisiert oder eventuell auch gelöscht wird,
ausgewertet werden muss. Das bedeutet, dass komplexe Ausdrücke
die Leistung beeinträchtigen können, insbesondere, wenn
Operationen ausgeführt werden, die viele Zeilen auf einmal
betreffen (wie etwa Masseneinfügungen).
Am effizientesten sind Hash-Funktionen, die nur eine einzige Tabellenspalte bearbeiten und deren Wert mit dem Spaltenwert konsistent zu- oder abnimmt, da hierdurch ein „Pruning“ von Partitionsbereichen möglich wird. D. h.: Je enger sich der Wert des Ausdrucks an dem Wert der zugrunde liegenden Spalte orientiert, umso effizienter kann MySQL ihn für die Hash-Partitionierung einsetzen.
Wenn beispielsweise date_col
eine Spalte vom
Typ DATE
ist, dann ändert sich der Ausdruck
TO_DAYS(date_col)
unmittelbar mit dem Wert
von date_col
, da jede Änderung des Werts von
date_col
auch den Wert des Ausdrucks ändert,
und zwar in völlig konsistenter Form. Der Ausdruck
YEAR(date_col)
ändert sich bei
date_col
-Änderungen nicht ganz so
unmittelbar wie TO_DAYS(date_col)
, da nicht
jede Änderung in date_col
eine entsprechende
Änderung in YEAR(date_col)
nach sich zieht.
Dennoch ist auch YEAR(date_col)
ein guter
Kandidat für eine Hash-Funktion, da es sich direkt mit einem
Teil von date_col
ändert und nicht die
Gefahr besteht, dass eine Änderung von
date_col
zu einer unverhältnismäßigen
Änderung von YEAR(date_col)
führt.
Nehmen wir dagegen an, Sie hätten eine Spalte namens
int_col
vom Typ INT
. Nun
betrachten Sie den Ausdruck POW(5-int_col,3) +
6
. Dieser wäre ganz schlecht als Hash-Funktion
geeignet, da nicht garantiert ist, dass Änderungen von
int_col
proportionale Änderungen im Wert des
Ausdrucks nach sich ziehen. Wenn Sie den Wert von
int_col
um einen gegebenen Betrag ändern,
können dadurch ganz unterschiedliche Änderungen im Wert des
Ausdrucks eintreten. Ändern Sie beispielsweise
int_col
von 5
in
6
, so ändert sich der Wert des Ausdrucks um
-1
, ändern Sie dagegen
int_col
von 6
in
7
, so ändert sich der Wert des Ausdrucks um
-7
.
Mit anderen Worten: Je enger der Graph des Spaltenwerts im
Verhältnis zum Wert des Ausdrucks einer geraden Linie folgt,
wie sie durch die Gleichung
y=
vorgegeben
ist, wenn n
xn
eine von null
verschiedene Konstante ist, umso besser eignet sich der Ausdruck
für das Hashing. Denn je weniger linear ein Ausdruck ist, umso
ungleichmäßiger werden die Daten auf die Partitionen verteilt,
die dieser Ausdruck anlegt.
Theoretisch ist bei Ausdrücken, an denen mehrere Spaltenwerte beteiligt sind, auch Pruning möglich, aber es kann schwierig und langwierig sein, herauszufinden, welche dieser Ausdrücke nun wirklich für Pruning geeignet sind. Daher sind Hashing-Ausdrücke mit mehreren Spalten nicht sonderlich zu empfehlen.
Wenn PARTITION BY HASH
verwendet wird,
ermittelt MySQL anhand des Modulus des Ergebnisses der
Benutzerfunktion, welche von num
Partitionen verwendet wird. Anders ausgedrückt: Für einen
Ausdruck expr
wird der Datensatz in
der Partition N
gespeichert, wobei
ist. Nehmen wir
beispielsweise an, Tabelle N
=
MOD(expr
,
num
)t1
ist
folgendermaßen definiert, sodass sie 4 Partitionen hat:
CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATE) PARTITION BY HASH( YEAR(col3) ) PARTITIONS 4;
Wenn Sie in t1
einen Datensatz einfügen,
dessen col3
-Wert
'2005-09-15'
ist, dann wird die Partition, in
der er gespeichert wird, folgendermaßen ermittelt:
MOD(YEAR('2005-09-01'),4) = MOD(2005,4) = 1
MySQL 5.1 unterstützt auch eine Variante der
HASH
-Partitionierung namens
lineares Hashing, die einen komplexen
Algorithmus einsetzt, um neu in eine partitionierte Tabelle
eingefügte Zeilen zu platzieren. Eine Beschreibung dieses
Algorithmus finden Sie unter
Abschnitt 17.2.3.1, „LINEAR HASH
-Partitionierung“.
Die Benutzerfunktion wird bei jeder Einfügung oder Aktualisierung und unter Umständen auch bei einer Löschung eines Datensatzes ausgewertet.
Hinweis: Wenn die Tabelle, die
partitioniert werden soll, einen
UNIQUE
-Schlüssel hat, müssen Spalten, die
als Argumente an die HASH
-Benutzerfunktion
oder die column_list
des
KEY
s übergeben werden, Teil dieses
Schlüssels sein.
MySQL unterstützt auch lineares Hashing, das sich vom regulären Hashing insofern unterscheidet, als es einen linearen Zweierpotenz-Algorithmus verwendet, während das reguläre Hashing den Modulus des Werts der Hashing-Funktion benutzt.
Der einzige syntaktische Unterschied zwischen der linearen und
der regulären Hash-Partitionierung besteht darin, dass der
PARTITION BY
-Klausel das Schlüsselwort
LINEAR
hinzugefügt wird:
CREATE TABLE employees ( id INT NOT NULL, fname VARCHAR(30), lname VARCHAR(30), hired DATE NOT NULL DEFAULT '1970-01-01', separated DATE NOT NULL DEFAULT '9999-12-31', job_code INT, store_id INT ) PARTITION BY LINEAR HASH( YEAR(hired) ) PARTITIONS 4;
Wenn Sie einen Ausdruck expr
haben,
wird beim linearen Hashing der Datensatz in Partition Nummer
N
von
num
Partitionen gespeichert, wobei
N
nach dem folgenden Algorithmus
abgeleitet ist:
Finde die nächste Zweierpotenz größer
num
. Wir nennen diesen Wert
V
; er kann folgendermaßen
berechnet werden:
V
= POWER(2, CEILING(LOG(2,num
)))
(Nehmen wir beispielsweise an,
num
sei 13. Dann ist
LOG(2,13)
gleich 3.7004397181411.
CEILING(3.7004397181411)
ist 4 und
V
=
POWER(2,4)
, was 16 ergibt.)
Setze N
=
F
(column_list
)
& (V
- 1).
Wobei N
>=
num
:
Setze V
=
CEIL(V
/ 2)
Setze N
=
N
&
(V
- 1)
Angenommen, die Tabelle t1
, die lineare
Hash-Partitionierung nutzt und 6 Partitionen hat, wird mit
folgender Anweisung angelegt:
CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATE) PARTITION BY LINEAR HASH( YEAR(col3) ) PARTITIONS 6;
Nehmen wir weiterhin an, Sie möchten in t1
zwei Datensätze einfügen, in denen die Spalte
col3
die Werte
'2003-04-14'
und
'1998-10-19'
aufweist. Die Partitionsnummer
für die erste dieser Spalten wird folgendermaßen ermittelt:
V
= POWER(2, CEILING( LOG(2,7) )) = 8N
= YEAR('2003-04-14') & (8 - 1) = 2003 & 7 = 3 (3 >= 6 is FALSE: record stored in partition #3)
Die Partitionsnummer für den zweiten Eintrag wird berechnet mit:
V
= 8N
= YEAR('1998-10-19') & (8-1) = 1998 & 7 = 6 (6 >= 6 is TRUE: additional step required)N
= 6 & CEILING(5 / 2) = 6 & 3 = 2 (2 >= 6 is FALSE: record stored in partition #2)
Der Vorteil einer linearen Hash-Partitionierung besteht darin, dass sich Partitionen weit schneller hinzufügen, löschen, zusammenführen und aufspalten lassen. Das kann ein Segen sein, wenn man mit Tabellen arbeiten muss, die extrem große Datenmengen (Terabytes) enthalten. Der Nachteil ist, dass die Daten wahrscheinlich nicht so gleichmäßig auf die Partitionen verteilt werden wie bei der normalen Hash-Partitionierung.
Die Partitionierung durch Schlüssel gleicht der Partitionierung
durch Hash, nur dass dort, wo die Hash-Partitionierung einen
benutzerdefinierten Ausdruck verwendet, die
Schlüsselpartitionierung eine vom MySQL Server gelieferte
Hash-Funktion einsetzt. MySQL Cluster verwendet zu diesem Zweck
MD5()
; für Tabellen, die andere
Speicher-Engines benutzen, setzt der Server seine eigene interne
Hash-Funktion ein, die auf demselben Algorithmus wie
PASSWORD()
beruht.
Die Syntaxregeln für CREATE TABLE ... PARTITION BY
KEY
sind dieselben wie bei der Erstellung einer
Hash-partitionierten Tabelle. Die Hauptunterschiede sind:
Statt HASH
wird KEY
eingesetzt.
KEY
nimmt nur eine Liste mit einem oder
mehreren Spaltennamen entgegen. Seit MySQL 5.1.5 müssen die
Spalten, die als Partitionierungsschlüssel eingesetzt
werden, den Primärschlüssel der Tabelle (sofern sie einen
hat) ganz oder teilweise abdecken.
Seit MySQL 5.1.6 nimmt KEY
eine Liste mit
null oder mehr Spaltennamen entgegen. Wenn kein Spaltenname
als Partitionierungsschlüssel angegeben ist, wird der
Primärschlüssel der Tabelle verwendet. Die folgende
CREATE TABLE
-Anweisung gilt
beispielsweise in MySQL 5.1.6 oder höher:
CREATE TABLE k1 ( id INT NOT NULL PRIMARY KEY, name VARCHAR(20) ) PARTITION BY KEY() PARTITIONS 2;
In diesem Fall ist der Partitionierungsschlüssel die Spalte
id
, auch wenn das in der Ausgabe von
SHOW CREATE TABLE
oder in der Spalte
PARTITION_EXPRESSION
der Tabelle
INFORMATION_SCHEMA.PARTITIONS
nicht
erkennbar ist.
Hinweis: Seit MySQL 5.1.6
werden außerdem Tabellen, die die Speicher-Engine
NDB Cluster
verwenden, implizit mit
KEY
partitioniert, wobei auch hier wieder
der Primärschlüssel der Tabelle als
Partitionierungsschlüssel dient. Nehmen wir als Beispiel
die Tabelle, die mit folgender Anweisung erzeugt wird:
CREATE TABLE kndb ( id INT NOT NULL PRIMARY KEY, name VARCHAR(20) NOT NULL ) ENGINE=NDBCLUSTER;
Obwohl die Anweisung keine PARTITION
BY
-Klausel enthält, zeigt die Ausgabe von
SHOW CREATE TABLE kndb
Folgendes an:
CREATE TABLE `kndb` ( `id` int(11) NOT NULL, `name` varchar(20) NOT NULL. PRIMARY KEY (`id`) ) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY ();
Falls die Cluster-Tabelle keinen expliziten
Primärschlüssel hat, wird der „verborgene“
Primärschlüssel, den die Speicher-Engine
NDB
automatisch für jede Cluster-Tabelle
generiert, als Partitionierungsschlüssel eingesetzt.
Wichtig: Auf einer
schlüsselpartitionierten Tabelle, die eine andere
Speicher-Engine als NDB CLuster
verwendet, können Sie keine ALTER TABLE DROP
PRIMARY KEY
-Anweisung ausführen, ansonsten tritt
der Fehler ERROR 1466 (HY000): Field in list of
fields for partition function not found in table
ein. Dieses Problem betrifft keine MySQL CLuster-Tabellen,
die durch KEY
partitioniert werden: In
solchen Fällen wird die Tabelle reorganisiert, wobei der
„verborgene“ Primärschlüssel als neuer
Partitionierungsschlüssel der Tabelle verwendet wird. Siehe
Kapitel 16, MySQL Cluster.
Es ist auch möglich, eine Tabelle durch linearen Schlüssel zu partitionieren. Hier sehen Sie ein einfaches Beispiel:
CREATE TABLE tk ( col1 INT NOT NULL, col2 CHAR(5), col3 DATE ) PARTITION BY LINEAR KEY (col1) PARTITIONS 3;
Die Verwendung von LINEAR
hat auf die
KEY
-Partitionierung denselben Effekt wie auf
die HASH
-Partitionierung, wobei die
Partitionsnummer mit einem Zweierpotenz-Algorithmus anstatt mit
Modulo-Arithmetik abgeleitet wird. Eine Beschreibung dieses
Algorithmus und seiner Implikationen finden Sie unter
Abschnitt 17.2.3.1, „LINEAR HASH
-Partitionierung“.
Teilpartitionierung, auch als zusammengesetzte
Partitionierung bezeichnet, ist die weitere
Unterteilung von Partitionen einer partitionierten Tabelle.
Betrachten Sie als Beispiel die folgende CREATE
TABLE
-Anweisung:
CREATE TABLE ts (id INT, purchased DATE) PARTITION BY RANGE(YEAR(purchased)) SUBPARTITION BY HASH(TO_DAYS(purchased)) SUBPARTITIONS 2 ( PARTITION p0 VALUES LESS THAN (1990), PARTITION p1 VALUES LESS THAN (2000), PARTITION p2 VALUES LESS THAN MAXVALUE );
Die Tabelle ts
hat 3
RANGE
-Partitionen. Jede dieser Partitionen,
also p0
, p1
und
p2
, ist ihrerseits in 2 Teilpartitionen
unterteilt. Im Endeffekt ist die gesamte Tabelle auf 3
* 2 = 6
Partitionen verteilt. Durch die
PARTITION BY RANGE
-Klausel speichern
allerdings die ersten beiden dieser Partitionen nur Datensätze,
die in der purchased
-Spalte einen Wert
kleiner als 1990 aufweisen.
In MySQL 5.1 können Sie Tabellen, die durch
RANGE
oder LIST
partitioniert werden, noch weiter aufteilen. Teilpartitionen
können entweder die HASH
- oder die
KEY
-Partitionierung verwenden. Dies
bezeichnet man auch als zusammengesetzte
Partitionierung.
Außerdem ist es möglich, Teilpartitionen explizit mit
SUBPARTITION
-Klauseln zu definieren, um
Optionen für einzelne Teilpartitionen angeben zu können. So
könnte man dieselbe ts
-Tabelle wie im
vorigen Beispiel auch wortreicher erzeugen:
CREATE TABLE ts (id INT, purchased DATE) PARTITION BY RANGE( YEAR(purchased) ) SUBPARTITION BY HASH( TO_DAYS(purchased) ) ( PARTITION p0 VALUES LESS THAN (1990) ( SUBPARTITION s0, SUBPARTITION s1 ), PARTITION p1 VALUES LESS THAN (2000) ( SUBPARTITION s2, SUBPARTITION s3 ), PARTITION p2 VALUES LESS THAN MAXVALUE ( SUBPARTITION s4, SUBPARTITION s5 ) );
An dieser Syntax ist Folgendes bemerkenswert:
Jede Partition muss dieselbe Anzahl Teilpartitionen haben.
Wenn Sie mit SUBPARTITION
explizit
Teilpartitionen für eine Partition einer partitionierten
Tabelle definieren, müssen Sie sie für alle anderen auch
definieren. Die folgende Anweisung wird scheitern:
CREATE TABLE ts (id INT, purchased DATE) PARTITION BY RANGE( YEAR(purchased) ) SUBPARTITION BY HASH( TO_DAYS(purchased) ) ( PARTITION p0 VALUES LESS THAN (1990) ( SUBPARTITION s0, SUBPARTITION s1 ), PARTITION p1 VALUES LESS THAN (2000), PARTITION p2 VALUES LESS THAN MAXVALUE ( SUBPARTITION s2, SUBPARTITION s3 ) );
Die Anweisung würde sogar dann fehlschlagen, wenn sie eine
SUBPARTITIONS 2
-Klausel enthielte.
Jede SUBPARTITION
-Klausel muss
(mindestens) den Namen für die Teilpartition enthalten.
Ansonsten können Sie alle Optionen setzen, die Sie
wünschen, oder aber die Teilpartition mit den
Standardeinstellungen anlegen.
Teilpartitionsnamen müssen innerhalb einer Partition
eindeutig sein, aber nicht innerhalb der Tabelle als Ganzes.
So ist beispielsweise die folgende CREATE
TABLE
-Anweisung zulässig:
CREATE TABLE ts (id INT, purchased DATE) PARTITION BY RANGE( YEAR(purchased) ) SUBPARTITION BY HASH( TO_DAYS(purchased) ) ( PARTITION p0 VALUES LESS THAN (1990) ( SUBPARTITION s0, SUBPARTITION s1 ), PARTITION p1 VALUES LESS THAN (2000) ( SUBPARTITION s0, SUBPARTITION s1 ), PARTITION p2 VALUES LESS THAN MAXVALUE ( SUBPARTITION s0, SUBPARTITION s1 ) );
Teilpartitionen können bei extrem großen Tabellen helfen, die
Daten und Indizes über viele Festplatten zu verteilen.
Angenommen, Sie haben 6 Festplatten als
/disk0
, /disk1
,
/disk2
und so weiter gemountet. Nun schauen
Sie sich folgendes Beispiel an:
CREATE TABLE ts (id INT, purchased DATE) PARTITION BY RANGE( YEAR(purchased) ) SUBPARTITION BY HASH( TO_DAYS(purchased) ) ( PARTITION p0 VALUES LESS THAN (1990) ( SUBPARTITION s0 DATA DIRECTORY = '/disk0/data' INDEX DIRECTORY = '/disk0/idx', SUBPARTITION s1 DATA DIRECTORY = '/disk1/data' INDEX DIRECTORY = '/disk1/idx' ), PARTITION p1 VALUES LESS THAN (2000) ( SUBPARTITION s0 DATA DIRECTORY = '/disk2/data' INDEX DIRECTORY = '/disk2/idx', SUBPARTITION s1 DATA DIRECTORY = '/disk3/data' INDEX DIRECTORY = '/disk3/idx' ), PARTITION p2 VALUES LESS THAN MAXVALUE ( SUBPARTITION s0 DATA DIRECTORY = '/disk4/data' INDEX DIRECTORY = '/disk4/idx', SUBPARTITION s1 DATA DIRECTORY = '/disk5/data' INDEX DIRECTORY = '/disk5/idx' ) );
In diesem Fall wird für die Daten und die Indizes jedes
RANGE
eine eigene Festplatte genutzt. Es sind
aber auch viele andere Varianten möglich; ein anderes Beispiel
wäre:
CREATE TABLE ts (id INT, purchased DATE) PARTITION BY RANGE(YEAR(purchased)) SUBPARTITION BY HASH(TO_DAYS(purchased)) ( PARTITION p0 VALUES LESS THAN (1990) ( SUBPARTITION s0a DATA DIRECTORY = '/disk0' INDEX DIRECTORY = '/disk1', SUBPARTITION s0b DATA DIRECTORY = '/disk2' INDEX DIRECTORY = '/disk3' ), PARTITION p1 VALUES LESS THAN (2000) ( SUBPARTITION s1a DATA DIRECTORY = '/disk4/data' INDEX DIRECTORY = '/disk4/idx', SUBPARTITION s1b DATA DIRECTORY = '/disk5/data' INDEX DIRECTORY = '/disk5/idx' ), PARTITION p2 VALUES LESS THAN MAXVALUE ( SUBPARTITION s2a, SUBPARTITION s2b ) );
Hier wird nach folgenden Regeln gespeichert:
Da Zeilen mit purchased
-Daten aus der
Zeit vor 1990 sehr viel Platz belegen, werden sie auf vier
Arten aufgeteilt, wobei jeweils eine eigene Festplatte den
Daten und Indizes jeder der beiden Teilpartitionen
(s0a
und s0b
) der
Partition p0
gewidmet ist. Mit anderen
Worten:
Die Daten für die Teilpartition s0a
werden auf /disk0
gespeichert.
Die Indizes für die Teilpartition
s0a
werden auf
/disk1
gespeichert.
Die Daten für die Teilpartition s0b
werden auf /disk2
gespeichert.
Die Indizes für die Teilpartition
s0b
werden auf
/disk3
gespeichert.
Die Zeilen mit den Daten der Jahre 1990 bis 1999 (Partition
p1
) belegen nicht so viel Speicher wie
die Daten von vor 1990. So werden sie auf zwei Festplatten
(/disk4
und
/disk5
) verteilt, nicht auf vier, wie
wir es mit den alten in p0
gespeicherten
Daten getan haben:
Die Daten und Indizes der ersten Teilpartition von
p1
(s1a
) werden
auf /disk4
gespeichert, und zwar
die Daten im Verzeichnis
/disk4/data
und die Indizes im
Verzeichnis /disk4/idx
.
Die Daten und Indizes der zweiten Teilpartition von
p1
(s1b
) werden
auf /disk5
gespeichert, und zwar
die Daten im Verzeichnis
/disk5/data
und die Indizes im
Verzeichnis /disk5/idx
.
Die Zeilen der Daten, die die Jahre ab 2000 betreffen
(Partition p2
), nehmen noch weniger
Speicherplatz in Anspruch als die beiden anderen
Datumsbereiche. Zurzeit reicht der Standardspeicherort noch
für sie aus.
Wenn später einmal die Verkaufsdaten für die mit dem Jahr
2000 beginnende Dekade so umfangreich werden, dass der
Standardspeicherort nicht mehr ausreicht, können die
entsprechenden Zeilen mit einer ALTER TABLE ...
REORGANIZE PARTITION
-Anweisung verschoben werden.
Wie das geht, erfahren Sie unter
Abschnitt 17.3, „Partitionsverwaltung“.
Die Partitionierung in MySQL gestattet durchaus auch einen
Partitionierungsausdruck mit dem Wert NULL
,
sei es nun ein Spaltenwert oder der Wert eines vom Benutzer
angegebenen Ausdrucks. Normalerweise behandelt MySQL
NULL
in solchen Fällen als null. Wenn Sie
dieses Verhalten unterbinden möchten, müssen Sie Tabellen so
entwerfen, dass sie keine Nullwerte erlauben, indem Sie die
Spalten als NOT NULL
deklarieren.
In diesem Abschnitt geben wir einige Beispiele, die zeigen
sollen, wie MySQL NULL
-Werte verarbeitet,
wenn die passende Partition für eine Zeile ermittelt werden
soll.
Wenn Sie eine Zeile in eine RANGE
- oder
LIST
-partitionierte Tabelle einfügen und der
Spaltenwert, der zur Bestimmung der Partition herangezogen wird,
NULL
ist, so wird dieser Wert als
0
interpretiert. Betrachten Sie
beispielsweise die folgenden beiden Tabellen:
mysql>CREATE TABLE tnlist (
->id INT,
->name VARCHAR(5)
->)
->PARTITION BY LIST(id) (
->PARTITION p1 VALUES IN (0),
->PARTITION p2 VALUES IN (1)
->);
Query OK, 0 rows affected (0.09 sec) mysql>CREATE TABLE tnrange (
->id INT,
->name VARCHAR(5)
->)
->PARTITION BY RANGE(id) (
->PARTITION p1 VALUES LESS THAN (1),
->PARTITION p2 VALUES LESS THAN MAXVALUE
->);
Query OK, 0 rows affected (0.09 sec) mysql>INSERT INTO tnlist VALUES (NULL, 'bob');
Query OK, 1 row affected (0.00 sec) mysql>INSERT INTO tnrange VALUES (NULL, 'jim');
Query OK, 1 row affected (0.00 sec) mysql>SELECT * FROM tnlist;
+------+------+ | id | name | +------+------+ | NULL | bob | +------+------+ 1 row in set (0.00 sec) mysql>SELECT * FROM tnrange;
+------+------+ | id | name | +------+------+ | NULL | jim | +------+------+ 1 row in set (0.00 sec)
In beiden Tabellen war die Spalte id
nicht
als NOT NULL
deklariert, kann also
NULL
-Werte annehmen. Dass die Zeilen in den
p1
-Partitionen der Tabellen gespeichert
wurden, können Sie überprüfen, indem Sie diese Partitionen
löschen und dann die SELECT
-Anweisungen
erneut ausführen:
mysql>ALTER TABLE tnlist DROP PARTITION p1;
Query OK, 0 rows affected (0.16 sec) mysql>ALTER TABLE tnrange DROP PARTITION p1;
Query OK, 0 rows affected (0.16 sec) mysql>SELECT * FROM tnlist;
Empty set (0.00 sec) mysql>SELECT * FROM tnrange;
Empty set (0.00 sec)
Bei einer HASH
- oder
KEY
-Partitionierung wird ein
Partitionierungsausdruck, der NULL
ergibt, so
behandelt, als sei sein Rückgabewert null. Dieses Verhalten
können wir überprüfen, indem wir betrachten, wie sich die
Erstellung einer HASH
-partitionierten
Tabelle, in die eine Zeile mit den entsprechenden Daten geladen
wird, auf das Dateisystem auswirkt. Angenommen, Sie haben eine
Tabelle namens tnhash
in der Datenbank
test
mit folgender Anweisung angelegt:
CREATE TABLE tnhash ( id INT, name VARCHAR(5) ) PARTITION BY HASH(id) PARTITIONS 2;
Wenn wir eine RPM-Installation von MySQL auf Linux zugrunde
legen, erzeugt diese Anweisung zwei
.MYD
-Dateien in
/var/lib/mysql/test
, die in der
bash-Shell wie folgt angezeigt werden
können:
/var/lib/mysql/test> ls *.MYD -l
-rw-rw---- 1 mysql mysql 0 2005-11-04 18:41 tnhash#P#p0.MYD
-rw-rw---- 1 mysql mysql 0 2005-11-04 18:41 tnhash#P#p1.MYD
(Hinweis: Vor MySQL 5.1.5
hätten diese Dateien tnhash_p0.MYD
und
tnhash_p1.MYD
geheißen. Unter
Abschnitt D.1.1, „Änderungen in Release 5.1.6 (Noch nicht veröffentlicht)“, und Bug#13437 finden Sie weitere
Informationen darüber, wie sich diese Änderung auf Upgrades
auswirkt.)
Beachten Sie, dass die beiden Dateien 0 Byte groß sind. Fügen
Sie nun in tnhash
eine Zeile ein, die in der
Spalte id
den Wert NULL
aufweist, und überprüfen Sie, ob die Zeile tatsächlich
eingefügt wurde:
mysql>INSERT INTO tnhash VALUES (NULL, 'sam');
Query OK, 1 row affected (0.00 sec) mysql>SELECT * FROM tnhash;
+------+------+ | id | name | +------+------+ | NULL | sam | +------+------+ 1 row in set (0.01 sec)
Bitte erinnern Sie sich, dass für einen Integer
N
der Wert von NULL MOD
immer
N
NULL
ist. Dieses Ergebnis wird behandelt, um
0
als die korrekte Partition festzulegen.
Wenn wir nun wieder in die System-Shell gehen (wobei weiterhin
bash zugrunde gelegt wird), können wir
erkennen, dass der Wert in die erste Partition (die nach
Voreinstellung p0
heißt) eingefügt wurde,
indem wir die Datendateien erneut auflisten:
var/lib/mysql/test> ls *.MYD -l
-rw-rw---- 1 mysql mysql 20 2005-11-04 18:44 tnhash#P#p0.MYD
-rw-rw---- 1 mysql mysql 0 2005-11-04 18:41 tnhash#P#p1.MYD
Wie Sie sehen, hat die INSERT
-Anweisung nur
die Datei tnhash_p0.MYD
modifiziert, deren
Umfang auf der Platte angewachsen ist, ohne auf die andere
Datendatei Einfluss zu nehmen.
Nehmen wir nun an, wir hätten folgende Tabelle:
CREATE TABLE tndate ( id INT, dt DATE ) PARTITION BY RANGE( YEAR(dt) ) ( PARTITION p0 VALUES LESS THAN (1990), PARTITION p1 VALUES LESS THAN (2000), PARTITION p2 VALUES LESS THAN MAXVALUE );
Wie andere MySQL-Funktionen gibt auch
YEAR(NULL)
den Wert NULL
zurück. Eine Zeile, die in der dt
-Spalte den
Wert NULL
hat, wird behandelt, als wäre der
Partitionierungsausdruck in Wirklichkeit 0
,
und folglich in die Partition p0
eingefügt.
MySQL 5.1 bietet eine Reihe von Möglichkeiten, um
partitionierte Tabellen zu modifizieren. Man kann Partitionen
hinzufügen, löschen, umdefinieren, zusammenführen oder
aufspalten. Alle diese Aktionen werden mit den
Partitionierungserweiterungen des ALTER
TABLE
-Befehls ausgeführt (zur Syntax siehe
Abschnitt 13.1.2, „ALTER TABLE
“). Darüber hinaus können Sie sich
Informationen über partitionierte Tabellen und Partitionen
beschaffen. Diese Themen werden in den nachfolgenden Abschnitten
behandelt.
Informationen über die Partitionsverwaltung in
RANGE
- oder
LIST
-partitionierten Tabellen finden Sie
unter Abschnitt 17.3.1, „Verwaltung von RANGE
- und
LIST
-Partitionen“.
Um die Verwaltung von HASH
- und
KEY
-Partitionen geht es in
Abschnitt 17.3.2, „Verwaltung von HASH
- und
KEY
-Partitionen“.
Mechanismen, mit denen Sie in MySQL 5.1 Informationen über partitionierte Tabellen and Partitionen erlangen können, werden in Abschnitt 17.3.4, „Abruf von Informationen über Partitionen“, vorgestellt.
Wartungsoperationen auf Partitionen werden in Abschnitt 17.3.3, „Wartung von Partitionen“, beschrieben.
Hinweis: In MySQL 5.1 müssen alle Partitionen einer partitionierten Tabelle die gleiche Anzahl von Teilpartitionen haben. Nach dem Anlegen der Tabelle ist es nicht mehr möglich, die Teilpartitionierung zu ändern.
Die Anweisung ALTER TABLE ... PARTITION BY ...
funktioniert seit MySQL 5.1.6; zuvor in MySQL 5.1 wurde ihre
Syntax zwar als gültig akzeptiert, aber Auswirkungen hatte sie
keine.
Um das Partitionierungsschema einer Tabelle zu ändern, müssen
Sie nur dem ALTER TABLE
-Befehl eine
partition_options
-Klausel hinzufügen.
Diese Klausel hat dieselbe Syntax, die auch in CREATE
TABLE
zur Erstellung einer partitionierten Tabelle
verwendet wird, und beginnt immer mit den Schlüsselwörtern
PARTITION BY
. Angenommen, Sie haben eine nach
Bereichen partitionierte Tabelle mit folgender CREATE
TABLE
-Anweisung angelegt:
CREATE TABLE trb3 (id INT, name VARCHAR(50), purchased DATE) PARTITION BY RANGE( YEAR(purchased) ) ( PARTITION p0 VALUES LESS THAN (1990), PARTITION p1 VALUES LESS THAN (1995), PARTITION p2 VALUES LESS THAN (2000), PARTITION p3 VALUES LESS THAN (2005) );
Um aus dieser Tabelle eine schlüsselpartitionierte Tabelle mit
zwei Partitionen zu machen, wobei der Wert der Spalte
id
die Grundlage für den Schlüssel liefert,
können Sie folgende Anweisung geben:
ALTER TABLE trb3 PARTITION BY KEY(id) PARTITIONS 2;
Auf die Struktur der Tabelle hat dies dieselben Auswirkungen wie
eine Löschung und Rekonstruktion mit CREATE TABLE trb3
PARTITION BY KEY(id) PARTITIONS 2;
.
Da das Hinzufügen und Löschen von Partitionen für Bereichs-
und Listenpartitionen ganz ähnlich behandelt wird, fassen wir
die Verwaltung dieser beiden Partitionierungsarten im
vorliegenden Abschnitt zusammen. Über den Umgang mit Hash- oder
schlüsselpartitionierten Tabellen erfahren Sie unter
Abschnitt 17.3.2, „Verwaltung von HASH
- und
KEY
-Partitionen“, Genaueres.
Weil das Löschen einer RANGE
- oder
LIST
--Partition einfacher ist als das
Hinzufügen, beginnen wir mit dem Löschen.
Um eine Partition aus einer RANGE
- oder
LIST
-partitionierten Tabelle zu löschen,
verwenden Sie den ALTER TABLE
-Befehl mit
einer DROP PARTITION
-Klausel. Das folgende
sehr einfach gehaltene Beispiel geht davon aus, dass Sie mit den
folgenden CREATE TABLE
- und
INSERT
-Anweisungen bereits eine nach Bereich
partitionierte Tabelle angelegt und mit 10 Datensätzen
bevölkert haben:
mysql>CREATE TABLE tr (id INT, name VARCHAR(50), purchased DATE)
->PARTITION BY RANGE( YEAR(purchased) ) (
->PARTITION p0 VALUES LESS THAN (1990),
->PARTITION p1 VALUES LESS THAN (1995),
->PARTITION p2 VALUES LESS THAN (2000),
->PARTITION p3 VALUES LESS THAN (2005)
->);
Query OK, 0 rows affected (0.01 sec) mysql>INSERT INTO tr VALUES
->(1, 'desk organiser', '2003-10-15'),
->(2, 'CD player', '1993-11-05'),
->(3, 'TV set', '1996-03-10'),
->(4, 'bookcase', '1982-01-10'),
->(5, 'exercise bike', '2004-05-09'),
->(6, 'sofa', '1987-06-05'),
->(7, 'popcorn maker', '2001-11-22'),
->(8, 'aquarium', '1992-08-04'),
->(9, 'study desk', '1984-09-16'),
->(10, 'lava lamp', '1998-12-25');
Query OK, 10 rows affected (0.01 sec)
Welche Daten in die Partition p2
geladen
wurden, sehen Sie hier:
mysql>SELECT * FROM tr
->WHERE purchased BETWEEN '1995-01-01' AND '1999-12-31';
+------+-----------+------------+ | id | name | purchased | +------+-----------+------------+ | 3 | TV set | 1996-03-10 | | 10 | lava lamp | 1998-12-25 | +------+-----------+------------+ 2 rows in set (0.00 sec)
Um nun die Partition p2
zu löschen, führen
Sie folgenden Befehl aus:
mysql> ALTER TABLE tr DROP PARTITION p2;
Query OK, 0 rows affected (0.03 sec)
Hinweis: Die Speicher-Engine NDB Cluster
in
MySQL 5.1 kennt kein ALTER TABLE ... DROP
PARTITION
. Doch immerhin unterstützt sie die anderen
in diesem Kapitel beschriebenen Partitionierungserweiterungen
der ALTER TABLE
-Anweisung.
Es ist sehr wichtig, sich zu merken, dass Sie beim
Löschen einer Partition alle darin gespeicherten Daten mit
löschen. Dies erkennen Sie, wenn Sie die obige
SELECT
-Anfrage erneut ausführen:
mysql>SELECT * FROM tr WHERE purchased
->BETWEEN '1995-01-01' AND '1999-12-31';
Empty set (0.00 sec)
Wenn Sie alle Daten aus allen Partitionen löschen, aber die
Tabellendefinition und ihr Partitionierungsschema erhalten
möchten, verwenden Sie den Befehl TRUNCATE
TABLE
. (Siehe auch Abschnitt 13.2.9, „TRUNCATE
“.)
Wenn Sie die Partitionierung einer Tabelle ändern möchten,
ohne Daten zu verlieren, verwenden Sie
stattdessen ALTER TABLE ... REORGANIZE
PARTITION
. Weiter unten oder in
Abschnitt 13.1.2, „ALTER TABLE
“, finden Sie Informationen über
REORGANIZE PARTITION
.
Wenn Sie nun einen SHOW CREATE TABLE
-Befehl
ausführen, können Sie sehen, wie sich die Partitionierung der
Tabelle geändert hat:
mysql> SHOW CREATE TABLE tr\G
*************************** 1. row ***************************
Table: tr
Create Table: CREATE TABLE `tr` (
`id` int(11) default NULL,
`name` varchar(50) default NULL,
`purchased` date default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
PARTITION BY RANGE ( YEAR(purchased) ) (
PARTITION p0 VALUES LESS THAN (1990) ENGINE = MyISAM,
PARTITION p1 VALUES LESS THAN (1995) ENGINE = MyISAM,
PARTITION p3 VALUES LESS THAN (2005) ENGINE = MyISAM
)
1 row in set (0.01 sec)
Wenn Sie nun in die geänderte Tabelle Zeilen einfügen, die in
der Spalte purchased
Werte zwischen
'1995-01-01'
und
'2004-12-31'
einschließlich aufweisen,
werden diese Zeilen in der Partition p3
gespeichert. Dies können Sie folgendermaßen überprüfen:
mysql>INSERT INTO tr VALUES (11, 'pencil holder', '1995-07-12');
Query OK, 1 row affected (0.00 sec) mysql>SELECT * FROM tr WHERE purchased
->BETWEEN '1995-01-01' AND '2004-12-31';
+------+----------------+------------+ | id | name | purchased | +------+----------------+------------+ | 11 | pencil holder | 1995-07-12 | | 1 | desk organiser | 2003-10-15 | | 5 | exercise bike | 2004-05-09 | | 7 | popcorn maker | 2001-11-22 | +------+----------------+------------+ 4 rows in set (0.00 sec) mysql>ALTER TABLE tr DROP PARTITION p3;
Query OK, 0 rows affected (0.03 sec) mysql>SELECT * FROM tr WHERE purchased
->BETWEEN '1995-01-01' AND '2004-12-31';
Empty set (0.00 sec)
Beachten Sie, dass die Anzahl der Zeilen, die aus der Tabelle
mit ALTER TABLE ... DROP PARTITION
gelöscht
wurden, vom Server nicht so gemeldet wird, wie es bei einer
entsprechenden DELETE
-Anweisung der Fall
wäre.
Zum Löschen von LIST
-Partitionen wird genau
dieselbe ALTER TABLE ... DROP
PARTITION
-Syntax verwendet wie zum Löschen von
RANGE
-Partitionen. Allerdings unterscheiden
sich die Auswirkungen, die dieses auf den späteren Gebrauch der
Tabelle hat, in einer wichtigen Hinsicht: In die Tabelle können
nun keine Zeilen mehr eingefügt werden, die irgendwelche in der
Werteliste der gelöschten Partition vorkommenden Werte
aufweisen. (Ein Beispiel finden Sie unter
Abschnitt 17.2.2, „LIST
-Partitionierung“.)
Um einer zuvor partitionierten Tabelle eine neue Bereichs- oder
Listenpartition hinzuzufügen, verwenden Sie die ALTER
TABLE ... ADD PARTITION
-Anweisung. Für Tabellen, die
nach RANGE
partitioniert werden, können Sie
mit dieser Anweisung einen neuen Wertebereich am Anfang oder
Ende der Liste der vorhandenen Partitionen hinzufügen.
Angenommen, Sie haben eine partitionierte Tabelle mit
Mitgliedsdaten Ihrer Organisation wie folgt definiert:
CREATE TABLE members ( id INT, fname VARCHAR(25), lname VARCHAR(25), dob DATE ) PARTITION BY RANGE( YEAR(dob) ) ( PARTITION p0 VALUES LESS THAN (1970), PARTITION p1 VALUES LESS THAN (1980), PARTITION p2 VALUES LESS THAN (1990) );
Nehmen wir nun weiterhin an, das Mindestalter der Mitglieder ist
16 Jahre. Da es bereits auf Ende 2005 zugeht, stellen Sie fest,
dass Sie demnächst Mitglieder aufnehmen müssen, die 1990
geboren wurden, und in den darauf folgenden Jahren wiederum
Mitglieder, die noch später zur Welt kamen. Mit folgender
Anweisung können Sie die members
-Tabelle so
umändern, dass auch Mitglieder zulässig sind, die in den
Jahren 1990 bis 1999 geboren wurden:
ALTER TABLE ADD PARTITION (PARTITION p3 VALUES LESS THAN (2000));
Wichtig: Tabellen, die nach
Bereich partitioniert wurden, können Sie mit dem Befehl
ADD PARTITION
nur am oberen Ende der
Wertebereichsliste neue Partitionen hinzufügen. Wenn Sie
versuchen, auf diesem Weg Partitionen zwischen oder vor
vorhandenen Partitionen einzufügen, wird folgender Fehler
generiert:
mysql>ALTER TABLE members
>ADD PARTITION (
>PARTITION p3 VALUES LESS THAN (1960));
ERROR 1463 (HY000): VALUES LESS THAN value must be strictly increasing for each partition
In ähnlicher Weise können Sie auch einer
LIST
-partitionierten Tabelle neue Partitionen
hinzufügen. Nehmen wir als Beispiel folgende Tabelle:
CREATE TABLE tt ( id INT, data INT ) PARTITION BY LIST(data) ( PARTITION p0 VALUES IN (5, 10, 15), PARTITION p1 VALUES IN (6, 12, 18) );
Mit der folgenden Anweisung können Sie eine neue Partition für
Zeilen einrichten, deren data
-Spalten die
Werte 7
, 14
und
21
aufweisen:
ALTER TABLE tt ADD PARTITION (PARTITION p2 VALUES IN (7, 14, 21));
Achtung: Sie können keine neue
LIST
-Partition hinzufügen, die irgendwelche
bereits in den Wertelisten bestehender Partitionen enthaltenen
Werte aufweist. Wenn Sie dieses versuchen, wird ein Fehler
gemeldet:
mysql>ALTER TABLE tt ADD PARTITION
>(PARTITION np VALUES IN (4, 8, 12));
ERROR 1465 (HY000): Multiple definition of same constant in list partitioning
Da Zeilen mit dem Wert 12
in der
data
-Spalte bereits der Partition
p1
zugewiesen sind, können Sie nicht in
Tabelle tt
eine neue Partition anlegen, die
ebenfalls 12
in ihrer Werteliste hat. Wenn
Sie dies dennoch tun müssen, löschen Sie zuerst
p1
und fügen dann np
und
danach eine neue p1
mit einer modifizierten
Definition hinzu. Allerdings würden dadurch, wie zuvor bereits
gesagt, alle in p1
gespeicherten Daten
verloren gehen, was im Allgemeinen nicht der angestrebte Effekt
ist. Eine andere Lösung könnte so aussehen, dass Sie eine
Kopie der Tabelle mit der neuen Partitionierung anlegen, dann
die Daten mit einer CREATE TABLE ... SELECT
...
hineinkopieren und schließlich die alte Tabelle
löschen und die neue umbenennen. Wenn Sie es mit großen
Datenmengen zu tun haben, könnte dies allerdings eine
zeitraubende Angelegenheit werden, die dort, wo
Hochverfügbarkeit gewährleistet werden muss, vielleicht
vollends unmöglich ist.
Seit MySQL 5.1.6 können Sie mehrere Partitionen in einer
einzigen ALTER TABLE ... ADD
PARTITION
-Anweisung anlegen:
CREATE TABLE employees ( id INT NOT NULL, fname VARCHAR(50) NOT NULL, lname VARCHAR(50) NOT NULL, hired DATE NOT NULL ) PARTITION BY RANGE( YEAR(hired) ) ( PARTITION p1 VALUES LESS THAN (1991), PARTITION p2 VALUES LESS THAN (1996), PARTITION p3 VALUES LESS THAN (2001), PARTITION p4 VALUES LESS THAN (2005) ); ALTER TABLE employees ADD PARTITION ( PARTITION p5 VALUES LESS THAN (2010), PARTITION p6 VALUES LESS THAN MAXVALUE );
Zum Glück bietet die Implementierung der Partitionierung in
MySQL Möglichkeiten, Partitionen ohne Datenverlust
umzudefinieren. Betrachten wir zunächst eine Reihe von
einfachen Beispielen zur
RANGE
-Partitionierung. Bitte erinnern Sie
sich an die members
-Tabelle, die nun
folgendermaßen definiert ist:
mysql> SHOW CREATE TABLE members\G
*************************** 1. row ***************************
Table: members
Create Table: CREATE TABLE `members` (
`id` int(11) default NULL,
`fname` varchar(25) default NULL,
`lname` varchar(25) default NULL,
`dob` date default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
PARTITION BY RANGE ( YEAR(dob) ) (
PARTITION p0 VALUES LESS THAN (1970) ENGINE = MyISAM,
PARTITION p1 VALUES LESS THAN (1980) ENGINE = MyISAM,
PARTITION p2 VALUES LESS THAN (1990) ENGINE = MyISAM.
PARTITION p3 VALUES LESS THAN (2000) ENGINE = MyISAM
)
Angenommen, Sie möchten alle Zeilen der Mitglieder, die vor
1960 geboren wurden, in eine separate Partition speichern. Wir
wir bereits sahen, ist dies mit der Anweisung ALTER
TABLE ... ADD PARTITION
nicht möglich. Sie können
jedoch eine andere Partitionierungserweiterung von
ALTER TABLE
benutzen, um dies zu erreichen:
ALTER TABLE members REORGANIZE PARTITION p0 INTO ( PARTITION s0 VALUES LESS THAN (1960), PARTITION s1 VALUES LESS THAN (1970) );
Im Endeffekt spaltet dieser Befehl die Partition
p0
in zwei neue Partitionen
s0
und s1
auf. Außerdem
werden die bisher in p0
gespeicherten Daten
nach den Regeln der beiden PARTITION ... VALUES
...
-Klauseln auf die neuen Partitionen verteilt,
sodass s0
nur Datensätze aufnimmt, deren
YEAR(dob)
-Wert kleiner als 1960 ist, und
s1
nur Datensätze, deren
YEAR(dob)
-Wert größer oder gleich 1960,
aber kleiner als 1970 ist.
Sie können auch mit einer REORGANIZE
PARTITION
-Klausel benachbartete Partitionen
verschmelzen. Mit dem folgenden Befehl stellen Sie die
members
-Tabelle wieder auf ihre vorherige
Partitionierung um:
ALTER TABLE members REORGANIZE PARTITION s0,s1 INTO ( PARTITION p0 VALUES LESS THAN (1970) );
Wenn Sie Partitionen mit REORGANIZE PARTITION
aufteilen oder zusammenführen, gehen keine Daten verloren. Bei
der Ausführung dieser Anweisung verschiebt MySQL alle
Datensätze, die zuvor in den Partitionen s0
und s1
gespeichert waren, wieder in die
Partition p0
.
REORGANIZE PARTITION
hat folgende allgemeine
Syntax:
ALTER TABLEtbl_name
REORGANIZE PARTITIONpartition_list
INTO (partition_definitions
);
tbl_name
ist hier der Name der
partitionierten Tabelle und
partition_list
ist eine
kommagetrennte Liste mit den Namen einer oder mehrerer
vorhandener Partitionen, die geändert werden sollen.
partition_definitions
ist eine
kommagetrennte Liste neuer Partitionsdefinitionen, für die
dieselben Regeln gelten, wie die
partition_definitions
einer
CREATE TABLE
-Anweisung (siehe
Abschnitt 13.1.5, „CREATE TABLE
“). Doch REORGANIZE
PARTITION
kann noch mehr, als nur Partitionen
aufspalten oder zusammenführen: Mit demselben Befehl können
Sie auch beispielsweise aus den vier Partitionen der
members
-Tabelle zwei machen:
ALTER TABLE members REORGANIZE PARTITION p0,p1,p2,p3 INTO ( PARTITION m0 VALUES LESS THAN (1980), PARTITION m1 VALUES LESS THAN (2000) );
REORGANIZE PARTITION
ist auch für
LIST
-partitionierte Tabellen geeignet.
Greifen wir noch einmal das Problem auf, wie man eine neue
Partition zu der listenpartitionierten Tabelle
tt
hinzufügen könnte. Der Versuch
scheiterte, weil die neue Partition einen Wert hatte, der
bereits in den Wertelisten der vorhandenen Partitionen
auftauchte. Dies können wir umgehen, indem wir eine Partition
hinzufügen, deren Liste nur zulässige Werte enthält, und dann
die neue und die vorhandenen Partitionen so umorganisieren, dass
der konfliktbeladene Wert aus der Werteliste der alten in die
Werteliste der neuen Partition übertragen wird:
ALTER TABLE tt ADD PARTITION (PARTITION np VALUES IN (4, 8)); ALTER TABLE tt REORGANIZE PARTITION p1,np INTO ( PARTITION p1 VALUES IN (6, 18), PARTITION np VALUES in (4, 8, 12) );
Die folgenden Punkte sind wichtig, wenn Sie ALTER TABLE
... REORGANIZE PARTITION
zur Neupartitionierung von
RANGE
- oder
LIST
-partitionierten Tabellen einsetzen:
Für die PARTITION
-Klauseln, mit denen
das neue Partitionierungsschema festgelegt wird, gelten
dieselben Regeln wie für die, die in einer CREATE
TABLE
-Anweisung benutzt werden.
Zuallererst müssen Sie daran denken, dass das neue
Partitionierungsschema keine sich überschneidenden
Wertebereiche (RANGE
-partitionierte
Tabellen) bzw. keine Überschneidungen in den Wertemengen
(LIST
-partitionierte Tabellen) haben
darf.
Hinweis: Vor MySQL 5.1.4
konnten Sie die Namen vorhandener Partitionen nicht in der
INTO
-Klausel wiederverwenden, selbst wenn
diese Partitionen gelöscht oder umdefiniert werden sollten.
Weitere Informationen gibt es unter
Abschnitt D.1.3, „Änderungen in Release 5.1.4 (21. Dezember 2005)“.
Die Kombination der Partitionen in der
partition_definitions
-Liste
sollte insgesamt denselben Wertebereich oder dieselbe
Wertemenge abdecken wie die Kombination der Partitionen, die
in der partition_list
aufgeführt
sind.
In der members
-Tabelle, die in diesem
Abschnitt als Beispiel dient, decken zum Beispiel die
Partitionen p1
und p2
zusammen die Jahre 1980 bis 1999 ab. Daher muss jede
Neuorganisation dieser beiden Partitionen insgesamt
denselben Zeitraum in Jahren abdecken.
In RANGE
-partitionierten Tabellen können
Sie nur benachbarte Partitionen reorganisieren, da keine
Bereichspartitionen übersprungen werden dürfen.
Sie können beispielsweise die
members
-Tabelle nicht mit einer Anweisung
reorganisieren, die mit ALTER TABLE members
REORGANIZE PARTITION p0,p2 INTO ...
anfängt, da
p0
die Jahre vor 1970 und
p2
die Jahre von 1990 bis einschließlich
1999 umfasst und somit die beiden Partitionen nicht
benachbart sind.
Sie können REORGANIZE PARTITION
nicht
einsetzen, um den Partitionierungstyp einer Tabelle zu
ändern, also beispielsweise nicht aus
RANGE
-Partitionen
HASH
-Partitionen oder umgekehrt machen.
Auch können Sie diesen Befehl nicht verwenden, um den
Partitionierungsausdruck oder die Partitionierungsspalte zu
ändern. Um dieses zu tun, ohne die Tabelle löschen und
rekonstruieren zu müssen, verwenden Sie ALTER
TABLE ... PARTITION BY ...
. Zum Beispiel:
ALTER TABLE members PARTITION BY HASH( YEAR(dob) ) PARTITIONS 8;
Hinweis: In MySQL 5.1
5.1.5-alpha ist ALTER TABLE ... PARTITION BY
...
noch nicht implementiert. Stattdessen müssen
Sie die Tabelle entweder löschen und mit der gewünschten
Partitionierung neu erzeugen oder, wenn Sie die Daten der
Tabelle bewahren möchten, mit CREATE TABLE ...
SELECT ...
die neue Tabelle anlegen und die Daten
aus der alten herüberkopieren, um anschließend die alte
Tabelle zu löschen und in einem letzten Schritt die neue
Tabelle umzubenennen, wenn dies gewünscht wird.
Die Partitionierung von Hash- oder schlüsselpartitionierten
Tabellen lässt sich in ähnlicher Weise ändern, wobei sich
Tabellen mit diesen beiden Formen der Partitionierung in
mehrerer Hinsicht von bereichs- oder listenpartitionierten
Tabellen unterscheiden. Daher werden in diesem Abschnitt nur
Änderungen von Hash- oder schlüsselpartitionierten Tabellen
behandelt. Das Hinzufügen und Löschen der Partitionen von
bereichs- oder listenpartitionierten Tabellen wird in
Abschnitt 17.3.1, „Verwaltung von RANGE
- und
LIST
-Partitionen“,
beschrieben.
Sie können Partitionen aus HASH
- oder
KEY
-partitionierten Tabellen nicht genauso
löschen wie aus RANGE
- oder
LIST
-partitionierten Tabellen. Doch zum
Zusammenführen von HASH
- oder
KEY
-partitionierten Tabellen können Sie
ebenfalls den ALTER TABLE ... COALESCE
PARTITION
-Befehl verwenden. Angenommen, Sie haben eine
Tabelle mit Kundendaten, die in 12 Partitionen aufgeteilt ist.
Diese clients
-Tabelle ist folgendermaßen
definiert:
CREATE TABLE clients ( id INT, fname VARCHAR(30), lname VARCHAR(30), signed DATE ) PARTITION BY HASH( MONTH(signed) ) PARTITIONS 12;
Um die Anzahl der Partitionen von 12 auf 6 zu reduzieren,
führen Sie folgenden ALTER TABLE
-Befehl aus:
mysql> ALTER TABLE clients COALESCE PARTITION 6;
Query OK, 0 rows affected (0.02 sec)
COALESCE
funktioniert genauso gut mit
HASH
-, KEY
-,
LINEAR HASH
- oder LINEAR
KEY
-partitionierten Tabellen. Hier sehen Sie ein
ähnliches Beispiel wie oben, allerdings dieses Mal mit einer
Tabelle, die nach LINEAR KEY
partitioniert
ist:
mysql>CREATE TABLE clients_lk (
->id INT,
->fname VARCHAR(30),
->lname VARCHAR(30),
->signed DATE
->)
->PARTITION BY LINEAR KEY(signed)
->PARTITIONS 12;
Query OK, 0 rows affected (0.03 sec) mysql>ALTER TABLE clients_lk COALESCE PARTITION 6;
Query OK, 0 rows affected (0.06 sec) Records: 0 Duplicates: 0 Warnings: 0
COALESCE
kann nicht verwendet werden, um die
Anzahl der Partitionen zu erhöhen. Ein Versuch, dies zu tun,
verursacht folgenden Fehler:
mysql> ALTER TABLE clients COALESCE PARTITION 18;
ERROR 1478 (HY000): Cannot remove all Partitionen, use DROP TABLE instead
Um die Anzahl der Partitionen der
clients
-Tabelle von 12 auf 18 zu erhöhen,
erteilen Sie folgende ALTER TABLE ... ADD
PARTITION
-Anweisung:
ALTER TABLE clients ADD PARTITION PARTITIONS 18;
Hinweis: ALTER TABLE
... REORGANIZE PARTITION
kann nicht für
HASH
- oder
KEY
-partitionierte Tabellen verwendet werden.
Hinweis: Die Befehle, die dieser Abschnitt beschreibt, sind in MySQL 5.1 noch nicht implementiert. Sie werden vor allem vorgestellt, um Feedback von Benutzern zu bekommen, die die Software während des Entwicklungszyklus der Version 5.1 vor der Produktionsreife testen. (Mit anderen Worten: Bitte schicken Sie uns keine Bugreports mit dem Hinweis, dass diese Befehle nicht funktionieren.) Die Informationen in diesem Abschnitt ändern sich noch ständig, da die Entwicklung der Partitionierung für MySQL 5.1 weitergeht. Wir werden den Abschnitt aktualisieren, wenn Partitionierungsfeatures implementiert oder verbessert werden.
MySQL 5.1 ermöglicht viele Wartungsarbeiten im
Bereich der Partitionierung. MySQL unterstützt für
partitionierte Tabellen nicht die Befehle CHECK
TABLE
, OPTIMIZE TABLE
,
ANALYZE TABLE
oder REPAIR
TABLE
. Dagegen können Sie jedoch eine Reihe von
Erweiterungen des ALTER TABLE
-Befehls
einsetzen, um diese Operationen auf einer oder mehreren
Partitionen direkt auszuführen. Diese Erweiterungen sind im
Folgenden dargestellt:
Partitionen neu erstellen: Legt die Partition neu an, hat denselben Effekt wie das Löschen und anschließende Wiedereinfügen aller in der Partition gespeicherten Datensätze. Kann bei der Defragmentierung nützlich sein.
Beispiel:
ALTER TABLE t1 REBUILD PARTITION (p0, p1);
Partitionen optimieren:
Wenn Sie viele Zeilen aus einer Partition gelöscht oder
viele Änderungen an einer partitionierten Tabelle mit
Zeilen variabler Länge (VARCHAR
-,
BLOB
- oder
TEXT
-Spalten) vorgenommen haben, können
Sie mit ALTER TABLE ... OPTIMIZE
PARTITION
unbenutzten Speicherplatz zurückholen
und die Datendatei der Partition defragmentieren.
Beispiel:
ALTER TABLE t1 OPTIMIZE PARTITION (p0, p1);
Wenn Sie auf einer Partition OPTIMIZE
PARTITION
ausführen, ist dies dasselbe, als
würden Sie CHECK PARTITION
,
ANALYZE PARTITION
und REPAIR
PARTITION
aufrufen.
Partitionen analysieren: Liest und speichert die Schlüsselverteilungen für Partitionen.
Beispiel:
ALTER TABLE t1 ANALYZE PARTITION (p3);
Partitionen reparieren: Repariert beschädigte Partitionen.
Beispiel:
ALTER TABLE t1 REPAIR PARTITION (p0,p1);
Partitionen überprüfen:
Sie können Partitionen in ganz ähnlicher Weise auf Fehler
untersuchen, wie Sie es mit CHECK TABLE
für nicht partitionierte Tabellen machen würden.
Beispiel:
ALTER TABLE trb3 CHECK PARTITION (p1);
Dieser Befehl sagt Ihnen, ob die Daten oder Indizes in
Partition p1
der Tabelle
t1
beschädigt sind. Wenn dies der Fall
ist, können Sie die Partition mit ALTER TABLE ...
REPAIR PARTITION
wieder reparieren.
Diese Aufgaben können Sie auch lösen, indem Sie
mysqlcheck oder myisamchk
auf den separaten .MYI
-Dateien ausführen,
die bei der Partitionierung einer Tabelle generiert werden.
Siehe Abschnitt 8.9, „mysqlcheck — Hilfsprogramm für die Wartung und Reparatur von Tabellen“. (Diese Möglichkeit steht
auch bereits im Pre-Alpha-Code zur Verfügung.)
Dieser Abschnitt beschreibt, wie Sie sich Informationen über bestehende Partitionen beschaffen können. Da sich diese Funktionalität noch in der Planung befindet, sind die folgenden Ausführungen zurzeit nur eine Absichtserklärung über die Dinge, die wir in MySQL 5.1 implementieren wollen.
Wie bereits an anderer Stelle in diesem Kapitel gesagt, zeigt
die Ausgabe von SHOW CREATE TABLE
auch eine
PARTITION BY
-Klausel an, mit der eine
partitionierte Tabelle angelegt wurde. Zum Beispiel:
mysql> SHOW CREATE TABLE trb3\G
*************************** 1. row ***************************
Table: trb3
Create Table: CREATE TABLE `trb3` (
`id` int(11) default NULL,
`name` varchar(50) default NULL,
`purchased` date default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
PARTITION BY RANGE (YEAR(purchased)) (
PARTITION p0 VALUES LESS THAN (1990) ENGINE = MyISAM,
PARTITION p1 VALUES LESS THAN (1995) ENGINE = MyISAM,
PARTITION p2 VALUES LESS THAN (2000) ENGINE = MyISAM,
PARTITION p3 VALUES LESS THAN (2005) ENGINE = MyISAM
)
1 row in set (0.00 sec)
Hinweis: In frühen MySQL
5.1-Releases wurde die PARTITIONS
-Klausel
nicht für Tabellen angezeigt, die nach HASH
oder KEY
partitioniert waren. Dies wurde in
MySQL 5.1.6 behoben.
SHOW TABLE STATUS
funktioniert auch für
partitionierte Tabellen und hat dieselbe Ausgabe wie für
nichtpartitionierte Tabellen, nur dass die Spalte
Engine
immer den Wert
'PARTITION'
hat. (Mehr über diesen Befehl
erfahren Sie in Abschnitt 13.5.4.21, „SHOW TABLE STATUS
“.)
Informationen über Partitionen liefert Ihnen auch das
INFORMATION_SCHEMA
, zu dem auch eine
PARTITIONS
-Tabelle gehört. Siehe
Abschnitt 22.19, „Die Tabelle INFORMATION_SCHEMA PARTITIONS
“.
Seit MySQL 5.1.5 können Sie mit EXPLAIN
PARTITIONS
herausfinden, welche Partitionen einer
partitionierten Tabelle an einer
SELECT
-Anfrage beteiligt sind. Das
Schlüsselwort PARTITIONS
fügt der Ausgabe
von EXPLAIN
eine
partitions
-Spalte hinzu, in der die
Partitionen aufgeführt sind, in denen die Anfrage Datensätze
erkannt hat.
Angenommen, Sie haben eine Tabelle trb1
, die
folgendermaßen definiert und mit Daten gefüllt ist:
CREATE TABLE trb1 (id INT, name VARCHAR(50), purchased DATE) PARTITION BY RANGE(id) ( PARTITION p0 VALUES LESS THAN (3), PARTITION p1 VALUES LESS THAN (7), PARTITION p2 VALUES LESS THAN (9), PARTITION p3 VALUES LESS THAN (11) ); INSERT INTO trb1 VALUES (1, 'desk organiser', '2003-10-15'), (2, 'CD player', '1993-11-05'), (3, 'TV set', '1996-03-10'), (4, 'bookcase', '1982-01-10'), (5, 'exercise bike', '2004-05-09'), (6, 'sofa', '1987-06-05'), (7, 'popcorn maker', '2001-11-22'), (8, 'aquarium', '1992-08-04'), (9, 'study desk', '1984-09-16'), (10, 'lava lamp', '1998-12-25');
Mit folgendem Befehl können Sie sich darüber informieren,
welche Partitionen in einer Anfrage wie SELECT * FROM
trb1;
benutzt werden:
mysql> EXPLAIN PARTITIONS SELECT * FROM trb1\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: trb1
partitions: p0,p1,p2,p3
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 10
Extra: Using filesort
In diesem Fall wurden 4 vier Partitionen durchsucht. Wenn Sie der Anfrage jedoch eine einschränkende Bedingung hinzufügen, die den Partitionierungsschlüssel enthält, können Sie erkennen, dass nur diejenigen Partitionen gescannt werden, die passende Werte enthalten:
mysql> EXPLAIN PARTITIONS SELECT * FROM trb1 WHERE id < 5\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: trb1
partitions: p0,p1
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 10
Extra: Using where
EXPLAIN PARTITIONS
informiert über
verwendete und mögliche Schlüssel ebenso wie die
standardmäßige EXPLAIN SELECT
-Anweisung:
mysql>ALTER TABLE trb1 ADD PRIMARY KEY (id);
Query OK, 10 rows affected (0.03 sec) Records: 10 Duplicates: 0 Warnings: 0 mysql>EXPLAIN PARTITIONS SELECT * FROM trb1 WHERE id < 5\G
*************************** 1. row *************************** id: 1 select_type: SIMPLE table: trb1 partitions: p0,p1 type: range possible_keys: PRIMARY key: PRIMARY key_len: 4 ref: NULL rows: 7 Extra: Using where
Beachten Sie jedoch folgende Restriktionen von EXPLAIN
PARTITIONS
:
Sie dürfen die Schlüsselwörter
PARTITIONS
und
EXTENDED
nicht zusammen in derselben
EXPLAIN ... SELECT
-Anweisung benutzen,
sonst verursachen Sie einen Syntaxfehler.
Der Befehl EXPLAIN PARTITIONS
liefert nur
dann brauchbare Ergebnisse, wenn er zur Untersuchung von
Anfragen auf RANGE
- oder
LIST
-partitionierten Tabellen verwendet
wird. (Bei KEY
- oder
HASH
-partitionierten Tabellen listet der
Befehl einfach alle Partitionen in der
partitions
-Spalte seiner Ausgabe auf.)
Wenn Sie mit EXPLAIN PARTITIONS
eine
Anfrage auf einer nichtpartitionierten Tabelle untersuchen,
wird zwar kein Fehler ausgelöst, aber der Wert der
partitions
-Spalte ist dann immer
NULL
.
EXPLAIN PARTITIONS
funktioniert zurzeit
nur mit Tabellen, die auf einer Integer-Spalte partitioniert
werden.
Dieser Abschnitt beschreibt die gegenwärtigen Restriktionen der MySQL-Partitionierungsunterstützung:
Partitionierte Tabellen unterstützen keine Fremdschlüssel.
Dies schließt auch Tabellen ein, die mit der Speicher-Engine
InnoDB
arbeiten.
Partitionierte Tabellen können zwar jede beliebige Speicher-Engine von MySQL benutzen, aber alle Partitionen und Teilpartitionen der Tabelle (wenn vorhanden) müssen dieselbe Engine verwenden.
Wir hoffen, diese Beschränkung in einem künftigen MySQL-Release aufzuheben.
Ein Partitionierungsschlüssel muss entweder eine
Integer-Spalte oder ein Ausdruck sein, der einen Integer
ergibt. In jedem Fall muss der verwendete Wert nichtnegativ
sein. Zurzeit sind auch NULL
-Werte
zulässig, aber dies wird sich noch ändern.
Teilpartitionen können nur HASH
- oder
KEY
-Partitionierung verwenden.
Inhaltsverzeichnis
Geometry
Point
Curve
LineString
Surface
Polygon
GeometryCollection
MultiPoint
MultiCurve
MultiLineString
MultiSurface
MultiPolygon
Geometry
-Funktionen
Mit den raumbezogenen Erweiterungen von MySQL lassen sich
geographische Features erstellen, speichern und analysieren. Diese
Features stehen für MyISAM
-,
InnoDB
-, NDB
-,
BDB
- und ARCHIVE
-Tabellen zur
Verfügung. (Da jedoch die ARCHIVE
-Engine keine
Indizes unterstützt, können raumbezogene Spalten in
ARCHIVE
nicht indiziert werden. Auch in MySQL
Cluster sind keine Indizes auf raumbezogenen Spalten möglich.
Dieses Kapitel behandelt folgende Themen:
Grundlagen der raumbezogenen Erweiterungen im Geodatenmodell OpenGIS
Datenformate zur Darstellung raumbezogener Daten
Wie raumbezogene Daten in MySQL verwendet werden
Indizierung raumbezogener Daten
MySQLs Abweichungen von der OpenGIS-Spezifikation
Das Open Geospatial Consortium veröffentlicht das OpenGIS® Simple Features Specifications For SQL: ein Dokument, das mehrere Konzepte vorstellt, wie ein auf SQL basierendes relationales Datenbanksystem auch raumbezogene Daten unterstützen könnte. Diese Spezifikation finden Sie auf der Website des OGC unter http://www.opengis.org/docs/99-049.pdf.
Wenn Sie Fragen oder sonstige Anliegen hinsichtlich der raumbezogenen Erweiterungen zu MySQL haben, können Sie diese im GIS-Forum zur Diskussion stellen: http://forums.mysql.com/list.php?23.
MySQL implementiert raumbezogene Erweiterungen nach der Spezifikation des Open Geospatial Consortium (OGC). Dabei handelt es sich um ein internationales Konsortium von mehr als 250 Unternehmen, Behörden und Universitäten, die alle an der Entwicklung von öffentlich zugänglichen, konzeptionellen Lösungen für alle Arten von Programmen arbeiten, welche mit der Verwaltung raumbezogener Daten zu tun haben. Das OGC betreibt eine Website unter http://www.opengis.org/.
Im Jahre 1997 veröffentlichte das Open Geospatial Consortium die OpenGIS® Simple Features Specifications For SQL, ein Dokument, das mehrere Konzepte vorstellt, wie ein SQL-RDBMS raumbezogene Daten unterstützen könnte. Diese Spezifikation finden Sie auf der Website des OGC unter http://www.opengis.org/docs/99-049.pdf. Sie enthält wichtige Zusatzinformationen zu diesem Kapitel.
MySQL implementiert einen Teil der vom OGC empfohlenen SQL with Geometry Types-Umgebung. Gemeint ist damit eine SQL-Umgebung, die um eine Reihe von geometrischen Typen erweitert wurde. Eine SQL-Spalte, die einen geometrischen Wert hat, wird als Spalte geometrischen Typs implementiert. Die Spezifikation beschreibt eine Reihe von geometrischen Typen für SQL sowie Funktionen, die mit diesen Typen arbeiten können, um geometrische Werte zu erzeugen und zu analysieren.
Ein geographisches Feature ist irgendetwas, das irgendwo auf der Welt einen Standort hat. Hierzu gehören:
ein Gegenstand, wie zum Beispiel ein Berg, ein Teich oder eine Stadt
ein Raum, wie beispielsweise ein Postleitzahlengebiet oder die Tropen
ein klar definierter Ort, wie zum Beispiel eine Straßenkreuzung als der Schnittpunkt zweier Straßen
In manchen Dokumenten werden geographische Features als geospatiale Features bezeichnet.
Auch das Wort Geometrie bezeichnet ein geographisches Feature. Ursprünglich wurde der Begriff Geometrie für die Vermessung der Erde verwendet. Eine weitere Bedeutung bekam das Wort in der Kartographie, wo es die geometrischen Merkmale bezeichnet, die Kartographen für ihr Abbild der Welt verwenden.
Im vorliegenden Kapitel werden die Begriffe geographisches Feature, geospatiales Feature, Feature und Geometrie synonym eingesetzt. Am häufigsten verwenden wir das Wort Geometrie im Sinne von einem Punkt oder einer Menge von Punkten, die irgendetwas auf der Welt darstellen, das sich an einem Ort befindet.
Geometry
Point
Curve
LineString
Surface
Polygon
GeometryCollection
MultiPoint
MultiCurve
MultiLineString
MultiSurface
MultiPolygon
Die Geometrietypen, die das OGC in seiner SQL with Geometry Types-Umgebung vorschlägt, beruhen auf dem OpenGIS Geometry Model. In diesem Modell hat jedes geometrische Objekt folgende allgemeine Eigenschaften:
Es ist verbunden mit einem Georeferenzsystem, welches den Koordinatenraum beschreibt, in dem das Objekt definiert ist.
Es gehört zu einer Geometrieklasse.
Die Geometrieklassen definieren folgende Hierarchie:
Geometry
(nichtinstanziierbar)
Point
(instanziierbar)
Curve
(nichtinstanziierbar)
LineString
(instanziierbar)
Line
LinearRing
Surface
(nichtinstanziierbar)
Polygon
(instanziierbar)
GeometryCollection
(instanziierbar)
MultiPoint
(instanziierbar)
MultiCurve
(nichtinstanziierbar)
MultiLineString
(instanziierbar)
MultiSurface
(nichtinstanziierbar)
MultiPolygon
(instanziierbar)
Von nichtinstanziierbaren Klassen können keine Objekte erzeugt werden, von instanziierbaren Klassen hingegen sehr wohl. Alle Klassen haben Eigenschaften und instanziierbare Klassen können darüber hinaus Zusicherungen machen (Regeln, nach denen gültige Klasseninstanzen definiert sind).
Geometry
ist die abstrakte Basisklasse. Die
instanziierbaren Unterklassen von Geometry
dürfen nur null-, eins- und zweidimensionale geometrische
Objekte haben, die in einem zweidimensionalen Koordinatenraum
vorkommen. Alle instanziierbaren Geometrieklassen sind so
definiert, dass gültige Instanzen dieser Klassen topologisch
geschlossen sein müssen (d. h., in allen definierten Geometrien
ist ihre jeweilige Grenze enthalten).
Die Basisklasse Geometry
hat die Unterklassen
Point
, Curve
,
Surface
und
GeometryCollection
:
Point
stellt nulldimensionale Objekte
dar.
Curve
stellt eindimensionale Objekte dar
und hat die Unterklasse LineString
, die
ihrerseits die Unterklassen Line
und
LinearRing
hat.
Surface
ist für zweidimensionale Objekte
da und hat die Unterklasse Polygon
.
GeometryCollection
besitzt die
spezialisierten null-, eins- und zweidimensionalen
Collection-Klassen namens MultiPoint
,
MultiLineString
und
MultiPolygon
zur Modellierung von
Geometrien aus Points
,
LineStrings
oder
Polygons
. MultiCurve
und MultiSurface
sind abstrakte
Oberklassen, die Collection-Interfaces für den Umgang mit
Curves
und Surfaces
realisieren.
Geometry
, Curve
,
Surface
, MultiCurve
und
MultiSurface
sind nichtinstanziierbare
Klassen. Sie definieren eine Menge von gemeinsamen Methoden für
ihre Unterklassen und sind dazu da, erweitert zu werden.
Point
, LineString
,
Polygon
,
GeometryCollection
,
MultiPoint
,
MultiLineString
und
MultiPolygon
sind instanziierbare Klassen.
Geometry
ist die Wurzelklasse der Hierarchie.
Sie ist eine nichtinstanziierbare Klasse, besitzt jedoch eine
Reihe von Eigenschaften, die alle Klassen gemeinsam haben,
welche aus einer Unterklasse von Geometry
erzeugt wurden. Diese Eigenschaften werden in der folgenden
Liste aufgeführt. Bestimmte Unterklassen haben ihre eigenen,
ganz speziellen Eigenschaften, die weiter unten beschrieben
werden.
Geometrie-Eigenschaften
Ein Geometriewert hat folgende Eigenschaften:
Den Typ. Jeder Geometriewert gehört zu einer der instanziierbaren Klassen der Hierarchie.
Seinen SRID (Spatial Reference Identifier). Dieser Wert steht für das Georeferenzsystem, welches den Koordinatenraum beschreibt, in dem das Geometrieobjekt definiert ist.
In MySQL ist der SRID-Wert ein einfacher Integer, der mit dem Geometriewert verbunden ist. Allen Berechnungen liegt die euklidische (planare) Geometrie zugrunde.
Seine Koordinaten in seinem Georeferenzsystem, dargestellt als Zahlen mit doppelter Genauigkeit (8 Byte). Alle nichtleeren Geometrien enthalten mindestens ein Koordinatenpaar (x,y). Leere Geometrien enthalten keine Koordinaten.
Koordinaten hängen mit dem SRID zusammen. So kann zum Beispiel in unterschiedlichen Koordinatensystemen der Abstand zwischen zwei Objekten verschieden sein, selbst dann, wenn die Objekte dieselben Koordinaten haben, da der Abstand in einem planaren Koordinatensystem und der Abstand in einem geozentrischen System (die Koordinaten auf der Erdoberfläche) zwei verschiedene Dinge sind.
Seinen Innenbereich, seine Grenze und seinen Außenbereich.
Jede Geometrie hat irgendeine Position im Raum. Der Außenbereich ist der Raum, welcher nicht von der Geometrie belegt wird, und der Innenbereich der Raum, der von ihr bedeckt ist. Die Grenze ist die Schnittstelle zwischen Innenbereich und Außenbereich der Geometrie.
Sein MBR (Minimum Bounding Rectangle, dt.: kleinstes einschließendes Rechteck), auch Envelope genannt. Dies ist die begrenzende Geometrie, die durch die kleinsten und größten (x,y)-Koordinaten gebildet wird:
((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))
Ob der Wert einfach
(simple) oder nicht einfach
(non-simple) ist. Geometriewerte der Typen
LineString
,
MultiPoint
und
MultiLineString
sind entweder einfach
oder nicht einfach. Jeder Typ hat seine eigenen
Zusicherungen darüber, ob er einfach oder nicht einfach
ist.
Ob der Wert geschlossen
oder nicht geschlossen ist.
Geometriewerte der Typen (LineString
,
MultiString
) sind entweder geschlossen
oder nicht geschlossen. Jeder Typ hat seine eigenen
Zusicherungen darüber, ob er geschlossen oder nicht
geschlossen ist.
Ob der Wert leer oder
nichtleer ist. Eine
Geometrie ist leer, wenn sie keine Punkte enthält.
Außenbereich, Innenbereich und Grenze einer leeren
Geometrie sind nicht definiert (d. h., sie werden durch
einen NULL
-Wert dargestellt). Eine leere
Geometrie ist per Definition immer einfach und hat die
Fläche 0.
Seine Dimension. Eine Geometrie kann die Dimension –1, 0, 1 oder 2 haben:
–1 für eine leere Geometrie.
0 für eine Geometrie ohne Länge und ohne Fläche.
1 für eine Geometrie mit einer von null verschiedenen Länge und der Fläche null.
2 für eine Geometrie mit einer von null verschiedenen Fläche.
Point
-Objekte haben die Dimension null.
LineString
-Objekte haben die Dimension 1.
Polygon
-Objekte haben die Dimension 2.
MultiPoint
-,
MultiLineString
- und
MultiPolygon
-Objekte haben dieselben
Dimensionen wie die Elemente, aus denen sie bestehen.
Ein Point
ist eine Geometrie, die einen
einzigen Punkt im Koordinatenraum darstellt.
Beispiele für
Point
Stellen Sie sich eine Weltkarte in großem Maßstab mit
vielen Städten vor. Die Städte könnte man mit
Point
-Objekten darstellen.
Auf einem Stadtplan könnte ein
Point
-Objekt eine Bushaltestelle
darstellen.
Eigenschaften von
Point
Wert der x-Koordinate.
Wert der y-Koordinate.
Ein Point
ist als eine nulldimensionale
Geometrie definiert.
Die Grenze eines Point
s ist die leere
Menge.
Eine Curve
ist eine eindimensionale
Geometrie, die in der Regel durch eine Abfolge von Punkten
dargestellt wird. Spezielle Unterklassen von
Curve
definieren die Art der Interpolation
zwischen den Punkten. Curve
ist eine
nichtinstanziierbare Klasse.
Eigenschaften von
Curve
Eine Curve
hat die Koordinaten ihrer
Punkte.
Eine Curve
ist als eindimensionale
Geometrie definiert.
Eine Curve
ist einfach, wenn sie nicht
zweimal durch denselben Punkt geht.
Eine Curve
ist geschlossen, wenn ihr
Anfangs- gleich ihrem Endpunkt ist.
Die Grenze einer geschlossenen Curve
ist
leer.
Die Grenze einer nicht geschlossenen
Curve
besteht aus ihren beiden
Endpunkten.
Eine Curve
, die einfach und geschlossen
ist, ist ein LinearRing
.
Ein LineString
ist eine
Curve
mit linearer Interpolation zwischen den
Punkten.
Beispiele für
LineString
Auf einer Weltkarte könnten
LineString
-Objekte Flüsse darstellen.
Auf einem Stadtplan könnten
LineString
-Objekte Straßen darstellen.
Eigenschaften von
LineString
Ein LineString
hat Segmentkoordinaten,
die durch jeweils aufeinander folgende Punktpaare definiert
sind.
Ein LineString
ist eine
Line
, wenn er aus genau zwei Punkten
besteht.
Ein LineString
ist ein
LinearRing
, wenn er sowohl geschlossen
als auch einfach ist.
Eine Surface
ist eine zweidimensionale
Geometrie. Sie ist eine nichtinstanziierbare Klasse. Ihre
einzige instanziierbare Unterklasse ist
Polygon
.
Eigenschaften von
Surface
Eine Surface
ist als zweidimensionale
Geometrie definiert.
Die OpenGIS-Spezifikation definiert eine einfache
Surface
als eine Geometrie, die aus einem
einzelnen „Patch“ besteht, zu dem eine einzige
Außengrenze und null oder mehr Innengrenzen gehören.
Die Grenze einer einfachen Surface
ist
die Menge der geschlossenen Kurven, die ihrer Außen- und
Innengrenze entsprechen.
Ein Polygon
ist eine planare
Surface
, die eine mehrseitige Geometrie
darstellt. Sie ist definiert durch eine einzige Außengrenze und
null oder mehr Innengrenzen, wobei jede Innengrenze ein Loch im
Polygon
darstellt.
Beispiele für
Polygon
Auf einer Regionalkarte könnten
Polygon
-Objekte Wälder, Landkreise usw.
darstellen.
Zusicherungen von
Polygon
Die Grenze eines Polygon
besteht aus
einer Menge von LinearRing
-Objekten (d.
h. LineString
-Objekten, die sowohl
einfach als auch geschlossen sind), die seine Außen- und
seine Innengrenze bilden.
Ein Polygon
wird nicht von Ringen
geschnitten. Ringe können in der Grenze eines
Polygon
zwar einen
Point
berühren, aber nur als Tangente.
Ein Polygon
hat keine geschnittenen
Linien, Zacken (Spikes) oder Lücken (Punctures).
Der Innenbereich eines Polygon
ist eine
Menge verbundener Punkte.
Ein Polygon
kann Löcher haben. Der
Außenbereich eines Polygon
mit Löchern
ist unzusammenhängend. Jedes Loch definiert einen
zusammenhängenden Bestandteil des Außenbereichs.
Aufgrund dieser Zusicherungen ist ein Polygon
eine einfache Geometrie.
Eine GeometryCollection
ist eine Sammlung aus
einer oder mehreren Geometrien beliebiger Klassen.
Alle Elemente einer GeometryCollection
müssen dasselbe Georeferenzsystem (also dasselbe
Koordinatensystem) haben. Andere Beschränkungen für die
Elemente einer GeometryCollection
gibt es
nicht, auch wenn die in den folgenden Abschnitten vorgestellten
Unterklassen von GeometryCollection
nicht
alles aufnehmen. Folgende Einschränkungen können für Mitglieder
dieser Klasse gelten:
Einschränkung des Elementtyps (so kann zum Beispiel ein
MultiPoint
nur
Point
-Elemente enthalten)
Einschränkung der Dimensionen
Einschränkung der räumlichen Überschneidung von Elementen
Ein MultiPoint
ist eine Ansammlung von
Point
-Geometrien. Die Punkte sind nicht
verbunden oder geordnet.
Beispiele für
MultiPoint
Auf einer Weltkarte könnte ein
MultiPoint
eine Kette kleiner Inseln
darstellen.
Auf einem Stadtplan könnte ein
MultiPoint
Fahrkartenverkaufsstellen
darstellen.
Eigenschaften von
MultiPoint
Ein MultiPoint
ist eine nulldimensionale
Geometrie.
Ein MultiPoint
ist einfach, wenn keine
zwei seiner Point
-Werte gleich sind
(dieselben Koordinatenwerte haben).
Die Grenze eines MultiPoint
ist die leere
Menge.
Eine MultiCurve
ist eine Ansammlung von
Curve
-Geometrien.
MultiCurve
ist eine nichtinstanziierbare
Klasse.
Eigenschaften von
MultiCurve
Eine MultiCurve
ist eine eindimensionale
Geometrie.
Eine MultiCurve
ist genau dann einfach,
wenn alle ihre Elemente einfach sind. Die einzigen
Überschneidungen von zwei Elementen können an Punkten
auftreten, die auf den Grenzen beider Elemente liegen.
Eine MultiCurve
-Grenze erhalten Sie durch
Anwendung der „Mod 2 Union Rule“ (auch
„Ungleich-Gleich-Regel“ genannt): Ein Punkt
liegt auf der Grenze einer MultiCurve
,
wenn er auf den Grenzen einer ungeraden Anzahl von
MultiCurve
-Elementen liegt.
Eine MultiCurve
ist geschlossen, wenn
alle ihre Elemente geschlossen sind.
Die Grenze einer geschlossenen MultiCurve
ist immer leer.
Ein MultiLineString
ist eine Ansammlung von
MultiCurve
-Geometrien, die aus
LineString
-Elementen besteht.
Beispiele für
MultiLineString
Auf einer Regionalkarte könnte ein
MultiLineString
ein Flusssystem oder ein
Straßennetz darstellen.
Eine MultiSurface
ist eine Ansammlung von
Geometrien, die aus Oberflächenelementen besteht.
MultiSurface
ist eine nichtinstanziierbare
Klasse. Ihre einzige instanziierbare Unterklasse ist
MultiPolygon
.
Zusicherungen von
MultiSurface
Der Innenbereich von zwei
MultiSurface
-Oberflächen darf sich nicht
überschneiden.
Die Grenzen von zwei
MultiSurface
-Elementen dürfen sich
höchstens an einer endlichen Anzahl von Punkten
überschneiden.
Ein MultiPolygon
ist ein
MultiSurface
-Objekt, das aus
Polygon
-Elementen besteht.
Beispiele für
MultiPolygon
Auf einer Regionalkarte könnte ein
MultiPolygon
eine Seenplatte darstellen.
Zusicherungen
fürMultiPolygon
Ein MultiPolygon
hat keine zwei
Polygon
-Elemente, deren Innenbereiche
sich überschneiden.
Ein MultiPolygon
hat keine zwei
Polygon
-Elemente, die sich überschneiden
(diese Überschneidung wurde auch bereits durch die vorige
Zusicherung untersagt) oder sich an einer unendlichen Anzahl
von Punkten berühren.
Ein MultiPolygon
darf keine geschnittenen
Linien, Zacken oder Lücken haben. Ein
MultiPolygon
ist eine regelmäßige,
geschlossene Punktmenge.
Ein MultiPolygon
mit mehreren
Polygon
en hat einen unzusammenhängenden
Innenbereich. Die Anzahl der zusammenhängenden Bestandteile
des Innenbereichs eines MultiPolygon
ist
gleich der Anzahl seiner Polygon
e.
Eigenschaften von
MultiPolygon
Ein MultiPolygon
ist eine
zweidimensionale Geometrie.
Die Grenze eines MultiPolygon
besteht aus
einer Menge von geschlossenen Kurven
(LineString
-Werten), die den Grenzen
seiner Polygon
-Elemente entsprechen.
Jede Curve
auf der Grenze des
MultiPolygon
liegt auf der Grenze von
genau einem Polygon
-Element.
Jede Curve
auf der Grenze eines
Polygon
-Elements liegt auf der Grenze des
MultiPolygon
.
Dieser Abschnitt beschreibt die raumbezogenen Standarddatenformate, mit denen Geometrieobjekte in Datenbankanfragen dargestellt werden. Diese sind:
Well-Known Text(WKT)-Format
Well-Known Binary(WKB)-Format
Intern speichert MySQL Geometriewerte in einem Format, das weder WKT noch WKB gleicht.
Die Well-Known Text(WKT)-Darstellung von Geometrien wurde geschaffen, um Geometriedaten in ASCII-Format austauschen zu können.
Beispiele für WKT-Darstellung von Geometrieobjekten:
Ein Point
:
POINT(15 20)
Beachten Sie, dass Punktkoordinaten ohne Komma dazwischen angegeben werden.
Ein LineString
mit vier Punkten:
LINESTRING(0 0, 10 10, 20 25, 50 60)
Beachten Sie, dass zwischen den Punktkoordinatenpaaren jeweils ein Komma steht.
Ein Polygon
mit einem äußeren und einem
inneren Ring:
POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))
Ein MultiPoint
mit drei
Point
-Werten:
MULTIPOINT(0 0, 20 20, 60 60)
Ein MultiLineString
mit zwei
LineString
-Werten:
MULTILINESTRING((10 10, 20 20), (15 15, 30 15))
Ein MultiPolygon
mit zwei
Polygon
-Werten:
MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0)),((5 5,7 5,7 7,5 7, 5 5)))
Eine GeometryCollection
, die aus zwei
Point
-Werten und einem
LineString
besteht:
GEOMETRYCOLLECTION(POINT(10 10), POINT(30 30), LINESTRING(15 15, 20 20))
Eine Backus-Naur-Grammatik mit den formalen Produktionsregeln zum Schreiben von WKT-Werten finden Sie in der OpenGIS-Spezifikation, auf die zu Beginn dieses Kapitels bereits verwiesen wurde.
Die Well-Known Binary(WKB)-Darstellung für Geometriewerte ist in der OpenGIS-Spezifikation sowie im ISO-Standard SQL/MM Part 3: Spatial definiert.
Mit der WKB-Darstellung werden Geometriedaten als Binärströme
übermittelt. Diese sind BLOB
-Werte, die
geometrische WKB-Informationen enthalten.
WKB verwendet Ein-Byte-Integer ohne Vorzeichen, Vier-Byte-Integer ohne Vorzeichen und Acht-Byte-Zahlen mit doppelter Genauigkeit (IEEE 754 format). Ein Byte sind acht Bits.
So besteht beispielsweise ein WKB-Wert, der POINT(1
1)
darstellt, aus der folgenden Reihe von 21 Byte
(hier jeweils durch zwei Hexadezimalziffern dargestellt):
0101000000000000000000F03F000000000000F03F
Diese Folge lässt sich in folgende Bestandteile zerlegen:
Byte order : 01 WKB type : 01000000 X : 000000000000F03F Y : 000000000000F03F
Die Bestandteile werden folgendermaßen dargestellt:
Die Byte-Reihenfolge kann 0 (Little-Endian-Speicherung) oder 1 (Big-Endian-Speicherung) sein. Diese Byte-Reihenfolgen bezeichnet man auch als Network Data Representation (NDR) bzw. External Data Representation (XDR).
Der WKB-Typ ist ein Code, der den Geometrietyp angibt. Seine
Werte von 1 bis 7 bedeuten Point
,
LineString
, Polygon
,
MultiPoint
,
MultiLineString
,
MultiPolygon
und
GeometryCollection
.
Ein Point
-Wert hat x- und y-Koordinaten,
die jeweils als Wert mit doppelter Genauigkeit dargestellt
sind.
Die WKB-Werte für komplexere Geometriewerte werden durch komplexere Datenstrukturen dargestellt. Diese sind in der OpenGIS-Spezifikation genauer beschrieben.
Der folgende Abschnitt beschreibt die Datentypen für raumbezogene Daten in MySQL und die Funktionen zur Erstellung und Abfrage raumbezogener Werte.
Die Datentypen von MySQL entsprechen den Klassen von OpenGIS. Einige dieser Typen speichern einzelne Geometriewerte:
GEOMETRY
POINT
LINESTRING
POLYGON
GEOMETRY
kann Geometriewerte jeden Typs
speichern. Die anderen Einzelwerttypen
(POINT
, LINESTRING
und
POLYGON
) können nur Werte eines bestimmten
Geometrietyps aufnehmen.
Die anderen Datentypen speichern Sammlungen von Werten:
MULTIPOINT
MULTILINESTRING
MULTIPOLYGON
GEOMETRYCOLLECTION
GEOMETRYCOLLECTION
kann eine Ansammlung von
Objekten beliebigen Typs speichern. Die anderen Collection-Typen
(MULTIPOINT
,
MULTILINESTRING
,
MULTIPOLYGON
und
GEOMETRYCOLLECTION
) können nur Werte eines
bestimmten Geometrietyps aufnehmen.
Dieser Abschnitt beschreibt, wie raumbezogene Werte mithilfe der Well-Known Text- und Well-Known Binary-Funktionen des OpenGIS-Standards und mit MySQL-spezifischen Funktionen erzeugt werden.
MySQL stellt eine Reihe von Funktionen zur Verfügung, die als Eingabeparameter eine Well-Known Text-Darstellung und optional einen Georeferenzsystembezeichner (Spatial Reference System Identifier, SRID) annehmen und die entsprechende Geometrie zurückliefern.
GeomFromText()
nimmt einen WKT eines
beliebigen Geometrietyps als erstes Argument entgegen. Eine
Implementierung stellt auch typspezifische
Konstruktorfunktionen zur Erzeugung von Geometriewerten jedes
Geometrietyps zur Verfügung.
GeomCollFromText(
,
wkt
[,srid
])GeometryCollectionFromText(
wkt
[,srid
])
Erzeugt einen GEOMETRYCOLLECTION
-Wert
anhand seiner WKT-Darstellung und seines SRID.
GeomFromText(
,
wkt
[,srid
])GeometryFromText(
wkt
[,srid
])
Erzeugt einen Geometriewert irgendeines Typs anhand seiner WKT-Darstellung und seines SRID.
LineFromText(
,
wkt
[,srid
])LineStringFromText(
wkt
[,srid
])
Erzeugt einen LINESTRING
-Wert anhand
seiner WKT-Darstellung und seines SRID.
MLineFromText(
,
wkt
[,srid
])MultiLineStringFromText(
wkt
[,srid
])
Erzeugt einen MULTILINESTRING
-Wert
anhand seiner WKT-Darstellung und seines SRID.
MPointFromText(
,
wkt
[,srid
])MultiPointFromText(
wkt
[,srid
])
Erzeugt einen MULTIPOINT
-Wert anhand
seiner WKT-Darstellung und seines SRID.
MPolyFromText(
,
wkt
[,srid
])MultiPolygonFromText(
wkt
[,srid
])
Erzeugt einen MULTIPOLYGON
-Wert anhand
seiner WKT-Darstellung und seines SRID.
Erzeugt einen POINT
-Wert anhand seiner
WKT-Darstellung und seines SRID.
PolyFromText(
,
wkt
[,srid
])PolygonFromText(
wkt
[,srid
])
Erzeugt einen POLYGON
-Wert anhand
seiner WKT-Darstellung und seines SRID.
Die OpenGIS-Spezifikation definiert auch die folgenden
optionalen Funktionen, die MySQL nicht implementiert. Diese
Funktionen erzeugen Polygon
- oder
MultiPolygon
-Werte anhand der
WKT-Darstellung einer Sammlung von Ringen oder geschlossenen
LineString
-Werten. Diese Werte können sich
schneiden.
Erzeugt einen MultiPolygon
-Wert aus
einem MultiLineString
-Wert im
WKT-Format, der eine beliebige Sammlung geschlossener
LineString
-Werte enthält.
Erzeugt einen Polygon
-Wert aus einem
MultiLineString
-Wert im WKT-Format, der
eine beliebige Sammlung geschlossener
LineString
-Werte enthält.
MySQL kennt Funktionen, die als Eingabeparameter einen
BLOB
annehmen, welcher eine Well-Known
Binary-Darstellung und optional auch einen
Georeferenzsystembezeichner (SRID) entgegennehmen. Sie geben
die entsprechende Geometrie zurück.
GeomFromWKB()
nimmt eine WKB eines
beliebigen Geometrietyps als erstes Argument entgegen. Es gibt
auch eine Implementierung für typspezifische
Konstruktionsfunktionen, die Geometriewerte der einzelnen
Geometrietypen erzeugen.
GeomCollFromWKB(
,
wkb
[,srid
])GeometryCollectionFromWKB(
wkb
[,srid
])
Erzeugt einen GEOMETRYCOLLECTION
-Wert
anhand seiner WKB-Darstellung und seines SRID.
GeomFromWKB(
,
wkb
[,srid
])GeometryFromWKB(
wkb
[,srid
])
Erzeugt einen Geometriewert beliebigen Typs anhand seiner WKB-Darstellung und seines SRID.
LineFromWKB(
,
wkb
[,srid
])LineStringFromWKB(
wkb
[,srid
])
Erzeugt einen LINESTRING
-Wert anhand
seiner WKB-Darstellung und seines SRID.
MLineFromWKB(
,
wkb
[,srid
])MultiLineStringFromWKB(
wkb
[,srid
])
Erzeugt einen MULTILINESTRING
-Wert
anhand seiner WKB-Darstellung und seines SRID.
MPointFromWKB(
,
wkb
[,srid
])MultiPointFromWKB(
wkb
[,srid
])
Erzeugt einen MULTIPOINT
-Wert anhand
seiner WKB-Darstellung und seines SRID.
MPolyFromWKB(
,
wkb
[,srid
])MultiPolygonFromWKB(
wkb
[,srid
])
Erzeugt einen MULTIPOLYGON
-Wert anhand
seiner WKB-Darstellung und seines SRID.
Erzeugt einen POINT
-Wert anhand seiner
WKB-Darstellung und seines SRID.
PolyFromWKB(
,
wkb
[,srid
])PolygonFromWKB(
wkb
[,srid
])
Erzeugt einen POLYGON
-Wert anhand
seiner WKB-Darstellung und seines SRID.
Die OpenGIS-Spezifikation beschreibt überdies optionale
Funktionen zur Erstellung von Polygon
- oder
MultiPolygon
-Werten anhand der
WKB-Darstellung einer Ansammlung von Ringen oder geschlossenen
LineString
-Werten. Diese Werte dürfen sich
schneiden. MySQL implementiert diese Funktionen nicht:
Erzeugt einen MultiPolygon
-Wert aus
einem MultiLineString
-Wert im
WKB-Format, der eine willkürliche Sammlung geschlossener
LineString
-Werte enthält.
Erzeugt einen Polygon
-Wert aus einem
MultiLineString
-Wert im WKB-Format, der
eine willkürliche Sammlung geschlossener
LineString
-Werte enthält.
MySQL stellt einige nichtstandardmäßige Funktionen zur
Erstellung von WKB-Darstellungen aus Geometriewerten zur
Vefügung. Die Funktionen in diesem Abschnitt sind
MySQL-Erweiterungen zur OpenGIS-Spezifikation. Die Ergebnisse
dieser Funktionen sind BLOB
-Werte, die
WKB-Darstellungen von Geometriewerten ohne SRID enthalten. Die
Ergebnisse dieser Funktionen lassen sich als erstes Argument
einer beliebigen Funktion der Funktionsfamilie
GeomFromWKB()
einsetzen.
Erzeugt eine WKB-GeometryCollection
.
Ist eines der Argumente keine wohlgeformte WKB-Darstellung
einer Geometrie, ist der Rückgabewert
NULL
.
Erzeugt einen WKB-LineString
-Wert aus
mehreren WKB-Point
-Argumenten. Ist
eines der Argumente kein WKB-Point
, ist
der Rückgabewert NULL
. Ist die Anzahl
der Point
-Argumente kleiner als zwei,
ist der Rückgabewert NULL
.
Erzeugt einen WKB-MultiLineString
-Wert
aus WKB-LineString
-Argumenten. Ist
eines der Argumente kein
WKB-LineString
, ist der Rückgabewert
NULL
.
Erzeugt einen WKB-MultiPoint
-Wert aus
WKB-Point
-Argumenten. Ist eines der
Argumente kein WKB-Point
, ist der
Rückgabewert NULL
.
Erzeugt einen WKB-MultiPolygon
-Wert aus
einer Menge von WKB-Polygon
-Argumenten.
Ist eines der Argumente kein
WKB-Polygon
, ist der Rückgabewert
NULL
.
Erzeugt einen WKB-Point
anhand seiner
Koordinaten.
Erzeugt einen WKB-Polygon
-Wert aus
einer Anzahl von
WKB-LineString
-Argumenten. Wenn eines
der Argumente nicht die WKB-Darstellung eines
LinearRing
s ist (d. h. kein
geschlossener und einfacher
LineString
), dann ist der Rückgabewert
NULL
.
MySQL kennt eine standardisierte Möglichkeit, raumbezogene
Spalten für Geometrietypen anzulegen, beispielsweise mit
CREATE TABLE
oder ALTER
TABLE
. Gegenwärtig werden raumbezogene Spalten für
MyISAM
-, InnoDB
-,
NDB
-, BDB
- und
ARCHIVE
-Tabellen unterstützt. Bitte lesen
Sie auch die Anmerkungen über raumbezogene Indizes unter
Abschnitt 18.6.1, „Erzeugung raumbezogener Indizes“.
Um eine Tabelle mit einer raumbezogenen Spalte anzulegen,
verwenden Sie die CREATE TABLE
-Anweisung:
CREATE TABLE geom (g GEOMETRY);
Mit ALTER TABLE
können Sie raumbezogene
Spalten in eine vorhandene Tabelle einfügen oder aus ihr
löschen:
ALTER TABLE geom ADD pt POINT; ALTER TABLE geom DROP pt;
Nachdem Sie raumbezogene Spalten eingerichtet haben, können Sie raumbezogene Daten hineinschreiben.
Die Werte sollten in einem internen Geometrieformat gespeichert werden, aber sie können aus dem Well-Known Text(WKT)- oder Well-Known Binary(WKB)-Format in dieses Format konvertiert werden. Die folgenden Beispiele zeigen, wie man Geometriewerte in eine Tabelle einfügt, indem man WKT-Werte in ein internes Geometrieformat konvertiert:
Die Konvertierung wird direkt in der
INSERT
-Anweisung ausgeführt:
INSERT INTO geom VALUES (GeomFromText('POINT(1 1)')); SET @g = 'POINT(1 1)'; INSERT INTO geom VALUES (GeomFromText(@g));
Die Konvertierung findet vor dem INSERT
statt:
SET @g = GeomFromText('POINT(1 1)'); INSERT INTO geom VALUES (@g);
Die folgenden Beispiele fügen komplexere Geometrien in eine Tabelle ein:
SET @g = 'LINESTRING(0 0,1 1,2 2)'; INSERT INTO geom VALUES (GeomFromText(@g)); SET @g = 'POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))'; INSERT INTO geom VALUES (GeomFromText(@g)); SET @g = 'GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(0 0,1 1,2 2,3 3,4 4))'; INSERT INTO geom VALUES (GeomFromText(@g));
In diesen Beispielen wurden die Geometriewerte immer mit
GeomFromText()
erzeugt. Sie können jedoch
auch typspezifische Funktionen benutzen:
SET @g = 'POINT(1 1)'; INSERT INTO geom VALUES (PointFromText(@g)); SET @g = 'LINESTRING(0 0,1 1,2 2)'; INSERT INTO geom VALUES (LineStringFromText(@g)); SET @g = 'POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))'; INSERT INTO geom VALUES (PolygonFromText(@g)); SET @g = 'GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(0 0,1 1,2 2,3 3,4 4))'; INSERT INTO geom VALUES (GeomCollFromText(@g));
Wenn eine Clientanwendung WKB-Darstellungen von Geometriewerten benutzen will, ist sie selbst dafür verantwortlich, wohlgeformte WKB-Daten in Anfragen an den Server zu senden. Diese Anforderung lässt sich allerdings auf mehrere Arten erfüllen. Zum Beispiel:
Indem man einen POINT(1 1)
-Wert mit der
Syntax eines Hexadezimal-Literals sendet:
mysql>INSERT INTO geom VALUES
->(GeomFromWKB(0x0101000000000000000000F03F000000000000F03F));
Eine ODBC-Anwendung kann eine WKB-Darstellung senden, indem
sie sie an einen Platzhalter mit einem Argument vom Typ
BLOB
bindet:
INSERT INTO geom VALUES (GeomFromWKB(?))
Andere Programmierschnittstellen können ähnliche Platzhaltermechanismen zur Verfügung stellen.
In einem C-Programm können Sie einen Binärwert durch
mysql_real_escape_string()
mit
Escape-Zeichen versehen und das Ergebnis in einen
Abfragestring laden, der an den Server geschickt wird. Siehe
hierzu Abschnitt 24.2.3.52, „mysql_real_escape_string()
“.
In einer Tabelle gespeicherte Geometriewerte können im internen Format abgefragt werden. Sie können sie jedoch auch in das WKT- oder WKB-Format konvertieren.
Raumbezogene Daten im internen Format abrufen:
Der Abruf von Geometriewerten im internen Format kann nützlich sein, wenn diese Daten zwischen Tabellen übertragen werden sollen:
CREATE TABLE geom2 (g GEOMETRY) SELECT g FROM geom;
Raumbezogene Daten im WKT-Format abrufen:
Die Funktion AsText()
konvertiert eine
Geometrie aus einem internen Format in einen WKT-String.
SELECT AsText(g) FROM geom;
Raumbezogene Daten im WKB-Format abrufen:
Die Funktion AsBinary()
konvertiert eine
Geometrie aus dem internen Format in einen
BLOB
, der den WKB-Wert enthält.
SELECT AsBinary(g) FROM geom;
Geometry
-FunktionenNachdem Sie die raumbezogenen Spalten mit Werten gefüllt haben, können diese abgefragt und analysiert werden. MySQL kennt eine Reihe von Funktionen, um diverse Operationen auf raumbezogenen Daten durchzuführen. Diese Funktionen lassen sich nach den jeweiligen Operationen, die sie ausführen, in vier große Kategorien einteilen:
Funktionen, die Geometrien zwischen verschiedenen Formaten konvertieren
Funktionen, die Zugriff auf qualitative oder quantitative Eigenschaften einer Geometrie geben
Funktionen, die Beziehungen zwischen zwei Geometrien beschreiben
Funktionen, die aus vorhandenen Geometrien neue erzeugen
Funktionen zur Analyse raumbezogener Daten können in vielen Zusammenhängen eingesetzt werden:
in einem interaktiven SQL-Programm wie beispielsweise mysql oder MySQL Query Browser
in Anwendungsprogrammen, die in irgendeiner Sprache mit MySQL-Client-API geschrieben sind
MySQL unterstützt die folgenden Funktionen zur Konvertierung von Geometriewerten zwischen einem internen Format und dem WKT- oder WKB-Format:
Konvertiert einen Wert aus einem internen Geometrieformat in seine WKB-Darstellung und gibt das binäre Ergebnis zurück.
SELECT AsBinary(g) FROM geom;
Konvertiert einen Wert aus einem internen Geometrieformat in seine WKT-Darstellung und gibt den Ergebnisstring zurück.
mysql>SET @g = 'LineString(1 1,2 2,3 3)';
mysql>SELECT AsText(GeomFromText(@g));
+--------------------------+ | AsText(GeomFromText(@g)) | +--------------------------+ | LINESTRING(1 1,2 2,3 3) | +--------------------------+
Konvertiert einen String-Wert aus seiner WKT-Darstellung in
ein internes Geometrieformat und gibt das Ergebnis zurück.
Es werden auch einige typspezifische Funktionen
unterstützt, wie beispielsweise
PointFromText()
und
LineFromText()
. Siehe
Abschnitt 18.4.2.1, „Erzeugung von Geometriewerten mit WKT-Funktionen“.
Konvertiert einen Binärwert von seiner WKB-Darstellung in
ein internes Geometrieformat und gibt das Ergebnis zurück.
Es werden auch einige typspezifische Funktionen
unterstützt, wie beispielsweise
PointFromWKB()
und
LineFromWKB()
. Siehe
Abschnitt 18.4.2.2, „Erzeugung von Geometriewerten mit WKB-Funktionen“.
Jede Funktion dieser Gruppe nimmt einen Geometriewert als
Argument entgegen und gibt eine quantitative oder qualitative
Eigenschaft der Geometrie zurück. Manche Funktionen schränken
den Typ ihres Arguments ein. Solche Funktionen geben
NULL
zurück, wenn das Argument den
verkehrten Geometrietyp hat. So liefert beispielsweise
Area()
den Wert NULL
, wenn
der Objekttyp weder Polygon
noch
MultiPolygon
ist.
Die im vorliegenden Abschnitt aufgeführten Funktionen schränken den Typ ihres Arguments nicht ein. Sie nehmen Geometriewerte jedes Typs entgegen.
Gibt die inhärente Dimension des Geometriewerts
g
zurück. Das Ergebnis kann
–1, 0, 1 oder 2 sein. Was diese Werte bedeuten,
lesen Sie in Abschnitt 18.2.2, „Die Klasse Geometry
“.
mysql> SELECT Dimension(GeomFromText('LineString(1 1,2 2)'));
+------------------------------------------------+
| Dimension(GeomFromText('LineString(1 1,2 2)')) |
+------------------------------------------------+
| 1 |
+------------------------------------------------+
Gibt das Minimum Bounding Rectangle (MBR) des
Geometriewerts g
zurück. Das
Ergebnis wird als Polygon
-Wert
geliefert.
Das Polygon ist durch die Eckpunkte seines Begrenzungskastens definiert:
POLYGON((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))
mysql> SELECT AsText(Envelope(GeomFromText('LineString(1 1,2 2)')));
+-------------------------------------------------------+
| AsText(Envelope(GeomFromText('LineString(1 1,2 2)'))) |
+-------------------------------------------------------+
| POLYGON((1 1,2 1,2 2,1 2,1 1)) |
+-------------------------------------------------------+
Liefert den Namen des Geometrietyps, zu welchem das
betreffende Geometrieobjekt g
gehört, als String zurück. Es ist der Name einer
instanziierbaren Unterklasse von
Geometry
.
mysql> SELECT GeometryType(GeomFromText('POINT(1 1)'));
+------------------------------------------+
| GeometryType(GeomFromText('POINT(1 1)')) |
+------------------------------------------+
| POINT |
+------------------------------------------+
Liefert die Integer-Kennung des Georeferenzsystems des
Geometriewerts g
.
In MySQL ist der SRID-Wert ein einfacher Integer, der mit dem Geometriewert verbunden ist. Alle Berechnungen werden auf der Grundlage der euklidischen (planaren) Geometrie ausgeführt.
mysql> SELECT SRID(GeomFromText('LineString(1 1,2 2)',101));
+-----------------------------------------------+
| SRID(GeomFromText('LineString(1 1,2 2)',101)) |
+-----------------------------------------------+
| 101 |
+-----------------------------------------------+
Die OpenGIS-Spezifikation definiert außerdem folgende Funktionen, die von MySQL nicht implementiert werden:
Gibt eine Geometrie zurück, die der Abschluss der
kombinatorischen Grenze des Geometriewerts
g
ist.
Liefert 1, wenn der Geometriewert
g
die leere Geometrie ist, 0,
wenn er nichtleer ist, und –1, wenn das Argument
NULL
ist. Eine leere Geometrie ist die
leere Punktmenge.
Zurzeit ist diese noch ein Platzhalter und sollte nicht benutzt werden. Wenn sie implementiert ist, wird sie das im nächsten Absatz beschriebene Verhalten haben.
Liefert 1, wenn der Geometriewert
g
keine anormalen geometrischen
Punkte hat, indem er sich beispielsweise selbst schneidet
oder tangiert. IsSimple()
gibt 0
zurück, wenn das Argument nicht einfach ist, und
–1, wenn es NULL
ist.
In den Beschreibungen der instanziierbaren geometrischen Klassen weiter oben in diesem Kapitel werden auch die konkreten Bedingungen genannt, unter denen eine Instanz der betreffenden Klasse als nichteinfach gilt. (Siehe Abschnitt 18.2.1, „Hierarchie der Geometrieklassen“.)
Ein Point
besteht aus einer x- und einer
y-Koordinate, die Sie mit den folgenden Funktionen beschaffen
können:
Gibt die x-Koordinate des Punkts
p
als Zahl mit doppelter
Genauigkeit zurück.
mysql>SET @pt = 'Point(56.7 53.34)';
mysql>SELECT X(GeomFromText(@pt));
+----------------------+ | X(GeomFromText(@pt)) | +----------------------+ | 56.7 | +----------------------+
Gibt die y-Koordinate des Punkts
p
als Zahl mit doppelter
Genauigkeit zurück.
mysql>SET @pt = 'Point(56.7 53.34)';
mysql>SELECT Y(GeomFromText(@pt));
+----------------------+ | Y(GeomFromText(@pt)) | +----------------------+ | 53.34 | +----------------------+
Ein LineString
besteht aus
Point
-Werten. Sie können bestimmte Punkte
eines LineString
extrahieren, die Anzahl
seiner Punkte abfragen oder seine Länge ermitteln.
Gibt den Point
zurück, der der
Endpunkt des LineString
-Werts
ls
ist.
mysql>SET @ls = 'LineString(1 1,2 2,3 3)';
mysql>SELECT AsText(EndPoint(GeomFromText(@ls)));
+-------------------------------------+ | AsText(EndPoint(GeomFromText(@ls))) | +-------------------------------------+ | POINT(3 3) | +-------------------------------------+
Liefert die Länge des LineString
-Werts
ls
in seinem zugehörigen
Georeferenzsystem als Zahl mit doppelter Genauigkeit.
mysql>SET @ls = 'LineString(1 1,2 2,3 3)';
mysql>SELECT GLength(GeomFromText(@ls));
+----------------------------+ | GLength(GeomFromText(@ls)) | +----------------------------+ | 2.8284271247462 | +----------------------------+
Der Name der Funktion GLength()
ist ein
nichtstandardmäßiger Name. Sie entspricht der
OpenGIS-Funktion Length()
.
Liefert die Anzahl der Point
-Objekte im
LineString
-Wert
ls
.
mysql>SET @ls = 'LineString(1 1,2 2,3 3)';
mysql>SELECT NumPoints(GeomFromText(@ls));
+------------------------------+ | NumPoints(GeomFromText(@ls)) | +------------------------------+ | 3 | +------------------------------+
Liefert den N
-ten
Point
im
Linestring
-Wert
ls
. Die Punkte werden beginnend
mit 1 nummeriert.
mysql>SET @ls = 'LineString(1 1,2 2,3 3)';
mysql>SELECT AsText(PointN(GeomFromText(@ls),2));
+-------------------------------------+ | AsText(PointN(GeomFromText(@ls),2)) | +-------------------------------------+ | POINT(2 2) | +-------------------------------------+
Gibt den Point
zurück, der der
Anfangspunkt des LineString
-Werts
ls
ist.
mysql>SET @ls = 'LineString(1 1,2 2,3 3)';
mysql>SELECT AsText(StartPoint(GeomFromText(@ls)));
+---------------------------------------+ | AsText(StartPoint(GeomFromText(@ls))) | +---------------------------------------+ | POINT(1 1) | +---------------------------------------+
Die OpenGIS-Spezifikation definiert darüber hinaus die folgende von MySQL nicht implementierte Funktion:
Gibt die Länge des
MultiLineString
-Werts
mls
als Zahl mit doppelter
Genauigkeit zurück. Die Länge von
mls
ist gleich der Summe der
Längen seiner Elemente.
mysql>SET @mls = 'MultiLineString((1 1,2 2,3 3),(4 4,5 5))';
mysql>SELECT GLength(GeomFromText(@mls));
+-----------------------------+ | GLength(GeomFromText(@mls)) | +-----------------------------+ | 4.2426406871193 | +-----------------------------+
GLength()
ist ein
nichtstandardmäßiger Name. Die Funktion entspricht der
OpenGIS-Funktion Length()
.
Gibt 1 zurück, wenn der
MultiLineString
-Wert
mls
geschlossen ist (d. h.,
wenn StartPoint()
und
EndPoint()
für jeden
LineString
in
mls
gleich sind). Gibt 0
zurück, wenn mls
nicht
geschlossen ist, und –1, wenn er
NULL
ist.
mysql>SET @mls = 'MultiLineString((1 1,2 2,3 3),(4 4,5 5))';
mysql>SELECT IsClosed(GeomFromText(@mls));
+------------------------------+ | IsClosed(GeomFromText(@mls)) | +------------------------------+ | 0 | +------------------------------+
Gibt die Fläche des Polygon
-Werts
poly
, gemessen in seinem
Georeferenzsystem, als Zahl mit doppelter Genauigkeit
zurück.
mysql>SET @poly = 'Polygon((0 0,0 3,3 0,0 0),(1 1,1 2,2 1,1 1))';
mysql>SELECT Area(GeomFromText(@poly));
+---------------------------+ | Area(GeomFromText(@poly)) | +---------------------------+ | 4 | +---------------------------+
Gibt den äußeren Ring des
Polygon
-Werts
poly
als
LineString
zurück.
mysql>SET @poly =
->'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))';
mysql>SELECT AsText(ExteriorRing(GeomFromText(@poly)));
+-------------------------------------------+ | AsText(ExteriorRing(GeomFromText(@poly))) | +-------------------------------------------+ | LINESTRING(0 0,0 3,3 3,3 0,0 0) | +-------------------------------------------+
Gibt den N
-ten inneren Ring des
Polygon
-Werts
poly
als
LineString
zurück. Die Ringe werden
beginnend mit 1 nummeriert.
mysql>SET @poly =
->'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))';
mysql>SELECT AsText(InteriorRingN(GeomFromText(@poly),1));
+----------------------------------------------+ | AsText(InteriorRingN(GeomFromText(@poly),1)) | +----------------------------------------------+ | LINESTRING(1 1,1 2,2 2,2 1,1 1) | +----------------------------------------------+
Gibt die Anzahl der inneren Ringe des
Polygon
-Werts
poly
zurück.
mysql>SET @poly =
->'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))';
mysql>SELECT NumInteriorRings(GeomFromText(@poly));
+---------------------------------------+ | NumInteriorRings(GeomFromText(@poly)) | +---------------------------------------+ | 1 | +---------------------------------------+
Gibt die Fläche des MultiPolygon
-Werts
mpoly
, gemessen in seinem
Georeferenzsystem, als Zahl mit doppelter Genauigkeit
zurück.
mysql>SET @mpoly =
->'MultiPolygon(((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1)))';
mysql>SELECT Area(GeomFromText(@mpoly));
+----------------------------+ | Area(GeomFromText(@mpoly)) | +----------------------------+ | 8 | +----------------------------+
Die OpenGIS-Spezifikation definiert auch die folgenden von MySQL nicht implementierten Funktionen:
Gibt die N
-te Geometrie im
GeometryCollection
-Wert des
gc
-Werts zurück. Die Geometrien
werden beginnend mit 1 nummeriert.
mysql>SET @gc = 'GeometryCollection(Point(1 1),LineString(2 2, 3 3))';
mysql>SELECT AsText(GeometryN(GeomFromText(@gc),1));
+----------------------------------------+ | AsText(GeometryN(GeomFromText(@gc),1)) | +----------------------------------------+ | POINT(1 1) | +----------------------------------------+
Gibt die Anzahl der Geometrien im
GeometryCollection
-Wert
gc
zurück.
mysql>SET @gc = 'GeometryCollection(Point(1 1),LineString(2 2, 3 3))';
mysql>SELECT NumGeometries(GeomFromText(@gc));
+----------------------------------+ | NumGeometries(GeomFromText(@gc)) | +----------------------------------+ | 2 | +----------------------------------+
In Abschnitt 18.5.2, „Geometry
-Funktionen“, werden
mehrere Funktionen beschrieben, die aus vorhandenen Geometrien
neue erstellen. Dort können Sie die Beschreibungen folgender
Funktionen nachlesen:
Envelope(
g
)
StartPoint(
ls
)
EndPoint(
ls
)
PointN(
ls
,N
)
ExteriorRing(
poly
)
InteriorRingN(
poly
,N
)
GeometryN(
gc
,N
)
OpenGIS stellt auch noch einige weitere Funktionen vor, die Geometrien erzeugen können. Diese sind so entworfen, dass sie raumbezogene Operatoren implementieren.
Diese Funktionen sind in MySQL nicht implementiert, könnten aber in zukünftigen Releases einbezogen werden.
Gibt eine Geometrie zurück, die alle Punkte darstellt,
deren Abstand vom Geometriewert
g
kleiner oder gleich dem
Abstand von d
ist.
Gibt eine Geometrie zurück, die die konvexe Hülle des
Geometriewerts g
darstellt.
Gibt eine Geometrie zurück, die die Differenz zwischen
den Punktmengen der Geometriewerte
g1
und
g2
angibt.
Gibt eine Geometrie zurück, die die Schnittmenge der
Punktmengen der Geometriewerte
g1
und
g2
darstellt.
Gibt eine Geometrie zurück, die die symmetrische
Punktmengendifferenz zwischen den Geometriewerten
g1
und
g2
darstellt.
Gibt eine Geometrie zurück, die die Vereinigungsmenge der
Punktmengen der Geometriewerte
g1
und
g2
darstellt.
Die Funktionen in diesen Abschnitten nehmen zwei Geometrien als Eingabeparameter und liefern eine qualitative oder quantitative Beziehung zwischen diesen zurück.
MySQL kennt mehrere Funktionen, um Beziehungen zwischen den
kleinsten begrenzenden Rechtecken (Minimal Bounding Rectangles,
MBRs) zweier Geometrien g1
und
g2
zu testen. Der Rückgabewert 1 bedeutet
wahr (true) und 0 bedeutet falsch (false).
Gibt 1 oder 0 zurück, je nachdem, ob das Minimum Bounding
Rectangle von g1
das Minimum
Bounding Rectangle von g2
enthält oder nicht.
mysql>SET @g1 = GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))');
mysql>SET @g2 = GeomFromText('Point(1 1)');
mysql>SELECT MBRContains(@g1,@g2), MBRContains(@g2,@g1);
----------------------+----------------------+ | MBRContains(@g1,@g2) | MBRContains(@g2,@g1) | +----------------------+----------------------+ | 1 | 0 | +----------------------+----------------------+
Gibt 1 oder 0 zurück, je nachdem, ob die Minimum Bounding
Rectangles der beiden Geometrien
g1
und
g2
disjunkt sind (sich nicht
überschneiden) oder nicht.
Gibt 1 oder 0 zurück, je nachdem, ob die Minimum Bounding
Rectangles der beiden Geometrien
g1
und
g2
gleich sind oder nicht.
Gibt 1 oder 0 zurück, je nachdem, ob die Minimum Bounding
Rectangles der beiden Geometrien
g1
und
g2
sich schneiden oder nicht.
Gibt 1 oder 0 zurück, je nachdem, ob die Minimum Bounding
Rectangles der beiden Geometrien
g1
und
g2
sich überlappen oder nicht.
Gibt 1 oder 0 zurück, je nachdem, ob die Minimum Bounding
Rectangles der beiden Geometrien
g1
und
g2
sich berühren oder nicht.
Gibt 1 oder 0 zurück, je nachdem, ob das Minimum Bounding
Rectangle von g1
innerhalb des
Minimum Bounding Rectangles von
g2
liegt.
mysql>SET @g1 = GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))');
mysql>SET @g2 = GeomFromText('Polygon((0 0,0 5,5 5,5 0,0 0))');
mysql>SELECT MBRWithin(@g1,@g2), MBRWithin(@g2,@g1);
+--------------------+--------------------+ | MBRWithin(@g1,@g2) | MBRWithin(@g2,@g1) | +--------------------+--------------------+ | 1 | 0 | +--------------------+--------------------+
Die OpenGIS-Spezifikation definiert die folgenden Funktionen, um
die Beziehungen zwischen zwei Geometriewerten
g1
und g2
zu testen.
MySQL implementiert diese Funktionen zurzeit noch nicht
entsprechend der Spezifikation. Die, die implementiert werden,
geben dasselbe Ergebnis wie die entsprechenden MBR-basierten
Funktionen zurück. Dazu gehören neben
Distance()
und Related()
auch die anderen Funktionen der folgenden Liste.
Diese Funktionen könnten in zukünftigen Releases auch mit voller anstatt nur mit MBR-basierter Unterstützung für raumbezogene Analyse implementiert werden.
Der Rückgabewert 1 bedeutet wahr (true) und 0 bedeutet falsch (false).
Gibt 1 oder 0 zurück, je nachdem, ob
g1
g2
vollständig enthält oder nicht.
Gibt 1 zurück, wenn g1
g2
räumlich kreuzt. Gibt
NULL
zurück, wenn g1
ein Polygon
oder
MultiPolygon
ist oder wenn
g2
ein Point
oder ein MultiPoint
ist. Gibt ansonsten 0
zurück.
Mit räumlich kreuzen ist eine räumliche Beziehung zwischen zwei Geometrien gemeint, die folgende Eigenschaften besitzt:
Die beiden Geometrien schneiden sich.
Ihre Überschneidung hat eine Geometrie zum Ergebnis, deren Dimension um eins kleiner ist als die maximale Dimension der beiden Geometrien.
Ihre Schnittmenge ist mit keiner der beiden Geometrien identisch.
Gibt 1 oder 0 zurück, je nachdem, ob
g1
räumlich disjunkt von
g2
ist (sich nicht
überschneidet) oder nicht.
Liefert den kürzesten Abstand zwischen zwei Punkten der beiden Geometrien als Zahl mit doppelter Genauigkeit.
Gibt 1 oder 0 zurück, je nachdem, ob
g1
und
g2
räumlich gleich sind oder
nicht.
Gibt 1 oder 0 zurück, je nachdem, ob
g1
sich räumlich mit
g2
überschneidet oder nicht.
Gibt 1 oder 0 zurück, je nachdem, ob
g1
sich räumlich mit
g2
überlappt oder nicht. Von
räumlich überlappen spricht man, wenn
sich zwei Geometrien schneiden und ihre Schnittmenge eine
Geometrie ergibt, die nicht gleich einer der beiden
gegebenen Geometrien ist, aber dieselbe Dimension hat.
Gibt 1 oder 0 zurück, je nachdem, ob die räumliche
Beziehung, die durch
pattern_matrix
vorgegeben ist,
zwischen g1
und
g2
existiert oder nicht. Gibt
–1 zurück, wenn die Argumente NULL
sind. Die Mustermatrix
(pattern_matrix
) ist ein String.
Ihre Spezifikation wird hier notiert werden, wenn die
Funktion implementiert wurde.
Gibt 1 oder 0 zurück, je nachdem, ob
g1
g2
räumlich berührt oder nicht. Von einer
räumlichen Berührung zweier
Geometrien spricht man, wenn ihre Innenbereiche sich nicht
schneiden, aber die Grenze der einen entweder die Grenze
oder den Innenbereich der anderen schneidet.
Gibt 1 oder 0 zurück, je nachdem, ob
g1
räumlich innerhalb von
g2
liegt oder nicht.
Suchoperationen in nichtraumbezogenen Datenbanken lassen sich mit Indizes optimieren. Dies gilt ebenso für raumbezogene Datenbanken. Es wurden bereits viele mehrdimensionale Indexmethoden entworfen, um auch die Suche nach raumbezogenen Daten zu optimieren. Die typischsten Methoden sind:
Punktabfragen, die alle Objekte suchen, welche einen gegebenen Punkt enthalten.
Bereichsabfragen, die alle Objekte suchen, welche einen gegebenen Bereich überlappen.
MySQL verwendet R-Trees mit quadratischem Split zum Indizieren raumbezogener Spalten. Ein raumbezogener Index wird anhand des MBRs einer Geometrie erstellt. Für die meisten Geometrien ist das MBR das kleinste die Geometrie umschließende Rechteck. Für einen horizontalen oder vertikalen Linestring ist das MBR ein auf eine Linie zusammengeschnurrtes Rechteck. Für einen Punkt ist das MBR ein Rechteck, das auf den Punkt zusammengeschrumpft ist.
Es ist auch möglich, normale Indizes auf raumbezogenen Spalten
anzulegen. Hierzu müssen Sie einem (nichtraumbezogenen) Index auf
einer raumbezogenen Spalte (ausgenommen
POINT
-Spalten) ein Präfix geben.
MySQL kann raumbezogene Indizes mit einer ähnlichen Syntax
anlegen, wie sie auch für normale Indizes verwendet wird,
allerdings erweitert um das Schlüsselwort
SPATIAL
. Zurzeit müssen raumbezogene
Spalten, die indiziert werden, als NOT NULL
deklariert werden. Die folgenden Beispiele zeigen, wie man
raumbezogene Indizes anlegen kann:
Mit CREATE TABLE
:
CREATE TABLE geom (g GEOMETRY NOT NULL, SPATIAL INDEX(g));
Mit ALTER TABLE
:
ALTER TABLE geom ADD SPATIAL INDEX(g);
Mit CREATE INDEX
:
CREATE SPATIAL INDEX sp_index ON geom (g);
Auf MyISAM
-Tabellen legt SPATIAL
INDEX
einen R-Tree-Index an, aber auf Tabellen mit
anderen Speicher-Engines, die raumbezogene Indizierung
unterstützen, erzeugt SPATIAL INDEX
einen
B-Tree-Index. Ein B-Tree-Index auf raumbezogenen Werten ist
nützlich für das Nachschlagen konkreter Werte, aber nicht für
Bereichsscans.
Gelöscht werden raumbezogene Indizes mit ALTER
TABLE
oder DROP INDEX
:
Mit ALTER TABLE
:
ALTER TABLE geom DROP INDEX g;
Mit DROP INDEX
:
DROP INDEX sp_index ON geom;
Beispiel: Angenommen, eine Tabelle namens
geom
enthält mehr als 32.000 Geometrien, die
alle in der Spalte g
vom Typ
GEOMETRY
gespeichert sind. Die Tabelle hat
außerdem eine AUTO_INCREMENT
-Spalte namens
fid
zum Speichern der Objekt-IDs.
mysql>DESCRIBE geom;
+-------+----------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+----------+------+-----+---------+----------------+ | fid | int(11) | | PRI | NULL | auto_increment | | g | geometry | | | | | +-------+----------+------+-----+---------+----------------+ 2 rows in set (0.00 sec) mysql>SELECT COUNT(*) FROM geom;
+----------+ | count(*) | +----------+ | 32376 | +----------+ 1 row in set (0.00 sec)
Mti folgender Anweisung definieren Sie einen raumbezogenen Index
auf der Spalte g
:
mysql> ALTER TABLE geom ADD SPATIAL INDEX(g);
Query OK, 32376 rows affected (4.05 sec)
Records: 32376 Duplicates: 0 Warnings: 0
Der Optimierer untersucht, ob die verfügbaren raumbezogenen
Indizes für Suchoperationen im Rahmen von Anfragen zu
gebrauchen sind, die eine Funktion wie
MBRContains()
oder
MBRWithin()
in der
WHERE
-Klausel haben. Die folgende Anfrage
findet alle Objekte, die sich im gegebenen Rechteck befinden:
mysql>SET @poly =
->'Polygon((30000 15000,31000 15000,31000 16000,30000 16000,30000 15000))';
mysql>SELECT fid,AsText(g) FROM geom WHERE
->MBRContains(GeomFromText(@poly),g);
+-----+---------------------------------------------------------------+ | fid | AsText(g) | +-----+---------------------------------------------------------------+ | 21 | LINESTRING(30350.4 15828.8,30350.6 15845,30333.8 15845,30 ... | | 22 | LINESTRING(30350.6 15871.4,30350.6 15887.8,30334 15887.8, ... | | 23 | LINESTRING(30350.6 15914.2,30350.6 15930.4,30334 15930.4, ... | | 24 | LINESTRING(30290.2 15823,30290.2 15839.4,30273.4 15839.4, ... | | 25 | LINESTRING(30291.4 15866.2,30291.6 15882.4,30274.8 15882. ... | | 26 | LINESTRING(30291.6 15918.2,30291.6 15934.4,30275 15934.4, ... | | 249 | LINESTRING(30337.8 15938.6,30337.8 15946.8,30320.4 15946. ... | | 1 | LINESTRING(30250.4 15129.2,30248.8 15138.4,30238.2 15136. ... | | 2 | LINESTRING(30220.2 15122.8,30217.2 15137.8,30207.6 15136, ... | | 3 | LINESTRING(30179 15114.4,30176.6 15129.4,30167 15128,3016 ... | | 4 | LINESTRING(30155.2 15121.4,30140.4 15118.6,30142 15109,30 ... | | 5 | LINESTRING(30192.4 15085,30177.6 15082.2,30179.2 15072.4, ... | | 6 | LINESTRING(30244 15087,30229 15086.2,30229.4 15076.4,3024 ... | | 7 | LINESTRING(30200.6 15059.4,30185.6 15058.6,30186 15048.8, ... | | 10 | LINESTRING(30179.6 15017.8,30181 15002.8,30190.8 15003.6, ... | | 11 | LINESTRING(30154.2 15000.4,30168.6 15004.8,30166 15014.2, ... | | 13 | LINESTRING(30105 15065.8,30108.4 15050.8,30118 15053,3011 ... | | 154 | LINESTRING(30276.2 15143.8,30261.4 15141,30263 15131.4,30 ... | | 155 | LINESTRING(30269.8 15084,30269.4 15093.4,30258.6 15093,30 ... | | 157 | LINESTRING(30128.2 15011,30113.2 15010.2,30113.6 15000.4, ... | +-----+---------------------------------------------------------------+ 20 rows in set (0.00 sec)
Mit EXPLAIN
können Sie prüfen, wie diese
Anfrage ausgeführt wird (die Spalte id
wurde
entfernt, damit die Ausgabe besser auf die Seite passt):
mysql>SET @poly =
->'Polygon((30000 15000,31000 15000,31000 16000,30000 16000,30000 15000))';
mysql>EXPLAIN SELECT fid,AsText(g) FROM geom WHERE
->MBRContains(GeomFromText(@poly),g)\G
*************************** 1. row *************************** id: 1 select_type: SIMPLE table: geom type: range possible_keys: g key: g key_len: 32 ref: NULL rows: 50 Extra: Using where 1 row in set (0.00 sec)
So prüfen Sie, was ohne raumbezogenen Index passieren würde:
mysql>SET @poly =
->'Polygon((30000 15000,31000 15000,31000 16000,30000 16000,30000 15000))';
mysql>EXPLAIN SELECT fid,AsText(g) FROM g IGNORE INDEX (g) WHERE
->MBRContains(GeomFromText(@poly),g)\G
*************************** 1. row *************************** id: 1 select_type: SIMPLE table: geom type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 32376 Extra: Using where 1 row in set (0.00 sec)
Wenn Sie die SELECT
-Anweisung ohne den
raumbezogenen Index ausführen, erhalten Sie zwar dasselbe
Ergebnis, aber die Ausführungszeit verlängert sich von 0,00
auf 0,46 Sekunden:
mysql>SET @poly =
->'Polygon((30000 15000,31000 15000,31000 16000,30000 16000,30000 15000))';
mysql>SELECT fid,AsText(g) FROM geom IGNORE INDEX (g) WHERE
->MBRContains(GeomFromText(@poly),g);
+-----+---------------------------------------------------------------+ | fid | AsText(g) | +-----+---------------------------------------------------------------+ | 1 | LINESTRING(30250.4 15129.2,30248.8 15138.4,30238.2 15136. ... | | 2 | LINESTRING(30220.2 15122.8,30217.2 15137.8,30207.6 15136, ... | | 3 | LINESTRING(30179 15114.4,30176.6 15129.4,30167 15128,3016 ... | | 4 | LINESTRING(30155.2 15121.4,30140.4 15118.6,30142 15109,30 ... | | 5 | LINESTRING(30192.4 15085,30177.6 15082.2,30179.2 15072.4, ... | | 6 | LINESTRING(30244 15087,30229 15086.2,30229.4 15076.4,3024 ... | | 7 | LINESTRING(30200.6 15059.4,30185.6 15058.6,30186 15048.8, ... | | 10 | LINESTRING(30179.6 15017.8,30181 15002.8,30190.8 15003.6, ... | | 11 | LINESTRING(30154.2 15000.4,30168.6 15004.8,30166 15014.2, ... | | 13 | LINESTRING(30105 15065.8,30108.4 15050.8,30118 15053,3011 ... | | 21 | LINESTRING(30350.4 15828.8,30350.6 15845,30333.8 15845,30 ... | | 22 | LINESTRING(30350.6 15871.4,30350.6 15887.8,30334 15887.8, ... | | 23 | LINESTRING(30350.6 15914.2,30350.6 15930.4,30334 15930.4, ... | | 24 | LINESTRING(30290.2 15823,30290.2 15839.4,30273.4 15839.4, ... | | 25 | LINESTRING(30291.4 15866.2,30291.6 15882.4,30274.8 15882. ... | | 26 | LINESTRING(30291.6 15918.2,30291.6 15934.4,30275 15934.4, ... | | 154 | LINESTRING(30276.2 15143.8,30261.4 15141,30263 15131.4,30 ... | | 155 | LINESTRING(30269.8 15084,30269.4 15093.4,30258.6 15093,30 ... | | 157 | LINESTRING(30128.2 15011,30113.2 15010.2,30113.6 15000.4, ... | | 249 | LINESTRING(30337.8 15938.6,30337.8 15946.8,30320.4 15946. ... | +-----+---------------------------------------------------------------+ 20 rows in set (0.46 sec)
In künftigen Releases könnten raumbezogene Indizes vielleicht auch zur Optimierung anderer Funktionen genutzt werden. Siehe Abschnitt 18.5.4, „Funktionen zum Testen raumbezogener Beziehungen zwischen geometrischen Objekten“.
Folgende GIS-Features werden von MySQL noch nicht implementiert:
Zusätzliche Metadaten-Views
Die OpenGIS-Spezifikationen empfehlen mehrere zusätzliche
Views für Metadaten, beispielsweise eine System-View namens
GEOMETRY_COLUMNS
mit einer Beschreibung der
Geometriespalten, wobei für jede Geometriespalte der
Datenbank eine Zeile angezeigt wird.
Die OpenGIS-Funktion Length()
für
LineString
und
MultiLineString
muss in MySQL zurzeit noch
unter dem Namen GLength()
aufgerufen
werden.
Das Problem besteht darin, dass es eine SQL-Funktion namens
Length()
gibt, die die Länge von
String-Werten berechnet, und dass es manchmal nicht zu
unterscheiden ist, ob diese Funktion nun im Zusammenhang mit
Text oder mit raumbezogenen Daten aufgerufen wird. Wir werden
dies entweder auf irgendeine Weise lösen oder einen anderen
Namen für die Funktion finden.
Inhaltsverzeichnis
CREATE PROCEDURE
und CREATE
FUNCTION
ALTER PROCEDURE
und ALTER FUNCTION
DROP PROCEDURE
und DROP FUNCTION
CALL
-AnweisungBEGIN ... END
-Syntax für komplexe AnweisungenDECLARE
-AnweisungMySQL 5.1 kennt auch gespeicherte Routinen (Prozeduren und Funktionen). Eine gespeicherte Prozedur ist eine Menge von SQL-Anweisungen, die auf dem Server gespeichert werden kann. So müssen Clients nicht immer wieder die jeweiligen Einzelanweisungen ausführen, sondern können stattdessen die gespeicherte Prozedur aufrufen.
In folgenden Situationen sind gespeicherte Routinen besonders nützlich:
Wenn mehrere Clientanwendungen in verschiedenen Sprachen geschrieben sind oder auf verschiedenen Plattformen laufen, aber dieselben Datenbankoperationen ausführen müssen.
Wenn Sicherheit sehr wichtig ist. Banken verwenden zum Beispiel für alle häufigen Operationen gespeicherte Prozeduren und Funktionen. Das gewährleistet eine konsistente und sichere Umgebung sowie eine korrekte Protokollierung jeder einzelnen Operation. In einer solchen Umgebung haben Anwendungen und Benutzer keinen Direktzugriff auf die Datenbanktabellen, sondern können nur bestimmte gespeicherte Routinen ausführen.
Gespeicherte Routinen bieten eine bessere Leistung, da weniger Informationen zwischen Server und Client übermittelt werden müssen. Der Nachteil ist der, dass die Belastung des Datenbankservers steigt, weil mehr Arbeit auf der Serverseite und weniger Arbeit auf der Seite des Clients (der Anwendungen) erledigt werden muss. Dies müssen Sie berücksichtigen, wenn viele Clientcomputer (wie beispielsweise Webserver) von nur einem oder sehr wenigen Datenbankservern bedient werden.
Mit gespeicherten Routinen sind Funktionsbibliotheken im Datenbankserver möglich. Dieses Feature haben auch moderne Anwendungssprachen, die einen solchen Entwurf intern umsetzen (zum Beispiel durch Klassen). Auch jenseits von Datenbankanwendungen bringen diese Features der Anwendungssprachen dem Programmierer Vorteile.
MySQL verwendet die Syntax für gespeicherte Routinen gemäß dem SQL:2003-Standard, den auch DB2 von IBM nutzt.
Die Implementierung gespeicherter Routinen in MySQL ist noch nicht abgeschlossen. Unterstützt wird allein die in diesem Kapitel beschriebene Syntax. Beschränkungen und Erweiterungen werden an geeigneter Stelle geschildert. Eine weitergehende Behandlung der Restriktionen, die für die Verwendung gespeicherter Routinen gelten, finden Sie in Abschnitt I.1, „Beschränkungen bei gespeicherten Routinen und Triggern“.
Das Binärlogging für gespeicherte Routinen wird in Abschnitt 19.4, „Binärloggen gespeicherter Routinen und Trigger“ beschrieben.
Für gespeicherte Routinen muss die Tabelle
proc
in der mysql
-Datenbank
vorhanden sein. Diese Tabelle wird schon bei der
Installationsprozedur von MySQL 5.1 angelegt. Wenn
Sie von einer älteren Version auf MySQL 5.1
aufrüsten, achten Sie bitte darauf, Ihre Berechtigungstabellen zu
aktualisieren, damit die Tabelle proc
vorhanden
ist. Siehe auch Abschnitt 5.6, „mysql_fix_privilege_tables — Upgrade von MySQL-Systemtabellen“.
Nach Anweisungen, die gespeicherte Routinen erzeugen, ändern oder
löschen, bearbeitet der Server die Tabelle
mysql.proc
. Eine manuelle Manipulation dieser
Tabelle wird der Server nicht bemerken.
Im Berechtigungssystem von MySQL werden gespeicherte Routinen folgendermaßen behandelt:
Das CREATE ROUTINE
-Recht ist erforderlich,
um gespeicherte Routinen zu erzeugen.
Das ALTER ROUTINE
-Recht wird benötigt, um
gespeicherte Routinen zu ändern oder zu löschen. Dieses
Recht wird automatisch dem Erzeuger einer Routine erteilt.
Das EXECUTE
-Recht ist notwendig, um
gespeicherte Routinen auszuführen, wird aber ebenfalls dem
Erzeuger einer Routine automatisch erteilt. Das
voreingestellte SQL SECURITY
-Merkmal einer
Routine ist DEFINER
und erlaubt es
Benutzern, mit denen die Routine verbunden ist, und die
darüber hinaus Datenbankzugriff haben, die Routine
auszuführen.
CREATE PROCEDURE
und CREATE
FUNCTION
ALTER PROCEDURE
und ALTER FUNCTION
DROP PROCEDURE
und DROP FUNCTION
CALL
-AnweisungBEGIN ... END
-Syntax für komplexe AnweisungenDECLARE
-Anweisung
Eine gespeicherte Routine ist entweder eine Prozedur oder eine
Funktion. Gespeicherte Routinen werden mit den Anweisungen
CREATE PROCEDURE
und CREATE
FUNCTION
angelegt. Eine Prozedur wird mit einer
CALL
-Anweisung aufgerufen und kann nur über
Ausgabevariablen Werte zurückgeben. Eine Funktion kann innerhalb
einer Anweisung aufgerufen werden - wie jede andere Funktion auch
(also durch Nennung ihres Namens) - und einen Skalarwert
zurückliefern. Gespeicherte Routinen können andere gespeicherte
Routinen aufrufen.
Eine gespeicherte Prozedur oder Funktion steht mit einer bestimmten Datenbank in Zusammenhang. Das hat Folgen:
Wenn die Routine aufgerufen wird, wird implizit ein
USE
ausgeführt (und wieder rückgängig gemacht, wenn die Routine
endet). db_name
USE
-Anweisungen sind in
gespeicherten Routinen nicht zulässig.
Den Namen einer Routine können Sie mit einem Datenbanknamen
qualifizieren, etwa wenn Sie eine Routine benutzen möchten,
die nicht in der aktuellen Datenbank vorliegt. Um
beispielsweise eine Prozedur p
oder eine
Funktion f
aus der Datenbank
test
aufzurufen, können Sie CALL
test.p()
oder test.f()
sagen.
Wird eine Datenbank gelöscht, so werden alle ihre gespeicherten Routinen mitgelöscht.
MySQL unterstützt die praktischen Erweiterungen, die eine Nutzung
der regulären SELECT
-Anweisungen innerhalb von
gespeicherten Prozeduren ermöglichen (also ohne Cursors oder
lokale Variablen). Die Ergebnismenge einer solchen Anfrage wird
einfach direkt an den Client gesandt. Da mehrere
SELECT
-Anweisungen mehrere Ergebnismengen
generieren, muss der Client eine MySQL-Clientbibliothek verwenden,
die mehrere Ergebnismengen unterstützt. Das bedeutet, dass er die
Clientbibliothek einer MySQL-Version benötigt, die mindestens so
jung ist wie 4.1. Außerdem sollte der Client die Option
CLIENT_MULTI_STATEMENTS
angeben, wenn er sich
verbindet. C-Programme können dies mit der C-API-Funktion
mysql_real_connect()
tun (siehe
Abschnitt 24.2.3.51, „mysql_real_connect()
“).
Die folgenden Abschnitte beschreiben die Syntax, mit der gespeicherte Prozeduren und Funktionen erzeugt, geändert und aufgerufen werden.
CREATE PROCEDUREsp_name
([proc_parameter
[,...]]) [characteristic
...]routine_body
CREATE FUNCTIONsp_name
([func_parameter
[,...]]) RETURNStype
[characteristic
...]routine_body
proc_parameter
: [ IN | OUT | INOUT ]param_name
type
func_parameter
:param_name
type
type
:Any valid MySQL data type
characteristic
: LANGUAGE SQL | [NOT] DETERMINISTIC | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA } | SQL SECURITY { DEFINER | INVOKER } | COMMENT 'string
'routine_body
:Valid SQL procedure statement
Diese Anweisungen erzeugen gespeicherte Routinen. Um sie nutzen
zu können, ist das CREATE ROUTINE
-Recht
erforderlich. Wenn Binärlogging eingeschaltet ist, kann für
die CREATE FUNCTION
-Anweisung auch das
SUPER
-Recht erforderlich sein, wie in
Abschnitt 19.4, „Binärloggen gespeicherter Routinen und Trigger“, beschrieben. MySQL
erteilt dem Erzeuger einer Routine automatisch das
ALTER ROUTINE
- und das
EXECUTE
-Recht.
Nach Voreinstellung wird die Routine mit der Standarddatenbank
verbunden. Um sie explizit mit einer bestimmten Datenbank zu
verbinden, geben Sie bei der Erzeugung der Routine den Namen der
Datenbank in der Form db_name.sp_name
an.
Wenn der Name der Routine gleichlautend mit dem Namen einer eingebauten SQL-Funktion ist, müssen Sie zwischen dem Namen und der nachfolgenden Klammer ein Leerzeichen setzen, wenn Sie die Routine definieren, sonst tritt ein Syntaxfehler ein. Das gilt auch, wenn Sie die Routine zu einem späteren Zeitpunkt aufrufen. Aus diesem Grund raten wir Ihnen, keine Namen vorhandener SQL-Funktionen für Ihre eigenen gespeicherten Routinen zu verwenden.
Der SQL-Modus IGNORE_SPACE
gilt für
eingebaute Funktionen und nicht für gespeicherte Routinen. Es
ist immer zulässig, Leerzeichen hinter den Namen einer Routine
zu setzen, egal ob IGNORE_SPACE
eingeschaltet
ist oder nicht.
Die Parameterliste in runden Klammern muss immer vorhanden sein.
Wenn keine Parameter übergeben werden, muss eine leere
Parameterliste ()
verwendet werden. Jeder
Parameter ist nach Voreinstellung ein
IN
-Parameter. Um einen Parameter
anderslautend zu definieren, setzen Sie das Schlüsselwort
OUT
oder INOUT
vor den
Parameternamen.
Hinweis: Als
IN
, OUT
oder
INOUT
können nur
PROCEDURE
-Parameter definiert werden.
(FUNCTION
-Parameter gelten immer als
IN
-Parameter.)
Jeder Parameter kann mit jedem zulässigen Datentyp deklariert
werden, nur das Attribut COLLATE
darf nicht
verwendet werden.
Die RETURNS
-Klausel kann nur für eine
FUNCTION
angegeben werden; hier ist sie sogar
obligatorisch. Sie gibt den Rückgabetyp der Funktion an. Der
Funktionsrumpf muss eine RETURN
-Anweisung enthalten.
value
Der routine_body
besteht aus einer
gültigen SQL-Prozeduranweisung. Diese kann eine einfache
Anweisung wie etwa ein SELECT
oder
INSERT
sein, sie kann aber auch eine
zusammengesetzte Anweisung mit BEGIN
und
END
sein. Die Syntax zusammengesetzter
Anweisungen wird in Abschnitt 19.2.5, „BEGIN ... END
-Syntax für komplexe Anweisungen“, erläutert.
Zusammengesetzte Anweisungen können Deklarationen, Schleifen
und andere Anweisungen mit Kontrollstrukturen enthalten. Die
Syntax dieser Anweisungen wird weiter unten in diesem Kapitel
erklärt, beispielsweise unter Abschnitt 19.2.6, „Syntax der DECLARE
-Anweisung“, und
Abschnitt 19.2.10, „Konstrukte für die Ablaufsteuerung“.
Die CREATE FUNCTION
-Anweisung diente in
früheren MySQL-Versionen der Unterstützung von UDFs
(User-defined Functions, benutzerdefinierte Funktionen). Siehe
auch Abschnitt 26.3, „Hinzufügen neuer Funktionen zu MySQL“. UDFs werden weiterhin
unterstützt, obwohl inzwischen auch die gespeicherten
Funktionen existieren. Eine UDF kann man als externe
gespeicherte Funktion betrachten. Bitte beachten Sie jedoch,
dass gespeicherte Funktionen denselben Namensraum wie UDFs
benutzen.
Eine Prozedur oder Funktion gilt als
„deterministisch“, wenn sie für gleiche
Eingabeparameter immer gleiche Resultate erzeugt; ansonsten ist
sie „nichtdeterministisch“. Wenn in der Definition
der Routine weder DETERMINISTIC
noch
NOT DETERMINISTIC
steht, ist die
Voreinstellung NOT DETERMINISTIC
.
Im Zusammenhang mit Replikation wird eine Routine durch
Verwendung der Funktion NOW()
(oder ihrer
Synonyme) oder RAND()
nicht unbedingt
nichtdeterministisch. Für NOW()
enthält das
Binärlog den Zeitstempel und repliziert korrekt.
RAND()
repliziert ebenfalls richtig, sofern
es in einer Routine nur ein einziges Mal aufgerufen wird. (Den
Ausführungszeitstempel der Routine und den Zufallszahlen-Seed
können Sie als implizite Eingaben betrachten, die auf Master
und Slave identisch sind.)
Zurzeit wird das DETERMINISTIC
-Merkmal vom
Optimierer zwar akzeptiert, aber noch nicht benutzt. Wenn jedoch
Binärlogging eingeschaltet ist, nimmt dieses Merkmal Einfluss
darauf, welche Routinendefinitionen von MySQL akzeptiert werden.
Siehe Abschnitt 19.4, „Binärloggen gespeicherter Routinen und Trigger“.
Einige Merkmale informieren über das Wesen der von der Routine
verwendeten Daten. CONTAINS SQL
weist darauf
hin, dass die Routine keine Anweisungen zum Lesen oder Schreiben
von Daten enthält. NO SQL
bedeutet, dass sie
keine SQL-Anweisungen enthält. READS SQL
DATA
kennzeichnet Routinen mit lesenden, aber ohne
schreibende Anweisungen und MODIFIES SQL DATA
Routinen mit Anweisungen, die Daten schreiben können.
CONTAINS SQL
ist der Standardwert, wenn kein
anderes dieser Merkmale explizit angegeben ist. Die Merkmale
haben nur beratenden Charakter. Sie schränken den Server nicht
ein, wenn es darum geht, welche Arten von Anweisungen
ausgeführt werden dürfen oder nicht.
Das Merkmal SQL SECURITY
gibt an, ob die
Routine mit den Berechtigungen des Benutzers, der sie erzeugte,
oder des Benutzers, der sie aufruft, ausgeführt werden soll.
Der Standardwert ist DEFINER
. Dieses Feature
ist neu in SQL:2003. Der Erzeuger oder Aufrufer muss die
Zugriffsberechtigung auf die Datenbank haben, mit der die
Routine verbunden ist. Um die Routine auszuführen, ist das
EXECUTE
-Recht erforderlich. Der Benutzer, der
diese Berechtigung haben muss, kann nur entweder der Erzeuger
oder der Aufrufer sein, je nachdem, wie SQL
SECURITY
eingestellt ist.
MySQL speichert die Einstellung der Systemvariablen
sql_mode
, die gerade in Kraft ist, wenn eine
Routine erzeugt wird, und führt diese Routine dann immer mit
dieser Einstellung aus.
Beim Aufruf der Routine wird ein implizites USE
ausgeführt (und
wieder rückgängig gemacht, wenn die Routine endet).
db_name
USE
-Anweisungen sind in gespeicherten
Routinen nicht erlaubt.
Der Server verwendet den Datentyp eines Routinenparameters oder
Funktionsrückgabewerts wie folgt. Diese Regeln gelten auch für
lokale Laufzeitvariablen, die mit der
DECLARE
-Anweisung angelegt wurden
(Abschnitt 19.2.7.1, „Lokale DECLARE
-Variablen“).
Zuweisungen werden auf Datentypinkompatibilitäten und Überlauf überprüft. Konvertierungs- und Überlaufprobleme werden mit Warnungen oder im Strict-Modus sogar mit Fehlern quittiert.
Für Zeichendatentypen gilt: Wenn in der Deklaration eine
CHARACTER SET
-Klausel steht, wird der
angegebene Zeichensatz mit seiner Standardkollation
verwendet. Fehlt eine solche Klausel, werden der Zeichensatz
und die Kollation der Datenbank benutzt. (Diese sind durch
die Systemvariablen
character_set_database
und
collation_database
vorgegeben.)
Parametern oder Variablen können nur Skalarwerte zugewiesen
werden. Eine Anweisung wie etwa SET x = (SELECT 1,
2)
wäre ungültig.
Die COMMENT
-Klausel ist eine
MySQL-Erweiterung und kann zur Beschreibung der gespeicherten
Routine genutzt werden. Diese Information wird mit den
Anweisungen SHOW CREATE PROCEDURE
und
SHOW CREATE FUNCTION
angezeigt.
In MySQL dürfen Routinen auch DDL-Anweisungen wie
beispielsweise CREATE
und
DROP
enthalten. Darüber hinaus dürfen
gespeicherte Prozeduren (nicht aber gespeicherte Funktionen) in
MySQL auch Transaktionsanweisungen in SQL enthalten, wie etwa
COMMIT
. Gespeicherte Funktionen dürfen keine
Anweisungen enthalten, die explizit oder implizit ein Commit
oder Rollback ausführen. Eine Unterstützung für diese
Anweisungen wird vom SQL-Standard auch gar nicht verlangt, der
Standard besagt lediglich, dass jeder DBMS-Hersteller selbst
entscheiden kann, ob er sie erlauben will oder nicht.
Gespeicherte Routinen dürfen kein LOAD DATA
INFILE
enthalten.
Anweisungen, die eine Ergebnismenge zurückgeben, dürfen nicht
innerhalb einer gespeicherten Funktion verwendet werden. Dazu
gehören auch SELECT
-Anweisungen, soweit sie
nicht mithilfe einer INTO
-Klausel
Spaltenwerte in Variablen laden, sowie SHOW
und andere Anweisungen wie beispielsweise
EXPLAIN
. Anweisungen, für die zur
Definitionszeit festgelegt werden kann, dass sie eine
Ergebnismenge zurückliefern, lösen einen Not allowed
to return a result set from a function
-Fehler aus
(ER_SP_NO_RETSET_IN_FUNC
). Anweisungen, für
die nur zur Laufzeit festgelegt werden kann, dass sie eine
Ergebnismenge zurückliefern, lösen einen PROCEDURE %s
can't return a result set in the given context
-Fehler
aus (ER_SP_BADSELECT
).
Das folgende Beispiel zeigt eine einfache gespeicherte Prozedur
mit einem OUT
-Parameter. Das Beispiel
verwendet den mysql-Clientbefehl
delimiter
, um das Begrenzungszeichen für die
Anweisung von ;
in //
zu
ändern, während die Prozedur definiert wird. So kann das
Begrenzungszeichen ;
im Prozedurrumpf an den
Server durchgereicht werden, ohne von mysql
selbst interpretiert zu werden.
mysql>delimiter //
mysql>CREATE PROCEDURE simpleproc (OUT param1 INT)
->BEGIN
->SELECT COUNT(*) INTO param1 FROM t;
->END;
->//
Query OK, 0 rows affected (0.00 sec) mysql>delimiter ;
mysql>CALL simpleproc(@a);
Query OK, 0 rows affected (0.00 sec) mysql>SELECT @a;
+------+ | @a | +------+ | 3 | +------+ 1 row in set (0.00 sec)
Wenn Sie den Befehl delimiter
benutzen, geben
Sie bitte nicht das Backslash-Zeichen
(‘\
’) an, da es das Escape-Symbol
für MySQL ist.
Das folgende Beispiel zeigt eine Funktion, die einen Parameter
entgegennimmt, eine Operation mit einer SQL-Funktion ausführt
und das Ergebnis zurückliefert. In diesem Fall ist es nicht
nötig, delimiter
zu benutzen, da die
Funktionsdefinition keine ;
-Zeichen als
interne Anweisungstrennzeichen enthält:
mysql>CREATE FUNCTION hello (s CHAR(20)) RETURNS CHAR(50)
->RETURN CONCAT('Hello, ',s,'!');
Query OK, 0 rows affected (0.00 sec) mysql>SELECT hello('world');
+----------------+ | hello('world') | +----------------+ | Hello, world! | +----------------+ 1 row in set (0.00 sec)
Eine gespeicherte Funktion gibt einen Wert zurück, dessen
Datentyp in ihrer RETURNS
-Klausel angegeben
ist. Wenn die RETURN
-Anweisung einen Wert
eines anderen Typs zurückgibt, wird dieser mit Gewalt in den
richtigen Typ umgewandelt. Wenn eine Funktion beispielsweise
einen Rückgabewert vom Typ ENUM
oder
SET
hat, die
RETURN
-Anweisung jedoch einen Integer
zurückgibt, so liefert die Funktion den String für das
entsprechende ENUM
-Element oder die Menge der
SET
-Elemente.
ALTER {PROCEDURE | FUNCTION}sp_name
[characteristic
...]characteristic
: { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA } | SQL SECURITY { DEFINER | INVOKER } | COMMENT 'string
'
Mit dieser Anweisung können die Merkmale einer gespeicherten
Prozedur oder Funktion geändert werden. Hierzu benötigen Sie
das ALTER ROUTINE
-Recht für die betreffende
Routine. (Diese Berechtigung wird dem Erzeuger einer Routine
automatisch erteilt.) Wenn Binärlogging eingeschaltet ist, kann
für die ALTER FUNCTION
-Anweisung unter
Umständen auch die SUPER
-Berechtigung
erforderlich werden, wie in
Abschnitt 19.4, „Binärloggen gespeicherter Routinen und Trigger“, beschrieben.
In einer einzigen ALTER PROCEDURE
- oder
ALTER FUNCTION
-Anweisung können auch mehrere
Änderungen verlangt werden.
DROP {PROCEDURE | FUNCTION} [IF EXISTS] sp_name
Diese Anweisung löscht eine gespeicherte Prozedur oder Funktion
in dem Sinne, dass die darin genannte Routine von dem Server
entfernt wird. Hierzu benötigen Sie das ALTER
ROUTINE
-Recht für die betreffende Routine. (Diese
Berechtigung wird dem Erzeuger einer Routine automatisch
erteilt.)
Die IF EXISTS
-Klausel ist eine
MySQL-Erweiterung. Sie verhindert, dass ein Fehler auftritt,
wenn die Prozdur oder Funktion nicht existiert. Es wird eine
Warnung ausgegeben, die mit SHOW WARNINGS
angezeigt werden kann.
CALLsp_name
([parameter
[,...]])
Die CALL
-Anweisung ruft eine mit
CREATE PROCEDURE
erstellte Prozedur auf.
CALL
kann Werte mithilfe von
OUT
- oder INOUT
-Parametern
an den Aufrufer zurückgeben. Außerdem kann
CALL
die Anzahl der betroffenen Zeilen
„zurückgeben“, wenn auf der SQL-Ebene die Funktion
ROW_COUNT()
oder auf der C-Ebene die Funktion
mysql_affected_rows()
aus der C-API
aufgerufen wird.
[begin_label
:] BEGIN [statement_list
] END [end_label
]
Die BEGIN ... END
-Syntax wird für
zusammengesetzte Anweisungen verwendet, die in gespeicherten
Routinen und Triggern auftreten können. Eine zusammengesetzte
Anweisung enthält mehrere Anweisungen, die zwischen den
Schlüsselwörtern BEGIN
und
END
stehen. Die
statement_list
ist eine Liste mit
einer oder mehreren Anweisungen. Jede Anweisung der
statement_list
muss durch ein
Semikolon (;
) abgegrenzt werden. Beachten
Sie, dass eine statement_list
optional ist, sodass auch eine leere zusammengesetzte Anweisung
(BEGIN END
) zulässig wäre.
Um überhaupt mehrere Anweisungen verbinden zu können, muss ein
Client in der Lage sein, Strings von Anweisungen zu senden, die
durch das Trennzeichen ;
abgegrenzt sind.
Dafür sorgt der Kommandozeilen-Client mysql
mit dem Befehl delimiter
. Wenn Sie das
Begrenzungszeichen für Anweisungen von ;
auf
etwas anderes umstellen (beispielsweise ein
//
), dann kann ;
auch im
Rumpf der Routine verwendet werden. Ein Beispiel finden Sie in
Abschnitt 19.2.1, „CREATE PROCEDURE
und CREATE
FUNCTION
“.
Eine zusammengesetzte Anweisung kann auch beschriftet sein. Ein
end_label
kann allerdings nur
verwendet werden, wo auch ein
begin_label
vorhanden ist. Wo beide
vorhanden sind, müssen sie identisch sein.
Die optionale Klausel [NOT] ATOMIC
wird noch
nicht unterstützt. Dies bedeutet, dass am Anfang eines
Anweisungsblocks kein Transaktions-Savepoint gesetzt wird und
dass eine BEGIN
-Klausel in diesem Kontext
keinen Einfluss auf die aktuelle Transaktion hat.
Die DECLARE
-Anweisung definiert Elemente als
lokal in einer Routine:
Lokale Variablen. Siehe Abschnitt 19.2.7, „Variablen in gespeicherten Routinen“.
Bedingungen und Handler. Siehe Abschnitt 19.2.8, „Bedingungen und Handler“.
Cursors. Siehe Abschnitt 19.2.9, „Cursor“.
Die Anweisungen SIGNAL
und
RESIGNAL
werden zurzeit nicht unterstützt.
DECLARE
ist nur in einer zusammengesetzten
Anweisung mit BEGIN ... END
zulässig und
muss ganz am Anfang vor allen anderen Anweisungen stehen.
Deklarationen müssen in einer bestimmten Reihenfolge stehen. Cursors müssen vor Handlern und Variablen und Bedingungen vor Cursors und Handlern deklariert werden.
Auch Variablen können in einer Routine deklariert und benutzt werden.
DECLAREvar_name
[,...]type
[DEFAULTvalue
]
Diese Anweisung deklariert lokale Variablen. Um der Variablen
einen Standardwert beizugeben, schreiben Sie eine
DEFAULT
-Klausel in die Deklaration. Der
Wert kann auch als Ausdruck angegeben werden, er muss nicht
unbedingt eine Konstante sein. Ist keine
DEFAULT
-Klausel vorhanden, ist der
Anfangswert der Variablen NULL
.
Lokale Variablen werden im Hinblick auf Datentyp und
Speicherüberlauf wie Routinenparameter behandelt. Siehe auch
Abschnitt 19.2.1, „CREATE PROCEDURE
und CREATE
FUNCTION
“.
Eine lokale Variable gilt innerhalb des BEGIN ...
END
-Blocks, in dem sie deklariert ist. Die Variable
kann auch in Blöcken verwendet werden, die in den
deklarierenden Block eingeschachtelt sind, sofern dort nicht
eine Variable mit demselben Namen deklariert ist.
SETvar_name
=expr
[,var_name
=expr
] ...
Die SET
-Anweisung in gespeicherten Routinen
ist eine erweiterte Version der allgemeinen
SET
-Anweisung. Die Variablen können in
einer Routine deklarierte Variablen oder globale
Systemvariablen sein.
Die SET
-Anweisung in gespeicherten Routinen
ist als Teil der bereits existierenden
SET
-Syntax implementiert. Diese ermöglicht
nämlich eine erweiterte Syntax mit SET a=x, b=y,
...
, wobei verschiedene Variablentypen (lokal
deklarierte Variablen sowie globale und
Session-Servervariablen) vermischt werden können. Das
ermöglicht auch Kombinationen von lokalen Variablen und
einigen Optionen, die nur für Systemvariablen sinnvoll sind.
In diesem Fall werden die Optionen zwar erkannt, aber
ignoriert.
SELECTcol_name
[,...] INTOvar_name
[,...]table_expr
Diese SELECT
-Syntax speichert die
ausgewählten Spalten direkt in Variablen. Daher kann nur eine
einzige Zeile abgerufen werden.
SELECT id,data INTO x,y FROM test.t1 LIMIT 1;
Bei den Namen von Benutzervariablen wird nicht zwischen Groß- und Kleinschreibung unterschieden. Siehe Abschnitt 9.3, „Benutzerdefinierte Variablen“.
Wichtig: In SQL dürfen
Variablennamen und Spaltennamen nicht gleich sein. Wenn eine
SQL-Anweisung wie etwa ein SELECT ... INTO
eine Spalte und eine mit demselben Namen deklarierte lokale
Variable benutzt, interpretiert MySQL in der gegenwärtigen
Version diese Referenz als den Namen der Variablen. So wird
beispielsweise xname
in der folgenden
Anweisung als die Variable und nicht als
die Spalte mit dem Namen
xname
interpretiert:
CREATE PROCEDURE sp1 (x VARCHAR(5)) BEGIN DECLARE xname VARCHAR(5) DEFAULT 'bob'; DECLARE newname VARCHAR(5); DECLARE xid INT; SELECT xname,id INTO newname,xid FROM table1 WHERE xname = xname; SELECT newname; END;
Wenn diese Prozedur aufgerufen wird, gibt die Variable
newname
immer den Wert
'bob'
zurück, egal welchen Wert die Spalte
table1.xname
auch immer haben mag.
Siehe auch Abschnitt I.1, „Beschränkungen bei gespeicherten Routinen und Triggern“.
Manche Bedingungen erfordern eine Sonderbehandlung, darunter Bedingungen, die Fehler oder den allgemeinen Kontrollfluss innerhalb einer Routine steuern.
DECLAREcondition_name
CONDITION FORcondition_value
condition_value
: SQLSTATE [VALUE]sqlstate_value
|mysql_error_code
Diese Anweisung spezifiziert Bedingungen, die speziell
behandelt werden müssen. Sie verbindet einen Namen mit einer
Fehlerbedingung. Dieser Name kann danach in einer
DECLARE HANDLER
-Anweisung eingesetzt
werden. Siehe Abschnitt 19.2.8.2, „DECLARE
-Handler“.
Ein condition_value
kann ein
SQLSTATE-Wert oder ein MySQL-Fehlercode sein.
DECLAREhandler_type
HANDLER FORcondition_value
[,...]statement
handler_type
: CONTINUE | EXIT | UNDOcondition_value
: SQLSTATE [VALUE]sqlstate_value
|condition_name
| SQLWARNING | NOT FOUND | SQLEXCEPTION |mysql_error_code
Die DECLARE ... HANDLER
-Anweisung
deklariert Handler, die jeweils eine oder mehrere Bedingungen
behandeln können. Wenn eine dieser Bedingungen eintritt, wird
das angegebene statement
ausgeführt. statement
kann eine
einfache Anweisung sein (beispielsweise SET
) oder auch eine
zusammengesetzte Anweisung in einem var_name
=
value
BEGIN
... END
-Block (siehe
Abschnitt 19.2.5, „BEGIN ... END
-Syntax für komplexe Anweisungen“).
Ein CONTINUE
-Handler lässt die Ausführung
der aktuellen Routine nach der Ausführung der
Handler-Anweisung weiterlaufen. Ein
EXIT
-Handler dagegen beendet die
Ausführung für die zusammengesetzte BEGIN ...
END
-Anweisung, in der er deklariert ist. (Das gilt
selbst dann, wenn die Bedingung in einem inneren Block
eintritt.) Eine Anweisung des Typs
UNDO
-Handler wird zurzeit noch nicht
unterstützt.
Wenn eine Bedingung eintritt, für die kein Handler deklariert
wurde, ist die Standardaktion ein EXIT
.
Ein condition_value
kann einer der
folgenden Werte sein:
Ein SQLSTATE-Wert oder MySQL-Fehlercode.
Ein zuvor mit DECLARE ... CONDITION
deklarierter Bedingungsname. Siehe
Abschnitt 19.2.8.1, „DECLARE
-Bedingungen“.
SQLWARNING
ist eine Abkürzung für
alle SQLSTATE-Codes, die mit 01
beginnen.
NOT FOUND
ist eine Abkürzung für alle
SQLSTATE-Codes, die mit 02
beginnen.
SQLEXCEPTION
ist eine Abkürzung für
alle SQLSTATE-Codes, die nicht unter
SQLWARNING
oder NOT
FOUND
fallen.
Beispiel:
mysql>CREATE TABLE test.t (s1 int,primary key (s1));
Query OK, 0 rows affected (0.00 sec) mysql>delimiter //
mysql>CREATE PROCEDURE handlerdemo ()
->BEGIN
->DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @x2 = 1;
->SET @x = 1;
->INSERT INTO test.t VALUES (1);
->SET @x = 2;
->INSERT INTO test.t VALUES (1);
->SET @x = 3;
->END;
->//
Query OK, 0 rows affected (0.00 sec) mysql>CALL handlerdemo()//
Query OK, 0 rows affected (0.00 sec) mysql>SELECT @x//
+------+ | @x | +------+ | 3 | +------+ 1 row in set (0.00 sec)
Dieses Beispiel verbindet einen Handler mit der Bedingung
SQLSTATE 23000, die bei doppelten Schlüsselwerten eintritt.
Beachten Sie, dass @x
die
3
ist: Dies zeigt, dass MySQL die Prozedur
bis zum Ende ausgeführt hat. Wäre die Zeile DECLARE
CONTINUE HANDLER FOR SQLSTATE '23000' SET @x2 = 1;
nicht vorhanden, hätte MySQL den Standardweg
(EXIT
) eingeschlagen, nachdem das zweite
INSERT
an dem PRIMARY
KEY
-Constraint gescheitert ist, und SELECT
@x
hätte eine 2
zurückgegeben.
Wenn Sie eine Bedingung ignorieren möchten, können Sie einen
CONTINUE
-Handler für sie deklarieren und
mit einem leeren Block verbinden. Zum Beispiel:
DECLARE CONTINUE HANDLER FOR SQLWARNING BEGIN END;
Einfache Cursors werden in gespeicherten Prozeduren und Funktionen unterstützt. Die Syntax ist dieselbe wie in eingebettetem SQL. Gegenwärtig sind Cursors asensitiv, nur-lesend und nicht scrollbar. Asensitiv bedeutet, dass der Server eine Kopie der Ergebnistabelle anfertigen kann, aber nicht muss.
Cursors müssen vor Handlern und Variablen und Bedingungen vor Cursors und Handlern deklariert werden.
Beispiel:
CREATE PROCEDURE curdemo() BEGIN DECLARE done INT DEFAULT 0; DECLARE a CHAR(16); DECLARE b,c INT; DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1; DECLARE cur2 CURSOR FOR SELECT i FROM test.t2; DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1; OPEN cur1; OPEN cur2; REPEAT FETCH cur1 INTO a, b; FETCH cur2 INTO c; IF NOT done THEN IF b < c THEN INSERT INTO test.t3 VALUES (a,b); ELSE INSERT INTO test.t3 VALUES (a,c); END IF; END IF; UNTIL done END REPEAT; CLOSE cur1; CLOSE cur2; END
DECLAREcursor_name
CURSOR FORselect_statement
Diese Anweisung deklariert einen Cursor. Es können zwar mehrere Cursors in einer Routine deklariert werden, aber in einem gegebenen Block muss jeder Cursor einen eindeutigen Namen haben.
Die SELECT
-Anweisung darf keine
INTO
-Klausel haben.
Die Konstrukte IF
, CASE
,
LOOP
, WHILE
,
REPLACE
ITERATE
und
LEAVE
sind vollständig implementiert.
Viele dieser Konstrukte können andere Anweisungen enthalten,
wie die Grammatikspezifikationen in den nachfolgenden
Abschnitten zeigen. Solche Konstrukte können auch geschachtelt
werden. So kann beispielsweise eine
IF
-Anweisung eine
WHILE
-Schleife enthalten, die ihrerseits eine
CASE
-Anweisung enthält.
FOR
-Schleifen werden zurzeit nicht
unterstützt.
IFsearch_condition
THENstatement_list
[ELSEIFsearch_condition
THENstatement_list
] ... [ELSEstatement_list
] END IF
IF
implementiert ein einfaches
Bedingungskonstrukt. Wenn die
search_condition
zutrifft, wird die
zugehörige SQL-Anweisungsliste ausgeführt. Trifft keine
search_condition
zu, wird die
Anweisungsliste aus der ELSE
-Klausel
ausgeführt. Jede statement_list
besteht aus einer oder mehreren Anweisungen.
Hinweis: Es gibt auch eine
IF()
-Funktion, die
sich von der hier beschriebenen
IF
-Anweisung
unterscheidet. Siehe Abschnitt 12.2, „Ablaufsteuerungsfunktionen“.
CASEcase_value
WHENwhen_value
THENstatement_list
[WHENwhen_value
THENstatement_list
] ... [ELSEstatement_list
] END CASE
Oder:
CASE WHENsearch_condition
THENstatement_list
[WHENsearch_condition
THENstatement_list
] ... [ELSEstatement_list
] END CASE
Die CASE
-Anweisung für gespeicherte
Routinen implementiert ein komplexes Bedingungskonstrukt. Wenn
die search_condition
zutrifft, wird
die zugehörige SQL-Anweisungsliste ausgeführt. Trifft keine
search_condition
zu, wird die
Anweisungsliste aus der ELSE
-Klausel
ausgeführt. Jede statement_list
besteht aus einer oder mehreren Anweisungen.
Hinweis: Die Syntax der hier
gezeigten
CASE
-Anweisung, die in
gespeicherten Routinen zum Einsatz kommt, unterscheidet sich
von der Syntax des
CASE
-Ausdrucks von
SQL, die in Abschnitt 12.2, „Ablaufsteuerungsfunktionen“,
beschrieben wird. Die CASE
-Anweisung darf
keine ELSE NULL
-Klausel haben und wird mit
END CASE
anstelle von
END
abgeschlossen.
[begin_label
:] LOOPstatement_list
END LOOP [end_label
]
LOOP
implementiert ein einfaches
Schleifenkonstrukt, das eine wiederholte Ausführung der aus
einer oder mehreren Anweisungen bestehenden Anweisungsliste
ermöglicht. Die Anweisungen werden in der Schleife so lange
wiederholt, bis die Schleife abgebrochen wird. Dies geschieht
normalerweise mit der LEAVE
-Anweisung.
Eine LOOP
-Anweisung kann auch beschriftet
sein. Ein end_label
kann allerdings
nur verwendet werden, wo auch ein
begin_label
vorhanden ist. Wo beide
vorhanden sind, müssen sie identisch sein.
LEAVE label
Diese Anweisung beendet ein beschriftetes Konstrukt zur
Flusskontrolle. Sie kann in einem BEGIN ...
END
-Block oder in Schleifenkonstrukten
(LOOP
, REPEAT
,
WHILE
) verwendet werden.
ITERATE label
ITERATE
kann nur in
LOOP
-, REPEAT
- und
WHILE
-Anweisungen auftreten.
ITERATE
bedeutet „Durchlaufe die
Schleife noch einmal“.
Beispiel:
CREATE PROCEDURE doiterate(p1 INT) BEGIN label1: LOOP SET p1 = p1 + 1; IF p1 < 10 THEN ITERATE label1; END IF; LEAVE label1; END LOOP label1; SET @x = p1; END
[begin_label
:] REPEATstatement_list
UNTILsearch_condition
END REPEAT [end_label
]
Die Anweisungsliste in einer
REPEAT
-Anweisung wird wiederholt, bis die
Suchbedingung search_condition
zutrifft. Somit geht ein REPEAT
immer
mindestens einmal in die Schleife. Die
statement_list
besteht aus einer
oder mehreren Anweisungen.
Eine REPEAT
-Anweisung kann auch beschriftet
sein. Ein end_label
kann allerdings
nur verwendet werden, wo auch ein
begin_label
vorhanden ist. Wo beide
vorhanden sind, müssen sie identisch sein.
Beispiel:
mysql>delimiter //
mysql>CREATE PROCEDURE dorepeat(p1 INT)
->BEGIN
->SET @x = 0;
->REPEAT SET @x = @x + 1; UNTIL @x > p1 END REPEAT;
->END
->//
Query OK, 0 rows affected (0.00 sec) mysql>CALL dorepeat(1000)//
Query OK, 0 rows affected (0.00 sec) mysql>SELECT @x//
+------+ | @x | +------+ | 1001 | +------+ 1 row in set (0.00 sec)
[begin_label
:] WHILEsearch_condition
DOstatement_list
END WHILE [end_label
]
Die Anweisungsliste in einer
WHILE
-Anweisung wird wiederholt, solange
die search_condition
zutrifft. Die
statement_list
besteht aus einer
oder mehreren Bedingungen.
Eine WHILE
-Anweisung kann auch beschriftet
sein. Ein end_label
kann allerdings
nur verwendet werden, wo auch ein
begin_label
vorhanden ist. Wo beide
vorhanden sind, müssen sie identisch sein.
Beispiel:
CREATE PROCEDURE dowhile() BEGIN DECLARE v1 INT DEFAULT 5; WHILE v1 > 0 DO ... SET v1 = v1 - 1; END WHILE; END
Funktionieren die gespeicherten Prozeduren von MySQL 5.1 mit Replikation?
Ja. Standardaktionen, die in gespeicherten Prozeduren und Funktionen ausgeführt werden, werden von einem MySQL-Master-Server auf einen Slave-Server repliziert. Es gibt einige wenige Beschränkungen, die in Abschnitt 19.4, „Binärloggen gespeicherter Routinen und Trigger“ genauer ausgeführt werden.
Werden gespeicherte Prozeduren und Funktionen, die auf einem Master-Server angelegt wurden, auf einen Slave repliziert?
Ja, gespeicherte Prozeduren und Funktionen, die mit normalen
DDL-Anweisungen auf einem Master-Server angelegt wurden,
werden auf einen Slave repliziert, sodass die Objekte auf
beiden Servern vorhanden sind. ALTER
- und
DROP
-Anweisungen für gespeicherte
Prozeduren und Funktionen werden ebenfalls repliziert.
Wie werden Aktionen repliziert, die innerhalb von gespeicherten Prozeduren und Funktionen stattfinden?
MySQL zeichnet jedes DML-Ereignis auf, das in einer gespeicherten Prozedur auftritt, und repliziert diese Einzelaktionen auf einen Slave-Server. Die eigentlichen Aufrufe der gespeicherten Prozeduren werden nicht repliziert.
Gespeicherte Funktionen, die Daten ändern, werden als Funktionsaufrufe ins Log geschrieben, und nicht als die DML-Ereignisse, die innerhalb der Funktionen stattfinden.
Gibt es spezielle Sicherheitsanforderungen, um gespeicherte Prozeduren und Funktionen mit Replikation zu benutzen?
Ja. Da ein Slave-Server das Recht hat, jede Anweisung auszuführen, die er aus dem Binärlog seines Masters liest, gibt es besondere Sicherheitsvorkehrungen für die Verwendung von gespeicherten Prozeduren mit Replikation. Wenn Replikation oder Binärlogging im Allgemeinen (für die Point-of-Time-Recovery) aktiv ist, haben MySQL-DBAs zwei Sicherheitsoptionen:
Option 1: Ein Benutzer, der eine gespeicherte Funktion
anlegen möchte, muss das SUPER
-Recht
besitzen.
Option 2: Alternativ kann ein DBA die Systemvariable
log_bin_trust_function_creators
auf 1
setzen. Dann kann jeder, der über die
Standardberechtigung CREATE ROUTINE
verfügt, gespeicherte Funktionen erstellen.
Welche Beschränkungen gelten für die Replikation von Aktionen gespeicherter Prozeduren und Funktionen?
Nichtdeterministische (zufällige) oder zeitabhängige
Aktionen, die in gespeicherten Prozeduren eingebettet sind,
werden eventuell nicht richtig repliziert. Nach dem
Zufallsprinzip entstandene Ergebnisse sind von Natur aus
unvorhersehbar und lassen sich nicht genau reproduzieren.
Somit spiegeln Zufallsaktionen, die auf einen Slave repliziert
werden, nicht die Aktionen des Masters wider. Wenn Sie
gespeicherte Funktionen als DETERMINISTIC
deklarieren oder die Systemvariable
log_bin_trust_function_creators
auf 0
setzen, können keine Operationen mit Zufallswerten aufgerufen
werden.
Auch zeitabhängige Aktionen lassen sich nicht auf einen Slave replizieren, da das Timing solcher Aktionen in einer gespeicherten Prozedur nicht durch das für die Replikation eingesetzte Binärlog reproduzierbar ist. Dieses zeichnet nur DML-Ereignisse auf und berücksichtigt keine Zeiteinschränkungen.
Auch in nichttransaktionssicheren Tabellen, mit denen bei
größeren DML-Aktionen (wie beispielsweise
Massen-Einfügeoperationen) Fehler auftreten, können
Replikationsprobleme entstehen, wenn ein Master aufgrund der
DML-Aktivität teilweise aktualisiert wurde, während der
Slave wegen eines Fehlers diese Änderung nicht mitgemacht
hat. Dies kann man umgehen, indem man die DML-Aktionen einer
Funktion mit dem Schlüsselwort IGNORE
ausführt, damit Änderungen auf dem Master, die Fehler
auslösen, ignoriert und Änderungen, die keine Fehler
auslösen, auf den Slave repliziert werden.
Beeinträchtigen die vorgenannten Beschränkungen die Fähigkeit von MySQL, eine Point-in-Time-Recovery durchzuführen?
Dieselben Beschränkungen, die sich auf die Replikation auswirken, wirken sich auch auf die Point-in-Time-Recovery aus.
Was unternimmt MySQL, um diese Beschränkungen auszuräumen?
Ab MySQL 5.1.5 können Sie zwischen anweisungs- und zeilenbasierter Replikation wählen. Die ursprüngliche Implementierung der Replikation beruht auf dem anweisungsbasierten Binärlogging. Zeilenbasiertes Binärlogging löst die oben beschriebenen Probleme. Mehr zum Thema finden Sie unter Abschnitt 6.3, „Zeilenbasierte Replikation“.
Funktionieren Trigger mit Replikation?
Trigger und Replikation funktionieren in MySQL 5.1 genau wie in den meisten anderen Datenbank-Engines: Aktionen, die auf einem Master mithilfe von Triggern ausgeführt werden, werden nicht auf einen Slave-Server repliziert. Dagegen müssen Trigger auf Tabellen, die auf einem MySQL-Master-Server liegen, auch auf den entsprechenden Tabellen des MySQL-Slave-Servers angelegt werden, um auf den Slaves ebenso wie auf dem Master aktiviert werden zu können.
Wie werden Trigger-Aktionen auf einem Master ausgeführt, der auf einen Slave repliziert wurde?
Erstens müssen die Trigger, die auf dem Master vorhanden
sind, auf dem Slave-Server rekonstruiert werden. Wenn dies
erledigt ist, läuft die Replikation so ab wie bei jeder
anderen DML-Standardanweisung, die an einer Replikation
beteiligt ist. Betrachten Sie als Beispiel die Tabelle
EMP
mit dem Insert-Trigger
AFTER
, die auf einem MySQL-Master-Server
liegt. Dieselbe EMP
-Tabelle mit demselben
AFTER
-Insert-Trigger liegt auch auf dem
Slave-Server. Der Replikationsfluss verliefe folgendermaßen:
Eine INSERT
-Anweisung für
EMP
wird abgesetzt.
Der AFTER
-Trigger auf
EMP
wird aktiviert.
Die INSERT
-Anweisung wird in das Binärlog
geschrieben.
Der Replikations-Slave nimmt die
INSERT
-Anweisung für
EMP
auf und führt sie aus.
Der AFTER
-Trigger auf
EMP
, der auf dem Slave existiert, wird
aktiviert.
Das Binärlog enthält Informationen über SQL-Anweisungen, die Datenbankinhalte ändern. Diese Informationen werden in Form von „Ereignissen“ gespeichert, welche die Modifikationen beschreiben. Das Binärlog dient zwei wichtigen Zwecken:
Für die Replikation sendet der Master-Server die Ereignisse, die in seinem Binärlog stehen, an seine Slaves. Diese führen die Ereignisse dann aus, um die Datenänderungen nachzuvollziehen, die auf dem Master stattgefunden haben. Siehe Abschnitt 6.2, „Replikation: Implementation“.
Für bestimmte Datenwiederherstellungsoperationen muss das Binärlog genutzt werden. Nach der Wiederherstellung einer Sicherungsdatei werden aus dem Binärlog die Ereignisse, die nach Erstellung der Sicherungsdatei eintraten, erneut ausgeführt. Diese Ereignisse bringen die Datenbank von dem Zeitpunkt der Sicherung auf den neuesten Stand. Siehe auch Abschnitt 5.10.2.2, „Verwenden von Datensicherungen zur Wiederherstellung“.
Dieser Abschnitt beschreibt, wie MySQL 5.1 das Binärlogging für gespeicherte Routinen (Prozeduren und Funktionen) und Trigger behandelt. Es wird beschrieben, welche Bedingungen die Implementierung zurzeit an die Verwendung gespeicherter Routinen knüpft, und diese Bedingungen werden auch begründet.
Die hier beschriebenen Probleme gründen im Wesentlichen auf die Tatsache, dass Binärlogging auf SQL-Anweisungsebene stattfindet. In einem künftigen Release von MySQL soll auch Binärlogging auf Zeilenebene eingeführt werden, wobei die Änderungen protokolliert werden, die bei der Ausführung von SQL-Anweisungen in den einzelnen Zeilen stattfinden.
Soweit nichts anderes gesagt wird, gehen wir in den nachfolgenden
Bemerkungen davon aus, dass Sie Binärlogging durch Hochfahren des
Servers mit der Option --log-bin
eingeschaltet
haben. (Siehe auch Abschnitt 5.12.3, „Die binäre Update-Logdatei“.) Wenn das
Binärlog nicht eingeschaltet ist, ist weder eine Replikation
möglich noch steht das Binärlog für die Wiederherstellung von
Daten zur Verfügung.
Die derzeit gültigen Bedingungen für die Nutzung gespeicherter Funktionen in MySQL 5.1 werden im Folgenden zusammengefasst. Diese Bedingungen gelten nicht für gespeicherte Prozeduren, und sie gelten auch ansonsten nur dann, wenn das Binärlogging auch eingeschaltet ist.
Um eine gespeicherte Funktion anzulegen oder zu ändern,
benötigen Sie das SUPER
-Recht zusätzlich
zu dem normalerweise erforderlichen CREATE
ROUTINE
- oder ALTER
ROUTINE
-Recht.
Wenn Sie eine gespeicherte Funktion erstellen, müssen Sie sie entweder als deterministisch deklarieren oder festlegen, dass sie keine Daten modifiziert. Andernfalls kann sie für die Datenwiederherstellung oder Replikation Unsicherheiten bergen.
Zur Lockerung der obigen Bedingungen für die Erstellung einer
Funktion (obligatorisches SUPER
-Recht und
das Erfordernis, entweder eine deterministische Funktion oder
eine Funktion, die keine Daten ändert, zu deklarieren)
können Sie die globale Systemvariable
log_bin_trust_function_creators
auf 1
setzen. Diese Variable hat den Standardwert 0, lässt sich
aber folgendermaßen umstellen:
mysql> SET GLOBAL log_bin_trust_function_creators = 1;
Sie können diese Variable auch einstellen, indem Sie beim
Starten des Servers die Option
--log-bin-trust-function-creators
einstellen.
Wenn Binärlogging nicht aktiviert ist, ist
log_bin_trust_function_creators
unwirksam
und das SUPER
-Recht ist nicht erforderlich,
um eine Funktion anzulegen.
Da Trigger gespeicherten Funktionen ähneln, gelten diese
Ausführungen zu Funktionen auch für Trigger, allerdings mit der
folgenden Einschränkung: Da CREATE TRIGGER
kein optionales DETERMINISTIC
-Merkmal hat, geht
man davon aus, dass Trigger immer deterministisch sind. Doch diese
Grundannahme muss nicht immer gelten. So ist beispielsweise die
Funktion UUID()
nichtdeterministisch (und wird
auch nicht repliziert). Solche Funktionen sollten Sie in Triggern
nur mit Vorsicht benutzen.
Da Trigger Tabellen ändern können, kommen im Zusammenhang mit
CREATE TRIGGER
ähnliche Fehlermeldungen wie
bei gespeicherten Funktionen vor, wenn Sie nicht das
SUPER
-Recht haben und
log_bin_trust_function_creators
den Wert 0 hat.
Im Folgenden erfahren Sie mehr über die Logging-Implementierung und ihre Implikationen.
Der Server schreibt CREATE PROCEDURE
-,
CREATE FUNCTION
-, ALTER
PROCEDURE
-, ALTER FUNCTION
-,
DROP PROCEDURE
- und DROP
FUNCTION
-Anweisungen in das Binärlog.
Der Aufruf einer gespeicherten Funktion wird als
DO
-Anweisung protokolliert, wenn die
Funktion Daten ändert und in einer Anweisung auftritt, die
ansonsten nicht protokolliert würde. Dadurch wird verhindert,
dass Datenänderungen, die durch die Verwendung von
gespeicherten Funktionen in nichtprotokollierten Anwendungen
auftreten, nicht repliziert werden. So werden beispielsweise
SELECT
-Anweisungen nicht in das Binärlog
geschrieben, aber ein SELECT
kann eine
gespeicherte Funktion aufrufen, die Datenänderungen
hervorruft. Um damit umzugehen, wird eine DO
-Anweisung in
das Binärlog geschrieben, wenn die Funktion eine Änderung
vornimmt. Angenommen, folgende Funktionen werden auf dem
Master ausgeführt:
func_name
()
CREATE FUNCTION f1(a INT) RETURNS INT BEGIN IF (a < 3) THEN INSERT INTO t2 VALUES (a); END IF; END; CREATE TABLE t1 (a INT); INSERT INTO t1 VALUES (1),(2),(3); SELECT f1(a) FROM t1;
Wenn die SELECT
-Anweisung ausgeführt wird,
wird die Funktion f1()
dreimal aufgerufen.
Zwei der Aufrufe fügen eine Zeile ein und MySQL schreibt für
jede von ihnen eine DO
-Anweisung in das
Log. Somit hält MySQL folgende Anweisungen im Binärlog fest:
DO f1(1); DO f1(2);
Der Server protokolliert auch eine
DO
-Anweisung für einen Aufruf einer
gespeicherten Funktion, wenn die Funktion eine gespeicherte
Prozedur aufruft, die einen Fehler verursacht. In diesem Fall
schreibt der Server die DO
-Anweisung
zusammen mit dem erwarteten Fehlercode in das Log. Wenn auf
dem Slave derselbe Fehler auftritt, ist dies das erwartete
Resultat und die Replikation läuft weiter. Andernfalls bricht
die Replikation ab.
Wenn anstelle von Anweisungen, die eine Funktion ausführt, Aufrufe gespeicherter Funktionen protokolliert werden, hat dies Folgen für die Sicherheit der Replikation. Dafür sind zwei Faktoren verantwortlich:
Es ist möglich, dass eine Funktion auf dem Master und den Slave-Servern unterschiedliche Ausführungspfade einschlägt.
Anweisungen, die auf einem Slave ausgeführt werden, werden von dem SQL-Thread des Slaves verarbeitet, der volle Berechtigungen hat.
Die Folge davon ist, dass zwar jeder Benutzer für die
Erstellung einer Funktion das CREATE
ROUTINE
-Recht benötigt. Doch damit könnte er eine
Funktion schreiben, die eine gefährliche Anweisung enthält,
die nur auf dem Slave ausgeführt wird, da sie dort von dem
SQL-Thread ausgeführt wird, der über volle Berechtigungen
verfügt. Wenn beispielsweise der Master-Server die Server-ID
1 und der Slave-Server die Server-ID 2 hätte, könnte ein
Benutzer auf dem Master-Server eine unsichere Funktion namens
unsafe_func()
folgendermaßen erstellen und
aufrufen:
mysql>delimiter //
mysql>CREATE FUNCTION unsafe_func () RETURNS INT
->BEGIN
->IF @@server_id=2 THEN
->dangerous_statement
; END IF;RETURN 1;
->END;
->//
mysql>delimiter ;
mysql>INSERT INTO t VALUES(unsafe_func());
Da die CREATE FUNCTION
- und die
INSERT
-Anweisung in das Binärlog
geschrieben werden, führt der Slave sie aus. Und da der
Slave-SQL-Thread wiederum über so umfassende Berechtigungen
verfügt, wird er die gefährliche Anweisung auch befolgen.
Somit hat der Funktionsaufruf auf dem Master andere Folgen als
auf dem Slave und ist nicht replikationssicher.
Um Server, auf denen das Binärlogging eingeschaltet ist, vor
dieser Gefahr zu schützen, benötigen die Erzeuger
gespeicherter Funktionen zusätzlich zu dem üblichen
CREATE ROUTINE
-Recht, das ohnehin notwendig
ist, auch das SUPER
-Recht. Ebenso darf
ALTER FUNCTION
nur benutzen, wer
zusätzlich zu dem ALTER ROUTINE
-Recht auch
das SUPER
-Recht besitzt. Fehlt die
SUPER
-Berechtigung, wird ein Fehler
ausgelöst:
ERROR 1419 (HY000): You do not have the SUPER privilege and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)
Wenn Sie von den Erzeugern von Funktionen nicht verlangen
möchten, dass sie das SUPER
-Recht besitzen
(zum Beispiel, wenn in Ihrem System alle Benutzer, die das
CREATE ROUTINE
-Recht haben, erfahrene
Anwendungsentwickler sind), dann können Sie die globale
Systemvariable
log_bin_trust_function_creators
auf 1
setzen. Das können Sie auch tun, indem Sie beim Serverstart
die Option --log-bin-trust-function-creators
einstellen. Wenn kein Binärlogging aktiviert ist, ist
log_bin_trust_function_creators
wirkungslos
und zum Anlegen von Funktionen ist kein
SUPER
-Recht erforderlich.
Wenn eine Funktion, die Änderungen vornimmt, nichtdeterministisch ist, so ist sie auch nicht wiederholbar. Dies kann zwei unangenehme Folgen haben:
Ein Slave entspricht nicht mehr dem Master.
Wiederhergestellte Daten entsprechen nicht mehr den Originaldaten.
Um diese Probleme in den Griff zu bekommen, stellt MySQL folgende Anforderung: Auf einem Master-Server ist die Erzeugung und Änderung einer Funktion nur möglich, wenn diese als deterministisch deklariert ist oder keine Daten ändert. Hierbei kommen zwei Arten von Funktionsmerkmalen ins Spiel:
Die Merkmale DETERMINISTIC
und
NOT DETERMINISTIC
zeigen an, ob eine
Funktion für dieselben Eingabewerte auch immer dieselben
Ergebnisse produziert. Da die Standardeinstellung, wenn
nichts anderes angegeben wird, NOT
DETERMINISTIC
lautet, müssen Sie explizit das
Merkmal DETERMINISTIC
angeben, um
klarzustellen, dass eine Funktion deterministisch ist.
Durch Verwendung der Funktion NOW()
(oder ihrer Synonyme) oder RAND()
wird
eine Funktion nicht unbedingt deterministisch. Für
NOW()
zeichnet das Binärlog den
Zeitstempel auf und repliziert richtig. Die Funktion
RAND()
repliziert ebenfalls korrekt,
sofern sie in einer Funktion nicht mehrmals aufgerufen
wird. (Den Ausführungs-Zeitstempel der Funktion und den
Zufallszahlen-Seedwert können Sie als implizite Eingaben
betrachten, die bei Master und Slave identisch sind.)
Die Merkmale CONTAINS SQL
, NO
SQL
, READS SQL DATA
und
MODIFIES SQL DATA
geben Informationen
darüber, ob die Funktion Daten liest oder schreibt.
NO SQL
oder READS SQL
DATA
zeigt an, dass eine Funktion keine Daten
ändert, aber Sie müssen eines dieser Merkmale explizit
angeben, da ansonsten der Standardwert CONTAINS
SQL
ist.
Damit eine CREATE FUNCTION
-Anweisung
akzeptiert wird, muss nach Voreinstellung
DETERMINISTIC
bzw. entweder NO
SQL
oder READS SQL DATA
explizit
angegeben werden. Andernfalls tritt ein Fehler auf:
ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)
Wenn Sie log_bin_trust_function_creators
auf 1 setzen, wird nicht mehr gefordert, dass Funktionen
entweder deterministisch sind oder keine Daten ändern.
Wie die Natur einer Funktion eingeschätzt wird, hängt von
der „Ehrlichkeit“ ihres Erzeugers ab: MySQL
prüft nicht, ob eine als DETERMINISTIC
deklarierte Funktion auch tatsächlich keine Anweisungen
enthält, die nichtdeterministische Ergebnisse produzieren.
Aufrufe an gespeicherte Prozeduren werden auf Anweisungs-
statt auf CALL
-Ebene protokolliert. Das
bedeutet, dass der Server nicht die
CALL
-Anweisung protokolliert, sondern
diejenigen Anweisungen der Prozedur, die tatsächlich
ausgeführt werden. Dadurch treten auf den Slave-Servern
dieselben Änderungen wie auf dem Master ein. So werden
Probleme vermieden, die entstehen könnten, wenn eine Prozedur
auf verschiedenen Rechnern verschiedene Ausführungspfade hat.
Im Allgemeinen werden Anweisungen, die in einer gespeicherten Prozedur ausgeführt werden, nach denselben Regeln in das Binärlog geschrieben, die auch für eigenständig ausgeführte Anweisungen gelten. Die Protokollierung von Prozeduranweisungen wird besonders vorsichtig gehandhabt, da die Ausführung von Anweisungen innerhalb einer Prozedur nicht dasselbe ist wie außerhalb einer Prozedur:
Eine zu protokollierende Anweisung könnte Verweise auf lokale Prozedurvariablen enthalten. Da diese Variablen außerhalb des Prozedurkontextes gar nicht vorhanden sind, kann eine Anweisung, die eine solche Variable benutzt, nicht wörtlich protokolliert werden. Stattdessen wird für das Log jede Referenz auf eine lokale Variable durch das folgende Konstrukt ersetzt:
NAME_CONST(var_name
,var_value
)
var_name
ist der Name der
lokalen Variablen und var_value
eine Konstante, die den Wert der Variablen zum Zeitpunkt
der Protokollierung der Anweisung anzeigt.
NAME_CONST()
hat den Wert
var_value
und den
„Namen“ var_name
.
Somit erhalten Sie folgendes Ergebnis, wenn Sie diese
Funktion direkt aufrufen:
mysql> SELECT NAME_CONST('myname', 14);
+--------+
| myname |
+--------+
| 14 |
+--------+
NAME_CONST()
ermöglicht es, eine
selbstständige Anweisung auf einem Slave so auszuführen,
dass sie denselben Effekt hat wie die Originalanweisung,
die innerhalb einer gespeicherten Prozedur auf dem
Master-Server ausgeführt wurde.
Eine zu protokollierende Anweisung könnte Referenzen auf
benutzerdefinierte Variablen enthalten. Also schreibt
MySQL eine SET
-Anweisung in das
Binärlog, um zu gewährleisten, dass die Variable auf dem
Slave mit demselben Wert wie auf dem Master existiert.
Wenn beispielsweise eine Anweisung die Variable
@my_var
benutzt, steht vor dieser
Anweisung im Binärlog folgende Anweisung, wobei
value
der Wert ist, den
@my_var
auf dem Master hat:
SET @my_var = value
;
Prozeduraufrufe können in einer committeten oder
zurückgerollten Transaktion auftreten. Früher wurden
CALL
-Anweisungen auch dann
protokolliert, wenn sie in einer zurückgerollten
Transaktion vorkamen. Seit MySQL 5.0.12 wird der
Transaktionskontext berücksichtigt, sodass die
transaktionsbedingten Aspekte der Prozedurausführung
korrekt repliziert werden. Das bedeutet, dass der Server
in der Prozedur nur diejenigen Anweisungen protokolliert,
die auch tatsächlich ausgeführt werden und Daten
ändern. Nach Bedarf protokolliert er darüber hinaus auch
BEGIN
-, COMMIT
- und
ROLLBACK
-Anweisungen. Wenn
beispielsweise eine Prozedur nur Transaktionstabellen
ändert und innerhalb einer Transaktion ausgeführt wird,
die zurückgerollt wird, werden solche Änderungen nicht
ins Log geschrieben. Tritt die Prozedur hingegen in einer
committeten Transaktion auf, werden
BEGIN
- und
COMMIT
-Anweisungen mit den Updates
protokolliert. Die Anweisungen einer in einer
zurückgerollten Transaktion ausgeführten Prozedur werden
nach denselben Regeln protokolliert, die auch gelten
würden, wenn die Anweisungen selbstständig ausgeführt
worden wären:
Änderungen an Transaktionstabellen werden nicht protokolliert.
Änderungen an anderen Tabellen werden protokolliert, weil sie durch ein Rollback nicht rückgängig gemacht werden.
Änderungen an einem Mix von Transaktionstabellen und
anderen Tabellen werden innerhalb eines
BEGIN
-ROLLBACK
Blocks protokolliert, damit die Slaves dieselben
Änderungen und Rollbacks wie der Master vornehmen.
Ein Aufruf einer gespeicherten Prozedur wird
nicht auf Anweisungsebene in das
Binärlog geschrieben, wenn die Prozedur innerhalb einer
gespeicherten Funktion aufgerufen wird. In einem solchen Fall
wird lediglich die Anweisung protokolliert, welche die
Funktion aufruft, (wenn diese innerhalb einer protokollierten
Anweisung benutzt wird), oder eine
DO
-Anweisung (wenn sie in einer Anweisung
benutzt wird, die nicht protokolliert wird). Daher sollten Sie
vorsichtig mit gespeicherten Funktionen sein, die eine
Prozedur aufrufen, selbst wenn die Prozedur ansonsten sicher
ist.
Inhaltsverzeichnis
Ein Trigger ist ein benanntes Datenbankobjekt, das mit einer Tabelle
verbunden ist und aktiviert wird, wenn für diese Tabelle ein
bestimmtes Ereignis eintritt. So legen beispielsweise die folgenden
Anweisungen eine Tabelle und einen INSERT
-Trigger
an. Der Trigger addiert die Werte, die in eine der Tabellenspalten
geladen werden:
mysql>CREATE TABLE account (acct_num INT, amount DECIMAL(10,2));
Query OK, 0 rows affected (0.03 sec) mysql>CREATE TRIGGER ins_sum BEFORE INSERT ON account
->FOR EACH ROW SET @sum = @sum + NEW.amount;
Query OK, 0 rows affected (0.06 sec)
Dieses Kapitel beschreibt die Syntax, mit der Trigger angelegt und gelöscht werden, und zeigt einige Anwendungsbeispiele für sie. Über die Beschränkungen für Trigger finden Sie in Abschnitt I.1, „Beschränkungen bei gespeicherten Routinen und Triggern“, genauere Hinweise. Informationen über Binärlogging in Bezug auf Trigger finden Sie unter Abschnitt 19.4, „Binärloggen gespeicherter Routinen und Trigger“.
CREATE [DEFINER = {user
| CURRENT_USER }] TRIGGERtrigger_name
trigger_time
trigger_event
ONtbl_name
FOR EACH ROWtrigger_stmt
Diese Anweisung erzeugt einen neuen Trigger. Ein Trigger ist ein
benanntes Datenbankobjekt, das mit einer Tabelle verbunden ist und
aktiviert wird, wenn für diese Tabelle ein bestimmtes Ereignis
eintritt. Gegenwärtig ist zur Ausführung von CREATE
TRIGGER
das TRIGGER
-Recht für die
Tabelle erforderlich, zu welcher der Trigger gehört. (Vor MySQL
5.1.6 war für diese Anweisung das SUPER
-Recht
notwendig.)
Der Trigger wird mit der Tabelle
tbl_name
verbunden, die eine permanante
Tabelle sein muss. Mit einer als TEMPORARY
definierten Tabelle oder View lässt sich kein Trigger verbinden.
Wenn der Trigger aktiviert wird, legt die
DEFINER
-Klausel fest, welche Rechte angewendet
werden. Genaueres erfahren Sie weiter unten in diesem Kapitel.
Die trigger_time
ist der Zeitpunkt der
Trigger-Aktion. Sie kann BEFORE
oder
AFTER
sein, je nachdem, ob der Trigger sich vor
oder nach der Anweisung einschaltet, die ihn aktivierte.
Das trigger_event
gibt an, welche Art
von Anweisung den Trigger aktiviert. Das
trigger_event
kann eines der folgenden
Ereignisse sein:
INSERT
: Der Trigger wird immer dann
aktiviert, wenn eine neue Zeile in die Tabelle eingefügt
wird, beispielsweise mit INSERT
-,
LOAD DATA
- und
REPLACE
-Anweisungen.
UPDATE
: Der Trigger wird immer dann
aktiviert, wenn eine Zeile in der Tabelle geändert wird,
beispielsweise mit UPDATE
-Anweisungen.
DELETE
: Der Trigger wird immer dann
aktiviert, wenn eine Zeile aus der Tabelle gelöscht wird,
beispielsweise mit DELETE
- und
REPLACE
-Anweisungen.
Es ist wichtig, zu verstehen, dass das
trigger_event
weniger eine Art von
SQL-Anweisung ist, die den Trigger aktiviert, als vielmehr eine
Art von Tabellenoperation. So wird beispielsweise ein
INSERT
-Trigger nicht nur von
INSERT
-Anweisungen, sondern auch von
LOAD DATA
-Anweisungen aktiviert, weil beide
Anweisungen Zeilen in eine Tabelle einfügen.
Ein potenziell verwirrendes Beispiel dafür ist die Syntax von
INSERT INTO ... ON DUPLICATE KEY UPDATE ...
:
Für jede Zeile wird ein BEFORE INSERT
-Trigger
aktiviert, gefolgt entweder von einem AFTER
INSERT
-Trigger oder von dem Triggerpaar aus
BEFORE UPDATE
und AFTER
UPDATE
, je nachdem, ob ein doppelter Schlüssel für die
Zeile vorlag oder nicht.
Es dürfen keine zwei Trigger einer Tabelle dieselbe Aktionszeit
und dasselbe Trigger-Ereignis haben. Zum Beispiel können Sie
keine zwei BEFORE UPDATE
-Trigger für eine
Tabelle definieren. Sie können jedoch einen BEFORE
UPDATE
- und einen BEFORE
INSERT
-Trigger oder einen BEFORE
UPDATE
- und einen AFTER
UPDATE
-Trigger definieren.
trigger_stmt
ist die Anweisung, die
ausgeführt wird, wenn der Trigger in Aktion tritt. Wenn Sie
mehrere Anweisungen ausführen möchten, verwenden Sie das
Konstrukt BEGIN ... END
für zusammengesetzte
Anweisungen. So können Sie auch dieselben Anweisungen wie in
gespeicherten Routinen verwenden. Siehe auch
Abschnitt 19.2.5, „BEGIN ... END
-Syntax für komplexe Anweisungen“.
Hinweis: Zurzeit werden Trigger nicht von kaskadierenden Fremdschlüsselaktionen aktiviert. Dieser Mangel wird jedoch so bald wie möglich behoben.
In MySQL 5.1 können Sie Trigger schreiben, die
Direktverweise auf Tabellennamen enthalten, wie der Trigger
testref
im folgenden Beispiel:
CREATE TABLE test1(a1 INT); CREATE TABLE test2(a2 INT); CREATE TABLE test3(a3 INT NOT NULL AUTO_INCREMENT PRIMARY KEY); CREATE TABLE test4( a4 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, b4 INT DEFAULT 0 ); DELIMITER | CREATE TRIGGER testref BEFORE INSERT ON test1 FOR EACH ROW BEGIN INSERT INTO test2 SET a2 = NEW.a1; DELETE FROM test3 WHERE a3 = NEW.a1; UPDATE test4 SET b4 = b4 + 1 WHERE a4 = NEW.a1; END; | DELIMITER ; INSERT INTO test3 (a3) VALUES (NULL), (NULL), (NULL), (NULL), (NULL), (NULL), (NULL), (NULL), (NULL), (NULL); INSERT INTO test4 (a4) VALUES (0), (0), (0), (0), (0), (0), (0), (0), (0), (0);
Angenommen, Sie setzen die folgenden Werte in die Tabelle
test1
ein, wie hier gezeigt:
mysql>INSERT INTO test1 VALUES
->(1), (3), (1), (7), (1), (8), (4), (4);
Query OK, 8 rows affected (0.01 sec) Records: 8 Duplicates: 0 Warnings: 0
Die Daten in den vier Tabellen stellen sich dann folgendermaßen dar:
mysql>SELECT * FROM test1;
+------+ | a1 | +------+ | 1 | | 3 | | 1 | | 7 | | 1 | | 8 | | 4 | | 4 | +------+ 8 rows in set (0.00 sec) mysql>SELECT * FROM test2;
+------+ | a2 | +------+ | 1 | | 3 | | 1 | | 7 | | 1 | | 8 | | 4 | | 4 | +------+ 8 rows in set (0.00 sec) mysql>SELECT * FROM test3;
+----+ | a3 | +----+ | 2 | | 5 | | 6 | | 9 | | 10 | +----+ 5 rows in set (0.00 sec) mysql>SELECT * FROM test4;
+----+------+ | a4 | b4 | +----+------+ | 1 | 3 | | 2 | 0 | | 3 | 1 | | 4 | 2 | | 5 | 0 | | 6 | 0 | | 7 | 1 | | 8 | 1 | | 9 | 0 | | 10 | 0 | +----+------+ 10 rows in set (0.00 sec)
Die Spalten der Subjekttabelle (der Tabelle, zu welcher der
Trigger gehört) können Sie mit den Aliasnamen
OLD
und NEW
ansprechen.
OLD.
bezieht
sich auf eine Spalte mit einer vorhandenen Zeile, bevor diese
geändert oder gelöscht wurde, und
col_name
NEW.
auf die
Spalte mit einer neu eingefügten oder geänderten Zeile.
col_name
Die DEFINER
-Klausel gibt an, welches
MySQL-Konto zur Prüfung der Zugriffsberechtigungen bei
Aktivierung des Triggers herangezogen wird. Wenn ein
user
-Wert angegeben ist, dann als
MySQL-Konto im Format
'
(dasselbe Format wird auch in der
user_name
'@'host_name
'GRANT
-Anweisung verwendet). Die Werte
user_name
und
host_name
sind beide obligatorisch.
CURRENT_USER
kann auch als
CURRENT_USER()
angegeben werden. Der
Standardwert für DEFINER
ist der Benutzer, der
die CREATE TRIGGER
-Anweisung ausführt. (Dies
ist dasselbe wie DEFINER = CURRENT_USER
.)
Wenn Sie die DEFINER
-Klausel angeben, dürfen
Sie den Wert auf kein anderes als Ihr eigenes Konto einstellen,
wenn Sie nicht über das SUPER
-Recht verfügen.
Die zulässigen Werte für den DEFINER
-Benutzer
richten sich nach folgenden Regeln:
Wenn Sie nicht das SUPER
-Recht haben, ist
der einzig zulässige user
-Wert Ihr
eigenes Konto, das entweder buchstäblich oder über
CURRENT_USER
angegeben werden kann. Auf ein
anderes Konto können Sie den DEFINER
nicht
einstellen.
Wenn Sie das SUPER
-Recht haben, können Sie
jeden gültigen Kontonamen angeben, der syntaktisch zulässig
ist. Existiert das Konto in Wirklichkeit nicht, wird eine
Warnung ausgegeben.
Hinweis: In älteren Versionen als MySQL 5.1.6 wird das
SUPER
-Recht für die Benutzung von
CREATE TRIGGER
verlangt, sodass für diese
älteren Releases nur die zweite der oben genannten Regeln gilt.
Seit der Version 5.1.6 ist SUPER
nur noch
erforderlich, wenn der DEFINER
auf etwas
anderes als das eigene Konto eingestellt werden soll.
MySQL prüft Trigger-Berechtigungen folgendermaßen:
Zur CREATE TRIGGER
-Zeit muss der Benutzer,
der die Anweisung gibt, das TRIGGER
-Recht
besitzen. (Vor MySQL 5.1.6 war sogar das
SUPER
-Recht erforderlich.)
Zum Zeitpunkt der Trigger-Aktivierung werden die
Berechtigungen mit denen des
DEFINER
-Benutzers verglichen. Dieser
benötigt folgende Berechtigungen:
Das TRIGGER
-Recht (vor MySQL 5.1.6 das
SUPER
-Recht).
Das SELECT
-Recht für die
Subjekttabelle, wenn mit
OLD.
oder
col_name
NEW.
in der Trigger-Definition auf Tabellenspalten verwiesen
wird.
col_name
Das UPDATE
-Recht für die
Subjekttabelle, wenn ihre Spalten Ziel von SET
NEW.
-Zuweisungen in
der Trigger-Definition sind.
col_name
=
value
Zusätzlich alle anderen Rechte, die normalerweise für die vom Trigger ausgeführten Anweisungen erforderlich sind.
DROP TRIGGER [schema_name
.]trigger_name
Diese Anweisung löscht einen Trigger. Der Schemaname (Datenbank)
ist optional. Wird kein Schema angegeben, wird der Trigger aus dem
Standardschema gelöscht. DROP TRIGGER
wurde in
MySQL 5.0.2 hinzugefügt und erfordert das
TRIGGER
-Recht für die Tabelle, zu welcher der
Trigger gehört. (Vor MySQL 5.1.6 war für diese Anweisung das
SUPER
-Recht erforderlich.)
Hinweis: Wenn Sie von einer älteren MySQL-Version als
MySQL 5.0.10 auf 5.0.10 oder neuer aufrüsten (einschließlich
aller MySQL 5.1-Releases), müssen Sie alle Trigger
vor dem Upgrade löschen und danach wieder
neu erstellen. DROP TRIGGER
funktioniert nach
dem Upgrade nicht mehr. Unter
Abschnitt 2.10.1, „Upgrade von MySQL 5.0“, wird eine empfehlenswerte
Upgrade-Prozedur beschrieben.
Dieser Abschnitt beschreibt die Verwendung von Triggern in MySQL 5.1 sowie einige Einschränkungen für die Nutzung von Triggern. Weitere Beschränkungen im Zusammenhang mit Triggern sind in Abschnitt I.1, „Beschränkungen bei gespeicherten Routinen und Triggern“, geschildert.
Ein Trigger ist ein benanntes Datenbankobjekt, das mit einer Tabelle verbunden ist und aktiviert wird, wenn für diese Tabelle ein bestimmtes Ereignis eintritt. Trigger werden beispielsweise verwendet, um Werte zu überprüfen, die in eine Tabelle eingesetzt werden sollen, oder um Berechnungen mit Werten auszuführen, die zu einem Update gehören.
Ein Trigger ist mit einer Tabelle verbunden und wird aktiviert,
wenn eine INSERT
-, DELETE
-
oder UPDATE
-Anweisung für diese Tabelle
ausgeführt wird. Ein Trigger kann so eingestellt werden, dass er
entweder vor oder nach der auslösenden Anweisung aktiviert wird.
So können Sie beispielsweise veranlassen, dass ein Trigger
jeweils vor jeder Zeilenlöschung oder nach jeder Zeilenänderung
aktiviert wird.
Ein Trigger wird mit CREATE TRIGGER
erstellt
und mit DROP TRIGGER
gelöscht. Die Syntax
dieser Anweisungen wird unter Abschnitt 20.1, „CREATE TRIGGER
“,
und Abschnitt 20.2, „DROP TRIGGER
“, erklärt.
Das folgende einfache Beispiel verbindet einen Trigger mit einer
Tabelle für den Fall von INSERT
-Anweisungen.
Er fungiert als Sammelbecken, um die Werte zu addieren, die in
eine der Tabellenspalten eingefügt werden.
Die folgenden Anweisungen legen eine Tabelle und einen Trigger für sie an:
mysql>CREATE TABLE account (acct_num INT, amount DECIMAL(10,2));
mysql>CREATE TRIGGER ins_sum BEFORE INSERT ON account
->FOR EACH ROW SET @sum = @sum + NEW.amount;
Die CREATE TRIGGER
-Anweisung erzeugt einen
Trigger namens ins_sum
, der mit der
account
-Tabelle verbunden ist. Außerdem
enthält sie Klauseln, um die Aktivierungszeit des Triggers, das
Trigger-Ereignis und die eigentlichen Trigger-Aktionen
festzulegen:
Das Schlüsselwort BEFORE
zeigt die
Aktivierungszeit des Triggers an. Hier sollte der Trigger in
Aktion treten, bevor eine Zeile in die Tabelle eingefügt
wird. Das zweite hier zulässige Schlüsselwort ist
AFTER
.
Das Schlüsselwort INSERT
zeigt das
Ereignis an, welches den Trigger aktiviert. In unserem
Beispiel lassen INSERT
-Anweisungen den
Trigger aktiv werden. Sie können jedoch auch Trigger für
DELETE
- und
UPDATE
-Anweisungen anlegen.
Hinter dem FOR EACH ROW
steht, welche
Anweisung jedes Mal ausgeführt werden soll, wenn der Trigger
in Aktion tritt, was in diesem Fall für jede von der
auslösenden Anweisung betroffene Zeile einmal passiert. Die
Trigger-Anweisung in diesem Beispiel ist ein einfaches
SET
, das die Werte, die in die
amount
-Spalte eingefügt werden, sammelt.
Die Anweisung nennt die Spalte NEW.amount
und meint damit „den Wert, der in die neue Zeile der
Spalte amount
eingesetzt werden
soll“.
Um den Trigger verwenden zu können, setzen Sie die Variable,
welche die Werte sammelt, auf null, führen eine
INSERT
-Anweisung aus und schauen, welchen Wert
die Variable danach hat:
mysql>SET @sum = 0;
mysql>INSERT INTO account VALUES(137,14.98),(141,1937.50),(97,-100.00);
mysql>SELECT @sum AS 'Total amount inserted';
+-----------------------+ | Total amount inserted | +-----------------------+ | 1852.48 | +-----------------------+
In diesem Fall hat @sum
nach Ausführung der
INSERT
-Anweisung den Wert 14.98 +
1937.50 - 100
, also 1852.48
.
Gelöscht wird der Trigger mit der DROP
TRIGGER
-Anweisung. Wenn der Trigger nicht im
Standardschema definiert ist, müssen Sie außerdem den
Schemanamen dazusetzen:
mysql> DROP TRIGGER test.ins_sum;
Da Trigger-Namen im Schema-Namensraum liegen, müssen alle Trigger innerhalb eines Schemas eindeutige Namen haben. Trigger in unterschiedlichen Schemata können dagegen gleich heißen.
Zusätzlich zu dem Erfordernis, dass Trigger-Namen in einem Schema
eindeutig sein müssen, gibt es noch weitere Einschränkungen
betreffend die Typen der Trigger. Insbesondere dürfen keine zwei
Trigger einer Tabelle dieselbe Aktivierungszeit und dasselbe
Aktivierungsereignis haben. Sie können also nicht zwei
BEFORE INSERT
-Trigger oder zwei AFTER
UPDATE
-Trigger für dieselbe Tabelle definieren.
Normalerweise dürfte diese Beschränkung jedoch keine Rolle
spielen, da ein Trigger auch so definiert werden kann, dass er
mehrere Anweisungen in einem BEGIN ...
END
-Block als zusammengesetzte Anweisung hinter dem
FOR EACH ROW
ausführt. (Weiter unten in diesem
Abschnitt finden Sie ein Beispiel dazu.)
Mit den Schlüsselwörtern OLD
und
NEW
können Sie auf Spalten zugreifen, die von
einem Trigger betroffen sind. (Die Groß- und Kleinschreibung
spielt für OLD
und NEW
keine Rolle.) In einem INSERT
-Trigger kann nur
NEW.
benutzt
werden, da keine alte Zeile vorhanden ist, und in einem
col_name
DELETE
-Trigger nur
OLD.
, da
keine neue Zeile vorhanden ist. In einem
col_name
UPDATE
-Trigger können sowohl
OLD.
für
den Verweis auf Tabellenzeilen vor der Änderung als auch
col_name
NEW.
für
einen Verweis auf die geänderten Zeilen verwendet werden.
col_name
Ein Spaltenname mit OLD
ist schreibgeschützt.
Sie können ihn benutzen (sofern Sie das
SELECT
-Recht für ihn haben), aber nicht
ändern. Ein Spaltenname mit NEW
kann mit dem
entsprechenden SELECT
-Recht angesprochen
werden. In einem BEFORE
-Trigger können Sie
auch seinen Wert mit SET
NEW.
ändern, sofern Sie das
col_name
=
value
UPDATE
-Recht dafür haben. Dies bedeutet, dass
Sie einen Trigger einsetzen können, um die Werte zu ändern, die
in eine neue Zeile eingefügt oder mit denen eine Zeile
aktualisiert wird.
In einem BEFORE
-Trigger ist der
NEW
-Wert für eine
AUTO_INCREMENT
-Spalte 0 und nicht die
automatisch generierte laufende Nummer, die angelegt wird, wenn
der neue Datensatz tatsächlich eingefügt wird.
OLD
und NEW
sind
MySQL-Erweiterungen für Trigger.
Mit dem BEGIN ... END
-Konstrukt können Sie
einen Trigger definieren, der mehrere Anweisungen ausführt.
Innerhalb des BEGIN
-Blocks können Sie auch
eine andere für gespeicherte Routinen zulässige Syntax
verwenden, wie beispielsweise Bedingungsanweisungen und Schleifen.
Doch wie für gespeicherte Routinen gilt auch für Trigger: Wenn
Sie das mysql-Programm verwenden, um einen
Trigger für mehrere Anweisungen zu definieren, muss das
Trennzeichen für die mysql-Anweisung auf etwas
anderes eingestellt werden, damit das Begrenzungszeichen
;
für Anweisungen in der Trigger-Definition
zur Verfügung steht. Dies wird im folgenden Beispiel deutlich, in
dem ein UPDATE
-Trigger definiert wird, der für
jede Zeilenänderung den neuen Wert prüft und diesen so
modifiziert, dass er im Bereich zwischen 0 und 100 liegt. Dieser
Trigger muss ein BEFORE
-Trigger sein, da der
Wert überprüft werden muss, bevor er in die Zeile eingesetzt
wird:
mysql>delimiter //
mysql>CREATE TRIGGER upd_check BEFORE UPDATE ON account
->FOR EACH ROW
->BEGIN
->IF NEW.amount < 0 THEN
->SET NEW.amount = 0;
->ELSEIF NEW.amount > 100 THEN
->SET NEW.amount = 100;
->END IF;
->END;//
mysql>delimiter ;
Unter Umständen ist es einfacher, eine gespeicherte Prozedur
separat zu definieren und dann im Trigger mit einer einfachen
CALL
-Anweisung aufzurufen. Dies ist auch dann
von Vorteil, wenn Sie dieselbe Routine in mehreren Triggern
aufrufen möchten.
In Anweisungen, die ein aktivierter Trigger ausführt, ist nicht alles erlaubt:
Der Trigger darf nicht mit einer
CALL
-Anweisung gespeicherte Prozeduren
aufrufen, die Daten an den Client zurückgeben oder
dynamisches SQL nutzen. (Gespeicherte Prozeduren dürfen
jedoch an den Trigger Daten über OUT
- oder
INOUT
-Parameter zurückgeben.)
Der Trigger darf keine Anweisungen benutzen, die explizit oder
implizit eine Transaktion starten oder beenden, wie etwa
START TRANSACTION
,
COMMIT
oder ROLLBACK
.
Mit Fehlern bei der Ausführung eines Triggers geht MySQL folgendermaßen um:
Bei einem Fehler in einem BEFORE
-Trigger
wird die Operation auf der betreffenden Zeile nicht
ausgeführt.
Ein AFTER
-Trigger wird nur ausgeführt,
wenn der BEFORE
-Trigger (wenn vorhanden)
und die Zeilenoperation beide erfolgreich waren.
Ein Fehler während eines BEFORE
- oder
AFTER
-Triggers lässt die gesamte Anweisung
scheitern, durch die der Trigger aufgerufen wurde.
Wenn auf einer Transaktionstabelle ein Trigger (und mit ihm die gesamte Anweisung) scheitert, müssen alle durch diese Anweisung verursachten Änderungen zurückgerollt werden. Da ein solcher Rollback bei Tabellen, die nicht an einer Transaktion beteiligt sind, unmöglich ist, bleiben dort alle bis zu dem Fehler eingetretenen Änderungen wirksam, obwohl die Anweisung eigentlich gescheitert ist.
Inhaltsverzeichnis
Views (auch veränderbare) stehen in MySQL Server 5.1 zur Verfügung.
Dieses Kapitel behandelt folgende Themen:
Erzeugen von Views mit CREATE VIEW
und
Ändern von Views mit ALTER VIEW
Löschen von Views mit DROP VIEW
Anzeigen der Metadaten von Views mit SHOW CREATE
VIEW
Die Beschränkungen für den Einsatz von Views werden in Abschnitt I.4, „Beschränkungen bei Views“, behandelt.
Um Views nach einem Upgrade von einer älteren Version auf MySQL 5.1 benutzen zu können, sollten Sie auch Ihre Berechtigungstabellen aktualisieren, damit sie die View-Berechtigungen enthalten. Siehe auch Abschnitt 5.6, „mysql_fix_privilege_tables — Upgrade von MySQL-Systemtabellen“.
ALTER [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}] [DEFINER = {user
| CURRENT_USER }] [SQL SECURITY { DEFINER | INVOKER }] VIEWview_name
[(column_list
)] ASselect_statement
[WITH [CASCADED | LOCAL] CHECK OPTION]
Diese Anweisung ändert die Definition einer vorhandenen View. Die
Syntax ähnelt der von CREATE VIEW
. Siehe auch
Abschnitt 21.2, „CREATE VIEW
“. Für diese Anweisung benötigen Sie
für die View die Berechtigungen CREATE VIEW
und DROP
und zusätzlich die
Spaltenberechtigungen, die in der
SELECT
-Anweisung verlangt werden.
CREATE [OR REPLACE] [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}] [DEFINER = {user
| CURRENT_USER }] [SQL SECURITY { DEFINER | INVOKER }] VIEWview_name
[(column_list
)] ASselect_statement
[WITH [CASCADED | LOCAL] CHECK OPTION]
Diese Anweisung legt eine neue View an oder ersetzt eine
vorhandene, wenn die OR REPLACE
-Klausel
angegeben wurde. Das select_statement
ist eine SELECT
-Anweisung, welche die
Definition der View liefert. Diese
SELECT
-Anweisung kann sich auf Basistabellen
oder andere Views beziehen.
Diese Anweisung erfordert das CREATE VIEW
-Recht
für die View sowie Spaltenrechte für die in der
SELECT
-Anweisung referenzierten Spalten. Für
Spalten, die anderswo in der SELECT
-Anweisung
angesprochen werden, benötigen Sie das
SELECT
-Recht. Wenn die OR
REPLACE
-Klausel angegeben wurde, benötigen Sie
überdies das DROP
-Recht für die View.
Eine View gehört zu einer Datenbank. Nach Voreinstellung wird
eine neue View immer in der Standarddatenbank angelegt. Um sie
explizit in einer bestimmten Datenbank anzulegen, geben Sie bei
ihrer Erzeugung ihren Namen als
db_name.view_name
an.
mysql> CREATE VIEW test.v AS SELECT * FROM t;
Da Basistabellen und Views in einer Datenbank denselben Namensraum teilen, darf eine Datenbank nicht eine Basistabelle und eine View gleichen Namens enthalten.
Views müssen eindeutige Spaltennamen ohne Doppelnennungen haben,
genau wie Basistabellen. Nach Voreinstellung werden die Namen von
Spalten, die mit der SELECT
-Anweisung abgefragt
werden, auch als Spaltennamen für die View genutzt. Wenn Sie
explizite Namen für die View-Spalten einsetzen möchten, können
Sie optional eine column_list
-Klausel
mit einer Liste von kommagetrennten Bezeichnern angeben. Die
Anzahl der Namen in der column_list
muss gleich der Anzahl der von der
SELECT
-Anweisung abgefragten Spalten sein.
Die von der SELECT
-Anweisung abgefragten
Spalten können einfache Verweise auf Tabellenspalten sein, oder
auch Ausdrücke mit Funktionen, Konstantenwerten, Operatoren und
so weiter.
Wird der Name einer Tabelle oder View in einer
SELECT
-Anweisung nicht weiter qualifiziert,
wird davon ausgegangen, dass er sich auf die Standarddatenbank
bezieht. Eine View kann jedoch auch auf Tabellen oder Views in
anderen Datenbanken Bezug nehmen, wenn sie die Namen dieser
Tabellen oder Views mit dem Namen der betreffenden Datenbank
qualifiziert.
Eine View kann aus vielen Arten von
SELECT
-Anweisungen angelegt werden. Sie kann
Basistabellen oder andere Views verwenden, ebenso wie Joins,
UNION
und Unterabfragen. Die
SELECT
-Anweisung muss nicht unbedingt Tabellen
verwenden. Das folgende Beispiel definiert eine View, die zwei
Spalten aus einer anderen Tabelle und darüber hinaus einen aus
diesen beiden Spalten berechneten Ausdruck abfragt:
mysql>CREATE TABLE t (qty INT, price INT);
mysql>INSERT INTO t VALUES(3, 50);
mysql>CREATE VIEW v AS SELECT qty, price, qty*price AS value FROM t;
mysql>SELECT * FROM v;
+------+-------+-------+ | qty | price | value | +------+-------+-------+ | 3 | 50 | 150 | +------+-------+-------+
Für die Definition einer View gelten folgende Beschränkungen:
Die SELECT
-Anweisung darf in der
FROM
-Klausel keine Unterabfrage enthalten.
Die SELECT
-Anweisung darf keine System-
oder Benutzervariablen verwenden.
Die SELECT
-Anweisung darf keine Parameter
enthalten, die vorbereitete Anweisungen sind.
Innerhalb einer gespeicherten Routine darf die Definition keine Routinenparameter oder lokalen Variablen referenzieren.
Eine Tabelle oder View, die in der Definition angegeben wird,
muss auch vorhanden sein. Nach der Erzeugung der View kann
allerdings eine Tabelle oder View, die in der Definition
angesprochen wird, gelöscht werden. Um eine View-Definition
auf derartige Probleme hin zu untersuchen, verwenden Sie die
CHECK TABLE
-Anweisung.
Die Definition darf weder eine
TEMPORARY
-Tabelle referenzieren noch eine
TEMPORARY
-View erzeugen.
Die in der View-Definition verwendeten Tabellen müssen vorhanden sein.
Sie dürfen mit einer View keinen Trigger verbinden.
Eine ORDER BY
-Klausel in einer View-Definition
ist zwar erlaubt, wird aber ignoriert, wenn Sie eine View mit
einer SELECT
-Anweisung abfragen, die eine
eigene ORDER BY
-Klausel hat.
Die sonstigen Optionen oder Klauseln in der Definition werden den
Optionen und Klauseln der Anweisung hinzugefügt, welche die View
referenziert, allerdings mit undefiniertem Ergebnis. Wenn
beispielsweise eine View-Definition eine
LIMIT
-Klausel enthält und Sie diese View mit
einer Anweisung abfragen, die ihre eigene
LIMIT
-Klausel hat, ist nicht definiert, welche
der beiden Klauseln gilt. Dasselbe gilt für Optionen wie
ALL
, DISTINCT
oder
SQL_SMALL_RESULT
, die auf das Schlüsselwort
SELECT
folgen, sowie für Klauseln wie
INTO
, FOR UPDATE
,
LOCK IN SHARE MODE
und
PROCEDURE
.
Wenn Sie eine View anlegen und dann die Verarbeitungsumgebung für Anfragen ändern, indem Sie Systemvariablen umstellen, kann sich dies auf die Ergebnisse der View auswirken:
mysql>CREATE VIEW v AS SELECT CHARSET(CHAR(65)), COLLATION(CHAR(65));
Query OK, 0 rows affected (0.00 sec) mysql>SET NAMES 'latin1';
Query OK, 0 rows affected (0.00 sec) mysql>SELECT * FROM v;
+-------------------+---------------------+ | CHARSET(CHAR(65)) | COLLATION(CHAR(65)) | +-------------------+---------------------+ | latin1 | latin1_swedish_ci | +-------------------+---------------------+ 1 row in set (0.00 sec) mysql>SET NAMES 'utf8';
Query OK, 0 rows affected (0.00 sec) mysql>SELECT * FROM v;
+-------------------+---------------------+ | CHARSET(CHAR(65)) | COLLATION(CHAR(65)) | +-------------------+---------------------+ | utf8 | utf8_general_ci | +-------------------+---------------------+ 1 row in set (0.00 sec)
Die DEFINER
- und die SQL
SECURITY
-Klausel geben an, in welchem Sicherheitskontext
die Zugriffsberechtigungen zum Zeitpunkt des Aufrufs der View
geprüft werden. Diese Klauseln kamen in MySQL 5.1.2 neu hinzu.
CURRENT_USER
kann auch als
CURRENT_USER()
angegeben werden.
In einer gespeicherten Routine, die mit dem Merkmal SQL
SECURITY DEFINER
definiert ist, gibt
CURRENT_USER
den Erzeuger der Routine zurück.
Dies wirkt sich auch auf eine innerhalb einer solchen Routine
definierte View aus, wenn in der View-Definition der
DEFINER
als CURRENT_USER
angegeben ist.
Nach Voreinstellung ist der DEFINER
der
Benutzer, der die CREATE VIEW
-Anweisung
ausführt. (Dies ist dasselbe wie DEFINER =
CURRENT_USER
.) Wird ein
user
-Wert angegeben, dann als
MySQL-Konto im Format
'
(dasselbe Format, das auch in der
user_name
'@'host_name
'GRANT
-Anweisung verwendet wird. Die Werte
user_name
und
host_name
sind beide erforderlich.
Wenn Sie die DEFINER
-Klausel angeben, können
Sie keinen anderen Benutzer als sich selbst einsetzen, sofern Sie
nicht über das SUPER
-Recht verfügen. Die
folgenden Regeln legen fest, welche Werte für
DEFINER
zulässig sind:
Wenn Sie nicht das SUPER
-Recht haben, ist
der einzig zulässige Wert für
user
Ihr eigenes Konto, das Sie
entweder wörtlich oder mit CURRENT_USER
angeben können. Auf ein anderes Konto dürfen Sie den
DEFINER
nicht einstellen.
Wenn Sie über das SUPER
-Recht verfügen,
dürfen Sie jeden Kontonamen angeben, wenn er nur syntaktisch
korrekt ist. Sollte das angegebene Konto nicht existieren,
wird eine Warnung ausgegeben.
Mit dem Merkmal SQL SECURITY
wird festgelegt,
welches MySQL-Konto zur Prüfung von Zugriffsberechtigungen für
die View herangezogen wird, wenn diese ausgeführt wird. Hier ist
das Merkmal DEFINER
oder
INVOKER
zulässig, um anzuzeigen, dass die View
von ihrem Erzeuger oder ihrem Aufrufer ausgeführt werden darf.
Der Standardwert für SQL SECURITY
ist
DEFINER
.
Seit MySQL 5.1.2 (der Version, in der die Klauseln
DEFINER
und SQL SECURITY
erstmals implementiert waren) werden die Berechtigungen für Views
folgendermaßen geprüft:
Zum Definitionszeitpunkt einer View benötigt ihr Erzeuger die Berechtigungen zum Zugriff auf die von seiner View benutzten Objekte der obersten Ebene. Wenn in der Definition einer View beispielsweise eine gespeicherte Funktion angesprochen wird, können nur die Berechtigungen zum Aufruf dieser Funktion geprüft werden. Die Berechtigungen, die erforderlich sind, wenn die Funktion läuft, können erst bei ihrer Ausführung geprüft werden: Für unterschiedliche Aufrufe der Funktion können unterschiedliche Ausführungspfade in ihr eingeschlagen werden.
Bei der Ausführung der View werden die Berechtigungen für
die von ihr benutzten Objekte mit den Berechtigungen ihres
Erzeugers oder Aufrufers verglichen, je nachdem, ob das
Merkmal SQL SECURITY
als
DEFINER
oder INVOKER
angegeben ist.
Wenn die Ausführung einer View die Ausführung einer
gespeicherten Funktion verursacht, werden die Berechtigungen
für Anweisungen im Rahmen dieser Funktion je nachdem
überprüft, ob die Funktion das SQL
SECURITY
-Merkmal DEFINER
oder
INVOKER
hat. Ist das Sicherheitsmerkmal
DEFINER
, läuft die Funktion mit den
Berechtigungen ihres Erzeugers; ist es
INVOKER
, läuft die Funktion mit den
Berechtigungen, die durch das SQL
SECURITY
-Merkmal der View vorgegeben sind.
Vor MySQL 5.1.2 (also vor der Implementierung der
DEFINER
- und der SQL
SECURITY
-Klausel) wurden die Berechtigungen für die in
einer View benutzten Objekte bei der Erzeugung dieser View
geprüft.
Beispiel: Eine View könnte von einer gespeicherten Funktion
abhängen, die ihrerseits andere gespeicherte Routinen aufruft. So
ruft zum Beispiel die folgende View eine gespeicherte Funktion
namens f()
auf:
CREATE VIEW v AS SELECT * FROM t WHERE t.id = f(t.name);
Angenommen, f()
enthält eine Anweisung wie
diese:
IF name IS NULL then CALL p1(); ELSE CALL p2(); END IF;
Die Berechtigungen zur Ausführung von Anweisungen innerhalb von
f()
müssen geprüft werden, wenn
f()
ausgeführt wird. Dies könnte je nach dem
Ausführungspfad für f()
bedeuten, dass
entweder die Berechtigungen für p1()
oder die
für p2()
gebraucht werden. Diese
Berechtigungen müssen zur Laufzeit geprüft werden, und der
Benutzer, der sie besitzen muss, wird anhand des SQL
SECURITY
-Werts der Funktion f()
und
der View v
bestimmt.
Die DEFINER
- und die SQL
SECURITY
-Klausel für Views sind Erweiterungen des
SQL-Standards. Im Standard-SQL werden Views nach den Regel für
SQL SECURITY INVOKER
behandelt.
Wenn Sie eine View aufrufen, die vor MySQL 5.0.13/5.1.2 erzeugt
wurde, wird sie behandelt, als sei sie mit einer SQL
SECURITY INVOKER
-Klausel und Ihrem eigenen Konto als
DEFINER
angelegt worden. Da jedoch der
tatsächliche Erzeuger unbekannt ist, gibt MySQL eine Warnung aus.
Um die Warnung abzuschalten, genügt es, die View mit einer
DEFINER
-Klausel erneut zu definieren.
Die optionale ALGORITHM
-Klausel ist ebenfalls
eine MySQL-Erweiterung des Standard-SQL.
ALGORITHM
kann drei Werte annehmen:
MERGE
, TEMPTABLE
oder
UNDEFINED
. Wenn keine
ALGORITHM
-Klausel angegeben wurde, ist der
Standardalgorithmus UNDEFINED
. Der Algorithmus
nimmt Einfluss darauf, wie MySQL die View verarbeitet.
Ist MERGE
der Algorithmus, wird der Text der
Anweisung, in welcher die View benutzt wird, mit der
View-Definition verschmolzen, sodass Teile der View-Definition die
entsprechenden Teile der Anweisung ersetzen.
Wenn TEMPTABLE
als Algorithmus eingestellt
wurde, werden die Ergebnisse der View in eine temporäre Tabelle
geladen, die dann zur Ausführung der Anweisung genutzt wird.
Ist der Algorithmus UNDEFINED
, sucht sich MySQL
den passenden Algorithmus selbst aus. Wo immer es möglich ist,
wird MERGE
gegenüber
TEMPTABLE
bevorzugt, da
MERGE
normalerweise effizienter ist und eine
View bei Verwendung einer temporären Tabelle unveränderbar wird.
Ein Grund, explizit TEMPTABLE
zu verlangen,
wäre der, dass Sperren auf zugrunde liegenden Tabellen aufgehoben
werden können, nachdem die temporäre Tabelle angelegt wurde und
bevor sie benutzt wird, um die Verarbeitung der Anweisung
abzuschließen. So könnte eine schnellere Freigabe der Sperre als
mit dem MERGE
-Algorithmus erreicht werden, um
andere Clients, die die View benötigen, nicht so lange zu
blockieren.
Es gibt drei Gründe, als View-Algorithmus
UNDEFINED
einzustellen:
Keine ALGORITHM
-Klausel in der
CREATE VIEW
-Anweisung.
Die CREATE VIEW
-Anweisung enthält eine
explizite ALGORITHM = UNDEFINED
-Klausel.
Für eine View, die nur mit einer temporären Tabelle
verarbeitet werden kann, wurde ALGORITHM =
MERGE
angegeben. In diesem Fall generiert MySQL eine
Warnung und stellt den Algorithmus auf
UNDEFINED
ein.
Wie bereits gesagt, werden durch den
MERGE
-Algorithmus die entsprechenden Teile
einer View-Definition mit Teilen der die View referenzierenden
Anweisung zusammengeführt. Die folgenden Beispiele sollen die
Funktionsweise des MERGE
-Algorithmus kurz
verdeutlichen. Die Beispiele legen eine View namens
v_merge
zugrunde, die folgendermaßen definiert
ist:
CREATE ALGORITHM = MERGE VIEW v_merge (vc1, vc2) AS SELECT c1, c2 FROM t WHERE c3 > 100;
Beispiel 1: Angenommen, wir geben folgende Anweisung:
SELECT * FROM v_merge;
MySQL würde diese Anweisung wie folgt bearbeiten:
v_merge
wird t
*
wird vc1, vc2
, was
c1, c2
entspricht.
Die WHERE
-Klausel der View wird
hinzugefügt.
Im Ergebnis wird folgende Anweisung ausgeführt:
SELECT c1, c2 FROM t WHERE c3 > 100;
Beispiel 2: Dieses Mal ist unsere Anweisung wie folgt:
SELECT * FROM v_merge WHERE vc1 < 100;
Diese Anweisung wird ähnlich wie die vorherige behandelt, nur
dass hier vc1 < 100
zu c1 <
100
wird und die WHERE
-Klausel der
View der WHERE
-Klausel der Anweisung mit einem
AND
hinzugefügt wird (und runde Klammern
sicherstellen, dass die Teile der Klausel in der richtigen
Reihenfolge ausgeführt werden). Infolgedessen wird folgende
Anweisung ausgeführt:
SELECT c1, c2 FROM t WHERE (c3 > 100) AND (c1 < 100);
Letztlich hat die Anweisung eine WHERE
-Klausel
in der folgenden Form:
WHERE (select WHERE) AND (view WHERE)
Der MERGE
-Algorithmus erfordert eine
Eins-zu-eins-Beziehung zwischen den Zeilen der View und den Zeilen
der zugrunde liegenden Tabelle. Wenn diese Beziehung nicht gilt,
muss stattdessen eine temporäre Tabelle benutzt werden. Die
Eins-zu-eins-Beziehung fehlt, wenn die View eines der folgenden
Konstrukte enthält:
Aggregatfunktionen (SUM()
,
MIN()
, MAX()
,
COUNT()
usw.)
DISTINCT
GROUP BY
HAVING
UNION
oder UNION ALL
wenn die View nur Literalwerte verwendet (in diesem Fall gibt es gar keine zugrunde liegende Tabelle)
Manche Views sind veränderbar und können somit in Anweisungen
wie UPDATE
, DELETE
oder
INSERT
genutzt werden, um die Inhalte der
zugrunde liegenden Tabelle zu ändern. Damit eine View
veränderbar ist, muss eine Eins-zu-eins-Beziehung zwischen den
Zeilen der View und den Zeilen der zugrunde liegenden Tabelle
existieren. Es gibt also eine Reihe von Konstrukten, durch die
eine View nicht mehr veränderbar wird. Hierzu gehören folgende:
Aggregatfunktionen (SUM()
,
MIN()
, MAX()
,
COUNT()
usw.)
DISTINCT
GROUP BY
HAVING
UNION
oder UNION ALL
eine Unterabfrage in der Select-Liste
Join
eine unveränderbare View in der
FROM
-Klausel
eine Unterabfrage in der WHERE
-Klausel, die
eine Tabelle in der FROM
-Klausel
referenziert.
wenn die View nur Literalwerte verwendet (in diesem Fall gibt es gar keine zugrunde liegende Tabelle)
ALGORITHM = TEMPTABLE
(die Verwendung einer
temporären Tabelle macht eine View immer unveränderbar)
Was Einfügungen betrifft (also die Veränderbarkeit mit
INSERT
-Anweisungen), so ist eine veränderbare
View für Einfügungen nutzbar, wenn ihre Spalten zusätzlich
folgende Anforderungen erfüllen:
Ein Spaltenname darf nicht mehrfach auftreten.
Die View muss alle Spalten der Basistabelle enthalten, die keinen Standardwert haben.
Die View-Spalten müssen einfache Spaltenreferenzen und keine abgeleiteten Spalten sein. Eine abgeleitete Spalte ist eine Spalte, die nicht einfach benannt werden kann, sondern von einem Ausdruck abgeleitet wird, wie in den folgenden Beispielen:
3.14159
col1 + 3
UPPER(col2)
col3 / col4
(subquery
)
Eine View mit einer Mischung von einfachen Spaltenreferenzen und abgeleiteten Spalten ist nicht für Einfügungen geeignet, kann aber veränderbar sein, wenn nur diejenigen Spalten geändert werden, die nicht abgeleitet sind. Betrachten Sie folgende View:
CREATE VIEW v AS SELECT col1, 1 AS col2 FROM t;
Diese col2
ist von einem Ausdruck abgeleitet.
Sie ist jedoch veränderbar, wenn das Update nicht versucht,
col2
zu verändern. Das folgende Update ist
erlaubt:
UPDATE v SET col1 = 0;
Dagegen ist das nun folgende Update unzulässig, weil es versucht, eine abgeleitete Spalte zu ändern:
UPDATE v SET col2 = 0;
Manchmal kann eine View aus mehreren Tabellen veränderbar sein,
sofern sie mit dem MERGE
-Algorithmus
verarbeitet wird. Damit das funktioniert, muss die View einen
Inner Join verwenden (keinen Outer Join und keine
UNION
). Außerdem kann nur eine einzige Tabelle
in der View-Definition verändert werden, sodass die
SET
-Klausel nur Spalten aus dieser einen
Tabelle der View aufführen darf. Views, die UNION
ALL
verwenden, sind selbst dann nicht erlaubt, wenn sie
theoretisch veränderbar wären, da die Implementierung für ihre
Verarbeitung temporäre Tabellen einsetzt.
Bei einer veränderbaren View mit mehreren Tabellen kann auch
INSERT
funktionieren, sofern nur eine einzelne
der Tabellen angesprochen wird. DELETE
ist
jedoch nicht möglich.
Die WITH CHECK OPTION
-Klausel kann für eine
veränderbare View benutzt werden, um Einfügungen oder
Änderungen an Zeilen zu verhindern, für welche das
select_statement
in der
WHERE
-Klausel nicht gilt.
In einer WITH CHECK OPTION
-Klausel einer
veränderbaren View legen die Schlüsselwörter
LOCAL
und CASCADED
den
Rahmen der Überprüfungen fest, wenn die View auf Grundlage einer
anderen View definiert wurde. Das Schlüsselwort
LOCAL
schränkt die CHECK
OPTION
auf die View ein, die gerade definiert wird,
während CASCADED
dafür sorgt, dass sich die
Prüfungen auch auf die zugrunde liegenden Views erstrecken. Wenn
keines der beiden Schlüsselwörter angegeben ist, ist
CASCADED
der Standard. Betrachten Sie folgende
Definitionen für die nachfolgende Tabelle und die Views:
mysql>CREATE TABLE t1 (a INT);
mysql>CREATE VIEW v1 AS SELECT * FROM t1 WHERE a < 2
->WITH CHECK OPTION;
mysql>CREATE VIEW v2 AS SELECT * FROM v1 WHERE a > 0
->WITH LOCAL CHECK OPTION;
mysql>CREATE VIEW v3 AS SELECT * FROM v1 WHERE a > 0
->WITH CASCADED CHECK OPTION;
Hier werden die Views v2
und
v3
mit einer anderen View namens
v1
definiert. Da v2
die
Check-Option LOCAL
hat, werden Einfügungen nur
anhand der Vorgaben für v2
getestet, während
die View v3
mit ihrer Prüfoption
CASCADED
für Einfügungen hier nicht nur die
eigenen, sondern auch die Prüfoptionen der zugrunde liegenden
Views berücksichtigen muss. Die folgende Anweisung
veranschaulicht die Unterschiede:
mysql>INSERT INTO v2 VALUES (2);
Query OK, 1 row affected (0.00 sec) mysql>INSERT INTO v3 VALUES (2);
ERROR 1369 (HY000): CHECK OPTION failed 'test.v3'
Die Veränderbarkeit von Views wird durch die Systemvariable
updatable_views_with_limit
beeinflusst. Siehe
auch Abschnitt 5.2.2, „Server-Systemvariablen“.
DROP VIEW [IF EXISTS]view_name
[,view_name
] ... [RESTRICT | CASCADE]
DROP VIEW
löscht eine oder mehrere Views.
Hierfür benötigen Sie für jede View das
DROP
-Recht.
Die IF EXISTS
-Klausel verhindert Fehler
aufgrund nicht existierender Views. Wenn diese Klausel angegeben
ist, wird für jede View, die nicht existiert, eine
NOTE
generiert. Siehe auch
Abschnitt 13.5.4.25, „SHOW WARNINGS
“.
RESTRICT
und CASCADE
werden
zwar geparst, aber nicht beachtet.
SHOW CREATE VIEW view_name
Mit der folgenden CREATE VIEW
-Anweisung wird
die gegebene View erzeugt.
mysql> SHOW CREATE VIEW v;
+------+----------------------------------------------------+
| View | Create View |
+------+----------------------------------------------------+
| v | CREATE VIEW `test`.`v` AS select 1 AS `a`,2 AS `b` |
+------+----------------------------------------------------+
Informationen über View-Objekte erhalten Sie auch über ihr
INFORMATION_SCHEMA
, das eine
VIEWS
-Tabelle enthält. Siehe
Abschnitt 22.15, „Die Tabelle INFORMATION_SCHEMA VIEWS
“.
Inhaltsverzeichnis
INFORMATION_SCHEMA SCHEMATA
INFORMATION_SCHEMA TABLES
INFORMATION_SCHEMA COLUMNS
INFORMATION_SCHEMA STATISTICS
INFORMATION_SCHEMA USER_PRIVILEGES
INFORMATION_SCHEMA SCHEMA_PRIVILEGES
INFORMATION_SCHEMA TABLE_PRIVILEGES
INFORMATION_SCHEMA COLUMN_PRIVILEGES
INFORMATION_SCHEMA CHARACTER_SETS
INFORMATION_SCHEMA COLLATIONS
INFORMATION_SCHEMA
COLLATION_CHARACTER_SET_APPLICABILITY
INFORMATION_SCHEMA TABLE_CONSTRAINTS
INFORMATION_SCHEMA KEY_COLUMN_USAGE
INFORMATION_SCHEMA ROUTINES
INFORMATION_SCHEMA VIEWS
INFORMATION_SCHEMA TRIGGERS
INFORMATION_SCHEMA PLUGINS
INFORMATION_SCHEMA ENGINES
INFORMATION_SCHEMA PARTITIONS
INFORMATION_SCHEMA EVENTS
INFORMATION_SCHEMA
-TabellenSHOW
-Anweisungen
INFORMATION_SCHEMA
gibt Zugriff auf
Datenbank-Metadaten.
Metadaten sind Informationen über Daten, also beispielsweise der Name einer Datenbank oder Tabelle, der Datentyp einer Spalte, oder Zugriffsberechtigungen. Manchmal werden diese Informationen auch als Data Dictionary oder Systemkatalog bezeichnet.
INFORMATION_SCHEMA
ist die Informationsdatenbank,
also der Ort, an dem Informationen über alle anderen auf dem
betreffenden MySQL Server gepflegten Datenbanken gespeichert werden.
Im INFORMATION_SCHEMA
gibt es eine Reihe von
schreibgeschützten Tabellen. Da diese in Wirklichkeit keine
Basistabellen, sondern Views sind, werden Sie keine Dateien sehen,
die mit ihnen verbunden sind.
Ein Beispiel:
mysql>SELECT table_name, table_type, engine
->FROM information_schema.tables
->WHERE table_schema = 'db5'
->ORDER BY table_name DESC;
+------------+------------+--------+ | table_name | table_type | engine | +------------+------------+--------+ | v56 | VIEW | NULL | | v3 | VIEW | NULL | | v2 | VIEW | NULL | | v | VIEW | NULL | | tables | BASE TABLE | MyISAM | | t7 | BASE TABLE | MyISAM | | t3 | BASE TABLE | MyISAM | | t2 | BASE TABLE | MyISAM | | t | BASE TABLE | MyISAM | | pk | BASE TABLE | InnoDB | | loop | BASE TABLE | MyISAM | | kurs | BASE TABLE | MyISAM | | k | BASE TABLE | MyISAM | | into | BASE TABLE | MyISAM | | goto | BASE TABLE | MyISAM | | fk2 | BASE TABLE | InnoDB | | fk | BASE TABLE | InnoDB | +------------+------------+--------+ 17 rows in set (0.01 sec)
Erklärung: Die Anweisung verlangt eine Liste aller Tabellen der
Datenbank db5
in umgekehrter alphabetischer
Reihenfolge, wobei jeweils nur drei Informationen angezeigt werden
sollen: der Name der Tabelle, ihr Typ und ihre Speicher-Engine.
Jeder MySQL-Benutzer hat das Recht, auf diese Tabellen zuzugreifen, allerdings nur auf diejenigen Tabellenzeilen, die sich auf Objekte beziehen, für welche er die richtigen Zugriffsberechtigungen hat.
Die Anweisung SELECT ... FROM INFORMATION_SCHEMA
ist als ein konsistenteres Mittel gedacht, Zugriff auf die
Informationen zu gewähren, welche die verschiedenen von MySQL
unterstützten SHOW
-Anweisungen geben
(SHOW DATABASES
, SHOW TABLES
usw.). Die Verwendung von SELECT
hat im Vergleich
zu SHOW
folgende Vorteile:
Sie entspricht den Codd'schen Regeln: Jeglicher Zugriff geht auf Tabellen.
Niemand muss eine neue Anweisungssyntax lernen. Da jeder bereits
weiß, wie SELECT
funktioniert, müssen
lediglich die Objektnamen gelernt werden.
Der Implementierer muss sich nicht um Schlüsselwörter Gedanken machen.
Es sind Millionen Varianten für die Ausgabe möglich, nicht nur eine. So erhält man mehr Flexibilität für Anwendungen, die immer wieder andere Metadaten benötigen.
Die Migration ist einfacher, da auch alle anderen DBMS so arbeiten.
Da jedoch SHOW
bei den Angestellten und Nutzern
von MySQL so beliebt ist und eine Abschaffung dieser Anweisung
Verwirrung stiften könnte, genügen die Vorteile der
konventionellen Syntax nicht als Grund, auf SHOW
ganz zu verzichten. Stattdessen gibt es sogar Verbesserungen an
SHOW
in MySQL 5.1. Diese werden in
Abschnitt 22.22, „Erweiterungen der SHOW
-Anweisungen“, genauer beschrieben.
Es gibt keinen Unterschied zwischen den Berechtigungen, die für
SHOW
-Anweisungen erforderlich sind, und jenen,
die zur Datenabfrage aus dem INFORMATION_SCHEMA
benötigt werden. In beiden Fällen müssen Sie irgendeine
Berechtigung für ein Objekt besitzen, um Informationen über es
anzeigen zu lassen.
Die Implementierung der
INFORMATION_SCHEMA
-Tabellenstrukturen in MySQL
entspricht dem ANSI/ISO SQL:2003-Standard Teil 11
Schemata. Unser Ziel ist es, möglichst
weitgehend dem SQL:2003-Core-Feature F021 Basic
information schema zu entsprechen.
Benutzer von SQL Server 2000 (auch dieses System befolgt den
Standard) werden vielleicht starke Ähnlichkeiten bemerken.
Allerdings hat MySQL viele Spalten weggelassen, die für unsere
Implementierung keine Rolle spielen, und stattdessen andere,
MySQL-spezifische Spalten hinzugefügt. Dazu gehört die Spalte
ENGINE
in der Tabelle
INFORMATION_SCHEMA.TABLES
.
Zwar verwenden die anderen DBMS unterschiedliche Namen, wie etwa
syscat
oder system
, aber der
Standardname lautet INFORMATION_SCHEMA
.
Letztlich haben wir eine Datenbank namens
INFORMATION_SCHEMA
vor uns, auch wenn der Server
kein Datenbankverzeichnis hierfür anlegt. Es ist möglich,
INFORMATION_SCHEMA
mit einer
USE
-Anweisung als Standarddatenbank einzustellen,
allerdings können die Tabelleninhalte nur gelesen werden.
Einfügungen, Änderungen oder Löschungen in den Tabellen sind
ausgeschlossen.
Die folgenden Abschnitte beschreiben die Tabellen und Spalten von
INFORMATION_SCHEMA
. Zu jeder Spalte gibt es drei
Informationen:
Der „Standard Name“ gibt den SQL-Standardnamen der Spalte an.
„SHOW
name“ ist der
entsprechende Feldname in der nächstgelegenen
SHOW
-Anweisung (sofern vorhanden).
„Remarks“ sind eventuelle Zusatzinformationen. Wenn
dieses Feld den Wert NULL
hat, bedeutet dies,
dass der Wert der Spalte immer NULL
lautet.
Um keine Namen zu verwenden, die im Standard oder in DB2, SQL Server
oder Oracle reserviert sind, haben wir die Namen der als
„MySQL extension“ markierten Spalten geändert. (So
wurde beispielsweise in der Tabelle TABLES
aus
COLLATION
eine
TABLE_COLLATION
.) Siehe auch die Liste der
reservierten Wörter am Ende dieses Artikels:
http://www.dbazine.com/gulutzan5.shtml.
Die Definition für Zeichenspalten (beispielsweise
TABLES.TABLE_NAME
) ist im Allgemeinen
VARCHAR(
, wobei N
) CHARACTER SET
utf8N
mindestens 64
ist.
Jeder Abschnitt gibt an, welche SHOW
-Anweisung
einer SELECT
-Anweisung entspricht, die
Informationen aus dem INFORMATION_SCHEMA
abfragt,
sofern eine solche Anweisung existiert.
Hinweis: Zurzeit fehlen noch einige Spalten und andere stehen in der verkehrten Reihenfolge. Wir arbeiten daran und werden die Dokumentation bei Änderungen aktualisieren.
Da ein Schema eine Datenbank ist, liefert die Tabelle
SCHEMATA
Informationen über Datenbanken.
Standard Name | SHOW name | Remarks |
CATALOG_NAME | - | NULL |
SCHEMA_NAME | Database | |
DEFAULT_CHARACTER_SET_NAME | ||
DEFAULT_COLLATION_NAME | ||
SQL_PATH | NULL |
Die folgenden Anweisungen sind äquivalent:
SELECT SCHEMA_NAME AS `Database` FROM INFORMATION_SCHEMA.SCHEMATA [WHERE SCHEMA_NAME LIKE 'wild
'] SHOW DATABASES [LIKE 'wild
']
Die Tabelle TABLES
informiert über die
Tabellen in der Datenbank.
Standard Name | SHOW name | Remarks |
TABLE_CATALOG | NULL | |
TABLE_SCHEMA | Table_ ... | |
TABLE_NAME | Table_ ... | |
TABLE_TYPE | ||
ENGINE | Engine | MySQL extension |
VERSION | Version | MySQL extension |
ROW_FORMAT | Row_format | MySQL extension |
TABLE_ROWS | Rows | MySQL extension |
AVG_ROW_LENGTH | Avg_row_length | MySQL extension |
DATA_LENGTH | Data_length | MySQL extension |
MAX_DATA_LENGTH | Max_data_length | MySQL extension |
INDEX_LENGTH | Index_length | MySQL extension |
DATA_FREE | Data_free | MySQL extension |
AUTO_INCREMENT | Auto_increment | MySQL extension |
CREATE_TIME | Create_time | MySQL extension |
UPDATE_TIME | Update_time | MySQL extension |
CHECK_TIME | Check_time | MySQL extension |
TABLE_COLLATION | Collation | MySQL extension |
CHECKSUM | Checksum | MySQL extension |
CREATE_OPTIONS | Create_options | MySQL extension |
TABLE_COMMENT | Comment | MySQL extension |
Hinweise:
TABLE_SCHEMA
und
TABLE_NAME
sind in einer
SHOW
-Anzeige ein einziges Feld,
beispielsweise Table_in_db1
.
Der TABLE_TYPE
sollte BASE
TABLE
oder VIEW
sein. Wenn die
Tabelle eine temporäre ist, ist TABLE_TYPE
= TEMPORARY
. (Da es keine temporären Views
gibt, ist dies eindeutig.)
Die Spalte TABLE_ROWS
ist
NULL
, wenn die Tabelle in der
INFORMATION_SCHEMA
-Datenbank vorliegt. Bei
InnoDB
-Tabellen ist die Zeilenzahl nur eine
ungefähre Schätzung, die für die SQL-Optimierung benötigt
wird.
Es ist kein Standardzeichensatz der Tabelle vorgegeben, doch
TABLE_COLLATION
kommt einem
Standardzeichensatz nahe, da die Namen von Kollationen mit dem
Namen eines Zeichensatzes anfangen.
Die folgenden Anweisungen sind äquivalent:
SELECT table_name FROM INFORMATION_SCHEMA.TABLES [WHERE table_schema = 'db_name
'] [WHERE|AND table_name LIKE 'wild
'] SHOW TABLES [FROMdb_name
] [LIKE 'wild
']
Die Tabelle COLUMNS
informiert über die
Spalten der Tabellen.
Standard Name | SHOW name | Remarks |
TABLE_CATALOG | NULL | |
TABLE_SCHEMA | ||
TABLE_NAME | ||
COLUMN_NAME | Field | |
ORDINAL_POSITION | see notes | |
COLUMN_DEFAULT | Default | |
IS_NULLABLE | Null | |
DATA_TYPE | Type | |
CHARACTER_MAXIMUM_LENGTH | Type | |
CHARACTER_OCTET_LENGTH | ||
NUMERIC_PRECISION | Type | |
NUMERIC_SCALE | Type | |
CHARACTER_SET_NAME | ||
COLLATION_NAME | Collation | |
COLUMN_TYPE | Type | MySQL extension |
COLUMN_KEY | Key | MySQL extension |
EXTRA | Extra | MySQL extension |
COLUMN_COMMENT | Comment | MySQL extension |
Hinweise:
In der SHOW
-Anweisung werden unter
Type
Werte von mehreren verschiedenen
COLUMNS
-Spalten wiedergegeben.
ORDINAL_POSITION
is notwendig, da Sie
vielleicht eines Tages ORDER BY
ORDINAL_POSITION
verwenden werden. Im Gegensatz zu
SHOW
verwendet ein
SELECT
keine automatische Reihenfolge.
CHARACTER_OCTET_LENGTH
sollte gleich
CHARACTER_MAXIMUM_LENGTH
sein, außer bei
Multibytezeichensätzen.
CHARACTER_SET_NAME
kann von
Collation
abgeleitet werden. Wenn Sie
beispielsweise SHOW FULL COLUMNS FROM t
verlangen und in der Collation
-Spalte den
Wert latin1_swedish_ci
entdecken, ist der
Zeichensatz das, was vor dem ersten Unterstrich steht:
latin1
.
Die folgenden Anweisungen sind nahezu äquivalent:
SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_DEFAULT FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = 'tbl_name
' [AND table_schema = 'db_name
'] [AND column_name LIKE 'wild
'] SHOW COLUMNS FROMtbl_name
[FROMdb_name
] [LIKE 'wild
']
Die STATISTICS
-Tabelle liefert Ihnen
Informationen über Tabellenindizes.
Standard Name | SHOW name | Remarks |
TABLE_CATALOG | NULL | |
TABLE_SCHEMA | = Database | |
TABLE_NAME | Table | |
NON_UNIQUE | Non_unique | |
INDEX_SCHEMA | = Database | |
INDEX_NAME | Key_name | |
SEQ_IN_INDEX | Seq_in_index | |
COLUMN_NAME | Column_name | |
COLLATION | Collation | |
CARDINALITY | Cardinality | |
SUB_PART | Sub_part | MySQL extension |
PACKED | Packed | MySQL extension |
NULLABLE | Null | MySQL extension |
INDEX_TYPE | Index_type | MySQL extension |
COMMENT | Comment | MySQL extension |
Hinweise:
Eine Standardtabelle für Indizes gibt es nicht. Die obige
Liste entspricht dem, was SQL Server 2000 als
sp_statistics
zurückliefert, nur dass wir
den Namen QUALIFIER
durch
CATALOG
und OWNER
durch
SCHEMA
ersetzt haben.
Es ist offensichtlich, dass die obige Tabelle und die Ausgabe
von SHOW INDEX
dieselbe Abstammung haben.
Daher besteht bereits eine enge Korrelation.
Die folgenden Anweisungen sind äquivalent:
SELECT * FROM INFORMATION_SCHEMA.STATISTICS WHERE table_name = 'tbl_name
' [AND table_schema = 'db_name
'] SHOW INDEX FROMtbl_name
[FROMdb_name
]
Die Tabelle USER_PRIVILEGES
informiert über
globale Berechtigungen. Diese Information stammt aus der
Berechtigungstabelle mysql.user
.
Standard Name | SHOW name | Remarks |
GRANTEE | '
value | |
TABLE_CATALOG | NULL | |
PRIVILEGE_TYPE | ||
IS_GRANTABLE |
Hinweis:
Dies ist keine Standardtabelle. Sie entnimmt ihre Werte der
Tabelle mysql.user
.
Die Tabelle SCHEMA_PRIVILEGES
liefert
Informationen über Schema-(Datenbank-)Berechtigungen. Diese
Informationen stammen aus der Berechtigungstabelle
mysql.db
.
Standard Name | SHOW name | Remarks |
GRANTEE | '
value | |
TABLE_CATALOG | NULL | |
TABLE_SCHEMA | ||
PRIVILEGE_TYPE | ||
IS_GRANTABLE |
Hinweis:
Dies ist ebenfalls keine Standardtabelle. Ihre Werte erhält
sie aus der Tabelle mysql.db
.
Die Tabelle TABLE_PRIVILEGES
liefert
Informationen über Tabellenberechtigungen.
Diese Informationen stammen aus der Berechtigungstabelle
mysql.tables_priv
.
Standard Name | SHOW name | Remarks |
GRANTEE | '
value | |
TABLE_CATALOG | NULL | |
TABLE_SCHEMA | ||
TABLE_NAME | ||
PRIVILEGE_TYPE | ||
IS_GRANTABLE |
Die folgenden Anweisungen sind nicht äquivalent:
SELECT ... FROM INFORMATION_SCHEMA.TABLE_PRIVILEGES SHOW GRANTS ...
Der PRIVILEGE_TYPE
kann einen (und nur einen)
der folgenden Werte annehmen: SELECT
,
INSERT
, UPDATE
,
REFERENCES
, ALTER
,
INDEX
, DROP
, CREATE
VIEW
.
Die COLUMN_PRIVILEGES
-Tabelle liefert
Informationen über Spaltenberechtigungen. Diese Informationen
entstammen der Berechtigungstabelle
mysql.columns_priv
.
Standard Name | SHOW name | Remarks |
GRANTEE | '
value | |
TABLE_CATALOG | NULL | |
TABLE_SCHEMA | ||
TABLE_NAME | ||
COLUMN_NAME | ||
PRIVILEGE_TYPE | ||
IS_GRANTABLE |
Hinweise:
SHOW FULL COLUMNS
gibt alle Berechtigungen
in einem einzigen Feld und kleingeschrieben aus,
beispielsweise als
select,insert,update,references
. In
COLUMN_PRIVILEGES
steht nur eine einzige
großgeschriebene Berechtigung pro Zeile.
PRIVILEGE_TYPE
kann einen (und nur einen)
der folgenden Werte haben: SELECT
,
INSERT
, UPDATE
,
REFERENCES
.
Wenn der Benutzer das GRANT OPTION
-Recht
hat, sollte IS_GRANTABLE
den Wert
YES
haben, andernfalls
NO
. In der Ausgabe ist GRANT
OPTION
nicht als separate Berechtigung aufgeführt.
Die folgenden Anweisungen sind nicht äquivalent:
SELECT ... FROM INFORMATION_SCHEMA.COLUMN_PRIVILEGES SHOW GRANTS ...
Die CHARACTER_SETS
-Tabelle gibt Informationen
über die verfügbaren Zeichensätze.
Standard Name | SHOW name | Remarks |
CHARACTER_SET_NAME | Charset | |
DEFAULT_COLLATE_NAME | Default collation | |
DESCRIPION | Description | MySQL extension |
MAXLEN | Maxlen | MySQL extension |
Hinweis:
Wir haben der Ausgabe von SHOW CHARACTER
SET
zwei Spalten hinzugefügt, die nicht zum
Standard gehören, nämlich Description
und
Maxlen
.
Die folgenden Anweisungen sind äquivalent:
SELECT * FROM INFORMATION_SCHEMA.CHARACTER_SETS [WHERE name LIKE 'wild
'] SHOW CHARACTER SET [LIKE 'wild
']
Die COLLATIONS
-Tabelle informiert über die
Kollationen der jeweiligen Zeichensätze.
Standard Name | SHOW name | Remarks |
COLLATION_NAME | Collation |
Hinweis:
Wir haben in der Ausgabe von SHOW COLLATION
fünf nicht zum Standard gehörende Spalten hinzugefügt,
nämlich Charset
, Id
,
Default
, Compiled
und
Sortlen
.
Die folgenden Anweisungen sind äquivalent:
SELECT COLLATION_NAME FROM INFORMATION_SCHEMA.COLLATIONS [WHERE collation_name LIKE 'wild
'] SHOW COLLATION [LIKE 'wild
']
Die
COLLATION_CHARACTER_SET_APPLICABILITY
-Tabelle
zeigt an, welcher Zeichensatz für welche Kollation gilt. Die
Spalten sind äquivalent zu den ersten beiden Feldern, die
SHOW COLLATION
anzeigt.
Standard Name | SHOW name | Remarks |
COLLATION_NAME | Collation | |
CHARACTER_SET_NAME | Charset |
Die TABLE_CONSTRAINTS
-Tabelle zeigt an, welche
Tabellen Constraints unterliegen.
Standard Name | SHOW name | Remarks |
CONSTRAINT_CATALOG | NULL | |
CONSTRAINT_SCHEMA | ||
CONSTRAINT_NAME | ||
TABLE_SCHEMA | ||
TABLE_NAME | ||
CONSTRAINT_TYPE |
Hinweise:
Der Wert von CONSTRAINT_TYPE
kann
UNIQUE
, PRIMARY KEY
oder
FOREIGN KEY
sein.
Die Informationen über UNIQUE
und
PRIMARY KEY
gleichen ungefähr dem, was
SHOW INDEX
im Feld
Key_name
ausgibt, wenn das Feld
Non_unique
den Wert 0
hat.
Die Spalte CONSTRAINT_TYPE
kann einen der
folgenden Werte enthalten: UNIQUE
,
PRIMARY KEY
, FOREIGN
KEY
, CHECK
. Sie ist eine
CHAR
-Spalte (keine
ENUM
-Spalte). Der
CHECK
-Wert wird erst zur Verfügung stehen,
wenn wir CHECK
unterstützen.
Die KEY_COLUMN_USAGE
-Tabelle beschreibt, welche
Schlüsselspalten Constraints haben.
Standard Name | SHOW name | Remarks |
CONSTRAINT_CATALOG | NULL | |
CONSTRAINT_SCHEMA | ||
CONSTRAINT_NAME | ||
TABLE_CATALOG | ||
TABLE_SCHEMA | ||
TABLE_NAME | ||
COLUMN_NAME | ||
ORDINAL_POSITION | ||
POSITION_IN_UNIQUE_CONSTRAINT | ||
REFERENCED_TABLE_SCHEMA | ||
REFERENCED_TABLE_NAME | ||
REFERENCED_COLUMN_NAME |
Hinweise:
Ist der Constraint ein Fremdschlüssel, so ist dies die Spalte des Fremdschlüssels und nicht die Spalte, auf die er verweist.
Der Wert von ORDINAL_POSITION
gibt die
Position der Spalte im Constraint und nicht in der Tabelle
wieder. Die Spaltenpositionen werden beginnend mit 1
durchnummeriert.
Der Wert von POSITION_IN_UNIQUE_CONSTRAINT
ist NULL
für Unique- und
Fremdschlüssel-Constraints. Bei Fremdschlüssel-Constraints
ist es die Ordinalposition im Schlüssel der referenzierten
Tabelle.
Nehmen wir beispielsweise an, wir hätten zwei Tabellen namens
t1
und t3
, die wie folgt
definiert sind:
CREATE TABLE t1 ( s1 INT, s2 INT, s3 INT, PRIMARY KEY(s3) ) ENGINE=InnoDB; CREATE TABLE t3 ( s1 INT, s2 INT, s3 INT, KEY(s1), CONSTRAINT CO FOREIGN KEY (s2) REFERENCES t1(s3) ) ENGINE=InnoDB;
Für diese beiden Tabellen hat die Tabelle
KEY_COLUMN_USAGE
zwei Zeilen:
eine Zeile mit CONSTRAINT_NAME
=
'PRIMARY'
,
TABLE_NAME
= 't1'
,
COLUMN_NAME
= 's3'
,
ORDINAL_POSITION
=
1
,
POSITION_IN_UNIQUE_CONSTRAINT
=
NULL
eine Zeile mit CONSTRAINT_NAME
=
'CO'
, TABLE_NAME
=
't3'
, COLUMN_NAME
=
's2'
,
ORDINAL_POSITION
=
1
,
POSITION_IN_UNIQUE_CONSTRAINT
=
1
Die ROUTINES
-Tabelle informiert über
gespeicherte Routinen (sowohl Prozeduren als auch Funktionen). Die
ROUTINES
-Tabelle enthält zurzeit keine
benutzerdefinierten Funktionen (UDFs).
Die Spalte „mysql.proc
name“ gibt die
mysql.proc
-Tabellenspalte an, die der
INFORMATION_SCHEMA.ROUTINES
-Tabellenspalte
entspricht (sofern vorhanden).
Standard Name | mysql.proc name | Remarks |
SPECIFIC_NAME | specific_name | |
ROUTINE_CATALOG | NULL | |
ROUTINE_SCHEMA | db | |
ROUTINE_NAME | name | |
ROUTINE_TYPE | type | {PROCEDURE|FUNCTION} |
DTD_IDENTIFIER | (data type descriptor) | |
ROUTINE_BODY | SQL | |
ROUTINE_DEFINITION | body | |
EXTERNAL_NAME | NULL | |
EXTERNAL_LANGUAGE | language | NULL |
PARAMETER_STYLE | SQL | |
IS_DETERMINISTIC | is_deterministic | |
SQL_DATA_ACCESS | sql_data_access | |
SQL_PATH | NULL | |
SECURITY_TYPE | security_type | |
CREATED | created | |
LAST_ALTERED | modified | |
SQL_MODE | sql_mode | MySQL extension |
ROUTINE_COMMENT | comment | MySQL extension |
DEFINER | definer | MySQL extension |
Hinweise:
MySQL berechnet die EXTERNAL_LANGUAGE
wie
folgt:
Wenn mysql.proc.language='SQL'
, so hat
EXTERNAL_LANGUAGE
den Wert
NULL
.
Ansonsten ist EXTERNAL_LANGUAGE
das,
was in mysql.proc.language
aufgeführt
ist. Da wir jedoch noch keine externen Sprachen
eingerichtet haben, ist dies immer
NULL
.
Die VIEWS
-Tabelle informiert über Views in
Datenbanken. Für den Zugriff auf diese Tabelle ist die
SHOW VIEW
-Berechtigung nötig.
Standard Name | SHOW name | Remarks |
TABLE_CATALOG | NULL | |
TABLE_SCHEMA | ||
TABLE_NAME | ||
VIEW_DEFINITION | ||
CHECK_OPTION | ||
IS_UPDATABLE | ||
DEFINER | ||
SECURITY_TYPE |
Hinweise:
Die Spalte VIEW_DEFINITION
enthält im
Wesentlichen das, was auch SHOW CREATE VIEW
im Feld Create Table
anzeigt. Übergehen
Sie die Wörter vor dem SELECT
und hinter
WITH CHECK OPTION
. Angenommen, die
Anweisung lautete ursprünglich:
CREATE VIEW v AS SELECT s2,s1 FROM t WHERE s1 > 5 ORDER BY s1 WITH CHECK OPTION;
Dann sieht die View-Definition folgendermaßen aus:
SELECT s2,s1 FROM t WHERE s1 > 5 ORDER BY s1
Die Spalte CHECK_OPTION
hat immer den Wert
NONE
.
Die Spalte IS_UPDATABLE
ist bei
veränderbaren Views YES
und bei
unveränderbaren NO
.
Die Spalte DEFINER
gibt an, wer die View
angelegt hat. SECURITY_TYPE
hat den Wert
DEFINER
oder INVOKER
.
Die TRIGGERS
-Tabelle informiert über Trigger.
Zugriff bekommt nur, wer die SUPER
-Berechtigung
vorweisen kann.
Standard Name | SHOW name | Remarks |
TRIGGER_CATALOG | NULL | |
TRIGGER_SCHEMA | ||
TRIGGER_NAME | Trigger | |
EVENT_MANIPULATION | Event | |
EVENT_OBJECT_CATALOG | NULL | |
EVENT_OBJECT_SCHEMA | ||
EVENT_OBJECT_TABLE | Table | |
ACTION_ORDER | 0 | |
ACTION_CONDITION | NULL | |
ACTION_STATEMENT | Statement | |
ACTION_ORIENTATION | ROW | |
ACTION_TIMING | Timing | |
ACTION_REFERENCE_OLD_TABLE | NULL | |
ACTION_REFERENCE_NEW_TABLE | NULL | |
ACTION_REFERENCE_OLD_ROW | OLD | |
ACTION_REFERENCE_NEW_ROW | NEW | |
CREATED | NULL (0 ) | |
SQL_MODE | ||
DEFINER |
Hinweise:
Die Spalten TRIGGER_SCHEMA
und
TRIGGER_NAME
zeigen den Namen der Datenbank
an, in welcher der Trigger auftritt, und den Namen des
Triggers.
Die Spalte EVENT_MANIPULATION
hat entweder
den Wert 'INSERT'
,
'DELETE'
oder 'UPDATE'
.
Wie in Kapitel 20, Trigger, bereits gesagt, ist jeder
Trigger mit genau einer Tabelle verbunden. Die Spalte
EVENT_OBJECT_SCHEMA
zeigt die Datenbank an,
zu der die Tabelle gehört, und
EVENT_OBJECT_TABLE
enthält den Namen der
Tabelle.
Die Anweisung ACTION_ORDER
zeigt an, an
welcher Ordinalposition die Aktion des Triggers in der Liste
aller ähnlichen Trigger auf derselben Tabelle steht. Dieser
Wert ist gegenwärtig immer 0
, da auf einer
Tabelle nicht mehr als ein Trigger mit derselben
EVENT_MANIPULATION
und demselben
ACTION_TIMING
zulässig ist.
Die Spalte ACTION_STATEMENT
enthält die
Anweisung, die bei Aufruf des Triggers ausgeführt wird. Dies
ist dasselbe wie der Text in der
Statement
-Spalte der Ausgabe von
SHOW TRIGGERS
. Beachten Sie, dass dieser
Text UTF-8-kodiert ist.
Die Spalte ACTION_ORIENTATION
enthält
immer den Wert 'ROW'
.
Die Spalte ACTION_TIMING
enthält entweder
den Wert 'BEFORE'
oder
'AFTER'
.
Die Spalten ACTION_REFERENCE_OLD_ROW
und
ACTION_REFERENCE_NEW_ROW
enthalten den
alten und den neuen Spaltenbezeichner. Dies bedeutet, dass
ACTION_REFERENCE_OLD_ROW
immer den Wert
'OLD'
und
ACTION_REFERENCE_NEW_ROW
immer den Wert
'NEW'
hat.
Die Spalte SQL_MODE
zeigt, welcher
SQL-Servermodus bei der Erstellung des Triggers in Kraft war
(und somit auch für jeden Aufruf dieses Triggers in Kraft
bleibt, egal welcher SQL-Servermodus gerade
eingestellt sein mag). Diese Spalte hat denselben
Wertebereich wie die Systemvariable
sql_mode
. Siehe auch
Abschnitt 5.2.5, „Der SQL-Modus des Servers“.
Die Spalte DEFINER
kam in MySQL 5.1.2 neu
hinzu. Der DEFINER
ist der, der den Trigger
definiert hat.
Die folgenden Spalten haben immer den Wert
NULL
: TRIGGER_CATALOG
,
EVENT_OBJECT_CATALOG
,
ACTION_CONDITION
,
ACTION_REFERENCE_OLD_TABLE
,
ACTION_REFERENCE_NEW_TABLE
und
CREATED
.
Ein Beispiel mit dem in Abschnitt 20.3, „Verwendung von Triggern“,
definierten Trigger ins_sum
:
mysql> SELECT * FROM INFORMATION_SCHEMA.TRIGGERS\G
*************************** 1. row ***************************
TRIGGER_CATALOG: NULL
TRIGGER_SCHEMA: test
TRIGGER_NAME: ins_sum
EVENT_MANIPULATION: INSERT
EVENT_OBJECT_CATALOG: NULL
EVENT_OBJECT_SCHEMA: test
EVENT_OBJECT_TABLE: account
ACTION_ORDER: 0
ACTION_CONDITION: NULL
ACTION_STATEMENT: SET @sum = @sum + NEW.amount
ACTION_ORIENTATION: ROW
ACTION_TIMING: BEFORE
ACTION_REFERENCE_OLD_TABLE: NULL
ACTION_REFERENCE_NEW_TABLE: NULL
ACTION_REFERENCE_OLD_ROW: OLD
ACTION_REFERENCE_NEW_ROW: NEW
CREATED: NULL
SQL_MODE:
DEFINER: me@localhost
Siehe auch Abschnitt 13.5.4.23, „SHOW TRIGGERS
“.
Die PLUGINS
-Tabelle informiert über
Server-Plug-Ins.
Name | SHOW name | Remarks |
PLUGIN_NAME | ||
PLUGIN_VERSION | ||
PLUGIN_STATUS | ||
PLUGIN_TYPE | ||
PLUGIN_TYPE_VERSION | ||
PLUGIN_LIBRARY | ||
PLUGIN_LIBRARY_VERSION | ||
PLUGIN_AUTHOR | ||
PLUGIN_DESCRIPTION |
Hinweis:
Die PLUGINS
-Tabelle gibt es seit MySQL
5.1.5.
Die ENGINES
-Tabelle informiert über
Speicher-Engines.
Name | SHOW name | Remarks |
ENGINE | Engine | |
SUPPORT | Support | |
COMMENT | Comment | |
TRANSACTIONS | Transactions | |
XA | XA | |
SAVEPOINTS | Savepoints |
Hinweis:
Die ENGINES
-Tabelle gibt es seit MySQL
5.1.5.
Siehe auch Abschnitt 13.5.4.9, „SHOW ENGINES
“.
Die PARTITIONS
-Tabelle informiert über
Tabellenpartitionen.
Name | SHOW name | Remarks |
TABLE_CATALOG | ||
TABLE_SCHEMA | ||
TABLE_NAME | ||
PARTITION_NAME | ||
SUBPARTITION_NAME | ||
PARTITION_ORDINAL_POSITION | ||
SUBPARTITION_ORDINAL_POSITION | ||
PARTITION_METHOD | ||
SUBPARTITION_METHOD | ||
PARTITION_EXPRESSION | ||
SUBPARTITION_EXPRESSION | ||
PARTITION_DESCRIPTION | ||
TABLE_ROWS | ||
AVG_ROW_LENGTH | ||
DATA_LENGTH | ||
MAX_DATA_LENGTH | ||
INDEX_LENGTH | ||
DATA_FREE | ||
CREATE_TIME | ||
UPDATE_TIME | ||
CHECK_TIME | ||
CHECKSUM | ||
PARTITION_COMMENT | ||
NODEGROUP | ||
TABLESPACE_NAME |
Hinweise:
Die PARTITIONS
-Tabelle gibt es seit MySQL
5.1.6.
Wichtig: Wenn nach einem
Upgrade auf MySQL 5.1.6 oder höher noch irgendwelche
partitionierten Tabellen vorhanden sind, die in einer älteren
MySQL-Version als MySQL 5.1.6 angelegt wurden, so ist auf der
PARTITIONS
-Tabelle kein
SELECT
, SHOW
oder
DESCRIBE
möglich. Bitte lesen Sie
Abschnitt D.1.1, „Änderungen in Release 5.1.6 (Noch nicht veröffentlicht)“, bevor Sie
von MySQL 5.1.5 oder einer älteren Version auf MySQL 5.1.6
oder höher aufrüsten.
Die EVENTS
-Tabelle informiert über
Ereignisplaner-Ereignisse.
Name | SHOW name | Remarks |
EVENT_CATALOG | ||
EVENT_SCHEMA | ||
EVENT_NAME | ||
DEFINER | ||
EVENT_BODY | ||
EVENT_TYPE | ||
EXECUTE_AT | ||
INTERVAL_VALUE | ||
INTERVAL_FIELD | ||
SQL_MODE | ||
STARTS | ||
ENDS | ||
STATUS | ||
ON_COMPLETION | ||
CREATED | ||
LAST_ALTERED | ||
LAST_EXECUTED | ||
EVENT_COMMENT |
Hinweis:
Die EVENTS
-Tabelle gibt es seit MySQL
5.1.6.
Wir haben vor, noch weitere
INFORMATION_SCHEMA
-Tabellen zu implementieren.
Insbesondere sehen wir die Notwendigkeit einer
PARAMETERS
- und einer
REFERENTIAL_CONSTRAINTS
-Tabelle.
Einige Erweiterungen von SHOW
-Anweisungen
gehören zur Implementierung des
INFORMATION_SCHEMA
:
SHOW
kann Informationen über die Struktur
des INFORMATION_SCHEMA
selbst liefern.
Einige SHOW
-Anweisungen können eine
WHERE
-Klausel haben. Dadurch können Sie
flexibler angeben, welche Zeilen angezeigt werden sollen.
Da INFORMATION_SCHEMA
eine
Informationsdatenbank ist, wird ihr Name von der SHOW
DATABASES
-Anweisung ebenfalls ausgegeben. Ebenso können
Sie auch SHOW TABLES
auf dem
INFORMATION_SCHEMA
verwenden, um eine Liste
seiner Tabellen zu erhalten:
mysql> SHOW TABLES FROM INFORMATION_SCHEMA;
+---------------------------------------+
| Tables_in_information_schema |
+---------------------------------------+
| CHARACTER_SETS |
| COLLATIONS |
| COLLATION_CHARACTER_SET_APPLICABILITY |
| COLUMNS |
| COLUMN_PRIVILEGES |
| ENGINES |
| EVENTS |
| KEY_COLUMN_USAGE |
| PARTITIONS |
| PLUGINS |
| ROUTINES |
| SCHEMATA |
| SCHEMA_PRIVILEGES |
| STATISTICS |
| TABLES |
| TABLE_CONSTRAINTS |
| TABLE_PRIVILEGES |
| TRIGGERS |
| USER_PRIVILEGES |
| VIEWS |
+---------------------------------------+
19 rows in set (0.03 sec)
SHOW COLUMNS
und DESCRIBE
können Informationen über die Spalten der einzelnen
INFORMATION_SCHEMA
-Tabellen liefern.
Mehrere SHOW
-Anweisungen wurden um eine
WHERE
-Klausel erweitert:
SHOW CHARACTER SET SHOW COLLATION SHOW COLUMNS SHOW DATABASES SHOW FUNCTION STATUS SHOW KEYS SHOW OPEN TABLES SHOW PROCEDURE STATUS SHOW STATUS SHOW TABLE STATUS SHOW TABLES SHOW VARIABLES
Wenn eine WHERE
-Klausel vorhanden ist, wird sie
mit den von SHOW
ausgewiesenen Spaltennamen
verglichen. So liefert beispielsweise die Anweisung SHOW
CHARACTER SET
folgende Ausgabespalten:
mysql> SHOW CHARACTER SET;
+----------+-----------------------------+---------------------+--------+
| Charset | Description | Default collation | Maxlen |
+----------+-----------------------------+---------------------+--------+
| big5 | Big5 Traditional Chinese | big5_chinese_ci | 2 |
| dec8 | DEC West European | dec8_swedish_ci | 1 |
| cp850 | DOS West European | cp850_general_ci | 1 |
| hp8 | HP West European | hp8_english_ci | 1 |
| koi8r | KOI8-R Relcom Russian | koi8r_general_ci | 1 |
| latin1 | cp1252 West European | latin1_swedish_ci | 1 |
| latin2 | ISO 8859-2 Central European | latin2_general_ci | 1 |
...
Wenn Sie eine WHERE
-Klausel mit SHOW
CHARACTER SET
verbinden würden, würden Sie auf diese
Spaltennamen Bezug nehmen. Die folgende Anweisung zeigt
beispielsweise Informationen über Zeichensätze an, deren
Standardkollation den String 'japanese'
enthält:
mysql> SHOW CHARACTER SET WHERE `Default collation` LIKE '%japanese%';
+---------+---------------------------+---------------------+--------+
| Charset | Description | Default collation | Maxlen |
+---------+---------------------------+---------------------+--------+
| ujis | EUC-JP Japanese | ujis_japanese_ci | 3 |
| sjis | Shift-JIS Japanese | sjis_japanese_ci | 2 |
| cp932 | SJIS for Windows Japanese | cp932_japanese_ci | 2 |
| eucjpms | UJIS for Windows Japanese | eucjpms_japanese_ci | 3 |
+---------+---------------------------+---------------------+--------+
Die folgende Anweisung zeigt die Multibytezeichensätze an:
mysql> SHOW CHARACTER SET WHERE Maxlen > 1;
+---------+---------------------------+---------------------+--------+
| Charset | Description | Default collation | Maxlen |
+---------+---------------------------+---------------------+--------+
| big5 | Big5 Traditional Chinese | big5_chinese_ci | 2 |
| ujis | EUC-JP Japanese | ujis_japanese_ci | 3 |
| sjis | Shift-JIS Japanese | sjis_japanese_ci | 2 |
| euckr | EUC-KR Korean | euckr_korean_ci | 2 |
| gb2312 | GB2312 Simplified Chinese | gb2312_chinese_ci | 2 |
| gbk | GBK Simplified Chinese | gbk_chinese_ci | 2 |
| utf8 | UTF-8 Unicode | utf8_general_ci | 3 |
| ucs2 | UCS-2 Unicode | ucs2_general_ci | 2 |
| cp932 | SJIS for Windows Japanese | cp932_japanese_ci | 2 |
| eucjpms | UJIS for Windows Japanese | eucjpms_japanese_ci | 3 |
+---------+---------------------------+---------------------+--------+
Inhaltsverzeichnis
MySQL 5.1 bietet Unterstützung für Präzisionsberechnungen: eine Verarbeitung numerischer Werte, die extrem genaue Ergebnisse und eine sehr gute Kontrolle über ungültige Werte garantiert. Präzisionsberechnungen beruhen auf zwei Features:
SQL-Modi, die steuern, wie streng der Server mit ungültigen Daten umgeht
die MySQL-Bibliothek für Festkommaarithmetik
Diese Features haben mehrere Auswirkungen auf numerische Operationen:
Präzisionsberechnungen: In
Berechnungen mit genauen Zahlen werden keine Fließkommafehler
eingebaut. Stattdessen wird eine genaue Anzahl Stellen
(Precision) verwendet. So wird zum Beispiel eine Zahl wie
.0001
nicht als Näherungswert, sondern als
genauer Wert verstanden, und wenn man ihn 10.000 Mal addiert,
erhält man genau 1
als Ergebnis und keinen
Wert, der bloß „annähernd“ gleich 1 ist.
Wohldefiniertes
Rundungsverhalten: Bei genauen Zahlen orientiert sich
das Ergebnis von ROUND()
am Argument der
Funktion und nicht an Umgebungsfaktoren wie etwa der
Funktionsweise der zugrunde liegenden C-Bibliothek.
Plattformunabhängigkeit: Operationen mit genauen numerischen Werten gleichen sich auf allen Plattformen, wie beispielsweise Windows und Unix.
Kontrolle über den Umgang mit ungültigen
Werten: Überlauf und Division durch null können
erkannt und als Fehler behandelt werden. So können Sie
beispielsweise einen Wert, der für eine Spalte zu groß ist,
als Fehler behandeln, anstatt ihn auf den Datentyp der Spalte
zurechtschustern zu lassen. Ebenso können Sie eine Division
durch null als Fehler erkennen, anstatt ihn als Operation mit
einem NULL
-Ergebnis zu handhaben. Durch die
Einstellung der Systemvariablen sql_mode
bestimmen Sie selbst, welchen Weg Sie einschlagen.
Ein wichtiges Ergebnis all dieser Features ist, dass MySQL 5.1 dem SQL-Standard sehr nahe kommt.
Die folgenden Ausführungen betreffen mehrere Aspekte der
Funktionsweise von Präzisionsberechnungen (einschließlich
möglicher Inkompatibilitäten mit älteren Anwendungen). Zum
Schluss geben wir einige Beispiele, um zu zeigen, wie präzise MySQL
5.1 numerische Operationen ausführt. Wie man mit der
Systemvariablen sql_mode
den SQL-Modus einstellt,
erfahren Sie unter Abschnitt 5.2.5, „Der SQL-Modus des Servers“.
In Operationen mit genauen Werten sind Präzisionsberechnungen mit
genauen numerischen Datentypen (DECIMAL
und
Integer-Typen) und genauen numerischen Literalen möglich.
Näherungsweise Datentypen und Zahlenliterale werden weiterhin als
Fließkommazahlen behandelt.
Genaue numerische Literale haben einen ganzzahligen oder einen
Bruchteilsanteil oder beides. Sie können ein Vorzeichen besitzen.
Beispiele: 1
, .2
,
3.4
, -5
,
-6.78
, +9.10
.
Näherungsweise numerische Literale werden in der
wissenschaftlichen Schreibweise mit Mantisse und Exponent
dargestellt. Beides kann auch vorzeichenbehaftet sein. Beispiele:
1.2E3
, 1.2E-3
,
-1.2E3
, -1.2E-3
.
Zwei Zahlen, die ähnlich aussehen, müssen nicht unbedingt beide
genaue Werte oder beide Näherungswerte sein. So ist
beispielsweise 2.34
eine genaue
(Festkomma-)Zahl, während 2.34E0
eine
näherungsweise (Fließkomma-)Zahl ist.
Der Datentyp DECIMAL
ist ein Festkommatyp und
Berechnungen mit diesem Typ sind genau. In MySQL hat
DECIMAL
mehrere Synonyme:
NUMERIC
, DEC
,
FIXED
. Auch die Integer-Typen sind genaue
Datentypen.
Die Datentypen FLOAT
und
DOUBLE
sind Fließkommatypen und Berechnungen
mit diesen Typen sind Näherungen. In MySQL haben
FLOAT
und DOUBLE
die
Synonyme DOUBLE PRECISION
und
REAL
.
In diesem Abschnitt werden die Merkmale des Datenyps
DECIMAL
(und seiner Synonyme) in MySQL
5.1 vorgestellt. Dabei werden besonders folgende
Themen angesprochen:
die Höchstzahl der Stellen
das Speicherformat
der Speicherbedarf
die nicht zum Standard gehörende MySQL-Erweiterung für den
oberen Bereich der DECIMAL
-Spalten
Auf mögliche Inkompatibilitäten mit Anwendungen, die für ältere Versionen von MySQL geschrieben wurden, weisen wir an geeigneter Stelle in diesem Abschnitt hin.
Die Deklarationssyntax für eine DECIMAL
-Spalte
lautet
DECIMAL(
.
Die Argumente haben in MySQL 5.1 folgende
Wertebereiche:
M
,D
)
M
ist die Höchstzahl der Stellen
(die Genauigkeit) und liegt zwischen 1 und 65. (Ältere
Versionen von MySQL hatten hier einen zulässigen Wertebereich
von 1 bis 254.)
D
ist die Anzahl der Stellen rechts
vom Dezimalpunkt (die Dezimalstellen) mit dem Wertebereich 0
bis 30. D
darf nicht größer als
M
sein.
Dass M
maximal 65 beträgt, führt
dazu, dass Berechnungen mit DECIMAL
-Werten auf
bis zu 65 Stellen genau sind. Da diese maximale Genauigkeit von 65
Stellen auch für genaue numerische Literale gilt, hat sich der
maximale Wertebereich solcher Literale geändert. (In älteren
MySQL-Versionen konnten Dezimalwerte bis zu 254 Stellen haben,
aber die Berechnungen wurden als Fließkommaoperationen
ausgeführt und waren daher Näherungen und nicht genau.)
Werte für DECIMAL
-Spalten werden in MySQL
5.1 in einem Binärformat gespeichert, das
Dezimalstellen in 4 Byte hineinpackt. Der Speicherbedarf für den
ganzzahligen Teil und den Bruchteil wird separat ermittelt. Ein
Vielfaches von 9 Stellen belegt 4 Byte und eventuelle Reststellen
belegen einen Bruchteil von 4 Byte. Da beispielsweise die Spalte
DECIMAL(18,9)
auf jeder Seite des Dezimalpunkts
9 Stellen hat, belegen ihr ganzzahliger und ihr Dezimalteil
jeweils 4 Byte. Eine DECIMAL(20,10)
-Spalte hat
dagegen auf jeder Seite des Dezimalpunkts 10 Stellen. Jeder Teil
belegt also 4 Byte für die ersten 9 Stellen und 1 Byte für die
Reststelle.
Folgende Tabelle zeigt den Speicherbedarf für Reststellen an:
Reststellen | Anzahl Bytes |
0 | 0 |
1 | 1 |
2 | 1 |
3 | 2 |
4 | 2 |
5 | 3 |
6 | 3 |
7 | 4 |
8 | 4 |
9 | 4 |
Im Gegensatz zu älteren Versionen von MySQL (vor 5.0.3) speichern
DECIMAL
-Spalten in MySQL 5.1 keine
Stelle für ein vorangestelltes +
-Zeichen oder
vorangestellte 0
-Ziffern. Wenn Sie
+0003.1
in eine
DECIMAL(5,1)
-Spalte speichern, so wird diese
Zahl einfach als 3.1
gespeichert. Anwendungen,
die das frühere Speicherverhalten benötigen, müssen
umgeschrieben werden, um sie an diese Änderung anzupassen.
DECIMAL
-Spalten können in MySQL
5.1 keine Werte speichern, die größer sind als in
der Spaltendefinition angegeben. So lässt beispielsweise eine
DECIMAL(3,0)
-Spalte Werte von
-999
bis 999
zu und eine
DECIMAL(
-Spalte
erlaubt höchstens M
,D
)M
–
D
Stellen auf der linken Seite des
Dezimalpunkts. Das ist nicht kompatibel mit Anwendungen, die sich
auf die älteren Versionen von MySQL stützen, welche eine
zusätzliche Stelle für das +
-Zeichen
speicherten.
Der SQL-Standard verlangt für
NUMERIC(
-Werte
eine Genauigkeit von exakt
M
,D
)M
Stellen und für
DECIMAL(
-Werte
eine Genauigkeit von mindestens M
,D
)M
Stellen (es darf auch mehr sein). In MySQL sind
DECIMAL(
und
M
,D
)NUMERIC(
dasselbe und haben beide eine Genauigkeit von exakt
M
,D
)M
Stellen.
Genauere Informationen über die Portierung von Anwendungen, die
sich auf die frühere Behandlung des Datentyps
DECIMAL
stützen, finden Sie unter
MySQL-Referenzhandbuch für die Version
5.0.
In Präzisionsberechnungen werden genaue Zahlen möglichst immer
so verwendet, wie sie angegeben sind. Beispielsweise werden Zahlen
in Vergleichsoperationen genau wie vorgegeben verwendet, ohne jede
Änderung. Im strikten SQL-Modus wird eine Zahl, die mit
INSERT
in eine Spalte mit einem genauen
Datentyp (DECIMAL
oder Integer) geladen wird,
mit ihrem genauen Wert eingefügt, wenn sie im Wertebereich der
Spalte liegt. Wird die Zahl abgerufen, ist ihr Wert immer noch
derselbe, der eingefügt wurde. (Ohne den Strict-Modus kann ein
Wert bei INSERT
-Operationen auch abgeschnitten
werden.)
Die Handhabung numerischer Ausdrücke hängt davon ab, welche Art von Werten die Ausdrücke enthalten:
Enthält ein Ausdruck Näherungswerte, so ist der gesamte Ausdruck eine Näherung und wird mit Fließkommaarithmetik ausgewertet.
Enthält der Ausdruck keine Näherungswerte, sind nur genaue
Werte vorhanden. Enthält irgendein genauer Wert einen
Bruchteilsanteil (also einen Wert, der hinter dem Dezimalpunkt
steht), so wird er mit genauer Arithmetik als
DECIMAL
ausgewertet und hat eine
Genauigkeit von 65 Stellen. (Was mit „genau“
gemeint ist, hängt von den Grenzen dessen ab, was im
Binärformat dargestellt werden kann. So kann beispielsweise
1.0/3.0
in Dezimalschreibweise als die
Näherung .333...
, aber nicht als genaue
Zahl dargestellt werden. Daher wird
(1.0/3.0)*3.0
nicht als genau
1.0
ausgewertet.)
Andernfalls enthält der Ausdruck nur Integer-Werte. Der
Ausdruck ist somit genau und wird mit Integer-Arithmetik
ausgewertet. Seine Genauigkeit ist dieselbe wie
BIGINT
(64 Bits).
Wenn ein numerischer Ausdruck Strings enthält, so werden diese in Fließkommawerte mit doppelter Genauigkeit umgewandelt und es entsteht ein näherungsweiser Ausdruck.
Einfügungen in numerische Spalten werden durch den SQL-Modus
beeinflusst, der mit der Systemvariablen
sql_mode
eingestellt wird. (Siehe
Abschnitt 1.9.2, „Auswahl der SQL-Modi“.) In den nachfolgenden Ausführungen
werden der Strict-Modus (der durch die Werte
STRICT_ALL_TABLES
oder
STRICT_TRANS_TABLES
eingeschaltet wird) und
ERROR_FOR_DIVISION_BY_ZERO
verwendet. Um alle
Restriktionen einzuschalten, können Sie auch einfach den
TRADITIONAL
-Modus wählen, der beide
Strict-Modi und ERROR_FOR_DIVISION_BY_ZERO
umfasst:
mysql> SET sql_mode='TRADITIONAL';
Wird eine Zahl in eine Spalte eines genauen Datentyps
(DECIMAL
oder Integer) eingefügt, so wird sie
mit ihrem genauen Wert in die Spalte geladen, wenn sie im
zulässigen Wertebereich dieser Spalte liegt.
Hat ihr Dezimalteil zu viele Stellen, wird sie gerundet und eine Warnung ausgegeben. Gerundet wird, wie es unter Rundungsverhalten beschrieben ist.
Hat die Zahl in ihrem ganzzahligen Teil zu viele Stellen, ist sie zu groß und wird folgendermaßen behandelt:
Wenn der Strict-Modus nicht eingeschaltet ist, wird der Wert auf den nächsten zulässigen Wert abgeschnitten und eine Warnung generiert.
Ist der Strict-Modus aktiviert, tritt ein Überlauffehler ein.
Da ein Speicherunterlauf nicht erkannt wird, ist die Behandlung eines Unterlaufs nicht definiert.
Nach Voreinstellung kommt bei einer Division durch null das
Ergebnis NULL
heraus und keine Warnung. Haben
Sie jedoch den SQL-Modus
ERROR_FOR_DIVISION_BY_ZERO
aktiviert, geht
MySQL mit einer Division durch null ganz anders um:
Wenn der Strict-Modus eingeschaltet ist, wird eine Warnung ausgegeben.
Bei eingeschaltetem Strict-Modus sind Einfügungen und Aktualisierungen, bei denen eine Division durch null vorkommt, verboten, und ein Fehler wird gemeldet.
Mit anderen Worten: Einfügungen und Aktualisierungen, in denen
Ausdrücke mit einer Division durch null vorkommen, können als
Fehler behandelt werden, allerdings nur dann, wenn zusätzlich zum
Strict-Modus ERROR_FOR_DIVISION_BY_ZERO
eingeschaltet ist.
Nehmen wir als Beispiel folgende Anweisung:
INSERT INTO t SET i = 1/0;
Nun sehen Sie, was bei unterschiedlichen Kombinationen von Strict
und ERROR_FOR_DIVISION_BY_ZERO
passiert:
sql_mode Wert | Ergebnis |
'' (Default) | Keine Warnung, kein Fehler; i wird auf
NULL gesetzt. |
strict | Keine Warnung, kein Fehler; i wird auf
NULL gesetzt. |
ERROR_FOR_DIVISION_BY_ZERO | Warnung, aber kein Fehler; i wird auf
NULL gesetzt. |
strict,ERROR_FOR_DIVISION_BY_ZERO | Fehlerbedingung, keine Zeile eingefügt. |
Werden Strings in numerische Spalten eingefügt, findet folgende Zahlenkonvertierung statt, wenn der String keinen numerischen Inhalt hat:
Ein String, der nicht mit einer Zahl anfängt, kann nicht als Zahl verwendet werden. Im Strict-Modus wird ein Fehler und ansonsten eine Warnung generiert. Das schließt auch den leeren String ein.
Ein mit einer Zahl beginnender String kann konvertiert werden, wobei jedoch der nachfolgende, nichtnumerische Teil abgeschnitten wird. Wenn der abgeschnittene Teil etwas anderes als Leerzeichen enthält, wird im Strict-Modus ein Fehler und ansonsten eine Warnung generiert.
Dieser Abschnitt beschreibt das Rundungsverhalten in
Präzisionsberechnungen für die Funktion
ROUND()
und Einfügungen in
DECIMAL
-Spalten.
Die Funktion ROUND()
rundet genaue und
näherungsweise Argumente unterschiedlich:
Genaue Zahlen rundet ROUND()
nach dem
Grundsatz „Ab der Hälfte wird aufgerundet“.
Dabei wird eine positive Zahl mit einem Dezimalteil von .5
oder mehr auf den nächsten Integer aufgerundet und eine
negative Zahl mit einem Dezimalteil von .5 oder mehr auf den
nächsten Integer abgerundet. (Mit anderen Worten: Die Zahl
wird von null weggerundet.) Ein Wert mit einem Dezimalteil
kleiner .5 wird dagegen auf den nächsten Integer abgerundet,
wenn er positiv ist, und auf den nächsten Integer
aufgerundet, wenn er negativ ist.
Das Ergebnis für Näherungswerte hängt von der C-Bibliothek
ab. Auf vielen Systemen bedeutet dies, dass
ROUND()
nach der Regel „Runde auf die
nächste gerade Zahl“ vorgeht: Ein Wert mit
Bruchteilsanteil wird auf den nächsten geraden Integer
gerundet.
Das folgende Beispiel verdeutlicht die Unterschiede einer Rundung von genauen und näherungsweisen Werten:
mysql> SELECT ROUND(2.5), ROUND(25E-1);
+------------+--------------+
| ROUND(2.5) | ROUND(25E-1) |
+------------+--------------+
| 3 | 2 |
+------------+--------------+
Da Einfügungen in eine DECIMAL
-Spalte einen
genauen Datentyp zum Ziel haben, wird immer nach der Regel
„Runde auf die nächste gerade Zahl“ gerundet, egal
ob der einzufügende Wert ein genauer oder ein Näherungswert ist:
mysql>CREATE TABLE t (d DECIMAL(10,0));
Query OK, 0 rows affected (0.00 sec) mysql>INSERT INTO t VALUES(2.5),(2.5E0);
Query OK, 2 rows affected, 2 warnings (0.00 sec) Records: 2 Duplicates: 0 Warnings: 2 mysql>SELECT d FROM t;
+------+ | d | +------+ | 3 | | 3 | +------+
Dieser Abschnitt zeigt Beispiele für die Ergebnisse von Anfragen mit Präzisionsberechnungen in MySQL 5.1.
Beispiel 1. Zahlen werden möglichst mit ihrem genauen Wert wie vorgegeben benutzt:
mysql> SELECT .1 + .2 = .3;
+--------------+
| .1 + .2 = .3 |
+--------------+
| 1 |
+--------------+
Bei Fließkommawerten sind die Ergebnisse Näherungen:
mysql> SELECT .1E0 + .2E0 = .3E0;
+--------------------+
| .1E0 + .2E0 = .3E0 |
+--------------------+
| 0 |
+--------------------+
Eine andere Möglichkeit, den Unterschied in der Behandlung von
genauen und Näherungswerten zu zeigen, besteht darin, eine kleine
Zahl immer wieder zu einer Summe zu addieren. Betrachten Sie
folgende gespeicherte Prozedur, die zu einer Variablen tausendmal
den Wert .0001
addiert.
CREATE PROCEDURE p () BEGIN DECLARE i INT DEFAULT 0; DECLARE d DECIMAL(10,4) DEFAULT 0; DECLARE f FLOAT DEFAULT 0; WHILE i < 10000 DO SET d = d + .0001; SET f = f + .0001E0; SET i = i + 1; END WHILE; SELECT d, f; END;
Logischerweise sollte die Summe für d
und
f
beide Male 1 ergeben, aber in Wirklichkeit
ist dies nur bei der Dezimalberechnung der Fall. In der
Fließkommaberechnung wird ein Fehler eingeführt:
+--------+------------------+ | d | f | +--------+------------------+ | 1.0000 | 0.99999999999991 | +--------+------------------+
Beispiel 2. Multiplikationen
werden mit der durch den SQL-Standard vorgegebenen Anzahl
Dezimalstellen ausgeführt: Für zwei Zahlen
X1
und X2
,
die S1
beziehungsweise
S2
Dezimalstellen haben, entsteht ein
Ergebnis mit
Dezimalstellen:
S1
+
S2
mysql> SELECT .01 * .01;
+-----------+
| .01 * .01 |
+-----------+
| 0.0001 |
+-----------+
Beispiel 3. Das Rundungsverhalten ist wohldefiniert:
So ist das Rundungsverhalten (beispielsweise der Funktion
ROUND()
) unabhängig von der Implementierung
der zugrunde liegenden C-Bibliothek, sodass die Ergebnisse
plattformübergreifend konsistent sind.
DECIMAL
-Spalten und genaue Zahlen werden nach
der Regel „Ab der Hälfte wird aufgerundet“
behandelt: Werte mit einem Dezimalteil von .5 oder mehr werden,
wie das nächste Beispiel zeigt, immer von null weg auf den
nächstgelegenen Integer aufgerundet:
mysql> SELECT ROUND(2.5), ROUND(-2.5);
+------------+-------------+
| ROUND(2.5) | ROUND(-2.5) |
+------------+-------------+
| 3 | -3 |
+------------+-------------+
Dagegen stützt sich die Rundung von Fließkommawerten auf die C-Bibliothek, die auf vielen Systemen nach dem Grundsatz „Runde auf die nächste gerade Zahl“ verfährt. Auf solchen Systemen werden Werte mit einem Bruchteilsanteil auf die nächste gerade Zahl gerundet:
mysql> SELECT ROUND(2.5E0), ROUND(-2.5E0);
+--------------+---------------+
| ROUND(2.5E0) | ROUND(-2.5E0) |
+--------------+---------------+
| 2 | -2 |
+--------------+---------------+
Beispiel 4. Wenn Sie im Strict-Modus einen zu großen Wert einfügen, führt dies zu einem Überlauf und verursacht einen Fehler. Der Wert wird nicht auf ein zulässiges Maß zurechtgestutzt.
Läuft MySQL jedoch nicht im Strict-Modus, wird der Wert abgeschnitten, bis er passt:
mysql>SET sql_mode='';
Query OK, 0 rows affected (0.00 sec) mysql>CREATE TABLE t (i TINYINT);
Query OK, 0 rows affected (0.01 sec) mysql>INSERT INTO t SET i = 128;
Query OK, 1 row affected, 1 warning (0.00 sec) mysql>SELECT i FROM t;
+------+ | i | +------+ | 127 | +------+ 1 row in set (0.00 sec)
Immerhin wird eine Überlaufbedingung registriert, wenn der Strict-Modus eingeschaltet ist:
mysql>SET sql_mode='STRICT_ALL_TABLES';
Query OK, 0 rows affected (0.00 sec) mysql>CREATE TABLE t (i TINYINT);
Query OK, 0 rows affected (0.00 sec) mysql>INSERT INTO t SET i = 128;
ERROR 1264 (22003): Out of range value adjusted for column 'i' at row 1 mysql>SELECT i FROM t;
Empty set (0.00 sec)
Beispiel 5: Sind der Strict-Modus
und ERROR_FOR_DIVISION_BY_ZERO
eingeschaltet,
verursacht eine Division durch null einen Fehler, anstatt das
Ergebnis NULL
nach sich zu ziehen.
Im nichtstrikten Modus hat die Division durch null das Ergebnis
NULL
:
mysql>SET sql_mode='';
Query OK, 0 rows affected (0.01 sec) mysql>CREATE TABLE t (i TINYINT);
Query OK, 0 rows affected (0.00 sec) mysql>INSERT INTO t SET i = 1 / 0;
Query OK, 1 row affected (0.00 sec) mysql>SELECT i FROM t;
+------+ | i | +------+ | NULL | +------+ 1 row in set (0.03 sec)
Sind jedoch die richtigen SQL-Modi eingeschaltet, verursacht eine Division durch null immer einen Fehler:
mysql>SET sql_mode='STRICT_ALL_TABLES,ERROR_FOR_DIVISION_BY_ZERO';
Query OK, 0 rows affected (0.00 sec) mysql>CREATE TABLE t (i TINYINT);
Query OK, 0 rows affected (0.00 sec) mysql>INSERT INTO t SET i = 1 / 0;
ERROR 1365 (22012): Division by 0 mysql>SELECT i FROM t;
Empty set (0.01 sec)
Beispiel 6. Vor MySQL 5.0.3 (also vor der Einführung von Präzisionsberechnungen) wurden sowohl genaue als auch näherungsweise Literale in Fließkommazahlen mit doppelter Genauigkeit umgewandelt:
mysql>SELECT VERSION();
+------------+ | VERSION() | +------------+ | 4.1.18-log | +------------+ 1 row in set (0.01 sec) mysql>CREATE TABLE t SELECT 2.5 AS a, 25E-1 AS b;
Query OK, 1 row affected (0.07 sec) Records: 1 Duplicates: 0 Warnings: 0 mysql>DESCRIBE t;
+-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | a | double(3,1) | | | 0.0 | | | b | double | | | 0 | | +-------+-------------+------+-----+---------+-------+ 2 rows in set (0.04 sec)
Seit MySQL 5.0.3 werden näherungsweise Literale zwar immer noch
in Fließkommazahlen konvertiert, genaue hingegen werden als
DECIMAL
behandelt:
mysql>SELECT VERSION();
+-----------------+ | VERSION() | +-----------------+ | 5.1.6-alpha-log | +-----------------+ 1 row in set (0.11 sec) mysql>CREATE TABLE t SELECT 2.5 AS a, 25E-1 AS b;
Query OK, 1 row affected (0.01 sec) Records: 1 Duplicates: 0 Warnings: 0 mysql>DESCRIBE t;
+-------+-----------------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-----------------------+------+-----+---------+-------+ | a | decimal(2,1) unsigned | NO | | 0.0 | | | b | double | NO | | 0 | | +-------+-----------------------+------+-----+---------+-------+ 2 rows in set (0.01 sec)
Beispiel 7. Wenn das Argument einer Aggregatfunktion ein genauer numerischer Typ ist, ist ihr Ergebnis ebenfalls ein genauer numerischer Typ, und zwar mit mindestens so vielen Dezimalstellen, wie das Argument hatte.
Betrachten Sie folgende Anweisungen:
mysql>CREATE TABLE t (i INT, d DECIMAL, f FLOAT);
mysql>INSERT INTO t VALUES(1,1,1);
mysql>CREATE TABLE y SELECT AVG(i), AVG(d), AVG(f) FROM t;
Vor MySQL 5.0.3 (also vor der Einführung von Präzisionsberechnungen in MySQL) sähe das Ergebnis folgendermaßen aus:
mysql> DESCRIBE y;
+--------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+--------------+------+-----+---------+-------+
| AVG(i) | double(17,4) | YES | | NULL | |
| AVG(d) | double(17,4) | YES | | NULL | |
| AVG(f) | double | YES | | NULL | |
+--------+--------------+------+-----+---------+-------+
Das Resultat ist ein Double-Wert, egal welchen Typ das Argument hatte.
Mit MySQL 5.0.3 hat sich dies geändert:
mysql> DESCRIBE y;
+--------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+---------------+------+-----+---------+-------+
| AVG(i) | decimal(14,4) | YES | | NULL | |
| AVG(d) | decimal(14,4) | YES | | NULL | |
| AVG(f) | double | YES | | NULL | |
+--------+---------------+------+-----+---------+-------+
Hier entsteht nur für das Fließkommaargument ein Ergebnis vom Typ Double. Argumente mit genauen Typen haben genaue Ergebnisse.
Inhaltsverzeichnis
libmysqld
kompilieren
In diesem Kapitel erfahren Sie, welche APIs für MySQL zur
Verfügung stehen, wo Sie sie bekommen und wie Sie sie benutzen. Die
C-API wird am gründlichsten behandelt, da sie von dem MySQL-Team
entwickelt wurde und die Grundlage der meisten anderen APIs bildet.
Außerdem behandelt das vorliegende Kapitel die
libmysqld
-Bibliothek (den Embedded Server) sowie
einige Programme, die für Anwendungsentwickler nützlich sind.
libmysqld
kompilierenDie MySQL Embedded Server-Bibliothek ermöglicht es, einen kompletten MySQL Server innerhalb einer Clientanwendung auszuführen. Die Hauptvorteile davon sind erhöhte Geschwindigkeit und eine einfachere Verwaltung eingebetteter Anwendungen.
Die Embedded Server-Bibliothek basiert auf der Client/Server-Version von MySQL, die in C/C++ geschrieben ist. Folglich ist auch der Embedded Server in C/C++ verfasst. In anderen Sprachen steht kein Embedded Server zur Verfügung.
Die API für die Embedded-MySQL-Version und die Client/Server-Version von MySQL sind identisch. Um eine alte Threaded-Anwendung auf die Embedded-Bibliothek umzustellen, müssen Sie normalerweise nur Aufrufe an folgende Funktionen hinzufügen:
Funktion | Wann aufrufen |
mysql_server_init() | Sollte vor jeder anderen MySQL-Funktion aufgerufen werden, am besten am
Anfang der main() -Funktion. |
mysql_server_end() | Sollte vor dem Beenden des Programms aufgerufen werden. |
mysql_thread_init() | Sollte in jedem Thread aufgerufen werden, mit dem Sie auf MySQL zugreifen. |
mysql_thread_end() | Sollte vor pthread_exit() aufgerufen werden. |
Dann müssen Sie Ihren Code mit libmysqld.a
statt mit libmysqlclient.a
verlinken.
Die
mysql_server_
-Funktionen
sind auch in xxx
()libmysqlclient.a
enthalten,
damit Sie zwischen der Embedded und der Client/Server-Version
umstellen können, indem Sie Ihre Anwendung einfach mit der
richtigen Bibliothek verknüpfen. Siehe
Abschnitt 24.2.12.1, „mysql_server_init()
“.
Ein Unterschied zwischen dem Embedded und dem Standalone-Server
besteht darin, dass die Authentifizierung für Verbindungen im
Embedded Server standardmäßig deaktiviert ist. Um sie auch
für den Embedded Server zu benutzen, geben Sie die Option
--with-embedded-privilege-control
an, wenn Sie
configure aufrufen, um Ihre
MySQL-Distribution zu konfigurieren.
Um eine libmysqld
-Bibliothek zu erhalten,
sollten Sie MySQL mit der Option
--with-embedded-server
konfigurieren. Siehe
Abschnitt 2.8.2, „Typische configure-Optionen“.
Wenn Sie Ihr Programm mit libmysqld
verknüpfen, müssen Sie auch die systemspezifischen
pthread
-Bibliotheken und einige andere vom
MySQL Server verwendeten Bibliotheken einbinden. Die
vollständige Liste der Bibliotheken können Sie mit dem Befehl
mysql_config --libmysqld-libs abrufen.
Sie müssen die richtigen Flags zum Kompilieren und Verlinken eines Threaded-Programms benutzen, auch wenn Sie in Ihrem Code nicht direkt irgendwelche Thread-Funktionen aufrufen.
Um ein C-Programm so zu kompilieren, dass es alle notwendigen
Dateien enthält, um die MySQL Server-Bibliothek in eine
kompilierte Version eines Programms einzubinden, verwenden Sie
den C-Compiler von GNU (gcc
). Dem Compiler
müssen Sie die Speicherorte diverser Dateien mitteilen und
Anweisungen geben, wie er das Programm kompilieren soll. Das
folgende Beispiel zeigt, wie ein Programm auf der Kommandozeile
kompiliert werden könnte:
gcc mysql_test.c -o mysql_test -lz \ `/usr/local/mysql/bin/mysql_config --include --libmysqld-libs`
Unmittelbar hinter dem Befehl gcc
steht der
Name der unkompilierten Datei des C-Programms. Darauf folgt die
Option -o
, die anzeigt, dass der nachfolgende
Dateiname der Name ist, den der Compiler der Ausgabedatei, also
dem kompilierten Programm, geben soll. Die nächste Codezeile
teilt dem Compiler die Speicherorte der Include-Dateien und
Bibliotheken sowie andere Einstellungen für das System mit, auf
dem das Programm kompiliert wird. Wegen eines Problems mit
mysql_config wird hier die Option
-lz
(für die Komprimierung) hinzugefügt. Der
mysql_config-Teil ist in Backticks statt in
einfache Anführungszeichen eingefasst.
Für den Embedded Server gelten folgende Beschränkungen:
Keine Unterstützung für ISAM
-Tabellen
(hauptsächlich, um die Bibliothek kleiner zu halten).
Keine benutzerdefinierten Funktionen (UDFs).
Kein Stack Trace bei einem Core Dump.
Kein interner RAID-Support. (Dieser ist normalerweise überflüssig, da die meisten modernen Betriebssysteme große Dateien unterstützen.)
Sie können ihn nicht als Master oder Slave einrichten (keine Replikation).
Auf Systemen mit wenig Arbeitsspeicher sind sehr große Ergebnismengen unter Umständen unbenutzbar.
Von außen über Sockets oder TCP/IP kann sich kein Prozess mit dem Embedded Server verbinden. Allerdings kann er sich mit einer zwischengeschalteten Anwendung verbinden, die ihrerseits für diesen Remote Client oder externen Prozess Verbindung mit dem Embedded Server aufnimmt.
Manche dieser Beschränkungen können Sie ändern, indem Sie die
Include-Datei mysql_embed.h
bearbeiten und
MySQL neu kompilieren.
Alle Optionen für den mysqld-Server-Daemon
können auch für eine Embedded Server-Bibliothek benutzt
werden. Serveroptionen können in einem Array als Argument an
die Funktion mysql_server_init()
übergeben
werden, die den Server initialisiert. Oder sie werden in einer
Optionsdatei wie my.cnf
übergeben. Um eine
Optionsdatei für ein C-Programm anzugeben, verwenden Sie die
Option --defaults-file
als eines der Elemente
des zweiten Arguments der
mysql_server_init()
-Funktion. Weitere
Informationen über die
mysql_server_init()
-Funktion finden Sie in
Abschnitt 24.2.12.1, „mysql_server_init()
“.
Optionsdateien erleichtern das Umschalten zwischen einer
Client/Server-Anwendung und einer mit Embedded MySQL. Die
gemeinsamen Optionen fassen Sie in der
[server]
-Gruppe zusammen. Diese werden dann
von beiden MySQL-Versionen gelesen. Client/Server-spezifische
Optionen gehören in den [mysqld]
-Abschnitt.
Optionen für die MySQL Embedded Server-Bibliothek speichern Sie
im Abschnitt [embedded]
und
anwendungsspezifische Optionen in einem Abschnitt namens
[ApplicationName_SERVER]
. Siehe
Abschnitt 4.3.2, „my.cnf-Optionsdateien“.
Die folgenden beiden Beispielprogramme müssten unverändert auf Linux oder FreeBSD laufen. Für andere Betriebssysteme sind kleinere Anpassungen erforderlich, hauptsächlich für die Dateipfade. Die Beispiele sollen genügend Einzelheiten vermitteln, um das Problem zu verdeutlichen, aber ohne den ganzen Ballast, der für eine echte Anwendung notwendig wäre. Das erste Beispiel ist ganz einfach, das zweite ein wenig fortgeschrittener, da es eine Fehlerprüfung enthält. Das erste wird gefolgt von einem Kommandozeileneintrag, mit dem man es kompilieren kann. Unter dem zweiten wird stattdessen eine GNU-Makefile für die Kompilierung angegeben.
Beispiel 1
test1_libmysqld.c
#include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include "mysql.h" MYSQL *mysql; MYSQL_RES *results; MYSQL_ROW record; static char *server_options[] = { "mysql_test", "--defaults-file=my.cnf" }; int num_elements = sizeof(server_options)/ sizeof(char *); static char *server_groups[] = { "libmysqld_server", "libmysqld_client" }; int main(void) { mysql_server_init(num_elements, server_options, server_groups); mysql = mysql_init(NULL); mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, "libmysqld_client"); mysql_options(mysql, MYSQL_OPT_USE_EMBEDDED_CONNECTION, NULL); mysql_real_connect(mysql, NULL,NULL,NULL, "database1", 0,NULL,0); mysql_query(mysql, "SELECT column1, column2 FROM table1"); results = mysql_store_result(mysql); while((record = mysql_fetch_row(results))) { printf("%s - %s \n", record[0], record[1]); } mysql_free_result(results); mysql_close(mysql); mysql_server_end(); return 0; }
Das Programm wird mit folgender Kommandozeile kompiliert:
gcc test1_libmysqld.c -o test1_libmysqld -lz \ `/usr/local/mysql/bin/mysql_config --include --libmysqld-libs`
Beispiel 2
Um das Beispiel auszuprobieren, legen Sie ein Verzeichnis namens
test2_libmysqld
auf derselben Ebene wie das
MySQL-Quellverzeichnis an. Speichern Sie die Quelldatei
test2_libmysqld.c
und die
GNUmakefile
in dieses Verzeichnis und
führen Sie GNU make
innerhalb des
test2_libmysqld
-Verzeichnisses aus.
test2_libmysqld.c
/* * Ein einfacher Beispielclient, der die MySQL Embedded Server-Bibliothek benutzt */ #include <mysql.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> MYSQL *db_connect(const char *dbname); void db_disconnect(MYSQL *db); void db_do_query(MYSQL *db, const char *query); const char *server_groups[] = { "test2_libmysqld_SERVER", "embedded", "server", NULL }; int main(int argc, char **argv) { MYSQL *one, *two; /* mysql_server_init() muss vor allen anderen mysql-* Funktionen aufgerufen werden. * * Sie können die Funktion mysql_server_init(0, NULL, NULL) benutzen; sie initialisiert * den Server mit groups = { * "server", "embedded", NULL * }. * * Eventuell setzen Sie Folgendes in Ihre $HOME/.my.cnf-Datei: [test2_libmysqld_SERVER] language = /path/to/source/of/mysql/sql/share/english * Natürlich können Sie argc und argv auch ändern, ehe Sie sie an * diese Funktion übergeben. Oder Sie erstellen neue, ganz nach Bedarf. * Doch alle Argumente in argv (außer dem Programmnamen * argv[0]) sollten gültige Optionen * für den MySQL Server sein. * * Wenn Sie diesen Client mit der normalen mysqlclient-Bibliothek verlinken, * ist diese Funktion lediglich ein Funktionsrumpf, der nichts weiter tut. */ mysql_server_init(argc, argv, (char **)server_groups); one = db_connect("test"); two = db_connect(NULL); db_do_query(one, "SHOW TABLE STATUS"); db_do_query(two, "SHOW DATABASES"); mysql_close(two); mysql_close(one); /* Dies muss nach allen anderen mysql-Funktionen aufgerufen werden. */ mysql_server_end(); exit(EXIT_SUCCESS); } static void die(MYSQL *db, char *fmt, ...) { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); (void)putc('\n', stderr); if (db) db_disconnect(db); exit(EXIT_FAILURE); } MYSQL * db_connect(const char *dbname) { MYSQL *db = mysql_init(NULL); if (!db) die(db, "mysql_init failed: no memory"); /* * Beachten Sie, dass Client und Server verschiedene Gruppennamen verwenden. * Das ist wichtig, da der Server nicht die Optionen des Clients und dieser nicht die Optionen * des Servers akzeptiert. */ mysql_options(db, MYSQL_READ_DEFAULT_GROUP, "test2_libmysqld_CLIENT"); if (!mysql_real_connect(db, NULL, NULL, NULL, dbname, 0, NULL, 0)) die(db, "mysql_real_connect failed: %s", mysql_error(db)); return db; } void db_disconnect(MYSQL *db) { mysql_close(db); } void db_do_query(MYSQL *db, const char *query) { if (mysql_query(db, query) != 0) goto err; if (mysql_field_count(db) > 0) { MYSQL_RES *res; MYSQL_ROW row, end_row; int num_fields; if (!(res = mysql_store_result(db))) goto err; num_fields = mysql_num_fields(res); while ((row = mysql_fetch_row(res))) { (void)fputs(">> ", stdout); for (end_row = row + num_fields; row < end_row; ++row) (void)printf("%s\t", row ? (char*)*row : "NULL"); (void)fputc('\n', stdout); } (void)fputc('\n', stdout); mysql_free_result(res); } else (void)printf("Affected rows: %lld\n", mysql_affected_rows(db)); return; err: die(db, "db_do_query failed: %s [%s]", mysql_error(db), query); }
GNUmakefile
# Dies setzt voraus, dass die MySQL-Software in /usr/local/mysql installiert ist inc := /usr/local/mysql/include/mysql lib := /usr/local/mysql/lib # Wenn Sie die MySQL-Software noch nicht installiert haben, versuchen Sie dies: #inc := $(HOME)/mysql-5.1/include #lib := $(HOME)/mysql-5.1/libmysqld CC := gcc CPPFLAGS := -I$(inc) -D_THREAD_SAFE -D_REENTRANT CFLAGS := -g -W -Wall LDFLAGS := -static # Sie können -lmysqld in -lmysqlclient ändern, um die # Client/Server-Bibliothek zu benutzen LDLIBS = -L$(lib) -lmysqld -lz -lm -lcrypt ifneq (,$(shell grep FreeBSD /COPYRIGHT 2>/dev/null)) # FreeBSD LDFLAGS += -pthread else # Linux vorausgesetzt LDLIBS += -lpthread endif # Dies funktioniert für einfache Testprogramme mit nur einer einzigen Datei sources := $(wildcard *.c) objects := $(patsubst %c,%o,$(sources)) targets := $(basename $(sources)) all: $(targets) clean: rm -f $(targets) $(objects) *.core
Wir ermutigen jeden Entwickler, freie Software zu fördern, indem er seinen Code unter der GPL oder einer ähnlichen Lizenz herausgibt. Wer dazu nicht in der Lage ist, kann eine kommerzielle Lizenz für den MySQL-Code von MySQL AB kaufen. Einzelheiten finden Sie unter http://www.mysql.com/company/legal/licensing/.
Der C-API-Code wird mit MySQL zusammen ausgeliefert. Er ist in der
mysqlclient
-Bibliothek inbegriffen und
ermöglicht C-Programmen den Zugriff auf die Datenbank.
Viele Clients der MySQL-Quelldistribution sind in C geschrieben.
Wenn Sie Beispiele für die Nutzung der C-API suchen, schauen Sie
sich diese Clients an. Zu finden sind sie im Verzeichnis
clients
der MySQL-Quelldistribution.
Die meisten anderen Client-APIs (alle außer Connector/J und
Connector/NET) nutzen die
mysqlclient
-Bibliothek zur Kommunikation mit
dem MySQL Server. Das bedeutet, dass Sie beispielsweise viele
derselben Umgebungsvariablen einsetzen können, die auch andere
Clientprogramme verwenden, da sie in der Bibliothek referenziert
werden. Eine Liste dieser Variablen finden Sie unter
Kapitel 8, Client- und Hilfsprogramme.
Der Client hat eine Größenbeschränkung für den Kommunikationspuffer. Für den Puffer werden anfangs 16 Kbyte reserviert, die jedoch automatisch bis hin zur Maximalgröße (16 Mbyte) ausgeweitet werden. Da Puffergrößen nur aufgrund der Nachfrage erhöht werden, werden allein dadurch, dass Sie die voreingestellte Maximalgröße erhöhen, keine größeren Ressourcen belegt. Die Überprüfung dieser Größe ist im Grunde nur eine Prüfung auf fehlerhafte Anweisungen und Kommunikationspakete.
Der Kommunikationspuffer muss groß genug sein, um eine einzelne
SQL-Anweisung (für die Übertragung von Client zu Server) und
eine Zeile der Rückgabedaten (für die Übertragung von Server zu
Client) zu speichern. Der Kommunikationspuffer jedes Threads wird
bis zum Größenlimit dynamisch vergrößert, um jede Anfrage oder
Zeile handhaben zu können. Wenn Sie beispielsweise
BLOB
-Werte mit bis zu 16 Mbyte Daten haben,
benötigen Sie für den Kommunikationspuffer ein Limit von
mindestens 16 Mbyte (sowohl im Server als auch im Client). Das
voreingestellte Limit im Client beträgt 16 Mbyte, aber im Server
nur 1 Mbyte. Sie können es erhöhen, indem Sie den Wert des
Parameters max_allowed_packet
beim Serverstart
heraufsetzen. Siehe Abschnitt 7.5.2, „Serverparameter feineinstellen“.
Der MySQL Server lässt jeden Kommunikationspuffer nach jeder
Anfrage auf net_buffer_length
zusammenschrumpfen. Bei Clients wird ein mit einer Verbindung
zusammenhängender Puffer erst beim Schließen der Verbindung
verkleinert, wenn der Arbeitsspeicher des Clients zurückgeholt
wird.
Zur Programmierung mit Threads siehe Abschnitt 24.2.15, „Wie man einen Thread-Client herstellt“. Zur Erstellung einer Standalone-Anwendung, die "Server" und "Client" in demselben Programm enthält (und nicht mit einem externen MySQL Server kommuniziert), siehe Abschnitt 24.1, „libmysqld, die eingebettete MySQL Server-Bibliothek“.
Diese Struktur ist ein Handle für eine einzelne
Datenbankverbindung. Sie wird für fast alle
MySQL-Funktionen benutzt. Bitte versuchen Sie nicht, eine
Kopie einer MYSQL
-Struktur anzulegen. Es
ist nicht garantiert, dass eine solche Kopie benutzbar ist.
Diese Struktur stellt das Ergebnis einer Anfrage dar, die
Zeilen liefert (SELECT
,
SHOW
, DESCRIBE
,
EXPLAIN
). Die Rückgabedaten aus der
Anfrage wird im weiteren Verlauf dieses Abschnitts als
Ergebnismenge bezeichnet.
Eine typsichere Darstellung einer Datenzeile. Sie ist
zurzeit als Array gezählter Byte-Strings implementiert.
(Diese dürfen nicht als auf null endende Strings behandelt
werden, wenn die Feldwerte Binärdaten enthalten könnten,
da solche Werte intern Nullbytes enthalten können.) Die
Zeilen werden mit mysql_fetch_row()
abgerufen.
Diese Struktur enthält Informationen über ein Feld, wie
beispielsweise seinen Namen, seinen Typ und seine Größe.
Ihre Bestandteile werden hier genauer erklärt. Die
MYSQL_FIELD
-Strukturen von Feldern
erhalten Sie, indem Sie wiederholt
mysql_fetch_field()
aufrufen. Die Werte
der Felder sind nicht Teil dieser Struktur, sondern in einer
MYSQL_ROW
-Struktur enthalten.
Dies ist eine typsichere Darstellung eines Offsets in einer
MySQL-Feldliste. (Wird von
mysql_field_seek()
benutzt.) Offsets sind
Feldnummern innerhalb einer Zeile. Sie werden beginnend mit
null gezählt.
Dieser Typ wird für die Anzahl der Zeilen und für
mysql_affected_rows()
,
mysql_num_rows()
und
mysql_insert_id()
genutzt. Er hat einen
Wertebereich von 0
bis
1.84e19
.
Auf manchen Systemen können Werte vom Typ
my_ulonglong
nicht ausgegeben werden. In
einem solchen Fall konvertieren Sie diesen in einen
unsigned long
und verwenden das
Ausgabeformat %lu
. Beispiel:
printf ("Number of rows: %lu\n", (unsigned long) mysql_num_rows(result));
Die MYSQL_FIELD
-Struktur hat folgende
Bestandteile:
char * name
Der Name des Felds als auf null endender String. Wenn dem
Feld mit einer AS
-Klausel ein Aliasname
gegeben wurde, ist der Wert von name
der
Alias.
char * org_name
Der Name des Felds als auf null endender String. Aliasnamen werden ignoriert.
char * table
Der Name der Tabelle, die dieses Feld enthält, wenn es
nicht ein berechnetes Feld ist. Für berechnete Felder ist
der table
-Wert ein leerer String. Wenn
der Tabelle mit einer AS
-Klausel ein
Aliasname gegeben wurde, ist der Wert von
name
der Alias.
char * org_table
Der Name der Tabelle als auf null endender String. Aliasnamen werden ignoriert.
char * db
Der Name der Datenbank, aus der das Feld stammt, als auf
null endender String. Ist das Feld ein berechnetes Feld, ist
db
ein leerer String.
char * catalog
Der Katalogname. Dieser Wert ist immer
"def"
.
char * def
Der Standardwert dieses Felds als auf null endender String.
Wird nur gesetzt, wenn Sie
mysql_list_fields()
verwenden.
unsigned long length
Die Feldbreite gemäß Tabellendefinition.
unsigned long max_length
Die maximale Breite des Felds für die Ergebnismenge (die
Länge des längsten Feldwerts der Zeilen, die sich
tatsächlich gerade in der Ergebnismenge befinden). Wenn Sie
mysql_store_result()
oder
mysql_list_fields()
benutzen, enthält
dieser Wert die Höchstlänge für das Feld. Wenn Sie
mysql_use_result()
aufrufen, ist der Wert
dieser Variablen null.
unsigned int name_length
Die Länge von name
.
unsigned int org_name_length
Die Länge von org_name
.
unsigned int table_length
Die Länge von table
.
unsigned int org_table_length
Die Länge von org_table
.
unsigned int db_length
Die Länge von db
.
unsigned int catalog_length
Die Länge von catalog
.
unsigned int def_length
Die Länge von def
.
unsigned int flags
Verschiedene Bit-Flags für das Feld. Im Wert von
flags
können null oder mehr der
folgenden Bits gesetzt sein:
Flag-Wert | Flag-Beschreibung |
NOT_NULL_FLAG | Feld kann nicht NULL sein |
PRI_KEY_FLAG | Feld ist Teil eines Primärschlüssels |
UNIQUE_KEY_FLAG | Feld ist Teil eines eindeutigen Schlüssels |
MULTIPLE_KEY_FLAG | Feld ist Teil eines nichteindeutigen Schlüssels |
UNSIGNED_FLAG | Feld hat das Attribut UNSIGNED |
ZEROFILL_FLAG | Feld hat das Attribut ZEROFILL |
BINARY_FLAG | Feld hat das Attribut BINARY |
AUTO_INCREMENT_FLAG | Feld hat das Attribut AUTO_INCREMENT |
ENUM_FLAG | Feld ist eine ENUM (veraltet) |
SET_FLAG | Feld ist ein SET (veraltet) |
BLOB_FLAG | Feld ist ein BLOB oder TEXT
(veraltet) |
TIMESTAMP_FLAG | Feld ist ein TIMESTAMP (veraltet) |
Die Flags BLOB_FLAG
,
ENUM_FLAG
, SET_FLAG
,
und TIMESTAMP_FLAG
sind veraltet, da sie
keinen Attribut-, sondern einen Feldtyp angeben. Es ist
besser, den field->type
mit
MYSQL_TYPE_BLOB
,
MYSQL_TYPE_ENUM
,
MYSQL_TYPE_SET
oder
MYSQL_TYPE_TIMESTAMP
zu vergleichen.
Das folgende Beispiel zeigt eine typische Verwendung des
flags
-Werts:
if (field->flags & NOT_NULL_FLAG) printf("Field can't be null\n");
Mit den folgenden Makros können Sie den booleschen Status
des flags
-Werts nachschauen:
Flag-Status | Beschreibung |
IS_NOT_NULL(flags) | Ist wahr, wenn dieses Feld als NOT NULL definiert ist |
IS_PRI_KEY(flags) | Ist wahr, wenn dieses Feld ein Primärschlüssel ist |
IS_BLOB(flags) | Ist wahr, wenn dieses Feld ein BLOB oder
TEXT ist (veraltet; bitte testen
Sie stattdessen field->type ) |
unsigned int decimals
Die Anzahl der Dezimalstellen für numerische Felder.
unsigned int charset_nr
Die Nummer des Zeichensatzes für das Feld.
enum enum_field_types type
Der Typ des Felds. Der type
-Wert kann
eines der MYSQL_TYPE_
-Symbole aus der
folgenden Tabelle sein.
Typwert | Typbeschreibung |
MYSQL_TYPE_TINY | TINYINT -Feld |
MYSQL_TYPE_SHORT | SMALLINT -Feld |
MYSQL_TYPE_LONG | INTEGER -Feld |
MYSQL_TYPE_INT24 | MEDIUMINT -Feld |
MYSQL_TYPE_LONGLONG | BIGINT -Feld |
MYSQL_TYPE_DECIMAL | DECIMAL - oder NUMERIC -Feld |
MYSQL_TYPE_NEWDECIMAL | DECIMAL - oder NUMERIC -Typ für
Präzisionsberechnungen |
MYSQL_TYPE_FLOAT | FLOAT -Feld |
MYSQL_TYPE_DOUBLE | DOUBLE - oder REAL -Feld |
MYSQL_TYPE_BIT | BIT -Feld |
MYSQL_TYPE_TIMESTAMP | TIMESTAMP -Feld |
MYSQL_TYPE_DATE | DATE -Feld |
MYSQL_TYPE_TIME | TIME -Feld |
MYSQL_TYPE_DATETIME | DATETIME -Feld |
MYSQL_TYPE_YEAR | YEAR -Feld |
MYSQL_TYPE_STRING | CHAR - oder BINARY -Feld |
MYSQL_TYPE_VAR_STRING | VARCHAR - oder VARBINARY -Feld |
MYSQL_TYPE_BLOB | BLOB - oder TEXT -Feld (die
Maximallänge wird mit max_length
ermittelt) |
MYSQL_TYPE_SET | SET -Feld |
MYSQL_TYPE_ENUM | ENUM -Feld |
MYSQL_TYPE_GEOMETRY | Feld eines raumbezogenen Typs |
MYSQL_TYPE_NULL | Feld mit NULL -Typ |
MYSQL_TYPE_CHAR | Veraltet; verwenden Sie stattdessen MYSQL_TYPE_TINY |
Mit dem Makro IS_NUM()
können Sie
testen, ob ein Feld einen numerischen Typ hat. Wenn Sie den
type
-Wert an IS_NUM()
übergeben und TRUE zurückgeliefert wird, ist das Feld
numerisch:
if (IS_NUM(field->type)) printf("Field is numeric\n");
Die Funktionen der C-API werden im Folgenden zusammengefasst und in einem späteren Abschnitt genauer beschrieben. Siehe hierzu Abschnitt 24.2.3, „C-API: Funktionsbeschreibungen“.
Funktion | Beschreibung |
mysql_affected_rows() | Liefert die Anzahl der mit dem letzten UPDATE ,
DELETE oder INSERT
geänderten/gelöschten/eingefügten Zeilen |
mysql_autocommit() | Schaltet Autocommit ein oder aus |
mysql_change_user() | Ändert den Benutzer und die Datenbank für eine offene Verbindung |
mysql_charset_name() | Liefert den Namen des Standardzeichensatzes für die Verbindung |
mysql_close() | Schließt eine Serververbindung |
mysql_commit() | Committet die Transaktion. |
mysql_connect() | Verbindet sich mit einem MySQL Server. Diese Funktion ist veraltet;
verwenden Sie stattdessen
mysql_real_connect() . |
mysql_create_db() | Legt eine Datenbank an. Diese Funktion ist veraltet; verwenden Sie
stattdessen die SQL-Anweisung CREATE
DATABASE . |
mysql_data_seek() | Sucht in der Ergebnismenge einer Anfrage eine beliebige Datenzeile |
mysql_debug() | Führt ein DBUG_PUSH mit dem angegebenen String durch |
mysql_drop_db() | Löscht eine Datenbank. Diese Funktion ist veraltet; verwenden Sie
stattdessen die SQL-Anweisung DROP
DATABASE . |
mysql_dump_debug_info() | Lässt den Server Debugginginformationen in das Log schreiben |
mysql_eof() | Stellt fest, ob die letzte Zeile einer Ergebnismenge gelesen wurde.
Diese Funktion ist veraltet; verwenden Sie stattdessen
mysql_errno() oder
mysql_error() . |
mysql_errno() | Liefert die Fehlernummer für die zuletzt aufgerufene MySQL-Funktion |
mysql_error() | Liefert die Fehlermeldung für die zuletzt aufgerufene MySQL-Funktion |
mysql_escape_string() | Versieht Sonderzeichen in einem String, der in einer SQL-Anweisung benutzt werden soll, mit Escape-Symbolen |
mysql_fetch_field() | Liefert den Typ des nächsten Tabellenfelds. |
mysql_fetch_field_direct() | Liefert den Typ des Tabellenfelds mit der gegebenen Feldnummer |
mysql_fetch_fields() | Liefert ein Array aller Feldstrukturen |
mysql_fetch_lengths() | Liefert die Längen aller Spalten der aktuellen Zeile |
mysql_fetch_row() | Holt die nächste Zeile der Ergebnismenge ab |
mysql_field_seek() | Setzt den Spalten-Cursor auf eine gegebene Spalte |
mysql_field_count() | Liefert die Anzahl der Ergebnisspalten der letzten Anweisung |
mysql_field_tell() | Liefert die Position des Feld-Cursors, der für das letzte
mysql_fetch_field() verwendet wurde |
mysql_free_result() | Gibt den von einer Ergebnismenge belegten Speicher frei |
mysql_get_client_info() | Liefert Versionsinformationen für den Client als String |
mysql_get_client_version() | Liefert Versionsinformationen für den Client als Integer |
mysql_get_host_info() | Liefert einen String, der die Verbindung beschreibt |
mysql_get_server_version() | Liefert die Versionsnummer des Servers als Integer. |
mysql_get_proto_info() | Liefert die Protokollversion der Verbindung |
mysql_get_server_info() | Liefert die Versionsnummer des Servers |
mysql_info() | Liefert Informationen über die zuletzt ausgeführte Anfrage |
mysql_init() | Holt oder initialisiert eine MYSQL -Struktur |
mysql_insert_id() | Liefert die für eine AUTO_INCREMENT -Spalte von der
vorhergehenden Anfrage generierte ID |
mysql_kill() | Hält einen gegebenen Thread an |
mysql_library_end() | Finalisiert die MySQL-C-API-Bibliothek |
mysql_library_init() | Initialisiert die MySQL-C-API-Bibliothek |
mysql_list_dbs() | Liefert Datenbanknamen, die mit einem einfachen regulären Ausdruck übereinstimmen |
mysql_list_fields() | Liefert Feldnamen, die mit einem einfachen regulären Ausdruck übereinstimmen |
mysql_list_processes() | Liefert eine Liste der aktuellen Server-Threads |
mysql_list_tables() | Liefert Tabellennamen, die mit einem einfachen regulären Ausdruck übereinstimmen |
mysql_more_results() | Prüft, ob noch weitere Ergebnisse vorhanden sind |
mysql_next_result() | Liefert/initiiert das nächste Ergebnis für Mehrfachanweisungen |
mysql_num_fields() | Liefert die Anzahl der Spalten einer Ergebnismenge |
mysql_num_rows() | Liefert die Anzahl der Zeilen einer Ergebnismenge |
mysql_options() | Stellt Verbindungsoptionen für mysql_connect() ein |
mysql_ping() | Prüft, ob die Serververbindung funktioniert, und baut bei Bedarf eine neue Verbindung auf |
mysql_query() | Führt eine SQL-Anfrage aus, die als auf null endender String angegeben ist. |
mysql_real_connect() | Verbindet sich mit einem MySQL Server |
mysql_real_escape_string() | Versieht Sonderzeichen in einem String, der in einer SQL-Anweisung benutzt werden soll, mit Escape-Symbolen, wobei der aktuelle Zeichensatz der Verbindung berücksichtigt wird |
mysql_real_query() | Führt eine als abgezählter String angegebene SQL-Anfrage aus |
mysql_refresh() | Schreibt Tabellen und Caches auf die Platte zurück oder setzt sie zurück |
mysql_reload() | Lässt den Server die Berechtigungstabellen neu laden |
mysql_rollback() | Rollt die Transaktion zurück |
mysql_row_seek() | Findet einen Zeilen-Offset in einer Ergebnismenge anhand des
Rückgabewerts von mysql_row_tell() |
mysql_row_tell() | Liefert die Position des Zeilen-Cursors |
mysql_select_db() | Wählt eine Datenbank aus |
mysql_server_end() | Finalisiert die Embedded Server-Bibliothek |
mysql_server_init() | Initialisiert die Embedded Server-Bibliothek |
mysql_set_server_option() | Setzt eine Option für die Verbindung (wie
multi-statements ) |
mysql_sqlstate() | Liefert den SQLSTATE-Fehlercode für den letzten Fehler |
mysql_shutdown() | Fährt den Datenbankserver herunter |
mysql_stat() | Liefert den Serverstatus als String |
mysql_store_result() | Holt eine vollständige Ergebnismenge auf den Client |
mysql_thread_id() | Liefert die aktuelle Thread-ID |
mysql_thread_safe() | Liefert 1, wenn die Clients als Thread-sicher kompiliert wurden |
mysql_use_result() | Initiiert einen zeilenweisen Abruf der Ergebnismenge |
mysql_warning_count() | Liefert die Anzahl der Warnungen für die vorangehende SQL-Anweisung |
Anwendungsprogramme sollten sich an folgende Vorgehensweise halten, wenn sie mit MySQL zusammenarbeiten wollen:
Sie initialisieren die MySQL-Bibliothek durch Aufruf von
mysql_library_init()
. Die Bibliothek kann
entweder die
mysqlclient
-C-Clientbibliothek oder die
mysqld
-Embedded Server-Bibliothek sein,
je nachdem, ob die Anwendung mit dem Flag
-libmysqlclient
oder
-libmysqld
verlinkt worden ist.
Sie initialisieren einen Verbindungs-Handler durch Aufruf
von mysql_init()
und verbinden sich durch
mysql_real_connect()
mit dem Server.
Sie geben ihre SQL-Anweisungen und verarbeiten die Ergebnisse. (Im Folgenden wird genauer beschrieben, wie dies getan wird.)
Sie schließen die Verbindung zum MySQL Server durch Aufruf
von mysql_close()
.
Sie beenden die Nutzung der MySQL-Bibliothek durch Aufruf
von mysql_library_end()
.
mysql_library_init()
und
mysql_library_end()
werden aufgerufen, um die
MySQL-Bibliothek richtig zu initialisieren und zu finalisieren.
Für Anwendungen, die mit der Clientbibliothek verlinkt sind,
bietet diese Funktionen eine verbesserte Speicherverwaltung.
Wenn Sie mysql_library_end()
nicht aufrufen,
bleibt weiterhin ein Arbeitsspeicherblock reserviert. (Zwar
belegt die Anwendung deswegen nicht mehr Speicher, aber
bestimmte Detektoren für Speicherlecks würden sich
beschweren.) Für Anwendungen, die mit dem Embedded Server
verlinkt sind, starten und stoppen diese Aufrufe den Server.
mysql_library_init()
und
mysql_library_end()
sind in Wirklichkeit
#define
-Symbole und somit äquivalent zu
mysql_server_init()
und
mysql_server_end()
, aber die anderen Namen
betonen stärker, dass diese Funktionen immer vor und nach der
Benutzung einer MySQL-Bibliothek aufgerufen werden müssen, egal
ob die Anwendung die mysqlclient
- oder die
mysqld
-Bibliothek verwendet. In älteren
MySQL-Versionen können Sie stattdessen
mysql_server_init()
und
mysql_server_end()
aufrufen.
Sie können den Aufruf von
mysql_library_init()
auch weglassen, da
mysql_init()
diese Funktion automatisch
aufruft, wenn es notwendig ist.
Um sich mit dem Server zu verbinden, initialisieren Sie mit
mysql_init()
einen Verbindungs-Handler und
rufen mysql_real_connect()
mit diesem Handler
(sowie anderen Informationen, wie zum Beispiel Hostname,
Benutzername und Passwort) auf. Beim Verbinden setzt
mysql_real_connect()
das
reconnect
-Flag (ein Teil der
MYSQL
-Struktur) auf den Wert
1
, wenn die API-Version älter als 5.0.3 ist,
oder auf 0
, wenn sie neuer ist. Wenn dieses
Flag den Wert 1
hat, bedeutet dies: Falls
eine Anweisung wegen Verbindungsabbruchs nicht ausgeführt
werden kann, versucht das System, sich erneut mit dem Server zu
verbinden, ehe es aufgibt. Seit MySQL 5.0.13 können Sie das
Verhalten in Bezug auf Neuverbindungen mit der Option
MYSQL_OPT_RECONNECT
von
mysql_options()
steuern. Wenn Sie die
Verbindung nicht mehr benötigen, beenden Sie sie mit
mysql_close()
.
Während eine Verbindung aktiv ist, kann der Client
SQL-Anweisungen mit mysql_query()
oder
mysql_real_query()
an den Server senden. Der
Unterschied ist der, dass mysql_query()
die
Anfrage als auf null endenden String erwartet, während
mysql_real_query()
mit einem abgezählten
String rechnet. Wenn der String Binärdaten enthält (die auch
Nullbytes umfassen können), müssen Sie
mysql_real_query()
verwenden.
Für alle Nicht-SELECT
-Anfragen
(beispielsweise INSERT
,
UPDATE
, DELETE
) können
Sie die Anzahl der betroffenen Zeilen durch
mysql_affected_rows()
ermitteln.
Bei SELECT
-Anfragen rufen Sie die betroffenen
Zeilen als Ergebnismenge ab. (Beachten Sie, dass manche
Anweisungen insofern SELECT
-ähnlich sind,
als sie Zeilen zurückliefern. Dazu gehören
SHOW
, DESCRIBE
und
EXPLAIN
. Diese sollten ebenso wie
SELECT
-Anweisungen behandelt werden.)
Ein Client hat zwei Möglichkeiten, mit Ergebnismengen
umzugehen: Erstens kann er die gesamte Ergebnismenge in einem
Schwung abholen, indem er
mysql_store_result()
aufruft. Diese Funktion
holt sich vom Server alle von der Anfrage gelieferten Zeilen und
speichert sie auf dem Client. Die zweite Möglichkeit besteht
darin, die Ergebnismenge mit
mysql_use_result()
zeilenweise abzurufen.
Diese Funktion initialisiert den Datenabruf, holt aber die
Zeilen vom Server nicht wirklich ab.
In beiden Fällen greifen Sie mit
mysql_fetch_row()
auf die Zeilen zu. Mit
mysql_store_result()
greift sich
mysql_fetch_row()
Zeilen, die vom Server
bereits abgeholt worden sind. Mit
mysql_use_result()
ruft
mysql_fetch_row()
die jeweilige Zeile selbst
vom Server. Informationen über den Umfang der Daten in den
Zeilen liefert Ihnen mysql_fetch_lengths()
.
Wenn Sie mit einer Ergebnismenge fertig sind, geben Sie mit
mysql_free_result()
ihren Arbeitsspeicher
wieder frei.
Die beiden Abrufmechanismen ergänzen einander. Clientprogramme
sollten den Ansatz verfolgen, der für ihre Zwecke am besten
geeignet ist. In der Praxis wird
mysql_store_result()
von den Clients
häufiger verwendet.
mysql_store_result()
hat einen Vorteil. Da
bereits alle Zeilen auf den Client geladen wurden, können Sie
nicht nur der Reihe nach auf sie zugreifen, sondern sich mit
mysql_data_seek()
oder
mysql_row_seek()
in der Ergebnismenge vor-
und zurückbewegen und auf eine andere Zeilenposition in der
Ergebnismenge gehen. Sie können überdies mit
mysql_num_rows()
herausfinden, wie viele
Zeilen die Ergebnismenge hat. Allerdings kann
mysql_store_result()
bei großen
Ergebnismengen auch viel Speicher belegen, wodurch die Gefahr
von out-of-memory
-Bedingungen wächst.
mysql_use_result()
hat den Vorteil, dass der
Client nicht so viel Arbeitsspeicher für die Ergebnismenge
benötigt, da er immer nur eine einzige Zeile speichern muss
(und durch den geringeren Aufwand bei der Zuweisung kann
mysql_use_result()
überdies schneller sein).
Die Nachteile: Sie müssen jede Zeile schnell verarbeiten, um
den Server nicht aufzuhalten, und Sie haben keinen beliebigen
Zugriff auf die Ergebnismenge (sondern können nur sequenziell
auf die Zeilen zugreifen). Außerdem kennen Sie die Anzahl der
Zeilen in der Ergebnismenge erst, wenn Sie sie alle abgeholt
haben. Hinzu kommt, dass Sie sämtliche Zeilen abholen
müssen, und zwar selbst dann,
wenn Sie mitten in der Verarbeitung die gesuchten Informationen
bereits gefunden haben.
Den Clients ermöglicht diese API, auf Anweisungen in
angemessener Form zu reagieren (also die Zeilen nur nach Bedarf
abzuholen), ohne zu wissen, ob die Anweisung ein
SELECT
ist. Dies erreichen Sie, indem Sie
mysql_store_result()
nach jeder
mysql_query()
(oder
mysql_real_query()
) aufrufen. Wenn der
Ergebnismengenaufruf Erfolg hat, war die Anweisung ein
SELECT
und Sie können die Zeilen einlesen.
Schlägt der Ergebnismengenaufruf fehl, so ermitteln Sie mit
mysql_field_count()
, ob überhaupt ein
Ergebnis zu erwarten war. Wenn
mysql_field_count()
null zurückliefert,
ergab die Anweisung keine Daten (war also ein
INSERT
, UPDATE
,
DELETE
oder etwas Ähnliches), von
denen man auch keine Rückgabezeilen erwarten konnte. Wenn
mysql_field_count()
einen von null
verschiedenen Wert hat, hätte die Anweisung eigentlich Zeilen
zurückgeben sollen, hat es aber nicht getan. Dies deutet auf
eine fehlgeschlagene SELECT
-Anweisung hin.
Ein Beispiel finden Sie unter
mysql_field_count()
.
Sowohl mysql_store_result()
als auch
mysql_use_result()
liefern Ihnen
Informationen über die Felder, aus denen die Ergebnismenge
besteht (die Anzahl der Felder, ihre Namen und Typen und so
weiter). Sie können auf die Feldinformationen in der Zeile
sequenziell zugreifen, indem Sie wiederholt
mysql_fetch_field()
aufrufen, oder anhand der
Feldnummer, indem Sie
mysql_fetch_field_direct()
aufrufen. Die
aktuelle Cursor-Position für das Feld können Sie durch
mysql_field_seek()
ändern. Wenn Sie den
Feld-Cursor verstellen, wirkt sich das auf nachfolgende
mysql_fetch_field()
-Aufrufe aus. Sie können
die Feldinformationen auch alle auf einmal abholen, indem Sie
mysql_fetch_fields()
aufrufen.
Um Fehler zu entdecken und zu melden, gibt Ihnen MySQL über die
Funktionen mysql_errno()
und
mysql_error()
Zugriff auf
Fehlerinformationen. Diese Funktionen geben den Fehlercode oder
die Fehlermeldung für die zuletzt aufgerufene Funktion zurück,
die mit oder ohne Erfolg gelaufen sein kann. So können Sie
ermitteln, wann welcher Fehler aufgetreten ist.
mysql_affected_rows()
mysql_autocommit()
mysql_change_user()
mysql_character_set_name()
mysql_close()
mysql_commit()
mysql_connect()
mysql_create_db()
mysql_data_seek()
mysql_debug()
mysql_drop_db()
mysql_dump_debug_info()
mysql_eof()
mysql_errno()
mysql_error()
mysql_escape_string()
mysql_fetch_field()
mysql_fetch_field_direct()
mysql_fetch_fields()
mysql_fetch_lengths()
mysql_fetch_row()
mysql_field_count()
mysql_field_seek()
mysql_field_tell()
mysql_free_result()
mysql_get_character_set_info()
mysql_get_client_info()
mysql_get_client_version()
mysql_get_host_info()
mysql_get_proto_info()
mysql_get_server_info()
mysql_get_server_version()
mysql_hex_string()
mysql_info()
mysql_init()
mysql_insert_id()
mysql_kill()
mysql_library_end()
mysql_library_init()
mysql_list_dbs()
mysql_list_fields()
mysql_list_processes()
mysql_list_tables()
mysql_more_results()
mysql_next_result()
mysql_num_fields()
mysql_num_rows()
mysql_options()
mysql_ping()
mysql_query()
mysql_real_connect()
mysql_real_escape_string()
mysql_real_query()
mysql_refresh()
mysql_reload()
mysql_rollback()
mysql_row_seek()
mysql_row_tell()
mysql_select_db()
mysql_set_character_set()
mysql_set_server_option()
mysql_shutdown()
mysql_sqlstate()
mysql_ssl_set()
mysql_stat()
mysql_store_result()
mysql_thread_id()
mysql_use_result()
mysql_warning_count()
In den folgenden Beschreibungen meint ein Parameter oder
Rückgabewert von NULL
einen
NULL
-Wert im Sinne der Programmiersprache C
und keinen NULL
-Wert von MySQL.
Funktionen, die einen Wert liefern, geben normalerweise einen
Zeiger oder einen Integer zurück. Wenn nichts anderes angegeben
ist, liefern Funktionen, die einen Zeiger zurückgeben, bei
Erfolg einen von NULL
verschiedenen Wert und
bei Misserfolg einen NULL
-Wert, und
Funktionen, die einen Integer liefern, geben bei Erfolg null und
bei Misserfolg einen von null verschiedenen Wert zurück.
Beachten Sie, dass „von null verschieden“ genau das
meint, was es sagt: Sofern die Funktionsbeschreibung nichts
Abweichendes festlegt, können Sie diesen Wert mit nichts
anderem als null vergleichen:
if (result) /* richtig */ ... error ... if (result < 0) /* falsch */ ... error ... if (result == -1) /* falsch */ ... error ...
Wenn eine Funktion einen Fehler zurückliefert, finden Sie im
Unterabschnitt Fehler der
jeweiligen Funktionsbeschreibung eine Liste der möglichen
Fehlertypen. Welcher dieser Fehler auftrat, ermitteln Sie mit
mysql_errno()
. Eine String-Darstellung des
Fehlers erhalten Sie durch mysql_error()
.
my_ulonglong mysql_affected_rows(MYSQL
*mysql)
Beschreibung
Liefert die Anzahl der vom letzten UPDATE
aktualisierten, vom letzten DELETE
gelöschten oder vom letzten INSERT
eingefügten Zeilen. Kann für UPDATE
-,
DELETE
- oder
INSERT
-Anweisungen direkt nach
mysql_query()
aufgerufen werden. Bei
SELECT
-Anweisungen funktioniert
mysql_affected_rows()
genau wie
mysql_num_rows()
.
Rückgabewerte
Ein Integer größer null zeigt die Anzahl der betroffenen
oder abgerufenen Zeilen an. Null bedeutet, dass mit dem
UPDATE
keine Zeilen aktualisiert wurden,
dass keine Zeilen zu der WHERE
-Klausel der
Anfrage gepasst haben oder die Anfrage noch gar nicht
ausgeführt worden ist. -1 bedeutet, dass die Anfrage einen
Fehler zurückgeliefert hat oder, bei einer
SELECT
-Anfrage, dass
mysql_affected_rows()
vor
mysql_store_result()
aufgerufen wurde. Da
mysql_affected_rows()
einen vorzeichenlosen
Wert liefert, können Sie -1 feststellen, indem Sie den
Rückgabewert mit (my_ulonglong)-1
vergleichen (oder mit (my_ulonglong)~0
; das
ist dasselbe).
Fehler
Keine.
Beispiel
mysql_query(&mysql,"UPDATE products SET cost=cost*1.25 WHERE group=10"); printf("%ld products updated",(long) mysql_affected_rows(&mysql));
Wenn Sie bei einer Verbindung mit mysqld
das Flag CLIENT_FOUND_ROWS
angeben, liefert
mysql_affected_rows()
die Anzahl der
Zeilen, die die WHERE
-Klausel von
UPDATE
-Anweisungen erkannt hat.
Beachten Sie, dass mysql_affected_rows()
bei Verwendung eines REPLACE
-Befehls 2
liefert, wenn die neue Zeile eine alte ersetzt, da hier eine
Zeile eingefügt wird, nachdem das Duplikat gelöscht worden
ist.
Wenn Sie mit INSERT ... ON DUPLICATE KEY
UPDATE
eine Zeile einfügen, liefert
mysql_affected_rows()
den Wert 1, wenn die
Zeile als neue Zeile eingefügt wurde, und 2, wenn eine
vorhandene Zeile geändert wurde.
my_bool mysql_autocommit(MYSQL *mysql, my_bool
mode)
Beschreibung
Schaltet den Autocommit-Modus ein, wenn
mode
1 ist, und aus, wenn
mode
0 ist.
Rückgabewerte
Null bei Erfolg und ein von null verschiedener Wert bei einem Fehler.
Fehler
Keine.
my_bool mysql_change_user(MYSQL *mysql, const char
*user, const char *password, const char *db)
Beschreibung
Wechselt auf der durch mysql
angegebenen
Verbindung den Benutzer und macht die in db
angegebene zur (aktuellen) Standarddatenbank. In nachfolgenden
Anfragen ist diese Datenbank dann der Standardbezugsrahmen
für Tabellenverweise, die nicht explizit eine Datenbank
angeben.
mysql_change_user()
scheitert, wenn der
Benutzer sich nicht authentifizieren kann oder keine
Berechtigung zur Nutzung der Datenbank hat. In diesem Fall
werden Benutzer und Datenbank nicht geändert.
Der Parameter db
kann auf
NULL
gesetzt werden, wenn keine
Standarddatenbank vorgegeben werden soll.
Dieser Befehl veranlasst immer ein ROLLBACK
aller laufenden Transaktionen, schließt alle temporären
Tabellen, hebt Tabellensperren auf und setzt den Status so
zurück, als hätte jemand eine ganz neue Verbindung
aufgebaut. Das geschieht sogar dann, wenn der Benutzer nicht
wechselt.
Rückgabewerte
Null bei Erfolg und ein von null verschiedener Wert bei einem Fehler.
Fehler
Dieselben wie bei mysql_real_connect()
.
CR_COMMANDS_OUT_OF_SYNC
Befehle wurden in der falschen Reihenfolge ausgeführt.
CR_SERVER_GONE_ERROR
Der MySQL Server ist nicht mehr verfügbar.
CR_SERVER_LOST
Die Serververbindung brach während der Anfrage ab.
CR_UNKNOWN_ERROR
Ein unbekannter Fehler ist aufgetreten.
ER_UNKNOWN_COM_ERROR
Der MySQL Server implementiert diesen Befehl gar nicht (wahrscheinlich ein älterer Server).
ER_ACCESS_DENIED_ERROR
Benutzer oder Passwort ist falsch.
ER_BAD_DB_ERROR
Die Datenbank existiert nicht.
ER_DBACCESS_DENIED_ERROR
Der Benutzer hat keine Zugriffsrechte auf die Datenbank.
ER_WRONG_DB_NAME
Der Datenbankname war zu lang.
Beispiel
if (mysql_change_user(&mysql, "user", "password", "new_database")) { fprintf(stderr, "Failed to change user. Error: %s\n", mysql_error(&mysql)); }
const char *mysql_character_set_name(MYSQL
*mysql)
Beschreibung
Gibt den Standardzeichensatz für die aktuelle Verbindung zurück.
Rückgabewerte
Der Standardzeichensatz.
Fehler
Keine.
void mysql_close(MYSQL *mysql)
Beschreibung
mysql_close()
schließt eine zuvor
geöffnete Verbindung und gibt den Verbindungs-Handle frei,
den mysql
benutzt hat, wenn der Handle
automatisch von mysql_init()
oder
mysql_connect()
zugewiesen worden war.
Rückgabewerte
Keine.
Fehler
Keine.
my_bool mysql_commit(MYSQL *mysql)
Beschreibung
Committet die laufende Transaktion.
Was diese Funktion tut, hängt von dem Wert der
Systemvariablen completion_type
ab. Wenn
der completion_type
2 ist, gibt der Server
nach Beendigung der Transaktion Ressourcen frei und schließt
die Clientverbindung. Das Clientprogramm sollte
mysql_close()
aufrufen, um die Verbindung
von der Clientseite aus zu schließen.
Rückgabewerte
Null bei Erfolg und ein von null verschiedener Wert bei einem Fehler.
Fehler
Keine.
MYSQL *mysql_connect(MYSQL *mysql, const char *host,
const char *user, const char *passwd)
Beschreibung
Diese Funktion ist veraltet. Stattdessen sollte
mysql_real_connect()
verwendet werden.
mysql_connect()
versucht, eine Verbindung
zu einer auf dem host
laufenden
MySQL-Datenbank-Engine herzustellen.
mysql_connect()
muss erfolgreich gelaufen
sein, ehe Sie irgendeine der anderen API-Funktionen ausführen
können, ausgenommen
mysql_get_client_info()
.
Die Parameter haben dieselbe Bedeutung wie die entsprechenden
Parameter für mysql_real_connect()
, mit
dem Unterschied, dass der Verbindungsparameter
NULL
sein kann. In diesem Fall weist die
C-API automatisch Speicher für die Verbindungsstruktur zu und
gibt ihn wieder frei, wenn Sie
mysql_close()
aufrufen. Der Nachteil: Sie
können keine Fehlermeldung abrufen, wenn die Verbindung
scheitert. (Um von mysql_errno()
oder
mysql_error()
Fehlerinformationen zu
bekommen, müssen Sie einen gültigen
MYSQL
-Zeiger zur Verfügung stellen.)
Rückgabewerte
Dieselben wie für mysql_real_connect()
.
Fehler
Dieselben wie für mysql_real_connect()
.
int mysql_create_db(MYSQL *mysql, const char
*db)
Beschreibung
Legt die im db
-Parameter genannte Datenbank
an.
Diese Funktion ist veraltet. Bitte verwenden Sie stattdessen
mysql_query()
, um eine SQL-CREATE
DATABASE
-Anweisung zu geben.
Rückgabewerte
Null, wenn die Datenbank erfolgreich angelegt wurde, und ein von null verschiedener Wert, wenn ein Fehler auftrat.
Fehler
CR_COMMANDS_OUT_OF_SYNC
Befehle wurden in der falschen Reihenfolge ausgeführt.
CR_SERVER_GONE_ERROR
Der MySQL Server ist nicht mehr verfügbar.
CR_SERVER_LOST
Die Serververbindung brach während der Anfrage ab.
CR_UNKNOWN_ERROR
Ein unbekannter Fehler ist aufgetreten.
Beispiel
if(mysql_create_db(&mysql, "my_database")) { fprintf(stderr, "Failed to create new database. Error: %s\n", mysql_error(&mysql)); }
void mysql_data_seek(MYSQL_RES *result, my_ulonglong
offset)
Beschreibung
Findet eine beliebige Zeile in einer Ergebnismenge. Der
offset
-Wert ist eine Zeilennummer zwischen
0
und
mysql_num_rows(result)-1
.
Da für diese Funktion erforderlich ist, dass die
Ergebnismengenstruktur die gesamte Ergebnismenge enthält,
kann mysql_data_seek()
nur in Verbindung
mit mysql_store_result()
und nicht mit
mysql_use_result()
verwendet werden.
Rückgabewerte
Keine.
Fehler
Keine.
void mysql_debug(const char *debug)
Beschreibung
Führt DBUG_PUSH
auf dem gegebenen String
aus. mysql_debug()
benutzt die Fred
Fish-Debugbibliothek. Um diese Funktion benutzen zu können,
müssen Sie die Clientbibliothek mit Debuggingunterstützung
kompilieren. Siehe Abschnitt E.1, „Einen MySQL-Server debuggen“ und
Abschnitt E.2, „Einen MySQL-Client debuggen“.
Rückgabewerte
Keine.
Fehler
Keine.
Beispiel
Dieser Aufruf lässt die Clientbibliothek eine Trace-Datei iin
/tmp/client.trace
auf dem Clientcomputer
generieren:
mysql_debug("d:t:O,/tmp/client.trace");
int mysql_drop_db(MYSQL *mysql, const char
*db)
Beschreibung
Löscht die im db
-Parameter angegebene
Datenbank.
Diese Funktion ist veraltet. Bitte benutzen Sie stattdessen
mysql_query()
, um eine SQL-DROP
DATABASE
-Anweisung zu erteilen.
Rückgabewerte
Null, wenn die Datenbank erfolgreich gelöscht wurde. Ein von null verschiedener Wert, wenn ein Fehler auftrat.
Fehler
CR_COMMANDS_OUT_OF_SYNC
Befehle wurden in der falschen Reihenfolge ausgeführt.
CR_SERVER_GONE_ERROR
Der MySQL Server ist nicht mehr verfügbar.
CR_SERVER_LOST
Die Serververbindung brach während der Anfrage ab.
CR_UNKNOWN_ERROR
Ein unbekannter Fehler ist aufgetreten.
Beispiel
if(mysql_drop_db(&mysql, "my_database")) fprintf(stderr, "Failed to drop the database: Error: %s\n", mysql_error(&mysql));
int mysql_dump_debug_info(MYSQL *mysql)
Beschreibung
Weist den Server an, Debugginginformationen in das Log zu
schreiben. Damit dies funktioniert, benötigt der Benutzer das
SUPER
-Recht.
Rückgabewerte
Null, wenn der Befehl Erfolg hatte. Ein von null verschiedener Wert, wenn ein Fehler auftrat.
Fehler
CR_COMMANDS_OUT_OF_SYNC
Befehle wurden in der falschen Reihenfolge ausgeführt.
CR_SERVER_GONE_ERROR
Der MySQL Server ist nicht mehr verfügbar.
CR_SERVER_LOST
Die Serververbindung brach während der Anfrage ab.
CR_UNKNOWN_ERROR
Ein unbekannter Fehler ist aufgetreten.
my_bool mysql_eof(MYSQL_RES *result)
Beschreibung
Diese Funktion ist veraltet. mysql_errno()
oder mysql_error()
können stattdessen
verwendet werden.
mysql_eof()
stellt fest, ob die letzte
Zeile einer Ergebnismenge gelesen worden ist.
Wenn Sie eine Ergebnismenge mit einem erfolgreichen Aufruf von
mysql_store_result()
abrufen, empfängt der
Client die gesamte Menge mit einer einzigen Operation. Der
Rückgabewert NULL
von
mysql_fetch_row()
bedeutet in diesem Fall
immer, dass das Ende der Ergebnismenge erreicht wurde, sodass
sich mysql_eof()
erübrigt. In Verbindung
mit mysql_store_result()
liefert
mysql_eof()
immer TRUE.
Wenn Sie dagegen den Abruf einer Ergebnismenge mit
mysql_use_result()
initiieren, werden die
Zeilen eine nach der anderen mit wiederholten
mysql_fetch_row()
-Aufrufen vom Server
geholt. Da bei diesem Prozess ein Verbindungsfehler auftreten
kann, bedeutet eine NULL
-Rückgabe von
mysql_fetch_row()
nicht unbedingt, dass
ganz normal das Ende der Ergebnismenge erreicht wurde. In
diesem Fall können Sie mit mysql_eof()
feststellen, was tatsächlich geschah.
mysql_eof()
liefert einen von null
verschiedenen Wert, wenn das Ende der Ergebnismenge erreicht
wurde, und null, wenn ein Fehler auftrat.
Eigentlich ist mysql_eof()
älter als die
MySQL-Standardfehlerfunktionen
mysql_errno()
und
mysql_error()
. Da diese Fehlerfunktionen
dieselben Informationen liefern, bevorzugen wir sie gegenüber
der veralteten Funktion mysql_eof()
.
(Eigentlich geben sie sogar mehr Informationen, da
mysql_eof()
nur einen booleschen Wert
zurückgibt, während die Fehlerfunktionen auch den Grund für
einen Fehler verraten.)
Rückgabewerte
Null, wenn kein Fehler auftrat. Ein von null verschiedener Wert, wenn das Ende der Ergebnismenge erreicht wurde.
Fehler
Keine.
Beispiel
Das folgende Beispiel zeigt, wie sich
mysql_eof()
einsetzen lässt:
mysql_query(&mysql,"SELECT * FROM some_table"); result = mysql_use_result(&mysql); while((row = mysql_fetch_row(result))) { // Tu etwas mit den Daten } if(!mysql_eof(result)) // mysql_fetch_row() scheiterte wegen eines Fehlers { fprintf(stderr, "Error: %s\n", mysql_error(&mysql)); }
Sie können jedoch denselben Effekt auch mit den Standardfehlerfunktionen von MySQL erzielen:
mysql_query(&mysql,"SELECT * FROM some_table"); result = mysql_use_result(&mysql); while((row = mysql_fetch_row(result))) { // Tu etwas mit den Daten } if(mysql_errno(&mysql)) // mysql_fetch_row() scheiterte wegen eines Fehlers { fprintf(stderr, "Error: %s\n", mysql_error(&mysql)); }
unsigned int mysql_errno(MYSQL *mysql)
Beschreibung
Für die von mysql
angegebene Verbindung
liefert mysql_errno()
den Fehlercode zu der
zuletzt aufgerufenen API-Funktion, die mit Erfolg gelaufen
oder gescheitert sein kann. Der Rückgabewert null bedeutet,
dass kein Fehler auftrat. Die Nummern der
Clientfehlermeldungen sind in der MySQL-Header-Datei
errmsg.h
aufgelistet. Die Nummern der
Serverfehlermeldungen stehen in der Datei
mysqld_error.h
. Außerdem werden die
Fehler in Anhang B, Fehlercodes und -meldungen, aufgeführt.
Beachten Sie, dass manche Funktionen, wie etwa
mysql_fetch_row()
, keine
mysql_errno()
setzen, wenn sie Erfolg
haben.
Als Faustregel gilt: Alle Funktionen, die vom Server
Informationen abfragen müssen, setzen
mysql_errno()
zurück, wenn sie Erfolg
hatten.
Rückgabewerte
Ein Fehlercodewert für den letzten
mysql_
-Aufruf,
wenn dieser gescheitert ist. Null bedeutet, dass kein Fehler
auftrat.
xxx
()
Fehler
Keine.
const char *mysql_error(MYSQL *mysql)
Beschreibung
Für die durch mysql
angegebene Verbindung
liefert mysql_error()
einen auf null
endenden String mit der Fehlermeldung für die zuletzt
aufgerufene API-Funktion, die gescheitert ist. Wenn keine
Funktion gescheitert ist, kann der Rückgabewert von
mysql_error()
auch der vorherige Fehler
oder ein leerer String sein, der anzeigt, dass kein Fehler
auftrat.
Als Faustregel gilt: Alle Funktionen, die vom Server
Informationen abfragen müssen, setzen
mysql_errno()
zurück, wenn sie Erfolg
hatten.
Für Funktionen, die mysql_errno()
zurücksetzen, sind die beiden folgenden Tests äquivalent:
if(mysql_errno(&mysql)) { // Ein Fehler ist aufgetreten } if(mysql_error(&mysql)[0] != '\0') { // Ein Fehler ist aufgetreten }
Sie können die Sprache für die Fehlermeldungen des Clients ändern, indem Sie die MySQL-Clientbibliothek neu kompilieren. Zurzeit haben Sie die Auswahl zwischen Fehlermeldungen in mehreren verschiedenen Sprachen. Siehe Abschnitt 5.11.2, „Nicht englische Fehlermeldungen“.
Rückgabewerte
Ein auf null endender Zeichen-String, der den Fehler beschreibt. Ein leerer String, wenn kein Fehler auftrat.
Fehler
Keine.
Bitte verwenden Sie stattdessen
mysql_real_escape_string()
!
Diese Funktion gleicht
mysql_real_escape_string()
, mit dem
Unterschied, dass
mysql_real_escape_string()
einen
Verbindungs-Handler als erstes Argument entgegennimmt und den
String entsprechend dem aktuellen Zeichensatz mit
Escape-Zeichen versieht.
mysql_escape_string()
nimmt kein
Verbindungsargument an und berücksichtigt auch nicht den
aktuellen Zeichensatz.
MYSQL_FIELD *mysql_fetch_field(MYSQL_RES
*result)
Beschreibung
Liefert die Definition einer Spalte einer Ergebnismenge in
Form einer MYSQL_FIELD
-Struktur. Um
Informationen über alle Spalten der Ergebnismenge zu
erhalten, rufen Sie diese Funktion wiederholt auf.
mysql_fetch_field()
liefert
NULL
, wenn keine weiteren Felder mehr
übrig sind.
Mit jeder neuen SELECT
-Anfrage wird
mysql_fetch_field()
so zurückgesetzt, dass
sie wieder Informationen über das erste Feld liefert. Auch
mysql_field_seek()
nimmt Einfluss darauf,
welches Feld mysql_fetch_field()
zurückgibt.
Wenn Sie mit mysql_query()
ein
SELECT
auf einer Tabelle ausgeführt haben,
ohne jedoch mysql_store_result()
zu
benutzen, dann liefert MySQL, wenn Sie mit
mysql_fetch_field()
die Länge eines
BLOB
-Felds erfragen, die Standardlänge
eines Blob-Werts (8 Kbyte). (Die Größe von 8 Kbyte wird
gewählt, weil MySQL die maximale Länge für den
BLOB
nicht kennt. Irgendwann soll dies
einmal konfigurierbar gemacht werden.) Wenn Sie die
Ergebnismenge abgeholt haben, enthält
field->max_length
die Länge des
längsten Werts dieser Spalte für diese konkrete Anfrage.
Rückgabewerte
Die MYSQL_FIELD
-Struktur der aktuellen
Spalte. NULL
, wenn keine Spalten mehr
übrig sind.
Fehler
Keine.
Beispiel
MYSQL_FIELD *field; while((field = mysql_fetch_field(result))) { printf("field name %s\n", field->name); }
MYSQL_FIELD *mysql_fetch_field_direct(MYSQL_RES
*result, unsigned int fieldnr)
Beschreibung
Wenn man ihr die Feldnummer fieldnr
einer
Spalte aus einer Ergebnismenge übergibt, liefert die Funktion
die Felddefinition dieser Spalte als
MYSQL_FIELD
-Struktur. Mit dieser Funktion
können Sie die Definition einer beliebigen Spalte abfragen.
Der Wert von fieldnr
sollte zwischen 0 und
mysql_num_fields(result)-1
liegen.
Rückgabewerte
Die MYSQL_FIELD
-Struktur für die
angegebene Spalte.
Fehler
Keine.
Beispiel
unsigned int num_fields; unsigned int i; MYSQL_FIELD *field; num_fields = mysql_num_fields(result); for(i = 0; i < num_fields; i++) { field = mysql_fetch_field_direct(result, i); printf("Field %u is %s\n", i, field->name); }
MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES
*result)
Beschreibung
Gibt ein Array mit allen
MYSQL_FIELD
-Strukturen für eine
Ergebnismenge zurück. Jede Struktur liefert die
Felddefinition für eine Spalte der Ergebnismenge.
Rückgabewerte
Ein Array von MYSQL_FIELD
-Strukturen für
alle Spalten einer Ergebnismenge.
Fehler
Keine.
Beispiel
unsigned int num_fields; unsigned int i; MYSQL_FIELD *fields; num_fields = mysql_num_fields(result); fields = mysql_fetch_fields(result); for(i = 0; i < num_fields; i++) { printf("Field %u is %s\n", i, fields[i].name); }
unsigned long *mysql_fetch_lengths(MYSQL_RES
*result)
Beschreibung
Gibt die Länge der Spalten der aktuellen Zeile einer
Ergebnismenge zurück. Wenn Sie planen, Feldwerte zu kopieren,
sind diese Längenangaben auch für die Optimierung hilfreich,
da Sie sich dadurch den Aufruf von strlen()
ersparen können. Wenn die Ergebnismenge Binärdaten enthält,
müssen Sie sogar diese
Funktion zur Ermittlung der Datenlänge einsetzen, da
strlen()
für Felder mit Nullwerten
verkehrte Ergebnisse liefert.
Die Länge von leeren Spalten und Spalten mit
NULL
-Werten ist null. Unter der
Beschreibung von mysql_fetch_row()
erfahren
Sie, wie Sie diese beiden Fälle unterscheiden können.
Rückgabewerte
Ein Array von vorzeichenlosen Long-Integers, das die Größen
der Spalten angibt (ausschließlich eventueller Nullzeichen am
Ende). Ist NULL
, wenn ein Fehler auftrat.
Fehler
mysql_fetch_lengths()
ist nur für die
aktuelle Zeile der Ergebnismenge gültig. Diese Funktion
liefert NULL
, wenn Sie sie vor
mysql_fetch_row()
oder nach dem Abruf aller
Ergebniszeilen aufrufen.
Beispiel
MYSQL_ROW row; unsigned long *lengths; unsigned int num_fields; unsigned int i; row = mysql_fetch_row(result); if (row) { num_fields = mysql_num_fields(result); lengths = mysql_fetch_lengths(result); for(i = 0; i < num_fields; i++) { printf("Column %u is %lu bytes in length.\n", i, lengths[i]); } }
MYSQL_ROW mysql_fetch_row(MYSQL_RES
*result)
Beschreibung
Ruft die nächste Zeile einer Ergebnismenge ab. Nach
mysql_store_result()
aufgerufen, liefert
mysql_fetch_row()
den Wert
NULL
, wenn keine weiteren Zeilen mehr
abzuholen sind. Nach mysql_use_result()
aufgerufen, liefert mysql_fetch_row()
den
Wert NULL
, wenn keine Zeilen mehr vorliegen
oder wenn ein Fehler auftrat.
mysql_num_fields(result)
gibt die Anzahl
der Werte in einer Zeile an. Wenn row
den
Rückgabewert eines
mysql_fetch_row()
-Aufrufs speichert,
können Sie mit row[0]
bis
row[mysql_num_fields(result)-1]
die Zeiger
auf die Werte dieser Zeile ansprechen.
NULL
-Werte in der Zeile werden durch
NULL
-Zeiger angezeigt.
Die Längen der Feldwerte der Zeile können Sie sich mit
mysql_fetch_lengths()
beschaffen. Leere
Felder und Felder mit NULL
haben beide die
Länge null. Sie können sie unterscheiden, indem Sie sich den
Zeiger auf den Feldwert anschauen: Ist er
NULL
, speichert das Feld den Wert
NULL
; andernfalls ist es leer.
Rückgabewerte
Eine MYSQL_ROW
-Struktur für die nächste
Zeile oder NULL
, wenn keine weiteren Zeilen
mehr vorliegen oder ein Fehler aufgetreten ist.
Fehler
Beachten Sie, dass der Fehler zwischen zwei Aufrufen von
mysql_fetch_row()
nicht zurückgesetzt
wird.
CR_SERVER_LOST
Die Serververbindung brach während der Anfrage ab.
CR_UNKNOWN_ERROR
Ein unbekannter Fehler ist aufgetreten.
Beispiel
MYSQL_ROW row; unsigned int num_fields; unsigned int i; num_fields = mysql_num_fields(result); while ((row = mysql_fetch_row(result))) { unsigned long *lengths; lengths = mysql_fetch_lengths(result); for(i = 0; i < num_fields; i++) { printf("[%.*s] ", (int) lengths[i], row[i] ? row[i] : "NULL"); } printf("\n"); }
unsigned int mysql_field_count(MYSQL
*mysql)
Beschreibung
Liefert die Anzahl der Spalten für die jüngste Anfrage auf dieser Verbindung.
Normalerweise benutzen Sie diese Funktion, wenn
mysql_store_result()
den Wert
NULL
zurückgegeben hat (und Sie deshalb
keinen Zeiger auf die Ergebnismenge haben). In diesem Fall
können Sie mit mysql_field_count()
feststellen, ob mysql_store_result()
ein
nichtleeres Ergebnis hätte produzieren müssen. So kann das
Clientprogramm die richtigen Maßnahmen ergreifen, ohne zu
wissen, ob die Anfrage eine SELECT
- (oder
SELECT
-ähnliche) Anweisung war. Wie dies
funktioniert, zeigt das folgende Beispiel.
Rückgabewerte
Ein vorzeichenloser Integer, der die Anzahl der Spalten einer Ergebnismenge angibt.
Fehler
Keine.
Beispiel
MYSQL_RES *result; unsigned int num_fields; unsigned int num_rows; if (mysql_query(&mysql,query_string)) { // Fehler } else // Anfrage erfolgreich, Rückgabedaten können verarbeitet werden { result = mysql_store_result(&mysql); if (result) // Es sind Zeilen vorhanden { num_fields = mysql_num_fields(result); // Hole Zeilen ab und rufe dann mysql_free_result(result) auf } else // mysql_store_result() gab nichts zurück. Hätte es sollen? { if(mysql_field_count(&mysql) == 0) { // Anfrage liefert keine Daten // (Es war kein SELECT) num_rows = mysql_affected_rows(&mysql); } else // mysql_store_result() hätte Daten zurückgeben müssen { fprintf(stderr, "Error: %s\n", mysql_error(&mysql)); } } }
Eine Alternative wäre es, den Aufruf von
mysql_field_count(&mysql)
durch
mysql_errno(&mysql)
zu ersetzen. In
diesem Fall schauen Sie direkt in
mysql_store_result()
nach einem Fehler,
anstatt aus dem Wert von
mysql_field_count()
zu erschließen, ob die
Anweisung ein SELECT
war.
MYSQL_FIELD_OFFSET mysql_field_seek(MYSQL_RES
*result, MYSQL_FIELD_OFFSET offset)
Beschreibung
Setzt den Feld-Cursor auf den gegebenen Offset. Der nächste
mysql_fetch_field()
-Aufruf fragt die
Felddefinition der mit diesem Offset verbundenen Spalte ab.
Um den Zeilenanfang zu suchen, übergeben Sie den
offset
-Wert null.
Rückgabewerte
Der vorherige Wert des Feld-Cursors.
Fehler
Keine.
MYSQL_FIELD_OFFSET mysql_field_tell(MYSQL_RES
*result)
Beschreibung
Liefert die Position des Feld-Cursors, der für den letzten
mysql_fetch_field()
-Aufruf verwendet wurde.
Dieser Wert kann als Argument für
mysql_field_seek()
dienen.
Rückgabewerte
Der aktuelle Offset des Feld-Cursors.
Fehler
Keine.
void mysql_free_result(MYSQL_RES *result)
Beschreibung
Gibt den Speicher frei, der einer Ergebnismenge durch
mysql_store_result()
,
mysql_use_result()
,
mysql_list_dbs()
und so weiter zugewiesen
wurde. Wenn Sie mit einer Ergebnismenge fertig sind, müssen
Sie ihren Speicher mit mysql_free_result()
wieder freigeben.
Versuchen Sie nicht mehr, auf eine Ergebnismenge zuzugreifen, nachdem Sie sie freigegeben haben.
Rückgabewerte
Keine.
Fehler
Keine.
void mysql_get_character_set_info(MYSQL *mysql,
MY_CHARSET_INFO *cs)
Beschreibung
Diese Funktion liefert Informationen über den
Standardzeichensatz des Clients. Dieser kann mit der Funktion
mysql_set_character_set()
geändert werden.
Diese Funktion kam in MySQL 5.0.10 hinzu.
Beispiel
if (!mysql_set_character_set(&mysql, "utf8")) { MY_CHARSET_INFO cs; mysql_get_character_set_info(&mysql, &cs); printf("character set information:\n"); printf("character set name: %s\n", cs.name); printf("collation name: %s\n", cs.csname); printf("comment: %s\n", cs.comment); printf("directory: %s\n", cs.dir); printf("multi byte character min. length: %d\n", cs.mbminlen); printf("multi byte character max. length: %d\n", cs.mbmaxlen); }
char *mysql_get_client_info(void)
Beschreibung
Liefert einen String, der die Version der Clientbibliothek darstellt.
Rückgabewerte
Ein Zeichen-String, der die Version der MySQL-Clientbibliothek darstellt.
Fehler
Keine.
unsigned long
mysql_get_client_version(void)
Beschreibung
Liefert einen Integer, der die Version der Clientbibliothek
darstellt. Der Wert hat das Format XYYZZ
,
wobei X
die Hauptversion,
YY
der Release-Level und
ZZ
die Versionsnummer innerhalb des
Releases ist. So bedeutet beispielsweise der Wert
40102
die Clientbibliotheksversion
4.1.2
.
Rückgabewerte
Ein Integer, der die Version der MySQL-Clientbibliothek angibt.
Fehler
Keine.
char *mysql_get_host_info(MYSQL *mysql)
Beschreibung
Liefert einen String, der den benutzten Verbindungstyp einschließlich des Hostnamens des Servers beschreibt.
Rückgabewerte
Ein Zeichen-String, der den Hostnamen des Servers und den Verbindungstyp darstellt.
Fehler
Keine.
unsigned int mysql_get_proto_info(MYSQL
*mysql)
Beschreibung
Liefert die Protokollversion der aktuellen Verbindung.
Rückgabewerte
Ein vorzeichenloser Integer, der die Protokollversion der aktuellen Verbindung darstellt.
Fehler
Keine.
char *mysql_get_server_info(MYSQL *mysql)
Beschreibung
Liefert einen String, der die Versionsnummer des Servers darstellt.
Rückgabewerte
Ein Zeichen-String, der die Versionsnummer des Servers darstellt.
Fehler
Keine.
unsigned long mysql_get_server_version(MYSQL
*mysql)
Beschreibung
Liefert die Versionsnummer des Servers als Integer.
Rückgabewerte
Eine Zahl, welche die MySQL Server-Version in folgendem Format darstellt:
major_version*10000 + minor_version *100 + sub_version
So wird beispielsweise 5.1.5 als 50105 zurückgegeben.
Diese Funktion ist nützlich, um in Clientprogrammen schnell herauszufinden, ob eine versionsspezifische Serverfähigkeit geboten wird.
Fehler
Keine.
unsigned long mysql_hex_string(char *to, const char
*from, unsigned long length)
Beschreibung
Diese Funktion dient der Erstellung eines gültigen SQL-Strings, den Sie in einer SQL-Anweisung benutzen können. Siehe Abschnitt 9.1.1, „Strings“.
Der String in from
ist im Hexadezimalformat
verschlüsselt, wobei jedes Zeichen als zwei
Hexadezimalziffern kodiert ist. Das Ergebnis wird in
to
eingesetzt und ein Nullbyte als
Abschlusszeichen angehängt.
Der String, auf den from
verweist, muss
length
Bytes lang sein. Den
to
-Puffer müssen Sie mindestens mit einer
Länge von length*2+1
Bytes zuweisen. Wenn
mysql_hex_string()
zurückkehrt, ist der
Inhalt von to
ein auf null endender String.
Der Rückgabewert ist die Länge des kodierten Strings ohne
das abschließende Nullzeichen.
Der Rückgabewert kann in eine SQL-Anweisung in einem der
Formate 0x
oder value
X'
eingesetzt werden. Allerdings enthält der Rückgabewert nicht
das value
'0x
oder X'...'
. Der
Aufrufer muss dieses Element selbst beisteuern, je nachdem,
für welches er sich entscheidet.
Beispiel
char query[1000],*end; end = strmov(query,"INSERT INTO test_table values("); end = strmov(end,"0x"); end += mysql_hex_string(end,"What's this",11); end = strmov(end,",0x"); end += mysql_hex_string(end,"binary data: \0\r\n",16); *end++ = ')'; if (mysql_real_query(&mysql,query,(unsigned int) (end - query))) { fprintf(stderr, "Failed to insert row, Error: %s\n", mysql_error(&mysql)); }
Die im Beispiel verwendete Funktion
strmov()
stammt aus der
mysqlclient
-Bibliothek und funktioniert wie
strcpy()
, liefert jedoch einen Zeiger auf
die abschließende Null des ersten Parameters.
Rückgabewerte
Die Länge des in to
eingesetzten Werts
ohne die abschließende Null.
Fehler
Keine.
char *mysql_info(MYSQL *mysql)
Beschreibung
Holt einen String mit Informationen über die zuletzt
ausgeführte Anfrage ab, aber nur für die hier aufgeführten
Anweisungen. Für andere Anweisungen liefert
mysql_info()
die Funktion
NULL
. Das Format des Strings hängt von der
Art der Anfrage ab, wie hier beschrieben. Die Zahlen dienen
nur der Veranschaulichung; der String enthält Werte, die für
die Anfrage passend sind.
INSERT INTO ... SELECT ...
String-Format: Records: 100 Duplicates: 0
Warnings: 0
INSERT INTO ... VALUES
(...),(...),(...)...
String-Format: Records: 3 Duplicates: 0 Warnings:
0
LOAD DATA INFILE ...
String-Format: Records: 1 Deleted: 0 Skipped: 0
Warnings: 0
ALTER TABLE
String-Format: Records: 3 Duplicates: 0 Warnings:
0
UPDATE
String-Format: Rows matched: 40 Changed: 40
Warnings: 0
Beachten Sie, dass mysql_info()
bei
INSERT ... VALUES
lediglich für die
mehrzeilige Form der Anweisung (also dann, wenn mehrere
Wertelisten angegeben werden) einen von
NULL
verschiedenen Wert liefert.
Rückgabewerte
Ein Zeichen-String mit Zusatzinformationen über die zuletzt
ausgeführte Anfrage. NULL
, wenn keine
Informationen über die Anfrage zur Verfügung stehen.
Fehler
Keine.
MYSQL *mysql_init(MYSQL *mysql)
Beschreibung
Reserviert oder initialisiert ein geeignetes
MYSQL
-Objekt für
mysql_real_connect()
. Wenn
mysql
ein NULL
-Zeiger
ist, reserviert, initialisiert und liefert die Funktion ein
neues Objekt. Andernfalls wird das Objekt initialisiert und
seine Adresse zurückgegeben. Wenn
mysql_init()
ein neues Objekt zuweist, wird
dieses wieder freigegeben, wenn
mysql_close()
zum Schließen der Verbindung
aufgerufen wird.
Rückgabewerte
Ein initialisierter MYSQL*
-Handle.
NULL
, wenn nicht genügend Speicher zur
Zuweisung eines neuen Objekts verfügbar war.
Fehler
Wenn der Speicher nicht ausreichte, wird
NULL
zurückgegeben.
my_ulonglong mysql_insert_id(MYSQL *mysql)
Beschreibung
Liefert den von der vorherigen INSERT
- oder
UPDATE
-Anweisung für eine
AUTO_INCREMENT
-Spalte generierten Wert.
Verwenden Sie diese Funktion, wenn Sie eine
INSERT
-Anweisung auf einer Tabelle mit
einem AUTO_INCREMENT
-Feld ausgeführt
haben.
Genauer gesagt: mysql_insert_id()
wird
unter folgenden Bedingungen aktualisiert:
INSERT
-Anweisungen, die einen Wert in
einer AUTO_INCREMENT
-Spalte speichern,
und zwar unabhängig davon, ob der Wert automatisch durch
Speichern der Spezialwerte NULL
oder
0
in der Spalte generiert oder ob ein
expliziter, nichtspezieller Wert gespeichert wurde.
Bei einer mehrzeiligen INSERT
-Anweisung
liefert mysql_insert_id()
den
ersten automatisch
generierten AUTO_INCREMENT
-Wert. Wurde
kein solcher Wert generiert, liefert die Funktion den
letzten explizit in die
AUTO_INCREMENT
-Spalte eingefügten
Wert.
INSERT
-Anweisungen, die einen
AUTO_INCREMENT
-Wert generieren, indem
sie
LAST_INSERT_ID(
in eine Spalte einfügen.
expr
)
INSERT
-Anweisungen, die einen
AUTO_INCREMENT
-Wert generieren, indem
sie eine Spalte auf
LAST_INSERT_ID(
setzen.
expr
)
Der Wert von mysql_insert_id()
wird
nicht von Anweisungen wie SELECT
beeinflusst, die eine Ergebnismenge zurückgeben.
Wenn die obige Anweisung einen Fehler zurückgab, ist der
Wert von mysql_insert_id()
undefiniert.
Beachten Sie, dass mysql_insert_id()
den
Wert 0
liefert, wenn die Anweisung keinen
AUTO_INCREMENT
-Wert verwendet. Wenn Sie den
Wert zur späteren Benutzung speichern möchten, müssen Sie
unmittelbar nach der Anweisung, die den Wert generiert,
mysql_insert_id()
aufrufen.
Der Wert von mysql_insert_id()
wird nur von
Anweisungen beeinflusst, die innerhalb der aktuellen
Clientverbindung gegeben werden, aber nicht durch Anweisungen
von anderen Clients.
Siehe Abschnitt 12.10.3, „Informationsfunktionen“.
Bitte beachten Sie auch, dass der Wert der SQL-Funktion
LAST_INSERT_ID()
immer den zuletzt
generierten AUTO_INCREMENT
-Wert enthält.
Dieser wird zwischen zwei Anweisungen nicht zurückgesetzt, da
der Wert dieser Funktion im Server gespeichert ist. Ein
weiterer Unterschied ist der, dass
LAST_INSERT_ID()
nicht aktualisiert wird,
wenn Sie eine AUTO_INCREMENT
-Spalte auf
einen bestimmten Wert setzen, der kein Spezialwert ist.
Der Grund für den Unterschied zwischen
LAST_INSERT_ID()
und
mysql_insert_id()
besteht darin, dass
LAST_INSERT_ID()
in Skripten einfach zu
benutzen sein soll, während
mysql_insert_id()
versucht, etwas genauere
Informationen über die Vorgänge in der
AUTO_INCREMENT
-Spalte zu liefern.
Rückgabewerte
Siehe oben.
Fehler
Keine.
int mysql_kill(MYSQL *mysql, unsigned long
pid)
Beschreibung
Lässt den Server den Thread pid
anhalten.
Rückgabewerte
Null bei Erfolg und ein von null verschiedener Wert bei einem Fehler.
Fehler
CR_COMMANDS_OUT_OF_SYNC
Befehle wurden in der falschen Reihenfolge ausgeführt.
CR_SERVER_GONE_ERROR
Der MySQL Server ist nicht mehr verfügbar.
CR_SERVER_LOST
Die Serververbindung brach während der Anfrage ab.
CR_UNKNOWN_ERROR
Ein unbekannter Fehler ist aufgetreten.
void mysql_library_end(void)
Beschreibung
Dies ist ein Synonym für die
mysql_server_end()
-Funktion.
Informationen zur Verwendung finden Sie unter Abschnitt 24.2.2, „C-API: Funktionsüberblick“.
int mysql_library_init(int argc, char **argv, char
**groups)
Beschreibung
Dies ist ein Synonym für die
mysql_server_init()
-Funktion. Siehe
Abschnitt 24.2.12.1, „mysql_server_init()
“.
Informationen zur Verwendung finden Sie unter Abschnitt 24.2.2, „C-API: Funktionsüberblick“.
MYSQL_RES *mysql_list_dbs(MYSQL *mysql, const char
*wild)
Beschreibung
Liefert eine Ergebnismenge mit Namen von Datenbanken auf dem
Server, die mit dem einfachen regulären Ausdruck im Parameter
wild
übereinstimmen.
wild
kann die Wildcard-Zeichen
‘%
’ oder
‘_
’ enthalten oder aber ein
NULL
-Zeiger sein, der auf alle Datenbanken
passt. Ein Aufruf von mysql_list_dbs()
ist
dasselbe wie die Anfrage SHOW databases [LIKE
wild]
.
Sie müssen die Ergebnismenge mit
mysql_free_result()
wieder freigeben.
Rückgabewerte
Bei einem Erfolg eine
MYSQL_RES
-Ergebnismenge und bei einem
Fehler der Wert NULL
.
Fehler
CR_COMMANDS_OUT_OF_SYNC
Befehle wurden in der falschen Reihenfolge ausgeführt.
CR_OUT_OF_MEMORY
Speicherüberlauf.
CR_SERVER_GONE_ERROR
Der MySQL Server ist nicht mehr verfügbar.
CR_SERVER_LOST
Die Serververbindung brach während der Anfrage ab.
CR_UNKNOWN_ERROR
Ein unbekannter Fehler ist aufgetreten.
MYSQL_RES *mysql_list_fields(MYSQL *mysql, const char
*table, const char *wild)
Beschreibung
Liefert eine Ergebnismenge mit Namen von Feldern aus der
gegebenen Tabelle, die mit dem einfachen regulären Ausdruck
im Parameter wild
übereinstimmen.
wild
kann die Wildcard-Zeichen
‘%
’ oder
‘_
’ enthalten oder aber ein
NULL
-Zeiger sein, der auf alle Felder
passt. Ein Aufruf von mysql_list_fields()
ist dasselbe wie die Anfrage SHOW COLUMNS FROM
.
tbl_name
[LIKE
wild
]
Wir empfehlen, SHOW COLUMNS FROM
anstelle von
tbl_name
mysql_list_fields()
zu benutzen.
Sie müssen die Ergebnismenge mit
mysql_free_result()
freigeben.
Rückgabewerte
Bei Erfolg eine MYSQL_RES
-Ergebnismenge und
bei einem Fehler der Wert NULL
.
Fehler
CR_COMMANDS_OUT_OF_SYNC
Befehle wurden in der falschen Reihenfolge ausgeführt.
CR_SERVER_GONE_ERROR
Der MySQL Server ist nicht mehr verfügbar.
CR_SERVER_LOST
Die Serververbindung brach während der Anfrage ab.
CR_UNKNOWN_ERROR
Ein unbekannter Fehler ist aufgetreten.
MYSQL_RES *mysql_list_processes(MYSQL
*mysql)
Beschreibung
Gibt eine Ergebnismenge mit einer Beschreibung der laufenden
Server-Threads zurück. Dieselben Informationen erhalten Sie
auch mit mysqladmin processlist oder der
Anfrage SHOW PROCESSLIST
.
Sie müssen die Ergebnismenge mit
mysql_free_result()
freigeben.
Rückgabewerte
Bei Erfolg eine MYSQL_RES
-Ergebnismenge und
bei einem Fehler der Wert NULL
.
Fehler
CR_COMMANDS_OUT_OF_SYNC
Befehle wurden in der falschen Reihenfolge ausgeführt.
CR_SERVER_GONE_ERROR
Der MySQL Server ist nicht mehr verfügbar.
CR_SERVER_LOST
Die Serververbindung brach während der Anfrage ab.
CR_UNKNOWN_ERROR
Ein unbekannter Fehler ist aufgetreten.
MYSQL_RES *mysql_list_tables(MYSQL *mysql, const char
*wild)
Beschreibung
Liefert eine Ergebnismenge mit Namen von Tabellen aus der
aktuellen Datenbank, die mit dem einfachen regulären Ausdruck
im Parameter wild
übereinstimmen.
wild
kann die Wildcard-Zeichen
‘%
’ oder
‘_
’ enthalten oder aber ein
NULL
-Zeiger sein, der auf alle Tabellen
passt. Ein Aufruf von mysql_list_tables()
ist dasselbe wie die Anfrage SHOW tables [LIKE
.
wild
]
Sie müssen die Ergebnismenge mit
mysql_free_result()
freigeben.
Rückgabewerte
Bei Erfolg eine MYSQL_RES
-Ergebnismenge und
bei einem Fehler der Wert NULL
.
Fehler
CR_COMMANDS_OUT_OF_SYNC
Befehle wurden in der falschen Reihenfolge ausgeführt.
CR_SERVER_GONE_ERROR
Der MySQL Server ist nicht mehr verfügbar.
CR_SERVER_LOST
Die Serververbindung brach während der Anfrage ab.
CR_UNKNOWN_ERROR
Ein unbekannter Fehler ist aufgetreten.
my_bool mysql_more_results(MYSQL *mysql)
Beschreibung
Gibt TRUE zurück, wenn noch weitere Ergebnisse der aktuellen
Anfrage vorliegen und die Anwendung
mysql_next_result()
aufrufen muss, um diese
Ergebnisse abzuholen.
Rückgabewerte
TRUE
(1), wenn noch weitere Ergebnisse
existieren. FALSE
(0), wenn keine
Ergebnisse mehr vorhanden sind.
In den meisten Fällen können Sie stattdessen mit
mysql_next_result()
testen, ob noch
Ergebnisse übrig sind, und den Abruf der Daten initiieren,
wenn dies der Fall ist.
Siehe Abschnitt 24.2.9, „C-API: Behandlung der Ausführung mehrerer Anweisungen“, und
Abschnitt 24.2.3.45, „mysql_next_result()
“.
Fehler
Keine.
int mysql_next_result(MYSQL *mysql)
Beschreibung
Wenn noch Anfrageergebnisse vorliegen, liest
mysql_next_result()
die nächsten
Ergebnisse und gibt den Status an die Anwendung zurück.
Sie müssen für die vorherige Anfrage
mysql_free_result()
aufrufen, falls diese
eine Ergebnismenge zurückgegeben hat.
Nach einem Aufruf von mysql_next_result()
hat die Verbindung denselben Status, als hätten Sie
mysql_real_query()
oder
mysql_query()
für die nächste Anfrage
aufgerufen. Das bedeutet, dass Sie
mysql_store_result()
,
mysql_warning_count()
,
mysql_affected_rows()
und so weiter
aufrufen können.
Wenn mysql_next_result()
einen Fehler
zurückgibt, werden andere Anweisungen ausgeführt und es
liegen keine Ergebnisse mehr zum Abruf bereit.
Siehe Abschnitt 24.2.9, „C-API: Behandlung der Ausführung mehrerer Anweisungen“.
Rückgabewerte
Rückgabewert | Beschreibung |
0 | Erfolg, und es gibt noch mehr Ergebnisse. |
-1 | Erfolg, und es gibt keine Ergebnisse mehr. |
>0 | Ein Fehler ist aufgetreten |
Fehler
CR_COMMANDS_OUT_OF_SYNC
Befehle wurden in der falschen Reihenfolge ausgeführt,
beispielsweise wenn Sie es versäumt haben,
mysql_use_result()
für die vorherige
Ergebnismenge aufzurufen.
CR_SERVER_GONE_ERROR
Der MySQL Server ist nicht mehr verfügbar.
CR_SERVER_LOST
Die Serververbindung brach während der Anfrage ab.
CR_UNKNOWN_ERROR
Ein unbekannter Fehler ist aufgetreten.
unsigned int mysql_num_fields(MYSQL_RES
*result)
Um stattdessen ein MYSQL*
-Argument zu
übergeben, sagen Sie unsigned int
mysql_field_count(MYSQL *mysql)
.
Beschreibung
Liefert die Anzahl der Spalten einer Ergebnismenge.
Beachten Sie, dass Sie die Anzahl der Spalten entweder aus
einem Zeiger auf eine Ergebnismenge oder aus einem
Verbindungs-Handle erfahren können. Den Verbindungs-Handle
verwenden Sie, wenn mysql_store_result()
oder mysql_use_result()
den Wert
NULL
zurückgegeben hat (sodass kein Zeiger
auf die Ergebnismenge zur Verfügung steht). In diesem Fall
können Sie mit mysql_field_count()
ermitteln, ob mysql_store_result()
eigentlich ein nichtleeres Ergebnis hätte liefern sollen. So
kann das Clientprogramm geeignete Maßnahmen ergreifen, ohne
zu wissen, ob die Anfrage eine SELECT
-
(oder SELECT
-ähnliche) Anweisung war. Das
Beispiel zeigt, wie man dies macht.
Rückgabewerte
Ein vorzeichenloser Integer, der die Anzahl der Spalten einer Ergebnismenge angibt.
Fehler
Keine.
Beispiel
MYSQL_RES *result; unsigned int num_fields; unsigned int num_rows; if (mysql_query(&mysql,query_string)) { // Fehler } else // Anfrage erfolgreich, Rückgabedaten werden verarbeitet { result = mysql_store_result(&mysql); if (result) // Es liegen Zeilen vor { num_fields = mysql_num_fields(result); // Zeilen abrufen und dann mysql_free_result(result) aufrufen } else // mysql_store_result() gab nichts zurück, hätte es sollen? { if (mysql_errno(&mysql)) { fprintf(stderr, "Error: %s\n", mysql_error(&mysql)); } else if (mysql_field_count(&mysql) == 0) { // Anfrage liefert keine Daten // (war kein SELECT) num_rows = mysql_affected_rows(&mysql); } } }
Wenn Sie wissen, dass Ihre Anfrage eine Ergebnismenge hätte
zurückgeben müssen, können Sie alternativ den Aufruf von
mysql_errno(&mysql)
durch eine Prüfung
ersetzen, die feststellt, ob
mysql_field_count(&mysql)
gleich 0 ist.
Das geschieht nur, wenn etwas schief gegangen ist.
my_ulonglong mysql_num_rows(MYSQL_RES
*result)
Beschreibung
Liefert die Anzahl der Zeilen in der Ergebnismenge.
Die Verwendung von mysql_num_rows()
hängt
davon ab, ob Sie die Ergebnismenge mit
mysql_store_result()
oder
mysql_use_result()
zurückgeben. Wenn Sie
mysql_store_result()
benutzen, kann
mysql_num_rows()
direkt aufgerufen werden,
aber wenn Sie mysql_use_result()
benutzen,
gibt mysql_num_rows()
erst dann den
richtigen Wert zurück, wenn alle Zeilen der Ergebnismenge
abgeholt worden sind.
Rückgabewerte
Die Anzahl der Zeilen in der Ergebnismenge.
Fehler
Keine.
int mysql_options(MYSQL *mysql, enum mysql_option
option, const char *arg)
Beschreibung
Kann verwendet werden, um zusätzliche Verbindungsoptionen einzustellen und das Verhalten einer Verbindung zu beeinflussen. Diese Funktion kann auch mehrmals aufgerufen werden, um mehrere Optionen zu setzen.
mysql_options()
sollte nach
mysql_init()
und vor
mysql_connect()
oder
mysql_real_connect()
aufgerufen werden.
Das option
-Argument ist die einzustellende
Option und das arg
-Argument ist ihr Wert.
Ist die Option ein Integer, so sollte arg
auf den Wert dieses Integers verweisen.
Mögliche Optionswerte:
Option | Argumenttyp | Funktion |
MYSQL_INIT_COMMAND | char * | Befehl, der bei Verbindung mit dem MySQL Server auszuführen ist. Wird bei Neuverbindungen automatisch erneut ausgeführt. |
MYSQL_OPT_COMPRESS | Nicht verwendet | Komprimiertes Client/Server-Protokoll soll verwendet werden. |
MYSQL_OPT_CONNECT_TIMEOUT | unsigned int * | Verbindungs-Timeout in Sekunden. |
MYSQL_OPT_GUESS_CONNECTION | Nicht verwendet | Für eine mit libmysqld verlinkte Anwendung, kann die
Bibliothek hiermit erschließen, ob ein Embedded
Server oder ein Remote Server verwendet wird.
„Erschließen“ bedeutet: Wenn ein
Hostname angegeben ist, der nicht auf
localhost lautet, wird ein
Remote-Server benutzt. Dieses voreingestellte
Verhalten kann mit
MYSQL_OPT_USE_EMBEDDED_CONNECTION
und MYSQL_OPT_USE_REMOTE_CONNECTION
außer Kraft gesetzt werden. Die Option wird von
Anwendungen, die mit libmysqlclient
verlinkt sind, ignoriert. |
MYSQL_OPT_LOCAL_INFILE | Optionaler Zeiger auf uint | Wenn kein Zeiger angegeben ist oder wenn der Zeiger auf ein
unsigned int != 0 verweist, wird
der Befehl LOAD LOCAL INFILE
eingeschaltet. |
MYSQL_OPT_NAMED_PIPE | Nicht verwendet | Zur Verbindung mit einem MySQL Server auf NT werden Named Pipes benutzt. |
MYSQL_OPT_PROTOCOL | unsigned int * | Der zu verwendende Protokolltyp. Er sollte einer der Enumerationswerte
von mysql_protocol_type sein, die
in mysql.h definiert sind. |
MYSQL_OPT_READ_TIMEOUT | unsigned int * | Timeout-Leseoperationen auf dem Server (funktioniert zurzeit nur für Windows und mit TCP/IP-Verbindungen). |
MYSQL_OPT_RECONNECT | my_bool * | Aktiviert/deaktiviert die automatische Neuverbindung mit dem Server, wenn die Verbindung abgebrochen war. Die Neuverbindung ist seit MySQL 5.0.3 standardmäßig ausgeschaltet. Diese Option ist neu in 5.0.13 und bietet die Möglichkeit, das Verhalten in Bezug auf Neuverbindungen explizit vorzugeben. |
MYSQL_OPT_SET_CLIENT_IP | char * | Für eine Anwendung, die mit libmysqld verlinkt ist
(wobei libmysqld mit
Authentifizierungsunterstützung kompiliert wurde),
bedeutet dies, dass bei der Authentifizierung davon
ausgegangen wird, dass sich der Benutzer von der (als
String) angegebenen IP-Adresse aus verbindet. Bei
Anwendungen, die mit libmysqlclient
verlinkt sind, wird diese Option ignoriert. |
MYSQL_OPT_USE_EMBEDDED_CONNECTION | Nicht verwendet | Für eine Anwendung, die mit libmysqld verlinkt ist,
zwingt dies zur Benutzung des Embedded Servers für
die Verbindung. Bei Anwendungen, die mit
libmysqlclient verlinkt sind, wird
diese Option ignoriert. |
MYSQL_OPT_USE_REMOTE_CONNECTION | Nicht verwendet | Für eine Anwendung, die mit libmysqld verlinkt ist,
zwingt dies zur Benutzung eines Remote-Servers für
die Verbindung. Bei Anwendungen, die mit
libmysqlclient verlinkt sind, wird
diese Option ignoriert. |
MYSQL_OPT_USE_RESULT | Nicht verwendet | Diese Option wird nicht benutzt. |
MYSQL_OPT_WRITE_TIMEOUT | unsigned int * | Timeout für Schreiboperationen auf dem Server (funktioniert zurzeit nur für Windows und mit TCP/IP-Verbindungen). |
MYSQL_READ_DEFAULT_FILE | char * | Leseoptionen werden aus der angegebenen Optionsdatei statt aus
my.cnf entnommen. |
MYSQL_READ_DEFAULT_GROUP | char * | Leseoptionen werden aus der angegebenen Gruppe aus
my.cnf oder aus der Datei, die in
MYSQL_READ_DEFAULT_FILE angegeben
wurde, entnommen. |
MYSQL_REPORT_DATA_TRUNCATION | my_bool * | Aktiviert oder deaktiviert die Meldung von Fehlern wegen des
Abschneidens von Daten für vorbereitete Anweisungen
mit MYSQL_BIND.error .
(Standardeinstellung: Deaktiviert.) |
MYSQL_SECURE_AUTH | my_bool* | Gibt an, ob eine Verbindung mit einem Server aufgebaut wird, der nicht das Passwort-Hashing von MySQL 4.1.1 und höher unterstützt. |
MYSQL_SET_CHARSET_DIR | char* | Der Pfad zu dem Verzeichnis, das die Dateien mit den Zeichensatzdefinitionen enthält. |
MYSQL_SET_CHARSET_NAME | char* | Der Name des Zeichensatzes, der als Standard zu verwenden ist. |
MYSQL_SHARED_MEMORY_BASE_NAME | char* | Der Name des Shared Memory-Objekts für die Serverkommunikation. Sollte
dasselbe sein wie die Option
--shared-memory-base-name für den
mysqld-Server, mit dem Sie sich
verbinden möchten. |
Beachten Sie, dass immer die client
-Gruppe
gelesen wird, wenn Sie
MYSQL_READ_DEFAULT_FILE
oder
MYSQL_READ_DEFAULT_GROUP
benutzen.
Die angegebene Gruppe in der Optionsdatei kann folgende Optionen enthalten:
Option | Beschreibung |
connect-timeout | Verbindungs-Timeout in Sekunden. Bei Linux wird dieser Timeout auch verwendet, wenn das System auf die erste Antwort vom Server wartet. |
compress | Verwendung des komprimierten Client/Server-Protokolls. |
database | Wenn im Verbindungsbefehl keine Datenbank angegeben wurde, wird diese verwendet. |
debug | Debuggingoptionen. |
disable-local-infile | Deaktiviert LOAD DATA LOCAL . |
host | Standardhostname. |
init-command | Befehl, der bei Verbindung mit dem MySQL Server ausgeführt wird. Wird bei Neuverbindung automatisch erneut ausgeführt. |
interactive-timeout | Dasselbe wie CLIENT_INTERACTIVE mit
mysql_real_connect() . Siehe
Abschnitt 24.2.3.51, „mysql_real_connect() “. |
local-infile[=(0|1)] | Wenn kein Argument oder argument != 0 vorhanden ist, wird LOAD
DATA LOCAL aktiviert. |
max_allowed_packet | Maximalgröße der Pakete, die der Client vom Server lesen kann. |
multi-results | Mehrfachergebnismengen von Mehrfachanweisungen oder mehrfach gespeicherten Prozeduren sind zulässig. |
multi-statements | Client darf mehrere Anweisungen in einem einzigen String senden
(getrennt durch ‘; ’). |
password | Standardpasswort. |
pipe | Zur Verbindung mit einem MySQL Server auf NT werden Named Pipes benutzt. |
protocol={TCP|SOCKET|PIPE|MEMORY} | Das Protokoll für die Serververbindung. |
port | Standardportnummer. |
return-found-rows | Lässt mysql_info() bei einem
UPDATE die gefundenen anstatt der
aktualisierten Zeilen zurückgeben. |
shared-memory-base-name= | Shared Memory-Name für die Serververbindung (Standardwert ist "MYSQL"). |
socket | Standardsocketdatei. |
user | Standardbenutzer. |
Beachten Sie, dass timeout
zwar durch
connect-timeout
ersetzt, aber
timeout
in MySQL 5.1.5-alpha aus
Gründen der Abwärtskompatibilität immer noch unterstützt
wird.
Weitere Informationen über Optionsdateien finden Sie unter Abschnitt 4.3.2, „my.cnf-Optionsdateien“.
Rückgabewerte
Bei Erfolg null und bei Verwendung einer unbekannten Option ein von null verschiedener Wert.
Beispiel
MYSQL mysql; mysql_init(&mysql); mysql_options(&mysql,MYSQL_OPT_COMPRESS,0); mysql_options(&mysql,MYSQL_READ_DEFAULT_GROUP,"odbc"); if (!mysql_real_connect(&mysql,"host","user","passwd","database",0,NULL,0)) { fprintf(stderr, "Failed to connect to database: Error: %s\n", mysql_error(&mysql)); }
Dieser Code veranlasst den Client, das komprimierte
Client/Server-Protokoll zu verwenden und die zusätzlichen
Optionen aus dem Abschnitt odbc
der Datei
my.cnf
zu lesen.
int mysql_ping(MYSQL *mysql)
Beschreibung
Prüft, ob die Serververbindung funktioniert. Wenn die Verbindung abgebrochen ist, wird automatisch eine Neuverbindung versucht.
Mit dieser Funktion können Clients, die geraume Zeit untätig waren, prüfen, ob der Server die Verbindung geschlossen hat, und sich notfalls neu verbinden.
Rückgabewerte
Null, wenn die Serververbindung noch steht, und ein von null verschiedener Wert, wenn ein Fehler auftrat. Ein von null verschiedener Wert bedeutet nicht unbedingt, dass der MySQL Server selbst abgestürzt ist, sondern kann auch bedeuten, dass die Verbindung aus anderen Gründen abgebrochen ist, etwa wegen eines Netzwerkproblems.
Fehler
CR_COMMANDS_OUT_OF_SYNC
Befehle wurden in der falschen Reihenfolge ausgeführt.
CR_SERVER_GONE_ERROR
Der MySQL Server ist nicht mehr verfügbar.
CR_UNKNOWN_ERROR
Ein unbekannter Fehler ist aufgetreten.
int mysql_query(MYSQL *mysql, const char
*query)
Beschreibung
Führt die SQL-Anfrage in dem auf null endenden String
query
aus. Normalerweise muss der String
eine einzige SQL-Anweisung ohne abschließendes Semikolon
(‘;
’) oder
\g
enthalten. Wenn die Ausführung von
Mehrfachanweisungen aktiviert wurde, kann der String auch
mehrere, durch Semikola getrennte Anweisungen enthalten. Siehe
Abschnitt 24.2.9, „C-API: Behandlung der Ausführung mehrerer Anweisungen“.
mysql_query()
darf nicht für Anfragen mit
Binärdaten verwendet werden. Hierfür müssen Sie stattdessen
mysql_real_query()
aufrufen. (Binärdaten
können das Zeichen ‘\0
’
enthalten, das mysql_query()
als Ende des
Anfrage-Strings interpretiert.)
Wenn Sie wissen möchten, ob die Anfrage eine Ergebnismenge
liefern sollte, können Sie dies mit
mysql_field_count()
überprüfen. Siehe
Abschnitt 24.2.3.22, „mysql_field_count()
“.
Rückgabewerte
Null, wenn die Anfrage Erfolg hatte. Ein von null verschiedener Wert, wenn ein Fehler auftrat.
Fehler
CR_COMMANDS_OUT_OF_SYNC
Befehle wurden in der falschen Reihenfolge ausgeführt.
CR_SERVER_GONE_ERROR
Der MySQL Server ist nicht mehr verfügbar.
CR_SERVER_LOST
Die Serververbindung brach während der Anfrage ab.
CR_UNKNOWN_ERROR
Ein unbekannter Fehler ist aufgetreten.
MYSQL *mysql_real_connect(MYSQL *mysql, const char
*host, const char *user, const char *passwd, const char *db,
unsigned int port, const char *unix_socket, unsigned long
client_flag)
Beschreibung
mysql_real_connect()
versucht, eine
Verbindung zu einer MySQL-Datenbank-Engine auf
host
herzustellen.
mysql_real_connect()
muss erfolgreich zum
Abschluss kommen, ehe Sie irgendwelche anderen API-Funktionen
ausführen können, die eine gültige
MYSQL
-Verbindungs-Handle-Struktur
erfordern.
Die Parameter werden folgendermaßen angegeben:
Der erste Parameter sollte die Adresse einer bestehenden
MYSQL
-Struktur sein. Bevor Sie
mysql_real_connect()
aufrufen können,
müssen Sie die MYSQL
-Struktur mit
mysql_init()
initialisieren. Mit dem
mysql_options()
-Aufruf können Sie
viele Verbindungsoptionen ändern. Siehe
Abschnitt 24.2.3.48, „mysql_options()
“.
Der Wert von host
ist entweder ein
Hostname oder eine IP-Adresse. Wenn
host
der Wert NULL
oder der String "localhost"
ist, wird
eine Verbindung mit dem lokalen Host zugrunde gelegt. Wenn
das Betriebssystem Sockets (Unix) oder Named Pipes
(Windows) unterstützt, werden diese anstelle von TCP/IP
für die Serververbindung benutzt.
Der Parameter user
enthält die
MySQL-Kennung für die Anmeldung des Benutzers. Wenn
user
NULL
oder der
leere String ""
ist, wird der aktuelle
Benutzer vorausgesetzt. Bei Unix ist dies der aktuelle
Login-Name und bei Windows ODBC muss der aktuelle
Benutzername explizit angegeben werden. Siehe
Abschnitt 25.1.3.2, „Konfiguration einer MyODBC-DSN unter Windows“.
Der Parameter passwd
enthält das
Passwort für den user
. Wenn
passwd
NULL
ist,
werden nur diejenigen Einträge der
user
-Tabelle, die ein leeres
Passwortfeld aufweisen, auf Übereinstimmung mit dem
Benutzer überprüft. Dadurch kann der
Datenbankadministrator das Berechtigungssystem von MySQL
so einrichten, dass die Benutzer je nachdem, ob sie ein
Passwort angegeben haben oder nicht, unterschiedliche
Rechte bekommen.
Hinweis: Versuchen Sie
nicht, das Passwort zu verschlüsseln, ehe Sie
mysql_real_connect()
aufrufen. Die
Passwortverschlüsselung wird automatisch von der
Client-API vorgenommen.
db
ist der Datenbankname. Wenn
db
nicht NULL
ist,
stellt die Verbindung diesen Wert als Standarddatenbank
ein.
Wenn port
nicht 0 ist, wird dieser Wert
als Portnummer für die TCP/IP-Verbindung benutzt.
Beachten Sie, dass der Parameter host
den Verbindungstyp definiert.
Wenn unix_socket
nicht
NULL
ist, gibt der String den Socket
oder die Named Pipe für die Verbindung an. Beachten Sie,
dass der Parameter host
den
Verbindungstyp definiert.
Der Wert von client_flag
ist
normalerweise 0, kann aber auf eine Kombination der
folgenden Flags eingestellt werden, um bestimmte Features
einzuschalten:
Flag-Name | Flag-Beschreibung |
CLIENT_COMPRESS | Verwendet das komprimierte Protokoll. |
CLIENT_FOUND_ROWS | Liefert die Anzahl der gefundenen (erkannten) anstatt der Anzahl der betroffenen Zeilen. |
CLIENT_IGNORE_SPACE | Erlaubt Leerzeichen hinter Funktionsnamen. Macht alle Funktionsnamen zu reservierten Wörtern. |
CLIENT_INTERACTIVE | Erlaubt interactive_timeout Sekunden (anstatt
wait_timeout Sekunden)
Müßiggang, bevor die Verbindung geschlossen
wird. Die wait_timeout -Variable
der Client-Session wird auf den Wert der
Session-Variablen
interactive_timeout gesetzt. |
CLIENT_LOCAL_FILES | Ermöglicht LOAD DATA LOCAL . |
CLIENT_MULTI_STATEMENTS | Teilt dem Server mit, dass der Client mehrere Anweisungen (durch
‘; ’ getrennt) in
einem einzigen String senden darf. Ist dieses Flag
nicht gesetzt, ist die Ausführung von
Mehrfachanweisungen nicht möglich. |
CLIENT_MULTI_RESULTS | Teilt dem Server mit, dass der Client mehrere Ergebnismengen von
Mehrfachanweisungen oder mehrfachen gespeicherten
Prozeduren behandeln kann. Wird automatisch
gesetzt, wenn
CLIENT_MULTI_STATEMENTS
eingestellt ist. |
CLIENT_NO_SCHEMA | Verbietet die
db_name.tbl_name.col_name -Syntax.
Dies gilt für ODBC. Der Parser löst bei
Verwendung dieser Syntax einen Fehler aus, was
für die Fehlerdiagnose in manchen ODBC-Programmen
nützlich ist. |
CLIENT_ODBC | Der Client ist ein ODBC-Client. Damit wird mysqld ODBC-freundlicher. |
CLIENT_SSL | Verwendet SSL (verschlüsseltes Protokoll). Diese Option sollte nicht
von Anwendungsprogrammen gesetzt werden, sondern
intern in der Clientbibliothek. Verwenden Sie
stattdessen mysql_ssl_set() vor
dem Aufruf von
mysql_real_connect() . |
Manche Parameterwerte können einer Optionsdatei entnommen
werden, anstatt sie explizit im Aufruf von
mysql_real_connect()
zu setzen. Um dies zu
tun, rufen Sie mysql_options()
mit der
Option MYSQL_READ_DEFAULT_FILE
oder
MYSQL_READ_DEFAULT_GROUP
auf, bevor Sie
mysql_real_connect()
verwenden. Danach
geben Sie im Aufruf von
mysql_real_connect()
den Wert
„no-value“ für jeden Parameter an, der seinen
Wert aus einer Optionsdatei holen soll:
Für host
geben Sie
NULL
oder den leeren String
(""
) an.
Für user
geben Sie
NULL
oder den leeren String
(""
) an.
Für passwd
geben Sie
NULL
an. (Ein leerer String als
Passwortwert kann im
mysql_real_connect()
-Aufruf nicht durch
einen Wert aus einer Optionsdatei überschrieben werden,
da der leere String ausdrücklich besagt, dass das
MySQL-Konto ein leeres Passwort besitzen muss.)
Für db
geben Sie
NULL
oder den leeren String
(""
) an.
Für port
geben Sie den Wert 0 an.
Für unix_socket
geben Sie den Wert
NULL
an.
Wenn in der Optionsdatei für einen Parameter kein Wert gefunden wird, wird sein Standardwert gemäß der Beschreibung weiter oben in diesem Abschnitt verwendet.
Rückgabewerte
Ein MYSQL*
-Verbindungs-Handle, wenn die
Verbindung erfolgreich eingerichtet wurde, und
NULL
, wenn der Verbindungsversuch keinen
Erfolg hatte. Der Rückgabewert für eine erfolgreiche
Verbindung ist derselbe wie der Wert des ersten Parameters.
Fehler
CR_CONN_HOST_ERROR
Verbindung zum MySQL Server konnte nicht hergestellt werden.
CR_CONNECTION_ERROR
Verbindung zum lokalen MySQL Server konnte nicht hergestellt werden.
CR_IPSOCK_ERROR
Es konnte kein IP-Socket hergestellt werden.
CR_OUT_OF_MEMORY
Speicherüberlauf.
CR_SOCKET_CREATE_ERROR
Es konnte kein Unix-Socket erzeugt werden.
CR_UNKNOWN_HOST
Die IP-Adresse des Hostnamens konnte nicht gefunden werden.
CR_VERSION_ERROR
Bei einem Versuch einer Verbindungsaufnahme zwischen einem
Server und einer Clientbibliothek, die eine andere
Protokollversion verwendet, wurde eine Diskrepanz der
Protokolle festgestellt. Das kann geschehen, wenn Sie eine
sehr alte Clientbibliothek zur Verbindung mit einem neuen
Server verwenden, der nicht mit der Option
--old-protocol
gestartet wurde.
CR_NAMEDPIPEOPEN_ERROR
Es konnte keine Named Pipe für Windows hergestellt werden.
CR_NAMEDPIPEWAIT_ERROR
Es konnte nicht auf eine Named Pipe auf Windows gewartet werden.
CR_NAMEDPIPESETSTATE_ERROR
Es konnte kein Pipe-Handler auf Windows beschafft werden.
CR_SERVER_LOST
Wenn connect_timeout
> 0 und es mehr
als connect_timeout
Sekunden dauerte,
eine Verbindung mit dem Server herzustellen, oder wenn der
Server während der Ausführung des Befehls
init-command
abgestürzt ist.
Beispiel
MYSQL mysql; mysql_init(&mysql); mysql_options(&mysql,MYSQL_READ_DEFAULT_GROUP,"your_prog_name"); if (!mysql_real_connect(&mysql,"host","user","passwd","database",0,NULL,0)) { fprintf(stderr, "Failed to connect to database: Error: %s\n", mysql_error(&mysql)); }
Wenn Sie mysql_options()
aufrufen, liest
die MySQL-Bibliothek die Abschnitte
[client]
und
[your_prog_name]
in der Datei
my.cnf
. So ist gewährleistet, dass Ihr
Programm auch dann funktioniert, wenn jemand MySQL in
nichtstandardmäßiger Weise eingerichtet hat.
Beachten Sie, dass mysql_real_connect()
beim Einrichten einer Verbindung das Flag
reconnect
(ein Teil der
MYSQL
-Struktur) bei API-Versionen vor 5.0.3
auf 1
und bei neueren Versionen auf
0
setzt. Hat das Flag den Wert
1
, versucht sich das System erneut mit dem
Server zu verbinden, wenn eine Anweisung wegen einer
abgebrochenen Verbindung nicht ausgeführt werden konnte. Seit
MySQL 5.0.13 können Sie das Verhalten in Bezug auf
Neuverbindungen mit der Option
MYSQL_OPT_RECONNECT
zu
mysql_options()
steuern.
unsigned long mysql_real_escape_string(MYSQL *mysql,
char *to, const char *from, unsigned long length)
Beachten Sie, dass mysql
eine gültige,
offene Verbindung sein muss. Diese ist erforderlich, da das
Escape-Verhalten von dem Zeichensatz des Servers abhängt.
Beschreibung
Diese Funktion wird verwendet, um einen gültigen SQL-String zu erzeugen, den Sie in einer SQL-Anweisung benutzen können. Siehe Abschnitt 9.1.1, „Strings“.
Der String in from
ist als SQL-String mit
Escape-Zeichen unter Berücksichtigung des aktuellen
Zeichensatzes der Verbindung kodiert. Das Ergebnis wird in
to
platziert und ein abschließendes
Nullbyte angehängt. Kodierte Zeichen sind
NUL
(ASCII 0),
‘\n
’,
‘\r
’,
‘\
’,
‘'
’,
‘"
’ und Strg-Z (siehe
Abschnitt 9.1, „Literale: wie Strings und Zahlen geschrieben werden“). (Streng genommen verlangt MySQL
ein Escape-Zeichen im Anfrage-String nur für den Backslash
und die Sorte Anführungszeichen, in welche der String
eingefasst ist. Diese Funktion setzt auch die anderen Zeichen
in Anführungszeichen, damit sie in Logdateien leichter zu
lesen sind.)
Der String, auf den from
verweist, muss
length
Bytes lang sein. Den Puffer für
to
müssen Sie mit einer Länge von
mindestens length*2+1
Bytes zuweisen. (Im
schlimmsten Fall braucht vielleicht jedes Zeichen 2 Byte für
die Kodierung und am Ende muss noch Platz für das Nullbyte
vorhanden sein.) Wenn
mysql_real_escape_string()
zurückkehrt,
ist der Inhalt von to
ein auf null endender
String. Der Rückgabewert ist die Länge des kodierten Strings
ohne das abschließende Nullzeichen.
Wenn Sie den Zeichensatz für die Verbindung umstellen
müssen, sollten Sie die Funktion
mysql_set_character_set()
anstelle einer
SET NAMES
- (oder SET CHARACTER
SET
-)Anweisung verwenden.
mysql_set_character_set()
arbeitet wie
SET NAMES
, beeinflusst aber auch den von
mysql_real_escape_string()
verwendeten
Zeichensatz. Das tut SET NAMES
nicht.
Beispiel
char query[1000],*end; end = strmov(query,"INSERT INTO test_table values("); *end++ = '\''; end += mysql_real_escape_string(&mysql, end,"What's this",11); *end++ = '\''; *end++ = ','; *end++ = '\''; end += mysql_real_escape_string(&mysql, end,"binary data: \0\r\n",16); *end++ = '\''; *end++ = ')'; if (mysql_real_query(&mysql,query,(unsigned int) (end - query))) { fprintf(stderr, "Failed to insert row, Error: %s\n", mysql_error(&mysql)); }
Die im Beispiel verwendete
strmov()
-Funktion gehört zur
mysqlclient
-Bibliothek und funktioniert wie
strcpy()
, gibt jedoch einen Zeiger auf die
abschließende Null des ersten Parameters zurück.
Rückgabewerte
Die Länge des in to
gesetzten Werts ohne
das abschließende Nullzeichen.
Fehler
Keine.
int mysql_real_query(MYSQL *mysql, const char *query,
unsigned long length)
Beschreibung
Führt die SQL-Anfrage aus, auf die query
verweist. Diese sollte ein length
Bytes
langer String sein. Normalerweise muss der String eine
einzelne SQL-Anweisung ohne abschließendes Semikolon
(‘;
’) oder
\g
enthalten. Wenn Mehrfachanweisungen
aktiviert sind, kann der String auch mehrere durch Semikola
getrennte Anweisungen enthalten. Siehe
Abschnitt 24.2.9, „C-API: Behandlung der Ausführung mehrerer Anweisungen“.
Sie müssen
mysql_real_query()
anstelle von
mysql_query()
benutzen, wenn Ihre Anfragen
Binärdaten enthalten, da diese das
‘\0
’-Zeichen enthalten können.
Überdies ist die Funktion
mysql_real_query()
schneller als
mysql_query()
, da sie nicht
strlen()
auf dem Anfrage-String aufruft.
Wenn Sie wissen möchten, ob die Anfrage eigentlich eine
Ergebnismenge zurückliefern sollte, können Sie dies mit
mysql_field_count()
überprüfen. Siehe
Abschnitt 24.2.3.22, „mysql_field_count()
“.
Rückgabewerte
Null, wenn die Anfrage Erfolg hatte. Ein von null verschiedener Wert, wenn ein Fehler auftrat.
Fehler
CR_COMMANDS_OUT_OF_SYNC
Befehle wurden in der falschen Reihenfolge ausgeführt.
CR_SERVER_GONE_ERROR
Der MySQL Server ist nicht mehr verfügbar.
CR_SERVER_LOST
Die Serververbindung brach während der Anfrage ab.
CR_UNKNOWN_ERROR
Ein unbekannter Fehler ist aufgetreten.
int mysql_refresh(MYSQL *mysql, unsigned int
options)
Beschreibung
Diese Funktionen leeren Tabellen oder Caches oder setzen
Replikationsserver-Informationen zurück. Der Benutzer, der
die Verbindung innehat, benötigt hierzu das
RELOAD
-Recht.
Das options
-Argument ist eine Bitmaske, die
sich aus einer beliebigen Kombination von folgenden Werten
zusammensetzt. Mehrere Werte können mit OR verknüpft werden,
um mehrere Operationen mit einem einzigen Aufruf zu erledigen.
REFRESH_GRANT
Aktualisiert die Berechtigungstabellen, wie FLUSH
PRIVILEGES
.
REFRESH_LOG
Leert die Logs, wie FLUSH LOGS
.
REFRESH_TABLES
Leert den Tabellen-Cache, wie FLUSH
TABLES
.
REFRESH_HOSTS
Leert den Host-Cache, wie FLUSH HOSTS
.
REFRESH_STATUS
Setzt die Statusvariablen zurück, wie FLUSH
STATUS
.
REFRESH_THREADS
Leert den Thread-Cache.
REFRESH_SLAVE
Setzt auf einem Slave-Replikationsserver die Informationen
über den Master-Server zurück und startet den Slave neu,
wie RESET SLAVE
.
REFRESH_MASTER
Entfernt auf einem Master-Replikationsserver die im
Binärlogindex aufgeführten Binärlogdateien und
schneidet die Indexdatei ab, wie RESET
MASTER
.
Rückgabewerte
Null bei Erfolg und ein von null verschiedener Wert bei einem Fehler.
Fehler
CR_COMMANDS_OUT_OF_SYNC
Befehle wurden in der falschen Reihenfolge ausgeführt.
CR_SERVER_GONE_ERROR
Der MySQL Server ist nicht mehr verfügbar.
CR_SERVER_LOST
Die Serververbindung brach während der Anfrage ab.
CR_UNKNOWN_ERROR
Ein unbekannter Fehler ist aufgetreten.
int mysql_reload(MYSQL *mysql)
Beschreibung
Veranlasst den MySQL Server, die Berechtigungstabellen neu zu
laden. Der verbundene Benutzer benötigt hierzu das
RELOAD
-Recht.
Diese Funktion ist veraltet. Bitte benutzen Sie stattdessen
mysql_query()
, um die SQL-Anweisung
FLUSH PRIVILEGES
zu erteilen.
Rückgabewerte
Null bei Erfolg und ein von null verschiedener Wert bei einem Fehler.
Fehler
CR_COMMANDS_OUT_OF_SYNC
Befehle wurden in der falschen Reihenfolge ausgeführt.
CR_SERVER_GONE_ERROR
Der MySQL Server ist nicht mehr verfügbar.
CR_SERVER_LOST
Die Serververbindung brach während der Anfrage ab.
CR_UNKNOWN_ERROR
Ein unbekannter Fehler ist aufgetreten.
my_bool mysql_rollback(MYSQL *mysql)
Beschreibung
Rollt die aktuelle Transaktion zurück.
Was diese Funktion tut, hängt von dem Wert der
Systemvariablen completion_type
ab. Wenn
der Wert von completion_type
2 ist, gibt
der Server nach dem Abschluss der Transaktion Ressourcen frei
und schließt die Clientverbindung. Das Clientprogramm sollte
mysql_close()
aufrufen, um die Verbindung
auf der Clientseite zu schließen.
Rückgabewerte
Null bei Erfolg und ein von null verschiedener Wert bei einem Fehler.
Fehler
Keine.
MYSQL_ROW_OFFSET mysql_row_seek(MYSQL_RES *result,
MYSQL_ROW_OFFSET offset)
Beschreibung
Setzt den Zeilen-Cursor auf eine beliebige Zeile in der
Ergebnismenge einer Anfrage. Der
offset
-Wert ist ein Zeilen-Offset. Dieser
sollte ein von mysql_row_tell()
oder
mysql_row_seek()
zurückgegebener Wert
sein. Er ist keine Zeilennummer; wenn Sie eine Zeile einer
Ergebnismenge anhand ihrer Nummer suchen möchten, müssen Sie
stattdessen mysql_data_seek()
aufrufen.
Da für diese Funktion erforderlich ist, dass die
Ergebnismengenstruktur das gesamte Anfrageergebnis enthält,
kann mysql_row_seek()
nur in Verbindung mit
mysql_store_result()
und nicht mit
mysql_use_result()
benutzt werden.
Rückgabewerte
Der vorherige Wert des Zeilen-Cursors. Dieser Wert kann an
einen nachfolgenden mysql_row_seek()
-Aufruf
übergeben werden.
Fehler
Keine.
MYSQL_ROW_OFFSET mysql_row_tell(MYSQL_RES
*result)
Beschreibung
Gibt die aktuelle Position des Zeilen-Cursors für den letzten
mysql_fetch_row()
-Aufruf zurück. Dieser
Wert kann als Argument an mysql_row_seek()
übergeben werden.
Verwenden Sie mysql_row_tell()
bitte nur
nach mysql_store_result()
und nicht nach
mysql_use_result()
.
Rückgabewerte
Der aktuelle Offset des Zeilen-Cursors.
Fehler
Keine.
int mysql_select_db(MYSQL *mysql, const char
*db)
Beschreibung
Macht die Datenbank db
zur
Standarddatenbank auf der durch mysql
angegebenen Verbindung. In den nachfolgenden Anfragen ist
diese Datenbank der Standard für Tabellenreferenzen, die
keine explizite Datenbankbezeichnung enthalten.
mysql_select_db()
funktioniert nur, wenn
der verbundene Benutzer mit der Berechtigung, die Datenbank zu
nutzen, authentifiziert werden kann.
Rückgabewerte
Null bei Erfolg und ein von null verschiedener Wert bei einem Fehler.
Fehler
CR_COMMANDS_OUT_OF_SYNC
Befehle wurden in der falschen Reihenfolge ausgeführt.
CR_SERVER_GONE_ERROR
Der MySQL Server ist nicht mehr verfügbar.
CR_SERVER_LOST
Die Serververbindung brach während der Anfrage ab.
CR_UNKNOWN_ERROR
Ein unbekannter Fehler ist aufgetreten.
int mysql_set_character_set(MYSQL *mysql, char
*csname)
Beschreibung
Diese Funktion stellt den Standardzeichensatz für die
laufende Verbindung ein. Der String csname
ist ein gültiger Zeichensatzname. Die Sortierreihenfolge der
Verbindung wird die Standardsortierreihenfolge dieses
Zeichensatzes. Die Funktion arbeitet wie die SET
NAMES
-Anweisung, stellt jedoch auch den Wert von
mysql->charset
ein und beeinflusst
dadurch den von mysql_real_escape_string()
verwendeten Zeichensatz.
Diese Funktion wurde in MySQL 5.0.7 hinzugefügt.
Rückgabewerte
Null bei Erfolg und ein von null verschiedener Wert bei einem Fehler.
Beispiel
MYSQL mysql; mysql_init(&mysql); if (!mysql_real_connect(&mysql,"host","user","passwd","database",0,NULL,0)) { fprintf(stderr, "Failed to connect to database: Error: %s\n", mysql_error(&mysql)); } if (!mysql_set_charset_name(&mysql, "utf8")) { printf("New client character set: %s\n", mysql_character_set_name(&mysql)); }
int mysql_set_server_option(MYSQL *mysql, enum
enum_mysql_set_option option)
Beschreibung
Aktiviert oder deaktiviert eine Verbindungsoption.
option
kann einen der folgenden Werte
haben:
MYSQL_OPTION_MULTI_STATEMENTS_ON | Schaltet Unterstützung für Mehrfachanweisungen ein. |
MYSQL_OPTION_MULTI_STATEMENTS_OFF | Schaltet Unterstützung für Mehrfachanweisungen aus. |
Rückgabewerte
Null bei Erfolg und ein von null verschiedener Wert bei einem Fehler.
Fehler
CR_COMMANDS_OUT_OF_SYNC
Befehle wurden in der falschen Reihenfolge ausgeführt.
CR_SERVER_GONE_ERROR
Der MySQL Server ist nicht mehr verfügbar.
CR_SERVER_LOST
Die Serververbindung brach während der Anfrage ab.
ER_UNKNOWN_COM_ERROR
Der Server unterstützte
mysql_set_server_option()
nicht (das
ist der Fall, wenn der Server älter als 4.1.1 ist) oder
er unterstützte die Option nicht, die man versuchte,
einzustellen.
int mysql_shutdown(MYSQL *mysql, enum
enum_shutdown_level shutdown_level)
Beschreibung
Veranlasst den Datenbankserver, herunterzufahren. Der Benutzer
der Verbindung muss dieSHUTDOWN
-Rechte
besitzen. MySQL 5.1 Server unterstützen nur eine
einzige Art von Shutdown; der
shutdown_level
muss der
SHUTDOWN_DEFAULT
sein. Wir planen, noch
weitere Shutdown-Level einzuführen, um eine Wahlmöglichkeit
zu eröffnen. Dynamisch verlinkte Executables, die mit
älteren Versionen der
libmysqlclient
-Header kompiliert wurden und
mysql_shutdown()
aufrufen, müssen mit der
älteren dynamischen Bibliothek
libmysqlclient
benutzt werden.
Der Shutdown-Prozess wird in Abschnitt 5.2.6, „Herunterfahren des MySQL Servers“, beschrieben.
Rückgabewerte
Null bei Erfolg und ein von null verschiedener Wert bei einem Fehler.
Fehler
CR_COMMANDS_OUT_OF_SYNC
Befehle wurden in der falschen Reihenfolge ausgeführt.
CR_SERVER_GONE_ERROR
Der MySQL Server ist nicht mehr verfügbar.
CR_SERVER_LOST
Die Serververbindung brach während der Anfrage ab.
CR_UNKNOWN_ERROR
Ein unbekannter Fehler ist aufgetreten.
const char *mysql_sqlstate(MYSQL *mysql)
Beschreibung
Gibt einen auf null endenden String mit dem
SQLSTATE-Fehlercode für den letzten Fehler zurück. Der
Fehlercode besteht aus fünf Zeichen.
'00000'
bedeutet „kein
Fehler“. Die Werte sind durch ANSI-SQL und ODBC
spezifiziert. Eine Liste der möglichen Werte finden Sie unter
Anhang B, Fehlercodes und -meldungen.
Beachten Sie, dass sich nicht alle MySQL-Fehler
SQLSTATE-Fehlercodes zuordnen lassen. Der Wert
'HY000'
(allgemeiner Fehler) wird für
Fehler verwendet, die nicht zuzuordnen sind.
Rückgabewerte
Ein auf null endender Zeichen-String mit dem SQLSTATE-Fehlercode.
Siehe auch
Siehe Abschnitt 24.2.3.14, „mysql_errno()
“,
Abschnitt 24.2.3.15, „mysql_error()
“, und
Abschnitt 24.2.7.26, „mysql_stmt_sqlstate()
“.
int mysql_ssl_set(MYSQL *mysql, const char *key,
const char *cert, const char *ca, const char *capath, const
char *cipher)
Beschreibung
mysql_ssl_set()
richtet sichere
SSL-Verbindungen ein. Diese Funktion muss vor
mysql_real_connect()
aufgerufen werden.
mysql_ssl_set()
arbeitet nur, wenn in der
Clientbibliothek die OpenSSL-Unterstützung aktiviert ist.
mysql
ist der Verbindungs-Handler, der von
mysql_init()
zurückgegeben wird. Die
anderen Parameter sind folgendermaßen spezifiziert:
key
ist der Pfad zur Schlüsseldatei.
cert
ist der Pfad zur Zertifikatsdatei.
ca
ist der Pfad zur
Certificate-Authority-Datei.
capath
ist der Pfad zu einem
Verzeichnis, das vertrauenswürdige SSL-CA-Zertifikate im
Pem-Format enthält.
cipher
ist eine Liste der zulässigen
Chiffren für die SSL-Verschlüsselung.
Ungenutzte SSL-Parameter können mit NULL
angegeben werden.
Rückgabewerte
Diese Funktion liefert immer 0
. Wenn SSL
verkehrt eingerichtet ist, gibt
mysql_real_connect()
bei
Verbindungsversuchen einen Fehler zurück.
char *mysql_stat(MYSQL *mysql)
Beschreibung
Gibt einen Zeichen-String mit ähnlichen Informationen wie der Befehl mysqladmin status zurück. Dazu gehört die Uptime in Sekunden und die Anzahl der laufenden Threads, Fragen, Reloads und offenen Tabellen.
Rückgabewerte
Ein Zeichen-String, der den Serverstatus beschreibt.
NULL
, wenn ein Fehler auftrat.
Fehler
CR_COMMANDS_OUT_OF_SYNC
Befehle wurden in der falschen Reihenfolge ausgeführt.
CR_SERVER_GONE_ERROR
Der MySQL Server ist nicht mehr verfügbar.
CR_SERVER_LOST
Die Serververbindung brach während der Anfrage ab.
CR_UNKNOWN_ERROR
Ein unbekannter Fehler ist aufgetreten.
MYSQL_RES *mysql_store_result(MYSQL *mysql)
Beschreibung
Sie müssen mysql_store_result()
oder
mysql_use_result()
für jede Anfrage
aufrufen, die erfolgreich Daten abruft
(SELECT
, SHOW
,
DESCRIBE
, EXPLAIN
,
CHECK TABLE
, und so weiter).
Für andere Anfragen brauchen Sie
mysql_store_result()
oder
mysql_use_result()
nicht zu verwenden, aber
es schadet auch nichts und bringt keine spürbaren
Leistungseinbußen, wenn Sie in jedem Fall
mysql_store_result()
aufrufen. Sie können
erkennen, ob die Anfrage eine Ergebnismenge hatte oder nicht,
indem Sie prüfen, ob mysql_store_result()
0 zurückgibt (darüber später mehr).
Wenn Sie wissen möchten, ob die Anfrage eine Ergebnismenge
zurückgeben müsste, prüfen Sie dies mit
mysql_field_count()
. Siehe
Abschnitt 24.2.3.22, „mysql_field_count()
“.
mysql_store_result()
liest das gesamte
Anfrageergebnis auf den Client ein, weist eine
MYSQL_RES
-Struktur zu und setzt das
Resultat in diese Struktur ein.
mysql_store_result()
liefert einen
Nullzeiger, wenn die Anfrage keine Ergebnismenge zurückgab
(also beispielsweise eine INSERT
-Anweisung
war).
mysql_store_result()
liefert auch einen
Nullzeiger, wenn die Ergebnismenge nicht gelesen werden
konnte. Ein Fehler ist aufgetreten, wenn
mysql_error()
einen nichtleeren String oder
einen von null verschiedenen Wert liefert oder wenn
mysql_field_count()
null zurückgibt.
Eine leere Ergebnismenge bedeutet, dass keine Zeilen zurückgegeben wurden. (Eine leere Ergebnismenge ist etwas anderes als ein Nullzeiger als Rückgabewert.)
Wenn Sie mysql_store_result()
aufgerufen
und ein Ergebnis erhalten haben, das kein Nullzeiger ist,
können Sie mit mysql_num_rows()
ermitteln,
wie viele Zeilen die Ergebnismenge hat.
Sie können mit mysql_fetch_row()
Zeilen
aus der Ergebnismenge abrufen oder mit
mysql_row_seek()
und
mysql_row_tell()
die aktuelle
Zeilenposition in der Ergebnismenge ermitteln oder einstellen.
Wenn Sie mit der Ergebnismenge fertig sind, rufen Sie
mysql_free_result()
auf.
Rückgabewerte
Eine MYSQL_RES
-Ergebnisstruktur mit den
Resultaten. NULL
, wenn ein Fehler auftrat.
Fehler
Die Funktion mysql_store_result()
setzt
mysql_error()
und
mysql_errno()
zurück, wenn sie erfolgreich
gelaufen ist.
CR_COMMANDS_OUT_OF_SYNC
Befehle wurden in der falschen Reihenfolge ausgeführt.
CR_OUT_OF_MEMORY
Speicherüberlauf.
CR_SERVER_GONE_ERROR
Der MySQL Server ist nicht mehr verfügbar.
CR_SERVER_LOST
Die Serververbindung brach während der Anfrage ab.
CR_UNKNOWN_ERROR
Ein unbekannter Fehler ist aufgetreten.
unsigned long mysql_thread_id(MYSQL *mysql)
Beschreibung
Gibt die Thread-ID der aktuellen Verbindung zurück. Dieser
Wert kann als Argument für mysql_kill()
verwendet werden, um den Thread anzuhalten.
Wenn die Verbindung abgebrochen ist und Sie sich mit
mysql_ping()
erneut zu verbinden versuchen,
ändert sich die Thread-ID. Daher sollten Sie keine Thread-ID
zur späteren Benutzung speichern, sondern sie erst dann
erfragen, wenn Sie sie benötigen.
Rückgabewerte
Die Thread-ID der aktuellen Verbindung.
Fehler
Keine.
MYSQL_RES *mysql_use_result(MYSQL *mysql)
Beschreibung
Sie müssen mysql_store_result()
oder
mysql_use_result()
für jede Anfrage
aufrufen, die erfolgreich Daten abruft
(SELECT
, SHOW
,
DESCRIBE
, EXPLAIN
).
mysql_use_result()
initiiert den Abruf
einer Ergebnismenge, lädt sie jedoch im Gegensatz zu
mysql_store_result()
nicht komplett auf den
Client herunter. Stattdessen wird jede Zeile einzeln mit einem
Aufruf von mysql_fetch_row()
abgefragt. So
wird ein Anfrageergebnis direkt vom Server gelesen, ohne es in
einer temporären Tabelle oder in einem lokalen Puffer
zwischenzuspeichern. Das geht schneller und belegt weniger
Speicher als mysql_store_result()
. Der
Client weist nur für die aktuelle Zeile Speicher zu und
reserviert einen Kommunikationspuffer, der bis zur Größe von
max_allowed_packet
Bytes anwachsen kann.
Demgegenüber sollten Sie
mysql_use_result()
nicht verwenden, wenn
Sie jede Zeile auf der Clientseite aufwändig vearbeiten oder
die Ausgabe an einen Bildschirm senden, in den der Benutzer
^S
(Stop Scroll) eintippen kann. Dies
würde den Server sperren und verhindern, dass andere Threads
Tabellen aktualisieren können, aus denen die Daten abgerufen
werden.
Wenn Sie mit mysql_use_result()
arbeiten,
müssen Sie mysql_fetch_row()
so oft
ausführen, bis ein NULL
-Wert
zurückgeliefert wird. Sonst werden die nicht abgerufenen
Zeilen zu einem Teil der Ergebnismenge der nächsten Anfrage.
Wenn Sie dies vergessen, meldet die C-API den Fehler
Commands out of sync; you can't run this command
now
!
Die Funktionen mysql_data_seek()
,
mysql_row_seek()
,
mysql_row_tell()
,
mysql_num_rows()
oder
mysql_affected_rows()
können nicht mit
einer Ergebnisrückgabe von
mysql_use_result()
benutzt werden. Ebenso
wenig können Sie andere Anfragen absetzen, bevor die Funktion
mysql_use_result()
ihre Arbeit beendet hat.
(Immerhin liefert mysql_num_rows()
ein
akkurates Ergebnis, wenn Sie alle Zeilen abgeholt haben.)
Sie müssen mysql_free_result()
aufrufen,
wenn Sie mit der Ergebnismenge fertig sind.
Bei Verwendung des Embedded Servers
libmysqld
geht der Vorteil des geringen
Speicherbedarfs verloren, da die Speicherbelegung inkrementell
mit jeder abgeholten Zeile anwächst, bis Sie
mysql_free_result()
aufrufen.
Rückgabewerte
Eine MYSQL_RES
-Ergebnisstruktur.
NULL
, wenn ein Fehler auftrat.
Fehler
mysql_use_result()
setzt bei Erfolg
mysql_error()
und
mysql_errno()
zurück.
CR_COMMANDS_OUT_OF_SYNC
Befehle wurden in der falschen Reihenfolge ausgeführt.
CR_OUT_OF_MEMORY
Speicherüberlauf.
CR_SERVER_GONE_ERROR
Der MySQL Server ist nicht mehr verfügbar.
CR_SERVER_LOST
Die Serververbindung brach während der Anfrage ab.
CR_UNKNOWN_ERROR
Ein unbekannter Fehler ist aufgetreten.
Das Client/Server-Protokoll von MySQL ermöglicht auch
vorbereitete Anweisungen. Diese nutzen die Datenstruktur eines
MYSQL_STMT
-Anweisungs-Handles, der von der
Initialisierungsfunktion mysql_stmt_init()
zurückgegeben wird. Die vorbereitete Ausführung ist ein
effizientes Mittel, um eine Anweisung mehrmals laufen zu lassen.
Zuerst wird sie geparst, um sie auf die Ausführung
vorzubereiten, und später wird sie einmal oder mehrmals
mithilfe des von der Initialisierungsfunktion zurückgelieferten
Anweisungs-Handles benutzt.
Die vorbereitete Ausführung ist für Anweisungen, die mehrmals laufen, schneller als eine direkte Ausführung, da die Anfrage nur ein einziges Mal geparst werden muss. Bei einer direkten Ausführung muss die Anfrage dagegen jedes Mal von Neuem geparst werden. Eine vorbereitete Ausführung kann außerdem die Netzwerklast reduzieren, da bei jeder Ausführung der vorbereiteten Anweisung lediglich die Parameterdaten übermittelt werden müssen.
Ein weiterer Vorteil vorbereiteter Anweisungen besteht darin, dass sie ein Binärprotokoll benutzen, das den Datentransfer zwischen Client und Server effizienter gestaltet.
Die folgenden Anweisungen können als vorbereitete Anweisungen
verwendet werden: CREATE TABLE
,
DELETE
, DO
,
INSERT
, REPLACE
,
SELECT
, SET
,
UPDATE
und die meisten
SHOW
-Anweisungen. Andere Anweisungen werden
in MySQL 5.1 nicht unterstützt.
Vorbereitete Anweisungen nutzen hauptsächlich die
Datenstrukturen MYSQL_STMT
und
MYSQL_BIND
. Eine dritte Datenstruktur,
nämlich MYSQL_TIME
, wird zur Übertragung
von Temporaldaten verwendet.
Diese Struktur stellt eine vorbereitete Anweisung dar. Eine
Anweisung wird mit der Funktion
mysql_stmt_init()
angelegt, die einen
Anweisungs-Handle liefert (d. h. einen Zeiger auf
MYSQL_STMT
). Der Handle wird für alle
folgenden mit der Anweisung verbundenen Funktionen benutzt,
bis Sie ihn mit mysql_stmt_close()
wieder
schließen.
Die MYSQL_STMT
-Struktur hat keine
Bestandteile für Anwendungen. Legen Sie bitte auch keine
Kopie einer MYSQL_STMT
-Struktur an, da
nicht garantiert werden kann, dass eine solche Kopie
benutzbar sein wird.
Mehrere Anweisungs-Handles können mit einer einzigen Verbindung verknüpft werden. Wie viele Handles möglich sind, hängt von den Systemressourcen ab.
Diese Struktur wird sowohl für die Eingabe einer Anweisung
(der Datenwerte, die an den Server gesandt werden) als auch
für ihre Ausgabe verwendet (die Ergebnisse, die vom Server
zurückkommen). Für die Eingabe wird sie mit
mysql_stmt_bind_param()
benutzt, um die
Parameterwerte an die Puffer zu binden, die
mysql_stmt_execute()
verwenden. Für die
Ausgabe wird sie mit
mysql_stmt_bind_result()
benutzt, um die
Ergebnismengenpuffer zu binden, die zum Abholen der Zeilen
mit mysql_stmt_fetch()
verwendet werden.
Die MYSQL_BIND
-Struktur enthält folgende
Bestandteile zur Nutzung durch Anwendungsprogramme. Jeder
Bestandteil wird sowohl für die Ein- als auch für die
Ausgabe verwendet, allerdings manchmal zu unterschiedlichen
Zwecken, je nachdem, in welche Richtung die Daten
übertragen werden.
enum enum_field_types buffer_type
Der Puffertyp. Die zulässigen
buffer_type
-Werte werden weiter unten
in diesem Abschnitt aufgeführt. Für die Eingabe zeigt
buffer_type
an, welchen Werttyp Sie
mit einem Anweisungsparameter verbinden. Für die
Ausgabe zeigt er an, welchen Werttyp Sie in einem
Ergebnispuffer erwarten.
void *buffer
Für die Eingabe ist dies ein Zeiger auf den Puffer, in
welchem die Parameterwerte einer Anweisung gespeichert
werden. Für die Ausgabe ist es ein Zeiger auf den
Puffer, in welchen die Spaltenwerte einer Ergebnismenge
zurückgeliefert werden. Für numerische Datentypen
sollte buffer
auf eine Variable des
korrekten C-Typs verweisen. (Wenn Sie die Variable mit
einer Spalte verbinden, die das
UNSIGNED
-Attribut hat, sollte sie ein
unsigned
-C-Typ sein. Ob die Variable
ein Vorzeichen hat oder nicht, geben Sie mithilfe des
weiter unten beschriebenen Strukturbestandteils
is_unsigned
an.) Für Datums- und
Uhrzeittypen sollte buffer
auf eine
MYSQL_TIME
-Struktur verweisen. Für
Zeichen- und Binär-String-Typen sollte
buffer
auf einen Zeichenpuffer
verweisen.
unsigned long buffer_length
Die tatsächliche Größe von *buffer
in Bytes. Dies zeigt an, wie viele Daten maximal in dem
Puffer gespeichert werden können. Für Zeichen und
binäre C-Daten ist der
buffer_length
-Wert die Länge von
*buffer
, wenn er mit
mysql_stmt_bind_param()
gebraucht
wird, beziehungsweise die Höchstzahl der Datenbytes,
die in den Puffer zu laden sind, wenn er mit
mysql_stmt_bind_result()
gebraucht
wird.
unsigned long *length
Ein Zeiger auf eine unsigned
long
-Variable, die angibt, wie viele Bytes
tatsächlich in *buffer
gespeichert
sind. length
wird für Zeichen- oder
Binärdaten in C verwendet. Zum Binden der
Eingabeparameterdaten verweist length
auf eine unsigned long
-Variable,
welche die Länge des in *buffer
gespeicherten Parameterwerts angibt. Diese wird von
mysql_stmt_execute()
benutzt. Zum
Binden der Ausgabewerte speichert
mysql_stmt_fetch()
die Länge des
Rückgabespaltenwerts in der Variablen, auf die
length
verweist.
length
wird bei numerischen und
temporalen Datentypen ignoriert, weil die Länge des
Datenwerts anhand des Werts von
buffer_type
ermittelt wird.
my_bool *is_null
Dies verweist auf eine
my_bool
-Variable, die TRUE ist, wenn
ein Wert NULL
ist, und FALSE, wenn er
nicht NULL
ist. Für die Eingabe
setzen Sie *is_null
auf TRUE, wenn
Sie mitteilen möchten, dass Sie einen
NULL
-Wert als Anweisungsparameter
übergeben. Für die Ausgabe wird dieser Wert nach dem
Abruf einer Zeile der Ergebnismenge immer dann auf TRUE
gesetzt, wenn der Spaltenwert, den die Anweisung
zurückliefert, NULL
ist.
is_null
ist ein Zeiger auf einen
booleschen Wert anstatt auf einen booleschen Skalar.
Daher kann er auf folgende Weise eingesetzt werden:
Wenn Ihre Datenwerte immer NULL
sind, verwenden Sie
MYSQL_TYPE_NULL
, um die Spalte zu
binden.
Wenn Ihre Datenwerte immer NOT
NULL
sind, stellen Sie ein:
is_null = (my_bool*) 0
.
In allen anderen Fällen sollten Sie
is_null
auf die Adresse einer
my_bool
-Variablen einstellen und
deren Wert zwischen den Ausführungen jeweils so
einstellen, dass sie anzeigt, ob Datenwerte
NULL
oder NOT
NULL
sind.
my_bool is_unsigned
Dies wird für Integer-Typen benutzt (die den Typcodes
MYSQL_TYPE_TINY
,
MYSQL_TYPE_SHORT
,
MYSQL_TYPE_LONG
und
MYSQL_TYPE_LONGLONG
entsprechen.)
is_unsigned
sollte für
vorzeichenlose Typen auf TRUE und für
vorzeichenbehaftete auf FALSE gesetzt werden.
my_bool error
Für die Ausgabe wird dieser Strukturbestandteil zur
Meldung von Fehlern wegen abgeschnittener Datenwerte
eingesetzt. Sie müssen diese Meldungen aktivieren,
indem Sie mysql_options()
mit der
Option MYSQL_REPORT_DATA_TRUNCATION
aufrufen. Wenn dies aktiviert ist, liefert
mysql_stmt_fetch()
die
MYSQL_DATA_TRUNCATED
-Meldungen und
error
ist in den
MYSQL_BIND
-Strukturen für Parameter,
deren Datenwerte abgeschnitten wurden, TRUE. Beim
Abschneiden geht ein Vorzeichen oder eine signifikante
Ziffer verloren oder ein String hat nicht in eine Spalte
gepasst.
Um eine MYSQL_BIND
-Struktur zu verwenden,
müssen Sie zur Initialisierung ihren Inhalt auf null setzen
und dann die soeben beschriebenen Bestandteile in geeigneter
Weise einstellen. Wenn Sie beispielsweise ein Array von drei
MYSQL_BIND
-Strukturen deklarieren und
initialisieren möchten, verfahren Sie folgendermaßen:
MYSQL_BIND bind[3]; memset(bind, 0, sizeof(bind));
Diese Struktur sendet und empfängt Daten vom Typ
DATE
, TIME
,
DATETIME
und TIMESTAMP
direkt an den bzw. von dem Server. Dies tut sie, indem der
buffer_type
-Teil einer
MYSQL_BIND
-Struktur auf einen der
temporalen Datentypen und der buffer
auf
eine MYSQL_TIME
-Struktur eingestellt
wird.
Die MYSQL_TIME
-Struktur enthält folgende
Bestandteile:
unsigned int year
Das Jahr.
unsigned int month
Der Monat des Jahres.
unsigned int day
Der Tag des Monats.
unsigned int hour
Die Stunde des Tages.
unsigned int minute
Die Minute der Stunde.
unsigned int second
Die Sekunde der Minute.
my_bool neg
Ein boolesches Flag, das angibt, ob der Zeitwert negativ ist.
unsigned long second_part
Ein Sekundenbruchteil. Dieser Teil wird zurzeit nicht benutzt.
Es werden nur diejenigen Teile einer
MYSQL_TIME
-Struktur benutzt, die auf
einen gegebenen Temporalwerttyp anwendbar sind: Die Elemente
year
, month
und
day
werden für DATE
-,
DATETIME
- und
TIMESTAMP
-Werte gebraucht und die
Elemente hour
, minute
und second
für TIME
-,
DATETIME
- und
TIMESTAMP
-Werte. Siehe
Abschnitt 24.2.10, „C-API: Behandlung von Datums- und Zeitwerten“.
Die folgende Tabelle zeigt die zulässigen Werte an, die im
buffer_type
-Teil von
MYSQL_BIND
-Strukturen angegeben werden
können. Sie dokumentiert auch, welche SQL-Typen am ehesten den
buffer_type
-Werten entsprechen, sowie den
entsprechenden C-Typ für numerische und temporale Typen.
buffer_type Wert | SQL-Typ | C-Typ |
MYSQL_TYPE_BIT | BIT |
|
MYSQL_TYPE_TINY | TINYINT | char |
MYSQL_TYPE_SHORT | SMALLINT | short int |
MYSQL_TYPE_LONG | INT | int |
MYSQL_TYPE_LONGLONG | BIGINT | long long int |
MYSQL_TYPE_FLOAT | FLOAT | float |
MYSQL_TYPE_DOUBLE | DOUBLE | double |
MYSQL_TYPE_TIME | TIME | MYSQL_TIME |
MYSQL_TYPE_DATE | DATE | MYSQL_TIME |
MYSQL_TYPE_DATETIME | DATETIME | MYSQL_TIME |
MYSQL_TYPE_TIMESTAMP | TIMESTAMP | MYSQL_TIME |
MYSQL_TYPE_STRING | CHAR | |
MYSQL_TYPE_VAR_STRING | VARCHAR | |
MYSQL_TYPE_TINY_BLOB | TINYBLOB/TINYTEXT | |
MYSQL_TYPE_BLOB | BLOB/TEXT | |
MYSQL_TYPE_MEDIUM_BLOB | MEDIUMBLOB/MEDIUMTEXT | |
MYSQL_TYPE_LONG_BLOB | LONGBLOB/LONGTEXT |
Eine implizite Typumwandlung ist in beiden Richtungen möglich.
Die Funktionen für vorbereitete Anweisungen werden hier zusammengefasst und im Weiteren genauer beschrieben. Siehe Abschnitt 24.2.7, „C-API Prepared Statements: Funktionsbeschreibungen“.
Funktion | Beschreibung |
mysql_stmt_affected_rows() | Liefert die Anzahl der Änderungen, Löschungen und Einfügungen in
Zeilen durch eine vorbereitete
UPDATE -, DELETE -
oder INSERT -Anweisung. |
mysql_stmt_attr_get() | Holt den Wert eines Attributs für eine vorbereitete Anweisung. |
mysql_stmt_attr_set() | Setzt ein Attribut für eine vorbereitete Anweisung. |
mysql_stmt_bind_param() | Verbindet Anwendungsdatenpuffer mit den Parametermarkern einer vorbereiteten SQL-Anweisung. |
mysql_stmt_bind_result() | Verbindet Anwendungsdatenpuffer mit den Spalten der Ergebnismenge. |
mysql_stmt_close() | Gibt den von einer vorbereiteten Anweisung benutzten Speicher frei. |
mysql_stmt_data_seek() | Sucht nach einer beliebigen Zeilennummer in der Ergebnismenge einer Anweisung. |
mysql_stmt_errno() | Liefert die Fehlernummer für die letzte Ausführung einer Anweisung. |
mysql_stmt_error() | Liefert die Fehlermeldung für die letzte Ausführung einer Anweisung. |
mysql_stmt_execute() | Führt die vorbereitete Anweisung aus. |
mysql_stmt_fetch() | Holt die nächste Datenzeile aus der Ergebnismenge und liefert Daten für alle gebundenen Spalten. |
mysql_stmt_fetch_column() | Holt Daten einer Spalte aus der aktuellen Zeile der Ergebnismenge. |
mysql_stmt_field_count() | Liefert die Anzahl der Ergebnisspalten für die letzte Anweisung. |
mysql_stmt_free_result() | Gibt die für den Anweisungs-Handle zugewiesenen Ressourcen frei. |
mysql_stmt_init() | Weist der MYSQL_STMT -Struktur Speicher zu und
initialisiert sie. |
mysql_stmt_insert_id() | Liefert die für eine AUTO_INCREMENT -Spalte von einer
vorbereiteten Anweisung generierte ID. |
mysql_stmt_num_rows() | Liefert die Gesamtzahl der Zeilen in der gepufferten Ergebnismenge der Anweisung. |
mysql_stmt_param_count() | Liefert die Anzahl der Parameter in einer vorbereiteten SQL-Anweisung. |
mysql_stmt_param_metadata() | Liefert Parametermetadaten in Form einer Ergebnismenge. |
mysql_stmt_prepare() | Bereitet einen SQL-String zur Ausführung vor. |
mysql_stmt_reset() | Setzt die Anweisungspuffer im Server zurück. |
mysql_stmt_result_metadata() | Liefert Metadaten zu einer vorbereiteten Anweisung in Form einer Ergebnismenge. |
mysql_stmt_row_seek() | Sucht einen Zeilen-Offset in der Ergebnismenge einer Anweisung und
verwendet dazu den Rückgabewert von
mysql_stmt_row_tell() . |
mysql_stmt_row_tell() | Liefert die Zeilen-Cursor-Position der Anweisung. |
mysql_stmt_send_long_data() | Sendet lange Daten stückweise an den Server. |
mysql_stmt_sqlstate() | Liefert den SQLSTATE-Fehlercode für die letzte Anweisungsausführung. |
mysql_stmt_store_result() | Lädt die gesamte Ergebnismenge auf den Client herunter. |
Rufen Sie zuerst mysql_stmt_init()
auf, um
einen Anweisungs-Handle zu erzeugen, dann
mysql_stmt_prepare
, um die Anweisung
vorzubereiten, dann mysql_stmt_bind_param()
,
um die Parameterdaten zu liefern, und zum Schluss
mysql_stmt_execute()
, um die Anweisung
auszuführen. Sie können den
mysql_stmt_execute()
-Aufruf wiederholen,
indem Sie die Parameterwerte in den jeweiligen von
mysql_stmt_bind_param()
zur Verfügung
gestellten Puffern ändern.
Ist die Anweisung ein SELECT
oder eine andere
Anweisung, die eine Ergebnismenge erstellt, liefert
mysql_stmt_prepare()
zu dieser Ergebnismenge
auch Metadaten in Form einer von
mysql_stmt_result_metadata()
zurückgegebenen
MYSQL_RES
-Ergebnismenge.
Sie können die Ergebnispuffer mit
mysql_stmt_bind_result()
zur Verfügung
stellen, sodass mysql_stmt_fetch()
automatisch Daten an diese Puffer liefert. Dabei handelt es sich
um einen zeilenweisen Datenabruf.
Sie können auch die Text- oder Binärdaten mit
mysql_stmt_send_long_data()
stückweise an
den Server senden. Siehe
Abschnitt 24.2.7.25, „mysql_stmt_send_long_data()
“.
Wenn die Anweisungsausführung abgeschlossen ist, muss der
Anweisungs-Handle mit mysql_stmt_close()
geschlossen werden, damit alle seine Ressourcen freigegeben
werden können.
Wenn Sie mit mysql_stmt_result_metadata()
Metadaten zur Ergebnismenge einer
SELECT
-Anweisung beschafft haben, müssen Sie
mit mysql_free_result()
auch diese Metadaten
freigeben.
Ausführungsschritte
Um eine Anweisung zur Nutzung in einer Anwendung vorzubereiten und auszuführen, müssen Sie Folgendes tun:
Mit msyql_stmt_init()
erzeugen Sie einen
Handle für eine vorbereitete Anweisung. Um die Anweisung
auf dem Server vorzubereiten, müssen Sie die Funktion
mysql_stmt_prepare()
aufrufen und ihr
einen String mit der SQL-Anweisung übergeben.
Wenn die Anweisung eine Ergebnismenge erstellt, müssen Sie
die Metadaten dieser Ergebnismenge mit
mysql_stmt_result_metadata()
abholen. Die
Metadaten liegen selbst ebenfalls in Form einer
Ergebnismenge vor, allerdings einer anderen als der, die die
Rückgabezeilen der Anfrage enthält. Die
Metadatenergebnismenge gibt an, wie viele Spalten das
Ergebnis enthält, und gibt Informationen über jede dieser
Spalten.
Die Parameterwerte setzen Sie mit
mysql_stmt_bind_param()
. Alle Parameter
müssen gesetzt werden. Andernfalls gibt die
Anweisungsausführung einen Fehler zurück oder liefert
unerwartete Resultate.
Mit einem Aufruf von mysql_stmt_execute()
führen Sie die Anweisung aus.
Wenn die Anweisung eine Ergebnismenge erstellt, binden Sie
die Datenpuffer zum Abruf der Zeilenwerte mit
mysql_stmt_bind_result()
.
Laden Sie die Daten zeilenweise durch wiederholten Aufruf
von mysql_stmt_fetch()
in die Puffer
herunter, bis keine weiteren Zeilen mehr vorliegen.
Wiederholen Sie die Schritte 3 bis 6 so oft wie nötig, indem Sie die Parameterwerte ändern und die Anweisung erneut ausführen.
Bei einem Aufruf von mysql_stmt_prepare()
tut
das MySQL-Client/Server-Protokoll Folgendes:
Der Server parst die Anweisung und sendet den Okay-Status an den Client, indem er eine Anweisungs-ID zuweist. Außerdem sendet er, falls die Anweisung eine Ergebnismenge liefert, die Gesamtzahl der Parameter, eine Zeilenzahl und die Metadaten. Die Syntax und Semantik der Anweisung werden auf dem Server während dieses Aufrufs überprüft.
Der Client verwendet diese Anweisungs-ID für weitere Operationen, damit der Server die Anweisung in seinem Anweisungspool wiederfinden kann.
Bei einem Aufruf von mysql_stmt_execute()
geht das MySQL-Client/Server-Protokoll folgendermaßen vor:
Der Client nutzt den Anweisungs-Handle und sendet die Parameterdaten an den Server.
Der Server findet die Anweisung anhand der vom Client übergebenen ID wieder, ersetzt die Parametermarker mit den frisch gelieferten Daten und führt die Anweisung aus. Wenn die Anweisung eine Ergebnismenge erstellt, sendet der Server die Daten an den Client zurück, ansonsten sendet er einen Okay-Status und die Gesamtzahl der geänderten, gelöschten oder eingefügten Zeilen.
Bei einem Aufruf von mysql_stmt_fetch()
geht
das MySQL-Client/Server-Protokoll folgendermaßen vor:
Der Client liest die Daten zeilenweise aus dem Paket ein und setzt sie in die Datenpuffer der Anwendung, indem er die notwendigen Typkonvertierungen vornimmt. Hat der Anwendungsdatenpuffer denselben Typ wie das vom Server zurückgegebene Feld, ist die Konvertierung einfach.
Wenn ein Fehler auftritt, können Sie den Anweisungsfehlercode,
die Fehlermeldung und den SQLSTATE-Wert mit den Funktionen
mysql_stmt_errno()
,
mysql_stmt_error()
und
mysql_stmt_sqlstate()
erhalten.
Protokollierung vorbereiteter Anweisungen
Für vorbereitete Anweisungen, die mit den C-API-Funktionen
mysql_stmt_prepare()
und
mysql_stmt_execute()
ausgeführt werden,
schreibt der Server Prepare
- und
Execute
-Zeilen in das allgemeine Anfragenlog,
damit Sie hinterher wissen, wann Anweisungen vorbereitet und
ausgeführt wurden.
Angenommen, Sie bereiten eine Anweisung folgendermaßen vor und führen sie aus:
Sie rufen mysql_stmt_prepare()
auf, um
den Anweisungs-String "SELECT ?"
vorzubereiten.
Sie rufen mysql_stmt_bind_param()
auf, um
den Wert 3
an den Parameter der
vorbereiteten Anweisung zu binden.
Sie rufen mysql_stmt_execute()
auf, um
die vorbereitete Anweisung auszuführen.
Aufgrund dieser Funktionsaufrufe schreibt der Server folgende Zeilen in das allgemeine Anfragenlog:
Prepare [1] SELECT ? Execute [1] SELECT 3
Jede Prepare
- und
Execute
-Zeile im Log wird mit einem
[
-Anweisungsbezeichner
markiert, damit Sie nachvollziehen können, welche vorbereitete
Anweisung gerade protokolliert wird.
N
]N
ist ein positiver Integer. Wenn
mehrere vorbereitete Anweisungen zugleich für den Client aktiv
sind, kann N
größer als 1 sein.
Jede Execute
-Zeile zeigt eine vorbereitete
Anweisung nach Einsetzung der Datenwerte in die
?
-Parameter an.
Versionshinweise: Prepare
-Zeilen werden vor
MySQL 4.1.10 ohne
[
angezeigt.
N
]Execute
-Zeilen werden vor MySQL 4.1.10
überhaupt nicht angezeigt.
mysql_stmt_affected_rows()
mysql_stmt_attr_get()
mysql_stmt_attr_set()
mysql_stmt_bind_param()
mysql_stmt_bind_result()
mysql_stmt_close()
mysql_stmt_data_seek()
mysql_stmt_errno()
mysql_stmt_error()
mysql_stmt_execute()
mysql_stmt_fetch()
mysql_stmt_fetch_column()
mysql_stmt_field_count()
mysql_stmt_free_result()
mysql_stmt_init()
mysql_stmt_insert_id()
mysql_stmt_num_rows()
mysql_stmt_param_count()
mysql_stmt_param_metadata()
mysql_stmt_prepare()
mysql_stmt_reset()
mysql_stmt_result_metadata()
mysql_stmt_row_seek()
mysql_stmt_row_tell()
mysql_stmt_send_long_data()
mysql_stmt_sqlstate()
mysql_stmt_store_result()
Um Anfragen vorzubereiten und auszuführen, verwenden Sie die Funktionen, die in den folgenden Abschnitten genauer beschrieben werden.
Beachten Sie, dass alle Funktionen, die mit der
MYSQL_STMT
-Struktur arbeiten, mit dem Präfix
mysql_stmt_
anfangen.
Um einen MYSQL_STMT
-Handle anzulegen,
verwenden Sie die mysql_stmt_init()
-Funktion.
my_ulonglong mysql_stmt_affected_rows(MYSQL_STMT
*stmt)
Beschreibung
Diese Funktion gibt die Gesamtzahl der von der zuletzt
ausgeführten Anweisung geänderten, gelöschten oder
eingefügten Zeilen zurück. Für UPDATE
-,
DELETE
- oder
INSERT
-Anweisungen kann sie unmittelbar
nach mysql_stmt_execute()
aufgerufen
werden. Für SELECT
-Anweisungen arbeitet
mysql_stmt_affected_rows()
genau wie
mysql_num_rows()
.
Rückgabewerte
Ein Integer größer null zeigt die Anzahl der betroffenen
oder abgerufenen Zeilen an. Null zeigt für eine
UPDATE
-Anweisung an, dass keine Zeilen
aktualisiert wurden, für eine
WHERE
-Klausel in der Anfrage, dass keine
Zeilen gepasst haben, oder ansonsten, dass die Anfrage noch
gar nicht ausgeführt wurde. -1 bedeutet, dass die Anfrage
einen Fehler zurückgeliefert hat oder, bei einer
SELECT
-Anfrage, dass
mysql_stmt_affected_rows()
vor
mysql_stmt_store_result()
aufgerufen wurde.
Da mysql_stmt_affected_rows()
einen
vorzeichenlosen Wert liefert, können Sie -1 überprüfen,
indem Sie den Rückgabewert mit
(my_ulonglong)-1
(oder dem Äquivalent
(my_ulonglong)~0
) vergleichen.
Weitere Informationen über den Rückgabewert finden Sie unter
Abschnitt 24.2.3.1, „mysql_affected_rows()
“.
Fehler
Keine.
Beispiel
Ein Anwendungsbeispiel für
mysql_stmt_affected_rows()
finden Sie im
Beispiel von Abschnitt 24.2.7.10, „mysql_stmt_execute()
“.
int mysql_stmt_attr_get(MYSQL_STMT *stmt, enum
enum_stmt_attr_type option, void *arg)
Beschreibung
Kann genutzt werden, um den aktuellen Wert eines Anweisungsattributs abzufragen.
Das option
-Argument ist die abzufragende
Option; das arg
sollte auf eine Variable
mit dem Optionswert verweisen. Wenn die Option ein Integer
ist, sollte arg
auf den Wert dieses
Integers verweisen.
Eine Liste aller Optionen und Optionstypen finden Sie unter
Abschnitt 24.2.7.3, „mysql_stmt_attr_set()
“.
Rückgabewerte
0
, wenn alles okay ist. Ein von null
verschiedener Wert, wenn option
unbekannt
ist.
Fehler
Keine.
int mysql_stmt_attr_set(MYSQL_STMT *stmt, enum
enum_stmt_attr_type option, const void *arg)
Beschreibung
Kann genutzt werden, um das Verhalten einer vorbereiteten Anweisung zu beeinflussen. Diese Funktion kann auch mehrmals aufgerufen werden, um mehrere Optionen zu setzen.
Das option
-Argument ist die Option, die Sie
einstellen möchten, und arg
ist ihr Wert.
Wenn die Option ein Integer ist, muss arg
auf den Wert eines Integers verweisen.
Mögliche option
-Werte:
Option | Argumenttyp | Funktion |
STMT_ATTR_UPDATE_MAX_LENGTH | my_bool * | Wenn 1: Metadaten zum Update
MYSQL_FIELD->max_length in
mysql_stmt_store_result() . |
STMT_ATTR_CURSOR_TYPE | unsigned long * | Typ des Cursors, der bei Aufruf von
mysql_stmt_execute() für die
Anweisung geöffnet wird. *arg kann
CURSOR_TYPE_NO_CURSOR
(Standardwert) oder
CURSOR_TYPE_READ_ONLY sein. |
STMT_ATTR_PREFETCH_ROWS | unsigned long * | Anzahl der Zeilen, die mit einem Cursor gleichzeitig vom Server geholt
werden. *arg liegt zwischen 1 und
dem Maximalwert von unsigned long .
Der Standardwert ist 1. |
Wenn Sie die Option STMT_ATTR_CURSOR_TYPE
mit CURSOR_TYPE_READ_ONLY
verwenden, wird
ein Cursor für die Anweisung geöffnet, sobald Sie
mysql_stmt_execute()
aufrufen. Existiert
bereits ein geöffneter Cursor aus einem früheren
mysql_stmt_execute()
-Aufruf, schließt die
Option diesen Cursor, bevor ein neuer geöffnet wird. Die
Funktion mysql_stmt_reset()
schließt auch
offene Cursors, bevor sie die Anweisung zur erneuten
Ausführung vorbereitet.
mysql_stmt_free_result()
schließt
ebenfalls einen eventuell noch offenen Cursor.
Wenn Sie einen Cursor für eine vorbereitete Anweisung
öffnen, ist mysql_stmt_store_result()
überflüssig, da diese Funktion die Ergebnismenge auf der
Clientseite puffern lässt.
Die Option STMT_ATTR_CURSOR_TYPE
wurde in
MySQL 5.0.2 hinzugefügt. Die Option
STMT_ATTR_PREFETCH_ROWS
wurde in MySQL
5.0.6 hinzugefügt.
Rückgabewerte
0
, wenn alles okay ist. Ein von null
verschiedener Wert, wenn option
unbekannt
ist.
Fehler
Keine.
Beispiel
Das folgende Beispiel öffnet einen Cursor für eine vorbereitete Anweisung und setzt die Anzahl der in einem Schwung abzuholenden Zeilen auf 5:
MYSQL_STMT *stmt; int rc; unsigned long type; unsigned long prefetch_rows = 5; stmt = mysql_stmt_init(mysql); type = (unsigned long) CURSOR_TYPE_READ_ONLY; rc = mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type); /* ... prüfe Rückgabewert... */ rc = mysql_stmt_attr_set(stmt, STMT_ATTR_PREFETCH_ROWS, (void*) &prefetch_rows); /* ... prüfe Rückgabewert ... */
my_bool mysql_stmt_bind_param(MYSQL_STMT *stmt,
MYSQL_BIND *bind)
Beschreibung
Die Funktion mysql_stmt_bind_param()
bindet
Daten an die Parametermarker in der SQL-Anweisung, die an
mysql_stmt_prepare()
übergeben wurde. Zur
Übergabe der Daten verwendet sie
MYSQL_BIND
-Strukturen.
bind
ist die Adresse eines Arrays von
MYSQL_BIND
-Strukturen. Die Clientbibliothek
erwartet, dass das Array für jeden
‘?
’-Parametermarker in der
Anfrage einen Wert enthält.
Angenommen, Sie bereiten folgende Anweisung vor:
INSERT INTO mytbl VALUES(?,?,?)
Wenn Sie die Parameter binden, muss das Array von
MYSQL_BIND
-Strukturen drei Elemente
enthalten. Es kann wie folgt deklariert werden:
MYSQL_BIND bind[3];
Die Bestandteile jedes MYSQL_BIND
-Elements,
das gesetzt werden muss, sind in
Abschnitt 24.2.5, „C-API: Prepared Statement-Datentypen“,
beschrieben.
Rückgabewerte
Null, wenn das Binden erfolgreich verlief. Ein von null verschiedener Wert, wenn ein Fehler auftrat.
Fehler
CR_INVALID_BUFFER_USE
Zeigt an, ob lange Daten beim Binden stückweise an einen Puffer übergeben werden, der kein String- oder Binärpuffer ist.
CR_UNSUPPORTED_PARAM_TYPE
Die Konvertierung wird nicht unterstützt. Eventuell ist
der buffer_type
-Wert unzulässig oder
hat keinen der unterstützten Typen.
CR_OUT_OF_MEMORY
Speicherüberlauf.
CR_UNKNOWN_ERROR
Ein unbekannter Fehler ist aufgetreten.
Beispiel
Wie man mysql_stmt_bind_param()
verwendet,
sehen Sie im Beispiel von
Abschnitt 24.2.7.10, „mysql_stmt_execute()
“.
my_bool mysql_stmt_bind_result(MYSQL_STMT *stmt,
MYSQL_BIND *bind)
Beschreibung
mysql_stmt_bind_result()
bindet Spalten der
Ergebnismenge an Daten- und Längenpuffer. Wenn Daten mit
mysql_stmt_fetch()
abgeholt werden, setzt
das MySQL-Client/Server-Protokoll die Daten für gebundene
Spalten in die angegebenen Puffer ein.
Alle Spalten müssen an ihre Puffer gebunden sein, bevor
mysql_stmt_fetch()
aufgerufen wird.
bind
ist die Adresse eines Arrays von
MYSQL_BIND
-Strukturen. Die Clientbibliothek
erwartet, dass dieses Array für jede Spalte der Ergebnismenge
ein Element enthält. Wenn Sie es versäumen, Spalten an
MYSQL_BIND
-Strukturen zu binden, ignoriert
mysql_stmt_fetch()
einfach den Datenabruf.
Die Puffer sollten groß genug sein, um die Datenwerte
speichern zu können, da dieses Protokoll die Daten nicht
stückweise zurückgeben kann.
Eine Spalte kann jederzeit gebunden oder neu gebunden werden,
auch dann, wenn eine Ergebnismenge teilweise abgeholt wurde.
Die neue Bindung tritt beim nächsten Aufruf von
mysql_stmt_fetch()
in Kraft. Nehmen wir an,
eine Anwendung bindet die Spalten in einer Ergebnismenge und
ruft mysql_stmt_fetch()
auf. Das
Client/Server-Protokoll liefert die Daten in die gebundenen
Puffer. Wenn die Anwendung nun aber die Spalten an andere
Puffer bindet, schreibt das Protokoll die Daten erst beim
nächsten Aufruf von mysql_stmt_fetch()
in
diese anderen Puffer.
Um eine Spalte zu binden, ruft eine Anwendung
mysql_stmt_bind_result()
auf und übergibt
den Typ, die Adresse und die Adresse des Längenpuffers. Die
Bestandteile der MYSQL_BIND
-Elemente
sollten so eingestellt werden wie in
Abschnitt 24.2.5, „C-API: Prepared Statement-Datentypen“,
beschrieben.
Rückgabewerte
Null, wenn das Binden erfolgreich verlief. Ein von null verschiedener Wert, wenn ein Fehler auftrat.
Fehler
CR_UNSUPPORTED_PARAM_TYPE
Die Konvertierung wird nicht unterstützt. Möglicherweise
ist der buffer_type
-Wert unzulässig
oder hat keinen Typ, der unterstützt wird.
CR_OUT_OF_MEMORY
Speicherüberlauf.
CR_UNKNOWN_ERROR
Ein unbekannter Fehler ist aufgetreten.
Beispiel
Die Verwendung von mysql_stmt_bind_result()
wird im Beispiel von Abschnitt 24.2.7.11, „mysql_stmt_fetch()
“,
gezeigt.
my_bool mysql_stmt_close(MYSQL_STMT *)
Beschreibung
Schließt die vorbereitete Anweisung. Außerdem gibt
mysql_stmt_close()
den Anweisungs-Handle
von stmt
frei.
Wenn die aktuelle Anweisung noch ausstehende oder ungelesene Ergebnisse hat, werden sie durch diese Funktion annulliert, damit die nächste Anfrage ausgeführt werden kann.
Rückgabewerte
Null, wenn die Anweisung erfolgreich freigegeben wurde. Ein von null verschiedener Wert, wenn ein Fehler auftrat.
Fehler
CR_SERVER_GONE_ERROR
Der MySQL Server ist nicht mehr verfügbar.
CR_UNKNOWN_ERROR
Ein unbekannter Fehler ist aufgetreten.
Beispiel
Die Anwendung von mysql_stmt_close()
sehen
Sie im Beispiel zu Abschnitt 24.2.7.10, „mysql_stmt_execute()
“.
void mysql_stmt_data_seek(MYSQL_STMT *stmt,
my_ulonglong offset)
Beschreibung
Findet eine beliebige Zeile in einer Ergebnismenge einer
Anweisung. Der offset
-Wert ist eine
Zeilennummer zwischen 0
und
mysql_stmt_num_rows(stmt)-1
.
Für diese Funktion ist erforderlich, dass die
Ergebnismengenstruktur der Anweisung das gesamte Ergebnis der
zuletzt ausgeführten Anfrage enthält. Daher kann
mysql_stmt_data_seek()
nur in Verbindung
mit mysql_stmt_store_result()
eingesetzt
werden.
Rückgabewerte
Keine.
Fehler
Keine.
unsigned int mysql_stmt_errno(MYSQL_STMT
*stmt)
Beschreibung
Für die durch stmt
spezifizierte Anweisung
liefert mysql_stmt_errno()
den Fehlercode
der zuletzt aufgerufenen Anweisungs-API-Funktion, die
erfolgreich laufen oder scheitern kann. Null wird
zurückgegeben, wenn kein Fehler auftrat. Die Nummern der
Clientfehlermeldungen sind in der MySQL-Header-Datei
errmsg.h
aufgeführt. Die Nummern der
Serverfehlermeldungen finden Sie in
mysqld_error.h
. Außerdem sind die Fehler
in Anhang B, Fehlercodes und -meldungen, aufgelistet.
Rückgabewerte
Der Wert eines Fehlercodes. Null, wenn kein Fehler auftrat.
Fehler
Keine.
const char *mysql_stmt_error(MYSQL_STMT
*stmt)
Beschreibung
Für die durch stmt
spezifizierte Anweisung
liefert mysql_stmt_error()
einen auf null
endenden String mit der Fehlermeldung für die zuletzt
aufgerufene Anweisungs-API-Funktion, die erfolgreich laufen
oder scheitern kann. Ein leerer String (""
)
wird zurückgegeben, wenn kein Fehler auftrat. Das bedeutet,
dass die beiden folgenden Tests äquivalent sind:
if (mysql_stmt_errno(stmt)) { // Ein Fehler trat auf } if (mysql_stmt_error(stmt)[0]) { // Ein Fehler trat auf }
Die Sprache der Clientfehlermeldungen kann sich durch Rekompilieren der MySQL-Clientbibliothek ändern. Zurzeit haben Sie die Wahl zwischen Fehlermeldungen in mehreren verschiedenen Sprachen.
Rückgabewerte
Ein Zeichen-String, der den Fehler beschreibt. Ein leerer String, wenn kein Fehler auftrat.
Fehler
Keine.
int mysql_stmt_execute(MYSQL_STMT *stmt)
Beschreibung
mysql_stmt_execute()
führt die
vorbereitete Anfrage aus, die zu dem Anweisungs-Handle
gehört. Die aktuellen Werte der gebundenen Parametermarker
werden bei diesem Aufruf an den Server geschickt, und der
Server ersetzt die Marker durch die frisch gelieferten Daten.
Wenn die Anweisung ein UPDATE
,
DELETE
oder INSERT
ist,
erfahren Sie durch einen Aufruf von
mysql_stmt_affected_rows()
, wie viele
Zeilen geändert, gelöscht oder eingefügt wurden. Ist es
eine Anweisung wie SELECT
, die eine
Ergebnismenge generiert, müssen Sie zuerst mit
mysql_stmt_fetch()
die Daten abholen, bevor
Sie irgendwelche Funktionen aufrufen, um die Anfrage zu
verarbeiten. Weitere Informationen über den Abruf von
Ergebnissen finden Sie in Abschnitt 24.2.7.11, „mysql_stmt_fetch()
“.
Für Anweisungen, die eine Ergebnismenge generieren, können
Sie verlangen, dass mysql_stmt_execute()
einen Cursor öffnet, indem Sie vor Ausführung der Anweisung
mysql_stmt_attr_set()
aufrufen. Wenn Sie
eine Anweisung mehrmals ausführen, schließt
mysql_stmt_execute()
einen eventuell noch
offenen Cursor, ehe es einen neuen öffnet.
Rückgabewerte
Null, wenn die Ausführung Erfolg hatte. Ein von null verschiedener Wert, wenn ein Fehler auftrat.
Fehler
CR_COMMANDS_OUT_OF_SYNC
Befehle wurden in der falschen Reihenfolge ausgeführt.
CR_OUT_OF_MEMORY
Speicherüberlauf.
CR_SERVER_GONE_ERROR
Der MySQL Server ist nicht mehr verfügbar.
CR_SERVER_LOST
Die Serververbindung brach während der Anfrage ab.
CR_UNKNOWN_ERROR
Ein unbekannter Fehler ist aufgetreten.
Beispiel
Das folgende Beispiel zeigt, wie eine Tabelle mithilfe von
mysql_stmt_init()
,
mysql_stmt_prepare()
,
mysql_stmt_param_count()
,
mysql_stmt_bind_param()
,
mysql_stmt_execute()
und
mysql_stmt_affected_rows()
angelegt und mit
Daten gefüllt wird. Die mysql
-Variable sei
ein gültiger Verbindungs-Handle.
#define STRING_SIZE 50 #define DROP_SAMPLE_TABLE "DROP TABLE IF EXISTS test_table" #define CREATE_SAMPLE_TABLE "CREATE TABLE test_table(col1 INT,\ col2 VARCHAR(40),\ col3 SMALLINT,\ col4 TIMESTAMP)" #define INSERT_SAMPLE "INSERT INTO test_table(col1,col2,col3) VALUES(?,?,?)" MYSQL_STMT *stmt; MYSQL_BIND bind[3]; my_ulonglong affected_rows; int param_count; short small_data; int int_data; char str_data[STRING_SIZE]; unsigned long str_length; my_bool is_null; if (mysql_query(mysql, DROP_SAMPLE_TABLE)) { fprintf(stderr, " DROP TABLE failed\n"); fprintf(stderr, " %s\n", mysql_error(mysql)); exit(0); } if (mysql_query(mysql, CREATE_SAMPLE_TABLE)) { fprintf(stderr, " CREATE TABLE failed\n"); fprintf(stderr, " %s\n", mysql_error(mysql)); exit(0); } /* Bereite eine INSERT-Anfrage mit 3 Parametern vor */ /* (Die TIMESTAMP-Spalte ist nicht benannt; der Server */ /* stellt sie auf das aktuelle Datum und die Uhrzeit ein.) */ stmt = mysql_stmt_init(mysql); if (!stmt) { fprintf(stderr, " mysql_stmt_init(), out of memory\n"); exit(0); } if (mysql_stmt_prepare(stmt, INSERT_SAMPLE, strlen(INSERT_SAMPLE))) { fprintf(stderr, " mysql_stmt_prepare(), INSERT failed\n"); fprintf(stderr, " %s\n", mysql_stmt_error(stmt)); exit(0); } fprintf(stdout, " prepare, INSERT successful\n"); /* Hole die Zahl der Parameter aus der Anweisung */ param_count= mysql_stmt_param_count(stmt); fprintf(stdout, " total parameters in INSERT: %d\n", param_count); if (param_count != 3) /* Validiere Parameterzahl */ { fprintf(stderr, " invalid parameter count returned by MySQL\n"); exit(0); } /* Binde die Daten für alle 3 Parameter */ memset(bind, 0, sizeof(bind)); /* INTEGER PARAM */ /* Da dies ein Zahlentyp ist, muss buffer_length nicht angegeben werden */ bind[0].buffer_type= MYSQL_TYPE_LONG; bind[0].buffer= (char *)&int_data; bind[0].is_null= 0; bind[0].length= 0; /* STRING PARAM */ bind[1].buffer_type= MYSQL_TYPE_STRING; bind[1].buffer= (char *)str_data; bind[1].buffer_length= STRING_SIZE; bind[1].is_null= 0; bind[1].length= &str_length; /* SMALLINT PARAM */ bind[2].buffer_type= MYSQL_TYPE_SHORT; bind[2].buffer= (char *)&small_data; bind[2].is_null= &is_null; bind[2].length= 0; /* Binde die Puffer */ if (mysql_stmt_bind_param(stmt, bind)) { fprintf(stderr, " mysql_stmt_bind_param() failed\n"); fprintf(stderr, " %s\n", mysql_stmt_error(stmt)); exit(0); } /* Gib Datenwerte für die erste Zeile an */ int_data= 10; /* Integer */ strncpy(str_data, "MySQL", STRING_SIZE); /* String */ str_length= strlen(str_data); /* INSERT SMALLINT-Daten als NULL */ is_null= 1; /* Führe die INSERT-Anweisung aus - 1*/ if (mysql_stmt_execute(stmt)) { fprintf(stderr, " mysql_stmt_execute(), 1 failed\n"); fprintf(stderr, " %s\n", mysql_stmt_error(stmt)); exit(0); } /* Hole Gesamtzahl der betroffenen Zeilen */ affected_rows= mysql_stmt_affected_rows(stmt); fprintf(stdout, " total affected rows(insert 1): %lu\n", (unsigned long) affected_rows); if (affected_rows != 1) /* validiere betroffene Zeilen */ { fprintf(stderr, " invalid affected rows by MySQL\n"); exit(0); } /* Gib Datenwerte für zweite Zeile an und führe Anweisung erneut aus */ int_data= 1000; strncpy(str_data, "The most popular Open Source database", STRING_SIZE); str_length= strlen(str_data); small_data= 1000; /* smallint */ is_null= 0; /* Zurücksetzen */ /* Führe die INSERT-Anweisung aus - 2*/ if (mysql_stmt_execute(stmt)) { fprintf(stderr, " mysql_stmt_execute, 2 failed\n"); fprintf(stderr, " %s\n", mysql_stmt_error(stmt)); exit(0); } /* Hole Gesamtzahl der betroffenen Zeilen */ affected_rows= mysql_stmt_affected_rows(stmt); fprintf(stdout, " total affected rows(insert 2): %lu\n", (unsigned long) affected_rows); if (affected_rows != 1) /* validiere betroffene Zeilen */ { fprintf(stderr, " invalid affected rows by MySQL\n"); exit(0); } /* Schließe die Anweisung */ if (mysql_stmt_close(stmt)) { fprintf(stderr, " failed while closing the statement\n"); fprintf(stderr, " %s\n", mysql_stmt_error(stmt)); exit(0); }
Hinweis: Vollständigere
Beispiele für die Nutzung von Funktionen für vorbereitete
Anweisungen finden Sie in der Datei
tests/mysql_client_test.c
. Diese liegt in
der MySQL-Quelldistribution und im BitKeeper-Quellarchiv.
int mysql_stmt_fetch(MYSQL_STMT *stmt)
Beschreibung
Die Funktion mysql_stmt_fetch()
liefert die
nächste Zeile der Ergebnismenge und kann nur aufgerufen
werden, während die Ergebnismenge besteht, also nach einem
mysql_stmt_execute()
-Aufruf, der eine
Ergebnismenge produziert, oder nach einem
mysql_stmt_store_result()
-Aufruf, der im
Anschluss an mysql_stmt_execute()
die
gesamte Ergebnismenge puffert.
Die Funktion mysql_stmt_fetch()
liefert
Zeilendaten über alle Spalten der aktuellen Zeilenmenge an
die in mysql_stmt_bind_result()
gebundenen
Puffer. Die Längen werden an den
length
-Zeiger zurückgegeben.
Alle Spalten müssen von der Anwendung gebunden werden, ehe
mysql_stmt_fetch()
aufgerufen werden kann.
Ist ein abgerufener Datenwert NULL
, ist der
*is_null
-Wert der zugehörigen
MYSQL_BIND
-Struktur TRUE (1). Andernfalls
werden die Daten und ihre Länge in die Elemente
*buffer
und *length
zurückgegeben, und zwar basierend auf dem von der Anwendung
angegebenen Puffertyp. Jeder numerische und temporale Typ hat
eine festgelegte Länge, wie in der folgenden Tabelle
angegeben. Die Länge von String-Typen hängt von der Länge
des tatsächlichen Datenwerts ab, wie in
data_length
angegeben.
Typ | Länge |
MYSQL_TYPE_TINY | 1 |
MYSQL_TYPE_SHORT | 2 |
MYSQL_TYPE_LONG | 4 |
MYSQL_TYPE_LONGLONG | 8 |
MYSQL_TYPE_FLOAT | 4 |
MYSQL_TYPE_DOUBLE | 8 |
MYSQL_TYPE_TIME | sizeof(MYSQL_TIME) |
MYSQL_TYPE_DATE | sizeof(MYSQL_TIME) |
MYSQL_TYPE_DATETIME | sizeof(MYSQL_TIME) |
MYSQL_TYPE_STRING | data_length |
MYSQL_TYPE_BLOB | data_length |
Rückgabewerte
Rückgabewert | Beschreibung |
0 | Erfolg, die Daten wurden in die Anwendungsdatenpuffer geladen. |
1 | Fehler. Den Fehlercode und die Fehlermeldung erhalten Sie von
mysql_stmt_errno() und
mysql_stmt_error() . |
MYSQL_NO_DATA | Keine weiteren Zeilen/Daten vorhanden. |
MYSQL_DATA_TRUNCATED | Daten wurden abgeschnitten. |
MYSQL_DATA_TRUNCATED
-Meldungen werden nur
zurückgegeben, wenn dies mit
mysql_options()
eingestellt wurde. Um bei
einer Rückgabe dieses Werts festzustellen, welche Daten
abgeschnitten wurden, schauen Sie sich die
error
-Bestandteile der
MYSQL_BIND
-Parameterstrukturen an.
Fehler
CR_COMMANDS_OUT_OF_SYNC
Befehle wurden in der falschen Reihenfolge ausgeführt.
CR_OUT_OF_MEMORY
Speicherüberlauf.
CR_SERVER_GONE_ERROR
Der MySQL Server ist nicht mehr verfügbar.
CR_SERVER_LOST
Die Serververbindung brach während der Anfrage ab.
CR_UNKNOWN_ERROR
Ein unbekannter Fehler ist aufgetreten.
CR_UNSUPPORTED_PARAM_TYPE
Der Puffertyp ist MYSQL_TYPE_DATE
,
MYSQL_TYPE_TIME
,
MYSQL_TYPE_DATETIME
oder
MYSQL_TYPE_TIMESTAMP
, aber der Datentyp
ist nicht DATE
,
TIME
, DATETIME
oder
TIMESTAMP
.
Alle anderen Fehler wegen nicht unterstützter
Konvertierungen werden von
mysql_stmt_bind_result()
zurückgegeben.
Beispiel
Das folgende Beispiel zeigt, wie man Daten aus einer Tabelle
mit mysql_stmt_result_metadata()
,
mysql_stmt_bind_result()
und
mysql_stmt_fetch()
abholt. (Es wird
erwartet, dass mit diesem Beispiel die beiden Zeilen abgerufen
werden, die in Abschnitt 24.2.7.10, „mysql_stmt_execute()
“,
eingefügt wurden.) Die Variable mysql
sei
ein gültiger Verbindungs-Handle.
#define STRING_SIZE 50 #define SELECT_SAMPLE "SELECT col1, col2, col3, col4 FROM test_table" MYSQL_STMT *stmt; MYSQL_BIND bind[4]; MYSQL_RES *prepare_meta_result; MYSQL_TIME ts; unsigned long length[4]; int param_count, column_count, row_count; short small_data; int int_data; char str_data[STRING_SIZE]; my_bool is_null[4]; /* SELECT-Anfrage vorbereiten, um Daten aus test_table zu holen*/ stmt = mysql_stmt_init(mysql); if (!stmt) { fprintf(stderr, " mysql_stmt_init(), out of memory\n"); exit(0); } if (mysql_stmt_prepare(stmt, SELECT_SAMPLE, strlen(SELECT_SAMPLE))) { fprintf(stderr, " mysql_stmt_prepare(), SELECT failed\n"); fprintf(stderr, " %s\n", mysql_stmt_error(stmt)); exit(0); } fprintf(stdout, " prepare, SELECT successful\n"); /* Hole Zahl der Parameter aus der Anweisung */ param_count= mysql_stmt_param_count(stmt); fprintf(stdout, " total parameters in SELECT: %d\n", param_count); if (param_count != 0) /* validiere Zahl der Parameter */ { fprintf(stderr, " invalid parameter count returned by MySQL\n"); exit(0); } /* Hole Metainformationen zur Ergebnismenge */ prepare_meta_result = mysql_stmt_result_metadata(stmt); if (!prepare_meta_result) { fprintf(stderr, " mysql_stmt_result_metadata(), returned no meta information\n"); fprintf(stderr, " %s\n", mysql_stmt_error(stmt)); exit(0); } /* Hole Gesamtzahl der Spalten in der Anfrage */ column_count= mysql_num_fields(prepare_meta_result); fprintf(stdout, " total columns in SELECT statement: %d\n", column_count); if (column_count != 4) /* Validiere Spaltenzahl*/ { fprintf(stderr, " invalid column count returned by MySQL\n"); exit(0); } /* Führe die SELECT-Anfrage aus */ if (mysql_stmt_execute(stmt)) { fprintf(stderr, " mysql_stmt_execute(), failed\n"); fprintf(stderr, " %s\n", mysql_stmt_error(stmt)); exit(0); } /* Binde die Ergebnispuffer für alle 4 Spalten, bevor sie abgeholt werden */ memset(bind, 0, sizeof(bind)); /* INTEGER COLUMN */ bind[0].buffer_type= MYSQL_TYPE_LONG; bind[0].buffer= (char *)&int_data; bind[0].is_null= &is_null[0]; bind[0].length= &length[0]; /* STRING COLUMN */ bind[1].buffer_type= MYSQL_TYPE_STRING; bind[1].buffer= (char *)str_data; bind[1].buffer_length= STRING_SIZE; bind[1].is_null= &is_null[1]; bind[1].length= &length[1]; /* SMALLINT COLUMN */ bind[2].buffer_type= MYSQL_TYPE_SHORT; bind[2].buffer= (char *)&small_data; bind[2].is_null= &is_null[2]; bind[2].length= &length[2]; /* TIMESTAMP COLUMN */ bind[3].buffer_type= MYSQL_TYPE_TIMESTAMP; bind[3].buffer= (char *)&ts; bind[3].is_null= &is_null[3]; bind[3].length= &length[3]; /* Binde die Ergebnispuffer */ if (mysql_stmt_bind_result(stmt, bind)) { fprintf(stderr, " mysql_stmt_bind_result() failed\n"); fprintf(stderr, " %s\n", mysql_stmt_error(stmt)); exit(0); } /* Alle Ergebnisse auf dem Client zwischenspeichern */ if (mysql_stmt_store_result(stmt)) { fprintf(stderr, " mysql_stmt_store_result() failed\n"); fprintf(stderr, " %s\n", mysql_stmt_error(stmt)); exit(0); } /* Alle Zeilen abholen */ row_count= 0; fprintf(stdout, "Fetching results ...\n"); while (!mysql_stmt_fetch(stmt)) { row_count++; fprintf(stdout, " row %d\n", row_count); /* Spalte 1 */ fprintf(stdout, " column1 (integer) : "); if (is_null[0]) fprintf(stdout, " NULL\n"); else fprintf(stdout, " %d(%ld)\n", int_data, length[0]); /* Spalte 2 */ fprintf(stdout, " column2 (string) : "); if (is_null[1]) fprintf(stdout, " NULL\n"); else fprintf(stdout, " %s(%ld)\n", str_data, length[1]); /* Spalte 3 */ fprintf(stdout, " column3 (smallint) : "); if (is_null[2]) fprintf(stdout, " NULL\n"); else fprintf(stdout, " %d(%ld)\n", small_data, length[2]); /* Spalte 4 */ fprintf(stdout, " column4 (timestamp): "); if (is_null[3]) fprintf(stdout, " NULL\n"); else fprintf(stdout, " %04d-%02d-%02d %02d:%02d:%02d (%ld)\n", ts.year, ts.month, ts.day, ts.hour, ts.minute, ts.second, length[3]); fprintf(stdout, "\n"); } /* Abgeholte Zeilen validieren */ fprintf(stdout, " total rows fetched: %d\n", row_count); if (row_count != 2) { fprintf(stderr, " MySQL failed to return all rows\n"); exit(0); } /* Vorbereitete Ergebnismetadaten freigeben */ mysql_free_result(prepare_meta_result); /* Anweisung schließen */ if (mysql_stmt_close(stmt)) { fprintf(stderr, " failed while closing the statement\n"); fprintf(stderr, " %s\n", mysql_stmt_error(stmt)); exit(0); }
int mysql_stmt_fetch_column(MYSQL_STMT *stmt,
MYSQL_BIND *bind, unsigned int column, unsigned long
offset)
Beschreibung
Holt eine Spalte aus der aktuellen Zeile der Ergebnismenge.
bind
sagt, in welchen Puffer die Daten
geschrieben werden sollen. Dieser sollte wie für
mysql_stmt_bind_result()
eingestellt sein.
column
gibt an, welche Spalte abgefragt
wird. Die erste Spalte hat die Nummer 0.
offset
ist der Offset im Datenwert, wo der
Datenabruf beginnen soll. Dieser kann genutzt werden, um die
Daten stückweise abzuholen. Der Anfang des Werts hat den
Offset 0.
Rückgabewerte
Null, wenn der Wert erfolgreich abgeholt wurde. Ein von null verschiedener Wert, wenn ein Fehler auftrat.
Fehler
CR_INVALID_PARAMETER_NO
Ungültige Spaltennummer.
CR_NO_DATA
Das Ende der Ergebnismenge wurde schon erreicht.
unsigned int mysql_stmt_field_count(MYSQL_STMT
*stmt)
Beschreibung
Liefert die Anzahl der Spalten für die letzte Anweisung des
Anweisungs-Handlers. Dieser Wert ist für Anweisungen wie
INSERT
oder DELETE
, die
keine Ergebnismengen produzieren, null.
mysql_stmt_field_count()
kann nach der
Vorbereitung einer Anweisung mit
mysql_stmt_prepare()
aufgerufen werden.
Rückgabewerte
Ein vorzeichenloser Integer, der die Anzahl der Spalten in einer Ergebnismenge angibt.
Fehler
Keine.
my_bool mysql_stmt_free_result(MYSQL_STMT
*stmt)
Beschreibung
Gibt den Speicher für die Ergebnismenge frei, die von der
Ausführung der vorbereiteten Anweisung erstellt wurde. Wenn
noch ein Cursor für die Anweisung geöffnet ist, wird er von
mysql_stmt_free_result()
geschlossen.
Rückgabewerte
Null, wenn die Ergebnismenge erfolgreich freigegeben wurde, und ein von null verschiedener Wert, wenn ein Fehler auftrat.
Fehler
(nicht verfügbar)
MYSQL_STMT *mysql_stmt_init(MYSQL *mysql)
Beschreibung
Erzeugt einen MYSQL_STMT
-Handle. Der Handle
sollte mit mysql_stmt_close(MYSQL_STMT *)
wieder freigegeben werden.
Rückgabewerte
Bei Erfolg ein Zeiger auf eine
MYSQL_STMT
-Struktur. Bei einem
Speicherüberlauf NULL
.
Fehler
CR_OUT_OF_MEMORY
Speicherüberlauf.
my_ulonglong mysql_stmt_insert_id(MYSQL_STMT
*stmt)
Beschreibung
Gibt den Wert zurück, der für eine
AUTO_INCREMENT
-Spalte von der vorbereiteten
INSERT
- oder
UPDATE
-Anweisung generiert wurde. Diese
Funktion verwenden Sie nach Ausführung einer vorbereiteten
INSERT
-Anweisung auf einer Tabelle, die ein
AUTO_INCREMENT
-Feld enthält.
Siehe auch Abschnitt 24.2.3.36, „mysql_insert_id()
“.
Rückgabewerte
Der Wert der AUTO_INCREMENT
-Spalte, der
automatisch generiert oder während der Ausführung einer
vorbereiteten Anweisung explizit gesetzt wurde, oder der Wert,
der von der Funktion
LAST_INSERT_ID(
generiert wurde. Wenn die Anweisung keinen
expr
)AUTO_INCREMENT
-Wert setzt, ist der
Rückgabewert undefiniert.
Fehler
Keine.
my_ulonglong mysql_stmt_num_rows(MYSQL_STMT
*stmt)
Beschreibung
Liefert die Anzahl der Zeilen in der Ergebnismenge.
mysql_stmt_num_rows()
können Sie nur
benutzen, wenn Sie die gesamte Ergebnismenge im
Anweisungs-Handle mit
mysql_stmt_store_result()
gepuffert haben.
Wenn Sie mysql_stmt_store_result()
verwenden, können Sie
mysql_stmt_num_rows()
sofort aufrufen.
Rückgabewerte
Die Anzahl der Zeilen in der Ergebnismenge.
Fehler
Keine.
unsigned long mysql_stmt_param_count(MYSQL_STMT
*stmt)
Beschreibung
Liefert die Anzahl der Parametermarker in der vorbereiteten Anweisung.
Rückgabewerte
Ein vorzeichenloser Long-Integer, der die Anzahl der Parameter in einer Anweisung darstellt.
Fehler
Keine.
Beispiel
Wie man mysql_stmt_param_count()
einsetzt,
sehen Sie im Beispiel zu Abschnitt 24.2.7.10, „mysql_stmt_execute()
“.
MYSQL_RES *mysql_stmt_param_metadata(MYSQL_STMT
*stmt)
Diese Funktion tut zurzeit gar nichts.
Beschreibung
Rückgabewerte
Fehler
int mysql_stmt_prepare(MYSQL_STMT *stmt, const char
*query, unsigned long length)
Beschreibung
Wenn man ihr den von mysql_stmt_init()
gelieferten Anweisungs-Handle übergibt, bereitet diese
Funktion die SQL-Anweisung vor, auf die der String
query
verweist, und liefert einen
Statuswert. Die Länge des Strings sollte im
length
-Argument angegeben werden. Der
String muss aus einer einzigen SQL-Anweisung bestehen. Bitte
fügen Sie am Ende der Anweisung kein Semikolon
(‘;
’) oder
\g
an.
Die Anwendung kann einen oder mehrere Parametermarker in die
SQL-Anweisung einbinden, indem sie die Fragezeichen
(‘?
’) an den passenden Stellen
in den SQL-String einbettet.
Die Marker sind nur an bestimmten Stellen in den
SQL-Anweisungen erlaubt, beispielsweise in der
VALUES()
-Liste einer
INSERT
Anweisung (um Spaltenwerte für eine
Zeile vorzugeben) oder um einen Vergleichswert zum Vergleich
mit einer Spalte einer WHERE
-Klausel
anzugeben. Sie dürfen jedoch nicht für Bezeichner (wie etwa
Tabellen- oder Spaltennamen) oder für die Operanden eines
Binäroperators wie etwa des Gleichheitszeichens
=
benutzt werden. Die zweite Beschränkung
ist notwendig, weil es ansonsten unmöglich wäre, den
Parametertyp festzustellen. Generell sind Parameter nur in
Data Manipulation Language(DML)-Anweisungen und nicht in Data
Definition Language(DDL)-Anweisungen zulässig.
Die Parametermarker müssen mit
mysql_stmt_bind_param()
an die
Anwendungsvariablen gebunden werden, bevor die Anweisung
ausgeführt wird.
Rückgabewerte
Null, wenn die Anweisung erfolgreich vorbereitet wurde, und ein von null verschiedener Wert, wenn ein Fehler auftrat.
Fehler
CR_COMMANDS_OUT_OF_SYNC
Befehle wurden in der falschen Reihenfolge ausgeführt.
CR_OUT_OF_MEMORY
Speicherüberlauf.
CR_SERVER_GONE_ERROR
Der MySQL Server ist nicht mehr verfügbar.
CR_SERVER_LOST
Die Serververbindung brach während der Anfrage ab.
CR_UNKNOWN_ERROR
Ein unbekannter Fehler ist aufgetreten.
Wenn die Vorbereitung gescheitert ist (d. h., wenn
mysql_stmt_prepare()
nicht null
zurückliefert), können Sie die Fehlermeldung mit
mysql_stmt_error()
abrufen.
Beispiel
Wie mysql_stmt_prepare()
eingesetzt wird,
erfahren Sie im Beispiel von
Abschnitt 24.2.7.10, „mysql_stmt_execute()
“.
my_bool mysql_stmt_reset(MYSQL_STMT *stmt)
Beschreibung
Setzt die vorbereitete Anweisung auf dem Client und Server in
den Zustand zurück, den sie nach der Vorbereitung hatte. Wird
vor allen Dingen genutzt, um die mit
mysql_stmt_send_long_data()
übersandten
Daten zurückzusetzen und eventuell noch offene
Anweisungs-Cursors zu schließen.
Um die Anweisung mit einer anderen Anfrage erneut
vorzubereiten, rufen Sie
mysql_stmt_prepare()
auf.
Rückgabewerte
Null, wenn die Anweisung erfolgreich zurückgesetzt wurde, und ein von null verschiedener Wert, wenn ein Fehler auftrat.
Fehler
CR_COMMANDS_OUT_OF_SYNC
Befehle wurden in der falschen Reihenfolge ausgeführt.
CR_SERVER_GONE_ERROR
Der MySQL Server ist nicht mehr verfügbar.
CR_SERVER_LOST
Die Serververbindung brach während der Anfrage ab.
CR_UNKNOWN_ERROR
Ein unbekannter Fehler ist aufgetreten.
MYSQL_RES *mysql_stmt_result_metadata(MYSQL_STMT
*stmt)
Beschreibung
Wenn an mysql_stmt_prepare()
eine Anweisung
übergeben wird, die eine Ergebnismenge produziert, liefert
mysql_stmt_result_metadata()
die Metadaten
zu dieser Ergebnismenge in Form eines Zeigers auf eine
MYSQL_RES
-Struktur, die genutzt werden
kann, um solche Daten wie etwa die Gesamtzahl der Felder und
Informationen über einzelne Felder zu verarbeiten. Dieser
Ergebnismengenzeiger kann als Argument an API-Feldfunktionen
übergeben werden, die Metadaten von Ergebnismengen
verarbeiten, wie zum Beispiel:
mysql_num_fields()
mysql_fetch_field()
mysql_fetch_field_direct()
mysql_fetch_fields()
mysql_field_count()
mysql_field_seek()
mysql_field_tell()
mysql_free_result()
Die Ergebnismengenstruktur sollte nach Abschluss der
Verarbeitung freigegeben werden, indem man sie an
mysql_free_result()
übergibt. Auf dieselbe
Weise wird eine Ergebnismenge aus einem
mysql_store_result()
-Aufruf freigegeben.
Die von mysql_stmt_result_metadata()
zurückgegebene Ergebnismenge enthält nur Metadaten und keine
Ergebniszeilen. Diese rufen Sie ab, indem Sie den
Anweisungs-Handle in Verbindung mit
mysql_stmt_fetch()
benutzen.
Rückgabewerte
Eine MYSQL_RES
-Ergebnisstruktur oder
NULL
, wenn keine Metainformationen über
die vorbereitete Anfrage existieren.
Fehler
CR_OUT_OF_MEMORY
Speicherüberlauf.
CR_UNKNOWN_ERROR
Ein unbekannter Fehler ist aufgetreten.
Beispiel
Die Benutzung von
mysql_stmt_result_metadata()
wird aus dem
Beispiel von Abschnitt 24.2.7.11, „mysql_stmt_fetch()
“, ersichtlich.
MYSQL_ROW_OFFSET mysql_stmt_row_seek(MYSQL_STMT
*stmt, MYSQL_ROW_OFFSET offset)
Beschreibung
Setzt den Zeilen-Cursor auf eine beliebige Zeile in der
Ergebnismenge einer Anweisung. Der
offset
-Wert ist ein Zeilen-Offset. Dieser
sollte ein Rückgabewert von
mysql_stmt_row_tell()
oder von
mysql_stmt_row_seek()
sein. Er ist keine
Zeilennummer; wenn Sie in einer Ergebnismenge eine Zeile
anhand ihrer Nummer ausfindig machen möchten, verwenden Sie
stattdessen mysql_stmt_data_seek()
.
Da für diese Funktion erforderlich ist, dass die
Ergebnismengenstruktur die gesamte Ergebnismenge der Anfrage
enthält, kann mysql_stmt_row_seek()
nur in
Verbindung mit mysql_stmt_store_result()
benutzt werden.
Rückgabewerte
Der vorherige Wert des Zeilen-Cursors. Dieser Wert kann an
einen nachfolgenden
mysql_stmt_row_seek()
-Aufruf übergeben
werden.
Fehler
Keine.
MYSQL_ROW_OFFSET mysql_stmt_row_tell(MYSQL_STMT
*stmt)
Beschreibung
Gibt die aktuelle Position des Zeilen-Cursors für die letzte
mysql_stmt_fetch()
-Operation zurück.
Dieser Wert kann als Argument für
mysql_stmt_row_seek()
verwendet werden.
mysql_stmt_row_tell()
sollte nur nach
mysql_stmt_store_result()
benutzt werden.
Rückgabewerte
Der aktuelle Offset des Zeilen-Cursors.
Fehler
Keine.
my_bool mysql_stmt_send_long_data(MYSQL_STMT *stmt,
unsigned int parameter_number, const char *data, unsigned long
length)
Beschreibung
Ermöglicht es einer Anwendung, Parameterdaten in Stücken
(oder „Chunks“) an den Server zu schicken. Diese
Funktion kann mehrmals aufgerufen werden, um die Teile eines
Zeichen- oder Binärdatenwerts für eine Spalte zu übergeben.
Die Werte müssen den Datentyp TEXT
oder
BLOB
haben.
parameter_number
gibt an, mit welchem
Parameter die Daten verbunden werden sollen. Die Parameter
werden beginnend mit 0 nummeriert. data
ist
ein Zeiger auf einen Puffer, der die zu übermittelnden Daten
enthält, und length
ist die Anzahl der
Bytes im Puffer.
Hinweis: Der nächste Aufruf
von mysql_stmt_execute()
ignoriert den
Bind-Puffer für alle Parameter, die seit dem letzten
mysql_stmt_execute()
oder
mysql_stmt_reset()
mit
mysql_stmt_send_long_data()
benutzt worden
sind.
Wenn Sie die gesendeten Daten zurücksetzen/vergessen
möchten, tun Sie dies mit
mysql_stmt_reset()
. Siehe
Abschnitt 24.2.7.21, „mysql_stmt_reset()
“.
Rückgabewerte
Null, wenn die Daten erfolgreich an den Server gesandt wurden. Ein von null verschiedener Wert, wenn ein Fehler auftrat.
Fehler
CR_COMMANDS_OUT_OF_SYNC
Befehle wurden in der falschen Reihenfolge ausgeführt.
CR_SERVER_GONE_ERROR
Der MySQL Server ist nicht mehr verfügbar.
CR_OUT_OF_MEMORY
Speicherüberlauf.
CR_UNKNOWN_ERROR
Ein unbekannter Fehler ist aufgetreten.
Beispiel
Das folgende Beispiel zeigt, wie die Daten für eine
TEXT
-Spalte stückchenweise übermittelt
werden. Es fügt den Datenwert 'MySQL - The most
popular Open Source database'
in die Spalte
text_column
ein. Die Variable
mysql
sei ein gültiger Verbindungs-Handle.
#define INSERT_QUERY "INSERT INTO test_long_data(text_column) VALUES(?)" MYSQL_BIND bind[1]; long length; smtt = mysql_stmt_init(mysql); if (!stmt) { fprintf(stderr, " mysql_stmt_init(), out of memory\n"); exit(0); } if (mysql_stmt_prepare(stmt, INSERT_QUERY, strlen(INSERT_QUERY))) { fprintf(stderr, "\n mysql_stmt_prepare(), INSERT failed"); fprintf(stderr, "\n %s", mysql_stmt_error(stmt)); exit(0); } memset(bind, 0, sizeof(bind)); bind[0].buffer_type= MYSQL_TYPE_STRING; bind[0].length= &length; bind[0].is_null= 0; /* Binde die Puffer */ if (mysql_stmt_bind_param(stmt, bind)) { fprintf(stderr, "\n param bind failed"); fprintf(stderr, "\n %s", mysql_stmt_error(stmt)); exit(0); } /* Liefere Daten stückweise an den Server */ if (!mysql_stmt_send_long_data(stmt,0,"MySQL",5)) { fprintf(stderr, "\n send_long_data failed"); fprintf(stderr, "\n %s", mysql_stmt_error(stmt)); exit(0); } /* Sende das nächste Datenstück */ if (mysql_stmt_send_long_data(stmt,0," - The most popular Open Source database",40)) { fprintf(stderr, "\n send_long_data failed"); fprintf(stderr, "\n %s", mysql_stmt_error(stmt)); exit(0); } /* Führe nun die Anfrage aus */ if (mysql_stmt_execute(stmt)) { fprintf(stderr, "\n mysql_stmt_execute failed"); fprintf(stderr, "\n %s", mysql_stmt_error(stmt)); exit(0); }
const char *mysql_stmt_sqlstate(MYSQL_STMT
*stmt)
Beschreibung
Für die Anweisung stmt
liefert
mysql_stmt_sqlstate()
einen auf null
endenden String mit dem SQLSTATE-Fehlercode für die zuletzt
aufgerufene Funktion der API für vorbereitete Anweisungen,
die Erfolg haben oder scheitern kann. Der Fehlercode besteht
aus fünf Zeichen. "00000"
bedeutet
„kein Fehler“. Die Werte sind durch ANSI-SQL und
ODBC vorgegeben. Eine Liste der möglichen Werte finden Sie
unter Anhang B, Fehlercodes und -meldungen.
Beachten Sie, dass noch nicht alle MySQL-Fehler SQLSTATE-Codes
zugeordnet sind. Für Fehler, die sich nicht zuordnen lassen,
wird der Wert "HY000"
(allgemeiner Fehler)
verwendet.
Rückgabewerte
Ein auf null endender Zeichen-String, der den SQLSTATE-Fehlercode enthält.
int mysql_stmt_store_result(MYSQL_STMT
*stmt)
Beschreibung
Sie können mysql_stmt_store_result()
für
jede Anweisung aufrufen, die eine Ergebnismenge erstellt
(SELECT
, SHOW
,
DESCRIBE
, EXPLAIN
),
sofern Sie die gesamte Ergebnismenge im Client puffern wollen,
damit der nachfolgende
mysql_stmt_fetch()
-Aufruf die gepufferten
Daten zurückgibt.
Es ist zwar nicht nötig,
mysql_stmt_store_result()
für andere
Anweisungen aufzurufen, aber es schadet auch nichts und hat
keine spürbaren Leistungseinbußen zur Folge. Ob die
Anweisung eine Ergebnismenge erzeugt hat, können Sie
ermitteln, indem Sie nachschauen, ob
mysql_stmt_result_metadata()
den Wert
NULL
zurückgibt. Weitere Informationen
gibt es unter Abschnitt 24.2.7.22, „mysql_stmt_result_metadata()
“.
Hinweis: MySQL berechnet nach
Voreinstellung nicht die
MYSQL_FIELD->max_length
für alle
Spalten in mysql_stmt_store_result()
, da
dieser Rechenaufwand
mysql_stmt_store_result()
deutlich
verlangsamen würde und die meisten Anwendungen auf
max_length
gut verzichten können. Wenn Sie
max_length
aktualisieren möchten, können
Sie dies mit mysql_stmt_attr_set(MYSQL_STMT,
STMT_ATTR_UPDATE_MAX_LENGTH, &flag)
ermöglichen. Siehe Abschnitt 24.2.7.3, „mysql_stmt_attr_set()
“.
Rückgabewerte
Null, wenn die Ergebnisse erfolgreich gepuffert wurden, und ein von null verschiedener Wert, wenn ein Fehler auftrat.
Fehler
CR_COMMANDS_OUT_OF_SYNC
Befehle wurden in der falschen Reihenfolge ausgeführt.
CR_OUT_OF_MEMORY
Speicherüberlauf.
CR_SERVER_GONE_ERROR
Der MySQL Server ist nicht mehr verfügbar.
CR_SERVER_LOST
Die Serververbindung brach während der Anfrage ab.
CR_UNKNOWN_ERROR
Ein unbekannter Fehler ist aufgetreten.
Im Folgenden werden einige bekannte Probleme mit vorbereiteten Anweisungen angesprochen:
TIME
, TIMESTAMP
und
DATETIME
unterstützen keine
Sekundenbruchteile (beispielsweise von
DATE_FORMAT()
.
Beim Konvertieren eines Integers in einen String wird
ZEROFILL
in vorbereiteten Anweisungen in
manchen Fällen umgesetzt, ohne dass der MySQL Server die
vorangestellten Nullen ausgibt (beispielsweise bei
MIN(number-with-zerofill)
).
Wird im Client eine Fließkommazahl in einen String konvertiert, können die rechten Ziffern des konvertierten Werts leicht vom Originalwert abweichen.
Vorbereitete Anweisungen verwenden nicht den Query Cache, auch dann nicht, wenn eine Anfrage keine Platzhalter enthält. Siehe Abschnitt 5.14.1, „Wie der Anfragen-Cache funktioniert“.
MySQL 5.1 unterstützt die Ausführung von
Mehrfachanweisungen, die in einem einzigen Anfrage-String
angegeben werden. Um diese Fähigkeit auf einer gegebenen
Verbindung nutzen zu können, müssen Sie die Option
CLIENT_MULTI_STATEMENTS
im Parameter
flags
der Funktion
mysql_real_connect()
angeben, wenn Sie die
Verbindung öffnen. Sie können dies jedoch mit
mysql_set_server_option(MYSQL_OPTION_MULTI_STATEMENTS_ON)
auch für eine laufende Verbindung tun.
Nach Voreinstellung geben mysql_query()
und
mysql_real_query()
nur den ersten
Anfragestatus zurück; der Status der nachfolgenden Anfragen
kann mit mysql_more_results()
und
mysql_next_result()
verarbeitet werden.
/* Richte Serververbindung mit der Option CLIENT_MULTI_STATEMENTS ein */ mysql_real_connect(..., CLIENT_MULTI_STATEMENTS); /* Führe mehrere Anfragen aus */ mysql_query(mysql,"DROP TABLE IF EXISTS test_table;\ CREATE TABLE test_table(id INT);\ INSERT INTO test_table VALUES(10);\ UPDATE test_table SET id=20 WHERE id=10;\ SELECT * FROM test_table;\ DROP TABLE test_table"); do { /* Verarbeite alle Ergebnisse */ ... printf("total affected rows: %lld", mysql_affected_rows(mysql)); ... if (!(result= mysql_store_result(mysql))) { printf(stderr, "Got fatal error processing query\n"); exit(1); } process_result_set(result); /* Clientfunktion */ mysql_free_result(result); } while (!mysql_next_result(mysql));
Die Fähigkeit zu Mehrfachanweisungen kann mit
mysql_query()
oder
mysql_real_query()
genutzt werden, aber nicht
mit der Schnittstelle für vorbereitete Anweisungen. Handles
für vorbereitete Anweisungen sind so definiert, dass sie nur
mit Strings funktionieren, die lediglich eine einzelne Anweisung
enthalten.
Das Binärprotokoll ermöglicht das Senden und Empfangen von
Datums- und Uhrzeitwerten (DATE
,
TIME
, DATETIME
und
TIMESTAMP
) mithilfe der
MYSQL_TIME
-Struktur. Die Bestandteile dieser
Struktur werden in
Abschnitt 24.2.5, „C-API: Prepared Statement-Datentypen“,
beschrieben.
Um temporale Datenwerte zu senden, legen Sie eine vorbereitete
Anweisung mit mysql_stmt_prepare()
an und
richten die Temporalparameter, bevor Sie die Anweisung mit
mysql_stmt_execute()
ausführen,
folgendermaßen ein:
In der MYSQL_BIND
-Struktur, die mit dem
Datenwert verbunden ist, stellen Sie den
buffer_type
-Teil auf den Typ, der die Art
des zu sendenden Temporalwerts angibt. Für
DATE
-, TIME
-,
DATETIME
- oder
TIMESTAMP
-Werte setzen Sie
buffer_type
auf
MYSQL_TYPE_DATE
,
MYSQL_TYPE_TIME
,
MYSQL_TYPE_DATETIME
oder
MYSQL_TYPE_TIMESTAMP
.
Stellen Sie den buffer
-Teil der
MYSQL_BIND
-Struktur auf die Adresse der
MYSQL_TIME
-Struktur ein, in die Sie den
Temporalwert übergeben.
Füllen Sie die Bestandteile der
MYSQL_TIME
-Struktur aus, die sich für
den Typ des zu übergebenden Temporalwerts eignen.
Binden Sie mit mysql_stmt_bind_param()
die
Parameterdaten an die Anweisung. Dann können Sie
mysql_stmt_execute()
aufrufen.
Abgerufen werden die Temporalwerte ganz ähnlich, nur dass Sie
beim Abruf den buffer_type
-Teil auf den Typ
des Werts einstellen, den Sie empfangen wollen, und den
buffer
-Teil auf die Adresse einer
MYSQL_TIME
-Struktur, in die der Rückgabewert
eingesetzt werden soll. Mit
mysql_bind_results()
binden Sie die Puffer an
die Anweisung, nachdem Sie
mysql_stmt_execute()
aufgerufen haben und
bevor Sie die Ergebnisse abholen.
Das folgende einfache Beispiel fügt DATE
-,
TIME
- und TIMESTAMP
-Daten
ein. Die mysql
-Variable sei ein gültiger
Verbindungs-Handle.
MYSQL_TIME ts; MYSQL_BIND bind[3]; MYSQL_STMT *stmt; strmov(query, "INSERT INTO test_table(date_field, time_field, timestamp_field) VALUES(?,?,?"); stmt = mysql_stmt_init(mysql); if (!stmt) { fprintf(stderr, " mysql_stmt_init(), out of memory\n"); exit(0); } if (mysql_stmt_prepare(mysql, query, strlen(query))) { fprintf(stderr, "\n mysql_stmt_prepare(), INSERT failed"); fprintf(stderr, "\n %s", mysql_stmt_error(stmt)); exit(0); } /* Richte Eingabepuffer für alle 3 Parameter ein */ bind[0].buffer_type= MYSQL_TYPE_DATE; bind[0].buffer= (char *)&ts; bind[0].is_null= 0; bind[0].length= 0; ... bind[1]= bind[2]= bind[0]; ... mysql_stmt_bind_param(stmt, bind); /* Liefere die Daten für die ts-Struktur*/ ts.year= 2002; ts.month= 02; ts.day= 03; ts.hour= 10; ts.minute= 45; ts.second= 20; mysql_stmt_execute(stmt); ..
Wenn Sie einen Threaded Client erstellen möchten, verwenden Sie folgende Funktionen. Siehe Abschnitt 24.2.15, „Wie man einen Thread-Client herstellt“.
void my_init(void)
Beschreibung
Diese Funktion muss einmalig vor dem Aufruf jeder anderen
MySQL-Funktion in einem Programm aufgerufen werden. Sie
initialisiert einige globale Variablen, die MySQL benötigt.
Wenn Sie eine Thread-sichere Clientbibliothek benutzen, wird
auch für diesen Thread mysql_thread_init()
aufgerufen.
Diese Funktion wird automatisch von
mysql_init()
,
mysql_library_init()
,
mysql_server_init()
und
mysql_connect()
aufgerufen.
Rückgabewerte
Keine.
my_bool mysql_thread_init(void)
Beschreibung
Diese Funktion muss für jeden erzeugten Thread aufgerufen werden, um Thread-spezifische Variablen zu initialisieren.
Die Funktion wird automatisch von my_init()
und mysql_connect()
aufgerufen.
Rückgabewerte
Null bei Erfolg und ein von null verschiedener Wert bei einem Fehler.
void mysql_thread_end(void)
Beschreibung
Diese Funktion muss vor pthread_exit()
benutzt werden, um den von
mysql_thread_init()
zugewiesenen Speicher
wieder freizugeben.
Beachten Sie, dass diese Funktion nicht automatisch von der Clientbibliothek aufgerufen wird. Sie muss explizit aufgerufen werden, um ein Speicherleck zu verhindern.
Rückgabewerte
Keine.
Wenn Sie es Ihrer Anwendung ermöglichen wollen, mit der MySQL
Embedded Server-Bibliothek verknüpft zu werden, müssen Sie die
Funktionen mysql_server_init()
und
mysql_server_end()
benutzen. Siehe
Abschnitt 24.1, „libmysqld, die eingebettete MySQL Server-Bibliothek“.
Für eine bessere Speicherverwaltung sollten allerdings auch
Programme, die mit -lmysqlclient
statt
-lmysqld
verknüpft sind, Aufrufe enthalten, um
die Benutzung der Bibliothek zu beginnen und zu beenden. Hierzu
dienen die Funktionen mysql_library_init()
und mysql_library_end()
. Diese sind in
Wirklichkeit #define
-Symbole und somit
äquivalent zu mysql_server_init()
und
mysql_server_end()
, aber die anderen Namen
betonen stärker, dass diese Funktionen immer vor und nach der
Benutzung einer MySQL-C-API-Bibliothek aufgerufen werden
müssen, egal ob die Anwendung libmysqlclient
oder libmysqld
verwendet. Weitere
Informationen finden Sie unter
Abschnitt 24.2.2, „C-API: Funktionsüberblick“.
int mysql_server_init(int argc, char **argv, char
**groups)
Beschreibung
Diese Funktion muss in einem
Programm, das den Embedded Server benutzt, einmalig vor jeder
anderen MySQL-Funktion aufgerufen werden. Sie startet den
Server und initialisiert eventuelle Subsysteme
(mysys
, InnoDB
und so
weiter), die der Server benötigt. Wird diese Funktion nicht
aufgerufen, führt der nächste
mysql_init()
-Aufruf
mysql_server_init()
aus. Wenn Sie das mit
MySQL gelieferte DBUG-Paket benutzen, sollten Sie die Funktion
nach my_init()
aufrufen.
Die Argumente argc
und
argv
entsprechen den Argumenten von
main()
. Das erste Element von
argv
wird ignoriert (es enthält
typischerweise den Namen des Programms). Der Bequemlichkeit
halber kann argc
den Wert
0
(null) haben, wenn keine
Kommandozeilenargumente für den Server vorhanden sind. Da
mysql_server_init()
die Argumente kopiert,
kann argv
oder groups
nach dem Aufruf getrost zerstört werden.
Wenn Sie sich mit einem externen Server verbinden möchten,
ohne den Embedded Server zu starten, müssen Sie einen
negativen Wert für argc
angeben.
Die mit NULL
endende Liste der Strings in
groups
wählt die Gruppen aus den
Optionsdateien aus, die aktiv sein sollen. Siehe
Abschnitt 4.3.2, „my.cnf-Optionsdateien“. Der Bequemlichkeit halber kann
groups
den Wert NULL
haben. In diesem Fall sind die Gruppen
[server]
und [embedded]
aktiv.
Beispiel
#include <mysql.h> #include <stdlib.h> static char *server_args[] = { "this_program", /* Dieser String wird nicht benutzt */ "--datadir=.", "--key_buffer_size=32M" }; static char *server_groups[] = { "embedded", "server", "this_program_SERVER", (char *)NULL }; int main(void) { if (mysql_server_init(sizeof(server_args) / sizeof(char *), server_args, server_groups)) exit(1); /* Hier werden MySQL-API-Funktionen benutzt */ mysql_server_end(); return EXIT_SUCCESS; }
Rückgabewerte
0, wenn alles okay ist, 1, wenn ein Fehler auftrat.
mysql_store_result()
manchmal
NULL
zurück, nachdem
mysql_query()
Erfolg zurückgegeben hat?
Es ist möglich, dass mysql_store_result()
nach einem erfolgreichen Aufruf von
mysql_query()
den Wert
NULL
zurückgibt. Wenn dies geschieht, so
bedeutet es, dass eine der folgenden Bedingungen eingetreten
ist:
Es gab einen Fehler in malloc()
(beispielsweise, wenn die Ergebnismenge zu groß war).
Die Daten konnten nicht gelesen werden (ein Verbindungsfehler).
Die Anfrage hat keine Daten geliefert (beispielsweise wenn
sie ein INSERT
,
UPDATE
oder DELETE
war).
Sie können immer mit mysql_field_count()
prüfen, ob die Anweisung eine nichtleere Ergebnismenge hätte
produzieren sollen. Wenn
mysql_field_count()
null liefert, ist das
Ergebnis leer und es handelte sich um eine Anweisung, die
keine Werte zurückgibt (beispielsweise ein
INSERT
oder DELETE
).
Wenn mysql_field_count()
einen von null
verschiedenen Wert liefert, hätte die Anweisung eigentlich
ein nichtleeres Ergebnis zurückgeben müssen. Ein Beispiel
finden Sie in der Beschreibung der
mysql_field_count()
-Funktion.
Ob ein Fehler auftrat, verrät Ihnen
mysql_error()
oder
mysql_errno()
.
Zusätzlich zu der Frage, ob eine Anfrage eine Ergebnismenge zurückgibt, können Sie auch die folgenden Informationen herausfinden:
mysql_affected_rows()
liefert die
Anzahl der von der letzten Anfrage betroffenen Zeilen,
wenn die Anfrage ein INSERT
,
UPDATE
oder DELETE
war.
Für eine schnelle Rekonstruktion verwenden Sie
TRUNCATE TABLE
.
mysql_num_rows()
liefert die Anzahl der
Zeilen in einer Ergebnismenge. Bei
mysql_store_result()
kann
mysql_num_rows()
aufgerufen werden,
sobald mysql_store_result()
zurückkehrt. Bei mysql_use_result()
kann mysql_num_rows()
erst aufgerufen
werden, nachdem alle Zeilen mit
mysql_fetch_row()
abgeholt worden sind.
mysql_insert_id()
liefert die ID,
welche die letzte Anfrage, die eine Zeile in eine Tabelle
mit einem AUTO_INCREMENT
-Index
eingefügt hat, generierte. Siehe
Abschnitt 24.2.3.36, „mysql_insert_id()
“.
Manche Anfragen (LOAD DATA INFILE ...
,
INSERT INTO ... SELECT ...
,
UPDATE
) geben weitere Informationen
zurück. Das Ergebnis erhalten Sie von
mysql_info()
. In der Beschreibung zu
mysql_info()
erfahren Sie, welches
String-Format diese Funktion liefert.
mysql_info()
gibt einen
NULL
-Zeiger zurück, wenn keine
weiteren Informationen mehr vorliegen.
Wenn Sie einen Datensatz in eine Tabelle mit einer
AUTO_INCREMENT
-Spalte einfügen, können
Sie den in dieser Spalte gespeicherten Wert mit der Funktion
mysql_insert_id()
erhalten.
In Ihren C-Anwendungen können Sie überprüfen, ob ein Wert
in einer UTO_INCREMENT
-Spalte gespeichert
wurde. Hierzu führen Sie folgenden Code aus (der voraussetzt,
dass Sie sich vom Erfolg der Anweisung überzeugt haben). Der
Code ermittelt, ob die Anfrage ein INSERT
mit einem AUTO_INCREMENT
-Index war:
if ((result = mysql_store_result(&mysql)) == 0 && mysql_field_count(&mysql) == 0 && mysql_insert_id(&mysql) != 0) { used_id = mysql_insert_id(&mysql); }
Weitere Informationen finden Sie unter
Abschnitt 24.2.3.36, „mysql_insert_id()
“.
Wurde ein neuer AUTO_INCREMENT
-Wert
generiert, so können Sie diesen auch erhalten, indem Sie die
SELECT LAST_INSERT_ID()
-Anweisung mit
mysql_query()
ausführen und den Wert aus
der Ergebnismenge dieser Anweisung abfragen.
Für LAST_INSERT_ID()
wird die zuletzt
generierte ID für jede Verbindung im Server gespeichert. Sie
wird von keinem anderen Client geändert, noch nicht einmal
dann, wenn Sie eine andere
AUTO_INCREMENT
-Spalte mit einem
nichtmagischen Wert aktualisieren (also einem Wert, der nicht
NULL
und nicht 0
ist).
Wenn Sie die für eine Tabelle generierte ID benutzen und in eine andere Tabelle einfügen möchten, erledigen Sie dies mit SQL-Anweisungen wie diesen:
INSERT INTO foo (auto,text) VALUES(NULL,'text'); # generiert ID durch Einfügen von NULL INSERT INTO foo2 (id,text) VALUES(LAST_INSERT_ID(),'text'); # benutzt ID in einer zweiten Tabelle
Beachten Sie, dass mysql_insert_id()
den
Wert liefert, der in einer
AUTO_INCREMENT
-Spalte gespeichert war, egal
ob dieser Wert automatisch durch Speichern von
NULL
oder 0
generiert
oder als expliziter Wert angegeben wurde.
LAST_INSERT_ID()
liefert nur automatisch
generierte AUTO_INCREMENT
-Werte. Wenn Sie
einen expliziten Wert, der nicht NULL
oder
0
ist, speichern, so beeinflusst dieser
nicht den Rückgabewert von
LAST_INSERT_ID()
.
Beim Verlinken mit der C-API können folgende Fehler auf manchen Systemen auftreten:
gcc -g -o client test.o -L/usr/local/lib/mysql -lmysqlclient -lsocket -lnsl Undefined first referenced symbol in file floor /usr/local/lib/mysql/libmysqlclient.a(password.o) ld: fatal: Symbol referencing errors. No output written to client
Wenn dies auf Ihrem System geschieht, müssen Sie die
Mathe-Bibliothek einbinden, indem Sie -lm
am
Ende der Compile/link-Zeile hinzufügen.
Wenn Sie MySQL-Clients kompilieren, die Sie selbst geschrieben
oder von einem Fremdhersteller bekommen haben, müssen diese im
Link-Befehl mit den -lmysqlclient -lz
-Optionen
verknüpft werden. Eventuell müssen Sie auch die Option
-L
angeben, um dem Linker mitzuteilen, wo er
die Bibliothek finden kann. Wenn die Bibliothek beispielsweise
in /usr/local/mysql/lib
installiert ist,
müssen Sie im Link-Befehl -L/usr/local/mysql/lib
-lmysqlclient -lz
verwenden.
Für Clients, die MySQL-Header-Dateien benutzen, müssen Sie
eventuell beim Kompilieren die Option -I
(zum
Beispiel -I/usr/local/mysql/include
)
einstellen, damit der Compiler die Header-Dateien finden kann.
Um das Kompilieren von MySQL-Programmen auf Unix zu erleichtern, haben wir das mysql_config-Skript für Sie erstellt. Siehe hierzu Abschnitt 24.9.2, „mysql_config — Kompilieroptionen zum Kompilieren von Clients erhalten“.
Mit dem Skript können Sie einen MySQL-Client wie folgt kompilieren:
CFG=/usr/local/mysql/bin/mysql_config sh -c "gcc -o progname `$CFG --cflags` progname.c `$CFG --libs`"
sh -c
ist erforderlich, damit die Shell die
Ausgabe von mysql_config nicht als ein
einziges Wort behandelt.
Die Clientbibliothek ist beinahe Thread-sicher. Das größte
Problem besteht darin, dass die Subroutinen in
net.c
, die Daten aus Sockets lesen, nicht
gegen Interrupts gesichert sind. Dies wurde mit dem
Hintergedanken so eingerichtet, dass Sie vielleicht einen
eigenen Alarm installieren möchten, der einen langen
Lesevorgang auf einem Server abbrechen kann. Wenn Sie
Interrupt-Handler für den SIGPIPE
-Interrupt
installieren, sollte die Arbeit auf dem Socket Thread-sicher
sein.
Um zu verhindern, dass das Programm abbricht, sobald eine
Verbindung endet, blockiert MySQL SIGPIPE
beim ersten Aufruf von mysql_server_init()
,
mysql_init()
oder
mysql_connect()
. Wenn Sie einen eigenen
SIGPIPE
-Handler benutzen möchten, sollten
Sie als Erstes mysql_server_init()
aufrufen
und dann Ihren Handler installieren.
In den älteren Binaries, die auf unserer Website angeboten werden (http://www.mysql.com/), werden die Clientbibliotheken normalerweise nicht mit der Thread-sicheren Option kompiliert (ausgenommen die Windows-Binaries, die standardmäßig Thread-sicher kompiliert werden). Neuere Binärdistributionen sollten sowohl eine normale als auch eine Thread-sichere Clientbibliothek besitzen.
Um einen Threaded Client zu erstellen, den Sie mit anderen
Threads unterbrechen und auf dem Sie Timeouts für die
Kommunikation mit dem MySQL Server einstellen können, verwenden
Sie die Bibliotheken -lmysys
,
-lmystrings
und -ldbug
sowie
den net_serv.o
-Code, den auch der Server
benutzt.
Wenn Sie keine Interrupts oder Timeouts benötigen, kompilieren
Sie einfach eine Thread-sichere Clientbibliothek
(mysqlclient_r)
und benutzen diese. Siehe
Abschnitt 24.2, „MySQL-C-API“. In diesem Fall müssen Sie sich über die
net_serv.o
-Objektdatei oder die anderen
MySQL-Bibliotheken keine Gedanken machen.
Wenn Sie einen Threaded Client mit Timeouts und Interrupts
benutzen möchten, sind die Routinen in der Datei
thr_alarm.c
sehr gut geeignet. Benutzen Sie
Routinen aus der mysys
-Bibliothek, so müssen
Sie nur daran denken, my_init()
immer als
Erstes aufzurufen! Siehe Abschnitt 24.2.11, „C-Threaded-Funktionsbeschreibungen“.
Alle Funktionen außer mysql_real_connect()
sind standardmäßig Thread-sicher. Die folgenden Hinweise
beschreiben, wie man eine Thread-sichere Clientbibliothek
kompiliert und in Thread-sicherer Weise benutzt. (Eigentlich
gelten die folgenden Hinweise zu
mysql_real_connect()
auch für
mysql_connect()
, aber da
mysql_connect()
veraltet ist, sollten Sie
ohnehin nur mit mysql_real_connect()
arbeiten.)
Um mysql_real_connect()
Thread-sicher zu
machen, müssen Sie die Clientbibliothek mit folgendem Befehl
neu kompilieren:
shell> ./configure --enable-thread-safe-client
Dies erzeugt die Thread-sichere Clientbibliothek
libmysqlclient_r
. (Immer vorausgesetzt, dass
Ihr Betriebssytem über eine Thread-sichere
gethostbyname_r()
-Funktion verfügt.) Diese
Bibliothek ist pro Verbindung Thread-sicher. Zwei Threads
können also dieselbe Verbindung nutzen, allerdings mit
folgenden Schwachstellen:
Zwei Threads können einem MySQL Server nicht gleichzeitig
über dieselbe Verbindung eine Anfrage senden. Sie müssen
vor allem gewährleisten, dass zwischen
mysql_query()
und
mysql_store_result()
kein anderer Thread
dieselbe Verbindung benutzt.
Viele Threads können auf unterschiedliche Ergebnismengen
zugreifen, die mit mysql_store_result()
abgerufen werden.
Wenn Sie dagegen mysql_use_result
benutzen, müssen Sie dafür sorgen, dass so lange kein
anderer Thread dieselbe Verbindung benutzt, bis die
Ergebnismenge wieder geschlossen wurde. Allerdings ist
mysql_store_result()
ohnehin die bessere
Lösung für Threaded Clients, die sich dieselbe Verbindung
teilen.
Wenn Sie mehrere Threads auf derselben Verbindung einsetzen
möchten, müssen Sie die mysql_query()
-
und
mysql_store_result()
-Aufrufkombinationen
mit einer Mutex-Sperre umgeben. Sobald
mysql_store_result()
fertig ist, kann die
Sperre aufgehoben werden und andere Threads können Anfragen
an dieselbe Verbindung schicken.
Wenn Sie mit POSIX-Threads programmieren, können Sie mit
pthread_mutex_lock()
und
pthread_mutex_unlock()
eine Mutex-Sperre
errichten und wieder freigeben.
Folgendes ist wichtig, wenn Sie einen Thread andere MySQL-Funktionen aufrufen lassen als die, welche die Verbindung zur MySQL-Datenbank eingerichtet haben:
Wenn Sie mysql_init()
oder
mysql_connect()
aufrufen, legt MySQL eine
Thread-spezifische Variable für den Thread an, die (unter
anderem) von der Debugbibliothek genutzt wird.
Wenn Sie eine MySQL-Funktion aufrufen, bevor der Thread
mysql_init()
oder
mysql_connect()
aufgerufen hat, wurden die
Thread-spezifischen Variablen für den Thread noch nicht
angelegt und Sie riskieren, dass es früher oder später zu
einem Core Dump kommt.
Damit alles reibunbslos funktioniert, müssen Sie Folgendes tun:
Rufen Sie my_init()
am Anfang Ihres
Programms auf, wenn dieses vor
mysql_real_connect()
noch eine andere
MySQL-Funktion aufruft.
Rufen Sie im Thread-Handler
mysql_thread_init()
auf, ehe Sie
irgendeine MySQL-Funktion benutzen.
Im Thread müssen Sie mysql_thread_end()
vor pthread_exit()
aufrufen. Das gibt den
Speicher frei, den MySQL für Thread-spezifische Variablen
reserviert hat.
Eventuell werden Fehler aufgrund von undefinierten Symbolen
gemeldet, wenn Sie Ihren Client mit
libmysqlclient_r
verlinken. In den meisten
Fällen liegt dies daran, dass Sie vergessen haben, auf der
Link/compile-Zeile die Thread-Bibliotheken einzubinden.
PHP ist eine serverseitige, in HTML eingebettete Skriptsprache zur Erstellung von dynamischen Webseiten. Sie steht für die meisten Betriebssysteme und Webserver zur Verfügung und kann auf die meisten gebräuchlichen Datenbanken zugreifen, darunter auch MySQL. PHP kann als separates Programm ausgeführt oder als Modul in den Apache-Webserver kompiliert werden.
PHP stellt zwei verschiedene MySQL-API-Erweiterungen zur Verfügung:
mysql
: Diese Erweiterung ist für PHP 4 und
5 verfügbar und für MySQL-Versionen gedacht, die älter als
MySQL 4.1 sind. Die Erweiterung unterstützt weder das
verbesserte Authentifizierungsprotokoll von MySQL
5.1, noch vorbereitete Anweisungen oder
Mehrfachanweisungen. Wenn Sie diese Erweiterung mit MySQL
5.1 benutzen möchten, müssen Sie den MySQL
Server wahrscheinlich mit der Option
--old-passwords konfigurieren (siehe
Abschnitt A.2.3, „Client does not support authentication protocol
“). Diese Erweiterung ist auf der
PHP-Website unter http://php.net/mysql
dokumentiert.
mysqli
(eine Abkürzung für „MySQL,
Improved“) ist eine Erweiterung, die nur in PHP 5
verfügbar ist. Sie ist für die Benutzung mit MySQL 4.1.1 und
höher gedacht. Diese Erweiterung unterstützt das
Authentifizierungsprotokoll von MySQL 5.1 sowie
die APIS für vorbereitete Anweisungen und Mehrfachanweisungen
(Prepared Statements und Multiple Statements). Überdies hat
diese Erweiterung eine moderne Schnittstelle für die
objektorientierte Programmierung zu bieten. Die Dokumentation
der Erweiterung mysqli
finden Sie unter
http://php.net/mysqli. Außerdem ist unter
http://www.zend.com/php5/articles/php5-mysqli.php
ein hilfreicher Fachartikel zu lesen.
Die PHP-Distribution und -Dokumentation stehen auf der PHP-Website zur Verfügung.
Error: Maximum Execution Time Exceeded
:
Dies ist ein PHP-Limit. Gehen Sie in die Datei
php.ini
und setzen Sie die maximale
Ausführungszeit von 30 Sekunden auf einen höheren Wert,
wie Sie ihn benötigen. Außerdem ist es keine schlechte
Idee, den pro Skript verfügbaren Arbeitsspeicher von 8 auf
16 Mbyte zu verdoppeln.
Fatal error: Call to unsupported or undefined
Funktion mysql_connect() in ...
: Dies bedeutet,
dass Ihre PHP-Version nicht mit MySQL-Unterstützung
kompiliert wurde. Sie können entweder ein dynamisches
MySQL-Modul kompilieren und in PHP laden oder PHP mit
integrierter MySQL-Unterstützung rekompilieren. Dieser
Prozess wird im PHP-Handbuch genauer erläutert.
Error: Undefined reference to
'uncompress'
: Dies bedeutet, dass die
Clientbibliothek mit Unterstützung für ein komprimiertes
Client/Server-Protokoll kompiliert wurde. Dies beheben Sie,
indem Sie die Option -lz
als Letztes beim
Verlinken mit -lmysqlclient
hinzufügen.
Error: Client does not support authentication
protocol
: Dieser Fehler tritt am häufigsten auf,
wenn Sie versuchen, die ältere
mysql
-Erweiterung mit MySQL 4.1.1 oder
höher zu verwenden. Mögliche Lösungen: Sie können auf
MySQL 4.0 umstellen, auf PHP 5 und die neuere
mysqli
umschalten oder den MySQL Server
mit der Option --old-passwords
konfigurieren. (Siehe auch Abschnitt A.2.3, „Client does not support authentication protocol
“.)
Wer noch mit älterem PHP4-Code arbeitet, kann eine Kompatibilitätsschicht für die alte und neue MySQL-Bibliothek verwenden, wie beispielsweise: http://www.coggeshall.org/oss/mysql2i.
Das DBI
-Modul von Perl stellt eine generische
Schnittstelle für den Datenbankzugriff zur Verfügung. Sie
können ein DBI-Skript schreiben, das ohne Änderungen mit vielen
verschiedenen Datenbank-Engines funktioniert. Um DBI nutzen zu
können, müssen Sie das DBI
-Modul sowie für
jeden Servertyp, auf den Sie zugreifen möchten, ein DataBase
Driver (DBD)-Modul kompilieren. Das Treibermodul für MySQL ist
DBD::mysql
.
Perl DBI ist die empfohlene Schnittstelle für Perl. Sie ersetzt
eine ältere Schnittstelle namens mysqlperl
,
die nun als obsolet gelten kann.
Installationsanleitungen für Perl DBI-Support finden Sie in Abschnitt 2.13, „Anmerkungen zur Perl-Installation“.
DBI-Informationen stehen auf der Kommandozeile, online oder gedruckt zur Verfügung:
Wenn Sie die Module DBI
und
DBD::mysql
installiert haben, können Sie
Informationen über diese Module mit dem Befehl
perldoc
auf der Kommandozeile abfragen:
shell>perldoc DBI
shell>perldoc DBI::FAQ
shell>perldoc DBD::mysql
Sie können diese Informationen auch mit
pod2man
, pod2html
und so
weiter in andere Formate übersetzen.
Online-Informationen über Perl DBI stehen auf der DBI-Website
unter http://dbi.perl.org/ zur Verfügung.
Diese Site hostet auch eine allgemeine Mailingliste zu DBI.
MySQL AB hostet überdies eine spezielle
DBD::mysql
-Mailingliste; siehe
Abschnitt 1.7.1, „Die MySQL-Mailinglisten“.
Was das gedruckte Wort angeht, so ist das offizielle DBI-Buch Programming the Perl DBI (Alligator Descartes und Tim Bunce, O'Reilly & Associates, 2000). Informationen über dieses Buch finden Sie auf der DBI-Website http://dbi.perl.org/.
Informationen, die speziell die Benutzung von DBI mit MySQL in den Mittelpunkt stellen, finden Sie unter MySQL and Perl for the Web (Paul DuBois, New Riders, 2001). Die Website zu diesem Buch ist http://www.kitebird.com/mysql-perl/.
MySQL++
ist eine MySQL-API für C++. Warren
Young hat dieses Projekt übernommen. Weitere Informationen finden
Sie unter http://www.mysql.com/products/mysql++/.
Sie können die MySQL Windows-Quelldatei mit Borland C++ 5.02 kompilieren. (Zur Windows-Quelldatei gehören nur Projekte für Microsoft VC++; Projektdateien für Borland C++ müssen Sie sich selbst beschaffen.)
Ein bekanntes Problem mit Borland C++ ist, dass er eine andere
Strukturanordnung als VC++ verwendet. Daher bekommen Sie
Probleme, wenn Sie versuchen, mit Borland C++ die
standardmäßigen libmysql.dll
-Bibliotheken
zu benutzen (die mit VC++ kompiliert wurden). Um dies zu
vermeiden, rufen Sie mysql_init()
nur mit
NULL
als Argument auf und verwenden keine
vorab zugewiesene MYSQL
-Struktur.
MySQLdb
stellt für Python eine
MySQL-Unterstützung zur Verfügung, die mit der
Python-DB-API-Version 2.0 harmoniert. Diese finden Sie unter
http://sourceforge.net/projects/mysql-python/.
MySQLtcl
ist eine einfache API, um mit der
Programmiersprache Tcl auf einen MySQL-Datenbankserver zugreifen
zu können. Zu finden ist sie unter
http://www.xdobry.de/mysqltcl/.
Eiffel MySQL ist eine Schnittstelle zum MySQL-Datenbankserver für die von Michael Ravits geschriebene Programmiersprache Eiffel. Diese finden Sie unter http://efsa.sourceforge.net/archive/ravits/mysql.htm.
Dieser Abschnitt beschreibt einige Utilities, die Ihnen bei der Entwicklung von MySQL-Programmen helfen können.
msql2mysql
Ein Shell-Skript, das mSQL
-Programme in
MySQL konvertiert. Es kann zwar nicht jeden Fall behandeln,
ist aber für die Konvertierung ein guter Anfang.
mysql_config
Ein Shell-Skript, das die zur Kompilierung von MySQL-Programmen notwendigen Optionswerte erstellt.
Anfangs wurde die MySQL-C-API ganz ähnlich wie die API für das Datenbanksystem mSQL entwickelt. Daher lassen sich mSQL-Programme oft relativ einfach für die Benutzung mit MySQL konvertieren, indem man einfach nur die Namen der C-API-Funktionen ändert.
Die Utility msql2mysql wandelt mSQL-C-API-Funktionsaufrufe in ihre MySQL-Entsprechungen um. Da msql2mysql die Eingabedatei an Ort und Stelle konvertiert, sollten Sie vorher eine Kopie des Originals anlegen. Sie können msql2mysql beispielsweise wie folgt verwenden:
shell>cp client-prog.c client-prog.c.orig
shell>msql2mysql client-prog.c
client-prog.c converted
Danach untersuchen Sie client-prog.c
und nehmen, so weit notwendig, abschließende
Überarbeitungen vor.
msql2mysql verwendet zum Ersetzen der Funktionsnamen die Utility replace. Siehe Abschnitt 8.17, „replace — Hilfsprogramm für String-Ersetzungen“.
mysql_config gibt Ihnen nützliche Informationen zum Kompilieren des MySQL-Clients und zur Verbindung mit MySQL.
mysql_config unterstützt die folgenden Optionen:
--cflags
Compiler-Flags zum Auffinden von Include-Dateien und
wichtige Compiler-Flags und Defines, die zum Kompilieren
der libmysqlclient
-Bibliothek
verwendet werden.
--include
Compiler-Optionen zum Auffinden von
MySQL-Include-Dateien. (Beachten Sie, dass normalerweise
statt dieser Option die Option --cflags
benutzt wird.)
--libmysqld-libs
,
---embedded
Bibliotheken und Optionen, die zum Verlinken mit dem MySQL Embedded Server erforderlich sind.
--libs
Bibliotheken und Optionen, die zum Verlinken mit der MySQL-Clientbibliothek erforderlich sind.
--libs_r
Bibliotheken und Optionen, die zum Verlinken mit der Thread-sicheren MySQL-Clientbibliothek erforderlich sind.
--port
Die Standard-TCP/IP-Portnummer, die beim Konfigurieren von MySQL definiert wird.
--socket
Die Standard-Unix-Socket-File, die beim Konfigurieren von MySQL definiert wird.
--version
Versionsnummer für die MySQL-Distribution.
Wenn Sie mysql_config ohne Optionen aufrufen, zeigt der Befehl eine Liste aller von ihm unterstützten Optionen samt ihrer Werte an:
shell> mysql_config
Usage: /usr/local/mysql/bin/mysql_config [options]
Options:
--cflags [-I/usr/local/mysql/include/mysql -mcpu=pentiumpro]
--include [-I/usr/local/mysql/include/mysql]
--libs [-L/usr/local/mysql/lib/mysql -lmysqlclient -lz
-lcrypt -lnsl -lm -L/usr/lib -lssl -lcrypto]
--libs_r [-L/usr/local/mysql/lib/mysql -lmysqlclient_r
-lpthread -lz -lcrypt -lnsl -lm -lpthread]
--socket [/tmp/mysql.sock]
--port [3306]
--version [4.0.16]
--libmysqld-libs [-L/usr/local/mysql/lib/mysql -lmysqld -lpthread -lz
-lcrypt -lnsl -lm -lpthread -lrt]
Sie können mysql_config in einer Kommandozeile benutzen, um den Wert, den dieser Befehl für eine bestimmte Option anzeigt, einzubinden. Um beispielsweise ein MySQL-Clientprogramm zu kompilieren, verwenden Sie mysql_config folgendermaßen:
shell>CFG=/usr/local/mysql/bin/mysql_config
shell>sh -c "gcc -o progname `$CFG --cflags` progname.c `$CFG --libs`"
Wenn Sie mysql_config auf diese Weise
benutzen, achten Sie darauf, es in Backtick-Zeichen
einzuschließen (‘`
’). So
weiß die Shell, dass sie dies ausführen und die Ausgabe in
den umgebenden Befehl einsetzen muss.
Inhaltsverzeichnis
Dieses Kapitel beschreibt MySQL Connectors, Treiber, die für Clientprogramme Verbindungsmöglichkeiten zu MySQL bereitstellen.
MySQL Connector/ODBC ist der Name einer Familie von MySQL-ODBC-Treibern (auch MyODBC-Treiber genannt), die Zugriff auf eine MySQL-Datenbank mithilfe der Open Database Connectivity (ODBC)-API geben, die Industriestandard ist. Die vorliegende Referenz behandelt die API-Version Connector/ODBC 3.51, die ODBC 3.5x-konformen Zugriff auf eine MySQL-Datenbank gibt.
Das Manual für ältere MyODBC-Versionen als 3.51 finden Sie in der entsprechenden Binär- oder Quelldistribution.
Weitere Informationen über den ODBC-API-Standard und seine Verwendung finden Sie unter http://www.microsoft.com/data/.
Der Teil dieser Referenz, der sich mit Anwendungsentwicklung beschäftigt, setzt gute Vorkenntnisse in C, allgemeine DBMS-Kenntnisse und nicht zuletzt auch die Vertrautheit mit MySQL voraus. Weitere Informationen über die Funktionalität und Syntax von MySQL finden Sie unter http://dev.mysql.com/doc/.
MyODBC muss in der Regel nur auf Windows-Rechnern installiert werden. Für Unix und Mac OS X kann das native MySQL-Netzwerk oder eine Named Pipe zur Kommunikation mit der MySQL-Datenbank benutzt werden. Eventuell benötigen Sie jedoch MyODBC für Unix oder Mac OS X, wenn Sie eine Anwendung haben, die für die Datenbankkommunikation eine ODBC-Schnittstelle benötigt. Solche Anwendungen sind beispielsweise ColdFusion, Microsoft Office und Filemaker Pro.
Wenn Sie den MyODBC-Connector auf einem Unix-Host benutzen, müssen Sie auch einen ODBC-Manager installieren.
Fragen, die dieses Dokument nicht beantwortet, richten Sie bitte per
E-Mail an <myodbc@lists.mysql.com>
.
ODBC (Open Database Connectivity) gibt Clientprogrammen Zugriffsmöglichkeiten auf eine breite Palette von Datenbanken oder Datenquellen. ODBC ist eine standardisierte API, die Verbindungen zu SQL-Datenbankservern ermöglicht. Sie wurde nach den Vorgaben der SQL Access Group entwickelt und definiert Funktionsaufrufe, Fehlercodes und Datentypen, die für die Entwicklung datenbankunabhängiger Anwendungen eingesetzt werden können. ODBC wird normalerweise dort genutzt, wo Datenbankunabhängigkeit oder paralleler Zugriff auf verschiedene Datenquellen erforderlich ist.
Mehr über ODBC können Sie unter http://www.microsoft.com/data/ nachlesen.
Zurzeit sind zwei Versionen von MyODBC erhältlich:
MyODBC 5.0, gegenwärtig noch in der Beta-Phase, wurde geschaffen, um die Funktionalität des MyODBC 3.51-Treibers zu erweitern und sämtliche Funktionen des MySQL Servers 5.0 zu unterstützen, einschließlich gespeicherter Prozeduren und Views. Anwendungen für MyODBC 3.51 werden auch mit MyODBC 5.0 funktionieren, zusätzlich jedoch auch die neuen Funktionen nutzen können. Die Features und Funktionalität des MyODBC 5.0-Treibers sind zurzeit noch nicht Gegenstand des vorliegenden Guides.
MyODBC 3.51 ist das aktuelle Release des 32-Bit-ODBC-Treibers, auch MySQL ODBC 3.51-Treiber genannt. Diese Version wurde gegenüber dem älteren MyODBC 2.50-Treiber verbessert. Sie unterstützt den ODBC 3.5x-Spezifikationslevel 1 (die gesamte Core-API + Features von Level 2), damit weiterhin auch die gesamte Funktionalität für den ODBC-Zugriff auf MySQL geboten werden kann.
MyODBC 2.50 ist die frühere Version des 32-Bit-ODBC-Treibers von der MySQL AB und beruht auf dem ODBC 2.50-Spezifikationslevel 0 (mit den Features von Level 1 und 2). Über den MyODBC 2.50-Treiber informiert diese Referenz nur zu Vergleichszwecken.
Hinweis: Ab diesem Abschnitt liegt das Hauptaugenmerk dieser Referenz auf dem MyODBC 3.51-Treiber. Weitere Informationen über den MyODBC-Treiber 2.50 finden Sie in der Dokumentation zu den Installationspaketen dieser Version. Wenn ein konkretes Thema (ein Fehler oder ein bekanntes Problem) nur die Version 2.50 betrifft, wird es unter Umständen zur Orientierung hier ebenfalls behandelt.
Open Database Connectivity (ODBC) ist eine allgemein anerkannte Programmierschnittstelle (API) für den Datenbankzugriff. Sie beruht auf den Call-Level Interface(CLI)-Spezifikationen von X/Open und ISO/IEC für Datenbank-APIs und benutzt als Sprache für den Datenbankzugriff die Structured Query Language (SQL).
Eine Übersicht über die von MyODBC unterstützten ODBC-Funktionen finden Sie unter Abschnitt 25.1.5.1, „MyODBC: API-Referenz“. Allgemeine Informationen über ODBC gibt es unter http://www.microsoft.com/data/.
Die MyODBC-Architektur basiert auf den im folgenden Diagramm gezeigten fünf Komponenten:
Anwendung:
Die Anwendung (Application) nutzt die ODBC-API, um auf die Daten auf dem MySQL Server zuzugreifen. Die ODBC-API ihrerseits kommuniziert mit dem Treiber-Manager (Driver Manager). Die Anwendung kommuniziert mit dem Treiber-Manager über normale ODBC-Aufrufe und kümmert sich nicht darum, wie und wo die Daten gespeichert sind oder wie das System für den Datenzugriff konfiguriert ist. Alles, was sie wissen muss, ist der Data Source Name (DSN).
Einige Aufgaben müssen von allen Anwendungen erledigt werden, egal auf welche Weise sie ODBC nutzen:
Sie müssen den MySQL Server auswählen und sich mit ihm verbinden.
Sie müssen SQL-Anweisungen zur Ausführung übermitteln.
Sie müssen die Ergebnisse (sofern vorhanden) abholen.
Sie müssen Fehler verarbeiten.
Sie müssen die Transaktion, zu der die SQL-Anweisung gehört, committen oder zurückrollen.
Sie müssen die Verbindung zum MySQL Server trennen.
Da die meiste Arbeit im Zusammenhang mit dem Datenzugriff mit SQL verrichtet wird, besteht die Hauptaufgabe von Anwendungen, die ODBC nutzen, in der Übermittlung von SQL-Anweisungen und dem Abruf der dadurch erzeugten Ergebnisse.
Treiber-Manager:
Der Treiber-Manager ist eine Bibliothek zur Verwaltung der Kommunikation zwischen Anwendung und Treiber(n). Er kümmert sich um folgende Aufgaben:
Er löst Data Source Names (DSN) auf. Der DSN ist ein Konfigurations-String, der einen Datenbanktreiber, einen Datenbank-Host und optional auch Authentifizierungsdaten enthält und der ODBC-Anwendung eine Datenbankverbindung über eine standardisierte Referenz ermöglicht.
Da der DSN die Informationen für die Datenbankverbindung enthält, kann sich jede ODBC-fähige Anwendung über dieselbe DSN-Referenz mit der Datenquelle verbinden. Dadurch ist es nicht mehr nötig, jede Anwendung, die Zugriff auf eine konkrete Datenbank benötigt, separat zu konfigurieren. Stattdessen instruieren Sie die Anwendung, einen vorkonfigurierten DSN zu verwenden.
Er lädt und entlädt den Treiber, der für den Zugriff auf eine bestimmte Datenbank notwendig ist, wie im DSN definiert. Wenn Sie zum Beispiel einen DSN für die Verbindung mit einer MySQL-Datenbank konfiguriert haben, lädt der Treiber-Manager den MyODBC-Treiber, damit die ODBC-API mit dem MySQL-Host kommunizieren kann.
Er verarbeitet ODBC-Funktionsaufrufe oder übergibt sie zur Verarbeitung an den Treiber.
MyODBC-Treiber:
Der MyODBC-Treiber ist eine Bibliothek, die Funktionen implementiert, welche von der ODBC-API unterstützt werden. Er verarbeitet ODBC-Funktionsaufrufe, übermittelt SQL-Requests an den MySQL Server und liefert die Ergebnisse an die Anwendung zurück. Wenn nötig, modifiziert der Treiber den von der Anwendung übermittelten Request so, dass er der MySQL-Syntax entspricht.
DSN-Konfiguration:
Die ODBC-Konfigurationsdatei speichert die Treiber- und Datenbankinformationen, die für die Serververbindung erforderlich sind. Der Treiber-Manager nutzt sie, um festzustellen, welcher Treiber laut der Definition im DSN geladen werden muss. Der Treiber liest daraus die Verbindungsparameter anhand des angegebenen DSN. Weitere Informationen finden Sie unter Abschnitt 25.1.3, „MyODBC: Konfiguration“.
MySQL Server:
Die MySQL-Datenbank, in der die Informationen gespeichert sind. Die Datenbank wird für Abfragen als Datenquelle und für Einfügungen und Änderungen als Ziel für die Daten genutzt.
Ein ODBC-Treiber-Manager ist eine Bibliothek zur Verwaltung der Kommunikation zwischen einer ODBC-fähigen Anwendung und Treibern. Seine Hauptfunktionen sind:
Data Source Names (DSN) auflösen
Treiber laden und entladen
ODBC-Funktionsaufrufe verarbeiten oder zur Verarbeitung an den Treiber weiterleiten
Bei Windows und Mac OS X sind ODBC-Treiber-Manager im Betriebssystem enthalten. Die meisten Implementierungen von ODBC-Treiber-Managern umfassen auch eine Administrationsanwendung, um die Konfiguration von DSN und Treibern zu vereinfachen. Beispiele und Informationen zu diesen Managern, einschließlich der ODBC-Treiber-Manager von Unix, sind im Folgenden aufgelistet:
Microsoft Windows ODBC-Treiber-Manager
(odbc32.dll
),
http://www.microsoft.com/data/.
Mac OS X enthält den ODBC
Administrator
, eine GUI-Anwendung, die einen
vereinfachten Konfigurationsmechanismus für den
iODBC-Treiber-Manager von Unix zur Verfügung stellt. Sie
können DSN- und Treiber-Informationen entweder über den
ODBC-Administrator oder durch die
iODBC-Konfigurationsdateien in Erfahrung bringen. Das
bedeutet auch, dass Sie die ODBC
Administrator-Konfigurationen mit dem Befehl
iodbctest
testen können.
http://www.apple.com.
unixODBC
-Treiber-Manager für Unix
(libodbc.so
). Siehe weitere
Informationen unter
http://www.unixodbc.org. Ab
der Version unixODBC
2.1.2 ist der
MyODBC-Treiber 3.51 im Installationspaket des
unixODBC
-Treiber-Managers enthalten.
Über den iODBC
-ODBC-Treiber-Manager
für Unix (libiodbc.so
) finden Sie
weitere Informationen unter
http://www.iodbc.org.
Die MyODBC-Treiber können Sie mit zwei verschiedenen Methoden installieren, nämlich entweder als Binär- oder als Quellinstallation. Die Binärinstallation ist die einfachste. Eine Quellinstallation dürfte nur auf Plattformen notwendig sein, für die kein Binärinstallationspaket zur Verfügung steht oder wenn Sie den Installationsprozess oder die MyODBC-Treiber vor der Installation modifizieren möchten.
Die MySQL AB vertreibt alle ihre Produkte unter der General Public License (GPL). Die neueste Version der MyODBC-Binär- und Quelldateien erhalten Sie auf der Website von MySQL AB unter http://dev.mysql.com/downloads/.
Weitere Informationen über MyODBC finden Sie unter http://www.mysql.com/products/myodbc/.
Über die Lizenzen können Sie sich unter http://www.mysql.com/company/legal/licensing/ informieren.
MyODBC kann auf allen von MySQL unterstützten Plattformen verwendet werden, als da sind:
Windows 95, 98, Me, NT, 2000, XP und 2003
Alle Unix-ähnlichen Betriebssysteme, darunter AIX, Amiga, BSDI, DEC, FreeBSD, HP-UX 10/11, Linux, NetBSD, OpenBSD, OS/2, SGI Irix, Solaris, SunOS, SCO OpenServer, SCO UnixWare, Tru64 Unix
Mac OS X und Mac OS X Server
Wenn für eine bestimmte Plattform keine Binärdistribution
verfügbar ist, schlagen Sie bitte
Abschnitt 25.1.2.4, „MyODBC von einer Quelldistribution installieren“, nach, um den
Treiber aus dem Originalquellcode zu erstellen. Die
Binärdateien, die Sie aus diesem Code erstellen, könnten Sie
dann MySQL zugänglich machen, indem Sie eine E-Mail an
<myodbc@lists.mysql.com>
schicken. So können auch
andere diese Binärdateien nutzen.
Am einfachsten lässt sich MyODBC von einer Binärdistribution installieren. Wenn Sie mehr Kontrolle über den Treiber oder das Installationsverzeichnis bekommen oder einzelne Elemente des Treibers an Ihre Bedürfnisse anpassen möchten, müssen Sie ihn aus den Quelldateien erstellen. Siehe hierzu Abschnitt 25.1.2.4, „MyODBC von einer Quelldistribution installieren“.
Bevor Sie die MyODBC-Treiber auf Windows installieren, sollten Sie sicherstellen, dass Ihre Microsoft Data Access Components (MDAC) auf dem neuesten Stand sind. Die aktuellste Version erhalten Sie auf der Website Microsoft Data Access and Storage.
Für die Windows-Installation stehen drei Distributionstypen zur Verfügung. Der Inhalt ist immer derselbe; nur die Installationsmethode ist unterschiedlich.
Der gezippte Installer besteht aus einem Zip-Archiv mit einer eigenständigen Installationsanwendung. Um dieses Paket zu installieren, packen Sie den Installer aus und führen die Installationsanwendung aus. Unter Abschnitt 25.1.2.3.1.1, „Windows MyODBC-Treiber mit einem Installer installieren“, erfahren Sie, wie die Installation fertig gestellt wird.
MSI-Installer ist eine Installationsdatei zur Verwendung mit dem Installer, der in Windows 2000, Windows XP und Windows Server 2003 enthalten ist. Unter Abschnitt 25.1.2.3.1.1, „Windows MyODBC-Treiber mit einem Installer installieren“, erfahren Sie, wie die Installation fertig gestellt wird.
Das gezippte DLL-Paket enthält die DLL-Dateien, die manuell installiert werden müssen. Unter Abschnitt 25.1.2.3.1.2, „Windows MyODBC-Treiber mit dem DLL-Zip-Archiv installieren“, erfahren Sie, wie die Installation fertig gestellt wird.
Die Installer-Programme bieten ein sehr einfaches Mittel zur Installation der MyODBC-Treiber. Wenn Sie den gezippten Installer heruntergeladen haben, müssen Sie die Installer-Anwendung noch auspacken. Der grundlegende Installationsprozess ist für beide Installer derselbe.
Um die Installation abzuschließen, gehen Sie folgendermaßen vor:
Setzen Sie einen Doppelklick auf den extrahierten Installer oder die heruntergeladene MSI-Datei.
Dadurch wird der MySQL Connector/ODBC 3.51 - Setup Wizard gestartet. Klicken Sie auf
, um den Installationsprozess zu starten.Nun wählen Sie den Installationstyp. Die typische Installation liefert die Standarddateien, die für eine ODBC-Verbindung mit einer MySQL-Datenbank benötigt werden. Die Complete-Option installiert sämtliche verfügbaren Dateien einschließlich Debugging und Hilfsprogrammen. Wir empfehlen, eine dieser beiden Optionen zu nutzen. Danach klicken Sie auf
und machen mit Schritt 5 weiter.Sie können auch eine benutzerdefinierte (Custom) Installation verlangen, bei der Sie die zu installierenden Komponenten selbst auswählen können. Wenn Sie diese Methode ausgewählt haben, klicken Sie auf
und gehen zu Schritt 4.Wenn Sie sich für eine benutzerdefinierte Installation entschieden haben, wählen Sie in den Popup-Fenstern aus, welche Komponenten Sie installieren möchten, und klicken dann auf
, um die notwendigen Dateien zu installieren.Wenn die Dateien auf Ihren Computer kopiert worden sind, ist die Installation abgeschlossen. Klicken Sie auf
, um den Installer zu schließen.Nun ist die Installation fertig und Sie können beginnen, Ihre ODBC-Verbindungen gemäß Abschnitt 25.1.3, „MyODBC: Konfiguration“, zu konfigurieren.
Wenn Sie das DLL-Paket als Zip-Archiv heruntergeladen haben, müssen Sie die einzelnen Dateien, die für MyODBC erforderlich sind, manuell installieren. Nach dem Auspacken der Installationsdateien können Sie dies entweder selbst tun, indem Sie jede notwendige Anweisung einzeln ausführen, oder die mitgelieferte Batch-Datei für eine Installation in den Standardverzeichnissen nutzen.
Installation mithilfe der Batch-Datei:
Extrahieren Sie das MyODBC Zipped DLL-Paket.
Öffnen Sie ein Befehlseingabefenster.
Gehen Sie in das Verzeichnis, das beim Extrahieren des MyODBC Zipped DLL-Pakets angelegt wurde.
Führen Sie Install.bat
aus:
C:\> Install.bat
Dieser Befehl kopiert die notwendigen Dateien in das Standardverzeichnis und registriert dann den MyODBC-Treiber beim Windows ODBC-Manager.
Wenn Sie die Dateien in ein anderes Verzeichnis kopieren möchten, etwa um unterschiedliche Versionen des MyODBC-Treibers auf demselben Computer auszuführen oder zu testen, dann müssen Sie die Dateien manuell kopieren. Allerdings kann man nur davon abraten, sie in ein anderes als das Standardverzeichnis zu installieren. Um die Dateien von Hand in das Standardinstallationsverzeichnis zu kopieren, verfahren Sie folgendermaßen:
Extrahieren Sie das MyODBC Zipped DLL-Paket.
Öffnen Sie ein Befehlseingabefenster.
Gehen Sie in das Verzeichnis, das beim Extrahieren des MyODBC Zipped DLL-Pakets angelegt wurde.
Kopieren Sie die Bibliotheksdateien in ein passendes
Verzeichnis. Standardmäßig werden sie in das
Systemverzeichnis von Windows kopiert, nämlich
\Windows\System32
:
C:\>copy lib\myodbc3S.dll \Windows\System32
C:\>copy lib\myodbc3S.lib \Windows\System32
C:\>copy lib\myodbc3.dll \Windows\System32
C:\>copy lib\myodbc3.lib \Windows\System32
Kopieren Sie die MyODBC-Tools. Diese müssen in ein
Verzeichnis gesetzt werden, das im
System-PATH
liegt. Standardmäßig
werden sie in das Systemverzeichnis von Windows
installiert, nämlich
\Windows\System32
:
C:\>copy bin\myodbc3i.exe \Windows\System32
C:\>copy bin\myodbc3m.exe \Windows\System32
C:\>copy bin\myodbc3c.exe \Windows\System32
Optional können Sie auch die Hilfedateien kopieren. Damit diese im Hilfe-System zugänglich sind, müssen sie im Windows-Systemverzeichnis installiert werden:
C:\> copy doc\*.hlp \Windows\System32
Zum Schluss registrieren Sie den MyODBC-Treiber beim ODBC-Manager:
C:\> myodbc3i -a -d -t"MySQL ODBC 3.51 Driver;\
DRIVER=myodbc3.dll;SETUP=myodbc3S.dll"
Wenn Sie die Dateien nicht im Standardverzeichnis installiert haben, müssen Sie bei diesem Befehl die Verweise auf die DLL-Dateien und den Ort des Befehls entsprechend ändern.
Auf Windows wird eventuell folgender Fehler gemeldet, wenn Sie versuchen, den älteren MyODBC 2.50-Treiber zu installieren:
An error occurred while copying C:\WINDOWS\SYSTEM\MFC30.DLL. Restart Windows and try installing again (before running any applications which use ODBC)
Dieser Fehler tritt auf, wenn eine andere Anwendung gerade
das ODBC-System benutzt. Windows erlaubt Ihnen dann
vielleicht nicht, die Installation abzuschließen. In den
meisten Fällen können Sie jedoch mit einem Klick auf
Ignorieren
fortfahren, den Rest der
MyODBC-Dateien zu kopieren, und das Ergebnis der
Installation sollte funktionieren. Wenn nicht, so fahren Sie
Ihren Computer im „abgesicherten Modus“ wieder
hoch. Diesen Modus steuern Sie an, indem Sie beim Booten,
unmittelbar bevor Windows gestartet wird, auf F8 drücken.
Installieren Sie sodann die MyODBC-Treiber und starten Sie
den Computer im Normalmodus neu.
Es gibt zwei Methoden, um MyODBC auf Unix von einer Binärdistribution zu installieren. Für die meisten Unix-Umgebungen wird die Tarball-Distribution benötigt. Für Linux-Systeme steht außerdem eine RPM-Distribution zur Verfügung.
Um den Treiber von einer Tarball-Distribution zu
installieren (die Datei .tar.gz
), laden
Sie die neueste Treiberversion für Ihr Betriebssystem
herunter und halten sich an die folgenden Schritte (gezeigt
wird das Vorgehen mit einer Linux-Version des Tarballs):
shell>su root
shell>gunzip MyODBC-3.51.11-i686-pc-linux.tar.gz
shell>tar xvf MyODBC-3.51.11-i686-pc-linux.tar
shell>cd MyODBC-3.51.11-i686-pc-linux
Lesen Sie die Installationsanweisungen in der Datei
INSTALL-BINARY
und führen Sie folgende
Befehle aus.
shell>cp libmyodbc* /usr/local/lib
shell>cp odbc.ini /usr/local/etc
shell>export ODBCINI=/usr/local/etc/odbc.ini
Dann fahren Sie mit
Abschnitt 25.1.3.4, „Konfiguration einer MyODBC-DSN unter Unix“,
fort, um den DSN für MyODBC zu konfigurieren. Weitere
Informationen finden Sie in der Datei
INSTALL-BINARY
aus Ihrer Distribution.
Um MyODBC von einer RPM-Distribution auf Linux zu
installieren oder zu aktualisieren, laden Sie einfach die
RPM-Distribution der neuesten MyODBC-Version herunter und
halten sich an die nachfolgenden Anleitungen. Zuerst müssen
Sie mit su root der
root
-User werden und dann können Sie die
RPM-Datei installieren.
Wenn es sich um eine Erstinstallation handelt:
shell>su root
shell>rpm -ivh MyODBC-3.51.12.i386.rpm
Wenn der Treiber bereits existiert und nur aktualisiert werden soll:
shell>su root
shell>rpm -Uvh MyODBC-3.51.12.i386.rpm
Falls ein Fehler in den Abhängigkeiten der
MySQL-Clientbibliothek libmysqlclient
gemeldet wird, übergehen Sie ihn einfach, indem Sie die
Option --nodeps
einstellen, und sorgen
dafür, dass die gemeinsame MySQL-Clientbibliothek im Pfad
oder mit LD_LIBRARY_PATH
eingestellt ist.
So werden die Treiberbibliotheken und zugehörigen Dokumente
in /usr/local/lib
und
/usr/share/doc/MyODBC
installiert.
Machen Sie nun weiter mit
Abschnitt 25.1.3.4, „Konfiguration einer MyODBC-DSN unter Unix“.
Um den Treiber zu
deinstallieren, müssen Sie
als root
einen
rpm-Befehl ausführen:
shell>su root
shell>rpm -e MyODBC
Mac OS X basiert auf dem Betriebssystem FreeBSD. Normalerweise können Sie den MySQL-Netzwerkanschluss benutzen, um sich mit MySQL Servern auf anderen Hosts zu verbinden. Die Installation des MyODBC-Treibers versetzt Sie in die Lage, sich mit MySQL-Datenbanken auf jeder beliebigen Plattform über die ODBC-Schnittstelle zu verbinden. Den MyODBC-Treiber müssen Sie nur dann installieren, wenn Ihre Anwendung eine ODBC-Schnittstelle benötigt. Zu den Anwendungen, die ODBC (und somit auch den MyODBC-Treiber) erfordern oder nutzen können, gehören ColdFusion, Filemaker Pro, 4th Dimension und viele andere mehr.
Mac OS X enthält einen eigenen ODBC-Manager, der auf dem
iODBC
-Manager basiert. Mac OS X hat ein
Administrationstool, das die Administration von ODBC-Treibern
und die Konfiguration erleichtert, wobei die zugrunde
liegenden iODBC
-Konfigurationsdateien
aktualisiert werden.
MyODBC kann auf einem Mac OS X oder Mac OS X Server mithilfe
der Binärdistribution installiert werden. Dieses Paket
steht als komprimierte Disk Image-Datei
(.dmg
) zur Verfügung. Um MyODBC mit
dieser Methode zu installieren, verfahren Sie wie folgt:
Laden Sie die Datei auf Ihren Computer herunter und führen Sie einen Doppelklick auf die Image-Datei aus.
Dort finden Sie ein Installer-Paket (mit der Erweiterung
.pkg
). Mit einem Doppelklick auf
diese Datei starten Sie den Mac OS X-Installer.
Wenn Sie die Grußbotschaft sehen, klicken Sie auf
, um den Installationsprozess zu starten.Bitte nehmen Sie sich ein wenig Zeit, um die wichtigen Informationen (Important Information) zu lesen, denn sie enthalten eine Anleitung für den weiteren Installationsprozess. Wenn Sie eine Verbindung zu einer MySQL-Datenbank testen möchten, müssen Sie den Standort Ihres MySQL Servers kennen und einen Benutzernamen und ein Passwort haben, um einen zum Testen der Installation geeigneten DSN zu erhalten. Ein solcher Test ist jedoch nicht erforderlich, um die Installation abzuschließen. Wenn Sie die Hinweise gelesen und die notwendigen Informationen gesammelt haben, klicken Sie auf
.MyODBC-Treiber unterliegen der GNU General Public License. Bitte lesen Sie die Lizenz, wenn Sie sie noch nicht kennen, ehe Sie mit der Installation fortfahren. Mit einem Klick auf
akzeptieren Sie die Lizenz (hier werden Sie noch einmal zur Bestätigung aufgefordert) und setzen die Installation fort.Wählen Sie ein Installationsverzeichnis für die MyODBC-Treiber und die ODBC Administrator-Anwendung. Sie müssen die Dateien auf einem Laufwerk mit einem Betriebssystem installieren, sodass Sie unter Umständen nicht viele Auswahlmöglichkeiten haben. Wählen Sie das Laufwerk, das Sie benutzen möchten, und klicken Sie auf
.Der Installer wählt automatisch die Dateien aus, die auf Ihrem Computer installiert werden müssen. Um fortzufahren, klicken Sie auf
. Der Installer kopiert nun die erforderlichen Dateien auf Ihren Computer. Eine Fortschrittsanzeige informiert Sie über den Installationsfortschritt.Nach Abschluss der Installation sehen Sie ein Fenster wie das unten abgebildete. Klicken Sie auf
, um den Installer zu beenden.Wenn Sie MyODBC von einer Quelldistribution installieren, haben Sie mehr Einfluss auf den Inhalt und das Installationsverzeichnis der MyODBC-Komponenten. Außerdem können Sie dann MyODBC auch auf Plattformen installieren, für die keine vorkompilierte Binärversion verfügbar ist.
MyODBC-Quelldateien erhalten Sie entweder als Download oder über das Revisionskontrollsystem, das die MyODBC-Entwickler benutzen.
Auf Windows müsste eine Quellinstallation von MyODBC nur dann nötig sein, wenn Sie die Quelle oder die Installation ändern möchten. Wenn Sie unsicher sind, ob Sie von Quelldateien installieren sollten, verwenden Sie besser die Binärinstallation, die in Abschnitt 25.1.2.3.1, „Installation von MyODBC aus einer Binärdistribution unter Windows“, beschrieben ist.
Für eine Quellinstallation von MyODBC auf Windows sind verschiedene Tools und Pakete erforderlich:
MDAC, Microsoft Data Access SDK von http://www.microsoft.com/data/.
Ein geeigneter C-Compiler, wie etwa Microsoft Visual C++ oder der C-Compiler von Microsoft Visual Studio.
Ein kompatibles make
-Tool. In den
Beispielen dieses Abschnitts wird nmake
von Microsoft eingesetzt.
MySQL-Clientbibliotheken und Include-Dateien von MySQL 4.0.0 oder höher (vorzugsweise MySQL 4.0.16 oder höher). Diese sind notwendig, weil MyODBC neue Aufrufe und Strukturen verwendet, die erst ab dieser Version der Bibliothek vorhanden sind. Die MySQL-Clientbibliotheken und Include-Dateien erhalten Sie von http://dev.mysql.com/downloads/.
MyODBC-Quelldistributionen enthalten
Makefiles
, für die
nmake oder die
make
-Utility notwendig ist. Die
Distribution enthält Makefile
, um die
Release-Version, und Makefile_debug
, um
Debugging-Versionen der Treiberbibliotheken und DLLs zu
bauen.
Den Treiber bauen Sie wie folgt:
Sie laden die Quelldateien herunter und extrahieren sie
in einen Ordner. Dann gehen Sie in dieses Verzeichnis.
Der folgende Befehl geht davon aus, dass der Ordner
myodbc3-src
heißt:
C:\> cd myodbc3-src
Sie editieren Makefile
, um den Pfad
der MySQL-Clientbibliotheken und -Header-Dateien
anzugeben. Dann erstellen und installieren Sie mit
folgenden Befehlen die Release-Version:
C:\>nmake -f Makefile
C:\>nmake -f Makefile install
nmake -f Makefile erstellt die
Release-Version des Treibers und speichert die
Binärdateien in einem Unterverzeichnis namens
Release
.
nmake -f Makefile install installiert
(kopiert) die Treiber-DLLs und Bibliotheken
(myodbc3.dll
,
myodbc3.lib
) in Ihr
Systemverzeichnis.
Die Debugversion wird mit
Makefile_Debug
anstelle von
Makefile
erstellt:
C:\>nmake -f Makefile_debug
C:\>nmake -f Makefile_debug install
Um den Treiber sauber neu zu installieren, geben Sie Folgendes ein:
C:\>nmake -f Makefile clean
C:\>nmake -f Makefile install
Hinweis
Achten Sie darauf, in den Makefiles den richtigen Pfad
zu den MySQL-Clientbibliotheken und Header-Dateien
anzugeben. (Hierzu müssen Sie die Variablen
MYSQL_LIB_PATH
und
MYSQL_INCLUDE_PATH
einstellen.) Der
Standardpfad zur Header-Datei ist voraussichtlich
C:\mysql\include
und der
Standardpfad zur Bibliothek lautet
C:\mysql\lib\opt
für Release-DLLs
und C:\mysql\lib\debug
für
Debugging-Versionen.
Mehr über die Verwendung von nmake erfahren Sie unter http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_vcce4/html/evgrfRunningNMAKE.asp.
Wenn Sie den Subversion-Baum zum Kompilieren verwenden,
bekommen alle Windows-spezifischen
Makefiles
den Namen
Win_Makefile*
.
Wenn die Treiberbibliotheken in das Systemverzeichnis
kopiert/installiert worden sind, können Sie anhand der
Beispiele aus dem Unterverzeichnis
samples
testen, ob die Bibliotheken
korrekt erstellt wurden:
C:\>cd samples
C:\>nmake -f Makefile all
Folgende Tools werden benötigt, um MySQL auf Unix aus der Quelldistribution zu erstellen:
Ein funktionierender ANSI C++-Compiler. gcc 2.95.2 oder höher, egcs 1.0.2 oder höher oder egcs 2.91.66, SGI C++ und SunPro C++ sind Beispiele für funktionierende Compiler.
Ein gutes make-Programm. Das make von GNU ist immer empfehlenswert und manchmal sogar obligatorisch.
MySQL-Clientbibliotheken und Include-Dateien von MySQL 4.0.0 oder höher (vorzugweise MySQL 4.0.16 oder höher). Diese sind notwendig, weil MyODBC neue Aufrufe und Strukturen benutzt, die erst ab dieser Version der Bibliothek zur Verfügung stehen. Sie erhalten die MySQL-Clientbibliotheken und Include-Dateien unter http://dev.mysql.com/downloads/.
Wenn Sie einen eigenen MySQL Server und/oder
Clientbibliotheken aus den Quelldateien gebaut haben,
müssen Sie bei der Erstellung der Bibliotheken
configure
mit der Option
--enable-thread-safe-client
verwendet
haben.
Außerdem müssen Sie sich vergewissern, dass die
Bibliothek libmysqlclient
als Shared
Library gebaut und installiert wurde.
Ein kompatibler ODBC-Manager muss installiert sein. Von
MyODBC ist bekannt, dass es mit den Managern
iODBC
und unixODBC
funktioniert. Siehe auch
Abschnitt 25.1.1.2.2, „ODBC-Treiber-Manager“.
Wenn Sie einen Zeichensatz verwenden, der nicht in die
MySQL-Clientbibliothek kompiliert ist, müssen Sie die
MySQL-Zeichendefinitionen aus dem Verzeichnis
charsets
in
SHAREDIR
installieren (nach
Voreinstellung ist dies
/usr/local/mysql/share/mysql/charsets
).
Wenn Sie den MySQL Server auf demselben Computer
installiert haben, müssten die Zeichendefinitionen
vorhanden sein. Mehr über Unterstützung von
Zeichensätzen erfahren Sie unter
Kapitel 10, Zeichensatz-Unterstützung.
Wenn Sie alle erforderlichen Dateien beisammen haben, extrahieren Sie die Quelldateien in ein getrenntes Verzeichnis. Danach führen Sie configure aus und erstellen mit make die Bibliothek.
Das configure-Skript gibt Ihnen viel Einfluss auf die Konfiguration Ihres MyODBC-Builds. Diesen Einfluss üben Sie aus, indem Sie auf der Kommandozeile Optionen für configure benutzen. Außerdem können Sie configure mit gewissen Umgebungsvariablen beeinflussen. Eine Liste der Optionen und Umgebungsvariablen für configure liefert Ihnen folgender Befehl:
shell> ./configure --help
Die gebräuchlichsten Optionen für configure werden im Folgenden beschrieben:
Um MyODBC zu kompilieren, müssen Sie den Pfad zu den
Include- und Bibliotheksdateien des MySQL-Clients mit
der Option
--with-mysql-path=
angeben, wobei DIR
DIR
das
Verzeichnis ist, in dem MySQL installiert wurde.
Die Optionen zum Kompilieren von MySQL ermitteln Sie,
indem Sie
ausführen.
DIR
/bin/mysql_config
Geben Sie den Standardpfad für die Header- und
Bibliotheksdateien für Ihren ODBC-Treiber-Manager an
(iODBC
oder
unixODBC
).
Wenn Sie iODBC
benutzen, aber
nicht im Standardverzeichnis
(/usr/local
) installiert haben,
müssen Sie eventuell die Option
--with-iodbc=
angeben, wobei DIR
DIR
das
Verzeichnis ist, in dem iODBC
installiert wurde.
Liegen die iODBC
-Header nicht
unter
,
können Sie ihren Speicherort mit der Option
DIR
/include--with-iodbc-includes=
angeben.
INCDIR
Dies gilt auch für Bibliotheken. Wenn sie nicht
unter
zu finden sind, können Sie die Option
DIR
/lib--with-iodbc-libs=
verwenden.
LIBDIR
Wenn Sie unixODBC
nutzen,
verwenden Sie die Option
--with-unixODBC=
(Groß- und Kleinschreibung beachten!), damit
configure standardmäßig nach
DIR
unixODBC
statt nach
iODBC
sucht.
DIR
ist das Verzeichnis,
wo unixODBC
installiert ist.
Wenn die unixODBC
-Header und
Bibliotheken nicht in
und
DIR
/include
liegen, müssen Sie die Optionen
DIR
/lib--with-unixODBC-includes=
und
INCDIR
--with-unixODBC-libs=
einstellen.
LIBDIR
Vielleicht möchten Sie ein anderes Installationspräfix
als /usr/local
vorgeben. Wenn Sie
zum Beispiel die MyODBC-Treiber in
/usr/local/odbc/lib
installieren
möchten, setzen Sie die Option
--prefix=/usr/local/odbc
.
Zum Schluss sieht der Konfigurationsbefehl in etwa wie folgt aus:
shell>./configure --prefix=/usr/local \
--with-iodbc=/usr/local \
--with-mysql-path=/usr/local/mysql
Es gibt noch mehr Optionen, die Sie einstellen müssen oder können, wenn Sie den MyODBC-Treiber vor dem Build konfigurieren.
Um den Treiber mit den Thread-sicheren
Clientbibliotheken von MySQL,
libmysqlclient_r.so
oder
libmysqlclient_r.a
, zu verlinken,
geben Sie folgende configure-Option
an:
--enable-thread-safe
Deaktiviert (die Standardeinstellung) wird dies wie folgt:
--disable-thread-safe
Diese Option ermöglicht die Erstellung der
Thread-sicheren Treiberbibliothek
libmyodbc3_r.so
durch das Verlinken
mit der Thread-sicheren MySQL-Clientbibliothek
libmysqlclient_r.so
(die
Erweiterungen hängen vom Betriebssystem ab).
Wenn das Kompilieren mit der Thread-sicheren Option
scheitert, dann möglicherweise deshalb, weil auf dem
betreffenden System die richtigen Thread-Bibliotheken
nicht gefunden werden konnten. Stellen Sie den Wert von
LIBS
also auf die für Ihr System
passende Thread-Bibliothek ein.
LIBS="-lpthread" ./configure ..
Die gemeinsam genutzte und die statische Version von MyODBC werden mit folgenden Optionen aktiviert und deaktiviert:
--enable-shared[=yes/no] --disable-shared --enable-static[=yes/no] --disable-static
Nach Voreinstellung werden alle Binärdistributionen
ohne Debugging gebaut (mit
--without-debug
konfiguriert).
Um Debugging-Informationen zu erhalten, erstellen Sie
den Treiber aus der Quellversion und stellen die Option
--with-debug
ein, wenn Sie
configure ausführen.
Diese Option steht nur für Quellbäume aus dem Subversion-Repository zur Verfügung, nicht für Quelldistributionen, die als Package geliefert werden.
Nach Voreinstellung wird der Treiber mit der Option
--without-docs
gebaut. Wenn Sie die
Dokumentation einrichten möchten, führen Sie
configure folgendermaßen aus:
--with-docs
Um die Treiberbibliotheken zu bauen, müssen Sie nur make laufen lassen.
shell> make
Wenn Fehler auftreten, berichtigen Sie sie und fahren im
Build-Prozess fort. Ist der Build nicht möglich, senden Sie
eine ausführliche E-Mail an
<myodbc@lists.mysql.com>
, um sich Hilfe zu
holen.
Auf den meisten Plattformen werden .so
(shared) Client-Bibliotheken standardmäßig nicht gebaut
oder unterstützt. Grund dafür sind die schlechten
Erfahrungen, die wir beim Erstellen von Shared Libraries
gemacht haben.
In solchen Fällen müssen Sie die MySQL-Distribution herunterladen und mit folgenden Optionen konfigurieren:
--without-server --enable-shared
Um den Treiber mit Shared Libraries zu erstellen, müssen
Sie die Option --enable-shared
für
configure angeben. Standardmäßig ist
diese Option für configure nicht
aktiviert.
Wenn Sie den Treiber mit --disable-shared
konfiguriert haben, können Sie aus den statischen
Bibliotheken die .so
-Datei mit
folgenden Befehlen erstellen:
shell>cd MyODBC-3.51.01
shell>make
shell>cd driver
shell>CC=/usr/bin/gcc \
$CC -bundle -flat_namespace -undefined error \
-o .libs/libmyodbc3-3.51.01.so \
catalog.o connect.o cursor.o dll.o error.o execute.o \
handle.o info.o misc.o myodbc3.o options.o prepare.o \
results.o transact.o utility.o \
-L/usr/local/mysql/lib/mysql/ \
-L/usr/local/iodbc/lib/ \
-lz -lc -lmysqlclient -liodbcinst
Aus -liodbcinst
müssen Sie
-lodbcinst
machen, wenn Sie
unixODBC
anstelle von
iODBC
nutzen. Die Bibliothekspfade
müssen Sie dann auch entsprechend konfigurieren.
So wird die Datei libmyodbc3-3.51.01.so
erstellt und in das Verzeichnis .libs
gelegt. Diese Datei kopieren Sie in das
Installationsverzeichnis der MyODBC-Bibliotheken
(/usr/local/lib
) oder in das
lib
-Verzeichnis unter dem
Installationsverzeichnis, das Sie mit
--prefix
vorgegeben haben.
shell>cd .libs
shell>cp libmyodbc3-3.51.01.so /usr/local/lib
shell>cd /usr/local/lib
shell>ln -s libmyodbc3-3.51.01.so libmyodbc3.so
Die Thread-sichere Treiberbibliothek bauen Sie mit:
shell>CC=/usr/bin/gcc \
$CC -bundle -flat_namespace -undefined error
-o .libs/libmyodbc3_r-3.51.01.so
catalog.o connect.o cursor.o dll.o error.o execute.o
handle.o info.o misc.o myodbc3.o options.o prepare.o
results.o transact.o utility.o
-L/usr/local/mysql/lib/mysql/
-L/usr/local/iodbc/lib/
-lz -lc -lmysqlclient_r -liodbcinst
Mit folgendem Befehl installieren Sie die Treiberbibliotheken:
shell> make install
Damit wird eines der folgenden Bibliotheken-Sets installiert:
Für MyODBC 3.51:
libmyodbc3.so
libmyodbc3-3.51.01.so
, wobei
3.51.01 die Treiberversion ist
libmyodbc3.a
Für Thread-sicheres MyODBC 3.51:
libmyodbc3_r.so
libmyodbc3-3_r.51.01.so
libmyodbc3_r.a
Für MyODBC 2.5.0:
libmyodbc.so
libmyodbc-2.50.39.so
, wobei 2.50.39
die Treiberversion ist
libmyodbc.a
Mehr über den Build-Prozess erfahren Sie in der Datei
INSTALL
, die mit der Quelldistribution
mitgeliefert wird. Achtung:
Wenn Sie den make-Befehl von Sun
verwenden, können Fehler entstehen. Das
gmake von GNU dagegen müsste auf allen
Plattformen funktionieren.
Um die einfachen Beispiele in der von Ihnen gebauten Distribution mit den Bibliotheken auszuführen, geben Sie folgenden Befehl ein:
shell> make test
Ehe Sie Tests laufen lassen, legen Sie den DSN 'myodbc3' in
odbc.ini
an und stellen die
Umgebungsvariable ODBCINI
auf die
korrekte odbc.ini
-Datei ein. Dann
läuft der MySQL Server. Eine
odbc.ini
-Beispieldatei wird mit der
Treiberdistribution mitgeliefert.
Sie können das Skript
samples/run-samples
auch so
umschreiben, dass es die gewünschten DSN-, UID- und
PASSWORD-Werte als Kommandozeilenargumente für jedes
Beispiel übergibt.
Um den Treiber auf Mac OS X (Darwin) zu erstellen, verwenden Sie folgendes configure-Beispiel:
shell>./configure --prefix=/usr/local
--with-unixODBC=/usr/local
--with-mysql-path=/usr/local/mysql
--disable-shared
--enable-gui=no
--host=powerpc-apple
Dieser Befehl setzt voraus, dass unixODBC
und MySQL in den Standardverzeichnissen installiert wurden.
Ist dies nicht der Fall, müssen Sie die Konfiguration
entsprechend ändern.
Auf Mac OS X werden mit der Option
--enable-shared
die
.dylib
-Dateien standardmäßig
erstellt. Die .so
-Dateien können Sie
folgendermaßen bauen:
shell>make
shell>cd driver
shell>CC=/usr/bin/gcc \
$CC -bundle -flat_namespace -undefined error
-o .libs/libmyodbc3-3.51.01.so *.o
-L/usr/local/mysql/lib/
-L/usr/local/iodbc/lib
-liodbcinst -lmysqlclient -lz -lc
Die Thread-sichere Treiberbibliothek bauen Sie mit:
shell>CC=/usr/bin/gcc \
$CC -bundle -flat_namespace -undefined error
-o .libs/libmyodbc3-3.51.01.so *.o
-L/usr/local/mysql/lib/
-L/usr/local/iodbc/lib
-liodbcinst -lmysqlclienti_r -lz -lc -lpthread
Aus -liodbcinst
müssen Sie
-lodbcinst
machen, wenn Sie
unixODBC
anstelle von
iODBC
nutzen. Die Bibliothekspfade
müssen Sie dann auch entsprechend konfigurieren.
In der Apple-Version von GCC sind cc und gcc in Wirklichkeit symbolische Links zu gcc3.
Kopieren Sie diese Bibliothek in das Verzeichnis
$prefix/lib
und richten Sie einen
symbolischen Link auf libmyodbc3.so
ein.
Mit folgendem Befehl überprüfen Sie die Ausgabeeigenschaften für die gemeinsam genutzten Bibliotheken:
shell> otool -LD .libs/libmyodbc3-3.51.01.so
Zur Erstellung des Treibers auf HP-UX 10.x or 11.x nutzen Sie folgendes configure-Beispiel:
Wenn cc verwendet wird:
shell>CC="cc" \
CFLAGS="+z" \
LDFLAGS="-Wl,+b:-Wl,+s" \
./configure --prefix=/usr/local
--with-unixodbc=/usr/local
--with-mysql-path=/usr/local/mysql/lib/mysql
--enable-shared
--enable-thread-safe
Wenn gcc verwendet wird:
shell>CC="gcc" \
LDFLAGS="-Wl,+b:-Wl,+s" \
./configure --prefix=/usr/local
--with-unixodbc=/usr/local
--with-mysql-path=/usr/local/mysql
--enable-shared
--enable-thread-safe
Haben Sie den Treiber gebaut, so überprüfen Sie seine
Attribute mit chatr .libs/libmyodbc3.sl,
um festzustellen, ob der Pfad der MySQL-Clientbibliothek mit
der Umgebungsvariablen SHLIB_PATH
hätte
eingestellt werden müssen. Bei statischen Versionen können
Sie alle Optionen, die gemeinsam genutzte Bibliotheken
betreffen, ignorieren und configure mit
der --disable-shared
-Option laufen lassen.
Um den Treiber auf AIX zu bauen, gehen Sie nach folgendem configure-Beispiel vor:
shell>./configure --prefix=/usr/local
--with-unixodbc=/usr/local
--with-mysql-path=/usr/local/mysql
--disable-shared
--enable-thread-safe
Hinweis: Weitere Informationen über das Bauen und Einrichten statischer und gemeinsam genutzter Bibliotheken auf unterschiedlichen Plattformen finden Sie unter Using static and shared libraries across platforms'.
Achtung: Bitte lesen Sie den folgenden Abschnitt nur dann, wenn Sie daran interessiert sind, uns zu helfen oder Code zu testen. Wenn Sie MySQL Connector/ODBC lediglich auf Ihrem System ans Laufen bringen möchten, benutzen Sie bitte eine Standard-Release-Distribution.
Um auf den Quellbaum von MyODBC zugreifen zu können, müssen Sie Subversion installiert haben. Subversion ist kostenlos unter http://subversion.tigris.org/ erhältlich.
Folgende Tools sind erforderlich, um MyODBC von den Quellbäumen erstellen zu können:
autoconf 2.52 (oder neuer)
automake 1.4 (oder neuer)
libtool 1.4 (oder neuer)
m4
Den aktuellsten Quellbaum in der Entwicklung finden Sie unter unseren öffentlichen Subversion-Bäumen unter http://dev.mysql.com/tech-resources/sources.html.
Um die Connector/ODBC-Quelldateien auszuchecken, gehen Sie in das Verzeichnis, in welches Sie den zu speichernden MyODBC-Baum kopieren möchten, und geben folgenden Befehl ein:
shell> svn co http://svn.mysql.com/svnpublic/connector-odbc3
Danach dürfte eine Kopie des gesamten MyODBC-Quellbaums im
Verzeichnis connector-odbc3
vorliegen.
Auf Unix oder Linux erstellen Sie den Build aus diesen
Quelldateien wie folgt:
shell>cd connector-odbc3
shell>aclocal
shell>autoheader
shell>autoconf
shell>automake;
shell>./configure # Hier geben Sie Ihre Optionen an
shell>make
Weitere Informationen über den Build finden Sie in der Datei
INSTALL
, die in demselben Verzeichnis
liegt. Über configure-Optionen können Sie
unter
Abschnitt 25.1.2.4.2.1, „Typische configure-Optionen“,
Genaueres erfahren.
Nach dem Build führen Sie make install aus, um den MyODBC 3.51-Treiber auf Ihrem System zu installieren.
Wenn Sie bis make vorgedrungen sind, aber
die Distribution sich nicht kompilieren lässt, schicken Sie
bitte einen Bericht an <myodbc@lists.mysql.com>
.
Auf Windows können Sie zur Erstellung des Treibers die
Windows-Makefiles WIN-Makefile
und
WIN-Makefile_debug
benutzen. Weiteres
erfahren Sie unter
Abschnitt 25.1.2.4.1, „Installation von MyODBC aus einer Quelldistribution unter Windows“.
Nach dem ersten Auschecken, mit dem Sie den Quellbaum heruntergeladen haben, sollten Sie regelmäßig svn update laufen lassen, um Ihre Quelldateien mit den neuesten Versionen zu aktualisieren.
Bevor Sie eine Verbindung zu einer MySQL-Datenbank über den MyODBC-Treiber einrichten können, müssen Sie einen ODBC-Data Source Name (DSN) konfigurieren. Der DSN verbindet die diversen Konfigurationsparameter, die zur Kommunikation mit einer Datenbank erforderlich sind, mit einem bestimmten Namen. Um mit der Datenbank zu kommunizieren, verwenden Sie in einer Anwendung den DSN, anstatt die einzelnen Parameter in der Anwendung selbst zu konfigurieren. DSN-Informationen können benutzer- oder systemspezifisch sein, oder sie können in einer gesonderten Datei angegeben werden. Die Namen der ODBC-Datenquellen werden je nach Plattform und ODBC-Treiber unterschiedlich konfiguriert.
Mit einem Data Source Name sind die Konfigurationsparameter für die Kommunikation mit einer bestimmten Datenbank verbunden. Normalerweise besteht ein DSN aus folgenden Parametern:
Zusätzlich können verschiedene ODBC-Treiber, darunter auch MyODBC, weitere treiberspezifische Optionen und Parameter haben.
Es gibt drei DSN-Typen:
Ein System-DSN ist eine globale DSN-Definition, die jedem Benutzer und jeder Anwendung auf einem bestimmten System zur Verfügung steht. Ein System-DSN kann normalerweise nur von einem Systemadministrator konfiguriert werden, oder aber von einem Benutzer, der die speziellen Berechtigungen zur Erstellung von System-DSNs hat.
Ein User-DSN ist für einen einzelnen Benutzer spezifisch und dient der Speicherung von Datenbankverbindungsinformationen, die dieser Benutzer regelmäßig verwendet.
Ein File-DSN definiert die DSN-Konfiguration in einer einfachen Datei. File-DSNs können von Benutzern und Computern gemeinsam genutzt werden und sind daher praktischer, wenn DSN-Informationen als Teil einer Anwendung auf mehreren Computern installiert oder verteilt werden sollen.
DSN-Informationen werden je nach Plattform und Umgebung an unterschiedlichen Speicherorten abgelegt.
Mit dem ODBC-Datenquellen-Administrator
von
Windows können Sie DSNs anlegen, die Treiberinstallation
überprüfen und ODBC-Systeme wie etwa Tracing
(Ablaufverfolgung, dient dem Debugging) und Verbindungspooling
einrichten.
Verschiedene Ausgaben und Versionen von Windows speichern den
ODBC-Datenquellen-Administrator
an
verschiedenen Orten, je nach der verwendeten Windows-Version.
Den ODBC-Datenquellen-Administrator
in
Windows Server 2003 öffnen:
Wählen Sie im Startmenü Verwaltung
und
klicken Sie auf Datenquellen (ODBC)
.
Den ODBC-Datenquellen-Administrator
in
Windows 2000 Server oder Windows 2000 Professional öffnen:
Wählen Sie im Startmenü Einstellungen
und klicken Sie auf Systemsteuerung
.
In der Systemsteuerung
klicken Sie auf
Verwaltung
.
In der Verwaltung
klicken Sie auf
Datenquellen (ODBC)
.
Den ODBC-Datenquellen-Administrator
in
Windows XP öffnen:
Klicken Sie im Startmenü auf
Systemsteuerung
.
In der Systemsteuerung
klicken Sie, wenn
die Kategorienansicht eingestellt ist, auf Leistung
und Wartung
und dann auf
Verwaltung
. Wenn Sie die Klassische
Ansicht für die Systemsteuerung eingestellt haben, klicken
Sie hier direkt auf Verwaltung
.
In der Verwaltung
klicken Sie auf
Datenquellen (ODBC)
.
Unabhängig von der Windows-Version müssten Sie nun das Fenster
des ODBC-Datenquellen-Administrators
vor sich
sehen:
In Windows XP können Sie den Ordner
Verwaltung
Ihrem Startmenü hinzufügen, um
den ODBC-Datenquellen-Administrator später leichter finden zu
können:
Klicken Sie mit rechts auf die Schaltfläche
.
Wählen Sie Eigenschaften
.
Klicken Sie auf
.Wählen Sie die Registerkarte
.
Markieren Sie unter Startmenüelemente
im
Abschnitt Systemverwaltung
den Punkt
Im Menü "Alle Programme" anzeigen
.
In Windows Server 2003 und Windows XP können Sie den
ODBC-Datenquellen-Administrator
auch
dauerhaft Ihrem Startmenü hinzufügen. Hierzu suchen Sie wie
oben beschrieben das Symbol Datenquellen
(ODBC)
, klicken mit rechts darauf und wählen dann
.
Zum Hinzufügen und Konfigurieren einer neuen
MyODBC-Datenquelle auf Windows benutzen Sie den
ODBC-Datenquellen-Administrator
:
Öffnen Sie den
ODBC-Datenquellen-Administrator
.
Um einen System-DSN hinzuzufügen (der allen Benutzern
zugänglich ist), wählen Sie die Registerkarte
System DSN
. Einen Benutzer-DSN, der
ausschließlich für den aktuellen Benutzer zur Verfügung
steht, erstellen Sie mit einem Klick auf
.
Sie müssen den ODBC-Treiber für diesen DSN auswählen.
Wählen Sie MySQL ODBC 3.51 Driver
und
klicken Sie dann auf Finish
.
Nun müssen Sie noch die spezifischen Felder für den DSN
im Dialog Add Data Source Name
anlegen.
Im Feld Data Source Name
geben Sie den
Namen der Datenquelle ein, auf die Sie zugreifen möchten.
Das kann jeder gültige Name Ihrer Wahl sein.
In das Feld Description
geben Sie einen
Text ein, der dabei hilft, die Verbindung zu
identifizieren.
In das Feld Server
geben Sie den Namen
des MySQL Serverhosts ein, auf den Sie zugreifen möchten.
Nach Voreinstellung ist dies localhost
.
In das Feld User
geben Sie den
Benutzernamen für diese Verbindung ein.
In das Feld Password
geben Sie das
Passwort für diese Verbindung ein.
Im Popup-Fenster Database
müsste
automatisch eine Liste der Datenbanken erscheinen, auf die
der Benutzer ein Zugriffsrecht hat.
Mit einem Klick auf
wird der DSN gespeichert.Eine vollständige DSN-Konfiguration kann folgendermaßen aussehen:
Um die Verbindung mit den von Ihnen eingegebenen Parametern zu
überprüfen, klicken Sie auf Success; connection was
made!
(abhängig von den Spracheinstellungen auch
auf Deutsch).
Wenn die Verbindung nicht zustande kam, können Sie Informationen über den Test und die Gründe seines Scheiterns mit einem Klick auf
einholen. Es werden dann zusätzliche Fehlermeldungen angezeigt.Sie können eine Reihe von Optionen für einen konkreten DSN einstellen, indem Sie im DSN-Konfigurationsdialog entweder eine der Registerkarten
oder anklicken.Den Dialog
sehen Sie unten.Folgende drei Optionen können konfiguriert werden:
Port
ist die Nummer des TCP/IP-Ports,
der zur Kommunikation mit MySQL genutzt wird.
Normalerweise wird nach Voreinstellung der Port 3306
verwendet. Wenn für Ihren Server ein anderer TCP/IP-Port
konfiguriert ist, müssen Sie dessen Portnummer hier
angeben.
Socket
stellt den Namen oder Ort eines
bestimmten Sockets oder einer Windows-Pipe ein, die für
die Kommunikation mit MySQL benutzt wird.
Initial Statement
definiert eine
SQL-Anweisung, die beim Aufbau einer Verbindung zu MySQL
ausgeführt wird. Das können Sie nutzen, um
MySQL-Optionen für Ihre Verbindung anzugeben, etwa den
Standardzeichensatz oder die Datenbank, die für diese
Verbindung verwendet werden soll.
Auf der Registerkarte Abschnitt 25.1.3.5, „MyODBC: Verbindungsparameter“.
können Sie MyODBC-Verbindungsparameter einstellen. Informationen über die Bedeutung dieser Optionen finden Sie unterDieser Abschnitt beantwortet Fragen im Zusammenhang mit MyODBC-Verbindungen.
Beim Konfigurieren eines MyODBC-DSN
tritt der Fehler Could Not Load Translator or
Setup Library
auf
Weitere Informationen finden Sie im
MS
Knowledge Base Article(Q260558) . Bitte stellen
Sie außerdem sicher, dass Sie die neueste gültige
ctl3d32.dll
in Ihrem
Systemverzeichnis haben.
Auf Windows wird für eine optimale Performance die
myodbc3.dll
kompiliert. Wenn Sie
MyODBC 3.51 debuggen möchten (etwa um Tracing zu
ermöglichen), sollten Sie stattdessen
myodbc3d.dll
verwenden. Um diese
Datei zu installieren, kopieren Sie
myodbc3d.dll
über die installierte
myodbc3.dll
-Datei. Achten Sie darauf,
die Treiber-DLL auf die Release-Version zurückzustellen,
wenn Sie mit dem Debuggen fertig sind, da die
Debugging-Version Leistungsprobleme verursachen kann.
Beachten Sie, dass die
myodbc3d.dll
-Datei in den
MyODBC-Versionen 3.51.07 bis 3.51.11 nicht inbegriffen
ist. Wenn Sie eine dieser Versionen benutzen, müssen Sie
die DLL aus einer Vorversion herüberkopieren (zum
Beispiel aus 3.51.06).
Für MyODBC 2.50 werden stattdessen
myodbc.dll
und
myodbcd.dll
verwendet.
Um einen DSN unter Mac OS X zu konfigurieren, verwenden Sie den ODBC Administrator. Arbeiten Sie mit Mac OS X 10.2 oder älter, schauen Sie in Abschnitt 25.1.3.4, „Konfiguration einer MyODBC-DSN unter Unix“. Bitte wählen Sie aus, ob Sie einen User DSN oder einen System DSN anlegen möchten. Wenn Sie einen System DSN wollen, müssen Sie sich unter Umständen authentifizieren. Hierzu klicken Sie auf das Vorhängeschlosssymbol und geben einen Benutzernamen und ein Passwort mit Administratorrechten an.
Öffnen Sie den ODBC Administrator im
Utilities
-Ordner im Verzeichnis
Applications
.
Klicken Sie unter User DSN oder System DSN auf
.Wählen Sie den MyODBC-Treiber und klicken Sie auf
.
Nun sehen Sie das Dialogfeld Data Source
Name
. Geben Sie hier den Data Source
Name
und eine optionale Beschreibung in das Feld
Description
für den DSN ein.
Mit einem Klick auf server
, username
,
password
und database
.
Siehe
Abschnitt 25.1.3.5, „MyODBC: Verbindungsparameter“.
Mit einem Klick auf
fügen Sie den DSN der Liste der konfigurierten Datenquellennamen hinzu.Eine vollständige DSN-Konfiguration sieht in etwa folgendermaßen aus:
Sie können auch noch weitere ODBC-Optionen für Ihren DSN einrichten, indem Sie weitere Schlüsselwort/Wert-Paare anlegen und die entsprechenden Werte einstellen. Siehe hierzu Abschnitt 25.1.3.5, „MyODBC: Verbindungsparameter“.
Unter Unix
konfigurieren Sie DSN-Einträge
direkt in der Datei odbc.ini
. Hier sehen
Sie eine typische odbc.ini
-Datei, die
myodbc
und myodbc3
als
DSN-Namen für MyODBC 2.50 und MyODBC 3.51 einrichtet:
; ; odbc.ini configuration for MyODBC and MyODBC 3.51 drivers ; [ODBC Data Sources] myodbc = MyODBC 2.50 Driver DSN myodbc3 = MyODBC 3.51 Driver DSN [myodbc] Driver = /usr/local/lib/libmyodbc.so Description = MyODBC 2.50 Driver DSN SERVER = localhost PORT = USER = root Password = Database = test OPTION = 3 SOCKET = [myodbc3] Driver = /usr/local/lib/libmyodbc3.so Description = MyODBC 3.51 Driver DSN SERVER = localhost PORT = USER = root Password = Database = test OPTION = 3 SOCKET = [Default] Driver = /usr/local/lib/libmyodbc3.so Description = MyODBC 3.51 Driver DSN SERVER = localhost PORT = USER = root Password = Database = test OPTION = 3 SOCKET =
In Abschnitt 25.1.3.5, „MyODBC: Verbindungsparameter“, sind die möglichen Verbindungsparameter aufgelistet.
Hinweis: Wenn Sie
unixODBC
benutzen, können Sie den DSN mit
folgenden Tools einrichten:
ODBCConfig GUI-Tool (HOWTO: ODBCConfig)
odbcinst
Gelegentlich tritt bei unixODBC
folgender
Fehler auf:
Data source name not found and no default driver specified
Wenn dies geschieht, müssen Sie sich vergewissern, dass die
Umgebungsvariablen ODBCINI
und
ODBCSYSINI
auf die richtige
odbc.ini
-Datei verweisen. Wenn
beispielsweise Ihre odbc.ini
-Datei unter
/usr/local/etc
liegt, müssen die
Umgebungsvariablen folgendermaßen gesetzt werden:
export ODBCINI=/usr/local/etc/odbc.ini export ODBCSYSINI=/usr/local/etc
Sie können die Parameter aus den folgenden Tabellen für MyODBC
verwenden, wenn Sie einen DSN konfigurieren. Windows-Benutzer
können diese Parameter bei der DSN-Konfiguration in den Feldern
Optionen und Erweitert angeben. Welche Optionen für welche
Felder und Kontrollkästchen da sind, ist der Tabelle zu
entnehmen. Auf Unix und Mac OS X verwenden Sie den
Parameternamen und -wert als Schlüsselwort/Wert-Paar.
Alternativ können Sie diese Parameter in dem
InConnectionString
-Argument im Aufruf von
SQLDriverConnect()
einstellen.
Parameter | Standardwert | Bemerkungen |
user | ODBC (auf Windows) | Der Benutzername für die MySQL-Verbindung. |
server | localhost | Der Hostname des MySQL Servers. |
database | Die Standarddatenbank. | |
option | 0 | Optionen für die Arbeitsweise von MyODBC. Siehe unten. |
port | 3306 | Der TCP/IP-Port, der verwendet wird, wenn server
nicht localhost ist. |
stmt | Eine Anweisung, die bei einer MySQL-Verbindung ausgeführt wird. | |
password | Das Passwort für den user -Account auf dem
server . | |
socket | Die Unix-Socketdatei oder die Named Pipe von Windows, die für die
Verbindung verwendet wird, wenn
server der
localhost ist. |
Das Argument option
teilt MyODBC mit, dass
der Client nicht absolut ODBC-fähig ist. Auf Windows wählt man
Optionen normalerweise aus, indem man die Kontrollkästchen im
Verbindungsbildschirm markiert, aber ebenso gut kann man sie
auch mit dem option
-Argument angeben. Die
folgenden Optionen werden in derselben Reihenfolge wie auf dem
MyODBC-Verbindungsbildschirm aufgeführt:
Wert | Windows-Kontrollkästchen | Beschreibung |
1 | Don't Optimized Column Width | Der Client kann nicht damit umgehen, dass MyODBC die echte Breite einer Spalte zurückgibt. |
2 | Return Matching Rows | Der Client kann nicht damit umgehen, dass MySQL den wirklichen Wert der betroffenen Zeilen zurückgibt. Wenn dieses Flag gesetzt ist, liefert MySQL stattdessen die „gefundenen Zeilen“. Damit dies funktioniert, benötigen Sie MySQL 3.21.14 oder höher. |
4 | Trace Driver Calls To myodbc.log | Erstellt ein Debuglog in C:\myodbc.log auf Windows
bzw. in /tmp/myodbc.log auf
Unix-Varianten. |
8 | Allow Big Results | Es wird keine Größenbegrenzung für Ergebnisse und Parameter eingestellt. |
16 | Don't Prompt Upon Connect | Nicht zu Fragen auffordern, selbst wenn der Treiber dies tun würde. |
32 | Enable Dynamic Cursor | Aktiviert oder deaktiviert Unterstützung für dynamische Cursors. (Unzulässig in MyODBC 2.50.) |
64 | Ignore # in Table Name | Ignoriert Datenbanknamen in
db_name.tbl_name.col_name . |
128 | User Manager Cursors | Erzwingt Benutzung von ODBC-Manager-Cursors (experimentell). |
256 | Don't Use Set Locale | Deaktiviert die Nutzung erweiterter Fetch-Operationen (experimentell). |
512 | Pad Char To Full Length | CHAR -Spalten werden auf die volle Spaltenlänge
aufgefüllt. |
1024 | Return Table Names for SQLDescribeCol | SQLDescribeCol() gibt voll qualifizierte Spaltennamen
zurück. |
2048 | Use Compressed Protocol | Verwendet das komprimierte Client/Server-Protokoll. |
4096 | Ignore Space After Function Names | Lässt den Server Leerraum zwischen Funktionsname und ‘
( ’ ignorieren (nötig für
PowerBuilder). Macht alle Funktionsnamen zu
Schlüsselwörtern. |
8192 | Force Use of Named Pipes | Verbindung über Named Pipes mit einem mysqld-Server, der auf NT läuft. |
16384 | Change BIGINT Columns to Int | Wandelt BIGINT -Spalten in
INT -Spalten um (manche Anwendungen
können mit BIGINT nicht umgehen). |
32768 | No Catalog (exp) | Gibt 'user' als Table_qualifier und
Table_owner von
SQLTables zurück (experimentell). |
65536 | Read Options From my.cnf | Liest Parameter aus den Gruppen [client] und
[odbc] in
my.cnf . |
131072 | Safe | Fügt einige zusätzliche Sicherheitsprüfungen hinzu (eigentlich unnötig, aber ...). |
262144 | Disable transaction | Deaktiviert Transaktionen. |
524288 | Save queries to myodbc.sql | Ermöglicht Anweisungs-Logging in der Datei
c:\myodbc.sql (/tmp/myodbc.sql )
(nur im Debug-Modus aktiviert) |
1048576 | Don't Cache Result (forward only cursors) | Ergebnisse werden nicht lokal im Treiber zwischengespeichert, sondern
vom Server gelesen
(mysql_use_result() ). Das geht nur
bei Forward-only-Cursors. Diese Option ist wichtig für
den Umgang mit großen Tabellen, wenn der Treiber nicht
die ganze Ergebnismenge speichern soll. |
2097152 | Force Use Of Forward Only Cursors | Erzwingt Forward-only -Cursors. Wenn Anwendungen den
Standard-Cursor-Typ static/dynamic einstellen, aber der
Treiber Ergebnismengen nicht im Cache speichern soll,
gewährleistet diese Option das gewünschte
Forward-only-Cursor-Verhalten. |
Um mehrere Optionen auszuwählen, addieren Sie ihre Werte. Wenn
Sie beispielsweise option
auf 12 (4+8)
setzen, bedeutet das Debugging ohne Paketlimits.
Die folgende Tabelle zeigt einige empfohlene
option
-Werte für unterschiedliche
Konfigurationen:
Konfiguration | Optionswert |
Microsoft Access, Visual Basic | 3 |
Treiber-Tracing (Debug-Modus) | 4 |
Microsoft Access (mit verbesserten DELETE-Anfragen) | 35 |
Große Tabellen mit zu vielen Zeilen | 2049 |
Sybase PowerBuilder | 135168 |
Query-Logging (Debug-Modus) | 524288 |
Treiber-Tracing und Query-Logging (Debug-Modus) | 524292 |
Große Tabellen ohne Ergebnis-Caching | 3145731 |
Eine Verbindung zum MySQL Server können Sie mit
SQLDriverConnect unter Angabe des
DRIVER
-Namens herstellen. Die folgenden
Verbindungs-Strings gelten für MyODBC mit
DSN-Less-Verbindungen:
Für MyODBC 2.50:
ConnectionString = "DRIVER={MySQL};\ SERVER=localhost;\ DATABASE=test;\ USER=venu;\ PASSWORD=venu;\ OPTION=3;"
Für MyODBC 3.51:
ConnectionString = "DRIVER={MySQL ODBC 3.51 Driver};\ SERVER=localhost;\ DATABASE=test;\ USER=venu;\ PASSWORD=venu;\ OPTION=3;"
Wenn Ihre Programmiersprache Backslashes mit nachfolgendem Whitespace in ein Leerzeichen umwandelt, sollte der Verbindungs-String besser als ein einziger langer String oder als mehrere verkettete Strings ohne Leerraum dazwischen angegeben werden:
ConnectionString = "DRIVER={MySQL ODBC 3.51 Driver};" "SERVER=localhost;" "DATABASE=test;" "USER=venu;" "PASSWORD=venu;" "OPTION=3;"
Unter Abschnitt 25.1.3.5, „MyODBC: Verbindungsparameter“, finden Sie die möglichen Verbindungsparameter.
Verbindungspooling versetzt den ODBC-Treiber in die Lage, vorhandene Verbindungen zu einer gegebenen Datenbank aus einem Pool von Verbindungen wiederzuverwenden, anstatt sie bei jedem Zugriff auf die betreffende Datenbank wieder neu aufzubauen. Durch Verbindungspooling können Sie also die gesamte Leistung Ihrer Anwendung verbessern, da es weniger lange dauert, eine Verbindung zu einer im Pool befindlichen Datenbank zu öffnen.
Mehr über Verbindungspooling erfahren Sie unter http://support.microsoft.com/default.aspx?scid=kb;EN-US;q169470.
Wenn Sie Schwierigkeiten oder Probleme mit MyODBC haben,
erstellen Sie als Erstes eine Logdatei aus dem ODBC
Manager
und MyODBC. Dieses als
Tracing bezeichnete Vorgehen wird durch
den ODBC Manager ermöglicht. Tracing wird auf Windows, Mac OS X
und Unix in unterschiedlicher Weise eingeschaltet.
Trace-Option auf Windows aktivieren:
Über die Registerkarte Tracing
des
Dialogfelde ODBC Data Source Administrator können Sie
einstellen, wie ODBC-Funktionsaufrufe nachverfolgt werden.
Wenn Sie auf der Registerkarte Tracing
das Tracing eingeschaltet haben, protokolliert der
Treiber-Manager
alle
ODBC-Funktionsaufrufe für alle in der Folgezeit
ausgeführten Anwendungen.
ODBC-Funktionsaufrufe für Anwendungen, die vor Einschaltung des Tracings ausgeführt wurden, werden nicht protokolliert. Die ODBC-Funktionsaufrufe werden in einer von Ihnen vorgegebenen Logdatei festgehalten.
Das Tracing hört erst auf, nachdem Sie auf Stop
tracing now
geklickt haben. Vergessen Sie nicht:
Während das Tracing läuft, wächst die Logdatei immer
weiter an. Überdies beeinträchtigt das Tracing die
Leistung aller Ihrer ODBC-Anwendungen.
Um die Trace-Option unter Mac OS X 10.3 oder höher zu
aktivieren, nutzen Sie die Registerkarte
Tracing
im
ODBC
Administrator
.
Öffnen Sie den ODBC Administrator.
Wählen Sie die Registerkarte Tracing
.
Markieren Sie das Kontrollkästchen Enable
Tracing
.
Geben Sie an, wo das Tracing-Log gespeichert werden soll. Wenn Sie die Daten an eine vorhandene Logdatei anfügen möchten, klicken Sie auf die Schaltfläche
.
Um die Trace-Option unter Mac OS X 10.2 (oder früher) oder
unter Unix einzuschalten, müssen Sie die
trace
-Option zur ODBC-Konfiguration
hinzufügen:
Unter Unix müssen Sie die Trace
-Option
explizit in die Datei ODBC.INI
einfügen.
Das Tracing setzen Sie auf ON
oder
OFF
, indem Sie die Parameter
TraceFile
und Trace
in odbc.ini
wie folgt verwenden:
TraceFile = /tmp/odbc.trace Trace = 1
TraceFile
gibt den Namen und
vollständigen Pfad der Trace-Datei an und
Trace
wird auf ON
oder OFF
gesetzt. Sie können auch
1
oder YES
für
ON
und 0
oder
NO
für OFF
einsetzen. Wenn Sie ODBCConfig von
unixODBC
benutzen, müssen Sie die
Tracing-Anleitung für unixODBC
-Aufrufe
unter
HOWTO-ODBCConfig
befolgen.
Ein MyODBC-Log wird folgendermaßen erstellt:
Unter Windows müssen Sie hierzu das Optionsflag
Trace MyODBC
im Bildschirm für die
MyODBC-Verbindungs- und Konfigurationseinstellungen
aktivieren. Das Log wird in die Datei
C:\myodbc.log
geschrieben. Wird die
Trace-Option nicht berücksichtigt, wenn Sie zum obigen
Bildschirm zurückkehren, so bedeutet dies, dass Sie nicht
den myodbcd.dll
-Treiber benutzen,
siehe auch
Abschnitt 25.1.3.2.4, „Fehler und ihre Behebung“.
Wenn Sie Mac OS X, Unix oder eine Verbindung ohne DSN
verwenden, müssen Sie im Verbindungs-String
OPTION=4
angeben oder in den DSN das
entsprechende Schlüsselwort/Wert-Paar aufnehmen.
Starten Sie Ihre Anwendung und versuchen Sie, einen Absturz herbeizuführen. Dann schauen Sie in der MyODBC-Trace-Datei nach, was schief gegangen ist.
Wenn Sie Hilfe benötigen, um herauszufinden, wo das Problem liegt, schauen Sie in Abschnitt 25.1.7.1, „MyODBC: Community-Support“.
Wenn Sie einen DSN für den Zugriff auf eine Datenbank konfiguriert haben, hängt es von der jeweils verwendeten Anwendung oder Programmiersprache ab, wie diese Verbindung geöffnet und benutzt wird. Da ODBC eine standardisierte Schnittstelle ist, kann jede Anwendung oder Sprache, die ODBC unterstützt, den DSN nutzen und sich mit der konfigurierten Datenbank verbinden.
Anwendungen, die MyODBC benutzen, müssen Folgendes tun, um sich mit einem MySQL Server zu verbinden:
Den MyODBC-DSN konfigurieren
Verbindung zum MySQL Server aufbauen
Initialisierungsoperationen
SQL-Anweisungen ausführen
Ergebnisse abrufen
Transaktionen ausführen
Serververbindung trennen
Diese Schritte werden von den Anwendungen mit einigen Variationen ausgeführt. Das folgende Diagramm zeigt den grundsätzlichen Ablauf:
Eine typische Situation, in der MyODBC installiert würde, tritt ein, wenn man von einem Windows-Rechner aus auf eine Datenbank zugreifen möchte, die auf einem Linux- oder Unix-Host läuft.
Um ein Beispiel zu geben, wie man den Zugriff zwischen den
beiden Computern einrichten könnte, zeigen wir im Folgenden die
wichtigsten Schritte. Wir gehen davon aus, dass Sie sich vom
System BETA aus mit dem Benutzernamen myuser
und dem Passwort mypassword
mit dem System
ALPHA verbinden.
Auf dem System ALPHA (dem MySQL Server) sind folgende Schritte erforderlich:
Sie starten den MySQL Server.
Sie richten mit GRANT
ein Konto mit dem
Benutzernamen myuser
ein, das sich vom
System BETA aus mit dem Passwort myuser
mit der Datenbank test
verbinden darf:
GRANT ALL ON test.* to 'myuser'@'BETA' IDENTIFIED BY 'mypassword';
Genaueres über die Berechtigungen von MySQL lesen Sie unter Abschnitt 5.9, „MySQL-Benutzerkontenverwaltung“.
Auf dem System BETA (dem MyODBC-Client) gehen Sie folgendermaßen vor:
Sie konfigurieren einen MyODBC-DSN mit den passenden Parametern für Server, Datenbank und Authentifizierungsdaten, wie Sie sie gerade auf dem System ALPHA eingerichtet haben.
Parameter | Wert | Bemerkungen |
DSN | remote_test | Der Name der Verbindung |
SERVER | ALPHA | Die Adresse des Remote-Servers |
DATABASE | test | Der Name der Standarddatenbank |
USER | myuser | Der Benutzername, der für den Zugriff auf diese Datenbank konfiguriert wurde |
PASSWORD | mypassword | Das Passwort für myuser |
Sie verbinden sich mit einer ODBC-fähigen Anwendung, wie etwa Microsoft Office, unter Verwendung des soeben angelegten DSN mit dem MySQL Server. Scheitert die Verbindung, so untersuchen Sie den Verbindungsprozess mit Tracing. Weitere Informationen finden Sie unter Abschnitt 25.1.3.8, „Erzeugen einer ODBC-Trace-Datei“.
Wenn Sie Ihren MyODBC DSN konfiguriert haben, können Sie mit jeder Anwendung, die die ODBC-Schnittstelle unterstützt, auf die MySQL-Datenbank zugreifen, auch mit Programmiersprachen und Anwendungen von Drittanbietern. Dieser Abschnitt verrät Ihnen, wie man MyODBC mit verschiedenen ODBC-kompatiblen Tools und Anwendungen einsetzt, darunter Microsoft Word, Microsoft Excel und Adobe/Macromedia ColdFusion.
MyODBC wurde mit folgenden Anwendungen getestet:
Hersteller | Anwendung | Hinweise |
Adobe | ColdFusion | Früher Macromedia ColdFusion |
Borland | C++ Builder | |
Builder 4 | ||
Delphi | ||
Business Objects | Crystal Reports | |
Claris | Filemaker Pro | |
Corel | Paradox | |
Computer Associates | Visual Objects | Auch CAVO genannt |
AllFusion ERwin Data Modeler | ||
Gupta | Team Developer | Früher bekannt als Centura Team Developer; Gupta SQL/Windows |
Gensym | G2-ODBC Bridge | |
Inline | iHTML | |
Lotus | Notes | Versionen 4.5 und 4.6 |
Microsoft | Access | |
Excel | ||
Visio Enterprise | ||
Visual C++ | ||
Visual Basic | ||
ODBC.NET | Mit C#, Visual Basic, C++ | |
FoxPro | ||
Visual Interdev | ||
OpenOffice.org | OpenOffice.org | |
Perl | DBD::ODBC | |
Pervasive Software | DataJunction | |
Sambar Technologies | Sambar Server | |
SPSS | SPSS | |
SoftVelocity | Clarion | |
SQLExpress | SQLExpress for Xbase++ | |
Sun | StarOffice | |
SunSystems | Vision | |
Sybase | PowerBuilder | |
PowerDesigner | ||
theKompany.com | Data Architect |
Wenn Sie von anderen Anwendungen wissen, dass sie mit MyODBC
funktionieren, melden Sie sie bitte per E-Mail an
<myodbc@lists.mysql.com>
.
Sie können Microsoft Word und Microsoft Excel nutzen, um auf Daten einer MySQL-Datenbank mithilfe von MyODBC zuzugreifen. In Microsoft Word ist diese Fähigkeit besonders nützlich, wenn Daten für einen Serienbrief importiert oder Tabellen und Daten in Reports eingebunden werden sollen. In Microsoft Excel können Sie Anfragen auf Ihrem MySQL Server verarbeiten und die Daten direkt in ein Excel-Arbeitsblatt importieren, wo sie dann in Form von Zeilen und Spalten dargestellt werden.
In beiden Anwendungen werden die Daten mit Microsoft Query abgefragt und importiert. Diese Anwendung kann eine Anfrage über eine ODBC-Quelle ausführen. Sie erstellen mit Microsoft Query die SQL-Anweisung, die ausgeführt werden soll, und wählen dabei die Tabellen, Felder, Auswahlkriterien und Sortierreihenfolge. Um beispielsweise Tabellendaten aus einer Tabelle der Testdatenbank World in ein Excel-Arbeitsblatt einzufügen und dazu die DSN-Beispiele aus Abschnitt 25.1.3, „MyODBC: Konfiguration“, zu verwenden, gehen Sie folgendermaßen vor:
Sie legen ein neues Arbeitsblatt an.
Sie wählen aus dem Menü Daten
den
Befehl Externe Daten importieren
und
dann Neue Abfrage erstellen
.
Microsoft Query fährt jetzt hoch. Als Erstes müssen Sie nun die Datenquelle auswählen, indem Sie einen vorhandenen Data Source Name aussuchen.
Im Query-Assistenten
müssen Sie die zu
importierenden Spalten auswählen. Die Liste der Tabellen,
die dem Benutzer über den konfigurierten DSN zur
Verfügung stehen, wird links angezeigt, und die Spalten,
die der Anfrage hinzugefügt werden, rechts. Die Spalten,
die Sie wählen, entsprechen denen, die im ersten
Abschnitt einer SELECT
-Anfrage
erscheinen. Klicken Sie auf ,
um fortzufahren.
Die Spalten der Anfrage können Sie mit dem
Filter Data
-Dialog filtern (wie mit
einer WHERE
-Klausel) . Klicken Sie nun
wieder auf .
Wählen Sie eine (optionale) Sortierreihenfolge für die
Daten. Dies entspricht einer ORDER
BY
-Klausel in einer SQL-Anfrage. Bis zu drei
Felder können Sie auswählen, um die Rückgabedaten der
Anfrage zu sortieren. Nun klicken Sie wieder auf
.
Nun wählen Sie das Zielobjekt für Ihre Anfrage, beispielsweise Microsoft Excel. Hier können Sie aussuchen, in welches Arbeitsblatt und welche Zelle die Daten eingefügt werden sollen. Sie können dann die Anfrage und Ergebnisse in Microsoft Query anzeigen lassen, wo Sie die SQL-Anfrage weiter bearbeiten und die Rückgabedaten weiter filtern und sortieren können; oder Sie erstellen aus der Anfrage einen OLAP Cube, der dann direkt in Microsoft Excel verwendet werden kann. Klicken Sie nun auf
.Mit demselben Verfahren können Sie Daten auch in ein Word-Dokument importieren, wo sie in Form einer Tabelle eingefügt werden. Dies kann für Serienbriefe genutzt werden (wo die Felddaten aus einer Word-Tabelle gelesen werden) oder auch zum Einbinden von Daten und Berichten in einen anderen Bericht oder ein Dokument.
Unter Verwendung von MyODBC können Sie MySQL-Datenbanken auch mit Microsoft Access benutzen. Die MySQL-Datenbank kann als Importquelle, als Exportquelle oder als verknüpfte Tabelle verwendet werden, die direkt in einer Access-Anwendung eingesetzt wird. So wird Access zu einem Frontend einer MySQL-Datenbank.
Um eine Tabelle mit Daten aus einer Access-Datenbank in MySQL zu importieren, verfahren Sie wie folgt:
Wenn Sie eine Access-Datenbank oder ein Access-Projekt öffnen, erscheint ein Datenbankfenster. Hier können Sie mit Shortcuts neue Datenbankobjekte erzeugen oder vorhandene öffnen.
Klicken Sie auf den Namen der zu exportierenden
table
oder query
und wählen Sie dann im Menü Datei
(File)
den Befehl Exportieren
(Export)
.
Im Dialogfeld Export Object Type
wählen Sie im Feld Objektname
ToSpeichern unter (Save
as)
den Punkt ODBC Databases
()
:
Im Dialogfeld Exportieren (Export)
geben Sie einen Namen für die Datei ein (oder
akzeptieren den Namensvorschlag) und wählen dann
OK
.
Im Dialogfeld zur Auswahl der Datenquelle werden die definierten Datenquellen für alle auf Ihrem Computer installierten ODBC-Treiber aufgelistet. Klicken Sie hier auf die Registerkarte Dateidatenquelle oder Maschinendatenquelle und setzen Sie dann einen Doppelklick auf die MyODBC- oder MyODBC-3.51-Datenquelle, in die Sie Daten exportieren möchten. Wie eine neue Datenquelle für MyODBC definiert wird, erfahren Sie unter Abschnitt 25.1.3.2, „Konfiguration einer MyODBC-DSN unter Windows“.
Microsoft Access verbindet sich über diese Datenquelle mit dem MySQL Server und exportiert dann neue Tabellen und/oder Daten.
Um einen Link oder eine oder mehrere Tabellen von MySQL in Access zu importieren, gehen Sie folgendermaßen vor:
Sie öffnen eine Datenbank oder gehen in das Datenbankfenster und öffnen sie dort.
Um Tabellen zu importieren, zeigen Sie im
Datei
-Menü auf Externe
Daten abrufen
und klicken dann auf
Importieren
. Um Tabellen zu
verknüpfen, zeigen Sie im Dateimenü auf
Externe Daten abrufen
und klicken
dann auf Tabellen verknüpfen
.
Im Dialogfeld Import
(oder
Verknüpfen
) wählen Sie im Feld
Dateityp den Eintrag ODBC
Databases ()
. Das Dialogfeld
Datenquelle wählen führt die
definierten Datenquellen auf.
Wenn für die gewünschte ODBC-Datenquelle eine
Anmeldung erforderlich ist, geben Sie Ihren
Benutzernamen und Ihr Passwort ein (sowie eventuell
erforderliche Zusatzinformationen) und klicken dann auf
OK
.
Microsoft Access verbindet sich mit dem MySQL Server
über die ODBC-Datenquelle
und zeigt
die Liste der Tabellen an, die Sie
importieren
oder
verknüpfen
können.
Klicken Sie nun alle Tabellen an, die Sie
importieren
oder
verknüpfen
möchten, und klicken Sie
dann auf OK
. Wenn Sie eine Tabelle
verknüpfen, die keinen Index besitzt, über den
Datensätze eindeutig identifiziert werden können,
zeigt Microsoft Access eine Liste der Felder dieser
verknüpften Tabelle an. Klicken Sie auf ein Feld oder
eine Feldkombination, die Datensätze eindeutig
identifiziert, und dann auf OK
.
Mit folgendem Verfahren können Sie Verknüpfungen anzeigen oder aktualisieren, wenn sich die Struktur oder der Speicherort einer verknüpften Tabelle geändert hat. Der Verknüpfungsassistent führt die Pfade aller Tabellen auf, die gerade verknüpft sind.
Verknüpfungen anzeigen oder aktualisieren:
Öffnen Sie die Datenbank, die die Verknüpfungen zu den Tabellen enthält.
Zeigen Sie im Menü Extras
auf
Add-ins
(Datenbank-Utilities
in Access 2000
oder höher) und klicken Sie dann auf
Verknüpfungsassistent
.
Markieren Sie die Kontrollkästchen der Tabellen, deren Links Sie aktualisieren möchten.
Mit einem Klick auf OK werden die Verknüpfungen aktualisiert.
Microsoft Access bestätigt eine erfolgreiche Aktualisierung
oder zeigt, wenn die Tabelle nicht gefunden wurde, das
Dialogfeld Neuen Speicherort wählen für
<table name> an, in welchem Sie den neuen Speicherort
der Tabelle eingeben können. Wenn mehrere der ausgewählten
Tabellen an den neuen Speicherort verschoben wurden,
durchsucht der Verknüpfungsassistent diesen Ort nach allen
diesen Tabellen und aktualisiert die Verknüpfungen in einem
einzigen Durchgang.
Pfad für mehrere verknüpfte Tabellen ändern:
Öffnen Sie die Datenbank, die die Verknüpfungen zu den Tabellen enthält.
Zeigen Sie im Menü Extras
auf
Add-ins
(Datenbank-Utilities
in Access 2000
oder höher) und klicken Sie dann auf
Verknüpfungsassistent
.
Markieren Sie das Kontrollkästchen Bei neuem
Speicherort immer nachfragen
.
Markieren Sie die Kontrollkästchen der Tabellen, deren
Verknüpfungen Sie ändern möchten, und klicken Sie auf
OK
.
Geben Sie im Dialogfeld Neuen Speicherort
wählen für
den
neuen Speicherort ein und klicken Sie auf
tabellenname
Öffnen
und dann auf
OK
.
Wenn ein geeigneter ODBC-Manager und der MyODBC-Treiber installiert sind, müsste jede Programmiersprache und Umgebung, die ODBC unterstützt, über MyODBC mit einer MySQL-Datenbank Verbindung aufnehmen können.
Dazu gehören auch (aber natürlich nicht nur) die Microsoft-Sprachen (Visual Basic, C# und Schnittstellen wie ODBC.NET) und Perl (über das DBI-Modul und den DBD::ODBC-Treiber).
Dieser Abschnitt zeigt einfache Beispiele für die Verwendung des MySQL ODBC 3.51-Treibers mit ADO, DAO und RDO.
Das folgende ADO(ActiveX Data Objects)-Beispiel legt eine
Tabelle an (my_ado
) und demonstriert die
Verwendung von rs.addNew
,
rs.delete
und
rs.update
.
Private Sub myodbc_ado_Click() Dim conn As ADODB.Connection Dim rs As ADODB.Recordset Dim fld As ADODB.Field Dim sql As String 'connect to MySQL server using MySQL ODBC 3.51 Driver Set conn = New ADODB.Connection conn.ConnectionString = "DRIVER={MySQL ODBC 3.51 Driver};"_ & "SERVER=localhost;"_ & " DATABASE=test;"_ & "UID=venu;PWD=venu; OPTION=3" conn.Open 'create table conn.Execute "DROP TABLE IF EXISTS my_ado" conn.Execute "CREATE TABLE my_ado(id int not null primary key, name varchar(20)," _ & "txt text, dt date, tm time, ts timestamp)" 'direct insert conn.Execute "INSERT INTO my_ado(id,name,txt) values(1,100,'venu')" conn.Execute "INSERT INTO my_ado(id,name,txt) values(2,200,'MySQL')" conn.Execute "INSERT INTO my_ado(id,name,txt) values(3,300,'Delete')" Set rs = New ADODB.Recordset rs.CursorLocation = adUseServer 'fetch the initial table .. rs.Open "SELECT * FROM my_ado", conn Debug.Print rs.RecordCount rs.MoveFirst Debug.Print String(50, "-") & "Initial my_ado Result Set " & String(50, "-") For Each fld In rs.Fields Debug.Print fld.Name, Next Debug.Print Do Until rs.EOF For Each fld In rs.Fields Debug.Print fld.Value, Next rs.MoveNext Debug.Print Loop rs.Close 'rs insert rs.Open "select * from my_ado", conn, adOpenDynamic, adLockOptimistic rs.AddNew rs!Name = "Monty" rs!txt = "Insert row" rs.Update rs.Close 'rs update rs.Open "SELECT * FROM my_ado" rs!Name = "update" rs!txt = "updated-row" rs.Update rs.Close 'rs update second time.. rs.Open "SELECT * FROM my_ado" rs!Name = "update" rs!txt = "updated-second-time" rs.Update rs.Close 'rs delete rs.Open "SELECT * FROM my_ado" rs.MoveNext rs.MoveNext rs.Delete rs.Close 'fetch the updated table .. rs.Open "SELECT * FROM my_ado", conn Debug.Print rs.RecordCount rs.MoveFirst Debug.Print String(50, "-") & "Updated my_ado Result Set " & String(50, "-") For Each fld In rs.Fields Debug.Print fld.Name, Next Debug.Print Do Until rs.EOF For Each fld In rs.Fields Debug.Print fld.Value, Next rs.MoveNext Debug.Print Loop rs.Close conn.Close End Sub
Das folgende DAO(Data Access Objects)-Beispiel legt die
Tabelle my_dao
an und demonstriert die
Verwendung von rs.addNew
,
rs.update
und Ergebnismengen-Scrolling.
Private Sub myodbc_dao_Click() Dim ws As Workspace Dim conn As Connection Dim queryDef As queryDef Dim str As String 'connect to MySQL using MySQL ODBC 3.51 Driver Set ws = DBEngine.CreateWorkspace("", "venu", "venu", dbUseODBC) str = "odbc;DRIVER={MySQL ODBC 3.51 Driver};"_ & "SERVER=localhost;"_ & " DATABASE=test;"_ & "UID=venu;PWD=venu; OPTION=3" Set conn = ws.OpenConnection("test", dbDriverNoPrompt, False, str) 'Create table my_dao Set queryDef = conn.CreateQueryDef("", "drop table if exists my_dao") queryDef.Execute Set queryDef = conn.CreateQueryDef("", "create table my_dao(Id INT AUTO_INCREMENT PRIMARY KEY, " _ & "Ts TIMESTAMP(14) NOT NULL, Name varchar(20), Id2 INT)") queryDef.Execute 'Insert new records using rs.addNew Set rs = conn.OpenRecordset("my_dao") Dim i As Integer For i = 10 To 15 rs.AddNew rs!Name = "insert record" & i rs!Id2 = i rs.Update Next i rs.Close 'rs update.. Set rs = conn.OpenRecordset("my_dao") rs.Edit rs!Name = "updated-string" rs.Update rs.Close 'fetch the table back... Set rs = conn.OpenRecordset("my_dao", dbOpenDynamic) str = "Results:" rs.MoveFirst While Not rs.EOF str = " " & rs!Id & " , " & rs!Name & ", " & rs!Ts & ", " & rs!Id2 Debug.Print "DATA:" & str rs.MoveNext Wend 'rs Scrolling rs.MoveFirst str = " FIRST ROW: " & rs!Id & " , " & rs!Name & ", " & rs!Ts & ", " & rs!Id2 Debug.Print str rs.MoveLast str = " LAST ROW: " & rs!Id & " , " & rs!Name & ", " & rs!Ts & ", " & rs!Id2 Debug.Print str rs.MovePrevious str = " LAST-1 ROW: " & rs!Id & " , " & rs!Name & ", " & rs!Ts & ", " & rs!Id2 Debug.Print str 'free all resources rs.Close queryDef.Close conn.Close ws.Close End Sub
Das folgende RDO(Remote Data Objects)-Beispiel legt die
Tabelle my_rdo
an und demonstriert die
Verwendung von rs.addNew
und
rs.update
.
Dim rs As rdoResultset Dim cn As New rdoConnection Dim cl As rdoColumn Dim SQL As String 'cn.Connect = "DSN=test;" cn.Connect = "DRIVER={MySQL ODBC 3.51 Driver};"_ & "SERVER=localhost;"_ & " DATABASE=test;"_ & "UID=venu;PWD=venu; OPTION=3" cn.CursorDriver = rdUseOdbc cn.EstablishConnection rdDriverPrompt 'drop table my_rdo SQL = "drop table if exists my_rdo" cn.Execute SQL, rdExecDirect 'create table my_rdo SQL = "create table my_rdo(id int, name varchar(20))" cn.Execute SQL, rdExecDirect 'insert - direct SQL = "insert into my_rdo values (100,'venu')" cn.Execute SQL, rdExecDirect SQL = "insert into my_rdo values (200,'MySQL')" cn.Execute SQL, rdExecDirect 'rs insert SQL = "select * from my_rdo" Set rs = cn.OpenResultset(SQL, rdOpenStatic, rdConcurRowVer, rdExecDirect) rs.AddNew rs!id = 300 rs!Name = "Insert1" rs.Update rs.Close 'rs insert SQL = "select * from my_rdo" Set rs = cn.OpenResultset(SQL, rdOpenStatic, rdConcurRowVer, rdExecDirect) rs.AddNew rs!id = 400 rs!Name = "Insert 2" rs.Update rs.Close 'rs update SQL = "select * from my_rdo" Set rs = cn.OpenResultset(SQL, rdOpenStatic, rdConcurRowVer, rdExecDirect) rs.Edit rs!id = 999 rs!Name = "updated" rs.Update rs.Close 'fetch back... SQL = "select * from my_rdo" Set rs = cn.OpenResultset(SQL, rdOpenStatic, rdConcurRowVer, rdExecDirect) Do Until rs.EOF For Each cl In rs.rdoColumns Debug.Print cl.Value, Next rs.MoveNext Debug.Print Loop Debug.Print "Row count="; rs.RowCount 'close rs.Close cn.Close End Sub
Dieser Abschnitt zeigt einfache Beispiele für die Verwendung von MyODBC-Treibern mit ODBC.NET.
Das folgende Beispiel legt die Tabelle
my_odbc_net
an und demonstriert ihre
Verwendung in C#.
/**
* @sample : mycon.cs
* @purpose : Demo sample for ODBC.NET using MyODBC
* @author : Venu, <myodbc@lists.mysql.com>
*
* (C) Copyright MySQL AB, 1995-2006
*
**/
/* Build-Befehl
*
* csc /t:exe
* /out:mycon.exe mycon.cs
* /r:Microsoft.Data.Odbc.dll
*/
using Console = System.Console;
using Microsoft.Data.Odbc;
namespace myodbc3
{
class mycon
{
static void Main(string[] args)
{
try
{
//Verbindungs-String für MyODBC 2.50
/*string MyConString = "DRIVER={MySQL};" +
"SERVER=localhost;" +
"DATABASE=test;" +
"UID=venu;" +
"PASSWORD=venu;" +
"OPTION=3";
*/
//Verbindungs-String für MyODBC 3.51
string MyConString = "DRIVER={MySQL ODBC 3.51 Driver};" +
"SERVER=localhost;" +
"DATABASE=test;" +
"UID=venu;" +
"PASSWORD=venu;" +
"OPTION=3";
//Verbindung zu MySQL mittels MyODBC
OdbcConnection MyConnection = new OdbcConnection(MyConString);
MyConnection.Open();
Console.WriteLine("\n !!! success, connected successfully !!!\n");
//Verbindungs-Informationen anzeigen
Console.WriteLine("Connection Information:");
Console.WriteLine("\tConnection String:" +
MyConnection.ConnectionString);
Console.WriteLine("\tConnection Timeout:" +
MyConnection.ConnectionTimeout);
Console.WriteLine("\tDatabase:" +
MyConnection.Database);
Console.WriteLine("\tDataSource:" +
MyConnection.DataSource);
Console.WriteLine("\tDriver:" +
MyConnection.Driver);
Console.WriteLine("\tServerVersion:" +
MyConnection.ServerVersion);
//Beispieltabelle anlegen
OdbcCommand MyCommand =
new OdbcCommand("DROP TABLE IF EXISTS my_odbc_net",
MyConnection);
MyCommand.ExecuteNonQuery();
MyCommand.CommandText =
"CREATE TABLE my_odbc_net(id int, name varchar(20), idb bigint)";
MyCommand.ExecuteNonQuery();
//Insert
MyCommand.CommandText =
"INSERT INTO my_odbc_net VALUES(10,'venu', 300)";
Console.WriteLine("INSERT, Total rows affected:" +
MyCommand.ExecuteNonQuery());;
//Insert
MyCommand.CommandText =
"INSERT INTO my_odbc_net VALUES(20,'mysql',400)";
Console.WriteLine("INSERT, Total rows affected:" +
MyCommand.ExecuteNonQuery());
//Insert
MyCommand.CommandText =
"INSERT INTO my_odbc_net VALUES(20,'mysql',500)";
Console.WriteLine("INSERT, Total rows affected:" +
MyCommand.ExecuteNonQuery());
//Update
MyCommand.CommandText =
"UPDATE my_odbc_net SET id=999 WHERE id=20";
Console.WriteLine("Update, Total rows affected:" +
MyCommand.ExecuteNonQuery());
//COUNT(*)
MyCommand.CommandText =
"SELECT COUNT(*) as TRows FROM my_odbc_net";
Console.WriteLine("Total Rows:" +
MyCommand.ExecuteScalar());
//Fetch
MyCommand.CommandText = "SELECT * FROM my_odbc_net";
OdbcDataReader MyDataReader;
MyDataReader = MyCommand.ExecuteReader();
while (MyDataReader.Read())
{
if(string.Compare(MyConnection.Driver,"myodbc3.dll") == 0) {
//Nur von MyODBC 3.51 unterstützt
Console.WriteLine("Data:" + MyDataReader.GetInt32(0) + " " +
MyDataReader.GetString(1) + " " +
MyDataReader.GetInt64(2));
}
else {
//BIGINTs werden von MyODBC nicht unterstützt
Console.WriteLine("Data:" + MyDataReader.GetInt32(0) + " " +
MyDataReader.GetString(1) + " " +
MyDataReader.GetInt32(2));
}
}
//Alle Ressourcen schließen
MyDataReader.Close();
MyConnection.Close();
}
catch (OdbcException MyOdbcException) //Catch any ODBC exception ..
{
for (int i=0; i < MyOdbcException.Errors.Count; i++)
{
Console.Write("ERROR #" + i + "\n" +
"Message: " +
MyOdbcException.Errors[i].Message + "\n" +
"Native: " +
MyOdbcException.Errors[i].NativeError.ToString() + "\n" +
"Source: " +
MyOdbcException.Errors[i].Source + "\n" +
"SQL: " +
MyOdbcException.Errors[i].SQLState + "\n");
}
}
}
}
}
Das folgende Beispiel legt die Tabelle
my_vb_net
an und demonstriert ihre
Verwendung in VB.
' @sample : myvb.vb
' @purpose : Demo sample for ODBC.NET using MyODBC
' @author : Venu, <myodbc@lists.mysql.com>
'
' (C) Copyright MySQL AB, 1995-2006
'
'
'
' build command
'
' vbc /target:exe
' /out:myvb.exe
' /r:Microsoft.Data.Odbc.dll
' /r:System.dll
' /r:System.Data.dll
'
Imports Microsoft.Data.Odbc
Imports System
Module myvb
Sub Main()
Try
'MyODBC 3.51 connection string
Dim MyConString As String = "DRIVER={MySQL ODBC 3.51 Driver};" & _
"SERVER=localhost;" & _
"DATABASE=test;" & _
"UID=venu;" & _
"PASSWORD=venu;" & _
"OPTION=3;"
'Connection
Dim MyConnection As New OdbcConnection(MyConString)
MyConnection.Open()
Console.WriteLine("Connection State::" & MyConnection.State.ToString)
'Drop
Console.WriteLine("Dropping table")
Dim MyCommand As New OdbcCommand()
MyCommand.Connection = MyConnection
MyCommand.CommandText = "DROP TABLE IF EXISTS my_vb_net"
MyCommand.ExecuteNonQuery()
'Create
Console.WriteLine("Creating....")
MyCommand.CommandText = "CREATE TABLE my_vb_net(id int, name varchar(30))"
MyCommand.ExecuteNonQuery()
'Insert
MyCommand.CommandText = "INSERT INTO my_vb_net VALUES(10,'venu')"
Console.WriteLine("INSERT, Total rows affected:" & _
MyCommand.ExecuteNonQuery())
'Insert
MyCommand.CommandText = "INSERT INTO my_vb_net VALUES(20,'mysql')"
Console.WriteLine("INSERT, Total rows affected:" & _
MyCommand.ExecuteNonQuery())
'Insert
MyCommand.CommandText = "INSERT INTO my_vb_net VALUES(20,'mysql')"
Console.WriteLine("INSERT, Total rows affected:" & _
MyCommand.ExecuteNonQuery())
'Insert
MyCommand.CommandText = "INSERT INTO my_vb_net(id) VALUES(30)"
Console.WriteLine("INSERT, Total rows affected:" & _
MyCommand.ExecuteNonQuery())
'Update
MyCommand.CommandText = "UPDATE my_vb_net SET id=999 WHERE id=20"
Console.WriteLine("Update, Total rows affected:" & _
MyCommand.ExecuteNonQuery())
'COUNT(*)
MyCommand.CommandText = "SELECT COUNT(*) as TRows FROM my_vb_net"
Console.WriteLine("Total Rows:" & MyCommand.ExecuteScalar())
'Select
Console.WriteLine("Select * FROM my_vb_net")
MyCommand.CommandText = "SELECT * FROM my_vb_net"
Dim MyDataReader As OdbcDataReader
MyDataReader = MyCommand.ExecuteReader
While MyDataReader.Read
If MyDataReader("name") Is DBNull.Value Then
Console.WriteLine("id = " & _
CStr(MyDataReader("id")) & " name = " & _
"NULL")
Else
Console.WriteLine("id = " & _
CStr(MyDataReader("id")) & " name = " & _
CStr(MyDataReader("name")))
End If
End While
'Catch ODBC Exception
Catch MyOdbcException As OdbcException
Dim i As Integer
Console.WriteLine(MyOdbcException.ToString)
'Catch program exception
Catch MyException As Exception
Console.WriteLine(MyException.ToString)
End Try
End Sub
Der vorliegende Abschnitt enthält Referenzmaterial für die MyODBC-API, zeigt die unterstützten Funktionen und Methoden, die MySQL-Spaltentypen und die entsprechenden nativen Typen in MyODBC sowie die von MyODBC zurückgegebenen Fehlercodes.
Dieser Abschnitt fasst ODBC-Routinen nach Funktionalität zusammen.
Die vollständige Referenz zur ODBC-API finden Sie in der ODBC Programmer's Reference unter http://msdn.microsoft.com/library/en-us/odbc/htm/odbcabout_this_manual.asp.
Eine Anwendung kann die Funktion SQLGetInfo
aufrufen, um Konformitätsinformationen über MyODBC einzuholen.
Ob der Treiber eine bestimmte Funktion unterstützt, kann eine
Anwendung mit SQLGetFunctions
in Erfahrung
bringen.
Hinweis: Zur Abwärtskompatibilität unterstützt der MyODBC 3.51-Treiber auch die veralteten Funktionen.
Die folgenden Tabellen zeigen die MyODBC-API-Funktionsaufrufe nach Aufgabenbereich:
Verbindung mit einer Datenquelle:
MyODBC | ||||
Funktionsname | 2.50 | 3.51 | Standard | Zweck |
SQLAllocHandle | Nein | Ja | ISO 92 | Beschafft einen Handle für Umgebung, Verbindung, Anweisung oder Deskriptor. |
SQLConnect | Ja | Ja | ISO 92 | Verbindet sich mit einem konkreten Treiber über Data Source Name, Benutzername und Passwort. |
SQLDriverConnect | Ja | Ja | ODBC | Verbindet sich mit einem konkreten Treiber über einen Verbindungs-String oder verlangt, dass der Treiber-Manager und Treiber Verbindungsdialogfelder für den Benutzer anzeigen. |
SQLAllocEnv | Ja | Ja | Veraltet | Beschafft einen vom Treiber zugewiesenen Umgebungs-Handle. |
SQLAllocConnect | Ja | Ja | Veraltet | Beschafft einen Verbindungs-Handle |
Informationen über einen Treiber und Datenquellen beschaffen:
MyODBC | ||||
Funktionsname | 2.50 | 3.51 | Standard | Zweck |
SQLDataSources | Nein | Nein | ISO 92 | Liefert eine Liste der verfügbaren Datenquellen, mit denen der Treiber-Manager umgehen kann. |
SQLDrivers | Nein | Nein | ODBC | Liefert eine Liste der installierten Treiber und ihrer Attribute, mit denen der Treiber-Manager umgehen kann. |
SQLGetInfo | Ja | Ja | ISO 92 | Liefert Informationen über einen spezifischen Treiber und eine Datenquelle. |
SQLGetFunctions | Ja | Ja | ISO 92 | Zeigt die unterstützten Treiberfunktionen an. |
SQLGetTypeInfo | Ja | Ja | ISO 92 | Gibt Informationen über die unterstützten Datentypen. |
Treiberattribute einstellen und abfragen:
MyODBC | ||||
Funktionsname | 2.50 | 3.51 | Standard | Zweck |
SQLSetConnectAttr | Nein | Ja | ISO 92 | Setzt ein Verbindungsattribut. |
SQLGetConnectAttr | Nein | Ja | ISO 92 | Gibt den Wert eines Verbindungsattributs zurück. |
SQLSetConnectOption | Ja | Ja | Veraltet | Setzt eine Verbindungsoption. |
SQLGetConnectOption | Ja | Ja | Veraltet | Gibt den Wert einer Verbindungsoption zurück. |
SQLSetEnvAttr | Nein | Ja | ISO 92 | Setzt ein Umgebungsattribut. |
SQLGetEnvAttr | Nein | Ja | ISO 92 | Gibt den Wert eines Umgebungsattributs zurück. |
SQLSetStmtAttr | Nein | Ja | ISO 92 | Setzt ein Anweisungsattribut. |
SQLGetStmtAttr | Nein | Ja | ISO 92 | Gibt den Wert eines Anweisungsattributs zurück. |
SQLSetStmtOption | Ja | Ja | Veraltet | Setzt eine Anweisungsoption. |
SQLGetStmtOption | Ja | Ja | Veraltet | Gibt den Wert einer Anweisungsoption zurück. |
Vorbereitung von SQL-Requests:
MyODBC | ||||
Funktionsname | 2.50 | 3.51 | Standard | Zweck |
SQLAllocStmt | Ja | Ja | Veraltet | Weist einen Anweisungs-Handle zu. |
SQLPrepare | Ja | Ja | ISO 92 | Bereitet eine SQL-Anweisung zur späteren Ausführung vor. |
SQLBindParameter | Ja | Ja | ODBC | Weist Speicher für einen Parameter in einer SQL-Anweisung zu. |
SQLGetCursorName | Ja | Ja | ISO 92 | Gibt den mit einem Anweisungs-Handle verbundenen Cursor-Namen zurück. |
SQLSetCursorName | Ja | Ja | ISO 92 | Gibt einen Cursor-Namen an. |
SQLSetScrollOptions | Ja | Ja | ODBC | Setzt Optionen zur Steuerung des Cursor-Verhaltens. |
Übermittlung von Requests:
MyODBC | ||||
Funktionsname | 2.50 | 3.51 | Standard | Zweck |
SQLExecute | Ja | Ja | ISO 92 | Führt eine vorbereitete Anweisung aus. |
SQLExecDirect | Ja | Ja | ISO 92 | Führt eine Anweisung aus. |
SQLNativeSql | Ja | Ja | ODBC | Gibt den Text einer vom Treiber übersetzten SQL-Anweisung zurück. |
SQLDescribeParam | Ja | Ja | ODBC | Gibt die Beschreibung eines bestimmten Parameters in einer Anweisung zurück. |
SQLNumParams | Ja | Ja | ISO 92 | Gibt die Anzahl der Parameter in einer Anweisung zurück. |
SQLParamData | Ja | Ja | ISO 92 | Wird in Verbindung mit SQLPutData verwendet, um
Parameterdaten zur Ausführungszeit zu liefern.
(Nützlich für lange Datenwerte.) |
SQLPutData | Ja | Ja | ISO 92 | Sendet einen Datenwert eines Parameters ganz oder teilweise. (Nützlich für lange Datenwerte.) |
Ergebnisse und Ergebnisinformationen abrufen:
MyODBC | ||||
Funktionsname | 2.50 | 3.51 | Standard | Zweck |
SQLRowCount | Ja | Ja | ISO 92 | Meldet, wie viele Zeilen von einem Insert, Update oder Delete betroffen wurden. |
SQLNumResultCols | Ja | Ja | ISO 92 | Meldet die Anzahl der Zeilen in der Ergebnismenge. |
SQLDescribeCol | Ja | Ja | ISO 92 | Beschreibt eine Spalte der Ergebnismenge. |
SQLColAttribute | Nein | Ja | ISO 92 | Beschreibt Attribute einer Spalte der Ergebniszeile. |
SQLColAttributes | Ja | Ja | Veraltet | Beschreibt Attribute einer Spalte der Ergebniszeile. |
SQLFetch | Ja | Ja | ISO 92 | Gibt mehrere Ergebniszeilen zurück. |
SQLFetchScroll | Nein | Ja | ISO 92 | Gibt scrollbare Ergebniszeilen zurück. |
SQLExtendedFetch | Ja | Ja | Veraltet | Gibt scrollbare Ergebniszeilen zurück. |
SQLSetPos | Ja | Ja | ODBC | Setzt einen Cursor in einen abgeholten Datenblock, sodass eine Anwendung Daten in der Zeilenmenge erneuern oder Daten in der Ergebnismenge aktualisieren oder löschen kann. |
SQLBulkOperations | Nein | Ja | ODBC | Führt Einfügungen oder Bookmarking als Massenoperationen aus, darunter Updates, Deletes und Datenabruf anhand von Bookmarks. |
Fehler- oder Diagnosedaten abrufen:
MyODBC | ||||
Funktionsname | 2.50 | 3.51 | Standard | Zweck |
SQLError | Ja | Ja | Veraltet | Gibt zusätzliche Fehler- oder Statusinformationen zurück. |
SQLGetDiagField | Ja | Ja | ISO 92 | Gibt zusätzliche diagnostische Informationen zurück (ein einzelnes Feld der diagnostischen Datenstruktur). |
SQLGetDiagRec | Ja | Ja | ISO 92 | Gibt zusätzliche diagnostische Informationen zurück (mehrere Felder der diagnostischen Datenstruktur). |
Informationen über die Systemtabellen (Katalogfunktionen) der Datenquelle abrufen:
MyODBC | ||||
Funktionsname | 2.50 | 3.51 | Standard | Zweck |
SQLColumnPrivileges | Ja | Ja | ODBC | Liefert eine Liste von Spalten und zugehörigen Berechtigungen für eine oder mehr Tabellen. |
SQLColumns | Ja | Ja | X/Open | Liefert eine Liste der Spaltennamen in den angegebenen Tabellen. |
SQLForeignKeys | Ja | Ja | ODBC | Liefert für eine angegebene Tabelle eine Liste der Spalten, die den Fremdschlüssel bilden (sofern vorhanden). |
SQLPrimaryKeys | Ja | Ja | ODBC | Liefert die Liste der Spalten, die den Primärschlüssel einer Tabelle bilden. |
SQLSpecialColumns | Ja | Ja | X/Open | Liefert Informationen über die optimale Spaltenmenge zur eindeutigen Identifikation einer Zeile in einer angegebenen Tabelle oder die Spalten, die automatisch aktualisiert werden, wenn eine Transaktion einen Wert in der Zeile ändert. |
SQLStatistics | Ja | Ja | ISO 92 | Liefert Statistikdaten über eine einzelne Tabelle und die Liste der mit ihr verbundenen Indizes. |
SQLTablePrivileges | Ja | Ja | ODBC | Liefert eine Liste der Tabellen und zugehörigen Berechtigungen. |
SQLTables | Ja | Ja | X/Open | Liefert eine Liste der Tabellennamen, die in einer bestimmten Datenstruktur gespeichert sind. |
Transaktionen ausführen:
MyODBC | ||||
Funktionsname | 2.50 | 3.51 | Standard | Zweck |
SQLTransact | Ja | Ja | Veraltet | Schreibt eine Transaktion fest (Commit) oder rollt sie zurück (Rollback). |
SQLEndTran | Nein | Ja | ISO 92 | Schreibt eine Transaktion fest (Commit) oder rollt sie zurück (Rollback). |
Anweisungen abschließen:
MyODBC | ||||
Funktionsname | 2.50 | 3.51 | Standard | Zweck |
SQLFreeStmt | Ja | Ja | ISO 92 | Beendet die Anweisungsverarbeitung, verwirft noch anhängige Ergebnisse und gibt optional die Ressourcen frei, die mit dem Anweisungs-Handle verbunden waren. |
SQLCloseCursor | Ja | Ja | ISO 92 | Schließt einen auf einem Anweisungs-Handle geöffneten Cursor. |
SQLCancel | Ja | Ja | ISO 92 | Bricht eine SQL-Anweisung ab. |
Verbindungen schließen:
MyODBC | ||||
Funktionsname | 2.50 | 3.51 | Standard | Zweck |
SQLDisconnect | Ja | Ja | ISO 92 | Schließt die Verbindung. |
SQLFreeHandle | Nein | Ja | ISO 92 | Gibt einen Umgebungs-, Verbindungs-, Anweisungs- oder Deskriptor-Handle frei. |
SQLFreeConnect | Ja | Ja | Veraltet | Gibt einen Verbindungs-Handle frei. |
SQLFreeEnv | Ja | Ja | Veraltet | Gibt einen Umgebungs-Handle frei |
Die folgende Tabelle zeigt, wie der Treiber die Datentypen des Servers den Standarddatentypen von SQL und C zuordnet:
Nativer Wert | SQL-Typ | C-Typ |
bit | SQL_BIT | SQL_C_BIT |
tinyint | SQL_TINYINT | SQL_C_STINYINT |
tinyint unsigned | SQL_TINYINT | SQL_C_UTINYINT |
bigint | SQL_BIGINT | SQL_C_SBIGINT |
bigint unsigned | SQL_BIGINT | SQL_C_UBIGINT |
long varbinary | SQL_LONGVARBINARY | SQL_C_BINARY |
blob | SQL_LONGVARBINARY | SQL_C_BINARY |
longblob | SQL_LONGVARBINARY | SQL_C_BINARY |
tinyblob | SQL_LONGVARBINARY | SQL_C_BINARY |
mediumblob | SQL_LONGVARBINARY | SQL_C_BINARY |
long varchar | SQL_LONGVARCHAR | SQL_C_CHAR |
text | SQL_LONGVARCHAR | SQL_C_CHAR |
mediumtext | SQL_LONGVARCHAR | SQL_C_CHAR |
char | SQL_CHAR | SQL_C_CHAR |
numeric | SQL_NUMERIC | SQL_C_CHAR |
decimal | SQL_DECIMAL | SQL_C_CHAR |
integer | SQL_INTEGER | SQL_C_SLONG |
integer unsigned | SQL_INTEGER | SQL_C_ULONG |
int | SQL_INTEGER | SQL_C_SLONG |
int unsigned | SQL_INTEGER | SQL_C_ULONG |
mediumint | SQL_INTEGER | SQL_C_SLONG |
mediumint unsigned | SQL_INTEGER | SQL_C_ULONG |
smallint | SQL_SMALLINT | SQL_C_SSHORT |
smallint unsigned | SQL_SMALLINT | SQL_C_USHORT |
real | SQL_FLOAT | SQL_C_DOUBLE |
double | SQL_FLOAT | SQL_C_DOUBLE |
float | SQL_REAL | SQL_C_FLOAT |
double precision | SQL_DOUBLE | SQL_C_DOUBLE |
date | SQL_DATE | SQL_C_DATE |
time | SQL_TIME | SQL_C_TIME |
year | SQL_SMALLINT | SQL_C_SHORT |
datetime | SQL_TIMESTAMP | SQL_C_TIMESTAMP |
timestamp | SQL_TIMESTAMP | SQL_C_TIMESTAMP |
text | SQL_VARCHAR | SQL_C_CHAR |
varchar | SQL_VARCHAR | SQL_C_CHAR |
enum | SQL_VARCHAR | SQL_C_CHAR |
set | SQL_VARCHAR | SQL_C_CHAR |
bit | SQL_CHAR | SQL_C_CHAR |
bool | SQL_CHAR | SQL_C_CHAR |
Die folgenden Tabellen führen die Fehlercodes auf, die der Treiber neben den Serverfehlern noch zurückliefert.
Nativer Code | SQLSTATE 2 | SQLSTATE 3 | Fehlermeldung |
500 | 01000 | 01000 | General warning |
501 | 01004 | 01004 | String data, right truncated |
502 | 01S02 | 01S02 | Option value changed |
503 | 01S03 | 01S03 | No rows updated/deleted |
504 | 01S04 | 01S04 | More than one row updated/deleted |
505 | 01S06 | 01S06 | Attempt to fetch before the result set returned the first row set |
506 | 07001 | 07002 | SQLBindParameter not used for all parameters |
507 | 07005 | 07005 | Prepared statement not a cursor-specification |
508 | 07009 | 07009 | Invalid descriptor index |
509 | 08002 | 08002 | Connection name in use |
510 | 08003 | 08003 | Connection does not exist |
511 | 24000 | 24000 | Invalid cursor state |
512 | 25000 | 25000 | Invalid transaction state |
513 | 25S01 | 25S01 | Transaction state unknown |
514 | 34000 | 34000 | Invalid cursor name |
515 | S1000 | HY000 | General driver defined error |
516 | S1001 | HY001 | Memory allocation error |
517 | S1002 | HY002 | Invalid column number |
518 | S1003 | HY003 | Invalid application buffer type |
519 | S1004 | HY004 | Invalid SQL data type |
520 | S1009 | HY009 | Invalid use of null pointer |
521 | S1010 | HY010 | Function sequence error |
522 | S1011 | HY011 | Attribute can not be set now |
523 | S1012 | HY012 | Invalid transaction operation code |
524 | S1013 | HY013 | Memory management error |
525 | S1015 | HY015 | No cursor name available |
526 | S1024 | HY024 | Invalid attribute value |
527 | S1090 | HY090 | Invalid string or buffer length |
528 | S1091 | HY091 | Invalid descriptor field identifier |
529 | S1092 | HY092 | Invalid attribute/option identifier |
530 | S1093 | HY093 | Invalid parameter number |
531 | S1095 | HY095 | Function type out of range |
532 | S1106 | HY106 | Fetch type out of range |
533 | S1117 | HY117 | Row value out of range |
534 | S1109 | HY109 | Invalid cursor position |
535 | S1C00 | HYC00 | Optional feature not implemented |
0 | 21S01 | 21S01 | Column count does not match value count |
0 | 23000 | 23000 | Integrity constraint violation |
0 | 42000 | 42000 | Syntax error or access violation |
0 | 42S02 | 42S02 | Base table or view not found |
0 | 42S12 | 42S12 | Index not found |
0 | 42S21 | 42S21 | Column already exists |
0 | 42S22 | 42S22 | Column not found |
0 | 08S01 | 08S01 | Communication link failure |
Nun folgen einige allgemeine Hinweise und Tipps für die Verwendung von MyODBC in unterschiedlichen Umgebungen, Anwendungen und Tools. Die Hinweise basieren auf den Erfahrungen von MyODBC-Entwicklern und -Nutzern.
In diesem Abschnitt geht es um häufig benutzte Abfragen und Funktionalitätsbereiche in MySQL und ihre Verwendung mit MyODBC.
Den Wert einer Spalte, die nach einer
INSERT
-Anweisung
AUTO_INCREMENT
verwendet, kann man auf
mehrere Weisen beschaffen. Um ihn unmittelbar nach dem
INSERT
abzurufen, verwendet man eine
SELECT
-Anfrage mit der
LAST_INSERT_ID()
-Funktion.
Mit MyODBC würden Sie hier zwei Anweisungen absetzen: die
INSERT
-Anweisung und die
SELECT
-Anfrage, die Ihnen den
Auto-Increment-Wert liefert.
INSERT INTO tbl (auto,text) VALUES(NULL,'text'); SELECT LAST_INSERT_ID();
Wenn Sie den Wert nicht für Ihre Anwendung, aber für ein
anderes INSERT
benötigen, können Sie das
Ganze auch mit folgenden beiden Anweisungen erledigen:
INSERT INTO tbl (auto,text) VALUES(NULL,'text'); INSERT INTO tbl2 (id,text) VALUES(LAST_INSERT_ID(),'text');
Manche ODBC-Anwendungen (darunter Delphi und Access) haben Schwierigkeiten, mit den oben gezeigten Methoden den Auto-Increment-Wert abzurufen. Hier bietet sich als Alternative folgende Anweisung an:
SELECT * FROM tbl WHERE auto IS NULL;
Siehe Abschnitt 24.2.13.3, „Wie erhalte ich die eindeutige Kennung für die letzte eingefügte Zeile?“.
MyODBC 3.51 bietet zwar dynamic
cursor
-Unterstützung, aber nach Voreinstellung sind
dynamische Cursors nicht aktiviert. In Windows schalten Sie
diese Funktion ein, indem Sie das Kontrollkästchen
Dynamische Cursor aktivieren
im
ODBC-Datenquellen-Administrator markieren.
Auf anderen Plattformen schalten Sie dynamische Cursors ein,
indem Sie zu dem Wert von OPTION
den Wert
32
addieren, wenn Sie den DSN anlegen.
Der MyODBC-Treiber wurde auf eine sehr schnelle Leistung hin optimiert. Wenn Sie Probleme mit der Leistung von MyODBC haben oder viele Plattenzugriffe für einfache Anfragen auftreten, sollten Sie mehrere Dinge überprüfen:
Stellen Sie sicher, dass ODBC Tracing
nicht eingeschaltet ist. Wenn das Tracing aktiv ist,
zeichnet der ODBC-Manager massenhaft Daten in der
Tracing-Datei auf. Unter Windows können Sie dies prüfen
und das Tracing gegebenenfalls deaktivieren, indem Sie die
im
ODBC-Datenquellen-Administrator ausschalten. In Mac OS X
überprüfen Sie das -Feld
des ODBC Administrators. Siehe auch
Abschnitt 25.1.3.8, „Erzeugen einer ODBC-Trace-Datei“.
Vergewissern Sie sich, dass Sie die Standardversion und nicht die Debugging-Version des Treibers benutzen. In der Debugging-Version werden zusätzliche Überprüfungen und Berichte ausgeführt.
Deaktivieren Sie die Trace- und Query-Logs des MyODBC-Treibers. Da diese für jeden DSN aktiviert sind, müssen Sie darauf achten, nur den DSN zu bearbeiten, den Sie in Ihrer Anwendung benutzen. Unter Windows deaktivieren Sie die MyODBC- und Query-Logs, indem Sie die DSN-Konfiguration modifizieren. Unter Mac OS X und Unix müssen Sie dafür sorgen, dass der Treiber-Trace (Optionswert 4) und das Anfragen-Logging (Optionswert 524288) ausgeschaltet sind.
Wie Sie in Microsoft Windows ein Anfragen-Timeout einstellen, wenn Anfragen über eine ODBC-Verbindung ausgeführt werden, erfahren Sie in folgendem Artikel der Microsoft Knowledge Base: http://support.microsoft.com/default.aspx?scid=kb%3Ben-us%3B153756.
Die meisten Programme sollten mit MyODBC gut harmonieren, doch für die folgenden gibt es bestimmte Hinweise und Tipps zur Verbesserung der Arbeit mit MyODBC und dem betreffenden Programm.
Bei allen Anwendungen sollten Sie immer darauf achten, die jeweils neuesten Versionen von MyODBC-Treibern, ODBC-Manager und den von der Anwendung benutzten Bibliotheken und Schnittstellen einzusetzen. Wenn Sie beispielsweise unter Windows die neueste Version der Microsoft Data Access Components (MDAC) verwenden, wird die Kompatibilität mit ODBC im Allgemeinen und mit dem MyODBC-Treiber im Besonderen besser.
Die meisten Microsoft-Anwendungen wurden mit MyODBC getestet, einschließlich Microsoft Office, Microsoft Access und den verschiedenen von ASP und Microsoft Visual Studio unterstützten Programmiersprachen.
Wenn Sie mit MyODBC Probleme haben, aber Ihr Programm auch mit OLEDB funktioniert, sollten Sie den OLEDB-Treiber ausprobieren.
Die Integration von Microsoft Access und MySQL können Sie mit MyODBC wie folgt verbessern:
Für alle Access-Versionen sollten Sie die MyODBC-Option
Übereinstimmende Zeilen zurückgeben
einschalten. Für Access 2.0 sollten Sie zusätzlich die
Option Simulate ODBC 1.0
aktivieren.
Alle Tabellen, die für Aktualisierungen zur Verfügung
stehen sollen, müssen eine
TIMESTAMP
-Spalte haben. Um die
größtmögliche Portierbarkeit zu erzielen, sollten Sie
keine Länge in der Spaltendeklaration angeben (dies
wird von MySQL-Versionen vor 4.1 nicht unterstützt).
Jede MySQL-Tabelle, die mit Access benutzt werden soll,
benötigt einen Primärschlüssel. Ist dieser nicht
vorhanden, können neu eingefügte oder aktualisierte
Zeilen als #DELETED#
erscheinen.
Verwenden Sie nur
DOUBLE
-Float-Felder. Access kann
keine Float-Werte mit einfacher Genauigkeit vergleichen.
Infolgedessen können neu eingefügte oder aktualisierte
Zeilen als #DELETED#
erscheinen, oder
Sie können Zeilen nicht finden oder aktualisieren.
Wenn Sie MyODBC zum Verknüpfen einer Tabelle verwenden,
die eine BIGINT
-Spalte hat, werden
die Ergebnisse als #DELETED#
angezeigt. Der Workaround hierfür ist:
Sie richten eine oder mehrere Dummy-Spalten mit dem
Datentyp TIMESTAMP
ein.
Sie wählen die Option Change BIGINT
columns to INT
im Verbindungsdialog vom
ODBC DSN Administrator.
Sie löschen die Tabellenverknüpfung aus Access und legen sie neu an.
Eventuell werden alte Einträge immer noch als
#DELETED#
angezeigt, während neu
eingefügte/aktualisierte Einträge richtig angezeigt
werden.
Wenn Sie nach dem Hinzufügen einer
TIMESTAMP
-Spalte immer noch den
Fehler Another user has changed your
data
bekommen, können Sie sich mit folgendem
Trick behelfen:
Verwenden Sie keine
table
-Datenblattansicht, sondern
legen Sie ein Formular mit den gewünschten Feldern an
und benutzen dann die
form
-Datenblattansicht. Die
Eigenschaft DefaultValue
der
TIMESTAMP
-Spalte setzen Sie auf
NOW()
. Am besten verbergen Sie die
TIMESTAMP
-Spalte, um die Benutzer
nicht zu verwirren.
In manchen Fällen generiert Access SQL-Anweisungen, die
MySQL nicht versteht. Dann wählen Sie
"Query|SQLSpecific|Pass-Through"
aus
dem Access-Menü.
Auf Windows NT meldet Access
BLOB
-Spalten als OLE
OBJECTS
. Wenn Sie stattdessen
MEMO
-Spalten wünschen, wandeln Sie
mit einem ALTER TABLE
die
BLOB
-Spalten in
TEXT
-Spalten um.
Access kommt nicht immer mit der
DATE
-Spalte von MySQL zurecht. Wenn
Sie deswegen Probleme haben, ändern Sie die Spalten in
DATETIME
-Spalten um.
Access versucht, BYTE
-Spalten als
TINYINT
statt als TINYINT
UNSIGNED
zu exportieren. Das führt zu
Problemen, wenn die Spalte größere Werte als 127
enthält.
Wenn Sie in Access äußerst große (long) Tabellen
gespeichert haben, kann es lange dauern, sie zu öffnen.
Oder es geht Ihnen der virtuelle Speicher aus, sodass
Sie einen ODBC Query Failed
-Fehler
bekommen und die Tabelle sich gar nicht mehr öffnen
lässt. Dies können Sie mit folgenden Optionen beheben:
Return Matching Rows (2)
Allow BIG Results (8)
In der Summe ergibt das 10
(OPTION=10
).
Einige externe Fachbeiträge und Tipps zu Access, ODBC und MyODBC sind recht nützlich:
ODBC-Anwendungen für Access optimieren
Eine Liste von Tools für die Verwendung mit Access und ODBC-Datenquellen gibt es unter converters.
Wenn Sie Probleme mit dem Importieren von Daten in Microsoft Excel haben, insbesondere bei numerischen Werten sowie Datums- und Uhrzeitwerten, so liegt das wahrscheinlich an einem Excel-Bug: Der Datentyp für Einfügungen in Arbeitsblatt-Zellen wird anhand des Spaltentyps der Quelldaten bestimmt. Das führt dazu, dass Excel den Inhalt nicht richtig identifiziert, was sich sowohl auf das Anzeigeformat als auch auf Berechnungen auswirkt.
Dies beheben Sie, indem Sie in Ihren Anfragen die
CONCAT()
-Funktion einsetzen. So zwingen
Sie Excel, den Wert als String zu behandeln: Excel parst
dann den String und erkennt die darin enthaltenen Daten
richtig.
Dennoch können manche Daten dann immer noch falsch
formatiert werden, auch wenn die Quelldaten unverändert
bleiben. Die Excel-Option Zellen
formatieren
ändert das Format der angezeigten
Informationen.
Um eine Tabelle aktualisieren zu können, müssen Sie zuerst einen Primärschlüssel für die Tabelle definieren.
Visual Basic mit ADO kann mit großen Integern nicht
umgehen. Das führt dazu, dass manche Anfragen, wie etwa
SHOW PROCESSLIST
, nicht richtig
funktionieren. Dies beheben Sie mit
OPTION=16384
im ODBC-Verbindungs-String
oder indem Sie im MyODBC-Verbindungsbildschirm die Option
Change BIGINT columns to INT
aktivieren.
Zugleich sollten Sie dann auch die Option Return
matching rows
einschalten.
Wenn Ihre Ergebnismenge einen BIGINT
enthält, kann der Fehler [Microsoft][ODBC Driver
Manager] Driver does not support this parameter
auftreten. Versuchen Sie in diesem Fall, die Option
Change BIGINT columns to INT
im
MyODBC-Verbindungsbildschirm einzuschalten.
Wenn Sie die ADO-API und MyODBC verwenden, müssen Sie auf
einige Standardeigenschaften achten, die vom MySQL Server
nicht unterstützt werden. Wenn Sie beispielsweise
CursorLocation Property
als
adUseServer
verwenden, bekommen Sie für
die RecordCount Property
das Ergebnis
–1 heraus. Um den richtigen Wert zu erhalten, müssen
Sie diese Eigenschaft auf adUseClient
setzen, wie es im nachfolgenden VB-Code getan wird:
Dim myconn As New ADODB.Connection Dim myrs As New Recordset Dim mySQL As String Dim myrows As Long myconn.Open "DSN=MyODBCsample" mySQL = "SELECT * from user" myrs.Source = mySQL Set myrs.ActiveConnection = myconn myrs.CursorLocation = adUseClient myrs.Open myrows = myrs.RecordCount myrs.Close myconn.Close
Ein anderer Workaround besteht darin, eine SELECT
COUNT(*)
-Anweisung für ähnliche Abfragen zu
verwenden, um die richtige Zeilenzahl zu erhalten.
Um die Anzahl der von einer bestimmten SQL-Anweisung in ADO
betroffenen Zeilen zu ermitteln, setzen Sie die Eigenschaft
RecordsAffected
in der
ADO-Execute-Methode. Mehr über Execute-Methoden erfahren
Sie unter
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ado270/htm/mdmthcnnexecute.asp.
Weitere Informationen gibt es unter ActiveX Data Objects (ADO) Frequently Asked Questions.
Sie sollten die Option Return matching
rows
im DSN aktivieren.
Weitere Informationen über den Zugriff auf MySQL mit ASP und MyODBC finden Sie in folgenden Fachbeiträgen:
Eine Liste häufig gestellter Fragen (FAQ) zu ASP finden Sie unter http://support.microsoft.com/default.aspx?scid=/Support/ActiveServer/faq/data/adofaq.asp.
Folgende Beiträge bieten Hilfe zu Visual Basic und ASP:
MySQL
BLOB columns and Visual Basic 6 von Mike Hillyer
(<mike@openwin.org>
).
How
to map Visual basic data type to MySQL types von
Mike Hillyer (<mike@openwin.org>
).
Für alle Borland-Anwendungen, in denen die Borland Database Engine (BDE) benutzt wird, gelten folgende Hinweise zur Verbesserung der Kompatibilität:
Aktualisieren Sie auf BDE 3.2 oder neuer.
Aktivieren Sie die Option Don't optimize column
widths
im DSN.
Aktivieren Sie die Option Return matching
rows
im DSN.
Wenn Sie eine Anfrage starten, können Sie die Eigenschaft
Active
oder die Methode
Open
einsetzen. Das Starten mit
Active
verläuft so, dass automatisch
eine SELECT * FROM ...
-Anfrage abgesetzt
wird. Das kann nach hinten losgehen, wenn Ihre Tabellen zu
groß sind.
Der nachfolgende Delphi-Code kann sehr nützlich sein, um
sowohl einen ODBC- als auch einen BDE-Eintrag für MyODBC zu
erstellen. Für den BDE-Eintrag ist ein BDE Alias Editor
erforderlich, den Sie kostenlos bei einer Delphi Super Page
in Ihrer Nähe bekommen können (Danke an Bryan Brunton
<bryan@flesherfab.com>
für dieses Programm):
fReg:= TRegistry.Create; fReg.OpenKey('\Software\ODBC\ODBC.INI\DocumentsFab', True); fReg.WriteString('Database', 'Documents'); fReg.WriteString('Description', ' '); fReg.WriteString('Driver', 'C:\WINNT\System32\myodbc.dll'); fReg.WriteString('Flag', '1'); fReg.WriteString('Password', ''); fReg.WriteString('Port', ' '); fReg.WriteString('Server', 'xmark'); fReg.WriteString('User', 'winuser'); fReg.OpenKey('\Software\ODBC\ODBC.INI\ODBC Data Sources', True); fReg.WriteString('DocumentsFab', 'MySQL'); fReg.CloseKey; fReg.Free; Memo1.Lines.Add('DATABASE NAME='); Memo1.Lines.Add('USER NAME='); Memo1.Lines.Add('ODBC DSN=DocumentsFab'); Memo1.Lines.Add('OPEN MODE=READ/WRITE'); Memo1.Lines.Add('BATCH COUNT=200'); Memo1.Lines.Add('LANGDRIVER='); Memo1.Lines.Add('MAX ROWS=-1'); Memo1.Lines.Add('SCHEMA CACHE DIR='); Memo1.Lines.Add('SCHEMA CACHE SIZE=8'); Memo1.Lines.Add('SCHEMA CACHE TIME=-1'); Memo1.Lines.Add('SQLPASSTHRU MODE=SHARED AUTOCOMMIT'); Memo1.Lines.Add('SQLQRYMODE='); Memo1.Lines.Add('ENABLE SCHEMA CACHE=FALSE'); Memo1.Lines.Add('ENABLE BCD=FALSE'); Memo1.Lines.Add('ROWSET SIZE=20'); Memo1.Lines.Add('BLOBS TO CACHE=64'); Memo1.Lines.Add('BLOB SIZE=32'); AliasEditor.Add('DocumentsFab','MySQL',Memo1.Lines);
Ist getestet mit BDE 3.0. Das einzige bekannte Problem ist:
Wenn sich das Tabellenschema ändert, werden die Felder der
Anfrage nicht aktualisiert. Allerdings erkennt BDE offenbar
auch keine Primärschlüssel, sondern nur den Index mit dem
Namen PRIMARY
, was allerdings bisher noch
keine Probleme verursacht hat.
Die folgenden Informationen wurden der ColdFusion-Dokumentation entnommen:
Anhand der folgenden Informationen konfigurieren Sie den
ColdFusion Server für Linux für die Benutzung des
unixODBC
-Treibers mit MyODBC für
MySQL-Datenquellen. Allaire hat sichergestellt, dass MyODBC
2.50.26 mit MySQL 3.22.27 und ColdFusion für Linux
funktioniert. (Auch alle neueren Versionen müssten
funktionieren.) Sie können MyODBC unter folgender Adresse
herunterladen:
http://dev.mysql.com/downloads/connector/odbc/.
Die ColdFusion-Version 4.5.1 ermöglicht es, die
MySQL-Datenquelle mit ColdFusion Administrator zu laden.
Allerdings wird der Treiber mit der ColdFusion-Version 4.5.1
nicht mitgeliefert. Bevor der MySQL-Treiber in der
Dropdown-Liste der ODBC-Datenquellen auftaucht, müssen Sie
den MyODBC-Treiber bauen und in
/opt/coldfusion/lib/libmyodbc.so
kopieren.
Das Contrib-Verzeichnis enthält das Programm
mydsn-
,
mit dem Sie die DSN-Registrierungsdatei für den
MyODBC-Treiber in ColdFusion-Anwendungen erstellen und
entfernen können.
xxx
.zip
Weitere Informationen und Hinweise für die Benutzung von ColdFusion und MyODBC finden Sie auf folgenden externen Sites:
MySQL ColdFusion unixODBC MyODBC and Solaris - how to succeed
ColdFusion (auf Solaris und NT mit Service Pack 5), How-to: MySQL and ColdFusion
Troubleshooting Data Sources and Database Connectivity for Unix Platforms
Open Office (http://www.openoffice.org) How-to: MySQL + OpenOffice. How-to: OpenOffice + MyODBC + unixODBC
Sambar Server (http://www.sambarserver.info) How-to: MyODBC + SambarServer + MySQL
Im folgenden Abschnitt geht es um häufige Fehler und ihre Behebung oder Alternativlösungen. Wenn Sie danach immer noch Probleme haben, nutzen Sie bitte die MyODBC-Mailingliste unter Abschnitt 25.1.7.1, „MyODBC: Community-Support“.
Viele Probleme lassen sich bereits durch einen Upgrade der MyODBC-Treiber auf die neueste verfügbare Version beheben. Unter Windows müssen Sie auch darauf achten, immer die neueste Version der Microsoft Data Access Components (MDAC) zu installieren.
Fragen
26.1.6.3.1: Sind MyODBC 2.50-Anwendungen kompatibel mit MyODBC 3.51?
26.1.6.3.2: Bei Transaktionen kommt es gelegentlich zu folgendem Fehler:
Transactions are not enabled
26.1.6.3.3: Der folgende Fehler tritt bei der Übermittlung einer Anfrage auf:
Cursor not found
26.1.6.3.4:
Access meldet Datensätze als
#DELETED#
, wenn Einträge in
verknüpften Tabellen eingefügt oder geändert werden.
26.1.6.3.5: Wie gehe ich mit Write Conflicts oder Row Location-Fehlern um?
26.1.6.3.6:
Beim Exportieren von Daten aus Access 97 in MySQL wird ein
Syntax Error
gemeldet.
26.1.6.3.7:
Beim Exportieren von Daten aus Microsoft DTS in MySQL wird
ein Syntax Error
gemeldet.
26.1.6.3.8: Wenn Sie ODBC.NET mit MyODBC benutzen, wird beim Abrufen von leeren Strings (Strings der Länge 0) die SQL_NO_DATA-Exception ausgelöst.
26.1.6.3.9:
Wenn Sie SELECT COUNT(*) FROM
in Visual
Basic und ASP benutzen, wird ein Fehler gemeldet.
tbl_name
26.1.6.3.10:
Bei Verwendung der ADO-Methode
AppendChunk()
oder
GetChunk()
wird der Fehler
Multiple-step operation generated errors. Check
each status value
gemeldet.
26.1.6.3.11:
Access gibt beim Bearbeiten von Einträgen einer
verknüpften Tabelle Another user had modified
the record that you have modified
zurück.
Fragen und Antworten
26.1.6.3.1: Sind MyODBC 2.50-Anwendungen kompatibel mit MyODBC 3.51?
Anwendungen, die auf MyODBC 2.50 basieren, müssten auch mit MyODBC 3.51 und späteren Versionen gut funktionieren. Wenn Sie feststellen, dass etwas mit der neuesten Version von MyODBC nicht mehr funktioniert, was mit einer älteren Version noch geklappt hat, schicken Sie uns bitte einen Bugreport. Siehe hierzu Abschnitt 25.1.7.2, „Melden von MyODBC-Problemen und -Fehlern“.
26.1.6.3.2: Bei Transaktionen kommt es gelegentlich zu folgendem Fehler:
Transactions are not enabled
Dies bedeutet, dass Sie auf einer MySQL-Tabelle, die keine
Transaktionen unterstützt, eine Transaktion versuchen.
Transaktionen werden in MySQL nur von den Speicher-Engines
InnoDB
und BDB
unterstützt.
Bitte prüfen Sie Folgendes:
Vergewissern Sie sich, dass Ihr MySQL Server eine
transaktionsfähige Speicher-Engine verwendet.
SHOW ENGINES
zeigt Ihnen die Liste
der verfügbaren Engines an.
Vergewissern Sie sich, dass die Tabellen, die Sie zu aktualisieren versuchen, eine transaktionsfähige Speicher-Engine verwenden.
Achten Sie darauf, dass im DSN nicht die Option
disable transactions
eingeschaltet
ist.
26.1.6.3.3: Der folgende Fehler tritt bei der Übermittlung einer Anfrage auf:
Cursor not found
Dies bedeutet, dass die Anwendung die ältere Version MyODBC 2.50 verwendet und den Cursor-Namen nicht explizit mit SQLSetCursorName gesetzt hat. Dies beheben Sie durch einen Upgrade auf die Version MyODBC 3.51.
26.1.6.3.4:
Access meldet Datensätze als
#DELETED#
, wenn Einträge in
verknüpften Tabellen eingefügt oder geändert werden.
Wenn die eingefügten oder geänderten Datensätze als
#DELETED#
erscheinen:
Wenn Sie Access 2000 benutzen, installieren Sie bitte
die neueste Version (2.6 oder höher) der Microsoft
MDAC (Microsoft Data Access
Components
) von
http://www.microsoft.com/data/. Darin
wird ein Access-Fehler behoben, der dazu führt, dass
bei einem Export von Daten in MySQL die Tabellen- und
Spaltennamen nicht angegeben werden. Eine andere
Möglichkeit besteht darin, auf MyODBC 2.50.33 oder
höher und auf MySQL 3.23.x oder höher aufzurüsten,
da beide gemeinsam einen Workaround für dieses
Problem enthalten.
Außerdem sollten Sie das Microsoft Jet 4.0 Service
Pack 5 (SP5) anwenden, das unter
http://support.microsoft.com/default.aspx?scid=kb;EN-US;q239114
zur Verfügung steht. Damit werden einige Fälle
behoben, bei denen Access-Zeilen als
#DELETED#
erscheinen.
Hinweis: Wenn Sie MySQL 3.22 verwenden, müssen Sie den MDAC-Patch anwenden und MyODBC 2.50.32 oder 2.50.34 (oder höher) installieren, um dieses Problem zu umgehen.
Für alle Versionen von Access müssen Sie die Option
MyODBC Return matching rows
einschalten. Für Access 2.0 sollten Sie zusätzlich
die Option Simulate ODBC 1.0
aktivieren.
Alle Tabellen, die später updatefähig sein sollen, müssen einen Timestamp enthalten.
Jede Tabelle sollte einen Primärschlüssel haben,
sonst können neue oder aktualisierte Zeilen als
#DELETED#
erscheinen.
Verwenden Sie nur
DOUBLE
-Float-Felder. Access kann
Float-Werte mit einfacher Genauigkeit nicht
vergleichen. Dies führt dazu, dass neue oder
aktualisierte Zeilen als #DELETED#
erscheinen oder nicht zu finden sind.
Wenn Sie MyODBC zur Verknüpfung einer Tabelle
benutzen, die eine BIGINT
-Spalte
hat, werden die Ergebnisse als
#DELETED
angezeigt. Hierfür gibt
es folgenden Workaround:
Richten Sie eine zusätzliche Dummy-Spalte mit dem
Datentyp TIMESTAMP
ein.
Wählen Sie im Verbindungsdialog vom ODBC DSN
Administrator die Option Change BIGINT
columns to INT
.
Löschen Sie die Tabellenverknüpfung von Access und erstellen Sie sie neu.
Alte Einträge werden weiterhin als
#DELETED#
angezeigt, aber neue oder
geänderte erscheinen in der richtigen Form.
26.1.6.3.5: Wie gehe ich mit Write Conflicts oder Row Location-Fehlern um?
Bei folgenden Fehlern sollten Sie die Option
Return Matching Rows
im
DSN-Konfigurationsdialog einstellen oder
OPTION=2
als Verbindungsparameter
angeben:
Write Conflict. Another user has changed your data. Row cannot be located for updating. Some values may have been changed since it was last read.
26.1.6.3.6:
Beim Exportieren von Daten aus Access 97 in MySQL wird ein
Syntax Error
gemeldet.
Dieser Fehler ist spezifisch für Access 97 und MyODBC-Versionen, die älter sind als 3.51.02. Rüsten Sie auf die neueste Version des MyODBC-Treibers auf.
26.1.6.3.7:
Beim Exportieren von Daten aus Microsoft DTS in MySQL wird
ein Syntax Error
gemeldet.
Dieser Fehler tritt nur bei MySQL-Tabellen auf, in denen
die Datentypen TEXT
oder
VARCHAR
vorkommen. Rüsten Sie Ihren
MyODBC-Treiber auf die Version 3.51.02 oder höher auf.
26.1.6.3.8: Wenn Sie ODBC.NET mit MyODBC benutzen, wird beim Abrufen von leeren Strings (Strings der Länge 0) die SQL_NO_DATA-Exception ausgelöst.
Hierfür gibt es einen Patch unter http://support.microsoft.com/default.aspx?scid=kb;EN-US;q319243.
26.1.6.3.9:
Wenn Sie SELECT COUNT(*) FROM
in Visual
Basic und ASP benutzen, wird ein Fehler gemeldet.
tbl_name
Dieser Fehler tritt auf, weil der Ausdruck
COUNT(*)
einen
BIGINT
zurückliefert, mit dem ADO
nichts anfangen kann. Wählen Sie die Option
Change BIGINT columns to INT
(Optionswert 16384).
26.1.6.3.10:
Bei Verwendung der ADO-Methode
AppendChunk()
oder
GetChunk()
wird der Fehler
Multiple-step operation generated errors. Check
each status value
gemeldet.
Die Methoden GetChunk()
und
AppendChunk()
von ADO funktionieren
nicht richtig, wenn der Cursor-Standort mit
adUseServer
angegeben wird. Das beheben
Sie, indem Sie adUseClient
verwenden.
Ein einfaches Beispiel finden Sie unter http://www.dwam.net/iishelp/ado/docs/adomth02_4.htm.
26.1.6.3.11:
Access gibt beim Bearbeiten von Einträgen einer
verknüpften Tabelle Another user had modified
the record that you have modified
zurück.
Dies lässt sich meistens durch eine der folgenden Maßnahmen lösen:
Sie geben der Tabelle einen Primärschlüssel, falls sie noch keinen hat.
Sie geben der Tabelle einen Timestamp, falls sie noch keinen hat.
Sie verwenden Float-Felder nur mit doppelter Genauigkeit. Manche Programme können Floats mit einfacher Genauigkeit nicht vergleichen.
Wenn dies alles nichts hilft, legen Sie eine Logdatei für den ODBC-Manager (das Log, das Sie bekommen, wenn Sie eines von ODBCADMIN anfordern) sowie ein MyODBC-Log an. So können Sie vielleicht dem Fehler auf die Spur kommen. Anleitungen finden Sie unter Abschnitt 25.1.3.8, „Erzeugen einer ODBC-Trace-Datei“.
Es gibt viele Stellen, an denen Sie sich Hilfe zu MyODBC holen können. Schauen Sie immer als Erstes in die MyODBC-Mailingliste oder das MyODBC-Forum. Unter Abschnitt 25.1.7.1, „MyODBC: Community-Support“ erfahren Sie, was zu tun ist, ehe Sie einen Bug oder ein Problem an MySQL melden.
MySQL AB stellt der Benutzergemeinde via Mailingliste Hilfe zur
Verfügung. Bei MyODBC-Problemen helfen Ihnen erfahrene Nutzer
in der Mailingliste <myodbc@lists.mysql.com>
weiter. Die Archive stehen online unter
http://lists.mysql.com/myodbc zur
Verfügung.
Wie Sie die MySQL-Mailinglisten abonnieren oder die Archive durchforsten können, erfahren Sie unter http://lists.mysql.com/. Siehe Abschnitt 1.7.1, „Die MySQL-Mailinglisten“.
Support von erfahrenen Benutzern bekommen Sie auch im MyODBC Forum sowie in den anderen MySQL-Foren unter http://forums.mysql.com. Siehe Abschnitt 1.7.2, „MySQL-Community-Support in den MySQL-Foren“.
Bei Schwierigkeiten oder Problemen mit MyODBC sollten Sie als
Erstes eine Logdatei mit dem ODBC Manager
(das Log, das Sie erhalten, wenn Sie eines von ODBC
ADMIN
anfordern) und für MyODBC anlegen. Wie das
geht, erfahren Sie unter
Abschnitt 25.1.3.8, „Erzeugen einer ODBC-Trace-Datei“.
Vielleicht finden Sie in der MyODBC-Trace-Datei die
Fehlerursache. Der String
>mysql_real_query
im
myodbc.log
verrät Ihnen, welche
Anweisungen abgesetzt wurden.
Außerdem können Sie versuchen, die Anweisungen aus dem
mysql-Clientprogramm oder
admndemo
einzugeben. So können Sie
herausfinden, ob das Problem an MyODBC oder MySQL liegt.
Wenn Sie feststellen, dass etwas schief geht, senden Sie bitte
nur die relevanten Zeilen (maximal 40) an die
myodbc
-Mailingliste. Siehe auch
Abschnitt 1.7.1, „Die MySQL-Mailinglisten“. Senden Sie bitte niemals die
gesamte MyODBC- oder ODBC-Logdatei!
Im Idealfall sollte Ihre E-Mail folgende Informationen enthalten:
Betriebssystem und Version
MyODBC-Version
ODBC-Treiber-Manager-Typ und -Version
MySQL Server-Version
ODBC-Trace vom Treiber-Manager
MyODBC-Logdatei vom MyODBC-Treiber
ein einfaches, reproduzierbares Beispiel
Denken Sie daran: Je mehr Informationen Sie uns geben können, umso wahrscheinlicher ist es, dass wir eine Lösung finden!
Schauen Sie jedoch immer in das Archiv der MyODBC-Mailingliste, ehe Sie uns einen Fehler melden: http://lists.mysql.com/myodbc.
Wenn Sie nicht herausfinden können, wo das Problem liegt,
können Sie als letztes Mittel ein Archiv im
tar- oder Zip-Format anlegen, das eine
MyODBC-Trace-Datei, die ODBC-Logdatei und eine
README
-Datei mit einer Problembeschreibung
enthält. Diese können Sie an ftp://ftp.mysql.com/pub/mysql/upload/
senden. Nur MySQL-Ingenieure haben Zugriff auf die Dateien, die
Sie hochladen, und wir gehen sehr diskret mit den Daten um.
Wenn Sie ein Programm schreiben können, welches das Problem demonstriert, fügen Sie es bitte ebenfalls dem Archiv hinzu.
Wenn das Programm mit einem anderen SQL-Server läuft, legen Sie bitte eine ODBC-Logdatei bei, in der genau dieselben SQL-Anweisungen ausgeführt werden, damit wir die Ergebnisse der beiden Systeme miteinander vergleichen können.
Wieder gilt: Je mehr Informationen Sie uns geben können, umso wahrscheinlicher ist es, dass wir eine Lösung finden.
Einen Patch oder Lösungsvorschlag für vorhandenen Code oder
bekannte Probleme übermitteln Sie bitte per E-Mail an
<myodbc@lists.mysql.com>
.
Mit Connector/NET lassen sich .NET-Anwendungen entwickeln, die sichere und leistungsfähige Datenbankverbindungen mit MySQL benutzen. Connector/NET implementiert die erforderlichen ADO.NET-Schnittstellen und lässt sich in ADO.NET-fähige Tools integrieren. Die Entwickler können ihre Anwendungen in den .NET-Sprachen ihrer Wahl schreiben. Connector/NET ist ein vollständig verwalteter ADO.NET-Treiber, der zu 100 % in C# geschrieben wurde.
Connector/NET bietet volle Unterstützung für:
MySQL 5.0-Features (beispielsweise gespeicherte Prozeduren)
MySQL 4.1-Features (vorbereitete Anweisungen auf der Serverseite, Unicode, Shared Memory-Zugriff usw.)
große Pakete zum Senden und Empfangen von bis zu 2 Gbyte großen Zeilen und BLOBs
Protokollkompression zum Komprimieren des Datenstroms zwischen Client und Server
Verbindung über TCP/IP-Sockets, Named Pipes oder Shared Memory auf Windows
Verbindung über TCP/IP-Sockets oder Unix-Sockets auf Unix
Open Source Mono-Framework von Novell
vollständig verwaltet, benutzt keine MySQL-Clientbibliothek
Dieses Dokument soll den Benutzer zur Verwendung von Connector/NET
anleiten und enthält eine vollständige Syntaxreferenz.
Syntaxinformationen finden Sie auch in der Datei
Documentation.chm
in Ihrer
Connector/NET-Distribution.
Gegenwärtig ist nur eine Version von Connector/NET erhältlich:
Connector/NET 1.0 bietet Unterstützung für die Features von MySQL 4.0 und MySQL 5.0 sowie volle Kompatibilität mit dem ADO.NET-Treiber.
Connector/NET läuft auf jeder Plattform, die das .NET-Framework unterstützt. Das ist vor allem bei den neueren Versionen von Microsoft Windows der Fall, sowie bei Linux über das Open Source Mono-Framework (siehe http://www.mono-project.com).
Connector/NET können Sie von folgender Adresse herunterladen: http://dev.mysql.com/downloads/connector/net/1.0.html.
Auf Windows installieren Sie Connector/NET entweder mit einer Binärversion oder aus einer heruntergeladenen Zip-Datei mit den Connector/NET-Komponenten.
Vor der Installation müssen Sie sicherstellen, dass Ihr System aktuell ist und dass Sie die neueste Version von .NET besitzen.
Mit dem Installer gelingt die Installation von Connector/NET auf Windows am einfachsten. Er installiert den Quellcode, den Testcode und die vollständige Referenzdokumentation.
Connector/NET wird auf allen Windows-Betriebssystemen mit
einem Windows-Installer
(.msi
-Installations-Package) installiert.
Das MSI-Package liegt in einem ZIP-Archiv namens
mysql-connector-net-
,
wobei version
.zipversion
die
Connector/NET-Version ist.
Connector/NET installieren Sie wie folgt:
Führen Sie einen Doppelklick auf die aus der heruntergeladenen Zip-Datei extrahierte MSI-Installer-Datei aus. Mit einem Klick auf
starten Sie die Installation.Sie müssen den gewünschten Installationstyp auswählen.
Für die meisten Fälle eignet sich die typische Installation. Klicken Sie also auf
und fahren Sie fort mit Schritt 5. Mit der vollständigen ( ) Installation installieren Sie sämtliche verfügbaren Dateien. Hierzu klicken Sie auf die Schaltfläche und machen dann mit Schritt 5 weiter. Wenn Sie eine benutzerdefinierte Installation bevorzugen und die zu installierenden Komponenten und Optionen selbst auswählen möchten, klicken Sie auf und machen mit Schritt 3 weiter.Bei der benutzerdefinierten Installation können Sie die einzelnen zu installierenden Komponenten selbst aussuchen, einschließlich der Core-Interface-Komponente, der Dokumentation (einer CHM-Datei), Beispielen und des Quellcodes. Wählen Sie die zu installierenden Bestandteile aus und klicken Sie auf
.Bei einer benutzerdefinierten Installation können Sie auch entscheiden, ob die Connector/NET-Komponente im Global Assembly Cache registriert werden soll. Dann steht Connector/NET allen Anwendungen zur Verfügung, nicht nur denen, die explizit auf Connector/NET verweisen. Sie können auch die Erzeugung von entsprechenden Symbolen im Startmenü aktivieren oder deaktivieren. Wenn Sie die notwendigen Optionen ausgewählt haben, klicken Sie wieder auf
.Zum Schluss haben Sie Gelegenheit, die Installation zu bestätigen. Klicken Sie auf
, um die Dateien auf Ihren Computer zu übertragen und zu installieren.Ist die Installation abgeschlossen, schließen Sie den Installer mit einem Klick auf
.
Wenn Sie nichts anderes eingestellt haben, wird Connector/NET
C:\Program Files\MySQL\MySQL Connector Net
installiert, wobei
X.X.X
X.X.X
die installierte Version von
Connector/NET ist. Neue Installationen werden die vorhandenen
Versionen von Connector/NET nicht überschreiben.
Je nach Installationstyp werden einige oder alle der folgenden Komponenten installiert:
bin
– Connector/NET
MySQL-Bibliotheken für verschiedene Versionen der
.NET-Umgebung
docs
– enthält eine CHM der
Connector/NET-Dokumentation
samples
– Beispielcode und
-anwendungen, die die Connector/NET-Komponente nutzen
src
– der Quellcode für die
Connector/NET-Komponente
Wenn Sie Schwierigkeiten mit dem Installer haben, können Sie
auch eine .zip-Datei ohne Installer herunterladen. Diese Datei
heißt
mysql-connector-net-
.
Die darin enthaltenen Dateien extrahieren Sie in ein
Verzeichnis Ihrer Wahl.
version
-noinstall.zip
Die .zip-Datei enthält folgende Verzeichnisse:
bin
- Connector/NET MySQL-Bibliotheken
für verschiedene Versionen von .NET
doc
– eine CHM-Version der
Connector/NET-Dokumentation
Samples
– Beispielcode und
-anwendungen, die die Connector/NET-Komponente nutzen
mysqlclient
– der Quellcode für
die Connector/NET-Komponente
testsuite
– Testsuite zur
Funktionsprüfung der Connector/NET-Komponente.
Es gibt keinen Installer für Connector/NET auf Unix, aber die Installation ist dennoch ganz einfach. Vorher müssen Sie gewährleisten, dass Sie über eine funktionierende Mono-Installation verfügen.
Installieren Sie Connector/NET bitte nur auf Unix, wenn Sie sich mit einem MySQL Server über Mono verbinden wollen. Möchten Sie Connector/NET in einer anderen Umgebung, wie beispielsweise Java oder Perl, installieren oder damit arbeiten, wählen Sie bitte eine passendere Komponente für die Verbindungen aus. Weitere Informationen finden Sie unter Kapitel 25, Connectors, oder Kapitel 24, APIs und Bibliotheken.
Um Connector/NET auf Unix/Mono zu installieren, gehen Sie folgendermaßen vor:
Laden Sie
mysql-connector-net-
herunter und extrahieren Sie den Inhalt.
version
-noinstall.zip
Kopieren Sie die Datei MySql.Data.dll
in Ihren Installationsordner für das Mono-Projekt.
Mit folgendem gacutil
-Befehl
registrieren Sie die Connector/NET-Komponente im Global
Assembly Cache:
shell> gacutil /i MySql.Data.dll
Nach der Installation sind an Anwendungen, die mit der
Connector/NET-Komponente installiert wurden, keine weiteren
Änderungen mehr erforderlich. Sie müssen allerdings darauf
achten, die Connector/NET-Komponente mit der
Kommandozeilenoption -r:MySqlData.dll
beim
Kompilieren Ihrer Anwendungen einzubinden.
Vorsicht: Diesen Abschnitt sollten Sie nur lesen, wenn Sie uns beim Testen des neuen Codes unterstützen möchten. Wenn Sie lediglich Connector/NET auf Ihrem System zum Laufen bringen möchten, verwenden Sie am besten eine Standarddistribution.
Um auf den Connector/NET-Quellbaum zugreifen zu können, müssen Sie Subversion installieren. Sie erhalten Subversion kostenlos von http://subversion.tigris.org/.
Den aktuellsten Entwicklungsquellbaum erhalten Sie in unseren öffentlichen Subversion-Bäumen unter http://dev.mysql.com/tech-resources/sources.html.
Um die Quelldateien von Connector/NET auszuchecken, gehen Sie in das Verzeichnis, in welches Sie den Connector/NET-Baum kopieren möchten, und geben folgenden Befehl ein:
shell> svn co http://svn.mysql.com/svnpublic/connector-net
Die Quelldateien enthalten auch ein Visual Studio-Projekt, das Sie nutzen können, um Connector/NET zu bauen.
Dieser Abschnitt behandelt einige häufige Einsatzgebiete für Connector/NET, darunter den Umgang mit BLOBs und Datumswerten sowie die Kombination von Connector/NET mit gebräuchlichen Tools wie Crystal Reports.
Jegliche Interaktion zwischen einer .NET-Anwendung und einem
MySQL Server vollzieht sich durch ein
MySqlConnection
-Objekt. Also muss, ehe Sie
mit dem Server kommunizieren können, zunächst ein
MySqlConnection
-Objekt erzeugt,
konfiguriert und geöffnet werden.
Auch wenn die Klasse MySqlHelper
benutzt
wird, wird ein MySqlConnection
-Objekt von
dieser Hilfsklasse angelegt.
In diesem Abschnitt wird beschrieben, wie man über das
MySqlConnection
-Objekt mit MySQL Verbindung
aufnimmt.
Das MySqlConnection
-Objekt ist für einen
Verbindungs-String konfiguriert. Dieser String enthält
mehrere, durch Semikola getrennte Schlüssel/Wert-Paare, die
jeweils durch ein Gleichheitszeichen verbunden sind.
Sehen Sie hier ein Beispiel für einen Verbindungs-String:
Server=127.0.0.1;Uid=root;Pwd=12345;Database=test;
In diesem Beispiel ist das
MySqlConnection
-Objekt so konfiguriert,
dass es sich mit einem MySQL Server auf
127.0.0.1
verbindet und dazu den
Benutzernamen root
und das Passwort
12345
verwendet. Als Standarddatenbank für
alle Anweisungen benutzen wir test
.
Die folgenden Optionen werden typischerweise gesetzt (eine vollständige Liste der Optionen finden Sie in der nachfolgenden Tabelle):
Server
: Der Name oder die
Netzwerkadresse der MySQL-Instanz, mit der Verbindung
aufgenommen werden soll. Der Standardwert ist
localhost
. Aliase sind
host
, Data Source
,
DataSource
, Address
,
Addr
und Network
Address
.
Uid
: Das MySQL-Benutzerkonto, das für
die Verbindung genutzt wird. Aliase sind User
Id
, Username
und
User name
.
Pwd
: Das Passwort für das verwendete
MySQL-Konto. Der Alias Password
kann
ebenfalls gesetzt werden.
Database
: Die Standarddatenbank, auf
die alle Anweisungen angewendet werden. Der Standardwert
lautet mysql
, aber es kann auch der
Alias Initial Catalog
verwendet werden.
Port
: Der Port, auf dem MySQL auf
Verbindungen lauscht. Der Standardwert ist
3306
. Wenn Sie hier
-1
einsetzen, wird eine
Named-Pipe-Verbindung verwendet.
Die folgende Tabelle führt die Namen für alle zulässigen
Schlüsselwortwerte des ConnectionString
s
auf.
Name | Standardwert | Beschreibung |
Connect Timeout -oder- Connection Timeout | 15 | So viele Sekunden wird auf eine Serververbindung gewartet, ehe der Versuch abgebrochen und ein Fehler ausgelöst wird. |
Host -oder- Server -oder- Data Source -oder- DataSource -oder- Address -oder- Addr -oder- Network Address | localhost | Name oder Netzwerkadresse der MySQL-Instanz, mit der Verbindung aufgenommen wird. Es können mehrere, durch & getrennte Hosts angegeben werden. Das kann praktisch sein, wenn mehrere MySQL Server für die Replikation konfiguriert wurden und Sie nicht wissen, mit welchem Server Sie sich verbinden. Da der Provider Schreibvorgänge auf der Datenbank nicht synchronisiert, müssen Sie mit dieser Option vorsichtig sein. In einer Unix-Umgebung mit Mono kann dies ein vollqualifizierter Pfad zu einer MySQL-Socketdatei sein. Dann wird der Unix-Socket anstelle des TCP/IP-Sockets benutzt. Da zurzeit nur ein einziger Socketname angegeben werden kann, wird der MySQL-Zugriff in einer Replikationsumgebung über Unix-Sockets aktuell noch nicht unterstützt. |
Port | 3306 | Der Port, auf dem MySQL auf Verbindungen lauscht. Wenn Sie hier -1 angeben, wird eine Named-Pipe-Verbindung benutzt (nur Windows). Dieser Wert wird bei Verwendung von Unix-Socket ignoriert. |
Protocol | socket | Gibt an, welche Art von Serververbindung eingerichtet wird. Mögliche Werte sind: socket oder tcp für eine Socketverbindung, pipe für eine Named-Pipe-Verbindung, unix für eine Unix-Socketverbindung und memory für MySQL-Shared Memory |
CharSet -oder- Character Set | Der Zeichensatz, mit dem alle an den Server gesandten Anfragen kodiert werden. Ergebnismengen werden weiterhin in dem Zeichensatz der Rückgabedaten kodiert. | |
Logging | false | Ist diese Option true, werden diverse Informationen an die eingestellten TraceListeners ausgegeben. |
Allow Batch | true | Ist diese Option true, können mehrere SQL-Anweisungen mit einem einzigen Befehl ausgeführt werden. Hinweis: Seit MySQL 4.1.1 müssen Batch-Anweisungen durch das für den Server definierte Trennzeichen voneinander abgesetzt werden. Für frühere Versionen von MySQL ist ';' das Trennzeichen. |
Encrypt | false | Ist diese Option true , wird für alle zwischen Client
und Server übermittelten Daten SSL-Verschlüsselung
verwendet, wenn auf dem Server ein Zertifikat
installiert ist. Zulässige Werte sind
true , false ,
yes und no .
Hinweis: Dieser
Parameter ist zurzeit wirkungslos. |
Initial Catalog -oder- Database | mysql | Der Name der Datenbank, die anfangs genutzt wird |
Password -oder- pwd | Das Passwort für das verwendete MySQL-Konto | |
Persist Security Info | false | Ist diese Option false oder no
(was dringend empfohlen wird), werden
sicherheitsrelevante Daten wie beispielsweise das
Passwort nicht mit der Verbindung zurückgegeben, wenn
die Verbindung geöffnet ist oder jemals war. Mit dem
Verbindungs-String werden auch alle darin enthaltenen
Werte zurückgesetzt, einschließlich des Passworts.
Zulässige Werte sind true ,
false , yes und
no . |
User Id -oder- Username -oder- Uid -oder- User name | Das für das Login verwendete MySQL-Konto | |
Shared Memory Name | MYSQL | Der Name des Shared Memory-Objekts, das für die Kommunikation genutzt wird, wenn das Verbindungsprotokoll auf "memory" gesetzt wurde. |
Allow Zero Datetime | false | Stellen Sie dies auf true, wenn MySqlDataReader.GetValue() für Datums-/Uhrzeitspalten, die unzulässige Werte aufweisen, eine MySqlDateTime zurückgeben soll, und auf false, wenn nur für zulässige Werte ein DateTime-Objekt, aber für unzulässige eine Ausnahme zurückgegeben werden soll. |
Convert Zero Datetime | false | Ist diese Option true, geben MySqlDataReader.GetValue() und MySqlDataReader.GetDateTime() für Datums- oder Datums-/Uhrzeitspalten, die unzulässige Werte aufweisen, DateTime.MinValue zurück. |
Old Syntax -oder- OldSyntax | false | Erlaubt '@' als Parameterkennzeichen. Mehr darüber in
MySqlCommand . Dient nur der
Kompatibilität. Zukünftig soll immer das
Parameterkennzeichen '?' benutzt werden. |
Pipe Name -oder- Pipe | mysql | Ist diese der Name einer Named Pipe, versucht
MySqlConnection , diese zur
Verbindung zu nutzen. Gilt nur für Windows. |
Sobald Sie den Verbindungs-String angelegt haben, können Sie ihn nutzen, um eine Verbindung zu einem MySQL Server damit aufzubauen.
Der folgende Code erzeugt ein
MySqlConnection
-Objekt, weist den
Verbindungs-String zu und öffnet die Verbindung.
Visual Basic-Beispiel
Dim conn As New MySql.Data.MySqlClient.MySqlConnection Dim myConnectionString as String myConnectionString = "server=127.0.0.1;" _ & "uid=root;" _ & "pwd=12345;" _ & "database=test;" Try conn.ConnectionString = myConnectionString conn.Open() Catch ex As MySql.Data.MySqlClient.MySqlException MessageBox.Show(ex.Message) End Try
C#-Beispiel
MySql.Data.MySqlClient.MySqlConnection conn; string myConnectionString; myConnectionString = "server=127.0.0.1;uid=root;" + "pwd=12345;database=test;"; try { conn = new MySql.Data.MySqlClient.MySqlConnection(); conn.ConnectionString = myConnectionString; conn.Open(); } catch (MySql.Data.MySqlClient.MySqlException ex) { MessageBox.Show(ex.Message); }
Sie können den Verbindungs-String auch an den
Klassenkonstruktor von MySqlConnection
übergeben:
Visual Basic-Beispiel
Dim myConnectionString as String myConnectionString = "server=127.0.0.1;" _ & "uid=root;" _ & "pwd=12345;" _ & "database=test;" Try Dim conn As New MySql.Data.MySqlClient.MySqlConnection(myConnectionString) conn.Open() Catch ex As MySql.Data.MySqlClient.MySqlException MessageBox.Show(ex.Message) End Try
C#-Beispiel
MySql.Data.MySqlClient.MySqlConnection conn; string myConnectionString; myConnectionString = "server=127.0.0.1;uid=root;" + "pwd=12345;database=test;"; try { conn = new MySql.Data.MySqlClient.MySqlConnection(myConnectionString); conn.Open(); } catch (MySql.Data.MySqlClient.MySqlException ex) { MessageBox.Show(ex.Message); }
Sobald die Verbindung geöffnet ist, können auch andere Connector/NET-Klassen sie zur Kommunikation mit dem MySQL Server nutzen.
Da eine Verbindung mit einem externen Server immer
Unwägbarkeiten in sich birgt, muss Ihre .NET-Anwendung auch
mit Fehlern umgehen können. Tritt bei der Verbindung ein
Fehler auf, gibt die Klasse MySqlConnection
ein MySqlException
-Objekt zurück. Dieses
Objekt hat zwei Eigenschaften, die für die Fehlerbehandlung
interessant sind:
Message
: eine Meldung, die die Ausnahme
beschreibt
Number
: die MySQL-Fehlernummer
Sie können die Reaktion Ihrer Anwendung auf Fehler auf der Basis der Fehlernummer gestalten. Die beiden Fehler, die bei Verbindungsproblemen am häufigsten auftreten, sind:
0
: Serververbindung nicht möglich
1045
: Benutzername und/oder Passwort
ungültig
Der folgende Code zeigt, wie die Anwendung auf die jeweilige Fehlernummer reagieren kann:
Visual Basic-Beispiel
Dim myConnectionString as String myConnectionString = "server=127.0.0.1;" _ & "uid=root;" _ & "pwd=12345;" _ & "database=test;" Try Dim conn As New MySql.Data.MySqlClient.MySqlConnection(myConnectionString) conn.Open() Catch ex As MySql.Data.MySqlClient.MySqlException Select Case ex.Number Case 0 MessageBox.Show("Cannot connect to server. Contact administrator") Case 1045 MessageBox.Show("Invalid username/password, please try again") End Select End Try
C#-Beispiel
MySql.Data.MySqlClient.MySqlConnection conn; string myConnectionString; myConnectionString = "server=127.0.0.1;uid=root;" + "pwd=12345;database=test;"; try { conn = new MySql.Data.MySqlClient.MySqlConnection(myConnectionString); conn.Open(); } catch (MySql.Data.MySqlClient.MySqlException ex) { switch (ex.Number) { case 0: MessageBox.Show("Cannot connect to server. Contact administrator"); case 1045: MessageBox.Show("Invalid username/password, please try again"); } }
Wichtig: Wenn Sie Datenbanken
mit mehreren Sprachen verwenden, müssen Sie den jeweiligen
Zeichensatz im Verbindungs-String angeben, sonst wird
latin1
als Standardzeichensatz zugrunde
gelegt. Ein Beispiel für die Angabe eines Zeichensatzes im
Verbindungs-String folgt:
MySqlConnection myConnection = new MySqlConnection("server=127.0.0.1;uid=root;" + "pwd=12345;database=test;Charset=latin1;");
Seit MySQL 4.1 ist es möglich, vorbereitete Anweisungen mit Connector/NET zu verwenden. Diese können bei Anfragen, die immer wieder ausgeführt werden müssen, die Leistung massiv steigern.
Die vorbereitete Ausführung von Anweisungen ist viel schneller als die direkte Ausführung, da die Anfrage nur ein einziges Mal geparst werden muss. Bei einer Direktausführung müsste sie jedes Mal von neuem geparst werden. Außerdem kann die vorbereitete Ausführung die Netzwerklast reduzieren, da bei der Ausführung einer vorbereiteten Anweisung nur die Parameterdaten übermittelt werden müssen.
Ein weiterer Vorteil vorbereiteter Anweisungen ist die Verwendung eines Binärprotokolls, das die Datenübertragung zwischen Client und Server beschleunigt.
Um eine Anweisung vorzubereiten, erzeugen Sie ein
Befehlsobjekt und stellen die Eigenschaft
.CommandText
auf Ihre Anfrage ein.
Nach dem Eintritt in die Anweisung rufen Sie die
.Prepare
-Methode des
MySqlCommand
-Objekts auf. Ist die Anweisung
vorbereitet, fügen Sie die Parameter für die dynamischen
Elemente der Anfrage hinzu.
Danach führen Sie die Anweisung mit
.ExecuteNonQuery()
-,
.ExecuteScalar()
- oder
.ExecuteReader
-Methoden aus.
Für jede weitere Ausführung müssen Sie nur noch die
Parameterwerte einstellen und dann die Ausführungsmethode
erneut aufrufen. Es ist nicht mehr erforderlich, die
.CommandText
-Eigenschaft zu setzen oder die
Parameter umzudefinieren.
Visual Basic-Beispiel
Dim conn As New MySqlConnection Dim cmd As New MySqlCommand conn.ConnectionString = strConnection Try conn.Open() cmd.Connection = conn cmd.CommandText = "INSERT INTO myTable VALUES(NULL, ?number, ?text)" cmd.Prepare() cmd.Parameters.Add("?number", 1) cmd.Parameters.Add("?text", "One") For i = 1 To 1000 cmd.Parameters["?number"].Value = i cmd.Parameters["?text"].Value = "A string value" cmd.ExecuteNonQuery() Next Catch ex As MySqlException MessageBox.Show("Error " & ex.Number & " has occurred: " & ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error) End Try
C#-Beispiel
MySql.Data.MySqlClient.MySqlConnection conn; MySql.Data.MySqlClient.MySqlCommand cmd; conn = new MySql.Data.MySqlClient.MySqlConnection(); cmd = new MySql.Data.MySqlClient.MySqlCommand(); conn.ConnectionString = strConnection; try { conn.Open(); cmd.Connection = conn; cmd.CommandText = "INSERT INTO myTable VALUES(NULL, ?number, ?text)"; cmd.Prepare(); cmd.Parameters.Add("?number", 1); cmd.Parameters.Add("?text", "One"); for (int i=1; i <= 1000; i++) { cmd.Parameters["?number"].Value = i; cmd.Parameters["?text"].Value = "A string value"; cmd.ExecuteNonQuery(); } } catch (MySql.Data.MySqlClient.MySqlException ex) { MessageBox.Show("Error " + ex.Number + " has occurred: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); }
Seit der MySQL-Version 5 kennt der MySQL Server nun auch gespeicherte Prozeduren mit der Syntax von SQL 2003.
Eine gespeicherte Prozedur besteht in einer Reihe von SQL-Anweisungen, die im Server gespeichert werden können. fortan müssen die Clients keine individuellen Anweisungen mehr geben, sondern können stattdessen auf die gespeicherte Prozedur verweisen.
Gespeicherte Prozeduren können vor allem in folgenden Situationen nützlich sein:
Wenn mehrere Clientanwendungen in verschiedenen Sprachen für unterschiedliche Plattformen geschrieben wurden, aber dieselben Datenbankoperationen ausführen.
In Hochsicherheitsumgebungen. Banken nutzen beispielsweise für alle häufigen Operationen gespeicherte Prozeduren. So bleibt die Umgebung konsistent und sicher, und die Prozeduren sorgen dafür, dass jede Operation ordentlich protokolliert wird. In einer solchen Konstellation haben Anwendungen und Benutzer keinen Direktzugriff auf die Datenbanktabellen, sondern können lediglich bestimmte gespeicherte Prozeduren ausführen.
Connector/NET unterstützt den Aufruf von gespeicherten
Prozeduren mit dem MySqlCommand
-Objekt. Zur
Übergabe von Daten in die und aus der gespeicherten Prozedur
von MySQL dient die
MySqlCommand.Parameters
-Collection.
Hinweis:
Wenn Sie eine gespeicherte Prozedur aufrufen, setzt das
Befehlsobjekt einen zusätzlichen
SELECT
-Aufruf ab, um die Parameter der
gespeicherten Prozedur zu ermitteln. Sie müssen
sicherstellen, dass der Benutzer, der die Prozedur aufruft,
die SELECT
-Berechtigung für die
mysql.proc
-Tabelle besitzt, um die
Parameter überprüfen zu können. Sonst wird beim Aufruf
der Prozedur ein Fehler ausgelöst.
Eine tiefer gehende Erörterung zu gespeicherten Prozeduren finden Sie in http://dev.mysql.com/doc/mysql/en/stored-procedures.html, aber nicht im vorliegenden Abschnitt.
Eine Beispielanwendung zur Verwendung von gespeicherten
Prozeduren mit Connector/NET finden Sie im
Samples
-Verzeichnis Ihrer
Connector/NET-Installation.
In MySQL gibt es mehrere Möglichkeiten, gespeicherte
Prozeduren anzulegen. Erstens können gespeicherte Prozeduren
mit dem Kommandozeilen-Client mysql erzeugt
werden, zweitens mit dem GUI-Client MySQL Query
Browser
und drittens mit der
.ExecuteNonQuery
-Methode des
MySqlCommand
-Objekts:
Visual Basic-Beispiel
Dim conn As New MySqlConnection Dim cmd As New MySqlCommand conn.ConnectionString = "server=127.0.0.1;" _ & "uid=root;" _ & "pwd=12345;" _ & "database=test" Try conn.Open() cmd.Connection = conn cmd.CommandText = "CREATE PROCEDURE add_emp(" _ & "IN fname VARCHAR(20), IN lname VARCHAR(20), IN bday DATETIME, OUT empno INT) " _ & "BEGIN INSERT INTO emp(first_name, last_name, birthdate) " _ & "VALUES(fname, lname, DATE(bday)); SET empno = LAST_INSERT_ID(); END" cmd.ExecuteNonQuery() Catch ex As MySqlException MessageBox.Show("Error " & ex.Number & " has occurred: " & ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error) End Try
C#-Beispiel
MySql.Data.MySqlClient.MySqlConnection conn; MySql.Data.MySqlClient.MySqlCommand cmd; conn = new MySql.Data.MySqlClient.MySqlConnection(); cmd = new MySql.Data.MySqlClient.MySqlCommand(); conn.ConnectionString = "server=127.0.0.1;uid=root;" + "pwd=12345;database=test;"; try { conn.Open(); cmd.Connection = conn; cmd.CommandText = "CREATE PROCEDURE add_emp(" + "IN fname VARCHAR(20), IN lname VARCHAR(20), IN bday DATETIME, OUT empno INT) " + "BEGIN INSERT INTO emp(first_name, last_name, birthdate) " + "VALUES(fname, lname, DATE(bday)); SET empno = LAST_INSERT_ID(); END"; cmd.ExecuteNonQuery(); } catch (MySql.Data.MySqlClient.MySqlException ex) { MessageBox.Show("Error " + ex.Number + " has occurred: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); }
Wenn Sie gespeicherte Prozeduren in Connector/NET anlegen, sind Sie, anders als beim Kommandozeilen- oder GUI-Client, nicht auf ein bestimmtes Trennzeichen festgelegt.
Um eine gespeicherte Prozedur mit Connector/NET aufzurufen,
erzeugen Sie ein MySqlCommand
-Objekt und
übergeben den Namen der Prozedur als
.CommandText
-Eigenschaft. Setzen Sie die
.CommandType
-Eigenschaft auf
CommandType.StoredProcedure
.
Auf die Angabe der gespeicherten Prozedur folgt für jeden
ihrer Parameter ein MySqlCommand
-Parameter.
IN
-Parameter werden mit ihrem Namen und dem
Objekt, das ihren Wert enthält, definiert, und
OUT
-Parameter mit ihrem Namen und dem
erwarteten Rückgabe-Datentyp. Alle Parameter müssen mit
Richtung definiert werden.
Sind die Parameter angelegt, so kann die gespeicherte Prozedur
mit der Methode
MySqlCommand.ExecuteNonQuery()
aufgerufen
werden:
Visual Basic-Beispiel
Dim conn As New MySqlConnection Dim cmd As New MySqlCommand conn.ConnectionString = "server=127.0.0.1;" _ & "uid=root;" _ & "pwd=12345;" _ & "database=test" Try conn.Open() cmd.Connection = conn cmd.CommandText = "add_emp" cmd.CommandType = CommandType.StoredProcedure cmd.Parameters.Add("?lname", 'Jones') cmd.Parameters["?lname"].Direction = ParameterDirection.Input cmd.Parameters.Add("?fname", 'Tom') cmd.Parameters["?fname"].Direction = ParameterDirection.Input cmd.Parameters.Add("?bday", #12/13/1977 2:17:36 PM#) cmd.Parameters["?bday"].Direction = ParameterDirection.Input cmd.Parameters.Add("?empno", MySqlDbType.Int32) cmd.Parameters["?empno"].Direction = ParameterDirection.Output cmd.ExecuteNonQuery() MessageBox.Show(cmd.Parameters["?empno"].Value) Catch ex As MySqlException MessageBox.Show("Error " & ex.Number & " has occurred: " & ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error) End Try
C#-Beispiel
MySql.Data.MySqlClient.MySqlConnection conn; MySql.Data.MySqlClient.MySqlCommand cmd; conn = new MySql.Data.MySqlClient.MySqlConnection(); cmd = new MySql.Data.MySqlClient.MySqlCommand(); conn.ConnectionString = "server=127.0.0.1;uid=root;" + "pwd=12345;database=test;"; try { conn.Open(); cmd.Connection = conn; cmd.CommandText = "add_emp"; cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.Add("?lname", "Jones"); cmd.Parameters["?lname"].Direction = ParameterDirection.Input; cmd.Parameters.Add("?fname", "Tom"); cmd.Parameters["?fname"].Direction = ParameterDirection.Input; cmd.Parameters.Add("?bday", DateTime.Parse("12/13/1977 2:17:36 PM")); cmd.Parameters["?bday"].Direction = ParameterDirection.Input; cmd.Parameters.Add("?empno", MySqlDbType.Int32); cmd.Parameters["?empno"].Direction = ParameterDirection.Output; cmd.ExecuteNonQuery(); MessageBox.Show(cmd.Parameters["?empno"].Value); } catch (MySql.Data.MySqlClient.MySqlException ex) { MessageBox.Show("Error " + ex.Number + " has occurred: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); }
Sobald die gespeicherte Prozedur aufgerufen wird, können die
Werte ihrer Ausgabeparameter mit der
.Value
-Eigenschaft der
MySqlConnector.Parameters
-Collection
abgerufen werden.
Häufig werden mit MySQL Binärdaten in
BLOB
-Spalten gespeichert. MySQL
unterstützt vier verschiedene BLOB-Datentypen:
TINYBLOB
, BLOB
,
MEDIUMBLOB
und LONGBLOB
.
Die Daten einer BLOB-Spalte können mit Connector/NET angesprochen und mit clientseitigem Code manipuliert werden. Es gibt keine Sonderbedingungen für den Einsatz von Connector/NET mit BLOB-Daten.
In diesem Abschnitt werden wir einfache Codebeispiele
vorstellen. Eine vollständige Musteranwendung finden Sie im
Samples
-Verzeichnis der
Connector/NET-Installation.
Um MySQL für BLOB-Daten einsetzen zu können, müssen Sie als Erstes den Server konfigurieren. Zunächst werden wir eine Tabelle anlegen. Meine Dateitabellen haben normalerweise vier Spalten: Eine AUTO_INCREMENT-Spalte passender Größe (UNSIGNED SMALLINT) dient als Primärschlüssel, um die Datei zu identifizieren, eine VARCHAR-Spalte speichert den Dateinamen, eine UNSIGNED MEDIUMINT-Spalte hält die Größe der Datei fest und eine MEDIUMBLOB-Spalte enthält die Datei selbst. Für dieses Beispiel werde ich folgende Tabellendefinition einsetzen:
CREATE TABLE file( file_id SMALLINT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, file_name VARCHAR(64) NOT NULL, file_size MEDIUMINT UNSIGNED NOT NULL, file MEDIUMBLOB NOT NULL);
Nach der Erstellung einer Tabelle muss eventuell die Systemvariable max_allowed_packet modifiziert werden, die festlegt, welche maximale Paketgröße (d. h. eine einzelne Zeile) an den MySQL Server geschickt werden kann. Nach Voreinstellung akzeptiert der Server nur 1 Mbyte als maximale Paketgröße von der Clientanwendung. Wenn Sie diesen Wert nicht überschreiten wollen, ist er in Ordnung, aber wenn doch, müssen Sie ihn heraufsetzen.
Die Option max_allowed_packet kann in den MySQL
Administrator's Startup Variables eingestellt werden. Setzen
Sie hierzu die Option Maximum allowed im Memory-Teil der
Registerkarte Networking auf einen geeigneten Wert. Dann
klicken Sie auf Service
Control
-Bildschirm des MySQL Administrators neu. Sie
können diesen Wert allerdings auch direkt in der my.cnf-Datei
einstellen (und die Zeile max_allowed_packet=xxM hinzufügen)
oder die Syntax SET max_allowed_packet=xxM; in MySQL nutzen.
Bitte stellen Sie max_allowed_packet nicht zu hoch ein, da eine Übertragung von BLOB-Daten viel Zeit in Anspruch nehmen kann. Versuchen Sie, einen für Ihre Situation angemessenen Wert zu finden, und setzen Sie ihn notfalls später herauf.
Um eine Datei in eine Datenbank zu schreiben, konvertieren wir
die Datei zuerst in ein Byte-Array und übergeben dieses dann
als Parameter an die INSERT
-Anfrage.
Der folgende Code öffnet eine Datei mithilfe eines
FileStream-Objekts, liest sie in ein Byte-Array ein und fügt
sie in die Tabelle file
ein:
Visual Basic-Beispiel
Dim conn As New MySqlConnection Dim cmd As New MySqlCommand Dim SQL As String Dim FileSize As UInt32 Dim rawData() As Byte Dim fs As FileStream conn.ConnectionString = "server=127.0.0.1;" _ & "uid=root;" _ & "pwd=12345;" _ & "database=test" Try fs = New FileStream("c:\image.png", FileMode.Open, FileAccess.Read) FileSize = fs.Length rawData = New Byte(FileSize) {} fs.Read(rawData, 0, FileSize) fs.Close() conn.Open() SQL = "INSERT INTO file VALUES(NULL, ?FileName, ?FileSize, ?File)" cmd.Connection = conn cmd.CommandText = SQL cmd.Parameters.Add("?FileName", strFileName) cmd.Parameters.Add("?FileSize", FileSize) cmd.Parameters.Add("?File", rawData) cmd.ExecuteNonQuery() MessageBox.Show("File Inserted into database successfully!", _ "Success!", MessageBoxButtons.OK, MessageBoxIcon.Asterisk) conn.Close() Catch ex As Exception MessageBox.Show("There was an error: " & ex.Message, "Error", _ MessageBoxButtons.OK, MessageBoxIcon.Error) End Try
C#-Beispiel
MySql.Data.MySqlClient.MySqlConnection conn; MySql.Data.MySqlClient.MySqlCommand cmd; conn = new MySql.Data.MySqlClient.MySqlConnection(); cmd = new MySql.Data.MySqlClient.MySqlCommand(); string SQL; UInt32 FileSize; byte[] rawData; FileStream fs; conn.ConnectionString = "server=127.0.0.1;uid=root;" + "pwd=12345;database=test;"; try { fs = new FileStream(@"c:\image.png", FileMode.Open, FileAccess.Read); FileSize = fs.Length; rawData = new byte[FileSize]; fs.Read(rawData, 0, FileSize); fs.Close(); conn.Open(); SQL = "INSERT INTO file VALUES(NULL, ?FileName, ?FileSize, ?File)"; cmd.Connection = conn; cmd.CommandText = SQL; cmd.Parameters.Add("?FileName", strFileName); cmd.Parameters.Add("?FileSize", FileSize); cmd.Parameters.Add("?File", rawData); cmd.ExecuteNonQuery(); MessageBox.Show("File Inserted into database successfully!", "Success!", MessageBoxButtons.OK, MessageBoxIcon.Asterisk); conn.Close(); } catch (MySql.Data.MySqlClient.MySqlException ex) { MessageBox.Show("Error " + ex.Number + " has occurred: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); }
Die Methode Read
des
FileStream
-Objekts lädt die Datei in ein
Byte-Array, über dessen Größe die
Length
-Eigenschaft des FileStream-Objekts
entscheidet.
Nachdem das Byte-Array als Parameter des
MySqlCommand
-Objekts zugewiesen wurde, wird
die ExecuteNonQuery
-Methode aufgerufen und
der BLOB in die file
-Tabelle eingefügt.
Sobald wir eine Datei in der file
-Tabelle
gespeichert haben, können wir sie mit der Klasse
MySqlDataReader
abrufen.
Der folgende Code ruft eine Zeile aus der Tabelle
file
ab und lädt die Daten dann in ein
FileStream
-Objekt, das auf die Festplatte
geschrieben wird:
Visual Basic-Beispiel
Dim conn As New MySqlConnection Dim cmd As New MySqlCommand Dim myData As MySqlDataReader Dim SQL As String Dim rawData() As Byte Dim FileSize As UInt32 Dim fs As FileStream conn.ConnectionString = "server=127.0.0.1;" _ & "uid=root;" _ & "pwd=12345;" _ & "database=test" SQL = "SELECT file_name, file_size, file FROM file" Try conn.Open() cmd.Connection = conn cmd.CommandText = SQL myData = cmd.ExecuteReader If Not myData.HasRows Then Throw New Exception("There are no BLOBs to save") myData.Read() FileSize = myData.GetUInt32(myData.GetOrdinal("file_size")) rawData = New Byte(FileSize) {} myData.GetBytes(myData.GetOrdinal("file"), 0, rawData, 0, FileSize) fs = New FileStream("C:\newfile.png", FileMode.OpenOrCreate, FileAccess.Write) fs.Write(rawData, 0, FileSize) fs.Close() MessageBox.Show("File successfully written to disk!", "Success!", MessageBoxButtons.OK, MessageBoxIcon.Asterisk) myData.Close() conn.Close() Catch ex As Exception MessageBox.Show("There was an error: " & ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error) End Try
C#-Beispiel
MySql.Data.MySqlClient.MySqlConnection conn; MySql.Data.MySqlClient.MySqlCommand cmd; MySql.Data.MySqlClient.MySqlDataReader myData; conn = new MySql.Data.MySqlClient.MySqlConnection(); cmd = new MySql.Data.MySqlClient.MySqlCommand(); string SQL; UInt32 FileSize; byte[] rawData; FileStream fs; conn.ConnectionString = "server=127.0.0.1;uid=root;" + "pwd=12345;database=test;"; SQL = "SELECT file_name, file_size, file FROM file"; try { conn.Open(); cmd.Connection = conn; cmd.CommandText = SQL; myData = cmd.ExecuteReader(); if (! myData.HasRows) throw new Exception("There are no BLOBs to save"); myData.Read(); FileSize = myData.GetUInt32(myData.GetOrdinal("file_size")); rawData = new byte[FileSize]; myData.GetBytes(myData.GetOrdinal("file"), 0, rawData, 0, FileSize); fs = new FileStream(@"C:\newfile.png", FileMode.OpenOrCreate, FileAccess.Write); fs.Write(rawData, 0, FileSize); fs.Close(); MessageBox.Show("File successfully written to disk!", "Success!", MessageBoxButtons.OK, MessageBoxIcon.Asterisk); myData.Close(); conn.Close(); } catch (MySql.Data.MySqlClient.MySqlException ex) { MessageBox.Show("Error " + ex.Number + " has occurred: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); }
Nach dem Aufbau der Verbindung werden die Daten der
file
-Tabelle in ein
MySqlDataReader
-Objekt geladen. Die Methode
GetBytes
des MySqlDataReaders lädt den
BLOB in ein Byte-Array, das dann mit einem FileStream-Objekt
auf die Festplatte geschrieben wird.
Die Methode GetOrdinal
des MySqlDataReaders
kann den ganzzahligen Index einer benannten Spalte ermitteln.
Wenn Sie GetOrdinal verwenden, vermeiden Sie Fehler, die bei
einer Änderung der Spaltenreihenfolge in der
SELECT
-Anfrage entstehen könnten.
Crystal Reports ist ein Tool, das Windows-Anwendungsentwickler gerne für das Reporting und zur Dokumenterstellung einsetzen. In diesem Abschnitt erfahren Sie, wie man Crystal Reports XI mit MySQL und Connector/NET einsetzt.
Wenn Sie in Crystal Reports einen Bericht anlegen, können Sie in zwei Weisen auf MySQL-Daten für den Bericht zugreifen.
Die erste Möglichkeit: Sie verwenden Connector/ODBC als ADO-Datenquelle, wenn Sie Ihren Bericht entwerfen. Sie können dann in der Datenbank stöbern und Tabellen und Felder mit Drag & Drop in den Bericht einbinden. Der Nachteil dieser Methode: Es ist zusätzliche Arbeit an Ihrer Anwendung erforderlich, um ein zu Ihrem Bericht passendes Dataset zu erzeugen.
Die zweite Möglichkeit: Sie erstellen ein Dataset in VB.NET und speichern Sie im XML-Format. Diese XML-Datei kann dann zur Berichterstellung eingesetzt werden. Das funktioniert zwar recht gut, wenn Sie den Bericht in Ihrer Anwendung anzeigen, ist aber zur Entwurfszeit unpraktisch, da Sie alle relevanten Spalten auswählen müssen, wenn Sie das Dataset anlegen. Vergessen Sie eine Spalte, so müssen Sie das gesamte Dataset neu anlegen, um die Spalte dem Bericht hinzuzufügen.
Mit dem folgenden Code erzeugen Sie aus einer Anfrage ein Dataset und schreiben es auf die Festplatte:
Visual Basic-Beispiel
Dim myData As New DataSet Dim conn As New MySqlConnection Dim cmd As New MySqlCommand Dim myAdapter As New MySqlDataAdapter conn.ConnectionString = "server=127.0.0.1;" _ & "uid=root;" _ & "pwd=12345;" _ & "database=world" Try conn.Open() cmd.CommandText = "SELECT city.name AS cityName, city.population AS CityPopulation, " _ & "country.name, country.population, country.continent " _ & "FROM country, city ORDER BY country.continent, country.name" cmd.Connection = conn myAdapter.SelectCommand = cmd myAdapter.Fill(myData) myData.WriteXml("C:\dataset.xml", XmlWriteMode.WriteSchema) Catch ex As Exception MessageBox.Show(ex.Message, "Report could not be created", MessageBoxButtons.OK, MessageBoxIcon.Error) End Try
C#-Beispiel
DataSet myData = new DataSet(); MySql.Data.MySqlClient.MySqlConnection conn; MySql.Data.MySqlClient.MySqlCommand cmd; MySql.Data.MySqlClient.MySqlDataAdapter myAdapter; conn = new MySql.Data.MySqlClient.MySqlConnection(); cmd = new MySql.Data.MySqlClient.MySqlCommand(); myAdapter = new MySql.Data.MySqlClient.MySqlDataAdapter(); conn.ConnectionString = "server=127.0.0.1;uid=root;" + "pwd=12345;database=test;"; try { cmd.CommandText = "SELECT city.name AS cityName, city.population AS CityPopulation, " + "country.name, country.population, country.continent " + "FROM country, city ORDER BY country.continent, country.name"; cmd.Connection = conn; myAdapter.SelectCommand = cmd; myAdapter.Fill(myData); myData.WriteXml(@"C:\dataset.xml", XmlWriteMode.WriteSchema); } catch (MySql.Data.MySqlClient.MySqlException ex) { MessageBox.Show(ex.Message, "Report could not be created", MessageBoxButtons.OK, MessageBoxIcon.Error); }
Die resultierende XML-Datei kann bei der Berichterstellung als ADO.NET XML-Datenquelle verwendet werden.
Wenn Sie Ihre Berichte mit Connector/ODBC erstellen möchten, können Sie diese Komponente von dev.mysql.com herunterladen.
Für die meisten Zwecke müsste der Standard Report-Assistent
für die ersten Schritte der Berichterstellung ausreichen. Um
den Assistenten zu starten, öffnen Sie Crystal Reports und
wählen aus dem Dateimenü die Option Neu > Standard
Report
.
Der Assistent fragt Sie dann nach einer Datenquelle. Wenn Sie Connector/ODBC verwenden, wählen Sie die Option OLEDB provider for ODBC aus dem OLE DB (ADO)-Baum statt aus dem ODBC (RDO)-Baum, wenn Sie die Datenquelle einstellen. Wenn Sie ein gespeichertes Dataset verwenden, wählen Sie die Option ADO.NET (XML) und gehen zu diesem Dataset.
Der Rest des Berichterstellungsprozesses läuft im Assistenten automatisch ab.
Nachdem der Bericht angelegt wurde, wählen Sie den Eintrag Report Options... aus dem Dateimenü. Deaktivieren Sie die Option Save Data With Report, damit keine gespeicherten Daten das Laden der Daten in Ihrer Anwendung behindern.
Um einen Bericht anzuzeigen, laden wir zuerst das Dataset hinein, in dem die benötigten Daten gespeichert sind, laden dann den Bericht und binden ihn an das Dataset. Zum Schluss übergeben wir den Bericht an den crViewer, damit er dem Benutzer angezeigt wird.
Folgendes müssen Sie in einem Projekt, das einen Bericht anzeigt, referenzieren:
CrytalDecisions.CrystalReports.Engine
CrystalDecisions.ReportSource
CrystalDecisions.Shared
CrystalDecisions.Windows.Forms
Der folgende Code geht davon aus, dass Sie Ihren Bericht mit
einem Dataset angelegt haben, das wie in
Abschnitt 25.2.3.5.2, „Datenquelle anlegen“,
gezeigt gespeichert wurde, und dass Sie einen crViewer namens
myViewer
auf Ihrem Formular haben.
Visual Basic-Beispiel
Imports CrystalDecisions.CrystalReports.Engine Imports System.Data Imports MySql.Data.MySqlClient Dim myReport As New ReportDocument Dim myData As New DataSet Dim conn As New MySqlConnection Dim cmd As New MySqlCommand Dim myAdapter As New MySqlDataAdapter conn.ConnectionString = _ "server=127.0.0.1;" _ & "uid=root;" _ & "pwd=12345;" _ & "database=test" Try conn.Open() cmd.CommandText = "SELECT city.name AS cityName, city.population AS CityPopulation, " _ & "country.name, country.population, country.continent " _ & "FROM country, city ORDER BY country.continent, country.name" cmd.Connection = conn myAdapter.SelectCommand = cmd myAdapter.Fill(myData) myReport.Load(".\world_report.rpt") myReport.SetDataSource(myData) myViewer.ReportSource = myReport Catch ex As Exception MessageBox.Show(ex.Message, "Report could not be created", MessageBoxButtons.OK, MessageBoxIcon.Error) End Try
C#-Beispiel
using CrystalDecisions.CrystalReports.Engine; using System.Data; using MySql.Data.MySqlClient; ReportDocument myReport = new ReportDocument(); DataSet myData = new DataSet(); MySql.Data.MySqlClient.MySqlConnection conn; MySql.Data.MySqlClient.MySqlCommand cmd; MySql.Data.MySqlClient.MySqlDataAdapter myAdapter; conn = new MySql.Data.MySqlClient.MySqlConnection(); cmd = new MySql.Data.MySqlClient.MySqlCommand(); myAdapter = new MySql.Data.MySqlClient.MySqlDataAdapter(); conn.ConnectionString = "server=127.0.0.1;uid=root;" + "pwd=12345;database=test;"; try { cmd.CommandText = "SELECT city.name AS cityName, city.population AS CityPopulation, " + "country.name, country.population, country.continent " + "FROM country, city ORDER BY country.continent, country.name"; cmd.Connection = conn; myAdapter.SelectCommand = cmd; myAdapter.Fill(myData); myReport.Load(@".\world_report.rpt"); myReport.SetDataSource(myData); myViewer.ReportSource = myReport; } catch (MySql.Data.MySqlClient.MySqlException ex) { MessageBox.Show(ex.Message, "Report could not be created", MessageBoxButtons.OK, MessageBoxIcon.Error); }
Ein neues Dataset wird mit derselben Anfrage wie das zuvor gespeicherte angelegt. Sobald es mit Daten gefüllt ist, wird die Berichtsdatei mithilfe eines ReportDocuments geladen und an das Dataset gebunden. Das ReportDocument wird als ReportSource des crViewers übergeben.
Denselben Ansatz verfolgen wir, wenn ein Bericht mit Connector/ODBC aus einer einzelnen Tabelle erstellt wird. Das Dataset ersetzt die im Bericht verwendete Tabelle und der Bericht wird korrekt angezeigt.
Wird ein Bericht mit Connector/ODBC aus mehreren Tabellen erstellt, müssen wir in unserer Anwendung ein Dataset aus mehreren Tabellen anlegen. So kann jede Tabelle aus der Berichtsdatenquelle im Dataset durch einen Bericht ersetzt werden.
Um mehrere Tabellen in ein Dataset zu laden, sind mehrere
SELECT
-Anweisungen in unserem
MySqlCommand-Objekt erforderlich. Diese
SELECT
-Anweisungen beruhen auf der
SQL-Anfrage, die in Crystal Reports in der Option Show SQL
Query des Datenbankmenüs angezeigt wird. Legen wir einmal
folgende Anfrage zugrunde:
SELECT `country`.`Name`, `country`.`Continent`, `country`.`Population`, `city`.`Name`, `city`.`Population` FROM `world`.`country` `country` LEFT OUTER JOIN `world`.`city` `city` ON `country`.`Code`=`city`.`CountryCode` ORDER BY `country`.`Continent`, `country`.`Name`, `city`.`Name`
Diese Anfrage wird in zwei SELECT
-Anfragen
aufgespalten und mit folgendem Code angezeigt:
Visual Basic-Beispiel
Imports CrystalDecisions.CrystalReports.Engine Imports System.Data Imports MySql.Data.MySqlClient Dim myReport As New ReportDocument Dim myData As New DataSet Dim conn As New MySqlConnection Dim cmd As New MySqlCommand Dim myAdapter As New MySqlDataAdapter conn.ConnectionString = "server=127.0.0.1;" _ & "uid=root;" _ & "pwd=12345;" _ & "database=world" Try conn.Open() cmd.CommandText = "SELECT name, population, countrycode FROM city ORDER BY countrycode, name; " _ & "SELECT name, population, code, continent FROM country ORDER BY continent, name" cmd.Connection = conn myAdapter.SelectCommand = cmd myAdapter.Fill(myData) myReport.Load(".\world_report.rpt") myReport.Database.Tables(0).SetDataSource(myData.Tables(0)) myReport.Database.Tables(1).SetDataSource(myData.Tables(1)) myViewer.ReportSource = myReport Catch ex As Exception MessageBox.Show(ex.Message, "Report could not be created", MessageBoxButtons.OK, MessageBoxIcon.Error) End Try
C#-Beispiel
using CrystalDecisions.CrystalReports.Engine;
using System.Data;
using MySql.Data.MySqlClient;
ReportDocument myReport = new ReportDocument();
DataSet myData = new DataSet();
MySql.Data.MySqlClient.MySqlConnection conn;
MySql.Data.MySqlClient.MySqlCommand cmd;
MySql.Data.MySqlClient.MySqlDataAdapter myAdapter;
conn = new MySql.Data.MySqlClient.MySqlConnection();
cmd = new MySql.Data.MySqlClient.MySqlCommand();
myAdapter = new MySql.Data.MySqlClient.MySqlDataAdapter();
conn.ConnectionString = "server=127.0.0.1;uid=root;" +
"pwd=12345;database=test;";
try
{
cmd.CommandText = "SELECT name, population, countrycode FROM city ORDER " +
"BY countrycode, name; SELECT
name, population, code, continent FROM " +
"country ORDER BY continent, name";
cmd.Connection = conn;
myAdapter.SelectCommand = cmd;
myAdapter.Fill(myData);
myReport.Load(@".\world_report.rpt");
myReport.Database.Tables(0).SetDataSource(myData.Tables(0));
myReport.Database.Tables(1).SetDataSource(myData.Tables(1));
myViewer.ReportSource = myReport;
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
MessageBox.Show(ex.Message, "Report could not be created",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
Die SELECT
-Anfragen müssen unbedingt in
alphabetischer Reihenfolge stehen, da der Bericht erwartet,
dass seine Quelltabellen diese Reihenfolge haben. Für jede
Tabelle im Bericht ist eine SetDataSource-Anweisung
erforderlich.
Dieser Ansatz kann Performanceprobleme mit sich bringen, da Crystal Reports die Tabellen auf der Clientseite aneinander binden muss. Das braucht mehr Zeit als ein vordefiniertes, gespeichertes Dataset.
MySQL und die .NET-Sprachen gehen unterschiedlich mit Datums-
und Uhrzeitinformationen um: MySQL erlaubt Datumswerte, die
von keinem .NET-Datentyp dargestellt werden können, wie etwa
'0000-00-00 00:00:00
'. Diese Unterschiede
können Probleme verursachen, wenn man nicht richtig damit
umgeht.
In diesem Abschnitt werden wir zeigen, wie Datums- und Uhrzeitinformationen mit Connector/NET korrekt behandelt werden.
Die Unterschiede in der Datumsbehandlung können Probleme
bereiten, wenn Entwickler ungültige Datumswerte verwenden.
Ungültige MySQL-Datumswerte, einschließlich
NULL
-Datumswerten, lassen sich nicht in
native DateTime
-Objekte von .NET laden.
Daher können DataSet
-Objekte von .NET
nicht mit der Fill
-Methode der Klasse
MySqlDataAdapter
gefüllt werden, da
ungültige Datumswerte eine
System.ArgumentOutOfRangeException
verursachen würden.
Datumsprobleme lassen sich am besten dadurch in den Griff bekommen, dass die Benutzer gar keine Möglichkeit erhalten, ungültige Datumswerte einzugeben. Dies lässt sich auf der Client- oder der Serverseite bewerkstelligen.
Um ungültige Datumswerte auf der Clientseite zu unterbinden,
müssen Sie die Datumswerte nur immer mit der .NET-Klasse
DateTime
behandeln. Diese erlaubt nämlich
nur gültige Datumswerte und stellt dadurch sicher, dass auch
in Ihre Datenbank nur gültige Werte gelangen. Leider kann man
sie jedoch nicht in einer gemischten Umgebung einsetzen, in
der die Datenbank sowohl mit .NET- als auch mit
Nicht-.NET-Code bearbeitet wird, da jede Anwendung ihre eigene
Datumsvalidierung vornehmen muss.
Auf MySQL 5.0.2 und höher können Sie den neuen SQL-Modus
traditional
einstellen, um ungültige
Datumswerte zu unterbinden. Informationen über diesen
SQL-Modus erhalten Sie unter traditional
,
Abschnitt 5.2.5, „Der SQL-Modus des Servers“.
Zwar raten wir von ungültigen Datumswerten in
.NET-Anwendungen ausdrücklich ab, aber es ist immerhin
möglich, ungültige Datumswerte über den Datentyp
MySqlDateTime
zu behandeln.
Der Datentyp MySqlDateTime
unterstützt
dieselben Datumswerte wie der MySQL Server. Standardmäßig
gibt Connector/NET für gültige Datumswerte ein
DateTime-Objekt von .NET und für ungültige Datumswerte einen
Fehler zurück. Diese Voreinstellung können Sie jedoch so
abändern, dass Connector/NET
MySqlDateTime
-Objekte für ungültige
Datumswerte zurückliefert.
Damit Connector/NET für ungültige Datumswerte ein
MySqlDateTime
-Objekt zurückgibt, fügen
Sie Ihrem Verbindungs-String folgende Zeile hinzu:
Allow Zero Datetime=True
Bitte beachten Sie, dass die Verwendung der Klasse
MySqlDateTime
immer problematisch sein
kann. Folgende Probleme sind bereits aufgetreten:
Die Datenbindung an ungültige Datumswerte kann trotz allem Fehler verursachen (Null-Datumswerte wie 0000-00-00 scheinen jedoch keine Schwierigkeiten zu bereiten).
Die ToString
-Methode gibt ein Datum im
MySQL-Standardformat zurück (zum Beispiel
2005-02-23 08:50:25
). Dieses
unterscheidet sich von dem
ToString
-Verhalten der .NET-Klasse
DateTime.
Die Klasse MySqlDateTime
unterstützt
NULL-Datumswerte, die .NET-Klasse DateTime hingegen nicht.
Das kann Fehler verursachen, wenn Sie versuchen, eine
MySQLDateTime in ein DateTime-Objekt zu konvertieren, ohne
sie zuvor auf NULL zu prüfen.
Wegen dieser bekannten Probleme lautet der beste Rat: Verwenden Sie bitte nur gültige Datumswerte Ihrer Anwendung.
Der .NET-Datentyp DateTime
kann mit
NULL
-Werten nicht umgehen. Daher müssen
Sie, wenn Sie Werte aus einer Anfrage an eine
DateTime
-Variable zuweisen, immer zuerst
prüfen, ob nicht ein NULL
-Wert vorliegt.
Wenn Sie einen MySqlDataReader
verwenden,
sollten Sie mit der Methode .IsDBNull
überprüfen, ob ein NULL
-Wert vorliegt,
bevor Sie die Zuweisung vornehmen:
Visual Basic-Beispiel
If Not myReader.IsDBNull(myReader.GetOrdinal("mytime")) Then myTime = myReader.GetDateTime(myReader.GetOrdinal("mytime")) Else myTime = DateTime.MinValue End If
C#-Beispiel
if (! myReader.IsDBNull(myReader.GetOrdinal("mytime"))) myTime = myReader.GetDateTime(myReader.GetOrdinal("mytime")); else myTime = DateTime.MinValue;
NULL
-Werte funktionieren nicht in einem
Dataset und können ohne Sonderbehandlung an Formularelemente
gebunden werden.
Den Entwicklern von Connector/NET ist die Meinung der Benutzer und ihr Beitrag zum Softwareentwicklungsprozess sehr wichtig. Wenn Sie bei Connector/NET ein Feature vermissen oder einen Fehler finden und einen Bugreport übermitteln müssen, richten Sie sich bitte nach den Hinweisen in Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“.
Community-Support zu Connector/NET finden Sie in den Foren unter http://forums.mysql.com.
Außerdem erhalten Sie in den Mailinglisten unter http://lists.mysql.com Community-Support für Connector/NET.
MySQL AB bietet auch einen zahlungspflichtigen Support. Informationen darüber finden Sie in http://www.mysql.com/support/.
Wenn Sie Probleme mit Connector/NET haben, wenden Sie sich bitte zuerst an die Connector/NET-Community, siehe Abschnitt 25.2.4.1, „Support von der Connector/NET-Community“.
Zuerst versuchen Sie jedoch, SQL-Anweisungen und -Befehle vom
mysql-Client oder admndemo
abzusetzen. So können Sie erkennen, ob das Problem an
Connector/NET oder MySQL liegt.
Wenn Sie ein Problem melden, geben Sie uns bitte per E-Mail folgende Informationen:
Betriebssystem und Version
Connector/NET-Version
MySQL Server-Version
Kopien von Fehlermeldungen oder anderen unerwarteten Ausgaben
Einfaches, reproduzierbares Beispiel
Achtung: Je mehr Informationen Sie uns geben können, umso wahrscheinlicher ist es, dass wir das Problem beheben können.
Wenn Sie der Auffassung sind, dass es sich um einen Bug handelt, senden Sie uns einen Bugreport über http://bugs.mysql.com/.
MySQL stellt für Clientprogramme, die in Java erstellt wurden, Verbindungsmöglichkeiten über einen JDBC-Treiber namens MySQL Connector/J zur Verfügung.
MySQL Connector/J ist ein JDBC-3.0-Treiber vom „Typ 4“, also reines Java. Er implementiert die Version 3.0 der JDBC-Spezifikation und kommuniziert mit dem MySQL-Server direkt über das MySQL-Protokoll.
JDBC ist zwar sehr hilfreich, doch wenn Sie nach der Lektüre der ersten Abschnitte dieses Kapitels noch nicht voll und ganz damit vertraut sind, sollten Sie mit JDBC alleine nur sehr einfache Probleme bearbeiten. Den Löwenanteil der wiederkehrenden Aufgaben sollten Sie mit einem der populären Persistence-Frameworks wie etwa Hibernate, Spring's JDBC Templates oder Ibatis SQL Maps erledigen und die Grundrenovierungen, die manchmal erforderlich sind, mit JDBC.
Dieser Abschnitt ist nicht als umfassendes JDBC-Tutorial konzipiert. Wenn Sie mehr über JDBC erfahren möchten, schauen Sie bitte in eines der folgenden Online-Tutorials, die mehr in die Tiefe gehen als die vorliegenden Ausführungen:
JDBC Basics — Ein JDBC-Tutorial von Sun für Anfänger
JDBC Short Course — Ein detaillierteres Tutorial von Sun und JGuru
Zurzeit stehen drei Versionen von MySQL Connector/J zur Verfügung:
Connector/J 3.0 stellt die Kernfunktionalität zur Verfügung und wurde für die Verbindung mit MySQL 3.x oder MySQL 4.1 geschaffen, obwohl es auch mit neueren Versionen von MySQL grundsätzlich kompatibel ist. Connector/J 3.0 unterstützt keine vorbereiteten Anweisungen auf der Serverseite und keine neuen Features der MySQL-Versionen nach 4.1.
Connector/J 3.1 dient der Verbindung mit MySQL 4.1- und MySQL 5.0-Servern und unterstützt alle Funktionen von MySQL 5.0 außer verteilten Transaktionen (XA).
Connector/J 5.0 unterstützt dieselben Funktionen wie Connector/J 3.1, aber zusätzlich auch verteilte Transaktionen (XA).
Die zurzeit empfohlene Version von Connector/J ist 5.0. Die vorliegende Anleitung bezieht sich auf alle drei Connector-Versionen und weist besonders darauf hin, wenn eine Einstellung nur für eine bestimmte Option gilt.
MySQL Connector/J unterstützt Java-2-JVMs, einschließlich:
JDK 1.2.x
JDK 1.3.x
JDK 1.4.x
JDK 1.5.x
Wenn Sie Connector/J mit der Quelldistribution aus den Quelldateien erstellen (siehe Abschnitt 25.3.2.4, „Installation vom Entwicklungsquellbaum“), dann müssen Sie JDK 1.4.x oder höher zum Kompilieren des Connectors einsetzen.
MySQL Connector/J funktioniert nicht mit JDK-1.1.x oder JDK-1.0.x
Wegen der Implementierung von
java.sql.Savepoint
funktioniert
Connector/J 3.1.0 und höher nicht mit JDKs, die älter als 1.4
sind, es sei denn, Sie schalten die Klassenprüfung aus
(-Xverify:none
). Diese würde nämlich
versuchen, die Klassendefinition für
java.sql.Savepoint
zu laden, obwohl der
Treiber auf diese Klasse nur zugreift, wenn
Savepoint-Funktionalität genutzt wird.
Auch die Caching-Funktionalität von Connector/J 3.1.0 oder
höher steht für JVMs, die älter als 1.4.x sind, nicht zur
Verfügung, da sie sich auf die Klasse
java.util.LinkedHashMap
stützt, die
erstmals im JDK-1.4.0 eingeführt wurde.
Sie können Connector/J entweder aus der Binär- oder aus der Quelldistribution installieren. Die Binärdistribution ist die einfachste Methode, während die Quelldistribution mehr Anpassungen ermöglicht.
Am einfachsten installieren Sie Connector/J mit der
Binärdistribution. Diese steht als Tar/Gzip- oder Zip-Datei zur
Verfügung. Extrahieren Sie das Archiv in ein passendes
Verzeichnis und stellen Sie optional Informationen über das
verwendete Package zur Verfügung, indem Sie Ihren
CLASSPATH
ändern (siehe
Abschnitt 25.3.2.2, „Treiber installieren und CLASSPATH
konfigurieren“).
MySQL Connector/J wird als .zip- oder .tar.gz-Archiv vertrieben,
das die Quell- und Klassendateien sowie das JAR-Archiv namens
mysql-connector-java-
enthält. Seit Connector/J 3.1.8 ist auch ein Debug-Build des
Treibers in einer Datei namens
[version]
-bin.jarmysql-connector-java-
inbegriffen.
[version]
-bin-g.jar
Ab der Version Connector/J 3.1.9 sind die
.class
-Dateien, die die JAR-Dateien bilden,
nur als Teil der Treiber-JAR-Datei enthalten.
Den „Debug“-Build des Treibers sollten Sie bitte
nur benutzen, wenn Sie dazu aufgefordert werden, um ein Problem
oder einen Fehler an MySQL AB zu melden, da dieser Build nicht
für Produktionsumgebungen geschaffen ist und sich nachteilig
auf die Performance auswirkt. Die Debug-Binärdatei ist
außerdem von der Aspect/J-Laufzeitbibliothek abhängig, die Sie
in der zur Connector/J-Distribution gehörigen Datei
src/lib/aspectjrt.jar
finden.
Um die Distribution auspacken zu können, benötigen Sie ein geeignetes Hilfsprogramm (zum Beispiel WinZip für das .zip-Archiv und tar für das .tar.gz-Archiv). Da die Distribution lange Dateinamen enthalten kann, verwenden wir das GNU-Format für tar-Archive. Mit GNU tar (oder einer Anwendung, die das GNU-tar-Archivformat versteht) können Sie die .tar.gz-Variante der Distribution auspacken.
WennSie das Archiv der Distribution extrahiert haben,
installieren Sie den Treiber, indem Sie Ihrem Klassenpfad
mysql-connector-java-[version]-bin.jar
hinzufügen. Hierzu schreiben Sie entweder den vollständigen
Pfad in Ihre Umgebungsvariable CLASSPATH
oder
geben ihn direkt mit der Kommandozeilenoption -cp an, wenn Sie
Ihre JVM starten.
Wenn Sie den Treiber mit dem JDBC DriverManager benutzen,
verwenden Sie com.mysql.jdbc.Driver
als die
Klasse, die java.sql.Driver
implementiert.
Die Umgebungsvariable CLASSPATH
können Sie
unter UNIX, Linux oder Mac OS X entweder lokal für einen
Benutzer in seinem .profile
oder in
.login
oder in einer anderen Login-Datei
setzen. Sie kann aber auch global in der Datei
/etc/profile
eingestellt werden.
In einer C-Shell (csh, tcsh) würde der Connector/J-Treiber dem
CLASSPATH
folgendermaßen hinzugefügt:
shell> setenv CLASSPATH /path/to/mysql-connector-java-[version]-bin.jar:$CLASSPATH
In einer Bourne-kompatiblen Shell (sh, ksh, bash) würden Sie dieses tun:
export set CLASSPATH=/path/to/mysql-connector-java-[version]-bin.jar:$CLASSPATH
In Windows 2000, Windows XP und Windows Server 2003 muss die Umgebungsvariable in der Systemsteuerung eingestellt werden.
Wenn Sie MySQL Connector/J mit einem Anwendungsserver wie etwa
Tomcat oder JBoss benutzen möchten, müssen Sie in der
Herstellerdokumentation nachlesen, wie Klassenbibliotheken von
Drittanbietern konfiguriert werden, da die meisten
Anwendungsserver die Umgebungsvariable
CLASSPATH
ignorieren. Beispiele für die
Konfiguration einiger J2EE-Anwendungsserver finden Sie in
Abschnitt 25.3.5.2, „Connector/J mit J2EE und anderen Java-Frameworks einsetzen“. Die
maßgebliche Quelle für die Konfiguration eines
JDBC-Verbindungspools auf Ihrem konkreten Anwendungsserver ist
jedoch dessen Dokumentation.
Wenn Sie Servlets oder JSPs entwickeln und Ihr Anwendungsserver J2EE-fähig ist, können Sie die .jar-Datei des Treibers in das Unterverzeichnis WEB-INF/lib Ihrer Webanwendungen legen, da dies der Standardspeicherort für Bibliotheken von Drittanbietern in J2EE-Webanwendungen ist.
Sie können auch die Klasse MysqlDataSource oder
MysqlConnectionPoolDataSource im Package
com.mysql.jdbc.jdbc2.optional
verwenden, wenn
Ihr J2EE-Anwendungsserver sie unterstützt oder benötigt. Ab
Connector/J 5.0.0 ist über die Klasse
com.mysql.jdbc.jdbc2.optional.MysqlXADataSource
auch die Schnittstelle javax.sql.XADataSource
implementiert, die in Verbindung mit dem MySQL-Server 5.0
verteilte XA-Transaktionen unterstützt.
Die diversen MysqlDataSource-Klassen unterstützen (über Standard-Set-Mutators) folgende Parameter:
user
password
serverName (siehe vorhergehenden Abschnitt über Ausfall-Hosts)
databaseName
port
MySQL AB versucht, den Upgrade-Prozess so einfach wie möglich zu halten, doch wie bei jeder Software müssen gelegentlich in neuen Versionen neue Features unterstützt, vorhandene verbessert oder neue Standards erfüllt werden.
In diesem Abschnitt erfahren Benutzer, die von einer Connector/J-Version auf eine andere aufrüsten (oder, im Hinblick auf die JDBC-Funktionalität, auf eine neue Version des MySQL-Servers), worauf sie achten müssen.
Connector/J 3.1 ist auf größtmögliche Abwärtskompatibilität mit Connector/J 3.0 ausgelegt. Größere Änderungen beschränken sich auf die neuen Funktionen von MySQL 4.1 und höher, darunter Unicode-Zeichensätze, vorbereitete Anweisungen auf der Serverseite, SQLState-Codes die in Fehlermeldungen vom Server zurückgegeben werden, und verschiedene Leistungsverbesserungen, die mit Konfigurationseigenschaften ein- und ausgeschaltet werden können.
Unicode-Zeichensätze
— Informationen über dieses neue MySQL-Feature
finden Sie im folgenden Abschnitt und in
Kapitel 10, Zeichensatz-Unterstützung. Wenn Sie etwas
falsch konfiguriert haben, merken Sie das in der Regel an
einer Fehlermeldung wie Illegal mix of
collations
.
Vorbereitete Anweisungen auf der Serverseite — Connector/J 3.1 erkennt und nutzt vorbereitete Anweisungen auf der Serverseite automatisch, wenn sie verfügbar sind (MySQL -Server der Version 4.1.0 und höher).
Seit Version 3.1.7 untersucht der Server alle Arten mit
Connection.prepareStatement()
vorbereiteter SQL-Anweisungen, um festzustellen, ob es
sich um eine Anweisungsart handelte deren Vorbereitung auf
der Serverseite unterstützt wird. Ist dies nicht der
Fall, emuliert der Server sie als clientseitige
vorbereitete Anweisung. Dieses Feature können Sie
deaktivieren, indem Sie
emulateUnsupportedPstmts=false in
Ihren JDBC-URL einbinden.
Wenn Ihre Anwendung Probleme mit vorbereiteten Anweisungen auf der Serverseite hat, können Sie auf den älteren Code für emulierte vorbereitete Anweisungen auf der Clientseite zurückgreifen, der immer noch für ältere MySQL-Server als 4.1.0 mit der Verbindungseigenschaft useServerPrepStmts=false unterstützt wird.
Datums- und Uhrzeitwerte,
die nur aus Nullen bestehen (0000-00-00
...
) — Diese Werte lassen sich in Java
nicht zuverlässig darstellen. Connector/J 3.0.x wandelte
sie immer in NULL um, wenn sie aus einem ResultSet gelesen
wurden.
Connector/J 3.1 löst nach Voreinstellung eine Ausnahme aus, wenn diese Werte auftreten, da dies nach den Standards von JDBC und SQL das korrekte Verhalten ist. Sie können dieses Verhalten aber mit der Konfigurationseigenschaft zeroDateTimeBehavior ändern, die folgende Werte annehmen kann:
exception
(der Standardwert) löst
eine SQLException mit dem SQLState
S1009
aus.
convertToNull
gibt
NULL
anstelle des Datums zurück.
round
rundet das Datum auf den
nächstgelegenen Wert auf, also auf
0001-01-01
.
Ab Connector/J 3.1.7 lässt sich
ResultSet.getString()
mit der
Eigenschaft noDatetimeStringSync=true
von diesem Verhalten abkoppeln (der Standardwert ist
false
). Auf diese Weise können Sie den
Wert mit den Nullen unverändert als String abrufen. Da
dies allerdings jegliche Zeitzonenkonvertierungen
ausschließt, erlaubt Ihnen der Treiber nicht,
noDatetimeStringSync und
useTimezone gleichzeitig
einzuschalten.
Neue SQLState-Codes — Connector/J 3.1 benutzt die SQLState-Codes von SQL:1999, die vom MySQL-Server (sofern er dies unterstützt) zurückgegeben werden. Diese unterscheiden sich von den alten X/Open-Zustandscodes, die Connector/J 3.0 verwendet. Wenn der Treiber mit einem älteren MySQL-Server als MySQL 4.1.0 verbunden ist (die älteste Version, die SQLStates in Fehlercodes zurückliefert), verwendet er eine integrierte Zuordnung. Sie können auf die alte Zuordnung umschalten, indem Sie die Konfigurationseigenschaft useSqlStateCodes=false einstellen.
ResultSet.getString()
— Wenn Sie ResultSet.getString()
auf einer BLOB-Spalte aufrufen, wird nunmehr die Adresse
ihres byte[]-Arrays anstelle einer Stringdarstellung des
BLOBs zurückgegeben. Da BLOBs keinen Zeichensatz haben,
können sie nicht ohne Datenverlust oder Schäden in
java.lang.Strings konvertiert werden.
Um in MySQL Strings mit LOB-Verhalten zu speichern, verwenden Sie einen der TEXT-Typen, die der Treiber alle als java.sql.Clob behandelt.
Debug-Builds — Seit
Connector/J 3.1.8 wird ein Debug-Build des Treibers in
einer Datei namens
mysql-connector-java-
zusammen mit der normalen Binär-jar-Datei namens
[version]
-bin-g.jarmysql-connector-java-
mitgeliefert.
[version]
-bin.jar
Seit Connector/J 3.1.9 liefern wir die .class-Dateien nur noch im Bundle aus, also nur in den JAR-Archiven zusammen mit dem Treiber.
Den „Debug“-Build des Treibers sollten Sie
bitte nur benutzen, wenn Sie dazu aufgefordert werden, um
ein Problem oder einen Fehler an MySQL AB zu melden, da
dieser Build nicht für Produktionsumgebungen geschaffen
ist und sich nachteilig auf die Performance auswirkt. Die
Debug-Binärdatei ist außerdem von der
Aspect/J-Laufzeitbibliothek abhängig, die Sie in der zur
Connector/J-Distribution gehörigen Datei
src/lib/aspectjrt.jar
finden.
Verwendung der UTF-8-Zeichencodes - Vor MySQL Server 4.1 wurde die UTF-8-Zeichencodierung vom Server nicht unterstützt. Der JDBC-Treiber dagegen konnte diese Codierung nutzen, sodass mehrere Zeichensätze in latin1-Tabellen auf dem Server gespeichert werden konnten.
Seit MySQL-4.1 ist diese Funktionalität veraltet. Wenn Sie Anwendungen haben, die sich darauf stützen und sich nicht auf die Unterstützung der offiziellen Unicode-Zeichen in MySQL Server 4.1 oder höher aktualisieren lassen, müssen Sie folgende Eigenschaft in Ihren Verbindungs-URL aufnehmen:
useOldUTF8Behavior=true
Vorbereitete Anweisungen auf der Serverseite - Connector/J 3.1 erkennt und nutzt vorbereitete Anweisungen auf der Serverseite automatisch, wenn sie verfügbar sind (MySQL -Server der Version 4.1.0 und höher). Wenn Ihre Anwendung Probleme mit vorbereiteten Anweisungen auf der Serverseite hat, können Sie auf den älteren Code für emulierte vorbereitete Anweisungen auf der Clientseite zurückgreifen, der immer noch für ältere MySQL-Server als 4.1.0 mit folgender Verbindungseigenschaft unterstützt wird:
useServerPrepStmts=false
Caution. Sie sollten diesen Abschnitt nur lesen, wenn Sie Interesse daran haben, uns beim Testen unseres neuen Codes behilflich zu sein. Wenn Sie MySQL Connector/J lediglich in funktionsfähiger Form auf Ihrem System einrichten wollen, sollten Sie einen Standard-Release verwenden.
Um MySQL Connector/J vom Entwicklungsquellbaum zu installieren, müssen folgende Voraussetzungen erfüllt sein:
Sie benötigen Subversion (erhältlich bei http://subversion.tigris.org/), um die Quelldateien aus unserem Repository auszuchecken .
Sie benötigen Apache Ant Version 1.6 oder höher (erhältlich bei http://ant.apache.org/).
Sie benötigen JDK-1.4.2 oder höher. Zwar kann MySQL Connector/J auch auf älteren JDKs installiert werden, aber um es von der Quelle zu kompilieren, ist mindestens JDK-1.4.2 erforderlich.
Das Subversion-Quellcode-Repository für MySQL Connector/J liegt unter http://svn.mysql.com/svnpublic/connector-j. Generell sollten Sie nicht gleich das ganze Repository auschecken, da es jeden Branch und Tag für MySQL Connector/J enthält und daher sehr groß ist.
Einen konkreten Branch von MySQL Connector/J checken Sie folgendermaßen aus:
Zurzeit sind drei Branches von Connector/J aktiv:
branch_3_0
, branch_3_1
und branch_5_0
. Checken Sie den neuesten
Code aus dem gewünschten Branch mit folgendem Befehl aus
(wobei [major]
und
[minor]
durch die passenden
Versionsnummern ersetzt werden müssen):
shell> svn co »
http://svn.mysql.com/svnpublic/connector-j/branches/branch_[major]
_[minor]
/connector-j
Dies erzeugt im aktuellen Verzeichnis ein Unterverzeichnis
namens connector-j
, das die neuesten
Quelldateien für den gewünschten Branch enthält.
Wechseln Sie nun in das Verzeichnis
connector-j
, um es zu Ihrem aktuellen
Arbeitsverzeichnis zu machen:
shell> cd connector-j
Mit folgendem Befehl können Sie den Treiber kompilieren und
eine .jar
-Datei für die Installation
anlegen:
shell> ant dist
Dies erzeugt im aktuellen Verzeichnis ein
build
-Verzeichnis, in das die gesamte
Ausgabe des Builds gespeichert wird. Unter dem
build
-Verzeichnis wird ein weiteres
Verzeichnis angelegt, das die Versionsnummer der für den
Build verwendeten Quelle enthält. Dieses Verzeichnis
enthält die Quelldateien, die kompilierten
.class
-Dateien und eine
.jar
-Datei, die sich für die
Installation eignet. Für andere mögliche Ziele,
einschließlich einer kompletten Package-Distribution, geben
Sie folgenden Befehl:
shell> ant --projecthelp
Nun wird eine neu erzeugte .jar
-Datei,
die den JDBC-Treiber enthält, in das Verzeichnis
build/mysql-connector-java-
gelegt.
[version]
Diesen neu erstellten JDBC-Treiber installieren Sie genau
so, als sei es eine .jar
-Datei, die Sie
gemäß den Anleitungen in
Abschnitt 25.3.2.2, „Treiber installieren und CLASSPATH
konfigurieren“
von MySQL heruntergeladen haben.
Im ganzen Dokument finden sich immer wieder Beispiele für Connector/J, die nachfolgend verlinkt und zusammengefasst werden.
Beispiel 25.2, „Mit java.sql.Statement eine SELECT
-Anfrage ausführen“
Beispiel 25.6, „Einstellung von CallableStatement
-Eingabeparametern“
Beispiel 25.7, „Abruf von Ergebnissen und Ausgabeparameterwerten“
Beispiel 25.8, „AUTO_INCREMENT
-Spaltenwerte mit
Statement.getGeneratedKeys()
abrufen“
Beispiel 25.9, „Abruf von AUTO_INCREMENT
-Spaltenwerten mit
SELECT LAST_INSERT_ID()
“
Beispiel 25.10, „Retrieving AUTO_INCREMENT
column values in
Updatable ResultSets
“
Beispiel 25.11, „Verwendung eines Verbindungspools mit einem J2EE-Anwendungsserver“
Beispiel 25.12, „Beispiel einer Transaktion mit Retry-Logik“
Dieser Abschnitt des Handbuchs enthält Referenzmaterial zu MySQL Connector/J, das zum Teil während des Build-Prozesses von Connector/J automatisch generiert wurde.
Die Klasse, die java.sql.Driver in MySQL Connector/J
implementiert, heißt com.mysql.jdbc.Driver
.
Der Klassenname org.gjt.mm.mysql.Driver
eignet sich auch, um die Abwärtskompatibilität mit MM.MySQL zu
bewahren. Verwenden Sie also diesen Klassennamen, wenn Sie den
Treiber registrieren oder andere Software konfigurieren, die
MySQL Connector/J benutzen soll.
Es folgt das JDBC-URL-Format für MySQL Connector/J, wobei die Elemente in den eckigen Klammern ([, ]) optional sind:
jdbc:mysql://[host][,failoverhost...][:port]/[database] » [?propertyName1][=propertyValue1][&propertyName2][=propertyValue2]...
Ist kein Hostname angegeben, wird der Standardwert 127.0.0.1 verwendet. Fehlt die Port-Angabe, wird 3306, die Standard-Portnummer für MySQL-Server eingesetzt.
jdbc:mysql://[host:port],[host:port].../[database] » [?propertyName1][=propertyValue1][&propertyName2][=propertyValue2]...
Wenn die Datenbank nicht angegeben ist, wird keine Verbindung
mit einer Standarddatenbank aufgenommen. Sie müssen dann
entweder die Methode setCatalog()
auf dem
Connection-Objekt aufrufen, oder in der SQL-Anweisung
Tabellennamen mit dem Datenbanknamen vollständig qualifizieren
(d.h. SELECT dbname.tablename.colname FROM
dbname.tablename...
). Bei der Verbindung keine
Datenbank anzugeben ist jedoch normalerweise nur dann sinnvoll,
wenn Sie Tools erstellen, die mit mehreren Datenbanken arbeiten
sollen, wie beispielsweise GUI-Datenbankmanager.
MySQL Connector/J unterstützt Ausfallsicherungen. So kann der
Treiber auf beliebig viele Slave-Hosts zurückgreifen und immer
noch nur-lesende Anfragen ausführen. Die Ausfallsicherung tritt
nur dann in Kraft, wenn für die Verbindung
autoCommit(true)
gilt, da bei laufenden
Transaktionen kein zuverlässiges Umschalten möglich ist. Die
meisten Anwendungsserver und Verbindungspools setzen
autoCommit
am Ende jeder
Transaktion/Verbindungsnutzung auf true
.
Die Ausfallsicherung verhält sich folgendermaßen:
Wenn die URL-Eigenschaft autoReconnect false ist, wird nur bei der Initialisierung einer Verbindung auf den Sekundär-Host umgeschaltet (sog. Failover), und auf den Primär-Host wird wieder zurückgeschaltet (sog. Failback), wenn der Treiber feststellt, dass dieser wieder zur Verfügung steht.
Wenn die URL-Eigenschaft autoReconnect
true ist, wird auf den Sekundär-Host umgeschaltet, wenn der
Treiber feststellt, das die Verbindung (vor der Ausführung
jeglicher Anfrage) gescheitert ist, und
wieder auf den Primär-Host zurückgeschaltet, wenn dieser
wieder verfügbar ist (nach der Ausführung von
queriesBeforeRetryMaster
-Anfragen).
In beiden Fällen gilt: Wenn Sie mit einem "Sekundär"-Server verbunden sind, wird die Verbindung in einen nur-lesenden Zustand versetzt, sodass Anfragen, die Daten modifizieren würden, Ausnahmen auslösen (eine solche Anfrage wird niemals vom MySQL-Server verarbeitet).
Wie Connector/J eine Verbindung zu einem MySQL-Server einrichtet, ist in den Konfigurationseigenschaften definiert. Wenn nichts anderes gesagt wird, können die Eigenschaften für ein DataSource- oder für ein Connection-Objekt gesetzt werden.
Konfigurationseigenschaften können auf folgende Weisen eingestellt werden:
Mit den set*()-Methoden von MySQL-Implementierungen auf java.sql.DataSource (die bevorzugte Methode, wenn Implementierungen von java.sql.DataSource verwendet werden):
com.mysql.jdbc.jdbc2.optional.MysqlDataSource
com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource
Als Schlüssel/Wert-Paar in der
java.util.Properties-Instanz, die an
DriverManager.getConnection()
oder
Driver.connect()
übergeben wird.
Als JDBC-URL-Parameter in dem an
java.sql.DriverManager.getConnection()
,
java.sql.Driver.connect()
oder
MySQL-Implementierungen der
setURL()
-Methode von
javax.sql.DataSource
übergebenen URL.
Hinweis. Wenn Sie zur Konfiguration eines JDBC-URLs einen XML-Mechanismus verwenden, müssen sie den XML-Zeichenliteral & auf andere Konfigurationsparameter einstellen, da das Ampersand in XML ein reserviertes Zeichen ist.
Die Eigenschaften werden in den folgenden Tabellen aufgeführt.
Verbindung/Authentifizierung.
Name der Eigenschaft | Definition | Standardwert | Seit Version |
user | Der Benutzername für die Verbindung | alle | |
password | Das Passwort für die Verbindung | alle | |
socketFactory | Der Name der Klasse, die der Treiber zur Einrichtung von
Socket-Verbindungen zum Server benutzen soll. Diese
Klasse muss die Schnittstelle
com.mysql.jdbc.SocketFactory
implementieren und einen öffentlichen,
parameterlosen Konstruktor haben. | com.mysql.jdbc.StandardSocketFactory | 3.0.3 |
connectTimeout | Timeout für Socket-Verbindung (in Millisekunden). 0 bedeutet: kein Timeout. Funktioniert nur mit JDK-1.4 oder höher. Standardwert ist 0. | 0 | 3.0.1 |
socketTimeout | Timeout für Socket-Operationen im Netzwerk. (Die Standardeinstellung 0 bedeutet: kein Timeout). | 0 | 3.0.1 |
useConfigs | Lade die kommagetrennte Liste der Konfigurationseigenschaften vor dem Parsen des URLs oder der Anwendung benutzerdefinierter Eigenschaften. Siehe Abschnitt 25.3.4.1, „Driver/Datasource-Klassennamen, URL-Syntax und Konfigurationseigenschaften für Connector/J“ | 3.1.5 | |
interactiveClient | Setzt das Flag CLIENT_INTERACTIVE, damit MySQL das Verbindungs-Timeout gemäß INTERACTIVE_TIMEOUT anstelle von WAIT_TIMEOUT einstellt | false | 3.1.0 |
propertiesTransform | Eine Implementierung von
com.mysql.jdbc.ConnectionPropertiesTransform ,
die der Treiber benutzt, um an ihn übergebene
URL-Eigenschaften zu modifizieren, ehe er versucht,
eine Verbindung einzurichten | 3.1.4 | |
useCompression | Verwendung von zlib-Kompression zur Kommunikation mit dem Server
(true/false)? Standardwert ist
false . | false | 3.0.17 |
Hochverfügbarkeit und Clustering.
Name der Eigenschaft | Definition | Standardwert | Seit Version |
autoReconnect | Sollte der Treiber alte und/oder tote Verbindungen wiederbeleben oder nicht? Wenn diese Eigenschaft aktiviert ist, löst der Treiber eine Ausnahme aus, wenn Anfragen, die zur laufenden Transaktion gehören, über eine alte oder tote Verbindung gesendet werden. Werden über die Verbindung jedoch Anfragen gesendet, die zu einer neuen Transaktion gehören, versucht der Server vor der nächsten Anfrage eine Neuverbindung. Von der Verwendung dieses Features wird abgeraten, da es Auswirkungen auf den Session-Zustand und die Datenkonsistenz hat, wenn Anwendungen nicht richtig mit SQLExceptions umgehen können. Es sollte nur verwendet werden, wenn die Anwendung nicht richtig konfiguriert werden kann, um SQLExceptions, die aus alten oder toten Verbindungen resultieren, richtig zu handhaben. Als Alternative können Sie eventuell die MySQL-Server-Variable "wait_timeout" auf einen höheren als den Standardwert von 8 Stunden setzen. | false | 1.1 |
autoReconnectForPools | Verwendung einer Neuverbindungsstrategie, die sich für Verbindungspools eignet (Standardwert ist 'false') | false | 3.1.3 |
failOverReadOnly | Soll die Verbindung 'read-only' gesetzt werden, wenn im autoReconnect-Modus ein Ausfall passiert? | true | 3.0.12 |
reconnectAtTxEnd | Soll der Treiber am Ende jeder Transaktion eine Neuverbindung versuchen, wenn autoReconnect auf true gesetzt ist? | false | 3.0.10 |
roundRobinLoadBalance | Sollen Verbindungs-Hosts round-robin ausgewählt werden, wenn autoReconnect eingeschaltet und failoverReadonly auf false gesetzt ist? | false | 3.1.2 |
queriesBeforeRetryMaster | Anzahl der Anfragen, die bei einem Ausfall (Failover) abgesetzt werden, ehe wieder auf den Master zurückgegriffen wird (bei Verwendung von Multi-Host-Failover). Die Bedingung, die zuerst erfüllt wird, ('queriesBeforeRetryMaster' oder 'secondsBeforeRetryMaster') veranlasst einen neuen Verbindungsversuch mit dem Master. Standardwert ist 50. | 50 | 3.0.2 |
secondsBeforeRetryMaster | Wie lange soll der Treiber bei einem Ausfall warten, ehe er wieder eine Verbindung zum Masterserver versucht? Die Bedingung, die zuerst erfüllt wird, ('queriesBeforeRetryMaster' oder 'secondsBeforeRetryMaster') veranlasst einen neuen Verbindungsversuch mit dem Master. Zeitangabe in Sekunden, Standardwert ist 30 | 30 | 3.0.2 |
resourceId | Ein global eindeutiger Bezeichner für die Ressource, mit welcher diese
Datenquelle oder Verbindung verbunden ist, wird für
XAResource.isSameRM() verwendet,
wenn der Treiber diesen Wert nicht anhand der
Hostnamen im URL ermitteln kann | 5.0.1 |
Sicherheit.
Name der Eigenschaft | Definition | Standardwert | Seit Version |
allowMultiQueries | Erlaubt das Trennzeichen' ;', um mehrere Anfragen in einer einzigen Anweisung abzugrenzen. (true/false, Standardwert ist 'false') | false | 3.1.1 |
useSSL | SSL wird zur Kommunikation mit dem Server eingesetzt (true/false), Standardwert ist 'false' | false | 3.0.2 |
requireSSL | Wird SSL-Verbindung verlangt, wenn useSSL=true? (Standardwert ist 'false'). | false | 3.1.0 |
allowUrlInLocalInfile | Soll der Treiber URLs in 'LOAD DATA LOCAL INFILE'-Anweisungen zulassen? | false | 3.1.4 |
paranoid | Maßnahmen ergreifen, damit keine schutzwürdigen Informationen in Fehlermeldungen erscheinen und Datenstrukturen, die schutzwürdige Daten enthalten, nach Möglichkeit löschen? (Standardwert ist 'false') | false | 3.0.1 |
Performance-Erweiterungen.
Name der Eigenschaft | Definition | Standardwert | Seit Version |
metadataCacheSize | Die Anzahl der Anfragen, für die cacheResultSetMetadata eintritt, wenn cacheResultSetMetaData auf 'true' gesetzt ist (Standardwert 50) | 50 | 3.1.1 |
prepStmtCacheSize | Wie viele vorbereitete Anweisungen sollen gespeichert werden, wenn Caching von vorbereiteten Anweisungen eingeschaltet ist? | 25 | 3.0.10 |
prepStmtCacheSqlLimit | Wie lang darf eine SQL-Anweisung, deren Parse-Ergebnis der Treiber speichert, höchstens sein, wenn Caching von vorbereiteten Anweisungen eingeschaltet ist? | 256 | 3.0.10 |
useCursorFetch | Wenn bei einer Anweisung MySQL > 5.0.2 und
setFetchSize() > 0 gilt, soll
diese Anweisung Zeilen mit Cursor-Fetching abholen? | false | 5.0.0 |
blobSendChunkSize | Datenblöcke dieser Größe verwenden, wenn BLOB/CLOBs mit ServerPreparedStatements verschickt werden | 1048576 | 3.1.9 |
cacheCallableStmts | Soll der Treiber das Parsing-Stadium von CallableStatements cachen? | false | 3.1.2 |
cachePrepStmts | Soll der Treiber das Parsing-Stadium von PreparedStatements von clientseitigen vorbereiteten Anweisungen sowie die Eignungsprüfung von serverseitigen vorbereiteten Anweisungen und die serverseitigen vorbereiteten Anweisungen selbst cachen? | false | 3.0.10 |
cacheResultSetMetadata | Soll der Treiber ResultSetMetaData für Statements und PreparedStatements cachen? (JDK-1.4+ erforderlich, true/false, Standardwert 'false') | false | 3.1.1 |
cacheServerConfiguration | Soll der Treiber die Ergebnisse von SHOW VARIABLES
und SHOW COLLATION pro URL
cachen? | false | 3.1.5 |
defaultFetchSize | Der Treiber ruft setFetchSize(n) mit diesem Wert auf allen neu erstellten Anweisungen auf | 0 | 3.1.9 |
dontTrackOpenResources | Laut JDBC-Spezifikation muss der Treiber automatisch Ressourcen
verfolgen und schließen, doch wenn Ihre Anwendung
nicht gut darin ist, explizit
close() auf Anweisungen oder
Ergebnismengen aufzurufen, kann dies zu
Speicherverlust führen. Wenn Sie diese Eigenschaft
auf true setzen, lockern Sie diese Einschränkung
und erhöhen für bestimmte Anwendungen die
Speichereffizienz | false | 3.1.7 |
dynamicCalendars | Soll der Treiber den Standardkalender abrufen, oder ihn pro Verbindung/Session cachen? | false | 3.1.5 |
elideSetAutoCommits | Für MySQL-4.1 oder neuer: Soll der Treiber 'set autocommit=n'-Anfragen
nur absetzen, wenn der Server-Zustand nicht dem
durch
Connection.setAutoCommit(boolean)
geforderten Zustand entspricht? | false | 3.1.3 |
holdResultsOpenOverStatementClose | Soll der Treiber bei Statement.close() Ergebnismengen
abschließen, wie es die JDBC-Spezifikation fordert? | false | 3.1.7 |
locatorFetchBufferSize | Wenn 'emulateLocators' auf 'true' gesetzt ist: Wie groß soll der Puffer sein, wenn BLOB-Daten für einen getBinaryInputStream abgeholt werden? | 1048576 | 3.2.1 |
rewriteBatchedStatements | Soll der Treiber Multiqueries verwenden (unabhängig von der Einstellung
von allowMultiQueries ) und
vorbereitete INSERT -Anweisungen
in Insert-Operationen mit mehreren Werten
umformulieren, wenn executeBatch() aufgerufen wird?
Beachten Sie, dass dies die Gefahr von SQL-Injection
birgt, wenn Sie einfache java.sql.Statements
verwenden und Ihr Code die Eingabewerte nicht
richtig säubert. Für vorbereitete Anweisungen
müssen Sie wissen, dass serverseitige vorbereitete
Anweisungen gegenwärtig noch nicht von dieser
Umformulierungsoption Gebrauch machen können. Wenn
Sie PreparedStatement.set*Stream() ohne Angabe von
Stream-Längen verwenden, kann darüber hinaus der
Treiber die optimale Anzahl der Parameter pro Batch
nicht ermitteln und meldet einen Fehler, dass das
resultierende Paket zu groß wird.
Statement.getGeneratedKeys() funktioniert für diese
umformulierten Anweisungen nur dann, wenn der
gesamte Batch INSERT-Anweisungen enthält. | false | 3.1.13 |
useFastIntParsing | Interne String->Integer-Konvertierungsroutinen verwenden, damit nicht zu viele Objekte angelegt werden? | true | 3.1.4 |
useJvmCharsetConverters | Immer die in der JVM integrierten Zeichencodierungsroutinen verwenden, anstatt Lookup-Tabellen für Single-Byte-Zeichensätze zu benutzen? (Der Standardwert "true" ist für neuere JVMs geeignet) | true | 5.0.1 |
useLocalSessionState | Soll der Treiber die internen Werte für Autocommit und Transaktionsisolation benutzen, die von Connection.setAutoCommit() und Connection.setTransactionIsolation() gesetzt werden, anstatt die Datenbank anzufragen? | false | 3.1.7 |
useReadAheadInput | Soll beim Lesen von Serverdaten der optimierte nicht-blockierende, gepufferte Eingabestrom verwendet werden? | true | 3.1.5 |
Debugging/Profiling.
Name der Eigenschaft | Definition | Standardwert | Seit Version |
logger | Name einer Klasse, die 'com.mysql.jdbc.log.Log' implementiert und zur Protokollierung von Nachrichten verwendet wird. (Standardwert ist 'com.mysql.jdbc.log.StandardLogger', eine Klasse, die in STDERR schreibt) | com.mysql.jdbc.log.StandardLogger | 3.1.1 |
profileSQL | Anfragen und ihre Ausführungs/Fetch-Zeiten werden im konfigurierten Logger verfolgt (true/false), Standardwert ist 'false' | false | 3.1.0 |
reportMetricsIntervalMillis | Wenn 'gatherPerfMetrics' aktiviert ist: In welchen Abständen sollen diese Daten gesammelt werden (in Millisekunden)? | 30000 | 3.1.2 |
maxQuerySizeToLog | Die maximale Länge einer Anfrage, die bei Profiling oder Tracing prokolliert wird | 2048 | 3.1.3 |
packetDebugBufferSize | Die Höchstzahl der Pakete, die gepuffert werden, wenn 'enablePacketDebug' true ist | 20 | 3.1.3 |
slowQueryThresholdMillis | Wenn 'logSlowQueries' eingeschaltet ist: Wie lange darf eine Anfrage (in ms) dauern, ehe sie als 'langsam' protokolliert wird? | 2000 | 3.1.2 |
useUsageAdvisor | Soll der Treiber ins Log 'usage'-Warnungen schreiben, um eine korrekte und effiziente Nutzung von JDBC und MySQL Connector/J anzuraten (true/false, Standardwert ist 'false')? | false | 3.1.1 |
autoGenerateTestcaseScript | Soll der Treiber ausgeführtes SQL einschließlich serverseitige vorbereitete Anweisungen in STDERR speichern? | false | 3.1.9 |
dumpMetadataOnColumnNotFound | Soll der Treiber feldbezogene Metadaten einer Ergebnismenge in die Ausnahmemeldung schreiben, wenn ResultSet.findColumn() fehlschlägt? | false | 3.1.13 |
dumpQueriesOnException | Soll der Treiber den Inhalt der an den Server gesandten Anfrage in der Meldung für SQLExceptions speichern? | false | 3.1.3 |
enablePacketDebug | Wenn dies eingeschaltet ist, wird ein Ring-Puffer mit 'packetDebugBufferSize'-Paketen behalten und gespeichert, sofern in bestimmten Bereichen des Treibercodes Ausnahmen ausgelöst werden | false | 3.1.3 |
explainSlowQueries | Wenn 'logSlowQueries' eingeschaltet ist: Soll der Treiber automatisch eine 'EXPLAIN'-Anweisung an den Server stellen und die Ergebnisse auf WARN-Level an das konfigurierte Log schicken? | false | 3.1.2 |
logSlowQueries | Sollen Anfragen protokolliert werden, die länger als 'slowQueryThresholdMillis' dauern? | false | 3.1.2 |
traceProtocol | Soll das Trace-Netzwerkprotokoll ins Log gespeichert werden? | false | 3.1.2 |
Verschiedenes.
Name der Eigenschaft | Definition | Standardwert | Seit Version |
useUnicode | Soll der Treiber zur Behandlung von Strings Unicode-Zeichencodes verwenden? Dies sollte nur eingesetzt werden, wenn der Treiber die Zeichensatzzuordnung nicht ermitteln kann, oder wenn Sie versuchen, dem Treiber einen Zeichensatz 'aufzuzwingen', den MySQL nicht nativ unterstützt (wie UTF-8). true/false, Standardwert ist 'true' | true | 1.1g |
characterEncoding | Wenn 'useUnicode' auf true gesetzt ist: Welche Zeichencodierung soll der Treiber für den Umgang mit Strings verwenden? (Standardwert ist 'autodetect') | 1.1g | |
characterSetResults | Mit diesem Zeichensatz soll der Server Ergebnismengen zurückgeben. | 3.0.13 | |
connectionCollation | Wenn dies gesetzt ist, verwendet der Server die mit 'set collation_connection' eingestellte Sortierreihenfolge für Zeichen | 3.0.13 | |
sessionVariables | Eine kommagetrennte Liste von Namen/Wert-Paaren, die als SET SESSION ... an den Server geschickt wird, wenn sich der Treiber verbindet | 3.1.8 | |
allowNanAndInf | Soll der Treiber NaN- oder +/- INF-Werte in PreparedStatement.setDouble() zulassen? | false | 3.1.5 |
autoClosePStmtStreams | Soll der Treiber automatisch .close() auf Streams/Readern aufrufen, die mit set*()-Methoden als Argumente übergeben wurden? | false | 3.1.12 |
autoDeserialize | Soll der Treiber in BLOB-Feldern gespeicherte Objekte automatisch erkennen und deserialisieren? | false | 3.1.5 |
capitalizeTypeNames | Sollen Typnamen in DatabaseMetaData groß geschrieben werden? (Ist normalerweise nur für WebObjects nützlich, true/false, Standardwert ist 'false') | false | 2.0.7 |
clobCharacterEncoding | Diese Zeichencodierung soll anstelle der für die Verbindung konfigurierten characterEncoding zum Senden und Abrufen von TEXT-, MEDIUMTEXT- und LONGTEXT-Werten verwendet werden. | 5.0.0 | |
clobberStreamingResults | Sorgt dafür, dass ein 'streaming'-ResultSet automatisch geschlossenwird, und dass anhängige Daten, die immer vom Server eintreffen, verworfen werden, wenn eine andere Anfrage ausgeführt wird, bevor alle Daten vom Server eingelesen worden sind. | false | 3.0.9 |
continueBatchOnError | Soll der Treiber weiterhin Batch-Befehle ausführen, wenn eine Anweisung gescheitert ist? Laut JDBC-Spezifikation sind beide Möglichkeiten erlaubt (Standardwert ist 'true'). | true | 3.0.3 |
createDatabaseIfNotExist | Legt die im URL angegebene Datenbank an, wenn sie noch nicht existiert, vorausgesetzt, der Benutzer hat die Berechtigung zum Anlegen von Datenbanken. | false | 3.1.9 |
emptyStringsConvertToZero | Soll der Treiber erlauben, dass leere String-Felder in '0'-Werte konvertiert werden? | true | 3.1.8 |
emulateLocators | N/A | false | 3.1.0 |
emulateUnsupportedPstmts | Soll der Treiber vorbereitete Anweisungen erkennen, die nicht vom Server unterstützt werden, und sie durch emulierte Versionen auf der Clientseite ersetzen? | true | 3.1.7 |
ignoreNonTxTables | Warnungen wegen nicht-transaktionssicherer Tabellen beim Rollback ignorieren? (Standardwert ist 'false'). | false | 3.0.9 |
jdbcCompliantTruncation | Soll der Treiber beim Kappen von Daten java.sql.DataTruncation-Ausnahmen auslösen, wie es die JDBC-Spezifikation verlangt, wenn er mit einem Server verbunden ist, der Warnungen unterstützt (MySQL 4.1.0 und neuer)? | true | 3.1.2 |
maxRows | So viele Zeilen werden maximal zurückgegeben (der Standardwert 0 bedeutet, dass alle Zeilen zurückgegeben werden). | -1 | alle Versionen |
noAccessToProcedureBodies | Soll der Treiber grundlegende Metadaten erstellen (alle Parameter werden als INOUT VARCHARs gemeldet), anstatt eine Ausnahme auszulösen, wenn er Prozedurparametertypen für CallableStatements ermitteln soll und der Benutzer nicht mit "SHOW CREATE PROCEDURE" auf die Prozdedurrümpfe zugreifen oder mysql.proc abfragen kann? | false | 5.0.3 |
noDatetimeStringSync | Nicht dafür sorgen, dass ResultSet.getDatetimeType().toString().equals(ResultSet.getString()) | false | 3.1.7 |
noTimezoneConversionForTimeType | TIME-Werte nicht auf die Server-Zeitzone umstellen, wenn 'useTimezone'='true' | false | 5.0.0 |
nullCatalogMeansCurrent | Wenn DatabaseMetadataMethods einen 'catalog'-Parameter abfragen, steht dann der Wert Null für den aktuellen Katalog? (Das ist zwar nicht JDBC-konform, entspricht aber dem Verhalten älterer Treiberversionen) | true | 3.1.8 |
nullNamePatternMatchesAll | Sollen DatabaseMetaData-Methoden, die *pattern-Parameter entgegennehmen, Null ebenso wie '%' behandeln (ist zwar nicht JDBC-konform, aber ältere Treiberversionen akzeptierten diese Abweichung von der Spezifikation) | true | 3.1.8 |
overrideSupportsIntegrityEnhancementFacility | Soll der Treiber für DatabaseMetaData.supportsIntegrityEnhancementFacility() auch dann "true" zurückgeben, wenn die Datenbank es nicht akzeptiert, um einen Workaround für Anwendungen (wie beispielsweise OpenOffice) zu ermöglichen, die verlangen, dass diese Methode "true" zurückgibt, um Unterstützung für Fremdschlüssel zu signalisieren, auch wenn die SQL-Spezifikation besagt, dass diese Facility noch viel mehr als nur Fremdschlüsselunterstützung umfasst? | false | 3.1.12 |
pedantic | Die JDBC-Spezifikation wortwörtlich befolgen | false | 3.0.0 |
pinGlobalTxToPhysicalConnection | Wenn XAConnections verwendet werden: Soll der Treiber gewährleisten, dass Operationen auf einer konkreten XID immer an dieselbe physikalische Verbindung weitergeleitet werden? So kann die XAConnection "XA START ... JOIN" auch nach dem Aufruf von "XA END" noch unterstützen. | false | 5.0.1 |
processEscapeCodesForPrepStmts | Soll der Treiber Escape-Codes in vorbereiteten Anweisungen verarbeiten? | true | 3.1.12 |
relaxAutoCommit | Wenn sich der Treiber mit einer MySQL-Version verbindet, die keine Transaktionen unterstützt: Sollen dennoch commit(), rollback() und setAutoCommit() erlaubt sein? (true/false, Standardwert ist 'false')? | false | 2.0.13 |
retainStatementAfterResultSetClose | Soll sich der Treiber die Statement-Referenz in einem ResultSet merken, nachdem ResultSet.close() aufgerufen wurde? Dies ist nach JDBC-4.0 nicht mehr JDBC-konform. | false | 3.1.11 |
rollbackOnPooledClose | Soll der Treiber rollback() aufrufen, wenn die logische Verbindung in einem Pool geschlossen wird? | true | 3.0.15 |
runningCTS13 | Ermöglicht Workarounds für Fehler in der JDBC Compliance Testsuite Version 1.3 von Sun | false | 3.1.7 |
serverTimezone | Überschreibt die Erkennung/Zuordnung der Zeitzone. Wird verwendet, wenn sich die Zeitzone des Servers nicht auf die Java-Zeitzone abbilden lässt. | 3.0.2 | |
strictFloatingPoint | Wird nur in älteren Versionen des Compliance Tests verwendet | false | 3.0.0 |
strictUpdates | Soll der Treiber eine strenge Prüfung (aller ausgewählten Primärschlüssel) aktualisierbarer Ergebnismenge vornehmen? (true, false, Standardwert ist 'true') | true | 3.0.4 |
tinyInt1isBit | Soll der Treiber den Datentyp TINYINT(1) als BIT-Typ behandeln (da der Server insgeheim sowieso eine BIT -> TINYINT(1)-Konvertierung vornimmt, wenn er Tabellen anlegt)? | true | 3.0.16 |
transformedBitIsBoolean | Wenn der Treiber TINYINT(1) in einen anderen Datentyp konvertiert: Soll er BOOLEAN anstelle von BIT verwenden (dient der zukünftigen Kompatibilität mit MySQL-5.0, da MySQL-5.0 einen BIT-Typ hat)? | false | 3.1.9 |
ultraDevHack | Wenn nötig PreparedStatements für prepareCall() erstellen, da UltraDev nicht funktioniert und prepareCall() für alle Anweisungen aufruft? (true/false, Standardwert ist 'false') | false | 2.0.3 |
useGmtMillisForDatetimes | Konvertiert zwischen Session-Zeitzone und GMT vor der Erzeugung von Date- und Timestamp-Objekten ("false" ist veraltetes Verhalten, "true" ist eher JDBC-konform). | false | 3.1.12 |
useHostsInPrivileges | Den Benutzern in DatabaseMetaData.getColumn/TablePrivileges() einen '@hostname' hinzufügen (true/false), Standardwert ist 'true'. | true | 3.0.2 |
useInformationSchema | Soll der Treiber bei Verbindung mit MySQL-5.0.7 oder neuer die von DatabaseMetaData benötigten Informationen aus dem INFORMATION_SCHEMA ableiten? | false | 5.0.0 |
useJDBCCompliantTimezoneShift | Soll der Treiber sich beim Konvertieren der Zeitzoneninformationen von TIME/TIMESTAMP/DATETIME-Werten für JDBC-Argumente, die ein java.util.Calendar-Argument nehmen an den JDBC-Standard halten? (Achtung, diese Option und die Konfigurationsoption "useTimezone=true" schließen sich gegenseitig aus.) | false | 5.0.0 |
useOldUTF8Behavior | Stellt das alte UTF-8-Verhalten ein, das der Treiber bei Kommunikation mit 4.0 und älteren Servern an den Tag legt. | false | 3.1.6 |
useOnlyServerErrorMessages | Keine 'Standard'-SQLState-Fehlermeldungen den vom Server zurückgelieferten Fehlermeldungen voranstellen. | true | 3.0.15 |
useServerPrepStmts | Serverseitige vorbereitete Anweisungen verwenden, wenn der Server sie unterstützt? (Standardwert ist 'true'). | true | 3.1.0 |
useSqlStateCodes | Zustandscodes gemäß SQL-Standard anstelle der 'alten' X/Open/SQL-Zustandscodes verwenden? (true/false), Standardwert ist 'true' | true | 3.1.3 |
useStreamLengthsInPrepStmts | StreamLength-Parameter in Aufrufen der PreparedStatement/ResultSet.setXXXStream()-Methode berücksichtigen? (true/false, Standardwert ist 'true') | true | 3.0.2 |
useTimezone | Datums/Uhrzeittypen zwischen Client- und Server-Zeitzone konvertieren (true/false, Standardwert ist 'false')? | false | 3.0.2 |
useUnbufferedInput | Keinen BufferedInputStream zum Lesen von Daten auf dem Server verwenden | true | 3.0.11 |
yearIsDateType | Soll der JDBC-Treiber den MySQL-Typ "YEAR" als java.sql.Date oder als SHORT behandeln? | true | 3.1.9 |
zeroDateTimeBehavior | Was soll geschehen, wenn der Server auf DATETIME-Werte trifft, die ausschließlich aus Nullen bestehen (so stellt MySQL ungültige Datumswerte dar)? Zulässige Werte sind 'exception', 'round' und 'convertToNull'. | exception | 3.1.4 |
Connector/J bietet auch MySQL-Zugriff über Named Pipes für
Windows NT/2000/XP. Hierzu wird die
NamedPipeSocketFactory als
Plugin-Socket-Factory mithilfe der Eigenschaft
socketFactory eingestellt. Wenn Sie keine
namedPipePath-Eigenschaft einstellen, wird
standardmäßig '\\.\pipe\MySQL' benutzt. Verwenden Sie die
NamedPipeSocketFactory
, so werden der
Hostname und die Port-Nummer im JDBC-URL ignoriert. Sie können
dieses Feature wie folgt einschalten:
socketFactory=com.mysql.jdbc.NamedPipeSocketFactory
Named Pipes funktinieren nur, wenn Sie sich mit dem MySQL-Server auf demselben Computer verbinden, auf dem auch der JDBC-Treiber eingesetzt wird. In einfachen Performance-Tests sieht es so aus, als sei der Zugriff über Named Pipes um 30%-50% schneller als der traditionelle TCP/IP-Zugriff.
Mit dem Beispielcode in
com.mysql.jdbc.NamedPipeSocketFactory
oder com.mysql.jdbc.StandardSocketFactory
können Sie eigene Socket-Factories bauen.
MySQL Connector/J besteht alle Tests der öffentlich zugänglichen JDBC Compliance Testsuite von Sun. Doch an vielen Stellen sagt die JDBC-Spezifikation nicht genau, wie eine Funktionalität implementiert werden soll.
In diesem Abschnitt wird für jede Schnittstelle untersucht, wie sich Ihre Implementierungsentscheidungen auf die Verwendung von MySQL Connector/J auswirken können.
Blob
Die BLOB-Implementierung erlaubt keine Modifikationen an Ort
und Stelle (sondern nur in Kopien, die von der Methode
DatabaseMetaData.locatorsUpdateCopies()
angezeigt werden). Daher sollten Sie Änderungen mit der
entsprechenden
PreparedStatement.setBlob()
- oder
ResultSet.updateBlob()
-Methode (für
aktualisierbare Ergebnismengen) in die Datenbank
zurückspeichern.
Seit Connector/J version 3.1.0 können Sie Blobs mit
Locators emulieren, indem Sie Ihrem JDBC-URL die Eigenschaft
'emulateLocators=true' hinzufügen. Sie müssen dann einen
Spaltenalias einsetzen, wobei der Wert der Spalte auf den
tatsächlichen Namen der Blob-Spalte in der
SELECT
-Anweisung gesetzt wird, die Sie
zum Abrufen des Blob schreiben. Die
SELECT
-Anweisung darf nur eine einzige
Tabelle referenzieren, die Tabelle muss einen
Primärschlüssel haben, und das SELECT
muss alle Spalten enthalten, die diesen Primärschlüssel
ausmachen. Der Treiber wird dann das Laden der
tatsächlichen Blob-Daten so lange aufschieben, bis Sie den
Blob abrufen und auf ihm entsprechende Abrufmethoden
aufrufen (getInputStream()
,
getBytes()
usw.).
CallableStatement
Seit Connector/J 3.1.1 werden über die Schnittstelle
CallableStatement
bei Verbindungen
mit MySQL 5.0 oder neuer gespeicherte Prozeduren
unterstützt. Die Methode
getParameterMetaData()
von
CallableStatement
wird gegenwärtig
noch nicht unterstützt.
Clob
Die CLOB-Implementierung erlaubt keine Modifikationen an Ort
und Stelle (sondern nur in Kopien, die von der Methode
DatabaseMetaData.locatorsUpdateCopies()
angezeigt werden). Daher sollten Sie Änderungen mit der
entsprechenden
PreparedStatement.setClob()
-Methode in
die Datenbank zurückspeichern. Die JDBC-API kennt keine
ResultSet.updateClob()
-Methode.
Connection
Im Gegensatz zu älteren Versionen von MM.MySQL wird die
Methode isClosed()
den Server nicht
pingen, um festzustellen, ob er noch lebendig ist.
Entsprechend der JDBC-Spezifikation gibt sie lediglich true
zurück, wenn closed()
auf der Verbindung
aufgerufen worden ist. Wenn Sie feststellen möchten, ob die
Verbindung noch steht, setzen Sie eine einfache Anfrage wie
beispielsweise SELECT 1
ab. Ist die
Verbindung ungültig geworden, löst der Treiber eine
Ausnahme aus.
DatabaseMetaData
Fremdschlüsselinformationen
(getImportedKeys()
/getExportedKeys()
und getCrossReference()
) sind nur für
InnoDB-Tabellen erhältlich. Da der Server diese
Informationen jedoch mit SHOW CREATE
TABLE
abruft, wird er auch andere Speicher-Engines
unterstützen, die Fremdschlüssel kennen.
PreparedStatement
PreparedStatements werden vom Treiber implementiert, da
MySQL keine vorbereiteten Anweisungen kennt. Dahler
implementiert der Treiber auch kein
getParameterMetaData()
oder
getMetaData()
, da er dann einen
kompletten SQL-Parser im Client benötigen würde.
Seit Version 3.1.0 verwendet MySQL Connector/J serverseitige vorbereitete Anweisungen und binär codierte Ergebnsmengen, wenn der Server diese ermöglicht.
Seien Sie vorsichtig, wenn Sie eine serverseitige
vorbereitete Anweisung mit
großen Parametern
verwenden, die mit setBinaryStream()
,
setAsciiStream()
,
setUnicodeStream()
,
setBlob()
oder
setClob()
eingestellt werden. Wenn Sie
die Anweisung erneut ausführen, aber dabei die großen auf
kleine Parameter umstellen möchten, müssen Sie
clearParameters()
aufrufen und alle
Parameter neu einstellen. Dies hat folgenden Grund:
Wenn der Parameter gesetzt ist, lässt der Treiber die großen Daten Band-extern in die vorbereitete Anweisung auf der Serverseite streamen (und zwar vor Ausführung der vorbereiteten Anweisung).
Wenn dies erledigt ist, wird der Stream, mit dem Daten auf der Clientseite gelesen wurden, geschlossen (genz JDBC-konform), und kann nicht mehr gelesen werden.
Wird der Parameter von groß auf klein umgestellt, muss
der Treiber den serverseitigen Zustand der vorbereiteten
Anweisung zurücksetzen, damit der neue Parameter den
Platz des vorherigen, großen Werts einnehmen kann.
Dadurch werden alle großen Daten, die bereits an den
Server geschickt wurden, entfernt, sodass sie mit einer
der Methoden setBinaryStream()
,
setAsciiStream()
,
setUnicodeStream()
,
setBlob()
oder
setClob()
erneut gesandt werden
müssen.
Um einen Parameter von einem großen auf einen kleinen Typ
umzustellen, müssen Sie folglich
clearParameters()
aufrufen und alle
Parameter der vorbereiteten Anweisung neu einstellen, ehe
diese wieder ausgeführt werden kann.
ResultSet
Nach Voreinstellung werden ResultSets vollständig abgeholt und in den Arbeitsspeicher geladen. Meist ist dies am effizientesten und durch den Entwurf des MySQL-Netzwerkprotokolls auch am einfachsten zu implementieren. Wenn Sie jedoch mit ResultSets arbeiten, die viele Zeilen oder große Werte enthalten, und in Ihrer JVM keinen Heap-Space für den erforderlichen Arbeitsspeicher zuweisen können, können Sie den Treiber auch veranlassen, die Ergebnisse zeilenweise hereinströmen zu lassen.
Um diese Funktionalität nutzen zu können, müssen Sie ein Statement-Objekt wie folgt erzeugen:
stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY); stmt.setFetchSize(Integer.MIN_VALUE);
Die Kombination aus einer forward-only, nur-lesenden
Ergebnismenge der Größe
Integer.MIN_VALUE
ist für den Treiber
das Signal, die Ergebnismengen zeilenweise hereinströmen zu
lassen. Danach werden auch alle weiteren mit dieser
Anweisung abgerufenen Ergebnismengen zeilenweise eingelesen.
Dieser Ansatz hat einige Tücken. Sie müssen alle Zeilen der Ergebnismenge lesen (oder sie schließen), ehe Sie auf der Verbindung weitere Anfragen absetzen können. Sonst wird eine Ausnahme ausgelöst.
Die Sperren, die diese Anweisungen halten, können
frühestens freigegeben werden, wenn die Anweisung
abgeschlossen ist. (Dies gilt für
MyISAM
-Tabellensperren ebenso wie für
die Zeilensperren einiger anderer Speicher-Engines, wie etwa
InnoDB
.)
Wenn die Anweisung zu einer Transaktion gehört, werden die Sperren erst freigegeben, wenn die Transaktion fertig ist (was impliziert, dass auch die Anweisung zuerst fertig sein muss). Wie in den meisten anderen Datenbanken auch, sind Anweisungen erst dann abgeschlossen, wenn alle Ergebnisse gelesen wurden, oder die aktive Ergebnismenge der Anweisung geschlossen worden ist.
Daher sollten Sie Streaming-Ergebnisse immer so schnell wie möglich lesen, wenn die von der Anweisung referenzierten Tabellen weiterhin nebenläufig zugänglich sein sollen.
ResultSetMetaData
Die Methode isAutoIncrement()
funktioniert nur mit MySQL 4.0 und neuer.
Statement
Wenn Sie ältere JDBC-Treiberversionen als 3.2.1 in Verbindung mit älteren älteren Server-Versionen als 5.0.3 benutzen, hat die Methode "setFetchSize()" keine andere Wirkung, als das Ergebnismengen-Streaming umzuschalten, wie oben beschrieben.
MySQL unterstützt keine SQL-Cursors und der JDBC-Treiber emuliert sie auch nicht. Daher hat "setCursorName()" keine Wirkung.
MySQL Connector/J ist flexibel in Bezug auf die Konvertierung von MySQL- und Java-Datentypen.
Generell lässt sich jeder MySQL-Datentyp in einen java.lang.String und jeder numerische Typ in einen numerischen Java-Typ umwandeln, wobei jedoch Rundungen, Überlauf oder Genauigkeitsverluste eintreten können.
Seit Connector/J 3.1.0 gibt der JDBC-Treiber Warnungen oder
DataTruncation-Ausnahmen im Einklang mit der JDBC-Spezifikation
aus, wenn Sie dies nicht ausdrücklich unterbinden, indem Sie
die Eigenschaft jdbcCompliantTruncation auf
false
setzen.
Die in der folgenden Tabelle aufgeführten Konvertierungen funktionieren garantiert:
Verbindungseigenschaften - Diverse.
Diese MySQL-Datentypen | lassen sich immer in diese Java-Typen konvertieren |
CHAR, VARCHAR, BLOB, TEXT, ENUM, and SET | java.lang.String, java.io.InputStream, java.io.Reader,
java.sql.Blob, java.sql.Clob |
FLOAT, REAL, DOUBLE PRECISION, NUMERIC, DECIMAL, TINYINT,
SMALLINT, MEDIUMINT, INTEGER, BIGINT | java.lang.String, java.lang.Short, java.lang.Integer,
java.lang.Long, java.lang.Double,
java.math.BigDecimal |
DATE, TIME, DATETIME, TIMESTAMP | java.lang.String, java.sql.Date, java.sql.Timestamp |
Hinweis: Wenn Sie einen numerischen Java-Typ auswählen, der weniger genau oder groß als der MySQL-Typ ist, aus oder in welchen Sie konvertieren, kann es zu Rundungsverhalten, Überlauf oder Genauigkeitsverlust kommen.
Die Methode ResultSet.getObject()
nimmt
folgende Konvertierungen zwischen MySQL- und Java-Typen vor,
wobei sie sich möglichst an die JDBC-Spezifikation hält:
Konvertierung von MySQL- in Java-Typen für ResultSet.getObject().
MySQL-Typname | Rückgabe als Java-Klasse |
BIT(1) (neu in MySQL-5.0) | java.lang.Boolean |
BIT( > 1) (neu in MySQL-5.0) | byte[] |
TINYINT | java.lang.Boolean , wenn die
Konfigurationseigenschaft
tinyInt1isBit auf
true gesetzt ist (der
Standardwert) und die Speichergröße 1 ist,
andernfalls
java.lang.Integer . |
BOOL, BOOLEAN | Siehe TINYINT weiter oben, da diese Typen zurzeit Aliase für TINYINT(1) sind. |
SMALLINT[(M)] [UNSIGNED] | java.lang.Integer (egal ob UNSIGNED oder nicht) |
MEDIUMINT[(M)] [UNSIGNED] | java.lang.Integer, wenn UNSIGNED
java.lang.Long |
INT,INTEGER[(M)] [UNSIGNED] | java.lang.Integer , wenn UNSIGNED
java.lang.Long |
BIGINT[(M)] [UNSIGNED] | java.lang.Long , wenn UNSIGNED
java.math.BigInteger |
FLOAT[(M,D)] | java.lang.Float |
DOUBLE[(M,B)] | java.lang.Double |
DECIMAL[(M[,D])] | java.math.BigDecimal |
DATE | java.sql.Date |
DATETIME | java.sql.Timestamp |
TIMESTAMP[(M)] | java.sql.Timestamp |
TIME | java.sql.Time |
YEAR[(2|4)] | java.sql.Date (Datum wird um Mitternacht auf 1.
Januar umgestellt) |
CHAR(M) | java.lang.String (wenn der Zeichensatz für die
Spalte BINARY ist, wird
byte[] zurückgegeben). |
VARCHAR(M) [BINARY] | java.lang.String (wenn der Zeichensatz für die
Spalte BINARY ist, wird
byte[] zurückgegeben). |
BINARY(M) | byte[] |
VARBINARY(M) | byte[] |
TINYBLOB | byte[] |
TINYTEXT | java.lang.String |
BLOB | byte[] |
TEXT | java.lang.String |
MEDIUMBLOB | byte[] |
MEDIUMTEXT | java.lang.String |
LONGBLOB | byte[] |
LONGTEXT | java.lang.String |
ENUM('value1','value2',...) | java.lang.String |
SET('value1','value2',...) | java.lang.String |
Alle vom JDBC-Treiber zum Server geschickten Strings werden
automatisch vom nativen Java-Unicode in die Zeichencodierung des
Clients konvertiert, einschließlich aller mit
Statement.execute()
,
Statement.executeUpdate()
und
Statement.executeQuery()
übermittelten
Anfragen, sowie aller
PreparedStatement
- und
CallableStatement
- Parameter mit Ausnahme der Parameter, die mit
setBytes()
,
setBinaryStream()
,
setAsciiStream()
,
setUnicodeStream()
und
setBlob()
eingestellt wurden.
Vor MySQL Server 4.1 unterstützte Connector/J eine einzige
Zeichencodierung pro Verbindung. Diese konnte entweder
automatisch aus der Severkonfiguration erschlossen oder vom
Benutzer mit den Eigenschaften useUnicode
und "characterEncoding
" eingestellt
werden.
Seit MySQL Server 4.1 unterstützt Connector/J eine einzige
Zeichencodierung zwischen Client und Server, aber beliebig viele
Zeichencodierungen für Daten, die vom Server in
ResultSets
an den Client zurückgeliefert
werden.
Die Zeichencodierung zwischen Client und Server wird automatisch
beim Verbindungsaufbau ermittelt. Die vom Treiber verwendete
Codierung wird auf dem Server mit der Systemvariablen
character_set
(für ältere Server-Versionen
als 4.1.0) oder character_set_server
(für
Server-Versionen ab 4.1.0 ) eingestellt. Weitere Informationen
finden Sie unter Abschnitt 10.3.1, „Serverzeichensatz und -sortierfolge“.
Um die automatische Erkennung der Codierung auf der Clientseite
außer Kraft zu setzen, setzen Sie die Eigenschaft
characterEncoding
in den für die
Server-Verbindung verwendeten URL.
Zeichencodierungen auf der Clientseite geben Sie bitte mit Java-Namen an. In der folgenden Tabelle werden die Java-Namen der MySQL-Zeichensätze aufgeführt:
Übersetzung der Zeichencodierungen von MySQL in Java.
Zeichensatzname in MySQL | Name der Zeichencodierung in Java |
usa7 | US-ASCII |
big5 | Big5 |
gbk | GBK |
sjis | SJIS (oder Cp932 oder MS932 für MySQL Server < 4.1.11) |
cp932 | Cp932 oder MS932 (MySQL Server > 4.1.11) |
gb2312 | EUC_CN |
ujis | EUC_JP |
euc_kr | EUC_KR |
latin1 | ISO8859_1 |
latin1_de | ISO8859_1 |
german1 | ISO8859_1 |
danish | ISO8859_1 |
latin2 | ISO8859_2 |
czech | ISO8859_2 |
hungarian | ISO8859_2 |
croat | ISO8859_2 |
greek | ISO8859_7 |
hebrew | ISO8859_8 |
latin5 | ISO8859_9 |
latvian | ISO8859_13 |
latvian1 | ISO8859_13 |
estonia | ISO8859_13 |
dos | Cp437 |
pclatin2 | Cp852 |
cp866 | Cp866 |
koi8_ru | KOI8_R |
tis620 | TIS620 |
win1250 | Cp1250 |
win1250ch | Cp1250 |
win1251 | Cp1251 |
cp1251 | Cp1251 |
win1251ukr | Cp1251 |
cp1257 | Cp1257 |
macroman | MacRoman |
macce | MacCentralEurope |
utf8 | UTF-8 |
ucs2 | UnicodeBig |
Warnung. Verwenden Sie niemals die Anfrage 'set names' mit Connector/J, da der Treiber dann nicht erkennt, dass der Zeichensatz geändert wurde, und weiterhin den Zeichensatz verwendet, den er beim Einrichten der Verbindung gefunden hat.
Wenn Sie ermöglichen möchten, dass mehrere Zeichensätze vom
Client gesendet werden können, verwenden Sie bitte die
UTF-8-Codierung. Diese können Sie einstellen, indem Sie
entweder utf8
als Standardzeichensatz des
Servers angeben, oder den JDBC-Treiber mit der Eigenschaft
characterEncoding
zur Benutzung von UTF-8
veranlassen.
SSL in MySQL Connector/J verschlüsselt alle Daten (außer dem Handshake am Anfang) zwischen dem JDBC-Treiber und dem Server. Allerdings dauert die Verarbeitung von Anfragen, je nach ihrer Größe und dem Umfang der Rückgabedaten, bei Einschaltung von SSL 36% bis 50% länger.
Damit die SSL-Unterstützung funktioniert, ist folgendes erforderlich:
Ein JDK, das JSSE (Java Secure Sockets Extension) enthält, wie etwa JDK 1.4.1 oder höher. SSL funktioniert zurzeit nicht mit einem JDK, zu dem man JSSE hinzufügen kann, wie JDK-1.2.x oder JDK-1.3.x. Das liegt an folgendem Fehler in JSSE: http://developer.java.sun.com/developer/bugParade/bugs/4273544.html
Ein MySQL-Server, der SSL unterstützt und auch für SSL kompiliert und konfiguriert ist, also MySQL-4.0.4 oder höher. Mehr Informationen finden Sie unter Abschnitt 5.9.7, „Verwendung sicherer Verbindungen“.
Ein Client-Zertifikat (wird weiter unten in diesem Abschnitt noch erklärt)
Sie müssen als Erstes das CA-Zertifikat des MySQL-Servers in
einen Java-Truststore importieren. Ein Beispiel eines
CA-Zertifikats für MySQL-Server finden Sie im Unterverzeichnis
SSL
der MySQL-Quelldistribution. Anhand
dieses Zertifikats wird SSL feststellen, ob Sie mit einem
sicheren MySQL-Server kommunizieren.
Um mit dem Java-keytool einen Truststore im
aktuellen Verzeichnis anzulegen und das CA-Zertifikat des
Servers (cacert.pem
) zu importieren, gehen
Sie wie unten beschrieben vor (vorausgesetzt, das
keytool liegt in Ihrem Pfad). (Das
keytool müsste im Unterverzeichnis
bin
Ihres JDK oder JRE zu finden sein):
shell> keytool -import -alias mysqlServerCACert -file cacert.pem -keystore truststore
Keytool antwortet mit folgenden Informationen:
Enter keystore password: ********* Owner: EMAILADDRESS=walrus@example.com, CN=Walrus, O=MySQL AB, L=Orenburg, ST=Some -State, C=RU Issuer: EMAILADDRESS=walrus@example.com, CN=Walrus, O=MySQL AB, L=Orenburg, ST=Som e-State, C=RU Serial number: 0 Valid from: Fri Aug 02 16:55:53 CDT 2002 until: Sat Aug 02 16:55:53 CDT 2003 Certificate fingerprints: MD5: 61:91:A0:F2:03:07:61:7A:81:38:66:DA:19:C4:8D:AB SHA1: 25:77:41:05:D5:AD:99:8C:14:8C:CA:68:9C:2F:B8:89:C3:34:4D:6C Trust this certificate? [no]: yes Certificate was added to keystore
Dann müssen sie ein Client-Zertifikat generieren, damit der MySQL-Server weiß, dass er es mit einem sicheren Client zu tun hat:
shell> keytool -genkey -keyalg rsa -alias mysqlClientCertificate -keystore keystore
Das Keytool fragt Sie nach folgenden Informationen und erstellt
einen Keystore namens keystore
im aktuellen
Verzeichnis.
Bitte geben Sie die passenden Informationen für Ihre Situation ein:
Enter keystore password: ********* What is your first and last name? [Unknown]: Matthews What is the name of your organizational unit? [Unknown]: Software Development What is the name of your organization? [Unknown]: MySQL AB What is the name of your City or Locality? [Unknown]: Flossmoor What is the name of your State or Province? [Unknown]: IL What is the two-letter country code for this unit? [Unknown]: US Is <CN=Matthews, OU=Software Development, O=MySQL AB, L=Flossmoor, ST=IL, C=US> correct? [no]: y Enter key password for <mysqlClientCertificate> (RETURN if same as keystore password):
Damit JSSE den Keystore und den Truststore auch benutzt, müssen Sie zum Schluss die folgenden Systemeigenschaften einstellen, wenn Sie Ihre JVM starten. Ersetzen Sie dabei path_to_keystore_file durch den vollständigen Pfad zu der von Ihnen angelegten Keystore-Datei und path_to_truststore_filedurch den vollständigen Pfad zu der von Ihnen angelegten Truststore-Datei und benutzen Sie für jede Eigenschaft die passenden Passwortwerte.
-Djavax.net.ssl.keyStore=path_to_keystore_file -Djavax.net.ssl.keyStorePassword=********* -Djavax.net.ssl.trustStore=path_to_truststore_file -Djavax.net.ssl.trustStorePassword=*********
Außerdem müssen Sie in den Verbindungsparametern für SQL
Connector/JuseSSL auf
true
setzen, indem Sie entweder
useSSL=true
in Ihren URL einfügen, oder die
Eigenschaft useSSL in dem
java.util.Properties
-Objekt, das Sie an
DriverManager.getConnection()
übergeben, auf
true
einstellen.
Das Funktionieren von SSL können Sie testen, indem Sie JSSE-Debugging (wie unten beschrieben) einschalten und nach folgenden Key-Ereignissen Ausschau halten:
... *** ClientHello, v3.1 RandomCookie: GMT: 1018531834 bytes = { 199, 148, 180, 215, 74, 12, 54, 244, 0, 168, 55, 103, 215, 64, 16, 138, 225, 190, 132, 153, 2, 217, 219, 239, 202, 19, 121, 78 } Session ID: {} Cipher Suites: { 0, 5, 0, 4, 0, 9, 0, 10, 0, 18, 0, 19, 0, 3, 0, 17 } Compression Methods: { 0 } *** [write] MD5 and SHA1 hashes: len = 59 0000: 01 00 00 37 03 01 3D B6 90 FA C7 94 B4 D7 4A 0C ...7..=.......J. 0010: 36 F4 00 A8 37 67 D7 40 10 8A E1 BE 84 99 02 D9 6...7g.@........ 0020: DB EF CA 13 79 4E 00 00 10 00 05 00 04 00 09 00 ....yN.......... 0030: 0A 00 12 00 13 00 03 00 11 01 00 ........... main, WRITE: SSL v3.1 Handshake, length = 59 main, READ: SSL v3.1 Handshake, length = 74 *** ServerHello, v3.1 RandomCookie: GMT: 1018577560 bytes = { 116, 50, 4, 103, 25, 100, 58, 202, 79, 185, 178, 100, 215, 66, 254, 21, 83, 187, 190, 42, 170, 3, 132, 110, 82, 148, 160, 92 } Session ID: {163, 227, 84, 53, 81, 127, 252, 254, 178, 179, 68, 63, 182, 158, 30, 11, 150, 79, 170, 76, 255, 92, 15, 226, 24, 17, 177, 219, 158, 177, 187, 143} Cipher Suite: { 0, 5 } Compression Method: 0 *** %% Created: [Session-1, SSL_RSA_WITH_RC4_128_SHA] ** SSL_RSA_WITH_RC4_128_SHA [read] MD5 and SHA1 hashes: len = 74 0000: 02 00 00 46 03 01 3D B6 43 98 74 32 04 67 19 64 ...F..=.C.t2.g.d 0010: 3A CA 4F B9 B2 64 D7 42 FE 15 53 BB BE 2A AA 03 :.O..d.B..S..*.. 0020: 84 6E 52 94 A0 5C 20 A3 E3 54 35 51 7F FC FE B2 .nR..\ ..T5Q.... 0030: B3 44 3F B6 9E 1E 0B 96 4F AA 4C FF 5C 0F E2 18 .D?.....O.L.\... 0040: 11 B1 DB 9E B1 BB 8F 00 05 00 .......... main, READ: SSL v3.1 Handshake, length = 1712 ...
JSSE bietet Debugging (in STDOUT), wenn Sie die
Systemeigenschaft -Djavax.net.debug=all
einstellen. So erfahren Sie, welche Keystores und Truststores
benutzt werden und was während des SSL-Handshakes und beim
Austauschen des Zertifikats passiert. Dies ist nützlich, wenn
eine SSL-Verbindung einmal nicht erfolgreich aufgebaut werden
kann und Sie versuchen, den Fehler zu finden.
Seit Connector/J 3.1.7 haben wir eine Variante des Treibers
entwickelt, die Anfragen je nach dem Zustand von
Connection.getReadOnly()
automatisch an einen
lesenden und schreibenden Master oder eine Ausfallserver oder
eine nach dem Round-Robin-Verfahren lastbalancierte Gruppe von
Slaves weiterleitet.
Wenn eine Anwendung durch Aufruf von
Connection.setReadOnly(true)
signalisiert,
dass eine Transaktion nur-lesend sein soll, verwendet diese
replikationsfähige Verbindung eine der per round-robin
lastbalancierten Slave-Verbindungen (eine Verbindung verbleibt
bei einem Slave, bis dieser aus dem Dienst genommen wird). Wenn
Sie eine schreibende Transaktion haben oder eine zeitsensible
Leseoperation ausführen müssen (vergessen Sie nicht, die
Replikation in MySQL ist asynchron), dann stellen Sie die
Verbindung mit Connection.setReadOnly(false)
so ein, dass sie nicht nur-lesend ist. Der Treiber sorgt dann
dafür, dass zukünftige Aufrufe an den MySQL-Masterserver
gehen. Außerdem reicht der Server den aktuellen Zustand von
Autocommit, Isolationsebene und Katalog an alle Verbindungen
weiter, die er für diese Lastverteilungsfunktionalität
benötigt.
Um diese Funktionalität zu ermöglichen, verwenden Sie die
Klasse " com.mysql.jdbc.ReplicationDriver
",
wenn Sie den Verbindungspool Ihres Anwendungsservers
konfigurieren, oder wenn Sie eine Instanz eines JDBC-Treibers
für Ihre Standalone-Anwendung erzeugen. Da der
ReplicationDriver
dasselbe URL-Format wie der
Standard-MySQL-JDBC-Treiber akzeptiert, funktioniert er
gegenwärtig mit einem Verbindungsaufbau à la
java.sql.DriverManager
nur dann, wenn er der
einzige MySQL-JDBC-Treiber ist, der beim
DriverManager
registriert wurde.
Hier sehen Sie ein einfaches, kurzes Beispiel dafür, wie man einen ReplicationDriver in einer Standalone-Anwendung einsetzen könnte.
import java.sql.Connection; import java.sql.ResultSet; import java.util.Properties; import com.mysql.jdbc.ReplicationDriver; public class ReplicationDriverDemo { public static void main(String[] args) throws Exception { ReplicationDriver driver = new ReplicationDriver(); Properties props = new Properties(); // Für die Ausfallsicherung mit Slaves props.put("autoReconnect", "true"); // Lastverteilung zwischen den Slaves props.put("roundRobinLoadBalance", "true"); props.put("user", "foo"); props.put("password", "bar"); // // Sieht aus wie ein normaler MySQL-JDBC-URL mit einer kommagetrennten Liste von Hosts, // wobei der erste der 'Master' und die restlichen // die Slaves sind, auf die der Treiber die Last verteilt // Connection conn = driver.connect("jdbc:mysql://master,slave1,slave2,slave3/test", props); // // Lese/Schreiboperationen auf dem Master ausführen, indem // das Readonly-Flag auf "false" gesetzt wird. // conn.setReadOnly(false); conn.setAutoCommit(false); conn.createStatement().executeUpdate("UPDATE some_table ...."); conn.commit(); // // Nun eine Anfrage auf einem Slave ausführen, wobei der Treiber automatisch // einen aus der Liste auswählt // conn.setReadOnly(true); ResultSet rs = conn.createStatement().executeQuery("SELECT a,b,c FROM some_other_table"); ....... } }
In diesem Abschnitt wird Grundlagenwissen über JDBC vermittelt.
Wenn Sie JDBC außerhalb eines Anwendungsservers benutzen,
wird die Einrichtung von Verbindungen über die Klasse
DriverManager
verwaltet.
Sie müssen dem DriverManager
mitteilen,
mit welchen JDBC-Treibern er sich verbinden soll. Die
einfachste Möglichkeit besteht darin, die Methode
Class.forName()
auf der Klasse aufzurufen,
welche die java.sql.Driver
-Schnittstelle
implementiert. Bei MySQL Connector/J heißt diese Klasse
com.mysql.jdbc.Driver
. Mit dieser Methode
können Sie eine externe Konfigurationsdatei verwenden, um den
Namen der Treiberklasse und die Treiberparameter zu
übergeben, wenn eine Datenbankverbindung aufgebaut wird.
Der folgende Java-Code zeigt, wie Sie MySQL Connector/J in der
main()
-Methode Ihrer Anwendung registrieren
könnten:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; // Achtung, nicht com.mysql.jdbc.* importieren, // sonst bekommen Sie Probleme! public class LoadDriver { public static void main(String[] args) { try { // Der Aufruf von newInstance() ist ein Workaround // für einige misslungene Java-Implementierungen Class.forName("com.mysql.jdbc.Driver").newInstance(); } catch (Exception ex) { // Fehler behandeln } }
Nachdem der Treiber beim DriverManager
registriert wurde, können Sie eine
Connection
-Instanz zur Verbindung mit einer
bestimmten Datenbank erzeugen, indem Sie
DriverManager.getConnection()
aufrufen:
Beispiel 25.1. Eine Verbindung vom DriverManager
erhalten
Dieses Beispiel zeigt, wie Sie eine
Connection
-Instanz vom
DriverManager
bekommen können. Es gibt
verschiedene Signaturen für die
getConnection()
-Methode. Wie man mit
ihnen umgeht, entnehmen Sie bitte der API-Dokumentation, die
mit Ihrem JDK mitgeliefert wurde.
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; ... try { Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/test?user=monty&password=greatsqldb"); // Verbindung benutzen .... } catch (SQLException ex) { // Fehler behandeln System.out.println("SQLException: " + ex.getMessage()); System.out.println("SQLState: " + ex.getSQLState()); System.out.println("VendorError: " + ex.getErrorCode()); }
Sobald eine Connection
eingerichtet
ist, kann sie genutzt werden, um
Statement
- und
PreparedStatement
-Objekte
auszuführen und Metadaten über die Datenbank abzurufen.
Dies wird in den folgenden Abschnitten erklärt.
Mit Statement
-Objekten können Sie
grundlegende SQL-Anfragen ausführen und die Ergebnisse
mithilfe der weiter unten beschriebenen Klasse
ResultSet
abrufen.
Um ein Statement
-Objekt zu erzeugen,
rufen Sie die Methode createStatement()
auf
dem Connection
-Objekt auf, das Sie mit
einer der zuvor beschriebenen Methoden
DriverManager.getConnection()
oder
DataSource.getConnection()
erzeugt haben.
Wenn Sie ein Statement
-Objekt angelegt
haben, können Sie eine SELECT
-Anfrage
ausführen, indem Sie executeQuery(String)
mit der gewünschten SQL-Anweisung aufrufen.
Um Daten in der Datenbank zu aktualisieren, verwenden Sie die
Methode executeUpdate(String SQL)
. Diese
liefert die Anzahl der von dem Update betroffenen Zeilen
zurück.
Wenn Sie im Voraus noch nicht wissen, ob Ihre SQL-Anweisung
ein SELECT
oder ein
UPDATE
/INSERT
wird,
können Sie die Methode execute(String SQL)
verwenden. Sie gibt true zurück, wenn die SQL-Anfrage ein
SELECT
ist, oder false, wenn sie ein
UPDATE
, INSERT
oder
DELETE
ist. Handelt es sich um ein
SELECT
, so können Sie die Ergebnisse mit
der Methode getResultSet()
abrufen. Für
UPDATE
-, INSERT
- oder
DELETE
-Anweisungen können Sie die Anzahl
der betroffenen Zeilen in Erfahrung bringen, indem Sie
getUpdateCount()
auf dem
Statement
-Objekt aufrufen.
Beispiel 25.2. Mit java.sql.Statement eine SELECT
-Anfrage ausführen
// conn sei eine bereits vorhandene JDBC-Verbindung Statement stmt = null; ResultSet rs = null; try { stmt = conn.createStatement(); rs = stmt.executeQuery("SELECT foo FROM bar"); // oder, wenn Sie im Voraus nicht wissen, ob die // Anfrage ein SELECT ist... if (stmt.execute("SELECT foo FROM bar")) { rs = stmt.getResultSet(); } // Tue etwas mit dem ResultSet .... } finally { // Ressourcen sollten immer in einem // finally{}-Block // in der umgekehrten Reihenfolge ihrer Zuweisung // freigegeben werden if (rs != null) { try { rs.close(); } catch (SQLException sqlEx) { // ignore } rs = null; } if (stmt != null) { try { stmt.close(); } catch (SQLException sqlEx) { // ignore } stmt = null; } }
Seit der MySQL-Server-Version 5.0 in Verbindung mit
Connector/J 3.1.1 oder höher ist die Schnittstelle
java.sql.CallableStatement
mit Ausnahme
der Methode getParameterMetaData()
vollständig implementiert.
Mehr über gespeicherte Prozeduren in MySQL erfahren Sie in Kapitel 19, Gespeicherte Prozeduren und Funktionen.
Connector/J stellt Funktionalität für gespeicherte
Prozeduren über die JDBC-Schnittstelle
CallableStatement
zur Verfügung.
Hinweis.
Aktuelle Versionen von MySQL-Server geben nicht genug
Informationen zurück, damit der JDBC-Treiber
Ergebnismengen-Metadaten für Callable Statements liefern
kann. Folglich wird ResultSetMetaData
für CallableStatement
unter Umständen
den Wert NULL
zurückgeben.
Das folgende Beispiel zeigt eine gespeicherte Prozedur, die
den Wert von inOutParam
um 1 inkrementiert
und den im inputParam
übergebenen String
als ResultSet
zurückgibt:
Beispiel 25.3. Gespeicherte Prozeduren
CREATE PROCEDURE demoSp(IN inputParam VARCHAR(255), INOUT inOutParam INT) BEGIN DECLARE z INT; SET z = inOutParam + 1; SET inOutParam = z; SELECT inputParam; SELECT CONCAT('zyxw', inputParam); END
Um die Prozedur demoSp
mit Connector/J
einzusetzen, gehen Sie folgendermaßen vor:
Sie bereiten das Callable Statement mit
Connection.prepareCall()
vor.
Beachten Sie, dass Sie die Escape-Syntax von JDBC anwenden müssen, und dass die runden Klammern um die Parameter-Platzhalter obligatorisch sind:
Beispiel 25.4. Using Connection.prepareCall()
import java.sql.CallableStatement; ... // // Bereite Aufruf der gespeicherten Prozedur 'demoSp' // mit zwei Parametern vor // // Beachten Sie die JDBC-Escape-Syntax ({call ...}) // CallableStatement cStmt = conn.prepareCall("{call demoSp(?, ?)}"); cStmt.setString(1, "abcdefg");
Note.
Connection.prepareCall()
ist eine
aufwändige Methode, da der Treiber Metadaten abfragen
muss, um die Ausgabeparameter zu unterstützen. Aus
Performance-Gründen sollten Sie unnötige Aufrufe von
Connection.prepareCall()
vermeiden,
indem Sie
CallableStatement
-Objekte in
Ihrem Code wiederverwenden.
Registrieren Sie die Ausgabeparameter (sofern vorhanden)
Um die Werte der Ausgabeparameter (Parameter, die Sie beim
Anlegen der gespeicherten Prozedur als
OUT
oder INOUT
gekennzeichnet haben) abrufen zu können, müssen sie in
JDBC vor der Ausführung der Anweisung mit einer der
diversen
registerOutputParameter()
-Methoden in
der Klasse CallableStatement
registriert worden sein:
Beispiel 25.5. Registrierung von Ausgabeparametern
import java.sql.Types; ... // // Connector/J unterstützt benannte und indizierte // Ausgabeparameter. Mit beiden Methoden können Sie // Ausgabeparameter registrieren oder, unabhängig // von der gewählten Registrierungsmethode, // auch abrufen. // // Die folgenden Beispiele zeigen, wie die verschiedenen // Registrierungsmethoden für Ausgabeparameter verwendet werden // (wobei Sie natürlich nur eine Registrierung // pro Parameter verwenden). // // // Registriert den zweiten Parameter als Ausgabe und // verwendet den Typ 'INTEGER' für Rückgabewerte von // getObject() // cStmt.registerOutParameter(2, Types.INTEGER); // // Registriert den benannten Parameter 'inOutParam' und // verwendet den Typ 'INTEGER' für Rückgabewerte von // getObject() // cStmt.registerOutParameter("inOutParam", Types.INTEGER); ...
Stellt die Eingabeparameter ein (sofern vorhanden)
Eingabe und Ein/Ausgabeparameter werden ebenso gesetzt,
wie für PreparedStatement
-Objekte.
Allerdings können
CallableStatement
-Parameter auch
namentlich eingestellt werden:
Beispiel 25.6. Einstellung von CallableStatement
-Eingabeparametern
... // // Parameter nach Index einstellen // cStmt.setString(1, "abcdefg"); // // Oder Parameter mit // Namen einstellen // cStmt.setString("inputParameter", "abcdefg"); // // 'in/out'-Parameter nach Index einstellen // cStmt.setInt(2, 1); // // Oder 'in/out'-Parameter // mit Namen einstellen // cStmt.setInt("inOutParam", 1); ...
Führen Sie CallableStatement
aus
und rufen Sie Ergebnismengen oder Ausgabeparameter, sofern
vorhanden, ab.
CallableStatement
unterstützt zwar
alle Ausführungsmethoden von
Statement
(executeUpdate()
,
executeQuery()
oder
execute()
), aber
execute()
ist am flexibelsten, da Sie
mit dieser Methode nicht im Voraus wissen müssen, ob die
gespeicherte Prozedur Ergebnismengen unterstützt:
Beispiel 25.7. Abruf von Ergebnissen und Ausgabeparameterwerten
... boolean hadResults = cStmt.execute(); // // Alle zurückgelieferten Ergebnismengen verarbeiten // while (hadResults) { ResultSet rs = cStmt.getResultSet(); // Ergebnismenge verarbeiten ... hadResults = rs.getMoreResults(); } // // Ausgabeparameter abrufen // // Connector/J unterstützt Abruf sowohl nach Index // als auch nach Namen // int outputValue = rs.getInt(2); // index-based outputValue = rs.getInt("inOutParam"); // name-based ...
Vor der Version 3.0 der JDBC-API gab es kein Standardmittel,
um Schlüsselwerte aus Datenbanken zu holen, die „Auto
Increment“- oder Identitätsspalte unterstützten. Mit
älteren JDBC-Treibern für MySQL konnten Sie immer eine
MySQL-spezifische Methode auf der Schnittstelle
Statement
verwenden, oder
SELECT LAST_INSERT_ID()
sagen, wenn Sie
eine INSERT
-Operation auf einer Tabelle mit
AUTO_INCREMENT
-Schlüssel ausgeführt
hatten. Doch die MySQL-spezifische Methode ist nicht
portierbar und der Abruf der Werte des
AUTO_INCREMENT
-Schlüssels mit
SELECT
macht einen zusätzlichen
Datenbankzugriff erforderlich, ist also nicht die
effizienteste Methode. Die folgenden Codestücke zeigen die
drei unterschiedlichen Möglichkeiten zum Abruf von
AUTO_INCREMENT
-Werten. Zuerst zeigen wir,
wie die neue JDBC-3.0-Methode
getGeneratedKeys()
benutzt wird, die
jetzt die Methode der Wahl ist, wenn Sie
AUTO_INCREMENT
-Schlüssel abfragen müssen
und Zugang zu JDBC-3.0 haben. Das zweite Beispiel zeigt, wie
Sie denselben Wert mit einer standardmäßigen SELECT
LAST_INSERT_ID()
-Anfrage abholen können. Das letzte
Beispiel zeigt, wie aktualisierbare Ergebnismengen den
AUTO_INCREMENT
-Wert abrufen können, wenn
die Methode insertRow()
verwendet wurde.
Beispiel 25.8. AUTO_INCREMENT
-Spaltenwerte mit
Statement.getGeneratedKeys()
abrufen
Statement stmt = null; ResultSet rs = null; try { // // Erzeugt ein Statement-Objekt, das wir für // 'normale' Ergebnismengen verwenden können. // Die 'conn'-Verbindung zu einer MySQL-Datenbank // sei bereits vorhanden. stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_UPDATABLE); // // DDL-Anfragen für dieses Beispiel // stmt.executeUpdate("DROP TABLE IF EXISTS autoIncTutorial"); stmt.executeUpdate( "CREATE TABLE autoIncTutorial (" + "priKey INT NOT NULL AUTO_INCREMENT, " + "dataField VARCHAR(64), PRIMARY KEY (priKey))"); // // Fügt eine Zeile ein, die einen AUTO INCREMENT-Schlüssel im // Feld 'priKey' generiert // stmt.executeUpdate( "INSERT INTO autoIncTutorial (dataField) " + "values ('Can I Get the Auto Increment Field?')", Statement.RETURN_GENERATED_KEYS); // // So kann man den Wert einer Auto-Increment-Spalte mit // Statement.getGeneratedKeys() abholen // int autoIncKeyFromApi = -1; rs = stmt.getGeneratedKeys(); if (rs.next()) { autoIncKeyFromApi = rs.getInt(1); } else { // hier Ausnahme auslösen } rs.close(); rs = null; System.out.println("Key returned from getGeneratedKeys():" + autoIncKeyFromApi); } finally { if (rs != null) { try { rs.close(); } catch (SQLException ex) { // ignorieren } } if (stmt != null) { try { stmt.close(); } catch (SQLException ex) { // ignorieren } } }
Beispiel 25.9. Abruf von AUTO_INCREMENT
-Spaltenwerten mit
SELECT LAST_INSERT_ID()
Statement stmt = null; ResultSet rs = null; try { // // Erzeugt ein Statement-Objekt, das wir für // 'normale' Ergebnismengen benutzen können. stmt = conn.createStatement(); // // DDL-Anfragen für dieses Beispiel // stmt.executeUpdate("DROP TABLE IF EXISTS autoIncTutorial"); stmt.executeUpdate( "CREATE TABLE autoIncTutorial (" + "priKey INT NOT NULL AUTO_INCREMENT, " + "dataField VARCHAR(64), PRIMARY KEY (priKey))"); // // Fügt eine Zeile ein, die einen AUTO INCREMENT-Schlüssel im Feld // 'priKey' generiert // stmt.executeUpdate( "INSERT INTO autoIncTutorial (dataField) " + "values ('Can I Get the Auto Increment Field?')"); // // Verwendet die Funktion MySQL LAST_INSERT_ID(), // um dasselbe wie getGeneratedKeys() zu tun // int autoIncKeyFromFunc = -1; rs = stmt.executeQuery("SELECT LAST_INSERT_ID()"); if (rs.next()) { autoIncKeyFromFunc = rs.getInt(1); } else { // hier Ausnahme auslösen } rs.close(); System.out.println("Key returned from " + "'SELECT LAST_INSERT_ID()': " + autoIncKeyFromFunc); } finally { if (rs != null) { try { rs.close(); } catch (SQLException ex) { // ignorieren } } if (stmt != null) { try { stmt.close(); } catch (SQLException ex) { // ignorieren } } }
Beispiel 25.10. Retrieving AUTO_INCREMENT
column values in
Updatable ResultSets
Statement stmt = null; ResultSet rs = null; try { // // Erzeugt ein Statement-Objekt, das wir für // 'normale' ebenso wie für 'aktualisierbare' Ergebnismengen verwenden können. // Die 'conn''-Verbindung zu // einer MySQL-Datenbank sei bereits vorhanden // stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_UPDATABLE); // // DDL-Anfragen für dieses Beispiel // stmt.executeUpdate("DROP TABLE IF EXISTS autoIncTutorial"); stmt.executeUpdate( "CREATE TABLE autoIncTutorial (" + "priKey INT NOT NULL AUTO_INCREMENT, " + "dataField VARCHAR(64), PRIMARY KEY (priKey))"); // // So wird ein AUTO INCREMENT-Schlüssel von einer // aktualisierbaren Ergebnismenge abgerufen // rs = stmt.executeQuery("SELECT priKey, dataField " + "FROM autoIncTutorial"); rs.moveToInsertRow(); rs.updateString("dataField", "AUTO INCREMENT here?"); rs.insertRow(); // // Der Treiber fügt die Zeilen am Ende hinzu // rs.last(); // // Jetzt müsste die zuvor eingefügte Zeile erreicht sein // int autoIncKeyFromRS = rs.getInt("priKey"); rs.close(); rs = null; System.out.println("Key returned for inserted row: " + autoIncKeyFromRS); } finally { if (rs != null) { try { rs.close(); } catch (SQLException ex) { // ignorieren } } if (stmt != null) { try { stmt.close(); } catch (SQLException ex) { // ignorieren } } }
Wenn Sie den Code des obigen Beispiels ausführen, müsste
folgende Ausgabe erscheinen: Key returned from
getGeneratedKeys()
: 1 Key returned from
SELECT LAST_INSERT_ID()
: 1 Key returned for
inserted row: 2 Bitte denken Sie daran, dass die Verwendung
der Anfrage SELECT LAST_INSERT_ID()
gelegentlich knifflig sein kann, da der Wert dieser Funktion
als Geltungsbereich die Verbindung hat. Wenn also eine andere
Anfrage auf derselben Verbindung ausgeführt wird, wird der
Wert überschrieben. Dagegen hat die Methode
getGeneratedKeys()
das
Statement
-Objekt als Geltungsbereich
und kann daher zwar genutzt werden, wenn andere Anfragen auf
derselben Verbindung ausgeführt werden, aber nicht, wenn die
Anfragen auf dem Statement
-Objekt
ausgeführt werden.
In diesem Abschnitt wird beschrieben, wie Sie Connector/J in in unterschiedlichen Zusammenhängen einsetzen können.
Dieser Abschnitt vermittelt einige Grundkonzepte von J2EE, die für die Arbeit mit Connector/J von Bedeutung sind.
Verbindungspooling ist eine Technik, die darin besteht, einen Pool von Verbindungen aufzubauen und zu verwalten, damit diese für Threads, die sie benötigen, bereits zur Verfügung stehen.
Diese Technik beruht auf der Tatsache, dass die meisten Anwendungen nur dann Thread-Zugriff auf eine JDBC-Verbindung benötigen, wenn sie gerade aktiv eine Transaktion abwickeln, die in wenigen Millisekunden fertig ist. Wenn nicht gerade eine Transaktion verarbeitet wird, würde die Verbindung normalerweise untätig herumsitzen. In einem Verbindungspool kann sie dagegen von anderen Threads sinnvoll eingesetzt werden.
In der Praxis sieht das so aus: Wenn ein Thread auf MySQL oder eine andere Datenbank mit JDBC zugreifen muss, fordert er eine Verbindung aus dem Pool an. Hat er seine Arbeit auf der Verbindung beendet, gibt er sie an den Pool zurück, damit andere Threads sie wiederverwenden können.
Eine Verbindung, die aus dem Pool entliehen wurde, wird
ausschließlich von dem Thread benutzt, der sie angefordert
hatte. Aus Sicht der Programmierung ist dies dasselbe, als
riefe der Thread jedesmal, wenn ein eine JDBC-Verbindung
benötigt, DriverManager.getConnection()
auf. Beim Verbindungspooling kann er allerdings am Ende
entweder eine neue oder eine bereits vorhandene Verbindung
erwerben.
Verbindungspooling kann die Performance einer Java-Anwendung deutlich verbessern, da weniger Ressourcen verbraucht werden. Die Hauptvorteile des Verbindungspoolings sind:
Schnellerer Verbindungsaufbau
MySQL baut zwar im Vergleich zu anderen Datenbanken ohnehin Verbindungen sehr schnell auf, aber dennoch steigt bei der Aufnahme neuer JDBC-Verbindungen immer noch die Belastung für Netzwerk und JDBC-Treiber. Diese Belastung wird durch die Wiederverwendung von Verbindungen vermieden.
Einfacheres Programmiermodell
Durch das Verbindungspooling kann sich jeder einzelne Thread verhalten, als hätte er eine eigene JDBC-Verbindung. So können Sie ganz einfache JDBC-Programmiertechniken verwenden.
Bessere Kontrolle über den Ressourcenverbrauch
Wenn Sie auf Verbindungspooling verzichten und stattdessen jedesmal eine neue Verbindung öffnen, wenn ein Thread eine braucht, wird Ihre Anwendung unter Umständen viele Ressourcen unnötig belegen. Bei besonderer Belastung kann dies zu unvorhersehbarem Verhalten führen.
Bedenken Sie, dass jede Verbindung zu MySQL einen Aufwand bedeutet (für Arbeitsspeicher, CPU, Kontextumschaltungen usw.), und dies sowohl auf der Client- als auch auf der Serverseite. Mit jeder weiteren Verbindung schrumpfen die Ressourcen, die Ihrer Anwendung und dem MySQL-Server noch zur Verfügung stehen. Viele dieser Ressourcen werden ganz unabhängig davon belegt, ob die Verbindung gerade etwas Nützliches leistet oder nicht!
Verbindungspools können so getunt werden, dass die Performance möglichst gut ist, während gleichtzeitig die Ressourcenauslastung immer unter dem Niveau gehalten wird, ab dem die Anwendung nicht nur langsamer läuft, sondern sogar abstürzen kann.
Zum Glück hat Sun das Verbindungspooling in JDBC in den JDBC-2.0 Optional-Schnittstellen standardisiert, und alle wichtigen Anwendungsserver verfügen über Implementierungen dieser APIs, die mit MySQL Connector/J gut harmonieren.
Generell richten Sie den Verbindungspool in den Konfigurationsdateien Ihres Anwendungsservers ein und greifen über das Java Naming and Directory Interface (JNDI) darauf zu. Der folgende Code zeigt, wie ein Verbindungspool mit einer Anwendung auf einem J2EE-Anwendungsserver genutzt werden könnte:
Beispiel 25.11. Verwendung eines Verbindungspools mit einem J2EE-Anwendungsserver
import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; import javax.naming.InitialContext; import javax.sql.DataSource; public class MyServletJspOrEjb { public void doSomething() throws Exception { /* * JNDI Initial-Kontext erstellen, um die * DataSource nachschlagen zu können * * In Produktionscode sollte dieser als Objekt oder statische Variable * gespeichert werden, da die Erstellung eines * JNDI-Kontexts sehr aufwändig sein kann. * * Hinweis: Der Code funktioniert nur, wenn Sie Servlets * oder EJBs in einem J2EE-Anwendungsserver verwenden. Nutzen Sie * Verbindungspooling in Standalone-Java-Code, so * müssen sie die Datenquellen mit den Mitteln erstellen/konfigurieren, * die Ihre jeweilige Bibliothek für Verbindungspooling * zur Verfügung stellt. */ InitialContext ctx = new InitialContext(); /* * Nachschlageoperation auf der DataSource mit einem vom Anwendungsserver * bereitgestellten Pool im Rücken. DataSource-Objekte sollten ebenfalls * als Instanzvariablen zwischengespeichert werden, * da auch JNDI-Lookups aufwändig sind. */ DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/MySQLDB"); /* * Der folgende Code würde eigentlich in die 'service'-Methode Ihres * Servlets, JSPs oder EJBs gehören, dorthin, wo * sie mit einer JDBC-Verbindung arbeiten müssen. */ Connection conn = null; Statement stmt = null; try { conn = ds.getConnection(); /* * Die weitere Arbeit mit MySQL wird mit normaler JDBC-Programmierung * erledigt. Schließen sie jede Ressource, wenn Sie sie nicht mehr benötigen, * damit die Verbindungspool-Ressourcen so rasch wie möglich * wiederhergestellt werden */ stmt = conn.createStatement(); stmt.execute("SOME SQL QUERY"); stmt.close(); stmt = null; conn.close(); conn = null; } finally { /* * Hier werden jdbc-Objekte abgeschlossen, die im normalen * Code nicht explizit geschlossen worden sind. So * entstehen keine Ressourcen-'Lecks'... */ if (stmt != null) { try { stmt.close(); } catch (sqlexception sqlex) { // ignorieren -- da wir hier sowieso nichts daran tun können } stmt = null; } if (conn != null) { try { conn.close(); } catch (sqlexception sqlex) { // ignorieren -- da wir hier sowieso nichts daran tun können } conn = null; } } } }
Wie das obige Beispiel zeigt, sieht der Rest des Codes, nachdem Sie den JNDI-InitialContext beschafft und die DataSource nachgeschlagen haben, für erfahrene JDBC-Programmierer schon vertrauter aus.
Das Wichtigste, was Sie sich merken müssen, wenn Sie mit Verbindungspooling arbeiten: Egal was in Ihrem Code passiert (Ausnahmen, Kontrollfluss usw.), sorgen Sie immer dafür, dass Verbindungen und alles, was mit ihnen angelegt wurde (Anweisungen, Ergebnismengen usw.) immer geschlossen werden. Sonst können sie nicht wiederverwendet werden und verlaufen im Sande. Im besten Fall bedeutet dies, dass die von ihnen belegten MySQL-Server-Ressourcen (Puffer, Sperren oder Sockets) für einige Zeit wegfallen, aber im schlimmsten Fall gehen sie für immer verloren.
Was ist die optimale Größe für meinen Verbindungspool?
Wie bei anderen Konfigurations-Faustregeln lautet auch hier die Antwort: Kommt drauf an. Zwar hängt die optimale Größe von der erwarteten Last und durchschnittlichen Datenbanktransaktionsdauer ab, aber die beste Größe für einen Verbindungspool kann kleiner sein als Sie erwarten. Wenn man die Java Petstore Blueprint-Anwendung von Sun als Beispiel nimmt, kann ein Pool von 15-20 Verbindungen für eine mäßige Last (600 Benutzer gleichzeitig) ausreichen. Mit MySQL und Tomcat wären die Reaktionszeiten in einem solchen Szenario annehmbar.
Um einen Verbindungspool für Ihre Anwendung angemessen zu dimensionieren, sollten Sie Belastungstestskripten mit Apache JMeter oder The Grinder erstellen und ausprobieren, wie sich Ihre Anwendung unter Last verhält.
Am einfachsten beginnen Sie wie folgt: Stellen Sie die Höchstzahl von Verbindungen für Ihren Pool auf unbegrenzt ein, lassen Sie einen Belastungstest laufen, und messen Sie, wie viele nebenläufige Verbindungen maximal gebraucht wurden. Von dort aus gehen sie einen Schritt zurück und schauen nach, welche Mindest- und Höchstzahlen an Pool-Verbindungen die beste Performance für Ihre Anwendung ergeben.
Die folgenden Hinweise beruhen auf den Anleitungen für Tomcat-5.x in http://jakarta.apache.org/tomcat/tomcat-5.0-doc/jndi-datasource-examples-howto.html Dies ist zum Zeitpunkt der Erstellung dieses Dokuments die aktuelle Version.
Zuerst installieren Sie die mit Connector/J mitgelieferte
.jar-Datei in $CATALINA_HOME/common/lib
,
sodass sie allen in dem Container installierten Anwendungen
zur Verfügung steht.
Nun konfigurieren Sie die JNDI-DataSource, indem Sie
$CATALINA_HOME/conf/server.xml
in dem
Kontext, der Ihre Webanwendung definiert, eine
Ressourcendeklaration hinzufügen:
<Context ....> ... <Resource name="jdbc/MySQLDB" auth="Container" type="javax.sql.DataSource"/> <!-- Muss _genau_ mit dem oben verwendeten Namen übereinstimmen! Der Verbindungspool wird mit dem Namen "java:/comp/env/jdbc/MySQLDB" in JNDI eingebunden --> <ResourceParams name="jdbc/MySQLDB"> <parameter> <name>factory</name> <value>org.apache.commons.dbcp.BasicDataSourceFactory</value> </parameter> <!-- Stellen Sie diesen Wert nicht höher als max_connections auf Ihrem MySQL-Server ein. Normalerweise sollte er 10 oder einige Dutzend Verbindungen vorsehen, nicht hunderte oder tausende --> <parameter> <name>maxActive</name> <value>10</value> </parameter> <!-- Sie möchten nicht zu viele untätige Verbindungen unnötig offen lassen, nur ein paar, um mögliche Belastungsspitzen zu absorbieren --> <parameter> <name>maxIdle</name> <value>5</value> </parameter> <!-- Bitte verwenden Sie nicht autoReconnect=true, erstens wird es irgendwann abgeschafft und zweitens ist es ein Kreuz für ältere Verbindungspools, die keine Verbindungen testen konnten. Sie müssen entscheiden, ob Ihre Verbindung SQLExceptions beherrschen soll (Hinweis: das sollte sie!) und wie viel Leistungseinbußen Sie hinnehmen wollen, um zu gewährleisten, dass die Verbindung "frisch" ist --> <parameter> <name>validationQuery</name> <value>SELECT 1</value> </parameter> <!-- Der konservativste Ansatz ist: Testen Sie Verbindungen, bevor Ihre Anwendung sie bekommt. Für die meisten Anwendungen ist das gut, außerdem ist die obige Anfrage ganz klein und belegt kaum Serverressourcen, abgesehen von der Zeit, die es braucht, sie im Netzwerk zu übermitteln. Wenn Sie eine Hochlast-Anwendung haben, werden Sie eine andere Lösung suchen müssen. --> <parameter> <name>testOnBorrow</name> <value>true</value> </parameter> <!-- Ansonsten, oder zusätzlich zu testOnBorrow, können Sie testen, während die Verbindung untätig ist --> <parameter> <name>testWhileIdle</name> <value>true</value> </parameter> <!-- Diesen Wert müssen Sie einstellen, sonst wird der Idle-Evicter-Thread nie ausgeführt, selbst wenn Sie veranlasst haben, dass untätige Verbindungen getestet werden --> <parameter> <name>timeBetweenEvictionRunsMillis</name> <value>10000</value> </parameter> <!-- Verbindungen sollten nie zu lange untätig herumsitzen, jedenfalls nicht länger als wait_timeout in der Serverkonfiguration. Einige Minuten oder Minutenbruchteile sind hier manchmal akzeptabel, es hängt von Ihrer Anwendung und den Belastungsspitzen ab --> <parameter> <name>minEvictableIdleTimeMillis</name> <value>60000</value> </parameter> <!-- Benutzername und Passwort für die MySQL-Verbindung --> <parameter> <name>username</name> <value>someuser</value> </parameter> <parameter> <name>password</name> <value>somepass</value> </parameter> <!-- Klassenname für den Connector/J-Treiber --> <parameter> <name>driverClassName</name> <value>com.mysql.jdbc.Driver</value> </parameter> <!-- Der JDBC-Verbindungs-URL für MySQL. Wenn Sie andere MySQL-spezifische Parameter üübergeben möchten, müssen Sie dies hier im URL tun. Sie in den obigen Parameter-Tags einzustellen, hätte keine Wirkung. Außerdem müssen Sie & als Trennzeichen zwischen die Parameterwerte setzen, da das Ampersand in XML ein reserviertes Zeichen ist. --> <parameter> <name>url</name> <value>jdbc:mysql://localhost:3306/test</value> </parameter> </ResourceParams> </Context>
Generell sollten Sie die Installationsanleitung zu Ihrer Tomcat-Version befolgen, da sich die Datenquellenkonfiguration in Tomcat von Zeit zu Zeit ändert. Leider wird, wenn Sie in Ihrer XML-Datei die verkehrte Syntax verwenden, eine Ausnahme wie diese angezeigt:
Error: java.sql.SQLException: Cannot load JDBC driver class 'null ' SQL state: null
Die folgenden Anleitungen beziehen sich auf JBoss-4.x. Um die
Klassen des JDBC-Teibers dem Anwendungsserver zur Verfügung
zu stellen, kopieren Sie die .jar-Datei von Connector/J in das
lib
-Verzeichnis für Ihre
Server-Konfiguration (normalerweise heißt es
default
). Dann legen Sie in demselben
Konfigurationsverzeichnis in einem Unterverzeichnis namens
deploy
eine
Datenquellenkonfigurationsdatei an, die mit "-ds.xml" endet.
Diese veranlasst JBoss, die betreffende Datei als
JDBC-Datasource einzusetzen. Die Datei sollte folgendes
enthalten:
<datasources> <local-tx-datasource> <!-- Dieser Verbindungspool wird in JNDI unter dem Namen "java:/MySQLDB" eingebunden --> <jndi-name>MySQLDB</jndi-name> <connection-url>jdbc:mysql://localhost:3306/dbname</connection-url> <driver-class>com.mysql.jdbc.Driver</driver-class> <user-name>user</user-name> <password>pass</password> <min-pool-size>5</min-pool-size> <!-- Stellen Sie diesen Wert nicht höher als max_connections auf Ihrem MySQL-Server ein. Normalerweise sollte er 10 oder einige Dutzend Verbindungen vorsehen, nicht hunderte oder tausende --> <max-pool-size>20</max-pool-size> <!-- Verbindungen sollten nie zu lange untätig herumsitzen, jedenfalls nicht länger als wait_timeout in der Serverkonfiguration. Einige Minuten oder Minutenbruchteile sind hier manchmal akzeptabel, es hängt von Ihrer Anwendung und den Belastungsspitzen ab --> <idle-timeout-minutes>5</idle-timeout-minutes> <!-- Wenn Sie Connector/J 3.1.8 oder höher benutzen, können Sie unsere Implementierung verwenden, um die Stabilität des Verbindungspools zu erhöhen. --> <exception-sorter-class-name>com.mysql.jdbc.integration.jboss.ExtendedMysqlExceptionSorter</exception-sorter-class-name> <valid-connection-checker-class-name>com.mysql.jdbc.integration.jboss.MysqlValidConnectionChecker</valid-connection-checker-class-name> </local-tx-datasource> </datasources>
Einige Probleme treten öfters mit MySQL Connector/J auf. Dieser Abschnitt beschreibt die Symtome und ihre Heilung.
Fragen
26.3.5.3.1: Wenn ich mit MySQL Connector/J eine Datenbankverbindung aufbaue, wird folgende Ausnahme ausgelöst:
SQLException: Server configuration denies access to data source SQLState: 08001 VendorError: 0
Was ist da los? Mit dem Kommandozeilen-Client von MySQL funktioniert die Verbindung einwandfrei.
26.3.5.3.2: Meine Anwendung löst die SQLException 'No Suitable Driver' aus. Warum?
26.3.5.3.3: Ich versuche, MySQL Connector/J in einem Applet oder einer Anwendung einzusetzen und bekomme einen Fehler wie diesen gemeldet:
SQLException: Cannot connect to MySQL server on host:3306. Is there a MySQL server running on the machine/port you are trying to connect to? (java.security.AccessControlException) SQLState: 08S01 VendorError: 0
26.3.5.3.4: Ich habe ein Servlet/Programm, das es einen Tag lang tut und dann über Nacht nicht mehr funktioniert
26.3.5.3.5: Ich versuche, aktualisierbare Ergebnismengen von JDBC-2.0 einzusetzen, und eine Fehlermeldung behauptet, meine Ergebnismenge sei gar nicht aktualisierbar.
Fragen und Antworten
26.3.5.3.1: Wenn ich mit MySQL Connector/J eine Datenbankverbindung aufbaue, wird folgende Ausnahme ausgelöst:
SQLException: Server configuration denies access to data source SQLState: 08001 VendorError: 0
Was ist da los? Mit dem Kommandozeilen-Client von MySQL funktioniert die Verbindung einwandfrei.
MySQL Connector/J muss für die Verbindung mit MySQL TCP/IP-Sockets einsetzen, da Java keine Unix Domain Sockets unterstützt. Der Sicherheitsmanager von MySQL schaut deshalb bei einem Verbindungsversuch mit MySQL Connector/J in seine Berechtigungstabellen, um festzustellen, ob die Verbindung zulässig ist.
Damit das funktionieren kann, müssen Sie dem MySQL-Server
mithilfe der GRANT
Anweisung die
notwendigen Sicherheitszeugnisse vorweisen. Weitere
Informationen siehe
Abschnitt 13.5.1.3, „GRANT
und REVOKE
“.
Hinweis.
Ein Verbindungstest mit dem Kommandozeilenclient
mysql funktioniert nur, wenn Sie das
Flag --host
hinzufügen und als Host
etwas anderes als localhost
einsetzen. Der Kommandozeilenclient
mysql wird Unix-Domain-Sockets
verwenden, wen Sie den speziellen Hostnamen
localhost
benutzen. Um die Verbindung
mit localhost
zu testen, müssen Sie
stattdessen 127.0.0.1
als Hostnamen
einsetzen.
Warnung. Wenn Sie bei der Änderungen von Berechtigungen in MySQL Fehler machen, kann dies dazu führen, dass Ihre Serverinstallation keine optimalen Sicherheitseigenschaften mehr hat.
26.3.5.3.2: Meine Anwendung löst die SQLException 'No Suitable Driver' aus. Warum?
Für diesen Fehler gibt es drei mögliche Gründe:
Der Connector/J-Treiber liegt nicht in Ihrem
CLASSPATH
, siehe auch
Abschnitt 25.3.2, „Installation von Connector/J“.
Der Verbindungs URL hat ein falsches Format oder Sie referenzieren den verkehrten JDBC-Treiber.
Die Systemeigenschaft jdbc.drivers
wurde bei Benutzung des DriverManager nicht auf das
Verzeichnis des Connector/J-Treibers eingestellt.
26.3.5.3.3: Ich versuche, MySQL Connector/J in einem Applet oder einer Anwendung einzusetzen und bekomme einen Fehler wie diesen gemeldet:
SQLException: Cannot connect to MySQL server on host:3306. Is there a MySQL server running on the machine/port you are trying to connect to? (java.security.AccessControlException) SQLState: 08S01 VendorError: 0
Entweder führen Sie ein Applet aus, oder Ihr MySQL-Server wurde mit der Option "--skip-networking" installiert, oder Ihr MySQL-Server sitzt hinter einer Firewall.
Applets können Netzwerkverbindungen nur mit dem Computer aufnehmen, auf den der Webserver läuft, der die .class-Dateien des Applets liefert. Das bedeutet, dass MySQL ebenfalls auf demselben Computer laufen muss (es sei denn, Sie verwenden irgendeine Art von Port-Umleitung). Außerdem bedeutet es, dass Sie Applets nicht in Ihrem lokalen Dateisystem testen können, sondern immer erst auf einem Webserver installieren müssen.
MySQL Connector/J kann mit MySQL nur über TCP/IP kommunizieren, da Java keine Unix-Domain-Sockets unterstützt. Die TCP/IP-Kommunikation mit MySQL kann jedoch in Mitleidenschaft gezogen werden, wenn MySQL mit der Option "--skip-networking" gestartet wurde oder hinter einer Firewall sitzt.
Wenn MySQL mit der Option "--skip-networking" gestartet
wurde (dies tut beispielsweise das Debian Linux-Package
von MySQL Server), müssen Sie dies in der Datei
/etc/mysql/my.cnf or /etc/my.cnf auskommentieren.
Natürlich kann Ihre my.cnf-Datei auch im
data
-Verzeichnis Ihres MySQL-Servers
oder irgendwo sonst liegen (je nachdem, wie MySQL für Ihr
System kompiliert wurde). Binärversionen von MySQL AB
schauen immer in /etc/my.cnf and [datadir]/my.cnf. Wenn
Ihr MySQL-Server durch eine Firewall geschützt ist,
müssen Sie diese so konfigurieren, dass sie
TCP/IP-Verbindungen von dem Host, auf dem der Java-Code
läuft, zu dem MySQL-Server auf dem Port zulässt, auf den
MySQL lauscht (nach Voreinstellung 3306).
26.3.5.3.4: Ich habe ein Servlet/Programm, das es einen Tag lang tut und dann über Nacht nicht mehr funktioniert
MySQL schließt Verbindungen, die 8 Stunden lang inaktiv waren. Sie müssen entweder einen Verbindungspool, der alte Verbindungen behandelt, oder den "autoReconnect"-Parameter verwenden (siehe Abschnitt 25.3.4.1, „Driver/Datasource-Klassennamen, URL-Syntax und Konfigurationseigenschaften für Connector/J“).
Außerdem sollten Sie SQLExceptions in Ihrer Anwendung
abfangen und behandeln, anstatt sie immer weiter
durchzureichen, bis Ihre Anwendung abbricht; schon allein
weil es guter Stil ist. MySQL Connector/J stellt den
SQLState (siehe
java.sql.SQLException.getSQLState()
in
Ihren APIDOCS) auf "08S01" ein, wenn es während der
Verarbeitung einer Anfrage Netzwerkprobleme bekommt. Ihr
Anwendungscode sollte dann versuchen, sich erneut mit
MySQL zu verbinden.
Das folgende (vereinfachte) Beispiel zeigt, mit welchem Code man solche Ausnahmen behandeln könnte:
Beispiel 25.12. Beispiel einer Transaktion mit Retry-Logik
public void doBusinessOp() throws SQLException { Connection conn = null; Statement stmt = null; ResultSet rs = null; // // Wie oft wollen Sie die Transaktion erneut versuchen // (oder wenigstens eine Verbindung zu bekommen)? // int retryCount = 5; boolean transactionCompleted = false; do { try { conn = getConnection(); // wir setzen voraus, dass diese von einer // javax.sql.DataSource oder dem // java.sql.DriverManager geliefert wird conn.setAutoCommit(false); // // An diesem Punkt hängt die 'Retry-Fähigkeit' der // Transaktion von Ihrer Anwendungslogik ab und davon // ob Sie Autocommit verwenden (in diesem Fall nicht) // und ob Sie transaktionssichere Speicher-Engines // einsetzen // // Für dieses Beispiel gehen wir davon aus, das es _nicht_ sicher ist, // die gesamte Transaktion erneut zu versuchen, und setzen daher // die Retry-Zahl auf 0 // // Wenn Sie nur transaktionssichere Tabellen verwenden oder // Ihre Anwendung sich davon erholen könnte, wenn eine Verbindung // mitten in der Operation abstürzt, dann würden Sie hier am // 'retryCount' nichts ändern und die Schleife einfach so lange durchlaufen, // bis retryCount == 0. // retryCount = 0; stmt = conn.createStatement(); String query = "SELECT foo FROM bar ORDER BY baz"; rs = stmt.executeQuery(query); while (rs.next()) { } rs.close(); rs = null; stmt.close(); stmt = null; conn.commit(); conn.close(); conn = null; transactionCompleted = true; } catch (SQLException sqlEx) { // // Die beiden 'Retry-fähigen' SQL-Zustände sind 08S01 // für einen Kommunikationsfehler und 40001 für Deadlock. // // Retry nur dann, wenn der Fehler wegen einer alten Verbindung, // Kommunikationsproblemen oder einem Deadlock auftrat // String sqlState = sqlEx.getSQLState(); if ("08S01".equals(sqlState) || "40001".equals(sqlState)) { retryCount--; } else { retryCount = 0; } } finally { if (rs != null) { try { rs.close(); } catch (SQLException sqlEx) { // Das gehört ins Log. . . } } if (stmt != null) { try { stmt.close(); } catch (SQLException sqlEx) { // Das gehört ebenfalls ins Log. . . } } if (conn != null) { try { // // Wenn hier conn nicht Null ist, sollte die // Transaktion zurückgerollt werden, da noch // nicht alle Arbeit erledigt ist try { conn.rollback(); } finally { conn.close(); } } catch (SQLException sqlEx) { // // Wenn hier eine Ausnahme auftritt, ist es ernst. // Daher reichen wir sie besser im // Stapel nach oben anstatt sie nur // zu protokollieren . . . throw sqlEx; } } } } while (!transactionCompleted && (retryCount > 0)); }
Hinweis.
Die Option autoReconnect
wird nicht
empfohlen, da es keine sichere Methode einer
Neuverbindung mit dem MySQL-Server ohne das Risiko von
Schäden am Verbindungszustand oder den
Datenbankzustandsinformationen gibt. Nutzen Sie
stattdessen einen Verbindungspool, der Ihre Anwendung in
die Lage versetzt, eine verfügbare Verbindung aus dem
Pool zur Kontaktaufnahme mit dem MySQL-Server zu
benutzen. Die autoReconnect
-Facility
ist veraltet und wird in einem zukünftigen Release
wahrscheinlich abgeschafft werden.
26.3.5.3.5: Ich versuche, aktualisierbare Ergebnismengen von JDBC-2.0 einzusetzen, und eine Fehlermeldung behauptet, meine Ergebnismenge sei gar nicht aktualisierbar.
Da MySQL keine Zeilenbezeichner kennt, kann MySQL Connector/J Ergebnismengen nur dann aktualsieren, wenn sie von Anfragen auf Tabellen herrühren, die mindestens einen Primärschlüssel haben. Außerdem muss die Anfrage jeden Primärschlüssel auswählen und darf sich nur auf eine einzige Tabelle beziehen (also keine Joins). Dies ist in der JDBC-Spezifikation festgelegt.
MySQL AB bietet der Benutzercommunity Unterstützung über Mailinglisten an. Bei Problemen mit Connector/J können Sie sich in der MySQL- und Java-Mailingliste Hilfe von erfahrenen Benutzern holen. Archive und Abonnementsinformationen stehen online unter http://lists.mysql.com/java zur Verfügung.
Wie Sie MySQL-Mailinglisten abonnieren oder die Listenarchive durchsuchen können, erfahren Sie unter http://lists.mysql.com/. Siehe Abschnitt 1.7.1, „Die MySQL-Mailinglisten“.
Community-Support von erfahrenen Benutzern erhalten Sie auch im JDBC Forum. Auch in den anderen MySQL-Foren unter http://forums.mysql.com wird Ihnen geholfen. Siehe auch Abschnitt 1.7.2, „MySQL-Community-Support in den MySQL-Foren“.
Normalerweise melden Sie Bugs bei http://bugs.mysql.com/, unserer Fehlerdatenbank. Diese Datenbank ist öffentlich; jeder kann in ihr stöbern oder suchen. Wenn Sie sich beim System anmelden, können Sie auch neue Bugreports übermitteln.
Wenn Sie einen Sicherheitsbug in MySQL gefunden haben, schicken Sie eine E-Mail an security_at_mysql.com.
Zum Schreiben eines guten Bugreports gehört Geduld, doch wenn Sie es von Anfang an richtig machen, sparen Sie unsere und Ihre eigene Zeit. Wenn wir einen guten Bugreport mit einem vollständigen Testfall für den Bug bekommen, werden wir den Fehler höchstwahrscheinlich im nächsten Release beheben können.
Dieser Abschnitt hilft Ihnen, Ihren Bericht korrekt zu verfassen, damit Sie nicht Ihre Zeit verschwenden, um uns Dinge mitzuteilen, die uns kaum oder gar nicht weiterhelfen.
Wenn Sie einen reproduzierbaren Bug melden, schicken Sie Ihren Bericht bitte an die Fehlerdatenbank unter http://bugs.mysql.com/. Einen Fehler, den wir reproduzieren können, werden wir mit Sicherheit im nächsten MySQL-Release auch beheben können.
Um andere Probleme zu melden, nutzen Sie bitte eine der MySQL-Mailinglisten.
Mit einer zu ausführlichen Meldung können wir meist etwas anfangen, aber nicht mit einer, die zu wenig Informationen enthält. Oft lassen die Nutzer Einzelheiten weg, weil sie glauben, die Fehlerursache bereits zu kennen, und manche Details für bedeutungslos halten.
Halten Sie sich an das Prinzip: Wenn Sie im Zweifel sind, ob Sie ein Detail erwähnen sollen, tun Sie es. Ein paar Zeilen mehr in Ihrem Bericht kosten Sie wenig Zeit und Mühe. Das ist besser, als lange auf eine Antwort zu warten, weil wir Informationen, die im Bericht fehlten, nachträglich von Ihnen einholen müssen.
Die häufigsten Fehler in Bugreports sind (a) der Verfasser gibt die Versionsnummer von Connector/J oder MySQL nicht an, und (b) er beschreibt die Plattform auf der Connector/J installiert ist, nicht genau genug (einschließlich JVM-Version sowie Plattformtyp und -version, auf der MySQL selbst installiert ist).
Ohne diese ungeheuer wichtigen Informationen ist der Bugreport in 99 Prozent der Fälle nutzlos. Sehr oft werden uns Fragen gestellt wie: „Warum funktioniert das bei mir nicht?“ Dann stellen wir fest, dass das verlangte Feature in dieser MySQL-Version nicht implementiert war, oder dass ein Bug, der in einem Bericht beschrieben wird, in den neueren MySQL-Versionen bereits behoben wurde.
Manchmal ist der Fehler plattformunabhängig. In solchen Fällen ist es für uns nachgerade unmöglich, irgendetwas zu reparieren, ohne das Betriebssystem und die Versionsnummer der Plattform zu kennen.
Wenn es irgend möglich ist, erstellen Sie bitte einen reproduzierbaren, eigenständigen Testfall, der keine Klassen von Drittanbietern einbezieht.
Um dies zu vereinfachen, liefern wir eine Basisklasse namens
'com.mysql.jdbc.util.BaseBugReport
' für
Testfälle mit Connector/J. Um mit dieser Klasse einen Testfall
für Connector/J anzulegen, erstellen Sie eine eigene Klasse,
die von com.mysql.jdbc.util.BaseBugReport
erbt und die Methoden setUp()
,
tearDown()
und runTest()
überschreibt.
In der Methode setUp()
legen Sie Ihre
Tabellen an und laden die Daten hinein, die zum Demonstrieren
des Fehlers erforderlich sind.
In die Methode runTest()
schreiben Sie Code,
der den Bug an den Tabellen und Daten, die mit
setUp
erstellt wurden, aufzeigt.
Mit der Methode tearDown()
löschen Sie die
mit setUp()
erstellten Tabellen.
In einer dieser drei Methoden sollten Sie mit einer Variante der
getConnection()
-Methode eine JDBC-Verbindung
mit MySQL aufbauen:
getConnection()
- Richtet eine Verbindung
mit dem in getUrl()
angegebenen JDBC URL
ein. Wenn bereits eine Verbindung besteht, wird diese
zurückgegeben, andernfalls wird eine neue Verbindung
angelegt.
getNewConnection()
- Dies verwenden Sie,
wenn sie eine neue Verbindung für Ihren Bugreport
benötigen (d.h. wenn mehr als eine Verbindung beteiligt
sind).
getConnection(String url)
- Gibt eine
Verbindung mit dem angegebenen URL zurück.
getConnection(String url, Properties
props)
- Gibt eine Verbindung mit diesem URL und
diesen Eigenschaften zurück.
Wenn Sie einen anderen JDBC-URL als 'jdbc:mysql:///test'
benutzen müssen, überschreiben Sie auch die Methode
getUrl()
.
Mit den Methoden assertTrue(boolean
expression)
und assertTrue(String
failureMessage, boolean expression)
erstellen Sie
Bedingungen, die in Ihrem Testfall erfüllt sein müssen, um das
erwartete Verhalten zu demonstrieren (im Gegensatz zu dem
Verhalten, das Sie beobachten, und wegen dem Sie den Bugreport
schreiben).
Zum Schluss schreiben Sie eine
main()
-Methode, die eine neue Instanz Ihres
Testfalls erzeugt und die run
-Methode
aufruft:
public static void main(String[] args) throws Exception { new MyBugReport().run(); }
Wenn Sie mit Ihrem Testfall fertig sind und sich überzeugt haben, dass er den Fehler, den Sie melden, demonstriert, übermitteln Sie ihn mit Ihrem Bugreport an http://bugs.mysql.com/.
Die Connector/J Change History (Changelog) befindet sich im Haupt-Changelog für MySQL. Siehe Abschnitt D.3, „MySQL Connector/J Change History“.
MySQL Connector/MXJ ist eine intelligente Lösung, um eine
MySQL-Datenbank-Engine (mysqld
) innerhalb eines
Java-Packages zu installieren.
MySQL Connector/MXJ ist ein Java Utility-Package, mit dem Sie eine MySQL-Datenbank ganz einfach durch Angabe eines Zusatzparameters im JDBC-Verbindungs-URL einsetzen und managen können. Dieser Parameter sorgt dafür, dass die Datenbank beim ersten Verbindungsaufbau gestartet wird. Java-Entwickler können datenbankgestützte Anwendungen dadurch einfacher erstellen, da die Installationshindernisse für sie selbst und die Endanwender wegfallen.
MySQL Connector/MXJ lässt die MySQL-Datenbank wie eine Java-Komponente erscheinen, indem es ermittelt, auf welcher Plattform ein System läuft, die passende Binärversion heraussucht und die Installationsdatei startet. Optional wird sogar eine Anfangsdatenbank mit den vom Benutzer vorgegebenen Parametern eingerichtet.
In den folgenden Anleitungen wird MySQL Connector/MXJ mit einem JDBC-Treiber eingesetzt und als JMX MBean auf JBoss installiert.
Quell- und Binärdateien erhalten Sie bei: http://dev.mysql.com/downloads/connector/mxj/.
Da dies ein Beta-Release ist, freuen wir uns über Feedback von Ihrer Seite.
Bitte richten Sie Fragen oder Kommentare an die MySQL- und Java-Mailingliste.
Connector/MX
Connector/MXJ 5.x, zurzeit noch im Beta-Stadium, enthält
mysqld
in der Version 5.0.22 sowie
Binärdateien für Linux x86, Mac OS X PPC, Windows
XP/NT/2000 x86 und Solaris SPARC. Connector/MXJ 5.x
erfordert das Connector/J 5.x-Package.
Connector/MXJ 1.x umfasst mysqld
in der
Version 4.1.13 und Binärdateien für Linux x86, Windows
XP/NT/2000 x86 und Solaris SPARC. Connector/MXJ 1.x
erfordert das Connector/J 3.x-Package.
Diese Anleitung bezieht sich auf den Connector/MXJ 5.x-Release. Informationen über ältere Releases entnehmen Sie bitte der Dokumentation zu der jeweiligen Distribution.
Connector/MXJ besteht aus einer Java-Klasse, einer Kopie der
mysqld
-Binary für eine bestimmte Liste von
Plattformen sowie den zugehörigen Dateien und
Support-Utilities. Die Java-Klasse steuert die Initialisierung
einer Instanz der eingebetteten mysqld
-Binary
und die weitere Verwaltung des
mysqld
-Prozesses. Die gesamte Sequenz und
Verwaltung kann mit den Java-Klassen von Connector/MXJ komplett
in Java abgewickelt werden. Die nachfolgende Abbildung gibt
einen Überblick über den Inhalt von Connector/MXJ.
Es ist wichtig zu wissen, dass Connector/MXJ keine eingebettete
Version von MySQL ist und ebenso wenig eine MySQL-Version, die
als Teil einer Java-Klasse geschrieben wurde. Connector/MXJ
arbeitet mit einer eingebetteten, kompilierten Binärversion von
mysqld
, wie sie auch sonst bei einer normalen
MySQL-Installation zum Einsatz kommen würde.
Es sind der Connector/MXJ-Wrapper sowie die unterstützenden Klassen und Tools, die Connector/MXJ wie eine MySQL-Instanz aussehen lassen.
Wenn Sie Connector/MXJ initialisieren, wird die
mysqld
-Binärdatei für die betreffende
Plattform, zusammen mit einem vorkonfigurierten Data Directory,
extrahiert. Beides ist in der JAR-Datei von Connector/MXJ
enthalten. Die mysqld
-Instanz wird dann mit
den bei der Initialisierung angegebenen weiteren Optionen
gestartet, und schon ist die MySQL-Datenbank zugänglich.
Da Connector/MXJ in Kombination mit Connector/J arbeitet, können Sie über eine JDBC-Verbindung auf die MySQL-Instanz zugreifen. Wenn Sie den Server nicht mehr benötigen, wird die Instanz abgeschlossen und die während der Session angelegten Daten werden nach Voreinstellung in dem temporären Verzeichnis bewahrt, das beim Hochfahren der Instanz angelegt worden ist.
Connector/MXJ und die eingebettete mysqld
können in mehreren Umgebungen eingesetzt werden, in denen es
unmöglich wäre, eine vorhandene Datenbank zu benutzen oder
eine neue MySQL-Instanz zu installieren. Solche Umgebungen sind
beispielsweise Embedded Datenbankanwendungen auf CD-ROM und
vorübergehende Datenbankanforderungen einer
Java-Anwendungsumgebung.
Für Connector/MXJ gibt es keine Installationsanwendung oder -prozesse, doch die folgenden Schritte können die Installation und den Einsatz von Connector/MXJ erleichtern.
Folgende Grundvoraussetzungen müssen erfüllt sein:
Java Runtime Environment (v1.4.0 oder höher), wenn Sie nur das Package einsetzen möchten.
Java Development Kit (v1.4.0 oder höher), wenn Sie Connector/MXJ aus den Quelldateien erstellen wollen.
Connector/J 5.0 oder höher.
Je nach der Installations-/Einsatzumgebung benötigen Sie vielleicht auch Folgendes:
JBoss – 4.0rc1 oder höher
Apache Tomcat – 5.0 oder höher
JMX-Referenzimplementierung Version 1.2.1 von Sun (von http://java.sun.com/products/JavaManagement/)
Connector/MXJ ist mit jeder Plattform kompatibel, die Java und
MySQL unterstützt. Connector/MXJ enthält die
mysqld
-Binary für ausgewählte Plattformen
bereits ab Werk:
Linux, i386
Windows NT, Windows 2000, Windows XP, x86
Solaris 8, SPARC 32 (kompatibel mit Solaris 8, Solaris 9 und Solaris 10 auf SPARC mit 32 Bit und 64 Bit)
Mac OS X, PowerPC
Mehr über die Integration Ihres eigenen Connector/MXJ in die verschiedenen Plattformen erfahren Sie unter Abschnitt 25.4.5.1, „Ein eigenes Connector/MXJ-Package anlegen“.
Da kein formaler Installationsprozess existiert, bleiben die Installationsmethode, das Installationsverzeichnis und die Zugriffsmethoden von Connector/MXJ vollständig Ihren persönlichen Bedürfnissen überlassen.
Für eine Basisinstallation suchen Sie ein Zielverzeichnis für
die Dateien von Connector/MXJ aus. Auf Unix/Linux wäre dies so
etwas wie /usr/local/connector-mxj
und auf
Windows so etwas wie C:\Connector-MXJ
oder
ein Unterverzeichnis von Programmdateien
.
Die Dateien werden folgendermaßen installiert:
Sie laden das Connector/MXJ-Package entweder im Tar/Gzip-Format (ideal für Unix/Linux) oder im Zip-Format (Windows) herunter.
Sie extrahieren die Dateien, wodurch das Verzeichnis
connector-mxj
angelegt wird. Dieses
können Sie an den gewünschten Speicherort kopieren und
nach Wunsch umbenennen.
Am besten schreiben Sie das Verzeichnis von Connector/MXJ
JAR (connextor-mxj.jar
) auch in Ihre
globale Variable CLASSPATH
. Zusätzlich
müssen Sie die AspectJ Runtime hinzufügen, die in
lib/aspectjrt.jar
liegt.
Auf Unix/Linux können Sie dies entweder global tun, indem Sie das globale Shell-Profil entsprechend bearbeiten, oder auf Benutzerebene, indem Sie das jeweilige individuelle Shell-Profil ändern.
Auf Windows 2000, Windows NT und Windows XP bearbeiten Sie
den globalen CLASSPATH
, indem Sie die
Umgebungsvariablen
in der Systemsteuerung
für System
ändern.
Sobald Sie die Komponenten von Connector/MXJ und Connector/J
extrahiert haben, können Sie eine Beispielanwendung ausführen,
die eine MySQL-Instanz erstellt. Testen können Sie die
Installation mit ConnectorMXJUrlTestExample
:
java ConnectorMXJUrlTestExample jdbc:mysql:mxj://localhost:3336/test?server.basedir=/var/tmp/test-mxj [MysqldResource] launching mysqld (getOptions) [/var/tmp/test-mxj/bin/mysqld][--no-defaults][--pid-file=/var/tmp/test-mxj/data/MysqldResource.pid][--socket=mysql.sock][--datadir=/var/tmp/test-mxj/data][--port=3336][--basedir=/var/tmp/test-mxj] [MysqldResource] launching mysqld (driver_launched_mysqld_1) InnoDB: The first specified data file ./ibdata1 did not exist: InnoDB: a new database to be created! 060726 15:40:42 InnoDB: Setting file ./ibdata1 size to 10 MB InnoDB: Database physically writes the file full: wait... 060726 15:40:43 InnoDB: Log file ./ib_logfile0 did not exist: new to be created InnoDB: Setting log file ./ib_logfile0 size to 5 MB InnoDB: Database physically writes the file full: wait... 060726 15:40:43 InnoDB: Log file ./ib_logfile1 did not exist: new to be created InnoDB: Setting log file ./ib_logfile1 size to 5 MB InnoDB: Database physically writes the file full: wait... InnoDB: Doublewrite buffer not found: creating new InnoDB: Doublewrite buffer created InnoDB: Creating foreign key constraint system tables InnoDB: Foreign key constraint system tables created 060726 15:40:44 InnoDB: Started; log sequence number 0 0 060726 15:40:44 [Note] /var/tmp/test-mxj/bin/mysqld: ready for connections. Version: '5.0.22-max' socket: 'mysql.sock' port: 3336 MySQL Community Edition - Experimental (GPL) [MysqldResource] mysqld running as process: 1210 ------------------------ 5.0.22-max ------------------------ [MysqldResource] stopping mysqld (process: 1210) 060726 15:40:44 [Note] /var/tmp/test-mxj/bin/mysqld: Normal shutdown 060726 15:40:45 InnoDB: Starting shutdown... 060726 15:40:48 InnoDB: Shutdown completed; log sequence number 0 43655 060726 15:40:48 [Note] /var/tmp/test-mxj/bin/mysqld: Shutdown complete [MysqldResource] clearing options [MysqldResource] shutdown complete
Diese Ausgabe zeigt, wie MySQL startet, die notwendigen Dateien (Logdateien, InnoDB-Datendateien) angelegt werden und die MySQL-Datenbank in den Betriebszustand geht. Dann wird die Instanz von Connector/MXJ heruntergefahren, bevor das Beispiel endet.
Connector/MXJ und Connector/J arbeiten zusammen, damit Sie eine
Instanz des mysqld
-Servers einfach durch ein
Schlüsselwort im JDBC-Verbindungs-String starten können. So
lässt sich die Integration von Connector/MXJ in eine
Java-Anwendung automatisieren und der Einsatz von Connector/MXJ
wird ganz einfach:
Laden und extrahieren Sie Connector/MXJ und schreiben Sie
connector-mxj.jar
in den
CLASSPATH
.
Nehmen Sie in den JDBC-Verbindungs-String das Schlüsselwort
mxj
auf, wie hier gezeigt:
jdbc:mysql:mxj://localhost:
.
PORT
/DBNAME
Mehr zum Thema erfahren Sie in Abschnitt 25.4.3, „Konfiguration von Connector/MXJ“.
Für den Einsatz in einer JBoss-Umgebung müssen Sie diese in den JDBC-Parametern so konfigurieren, dass sie die Connector/MXJ-Komponente benutzt:
Laden Sie Connector/MXJ und kopieren Sie die Datei
connector-mxj.jar
in das Verzeichnis
$JBOSS_HOME/server/default/lib
.
Laden Sie Connector/J und kopieren Sie die Datei
connector-mxj.jar
in das Verzeichnis
$JBOSS_HOME/server/default/lib
.
Erzeugen Sie eine MBean-Service-XML-Datei im Verzeichnis
$JBOSS_HOME/server/default/deploy
,
wobei eventuell Attribute wie datadir
und
autostart
eingestellt werden.
Stellen Sie die JDBC-Parameter Ihrer Webanwendung wie folgt ein:
String driver = "com.mysql.jdbc.Driver"; String url = "jdbc:mysql:///test?propertiesTransform="+ "com.mysql.management.jmx.ConnectorMXJPropertiesTransform"; String user = "root"; String password = ""; Class.forName(driver); Connection conn = DriverManager.getConnection(url, user, password);
Am besten legen Sie für Benutzer und Datenbank separate Tablespaces an, anstatt "root und test" zu verwenden.
Außerdem sollten Sie unbedingt eine Backup-Prozedur einrichten,
um die Datenbankdateien im datadir
zu
sichern.
Das beste Mittel, um sicherzustellen, dass Ihre Plattform unterstützt wird, sind die JUnit-Tests. Diese überprüfen die Connector/MXJ-Klassen und zugehörige Komponenten.
Zuerst müssen Sie sich vergewissern, dass die Komponenten auf
Ihrer Plattform funktionieren. Da die Klasse
MysqldResource
in Wirklichkeit ein
Wrapper für eine native MySQL-Version ist, werden nicht alle
Plattformen unterstützt. Zu der Zeit, da dies geschrieben
wird, funktioniert Linux auf der i386-Architektur ziemlich
gut, ebenso wie OS X v10.3. Begrenzte Tests wurden auch
bereits mit Windows und Solaris vorgenommen.
Anforderungen:
JDK-1.4 oder höher (oder die JRE, wenn Sie keine Quelldateien oder JSPs kompilieren).
MySQL Connector/J Version 5.0 oder höher (von http://dev.mysql.com/downloads/connector/j/) muss installiert und über den CLASSPATH zugänglich sein.
Die javax.management
-Klassen für die
JMX-Version 1.2.1, die in folgenden Anwendungsservern
vorhanden sind:
JBoss – 4.0rc1 oder höher.
Apache Tomcat – 5.0 oder höher.
Die JMX-Referenzimplementierung Version 1.2.1 von Sun (von http://java.sun.com/products/JavaManagement/).
JUnit 3.8.1 (von http://www.junit.org/).
Wenn Sie von der Quelle kompilieren, gelten zusätzlich zu den obigen Anforderungen folgende:
Ant in der Version 1.5 oder höher (von http://ant.apache.org/).
Die Tests versuchen, MySQL auf Port 3336 zu starten. Wenn Sie MySQL bereits ausführen, kann dies Konflikte verursachen. Das ist jedoch recht unwahrscheinlich, da der Standardport für MySQL 3306 ist. Sie können allerdings die Java-Eigenschaft "c-mxj_test_port" auch auf einen anderen Port Ihrer Wahl einstellen. Alternativ können Sie auch beim Starten alle noch laufenden MySQL-Instanzen auf dem Zielrechner herunterfahren.
Nach Voreinstellung unterdrücken die Tests die Konsolenausgabe. Wenn Sie ausführliche Meldungen haben möchten, setzen Sie die Java-Eigenschaft "c-mxj_test_silent" auf "false".
Um die JUnit-Testsuite auszuführen, muss der $CLASSPATH Folgendes enthalten:
JUnit
JMX
Connector/J
MySQL Connector/MXJ
Fehlt connector-mxj.jar
in Ihrem
Download, extrahieren Sie bitte das MySQL
Connector/MXJ-Quellarchiv.
cd mysqldjmx ant dist
Dann fügen Sie dem CLASSPATH
$TEMP/cmxj/stage/connector-mxj/connector-mxj.jar
hinzu.
Wenn Sie junit
haben, führen Sie die
JUnit-Tests durch. Geben Sie hierzu auf der Kommandozeile
Folgendes ein:
java junit.textui.TestRunner com.mysql.management.AllTestsSuite
Es müsste in etwa folgende Ausgabe erscheinen:
......................................... ......................................... .......... Time: 259.438 OK (101 tests)
Die Tests laufen gegen Ende etwas langsam, fassen Sie sich also in Geduld.
Ein Feature des MySQL Connector/J-JDBC-Treibers ist seine Fähigkeit, eine Verbindung mit einer eingebetteten Connector/MXJ-Instanz durch das Schlüsselwort mxj im JDBC-Verbindungs-String einzurichten.
Das folgende Beispiel ist ein Programm, das eine Verbindung aufbaut, eine Anfrage ausführt und die Ergebnisse an System.out ausgibt. Die MySQL-Datenbank wird im Rahmen des Verbindungsprozesses gestartet und im finally-Block heruntergefahren.
Diese Datei liegt im Connector/MXJ-Package unter
src/ConnectorMXJUrlTestExample.java
.
import java.io.File; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; import com.mysql.management.driverlaunched.ServerLauncherSocketFactory; public class ConnectorMXJUrlTestExample { public static String DRIVER = "com.mysql.jdbc.Driver"; public static String JAVA_IO_TMPDIR = "java.io.tmpdir"; public static void main(String[] args) throws Exception { File ourAppDir = new File(System.getProperty(JAVA_IO_TMPDIR)); File databaseDir = new File(ourAppDir, "test-mxj"); int port = 3336; String url = "jdbc:mysql:mxj://localhost:" + port + "/test" + "?" + "server.basedir=" + databaseDir; System.out.println(url); String userName = "root"; String password = ""; Class.forName(DRIVER); Connection conn = null; try { conn = DriverManager.getConnection(url, userName, password); printQueryResults(conn, "SELECT VERSION()"); } finally { try { if (conn != null) conn.close(); } catch (Exception e) { e.printStackTrace(); } ServerLauncherSocketFactory.shutdown(databaseDir, null); } } public static void printQueryResults(Connection conn, String SQLquery) throws Exception { Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(SQLquery); int columns = rs.getMetaData().getColumnCount(); System.out.println("------------------------"); System.out.println(); while (rs.next()) { for (int i = 1; i <= columns; i++) { System.out.println(rs.getString(i)); } System.out.println(); } rs.close(); stmt.close(); System.out.println("------------------------"); System.out.flush(); Thread.sleep(100); // wait for System.out to finish flush } }
Um dieses Programm auszuführen, vergewissern Sie sich zuerst, dass connector-mxj.jar und Connector/J im CLASSPATH liegen, und geben dann Folgendes ein:
java ConnectorMXJTestExample
Wenn Sie eine Java-Anwendung haben und eine MySQL-Datenbank darin „einbetten“ möchten, benutzen Sie die Klasse com.mysql.management.MysqldResource. Diese Klasse instanziieren Sie entweder mit dem (parameterlosen) Standardkonstruktor oder, indem Sie ein java.io.File-Objekt übergeben, welches das Verzeichnis darstellt, in das Sie den Server "entpacken" möchten. Sie können sie auch mit Ausgabeströmen zu "stdout" und "stderr" für die Protokollierung instanziieren.
Sobald das Datenbankobjekt erzeugt ist, ist es in der Lage, eine java.util.Map mit den für die Plattform und verwendete MySQL-Version passenden Serveroptionen anzuzeigen.
Die MysqldResource versetzt Sie in die Lage, MySQL mit einer von Ihnen gelieferten java.util.Map von Serveroptionen zu "starten" und die Datenbank "herunterzufahren". Das folgende Beispiel zeigt in vereinfachter Form, wie MySQL mit reinen Java-Objekten in eine Anwendung eingebettet wird.
Diese Datei liegt im Connector/MXJ-Package unter dem Namen
src/ConnectorMXJObjectTestExample.java
vor.
import java.io.File; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; import java.util.HashMap; import java.util.Map; import com.mysql.management.MysqldResource; public class ConnectorMXJObjectTestExample { public static String DRIVER = "com.mysql.jdbc.Driver"; public static String JAVA_IO_TMPDIR = "java.io.tmpdir"; public static void main(String[] args) throws Exception { File ourAppDir = new File(System.getProperty(JAVA_IO_TMPDIR)); File databaseDir = new File(ourAppDir, "mysql-mxj"); int port = 3336; MysqldResource mysqldResource = startDatabase(databaseDir, port); String userName = "root"; String password = ""; Class.forName(DRIVER); Connection conn = null; try { String url = "jdbc:mysql://localhost:" + port + "/test"; conn = DriverManager.getConnection(url, userName, password); printQueryResults(conn, "SELECT VERSION()"); } finally { try { if (conn != null) { conn.close(); } } catch (Exception e) { e.printStackTrace(); } try { mysqldResource.shutdown(); } catch (Exception e) { e.printStackTrace(); } } } public static MysqldResource startDatabase(File databaseDir, int port) { MysqldResource mysqldResource = new MysqldResource(databaseDir); Map database_options = new HashMap(); database_options.put("port", Integer.toString(port)); mysqldResource.start("test-mysqld-thread", database_options); if (!mysqldResource.isRunning()) { throw new RuntimeException("MySQL did not start."); } System.out.println("MySQL is running."); return mysqldResource; } public static void printQueryResults(Connection conn, String SQLquery) throws Exception { Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(SQLquery); int columns = rs.getMetaData().getColumnCount(); System.out.println("------------------------"); System.out.println(); while (rs.next()) { for (int i = 1; i <= columns; i++) { System.out.println(rs.getString(i)); } System.out.println(); } rs.close(); stmt.close(); System.out.println("------------------------"); System.out.flush(); Thread.sleep(100); // wait for System.out to finish flush } }
Für eine MySQL-Datenbank sind natürlich viele Optionen einzustellen. Diese können Sie im JDBC-Verbindungs-String angeben, indem Sie einfach vor jede Serveroption das Präfix ''server.'' setzen. In den folgenden Beispielen setzen wir zwei Treiber- und zwei Serverparameter:
String url = "jdbc:mysql://" + hostColonPort + "/" + "?" + "cacheServerConfiguration=true" + "&" + "useLocalSessionState=true" + "&" + "server.basedir=/opt/myapp/db" + "&" + "server.datadir=/mnt/bigdisk/myapp/data";
Die Klasse MysqldResource
kennt drei
verschiedene Konstruktorformen:
public MysqldResource(File baseDir, File dataDir,
String mysqlVersionString, PrintStream out, PrintStream
err, Utils util)
Dieser detaillierteste Konstruktor stellt das Basisverzeichnis und das Data Directory ein, wählt einen Server anhand seines Versions-Strings aus und stellt die Standardausgabe, das Standardfehlerlog und die MySQL-Utilities-Klasse ein.
public MysqldResource(File baseDir, File dataDir,
String mysqlVersionString, PrintStream out, PrintStream
err)
Dieser Konstruktor stellt das Basisverzeichnis und das Data Directory ein, wählt einen Server anhand seines Versions-Strings aus und stellt die Standardausgabe und das Standardfehlerlog ein.
public MysqldResource(File baseDir, File dataDir,
String mysqlVersionString)
Dieser Konstruktor stellt das Basisverzeichnis und das Data Directory ein und wählt einen Server anhand seines Versions-Strings aus. Die Standardausgabe und das Standardfehlerlog werden in System.out und System.err geschrieben.
public MysqldResource(File baseDir, File dataDir)
Dieser Konstruktor stellt das Basisverzeichnis und das Data Directory ein und wählt die Standard-MySQL-Version aus. Die Standardausgabe und das Standardfehlerlog werden in System.out und System.err geschrieben.
public MysqldResource(File baseDir);
Dieser Konstruktor erlaubt die Einstellung eines "basedir" für die MySQL-Dateien. Die Standardausgabe und das Standardfehlerlog werden in System.out und System.err geschrieben.
public MysqldResource();
Das Basisverzeichnis ist auf java.io.tempdir voreingestellt. Die Standardausgabe und das Standardfehlerlog werden in System.out und System.err geschrieben.
Die MysqldResource-API kennt folgende Methoden:
void start(String threadName, Map
mysqldArgs);
Lädt und startet MySQL. Der String "threadName" benennt den Thread, der die MySQL-Kommandozeile ausführt. Die Map enthält die an die Kommandozeile zu übergebenden Argumente und ihre Werte.
void shutdown();
Fährt die vom MysqldResource-Objekt verwaltete MySQL-Instanz herunter.
Map getServerOptions();
Gibt eine Map mit allen Optionen und ihren aktuellen Optionen zurück, die der MySQL-Datenbank zur Verfügung stehen (oder mit den Standardoptionen, wenn die Datenbank nicht läuft).
boolean isRunning();
Gibt true zurück, wenn die MySQL-Datenbank läuft.
boolean isReadyForConnections();
Gibt true zurück, wenn die Datenbank meldet, dass sie für Verbindungen zur Verfügung steht.
void setKillDelay(int millis);
Das Standard-„Kill Delay“ beträgt 30 Sekunden. Dies ist die Zeit, die zwischen der Shutdown-Anforderung und einem „force kill“ vergeht, wenn die Datenbank nicht selbst herunterfährt.
void addCompletionListenser(Runnable listener);
Ermöglicht es, Anwendungen zu benachrichtigen, wenn der Serverprozess fertig ist. Jeder ''Listener'' wird in seinem eigenen Thread abgeschlossen.
String getVersion();
Gibt die MySQL-Version zurück.
void setVersion(int MajorVersion, int
minorVersion, int patchLevel);
In der Standarddistribution ist nur eine einzige MySQL-Version enthalten. Es ist jedoch auch möglich, mehrere Versionen beizufügen und anzugeben, welche davon benutzt werden soll.
Dieser Abschnitt enthält Hinweise und Tipps zur Verwendung von Connector/MXJ in Ihren Anwendungen.
Wenn Sie ein eigenes Connector/MXJ-Package schnüren wollen, das
eine bestimmte mysqld
-Version oder Plattform
enthält, dann müssen Sie die Datei
connector-mxj.jar
extrahieren und neu
erstellen.
Als Erstes legen Sie ein neues Verzeichnis an, in welches Sie
die connector-mxj.jar
-Datei extrahieren:
shell> mkdir custom-mxj shell> cd custom-mxj shell> jar -xf connector-mxj.jar shell> ls 5-0-22/ ConnectorMXJObjectTestExample.class ConnectorMXJUrlTestExample.class META-INF/ TestDb.class com/ kill.exe
Das MySQL-Versionsverzeichnis, im obigen Beispiel
5-0-22
, enthält alle Dateien, die notwendig
sind, um bei der Ausführung von Connector/MXJ eine
MySQL-Instanz zu erzeugen. Alle Dateien in diesem Verzeichnis
sind für jede Version von MySQL notwendig, die Sie einbetten
möchten. Achten Sie bitte auch auf das Format der
Versionsnummer, das Bindestriche statt Punkte enthält, um die
Einzelbestandteile der Versionsnummer abzugrenzen.
In dem versionsspezifischen Verzeichnis liegen
plattformspezifische Verzeichnisse sowie die von MySQL für die
diversen Plattformen benötigten Archive des
data
- und
share
-Verzeichnisses. Hier sehen Sie zum
Beispiel das Listing des standardmäßigen
Connector/MXJ-Packages:
shell>> ls Linux-i386/ META-INF/ Mac_OS_X-ppc/ SunOS-sparc/ Win-x86/ com/ data_dir.jar share_dir.jar win_share_dir.jar
Plattformspezifische Verzeichnisse werden nach Betriebssystem
und Plattform aufgeführt. So liegt zum Beispiel die
mysqld
für Mac OS X PowerPC im Verzeichnis
Mac_OS_X-ppc
. Sie können Verzeichnisse,
die Sie nicht benötigen, löschen und neue Verzeichnisse für
weitere Plattformen hinzufügen.
Um eine plattformspezifische mysqld
hinzuzufügen, erstellen Sie ein neues Verzeichnis mit dem für
Ihr Betriebssystem/Ihre Plattform passenden Namen. Sie könnten
zum Beispiel für Mac OS X/Intel das Verzeichnis
Mac_OS_X-i386
einrichten.
Auf Unix-Systemen können Sie die Plattform mit
uname
ermitteln:
shell> uname -p i386
Nun müssen Sie mysqld
für die MySQL-Version
und Plattform in das neue Verzeichnis kompilieren, die Sie in
Ihr eigenes connector-mxj.jar
-Package
aufnehmen möchten.
Legen Sie in dem soeben erstellten BS/Plattform-Verzeichnis eine
Datei namens version.txt
an, die den
Versions-String und Pfad der mysqld-Binary enthält, zum
Beispiel:
mysql-5.0.22-osx10.3-i386/bin/mysqld
Nun können Sie die Dateiconnector-mxj.jar
mit der frisch hinzugefügten mysqld
-Binary
neu erstellen:
shell> cd custom-mxj shell> jar -cf ../connector-mxj.jar *
Testen können Sie dieses Ppackage wie in Abschnitt 25.4.2.3, „Schnellstart mit Connector/MXJ“, beschrieben.
Um eine vorkonfigurierte und mit Daten bevölkerte Datenbank in
Ihre Connector/MXJ-JAR-Datei aufzunehmen, müssen Sie eine
eigene data_dir.jar
-Datei anlegen, wie sie
in der Haupt-connector-mxj.jar
-Datei
enthalten ist:
Zuerst extrahieren Sie
connector-mxj.jar
wie im vorigen
Abschnitt beschrieben (siehe
Abschnitt 25.4.5.1, „Ein eigenes Connector/MXJ-Package anlegen“).
Erstellen Sie in einer vorhandenen MySQL-Instanz (einschließlich Connector/MXJ-Instanzen) Ihre Datenbank und laden Sie Daten hinein. Die Formate der Datendateien sind plattformunabhängig.
Fahren Sie die MySQL-Instanz herunter.
Erstellen Sie aus dem Data Directory und den Datenbanken,
die Sie in Ihr Connector/MXJ-Package einbinden möchten,
eine JAR-Datei. Diese sollte zusätzlich zu den spezifischen
Datenbanken, die Sie aufnehmen möchten, auch die
mysql
-Datenbank mit den Daten zur
Benutzerauthentifizierung enthalten. Folgender Befehl legt
beispielsweise ein JAR mit den Datenbanken
mysql
und mxjtest
an:
shell> jar -cf ../data_dir.jar mysql mxjtest
Kopieren Sie die data_dir.jar
-Datei in
das extrahierte
connector-mxj.jar
-Verzeichnis und
erstellen Sie dann ein Archiv für
connector-mxj.jar
.
Wenn Sie Datenbanken mit der InnoDB-Engine anlegen, müssen Sie
die Dateien ibdata.*
und
ib_logfile.*
in das
data_dir.jar
-Archiv aufnehmen.
Als JMX MBean erfordert MySQL Connector/MXJ einen JMX v1.2-konformen MBean-Container wie etwa JBoss in der Version 4. Die MBean stellt mithilfe der JMX-Management-APIs die für die gegebene Plattform geeigneten Parameter ein (und ermöglicht auch Ihnen, die Parameter zu setzen).
Wenn Sie nicht die SUN-Referenzimplementierung der JMX-Bibliotheken verwenden, sollten Sie diesen Abschnitt übergehen, und wenn Sie JBoss verwenden, überspringen Sie auch den nachfolgenden Abschnitt.
Betrachten wir nun die MysqldDynamicMBean in einem JMX-Agenten
in Aktion. Im
com.mysql.management.jmx.sunri
-Package
befindet sich ein speziell angepasster JMX-Agent mit zwei
MBeans:
MysqldDynamicMBean und
einem com.sun.jdmk.comm.HtmlAdaptorServer, der eine Webschnittstelle zur Manipulation der Beans in einem JMX-Agent bereitstellt.
Wenn dieser sehr einfache Agent gestartet wird, kann eine MySQL-Datenbank über einen Webbrowser gestartet und angehalten werden.
Beenden Sie den Plattformtest wie oben.
Aktuelle Versionen von JDK, JUnit, Connector/J, MySQL Connector/MXJ
Dieser Abschnitt erfordert die SUN-Referenzimplementierung von JMX.
PATH
, JAVA_HOME
,
ANT_HOME
,
CLASSPATH
Wenn Sie nicht von der Quelle installieren, gehen Sie zum nächsten Abschnitt weiter.
Rebuild mit "sunri.present"
ant -Dsunri.present=true dist re-run tests: java junit.textui.TestRunner com.mysql.management.AllTestsSuite
Starten Sie den Test-Agenten auf der Kommandozeile:
java com.mysql.management.jmx.sunri.MysqldTestAgentSunHtmlAdaptor &
... von einem Browser:
http://localhost:9092/
... unter MysqldAgent:
select "name=mysqld"
Beobachten Sie die MBean-View.
Scrollen Sie den Bildschirm nach unten und klicken Sie auf
.
Klicken Sie auf Back to MBean View
.
Scrollen Sie den Bildschirm nach unten und klicken Sie auf
.Halten Sie den Java-Prozess an, der den Test-Agent ausführt (jmx server).
Wenn Sie sich darauf verlassen können, dass MBean auf der Plattform funktioniert, können Sie die MBean in einem normalen JMX Agent einsetzen. Die folgenden Anleitungen beziehen sich auf eine Installation mit JBoss.
Achten Sie auf eine aktuelle Version des Java Development Kits (v1.4.x), siehe oben.
Vergewissern Sie sich, dass JAVA_HOME
gesetzt ist (JBoss benötigt
JAVA_HOME
).
Sorgen Sie dafür, dass JAVA_HOME/bin
im PATH
liegt (Sie müssen NICHT den
CLASSPATH einstellen und benötigen auch keines der JARs
aus den vorherigen Tests).
Achten Sie auf eine aktuelle Version von JBoss (v4.0RC1 oder höher).
http://www.jboss.org/index.html select "Downloads" select "jboss-4.0.zip" pick a mirror unzip ~/dload/jboss-4.0.zip create a JBOSS_HOME environment variable set to the unzipped directory unix only: cd $JBOSS_HOME/bin chmod +x *.sh
Kopieren Sie connector-mxj.jar
in
$JBOSS_HOME/server/default/lib
.
Kopieren Sie
mysql-connector-java-3.1.4-beta-bin.jar
in $JBOSS_HOME/server/default/lib
.
Legen Sie ein mxjtest.war
-Verzeichnis
in $JBOSS_HOME/server/default/deploy
an.
Kopieren Sie index.jsp
in
$JBOSS_HOME/server/default/deploy/mxjtest.war
.
Legen Sie eine mysqld-service.xml
-Datei
in $JBOSS_HOME/server/default/deploy
an.
<?xml version="1.0" encoding="UTF-8"?> <server> <mbean code="com.mysql.management.jmx.jboss.JBossMysqldDynamicMBean" name="mysql:type=service,name=mysqld"> <attribute name="datadir">/tmp/xxx_data_xxx</attribute> <attribute name="autostart">true</attribute> </mbean> </server>
Starten Sie jboss:
auf Unix: $JBOSS_HOME/bin/run.sh
auf Windows: %JBOSS_HOME%\bin\run.bat
Wappnen Sie sich: JBoss schickt jede Menge Ausgabe auf den Bildschirm.
Wenn JBoss keine Ausgabe mehr an den Bildschirm sendet,
öffnen Sie einen Browser auf
http://localhost:8080/jmx-console
.
Scrollen Sie auf der Seite nach unten zum Abschnitt
mysql
und wählen Sie den
mysqld
-Link aus.
Schauen Sie auf die Seite JMX MBean View. MySQL müsste bereits laufen.
(Wenn "autostart=true" eingestellt ist, können Sie diesen
Schritt übergehen.) Scrollen Sie auf dem Bildschirm nach
unten. Sie können auf Operation completed successfully without a return
value
zu sagen. Klicken Sie auf Back to
MBean View
.
Um sich zu vergewissern, dass MySQL läuft, öffnen Sie
einen Browser auf
http://localhost:8080/mxjtest/
. Sie
müssten jetzt sehen können, dass
SELECT 1
folgendes Ergebnis zurückgegeben hat:
1
Mit der Benutzerführung von
$JBOSS_HOME/server/default/deploy/mxjtest.war/index.jsp
können Sie MySQL in Ihrer Webanwendung einsetzen. Eine
test
-Datenbank und ein
root
-User (ohne Passwort) stehen bereits
zum Herumexperimentieren bereit. Versuchen Sie, eine Tabelle
anzulegen, einige Zeilen einzufügen und SELECT-Operationen
darauf auszuführen.
Fahren Sie MySQL herunter. MySQL wird automatisch
angehalten, wenn JBoss herunterfährt. Oder scrollen Sie im
Browser die MBean View nach unten und klicken Sie auf den
Button Operation completed
successfully without a return value
angezeigt.
ps
oder der
Taskmanager
werden Ihnen bestätigen,
dass MySQL nicht mehr ausgeführt wird.
Seit der Beta-Version 1.0.6 kann die MBean die MySQL-Datenbank beim Hochfahren starten. Mithilfe der Life-Cycle-Erweiterungsmethoden von JBoss haben wir außerdem dafür gesorgt, dass MySQL mit JBoss gemeinsam herunterfährt.
Es gibt viele Möglichkeiten, Support für Connector/MXJ zu bekommen. Bitte fragen Sie die Connector/MXJ-Community um Hilfe, ehe Sie einen potenziellen Bug oder ein Problem melden. Siehe Abschnitt 25.4.6.1, „Support von der Connector/MXJ-Community“.
MySQL AB unterstützt die Benutzer-Community mit mehreren Mailinglisten und Webforen.
Hilfe und Support finden Sie in der MySQL- und Java-Mailingliste.
Wie Sie MySQL-Mailinglisten abonnieren oder die Listenarchive durchsuchen können, erfahren Sie unter http://lists.mysql.com/. Siehe Abschnitt 1.7.1, „Die MySQL-Mailinglisten“.
Community-Support von erfahrenen Benutzern erhalten Sie auch im MyODBC-Forum . Auch in den anderen MySQL-Foren unter http://forums.mysql.com wird Ihnen geholfen. Siehe Abschnitt 1.7.2, „MySQL-Community-Support in den MySQL-Foren“.
Wenn Sie Probleme mit Connector/MXJ haben, wenden Sie sich bitte zuerst an die Connector/MXJ-Community, siehe Abschnitt 25.4.6.1, „Support von der Connector/MXJ-Community“.
Wenn Sie ein Problem melden, geben Sie uns bitte per E-Mail folgende Informationen:
Betriebssystem und Version
Connector/MXJ-Version
MySQL Server-Version
Kopien von Fehlermeldungen oder anderen unerwarteten Ausgaben
einfaches, reproduzierbares Beispiel
Achtung
: Je mehr Informationen
Sie uns geben können, umso wahrscheinlicher ist es, dass wir
das Problem beheben können.
Wenn Sie der Auffassung sind, dass es sich um einen Bug handelt, senden Sie uns einen Bugreport über http://bugs.mysql.com/.
Inhaltsverzeichnis
In diesem Kapitel wird vieles beschrieben, was Sie wissen müssen,
wenn Sie am Code von MySQL arbeiten möchten. Wenn Sie selbst zu
der Entwicklung von MySQL beitragen wollen, Zugriff auf den
allerneuesten Entwicklungsstand des Codes zwischen zwei Versionen
benötigen oder einfach nur die Entwicklung mitverfolgen möchten,
befolgen Sie bitte die Anleitungen unter
Abschnitt 2.8.3, „Installation vom Entwicklungs-Source-Tree“. Wenn Sie sich für die
Interna von MySQL interessieren, sollten Sie auch unsere
internals
-Mailingliste abonnieren. Auf dieser
Liste herrscht relativ wenig Verkehr. Wie Sie sie abonnieren
können, erfahren Sie unter Abschnitt 1.7.1, „Die MySQL-Mailinglisten“. Alle
Entwickler bei MySQL AB sind auf der
internals
-List und wir helfen gerne auch
anderen weiter, die am MySQL-Code arbeiten. Bitte nutzen Sie diese
Liste, um Fragen über den Code zu stellen und Patches zu
übermitteln, falls Sie gerne selbst zu dem MySQL-Projekt
beitragen möchten!
Der MySQL Server erzeugt folgende Threads:
Der TCP/IP-Verbindungs-Thread behandelt alle Verbindungsanfragen und erzeugt für jede Verbindung einen neuen dedizierten Thread zur Authentifizierung und Verarbeitung von SQL-Anfragen.
Auf Windows NT gibt es einen Handler-Thread für die Named Pipe, der für Named-Pipe-Verbindungsanfragen dieselbe Arbeit wie der TCP/IP-Verbindungs-Thread leistet.
Der Signal-Thread kümmert sich um Signale und normalerweise
auch um Alarmsignale und
process_alarm()
-Aufrufe, um Verbindungen,
die zu lange ungenutzt waren, per Timeout zu beenden.
Wenn mysqld mit
-DUSE_ALARM_THREAD
kompiliert wird, wird
ein spezieller Thread für den Umgang mit Alarmen erzeugt.
Das wird aber nur bei Systemen getan, auf denen es Probleme
mit sigwait()
gibt, oder wenn Sie den
Code der Funktion thr_alarm()
in Ihrer
Anwendung ohne einen dedizierten Thread zur Signalbehandlung
einsetzen möchten.
Wenn die Option
--flush_time=
gesetzt ist, wird ein dedizierter Thread erzeugt, der in den
gegebenen Abständen alle Tabellen auf die Platte
zurückschreibt.
val
Jede Verbindung besitzt ihren eigenen Thread.
Jede Tabelle, für die INSERT DELAYED
gilt, bekommt ihren eigenen Thread.
Wenn Sie die Option --master-host
setzen,
wird ein Thread für die Slave-Replikation gestartet, um
Updates vom Master zu lesen und anzuwenden.
Der Befehl mysqladmin processlist zeigt nur
den Verbindungs-Thread, den INSERT
DELAYED
-Thread und den Replikations-Thread an.
Mit dem in den Unix-Quell- und Binärdistributionen enthaltenen Testsystem können Nutzer und Entwickler Regressionstests mit dem MySQL-Code durchführen. Diese Tests kann man auf Unix, aber zurzeit noch nicht in einer nativen Windows-Umgebung laufen lassen.
Die momentan vorhandenen Testfälle testen nicht alles in MySQL, sollten aber die offensichtlichsten Fehler im Code zur SQL-Verarbeitung sowie OS/Bibliothek-Probleme finden, und leisten ziemlich gründliche Arbeit beim Testen von Replikation. Unser Ziel ist es, letztlich 100 % des Codes mit unseren Tests abzudecken. Wir freuen uns über Beiträge zu unserer Testreihe. Insbesondere können Sie uns Tests für systemkritische Funktionalitäten schicken, um zu gewährleisten, dass alle zukünftigen MySQL-Releases auch mit Ihren Anwendungen harmonieren.
Das Testsystem besteht aus einem Testsprachen-Interpreter
(mysqltest), einem Shell-Skript, um alle
Tests auszuführen (mysql-test-run), den
eigentlichen Testfällen, die in einer speziellen Testsprache
geschrieben sind, sowie aus den erwarteten Ergebnissen. Um die
Testreihe nach einem Build auf Ihrem System auszuführen,
geben Sie make test oder
mysql-test/mysql-test-run im
Wurzelverzeichnis des Quellcodes ein. Wenn Sie eine
Binärdistribution installiert haben, wechseln Sie in das
Wurzelverzeichnis der Installation (beispielsweise
/usr/local/mysql
) und führen
scripts/mysql-test-run aus. Alle Tests
sollten erfolgreich laufen. Ist das nicht der Fall, müssen
Sie die Gründe herausfinden und einen Bugreport übermitteln,
wenn es sich um einen Fehler in MySQL handelt. Siehe
Abschnitt 26.1.2.3, „Berichten von Bugs in der MySQL-Test-Suite“.
Wenn eine Instanz von mysqld auf dem
Computer läuft, auf dem Sie die Testreihe ausführen
möchten, müssen Sie diese nur dann herunterfahren, wenn sie
den Port 9306
oder 9307
belegt. Wenn einer dieser Ports nicht frei ist, müssen Sie in
mysql-test-run die Werte des Master- oder
Slave-Ports umändern und einen Port einsetzen, der frei ist.
Sie können einen einzelnen Testfall mit mysql-test/mysql-test-run test_name ausführen.
Wenn ein Test scheitert, führen Sie
mysql-test-run mit der Option
--force
aus, um zu prüfen, ob auch andere
Tests fehlschlagen.
Mit der Sprache mysqltest können Sie auch Ihre eigenen Testfälle schreiben. Allerdings haben wir leider die Dokumentation dieser Sprache noch nicht ganz fertig gestellt. Sie können sich jedoch unsere aktuellen Testfälle anschauen und als Beispiele heranziehen. Die folgenden Hinweise müssten Ihnen bei den ersten Schritten eine Hilfe sein:
Sie finden die Tests in
mysql-test/t/*.test
.
Ein Testfall besteht aus Anweisungen, die mit
;
abgeschlossen werden, und ähnelt der
Eingabe für den
mysql-Kommandozeilen-Client. Eine
Anweisung ist standardmäßig eine SQL-Anweisung, die an
den MySQL Server gesandt wird, es sei denn, sie wird als
interner Befehl erkannt (wie beispielsweise
sleep).
Vor allen Anfragen, die Ergebnisse produzieren, wie
beispielsweise SELECT
,
SHOW
oder EXPLAIN
,
muss ein @/path/to/result/file
stehen. Diese Datei muss die erwarteten Ergebnisse
enthalten. Ein einfaches Mittel, um die Ergebnisdatei zu
generieren, besteht darin, mysqltest -r <
t/test-case-name.test im Verzeichnis
mysql-test
auszuführen und dann die
generierten Ergebnisdateien wenn nötig zu bearbeiten, um
sie an die erwartete Ausgabe anzupassen. In diesem Fall
müssen Sie sehr genau darauf achten, keine unsichtbaren
Zeichen zu löschen oder hinzuzufügen. Sie dürfen nur
den Text ändern oder Zeilen löschen. Wenn Sie eine Zeile
einfügen müssen, achten Sie darauf, dass die Felder
durch einen Tabulator getrennt werden, und setzen Sie auch
am Ende einen Tabulator. Mit od -c
können Sie sich vergewissern, dass Ihr Editor bei der
Bearbeitung keinen Unsinn gemacht hat. Wir hoffen, dass
Sie niemals die Ausgabe von mysqltest
-r bearbeiten müssen, da dies nur nötig wird,
wenn Sie einen Fehler finden.
Um Ihr System wie unseres einzurichten, legen Sie die
Ergebnisdateien in das Verzeichnis
mysql-test/r
und nennen sie
test_name.result
. Wenn der Test mehr
als ein Ergebnis produziert, verwenden Sie die Namen
test_name.a.result
,
test_name.b.result
und so weiter.
Wenn eine Anweisung einen Fehler zurückgibt, sollten Sie
diesen mit --error error-number
auf der
Zeile vor dieser Anweisung angeben. Die Fehlernummer kann
auch eine kommagetrennte Liste von Fehlernummern sein.
Wenn Sie einen Replikationstestfall schreiben, setzen Sie
in die erste Zeile der Testdatei den Text source
include/master-slave.inc;
. Mit
connection master;
und
connection slave;
schalten Sie zwischen
Master und Slave um. Wenn Sie auf einer anderen Verbindung
arbeiten müssen, können Sie für den Master
connection master1;
und für den Slave
connection slave1;
eingeben.
Falls Sie eine Schleifenverarbeitung ausführen müssen, können Sie Folgendes tun:
let $1=1000; while ($1) { # Hier Anfragen einfügen dec $1; }
Mit sleep schläft das System zwischen zwei Anfragen. Da in diesem Befehl auch Sekundenbruchteile eingestellt werden können, bedeutet beispielsweise sleep 1.3;, dass das System 1,3 Sekunden schläft.
Um den Slave mit Zusatzoptionen für den Testfall
auszuführen, setzen Sie die Optionen in einem
Kommandozeilenformat in die Datei
mysql-test/t/test_name-slave.opt
bzw.
für den Master in die Datei
mysql-test/t/test_name-master.opt
.
Wenn Sie Fragen zu der Testreihe haben oder selbst einen
Test beisteuern möchten, schicken Sie eine E-Mail an die
MySQL-Mailingliste internals
(siehe
Abschnitt 1.7.1, „Die MySQL-Mailinglisten“). Da diese Liste keine
Anhänge akzeptiert, laden Sie alle relevanten Dateien per
FTP auf folgende Adresse hoch:
ftp://ftp.mysql.com/pub/mysql/upload/.
Wenn Ihre MySQL-Version die Testreihe nicht besteht, tun Sie Folgendes:
Senden Sie uns bitte erst dann einen Bugreport, wenn Sie so viel wie möglich über das Problem herausgefunden haben! Schauen Sie bitte auch in die Anleitungen unter Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“.
Speichern Sie die Ausgabe von
mysql-test-run sowie die Inhalte
sämtlicher .reject
-Dateien im
Verzeichnis mysql-test/r
.
Wenn ein Test in der Testreihe fehlschlägt, überprüfen Sie, ob der Test auch dann scheitert, wenn er isoliert ausgeführt wird:
cd mysql-test mysql-test-run --local test-name
Wenn dies scheitert, sollten Sie MySQL mit der Option
--with-debug
konfigurieren und
mysql-test-run mit der Option
--debug
ausführen. Wenn auch das
fehlschlägt, senden Sie die Trace-Datei
var/tmp/master.trace
an
ftp://ftp.mysql.com/pub/mysql/upload/,
damit wir sie untersuchen können. Bitte senden Sie uns
außerdem eine vollständige Beschreibung Ihres Systems,
die Version Ihrer mysqld-Binary sowie
Informationen, wie Sie sie kompiliert haben.
Lassen Sie mysql-test-run mit der
--force
-Option laufen, um zu erfahren, ob
auch ein anderer Test scheitert.
Wenn Sie MySQL selbst kompiliert haben, schlagen Sie in unserem Handbuch nach, wie MySQL auf Ihrer Plattform kompiliert wird, oder – noch besser – verwenden Sie eine der Binaries, die wir für Sie bereits vokompiliert haben (siehe http://dev.mysql.com/downloads/). Alle unsere Standardbinaries dürften die Testreihe überstehen!
Wenn Sie eine Fehlermeldung wie Result length
mismatch
oder Result content
mismatch
bekommen, so bedeutet dies, dass die
Testausgabe nicht mit der erwarteten Ausgabe
übereinstimmt. Dies könnte ein Bug in MySQL sein oder
aber daran liegen, dass Ihre
mysqld-Version unter bestimmten
Umständen abweichende Ergebnisse bringt.
Die Ergebnisse von gescheiterten Tests werden in eine
Datei gespeichert, die genau wie die Ergebnisdatei heißt,
aber die Erweiterung .reject
hat. Wenn
Ihr Testfall scheitert, lassen Sie einen Diff-Befehl auf
den beiden Dateien laufen. Ist nicht zu erkennen, worin
sie sich unterscheiden, so untersuchen Sie beide mit
od -c
und vergleichen auch ihre
Längen.
Scheitert ein Test vollständig, suchen Sie in den
Logdateien im Verzeichnis
mysql-test/var/log
nach Gründen.
Haben Sie MySQL mit Debugging kompiliert, so können Sie
versuchen, mysql-test-run mit der
Option --gdb
und/oder
--debug
auszuführen. Siehe auch
Abschnitt E.1.2, „Trace-Dateien erzeugen“.
Wurde MySQL nicht mit Debugging kompiliert, so sollten Sie
dies nun nachholen. Dazu müssen Sie lediglich
configure mit den
--with-debug
-Optionen ausführen. Siehe
Abschnitt 2.8, „Installation der Quelldistribution“.
MySQL 5.1 und höher unterstützt eine Plug-In-API, mit der Serverkomponenten zur Laufzeit ge- oder entladen werden können, ohne den Server neu zu starten. Zurzeit unterstützt diese API die Erstellung von Volltext-Parser-Plug-Ins. Durch ein solches Plug-In lässt sich der eingebaute Volltext-Parser ersetzen oder verbessern. So kann beispielsweise ein Plug-In andere Regeln als der eingebaute Parser verwenden, um Text in Wörter zu parsen. Das kann nützlich sein, wenn Sie Text parsen möchten, der andere Merkmale hat, als sie der eingebaute Parser erwartet.
Die Plug-In-API soll Nachfolger der älteren Schnittstelle für benutzerdefinierte Funktionen (UDFs) sein. Im Endausbau wird sie auch eine API für die Erstellung von UDFs enthalten und die ältere, nicht als Plug-In geschriebene UDF-API ersetzen. Von da an wird es möglich sein, UDFs so zu überarbeiten, dass sie als Plug-In-UDFs benutzt werden können und somit auch von den besseren Sicherheits- und Versionierungsfähigkeiten der Plug-In-API profitieren. Im Anschluss daran wird der Support für die alte UDF-API auslaufen.
Die Plug-In-API benötigt die plugin
-Tabelle in
der mysql
-Datenbank. Diese Tabelle wird im
Installationsprozess von MySQL angelegt. Wenn Sie von einer
älteren Version auf MySQL 5.1 aufrüsten, erstellen Sie diese
Tabelle mit dem Befehl
mysql_fix_privilege_tables. Siehe
Abschnitt 5.6, „mysql_fix_privilege_tables — Upgrade von MySQL-Systemtabellen“.
In mancher Hinsicht ähnelt die Plug-In-API der älteren UDF-API, die sie ersetzen soll, aber sie bietet eine Reihe von Vorteilen gegenüber ihrer Vorläuferin:
Das Plug-In-Framework ist erweiterbar, sodass es verschiedene Arten von Plug-Ins aufnehmen kann.
Manche Aspekte hat die Plug-In-API mit allen Plug-Ins gemeinsam, aber sie gestattet darüber hinaus auch typspezifische Schnittstellenelemente, sodass unterschiedliche Arten von Plug-Ins erstellt werden können. Ein Plug-In, das einem bestimmten Zweck dient, kann somit die für seine Erfordernisse geeignetste Schnittstelle haben, anstatt sich an den Bedürfnissen eines anderen Plug-In-Typs zu orientieren.
Auch wenn zurzeit nur die Schnittstelle für Volltext-Parser-Plug-Ins implementiert ist, können noch andere hinzukommen, wie beispielsweise eine Schnittsstelle für UDF-Plug-Ins.
Zur Plug-In-API gehören auch Versionsinformationen.
Durch die Versionsinformationen der Plug-In-API kann sich eine Plug-In-Bibliothek sowie jedes in ihr enthaltene Plug-In selbst identifizieren, und zwar mithilfe der API-Version, die zur Erstellung der Bibliothek benutzt wurde. Wenn sich die API mit der Zeit ändert, ändern sich auch die Versionsnummern, aber der Server kann immer anhand der Versionsinformationen einer konkreten Plug-In-Bibliothek herausfinden, ob er die Plug-Ins dieser Bibliothek unterstützt.
Es gibt zwei Arten von Versionsnummern. Die erste ist die Version des allgemeinen Plug-In-Frameworks selbst. Jede Plug-In-Bibliothek enthält diese Art von Versionsnummer. Die zweite ist die Nummer des einzelnen Plug-Ins. Jeder spezifische Typ von Plug-In in einer Bibliothek hat für seine Schnittstelle eine Versionsnummer, sodass jedes Plug-In in einer Bibliothek eine typspezifische Versionsnummer besitzt. So hat beispielsweise eine Bibliothek, in der ein Volltext-Parser-Plug-In liegt, eine allgemeine Plug-In-API-Versionsnummer und das einzelne Plug-In hat seinerseits eine Versionsnummer, die für ebendiese Volltext-Plug-In-Schnittstelle spezifisch ist.
Die Sicherheit der Plug-Ins wurde gegenüber der alten UDF-Schnittstelle verbessert.
Die ältere Schnittstelle zur Erstellung von UDFs ohne Plug-In ermöglichte es, Bibliotheken aus jedem Verzeichnis zu laden, das der dynamische Linker des Systems durchsuchte, und die Symbole zur Identifikation der UDF-Bibliothek waren relativ unspezifisch. Die neueren Regeln sind strenger. Eine Plug-In-Bibliothek muss in einem speziellen dedizierten Verzeichnis installiert sein, dessen Speicherort vom Server kontrolliert wird und zur Laufzeit nicht geändert werden kann. Außerdem muss die Bibliothek bestimmte Symbole enthalten, die sie als Plug-In-Bibliothek kennzeichnen. Der Server wird nichts als Plug-In laden, das nicht als Plug-In gebaut wurde.
Die neuere Plug-In-Schnittstelle löst die Sicherheitsprobleme der älteren UDF-Schnittstelle. Wenn ein UDF-Plug-In-Typ implementiert wird, können Nicht-Plug-In-UDFs in das neue Framework überführt werden und die alte Schnittstelle kann auslaufen.
Die Plug-In-Implementierung besteht aus folgenden Komponenten:
Quelldateien (die angegebenen Speicherorte gelten für eine MySQL-Quelldistribution):
include/plugin.h
stellt die
öffentliche Plug-In-API zur Verfügung. Jeder, der eine
Plug-In-Bibliothek schreiben möchte, sollte sich diese
Datei anschauen.
sql/sql_plugin.h
und
sql/sql_plugin.cc
enthalten die interne
Plug-In-Implementierung. Diese Dateien müssen Verfasser von
Plug-Ins sich nicht anschauen. Nur wenn Sie mehr darüber
erfahren möchten, wie der Server mit Plug-Ins umgeht, sind
diese Dateien für Sie interessant.
Systemtabelle:
Die plugin
-Tabelle in der
mysql
-Datenbank listet alle installierten
Plug-Ins auf und ist für die Nutzung von Plug-Ins
erforderlich. Neuere MySQL-Versionen legen diese Tabelle bei
der Installation an. Wenn Sie von einer älteren Version als
MySQL 5.1 aufrüsten, sollten Sie mit
mysql_fix_privilege_tables Ihre
Systemtabellen aktualisieren und die
plugin
-Tabelle anlegen.
SQL-Anweisungen:
INSTALL PLUGIN
registriert ein Plug-In in
der plugin
-Tabelle und lädt den
Plug-In-Code.
UNINSTALL PLUGIN
deregistriert ein
Plug-In bei der plugin
-Tabelle und und
entlädt den Plug-In-Code.
Die WITH PARSER
-Klausel für die
Erstellung von Volltextindizes verbindet ein
Volltext-Parser-Plug-In mit einem gegebenen
FULLTEXT
-Index.
SHOW PLUGIN
zeigt Informationen über
bekannte Plug-Ins an. Die PLUGINS
-Tabelle
in INFORMATION_SCHEMA
liefert ebenfalls
Informationen über Plug-Ins.
Systemvariable:
plugin_dir
zeigt an, wo im Verzeichnis
alle Plug-Ins installiert werden müssen. Den Wert dieser
Variablen können Sie beim Serverstart mit der Option
--plugin_dir=
angeben.
path
MySQL verfügt über einen eingebauten Parser, der nach Voreinstellung für Volltextoperationen eingesetzt wird (Text parsen, der indiziert werden soll, oder einen Anfrage-String parsen, um die Suchbegriffe herauszufinden). In der Volltextverarbeitung bedeutet „Parsen“, dass Wörter aus einem Text oder Anfrage-String anhand von Regeln extrahiert werden, die definieren, aus welcher Zeichenfolge ein Wort besteht und wo die Wortgrenzen liegen.
Beim Parsen für Indizierungszwecke übergibt der Parser jedes Wort an den Server, und dieser fügt das Wort einem Volltextindex hinzu. Beim Parsen eines Anfrage-Strings übergibt der Parser ebenfalls jedes Wort an den Server, und dieser sammelt die Wörter, um sie für eine Suchoperation zusammenzustellen.
Die Parsing-Eigenschaften des eingebauten Volltext-Parsers
werden in Abschnitt 12.7, „MySQL-Volltextsuche“, beschrieben. Hierzu
gehören auch die Regeln, nach denen Wörter aus einem Text
herausgezogen werden. Der Parser wird von bestimmten
Systemvariablen wie ft_min_word_len
und
ft_max_word_len
beeinflusst, die kürzere
oder längere Wörter ausschließen können, und durch die Liste
der Stoppwörter (diese sind häufig vorkommende Wörter, die
übergangen werden).
Durch die Plug-In-API sind Sie in der Lage, einen eigenen Volltext-Parser zu verwenden und somit die Grundaufgaben eines Parsers unter Kontrolle zu haben. Ein Parser-Plug-In kann zwei Rollen spielen:
Es kann den eingebauten Parser ersetzen. In dieser Rolle liest das Plug-In die zu parsende Eingabe, zerlegt sie in Wörter und übergibt diese Wörter an den Server (entweder zum Indizieren oder zum Sammeln von Wörtern).
Sie könnten einen Parser auf diese Weise einsetzen, wenn Sie die Eingabe nach anderen Regeln als der eingebaute Parser in Wörter zerlegen möchten. Für den eingebauten Parser besteht beispielsweise der Text „case-sensitive“ aus zwei Wörtern, nämlich „case“ und „sensitive“, während eine Anwendung diesen Text möglicherweise als ein einziges Wort ansehen sollte.
Das Plug-In kann auch mit dem eingebauten Parser
zusammenarbeiten, indem es als Frontend für diesen dient.
In dieser Rolle extrahiert das Plug-In Text aus der Eingabe
und übergibt ihn an den Parser, der seinerseits den Text
nach seinen normalen Parsing-Regeln in Wörter zerlegt.
Diese Art von Parsing wird besonders von den Systemvariablen
ft_
und der
Stoppwörterliste beeinflusst.
xxx
Auf diese Weise könnten Sie einen Parser einsetzen, wenn
Sie beispielsweise PDF- oder XML-Dokumente oder
.doc
-Dateien indizieren müssen. Der
eingebaute Parser ist nicht für diese Arten von Dokumenten
gedacht, aber ein Plug-In-Parser kann Text aus diesen
Quellen extrahieren und an den eingebauten Parser
übergeben.
Ein Parser-Plug-In kann auch in beiden Rollen aktiv sein. Es kann Text aus einer Eingabe holen, die kein einfaches Textdokument ist (die Frontend-Rolle), und diesen Text auch in Wörter zerlegen (also den eingebauten Parser ersetzen).
Ein Volltext-Plug-In ist mit Volltextindizes indexweise
verbunden: Wenn Sie ein Parser-Plug-In installieren, wird es
deswegen noch nicht für Volltextoperationen benutzt, sondern
steht zunächst einmal nur zur Verfügung. Ein Volltext-Parser
kann dann beispielsweise in einer WITH
PARSER
-Klausel bei der Erstellung einzelner
FULLTEXT
-Indizes angegeben werden. Um einen
solchen Index gleichzeitig mit der Tabelle zu erstellen, tun Sie
Folgendes:
CREATE TABLE t ( doc CHAR(255), FULLTEXT INDEX (doc) WITH PARSER my_parser );
Oder Sie fügen den Index nach der Erstellung der Tabelle hinzu:
ALTER TABLE t ADD FULLTEXT INDEX (doc) WITH PARSER my_parser;
Um den Parser mit dem Index zu verbinden, müssen Sie lediglich
die WITH PARSER
-Klausel in die SQL-Anfrage
einfügen. Suchoperationen werden wie immer formuliert, ohne die
Anfragen in irgendeiner Weise zu ändern.
Wenn Sie ein Parser-Plug-In mit einem
FULLTEXT
-Index verbinden, ist dieses Plug-In
erforderlich, um den Index nutzen zu können. Wird es gelöscht,
wird jeder mit ihm verbundene Index unbenutzbar. Jeder Versuch,
ihn in einer Tabelle zu verwenden, für die kein Plug-In zur
Verfügung steht, löst einen Fehler aus. Nur DROP
TABLE
ist nach wie vor möglich.
INSTALL PLUGINplugin_name
SONAME 'plugin_library
'
Mit dieser Anweisung wird ein Plug-In installiert.
plugin_name
ist der Name des
Plug-Ins, wie er in der Plug-In-Deklarationsstruktur in der
Bibliotheksdatei festgelegt ist. Ob in Plug-In-Namen die Groß-
und Kleinschreibung beachtet wird, hängt von der
Dateinamensemantik des Hostsystems ab.
plugin_library
ist der Name der
Shared Library, die den Plug-In-Code enthält. Dieser Name
umfasst auch die Dateinamenserweiterung (beispielsweise
libmyplugin.so
oder
libmyplugin.dylib
).
Die Shared Library muss im Plug-In-Verzeichnis liegen (also in
dem Verzeichnis, das die Systemvariable
plugin_dir
angibt). Die Bibliothek muss in
dem Plug-In-Verzeichnis selbst und nicht in einem
Unterverzeichnis liegen. Nach Voreinstellung ist
plugin_dir
das Verzeichnis, welches die
Konfigurationsvariable pkglibdir
vorgibt,
aber es kann auch durch Einstellen des Werts von
plugin_dir
beim Serverstart geändert werden.
Das folgende Beispiel zeigt, wie der Wert in einer
my.cnf
-Datei gesetzt wird:
[mysqld]
plugin_dir=/path/to/plugin/directory
Ist der Wert von plugin_dir
ein relativer
Pfadname, wird er mit Bezug auf das MySQL-Basisverzeichnis
interpretiert (dieses ist in der Systemvariablen
basedir
festgelegt).
INSTALL PLUGIN
fügt der
mysql.plugin
-Tabelle eine Zeile mit einer
Beschreibung des plugin
s hinzu. Diese Tabelle
enthält den Namen des Plug-Ins und der Bibliotheksdatei.
INSTALL PLUGIN
lädt und initialisiert auch
den Plug-In-Code, um das Plug-In nutzbar zu machen. Um ein
Plug-In zu initialisieren, wird seine Initialisierungsfunktion
ausgeführt, die alle Einstellungen vornimmt, welche zur
Benutzung des Plug-Ins erforderlich sind.
Für INSTALL PLUGIN
benötigen Sie das
INSERT
-Recht für die
mysql.plugin
-Tabelle.
Beim Serverstart lädt und initialisiert der Server alle in der
mysql.plugin
-Tabelle aufgelisteten Plug-Ins.
Dies bedeutet, dass ein Plug-In mit INSTALL
PLUGIN
nur einmalig installiert wird und nicht bei
jedem Serverstart. Das Laden von Plug-Ins beim Hochfahren des
Servers funktioniert nicht, wenn der Server mit der Option
--skip-grant-tables
gestartet wird.
Wenn der Server herunterfährt, führt er die Deinitialisierungsfunktion für jedes geladene Plug-In aus, damit dieses Gelegenheit zu eventuellen Aufräumarbeiten bekommt.
Um ein Plug-In vollständig zu entfernen, führen Sie die
UNINSTALL PLUGIN
-Anweisung aus.
Die SHOW PLUGIN
-Anweisung verrät Ihnen,
welche Plug-Ins installiert sind.
Wenn Sie eine Plug-In-Bibliothek neu kompilieren und neu installieren müssen, können Sie aus folgenden Methoden wählen:
Sie deinstallieren alle Plug-Ins der Bibliothek mit
UNINSTALL PLUGIN
, installieren die neue
Plug-In-Bibliotheksdatei in das Plug-In-Verzeichnis und
installieren dann mit INSTALL PLUGIN
alle
Plug-Ins in der Bibliothek. Diese Vorgehensweise hat den
Vorteil, dass man den Server nicht anhalten muss. Wenn
jedoch die Plug-In-Bibliothek viele Plug-Ins enthält,
müssen Sie viele INSTALL PLUGIN
- und
UNINSTALL PLUGIN
-Anweisungen geben.
Alternativ können Sie den Server anhalten, die neue Plug-In-Bibliotheksdatei in das Plug-In-Verzeichnis installieren und dann den Server neu starten.
UNINSTALL PLUGIN plugin_name
Diese Anweisung entfernt ein installiertes Plug-In. Sie können ein Plug-In nicht entfernen, wenn es von einer Tabelle, die offen ist, noch gebraucht wird.
Der plugin_name
muss der Name eines
in der mysql.plugin
-Tabelle aufgeführten
Plug-Ins sein. Der Server führt die Deinitialisierungsfunktion
des Plug-Ins aus und entfernt die Zeile für dieses Plug-In aus
der mysql.plugin
-Tabelle, damit es künftig
beim Hochfahren des Servers nicht mehr geladen und initialisiert
wird. UNINSTALL PLUGIN
entfernt allerdings
nicht die Dateien des Plug-Ins aus der Shared Library.
Um UNINSTALL PLUGIN
benutzen zu können,
benötigen Sie das DELETE
-Recht für die
mysql.plugin
-Tabelle.
Die Entfernung von Plug-Ins hat Folgen für die Benutzung von
Tabellen, die mit diesem Plug-In verbunden sind. Wenn
beispielsweise ein Volltext-Parser-Plug-In mit einem
FULLTEXT
-Index auf der Tabelle verbunden ist,
wird die Tabelle durch Deinstallation des Plug-Ins unbenutzbar.
Jeder Versuch, auf sie zuzugreifen, löst einen Fehler aus. Sie
kann noch nicht einmal mehr geöffnet werden, um den Index zu
entfernen, der das Plug-In benutzt. Also sollten Sie bei der
Deinstallation von Plug-Ins vorsichtig sein, wenn Ihnen Ihre
Tabelleninhalte wichtig sind. Wenn Sie ein Plug-In
deinstallieren, das Sie nicht wieder benutzen möchten, aber
sich noch für den Inhalt der zugehörigen Tabelle
interessieren, sollten Sie die Tabelle mit
mysqldump kopieren und die WITH
PARSER
-Klausel aus der gespeicherten CREATE
TABLE
-Anweisung entfernen, damit Sie die Tabelle
später erneut laden können. Wenn Ihnen die Tabelle egal ist,
können Sie sie mit DROP TABLE
auch dann noch
löschen, wenn Ihre Plug-Ins nicht mehr vorhanden sind.
Dieser Abschnitt beschreibt die allgemeinen und typspezifischen
Teile der Plug-In-API. Außerdem wird Schritt für Schritt
erklärt, wie man eine Plug-In-Bibliothek erstellt. Ein Beispiel
für Plug-In-Quellcode finden Sie im
plugin/fulltext
-Verzeichnis einer
MySQL-Quelldistribution.
Sie können Plug-Ins in C oder C++ schreiben. Da die Plug-Ins dynamisch ge- und entladen werden, muss Ihr Betriebssystem dynamisches Laden unterstützen und auch mysqld dynamisch (nicht statisch) kompiliert worden sein.
Ein Plug-In enthält Code, der Teil des laufenden Servers wird.
Daher gelten für das Schreiben von Plug-Ins dieselben
Einschränkungen wie für Servercode. Sie bekommen
beispielsweise Schwierigkeiten, wenn Sie versuchen, Funktionen
aus der libstdc++
-Bibliothek zu benutzen.
Beachten Sie, dass sich diese Einschränkungen in zukünftigen
Versionen des Servers noch ändern können, sodass bei einem
Server-Upgrade unter Umständen auch Plug-Ins überarbeitet
werden müssen, die ursprünglich für ältere Server erstellt
wurden. Informationen über diese Einschränkungen finden Sie in
Abschnitt 2.8.2, „Typische configure-Optionen“, und
Abschnitt 2.8.4, „Probleme beim Kompilieren?“.
Jedes Plug-In muss eine allgemeine Plug-In-Deklaration
besitzen. Die Deklaration entspricht der
st_mysql_plugin
-Struktur in der
plugin.h
-Datei:
struct st_mysql_plugin { int type; /* Der Plug-In-Typ (ein MYSQL_XXX_PLUGIN-Wert) */ void *info; /* Zeiger auf den typspezifischen Plug-In-Deskriptor */ const char *name; /* Plug-In-Name */ const char *author; /* Plug-In-Autor (für SHOW PLUGINS) */ const char *descr; /* Allgemeine Beschreibung (für SHOW PLUGINS ) */ int (*init)(void); /* Die beim Laden des Plug-Ins aufgerufene Funktion */ int (*deinit)(void); /* Die beim Entladen des Plug-Ins aufgerufene Funktion */ };
Die st_mysql_plugin
-Struktur ist allen
Plug-In-Typen gemein. Ihre Bestandteile sollten
folgendermaßen ausgefüllt werden:
type
Der Plug-In-Typ. Dieser muss einer der Plug-In-Typwerte
aus plugin.h
sein. Für ein
Volltext-Parser-Plug-In ist der
type
-Wert
MYSQL_FTPARSER_PLUGIN
.
info
Ein Zeiger auf den Deskriptor für das Plug-In. Anders als die allgemeine Plug-In-Deklarationsstruktur hängt die Struktur dieses Deskriptors von dem konkreten Plug-In-Typ ab. Jeder Deskriptor hat eine Versionsnummer, die auf die API-Version für diesen Plug-In-Typ verweist, sowie andere erforderliche Bestandteile. Der Deskriptor für Volltext-Plug-Ins ist in Abschnitt 26.2.5.2, „Typspezifische Plug-In-Strukturen und -Funktionen“, beschrieben.
name
Der Name des Plug-Ins. Dieser wird in der
plugin
-Tabelle aufgeführt und in
SQL-Anweisungen wie INSTALL PLUGIN
und
UNINSTALL PLUGIN
zur Benennung des
Plug-Ins verwendet.
author
Der Autor des Plug-Ins. Kann alles sein, was Sie wollen.
desc
Eine allgemeine Beschreibung des Plug-Ins. Kann alles sein, was Sie wollen.
init
Eine nur einmalig benutzte Initialisierungsfunktion. Diese
wird ausgeführt, wenn das Plug-In geladen wird, was bei
INSTALL PLUGIN
oder für Plug-Ins aus
der plugin
-Tabelle beim Serverstart
geschieht. Diese Funktion hat keine Argumente und gibt bei
Erfolg null und bei Misserfolg einen von null
verschiedenen Wert zurück.
deinit
Eine nur einmalig benutzte Deinitialisierungsfunktion.
Diese wird ausgeführt, wenn das Plug-In entladen wird,
was bei UNINSTALL PLUGIN
oder für
Plug-Ins aus der plugin
-Tabelle beim
Server-Shutdown geschieht. Diese Funktion hat keine
Argumente und gibt bei Erfolg null und bei Misserfolg
einen von null verschiedenen Wert zurück
Die Funktionen init
und
deinit
in der allgemeinen
Plug-In-Deklaration werden nur beim Laden und Entladen des
Plug-Ins aufgerufen. Sie haben nichts mit einer Benutzung des
Plug-Ins zu tun, wie sie vorliegt, wenn eine SQL-Anweisung das
Plug-In aufruft.
Wenn eine init
- oder
deinit
-Funktion für ein Plug-In nicht
notwendig ist, kann sie in der
st_mysql_plugin
-Struktur mit 0 angegeben
werden.
In der st_mysql_plugin
-Struktur, die eine
allgemeine Plug-In-Deklaration definiert, verweist der
Bestandteil info
auf einen typspezifischen
Plug-In-Deskriptor. Bei einem Volltext-Parser-Plug-In
entspricht dieser Deskriptor der
st_mysql_ftparser
-Struktur in der
plugin.h
-Datei:
struct st_mysql_ftparser { int interface_version; int (*parse)(MYSQL_FTPARSER_PARAM *param); int (*init)(MYSQL_FTPARSER_PARAM *param); int (*deinit)(MYSQL_FTPARSER_PARAM *param); };
Wie die Strukturdefinition zeigt, hat der Deskriptor eine
Versionsnummer
(MYSQL_FTPARSER_INTERFACE_VERSION
für
Volltext-Parser-Plug-Ins) und enthält Zeiger auf drei
Funktionen. Die Bestandteile init
und
deinit
sollten auf eine Funktion verweisen
oder auf 0 gesetzt werden, wenn die Funktion nicht gebraucht
wird. Der Bestandteil parse
muss auf die
Parse-Funktion verweisen.
Ein Volltext-Parser-Plug-In wird für zwei Dinge verwendet: Indizierung und Suchoperationen. In beiden Fällen ruft der Server die Initialisierungs- und Deinitialisierungsfunktion am Anfang und am Ende der Verarbeitung jeder SQL-Anweisung auf, in der das Plug-In benutzt wird. Während der Verarbeitung der Anweisung ruft der Server die Parsing-Hauptfunktion jedoch kontextabhängig auf:
Zum Indizieren ruft der Server den Parser für jeden zu indizierenden Spaltenwert auf.
In Suchoperationen ruft der Server den Parser auf, um den
Such-String zu parsen. Ebenso kann der Parser für Zeilen
aufgerufen werden, die von der Anweisung verarbeitet
werden. Im Modus für natürliche Sprache braucht der
Server den Parser nicht aufzurufen. Ini Phrasensuchen im
booleschen Modus oder Suchen in natürlicher Sprache mit
Abfrageerweiterung (Query Expansion) wird der Parser
eingesetzt, um in den Spaltenwerten Informationen zu
parsen, die nicht im Index vorliegen. Wenn eine Suche nach
einer Spalte mit FULLTEXT
-Index im
booleschen Modus durchgeführt wird, wird ebenfalls der
eingebaute Parser aufgerufen. (Plug-Ins sind mit konkreten
Indizes verbunden. Ist kein Index vorhanden, wird auch
kein Plug-In verwendet.)
Beachten Sie, dass die Plug-In-Deklaration im Plug-In-Bibliotheksdeskriptor Initialisierungs- und Deinitialisierungsfunktionen hat, ebenso wie der Plug-In-Deskriptor, auf den sie verweist. Diese Funktionspaare dienen unterschiedlichen Zwecken und werden aus unterschiedlichen Gründen aufgerufen:
Für die Plug-In-Deklaration im Plug-In-Bibliotheksdeskriptor werden die Initialisierungs- und Deinitialisierungsfunktionen beim Laden und Entladen des Plug-Ins aufgerufen.
Für den Plug-In-Deskriptor werden die Initialisierungs- und Deinitialisierungsfunktionen für jede SQL-Anweisung aufgerufen, in der das Plug-In benutzt wird.
Jede API-Funktion, die im Plug-In-Deskriptor genannt ist,
sollte null bei einem Erfolg und einen von null verschiedenen
Wert bei einem Misserfolg zurückgeben, und jede sollte ein
Argument entgegennehmen, das auf eine
MYSQL_FTPARSER_PARAM
-Struktur verweist, die
den Parsing-Kontext enthält. Die Struktur ist wie folgt
definiert:
typedef struct st_mysql_ftparser_param { int (*mysql_parse)(void *param, byte *doc, uint doc_len); int (*mysql_add_word)(void *param, byte *word, uint word_len, MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info); void *ftparser_state; void *mysql_ftparam; CHARSET_INFO *cs; byte *doc; uint length; int mode; } MYSQL_FTPARSER_PARAM;
Die Bestandteile der Struktur werden folgendermaßen benutzt:
mysql_parse
Ein Zeiger auf eine Callback-Funktion, die den eingebauten
Parser des Servers aufruft. Diesen Callback verwenden Sie,
wenn das Plug-In als Frontend des eingebauten Parsers
fungiert. Wenn also die Plug-In-Parsing-Funktion
aufgerufen wird, soll sie die Eingabe verarbeiten, um den
Inhalt zu extrahieren, und diesen dann an den
mysql_parse
-Callback übergeben.
Der erste Parameter dieser Callback-Funktion sollte der
mysql_ftparam
-Teil der Struktur des
Parsing-Kontextes sein. Das heißt: Wenn
param
auf die Struktur verweist, wird
der Callback folgendermaßen aufgerufen:
param->mysql_parse(param->mysql_ftparam, ...);
Ein Frontend-Plug-In kann Text extrahieren und komplett oder häppchenweise an den eingebauten Parser übergeben. Im zweiten Fall behandelt der eingebaute Parser die Textstücke, als befänden sich implizite Wortgrenzen zwischen ihnen.
mysql_add_word
Ein Zeiger auf eine Callback-Funktion, die einem
Volltextindex oder der Liste der Suchbegriffe ein Wort
hinzufügt. Diesen Callback verwenden Sie, wenn das
Parser-Plug-In den eingebauten Parser ersetzen soll. Das
bedeutet: Wenn die Parsing-Funktion des Plug-Ins
aufgerufen wird, soll sie die Eingabe in Wörter parsen
und für jedes Wort den
mysql_add_word
-Callback aufrufen.
Der erste Parameter dieser Callback-Funktion soll der
mysql_ftparam
-Teil der Struktur des
Parsing-Kontexts sein. Das heißt: Wenn
param
auf die Struktur verweist, wird
der Callback wie folgt aufgerufen:
param->mysql_add_word(param->mysql_ftparam, ...);
ftparser_state
Dies ist ein generischer Zeiger. Das Plug-In kann ihn auf die Informationen verweisen lassen, die es intern für seine eigenen Zwecke benutzt.
mysql_ftparam
Wird durch den Server eingestellt und als erstes Argument
an den mysql_parse
- oder
mysql_add_word
-Callback übergeben.
cs
Verweist auf den Zeichensatz für den Text, oder auf 0, wenn diese Information nicht zur Verfügung steht.
doc
Ein Zeiger auf den zu parsenden Text.
length
Die Länge des zu parsenden Texts in Bytes.
mode
Der Parsing-Modus. Dieser Wert ist eine der folgenden Konstanten:
MYSQL_FTPARSER_SIMPLE_MODE
Parsen im schnellen, einfachen Modus. Dies wird für Indizes und für Anfragen mit natürlichen Sprachen verwendet. Der Parser sollte an den Server nur die zu indizierenden Wörter übergeben. Wenn er Längenbeschränkungen oder eine Liste mit zu ignorierenden Stoppwörtern verwendet, soll er die hierdurch ausgeschlossenen Wörter nicht an den Server übergeben.
MYSQL_FTPARSER_WITH_STOPWORDS
Parsen im Stoppwortmodus. Dies wird bei booleschen Suchoperationen für den Abgleich von Begriffen verwendet. Der Parser sollte alle Wörter an den Server übergeben, auch Stoppwörter oder Wörter, die die normalen Längenbeschränkungen übersteigen.
MYSQL_FTPARSER_FULL_BOOLEAN_INFO
Parsen im booleschen Modus. Wird zum Parsen von
booleschen Anfrage-Strings genutzt. Der Parser soll
nicht nur Wörter, sondern auch Operatoren für den
booleschen Modus erkennen, und diese als Token mit dem
mysql_add_word
-Callback an den
Server übergeben. Um dem Server zu sagen, welche Art
von Token übergeben wird, muss das Plug-In eine
MYSQL_FTPARSER_BOOLEAN_INFO
-Struktur
ausfüllen und einen Zeiger auf diese Struktur mit
übergeben.
Wenn der Parser im booleschen Modus aufgerufen wird, hat
param->mode
den Wert
MYSQL_FTPARSER_FULL_BOOLEAN_INFO
. Die
MYSQL_FTPARSER_BOOLEAN_INFO
-Struktur, die
der Parser zur Übergabe von Token-Informationen an den Server
benutzt, sieht folgendermaßen aus:
typedef struct st_mysql_ftparser_boolean_info { enum enum_ft_token_type type; int yesno; int weight_adjust; bool wasign; bool trunc; /* Diese sind im Parser-Zustand und müssen entfernt werden. */ byte prev; byte *quot; } MYSQL_FTPARSER_BOOLEAN_INFO;
Der Parser sollte die Bestandteile der Struktur folgendermaßen ausfüllen:
type
Der Token-Typ. Dies sollte einer der Werte der folgenden Tabelle sein:
Typ | Bedeutung |
FT_TOKEN_EOF | Ende der Daten |
FT_TOKEN_WORD | Ein normales Wort |
FT_TOKEN_LEFT_PAREN | Beginn einer Gruppe oder eines Teilausdrucks |
FT_TOKEN_RIGHT_PAREN | Ende einer Gruppe oder eines Teilausdrucks |
FT_TOKEN_STOPWORD | Ein Stoppwort |
yesno
Gibt an, ob das Wort vorhanden sein muss, damit eine Übereinstimmung festgestellt wird. 0 bedeutet, dass das Wort optional ist, sein Vorhandensein jedoch die Relevanz der Übereinstimmung erhöht. Werte größer 0 bedeuten, dass das Wort obligatorisch ist, und Werte kleiner 0, dass es nicht vorhanden sein darf.
weight_adjust
Ein Gewichtsfaktor, der festlegt, wie viel eine
Übereinstimmung für das Wort zählt. Indem man diesen
Faktor herauf- oder heruntersetzt, beeinflusst man die
Bedeutung, die dieses Wort in Relevanzberechnungen hat.
Ist der Wert null, so erfolgt keine Anpassung der
Gewichtung. Werte größer oder kleiner null bedeuten ein
höheres oder geringeres Gewicht. Die Beispiele unter
Abschnitt 12.7.1, „Boolesche Volltextsuche“, die
<
- und
>
-Operatoren verwenden, zeigen, wie
Gewichtung funktioniert.
wasign
Das Vorzeichen des Gewichtungsfaktors. Ein negativer Wert
verhält sich wie der boolesche Suchoperator
~
, der dafür sorgt, dass das Wort in
negativer Weise zur Relevanz beiträgt.
trunc
Zeigt an, ob der Abgleich in derselben Weise durchgeführt
wird, als ob der Kappungsoperator *
im
booleschen Modus angegeben worden wäre.
Plug-Ins sollten nicht die Bestandteile
prev
und quot
der
MYSQL_FTPARSER_BOOLEAN_INFO
-Struktur
benutzen.
Dieser Abschnitt erklärt die Erstellung einer
Plug-In-Bibliothek Schritt für Schritt. Er zeigt, wie man
eine Bibliothek entwickelt, die ein Volltext-Parsing-Plug-In
namens simple_parser
enthält. Dieses
Plug-In wendet einfachere Regeln als der eingebaute
Volltext-Parser von MySQL an: Wörter sind nichtleere Folgen
von Whitespace-Zeichen.
Jede Plug-In-Bibliothek enthält Folgendes:
Ein Plug-In-Bibliotheksdeskriptor mit der Versionsnummer der allgemeinen Plug-In-API der Bibliothek und einer allgemeinen Deklaration für jedes Plug-In in der Bibliothek.
Jede allgemeine Plug-In-Deklaration enthält Informationen, die allen Arten von Plug-Ins gemeinsam sind: einen Wert, der den Plug-In-Typ anzeigt, den Namen, den Autor und die Beschreibung des Plug-Ins sowie Zeiger auf die Initialisierungs- und die Deinitialisierungfunktionen, die der Server beim Laden und Entladen des Plug-Ins aufrufen muss.
Außerdem enthält die allgemeine Plug-In-Deklaration einen Zeiger auf einen typspezifischen Plug-In-Deskriptor. Die Struktur dieser Deskriptoren kann je nach Plug-In-Typ unterschiedlich sein, da jede Art von Plug-In ihre eigene API haben kann. Ein Plug-In-Deskriptor enthält eine typspezifische API-Versionsnummer und Zeiger auf die Funktionen, die zur Implementierung dieses Plug-In-Typs erforderlich sind. So hat beispielsweise ein Volltext-Parser-Plug-In Initialisierungs- und Deinitialisierungsfunktionen und eine Parsing-Hauptfunktion. Der Server ruft diese Funktionen auf, wenn er das Plug-In zum Parsen von Text einsetzt.
Die Plug-In-Bibliothek enthält die Schnittstellenfunktionen, auf die der Bibliotheksdeskriptor und die Plug-In-Deskriptoren verweisen.
Eine Plug-In-Bibliothek wird folgendermaßen angelegt:
Zuerst binden Sie die von der Plug-In-Bibliothek
benötigten Header-Dateien ein. Die Datei
plugin.h
ist auf jeden Fall
notwendig, allerdings kann die Bibliothek auch noch andere
Dateien erfordern. Zum Beispiel:
#include <my_global.h> #include <m_string.h> #include <m_ctype.h> #include <plugin.h>
Dann richten Sie den Deskriptor für die Plug-In-Bibliotheksdatei ein.
Jede Plug-In-Bibliothek muss einen Bibliotheksdeskriptor besitzen, der zwei Symbole definiert:
_mysql_plugin_interface_version_
ist die Versionsnummer des allgemeinen
Plug-In-Frameworks. Sie wird durch das Symbol
MYSQL_PLUGIN_INTERFACE_VERSION
angegeben, das in der Datei
plugin.h
definiert ist.
_mysql_plugin_declarations_
definiert ein Array von Plug-In-Deklarationen, wobei
am Ende eine Deklaration steht, in der alle
Bestandteile auf 0 gesetzt sind. Jede Deklaration ist
eine Instanz der Struktur
st_mysql_plugin
(ebenfalls in
plugin.h
definiert). Für jedes
Plug-In in der Bibliothek muss eine solche Deklaration
vorhanden sein.
Wenn der Server diese beiden Symbole nicht in einer Bibliothek vorfindet, akzeptiert er sie nicht als gültige Plug-In-Bibliothek und weist sie mit einer Fehlermeldung zurück. So wird verhindert, dass eine Bibliothek für Plug-In-Zwecke benutzt wird, die nicht speziell als Plug-In-Bibliothek ausgelegt wurde.
Die üblichste (und bequemste) Art, die beiden notwendigen
Symbole zu definieren, bieten die beiden Makros
mysql_declare_plugin
und
mysql_declare_plugin_end
aus der Datei
plugin.h
:
mysql_declare_plugin
... eine oder mehr Plug-In-Deklarationen ...
mysql_declare_plugin_end;
Der Bibliotheksdeskriptor für eine Bibliothek mit einem
einzigen Plug-In namens simple_parser
sähe beispielsweise folgendermaßen aus:
mysql_declare_plugin { MYSQL_FTPARSER_PLUGIN, /* Typ */ &simple_parser_descriptor, /* Deskriptor */ "simple_parser", /* Name */ "MySQL AB", /* Autor */ "Simple Full-Text Parser", /* Beschreibung */ simple_parser_plugin_init, /* Initialisierungsfunktion */ simple_parser_plugin_deinit /* Deinitialisierungsfunktion */ } mysql_declare_plugin_end;
Der Typ eines Volltext-Parser-Plug-Ins müsste
MYSQL_FTPARSER_PLUGIN
sein. Dieser Wert
kennzeichnet das Plug-In als zulässig zur Benutzung in
einer WITH PARSER
-Klausel, wenn ein
FULLTEXT
-Index angelegt werden soll.
(Kein anderer Plug-In-Typ ist für diese Klausel erlaubt.)
Die Makros mysql_declare_plugin
und
mysql_declare_plugin_end
sind in
plugin.h
folgendermaßen definiert:
#define mysql_declare_plugin \ int _mysql_plugin_interface_version_= MYSQL_PLUGIN_INTERFACE_VERSION; \ struct st_mysql_plugin _mysql_plugin_declarations_[]= { #define mysql_declare_plugin_end ,{0,0,0,0,0,0,0}}
In der oben gezeigten Verwendung werden die Makros zu
folgendem Code expandiert, der beide erforderlichen
Symbole definiert
(_mysql_plugin_interface_version_
und
_mysql_plugin_declarations_
):
int _mysql_plugin_interface_version_= MYSQL_PLUGIN_INTERFACE_VERSION; struct st_mysql_plugin _mysql_plugin_declarations_[]= { { MYSQL_FTPARSER_PLUGIN, /* Typ */ &simple_parser_descriptor, /* Deskriptor */ "simple_parser", /* Name */ "MySQL AB", /* Autor */ "Simple Full-Text Parser", /* Beschreibung */ simple_parser_plugin_init, /* Initialisierungsfunktion */ simple_parser_plugin_deinit /* Deinitialisierungsfunktion */ } ,{0,0,0,0,0,0,0} };
Im obigen Beispiel wird nur ein einzelnes Plug-In im
Bibliotheksdeskriptor deklariert, aber es ist ebenso gut
möglich, mehrere Plug-Ins zu deklarieren. Hierzu führen
Sie die Deklarationen
– durch Kommata getrennt – in
mysql_declare_plugin
und
mysql_declare_plugin_end
auf.
Nun richten Sie den Plug-In-Deskriptor ein.
Jede Plug-In-Deklaration im Bibliotheksdeskriptor verweist
auf einen typspezifischen Deskriptor für das zugehörige
Plug-In. In der Deklaration von
simple_parser
wird dieser Deskriptor
von &simple_parser_descriptor
angezeigt. Der Deskriptor gibt die Versionsnummer für die
Volltext-Plug-In-Schnittstelle (wie sie in
MYSQL_FTPARSER_INTERFACE_VERSION
steht)
sowie die Parsing-, Initialisierungs- und
Deinitialisierungsfunktionen des Plug-Ins an:
static struct st_mysql_ftparser simple_parser_descriptor= { MYSQL_FTPARSER_INTERFACE_VERSION, /* Schnittstellenversion */ simple_parser_parse, /* Parsing-Funktion */ simple_parser_init, /* Parser-Initialisierungsfunktion */ simple_parser_deinit /* Parser-Deinitialisierungsfunktion */ };
Jetzt richten Sie die Plug-In-Schnittstellenfunktionen ein.
In der allgemeinen Plug-In-Deklaration des
Bibliotheksdeskriptors werden die Initialisierungs- und
Deinitialisierungsfunktionen angegeben, die der Server zum
Laden und Entladen des Plug-Ins aufrufen muss. Für den
simple_parser
geben diese Funktionen
lediglich null zurück, um anzuzeigen, dass sie Erfolg
hatten:
static int simple_parser_plugin_init(void) { return(0); } static int simple_parser_plugin_deinit(void) { return(0); }
Da diese Funktionen eigentlich nichts tun, könnten Sie sie ebenso gut weglassen und in der Plug-In-Deklaration jeweils durch 0 ersetzen.
Der typspezifische Plug-In-Deskriptor für den
simple_parser
gibt die
Initialisierungs-, Deinitialisierungs- und
Parsing-Funktionen an, die der Server bei Benutzung dieses
Plug-Ins aufrufen muss. Beim
simple_parser
tun die Initialisierungs-
und Deinitialisierungsfunktionen gar nichts:
static int simple_parser_init(MYSQL_FTPARSER_PARAM *param) { return(0); } static int simple_parser_deinit(MYSQL_FTPARSER_PARAM *param) { return(0); }
Da diese Funktionen nichts tun, könnte man sie hier ebenfalls weglassen und im Plug-In-Deskriptor 0 für sie angeben.
Da die Parsing-Hauptfunktion
simple_parser_parse()
den eingebauten
Volltext-Parser ersetzen soll, muss sie Text in Wörter
zerlegen und diese Wörter an den Server übergeben. Das
erste Argument der Parsing-Funktion ist ein Zeiger auf
eine Struktur, die den Parsing-Kontext enthält. Diese
Struktur besitzt einen doc
-Bestandteil,
der auf den zu parsenden Text verweist, und einen
length
-Bestandteil, der die Länge
dieses Texts anzeigt. Da das Plug-In ganz einfache
Parsing-Regeln verwendet, wonach nichtleere Folgen von
Whitespace-Zeichen als Wörter betrachtet werden, erkennt
es Wörter folgendermaßen:
static int simple_parser_parse(MYSQL_FTPARSER_PARAM *param) { char *end, *start, *docend= param->doc + param->length; for (end= start= param->doc;; end++) { if (end == docend) { if (end > start) add_word(param, start, end - start); break; } else if (isspace(*end)) { if (end > start) add_word(param, start, end - start); start= end + 1; } } return(0); }
Während der Parser ein Wort nach dem anderen erkennt,
ruft er die Funktion add_word()
auf, um
es an den Server zu übergeben.
add_word()
ist nur eine Hilfsfunktion,
die nicht zur Plug-In-Schnittstelle gehört. Der Parser
übergibt den Zeiger auf den Parsing-Kontext, den Zeiger
auf das Wort und einen Längenwert an
add_word()
.
static void add_word(MYSQL_FTPARSER_PARAM *param, char *word, size_t len) { MYSQL_FTPARSER_BOOLEAN_INFO bool_info= { FT_TOKEN_WORD, 0, 0, 0, 0, ' ', 0 }; if (param->mode == MYSQL_FTPARSER_FULL_BOOLEAN_INFO) param->mysql_add_word(param->mysql_ftparam, word, len, &bool_info); else param->mysql_add_word(param->mysql_ftparam, word, len, 0); }
Beim Parsen im booleschen Modus füllt
add_word()
die Bestandteile der
bool_info
-Struktur aus, wie in
Abschnitt 26.2.5.2, „Typspezifische Plug-In-Strukturen und -Funktionen“ beschrieben.
Kompilieren Sie die Plug-In-Bibliothek als Shared Library und installieren Sie sie in das Plug-In-Verzeichnis.
Die Prozedur zum Kompilieren von Shared-Objekten ist von
System zu System unterschiedlich. Wenn Sie Ihre Bibliothek
mithilfe der GNU-Autotools bauen, müsste
libtool in der Lage sein, die richtigen
Kompilierbefehle für Ihr System zu generieren. Wenn die
Bibliothek mypluglib
heißt, müssten
Sie zum Schluss mit einer Shared Object-Datei dastehen,
die so ähnlich wie libmypluglib.so
heißt. (Der Dateiname kann auf Ihrem System eine andere
Erweiterung haben.)
Die Stelle, an der Sie die Bibliothek in Ihrem
Plug-In-Verzeichnis installieren müssen, verrät Ihnen
die Systemvariable plugin_dir
. Zum
Beispiel:
mysql> SHOW VARIABLES LIKE 'plugin_dir';
+---------------+----------------------------+
| Variable_name | Value |
+---------------+----------------------------+
| plugin_dir | /usr/local/mysql/lib/mysql |
+---------------+----------------------------+
Wenn Sie die Plug-In-Bibliothek installieren, achten Sie bitte darauf, dass Ihre Berechtigungen eine Ausführung durch den Server erlauben.
Registrieren Sie das Plug-In beim Server.
Die INSTALL PLUGIN
-Anweisung lässt den
Server das Plug-In in die
plugin
-Tabelle
übernehmen und seinen Code aus der Bibliotheksdatei
laden. Registrieren Sie mit dieser Anweisung den
simple_parser
beim Server und
vergewissern Sie sich dann, dass er in die
plugin
-Tabelle aufgenommen wurde:
mysql>INSTALL PLUGIN simple_parser SONAME 'libmypluglib.so';
Query OK, 0 rows affected (0.00 sec) mysql>SELECT * FROM mysql.plugin;
+---------------+-----------------+ | name | dl | +---------------+-----------------+ | simple_parser | libmypluglib.so | +---------------+-----------------+ 1 row in set (0.00 sec)
Nun probieren Sie das Plug-In aus.
Legen Sie eine Tabelle mit einer String-Spalte an und
verbinden Sie das Parser-Plug-In mit einem
FULLTEXT
-Index auf der Spalte:
mysql>CREATE TABLE t (c VARCHAR(255),
->FULLTEXT (c) WITH PARSER simple_parser);
Query OK, 0 rows affected (0.01 sec)
Fügen Sie Text in die Tabelle ein und versuchen Sie einige Suchoperationen. Dabei sollte ausprobiert werden, ob das Parser-Plug-In wirklich alle Nicht-Whitespace-Zeichen als Wortzeichen betrachtet:
mysql>INSERT INTO t VALUES
->('latin1_general_cs is a case-sensitive collation'),
->('I\'d like a case of oranges'),
->('this is sensitive information'),
->('another row'),
->('yet another row');
Query OK, 5 rows affected (0.02 sec) Records: 5 Duplicates: 0 Warnings: 0 mysql>SELECT c FROM t;
+-------------------------------------------------+ | c | +-------------------------------------------------+ | latin1_general_cs is a case-sensitive collation | | I'd like a case of oranges | | this is sensitive information | | another row | | yet another row | +-------------------------------------------------+ 5 rows in set (0.00 sec) mysql>SELECT MATCH(c) AGAINST('case') FROM t;
+--------------------------+ | MATCH(c) AGAINST('case') | +--------------------------+ | 0 | | 1.2968142032623 | | 0 | | 0 | | 0 | +--------------------------+ 5 rows in set (0.00 sec) mysql>SELECT MATCH(c) AGAINST('sensitive') FROM t;
+-------------------------------+ | MATCH(c) AGAINST('sensitive') | +-------------------------------+ | 0 | | 0 | | 1.3253291845322 | | 0 | | 0 | +-------------------------------+ 5 rows in set (0.01 sec) mysql>SELECT MATCH(c) AGAINST('case-sensitive') FROM t;
+------------------------------------+ | MATCH(c) AGAINST('case-sensitive') | +------------------------------------+ | 1.3109166622162 | | 0 | | 0 | | 0 | | 0 | +------------------------------------+ 5 rows in set (0.01 sec) mysql>SELECT MATCH(c) AGAINST('I\'d') FROM t;
+--------------------------+ | MATCH(c) AGAINST('I\'d') | +--------------------------+ | 0 | | 1.2968142032623 | | 0 | | 0 | | 0 | +--------------------------+ 5 rows in set (0.01 sec)
Beachten Sie, dass weder „case“ noch „insensitive“ auf „case-insensitive“ passen, wie es bei dem eingebauten Parser der Fall wäre.
Es gibt zwei Möglichkeiten, neue Funktionen zu MySQL hinzuzufügen:
Die erste Möglichkeit ist die Schnittstelle für
benutzerdefinierte Funktionen (User-Defined Functions, UDFs).
Benutzerdefinierte Funktionen werden als Objektdateien
kompiliert und dann dynamisch mit den Anweisungen
CREATE FUNCTION
und DROP
FUNCTION
auf den Server geladen oder von ihm
entfernt. Siehe auch Abschnitt 26.3.2, „CREATE FUNCTION/DROP FUNCTION
“.
Die zweite Möglichkeit: Sie fügen die Funktionen als native (eingebaute) MySQL-Funktionen hinzu. Native Funktionen werden in den mysqld-Server kompiliert und stehen dann dauerhaft zur Verfügung.
Beide Methoden haben ihre Vor- und Nachteile:
Wenn Sie benutzerdefinierte Funktionen schreiben, müssen Sie zusätzlich zum Server auch noch Objektdateien installieren. Wenn Sie Ihre Funktion in den Server kompilieren, entfällt das.
Um native Funktionen zu erstellen, müssen Sie eine Quelldistribution ändern; für UDFs müssen Sie das nicht. UDFs können Sie auch einer Binärdistribution von MySQL hinzufügen, ohne in den Quellcode von MySQL eingreifen zu müssen.
Wenn Sie Ihre MySQL-Distribution aufrüsten, können Sie die zuvor installierten UDFs auch weiterhin nutzen, es sei denn, die neue Version ist eine, bei der sich die UDF-Schnittstelle geändert hat. Für native Funktionen müssen Sie Ihre Modifikationen bei jedem Upgrade wiederholen.
Ganz gleich, welchen Weg Sie einschlagen, um neue Funktionen
hinzuzufügen: Aufgerufen werden sie in SQL-Anweisungen nicht
anders als native Funktionen, wie zum Beispiel
ABS()
oder SOUNDEX()
.
Auch gespeicherte Funktionen bieten die Möglichkeit, Funktionen hinzuzufügen. Gespeicherte Funktionen schreiben Sie in SQL-Anweisungen, anstatt sie in den Objektcode zu kompilieren. Die Syntax für gespeicherte Funktionen wird in Kapitel 19, Gespeicherte Prozeduren und Funktionen, beschrieben.
Die folgenden Abschnitte beschreiben Features der UDF-Schnittstelle, geben Anleitungen zum Schreiben von UDFs, erläutern Sicherheitsmaßnahmen, mit denen MySQL den Missbrauch von UDFs verhindert, und erklären, wie native MySQL-Funktionen hinzugefügt werden.
Quellcode, der zeigt, wie man UDFs schreibt, finden Sie in der
Datei sql/udf_example.cc
, die in den
MySQL-Quelldistributionen enthalten ist.
Die MySQL-Schnittstelle für benutzerdefinierte Funktionen stellt folgende Features und Fähigkeiten zur Verfügung:
Funktionen können String-, Integer- oder Real-Werte zurückgeben.
Einfache Funktionen, die immer nur auf einer einzigen Zeile operieren, können ebenso definiert werden wie Aggregatfunktionen, die auf Zeilengruppen arbeiten.
Die Funktionen erhalten Informationen, die sie in die Lage versetzen, die Anzahl und den Typ der an sie übergebenen Argumente zu überprüfen.
Sie können MySQL anweisen, Argumenten einen bestimmten Typ aufzuzwingen, bevor sie an eine Funktion übergeben werden.
Sie können verlangen, dass eine Funktion
NULL
zurückgibt oder dass ein Fehler
ausgelöst wird.
CREATE [AGGREGATE] FUNCTIONfunction_name
RETURNS {STRING|INTEGER|REAL|DECIMAL} SONAMEshared_library_name
Mit benutzerdefinierten Funktionen (UDFs) können Sie MySQL um
neue Funktionen erweitern, die wie native (eingebaute)
MySQL-Funktionen wie etwa ABS()
oder
CONCAT()
funktionieren.
function_name
ist der Name, mit dem
die Funktion in SQL-Anweisungen aufgerufen wird. Die
RETURNS
-Klausel zeigt den Rückgabetyp der
Funktion an. DECIMAL
ist zwar hinter
RETURNS
zulässig, aber gegenwärtig geben
DECIMAL
-Funktionen String-Werte zurück und
sollten daher wie STRING
-Funktionen
geschrieben werden.
shared_library_name
ist der Basisname
der Shared Object-Datei, die den Code zur Implementierung der
Funktion enthält. Diese Datei muss im Plug-In-Verzeichnis
liegen, welches durch den Wert der Systemvariablen
plugin_dir
vorgegeben ist.
(Hinweis: Dies ist eine
Änderung in MySQL 5.1. In früheren Versionen von MySQL konnte
die Shared Object-Datei in jedem beliebigen Verzeichnis liegen,
das der dynamische Linker des Systems untersuchte.)
Zur Erstellung einer Funktion benötigen Sie das
INSERT
-Recht für die
mysql
-Datenbank, da CREATE
FUNCTION
in die Systemtabelle
mysql.func
eine Zeile mit dem Namen, Typ und
Shared Library-Namen der Funktion einfügt. Wenn diese Tabelle
bei Ihnen fehlt, müssen Sie sie mit dem Skript
mysql_fix_privilege_tables anlegen. Siehe
Abschnitt 5.6, „mysql_fix_privilege_tables — Upgrade von MySQL-Systemtabellen“.
Eine aktive Funktion ist eine Funktion, die mit CREATE
FUNCTION
geladen, aber nicht mit DROP
FUNCTION
wieder gelöscht wurde. Alle aktiven
Funktionen werden bei jedem Serverstart neu geladen, es sei
denn, Sie starten mysqld mit der Option
--skip-grant-tables
. In diesem Fall wird die
UDF-Initialisierung übersprungen und die UDFs stehen nicht zur
Verfügung.
Anleitungen zum Schreiben benutzerdefinierter Funktionen finden Sie unter Abschnitt 26.3.4, „Hinzufügen einer neuen benutzerdefinierten Funktion“. Damit der UDF-Mechanismus funktioniert, müssen die Funktionen in C oder C++ geschrieben sein, Ihr Betriebssystem muss dynamisches Laden unterstützen, und Sie müssen mysqld dynamisch (nicht statisch) kompiliert haben.
Eine AGGREGATE
-Funktion funktioniert genau
wie eine native MySQL-Aggregatfunktion (Summenfunktion), wie
beispielsweise SUM
oder
COUNT()
. Damit AGGREGATE
funktioniert, muss Ihre mysql.func
-Tabelle
eine type
-Spalte enthalten. Wenn Ihre
mysql.func
-Tabelle diese Spalte nicht hat,
müssen Sie sie mit dem Skript
mysql_fix_privilege_tables erzeugen.
DROP FUNCTION function_name
Diese Anweisung löscht eine benutzerdefinierte Funktion (UDF)
namens function_name
.
Um eine Funktion löschen zu dürfen, benötigen Sie das
DELETE
-Recht für die
mysql
-Datenbank, denn DROP
FUNCTION
löscht aus der Systemtabelle
mysql.func
die Zeile, die den Namen, Typ und
Shared Library-Namen der Funktion enthält.
Damit der UDF-Mechanismus funktioniert, müssen die Funktionen
in C oder C++ geschrieben sein, und Ihr Betriebssystem muss
dynamisches Laden unterstützen. Die MySQL-Quelldistribution
enthält eine Datei namens
sql/udf_example.cc
, die fünf neue
Funktionen definiert. In dieser Datei können Sie sehen, wie die
Aufrufkonventionen für UDFs funktionieren.
Da eine UDF Code enthält, der zum Teil des laufenden Servers
gehört, müssen Sie beim Schreiben von UDFs alle
Einschränkungen beachten, die auch sonst für das Schreiben von
Servercode gelten. Sie können beispielsweise Probleme bekommen,
wenn Sie versuchen, Funktionen aus der
libstdc++
-Bibliothek zu benutzen. Beachten
Sie, dass sich diese Einschränkungen in zukünftigen Versionen
des Servers noch ändern können. Daher kann es sein, dass Sie
bei einem Server-Upgrade auch Ihre für ältere Serverversionen
geschriebenen UDFs überarbeiten müssen. Informationen über
diese Einschränkungen erhalten Sie unter
Abschnitt 2.8.2, „Typische configure-Optionen“, und
Abschnitt 2.8.4, „Probleme beim Kompilieren?“.
Um UDFs nutzen zu können, müssen Sie mysqld
dynamisch verlinken. Bitte konfigurieren Sie MySQL nicht mit der
Option --with-mysqld-ldflags=-all-static
. Wenn
Sie eine UDF benutzen möchten, die auf Symbole aus
mysqld zugreifen muss (beispielsweise die
metaphone
-Funktion in
sql/udf_example.cc
, die
default_charset_info
braucht), müssen Sie
das Programm mit der Option -rdynamic
verlinken
(siehe man dlopen
). Wenn Sie den Einsatz von
UDFs planen, sollten Sie MySQL grundsätzlich mit
--with-mysqld-ldflags=-rdynamic
konfigurieren,
wenn nichts Wichtiges dagegen spricht.
Wenn Sie eine vorkompilierte Distribution von MySQL einsetzen müssen, so verwenden Sie MySQL-Max: Diese Version enthält einen dynamisch verlinkten Server, der dynamisches Laden unterstützt.
Für jede Funktion, die Sie in SQL-Anweisungen nutzen möchten,
sollten Sie zugehörige C- oder C++-Funktionen definieren. In
den folgenden Ausführungen steht der Name „xxx“
für den Namen einer Beispielfunktion. Um zwischen dem Einsatz
in SQL und C/C++ zu unterscheiden, wird ein Funktionsaufruf in
SQL mit XXX()
(Großbuchstaben) und ein
Funktionsaufruf in C/C++ mit xxx()
(Kleinbuchstaben) angegeben.
Sie schreiben folgende C-/C++-Funktionen, um die Schnittstelle
für XXX()
zu implementieren:
xxx()
(obligatorisch)
Die Hauptfunktion. Hier wird das Ergebnis der Funktion berechnet. Die Entsprechung zwischen dem Datentyp der SQL-Funktion und dem Rückgabetyp der C-/C++-Funktion sehen Sie hier:
SQL-Typ | C-/C++-Typ |
STRING | char * |
INTEGER | long long |
REAL | double |
Es ist auch möglich, eine
DECIMAL
-Funktion zu deklarieren. Da deren
Wert jedoch zurzeit noch als String zurückgeliefert wird,
sollten Sie eine solche UDF wie eine
STRING
-Funktion auslegen.
xxx_init()
(optional)
Die Initialisierungsfunktion für xxx()
.
Sie kann zu folgenden Zwecken benutzt werden:
Um zu prüfen, wie viele Argumente
XXX()
hat.
Um nachzuschauen, ob die Argumente den verlangten Typ haben oder, alternativ, um MySQL anzuweisen, den Argumenten die Typen aufzuzwingen, die für den Aufruf der Hauptfunktion erforderlich sind.
Um den von der Hauptfunktion benötigten Speicher zu reservieren.
Um die maximale Länge der Ergebnismenge anzugeben.
Um (für REAL
-Funktionen) die
Höchstzahl der Dezimalstellen in der Ergebnismenge
anzugeben.
Um mitzuteilen, ob das Ergebnis auch
NULL
sein darf.
xxx_deinit()
(optional)
Die Deinitialisierungsfunktion für
xxx()
. Diese sollte den von der
Initialisierungsfunktion reservierten Speicher wieder
freigeben.
Wenn eine SQL-Anweisung XXX()
aufruft, ruft
MySQL die Initialisierungsfunktion xxx_init()
auf, damit sie die notwendigen Vorbereitungen trifft, wie
beispielsweise eine Überprüfung der Argumente oder die
Speicherzuweisung. Wenn xxx_init()
einen
Fehler zurückliefert, bricht MySQL die SQL-Anweisung mit einer
Fehlermeldung ab und ruft weder die Haupt- noch die
Deinitialisierungsfunktion auf. Ansonsten ruft MySQL nun die
Hauptfunktion xxx()
einmal pro Zeile auf.
Wenn alle Zeilen verarbeitet wurden, ruft MySQL die
Deinitialisierungsfunktion xxx_deinit()
auf,
damit diese die notwendigen Aufräumarbeiten übernehmen kann.
Für Aggregatfunktionen, die wie SUM()
arbeiten, müssen Sie außerdem folgende Funktionen
bereitstellen:
xxx_clear()
(obligatorisch für
5.1)
Setzt den aktuellen Aggregatwert zurück, setzt aber das Argument nicht als Aggregatanfangswert für eine neue Gruppe ein.
xxx_add()
(obligatorisch)
Addiert das Argument zum aktuellen Aggregatwert.
MySQL geht folgendermaßen mit Aggregat-UDFs um:
Es ruft xxx_init()
auf, damit die
Aggregatfunktion den Speicher reserviert, den sie für ihre
Ergebnisse benötigt.
Es sortiert die Tabelle entsprechend dem GROUP
BY
-Ausdruck.
Es ruft für die erste Zeile jeder neuen Gruppe
xxx_clear()
auf.
Es ruft für jede neue Zeile, die zu derselben Gruppe
gehört, xxx_add()
auf.
Es ruft xxx()
auf, um das
Aggregatergebnis zu erhalten, wenn die Gruppe wechselt oder
nachdem die letzte Zeile verarbeitet wurde.
Es wiederholt die Schritte 3 bis 5, bis alle Zeilen verarbeitet sind.
Es ruft xxx_deinit()
auf, damit die UDF
den von ihr reservierten Speicher wieder freigibt.
Alle Funktionen müssen Thread-sicher sein, also nicht nur die
Hauptfunktion, sondern auch die Initialisierungs- und
Deinitialisierungsfunktionen und alle sonstigen Funktionen, die
für Aggregatfunktionen erforderlich sind. Dies hat zur Folge,
dass Sie keine globalen oder statischen Variablen zuweisen
dürfen, die sich ändern! Wenn Sie Arbeitsspeicher benötigen,
weisen Sie ihn mit xxx_init()
zu und geben
ihn mit xxx_deinit()
frei.
Dieser Abschnitt beschreibt die verschiedenen Funktionen, die Sie definieren müssen, um eine einfache UDF anzulegen. Abschnitt 26.3.4, „Hinzufügen einer neuen benutzerdefinierten Funktion“, beschreibt die Reihenfolge, in der MySQL diese Funktionen aufruft.
Die xxx()
-Hauptfunktion sollte so
deklariert werden, wie es in diesem Abschnitt gezeigt wird.
Beachten Sie, dass der Rückgabetyp und die Parameter
unterschiedlich sind, je nachdem, ob Sie die SQL-Funktion
XXX()
in der CREATE
FUNCTION
-Anweisung mit dem Rückgabetyp
STRING
, INTEGER
oder
REAL
deklarieren:
Für STRING
-Funktionen gilt:
char *xxx(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error);
Für INTEGER
-Funktionen gilt:
long long xxx(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error);
Für REAL
-Funktionen gilt:
double xxx(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error);
Die Initialisierungs- und Deinitialisierungsfunktionen werden wie folgt deklariert:
my_bool xxx_init(UDF_INIT *initid, UDF_ARGS *args, char *message); void xxx_deinit(UDF_INIT *initid);
Der Parameter initid
wird an alle drei
Funktionen übergeben. Er verweist auf eine
UDF_INIT
-Struktur, die Informationen
zwischen Funktionen übergibt. Die Bestandteile der
UDF_INIT
-Struktur werden im Folgenden
aufgeführt. Die Initialisierungsfunktion sollte alle
diejenigen Bestandteile ausfüllen, die geändert werden
sollen. (Um einen Standardwert beizubehalten, ändern Sie
einfach nichts.)
my_bool maybe_null
xxx_init()
sollte
maybe_null
auf 1
einstellen, wenn xxx()
den Wert
NULL
zurückliefern kann. Der
Standardwert ist 1
, wenn irgendwelche
Argumente als maybe_null
deklariert
sind.
unsigned int decimals
Die Anzahl der Dezimalstellen rechts vom Dezimalpunkt
(also salopp ausgedrückt: die Nachkommastellen). Der
Standardwert ist die Höchtzahl der Dezimalstellen in den
an die Hauptfunktion übergebenen Argumenten. (Wenn
beispielsweise 1.34
,
1.345
und 1.3
an die
Funktion übergeben werden, wäre der Standardwert 3, da
1.345
3 Nachkommastellen hat.
unsigned int max_length
Die Maximallänge des Ergebnisses. Der Standardwert
max_length
richtet sich nach dem
Ergebnistyp der Funktion. Bei String-Funktionen ist er die
Länge des längsten Arguments; bei Integer-Funktionen ist
er 21 Ziffern. Bei Real-Funktionen ist der Standardwert 13
plus die Anzahl der durch
initid->decimals
vorgegebenen
Dezimalstellen. (Bei numerischen Funktionen sind in der
Länge auch Vorzeichen und Dezimalpunkt inbegriffen.)
Wenn Sie einen Blob-Wert zurückliefern möchten, können
Sie max_length
auf 65 Kbyte oder 16
Mbyte einstellen. Der Speicherplatz wird zwar nicht
reserviert, aber anhand der Länge entscheidet das System,
welcher Datentyp für eine eventuell erforderliche
temporäre Speicherung der Daten verwendet wird.
char *ptr
Ein Zeiger, den die Funktion für ihre eigenen Zwecke
verwenden kann. So können sich die Funktionen
beispielsweise mit initid->ptr
gegenseitig mitteilen, wie viel Speicher sie reservieren
müssen. xxx_init()
sollte den Speicher
reservieren und diesem Zeiger zuweisen.
initid->ptr = allocated_memory;
In xxx()
und
xxx_deinit()
verweisen Sie auf
initid->ptr
, um Speicher zu benutzen
oder freizugeben.
my_bool const_item
xxx_init()
sollte
const_item
auf 1
setzen, wenn xxx()
immer denselben Wert
zurückgibt, und auf 0
, wenn das nicht
der Fall ist.
In diesem Abschnitt erfahren Sie, welche Funktionen Sie definieren müssen, um eine Aggregatfunktion als UDF anzulegen. Abschnitt 26.3.4, „Hinzufügen einer neuen benutzerdefinierten Funktion“, beschreibt die Reihenfolge, in der MySQL diese Funktionen aufruft.
xxx_reset()
Diese Funktion wird aufgerufen, wenn MySQL die erste Zeile
einer neuen Gruppe findet. Sie sollte eventuell vorhandene
interne Summenvariablen zurücksetzen und dann das
gegebene UDF_ARGS
-Argument als ersten
Wert des neuen internen Summenwerts für diese Gruppe
verwenden. xxx_reset()
wird
folgendermaßen deklariert:
char *xxx_reset(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error);
xxx_reset()
wird in MySQL
5.1 weder benötigt noch benutzt. Die
UDF-Schnittstelle verwendet stattdessen
xxx_clear()
. Sie können jedoch
xxx_reset()
zusätzlich zu
xxx_clear()
definieren, wenn Ihre UDF
auch mit älteren Serverversionen laufen soll. (Wenn Sie
beide Funktionen einbeziehen möchten, können Sie
xxx_reset()
intern oft implementieren,
indem Sie zunächst xxx_clear()
alle
Variablen zurücksetzen lassen und dann
xxx_add()
aufrufen, um das Argument
UDF_ARGS
als ersten Wert der Gruppe
hinzuzufügen.)
xxx_clear()
Diese Funktion wird aufgerufen, wenn MySQL die
Summenergebnisse zurücksetzen muss. Sie wird für jede
neue Gruppe ganz am Anfang aufgerufen, kann aber auch
verwendet werden, um die Werte für eine Anfrage
zurückzusetzen, wenn keine übereinstimmenden Zeilen
gefunden wurden. xxx_clear()
wird
folgendermaßen deklariert:
char *xxx_clear(UDF_INIT *initid, char *is_null, char *error);
is_null
wird auf
CHAR(0)
eingestellt, bevor
xxx_clear()
aufgerufen wird.
Wenn etwas schief gegangen ist, können Sie einen Wert in
der Variablen speichern, auf die das Argument
error
verweist.
error
zeigt auf eine
Singlebyte-Variable, nicht auf einen String-Puffer.
xxx_clear()
ist für MySQL
5.1 obligatorisch.
xxx_add()
Diese Funktion wird für alle Zeilen außer der ersten
aufgerufen, die zu derselben Gruppe gehören. Mit ihr
addieren Sie den Wert des Arguments
UDF_ARGS
zu Ihrer internen
Summenvariablen.
char *xxx_add(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error);
Die xxx()
-Funktion für eine Aggregat-UDF
sollte genauso definiert werden wie die für eine einfache
UDF. Siehe hierzu Abschnitt 26.3.4.1, „UDF-Aufrufsequenzen“.
Für eine Aggregat-UDF ruft MySQL die Funktion
xxx()
auf, nachdem alle Zeilen der Gruppe
abgearbeitet sind. Im Normalfall greifen Sie hier niemals auf
ihr UDF_ARGS
-Argument zu, sondern geben
einen Wert zurück, der auf Ihren internen Summenvariablen
beruht.
Rückgabewerte sollten in xxx()
genau wie
bei einer UDF behandelt werden, die keine Aggregatfunktion
ist. Siehe Abschnitt 26.3.4.4, „Rückgabewerte und Fehlerbehandlung“.
Die Funktionen xxx_reset()
und
xxx_add()
gehen mit ihrem
UDF_ARGS
-Argument genauso um wie Funktionen
für Nicht-Aggregat-UDFs. Siehe
Abschnitt 26.3.4.3, „Verarbeitung von Argumenten“.
Die Zeigerargumente für is_null
und
error
sind dieselben wie bei allen Aufrufen
von xxx_reset()
,
xxx_clear()
, xxx_add()
und xxx()
. Das können Sie nutzen, um sich
zu merken, dass ein Fehler ausgelöst wurde oder ob die
xxx()
-Funktion NULL
zurückgeben sollte. Bitte speichern Sie keinen String in
*error
! error
verweist
auf eine Single-Byte-Variable, nicht auf einen String-Puffer.
*is_null
wird für jede Gruppe (vor dem
Aufruf von xxx_clear()
) zurückgesetzt,
*error
nie.
Sind *is_null
oder
*error
gesetzt, wenn
xxx()
zurückkehrt, liefert MySQL
NULL
als Ergebnis der Gruppenfunktion
zurück.
Der Parameter args
verweist auf eine
UDF_ARGS
-Struktur mit folgenden
Bestandteilen:
unsigned int arg_count
Die Anzahl der Argumente. Diesen Wert muss die Initialisierungsfunktion prüfen, wenn Ihre Funktion mit einer bestimmten Anzahl von Argumenten aufgerufen werden muss. Zum Beispiel:
if (args->arg_count != 2) { strcpy(message,"XXX() requires two arguments"); return 1; }
enum Item_result *arg_type
Ein Zeiger auf ein Array, das die Argumenttypen enthält.
Mögliche Typwerte sind STRING_RESULT
,
INT_RESULT
und
REAL_RESULT
.
Um sicherzustellen, dass die Argumente einen bestimmten
Typ haben, und um einen Fehler auszulösen, wenn der Typ
nicht stimmt, muss die Initialisierungsfunktion das Array
arg_type
betrachten. Zum Beispiel:
if (args->arg_type[0] != STRING_RESULT || args->arg_type[1] != INT_RESULT) { strcpy(message,"XXX() requires a string and an integer"); return 1; }
Anstatt zu verlangen, dass die Funktionsargumente
bestimmte Typen haben, können Sie auch mit der
Initialisierungsfunktion die
arg_type
-Elemente auf die gewünschten
Typen einstellen. Dies veranlasst MySQL, den Argumenten
bei jedem Aufruf von xxx()
die
richtigen Typen aufzuzwingen. Um beispielsweise aus dem
ersten Argument einen String und aus dem zweiten einen
Integer zu machen, muss Ihre
xxx_init()
-Funktion Folgendes tun:
args->arg_type[0] = STRING_RESULT; args->arg_type[1] = INT_RESULT;
char **args
args->args
informiert die
Initialisierungsfunktion über das Wesen der an Ihre
Funktion übergebenen Argumente. Bei einem
Konstantenargument i
verweist
args->args[i]
auf den Argumentwert.
(Wie Sie richtig auf diesen Wert zugreifen, erfahren Sie
weiter unten.) Bei einem Nichtkonstantenargument ist
args->args[i]
gleich
0
. Ein Konstantenargument ist ein
Ausdruck, der nur Konstanten verwendet, wie beispielsweise
3
oder 4*7-2
oder
SIN(3.14)
. Ein Nichtkonstantenargument
ist ein Ausdruck, der auf Werte verweist, die sich von
Zeile zu Zeile ändern können, wie etwa Spaltennamen oder
Funktionen, die mit Nichtkonstantenargumenten aufgerufen
werden.
Für jeden Aufruf der Hauptfunktion enthält
args->args
die Argumente, die
tatsächlich an die in Bearbeitung befindliche Zeile
übergeben werden.
Funktionen können folgendermaßen auf ein Argument
i
verweisen:
Ein Argument vom Typ STRING_RESULT
wird als String-Zeiger mit einer Längenangabe
übergeben, damit auch Binärdaten oder Daten von
beliebiger Länge verarbeitet werden können. Der
String-Inhalt ist als
args->args[i]
und die Länge des
Strings als args->lengths[i]
angegeben. Bitte setzen Sie nicht voraus, dass Strings
mit null beendet werden.
Bei Argumenten vom Typ INT_RESULT
müssen Sie args->args[i]
in
einen long long
-Wert umwandeln:
long long int_val; int_val = *((long long*) args->args[i]);
Bei Argumenten vom Typ REAL_RESULT
müssen Sie args->args[i]
in
einen double
-Wert umwandeln:
double real_val; real_val = *((double*) args->args[i]);
unsigned long *lengths
Für die Initialisierungsfunktion zeigt das Array
lengths
die maximale String-Länge für
jedes Argument an. Diese sollten Sie nicht ändern. Für
jeden Aufruf der Hauptfunktion enthält
lengths
die tatsächlichen Längen der
String-Argumente, die an die in Bearbeitung befindliche
Zeile übergeben werden. Für Argumente der Typen
INT_RESULT
oder
REAL_RESULT
enthält
lengths
immer noch die maximale Länge
des Arguments (wie für die Initialisierungsfunktion).
Die Initialisierungsfunktion sollte 0
zurückgeben, wenn kein Fehler auftritt, und ansonsten
1
. Kommt es zu einem Fehler, so sollte
xxx_init()
eine auf null endende
Fehlermeldung im Parameter message
speichern. Die Meldung wird an den Client zurückgegeben. Der
Puffer für Fehlermeldungen ist zwar
MYSQL_ERRMSG_SIZE
Zeichen lang, aber Sie
sollten dennoch versuchen, die Meldungen auf maximal 80
Zeichen zu begrenzen, damit sie auf die Breite eines normalen
Bildschirms passen.
Der Rückgabewert der Hauptfunktion xxx()
ist für long long
-
und double
-Funktionen der Funktionswert.
Eine String-Funktion sollte einen Zeiger auf das Ergebnis
zurückliefern und *result
und
*length
auf den Inhalt und die Länge des
Ergebniswerts einstellen. Zum Beispiel:
memcpy(result, "result string", 13); *length = 13;
Der result
-Puffer, der an die
xxx()
-Funktion übergeben wird, ist 255
Byte lang. Wenn Ihr Ergebnis hineinpasst, müssen Sie sich um
die Speicherzuweisung für Ergebnisse keine Gedanken machen.
Muss Ihre String-Funktion jedoch einen String zurückliefern,
der länger als 255 Byte ist, so müssen Sie den Speicher
dafür reservieren, indem Sie malloc()
in
Ihrer xxx_init()
- oder
xxx()
-Funktion aufrufen und den Speicher
dann in der xxx_deinit()
-Funktion wieder
freigeben. Sie können den reservierten Speicher auch in dem
ptr
-Slot in der
UDF_INIT
-Struktur speichern, um ihn für
zukünftige xxx()
-Aufrufe wiederverwenden
zu können. Siehe Abschnitt 26.3.4.1, „UDF-Aufrufsequenzen“.
Um den Rückgabewert NULL
in der
Hauptfunktion anzuzeigen, setzen Sie
*is_null
auf 1
:
*is_null = 1;
Um anzuzeigen, dass die Hauptfunktion einen Fehler
zurückgibt, setzen Sie *error
auf
1
:
*error = 1;
Wenn xxx()
den Wert von
*error
für irgendeine Zeile auf
1
setzt, ist der Funktionswert für die
aktuelle Zeile und alle folgenden Zeilen, die in der Anweisung
verarbeitet werden, in welcher XXX()
aufgerufen wird, gleich NULL
.
(xxx()
wird für die nachfolgenden Zeilen
noch nicht einmal aufgerufen.)
Dateien, die UDFs implementieren, müssen auf dem Serverhost
kompiliert und installert werden. Dies wird weiter unten für
die Beispiel-UDF-Datei sql/udf_example.cc
aus der MySQL-Quelldistribution beschrieben.
Die nachfolgenden Instruktionen gelten für Unix. Anleitungen für Windows finden Sie weiter unten in diesem Abschnitt.
Die Datei udf_example.cc
enthält die
folgenden Funktionen:
Die Funktion metaphon()
gibt einen
Metaphon-String aus dem String-Argument zurück. Dieser
ist so etwas wie ein Soundex-String, allerdings besser auf
die englische Sprache zugeschnitten.
Die Funktion myfunc_double()
gibt die
Summe der ASCII-Werte der in ihren Argumenten enthaltenen
Zeichen geteilt durch die Summe der Längen dieser
Argumente zurück.
Die Funktion myfunc_int()
gibt die
Summe der Längen ihrer Argumente zurück.
Die Funktion sequence([const int])
gibt
eine Sequenz zurück, die ab der gegebenen Zahl oder, wenn
keine gegeben wurde, ab 1 beginnt.
Die Funktion lookup()
gibt die
IP-Nummer eines Hostnamens zurück.
Die Funktion reverse_lookup()
gibt den
Hostnamen zu einer IP-Nummer zurück. Diese Funktion kann
entweder mit einem einzigen String-Argument der Form
'xxx.xxx.xxx.xxx'
oder mit vier Zahlen
aufgerufen werden.
Eine Datei, die dynamisch zu laden sein soll, sollte als Sharable Object-Datei mit einem Befehl wie diesem kompiliert werden:
shell> gcc -shared -o udf_example.so udf_example.cc
Wenn Sie gcc benutzen, müsste sich
udf_example.so
auch mit einem einfacheren
Befehl anlegen lassen:
shell> make udf_example.so
Die richtigen Compiler-Optionen für Ihr System finden Sie
einfach heraus, indem Sie folgenden Befehl im
sql
-Verzeichnis Ihres MySQL-Quellbaums
laufen lassen:
shell> make udf_example.o
Sie sollten einen ähnlichen Compile-Befehl geben, wie ihn
make anzeigt, allerdings ohne die Option
-c
am Zeilenende. Stattdessen fügen Sie die
Option -o udf_example.so
hinzu. (Auf manchen
Systemen müssen Sie eventuell die Option -c
im Befehl beibehalten.)
Nachdem Sie ein Shared Object für UDFs kompiliert haben,
müssen Sie es installieren und MySQL mitteilen, dass es da
ist. Wenn Sie ein Shared Object aus
udf_example.cc
kompilieren, entsteht eine
Datei, die ungefähr udf_example.so
heißt (der genaue Name ist plattformabhängig). Diese Datei
kopieren Sie in das Plug-In-Verzeichnis des Servers, das Sie
anhand der Systemvariablen plugin_dir
herausfinden können.
(Hinweis: Dies ist eine
Änderung in MySQL 5.1. In früheren Versionen von MySQL
konnte das Shared Object in jedem Verzeichnis liegen, das der
dynamische Linker Ihres Systems untersuchte.)
Auf manchen Systemen erkennt das Programm
ldconfig, das den dynamischen Linker
konfiguriert, ein Shared Object nur dann, wenn sein Name mit
lib
anfängt. In solchen Fällen sollten
Sie eine Datei wie udf_example.so
in
libudf_example.so
umbenennen.
Auf Windows können Sie benutzerdefinierte Funktionen wie folgt kompilieren:
Zuerst benötigen Sie das BitKeeper-Quellarchiv für MySQL 5.1. Siehe Abschnitt 2.8.3, „Installation vom Entwicklungs-Source-Tree“.
In diesem Quellarchiv suchen Sie im Verzeichnis
VC++Files/examples/udf_example
nach
den Dateien udf_example.def
,
udf_example.dsp
und
udf_example.dsw
.
Außerdem schauen Sie im Quellarchiv in das Verzeichnis
sql
und kopieren daraus die Datei
udf_example.cc
in das
VC++Files/examples/udf_example
-Verzeichnis.
Dann benennen Sie die Datei in
udf_example.cpp
um.
Öffnen Sie die Datei udf_example.dsw
mit Visual Studio VC++ und kompilieren Sie damit die UDFs
als ganz normales Projekt.
Sobald die Shared Object-Datei installiert ist, teilen Sie mysqld die neuen Funktionen mit folgenden Anweisungen mit:
mysql>CREATE FUNCTION metaphon RETURNS STRING SONAME 'udf_example.so';
mysql>CREATE FUNCTION myfunc_double RETURNS REAL SONAME 'udf_example.so';
mysql>CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME 'udf_example.so';
mysql>CREATE FUNCTION lookup RETURNS STRING SONAME 'udf_example.so';
mysql>CREATE FUNCTION reverse_lookup
->RETURNS STRING SONAME 'udf_example.so';
mysql>CREATE AGGREGATE FUNCTION avgcost
->RETURNS REAL SONAME 'udf_example.so';
Zum Löschen von Funktionen verwenden Sie DROP
FUNCTION
:
mysql>DROP FUNCTION metaphon;
mysql>DROP FUNCTION myfunc_double;
mysql>DROP FUNCTION myfunc_int;
mysql>DROP FUNCTION lookup;
mysql>DROP FUNCTION reverse_lookup;
mysql>DROP FUNCTION avgcost;
Die Anweisungen CREATE FUNCTION
und
DROP FUNCTION
nehmen Änderungen in der
Systemtabelle func
in der
mysql
-Datenbank vor. Der Name, Typ und
Shared Library-Name werden in dieser Tabelle gespeichert.
Daher benötigen Sie INSERT
- und
DELETE
-Rechte für die
mysql
-Datenbank, um dort Funktionen
anzulegen und zu löschen.
Bitte verwenden Sie CREATE FUNCTION
nicht,
um eine Funktion hinzuzufügen, die bereits angelegt ist. Wenn
Sie eine Funktion neu installieren müssen, entfernen Sie sie
mit DROP FUNCTION
und installieren sie dann
mit CREATE FUNCTION
neu. Das müssen Sie
beispielsweise tun, wenn Sie eine neue Version Ihrer Funktion
installieren, damit auch mysqld von der
neuen Version weiß. Ansonsten würde der Server weiterhin die
alte Version verwenden.
Eine aktive Funktion ist eine Funktion, die mit
CREATE FUNCTION
geladen, aber nicht mit
DROP FUNCTION
entfernt wurde. Alle aktiven
Funktionen werden bei jedem Serverstart neu geladen, es sei
denn, Sie fahren mysqld mit der Option
--skip-grant-tables
hoch. In diesem Fall wird
die UDF-Initialisierung übersprungen und die UDFs stehen
nicht zur Verfügung.
MySQL verhindert durch folgende Maßnahmen den Missbrauch benutzerdefinierter Funktionen:
Sie benötigen das INSERT
-Recht, um
CREATE FUNCTION
, und das
DELETE
-Recht, um DROP
FUNCTION
sagen zu dürfen. Die Berechtigungen sind
erforderlich, weil diese Anweisungen Zeilen der
mysql.func
-Tabelle anlegen und löschen.
Für UDFs sollte zusätzlich zu dem
xxx
-Symbol für die Hauptfunktion
xxx()
mindestens ein weiteres Symbol
definiert sein. Diese Hilfssymbole stehen für die Funktionen
xxx_init()
,
xxx_deinit()
,
xxx_reset()
, xxx_clear()
und xxx_add()
. mysqld
unterstützt überdies eine
--allow-suspicious-udfs
-Option, die steuert,
ob UDFs, die nur das eine xxx
-Symbol haben,
überhaupt geladen werden dürfen. Nach Voreinstellung ist die
Option ausgeschaltet, um zu verhindern, dass aus Shared
Object-Dateien Funktionen geladen werden, die keine gültigen
UDFs sind. Wenn Sie noch mit älteren UDFs arbeiten, die
lediglich das xxx
-Symbol haben und nicht
mit einem Hilfssymbol rekompiliert werden können, kann es
notwendig werden, die Option
--allow-suspicious-udfs
anzugeben. Ansonsten
sollten Sie diese Option möglichst nicht einschalten.
Objektdateien für UDFs dürfen nicht in jedes beliebige
Verzeichnis gelegt werden, sondern nur in das
Plug-In-Verzeichnis des Servers, das Sie am Wert der
Systemvariablen plugin_dir
erkennen
können. (Hinweis: Dies ist
neu in MySQL 5.1. In früheren Versionen von MySQL konnte das
Shared Object in jedem Verzeichnis platziert werden, das der
dynamische Linker des Systems untersuchte.)
Hier wird erklärt, wie Sie vorgehen müssen, um eine neue native Funktion hinzuzufügen. Beachten Sie, dass Sie native Funktionen nicht in eine Binärdistribution einfügen können, da ein Eingriff in den Quellcode von MySQL notwendig ist. Sie müssen MySQL also selbst aus einer Quelldistribution kompilieren. Außerdem müssen Sie bei einer Umstellung auf eine andere MySQL-Version (beispielsweise wenn eine neue Version herauskommt) daran denken, die gesamte Prozedur mit der neuen Version zu wiederholen.
Um eine neue native MySQL-Funktion hinzuzufügen, verfahren Sie folgendermaßen:
Sie binden in lex.h
eine neue Zeile
ein, die den Namen der Funktion im Array
sql_functions[]
definiert.
Wenn der Funktionsprototyp einfach ist (nur null, ein, zwei
oder drei Argumente hat), geben Sie in
lex.h
als zweites Argument im Array
sql_functions[]
den Wert
SYM(FUNC_ARG
an (wobei N
)N
die Anzahl der
Argumente ist) und fügen eine Funktion hinzu, die ein
Funktionsobjekt in item_create.cc
erzeugt. Als Beispiele dafür können Sie sich
"ABS"
und
create_funcs_abs()
anschauen.
Ist der Funktionsprototyp komplizierter (wenn beispielsweise
die Funktion eine variable Anzahl Argumente entgegennimmt),
müssen Sie zwei neue Zeilen in
sql_yacc.yy
einfügen: Die eine gibt
ein Präprozessorsymbol an, das yacc
definieren sollte (diese sollte an den Anfang der Datei
eingefügt werden). Dann definieren Sie die
Funktionsparameter und fügen ein „item“ mit
diesen Parametern zu der Parsing-Regel für
simple_expr
Parametern hinzu. Als
Beispiel dafür, wie dies getan wird, können Sie die
diversen Exemplare von ATAN
in
sql_yacc.yy
anschauen.
Deklarieren Sie in item_func.h
eine
Klasse, die aus Item_num_func
oder
Item_str_func
erbt, je nachdem, ob Ihre
Funktion eine Zahl oder einen String zurückgibt.
In item_func.cc
fügen Sie eine der
folgenden Deklarationen ein, je nachdem, ob Sie eine
numerische oder eine String-Funktion definieren:
double Item_func_newname::val() longlong Item_func_newname::val_int() String *Item_func_newname::Str(String *str)
Wenn Sie Ihr Objekt aus einem der Standardelemente erben
(wie etwa Item_num_func
), müssen Sie
wahrscheinlich nur eine dieser Funktionen definieren und es
dann dem Parent-Objekt überlassen, sich um die übrigen
Funktionen zu kümmern. So definiert zum Beispiel die Klasse
Item_str_func
eine
val()
-Funktion, die
atof()
auf dem Rückgabewert von
::str()
ausführt.
Außerdem müssen Sie wahrscheinlich folgende Objektfunktion definieren:
void Item_func_newname::fix_length_and_dec()
Diese Funktion sollte zumindest
max_length
anhand der gegebenen Argumente
berechnen. max_length
gibt an, wie viele
Zeichen die Funktion höchstens zurückgeben kann. Diese
Funktion sollte überdies maybe_null = 0
einstellen, wenn die Hauptfunktion keinen
NULL
-Wert zurückgeben kann. Ob
irgendwelche Funktionsargumente NULL
zurückgeben könnten, prüft die Funktion anhand der
maybe_null
-Variablen dieser Argumente.
Ein typisches Beispiel dafür finden Sie in
Item_func_mod::fix_length_and_dec
.
Alle Funktionen müssen Thread-sicher sein. Mit anderen Worten: Sie dürfen keine globalen oder statischen Variablen in diesen Funktionen benutzen, ohne sie durch Mutex-Objekte zu schützen.
Wenn Sie NULL
aus einer
::val()
-, ::val_int()
-
oder ::str()
-Funktion zurückgeben möchten,
müssen Sie null_value
auf 1 setzen und 0
zurückliefern.
Für ::str()
-Objektfunktionen müssen Sie
sich darüber hinaus Folgendes merken:
Das String *str
-Argument liefert einen
String-Puffer, der genutzt werden kann, um das Ergebnis zu
speichern. (Um mehr über den Typ String
zu erfahren, werfen Sie einen Blick in die Datei
sql_string.h
.)
Die ::str()
-Funktion sollte den String
zurückgeben, der das Resultat speichert, oder
(char*) 0
, wenn das Resultat
NULL
ist.
Alle gegenwärtigen String-Funktionen versuchen, nur dann Speicher zu reservieren, wenn es absolut unumgänglich ist!
In MySQL können Sie mit der Sprache C++ eine Prozedur definieren,
die Daten in einer Anfrage betrachten und ändern kann, ehe sie
sie an den Client sendet. Diese Änderung kann zeilenweise oder
auf der Ebene von GROUP BY
erfolgen.
Wir haben eine Beispielprozedur geschrieben, um zu zeigen, was alles möglich ist.
Außerdem empfehlen wir Ihnen, einen Blick auf
mylua
zu werfen. Damit können Sie nämlich die
Sprache LUA einsetzen, um eine Prozedur zur Laufzeit in
mysqld zu laden.
analyse([
max_elements
,[max_memory
]])
Diese Prozedur ist in der Datei
sql/sql_analyse.cc
definiert. Sie
untersucht ein Anfrageergebnis und gibt eine Analyse der
Resultate zurück:
max_elements
(Standardwert 256)
ist die Höchstzahl unterschiedlicher Werte, die
analyse
pro Spalte erkennen kann. Diesen
Wert verwendet analyse
, um zu prüfen, ob
ENUM
der optimale Datentyp wäre.
max_memory
(Standardwert 8192)
ist der größtmögliche Speicher, den
analyse
pro Spalte zuweisen kann,
während die Prozedur versucht, alle unterschiedlichen Werte
zu finden.
SELECT ... FROM ... WHERE ... PROCEDURE ANALYSE([max_elements
,[max_memory
]])
Inhaltsverzeichnis
Access denied
-FehlerCan't connect to [local] MySQL server
-FehlerClient does not support authentication protocol
Host '...' is blocked
-FehlerToo many connections
-FehlerNo free memory
-FehlerMySQL server has gone away
-FehlerPacket too large
-FehlerThe table is full
-FehlerCan't create/write to file
-FehlerCommand out of sync
-Fehler in ClientUser ignored
-FehlerTable 'xxx' doesn't exist
-FehlerCan't initialize charset xxx
-Fehler/tmp/mysql.sock
schützen oder ändernDATE
-SpaltenNULL
-Wertenalias
In diesem Anhang sind einige häufige Probleme und Fehlermeldungen aufgeführt, auf die Sie vielleicht stoßen werden. Außerdem wird beschrieben, wie man die Fehlerursachen findet und die Probleme behebt.
Wenn Sie auf ein Problem stoßen, müssen Sie als Erstes herausfinden, von welchem Programm oder Hardwareteil es verursacht wird.
Die folgenden Symptome sprechen für Probleme mit der Hardware (Arbeitsspeicher, Motherboard, CPU oder Festplatte) oder mit dem Kernel:
Die Tastatur funktioniert nicht. Dies lässt sich normalerweise durch Drücken der Feststelltaste herausfinden. Wenn sich das Feststell-Licht dabei nicht ändert, müssen Sie Ihre Tastatur austauschen. (Bevor Sie das tun, sollten Sie allerdings den Computer neu starten und alle Kabelverbindungen der Tastatur überprüfen.)
Der Mauszeiger bewegt sich nicht.
Der Computer antwortet nicht auf die Ping-Versuche eines Remote-Computers.
Andere Programme, die nichts mit MySQL zu tun haben, funktionieren ebenfalls nicht.
Ihr System führt überraschend einen Neustart durch. (Ein fehlerhaftes Benutzerprogramm darf nie in der Lage sein, Ihr System herunterzufahren.)
In diesem Fall überprüfen Sie als Erstes alle Ihre Kabel und
lassen ein Diagnosetool laufen, um Ihre Hardware zu
überprüfen. Außerdem schauen Sie nach, ob es irgendwelche
Patches, Updates oder Service Packs für Ihr Betriebssystem
gibt, die Ihr Problem lösen könnten. Auch die Aktualität
Ihrer Bibliotheken (zum Beispiel glibc
)
muss überprüft werden.
Es ist immer gut, einen Computer mit ECC-Memory zu überprüfen, um eventuelle Arbeitsspeicherprobleme frühzeitig zu finden.
Wenn Ihre Tastatur gesperrt ist, können Sie dies vielleicht
beheben, indem Sie sich von einem anderen Computer aus auf
Ihrem Rechner anmelden und kbd_mode -a
ausführen.
Bitte fahnden Sie in Ihrem Systemlog
(/var/log/messages
oder ähnlich) nach
Ursachen für Ihr Problem. Wenn Sie denken, dass es an MySQL
liegt, sollten Sie auch die Logdateien von MySQL untersuchen.
Siehe Abschnitt 5.12, „Die MySQL-Logdateien“.
Wenn Sie nicht der Ansicht sind, dass es sich um ein Hardwareproblem handelt, müssen Sie herausfinden, welches Programm die Probleme macht. Mit top, ps, Task-Manager oder einem ähnlichen Tool können Sie nachschauen, welches Programm die gesamte CPU mit Beschlag belegt oder den Computer sperrt.
Mit top, df oder einem ähnlichen Programm können Sie prüfen, ob Arbeitsspeicher, Festplattenplatz, Dateideskriptoren oder eine andere wichtige Ressource ausgeht.
Ist das Problem ein außer Kontrolle geratener Prozess, können Sie versuchen, diesen anzuhalten. Wenn er sich weigert, liegt wahrscheinlich ein Fehler im Betriebssystem vor.
Wenn Sie nach gründlicher Prüfung aller anderen Möglichkeiten zu dem Schluss kommen, dass der MySQL Server oder ein MySQL-Client das Problem verursacht hat, ist es an der Zeit, einen Bugreport für unsere Mailingliste oder unser Support-Team zu verfassen. Bitte beschreiben Sie darin sehr genau, wie sich das System verhält und was Ihrer Meinung nach vorgeht. Außerdem schreiben Sie bitte Ihre Einschätzung, was die Wurzel des Problems sein könnte. Bitte berücksichtigen Sie alle im vorliegenden Kapitel beschriebenen Situationen und sagen Sie genau, wie die Probleme auftreten, wenn Sie Ihr System überprüfen. Ausgabe und Fehlermeldungen von Programmen und Logdateien können Sie mit „Kopieren und Einfügen“ in Ihren Fehlerbericht übernehmen.
Versuchen Sie, detailliert zu beschreiben, welches Programm nicht funktioniert und welche Symptome vorhanden sind. Wir haben schon viele Bugreports gesehen, in denen es lediglich hieß: „Das System funktioniert nicht“. So bekommen wir keine Informationen, die uns helfen, das Problem zu beheben.
Wenn ein Programm abstürzt, sind folgende Informationen nützlich:
Hat das Programm einen Segmentierungsfehler gemacht (hat es einen Core Dump erstellt)?
Belegt das Programm sämtliche Prozessorzeit? Dies können Sie mit top überprüfen. Lassen Sie das Programm für eine Weile laufen, vielleicht führt es ja nur gerade eine rechenintensive Operation durch.
Wenn der mysqld-Server Probleme macht: Können Sie mit mysqladmin -u root ping oder mysqladmin -u root processlist irgendeine Antwort von ihm bekommen?
Was sagt Ihr Clientprogramm, wenn Sie versuchen, sich mit dem MySQL Server zu verbinden? (Versuchen Sie es zum Beispiel mit mysql.) Blockiert der Client? Gibt das Programm irgendetwas aus?
Wenn Sie uns einen Bugreport schicken, halten Sie sich bitte an die in Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“, beschriebene Vorgehensweise.
Access denied
-FehlerCan't connect to [local] MySQL server
-FehlerClient does not support authentication protocol
Host '...' is blocked
-FehlerToo many connections
-FehlerNo free memory
-FehlerMySQL server has gone away
-FehlerPacket too large
-FehlerThe table is full
-FehlerCan't create/write to file
-FehlerCommand out of sync
-Fehler in ClientUser ignored
-FehlerTable 'xxx' doesn't exist
-FehlerCan't initialize charset xxx
-FehlerIn diesem Abschnitt werden einige Fehler beschrieben, auf die Benutzer häufig bei der Ausführung von MySQL-Programmen stoßen. Die Probleme zeigen sich zwar bei der Ausführung von Clientprogrammen, aber die Lösung ist in vielen Fällen eine Konfigurationsänderung des MySQL Servers.
Ein Access denied
-Fehler kann viele Ursachen
haben. Oft hängt er damit zusammen, welchen MySQL-Konten der
Server die Benutzung von Clientprogrammen gestattet. Siehe
Abschnitt 5.8.8, „Gründe für Access denied
-Fehler“, und
Abschnitt 5.8.2, „Wie das Berechtigungssystem funktioniert“.
Auf Unix hat ein MySQL-Client zwei Möglichkeiten, sich mit dem
mysqld-Server zu verbinden: Entweder
verwendet er eine Unix-Socketdatei (nach Voreinstellung
/tmp/mysql.sock
), um sich über eine Datei
im Dateisystem zu verbinden, oder er verwendet TCP/IP, um sich
über eine Portnummer zu verbinden. Eine Verbindung über eine
Unix-Socketdatei ist schneller als TCP/IP, kann aber nur genutzt
werden, wenn sich der Client mit einem Server auf demselben
Computer verbindet. Der Weg über die Unix-Socketdatei wird
gewählt, wenn Sie keinen Hostnamen oder
localhost
angeben.
Wenn der MySQL Server auf Windows 9x oder Me läuft, können Sie
sich nur per TCP/IP verbinden. Wenn er auf Windows NT, 2000, XP
oder 2003 läuft und mit der Option
--enable-named-pipe
gestartet wird, können Sie
sich auch mit Named Pipes verbinden, wenn der Client auf
demselben Host wie der Server läuft. Der Name der Named Pipe
ist nach Voreinstellung MySQL
. Wenn Sie für
die Verbindung mit mysqld keinen Hostnamen
angeben, versucht ein MySQL-Client als Erstes eine Verbindung
mit der Named Pipe. Wenn das nicht klappt, verbindet er sich mit
dem TCP/IP-Port. Indem Sie .
als Hostnamen
angeben, zwingen Sie Windows zur Verwendung von Named Pipes.
Der Fehler (2002) Can't connect to ...
bedeutet normalerweise, dass auf dem System kein MySQL Server
läuft oder dass Sie bei Ihrem Verbindungsversuch einen
verkehrten Unix-Socketdateinamen oder TCP/IP-Port angegeben
haben.
Prüfen Sie als Erstes, ob auf Ihrem Serverhost ein Prozess namens mysqld läuft. (Hierzu verwenden Sie auf Unix ps xa | grep mysqld und auf Windows den Task- Manager.) Wenn kein solcher Prozess läuft, starten Sie den Server. Siehe hierzu Abschnitt 2.9.2.3, „Probleme mit dem Start des MySQL Servers“.
Läuft ein mysqld-Server,
so überprüfen Sie ihn mit den folgenden Befehlen. Die
Portnummer oder der Name der Unix-Socketdatei können in Ihrem
Fall abweichen. host_ip
ist die IP-Nummer des
Computers, auf welchem der Server ausgeführt wird.
shell>mysqladmin version
shell>mysqladmin variables
shell>mysqladmin -h `hostname` version variables
shell>mysqladmin -h `hostname` --port=3306 version
shell>mysqladmin -h host_ip version
shell>mysqladmin --protocol=socket --socket=/tmp/mysql.sock version
Beachten Sie, dass Backticks anstelle von Anführungszeichen
für den hostname
-Befehl verwendet werden.
Diese sorgen dafür, dass die Ausgabe von
hostname
(also des aktuellen Hostnamens) in
den Befehl mysqladmin eingesetzt wird. Wenn
Sie keinen hostname
-Befehl zur Verfügung
haben oder mit Windows arbeiten, können Sie den Hostnamen Ihres
Computers hinter der Option -h
manuell
eingeben (ohne Backticks). Oder Sie versuchen, sich mit
-h 127.0.0.1
über TCP/IP mit dem lokalen
Host zu verbinden.
Der Fehler Can't connect to local MySQL
server
könnte aus folgenden Gründen auftreten:
mysqld läuft nicht. Vergewissern Sie sich, ob der Prozess mysqld in der Prozessliste Ihres Betriebssystems auftaucht.
Sie führen einen MySQL Server auf Windows mit vielen
TCP/IP-Verbindungen aus. Wenn es häufiger vorkommt, dass
Ihre Clients diesen Fehler melden, finden Sie an folgender
Stelle einen Workaround:
Abschnitt A.2.2.1, „Connection to MySQL server failing on Windows
-Fehler“.
Ihr System verwendet MIT-pthreads. Wenn Sie auf einem System arbeiten, das keine nativen Threads kennt, verwendet mysqld das Package MIT-pthreads (siehe Abschnitt 2.1.1, „Betriebssysteme, die von MySQL unterstützt werden“). Allerdings unterstützen nicht alle MIT-pthreads Unix-Socketdateien. Auf einem System ohne Socketdateiunterstützung müssen Sie bei einer Serververbindung den Hostnamen immer explizit angeben. Versuchen Sie, mit folgendem Befehl die Serververbindung zu überprüfen:
shell> mysqladmin -h `hostname` version
Jemand hat die von mysqld verwendete
Unix-Socketdatei entfernt (standardmäßig
/tmp/mysql.sock
). Vielleicht haben Sie
ja einen cron-Job, der alte Dateien aus
dem Verzeichnis /tmp
löscht. Mit
mysqladmin version können Sie sich
vergewissern, dass die Unix-Socketdatei, die
mysqladmin benötigt, auch tatsächlich
existiert. Wenn dies das Problem ist, müssen Sie den
cron-Job so abändern, dass er
mysql.sock
nicht mehr entfernt, oder
die Socketdatei an einen anderen Ort verlagern. Siehe
Abschnitt A.4.5, „Wie Sie die MySQL-Socketdatei /tmp/mysql.sock
schützen oder ändern“.
Sie haben den mysqld-Server zwar mit der
Option --socket=/path/to/socket
gestartet,
aber vergessen, den Clientprogrammen den neuen Namen der
Socketdatei mitzuteilen. Wenn Sie den Socketpfadnamen für
den Server ändern, müssen Sie auch die MySQL-Clients
entsprechend benachrichtigen. Dies erledigen Sie, indem Sie
dieselbe --socket
-Option einsetzen, wenn
Sie die Clientprogramme ausführen. Außerdem müssen Sie
gewährleisten, dass die Clients ein Zugriffsrecht auf die
mysql.sock
-Datei haben. Um
herauszufinden, wo die Socketdatei liegt, tun Sie Folgendes:
shell> netstat -ln | grep mysql
Siehe Abschnitt A.4.5, „Wie Sie die MySQL-Socketdatei /tmp/mysql.sock
schützen oder ändern“.
Sie arbeiten auf Linux und ein Server-Thread ist ausgefallen
(mit Core Dump). In diesem Fall müssen Sie auch die anderen
mysqld-Threads anhalten (zum Beispiel mit
kill
oder mit dem
mysql_zap
-Skript), bevor Sie den MySQL
Server neu starten können. Siehe
Abschnitt A.4.2, „Was zu tun ist, wenn MySQL andauernd abstürzt“.
Der Server oder das Clientprogramm hat nicht die richtigen
Zugriffsberechtigungen für das Verzeichnis mit der
Unix-Socketdatei oder der Socketdatei selbst. In diesem Fall
müssen Sie die Berechtigungen so ändern, dass der Server
und die Clients an diese Dateien herankommen, oder
mysqld mit einer
--socket
-Option neu starten, die eine
Socketdatei in einem Verzeichnis angibt, wo der Server sie
anlegen kann und die Clients auf sie zugreifen können.
Wenn Sie die Fehlermeldung Can't connect to MySQL
server on some_host
bekommen, können Sie mit
folgenden Mitteln herausfinden, wo das Problem liegt:
Prüfen Sie, ob der Server auf diesem Host läuft, indem Sie
telnet some_host 3306
ausführen und dann
die Eingabetaste einige Male drücken. (3306 ist die
Standardnummer für den MySQL-Port. Ändern Sie den Wert,
wenn Ihr Server einen anderen Port verwendet.) Wenn ein
MySQL Server auf diesem Port läuft und lauscht, müssten
Sie eine Antwort bekommen, die auch die Versionsnummer des
Servers angibt. Erhalten Sie stattdessen einen Fehler wie
beispielsweise telnet: Unable to connect to remote
host: Connection refused
, dann ist auf dem
angegebenen Port kein Server zu erreichen.
Wenn der Server auf dem lokalen Host läuft, können Sie
versuchen, sich per mysqladmin -h localhost
variables über die Unix-Socketdatei zu verbinden.
Überprüfen Sie, auf welcher TCP/IP-Portnummer der Server
lauscht (also den Wert der Variablen
port
).
Vergewissern Sie sich, dass der
mysqld-Server nicht mit der Option
--skip-networking
gestartet wurde.
Ansonsten können Sie sich nicht per TCP/IP verbinden.
Vergewissern Sie sich, dass keine Firewall den Zugriff auf MySQL verhindert. Anwendungen wie ZoneAlarm und die Windows XP-Firewall müssen unter Umständen speziell konfiguriert werden, damit sie den externen Zugriff auf einen MySQL Server erlauben.
Wenn Sie einen MySQL Server auf Windows mit vielen
TCP/IP-Verbindungen ausführen und Ihre Clients häufig einen
Can't connect to MySQL server
-Fehler
melden, könnte es sein, dass Windows nicht genügend
vorübergehende (kurzlebige) Ports erlaubt, um diese
Verbindungen zu ermöglichen.
Nach Voreinstellung gestattet Windows 5000 vorübergehende
(kurzlebige) TCP-Ports. Wenn ein Port geschlossen wird,
verbleibt er 120 Sekunden lang in einem
TIME_WAIT
-Status. Wird die Verbindung in
diesem Status wiederverwendet, so entstehen viel weniger
Kosten als bei der Einrichtung einer neuen Verbindung.
Allerdings steht der Port vor Ablauf dieser Zeit nicht zur
Verfügung.
Wenn Sie nur einen kleinen Vorrat verfügbarer TCP-Ports
(5000) haben und viele dieser Ports in kurzer Zeit geöffnet
und mit dem TIME_WAIT
-Status wieder
geschlossen werden, kann es leicht passieren, dass Ihnen die
Ports ausgehen. Es gibt zwei Möglichkeiten, dieses Problem in
den Griff zu bekommen:
Sie sorgen dafür, dass die TCP-Ports nicht so schnell aufgebraucht werden, indem Sie, wo immer es möglich ist, Verbindungspooling oder persistente Verbindungen in Betracht ziehen.
Sie ändern einige Einstellungen in der Windows-Registrierung (siehe weiter unten).
Wichtig: Im folgenden Verfahren wird die Windows-Registrierung geändert. Bevor Sie dies tun, müssen Sie Ihre Registrierung unbedingt sichern und genau wissen, wie Sie sie wiederherstellen können, falls etwas geschieht. Wie man die Registrierung sichert, wiederherstellt und bearbeitet, verrät Ihnen folgender Artikel aus der Microsoft Knowledge Base: http://support.microsoft.com/kb/256986/EN-US/.
Starten Sie den Registrierungs-Editor
(Regedt32.exe
).
Suchen Sie folgenden Registrierungsschlüssel:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
Klicken Sie im Menü Bearbeiten
auf
Wert hinzufügen
und fügen Sie dann
folgenden Registrierungswert ein:
Value Name: MaxUserPort Data Type: REG_DWORD Value: 65534
Dieser Wert stellt ein, wie viele vorübergehende Ports einem Benutzer zur Verfügung stehen. Der zulässige Wertebereich liegt zwischen 5000 und 65534 (Dezimalsystem). Der Standardwert ist 0x1388 (5000 dezimal).
Klicken Sie im Menü Bearbeiten
auf
Wert hinzufügen
und fügen Sie dann
folgenden Registrierungswert hinzu:
Value Name: TcpTimedWaitDelay Data Type: REG_DWORD Value: 30
Hiermit stellen Sie ein, wie viele Sekunden eine
Verbindung mit einem TCP-Port im
TIME_WAIT
-Status verbleibt, ehe sie
geschlossen wird. Der zulässige Wertebereich liegt
zwischen 0 (null) und 300 (dezimal). Der Standardwert ist
0x78 (120 dezimal).
Schließen Sie den Registrierungs-Editor.
Starten Sie den Computer neu.
Hinweis: Um die obigen Änderungen rückgängig zu machen, löschen Sie einfach die Registrierungseinträge, die Sie erstellt haben.
MySQL 5.1 verwendet ein Authentifizierungsprotokoll, das auf einem Passwort-Hash-Algorithmus basiert, der mit älteren Clients (vor Version 4.1) inkompatibel ist. Wenn Sie den Server von 4.1 auf die neue Version aufrüsten, können Verbindungsversuche mit einem älteren Client folgenden Fehler verursachen:
shell> mysql
Client does not support authentication protocol requested
by Server; consider upgrading MySQL client
Für dieses Problem gibt es folgende Lösungsansätze:
Sie aktualisieren alle Clientprogramme, sodass sie die Clientbibliothek von 4.1.1 oder eine neuere Version benutzen.
Wenn Sie mit einem Clientprogramm einer Version vor 4.1 auf den Server zugreifen, verwenden Sie ein Konto, das noch ein Passwort aus der Zeit von vor 4.1 hat.
Stellen Sie das Passwort für Benutzer, die ein älteres
Clientprogramm als 4.1 verwenden, im Stil der Version von
vor 4.1 ein. Dies können Sie mit der SET
PASSWORD
-Anweisung oder der
OLD_PASSWORD()
-Funktion tun:
mysql>SET PASSWORD FOR
->'
some_user
'@'some_host
' = OLD_PASSWORD('newpwd
');
Alternativ können Sie auch UPDATE
und
FLUSH PRIVILEGES
einsetzen:
mysql>UPDATE mysql.user SET Password = OLD_PASSWORD('
->newpwd
')WHERE Host = '
mysql>some_host
' AND User = 'some_user
';FLUSH PRIVILEGES;
In diesen Beispielen müssen Sie
„newpwd
“ durch das
neue, von Ihnen gewählte Passwort ersetzen. Da MySQL Ihnen
das Originalpasswort nicht verraten kann, müssen Sie ein
neues aussuchen.
Veranlassen Sie den Server, den älteren Passwort-Hashing-Algorithmus zu verwenden:
Starten Sie mysqld mit der Option
--old-passwords
.
Weisen Sie jedem Konto, dessen Passwort auf das längere 4.1-Fomat umgestellt wurde, ein Passwort im alten Format zu. Welche Konten das sind, verrät Ihnen folgende Anfrage:
mysql>SELECT Host, User, Password FROM mysql.user
->WHERE LENGTH(Password) > 16;
Für jeden Konteneintrag, den der Server zeigt, nehmen
Sie die Werte Host
und
User
und weisen mit der Funktion
OLD_PASSWORD()
und SET
PASSWORD
oder UPDATE
ein
neues Passwort zu, wie oben beschrieben.
Hinweis: In älteren
PHP-Versionen unterstützt die
mysql
-Erweiterung nicht das
Authentifizierungsprotokoll von MySQL 4.1.1 und höher. Das gilt
unabhängig von der verwendeten PHP-Version. Wenn Sie die
mysql
-Erweiterung mit MySQL 4.1 oder höher
nutzen möchten, müssen Sie unter Umständen einen der oben
beschriebenen Wege einschlagen, um MySQL für ältere Clients zu
konfigurieren. Die mysqli
-Erweiterung (die in
PHP 5 für "MySQL, Improved" steht) ist kompatibel mit dem
verbesserten Passwort-Hashing von MySQL 4.1 und höher. Hier ist
keine spezielle Konfiguration für MySQL erforderlich, um diese
MySQL-Clientbibliothek nutzen zu können. Weitere Informationen
über die mysqli
-Erweiterung finden Sie unter
http://php.net/mysqli.
Unter Umständen kann auch die ältere
mysql
-Erweiterung mit der neuen
MySQL-Clientbibliothek kompiliert werden. Dieser Vorgang ist
jedoch nicht Thema unseres Referenzhandbuchs. Weitere
Informationen finden Sie in der PHP-Dokumentation. Eventuell
können Sie in solchen Fragen auch im
MySQL with PHP
forum Hilfe finden.
Hintergrundinformationen über Passwort-Hashing und Authentifizierung gibt es unter Abschnitt 5.8.9, „Kennwort-Hashing ab MySQL 4.1“.
MySQL-Clientprogramme fordern zur Eingabe eines Passworts auf,
wenn sie mit der Option --password
oder
-p
ohne einen Passwortwert dahinter aufgerufen
werden:
shell> mysql -u user_name
-p
Enter password:
Auf manchen Systemen kann es vorkommen, dass das Passwort
funktioniert, wenn man es in einer Optionsdatei oder auf der
Kommandozeile angibt, aber nicht, wenn man es interaktiv am
Enter password:
-Prompt eintippt. Dies
geschieht, wenn die Bibliothek, die das System zum Lesen von
Passwörtern zur Verfügung stellt, die Passwortwerte auf eine
geringe Zeichenzahl einschränkt (in der Regel 8 Zeichen).
Dieses Problem betrifft nicht MySQL, sondern die
Systembibliothek. Um es zu lösen, müssen Sie entweder Ihr
MySQL-Passwort auf einen Wert kürzen, der nur 8 Zeichen lang
ist, oder es in eine Optionsdatei setzen.
Wenn folgender Fehler gemeldet wird, bedeutet dies, dass
mysqld vom Host
'
viele
Verbindungsanforderungen empfangen hat, die in der Mitte
unterbrochen wurden:
host_name
'
Host 'host_name
' is blocked because of many connection errors.
Unblock with 'mysqladmin flush-hosts'
Wie viele unterbrochene Anforderungen maximal zulässig sind,
ist in der Systemvariablen max_connect_errors
festgelegt. Nach max_connect_errors
gescheiterten Anforderungen nimmt mysqld an,
dass etwas nicht in Ordnung ist (beispielsweise ein
Einbruchsversuch), und blockiert weitere Verbindungen dieses
Hosts, bis Sie einen mysqladmin
flush-hosts-Befehl oder eine FLUSH
HOSTS
-Anweisung geben. Siehe
Abschnitt 5.2.2, „Server-Systemvariablen“.
Nach Voreinstellung blockiert mysqld einen Host nach 10 Verbindungsfehlern. Diesen Wert können Sie ändern, indem Sie den Server folgendermaßen starten:
shell> mysqld_safe --max_connect_errors=10000 &
Wenn Sie diese Fehlermeldung für einen Host bekommen, prüfen
Sie als Erstes, ob mit den TCP/IP-Verbindungen von diesem Host
alles in Ordnung ist. Bei Netzwerkproblemen nützt es nichts,
den Wert der Variablen max_connect_errors
heraufzusetzen.
Wenn Sie beim Versuch einer Verbindung mit dem
mysqld-Server einen Too many
connections
-Fehler bekommen, so bedeutet dies, dass
alle verfügbaren Verbindungen von anderen Clients belegt sind.
Die Systemvariable max_connections
legt fest,
wie viele Verbindungen zulässig sind. Ihr Standardwert ist 100.
Wenn Sie mehr Verbindungen benötigen, müssen Sie
mysqld mit einem größeren Wert für diese
Variable neu starten.
mysqld erlaubt in Wirklichkeit
max_connections+1
Clients eine Verbindung.
Die eine zusätzliche Verbindung ist für Konten reserviert, die
das SUPER
-Recht haben. Indem Sie dieses Recht
nur an Administratoren und nicht an normale Benutzer vergeben
(diese benötigen es ohnehin nicht), kann sich ein Administrator
selbst dann noch mit dem Server verbinden und mit der Anweisung
SHOW PROCESSLIST
eine Problemdiagnose
vornehmen, wenn die Höchstzahl der unprivilegierten
Clientverbindungen erreicht ist. Siehe
Abschnitt 13.5.4.19, „SHOW PROCESSLIST
“.
Wie viele Verbindungen MySQL maximal unterstützen kann, hängt von der Qualität der Thread-Bibliothek auf einer gegebenen Plattform ab. Linux oder Solaris müssten 500 bis 1.000 gleichzeitige Verbindungen dulden können, je nachdem, wie viel Arbeitsspeicher Sie haben und was Ihre Clients tun. Statische Linux-Binaries von MySQL AB können bis zu 4.000 Verbindungen unterstützen.
Wenn Sie mit dem Clientprogramm mysql eine Anfrage absetzen und einen Fehler wie den folgenden ernten, so bedeutet dies, dass mysql zu wenig Arbeitsspeicher hat, um das vollständige Abfrageergebnis zu speichern:
mysql: Out of memory at line 42, 'malloc.c' mysql: needed 8136 byte (8k), memory in use: 12481367 bytes (12189k) ERROR 2008: MySQL client ran out of memory
Dieses Problem beheben Sie, indem Sie zuerst prüfen, ob Ihre
Anfrage korrekt ist. Ist es normal, dass sie so viele Zeilen
zurückgibt? Wenn nicht, korrigieren Sie die Anfrage und
versuchen es erneut. Andernfalls können Sie
mysql mit der Option --quick
aufrufen. Dann verwendet sie zum Abruf der Ergebnismenge die
C-API-Funktion mysql_use_result()
, die
wesentlich weniger Last für den Client (aber mehr Last für den
Server) bedeutet.
In diesem Abschnitt wird auch der hiermit verwandte
Lost connection to server during query
-Fehler
behandelt.
Die häufigste Ursache eines MySQL server has gone
away
-Fehlers ist, dass der Server die Verbindung wegen
eines Timeouts geschlossen hat. In diesem Fall wird
normalerweise einer der folgenden Fehlercodes (je nach
Betriebssystem) gemeldet:
Fehlercode | Beschreibung |
CR_SERVER_GONE_ERROR | Der Client konnte keine Frage an den Server senden. |
CR_SERVER_LOST | Der Client konnte zwar ohne Fehler auf den Server schreiben, erhielt aber keine (oder keine vollständige) Antwort auf die Frage. |
Nach Voreinstellung schließt der Server die Verbindung, wenn
nichts geschieht, nach acht Stunden. Dieses Zeitlimit können
Sie in der Variablen wait_timeout
ändern,
wenn Sie mysqld starten. Siehe
Abschnitt 5.2.2, „Server-Systemvariablen“.
Wenn Sie ein Skript verwenden, müssen Sie die Anfrage nur
erneut absetzen, damit der Client sich automatisch erneut
verbindet. Das setzt voraus, dass die automatische Neuverbindung
im Client eingeschaltet ist (was beim
mysql
-Kommandozeilen-Client standardmäßig
der Fall ist).
Oft kommen MySQL server has gone away
-Fehler
auch aus folgenden Gründen zustande:
Sie (oder der Datenbankadministrator) haben den laufenden
Thread mit einer KILL
-Anweisung oder
einem mysqladmin kill-Befehl angehalten.
Sie haben versucht, eine Anfrage nach dem Schließen der Serververbindung abzusetzen. Dies weist auf einen Fehler in der Anwendungslogik hin, der korrigiert werden muss.
Sie haben einen Timeout von der TCP/IP-Verbindung auf der
Clientseite erhalten. Dazu kann es bei folgenden Befehlen
kommen: mysql_options(..., MYSQL_OPT_READ_TIMEOUT,
...)
oder mysql_options(...,
MYSQL_OPT_WRITE_TIMEOUT, ...)
. In diesem Fall
können Sie Ihr Problem lösen, indem Sie den Timeout
heraufsetzen.
Sie haben einen Timeout auf der Serverseite und die
automatische Neuverbindung ist im Client deaktiviert worden
(das Flag reconnect
in der
MYSQL
-Struktur ist gleich 0).
Sie verwenden einen Windows-Client und der Server hat die
Verbindung beendet (wahrscheinlich, weil
wait_timeout
abgelaufen ist), bevor der
Befehl gegeben wurde.
Das Problem mit Windows besteht darin, dass MySQL manchmal keinen Fehler vom Betriebssystem gemeldet bekommt, wenn es Daten in die TCP/IP-Verbindung mit dem Server schreibt. Stattdessen wird der Fehler erst bei dem Versuch gemeldet, Daten aus dieser Verbindung zu lesen.
Selbst wenn das Flag reconnect
in der
MYSQL
-Struktur gleich 1 ist, wird sich
MySQL in diesem Fall nicht automatisch neu verbinden und die
Anfrage neu absetzen, da es nicht wissen kann, ob der Server
die ursprüngliche Anfrage bekommen hat oder nicht.
Die Lösung ist entweder ein mysql_ping
auf der Verbindung, falls seit der letzten Abfrage viel Zeit
vergangen ist (so handelt auch MyODBC
),
oder eine Änderung von wait_timeout
auf
dem mysqld-Server auf einen Wert, der so
hoch ist, dass es praktisch nie zu einem Timeout kommt.
Solche Fehlermeldungen können Sie auch erhalten, wenn Sie
an den Server eine zu große oder eine falsche Anfrage
senden. Wenn mysqld ein Paket empfängt,
das zu groß oder nicht ordnungsgemäß ist, nimmt das
Programm an, dass mit dem Client etwas nicht stimmt, und
schließt die Verbindung. Wenn Sie große Anfragen
benötigen (zum Beispiel weil Sie mit umfangreichen
BLOB
-Spalten arbeiten), können Sie das
Limit pro Anfrage heraufsetzen, indem Sie die Servervariable
max_allowed_packet
von ihrem Standardwert
1 Mbyte auf etwas Höheres heraufsetzen. Vielleicht müssen
Sie auch die Paketgröße auf der Clientseite erhöhen.
Über die Einstellung der Paketgröße können Sie unter
Abschnitt A.2.9, „Packet too large
-Fehler“, mehr erfahren.
Ihre Verbindung wird auch abbrechen, wenn Sie ein Paket der Größe 16 Mbyte oder mehr verschicken und Ihr Client älter als Version 4.0.8 ist, während Ihr Server die Version 4.0.8 oder höher verwendet (oder umgekehrt).
Eventuell kommt es auch zu dem Fehler MySQL server
has gone away
, wenn MySQL mit der Option
--skip-networking
gestartet wird.
Während der Ausführung der Anfrage trat ein Fehler auf, der den Server angehalten hat.
Ob der MySQL Server abgestürzt und wieder hochgefahren ist, erfahren Sie, indem Sie mysqladmin version ausführen und auf die Uptime des Servers achten. Wenn die Clientverbindung unterbrochen war, weil mysqld abgestürzt und wieder hochgefahren ist, sollten Sie sich auf die Erforschung der Absturzursachen konzentrieren. Zuerst prüfen Sie, ob der Server bei derselben Anfrage erneut abstürzen wird. Siehe Abschnitt A.4.2, „Was zu tun ist, wenn MySQL andauernd abstürzt“.
Mehr Informationen über unterbrochene Verbindungen bekommen
Sie, wenn Sie mysqld mit der Option
--log-warnings=2
starten. Damit werden einige
Verbindungsabbruchfehler in der Datei
hostname.err
protokolliert. Siehe
Abschnitt 5.12.1, „Die Fehler-Logdatei“.
Wenn Sie einen Bugreport über dieses Problem schicken möchten, senden Sie uns bitte auch folgende Informationen:
Angabe, ob der MySQL Server abgestürzt ist. Dies erfahren Sie aus dem Fehlerlog des Servers. Siehe Abschnitt A.4.2, „Was zu tun ist, wenn MySQL andauernd abstürzt“.
Wenn eine bestimmte Anfrage mysqld
anhält und die beteiligten Tabellen mit CHECK
TABLE
vor Ausführung dieser Anfrage überprüft
wurden: Können Sie dann einen reproduzierbaren Testfall
herstellen? Siehe Abschnitt E.1.6, „Erzeugen eines Testfalls, wenn Sie Tabellenbeschädigung feststellen“.
Welchen Wert hat die Systemvariable
wait_timeout
im MySQL Server? (Mit
mysqladmin variables erhalten Sie den
Wert dieser Variablen.)
Haben Sie versucht, mysqld mit der Option
--log
auszuführen, um festzustellen, ob
die Problemanfrage im Log auftaucht?
Siehe auch Abschnitt A.2.10, „Kommunikationsfehler/abgebrochene Verbindung“, und Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“.
Ein Kommunikationspaket ist eine einzelne an den MySQL Server geschickte SQL-Anweisung oder eine einzelne an den Client geschickte Zeile.
Das größtmögliche Paket, das von einem oder an einen MySQL 5.1 Server oder -Client übermittelt werden kann, ist 1 Gbyte groß.
Wenn ein MySQL-Client oder der mysqld-Server
ein Paket empfängt, dessen Größe
max_allowed_packet
Bytes übersteigt, löst
er einen Packet too large
-Fehler aus und
schließt die Verbindung. Manche Clients melden auch einen
Lost connection to MySQL Server during
query
-Fehler, wenn das Kommunikationspaket zu groß
ist.
Da Client und Server jeweils ihre eigene
max_allowed_packet
-Variable haben, müssen
Sie diese auf beiden Seiten erhöhen, wenn Sie größere Pakete
verschicken möchten.
Der Standardwert der
max_allowed_packet
-Variable des
Clientprogramms mysql ist 16 Mbyte. Um ihn zu
erhöhen, starten Sie mysql wie folgt:
mysql> mysql --max_allowed_packet=32M
So wächst die Paketgröße auf 32 MB.
Die maximale max_allowed_packet
-Größe des
Servers ist 1 MB. Sie können sie heraufsetzen, wenn der Server
umfangreiche Anfragen verarbeiten muss (beispielsweise mit
großen BLOB
-Spalten). Um diese Variable auf
16 Mbytezu setzen, starten Sie den Server wie folgt:
mysql> mysqld --max_allowed_packet=16M
Sie können max_allowed_packet
auch mit einer
Optiondatei einstellen. Um beispielsweise die Paketgröße für
den Server auf 16 Mbytezu setzen, fügen Sie einer Optionsdatei
folgende Zeilen hinzu:
[mysqld] max_allowed_packet=16M
Der Wert dieser Variablen lässt sich ohne Sicherheitsrisiko erhöhen, da der zusätzliche Speicher nur bei Bedarf zugewiesen wird. So weist beispielsweise mysqld nur dann mehr Speicher zu, wenn Sie eine lange Anfrage haben oder wenn mysqld eine große Ergebniszeile zurückgeben muss. Der kleine Standardwert dieser Variablen ist eine Vorsichtsmaßnahme, um unkorrekte Pakete zwischen Client und Server abzufangen und zu gewährleisten, dass Sie keine Speicherplatzprobleme bekommen, weil Sie versehentlich zu große Pakete verwenden.
Es können auch seltsame Dinge mit großen Paketen passieren,
wenn Sie umfangreiche BLOB
-Werte benutzen,
aber mysqld zu wenig Speicher gegeben haben,
um mit der Anfrage umzugehen. Wenn Sie den Verdacht haben, dass
dies der Fall ist, müssen Sie ulimit -d
256000 am Anfang des
mysqld_safe-Skripts hinzufügen und
mysqld neu starten.
Das Fehlerlog des Servers kann wichtige Informationen über
Verbindungsprobleme geben (siehe Abschnitt 5.12.1, „Die Fehler-Logdatei“).
Wenn Sie den Server mit der Option
--log-warnings
starten, finden Sie im Fehlerlog
vielleicht Meldungen wie diese:
010301 14:38:23 Aborted connection 854 to db: 'users' user: 'josh'
Wenn Aborted connections
-Meldungen im
Fehlerlog stehen, kann das folgende Ursachen haben:
Das Clientprogramm hat nicht
mysql_close()
aufgerufen, bevor es
endete.
Der Client hat länger als wait_timeout
oder interactive_timeout
Sekunden
geschlafen, ohne Requests an den Server zu senden. Siehe
Abschnitt 5.2.2, „Server-Systemvariablen“.
Das Clientprogramm brach plötzlich mitten in einer Datenübertragung ab.
Wenn so etwas geschieht, setzt der Server die Statusvariable
Aborted_clients
herauf.
Bei folgenden Vorfällen inkrementiert der Server die
Statusvariable Aborted_connects
:
Ein Client hat kein Zugriffsrecht auf die Datenbank.
Ein Client benutzt ein falsches Passwort.
Ein Verbindungspaket enthält nicht die richtigen Informationen.
Es dauert mehr als connect_timeout
Sekunden, ein Verbindungspaket zu erhalten. Siehe
Abschnitt 5.2.2, „Server-Systemvariablen“.
Wenn diese Dinge passieren, kann das bedeuten, dass jemand versucht, in den Server einzudringen!
Andere Gründe für einen Abbruch von Clients oder Verbindungen können sein:
Verwendung eines Ethernet-Protokolls mit Linux, sowohl Halb- als auch Voll-Duplex. Viele Linux Ethernet-Treiber haben diesen Fehler. Ob der Fehler auch bei Ihnen vorhanden ist, können Sie testen, indem Sie eine große Datei per FTP zwischen dem Client- und dem Servercomputer übertragen. Wenn der Transfer in einer Art Stop-and-Go-Verkehr abläuft, haben Sie ein Linux-Duplex-Syndrom. Die einzige Lösung besteht darin, den Duplex-Modus für Ihre Netzwerkkarte und ihren Hub/Switch immer entweder auf Voll-Duplex oder auf Halb-Duplex einzustellen und anhand der Ergebnisse die geeignetste Einstellung zu ermitteln.
Ein Problem mit der Thread-Bibliothek, das Unterbrechungen der Lesevorgänge verursacht.
Ein schlecht konfiguriertes TCP/IP.
Fehler in Ethernets, Hubs, Switches, Kabeln usw. Diese lassen sich nur durch Ersetzung von Hardware zweifelsfrei diagnostizieren.
Die Variable max_allowed_packet
ist zu
klein oder Anfragen erfordern mehr Arbeitsspeicher, als Sie
für mysqld zugewiesen haben. Siehe
Abschnitt A.2.9, „Packet too large
-Fehler“.
Siehe auch Abschnitt A.2.8, „MySQL server has gone away
-Fehler“.
Ein Fehler wegen voller Tabelle kann aus mehreren Gründen auftreten:
Sie verwenden einen älteren MySQL Server als 3.23 und eine
arbeitsspeicherresidente temporäre Tabelle wird größer
als tmp_table_size
Bytes. Um dies zu
verhindern, lassen Sie mysqld mithilfe
der Option
--tmp_table_size=
die Größe der temporären Tabellen heraufsetzen oder
setzen die SQL-Option val
SQL_BIG_TABLES
,
bevor Sie die problematische Anfrage absetzen. Siehe
Abschnitt 13.5.3, „SET
“.
Sie können auch mysqld mit der Option
--big-tables
starten. Das ist genau
dasselbe, als würden Sie SQL_BIG_TABLES
für sämtliche Anfragen verwenden.
Seit MySQL 3.23 sollte dieses Problem erledigt sein. Wenn
eine speicherresidente temporäre Tabelle größer als
tmp_table_size
wird, macht sie der Server
automatisch zu einer MyISAM
-Tabelle auf
der Festplatte.
Sie verwenden InnoDB
-Tabellen und haben
keinen Platz mehr im InnoDB
-Tablespace.
In diesem Fall müssen Sie den
InnoDB
-Tablespace vergrößern. Siehe
Abschnitt 14.2.7, „Hinzufügen und Entfernen von InnoDB-Daten- und -Logdateien“.
Sie verwenden ISAM
- oder
MyISAM
-Tabellen auf einem Betriebssystem,
das nur maximal 2 Gbyte große Dateien zulässt, und Ihre
Daten- oder Indexdatei übersteigt dieses Limit.
Sie benutzen eine MyISAM
-Tabelle, die
mehr Platz braucht, als die interne Zeigergröße gestattet.
Wenn Sie nicht beim Anlegen der Tabelle die Tabellenoption
MAX_ROWS
gesetzt haben, verwendet MySQL
die Systemvariable
myisam_data_pointer_size
. Deren
Standardwert beträgt 6 Byte, genug, um 256-Tbyte- Daten
zuzulassen. Siehe Abschnitt 5.2.2, „Server-Systemvariablen“.
Die Größenlimits für Daten- und Indexdatei prüfen Sie mit folgender Anweisung:
SHOW TABLE STATUS FROM database LIKE 'tbl_name
';
Sie können auch myisamchk -dv /path/to/table-index-file benutzen.
Ist die Zeigergröße zu klein, können Sie dies mit
ALTER TABLE
ändern:
ALTER TABLEtbl_name
MAX_ROWS=1000000000 AVG_ROW_LENGTH=nnn
;
Den Wert AVG_ROW_LENGTH
müssen Sie nur
für Tabellen mit BLOB
- oder
TEXT
-Spalten angeben; in diesem Fall kann
MySQL den Platzbedarf nicht anhand der Zeilenzahl
optimieren.
Wenn Sie bei manchen Anfragen den folgenden Fehlertyp ernten, so bedeutet dies, dass MySQL keine temporäre Datei für die Ergebnismenge im temporären Verzeichnis anlegen kann:
Can't create/write to file '\\sqla3fe_0.ism'.
Dieser Fehler ist typisch für Windows; bei Unix sieht die Meldung ähnlich aus.
Eine Möglichkeit ist die, mysqld mit der
Option --tmpdir
zu starten oder sie in den
Abschnitt [mysqld]
Ihrer Optionsdatei zu
schreiben. Um beispielsweise das Verzeichnis
C:\temp
vorzugeben, schreiben Sie:
[mysqld] tmpdir=C:/temp
Das Verzeichnic C:\temp
muss existieren und
genügend Platz bieten, damit der MySQL Server hineinschreiben
kann. Siehe Abschnitt 4.3.2, „my.cnf-Optionsdateien“.
Auch Berechtigungsprobleme können den Fehler verursachen.
Achten Sie darauf, dass der MySQL Server in das
tmpdir
-Verzeichnis schreiben darf.
Schauen Sie auch auf den Fehlercode, den Ihnen perror liefert. Manchmal kann der Server nicht in eine Tabelle schreiben, weil das Dateisystem voll ist:
shell> perror 28
Error code 28: No space left on device
Wenn Commands out of sync; you can't run this command
now
in Ihrem Clientcode gemeldet wird, rufen Sie
Clientfunktionen in der verkehrten Reihenfolge auf.
Dies kann zum Beispiel geschehen, wenn Sie
mysql_use_result()
benutzen und versuchen,
eine neue Anfrage auszuführen, ehe Sie
mysql_free_result()
aufgerufen haben. Oder
wenn Sie versuchen, zwei Anfragen, die Daten liefern,
auszuführen, ohne dazwischen
mysql_use_result()
oder
mysql_store_result()
aufzurufen.
Wenn Sie folgende Fehlermeldung sehen, so bedeutet dies, dass
beim Starten von mysqld oder beim Neuladen
der Berechtigungstabellen in der user
-Tabelle
ein Konto mit einem verkehrten Passwort gefunden wurde.
Found wrong password for user
'
some_user
'@'some_host
';
ignoring user
Infolgedessen wird das Konto vom Berechtigungssystem einfach ignoriert.
Die folgende Liste zeigt mögliche Ursachen und Lösungen für dieses Problem auf:
Vielleicht führen Sie eine aktuelle
mysqld-Version mit einer alten
user
-Tabelle aus. Führen sie
mysqlshow mysql user aus, um zu
überprüfen, ob die Password
-Spalte
kürzer als 16 Zeichen ist. Wenn ja, so können Sie dies mit
dem Skript scripts/add_long_password
korrigieren.
Das Konto hat ein altes Passwort (8 Zeichen lang) und Sie
haben mysqld nicht mit der Option
--old-protocol
gestartet. Dann können Sie
entweder das Konto in der user
-Tabelle
auf ein neues Passwort umstellen oder
mysqld mit der Option
--old-protocol
neu starten.
Sie haben in der user
-Tabelle ein
Passwort angegeben, ohne die
PASSWORD()
-Funktion zu benutzen. Stellen
Sie mit mysql das Konto in der
user
-Tabelle auf ein neues Passwort um
und achten Sie darauf, die Funktion
PASSWORD()
zu verwenden:
mysql>UPDATE user SET Password=PASSWORD('
->newpwd
')WHERE User='
some_user
' AND Host='some_host
';
Wenn Sie eine der folgenden Fehlermeldungen sehen, so bedeutet dies, dass in der voreingestellten Datenbank keine Tabelle mit dem gegebenen Namen existiert:
Table 'tbl_name
' doesn't exist Can't find file: 'tbl_name
' (errno: 2)
In manchen Fällen ist die Tabelle zwar vorhanden, aber Sie sprechen sie nicht richtig an:
Da MySQL Datenbanken und Tabellen in Verzeichnissen und Dateien speichert, unterscheiden die Namen der Datenbanken und Tabellen zwischen Groß- und Kleinschreibung, wenn sie in einem Dateisystem vorliegen, das selbst zwischen Groß- und Kleinschreibung unterscheidet.
Selbst in Dateisystemen, die nicht zwischen Groß- und Kleinschreibung unterscheiden, wie etwa Windows, muss eine Tabelle in einer Anfrage immer gleich geschrieben werden (entweder groß oder klein).
Der Befehl SHOW TABLES
verrät Ihnen, welche
Tabellen in Ihrer Datenbank vorliegen. Siehe
Abschnitt 13.5.4, „SHOW
“.
Bei Zeichensatzproblemen kann ein Fehler wie dieser auftreten:
MySQL Connection Failed: Can't initialize character set charset_name
Dieser Fehler kann folgende Gründe haben:
Der Zeichensatz ist ein Multibytezeichensatz und in Ihrem
Client ist keine Unterstützung dafür vorhanden. In diesem
Fall müssen Sie den Client neu kompilieren, indem Sie
configure mit der Option
--with-charset=
oder
charset_name
--with-extra-charsets=
ausführen. Siehe Abschnitt 2.8.2, „Typische configure-Optionen“.
charset_name
Alle MySQL-Standardbinaries werden mit der Option
--with-extra-character-sets=complex
kompiliert, die alle Multibytezeichensätze unterstützt.
Siehe Abschnitt 5.11.1, „Der für Daten und zum Sortieren benutzte Zeichensatz“.
Der Zeichensatz ist ein einfacher Zeichensatz, der nicht in mysqld kompiliert ist, und seine Definitionsdateien sind nicht dort, wo der Client sie sucht.
In diesem Fall können Sie Ihr Problem mit einer der folgenden Methoden lösen:
Sie rekompilieren den Client mit Unterstützung für den betreffenden Zeichensatz. Siehe Abschnitt 2.8.2, „Typische configure-Optionen“.
Sie geben dem Client das Verzeichnis an, in dem er die
Definitionsdateien des Zeichensatzes finden kann. Für
viele Clients können Sie dies mit der Option
--character-sets-dir
tun.
Sie kopieren die Definitionsdateien des Zeichensatzes in den Pfad, wo der Client sie sucht.
Wenn Sie den Fehler ERROR '...' not found (errno:
23)
, Can't open file: ... (errno:
24)
oder einen anderen Fehler mit der errno
23
oder errno 24
von MySQL gemeldet
bekommen, haben Sie nicht genügend Dateideskriptoren für den
MySQL Server zugewiesen. Das Dienstprogramm
perror verrät Ihnen, was welche Fehlernummer
bedeutet:
shell>perror 23
Error code 23: File table overflow shell>perror 24
Error code 24: Too many open files shell>perror 11
Error code 11: Resource temporarily unavailable
Das Problem hierbei ist, dass mysqld versucht, zu viele Dateien gleichzeitig geöffnet zu halten. Sie können entweder mysqld veranlassen, nicht so viele Dateien zugleich zu öffnen, oder die Anzahl der für mysqld verfügbaren Dateideskriptoren erhöhen.
Damit mysqld weniger Dateien zugleich offen
behält, können Sie den Tabellen-Cache verkleinern, indem Sie
den Wert der Systemvariablen table_open_cache
heruntersetzen (ihr Standardwert ist 64). Wenn Sie die
max_connections
vermindern, vermindern Sie in
einem auch die Anzahl der offenen Dateien (der Standardwert
beträgt 100).
Die Anzahl der für mysqld verfügbaren
Dateideskriptoren ändern Sie mit der Option
--open-files-limit
für
mysqld_safe, oder Sie setzen (seit MySQL
3.23.30) die Systemvariable open_files_limit
.
Siehe Abschnitt 5.2.2, „Server-Systemvariablen“. Am einfachsten
können Sie diese Werte ändern, indem Sie eine Option in Ihrer
Optionsdatei einstellen. Siehe Abschnitt 4.3.2, „my.cnf-Optionsdateien“.
Wenn Sie eine ältere Version von mysqld
verwenden, in der sich die Höchstzahl der offenen Dateien nicht
einstellen lässt, können Sie das Skript
mysqld_safe bearbeiten. Dort gibt es eine
auskommentierte Zeile mit dem Inhalt ulimit -n
256. Daraus entfernen Sie das Kommentarzeichen
‘#
’ und stellen die Zahl
256
auf die Anzahl der gewünschten
Dateideskriptoren um, die mysqld zur
Verfügung stehen sollen.
--open-files-limit
und
ulimit können zwar die Anzahl der
Dateideskriptoren erhöhen, aber nur bis zu dem Limit, das für
Ihr Betriebssystem zulässig ist. Außerdem gibt es ein
„hartes“ Limit, das nur überschrieben werden kann,
wenn Sie mysqld_safe oder
mysqld als root
starten
(denken Sie aber daran, in diesem Fall den Server mit der
--user
-Option zu starten, damit er nicht nach
dem Hochfahren als root
weiterläuft). Wenn
Sie das Betriebssystemlimit für die Anzahl der
Dateideskriptoren, die für jeden Prozess verfügbar sind,
ändern möchten, müssen Sie in Ihre Systemdokumentation
schauen.
Hinweis: Wenn Sie die tcsh-Shell ausführen, funktioniert ulimit nicht! Außerdem meldet tcsh verkehrte Werte, wenn Sie nach den aktuellen Limits fragen. In diesem Fall sollten Sie mysqld_safe mit sh starten.
Wenn Sie ein Anwendungsprogramm so verlinken, dass es die
MySQL-Clientbibliothek benutzt, werden für Symbole, die mit
mysql_
anfangen, undefined
reference
-Fehler gemeldet werden:
/tmp/ccFKsdPa.o: In function `main': /tmp/ccFKsdPa.o(.text+0xb): undefined reference to `mysql_init' /tmp/ccFKsdPa.o(.text+0x31): undefined reference to `mysql_real_connect' /tmp/ccFKsdPa.o(.text+0x57): undefined reference to `mysql_real_connect' /tmp/ccFKsdPa.o(.text+0x69): undefined reference to `mysql_error' /tmp/ccFKsdPa.o(.text+0x9a): undefined reference to `mysql_close'
Um dieses Problem zu lösen, fügen Sie am Ende Ihres
Link-Befehls -Ldir_path -lmysqlclient
an,
wobei dir_path
den Pfadnamen des
Verzeichnisses darstellt, in dem die Clientbibliothek liegt. Mit
folgendem Befehl können Sie das richtige Verzeichnis
herausfinden:
shell> mysql_config --libs
Die Ausgabe von mysql_config kann auch auf andere Bibliotheken hinweisen, die ebenfalls im Link-Befehl angegeben werden sollten.
Wenn undefined reference
-Fehler für die
Funktion uncompress
oder
compress
gemeldet werden, fügen Sie am Ende
des Link-Befehls -lz
an und versuchen es
erneut.
Treten undefined reference
-Fehler im
Zusammenhang mit einer Funktion auf, die auf Ihrem System
existieren müsste, wie beispielsweise
connect
, sehen Sie auf der Handbuchseite zu
dieser Funktion nach, um festzustellen, welche Bibliotheken Sie
im Link-Befehl angeben müssen.
Wenn Funktionen auf Ihrem System nicht existieren, werden
undefined reference
-Fehler wie diese
gemeldet:
mf_format.o(.text+0x201): undefined reference to `__lxstat'
Das bedeutet normalerweise, dass Ihre MySQL-Clientbibliothek auf einem System kompiliert wurde, das mit Ihrem nicht zu 100 % kompatibel ist. In diesem Fall sollten Sie die neueste MySQL-Quelldistribution herunterladen und MySQL selbst kompilieren. Siehe Abschnitt 2.8, „Installation der Quelldistribution“.
Zur Laufzeit können undefined
reference
-Fehler auftreten, wenn Sie versuchen, ein
MySQL-Programm auszuführen. Wenn diese Fehler Symbole
betreffen, die mit mysql_
anfangen oder
anzeigen, dass die mysqlclient
-Bibliothek
nicht zu finden ist, so bedeutet dies, dass Ihr System die
Shared Library libmysqlclient.so
nicht
finden kann. Dies beheben Sie, indem Sie Ihr System dort, wo
sich die Bibliothek befindet, nach Shared Libraries suchen
lassen. Aus den folgenden Verfahren können Sie das für Ihr
System geeignete auswählen:
Sie fügen den Pfad zu dem Verzeichnis, in dem
libmysqlclient.so
liegt, der
Umgebungsvariablen LD_LIBRARY_PATH
hinzu.
Sie fügen den Pfad zu dem Verzeichnis, in dem
libmysqlclient.so
liegt, der
Umgebungsvariablen LD_LIBRARY
hinzu.
Sie kopieren libmysqlclient.so
in ein
Verzeichnis, in dem Ihr System nachschaut, wie
beispielsweise /lib
, und aktualisieren
die Shared Library-Informationen, indem Sie
ldconfig
ausführen.
Sie können dieses Problem auch angehen, indem Sie Ihr Programm
statisch mit der Option -static
verlinken
oder indem Sie die dynamischen MySQL-Bibliotheken entfernen,
bevor Sie Ihren Code verlinken. Ehe Sie die zweite Methode
wählen, müssen Sie sich vergewissern, dass keine anderen
Programme die dynamischen Bibliotheken benutzen.
Wenn Sie Probleme mit Dateiberechtigungen haben, ist vielleicht
die Umgebungsvariable UMASK
beim Starten von
mysqld falsch gesetzt. So könnte MySQL
beispielsweise folgende Fehlermeldung ausgeben, wenn Sie eine
Tabelle anlegen:
ERROR: Can't find file: 'path/with/filename.frm' (Errcode: 13)
Der Standardwert von UMASK
ist
0660
. Dies können Sie ändern, indem Sie
mysqld_safe folgendermaßen starten:
shell>UMASK=384 # = 600 in octal
shell>export UMASK
shell>mysqld_safe &
Nach Voreinstellung legt MySQL Datenbanken und
RAID
-Verzeichnisse mit dem
Zugriffsberechtigungswert 0700
an. Dies
können Sie ändern, indem Sie die Variable
UMASK_DIR
einstellen. Wenn Sie ihren
Standardwert ändern, werden neue Verzeichnisse mit einer
Kombination der Werte UMASK
und
UMASK_DIR
angelegt. Wenn Sie beispielsweise
Gruppenzugriff für alle neuen Verzeichnisse festlegen möchten,
gehen Sie folgendermaßen vor:
shell>UMASK_DIR=504 # = 770 in octal
shell>export UMASK_DIR
shell>mysqld_safe &
In der Version 3.23.25 und höher geht MySQL von einem Oktalwert
für UMASK
und UMASK_DIR
aus, wenn der Wert mit einer Null beginnt.
Siehe Anhang F, Umgebungsvariablen.
/tmp/mysql.sock
schützen oder ändern
Wenn Sie niemals ein root
-Passwort für MySQL
gesetzt haben, verlangt der Server überhaupt kein Passwort für
eine root
-Verbindung. Allerdings empfehlen
wir Ihnen dringend, für jedes Konto ein Passwort einzurichten.
Siehe Abschnitt 5.7.1, „Allgemeine Sicherheitsrichtlinien“.
Wenn Sie ein root
-Passwort eingerichtet
hatten, aber sich nicht mehr daran erinnern können, müssen Sie
es neu einstellen. Die nachfolgende Anleitung ist auf Windows
zugeschnitten; eine entsprechende Anleitung für Unix-Systeme
finden Sie weiter unten in diesem Abschnitt.
Vorgehen unter Windows:
Sie melden sich als Administrator an.
Sie halten den MySQL Server an, falls er läuft. Läuft er als Windows-Dienst, müssen Sie dazu den Dienstmanager verwenden:
Start -> Systemsteuerung -> Verwaltung -> Dienste
Suchen Sie in der Dienstliste den MySQL-Dienst und halten Sie ihn an.
Wenn Ihr Server nicht als Dienst läuft, müssen Sie eventuell den Task-Manager einschalten, um ihn mit Gewalt zu stoppen.
Legen Sie eine Textdatei an und schreiben Sie folgenden Befehl auf einer einzigen Zeile hinein:
SET PASSWORD FOR 'root'@'localhost' = PASSWORD('MyNewPassword');
Speichern Sie die Datei unter einem beliebigen Namen. In
diesem Beispiel nennen wir sie
C:\mysql-init.txt
.
Öffnen Sie ein Konsolenfenster mit der DOS-Eingabeaufforderung:
Start -> Ausführen -> cmd
Wir gehen davon aus, dass Sie MySQL in
C:\mysql
installiert haben. Wenn nicht,
müssen Sie die folgenden Befehle entsprechend abändern.
Führen Sie an der Eingabeaufforderung folgenden Befehl aus:
C:\> C:\mysql\bin\mysqld-nt --init-file=C:\mysql-init.txt
Der Inhalt der in der Option --init-file
angegebenen Datei wird beim Serverstart ausgeführt, sodass
das root
-Wort geändert wird. Nachdem der
Server hochgefahren ist, sollten Sie
C:\mysql-init.txt
löschen.
Wenn Sie MySQL mit dem MySQL Installation Wizard
installieren, müssen Sie unter Umständen die Option
--defaults-file
angeben:
C:\>"C:\Programme\MySQL\MySQL Server 5.1\bin\mysqld-nt.exe"
--defaults-file="C:\Program Files\MySQL\MySQL Server 5.1\my.ini"
--init-file=C:\mysql-init.txt
Die passende Einstellung für
--defaults-file
finden Sie mithilfe des
Dienstmanagers:
Start -> Systemsteuerung -> Verwaltung -> Dienste
Suchen Sie den MySQL-Dienst, klicken Sie ihn mit rechts an
und wählen Sie Eigenschaften
. Das Feld
Pfad zur EXE-Datei
enthält die
Einstellung für --defaults-file
.
Halten Sie den MySQL Server an und starten Sie ihn dann im Normalmodus neu. Wenn Sie den Server als Dienst betreiben, starten Sie ihn im Dienste-Fenster von Windows; wenn Sie ihn manuell betreiben, starten Sie ihn mit dem Befehl, den Sie auch sonst immer benutzen.
Nun müssten Sie mit dem neuen Passwort eine Verbindung bekommen können.
In einer Unix-Umgebung stellen Sie das
root
-Passwort folgendermaßen um:
Sie melden sich als Unix- root
-User oder
als der Benutzer, unter dem der
mysqld-Server läuft, an.
Sie suchen die .pid
-Datei, welche die
Prozess-ID des Servers enthält. Wo sie liegt und wie sie
heißt, hängt von Ihrer Distribution, Ihrem Hostnamen und
Ihrer Konfiguration ab. Gebräuchliche Speicherorte sind zum
Beispiel /var/lib/mysql/
,
/var/run/mysqld/
und
/usr/local/mysql/data/
. Im Allgemeinen
hat der Dateiname die Erweiterung .pid
und fängt entweder mit mysqld
oder dem
Hostnamen Ihres Systems an.
Sie können den MySQL Server anhalten, indem Sie einen
normalen kill
-Befehl (nicht kill
-9
) an den mysqld-Prozess
übermitteln und dabei den Pfadnamen der
.pid
-Datei angeben:
shell> kill `cat /mysql-data-directory/host_name.pid`
Beachten Sie, dass wir Backticks anstelle von
Anführungszeichen für den cat
-Befehl
benutzen. Sie sorgen dafür, dass die Ausgabe von
cat
in den kill
-Befehl
eingesetzt wird.
Legen Sie eine Textdatei an und schreiben Sie folgenden Befehl auf einer einzigen Zeile hinein:
SET PASSWORD FOR 'root'@'localhost' = PASSWORD('MyNewPassword');
Speichern Sie die Datei unter einem beliebigen Namen. In
diesem Beispiel heißt sie
~/mysql-init
.
Starten Sie den MySQL Server mit der Spezialoption
--init-file=~/mysql-init
:
shell> mysqld_safe --init-file=~/mysql-init &
Der Inhalt der init-Datei wird beim Serverstart ausgeführt
und ändert das Root-Passwort. Nachdem der Server
hochgefahren ist, sollten Sie
~/mysql-init
löschen.
Nun müsste das neue Passwort funktionieren.
Alternativ können Sie das neue Passwort auf jeder Plattform auch mit dem Client mysql einstellen (aber diese Methode ist nicht so sicher):
Halten Sie mysqld an und starten Sie ihn
erneut mit den Optionen --skip-grant-tables
--user=root
(Windows-Nutzer lassen
--user=root
weg).
Verbinden Sie sich mit folgendem Befehl mit dem mysqld-Server:
shell> mysql -u root
Geben Sie im mysql-Client folgende Anweisungen:
mysql>UPDATE mysql.user SET Password=PASSWORD('
->newpwd
')WHERE User='root';
mysql>FLUSH PRIVILEGES;
Ersetzen Sie
„newpwd
“ durch das
root
-Passwort, das Sie in Wirklichkeit
benutzen möchten.
Das neue Passwort sollte nun funktionieren.
Jede MySQL-Version wird vor dem Release auf vielen Plattformen getestet. Dennoch kann es immer noch Bugs in MySQL geben, allerdings ziemlich wenige, die darüber hinaus schwer zu finden sind. Wenn Sie ein Problem haben, ist es immer gut, ganz genau festzustellen, was Ihr System zum Absturz brachte. Dann sind Ihre Chancen auf schnelle Abhilfe viel besser.
Als Erstes müssen Sie herausfinden, ob Ihr mysqld-Server oder Ihr Client an dem Absturz schuld ist. Der Befehl mysqladmin version verrät Ihnen, wie lange Ihr mysqld-Server bereits läuft. Wenn mysqld herunter- und wieder hochgefahren ist, finden Sie die Wurzel des Problems vielleicht im Fehlerlog des Servers. Siehe Abschnitt 5.12.1, „Die Fehler-Logdatei“.
Auf manchen Systemen enthält das Fehlerlog einen Stack-Trace
mit der Information, wo mysqld abgestürzt
ist. Diesen Trace können Sie mit dem Programm
resolve_stack_dump
auswerten. Siehe
Abschnitt E.1.4, „Einen Stack-Trace benutzen“. Beachten Sie, dass die
Variablenwerte im Fehlerlog nicht immer hundertprozentig korrekt
sind.
Viele Serverabstürze werden durch beschädigte Daten- oder
Indexdateien verursacht. MySQL aktualisiert nach jeder
SQL-Anweisung und vor der Benachrichtigung des Clients über das
Ergebnis die Dateien auf der Festplatte mit dem Systemaufruf
write()
. (Das gilt allerdings nicht, wenn Sie
mit der Option --delay-key-write
arbeiten: Hier
werden zwar die Datendateien zeitnah geschrieben, aber nicht die
Indexdateien.) Das bedeutet, dass der Inhalt der Datendateien
selbst bei einem mysqld-Absturz sicher ist,
weil das Betriebssystem dafür sorgt, dass die
Arbeitsspeicherdaten auf die Platte zurückgeschrieben werden.
Sie können MySQL zwingen, nach jeder SQL-Anweisung gleich alles
auf die Platte zurückzuschreiben, indem Sie
mysqld mit der Option
--flush
starten.
Das bedeutet, dass Sie normalerweise nur in folgenden Fällen mit beschädigten Tabellen zu tun haben:
Wenn der MySQL Server oder der Serverhost mitten in einem Update abgestürzt ist.
Wenn Sie einen Bug in mysqld gefunden haben, der den Prozess mitten in einem Update anhielt.
Wenn ein externes Programm Daten- oder Indexdateien zur gleichen Zeit wie mysqld ändert, ohne die Tabelle ordentlich zu sperren.
Wenn Sie viele mysqld-Server zugleich mit
demselben Data Directory auf einem System betreiben, das
keine vernünftigen Dateisystemsperren kennt (diese werden
normalerweise von dem Sperrenmanager
lockd
verwaltet), oder wenn Sie mehrere
Server bei ausgeschaltetem externem Locking laufen lassen.
Wenn Sie eine abgestürzte Daten- oder Indexdatei mit völlig kaputten Daten haben, die mysqld in Verwirrung stürzt.
Wenn Sie einen Fehler im Code der Datenspeicherung gefunden
haben. Das ist zwar unwahrscheinlich, aber nicht unmöglich.
In diesem Fall können Sie versuchen, die Speicher-Engine
auf eine andere Engine umzustellen, indem Sie ALTER
TABLE
auf einer reparierten Kopie der Tabelle
ausführen.
Da der Grund für einen Absturz so schwer festzustellen ist, sollten Sie zuerst versuchen, herauszufinden, ob Dinge, die bei anderen funktionieren, bei Ihnen abstürzen. Hierzu sollten Sie Folgendes ausprobieren:
Halten Sie den mysqld-Server mit
mysqladmin shutdown an, führen Sie im
Data Directory myisamchk --silent --force
*/*.MYI aus, um alle
MyISAM
-Tabellen zu prüfen, und starten
Sie mysqld erneut. Dann ist
gewährleistet, dass der Server in einem sauberen Zustand
läuft. Siehe Kapitel 5, Datenbankverwaltung.
Starten Sie mysqld mit der Option
--log
und versuchen Sie, an den Logdaten zu
erkennen, ob eine spezifische Anfrage den Server abstürzen
lässt. Rund 95 % aller Fehler hängen mit einer konkreten
Anfrage zusammen. Normalerweise ist dies eine der letzten
Anfragen, die in der Logdatei kurz vor dem Neustart des
Servers protokolliert sind. Siehe auch
Abschnitt 5.12.2, „Die allgemeine Anfragen-Logdatei“. Wenn Sie MySQL mit einer
bestimmten Anfrage wiederholt zum Absturz bringen können,
obwohl Sie alle Tabellen kurz vorher überprüft haben, dann
haben Sie den Fehler gefunden und sollten einen Bugreport
übermitteln. Siehe hierzu Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“.
Versuchen Sie, einen Testfall einzurichten, den wir verwenden können, um den Fehler zu reproduzieren. Siehe Abschnitt E.1.6, „Erzeugen eines Testfalls, wenn Sie Tabellenbeschädigung feststellen“.
Versuchen Sie, die Tests im Verzeichnis
mysql-test
und die MySQL-Benchmarks
auszuführen. Siehe Abschnitt 26.1.2, „MySQL-Testsystem“.
Damit sollte MySQL ziemlich gut getestet sein. Sie können
den Benchmarks auch Code hinzufügen, der Ihre Anwendung
simuliert. Die Benchmarks finden Sie im Verzeichnis
sql-bench
einer Quelldistribution oder
im Verzeichnis sql-bench
unterhalb des
MySQL-Installationsverzeichnisses in einer
Binärdistribution.
Probieren Sie es mit dem Skript
fork_big.pl
. (Dieses finden Sie im
Verzeichnis tests
der
Quelldistributionen.)
Wenn Sie MySQL für das Debugging konfigurieren, lassen sich
Informationen über mögliche Fehler viel leichter
beschaffen. In der Debuggingkonfiguration ist eine
Arbeitsspeicherzuweisung enthalten, die so manchem Fehler
auf die Spur kommt. Außerdem liefert diese Konfiguration
viele Ausgabedaten über alles, was vor sich geht.
Rekonfigurieren Sie also MySQL mit der Option
--with-debug
oder
--with-debug=full
für
configure und kompilieren Sie dann neu.
Siehe auch Abschnitt E.1, „Einen MySQL-Server debuggen“.
Installieren Sie immer die neuesten Patches für Ihr Betriebssystem.
Stellen Sie die Option
--skip-external-locking
für
mysqld ein. Auf manchen Systemen
funktioniert der Sperrenmanager lockd
nicht richtig. Die Option
--skip-external-locking
hält
mysqld davon ab, externes Locking zu
benutzen. (Das bedeutet, dass Sie nicht zwei
mysqld-Server mit demselben Data
Directory betreiben können und dass Sie mit
myisamchk aufpassen müssen. Aber
immerhin kann es sehr aufschlussreich sein, die Option
einmal auszuprobieren.)
Haben Sie es schon mit mysqladmin -u root processlist versucht, wenn mysqld scheinbar läuft, aber nicht antwortet? Manchmal ist mysqld gar nicht ins Koma gefallen, auch wenn es den Anschein hat. Vielleicht sind alle Verbindungen belegt oder es gibt ein Problem mit internen Sperren. Normalerweise kann mysqladmin -u root processlist selbst in solchen Fällen eine Verbindung einrichten und Aufschluss über die Anzahl und den Status der laufenden Verbindungen geben.
Führen Sie in einem separaten Fenster den Befehl mysqladmin -i 5 status oder mysqladmin -i 5 -r status aus, um Statistiken zu erstellen, während sie andere Anfragen ausführen.
Versuchen Sie Folgendes:
Starten Sie mysqld von gdb (oder einem anderen Debugger) aus. Siehe auch Abschnitt E.1.3, „mysqld unter gdb debuggen“.
Lassen Sie Ihre Testskripten laufen.
Geben Sie den Backtrace und die lokalen Variablen auf den drei untersten Ebenen aus. In gdb tun Sie dies mit den folgenden Befehlen, wenn mysqld innerhalb von gdb abgestürzt ist:
backtrace info local up info local up info local
In gdb können Sie auch mit
info threads
herausfinden, welche
Threads vorhanden sind, und mit thread
auf einen
bestimmten Thread umschalten, wobei
N
N
die Thread-ID ist.
Versuchen Sie, Ihre Anwendung mit einem Perl-Skript zu simulieren, um MySQL zu einem Absturz oder Fehlverhalten zu veranlassen.
Senden Sie einen normalen Bugreport. Siehe Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“. Machen Sie noch detailliertere Angaben als üblich. Da MySQL bei den meisten Nutzern funktioniert, kann es sein, dass der Crash durch Umstände verursacht wird, die nur auf Ihrem Compter existieren (zum Beispiel im Zusammenhang mit Ihren Systembibliotheken).
Wenn Sie Schwierigkeiten mit Tabellen haben, die Datenzeilen
mit variabler Länge speichern und nur
VARCHAR
-, aber keine
BLOB
- oder
TEXT
-Spalten benutzen, können Sie mit
ALTER TABLE
ausprobieren, alle
VARCHAR
- in
CHAR
-Spalten zu ändern. Damit zwingen
Sie MySQL, Zeilen mit fester Länge zu verwenden, die zwar
ein bisschen mehr Platz belegen, aber weniger anfällig für
Beschädigungen sind.
Der jetzige Code für dynamische Zeilen, den MySQL AB schon seit Jahren verwendet, macht nur minimale Probleme, aber Zeilen dynamischer Länge sind von Natur aus fehleranfälliger. Daher sollten Sie bei Problemen folgende Strategie versuchen:
Beziehen Sie auch Ihre Serverhardware als mögliche Fehlerursache ein. Auch Hardwaredefekte können Datenkorruption verursachen. Achten Sie bei der Hardware besonders auf RAMs und Festplattenlaufwerke.
Dieser Abschnitt beschreibt, wie MySQL mit Fehlern umgeht, die aufgrund einer vollen Festplatte auftreten (wie beispielsweise „no space left on device“), und wie Fehler aufgrund von Kontingentüberschreitung behandelt werden (wie zum Beispiel „write failed“ oder „user block limit reached“).
Dieser Abschnitt ist für Schreiboperationen auf
MyISAM
-Tabellen relevant. Er gilt jedoch auch
für Schreiboperationen in Binärlogdateien und die
Binärlog-Indexdatei, nur dass die Begriffe „row“
und „record“ im Zusammenhang mit Logs
„Ereignisse“ bedeuten.
Wenn ein Fehler wegen voller Festplatte auftritt, geht MySQL wie folgt vor:
Es prüft einmal pro Minute, ob genug Platz vorhanden ist, um die aktuelle Zeile zu schreiben. Wenn dies der Fall ist, macht es weiter, als sei nichts geschehen.
Alle 10 Minuten schreibt es in die Logdatei eine Warnung, dass die Festplatte voll ist.
Dieses Problem können Sie folgendermaßen beheben:
Um weiterarbeiten zu können, müssen Sie lediglich genug Platz auf der Platte schaffen, um alle Datensätze zu schreiben.
Um den Thread anzuhalten, sagen Sie mysqladmin kill. Dann wird der Thread das nächste Mal, wenn er die Platte überprüft (also in einer Minute), gestoppt.
Eventuell warten andere Threads auf die Tabelle, welche die
Fehlerbedingung disk-full
verursacht hat.
Wenn Sie mehrere „gesperrte“ Threads haben,
können nach Abbruch des einen Threads, der wegen der
disk-full
-Bedingung wartet, die anderen
Threads weiterlaufen.
Das oben geschilderte Verhalten tritt nicht ein, wenn Sie
REPAIR TABLE
oder OPTIMIZE
TABLE
gesagt haben oder wenn die Indizes nach
LOAD DATA INFILE
oder nach einer
ALTER TABLE
-Anweisung in Stapelverarbeitung
erstellt werden. Alle diese Anweisungen können große
temporäre Dateien erzeugen, die den Rest des Systems in
Schwierigkeiten bringen, wenn sie sich selbst überlassen
bleiben. Wenn die Platte voll läuft, während MySQL eine dieser
Operationen ausführt, löscht MySQL eine der großen
temporären Dateien und kennzeichnet die Tabelle als
abgestürzt. Ausnahme: Bei ALTER TABLE
bleibt
die alte Tabelle unverändert.
MySQL verwendet den Wert der Umgebungsvariablen
TMPDIR
als Pfad zu dem Verzeichnis, in dem
die temporären Dateien gespeichert werden. Wenn Sie
TMPDIR
nicht eingestellt haben, benutzt MySQL
den systemeigenen Standardwert, also normalerweise
/tmp
, /var/tmp
oder
/usr/tmp
. Wenn das Dateisystem, in dem Ihr
Verzeichnis für temporäre Dateien liegt, zu klein ist, können
Sie mit der Option --tmpdir
von
mysqld ein anderes Verzeichnis in einem
ausreichend großen Dateisystem einstellen.
In MySQL 5.1 kann die Option
--tmpdir
auf eine Liste mit mehreren Pfaden
eingestellt werden, die dann im Ringverfahren (jeder kommt
einmal dran) benutzt werden. Die Pfade sollten auf Unix durch
Doppelpunkte (‘:
’) getrennt
werden, und auf Windows, NetWare und OS/2 durch Semikola
(‘;
’).
Hinweis: Um die Last
wirkungsvoll zu verteilen, sollten diese Pfade zu verschiedenen
physikalischen Platten und nicht nur zu
verschiedenen Partitionen derselben Festplatte führen.
Wenn der MySQL Server ein Replikationsslave ist, sollten Sie die
Option --tmpdir
nicht auf ein Verzeichnis in
einem arbeitsspeicherbasierten Dateisystem oder auf ein anderes
Verzeichnis einstellen, das beim Neustart des Serverhosts
gelöscht wird. Ein Replikationsslave benötigt einige seiner
temporären Dateien, um einen Neustart des Computers so zu
überleben, dass er temporäre Tabellen oder LOAD DATA
INFILE
-Operationen replizieren kann. Wenn Dateien aus
dem temporären Verzeichnis beim Neustart des Servers verloren
gehen, scheitert die Replikation.
MySQL legt alle temporären Dateien als verborgene Dateien an. Das soll gewährleisten, dass die temporären Dateien beim Herunterfahren von mysqld entfernt werden. Allerdings haben verborgene Dateien den Nachteil, dass eine große temporäre Datei, die das Dateisystem überlastet, in welchem das temporäre Verzeichnis liegt, nicht zu sehen ist.
Bei Sortieroperationen (ORDER BY
oder
GROUP BY
) verwendet MySQL normalerweise ein
oder zwei temporäre Dateien. Wie viel Platz auf der Festplatte
dafür maximal notwendig ist, verrät Ihnen der folgende
Ausdruck:
(Länge der Daten + sizeof(Zeilenzeiger)) * Anzahl der gefundenen Zeilen * 2
Der Zeilenzeiger ist normalerweise 4 Byte groß, kann aber bei sehr großen Tabellen in Zukunft noch wachsen.
Für manche SELECT
-Anfragen legt MySQL
ebenfalls temporäre SQL-Tabellen an. Diese sind nicht verborgen
und haben Namen der Form SQL_*
.
ALTER TABLE
legt eine temporäre Tabelle in
dem Verzeichnis der Originaltabelle an.
Die Unix-Socketdatei, die der Server für die Kommunikation mit
lokalen Clients benötigt, liegt nach Voreinstellung unter
/tmp/mysql.sock
. (In manchen
Distributionsformaten kann es auch ein anderes Verzeichnis sein,
wie beispielsweise /var/lib/mysql
für
RPMs.)
Auf manchen Unix-Versionen kann jeder Dateien aus dem
Verzeichnis /tmp
oder anderen ähnlichen
Verzeichnissen für temporäre Dateien löschen. Wenn die
Socketdatei auf Ihrem Dateisystem in einem solchen Verzeichnis
liegt, kann das zu Problemen führen.
Auf den meisten Unix-Versionen können Sie Ihr
/tmp
-Verzeichnis schützen, sodass die
Dateien nur von ihren Eigentümern oder dem Superuser
(root
) gelöscht werden können. Hierzu
setzen Sie das sticky
-Bit auf dem
/tmp
-Verzeichnis, indem Sie sich als
root
anmelden und folgenden Befehl geben:
shell> chmod +t /tmp
Ob das sticky
-Bit gesetzt wurde, prüfen Sie
mit ls -ld /tmp
. Wenn das letzte Zeichen der
Berechtigung ein t
ist, wurde das Bit
gesetzt.
Sie können auch veranlassen, dass der Server die Unix-Socketdatei in einem anderen Verzeichnis erstellt. Wenn Sie dies tun, müssen Sie den Clientprogrammen auch verraten, wo diese Datei jetzt liegt. Den Speicherort können Sie auf mehrere Weisen angeben:
Sie geben den Pfad in einer globalen oder lokalen
Optionsdatei an, zum Beispiel indem Sie folgende Zeilen in
/etc/my.cnf
speichern:
[mysqld] socket=/path/to/socket [client] socket=/path/to/socket
Sie geben auf der Kommandozeile für
mysqld_safe und beim Ausführen von
Clientprogrammen eine --socket
-Option an.
Sie stellen die Umgebungsvariable
MYSQL_UNIX_PORT
auf den Pfad zur
Unix-Socketdatei ein.
Sie rekompilieren MySQL aus den Quelldateien so, dass ein
anderer Standardspeicherort für die Unix-Socketdatei
festgelegt wird. Den Dateipfad definieren Sie mit der Option
--with-unix-socket-path
, wenn Sie
configure ausführen. Siehe auch
Abschnitt 2.8.2, „Typische configure-Optionen“.
Ob der neue Socketspeicherort funktioniert, können Sie überprüfen, indem Sie mit folgendem Befehl eine Serververbindung herstellen:
shell> mysqladmin --socket=/path/to/socket version
Wenn Sie das Problem haben, dass SELECT NOW()
Werte in UTC anstelle Ihrer Ortszeit liefert, müssen Sie Ihren
Server auf Ihre Zeitzone einstellen. Dasselbe gilt, wenn
UNIX_TIMESTAMP()
den verkehrten Wert
zurückgibt. Dies sollte für die Umgebung veranlasst werden, in
welcher der Server läuft, also zum Beispiel in
mysqld_safe oder
mysql.server. Siehe
Anhang F, Umgebungsvariablen.
Die Zeitzone für den Server stellen Sie mit der Option
--timezone=
von mysqld_safe ein. Alternativ können Sie
die Umgebungsvariable timezone_name
TZ
einstellen, bevor
Sie mysqld starten.
Die zulässigen Werte für --timezone
oder
TZ
hängen vom System ab. Bitte schlagen Sie
in der Dokumentation Ihres Betriebssystems die jeweils passenden
Werte nach.
DATE
-SpaltenNULL
-Wertenalias
Nach Voreinstellung unterscheiden Suchoperationen in MySQL nicht
zwischen Groß- und Kleinschreibung (wobei allerdings manche
Zeichensätze grundsätzlich immer zwischen Groß- und
Kleinschreibung unterscheiden, wie beispielsweise
czech
). Das bedeutet, dass Sie bei einer
Suche mit
alle Spaltenwerte geliefert bekommen, die mit
col_name
LIKE
'a%'A
oder a
anfangen. Wenn
Sie diese Suche auf Groß- oder Kleinbuchstaben einschränken
möchten, müssen Sie dafür sorgen, dass die Kollation eines
der beiden Operanden Groß- und Kleinschreibung unterscheidet
oder eine Binärkollation ist. Wenn Sie beispielsweise eine
Spalte und einen String vergleichen, die beide den Zeichensatz
latin1
verwenden, können Sie den
COLLATE
-Operator einschalten, um einem der
beiden Operanden die Kollation
latin1_general_cs
oder
latin1_bin
zuzuweisen. Zum Beispiel:
col_name
COLLATE latin1_general_cs LIKE 'a%'col_name
LIKE 'a%' COLLATE latin1_general_cscol_name
COLLATE latin1_bin LIKE 'a%'col_name
LIKE 'a%' COLLATE latin1_bin
Wenn Sie in einer Spalte immer die Groß- und Kleinschreibung
berücksichtigen möchten, deklarieren Sie sie mit einer
Binärkollation oder CS-Kollation (CS steht für die
Unterscheidung von Groß- und Kleinschreibung). Siehe
Abschnitt 13.1.5, „CREATE TABLE
“.
Einfache Vergleichsoperationen (>=, >, =, <,
<=
, Sortieren und Gruppieren) beruhen auf dem
„Sortierwert“ der Zeichen. Zeichen mit demselben
Sortierwert (wie etwa ‘E
’,
‘e
’ und
‘é
’) werden als gleich
betrachtet.
Das Format eines DATE
-Werts ist
'YYYY-MM-DD'
. Im Standard-SQL ist kein
anderes Format erlaubt. Dieses Format muss in
UPDATE
-Ausdrücken und in der
WHERE
-Klausel von
SELECT
-Anweisungen immer verwendet werden.
Zum Beispiel:
mysql> SELECT * FROM tbl_name
WHERE date >= '2003-05-05';
Der Bequemlichkeit halber konvertiert MySQL ein Datum, das in
einem numerischen Kontext benutzt wird, automatisch in eine Zahl
(und umgekehrt). MySQL ist auch clever genug, um bei Updates und
in einer WHERE
-Klausel, die ein Datum mit
einer TIMESTAMP
-, DATE
-
oder DATETIME
-Spalte vergleicht, eine
„lockere“-String-Form zuzulassen. („Lockere
Form“ bedeutet, dass zwischen den einzelnen Teilen jedes
Interpunktionszeichen als Trennzeichen zulässig ist. So sind
zum Beispiel '2004-08-15'
und
'2004#08#15'
äquivalent.) MySQL kann auch
einen String, der keine Trennzeichen enthält (wie etwa
'20040815'
) konvertieren, vorausgesetzt, er
ergibt einen vernünftigen Datumswert.
Wenn Sie Werte vom Typ DATE
,
TIME
, DATETIME
oder
TIMESTAMP
mit einem konstanten String
vergleichen, der die Operatoren <
,
<=
, =
,
>=
, >
oder
BETWEEN
enthält, konvertiert MySQL den
String normalerweise intern in einen langen Integer, um
Vergleiche schneller ausführen zu können (und ein wenig
„locker“ bei der String-Prüfung sein zu können).
Von dieser Konvertierung gibt es allerdings folgende Ausnahmen:
wenn Sie zwei Spalten vergleichen
wenn Sie eine DATE
-,
TIME
-, DATETIME
- oder
TIMESTAMP
-Spalte mit einem Ausdruck
vergleichen
wenn Sie eine andere Vergleichsmethode als die oben
aufgeführten verwenden, wie etwa IN
oder
STRCMP()
In diesen Ausnahmefällen führt MySQL den Vergleich durch, indem es die Objekte in Strings konvertiert und dann die Strings vergleicht.
Um sicherzugehen, sollten Sie davon ausgehen, dass Strings als Strings verglichen werden, und die passenden Funktionen einsetzen, wenn Sie einen Temporalwert mit einem String vergleichen möchten.
Das spezielle Datum '0000-00-00'
kann als
'0000-00-00'
gespeichert und abgerufen
werden. Wenn Sie ein '0000-00-00'
-Datum in
MyODBC benutzen, so wird es in MyODBC 2.50.12 und höher
automatisch in NULL
konvertiert, da ODBC mit
Datumswerten dieser Art nicht umgehen kann.
Da MySQL die oben beschriebenen Konvertierungen vornimmt, funktionieren folgende Anweisungen:
mysql>INSERT INTO
mysql>tbl_name
(idate) VALUES (19970505);INSERT INTO
mysql>tbl_name
(idate) VALUES ('19970505');INSERT INTO
mysql>tbl_name
(idate) VALUES ('97-05-05');INSERT INTO
mysql>tbl_name
(idate) VALUES ('1997.05.05');INSERT INTO
mysql>tbl_name
(idate) VALUES ('1997 05 05');INSERT INTO
mysql>tbl_name
(idate) VALUES ('0000-00-00');SELECT idate FROM
mysql>tbl_name
WHERE idate >= '1997-05-05';SELECT idate FROM
mysql>tbl_name
WHERE idate >= 19970505;SELECT MOD(idate,100) FROM
mysql>tbl_name
WHERE idate >= 19970505;SELECT idate FROM
tbl_name
WHERE idate >= '19970505';
Doch die folgende Anweisung funktioniert nicht:
mysql> SELECT idate FROM tbl_name
WHERE STRCMP(idate,'20030505')=0;
Da STRCMP()
eine String-Funktion ist,
konvertiert sie idate
in einen String im
Format 'YYYY-MM-DD'
und führt einen
String-Vergleich durch. '20030505'
wird nicht
in das Datum '2003-05-05'
konvertiert, um
einen Datumsvergleich durchzuführen.
Wenn Sie den SQL-Modus ALLOW_INVALID_DATES
eingestellt haben, gestattet MySQL Ihnen die Speicherung von
Datumswerten bei nur rudimentärer Überprüfung: MySQL verlangt
lediglich, dass der Tag im Bereich von 1 bis 31 und der Monat im
Bereich von 1 bis 12 liegt.
Dadurch eignet sich MySQL gut für Webanwendungen, bei denen Jahr, Monat und Tag in drei verschiedenen Feldern abgerufen werden und in denen Sie genau das, was der Benutzer eingibt, speichern möchten (ohne das Datum zu validieren).
Wenn Sie nicht den SQL-Modus NO_ZERO_IN_DATE
SQL verwenden, kann der Tag oder der Monat null sein. Das ist
praktisch, wenn Sie in einer DATE
-Spalte
einen Geburtstag speichern möchten, dessen Datum Sie nur
teilweise kennen.
Wenn Sie nicht den SQL-Modus NO_ZERO_DATE
verwenden, gestattet Ihnen MySQL auch,
'0000-00-00'
als „Dummy-Datum“
zu speichern. Das ist manchmal praktischer als
NULL
-Werte.
Wenn sich das Datum nicht in einen vernünftigen Wert
konvertieren lässt, wird eine 0
in der
DATE
-Spalte gespeichert und als
'0000-00-00'
abgerufen. Dies ist eine Frage
von Schnelligkeit und Bequemlichkeit. Wir sind der Ansicht, dass
der Datenbankserver dieselben Daten liefern sollte, die
gespeichert wurden (selbst wenn diese Daten im Einzelfall nicht
immer logisch richtig sind). Wir denken, dass es Sache der
Anwendung ist, die Datumswerte zu überprüfen.
Wenn Sie wollen, dass MySQL die Daten überprüft und nur
gültige zulässt (es sei denn, dies wird durch IGNORE außer
Kraft gesetzt), müssen Sie den sql_mode
auf
"NO_ZERO_IN_DATE,NO_ZERO_DATE"
einstellen.
NULL
-Werte stiften bei SQL-Neulingen immer
wieder Verwirrung, da diese oft denken, NULL
sei dasselbe wie der leere String ''
. Doch
das ist nicht der Fall. Die folgenden Anweisungen sind
beispielsweise völlig verschieden:
mysql>INSERT INTO my_table (phone) VALUES (NULL);
mysql>INSERT INTO my_table (phone) VALUES ('');
Beide Anweisungen fügen einen Wert in die
phone
-Spalte ein, die erste allerdings einen
NULL
-Wert und die zweite einen leeren String.
Die erste Eingabe bedeutet so viel wie „Telefonnummer
unbekannt“ und die zweite bedeutet „Die Person hat
kein Telefon und somit keine Telefonnummer“.
Als Hilfe für den Umgang mit NULL
-Werten
sind die Operatoren IS NULL
und IS
NOT NULL
sowie die Funktion
IFNULL()
da.
In SQL ergibt ein Vergleich zwischen NULL
und
irgendeinem anderen Wert nie einen Treffer, selbst wenn auch der
andere Wert NULL
ist. Ein Ausdruck, der
NULL
enthält, ergibt immer den Wert
NULL
, es sei denn, die Dokumentation der
Operatoren und Funktionen, die an dem Ausdruck beteiligt sind,
sagt ausdrücklich etwas anderes. Alle Spalten im folgenden
Beispiel geben NULL
zurück:
mysql> SELECT NULL, 1+NULL, CONCAT('Invisible',NULL);
Wenn Sie Spaltenwerte suchen, die NULL
sind,
verwenden Sie bitte nicht den Test expr =
NULL
. Die folgende Anweisung gibt gar keine Zeilen
zurück, da expr = NULL
niemals wahr sein
kann:
mysql> SELECT * FROM my_table WHERE phone = NULL;
Wenn Sie NULL
-Werte suchen, dann mit
IS NULL
. Die folgenden Anweisungen zeigen,
wie man die Telefonnummer NULL
und die leere
Telefonnummer finden kann:
mysql>SELECT * FROM my_table WHERE phone IS NULL;
mysql>SELECT * FROM my_table WHERE phone = '';
Weitere Informationen und Beispiele finden Sie unter
Abschnitt 3.3.4.6, „Mit NULL
-Werten arbeiten“.
Sie können einer Spalte, die NULL
-Werte
enthält, einen Index hinzufügen, wenn Sie
MyISAM
, InnoDB
,
BDB
oder MEMORY
als
Speicher-Engine einsetzen. Andernfalls müssen Sie die
indizierte Spalte als NOT NULL
deklarieren
und können keine NULL
-Werte in sie
einfügen.
Wenn Sie Daten mit LOAD DATA INFILE
lesen,
werden leere oder fehlende Spalten mit ''
aktualisiert. Möchten Sie in eine Spalte einen
NULL
-Wert einfügen, so müssen Sie
\N
in die Datendatei schreiben.
Das Literal „NULL
“ kann unter
bestimmten Umständen ebenfalls verwendet werden. Siehe
Abschnitt 13.2.5, „LOAD DATA INFILE
“.
DISTINCT
, GROUP BY
oder
ORDER BY
betrachten alle
NULL
-Werte als gleich.
ORDER BY
stellt die
NULL
-Werte immer an den Anfang oder, wenn
DESC
für eine absteigende Sortierreihenfolge
angegeben wurde, an das Ende.
Aggregatfunktionen (Summenfunktionen) wie
COUNT()
, MIN()
und
SUM()
ignorieren
NULL
-Werte. Eine Ausnahme bildet die Funktion
COUNT(*)
, die Zeilen und nicht einzelne
Spaltenwerte zählt. Die folgende Anweisung erstellt
beispielsweise zwei Zählungen: eine Zählung der Zeilen in der
Tabelle und eine Zählung der von NULL
verschiedenen Werte in der Spalte age
:
mysql> SELECT COUNT(*), COUNT(age) FROM person;
Für manche Datentypen behandelt MySQL
NULL
-Werte ganz speziell. Wenn Sie
NULL
in eine
TIMESTAMP
-Spalte einfügen, werden Datum und
Uhrzeit von jetzt eingefügt. Wenn Sie NULL
in eine Integer-Spalte einfügen, die das
AUTO_INCREMENT
-Attribut hat, wird stattdessen
die nächste Folgenummer eingesetzt.
Einen Alias können Sie verwenden, um eine Spalte in
GROUP BY
-, ORDER BY
- oder
HAVING
-Klauseln zu benennen. Außerdem sind
Aliasnamen nützlich, um Spalten bessere Namen zu verpassen:
SELECT SQRT(a*b) AS root FROMtbl_name
GROUP BY root HAVING root > 0; SELECT id, COUNT(*) AS cnt FROMtbl_name
GROUP BY id HAVING cnt > 0; SELECT id AS 'Customer identity' FROMtbl_name
;
Im Standard-SQL dürfen Sie in WHERE
-Klauseln
keine Spaltenaliase benutzen, da der Spaltenwert unter
Umständen noch gar nicht festliegt, wenn der
WHERE
-Code ausgeführt wird. Die folgende
Anfrage ist beispielsweise unzulässig:
SELECT id, COUNT(*) AS cnt FROM tbl_name
WHERE cnt > 0 GROUP BY id;
Die WHERE
-Anweisung soll festlegen, welche
Zeilen in den GROUP BY
-Teil einfließen,
während die HAVING
-Klausel entscheiden soll,
welche Zeilen der Ergebnismenge benutzt werden sollen.
Wenn Sie die folgende Meldung beim Versuch eines
ROLLBACK
erhalten, so bedeutet dies, dass
mindestens eine in der Transaktion verwendete Tabelle gar keine
Transaktionen unterstützt:
Änderungen an einigen nicht transaktionalen Tabellen konnten nicht zurückgerollt werden
Diese nichttransaktionssicheren Tabellen werden von der
ROLLBACK
-Anweisung gar nicht betroffen.
Wenn Sie nicht absichtlich transaktionssichere und
nichttransaktionssichere Tabellen in der Transaktion mischen,
tritt diese Fehlermeldung wahrscheinlich auf, weil eine Tabelle,
die Sie für transaktionssicher gehalten haben, dies in
Wirklichkeit nicht ist. Das kann passieren, wenn Sie eine
Tabelle mit einer transaktionssicheren Speicher-Engine anlegen,
die nicht von Ihrem mysqld-Server
unterstützt wird (oder mit einer Startoption ausgeschaltet
wurde). Wenn mysqld eine Speicher-Engine
nicht unterstützt, wird eine MyISAM
-Tabelle
angelegt, und diese ist nicht transaktionssicher.
Welche Speicher Engine eine Tabelle verwendet, erfahren Sie mit folgenden Anweisungen:
SHOW TABLE STATUS LIKE 'tbl_name
'; SHOW CREATE TABLEtbl_name
;
Siehe Abschnitt 13.5.4.21, „SHOW TABLE STATUS
“, und
Abschnitt 13.5.4.6, „SHOW CREATE TABLE
“.
Welche Speicher-Engines Ihr mysqld-Server verwendet, finden Sie mit dieser Anweisung heraus:
SHOW ENGINES;
Sie können jedoch auch nachfolgende Anweisung ausführen und den Wert der Variablen betrachten, die für die von Ihnen gewünschte Speicher-Engine steht:
SHOW VARIABLES LIKE 'have_%';
Um beispielsweise festzustellen, ob die Speicher-Engine
InnoDB
zur Verfügung steht, schauen Sie auf
den Wert der Variablen have_innodb
.
Siehe Abschnitt 13.5.4.9, „SHOW ENGINES
“, und
Abschnitt 13.5.4.24, „SHOW VARIABLES
“.
Wenn die DELETE
-Anweisung für
related_table
insgesamt mehr als 1 Mbyte
beträgt (der Standardwert der Systemvariablen
max_allowed_packet
), dann müssen Sie sie
aufteilen und als mehrere kleinere
DELETE
-Anweisungen ausführen. Am schnellsten
läuft ein DELETE
, wenn Sie nur 100 bis 1.000
related_column
-Werte pro (indizierter)
Anweisung angeben. Wenn related_column
keinen
Index hat, ist die Geschwindigkeit von der Anzahl der Argumente
der IN
-Klausel unabhängig.
Wenn Sie eine komplizierte Anfrage ausführen, die viele Tabellen benutzt, aber nichts zurückgibt, können Sie mit folgendem Verfahren herausfinden, was schief gegangen ist:
Testen Sie die Anfrage mit EXPLAIN
, um
offensichtliche Fehler zu finden. Siehe
Abschnitt 7.2.1, „EXPLAIN
-Syntax (Informationen über ein
SELECT
erhalten)“.
Wählen Sie nur diejenigen Spalten aus, die in der
WHERE
-Klausel aufgeführt sind.
Entfernen Sie immer nur eine einzige Tabelle aus der Anfrage
so lange, bis sie irgendwelche Zeilen zurückgibt. Wenn die
Tabellen groß sind, sollten Sie in Ihrer Anfrage
LIMIT 10
verwenden.
Geben Sie eine SELECT
-Anweisung für die
Spalte der zuletzt aus der Anfrage entfernten Tabelle, die
eigentlich eine passende Zeile hätte enthalten müssen.
Wenn Sie FLOAT
- oder
DOUBLE
-Spalten mit Dezimalzahlen
vergleichen, können Sie keine Gleichheitsvergleiche
(=
) durchführen. Dieses Problem tritt in
allen Programmiersprachen auf, da nicht alle
Fließkommawerte mit einer exakten Genauigkeit gespeichert
werden können. In manchen Fällen können Sie dies beheben,
indem Sie aus einem FLOAT
- einen
DOUBLE
-Wert machen. Siehe
Abschnitt A.5.8, „Probleme mit Fließkommavergleichen“.
Wenn Sie den Fehler immer noch nicht finden können, legen
Sie einen minimalen Testfall an, der mit mysql test
< query.sql
ausgeführt werden kann und Ihre
Probleme verdeutlicht. Eine Testdatei legen Sie an, indem
Sie die Tabellen mit mysqldump --quick db_name
tbl_name_1
...
tbl_name_n
>
query.sql kopieren. Öffnen Sie die Datei in einem
Editor, entfernen Sie einige eingefügte Zeilen (wenn mehr
da sind, als zur Verdeutlichung des Problems notwendig ist)
und fügen Sie am Ende der Datei Ihre
SELECT
-Anweisung an.
Mit folgenden Befehlen können Sie sich vergewissern, dass Ihre Testdatei das Problem zeigt:
shell>mysqladmin create test2
shell>mysql test2 < query.sql
Hängen Sie die Testdatei an einen Bugreport an. Diesen können Sie uns senden, wie in Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“, beschrieben.
Der folgende Abschnitt ist vor allem für
DOUBLE
- und FLOAT
-Spalten
interessant, da Fließkommazahlen von Natur aus ungenau sind.
MySQL führt DECIMAL
-Operationen mit einer
Genauigkeit von 64 Dezimalstellen aus. Das müsste die meisten
Probleme im Hinblick auf die Genauigkeit von
DECIMAL
-Spalten lösen.
Fließkommazahlen stiften gelegentlich Verwirrung, da sie in
einer Computerarchitektur nicht als exakte Werte gespeichert
werden. Das, was der Bildschirm zeigt, ist in der Regel nicht
der genaue Wert der Zahl. Die Datentypen
FLOAT
und DOUBLE
sind
Fließkommatypen. DECIMAL
-Spalten speichern
Werte mit einer exakten Anzahl Stellen, weil sie als Strings
dargestellt werden.
Das folgende Beispiel verdeutlicht das Problem an einem
DOUBLE
:
mysql>CREATE TABLE t1 (i INT, d1 DOUBLE, d2 DOUBLE);
mysql>INSERT INTO t1 VALUES (1, 101.40, 21.40), (1, -80.00, 0.00),
->(2, 0.00, 0.00), (2, -13.20, 0.00), (2, 59.60, 46.40),
->(2, 30.40, 30.40), (3, 37.00, 7.40), (3, -29.60, 0.00),
->(4, 60.00, 15.40), (4, -10.60, 0.00), (4, -34.00, 0.00),
->(5, 33.00, 0.00), (5, -25.80, 0.00), (5, 0.00, 7.20),
->(6, 0.00, 0.00), (6, -51.40, 0.00);
mysql>SELECT i, SUM(d1) AS a, SUM(d2) AS b
->FROM t1 GROUP BY i HAVING a <> b;
+------+-------+------+ | i | a | b | +------+-------+------+ | 1 | 21.4 | 21.4 | | 2 | 76.8 | 76.8 | | 3 | 7.4 | 7.4 | | 4 | 15.4 | 15.4 | | 5 | 7.2 | 7.2 | | 6 | -51.4 | 0 | +------+-------+------+
Das Ergebnis ist richtig. Auch wenn die ersten fünf Datensätze
nicht so aussehen, als würden sie den Test bestehen (die Werte
von a
und b
sehen nicht
verschieden aus), können sie dennoch unterschiedlich sein, da
sie womöglich in der zehnten Nachkommastelle oder so (je nach
Computerarchitektur) eine Abweichung aufweisen.
Wären die Spalten d1
und
d2
als DECIMAL
statt als
DOUBLE
definiert, so hätte die
SELECT
-Anfrage nur eine einzige Zeile
geliefert, nämlich die letzte der obigen Tabelle.
MySQL ermittelt den besten Ausführungsweg für eine Anfrage mit einem kostenorientierten Optimierer. In vielen Fällen kann MySQL den bestmöglichen Ausführungsplan berechnen, aber manchmal hat es nicht genügend Informationen über die Daten und muss „fundierte“ Annahmen über die Daten treffen.
Wenn MySQL einmal nicht das Richtige tun sollte, stehen folgende Tools als Hilfestellung zur Verfügung:
Die EXPLAIN
-Anweisung lässt erkennen, wie
MySQL eine Anfrage verarbeitet. Um sie zu benutzen, setzen Sie
einfach das Schlüsselwort EXPLAIN
vor Ihre
SELECT
-Anweisung:
mysql> EXPLAIN SELECT * FROM t1, t2 WHERE t1.i = t2.i;
EXPLAIN
wird in Abschnitt 7.2.1, „EXPLAIN
-Syntax (Informationen über ein
SELECT
erhalten)“,
genauer beschrieben.
Mit ANALYZE TABLE
können Sie die
Schlüsselverteilungen für die gescannte Tabelle
aktualisieren. Siehe auch Abschnitt 13.5.2.1, „tbl_name
ANALYZE TABLE
“.
Wenn Sie für die gescannte Tabelle die FORCE
INDEX
-Anweisung geben, teilen Sie MySQL dadurch mit,
dass Tabellenscans im Vergleich zur Verwendung des
vorgegebenen Indexes sehr aufwändig sind. Siehe
Abschnitt 13.2.7, „SELECT
“.
SELECT * FROM t1, t2 FORCE INDEX (index_for_column) WHERE t1.col_name=t2.col_name;
USE INDEX
und IGNORE
INDEX
können ebenfalls nützlich sein.
Globale und tabellenspezifische
STRAIGHT_JOIN
s. Siehe
Abschnitt 13.2.7, „SELECT
“.
Sie können auch globale oder Thread-spezifische
Systemvariablen einstellen, zum Beispiel indem Sie
mysqld mit der Option
--max-seeks-for-key=1000
starten oder dem
Optimierer mit SET max_seeks_for_key=1000
sagen, dass er davon ausgehen soll, dass kein Schlüsselscan
mehr als 1.000 Schlüsselsuchoperationen bedeutet. Siehe
Abschnitt 5.2.2, „Server-Systemvariablen“.
ALTER TABLE
stellt die Tabelle auf den
aktuellen Zeichensatz um. Wenn Sie während der Ausführung von
ALTER TABLE
einen Fehler wegen doppelt
vorhandener Schlüssel bekommen, liegt dies entweder daran, dass
der neue Zeichensatz zwei Schlüssel demselben Wert zuordnet,
oder daran, dass die Tabelle beschädigt ist. Im zweiten Fall
müssen Sie eine REPAIR TABLE
-Anweisung auf
der Tabelle ausführen.
Wenn ALTER TABLE
mit der folgenden
Fehlermeldung abbricht, kann dies daran liegen, dass MySQL bei
einer vorherigen ALTER TABLE
-Operation
abgestürzt ist und noch eine alte Tabelle namens
A-
oder
xxx
B-
in der
Gegend herumfliegt:
xxx
Error on rename of './database/name.frm'
to './database/B-xxx
.frm' (Errcode: 17)
In diesem Fall gehen Sie in das Data Directory von MySQL und
löschen alle Dateien, deren Namen mit A-
oder B-
anfangen. (Oder Sie verschieben sie
an einen anderen Ort, anstatt sie zu löschen).
ALTER TABLE
funktioniert folgendermaßen:
Erzeuge eine neue Tabelle namens
A-
mit den gewünschten Strukturänderungen.
xxx
Kopiere alle Zeilen der Originaltabelle in
A-
.
xxx
Benenne die Originaltabelle in
B-
um.
xxx
Gib A-
den ursprünglichen Namen der Tabelle.
xxx
Lösche
B-
.
xxx
Wenn bei der Umbenennungsoperation etwas schief geht, versucht
MySQL, die Änderungen rückgängig zu machen. Bei ernsthaften
Problemen (die eigentlich nicht vorkommen sollten) könnte MySQL
die alte Tabelle als
B-
zurücklassen. Mit einer einfachen Umbenennung der
Tabellendateien auf Systemebene müssten Sie Ihre Daten
zurückbekommen.
xxx
Wenn Sie ALTER TABLE
auf einer
transaktionssicheren Tabelle ausführen oder Windows oder OS/2
benutzen, wird ALTER TABLE
eine Sperre der
Tabelle aufheben, falls Sie zuvor eine LOCK
TABLE
-Anweisung auf ihr ausgeführt haben, da
InnoDB
und diese Betriebssysteme keine
Tabelle löschen können, die gerade in Gebrauch ist.
Zuerst müssen Sie überlegen, ob es wirklich notwendig ist, die
Spaltenreihenfolge in der Tabelle zu ändern. Das Hauptanliegen
von SQL ist ja schließlich, die Anwendung vom Format der
Datenspeicherung abzukoppeln. Sie sollten immer die Reihenfolge
angeben, in der Sie Ihre Daten abholen möchten. Die erste der
folgenden Anweisungen gibt die Spalten in der Reihenfolge
col_name1
,
col_name2
,
col_name3
zurück, und die zweite in
der Reihenfolge col_name1
,
col_name3
,
col_name2
:
mysql>SELECT
mysql>col_name1
,col_name2
,col_name3
FROMtbl_name
;SELECT
col_name1
,col_name3
,col_name2
FROMtbl_name
;
Wenn Sie dennoch die Reihenfolge der Spalten ändern möchten, tun Sie das folgendermaßen:
Sie erzeugen eine neue Tabelle, in der die Spalten die neue Reihenfolge haben.
Sie führen folgende Anweisung aus:
mysql>INSERT INTO new_table
->SELECT columns-in-new-order FROM old_table;
Sie löschen die old_table
oder benennen
sie um.
Sie geben der neuen Tabelle den Namen des Originals:
mysql> ALTER TABLE new_table RENAME old_table;
SELECT *
eignet sich gut für Testanfragen.
In einer Anwendung sollten Sie sich jedoch
nie darauf verlassen, mit SELECT
*
die Spalten nach ihrer Position abzufragen. Die
Reihenfolge und Position, in der die Spalten zurückgegeben
werden, kann sich ändern, wenn Sie Spalten neu einfügen,
verschieben oder löschen. Eine einfache Änderung an der
Tabellenstruktur kann so Ihre Anwendung bereits zum Absturz
bringen.
Für die Nutzung von TEMPORARY
-Tabellen gibt
es folgende Beschränkungen:
Eine TEMPORARY
-Tabelle kann nur den Typ
HEAP
, ISAM
,
MyISAM
, MERGE
oder
InnoDB
haben.
Eine TEMPORARY
-Tabelle kann nicht
mehrmals in derselben Anfrage benutzt werden. Das Folgende
funktioniert beispielsweise nicht:
mysql> SELECT * FROM temp_table, temp_table AS t2;
ERROR 1137: Can't reopen table: 'temp_table'
Die SHOW TABLES
-Anweisung führt keine
TEMPORARY
-Tabellen auf.
Sie können eine TEMPORARY
-Tabelle nicht
mit RENAME
, sondern nur mit
ALTER TABLE
umbenennen:
mysql> ALTER TABLE orig_name RENAME new_name;
Im Zusammenhang mit Replikation können temporäre Tabellen Probleme machen. Weiteres erfahren Sie unter Abschnitt 6.8, „Replikation: Features und bekannte Probleme“.
Die folgenden Fehler sind in den neueren Versionen von MySQL bekannt geworden.
Informationen über plattformspezifische Probleme finden Sie in den Anleitungen zur Installation und Portierung von MySQL unter Abschnitt 2.12, „Betriebssystemspezifische Anmerkungen“, und Anhang E, Anmerkungen zur Portierung auf andere Systeme.
Die folgenden Probleme sind bekannt und werden vorrangig gelöst:
Wenn Sie einen NULL
-Wert mit einer
Unterabfrage kombinieren, die eine
ALL/ANY/SOME
-Klausel hat, und die
Unterabfrage ein leeres Ergebnis zurückliefert, kann der
Vergleich das nicht standardmäßige Resultat
NULL
ergeben anstatt
TRUE
oder FALSE
. Dies
wird in MySQL 5.1 behoben.
Die Optimierung von Unterabfragen ist bei
IN
weniger effizient als bei
=
.
Selbst wenn Sie lower_case_table_names=2
verwenden (damit sich MySQL an die Groß-/Kleinschreibung
von Datenbank- und Tabellennamen erinnert) kann MySQL sich
diese nicht für Datenbanknamen im Zusammenhang mit der
Funktion DATABASE()
oder den diversen
Logs merken (dies gilt für Systeme, die nicht zwischen
Groß- und Kleinschreibung unterscheiden).
Das Löschen eines FOREIGN
KEY
-Constraints funktioniert nicht in einer
Replikation, da der Constraint auf dem Slave unter
Umständen einen anderen Namen hat.
REPLACE
(und LOAD DATA
mit der REPLACE
-Option) löst kein
ON DELETE CASCADE
aus.
DISTINCT
mit ORDER BY
funktioniert nicht in GROUP_CONCAT()
,
wenn Sie nicht nur die Spalten verwenden, die in der
DISTINCT
-Liste aufgeführt sind.
Wenn ein Benutzer eine langwierige Transaktion laufen lässt
und ein anderer Benutzer eine Tabelle löscht, die von der
Transaktion geändert wird, besteht ein gewisses Risiko,
dass der DROP TABLE
im Binärlog
festgehalten wird, bevor die Tabelle in der Transaktion
benutzt wird. Dies wollen wir beheben, indem wir den
DROP TABLE
-Befehl so lange aussetzen
lassen, bis die Tabelle in keiner Transaktion mehr benutzt
wird.
Wenn Sie einen großen Integer-Wert (zwischen 263 und 264–1) in eine Decimal- oder String-Spalte einfügen, wird er als negativer Wert geschrieben, da die Zahl als vorzeichenbehafteter Integer ausgewertet wird.
FLUSH TABLES WITH READ LOCK
kann
COMMIT
nicht blockieren, wenn der Server
ohne Binärlogging läuft. Das kann zu Konsistenzproblemen
mit Tabellen führen, wenn Sie eine vollständige
Datensicherung ausführen.
ANALYZE TABLE
kann
BDB
-Tabellen unter Umständen bis zum
nächsten Neustart von mysqld unbenutzbar
machen. Wenn dies geschieht, suchen Sie in der Fehlerdatei
von MySQL nach Fehlern der folgenden Art:
001207 22:07:56 bdb: log_flush: LSN past current end-of-log
Führen Sie kein ALTER TABLE
auf einer
BDB
-Tabelle aus, auf der Transaktionen
mit mehreren Anweisungen laufen. Dies können Sie erst nach
Abschluss aller dieser Transaktionen tun, da die Transaktion
ansonsten eventuell ignoriert wird.
ANALYZE TABLE
, OPTIMIZE
TABLE
und REPAIR TABLE
können
Probleme mit Tabellen verursachen, die mit INSERT
DELAYED
laufen.
Auch mit LOCK TABLE ...
und
FLUSH TABLES ...
ist nicht
gewährleistet, dass nicht noch eine halbfertige Transaktion
auf der Tabelle abläuft.
BDB
-Tabellen öffnen sich relativ
langsam. Wenn Sie viele BDB
-Tabellen in
einer Datenbank haben, braucht der
mysql-Client viel Zeit, es sei denn, Sie
verwenden die Option -A
oder
rehash
. Das macht sich besonders bei
großen Tabellen-Caches bemerkbar.
Replikation verwendet Logging auf Anweisungsebene: Der Master schreibt die ausgeführten Anweisungen in das Binärlog. Dies ist eine sehr schnelle, kompakte und wirkungsvolle Loggingmethode, die in den meisten Fällen auch perfekt funktioniert.
Es ist jedoch möglich, dass Unterschiede zwischen den Daten von Master und Slave auftreten, wenn eine Anfrage so entworfen wurde, dass sie Daten in nichtdeterministischer Weise ändert (was allerdings generell, auch außerhalb einer Replikation, nicht zu empfehlen ist).
Beispielsweise:
CREATE ... SELECT
- oder
INSERT ... SELECT
-Anweisungen, die
null oder NULL
-Werte in eine
AUTO_INCREMENT
-Spalte einfügen.
DELETE
, wenn Sie Zeilen aus einer
Tabelle löschen, die Fremdschlüssel mit ON
DELETE CASCADE
-Eigenschaften hat.
REPLACE ... SELECT
, INSERT
IGNORE ... SELECT
, wenn Sie in den
eingefügten Daten Schlüsselduplikate haben.
Genau dann, wenn die vorangegangenen
Anfragen keine ORDER BY
-Klausel haben,
die eine deterministische Sortierreihenfolge
garantiert.
So kann beispielsweise ein SELECT
für
INSERT ... SELECT
ohne ORDER
BY
-Klausel Zeilen in einer anderen Reihenfolge
zurückliefern (was dazu führt, dass eine Zeile einen
unterschiedlichen Rang und somit auch unterschiedliche
Nummern in der AUTO_INCREMENT
-Spalte
haben kann), je nachdem, wie sich die Optimierer von Master
und Slave entscheiden.
Eine Anfrage wird auf Master und Slave nur in folgenden Fällen unterschiedlich optimiert:
Wenn die Tabelle auf dem Master mit einer anderen
Speicher-Engine als auf dem Slave gespeichert wird. (Es
ist nämlich möglich, auf Master und Slave verschiedene
Speicher-Engines zu verwenden. So können Sie
beispielsweise InnoDB
auf dem Master
und MyISAM
auf dem Slave einsetzen,
wenn der Slave weniger Festplattenspeicher zur
Verfügung hat.)
Wenn die Größen der MySQL-Puffer
(key_buffer_size
und so weiter) auf
Master und Slave unterschiedlich sind.
Wenn Master und Slave mit unterschiedlichen MySQL-Versionen laufen und der Optimierungscode einen Unterschied zwischen diesen beiden Versionen macht.
Dieses Problem kann auch die Datenbankwiederherstellung mit mysqlbinlog|mysql beeinträchtigen.
Am einfachsten lässt sich dieses Problem verhindern, wenn
Sie den oben erwähnten nichtdeterministischen Anfragen eine
ORDER BY
-Klausel hinzufügen, um zu
gewährleisten, dass die Zeilen immer in derselben
Reihenfolge gespeichert oder modifiziert werden.
In künftigen MySQL-Versionen werden wir automatisch eine
ORDER BY
-Klausel hinzufügen, wo sie
nötig ist.
Die folgenden Probleme sind bekannt und werden bald behoben:
Die Logdateinamen basieren auf dem Namen des Serverhosts
(sofern Sie nicht mit der Startoption einen Dateinamen
vorgeben). Wenn Sie Ihren Hostnamen ändern möchten,
müssen Sie Optionen wie beispielsweise
--log-bin=
verwenden. Oder Sie benennen die alten Dateien mit dem neuen
Hostnamen um (wenn es Binärlogs sind, müssen Sie dazu auch
die Indexdatei des Binärlogs bearbeiten und die Binlognamen
ebenfalls ändern). Siehe Abschnitt 5.2.1, „Befehlsoptionen für mysqld“.
old_host_name
-bin
mysqlbinlog löscht keine temporären
Dateien, die nach einem LOAD DATA
INFILE
-Befehl übrig bleiben. Siehe
Abschnitt 8.8, „mysqlbinlog — Hilfsprogramm für die Verarbeitung binärer Logdateien“.
RENAME
funktioniert nicht mit
TEMPORARY
-Tabellen oder Tabellen, die in
einer MERGE
-Tabelle benutzt werden.
Aufgrund der Art und Weise, wie Tabellenformatdateien
(.frm
-Dateien) gespeichert werden,
können Sie Zeichen 255 (CHAR(255)
) nicht
in Tabellennamen, Spaltennamen und Enumerationen verwenden.
Dies soll in Version 5.1 behoben werden, wenn wir neue
Formatdateien für die Tabellendefinitionen implementieren.
Wenn Sie SET CHARACTER SET
benutzen,
können Sie keine übersetzten Zeichen in den Namen von
Datenbanken, Tabellen und Spalten verwenden.
Sie dürfen kein ‘_
’ oder
‘%
’ mit
ESCAPE
in LIKE ...
ESCAPE
verwenden.
Wenn Sie in einer DECIMAL
-Spalte dieselbe
Zahl in verschiedenen Formaten gespeichert haben
(beispielsweise +01.00
,
1.00
, 01.00
), kann es
passieren, dass GROUP BY
diese Werte als
unterschiedlich betrachtet.
Sie können den Server nicht in einem anderen Verzeichnis bauen, wenn Sie MIT-pthreads verwenden. Da sich dies nur durch eine Änderung von MIT-pthreads beheben ließe, werden wir es wahrscheinlich nicht reparieren können. Siehe auch Abschnitt 2.8.5, „Anmerkungen zu MIT-pthreads“.
BLOB
- und TEXT
-Werte
können in GROUP BY
, ORDER
BY
oder DISTINCT
nicht
zuverlässig benutzt werden, da in diesen Fällen zum
Vergleich von BLOB
-Werten nur die ersten
max_sort_length
Bytes herangezogen
werden. Der Standardwert von
max_sort_length
beträgt 1.024 und kann
beim Serverstart oder zur Laufzeit geändert werden.
Numerische Berechnungen werden mit BIGINT
oder DOUBLE
ausgeführt (beide sind
normalerweise 64 Bits lang). Welche Genauigkeit sie haben,
hängt von der Funktion ab. Im Allgemeinen werden
Bitfunktionen mit einer
BIGINT
-Genauigkeit, IF
und ELT()
mit einer
BIGINT
- oder
DOUBLE
-Genauigkeit und alles Übrige mit
einer DOUBLE
-Genauigkeit ausgeführt. Sie
sollten möglichst (außer für Bitfelder) keine sehr langen
Werte verwenden, wenn diese länger als 63 Bits
(9223372036854775807) werden können.
In einer Tabelle dürfen bis zu 255 ENUM
-
und SET
-Spalten vorhanden sein.
In MIN()
, MAX()
und
anderen Aggregatfunktionen vergleicht MySQL
ENUM
- und SET
-Spalten
gegenwärtig nach ihrem Stringwert anstatt nach der
relativen Position des Strings in der Menge.
mysqld_safe leitet alle Meldungen von
mysqld in das
mysqld-Log. Wenn Sie das Log mit
mysqladmin refresh schließen und neu
öffnen, besteht jedoch das Problem, dass
stdout
und stderr
weiterhin in das alte Log umgeleitet werden. Wenn Sie viel
mit --log
arbeiten, sollten Sie
mysqld_safe so bearbeiten, dass es
Logeinträge in
statt in
host_name
.err
schreibt, damit Sie den Speicherplatz des alten Logs
leichter zurückholen können, indem Sie es einfach löschen
und mysqladmin refresh ausführen.
host_name
.log
In einer UPDATE
-Anweisung werden die
Spalten von links nach rechts aktualisiert. Wenn Sie eine
aktualisierte Spalte benutzen, bekommen Sie den
aktualisierten statt des ursprünglichen Werts. Die folgende
Anweisung inkrementiert beispielsweise
KEY
um 2
und
nicht um
1
:
mysql> UPDATE tbl_name
SET KEY=KEY+1,KEY=KEY+1;
Sie können zwar in derselben Anfrage mehrere temporäre Tabellen benutzen, aber nicht dieselbe zweimal. Das Folgende funktioniert beispielsweise nicht:
mysql> SELECT * FROM temp_table, temp_table AS t2;
ERROR 1137: Can't reopen table: 'temp_table'
Der Optimierer behandelt DISTINCT
unterschiedlich, je nachdem, ob Sie in einem Join
„verborgene“ Spalten benutzen oder nicht.
Verborgene Spalten werden in einem Join als Teil des
Ergebnisses betrachtet (obwohl sie nicht angezeigt werden),
während sie in normalen Anfragen nicht an einem
DISTINCT
-Vergleich teilnehmen. Dies
werden wir wahrscheinlich in Zukunft dahingehend ändern,
dass die verborgenen Spalten bei DISTINCT
nicht mehr am Vergleich beteiligt werden.
Ein Beispiel dafür ist:
SELECT DISTINCT mp3id FROM band_downloads WHERE userid = 9 ORDER BY id DESC;
und
SELECT DISTINCT band_downloads.mp3id FROM band_downloads,band_mp3 WHERE band_downloads.userid = 9 AND band_mp3.id = band_downloads.mp3id ORDER BY band_downloads.id DESC;
Im zweiten Fall bekommen Sie mit MySQL Server 3.23.x
vielleicht zwei identische Zeilen in der Ergebnismenge (da
die Werte in der verborgenen id
-Spalte
unterschiedlich sein können).
Beachten Sie, dass dies nur in Anfragen ohne ORDER
BY
-Spalten im Ergebnis passieren kann.
Wenn Sie eine PROCEDURE
auf einer Anfrage
ausführen, die eine leere Menge zurückgibt, wird die
PROCEDURE
in manchen Fällen die Spalten
nicht transformieren.
Beim Anlegen einer Tabelle vom Typ MERGE
wird nicht geprüft, ob die Typen der zugrunde liegenden
Tabellen kompatibel sind.
Wenn Sie einer Tabelle, die in einer
MERGE
-Tabelle benutzt wird, mit
ALTER TABLE
einen
UNIQUE
-Index hinzufügen und dann einen
normalen Index auf die MERGE
-Tabelle
legen, ist die Reihenfolge der Schlüssel bei Tabellen
anders, wenn zuvor ein
Nicht-UNIQUE
-Schlüssel in der Tabelle
bestand. Der Grund: ALTER TABLE
setzt
UNIQUE
-Indizes vor normale Indizes, um so
früh wie möglich Schlüsselduplikate erkennen zu können.
Inhaltsverzeichnis
Dieses Kapitel enthält die Fehler, die auftreten können, wenn MySQL aus einer beliebigen Host-Sprache aus aufgerufen wird. Die erste Liste enhält die Fehlermeldungen des Servers, die zweite Liste die Fehlermeldungen der Clientprogramme.
Die Fehlermeldungen werden laufend überarbeitet. Daher kann es sein, dass einige Meldungen nicht, noch nicht, oder nicht mehr auf deutsch verfügbar sind. In diesem Fall werden englische Fehlermeldungen verwendet.
Die Fehlermeldungen des Servers stammen aus folgenden Quelldateien:
Die Texte der Fehlermeldungen befinden sich in der Datei
share/errmsg.txt
.
%d
und %s
stellen
Zahlen beziehungsweise Strings dar, die bei der Ausgabe der
Meldungen entsprechend ersetzt werden.
Die Inhalte der Datei
share/errmsg.txt
werden verwendet, um
die Definitionen in den MySQL-Quelldateien
include/mysqld_error.h
und include/mysqld_ername.h
zu erzeugen.
Die SQLSTATE-Werte in
share/errmsg.txt
werden zur Erzeugung der
Definitionen in der MySQL-Quelldatei
include/sql_state.h
verwendet.
Weil die Fehlermeldungen häufig aktualisiert werden, kann es sein, dass die genannten Dateien zusätzliche Fehlermeldungen enthalten, die hier noch nicht aufgeführt sind.
Fehler: 1000
SQLSTATE: HY000
(ER_HASHCHK
)
Meldung: hashchk
Fehler: 1001
SQLSTATE: HY000
(ER_NISAMCHK
)
Meldung: isamchk
Fehler: 1002
SQLSTATE: HY000
(ER_NO
)
Meldung: Nein
Fehler: 1003
SQLSTATE: HY000
(ER_YES
)
Meldung: Ja
Fehler: 1004
SQLSTATE: HY000
(ER_CANT_CREATE_FILE
)
Meldung: Kann Datei '%s' nicht erzeugen (Fehler: %d)
Fehler: 1005
SQLSTATE: HY000
(ER_CANT_CREATE_TABLE
)
Meldung: Kann Tabelle '%s' nicht erzeugen (Fehler: %d)
Fehler: 1006
SQLSTATE: HY000
(ER_CANT_CREATE_DB
)
Meldung: Kann Datenbank '%s' nicht erzeugen (Fehler: %d)
Fehler: 1007
SQLSTATE: HY000
(ER_DB_CREATE_EXISTS
)
Meldung: Kann Datenbank '%s' nicht erzeugen. Datenbank existiert bereits
Fehler: 1008
SQLSTATE: HY000
(ER_DB_DROP_EXISTS
)
Meldung: Kann Datenbank '%s' nicht löschen; Datenbank nicht vorhanden
Fehler: 1009
SQLSTATE: HY000
(ER_DB_DROP_DELETE
)
Meldung: Fehler beim Löschen der Datenbank ('%s' kann nicht gelöscht werden, Fehler: %d)
Fehler: 1010
SQLSTATE: HY000
(ER_DB_DROP_RMDIR
)
Meldung: Fehler beim Löschen der Datenbank (Verzeichnis '%s' kann nicht gelöscht werden, Fehler: %d)
Fehler: 1011
SQLSTATE: HY000
(ER_CANT_DELETE_FILE
)
Meldung: Fehler beim Löschen von '%s' (Fehler: %d)
Fehler: 1012
SQLSTATE: HY000
(ER_CANT_FIND_SYSTEM_REC
)
Meldung: Datensatz in der Systemtabelle nicht lesbar
Fehler: 1013
SQLSTATE: HY000
(ER_CANT_GET_STAT
)
Meldung: Kann Status von '%s' nicht ermitteln (Fehler: %d)
Fehler: 1014
SQLSTATE: HY000
(ER_CANT_GET_WD
)
Meldung: Kann Arbeitsverzeichnis nicht ermitteln (Fehler: %d)
Fehler: 1015
SQLSTATE: HY000
(ER_CANT_LOCK
)
Meldung: Datei kann nicht gesperrt werden (Fehler: %d)
Fehler: 1016
SQLSTATE: HY000
(ER_CANT_OPEN_FILE
)
Meldung: Kann Datei '%s' nicht öffnen (Fehler: %d)
Fehler: 1017
SQLSTATE: HY000
(ER_FILE_NOT_FOUND
)
Meldung: Kann Datei '%s' nicht finden (Fehler: %d)
Fehler: 1018
SQLSTATE: HY000
(ER_CANT_READ_DIR
)
Meldung: Verzeichnis von '%s' nicht lesbar (Fehler: %d)
Fehler: 1019
SQLSTATE: HY000
(ER_CANT_SET_WD
)
Meldung: Kann nicht in das Verzeichnis '%s' wechseln (Fehler: %d)
Fehler: 1020
SQLSTATE: HY000
(ER_CHECKREAD
)
Meldung: Datensatz hat sich seit dem letzten Zugriff auf Tabelle '%s' geändert
Fehler: 1021
SQLSTATE: HY000
(ER_DISK_FULL
)
Meldung: Festplatte voll (%s). Warte, bis jemand Platz schafft ...
Fehler: 1022
SQLSTATE: 23000
(ER_DUP_KEY
)
Meldung: Kann nicht speichern, Grund: doppelter Schlüssel in Tabelle '%s'
Fehler: 1023
SQLSTATE: HY000
(ER_ERROR_ON_CLOSE
)
Meldung: Fehler beim Schließen von '%s' (Fehler: %d)
Fehler: 1024
SQLSTATE: HY000
(ER_ERROR_ON_READ
)
Meldung: Fehler beim Lesen der Datei '%s' (Fehler: %d)
Fehler: 1025
SQLSTATE: HY000
(ER_ERROR_ON_RENAME
)
Meldung: Fehler beim Umbenennen von '%s' in '%s' (Fehler: %d)
Fehler: 1026
SQLSTATE: HY000
(ER_ERROR_ON_WRITE
)
Meldung: Fehler beim Speichern der Datei '%s' (Fehler: %d)
Fehler: 1027
SQLSTATE: HY000
(ER_FILE_USED
)
Meldung: '%s' ist für Änderungen gesperrt
Fehler: 1028
SQLSTATE: HY000
(ER_FILSORT_ABORT
)
Meldung: Sortiervorgang abgebrochen
Fehler: 1029
SQLSTATE: HY000
(ER_FORM_NOT_FOUND
)
Meldung: View '%s' existiert für '%s' nicht
Fehler: 1030
SQLSTATE: HY000
(ER_GET_ERRNO
)
Meldung: Fehler %d (Speicher-Engine)
Fehler: 1031
SQLSTATE: HY000
(ER_ILLEGAL_HA
)
Meldung: Diese Option gibt es nicht (Speicher-Engine für '%s')
Fehler: 1032
SQLSTATE: HY000
(ER_KEY_NOT_FOUND
)
Meldung: Kann Datensatz in '%s' nicht finden
Fehler: 1033
SQLSTATE: HY000
(ER_NOT_FORM_FILE
)
Meldung: Falsche Information in Datei '%s'
Fehler: 1034
SQLSTATE: HY000
(ER_NOT_KEYFILE
)
Meldung: Fehlerhafte Index-Datei für Tabelle '%s'; versuche zu reparieren
Fehler: 1035
SQLSTATE: HY000
(ER_OLD_KEYFILE
)
Meldung: Alte Index-Datei für Tabelle '%s'. Bitte reparieren
Fehler: 1036
SQLSTATE: HY000
(ER_OPEN_AS_READONLY
)
Meldung: Tabelle '%s' ist nur lesbar
Fehler: 1037
SQLSTATE: HY001
(ER_OUTOFMEMORY
)
Meldung: Kein Speicher vorhanden (%d Bytes benötigt). Bitte Server neu starten
Fehler: 1038
SQLSTATE: HY001
(ER_OUT_OF_SORTMEMORY
)
Meldung: Kein Speicher zum Sortieren vorhanden. sort_buffer_size sollte im Server erhöht werden
Fehler: 1039
SQLSTATE: HY000
(ER_UNEXPECTED_EOF
)
Meldung: Unerwartetes Ende beim Lesen der Datei '%s' (Fehler: %d)
Fehler: 1040
SQLSTATE: 08004
(ER_CON_COUNT_ERROR
)
Meldung: Zu viele Verbindungen
Fehler: 1041
SQLSTATE: HY000
(ER_OUT_OF_RESOURCES
)
Meldung: Kein Speicher mehr vorhanden. Prüfen Sie, ob mysqld oder ein anderer Prozess den gesamten Speicher verbraucht. Wenn nicht, sollten Sie mit 'ulimit' dafür sorgen, dass mysqld mehr Speicher benutzen darf, oder mehr Swap-Speicher einrichten
Fehler: 1042
SQLSTATE: 08S01
(ER_BAD_HOST_ERROR
)
Meldung: Kann Hostnamen für diese Adresse nicht erhalten
Fehler: 1043
SQLSTATE: 08S01
(ER_HANDSHAKE_ERROR
)
Meldung: Ungültiger Handshake
Fehler: 1044
SQLSTATE: 42000
(ER_DBACCESS_DENIED_ERROR
)
Meldung: Benutzer '%s'@'%s' hat keine Zugriffsberechtigung für Datenbank '%s'
Fehler: 1045
SQLSTATE: 28000
(ER_ACCESS_DENIED_ERROR
)
Meldung: Benutzer '%s'@'%s' hat keine Zugriffsberechtigung (verwendetes Passwort: %s)
Fehler: 1046
SQLSTATE: 3D000
(ER_NO_DB_ERROR
)
Meldung: Keine Datenbank ausgewählt
Fehler: 1047
SQLSTATE: 08S01
(ER_UNKNOWN_COM_ERROR
)
Meldung: Unbekannter Befehl
Fehler: 1048
SQLSTATE: 23000
(ER_BAD_NULL_ERROR
)
Meldung: Feld '%s' darf nicht NULL sein
Fehler: 1049
SQLSTATE: 42000
(ER_BAD_DB_ERROR
)
Meldung: Unbekannte Datenbank '%s'
Fehler: 1050
SQLSTATE: 42S01
(ER_TABLE_EXISTS_ERROR
)
Meldung: Tabelle '%s' bereits vorhanden
Fehler: 1051
SQLSTATE: 42S02
(ER_BAD_TABLE_ERROR
)
Meldung: Unbekannte Tabelle '%s'
Fehler: 1052
SQLSTATE: 23000
(ER_NON_UNIQ_ERROR
)
Meldung: Feld '%s' in %s ist nicht eindeutig
Fehler: 1053
SQLSTATE: 08S01
(ER_SERVER_SHUTDOWN
)
Meldung: Der Server wird heruntergefahren
Fehler: 1054
SQLSTATE: 42S22
(ER_BAD_FIELD_ERROR
)
Meldung: Unbekanntes Tabellenfeld '%s' in %s
Fehler: 1055
SQLSTATE: 42000
(ER_WRONG_FIELD_WITH_GROUP
)
Meldung: '%s' ist nicht in GROUP BY vorhanden
Fehler: 1056
SQLSTATE: 42000
(ER_WRONG_GROUP_FIELD
)
Meldung: Gruppierung über '%s' nicht möglich
Fehler: 1057
SQLSTATE: 42000
(ER_WRONG_SUM_SELECT
)
Meldung: Die Verwendung von Summierungsfunktionen und Spalten im selben Befehl ist nicht erlaubt
Fehler: 1058
SQLSTATE: 21S01
(ER_WRONG_VALUE_COUNT
)
Meldung: Die Anzahl der Spalten entspricht nicht der Anzahl der Werte
Fehler: 1059
SQLSTATE: 42000
(ER_TOO_LONG_IDENT
)
Meldung: Name des Bezeichners '%s' ist zu lang
Fehler: 1060
SQLSTATE: 42S21
(ER_DUP_FIELDNAME
)
Meldung: Doppelter Spaltenname: '%s'
Fehler: 1061
SQLSTATE: 42000
(ER_DUP_KEYNAME
)
Meldung: Doppelter Name für Schlüssel vorhanden: '%s'
Fehler: 1062
SQLSTATE: 23000
(ER_DUP_ENTRY
)
Meldung: Doppelter Eintrag '%s' für Schlüssel '%s'
Fehler: 1063
SQLSTATE: 42000
(ER_WRONG_FIELD_SPEC
)
Meldung: Falsche Spezifikation für Feld '%s'
Fehler: 1064
SQLSTATE: 42000
(ER_PARSE_ERROR
)
Meldung: %s bei '%s' in Zeile %d
Fehler: 1065
SQLSTATE: 42000
(ER_EMPTY_QUERY
)
Meldung: Leere Abfrage
Fehler: 1066
SQLSTATE: 42000
(ER_NONUNIQ_TABLE
)
Meldung: Tabellenname/Alias '%s' nicht eindeutig
Fehler: 1067
SQLSTATE: 42000
(ER_INVALID_DEFAULT
)
Meldung: Fehlerhafter Vorgabewert (DEFAULT) für '%s'
Fehler: 1068
SQLSTATE: 42000
(ER_MULTIPLE_PRI_KEY
)
Meldung: Mehrere Primärschlüssel (PRIMARY KEY) definiert
Fehler: 1069
SQLSTATE: 42000
(ER_TOO_MANY_KEYS
)
Meldung: Zu viele Schlüssel definiert. Maximal %d Schlüssel erlaubt
Fehler: 1070
SQLSTATE: 42000
(ER_TOO_MANY_KEY_PARTS
)
Meldung: Zu viele Teilschlüssel definiert. Maximal %d Teilschlüssel erlaubt
Fehler: 1071
SQLSTATE: 42000
(ER_TOO_LONG_KEY
)
Meldung: Schlüssel ist zu lang. Die maximale Schlüssellänge beträgt %d
Fehler: 1072
SQLSTATE: 42000
(ER_KEY_COLUMN_DOES_NOT_EXITS
)
Meldung: In der Tabelle gibt es kein Schlüsselfeld '%s'
Fehler: 1073
SQLSTATE: 42000
(ER_BLOB_USED_AS_KEY
)
Meldung: BLOB-Feld '%s' kann beim verwendeten Tabellentyp nicht als Schlüssel verwendet werden
Fehler: 1074
SQLSTATE: 42000
(ER_TOO_BIG_FIELDLENGTH
)
Meldung: Feldlänge für Feld '%s' zu groß (maximal %d). BLOB- oder TEXT-Spaltentyp verwenden!
Fehler: 1075
SQLSTATE: 42000
(ER_WRONG_AUTO_KEY
)
Meldung: Falsche Tabellendefinition. Es darf nur eine AUTO_INCREMENT-Spalte geben, und diese muss als Schlüssel definiert werden
Fehler: 1076
SQLSTATE: HY000
(ER_READY
)
Meldung: %s: Bereit für Verbindungen. Version: '%2' Socket: '%s' Port: %d
Fehler: 1077
SQLSTATE: HY000
(ER_NORMAL_SHUTDOWN
)
Meldung: %s: Normal heruntergefahren
Fehler: 1078
SQLSTATE: HY000
(ER_GOT_SIGNAL
)
Meldung: %s: Signal %d erhalten. Abbruch!
Fehler: 1079
SQLSTATE: HY000
(ER_SHUTDOWN_COMPLETE
)
Meldung: %s: Herunterfahren beendet
Fehler: 1080
SQLSTATE: 08S01
(ER_FORCING_CLOSE
)
Meldung: %s: Thread %ld zwangsweise beendet. Benutzer: '%s'
Fehler: 1081
SQLSTATE: 08S01
(ER_IPSOCK_ERROR
)
Meldung: Kann IP-Socket nicht erzeugen
Fehler: 1082
SQLSTATE: 42S12
(ER_NO_SUCH_INDEX
)
Meldung: Tabelle '%s' besitzt keinen wie den in CREATE INDEX verwendeten Index. Tabelle neu anlegen
Fehler: 1083
SQLSTATE: 42000
(ER_WRONG_FIELD_TERMINATORS
)
Meldung: Feldbegrenzer-Argument ist nicht in der erwarteten Form. Bitte im Handbuch nachlesen
Fehler: 1084
SQLSTATE: 42000
(ER_BLOBS_AND_NO_TERMINATED
)
Meldung: Eine feste Zeilenlänge kann für BLOB-Felder nicht verwendet werden. Bitte 'fields terminated by' verwenden
Fehler: 1085
SQLSTATE: HY000
(ER_TEXTFILE_NOT_READABLE
)
Meldung: Datei '%s' muss im Datenbank-Verzeichnis vorhanden oder lesbar für alle sein
Fehler: 1086
SQLSTATE: HY000
(ER_FILE_EXISTS_ERROR
)
Meldung: Datei '%s' bereits vorhanden
Fehler: 1087
SQLSTATE: HY000
(ER_LOAD_INFO
)
Meldung: Datensätze: %ld Gelöscht: %ld Ausgelassen: %ld Warnungen: %ld
Fehler: 1088
SQLSTATE: HY000
(ER_ALTER_INFO
)
Meldung: Datensätze: %ld Duplikate: %ld
Fehler: 1089
SQLSTATE: HY000
(ER_WRONG_SUB_KEY
)
Meldung: Falscher Unterteilschlüssel. Der verwendete Schlüsselteil ist entweder kein String, die verwendete Länge ist länger als der Teilschlüssel oder die Speicher-Engine unterstützt keine Unterteilschlüssel
Fehler: 1090
SQLSTATE: 42000
(ER_CANT_REMOVE_ALL_FIELDS
)
Meldung: Mit ALTER TABLE können nicht alle Felder auf einmal gelöscht werden. Dafür DROP TABLE verwenden
Fehler: 1091
SQLSTATE: 42000
(ER_CANT_DROP_FIELD_OR_KEY
)
Meldung: Kann '%s' nicht löschen. Existiert die Spalte oder der Schlüssel?
Fehler: 1092
SQLSTATE: HY000
(ER_INSERT_INFO
)
Meldung: Datensätze: %ld Duplikate: %ld Warnungen: %ld
Fehler: 1093
SQLSTATE: HY000
(ER_UPDATE_TABLE_USED
)
Meldung: Die Verwendung der zu aktualisierenden Zieltabelle '%s' ist in der FROM-Klausel nicht zulässig.
Fehler: 1094
SQLSTATE: HY000
(ER_NO_SUCH_THREAD
)
Meldung: Unbekannte Thread-ID: %lu
Fehler: 1095
SQLSTATE: HY000
(ER_KILL_DENIED_ERROR
)
Meldung: Sie sind nicht Eigentümer von Thread %lu
Fehler: 1096
SQLSTATE: HY000
(ER_NO_TABLES_USED
)
Meldung: Keine Tabellen verwendet
Fehler: 1097
SQLSTATE: HY000
(ER_TOO_BIG_SET
)
Meldung: Zu viele Strings für Feld %s und SET angegeben
Fehler: 1098
SQLSTATE: HY000
(ER_NO_UNIQUE_LOGFILE
)
Meldung: Kann keinen eindeutigen Dateinamen für die Logdatei %s(1-999) erzeugen
Fehler: 1099
SQLSTATE: HY000
(ER_TABLE_NOT_LOCKED_FOR_WRITE
)
Meldung: Tabelle '%s' ist mit Lesesperre versehen und kann nicht aktualisiert werden
Fehler: 1100
SQLSTATE: HY000
(ER_TABLE_NOT_LOCKED
)
Meldung: Tabelle '%s' wurde nicht mit LOCK TABLES gesperrt
Fehler: 1101
SQLSTATE: 42000
(ER_BLOB_CANT_HAVE_DEFAULT
)
Meldung: BLOB/TEXT-Feld '%s' darf keinen Vorgabewert (DEFAULT) haben
Fehler: 1102
SQLSTATE: 42000
(ER_WRONG_DB_NAME
)
Meldung: Unerlaubter Datenbankname '%s'
Fehler: 1103
SQLSTATE: 42000
(ER_WRONG_TABLE_NAME
)
Meldung: Unerlaubter Tabellenname '%s'
Fehler: 1104
SQLSTATE: 42000
(ER_TOO_BIG_SELECT
)
Meldung: Die Ausführung des SELECT würde zu viele Datensätze untersuchen und wahrscheinlich sehr lange dauern. Bitte WHERE-Klausel überprüfen und gegebenenfalls SET SQL_BIG_SELECTS=1 oder SET SQL_MAX_JOIN_SIZE=# verwenden
Fehler: 1105
SQLSTATE: HY000
(ER_UNKNOWN_ERROR
)
Meldung: Unbekannter Fehler
Fehler: 1106
SQLSTATE: 42000
(ER_UNKNOWN_PROCEDURE
)
Meldung: Unbekannte Prozedur '%s'
Fehler: 1107
SQLSTATE: 42000
(ER_WRONG_PARAMCOUNT_TO_PROCEDURE
)
Meldung: Falsche Parameterzahl für Prozedur '%s'
Fehler: 1108
SQLSTATE: HY000
(ER_WRONG_PARAMETERS_TO_PROCEDURE
)
Meldung: Falsche Parameter für Prozedur '%s'
Fehler: 1109
SQLSTATE: 42S02
(ER_UNKNOWN_TABLE
)
Meldung: Unbekannte Tabelle '%s' in '%s'
Fehler: 1110
SQLSTATE: 42000
(ER_FIELD_SPECIFIED_TWICE
)
Meldung: Feld '%s' wurde zweimal angegeben
Fehler: 1111
SQLSTATE: HY000
(ER_INVALID_GROUP_FUNC_USE
)
Meldung: Falsche Verwendung einer Gruppierungsfunktion
Fehler: 1112
SQLSTATE: 42000
(ER_UNSUPPORTED_EXTENSION
)
Meldung: Tabelle '%s' verwendet eine Erweiterung, die in dieser MySQL-Version nicht verfügbar ist
Fehler: 1113
SQLSTATE: 42000
(ER_TABLE_MUST_HAVE_COLUMNS
)
Meldung: Eine Tabelle muss mindestens eine Spalte besitzen
Fehler: 1114
SQLSTATE: HY000
(ER_RECORD_FILE_FULL
)
Meldung: Tabelle '%s' ist voll
Fehler: 1115
SQLSTATE: 42000
(ER_UNKNOWN_CHARACTER_SET
)
Meldung: Unbekannter Zeichensatz: '%s'
Fehler: 1116
SQLSTATE: HY000
(ER_TOO_MANY_TABLES
)
Meldung: Zu viele Tabellen. MySQL kann in einem Join maximal %d Tabellen verwenden
Fehler: 1117
SQLSTATE: HY000
(ER_TOO_MANY_FIELDS
)
Meldung: Zu viele Felder
Fehler: 1118
SQLSTATE: 42000
(ER_TOO_BIG_ROWSIZE
)
Meldung: Zeilenlänge zu groß. Die maximale Zeilenlänge für den verwendeten Tabellentyp (ohne BLOB-Felder) beträgt %ld. Einige Felder müssen in BLOB oder TEXT umgewandelt werden
Fehler: 1119
SQLSTATE: HY000
(ER_STACK_OVERRUN
)
Meldung: Thread-Stack-Überlauf. Benutzt: %ld von %ld Stack. 'mysqld -O thread_stack=#' verwenden, um bei Bedarf einen größeren Stack anzulegen
Fehler: 1120
SQLSTATE: 42000
(ER_WRONG_OUTER_JOIN
)
Meldung: OUTER JOIN enthält fehlerhafte Abhängigkeiten. In ON verwendete Bedingungen überprüfen
Fehler: 1121
SQLSTATE: 42000
(ER_NULL_COLUMN_IN_INDEX
)
Meldung: Table handler doesn't support NULL in given index. Please change column '%s' to be NOT NULL or use another handler
Fehler: 1122
SQLSTATE: HY000
(ER_CANT_FIND_UDF
)
Meldung: Kann Funktion '%s' nicht laden
Fehler: 1123
SQLSTATE: HY000
(ER_CANT_INITIALIZE_UDF
)
Meldung: Kann Funktion '%s' nicht initialisieren: %s
Fehler: 1124
SQLSTATE: HY000
(ER_UDF_NO_PATHS
)
Meldung: Keine Pfade gestattet für Shared Library
Fehler: 1125
SQLSTATE: HY000
(ER_UDF_EXISTS
)
Meldung: Funktion '%s' existiert schon
Fehler: 1126
SQLSTATE: HY000
(ER_CANT_OPEN_LIBRARY
)
Meldung: Kann Shared Library '%s' nicht öffnen (Fehler: %d %s)
Fehler: 1127
SQLSTATE: HY000
(ER_CANT_FIND_DL_ENTRY
)
Meldung: Kann Funktion '%s' in der Library nicht finden
Fehler: 1128
SQLSTATE: HY000
(ER_FUNCTION_NOT_DEFINED
)
Meldung: Funktion '%s' ist nicht definiert
Fehler: 1129
SQLSTATE: HY000
(ER_HOST_IS_BLOCKED
)
Meldung: Host '%s' blockiert wegen zu vieler Verbindungsfehler. Aufheben der Blockierung mit 'mysqladmin flush-hosts'
Fehler: 1130
SQLSTATE: HY000
(ER_HOST_NOT_PRIVILEGED
)
Meldung: Host '%s' hat keine Berechtigung, sich mit diesem MySQL-Server zu verbinden
Fehler: 1131
SQLSTATE: 42000
(ER_PASSWORD_ANONYMOUS_USER
)
Meldung: Sie benutzen MySQL als anonymer Benutzer und dürfen daher keine Passwörter ändern
Fehler: 1132
SQLSTATE: 42000
(ER_PASSWORD_NOT_ALLOWED
)
Meldung: Sie benötigen die Berechtigung zum Aktualisieren von Tabellen in der Datenbank 'mysql', um die Passwörter anderer Benutzer ändern zu können
Fehler: 1133
SQLSTATE: 42000
(ER_PASSWORD_NO_MATCH
)
Meldung: Kann keinen passenden Datensatz in Tabelle 'user' finden
Fehler: 1134
SQLSTATE: HY000
(ER_UPDATE_INFO
)
Meldung: Datensätze gefunden: %ld Geändert: %ld Warnungen: %ld
Fehler: 1135
SQLSTATE: HY000
(ER_CANT_CREATE_THREAD
)
Meldung: Kann keinen neuen Thread erzeugen (Fehler: %d). Sollte noch Speicher verfügbar sein, bitte im Handbuch wegen möglicher Fehler im Betriebssystem nachschlagen
Fehler: 1136
SQLSTATE: 21S01
(ER_WRONG_VALUE_COUNT_ON_ROW
)
Meldung: Anzahl der Felder stimmt nicht mit der Anzahl der Werte in Zeile %ld überein
Fehler: 1137
SQLSTATE: HY000
(ER_CANT_REOPEN_TABLE
)
Meldung: Kann Tabelle'%s' nicht erneut öffnen
Fehler: 1138
SQLSTATE: 22004
(ER_INVALID_USE_OF_NULL
)
Meldung: Unerlaubte Verwendung eines NULL-Werts
Fehler: 1139
SQLSTATE: 42000
(ER_REGEXP_ERROR
)
Meldung: regexp lieferte Fehler '%s'
Fehler: 1140
SQLSTATE: 42000
(ER_MIX_OF_GROUP_FUNC_AND_FIELDS
)
Meldung: Das Vermischen von GROUP-Feldern (MIN(),MAX(),COUNT()...) mit Nicht-GROUP-Feldern ist nicht zulässig, wenn keine GROUP-BY-Klausel vorhanden ist
Fehler: 1141
SQLSTATE: 42000
(ER_NONEXISTING_GRANT
)
Meldung: Für Benutzer '%s' auf Host '%s' gibt es keine solche Berechtigung
Fehler: 1142
SQLSTATE: 42000
(ER_TABLEACCESS_DENIED_ERROR
)
Meldung: %s Befehl nicht erlaubt für Benutzer '%s'@'%s' auf Tabelle '%s'
Fehler: 1143
SQLSTATE: 42000
(ER_COLUMNACCESS_DENIED_ERROR
)
Meldung: %s Befehl nicht erlaubt für Benutzer '%s'@'%s' und Feld '%s' in Tabelle '%s'
Fehler: 1144
SQLSTATE: 42000
(ER_ILLEGAL_GRANT_FOR_TABLE
)
Meldung: Unzulässiger GRANT- oder REVOKE-Befehl. Verfügbare Berechtigungen sind im Handbuch aufgeführt
Fehler: 1145
SQLSTATE: 42000
(ER_GRANT_WRONG_HOST_OR_USER
)
Meldung: Das Host- oder User-Argument für GRANT ist zu lang
Fehler: 1146
SQLSTATE: 42S02
(ER_NO_SUCH_TABLE
)
Meldung: Tabelle '%s.%s' existiert nicht
Fehler: 1147
SQLSTATE: 42000
(ER_NONEXISTING_TABLE_GRANT
)
Meldung: Eine solche Berechtigung ist für User '%s' auf Host '%s' an Tabelle '%s' nicht definiert
Fehler: 1148
SQLSTATE: 42000
(ER_NOT_ALLOWED_COMMAND
)
Meldung: Der verwendete Befehl ist in dieser MySQL-Version nicht zulässig
Fehler: 1149
SQLSTATE: 42000
(ER_SYNTAX_ERROR
)
Meldung: Fehler in der SQL-Syntax. Bitte die korrekte Syntax im Handbuch nachschlagen
Fehler: 1150
SQLSTATE: HY000
(ER_DELAYED_CANT_CHANGE_LOCK
)
Meldung: Verzögerter (DELAYED) Einfüge-Thread konnte die angeforderte Sperre für Tabelle '%s' nicht erhalten
Fehler: 1151
SQLSTATE: HY000
(ER_TOO_MANY_DELAYED_THREADS
)
Meldung: Zu viele verzögerte (DELAYED) Threads in Verwendung
Fehler: 1152
SQLSTATE: 08S01
(ER_ABORTING_CONNECTION
)
Meldung: Abbruch der Verbindung %ld zur Datenbank '%s'. Benutzer: '%s' (%s)
Fehler: 1153
SQLSTATE: 08S01
(ER_NET_PACKET_TOO_LARGE
)
Meldung: Empfangenes Paket ist größer als 'max_allowed_packet' Bytes
Fehler: 1154
SQLSTATE: 08S01
(ER_NET_READ_ERROR_FROM_PIPE
)
Meldung: Lese-Fehler bei einer Verbindungs-Pipe
Fehler: 1155
SQLSTATE: 08S01
(ER_NET_FCNTL_ERROR
)
Meldung: fcntl() lieferte einen Fehler
Fehler: 1156
SQLSTATE: 08S01
(ER_NET_PACKETS_OUT_OF_ORDER
)
Meldung: Pakete nicht in der richtigen Reihenfolge empfangen
Fehler: 1157
SQLSTATE: 08S01
(ER_NET_UNCOMPRESS_ERROR
)
Meldung: Kommunikationspaket lässt sich nicht entpacken
Fehler: 1158
SQLSTATE: 08S01
(ER_NET_READ_ERROR
)
Meldung: Fehler beim Lesen eines Kommunikationspakets
Fehler: 1159
SQLSTATE: 08S01
(ER_NET_READ_INTERRUPTED
)
Meldung: Zeitüberschreitung beim Lesen eines Kommunikationspakets
Fehler: 1160
SQLSTATE: 08S01
(ER_NET_ERROR_ON_WRITE
)
Meldung: Fehler beim Schreiben eines Kommunikationspakets
Fehler: 1161
SQLSTATE: 08S01
(ER_NET_WRITE_INTERRUPTED
)
Meldung: Zeitüberschreitung beim Schreiben eines Kommunikationspakets
Fehler: 1162
SQLSTATE: 42000
(ER_TOO_LONG_STRING
)
Meldung: Ergebnis-String ist länger als 'max_allowed_packet' Bytes
Fehler: 1163
SQLSTATE: 42000
(ER_TABLE_CANT_HANDLE_BLOB
)
Meldung: Der verwendete Tabellentyp unterstützt keine BLOB- und TEXT-Felder
Fehler: 1164
SQLSTATE: 42000
(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT
)
Meldung: Der verwendete Tabellentyp unterstützt keine AUTO_INCREMENT-Felder
Fehler: 1165
SQLSTATE: HY000
(ER_DELAYED_INSERT_TABLE_LOCKED
)
Meldung: INSERT DELAYED kann für Tabelle '%s' nicht verwendet werden, da sie mit LOCK TABLES gesperrt ist
Fehler: 1166
SQLSTATE: 42000
(ER_WRONG_COLUMN_NAME
)
Meldung: Falscher Spaltenname '%s'
Fehler: 1167
SQLSTATE: 42000
(ER_WRONG_KEY_COLUMN
)
Meldung: Die verwendete Speicher-Engine kann die Spalte '%s' nicht indizieren
Fehler: 1168
SQLSTATE: HY000
(ER_WRONG_MRG_TABLE
)
Meldung: Nicht alle Tabellen in der MERGE-Tabelle sind gleich definiert
Fehler: 1169
SQLSTATE: 23000
(ER_DUP_UNIQUE
)
Meldung: Schreiben in Tabelle '%s' nicht möglich wegen einer Eindeutigkeitsbeschränkung (unique constraint)
Fehler: 1170
SQLSTATE: 42000
(ER_BLOB_KEY_WITHOUT_LENGTH
)
Meldung: BLOB- oder TEXT-Spalte '%s' wird in der Schlüsseldefinition ohne Schlüssellängenangabe verwendet
Fehler: 1171
SQLSTATE: 42000
(ER_PRIMARY_CANT_HAVE_NULL
)
Meldung: Alle Teile eines PRIMARY KEY müssen als NOT NULL definiert sein. Wenn NULL in einem Schlüssel benötigt wird, muss ein UNIQUE-Schlüssel verwendet werden
Fehler: 1172
SQLSTATE: 42000
(ER_TOO_MANY_ROWS
)
Meldung: Ergebnis besteht aus mehr als einer Zeile
Fehler: 1173
SQLSTATE: 42000
(ER_REQUIRES_PRIMARY_KEY
)
Meldung: Dieser Tabellentyp benötigt einen Primärschlüssel (PRIMARY KEY)
Fehler: 1174
SQLSTATE: HY000
(ER_NO_RAID_COMPILED
)
Meldung: Diese MySQL-Version ist nicht mit RAID-Unterstützung kompiliert
Fehler: 1175
SQLSTATE: HY000
(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE
)
Meldung: MySQL läuft im sicheren Aktualisierungsmodus (safe update mode). Sie haben versucht, eine Tabelle zu aktualisieren, ohne in der WHERE-Klausel ein KEY-Feld anzugeben
Fehler: 1176
SQLSTATE: 42000
(ER_KEY_DOES_NOT_EXITS
)
Meldung: Schlüssel '%s' existiert in der Tabelle '%s' nicht
Fehler: 1177
SQLSTATE: 42000
(ER_CHECK_NO_SUCH_TABLE
)
Meldung: Kann Tabelle nicht öffnen
Fehler: 1178
SQLSTATE: 42000
(ER_CHECK_NOT_IMPLEMENTED
)
Meldung: Die Speicher-Engine für diese Tabelle unterstützt kein %s
Fehler: 1179
SQLSTATE: 25000
(ER_CANT_DO_THIS_DURING_AN_TRANSACTION
)
Meldung: Sie dürfen diesen Befehl nicht in einer Transaktion ausführen
Fehler: 1180
SQLSTATE: HY000
(ER_ERROR_DURING_COMMIT
)
Meldung: Fehler %d beim COMMIT
Fehler: 1181
SQLSTATE: HY000
(ER_ERROR_DURING_ROLLBACK
)
Meldung: Fehler %d beim ROLLBACK
Fehler: 1182
SQLSTATE: HY000
(ER_ERROR_DURING_FLUSH_LOGS
)
Meldung: Fehler %d bei FLUSH_LOGS
Fehler: 1183
SQLSTATE: HY000
(ER_ERROR_DURING_CHECKPOINT
)
Meldung: Fehler %d bei CHECKPOINT
Fehler: 1184
SQLSTATE: 08S01
(ER_NEW_ABORTING_CONNECTION
)
Meldung: Abbruch der Verbindung %ld zur Datenbank '%s'. Benutzer: '%s', Host: '%s' (%s)
Fehler: 1185
SQLSTATE: HY000
(ER_DUMP_NOT_IMPLEMENTED
)
Meldung: Die Speicher-Engine für die Tabelle unterstützt keinen binären Tabellen-Dump
Fehler: 1186
SQLSTATE: HY000
(ER_FLUSH_MASTER_BINLOG_CLOSED
)
Meldung: Binlog geschlossen. Kann RESET MASTER nicht ausführen
Fehler: 1187
SQLSTATE: HY000
(ER_INDEX_REBUILD
)
Meldung: Neuerstellung des Index der Dump-Tabelle '%s' fehlgeschlagen
Fehler: 1188
SQLSTATE: HY000
(ER_MASTER
)
Meldung: Fehler vom Master: '%s'
Fehler: 1189
SQLSTATE: 08S01
(ER_MASTER_NET_READ
)
Meldung: Netzfehler beim Lesen vom Master
Fehler: 1190
SQLSTATE: 08S01
(ER_MASTER_NET_WRITE
)
Meldung: Netzfehler beim Schreiben zum Master
Fehler: 1191
SQLSTATE: HY000
(ER_FT_MATCHING_KEY_NOT_FOUND
)
Meldung: Kann keinen FULLTEXT-Index finden, der der Feldliste entspricht
Fehler: 1192
SQLSTATE: HY000
(ER_LOCK_OR_ACTIVE_TRANSACTION
)
Meldung: Kann den angegebenen Befehl wegen einer aktiven Tabellensperre oder einer aktiven Transaktion nicht ausführen
Fehler: 1193
SQLSTATE: HY000
(ER_UNKNOWN_SYSTEM_VARIABLE
)
Meldung: Unbekannte Systemvariable '%s'
Fehler: 1194
SQLSTATE: HY000
(ER_CRASHED_ON_USAGE
)
Meldung: Tabelle '%s' ist als defekt markiert und sollte repariert werden
Fehler: 1195
SQLSTATE: HY000
(ER_CRASHED_ON_REPAIR
)
Meldung: Tabelle '%s' ist als defekt markiert und der letzte (automatische?) Reparaturversuch schlug fehl
Fehler: 1196
SQLSTATE: HY000
(ER_WARNING_NOT_COMPLETE_ROLLBACK
)
Meldung: Änderungen an einigen nicht transaktionalen Tabellen konnten nicht zurückgerollt werden
Fehler: 1197
SQLSTATE: HY000
(ER_TRANS_CACHE_FULL
)
Meldung: Transaktionen, die aus mehreren Befehlen bestehen, benötigten mehr als 'max_binlog_cache_size' Bytes an Speicher. Btte vergrössern Sie diese Server-Variable versuchen Sie es noch einmal
Fehler: 1198
SQLSTATE: HY000
(ER_SLAVE_MUST_STOP
)
Meldung: Diese Operation kann bei einem aktiven Slave nicht durchgeführt werden. Bitte zuerst STOP SLAVE ausführen
Fehler: 1199
SQLSTATE: HY000
(ER_SLAVE_NOT_RUNNING
)
Meldung: Diese Operation benötigt einen aktiven Slave. Bitte Slave konfigurieren und mittels START SLAVE aktivieren
Fehler: 1200
SQLSTATE: HY000
(ER_BAD_SLAVE
)
Meldung: Der Server ist nicht als Slave konfiguriert. Bitte in der Konfigurationsdatei oder mittels CHANGE MASTER TO beheben
Fehler: 1201
SQLSTATE: HY000
(ER_MASTER_INFO
)
Meldung: Konnte Master-Info-Struktur nicht initialisieren. Weitere Fehlermeldungen können im MySQL-Error-Log eingesehen werden
Fehler: 1202
SQLSTATE: HY000
(ER_SLAVE_THREAD
)
Meldung: Konnte Slave-Thread nicht starten. Bitte System-Ressourcen überprüfen
Fehler: 1203
SQLSTATE: 42000
(ER_TOO_MANY_USER_CONNECTIONS
)
Meldung: Benutzer '%s' hat mehr als 'max_user_connections' aktive Verbindungen
Fehler: 1204
SQLSTATE: HY000
(ER_SET_CONSTANTS_ONLY
)
Meldung: Bei SET dürfen nur konstante Ausdrücke verwendet werden
Fehler: 1205
SQLSTATE: HY000
(ER_LOCK_WAIT_TIMEOUT
)
Meldung: Beim Warten auf eine Sperre wurde die zulässige Wartezeit überschritten. Bitte versuchen Sie, die Transaktion neu zu starten
Fehler: 1206
SQLSTATE: HY000
(ER_LOCK_TABLE_FULL
)
Meldung: Die Gesamtzahl der Sperren überschreitet die Größe der Sperrtabelle
Fehler: 1207
SQLSTATE: 25000
(ER_READ_ONLY_TRANSACTION
)
Meldung: Während einer READ-UNCOMMITTED-Transaktion können keine UPDATE-Sperren angefordert werden
Fehler: 1208
SQLSTATE: HY000
(ER_DROP_DB_WITH_READ_LOCK
)
Meldung: DROP DATABASE ist nicht erlaubt, solange der Thread eine globale Lesesperre hält
Fehler: 1209
SQLSTATE: HY000
(ER_CREATE_DB_WITH_READ_LOCK
)
Meldung: CREATE DATABASE ist nicht erlaubt, solange der Thread eine globale Lesesperre hält
Fehler: 1210
SQLSTATE: HY000
(ER_WRONG_ARGUMENTS
)
Meldung: Falsche Argumente für %s
Fehler: 1211
SQLSTATE: 42000
(ER_NO_PERMISSION_TO_CREATE_USER
)
Meldung: '%s'@'%s' ist nicht berechtigt, neue Benutzer hinzuzufügen
Fehler: 1212
SQLSTATE: HY000
(ER_UNION_TABLES_IN_DIFFERENT_DIR
)
Meldung: Falsche Tabellendefinition. Alle MERGE-Tabellen müssen sich in derselben Datenbank befinden
Fehler: 1213
SQLSTATE: 40001
(ER_LOCK_DEADLOCK
)
Meldung: Beim Versuch, eine Sperre anzufordern, ist ein Deadlock aufgetreten. Versuchen Sie, die Transaktion neu zu starten
Fehler: 1214
SQLSTATE: HY000
(ER_TABLE_CANT_HANDLE_FT
)
Meldung: Der verwendete Tabellentyp unterstützt keine FULLTEXT-Indizes
Fehler: 1215
SQLSTATE: HY000
(ER_CANNOT_ADD_FOREIGN
)
Meldung: Fremdschlüssel-Beschränkung kann nicht hinzugefügt werden
Fehler: 1216
SQLSTATE: 23000
(ER_NO_REFERENCED_ROW
)
Meldung: Hinzufügen oder Aktualisieren eines Kind-Datensatzes schlug aufgrund einer Fremdschlüssel-Beschränkung fehl
Fehler: 1217
SQLSTATE: 23000
(ER_ROW_IS_REFERENCED
)
Meldung: Löschen oder Aktualisieren eines Eltern-Datensatzes schlug aufgrund einer Fremdschlüssel-Beschränkung fehl
Fehler: 1218
SQLSTATE: 08S01
(ER_CONNECT_TO_MASTER
)
Meldung: Fehler bei der Verbindung zum Master: %s
Fehler: 1219
SQLSTATE: HY000
(ER_QUERY_ON_MASTER
)
Meldung: Beim Ausführen einer Abfrage auf dem Master trat ein Fehler auf: %s
Fehler: 1220
SQLSTATE: HY000
(ER_ERROR_WHEN_EXECUTING_COMMAND
)
Meldung: Fehler beim Ausführen des Befehls %s: %s
Fehler: 1221
SQLSTATE: HY000
(ER_WRONG_USAGE
)
Meldung: Falsche Verwendung von %s und %s
Fehler: 1222
SQLSTATE: 21000
(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT
)
Meldung: Die verwendeten SELECT-Befehle liefern unterschiedliche Anzahlen von Feldern zurück
Fehler: 1223
SQLSTATE: HY000
(ER_CANT_UPDATE_WITH_READLOCK
)
Meldung: Augrund eines READ-LOCK-Konflikts kann die Abfrage nicht ausgeführt werden
Fehler: 1224
SQLSTATE: HY000
(ER_MIXING_NOT_ALLOWED
)
Meldung: Die gleichzeitige Verwendung von Tabellen mit und ohne Transaktionsunterstützung ist deaktiviert
Fehler: 1225
SQLSTATE: HY000
(ER_DUP_ARGUMENT
)
Meldung: Option '%s' wird im Befehl zweimal verwendet
Fehler: 1226
SQLSTATE: 42000
(ER_USER_LIMIT_REACHED
)
Meldung: Benutzer '%s' hat die Ressourcenbeschränkung '%s' überschritten (aktueller Wert: %ld)
Fehler: 1227
SQLSTATE: 42000
(ER_SPECIFIC_ACCESS_DENIED_ERROR
)
Meldung: Kein Zugriff. Hierfür wird die Berechtigung %s benötigt
Fehler: 1228
SQLSTATE: HY000
(ER_LOCAL_VARIABLE
)
Meldung: Variable '%s' ist eine lokale Variable und kann nicht mit SET GLOBAL verändert werden
Fehler: 1229
SQLSTATE: HY000
(ER_GLOBAL_VARIABLE
)
Meldung: Variable '%s' ist eine globale Variable und muss mit SET GLOBAL verändert werden
Fehler: 1230
SQLSTATE: 42000
(ER_NO_DEFAULT
)
Meldung: Variable '%s' hat keinen Vorgabewert
Fehler: 1231
SQLSTATE: 42000
(ER_WRONG_VALUE_FOR_VAR
)
Meldung: Variable '%s' kann nicht auf '%s' gesetzt werden
Fehler: 1232
SQLSTATE: 42000
(ER_WRONG_TYPE_FOR_VAR
)
Meldung: Falscher Argumenttyp für Variable '%s'
Fehler: 1233
SQLSTATE: HY000
(ER_VAR_CANT_BE_READ
)
Meldung: Variable '%s' kann nur verändert, nicht gelesen werden
Fehler: 1234
SQLSTATE: 42000
(ER_CANT_USE_OPTION_HERE
)
Meldung: Falsche Verwendung oder Platzierung von '%s'
Fehler: 1235
SQLSTATE: 42000
(ER_NOT_SUPPORTED_YET
)
Meldung: Diese MySQL-Version unterstützt '%s' nicht
Fehler: 1236
SQLSTATE: HY000
(ER_MASTER_FATAL_ERROR_READING_BINLOG
)
Meldung: Schwerer Fehler %d: '%s vom Master beim Lesen des binären Logs
Fehler: 1237
SQLSTATE: HY000
(ER_SLAVE_IGNORED_TABLE
)
Meldung: Slave-SQL-Thread hat die Abfrage aufgrund von replicate-*-table-Regeln ignoriert
Fehler: 1238
SQLSTATE: HY000
(ER_INCORRECT_GLOBAL_LOCAL_VAR
)
Meldung: Variable '%s' ist eine %s-Variable
Fehler: 1239
SQLSTATE: 42000
(ER_WRONG_FK_DEF
)
Meldung: Falsche Fremdschlüssel-Definition für '%s': %s
Fehler: 1240
SQLSTATE: HY000
(ER_KEY_REF_DO_NOT_MATCH_TABLE_REF
)
Meldung: Schlüssel- und Tabellenverweis passen nicht zusammen
Fehler: 1241
SQLSTATE: 21000
(ER_OPERAND_COLUMNS
)
Meldung: Operand sollte %d Spalte(n) enthalten
Fehler: 1242
SQLSTATE: 21000
(ER_SUBQUERY_NO_1_ROW
)
Meldung: Unterabfrage lieferte mehr als einen Datensatz zurück
Fehler: 1243
SQLSTATE: HY000
(ER_UNKNOWN_STMT_HANDLER
)
Meldung: Unbekannter Prepared-Statement-Handler (%.*s) für %s angegeben
Fehler: 1244
SQLSTATE: HY000
(ER_CORRUPT_HELP_DB
)
Meldung: Die Hilfe-Datenbank ist beschädigt oder existiert nicht
Fehler: 1245
SQLSTATE: HY000
(ER_CYCLIC_REFERENCE
)
Meldung: Zyklischer Verweis in Unterabfragen
Fehler: 1246
SQLSTATE: HY000
(ER_AUTO_CONVERT
)
Meldung: Feld '%s' wird von %s nach %s umgewandelt
Fehler: 1247
SQLSTATE: 42S22
(ER_ILLEGAL_REFERENCE
)
Meldung: Verweis '%s' wird nicht unterstützt (%s)
Fehler: 1248
SQLSTATE: 42000
(ER_DERIVED_MUST_HAVE_ALIAS
)
Meldung: Für jede abgeleitete Tabelle muss ein eigener Alias angegeben werden
Fehler: 1249
SQLSTATE: 01000
(ER_SELECT_REDUCED
)
Meldung: Select %u wurde während der Optimierung reduziert
Fehler: 1250
SQLSTATE: 42000
(ER_TABLENAME_NOT_ALLOWED_HERE
)
Meldung: Tabelle '%s', die in einem der SELECT-Befehle verwendet wurde, kann nicht in %s verwendet werden
Fehler: 1251
SQLSTATE: 08004
(ER_NOT_SUPPORTED_AUTH_MODE
)
Meldung: Client unterstützt das vom Server erwartete Authentifizierungsprotokoll nicht. Bitte aktualisieren Sie Ihren MySQL-Client
Fehler: 1252
SQLSTATE: 42000
(ER_SPATIAL_CANT_HAVE_NULL
)
Meldung: Alle Teile eines SPATIAL-Index müssen als NOT NULL deklariert sein
Fehler: 1253
SQLSTATE: 42000
(ER_COLLATION_CHARSET_MISMATCH
)
Meldung: COLLATION '%s' ist für CHARACTER SET '%s' ungültig
Fehler: 1254
SQLSTATE: HY000
(ER_SLAVE_WAS_RUNNING
)
Meldung: Slave läuft bereits
Fehler: 1255
SQLSTATE: HY000
(ER_SLAVE_WAS_NOT_RUNNING
)
Meldung: Slave wurde bereits angehalten
Fehler: 1256
SQLSTATE: HY000
(ER_TOO_BIG_FOR_UNCOMPRESS
)
Meldung: Unkomprimierte Daten sind zu groß. Die maximale Größe beträgt %d (wahrscheinlich wurde die Länge der unkomprimierten Daten beschädigt)
Fehler: 1257
SQLSTATE: HY000
(ER_ZLIB_Z_MEM_ERROR
)
Meldung: ZLIB: Nicht genug Speicher
Fehler: 1258
SQLSTATE: HY000
(ER_ZLIB_Z_BUF_ERROR
)
Meldung: ZLIB: Im Ausgabepuffer ist nicht genug Platz vorhanden (wahrscheinlich wurde die Länge der unkomprimierten Daten beschädigt)
Fehler: 1259
SQLSTATE: HY000
(ER_ZLIB_Z_DATA_ERROR
)
Meldung: ZLIB: Eingabedaten beschädigt
Fehler: 1260
SQLSTATE: HY000
(ER_CUT_VALUE_GROUP_CONCAT
)
Meldung: %d Zeile(n) durch GROUP_CONCAT() abgeschnitten
Fehler: 1261
SQLSTATE: 01000
(ER_WARN_TOO_FEW_RECORDS
)
Meldung: Zeile %ld enthält nicht für alle Felder Daten
Fehler: 1262
SQLSTATE: 01000
(ER_WARN_TOO_MANY_RECORDS
)
Meldung: Zeile %ld gekürzt, die Zeile enthielt mehr Daten, als es Eingabefelder gibt
Fehler: 1263
SQLSTATE: 22004
(ER_WARN_NULL_TO_NOTNULL
)
Meldung: Feld auf Vorgabewert gesetzt, da NULL für NOT-NULL-Feld '%s' in Zeile %ld angegeben
Fehler: 1264
SQLSTATE: 22003
(ER_WARN_DATA_OUT_OF_RANGE
)
Meldung: Out of range value for column '%s' at row %ld
Fehler: 1265
SQLSTATE: 01000
(WARN_DATA_TRUNCATED
)
Meldung: Daten abgeschnitten für Feld '%s' in Zeile %ld
Fehler: 1266
SQLSTATE: HY000
(ER_WARN_USING_OTHER_HANDLER
)
Meldung: Für Tabelle '%s' wird Speicher-Engine %s benutzt
Fehler: 1267
SQLSTATE: HY000
(ER_CANT_AGGREGATE_2COLLATIONS
)
Meldung: Unerlaubte Mischung von Sortierreihenfolgen (%s, %s) und (%s, %s) für Operation '%s'
Fehler: 1268
SQLSTATE: HY000
(ER_DROP_USER
)
Meldung: Kann einen oder mehrere der angegebenen Benutzer nicht löschen
Fehler: 1269
SQLSTATE: HY000
(ER_REVOKE_GRANTS
)
Meldung: Kann nicht alle Berechtigungen widerrufen, die für einen oder mehrere Benutzer gewährt wurden
Fehler: 1270
SQLSTATE: HY000
(ER_CANT_AGGREGATE_3COLLATIONS
)
Meldung: Unerlaubte Mischung von Sortierreihenfolgen (%s, %s), (%s, %s), (%s, %s) für Operation '%s'
Fehler: 1271
SQLSTATE: HY000
(ER_CANT_AGGREGATE_NCOLLATIONS
)
Meldung: Unerlaubte Mischung von Sortierreihenfolgen für Operation '%s'
Fehler: 1272
SQLSTATE: HY000
(ER_VARIABLE_IS_NOT_STRUCT
)
Meldung: Variable '%s' ist keine Variablen-Komponente (kann nicht als XXXX.variablen_name verwendet werden)
Fehler: 1273
SQLSTATE: HY000
(ER_UNKNOWN_COLLATION
)
Meldung: Unbekannte Sortierreihenfolge: '%s'
Fehler: 1274
SQLSTATE: HY000
(ER_SLAVE_IGNORED_SSL_PARAMS
)
Meldung: SSL-Parameter in CHANGE MASTER werden ignoriert, weil dieser MySQL-Slave ohne SSL-Unterstützung kompiliert wurde. Sie können aber später verwendet werden, wenn ein MySQL-Slave mit SSL gestartet wird
Fehler: 1275
SQLSTATE: HY000
(ER_SERVER_IS_IN_SECURE_AUTH_MODE
)
Meldung: Server läuft im Modus --secure-auth, aber '%s'@'%s' hat ein Passwort im alten Format. Bitte Passwort ins neue Format ändern
Fehler: 1276
SQLSTATE: HY000
(ER_WARN_FIELD_RESOLVED
)
Meldung: Feld oder Verweis '%s%s%s%s%s' im SELECT-Befehl Nr. %d wurde im SELECT-Befehl Nr. %d aufgelöst
Fehler: 1277
SQLSTATE: HY000
(ER_BAD_SLAVE_UNTIL_COND
)
Meldung: Falscher Parameter oder falsche Kombination von Parametern für START SLAVE UNTIL
Fehler: 1278
SQLSTATE: HY000
(ER_MISSING_SKIP_SLAVE
)
Meldung: Es wird empfohlen, mit --skip-slave-start zu starten, wenn mit START SLAVE UNTIL eine Schritt-für-Schritt-Replikation ausgeführt wird. Ansonsten gibt es Probleme, wenn ein Slave-Server unerwartet neu startet
Fehler: 1279
SQLSTATE: HY000
(ER_UNTIL_COND_IGNORED
)
Meldung: SQL-Thread soll nicht gestartet werden. Daher werden UNTIL-Optionen ignoriert
Fehler: 1280
SQLSTATE: 42000
(ER_WRONG_NAME_FOR_INDEX
)
Meldung: Falscher Indexname '%s'
Fehler: 1281
SQLSTATE: 42000
(ER_WRONG_NAME_FOR_CATALOG
)
Meldung: Falscher Katalogname '%s'
Fehler: 1282
SQLSTATE: HY000
(ER_WARN_QC_RESIZE
)
Meldung: Änderung der Query-Cache-Größe auf %lu fehlgeschlagen; neue Query-Cache-Größe ist %lu
Fehler: 1283
SQLSTATE: HY000
(ER_BAD_FT_COLUMN
)
Meldung: Feld '%s' kann nicht Teil eines FULLTEXT-Index sein
Fehler: 1284
SQLSTATE: HY000
(ER_UNKNOWN_KEY_CACHE
)
Meldung: Unbekannter Schlüssel-Cache '%s'
Fehler: 1285
SQLSTATE: HY000
(ER_WARN_HOSTNAME_WONT_WORK
)
Meldung: MySQL wurde mit --skip-name-resolve gestartet. Diese Option darf nicht verwendet werden, damit diese Rechtevergabe möglich ist
Fehler: 1286
SQLSTATE: 42000
(ER_UNKNOWN_STORAGE_ENGINE
)
Meldung: Unbekannte Speicher-Engine '%s'
Fehler: 1287
SQLSTATE: HY000
(ER_UNUSED_1
)
Meldung: '%s' ist veraltet. Bitte benutzen Sie '%s'
Fehler: 1288
SQLSTATE: HY000
(ER_NON_UPDATABLE_TABLE
)
Meldung: Die Zieltabelle %s von %s ist nicht aktualisierbar
Fehler: 1289
SQLSTATE: HY000
(ER_FEATURE_DISABLED
)
Meldung: Das Feature '%s' ist ausgeschaltet, Sie müssen MySQL mit '%s' übersetzen, damit es verfügbar ist
Fehler: 1290
SQLSTATE: HY000
(ER_OPTION_PREVENTS_STATEMENT
)
Meldung: Der MySQL-Server läuft mit der Option %s und kann diese Anweisung deswegen nicht ausführen
Fehler: 1291
SQLSTATE: HY000
(ER_DUPLICATED_VALUE_IN_TYPE
)
Meldung: Feld '%s' hat doppelten Wert '%s' in %s
Fehler: 1292
SQLSTATE: 22007
(ER_TRUNCATED_WRONG_VALUE
)
Meldung: Falscher %s-Wert gekürzt: '%s'
Fehler: 1293
SQLSTATE: HY000
(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS
)
Meldung: Fehlerhafte Tabellendefinition. Es kann nur eine einzige TIMESTAMP-Spalte mit CURRENT_TIMESTAMP als DEFAULT oder in einer ON-UPDATE-Klausel geben
Fehler: 1294
SQLSTATE: HY000
(ER_INVALID_ON_UPDATE
)
Meldung: Ungültige ON-UPDATE-Klausel für Spalte '%s'
Fehler: 1295
SQLSTATE: HY000
(ER_UNSUPPORTED_PS
)
Meldung: Dieser Befehl wird im Protokoll für vorbereitete Anweisungen noch nicht unterstützt
Fehler: 1296
SQLSTATE: HY000
(ER_GET_ERRMSG
)
Meldung: Fehler %d '%s' von %s
Fehler: 1297
SQLSTATE: HY000
(ER_GET_TEMPORARY_ERRMSG
)
Meldung: Temporärer Fehler %d '%s' von %s
Fehler: 1298
SQLSTATE: HY000
(ER_UNKNOWN_TIME_ZONE
)
Meldung: Unbekannte oder falsche Zeitzone: '%s'
Fehler: 1299
SQLSTATE: HY000
(ER_WARN_INVALID_TIMESTAMP
)
Meldung: Ungültiger TIMESTAMP-Wert in Feld '%s', Zeile %ld
Fehler: 1300
SQLSTATE: HY000
(ER_INVALID_CHARACTER_STRING
)
Meldung: Ungültiger %s-Zeichen-String: '%s'
Fehler: 1301
SQLSTATE: HY000
(ER_WARN_ALLOWED_PACKET_OVERFLOWED
)
Meldung: Ergebnis von %s() war größer als max_allowed_packet (%ld) Bytes und wurde deshalb gekürzt
Fehler: 1302
SQLSTATE: HY000
(ER_CONFLICTING_DECLARATIONS
)
Meldung: Widersprüchliche Deklarationen: '%s%s' und '%s%s'
Fehler: 1303
SQLSTATE: 2F003
(ER_SP_NO_RECURSIVE_CREATE
)
Meldung: Kann kein %s innerhalb einer anderen gespeicherten Routine erzeugen
Fehler: 1304
SQLSTATE: 42000
(ER_SP_ALREADY_EXISTS
)
Meldung: %s %s existiert bereits
Fehler: 1305
SQLSTATE: 42000
(ER_SP_DOES_NOT_EXIST
)
Meldung: %s %s existiert nicht
Fehler: 1306
SQLSTATE: HY000
(ER_SP_DROP_FAILED
)
Meldung: DROP %s %s ist fehlgeschlagen
Fehler: 1307
SQLSTATE: HY000
(ER_SP_STORE_FAILED
)
Meldung: CREATE %s %s ist fehlgeschlagen
Fehler: 1308
SQLSTATE: 42000
(ER_SP_LILABEL_MISMATCH
)
Meldung: %s ohne passende Marke: %s
Fehler: 1309
SQLSTATE: 42000
(ER_SP_LABEL_REDEFINE
)
Meldung: Neudefinition der Marke %s
Fehler: 1310
SQLSTATE: 42000
(ER_SP_LABEL_MISMATCH
)
Meldung: Ende-Marke %s ohne zugehörigen Anfang
Fehler: 1311
SQLSTATE: 01000
(ER_SP_UNINIT_VAR
)
Meldung: Zugriff auf nichtinitialisierte Variable %s
Fehler: 1312
SQLSTATE: 0A000
(ER_SP_BADSELECT
)
Meldung: PROCEDURE %s kann im gegebenen Kontext keine Ergebnismenge zurückgeben
Fehler: 1313
SQLSTATE: 42000
(ER_SP_BADRETURN
)
Meldung: RETURN ist nur innerhalb einer FUNCTION erlaubt
Fehler: 1314
SQLSTATE: 0A000
(ER_SP_BADSTATEMENT
)
Meldung: %s ist in gespeicherten Prozeduren nicht erlaubt
Fehler: 1315
SQLSTATE: 42000
(ER_UPDATE_LOG_DEPRECATED_IGNORED
)
Meldung: Das Update-Log ist veraltet und wurde durch das Binär-Log ersetzt. SET SQL_LOG_UPDATE wird ignoriert
Fehler: 1316
SQLSTATE: 42000
(ER_UPDATE_LOG_DEPRECATED_TRANSLATED
)
Meldung: Das Update-Log ist veraltet und wurde durch das Binär-Log ersetzt. SET SQL_LOG_UPDATE wurde in SET SQL_LOG_BIN übersetzt
Fehler: 1317
SQLSTATE: 70100
(ER_QUERY_INTERRUPTED
)
Meldung: Ausführung der Abfrage wurde unterbrochen
Fehler: 1318
SQLSTATE: 42000
(ER_SP_WRONG_NO_OF_ARGS
)
Meldung: Falsche Anzahl von Argumenten für %s %s; erwarte %u, erhalte %u
Fehler: 1319
SQLSTATE: 42000
(ER_SP_COND_MISMATCH
)
Meldung: Undefinierte CONDITION: %s
Fehler: 1320
SQLSTATE: 42000
(ER_SP_NORETURN
)
Meldung: Kein RETURN in FUNCTION %s gefunden
Fehler: 1321
SQLSTATE: 2F005
(ER_SP_NORETURNEND
)
Meldung: FUNCTION %s endete ohne RETURN
Fehler: 1322
SQLSTATE: 42000
(ER_SP_BAD_CURSOR_QUERY
)
Meldung: Cursor-Anweisung muss ein SELECT sein
Fehler: 1323
SQLSTATE: 42000
(ER_SP_BAD_CURSOR_SELECT
)
Meldung: Cursor-SELECT darf kein INTO haben
Fehler: 1324
SQLSTATE: 42000
(ER_SP_CURSOR_MISMATCH
)
Meldung: Undefinierter CURSOR: %s
Fehler: 1325
SQLSTATE: 24000
(ER_SP_CURSOR_ALREADY_OPEN
)
Meldung: Cursor ist schon geöffnet
Fehler: 1326
SQLSTATE: 24000
(ER_SP_CURSOR_NOT_OPEN
)
Meldung: Cursor ist nicht geöffnet
Fehler: 1327
SQLSTATE: 42000
(ER_SP_UNDECLARED_VAR
)
Meldung: Nicht deklarierte Variable: %s
Fehler: 1328
SQLSTATE: HY000
(ER_SP_WRONG_NO_OF_FETCH_ARGS
)
Meldung: Falsche Anzahl von FETCH-Variablen
Fehler: 1329
SQLSTATE: 02000
(ER_SP_FETCH_NO_DATA
)
Meldung: Keine Daten - null Zeilen geholt (fetch), ausgewählt oder verarbeitet
Fehler: 1330
SQLSTATE: 42000
(ER_SP_DUP_PARAM
)
Meldung: Doppelter Parameter: %s
Fehler: 1331
SQLSTATE: 42000
(ER_SP_DUP_VAR
)
Meldung: Doppelte Variable: %s
Fehler: 1332
SQLSTATE: 42000
(ER_SP_DUP_COND
)
Meldung: Doppelte Bedingung: %s
Fehler: 1333
SQLSTATE: 42000
(ER_SP_DUP_CURS
)
Meldung: Doppelter Cursor: %s
Fehler: 1334
SQLSTATE: HY000
(ER_SP_CANT_ALTER
)
Meldung: ALTER %s %s fehlgeschlagen
Fehler: 1335
SQLSTATE: 0A000
(ER_SP_SUBSELECT_NYI
)
Meldung: Subquery-Wert wird nicht unterstützt
Fehler: 1336
SQLSTATE: 0A000
(ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
)
Meldung: %s ist in gespeicherten Funktionen und in Triggern nicht erlaubt
Fehler: 1337
SQLSTATE: 42000
(ER_SP_VARCOND_AFTER_CURSHNDLR
)
Meldung: Deklaration einer Variablen oder einer Bedingung nach der Deklaration eines Cursors oder eines Handlers
Fehler: 1338
SQLSTATE: 42000
(ER_SP_CURSOR_AFTER_HANDLER
)
Meldung: Deklaration eines Cursors nach der Deklaration eines Handlers
Fehler: 1339
SQLSTATE: 20000
(ER_SP_CASE_NOT_FOUND
)
Meldung: Fall für CASE-Anweisung nicht gefunden
Fehler: 1340
SQLSTATE: HY000
(ER_FPARSER_TOO_BIG_FILE
)
Meldung: Konfigurationsdatei '%s' ist zu groß
Fehler: 1341
SQLSTATE: HY000
(ER_FPARSER_BAD_HEADER
)
Meldung: Nicht wohlgeformter Dateityp-Header in Datei '%s'
Fehler: 1342
SQLSTATE: HY000
(ER_FPARSER_EOF_IN_COMMENT
)
Meldung: Unerwartetes Dateiende beim Parsen des Kommentars '%s'
Fehler: 1343
SQLSTATE: HY000
(ER_FPARSER_ERROR_IN_PARAMETER
)
Meldung: Fehler beim Parsen des Parameters '%s' (Zeile: '%s')
Fehler: 1344
SQLSTATE: HY000
(ER_FPARSER_EOF_IN_UNKNOWN_PARAMETER
)
Meldung: Unerwartetes Dateiende beim Überspringen des unbekannten Parameters '%s'
Fehler: 1345
SQLSTATE: HY000
(ER_VIEW_NO_EXPLAIN
)
Meldung: EXPLAIN/SHOW kann nicht verlangt werden. Rechte für zugrunde liegende Tabelle fehlen
Fehler: 1346
SQLSTATE: HY000
(ER_FRM_UNKNOWN_TYPE
)
Meldung: Datei '%s' hat unbekannten Typ '%s' im Header
Fehler: 1347
SQLSTATE: HY000
(ER_WRONG_OBJECT
)
Meldung: '%s.%s' ist nicht %s
Fehler: 1348
SQLSTATE: HY000
(ER_NONUPDATEABLE_COLUMN
)
Meldung: Feld '%s' ist nicht aktualisierbar
Fehler: 1349
SQLSTATE: HY000
(ER_VIEW_SELECT_DERIVED
)
Meldung: SELECT der View enthält eine Subquery in der FROM-Klausel
Fehler: 1350
SQLSTATE: HY000
(ER_VIEW_SELECT_CLAUSE
)
Meldung: SELECT der View enthält eine '%s'-Klausel
Fehler: 1351
SQLSTATE: HY000
(ER_VIEW_SELECT_VARIABLE
)
Meldung: SELECT der View enthält eine Variable oder einen Parameter
Fehler: 1352
SQLSTATE: HY000
(ER_VIEW_SELECT_TMPTABLE
)
Meldung: SELECT der View verweist auf eine temporäre Tabelle '%s'
Fehler: 1353
SQLSTATE: HY000
(ER_VIEW_WRONG_LIST
)
Meldung: SELECT- und Feldliste der Views haben unterschiedliche Anzahlen von Spalten
Fehler: 1354
SQLSTATE: HY000
(ER_WARN_VIEW_MERGE
)
Meldung: View-Merge-Algorithmus kann hier momentan nicht verwendet werden (undefinierter Algorithmus wird angenommen)
Fehler: 1355
SQLSTATE: HY000
(ER_WARN_VIEW_WITHOUT_KEY
)
Meldung: Die aktualisierte View enthält nicht den vollständigen Schlüssel der zugrunde liegenden Tabelle
Fehler: 1356
SQLSTATE: HY000
(ER_VIEW_INVALID
)
Meldung: View '%s.%s' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
Fehler: 1357
SQLSTATE: HY000
(ER_SP_NO_DROP_SP
)
Meldung: Kann eine %s nicht von innerhalb einer anderen gespeicherten Routine löschen oder ändern
Fehler: 1358
SQLSTATE: HY000
(ER_SP_GOTO_IN_HNDLR
)
Meldung: GOTO ist im Handler einer gespeicherten Prozedur nicht erlaubt
Fehler: 1359
SQLSTATE: HY000
(ER_TRG_ALREADY_EXISTS
)
Meldung: Trigger existiert bereits
Fehler: 1360
SQLSTATE: HY000
(ER_TRG_DOES_NOT_EXIST
)
Meldung: Trigger existiert nicht
Fehler: 1361
SQLSTATE: HY000
(ER_TRG_ON_VIEW_OR_TEMP_TABLE
)
Meldung: '%s' des Triggers ist View oder temporäre Tabelle
Fehler: 1362
SQLSTATE: HY000
(ER_TRG_CANT_CHANGE_ROW
)
Meldung: Aktualisieren einer %s-Zeile ist in einem %-Trigger nicht erlaubt
Fehler: 1363
SQLSTATE: HY000
(ER_TRG_NO_SUCH_ROW_IN_TRG
)
Meldung: Es gibt keine %s-Zeile im %s-Trigger
Fehler: 1364
SQLSTATE: HY000
(ER_NO_DEFAULT_FOR_FIELD
)
Meldung: Feld '%s' hat keinen Vorgabewert
Fehler: 1365
SQLSTATE: 22012
(ER_DIVISION_BY_ZERO
)
Meldung: Division durch 0
Fehler: 1366
SQLSTATE: HY000
(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD
)
Meldung: Falscher %s-Wert: '%s' für Feld '%s' in Zeile %ld
Fehler: 1367
SQLSTATE: 22007
(ER_ILLEGAL_VALUE_FOR_TYPE
)
Meldung: Nicht zulässiger %s-Wert '%s' beim Parsen gefunden
Fehler: 1368
SQLSTATE: HY000
(ER_VIEW_NONUPD_CHECK
)
Meldung: CHECK OPTION auf nicht-aktualisierbarem View '%s.%s'
Fehler: 1369
SQLSTATE: HY000
(ER_VIEW_CHECK_FAILED
)
Meldung: CHECK OPTION fehlgeschlagen: '%s.%s'
Fehler: 1370
SQLSTATE: 42000
(ER_PROCACCESS_DENIED_ERROR
)
Meldung: Befehl %s nicht zulässig für Benutzer '%s'@'%s' in Routine '%s'
Fehler: 1371
SQLSTATE: HY000
(ER_RELAY_LOG_FAIL
)
Meldung: Bereinigen alter Relais-Logs fehlgeschlagen: %s
Fehler: 1372
SQLSTATE: HY000
(ER_PASSWD_LENGTH
)
Meldung: Passwort-Hash sollte eine Hexdaezimalzahl mit %d Stellen sein
Fehler: 1373
SQLSTATE: HY000
(ER_UNKNOWN_TARGET_BINLOG
)
Meldung: Ziel-Log im Binlog-Index nicht gefunden
Fehler: 1374
SQLSTATE: HY000
(ER_IO_ERR_LOG_INDEX_READ
)
Meldung: Fehler beim Lesen der Log-Index-Datei
Fehler: 1375
SQLSTATE: HY000
(ER_BINLOG_PURGE_PROHIBITED
)
Meldung: Server-Konfiguration erlaubt keine Binlog-Bereinigung
Fehler: 1376
SQLSTATE: HY000
(ER_FSEEK_FAIL
)
Meldung: fseek() fehlgeschlagen
Fehler: 1377
SQLSTATE: HY000
(ER_BINLOG_PURGE_FATAL_ERR
)
Meldung: Schwerwiegender Fehler bei der Log-Bereinigung
Fehler: 1378
SQLSTATE: HY000
(ER_LOG_IN_USE
)
Meldung: Ein zu bereinigendes Log wird gerade benutzt, daher keine Bereinigung
Fehler: 1379
SQLSTATE: HY000
(ER_LOG_PURGE_UNKNOWN_ERR
)
Meldung: Unbekannter Fehler bei Log-Bereinigung
Fehler: 1380
SQLSTATE: HY000
(ER_RELAY_LOG_INIT
)
Meldung: Initialisierung der Relais-Log-Position fehlgeschlagen: %s
Fehler: 1381
SQLSTATE: HY000
(ER_NO_BINARY_LOGGING
)
Meldung: Sie verwenden keine Binärlogs
Fehler: 1382
SQLSTATE: HY000
(ER_RESERVED_SYNTAX
)
Meldung: Die Schreibweise '%s' ist für interne Zwecke des MySQL-Servers reserviert
Fehler: 1383
SQLSTATE: HY000
(ER_WSAS_FAILED
)
Meldung: WSAStartup fehlgeschlagen
Fehler: 1384
SQLSTATE: HY000
(ER_DIFF_GROUPS_PROC
)
Meldung: Kann Prozeduren mit unterschiedlichen Gruppen noch nicht verarbeiten
Fehler: 1385
SQLSTATE: HY000
(ER_NO_GROUP_FOR_PROC
)
Meldung: SELECT muss bei dieser Prozedur ein GROUP BY haben
Fehler: 1386
SQLSTATE: HY000
(ER_ORDER_WITH_PROC
)
Meldung: Kann bei dieser Prozedur keine ORDER-BY-Klausel verwenden
Fehler: 1387
SQLSTATE: HY000
(ER_LOGGING_PROHIBIT_CHANGING_OF
)
Meldung: Binärlogs und Replikation verhindern Wechsel des globalen Servers %s
Fehler: 1388
SQLSTATE: HY000
(ER_NO_FILE_MAPPING
)
Meldung: Kann Datei nicht abbilden: %s, Fehler: %d
Fehler: 1389
SQLSTATE: HY000
(ER_WRONG_MAGIC
)
Meldung: Falsche magische Zahlen in %s
Fehler: 1390
SQLSTATE: HY000
(ER_PS_MANY_PARAM
)
Meldung: Vorbereitete Anweisung enthält zu viele Platzhalter
Fehler: 1391
SQLSTATE: HY000
(ER_KEY_PART_0
)
Meldung: Länge des Schlüsselteils '%s' kann nicht 0 sein
Fehler: 1392
SQLSTATE: HY000
(ER_VIEW_CHECKSUM
)
Meldung: View-Text-Prüfsumme fehlgeschlagen
Fehler: 1393
SQLSTATE: HY000
(ER_VIEW_MULTIUPDATE
)
Meldung: Kann nicht mehr als eine Basistabelle über Join-View '%s.%s' ändern
Fehler: 1394
SQLSTATE: HY000
(ER_VIEW_NO_INSERT_FIELD_LIST
)
Meldung: Kann nicht ohne Feldliste in Join-View '%s.%s' einfügen
Fehler: 1395
SQLSTATE: HY000
(ER_VIEW_DELETE_MERGE_VIEW
)
Meldung: Kann nicht aus Join-View '%s.%s' löschen
Fehler: 1396
SQLSTATE: HY000
(ER_CANNOT_USER
)
Meldung: Operation %s schlug fehl für %s
Fehler: 1397
SQLSTATE: XAE04
(ER_XAER_NOTA
)
Meldung: XAER_NOTA: Unbekannte XID
Fehler: 1398
SQLSTATE: XAE05
(ER_XAER_INVAL
)
Meldung: XAER_INVAL: Ungültige Argumente (oder nicht unterstützter Befehl)
Fehler: 1399
SQLSTATE: XAE07
(ER_XAER_RMFAIL
)
Meldung: XAER_RMFAIL: DEr Befehl kann nicht ausgeführt werden, wenn die globale Transaktion im Zustand %s ist
Fehler: 1400
SQLSTATE: XAE09
(ER_XAER_OUTSIDE
)
Meldung: XAER_OUTSIDE: Einige Arbeiten werden außerhalb der globalen Transaktion verrichtet
Fehler: 1401
SQLSTATE: XAE03
(ER_XAER_RMERR
)
Meldung: XAER_RMERR: Schwerwiegender Fehler im Transaktionszweig - prüfen Sie Ihre Daten auf Konsistenz
Fehler: 1402
SQLSTATE: XA100
(ER_XA_RBROLLBACK
)
Meldung: XA_RBROLLBACK: Transaktionszweig wurde zurückgerollt
Fehler: 1403
SQLSTATE: 42000
(ER_NONEXISTING_PROC_GRANT
)
Meldung: Es gibt diese Berechtigung für Benutzer '%s' auf Host '%s' für Routine '%s' nicht
Fehler: 1404
SQLSTATE: HY000
(ER_PROC_AUTO_GRANT_FAIL
)
Meldung: Gewährung von EXECUTE- und ALTER-ROUTINE-Rechten fehlgeschlagen
Fehler: 1405
SQLSTATE: HY000
(ER_PROC_AUTO_REVOKE_FAIL
)
Meldung: Rücknahme aller Rechte für die gelöschte Routine fehlgeschlagen
Fehler: 1406
SQLSTATE: 22001
(ER_DATA_TOO_LONG
)
Meldung: Daten zu lang für Feld '%s' in Zeile %ld
Fehler: 1407
SQLSTATE: 42000
(ER_SP_BAD_SQLSTATE
)
Meldung: Ungültiger SQLSTATE: '%s'
Fehler: 1408
SQLSTATE: HY000
(ER_STARTUP
)
Meldung: %s: bereit für Verbindungen. Version: '%s' Socket: '%s' Port: %d %s
Fehler: 1409
SQLSTATE: HY000
(ER_LOAD_FROM_FIXED_SIZE_ROWS_TO_VAR
)
Meldung: Kann Wert aus Datei mit Zeilen fester Größe nicht in Variable laden
Fehler: 1410
SQLSTATE: 42000
(ER_CANT_CREATE_USER_WITH_GRANT
)
Meldung: Sie dürfen keinen Benutzer mit GRANT anlegen
Fehler: 1411
SQLSTATE: HY000
(ER_WRONG_VALUE_FOR_TYPE
)
Meldung: Falscher %s-Wert: '%s' für Funktion %s
Fehler: 1412
SQLSTATE: HY000
(ER_TABLE_DEF_CHANGED
)
Meldung: Tabellendefinition wurde geändert, bitte starten Sie die Transaktion neu
Fehler: 1413
SQLSTATE: 42000
(ER_SP_DUP_HANDLER
)
Meldung: Doppelter Handler im selben Block deklariert
Fehler: 1414
SQLSTATE: 42000
(ER_SP_NOT_VAR_ARG
)
Meldung: OUT- oder INOUT-Argument %d für Routine %s ist keine Variable
Fehler: 1415
SQLSTATE: 0A000
(ER_SP_NO_RETSET
)
Meldung: Rückgabe einer Ergebnismenge aus einer %s ist nicht erlaubt
Fehler: 1416
SQLSTATE: 22003
(ER_CANT_CREATE_GEOMETRY_OBJECT
)
Meldung: Kann kein Geometrieobjekt aus den Daten machen, die Sie dem GEOMETRY-Feld übergeben haben
Fehler: 1417
SQLSTATE: HY000
(ER_FAILED_ROUTINE_BREAK_BINLOG
)
Meldung: Eine Routine, die weder NO SQL noch READS SQL DATA in der Deklaration hat, schlug fehl und Binärlogging ist aktiv. Wenn Nicht-Transaktions-Tabellen aktualisiert wurden, enthält das Binärlog ihre Änderungen nicht
Fehler: 1418
SQLSTATE: HY000
(ER_BINLOG_UNSAFE_ROUTINE
)
Meldung: Diese Routine hat weder DETERMINISTIC, NO SQL noch READS SQL DATA in der Deklaration und Binärlogging ist aktiv (*vielleicht* sollten Sie die weniger sichere Variable log_bin_trust_routine_creators verwenden)
Fehler: 1419
SQLSTATE: HY000
(ER_BINLOG_CREATE_ROUTINE_NEED_SUPER
)
Meldung: Sie haben keine SUPER-Berechtigung und Binärlogging ist aktiv (*vielleicht* sollten Sie die weniger sichere Variable log_bin_trust_routine_creators verwenden)
Fehler: 1420
SQLSTATE: HY000
(ER_EXEC_STMT_WITH_OPEN_CURSOR
)
Meldung: Sie können keine vorbereitete Anweisung ausführen, die mit einem geöffneten Cursor verknüpft ist. Setzen Sie die Anweisung zurück, um sie neu auszuführen
Fehler: 1421
SQLSTATE: HY000
(ER_STMT_HAS_NO_OPEN_CURSOR
)
Meldung: Die Anweisung (%lu) hat keinen geöffneten Cursor
Fehler: 1422
SQLSTATE: HY000
(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
)
Meldung: Explizites oder implizites Commit ist in gespeicherten Funktionen und in Triggern nicht erlaubt
Fehler: 1423
SQLSTATE: HY000
(ER_NO_DEFAULT_FOR_VIEW_FIELD
)
Meldung: Ein Feld der dem View '%s.%s' zugrundeliegenden Tabelle hat keinen Vorgabewert
Fehler: 1424
SQLSTATE: HY000
(ER_SP_NO_RECURSION
)
Meldung: Rekursive gespeicherte Routinen und Triggers sind nicht erlaubt
Fehler: 1425
SQLSTATE: 42000
(ER_TOO_BIG_SCALE
)
Meldung: Zu großer Skalierungsfaktor %d für Feld '%s' angegeben. Maximum ist %d
Fehler: 1426
SQLSTATE: 42000
(ER_TOO_BIG_PRECISION
)
Meldung: Zu große Genauigkeit %d für Feld '%s' angegeben. Maximum ist %d
Fehler: 1427
SQLSTATE: 42000
(ER_M_BIGGER_THAN_D
)
Meldung: Für FLOAT(M,D), DOUBLE(M,D) oder DECIMAL(M,D) muss M >= D sein (Feld '%s')
Fehler: 1428
SQLSTATE: HY000
(ER_WRONG_LOCK_OF_SYSTEM_TABLE
)
Meldung: Sie können Schreibsperren auf der Systemtabelle '%s.%s' nicht mit anderen Tabellen kombinieren
Fehler: 1429
SQLSTATE: HY000
(ER_CONNECT_TO_FOREIGN_DATA_SOURCE
)
Meldung: Kann nicht mit Fremddatenquelle verbinden: %s
Fehler: 1430
SQLSTATE: HY000
(ER_QUERY_ON_FOREIGN_DATA_SOURCE
)
Meldung: Bei der Verarbeitung der Abfrage ist in der Fremddatenquelle ein Problem aufgetreten. Datenquellenfehlermeldung: %s
Fehler: 1431
SQLSTATE: HY000
(ER_FOREIGN_DATA_SOURCE_DOESNT_EXIST
)
Meldung: Die Fremddatenquelle, auf die Sie zugreifen wollen, existiert nicht. Datenquellenfehlermeldung: %s
Fehler: 1432
SQLSTATE: HY000
(ER_FOREIGN_DATA_STRING_INVALID_CANT_CREATE
)
Meldung: Kann föderierte Tabelle nicht erzeugen. Der Datenquellen-Verbindungsstring '%s' hat kein korrektes Format
Fehler: 1433
SQLSTATE: HY000
(ER_FOREIGN_DATA_STRING_INVALID
)
Meldung: Der Datenquellen-Verbindungsstring '%s' hat kein korrektes Format
Fehler: 1434
SQLSTATE: HY000
(ER_CANT_CREATE_FEDERATED_TABLE
)
Meldung: Kann föderierte Tabelle nicht erzeugen. Fremddatenquellenfehlermeldung: %s
Fehler: 1435
SQLSTATE: HY000
(ER_TRG_IN_WRONG_SCHEMA
)
Meldung: Trigger im falschen Schema
Fehler: 1436
SQLSTATE: HY000
(ER_STACK_OVERRUN_NEED_MORE
)
Meldung: Thread-Stack-Überlauf: %ld Bytes eines %ld-Byte-Stacks in Verwendung, und %ld Bytes benötigt. Verwenden Sie 'mysqld -O thread_stack=#', um einen größeren Stack anzugeben
Fehler: 1437
SQLSTATE: 42000
(ER_TOO_LONG_BODY
)
Meldung: Routinen-Body für '%s' ist zu lang
Fehler: 1438
SQLSTATE: HY000
(ER_WARN_CANT_DROP_DEFAULT_KEYCACHE
)
Meldung: Der vorgabemäßige Schlüssel-Cache kann nicht gelöscht werden
Fehler: 1439
SQLSTATE: 42000
(ER_TOO_BIG_DISPLAYWIDTH
)
Meldung: Anzeigebreite außerhalb des zulässigen Bereichs für Spalte '%s' (Maximum: %d)
Fehler: 1440
SQLSTATE: XAE08
(ER_XAER_DUPID
)
Meldung: XAER_DUPID: Die XID existiert bereits
Fehler: 1441
SQLSTATE: 22008
(ER_DATETIME_FUNCTION_OVERFLOW
)
Meldung: Datetime-Funktion: %s Feldüberlauf
Fehler: 1442
SQLSTATE: HY000
(ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG
)
Meldung: Kann Tabelle '%s' in gespeicherter Funktion oder Trigger nicht aktualisieren, weil sie bereits von der Anweisung verwendet wird, die diese gespeicherte Funktion oder den Trigger aufrief
Fehler: 1443
SQLSTATE: HY000
(ER_VIEW_PREVENT_UPDATE
)
Meldung: Die Definition der Tabelle '%s' verhindert die Operation %s auf Tabelle '%s'
Fehler: 1444
SQLSTATE: HY000
(ER_PS_NO_RECURSION
)
Meldung: Die vorbereitete Anweisung enthält einen Aufruf einer gespeicherten Routine, die auf eben dieselbe Anweisung verweist. Es ist nicht erlaubt, eine vorbereitete Anweisung in solch rekursiver Weise auszuführen
Fehler: 1445
SQLSTATE: HY000
(ER_SP_CANT_SET_AUTOCOMMIT
)
Meldung: Es ist nicht erlaubt, innerhalb einer gespeicherten Funktion oder eines Triggers AUTOCOMMIT zu setzen
Fehler: 1446
SQLSTATE: HY000
(ER_MALFORMED_DEFINER
)
Meldung: Definierer des View ist nicht vollständig spezifiziert
Fehler: 1447
SQLSTATE: HY000
(ER_VIEW_FRM_NO_USER
)
Meldung: View '%s'.'%s' hat keine Definierer-Information (altes Tabellenformat). Der aktuelle Benutzer wird als Definierer verwendet. Bitte erstellen Sie den View neu
Fehler: 1448
SQLSTATE: HY000
(ER_VIEW_OTHER_USER
)
Meldung: Sie brauchen die SUPER-Berechtigung, um einen View mit dem Definierer '%s'@'%s' zu erzeugen
Fehler: 1449
SQLSTATE: HY000
(ER_NO_SUCH_USER
)
Meldung: '%s'@'%s' ist nicht registriert
Fehler: 1450
SQLSTATE: HY000
(ER_FORBID_SCHEMA_CHANGE
)
Meldung: Wechsel des Schemas von '%s' auf '%s' ist nicht erlaubt
Fehler: 1451
SQLSTATE: 23000
(ER_ROW_IS_REFERENCED_2
)
Meldung: Kann Eltern-Zeile nicht löschen oder aktualisieren: eine Fremdschlüsselbedingung schlägt fehl (%s)
Fehler: 1452
SQLSTATE: 23000
(ER_NO_REFERENCED_ROW_2
)
Meldung: Kann Kind-Zeile nicht hinzufügen oder aktualisieren: eine Fremdschlüsselbedingung schlägt fehl (%s)
Fehler: 1453
SQLSTATE: 42000
(ER_SP_BAD_VAR_SHADOW
)
Meldung: Variable '%s' muss mit `...` geschützt oder aber umbenannt werden
Fehler: 1454
SQLSTATE: HY000
(ER_TRG_NO_DEFINER
)
Meldung: Kein Definierer-Attribut für Trigger '%s'.'%s'. Der Trigger wird mit der Autorisierung des Aufrufers aktiviert, der möglicherweise keine zureichenden Berechtigungen hat. Bitte legen Sie den Trigger neu an.
Fehler: 1455
SQLSTATE: HY000
(ER_OLD_FILE_FORMAT
)
Meldung: '%s' hat altes Format, Sie sollten die '%s'-Objekt(e) neu erzeugen
Fehler: 1456
SQLSTATE: HY000
(ER_SP_RECURSION_LIMIT
)
Meldung: Rekursionsgrenze %d (durch Variable max_sp_recursion_depth gegeben) wurde für Routine %s überschritten
Fehler: 1457
SQLSTATE: HY000
(ER_SP_PROC_TABLE_CORRUPT
)
Meldung: Routine %s konnte nicht geladen werden. Die Tabelle mysql.proc fehlt, ist beschädigt, oder enthält fehlerhaften Daten (interner Code: %d)
Fehler: 1458
SQLSTATE: 42000
(ER_SP_WRONG_NAME
)
Meldung: Ungültiger Routinenname '%s'
Fehler: 1459
SQLSTATE: HY000
(ER_TABLE_NEEDS_UPGRADE
)
Meldung: Tabellenaktualisierung erforderlich. Bitte zum Reparieren "REPAIR TABLE `%s`" eingeben!
Fehler: 1460
SQLSTATE: 42000
(ER_SP_NO_AGGREGATE
)
Meldung: AGGREGATE wird bei gespeicherten Funktionen nicht unterstützt
Fehler: 1461
SQLSTATE: 42000
(ER_MAX_PREPARED_STMT_COUNT_REACHED
)
Meldung: Kann nicht mehr Anweisungen als max_prepared_stmt_count erzeugen (aktueller Wert: %lu)
Fehler: 1462
SQLSTATE: HY000
(ER_VIEW_RECURSIVE
)
Meldung: `%s`.`%s` enthält View-Rekursion
Fehler: 1463
SQLSTATE: 42000
(ER_NON_GROUPING_FIELD_USED
)
Meldung: In der %s-Klausel wird das die Nicht-Gruppierungsspalte '%s' verwendet
Fehler: 1464
SQLSTATE: HY000
(ER_TABLE_CANT_HANDLE_SPKEYS
)
Meldung: Der verwendete Tabellentyp unterstützt keine SPATIAL-Indizes
Fehler: 1465
SQLSTATE: HY000
(ER_ILLEGAL_HA_CREATE_OPTION
)
Meldung: Speicher-Engine '%s' der Tabelle unterstützt die Option '%s' nicht
Fehler: 1466
SQLSTATE: HY000
(ER_PARTITION_REQUIRES_VALUES_ERROR
)
Meldung: %s-PARTITIONierung erfordert Definition von VALUES %s für jede Partition
Fehler: 1467
SQLSTATE: HY000
(ER_PARTITION_WRONG_VALUES_ERROR
)
Meldung: Nur %s-PARTITIONierung kann VALUES %s in der Partitionsdefinition verwenden
Fehler: 1468
SQLSTATE: HY000
(ER_PARTITION_MAXVALUE_ERROR
)
Meldung: MAXVALUE kann nur für die Definition der letzten Partition verwendet werden
Fehler: 1469
SQLSTATE: HY000
(ER_PARTITION_SUBPARTITION_ERROR
)
Meldung: Unterpartitionen dürfen nur HASH- oder KEY-Partitionen sein
Fehler: 1470
SQLSTATE: HY000
(ER_PARTITION_SUBPART_MIX_ERROR
)
Meldung: Unterpartitionen können nur Hash- oder Key-Partitionen sein
Fehler: 1471
SQLSTATE: HY000
(ER_PARTITION_WRONG_NO_PART_ERROR
)
Meldung: Falsche Anzahl von Partitionen definiert, stimmt nicht mit vorherigen Einstellungen überein
Fehler: 1472
SQLSTATE: HY000
(ER_PARTITION_WRONG_NO_SUBPART_ERROR
)
Meldung: Falsche Anzahl von Unterpartitionen definiert, stimmt nicht mit vorherigen Einstellungen überein
Fehler: 1473
SQLSTATE: HY000
(ER_CONST_EXPR_IN_PARTITION_FUNC_ERROR
)
Meldung: Konstante oder Random-Ausdrücke in (Unter-)Partitionsfunktionen sind nicht erlaubt
Fehler: 1474
SQLSTATE: HY000
(ER_NO_CONST_EXPR_IN_RANGE_OR_LIST_ERROR
)
Meldung: Ausdrücke in RANGE/LIST VALUES müssen konstant sein
Fehler: 1475
SQLSTATE: HY000
(ER_FIELD_NOT_FOUND_PART_ERROR
)
Meldung: Felder in der Feldliste der Partitionierungsfunktion wurden in der Tabelle nicht gefunden
Fehler: 1476
SQLSTATE: HY000
(ER_LIST_OF_FIELDS_ONLY_IN_HASH_ERROR
)
Meldung: Eine Feldliste ist nur in KEY-Partitionen erlaubt
Fehler: 1477
SQLSTATE: HY000
(ER_INCONSISTENT_PARTITION_INFO_ERROR
)
Meldung: Die Partitionierungsinformationen in der frm-Datei stimmen nicht mit dem überein, was in die frm-Datei geschrieben werden kann
Fehler: 1478
SQLSTATE: HY000
(ER_PARTITION_FUNC_NOT_ALLOWED_ERROR
)
Meldung: Die %s-Funktion gibt einen falschen Typ zurück
Fehler: 1479
SQLSTATE: HY000
(ER_PARTITIONS_MUST_BE_DEFINED_ERROR
)
Meldung: Für %s-Partitionen muss jede Partition definiert sein
Fehler: 1480
SQLSTATE: HY000
(ER_RANGE_NOT_INCREASING_ERROR
)
Meldung: Werte in VALUES LESS THAN müssen für jede Partition strikt aufsteigend sein
Fehler: 1481
SQLSTATE: HY000
(ER_INCONSISTENT_TYPE_OF_FUNCTIONS_ERROR
)
Meldung: VALUES-Werte müssen vom selben Typ wie die Partitionierungsfunktion sein
Fehler: 1482
SQLSTATE: HY000
(ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR
)
Meldung: Mehrfachdefinition derselben Konstante bei Listen-Partitionierung
Fehler: 1483
SQLSTATE: HY000
(ER_PARTITION_ENTRY_ERROR
)
Meldung: Partitionierung kann in einer Abfrage nicht alleinstehend benutzt werden
Fehler: 1484
SQLSTATE: HY000
(ER_MIX_HANDLER_ERROR
)
Meldung: Das Vermischen von Handlern in Partitionen ist in dieser Version von MySQL nicht erlaubt
Fehler: 1485
SQLSTATE: HY000
(ER_PARTITION_NOT_DEFINED_ERROR
)
Meldung: Für die partitionierte Engine müssen alle %s definiert sein
Fehler: 1486
SQLSTATE: HY000
(ER_TOO_MANY_PARTITIONS_ERROR
)
Meldung: Es wurden zu vielen Partitionen (einschließlich Unterpartitionen) definiert
Fehler: 1487
SQLSTATE: HY000
(ER_SUBPARTITION_ERROR
)
Meldung: RANGE/LIST-Partitionierung kann bei Unterpartitionen nur zusammen mit HASH/KEY-Partitionierung verwendet werden
Fehler: 1488
SQLSTATE: HY000
(ER_CANT_CREATE_HANDLER_FILE
)
Meldung: Erzeugen einer spezifischen Handler-Datei fehlgeschlagen
Fehler: 1489
SQLSTATE: HY000
(ER_BLOB_FIELD_IN_PART_FUNC_ERROR
)
Meldung: In der Partitionierungsfunktion sind BLOB-Spalten nicht erlaubt
Fehler: 1490
SQLSTATE: HY000
(ER_UNIQUE_KEY_NEED_ALL_FIELDS_IN_PF
)
Meldung: A %s must include all columns in the table's partitioning function
Fehler: 1491
SQLSTATE: HY000
(ER_NO_PARTS_ERROR
)
Meldung: Eine Anzahl von %s = 0 ist kein erlaubter Wert
Fehler: 1492
SQLSTATE: HY000
(ER_PARTITION_MGMT_ON_NONPARTITIONED
)
Meldung: Partitionsverwaltung einer nicht partitionierten Tabelle ist nicht möglich
Fehler: 1493
SQLSTATE: HY000
(ER_FOREIGN_KEY_ON_PARTITIONED
)
Meldung: Fremdschlüssel-Beschränkungen sind im Zusammenhang mit Partitionierung nicht zulässig
Fehler: 1494
SQLSTATE: HY000
(ER_DROP_PARTITION_NON_EXISTENT
)
Meldung: Fehler in der Partitionsliste bei %s
Fehler: 1495
SQLSTATE: HY000
(ER_DROP_LAST_PARTITION
)
Meldung: Es lassen sich nicht sämtliche Partitionen löschen, benutzen Sie statt dessen DROP TABLE
Fehler: 1496
SQLSTATE: HY000
(ER_COALESCE_ONLY_ON_HASH_PARTITION
)
Meldung: COALESCE PARTITION kann nur auf HASH- oder KEY-Partitionen benutzt werden
Fehler: 1497
SQLSTATE: HY000
(ER_REORG_HASH_ONLY_ON_SAME_NO
)
Meldung: REORGANIZE PARTITION kann nur zur Reorganisation von Partitionen verwendet werden, nicht, um ihre Nummern zu ändern
Fehler: 1498
SQLSTATE: HY000
(ER_REORG_NO_PARAM_ERROR
)
Meldung: REORGANIZE PARTITION ohne Parameter kann nur für auto-partitionierte Tabellen verwendet werden, die HASH-Partitionierung benutzen
Fehler: 1499
SQLSTATE: HY000
(ER_ONLY_ON_RANGE_LIST_PARTITION
)
Meldung: %s PARTITION kann nur für RANGE- oder LIST-Partitionen verwendet werden
Fehler: 1500
SQLSTATE: HY000
(ER_ADD_PARTITION_SUBPART_ERROR
)
Meldung: Es wurde versucht, eine oder mehrere Partitionen mit der falschen Anzahl von Unterpartitionen hinzuzufügen
Fehler: 1501
SQLSTATE: HY000
(ER_ADD_PARTITION_NO_NEW_PARTITION
)
Meldung: Es muss zumindest eine Partition hinzugefügt werden
Fehler: 1502
SQLSTATE: HY000
(ER_COALESCE_PARTITION_NO_PARTITION
)
Meldung: Zumindest eine Partition muss mit COALESCE PARTITION zusammengefügt werden
Fehler: 1503
SQLSTATE: HY000
(ER_REORG_PARTITION_NOT_EXIST
)
Meldung: Es wurde versucht, mehr Partitionen als vorhanden zu reorganisieren
Fehler: 1504
SQLSTATE: HY000
(ER_SAME_NAME_PARTITION
)
Meldung: Doppelter Partitionsname: %s
Fehler: 1505
SQLSTATE: HY000
(ER_NO_BINLOG_ERROR
)
Meldung: Es es nicht erlaubt, bei diesem Befehl binlog abzuschalten
Fehler: 1506
SQLSTATE: HY000
(ER_CONSECUTIVE_REORG_PARTITIONS
)
Meldung: Bei der Reorganisation eines Satzes von Partitionen müssen diese in geordneter Reihenfolge vorliegen
Fehler: 1507
SQLSTATE: HY000
(ER_REORG_OUTSIDE_RANGE
)
Meldung: Die Reorganisation von RANGE-Partitionen kann Gesamtbereiche nicht verändern, mit Ausnahme der letzten Partition, die den Bereich erweitern kann
Fehler: 1508
SQLSTATE: HY000
(ER_PARTITION_FUNCTION_FAILURE
)
Meldung: Partitionsfunktion in dieser Version dieses Handlers nicht unterstützt
Fehler: 1509
SQLSTATE: HY000
(ER_PART_STATE_ERROR
)
Meldung: Partitionszustand kann nicht von CREATE oder ALTER TABLE aus definiert werden
Fehler: 1510
SQLSTATE: HY000
(ER_LIMITED_PART_RANGE
)
Meldung: Der Handler %s unterstützt in VALUES nur 32-Bit-Integers
Fehler: 1511
SQLSTATE: HY000
(ER_PLUGIN_IS_NOT_LOADED
)
Meldung: Plugin '%s' ist nicht geladen
Fehler: 1512
SQLSTATE: HY000
(ER_WRONG_VALUE
)
Meldung: Falscher %s-Wert: '%s'
Fehler: 1513
SQLSTATE: HY000
(ER_NO_PARTITION_FOR_GIVEN_VALUE
)
Meldung: Tabelle hat für den Wert %s keine Partition
Fehler: 1514
SQLSTATE: HY000
(ER_FILEGROUP_OPTION_ONLY_ONCE
)
Meldung: %s darf nicht mehr als einmal angegegeben werden
Fehler: 1515
SQLSTATE: HY000
(ER_CREATE_FILEGROUP_FAILED
)
Meldung: Anlegen von %s fehlgeschlagen
Fehler: 1516
SQLSTATE: HY000
(ER_DROP_FILEGROUP_FAILED
)
Meldung: Löschen (drop) von %s fehlgeschlagen
Fehler: 1517
SQLSTATE: HY000
(ER_TABLESPACE_AUTO_EXTEND_ERROR
)
Meldung: Der Handler unterstützt keine automatische Erweiterung (Autoextend) von Tablespaces
Fehler: 1518
SQLSTATE: HY000
(ER_WRONG_SIZE_NUMBER
)
Meldung: Ein Größen-Parameter wurde unkorrekt angegeben, muss entweder Zahl sein oder im Format 10M
Fehler: 1519
SQLSTATE: HY000
(ER_SIZE_OVERFLOW_ERROR
)
Meldung: Die Zahl für die Größe war korrekt, aber der Zahlanteil darf nicht größer als 2 Milliarden sein
Fehler: 1520
SQLSTATE: HY000
(ER_ALTER_FILEGROUP_FAILED
)
Meldung: Änderung von %s fehlgeschlagen
Fehler: 1521
SQLSTATE: HY000
(ER_BINLOG_ROW_LOGGING_FAILED
)
Meldung: Schreiben einer Zeilen ins zeilenbasierte Binärlog fehlgeschlagen
Fehler: 1522
SQLSTATE: HY000
(ER_BINLOG_ROW_WRONG_TABLE_DEF
)
Meldung: Tabellendefinition auf Master und Slave stimmt nicht überein
Fehler: 1523
SQLSTATE: HY000
(ER_BINLOG_ROW_RBR_TO_SBR
)
Meldung: Slave, die mit --log-slave-updates laufen, müssen zeilenbasiertes Loggen verwenden, um zeilenbasierte Binärlog-Ereignisse loggen zu können
Fehler: 1524
SQLSTATE: HY000
(ER_EVENT_ALREADY_EXISTS
)
Meldung: Event '%s' existiert bereits
Fehler: 1525
SQLSTATE: HY000
(ER_EVENT_STORE_FAILED
)
Meldung: Speichern von Event %s fehlgeschlagen. Fehlercode der Speicher-Engine: %d
Fehler: 1526
SQLSTATE: HY000
(ER_EVENT_DOES_NOT_EXIST
)
Meldung: Unbekanntes Event '%s'
Fehler: 1527
SQLSTATE: HY000
(ER_EVENT_CANT_ALTER
)
Meldung: Ändern des Events '%s' fehlgeschlagen
Fehler: 1528
SQLSTATE: HY000
(ER_EVENT_DROP_FAILED
)
Meldung: Löschen von %s fehlgeschlagen
Fehler: 1529
SQLSTATE: HY000
(ER_EVENT_INTERVAL_NOT_POSITIVE_OR_TOO_BIG
)
Meldung: INTERVAL ist entweder nicht positiv oder zu groß
Fehler: 1530
SQLSTATE: HY000
(ER_EVENT_ENDS_BEFORE_STARTS
)
Meldung: ENDS ist entweder ungültig oder liegt vor STARTS
Fehler: 1531
SQLSTATE: HY000
(ER_EVENT_EXEC_TIME_IN_THE_PAST
)
Meldung: Aktivierungszeit (AT) liegt in der Vergangenheit
Fehler: 1532
SQLSTATE: HY000
(ER_EVENT_OPEN_TABLE_FAILED
)
Meldung: Öffnen von mysql.event fehlgeschlagen
Fehler: 1533
SQLSTATE: HY000
(ER_EVENT_NEITHER_M_EXPR_NOR_M_AT
)
Meldung: Kein DATETIME-Ausdruck angegeben
Fehler: 1534
SQLSTATE: HY000
(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED
)
Meldung: Spaltenanzahl von mysql.%s falsch. %d erwartet, aber %d gefunden. Tabelle ist wahrscheinlich beschädigt
Fehler: 1535
SQLSTATE: HY000
(ER_CANNOT_LOAD_FROM_TABLE
)
Meldung: Kann mysql.%s nicht einlesen. Tabelle ist wahrscheinlich beschädigt, siehe Fehlerlog
Fehler: 1536
SQLSTATE: HY000
(ER_EVENT_CANNOT_DELETE
)
Meldung: Löschen des Events aus mysql.event fehlgeschlagen
Fehler: 1537
SQLSTATE: HY000
(ER_EVENT_COMPILE_ERROR
)
Meldung: Fehler beim Kompilieren des Event-Bodys
Fehler: 1538
SQLSTATE: HY000
(ER_EVENT_SAME_NAME
)
Meldung: Alter und neuer Event-Name sind gleich
Fehler: 1539
SQLSTATE: HY000
(ER_EVENT_DATA_TOO_LONG
)
Meldung: Daten der Spalte '%s' zu lang
Fehler: 1540
SQLSTATE: HY000
(ER_DROP_INDEX_FK
)
Meldung: Kann Index '%s' nicht löschen: wird für einen Fremdschlüssel benötigt
Fehler: 1541
SQLSTATE: HY000
(ER_WARN_DEPRECATED_SYNTAX
)
Meldung: Die Syntax '%s' ist veraltet und wird in MySQL %s entfernt. Bitte benutzen Sie statt dessen %s
Fehler: 1542
SQLSTATE: HY000
(ER_CANT_WRITE_LOCK_LOG_TABLE
)
Meldung: Eine Log-Tabelle kann nicht schreibgesperrt werden. Es ist ohnehin nur Lesezugriff möglich
Fehler: 1543
SQLSTATE: HY000
(ER_CANT_READ_LOCK_LOG_TABLE
)
Meldung: Log-Tabellen können nicht mit normalen Lesesperren gesperrt werden. Verwenden Sie statt dessen READ LOCAL
Fehler: 1544
SQLSTATE: 23000
(ER_FOREIGN_DUPLICATE_KEY
)
Meldung: Aufrechterhalten der Fremdschlüssel-Constraints für Tabelle '%s', Eintrag '%s', Schlüssel %d würde zu einem doppelten Eintrag führen
Fehler: 1545
SQLSTATE: HY000
(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE
)
Meldung: Spaltenanzahl von mysql.%s falsch. %d erwartet, aber %d erhalten. Erzeugt mit MySQL %d, jetzt unter %d. Bitte benutzen Sie scripts/mysql_fix_privilege_tables, um den Fehler zu beheben
Fehler: 1546
SQLSTATE: HY000
(ER_REMOVED_SPACES
)
Meldung: Führende Leerzeichen werden aus dem Namen '%s' entfernt
Fehler: 1547
SQLSTATE: HY000
(ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR
)
Meldung: Kann nicht aus dem zeilenbasierten Binärlog-Format herauswechseln, wenn die Sitzung offene temporäre Tabellen hat
Fehler: 1548
SQLSTATE: HY000
(ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT
)
Meldung: Das Binärlog-Format kann innerhalb einer gespeicherten Funktion oder eines Triggers nicht geändert werden
Fehler: 1549
SQLSTATE: HY000
(ER_NDB_CANT_SWITCH_BINLOG_FORMAT
)
Meldung: Die Speicher-Engine NDB Cluster unterstützt das Ändern des Binärlog-Formats zur Laufzeit noch nicht
Fehler: 1550
SQLSTATE: HY000
(ER_PARTITION_NO_TEMPORARY
)
Meldung: Anlegen temporärer Tabellen mit Partitionen nicht möglich
Fehler: 1551
SQLSTATE: HY000
(ER_PARTITION_CONST_DOMAIN_ERROR
)
Meldung: Partitionskonstante liegt außerhalb der Partitionsfunktionsdomäne
Fehler: 1552
SQLSTATE: HY000
(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED
)
Meldung: Diese Partitionierungsfunktion ist nicht erlaubt
Fehler: 1553
SQLSTATE: HY000
(ER_DDL_LOG_ERROR
)
Meldung: Fehler im DDL-Log
Fehler: 1554
SQLSTATE: HY000
(ER_NULL_IN_VALUES_LESS_THAN
)
Meldung: In VALUES LESS THAN dürfen keine NULL-Werte verwendet werden
Fehler: 1555
SQLSTATE: HY000
(ER_WRONG_PARTITION_NAME
)
Meldung: Falscher Partitionsname
Fehler: 1556
SQLSTATE: 25001
(ER_CANT_CHANGE_TX_ISOLATION
)
Meldung: Transaktionsisolationsebene kann während einer laufenden Transaktion nicht geändert werden
Fehler: 1557
SQLSTATE: HY000
(ER_DUP_ENTRY_AUTOINCREMENT_CASE
)
Meldung: ALTER TABLE führt zur Neusequenzierung von auto_increment, wodurch der doppelte Eintrag '%s' für Schlüssel '%s' auftritt
Fehler: 1558
SQLSTATE: HY000
(ER_EVENT_MODIFY_QUEUE_ERROR
)
Meldung: Interner Scheduler-Fehler %d
Fehler: 1559
SQLSTATE: HY000
(ER_EVENT_SET_VAR_ERROR
)
Meldung: Fehler während des Startens oder Anhalten des Schedulers. Fehlercode %u
Fehler: 1560
SQLSTATE: HY000
(ER_PARTITION_MERGE_ERROR
)
Meldung: Engine kann in partitionierten Tabellen nicht verwendet werden
Fehler: 1561
SQLSTATE: HY000
(ER_CANT_ACTIVATE_LOG
)
Meldung: Kann Logdatei '%s' nicht aktivieren
Fehler: 1562
SQLSTATE: HY000
(ER_RBR_NOT_AVAILABLE
)
Meldung: The server was not built with row-based replication
Fehler: 1563
SQLSTATE: HY000
(ER_BASE64_DECODE_ERROR
)
Meldung: Der Server hat keine zeilenbasierte Replikation
Fehler: 1564
SQLSTATE: HY000
(ER_NO_TRIGGERS_ON_SYSTEM_SCHEMA
)
Meldung: Trigger können nicht auf Systemtabellen erzeugt werden
Fehler: 1565
SQLSTATE: HY000
(ER_EVENT_RECURSIVITY_FORBIDDEN
)
Meldung: Rekursivität von EVENT-DDL-Anweisungen ist unzulässig wenn ein Hauptteil (Body) existiert
Fehler: 1566
SQLSTATE: HY000
(ER_EVENTS_DB_ERROR
)
Meldung: Kann nicht weitermachen, weil die Tabellen, die von Events verwendet werden, beim Serverstart als beschädigt markiert wurden
Fehler: 1567
SQLSTATE: HY000
(ER_ONLY_INTEGERS_ALLOWED
)
Meldung: An dieser Stelle sind nur Ganzzahlen zulässig
Fehler: 1568
SQLSTATE: HY000
(ER_AUTOINC_READ_FAILED
)
Meldung: Lesen des Autoincrement-Werts von der Speicher-Engine fehlgeschlagen
Fehler: 1569
SQLSTATE: HY000
(ER_USERNAME
)
Meldung: Benutzername
Fehler: 1570
SQLSTATE: HY000
(ER_HOSTNAME
)
Meldung: Hostname
Fehler: 1571
SQLSTATE: HY000
(ER_WRONG_STRING_LENGTH
)
Meldung: String '%s' ist zu lang für %s (sollte nicht länger sein als %d)
Fehler: 1572
SQLSTATE: HY000
(ER_UNSUPORTED_LOG_ENGINE
)
Meldung: Diese Speicher-Engine kann für Logtabellen nicht verwendet werden
Fehler: 1573
SQLSTATE: HY000
(ER_BAD_LOG_STATEMENT
)
Meldung: Sie können eine Logtabelle nicht '%s', wenn Loggen angeschaltet ist
Fehler: 1574
SQLSTATE: HY000
(ER_NON_INSERTABLE_TABLE
)
Meldung: The target table %s of the %s is not insertable-into
Die Fehlermeldungen der Clients stammen aus folgenden Quelldateien:
Die Fehlermeldungen und die Symbole in Klammern entsprechen
den Definitionen in der MySQL-Quelldatei
include/errmsg.h
.
Die Texte der Fehlermeldungen befinden sich in der Datei
libmysql/errmsg.c
.
%d
und %s
stellen
Zahlen beziehungsweise Strings dar, die bei der Ausgabe der
Meldungen entsprechend ersetzt werden.
Weil die Fehlermeldungen häufig aktualisiert werden, kann es sein, dass die genannten Dateien zusätzliche Fehlermeldungen enthalten, die hier noch nicht aufgeführt sind.
Fehler: 2000
(CR_UNKNOWN_ERROR
)
Meldung: Unknown MySQL error
Fehler: 2001
(CR_SOCKET_CREATE_ERROR
)
Meldung: Can't create UNIX socket (%d)
Fehler: 2002
(CR_CONNECTION_ERROR
)
Meldung: Can't connect to local MySQL server through socket '%s' (%d)
Fehler: 2003
(CR_CONN_HOST_ERROR
)
Meldung: Can't connect to MySQL server on '%s' (%d)
Fehler: 2004
(CR_IPSOCK_ERROR
)
Meldung: Can't create TCP/IP socket (%d)
Fehler: 2005
(CR_UNKNOWN_HOST
)
Meldung: Unknown MySQL server host '%s' (%d)
Fehler: 2006
(CR_SERVER_GONE_ERROR
)
Meldung: MySQL server has gone away
Fehler: 2007
(CR_VERSION_ERROR
)
Meldung: Protocol mismatch; server version = %d, client version = %d
Fehler: 2008
(CR_OUT_OF_MEMORY
)
Meldung: MySQL client ran out of memory
Fehler: 2009
(CR_WRONG_HOST_INFO
)
Meldung: Wrong host info
Fehler: 2010
(CR_LOCALHOST_CONNECTION
)
Meldung: Localhost via UNIX socket
Fehler: 2011
(CR_TCP_CONNECTION
)
Meldung: %s via TCP/IP
Fehler: 2012
(CR_SERVER_HANDSHAKE_ERR
)
Meldung: Error in server handshake
Fehler: 2013
(CR_SERVER_LOST
)
Meldung: Lost connection to MySQL server during query
Fehler: 2014
(CR_COMMANDS_OUT_OF_SYNC
)
Meldung: Commands out of sync; you can't run this command now
Fehler: 2015
(CR_NAMEDPIPE_CONNECTION
)
Meldung: Named pipe: %s
Fehler: 2016
(CR_NAMEDPIPEWAIT_ERROR
)
Meldung: Can't wait for named pipe to host: %s pipe: %s (%lu)
Fehler: 2017
(CR_NAMEDPIPEOPEN_ERROR
)
Meldung: Can't open named pipe to host: %s pipe: %s (%lu)
Fehler: 2018
(CR_NAMEDPIPESETSTATE_ERROR
)
Meldung: Can't set state of named pipe to host: %s pipe: %s (%lu)
Fehler: 2019
(CR_CANT_READ_CHARSET
)
Meldung: Can't initialize character set %s (path: %s)
Fehler: 2020
(CR_NET_PACKET_TOO_LARGE
)
Meldung: Got packet bigger than 'max_allowed_packet' bytes
Fehler: 2021
(CR_EMBEDDED_CONNECTION
)
Meldung: Embedded server
Fehler: 2022
(CR_PROBE_SLAVE_STATUS
)
Meldung: Error on SHOW SLAVE STATUS:
Fehler: 2023
(CR_PROBE_SLAVE_HOSTS
)
Meldung: Error on SHOW SLAVE HOSTS:
Fehler: 2024
(CR_PROBE_SLAVE_CONNECT
)
Meldung: Error connecting to slave:
Fehler: 2025
(CR_PROBE_MASTER_CONNECT
)
Meldung: Error connecting to master:
Fehler: 2026
(CR_SSL_CONNECTION_ERROR
)
Meldung: SSL connection error
Fehler: 2027
(CR_MALFORMED_PACKET
)
Meldung: Malformed packet
Fehler: 2028
(CR_WRONG_LICENSE
)
Meldung: This client library is licensed only for use with MySQL servers having '%s' license
Fehler: 2029
(CR_NULL_POINTER
)
Meldung: Invalid use of null pointer
Fehler: 2030
(CR_NO_PREPARE_STMT
)
Meldung: Statement not prepared
Fehler: 2031
(CR_PARAMS_NOT_BOUND
)
Meldung: No data supplied for parameters in prepared statement
Fehler: 2032
(CR_DATA_TRUNCATED
)
Meldung: Data truncated
Fehler: 2033
(CR_NO_PARAMETERS_EXISTS
)
Meldung: No parameters exist in the statement
Fehler: 2034
(CR_INVALID_PARAMETER_NO
)
Meldung: Invalid parameter number
Fehler: 2035
(CR_INVALID_BUFFER_USE
)
Meldung: Can't send long data for non-string/non-binary data types (parameter: %d)
Fehler: 2036
(CR_UNSUPPORTED_PARAM_TYPE
)
Meldung: Using unsupported buffer type: %d (parameter: %d)
Fehler: 2037
(CR_SHARED_MEMORY_CONNECTION
)
Meldung: Shared memory: %s
Fehler: 2038
(CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR
)
Meldung: Can't open shared memory; client could not create request event (%lu)
Fehler: 2039
(CR_SHARED_MEMORY_CONNECT_ANSWER_ERROR
)
Meldung: Can't open shared memory; no answer event received from server (%lu)
Fehler: 2040
(CR_SHARED_MEMORY_CONNECT_FILE_MAP_ERROR
)
Meldung: Can't open shared memory; server could not allocate file mapping (%lu)
Fehler: 2041
(CR_SHARED_MEMORY_CONNECT_MAP_ERROR
)
Meldung: Can't open shared memory; server could not get pointer to file mapping (%lu)
Fehler: 2042
(CR_SHARED_MEMORY_FILE_MAP_ERROR
)
Meldung: Can't open shared memory; client could not allocate file mapping (%lu)
Fehler: 2043
(CR_SHARED_MEMORY_MAP_ERROR
)
Meldung: Can't open shared memory; client could not get pointer to file mapping (%lu)
Fehler: 2044
(CR_SHARED_MEMORY_EVENT_ERROR
)
Meldung: Can't open shared memory; client could not create %s event (%lu)
Fehler: 2045
(CR_SHARED_MEMORY_CONNECT_ABANDONED_ERROR
)
Meldung: Can't open shared memory; no answer from server (%lu)
Fehler: 2046
(CR_SHARED_MEMORY_CONNECT_SET_ERROR
)
Meldung: Can't open shared memory; cannot send request event to server (%lu)
Fehler: 2047
(CR_CONN_UNKNOW_PROTOCOL
)
Meldung: Wrong or unknown protocol
Fehler: 2048
(CR_INVALID_CONN_HANDLE
)
Meldung: Invalid connection handle
Fehler: 2049
(CR_SECURE_AUTH
)
Meldung: Connection using old (pre-4.1.1) authentication protocol refused (client option 'secure_auth' enabled)
Fehler: 2050
(CR_FETCH_CANCELED
)
Meldung: Row retrieval was canceled by mysql_stmt_close() call
Fehler: 2051
(CR_NO_DATA
)
Meldung: Attempt to read column without prior row fetch
Fehler: 2052
(CR_NO_STMT_METADATA
)
Meldung: Prepared statement contains no metadata
Fehler: 2053
(CR_NO_RESULT_SET
)
Meldung: Attempt to read a row while there is no result set associated with the statement
Fehler: 2054
(CR_NOT_IMPLEMENTED
)
Meldung: This feature is not implemented yet
Inhaltsverzeichnis
This appendix lists the developers, contributors, and supporters that have helped to make MySQL what it is today.
These are the developers that are or have been employed by MySQL
AB to work on the MySQL
database software,
roughly in the order they started to work with us. Following each
developer is a small list of the tasks that the developer is
responsible for, or the accomplishments they have made. All
developers are involved in support.
Michael (Monty) Widenius
Lead developer and main author of the MySQL server (mysqld).
New functions for the string library.
Most of the mysys
library.
The ISAM
and MyISAM
libraries (B-tree index file handlers with index
compression and different record formats).
The HEAP
library. A memory table system
with our superior full dynamic hashing. In use since 1981
and published around 1984.
The replace program (take a look at it, it's COOL!).
Connector/ODBC (MyODBC), the ODBC driver for Windows.
Fixing bugs in MIT-pthreads to get it to work for MySQL Server. And also Unireg, a curses-based application tool with many utilities.
Porting of mSQL
tools like
msqlperl
,
DBD
/DBI
, and
DB2mysql
.
Most of crash-me
and the foundation for
the MySQL benchmarks.
David Axmark
Initial main writer of the Reference Manual, including enhancements to texi2html.
Automatic Web site updating from the manual.
Initial Autoconf, Automake, and Libtool support.
Licensing.
Parts of all the text files. (Nowadays only the
README
is left. The rest ended up in
the manual.)
Lots of testing of new features.
Our in-house Free Software legal expert.
Mailing list maintainer (who never has the time to do it right...).
Our original portability code (now more than 10 years
old). Nowadays only some parts of mysys
are left.
Someone for Monty to call in the middle of the night when he just got that new feature to work.
Chief "Open Sourcerer" (MySQL community relations).
Jani Tolonen
mysqlimport
A lot of extensions to the command-line clients.
PROCEDURE ANALYSE()
Sinisa Milivojevic (now in support)
Compression (with zlib
) in the
client/server protocol.
Perfect hashing for the lexical analyzer phase.
Multi-row INSERT
mysqldump -e option
LOAD DATA LOCAL INFILE
SQL_CALC_FOUND_ROWS
SELECT
option
--max-user-connections=...
option
net_read
and
net_write_timeout
GRANT
/REVOKE
and
SHOW GRANTS FOR
New client/server protocol for 4.0
UNION
in 4.0
Multiple-table
DELETE
/UPDATE
Subqueries in the FROM
clause (4.1).
User resources management
Initial developer of the MySQL++
C++
API and the MySQLGUI
client.
Tonu Samuel (past developer)
VIO interface (the foundation for the encrypted client/server protocol).
MySQL Filesystem (a way to use MySQL databases as files and directories).
The CASE
expression.
The MD5()
and
COALESCE()
functions.
RAID
support for
MyISAM
tables.
Sasha Pachev (past developer)
Initial implementation of replication (up to version 4.0).
SHOW CREATE TABLE
.
mysql-bench
Matt Wagner
MySQL test suite.
Webmaster (until 2002).
Miguel Solorzano (now in support)
Win32 development and release builds.
Windows NT server code.
WinMySQLAdmin
Timothy Smith (now in support)
Dynamic character sets support.
configure, RPMs and other parts of the build system.
Initial developer of libmysqld
, the
embedded server.
Sergei Golubchik
Full-text search.
Added keys to the MERGE
library.
Precision math.
Jeremy Cole (past developer)
Proofreading and editing this fine manual.
ALTER TABLE ... ORDER BY ...
.
UPDATE ... ORDER BY ...
.
DELETE ... ORDER BY ...
.
Indrek Siitan
Designing/programming of our Web interface.
Author of our newsletter management system.
Jorge del Conde (now in support)
MySQLCC (MySQL Control Center)
Win32 development
Initial implementation of the Web site portals.
Venu Anuganti (past developer)
MyODBC 3.51
New client/server protocol for 4.1 (for prepared statements).
Arjen Lentz (now handling community)
Maintainer of the MySQL Reference Manual.
Preparing the O'Reilly printed edition of the manual.
Alexander (Bar) Barkov, Alexey (Holyfoot) Botchkov, and Ramil Kalimullin
Spatial data (GIS) and R-Trees implementation for 4.1
Unicode and character sets for 4.1; documentation for same
Oleksandr (Sanja) Byelkin
Query cache in 4.0
Implementation of subqueries (4.1).
Implementation of views (5.0).
Aleksey (Walrus) Kishkin and Alexey (Ranger) Stroganov
Benchmarks design and analysis.
Maintenance of the MySQL test suite.
Zak Greant (past employee)
Open Source advocate, MySQL community relations.
Carsten Pedersen
The MySQL Certification program.
Lenz Grimmer
Production (build and release) engineering.
Peter Zaitsev
SHA1()
,
AES_ENCRYPT()
and
AES_DECRYPT()
functions.
Debugging, cleaning up various features.
Alexander (Salle) Keremidarski
Support.
Debugging.
Per-Erik Martin
Lead developer for stored procedures (5.0).
Jim Winstead
Former lead Web developer.
Improving server, fixing bugs.
Mark Matthews
Connector/J driver (Java).
Peter Gulutzan
SQL standards compliance.
Documentation of existing MySQL code/algorithms.
Character set documentation.
Guilhem Bichot
Replication, from MySQL
version 4.0.
Fixed handling of exponents for
DECIMAL
.
Author of mysql_tableinfo
.
Backup (in 5.1).
Antony T. Curtis
Porting of the MySQL Database software to OS/2.
Mikael Ronstrom
Much of the initial work on NDB Cluster until 2000. Roughly half the code base at that time. Transaction protocol, node recovery, system restart and restart code and parts of the API functionality.
Lead Architect, developer, debugger of NDB Cluster 1994-2004
Lots of optimizations
Jonas Oreland
On-line Backup
The automatic test environment of MySQL Cluster
Portability Library for NDB Cluster
Lots of other things
Pekka Nouisiainen
Ordered index implementation of MySQL Cluster
BLOB support in MySQL Cluster
Charset support in MySQL Cluster
Martin Skold
Unique index implementation of MySQL Cluster
Integration of NDB Cluster into MySQL
Magnus Svensson
The test framework for MySQL Cluster
Integration of NDB Cluster into MySQL
Tomas Ulin
Lots of work on configuration changes for simple installation and use of MySQL Cluster
Konstantin Osipov
Prepared statements.
Cursors.
Dmitri Lenev
Time zone support.
Triggers (in 5.0).
Although MySQL AB owns all copyrights in the MySQL
server
and the MySQL manual
, we wish
to recognize those who have made contributions of one kind or
another to the MySQL distribution
. Contributors
are listed here, in somewhat random order:
Gianmassimo Vigazzola <qwerg@mbox.vol.it>
or
<qwerg@tin.it>
The initial port to Win32/NT.
Per Eric Olsson
For more or less constructive criticism and real testing of the dynamic record format.
Irena Pancirov <irena@mail.yacc.it>
Win32 port with Borland compiler.
mysqlshutdown.exe
and
mysqlwatch.exe
David J. Hughes
For the effort to make a shareware SQL database. At TcX, the
predecessor of MySQL AB, we started with
mSQL
, but found that it couldn't satisfy
our purposes so instead we wrote an SQL interface to our
application builder Unireg. mysqladmin and
mysql client are programs that were largely
influenced by their mSQL
counterparts. We
have put a lot of effort into making the MySQL syntax a
superset of mSQL
. Many of the API's ideas
are borrowed from mSQL
to make it easy to
port free mSQL
programs to the MySQL API.
The MySQL software doesn't contain any code from
mSQL
. Two files in the distribution
(client/insert_test.c
and
client/select_test.c
) are based on the
corresponding (non-copyrighted) files in the
mSQL
distribution, but are modified as
examples showing the changes necessary to convert code from
mSQL
to MySQL Server.
(mSQL
is copyrighted David J. Hughes.)
Patrick Lynch
For helping us acquire http://www.mysql.com/.
Fred Lindberg
For setting up qmail to handle the MySQL mailing list and for the incredible help we got in managing the MySQL mailing lists.
Igor Romanenko <igor@frog.kiev.ua>
mysqldump (previously
msqldump
, but ported and enhanced by
Monty).
Yuri Dario
For keeping up and extending the MySQL OS/2 port.
Tim Bunce
Author of mysqlhotcopy.
Zarko Mocnik <zarko.mocnik@dem.si>
Sorting for Slovenian language.
"TAMITO" <tommy@valley.ne.jp>
The _MB
character set macros and the ujis
and sjis character sets.
Joshua Chamas <joshua@chamas.com>
Base for concurrent insert, extended date syntax, debugging on NT, and answering on the MySQL mailing list.
Yves Carlier <Yves.Carlier@rug.ac.be>
mysqlaccess, a program to show the access rights for a user.
Rhys Jones <rhys@wales.com>
(And GWE Technologies
Limited)
For one of the early JDBC drivers.
Dr Xiaokun Kelvin ZHU <X.Zhu@brad.ac.uk>
Further development of one of the early JDBC drivers and other MySQL-related Java tools.
James Cooper <pixel@organic.com>
For setting up a searchable mailing list archive at his site.
Rick Mehalick <Rick_Mehalick@i-o.com>
For xmysql
, a graphical X client for MySQL
Server.
Doug Sisk <sisk@wix.com>
For providing RPM packages of MySQL for Red Hat Linux.
Diemand Alexander V. <axeld@vial.ethz.ch>
For providing RPM packages of MySQL for Red Hat Linux-Alpha.
Antoni Pamies Olive <toni@readysoft.es>
For providing RPM versions of a lot of MySQL clients for Intel and SPARC.
Jay Bloodworth <jay@pathways.sde.state.sc.us>
For providing RPM versions for MySQL 3.21.
David Sacerdote <davids@secnet.com>
Ideas for secure checking of DNS hostnames.
Wei-Jou Chen <jou@nematic.ieo.nctu.edu.tw>
Some support for Chinese(BIG5) characters.
Wei He <hewei@mail.ied.ac.cn>
A lot of functionality for the Chinese(GBK) character set.
Jan Pazdziora <adelton@fi.muni.cz>
Czech sorting order.
Zeev Suraski <bourbon@netvision.net.il>
FROM_UNIXTIME()
time formatting,
ENCRYPT()
functions, and
bison advisor. Active mailing list member.
Luuk de Boer <luuk@wxs.nl>
Ported (and extended) the benchmark suite to
DBI
/DBD
. Have been of
great help with crash-me
and running
benchmarks. Some new date functions. The
mysql_setpermission script.
Alexis Mikhailov <root@medinf.chuvashia.su>
User-defined functions (UDFs); CREATE
FUNCTION
and DROP FUNCTION
.
Andreas F. Bobak <bobak@relog.ch>
The AGGREGATE
extension to user-defined
functions.
Ross Wakelin <R.Wakelin@march.co.uk>
Help to set up InstallShield for MySQL-Win32.
Jethro Wright III <jetman@li.net>
The libmysql.dll
library.
James Pereria <jpereira@iafrica.com>
Mysqlmanager, a Win32 GUI tool for administering MySQL Servers.
Curt Sampson <cjs@portal.ca>
Porting of MIT-pthreads to NetBSD/Alpha and NetBSD 1.3/i386.
Martin Ramsch <m.ramsch@computer.org>
Examples in the MySQL Tutorial.
Steve Harvey
For making mysqlaccess more secure.
Konark IA-64 Centre of Persistent Systems Private Limited
http://www.pspl.co.in/konark/. Help with the Win64 port of the MySQL server.
Albert Chin-A-Young.
Configure updates for Tru64, large file support and better TCP wrappers support.
John Birrell
Emulation of pthread_mutex()
for OS/2.
Benjamin Pflugmann
Extended MERGE
tables to handle
INSERTS
. Active member on the MySQL mailing
lists.
Jocelyn Fournier
Excellent spotting and reporting innumerable bugs (especially in the MySQL 4.1 subquery code).
Marc Liyanage
Maintaining the Mac OS X packages and providing invaluable feedback on how to create Mac OS X PKGs.
Robert Rutherford
Providing invaluable information and feedback about the QNX port.
Previous developers of NDB Cluster
Lots of people were involved in various ways summer students, master thesis students, employees. In total more than 100 people so too many to mention here. Notable name is Ataullah Dabaghi who up until 1999 contributed around a third of the code base. A special thanks also to developers of the AXE system which provided much of the architectural foundations for NDB Cluster with blocks, signals and crash tracing functionality. Also credit should be given to those who believed in the ideas enough to allocate of their budgets for its development from 1992 to present time.
Other contributors, bugfinders, and testers: James H. Thompson,
Maurizio Menghini, Wojciech Tryc, Luca Berra, Zarko Mocnik, Wim
Bonis, Elmar Haneke, <jehamby@lightside>
,
<psmith@BayNetworks.com>
,
<duane@connect.com.au>
, Ted Deppner
<ted@psyber.com>
, Mike Simons, Jaakko Hyvatti.
And lots of bug report/patches from the folks on the mailing list.
A big tribute goes to those that help us answer questions on the MySQL mailing lists:
Daniel Koch <dkoch@amcity.com>
Irix setup.
Luuk de Boer <luuk@wxs.nl>
Benchmark questions.
Tim Sailer <tps@users.buoy.com>
DBD::mysql
questions.
Boyd Lynn Gerber <gerberb@zenez.com>
SCO-related questions.
Richard Mehalick <RM186061@shellus.com>
xmysql
-related questions and basic
installation questions.
Zeev Suraski <bourbon@netvision.net.il>
Apache module configuration questions (log & auth), PHP-related questions, SQL syntax-related questions and other general questions.
Francesc Guasch <frankie@citel.upc.es>
General questions.
Jonathan J Smith <jsmith@wtp.net>
Questions pertaining to OS-specifics with Linux, SQL syntax, and other things that might need some work.
David Sklar <sklar@student.net>
Using MySQL from PHP and Perl.
Alistair MacDonald <A.MacDonald@uel.ac.uk>
Is flexible and can handle Linux and perhaps HP-UX. Tries to get users to use mysqlbug.
John Lyon <jlyon@imag.net>
Questions about installing MySQL on Linux systems, using
either .rpm
files or compiling from
source.
Lorvid Ltd. <lorvid@WOLFENET.com>
Simple billing/license/support/copyright issues.
Patrick Sherrill <patrick@coconet.com>
ODBC and VisualC++ interface questions.
Randy Harmon <rjharmon@uptimecomputers.com>
DBD
, Linux, some SQL syntax questions.
The following people have helped us with writing the MySQL documentation and translating the documentation or error messages in MySQL.
Paul DuBois
Ongoing help with making this manual correct and understandable. That includes rewriting Monty's and David's attempts at English into English as other people know it.
Kim Aldale
Helped to rewrite Monty's and David's early attempts at English into English.
Michael J. Miller Jr.
<mke@terrapin.turbolift.com>
For the first MySQL manual. And a lot of spelling/language fixes for the FAQ (that turned into the MySQL manual a long time ago).
Yan Cailin
First translator of the MySQL Reference Manual into simplified Chinese in early 2000 on which the Big5 and HK coded (http://mysql.hitstar.com/) versions were based. Personal home page at linuxdb.yeah.net.
Jay Flaherty <fty@mediapulse.com>
Big parts of the Perl
DBI
/DBD
section in the
manual.
Paul Southworth <pauls@etext.org>
, Ray Loyzaga
<yar@cs.su.oz.au>
Proof-reading of the Reference Manual.
Therrien Gilbert <gilbert@ican.net>
, Jean-Marc
Pouyot <jmp@scalaire.fr>
French error messages.
Petr Snajdr, <snajdr@pvt.net>
Czech error messages.
Jaroslaw Lewandowski <jotel@itnet.com.pl>
Polish error messages.
Miguel Angel Fernandez Roiz
Spanish error messages.
Roy-Magne Mo <rmo@www.hivolda.no>
Norwegian error messages and testing of MySQL 3.21.xx.
Timur I. Bakeyev <root@timur.tatarstan.ru>
Russian error messages.
<brenno@dewinter.com>
& Filippo Grassilli
<phil@hyppo.com>
Italian error messages.
Dirk Munzinger <dirk@trinity.saar.de>
German error messages.
Billik Stefan <billik@sun.uniag.sk>
Slovak error messages.
Stefan Saroiu <tzoompy@cs.washington.edu>
Romanian error messages.
Peter Feher
Hungarian error messages.
Roberto M. Serqueira
Portuguese error messages.
Carsten H. Pedersen
Danish error messages.
Arjen G. Lentz
Dutch error messages, completing earlier partial translation (also work on consistency and spelling).
The following is a list of the creators of the libraries we have included with the MySQL server source to make it easy to compile and install MySQL. We are very thankfully to all individuals that have created these and it has made our life much easier.
Fred Fish
For his excellent C debugging and trace library. Monty has made a number of smaller improvements to the library (speed and additional options).
Richard A. O'Keefe
For his public domain string library.
Henry Spencer
For his regex library, used in WHERE column REGEXP
regexp
.
Chris Provenzano
Portable user level pthreads. From the copyright: This product
includes software developed by Chris Provenzano, the
University of California, Berkeley, and contributors. We are
currently using version 1_60_beta6 patched by Monty (see
mit-pthreads/Changes-mysql
).
Jean-loup Gailly and Mark Adler
For the zlib library (used on MySQL on Windows).
Bjorn Benson
For his safe_malloc (memory checker) package which is used in
when you configure MySQL with --debug
.
Free Software Foundation
The readline
library (used by the
mysql command-line client).
The NetBSD foundation
The libedit
package (optionally used by the
mysql command-line client).
The following is a list of creators/maintainers of some of the most important API/packages/applications that a lot of people use with MySQL.
We can't list every possible package here because the list would then be way to hard to maintain. For other packages, please refer to the software portal at http://solutions.mysql.com/software/.
Tim Bunce, Alligator Descartes
For the DBD
(Perl) interface.
Andreas Koenig <a.koenig@mind.de>
For the Perl interface for MySQL Server.
Jochen Wiedmann <wiedmann@neckar-alb.de>
For maintaining the Perl DBD::mysql
module.
Eugene Chan <eugene@acenet.com.sg>
For porting PHP for MySQL Server.
Georg Richter
MySQL 4.1 testing and bug hunting. New PHP 5.0
mysqli
extension (API) for use with MySQL
4.1 and up.
Giovanni Maruzzelli <maruzz@matrice.it>
For porting iODBC (Unix ODBC).
Xavier Leroy <Xavier.Leroy@inria.fr>
The author of LinuxThreads (used by the MySQL Server on Linux).
The following is a list of some of the tools we have used to create MySQL. We use this to express our thanks to those that has created them as without these we could not have made MySQL what it is today.
Free Software Foundation
From whom we got an excellent compiler
(gcc), an excellent debugger
(gdb and the libc
library (from which we have borrowed
strto.c
to get some code working in
Linux).
Free Software Foundation & The XEmacs development team
For a really great editor/environment used by almost everybody at MySQL AB.
Julian Seward
Author of valgrind
, an excellent memory
checker tool that has helped us find a lot of otherwise hard
to find bugs in MySQL.
Dorothea Lütkehaus and Andreas Zeller
For DDD
(The Data Display Debugger) which
is an excellent graphical front end to
gdb).
Although MySQL AB owns all copyrights in the MySQL
server
and the MySQL manual
, we wish
to recognize the following companies, which helped us finance the
development of the MySQL server
, such as by
paying us for developing a new feature or giving us hardware for
development of the MySQL server
.
VA Linux / Andover.net
Funded replication.
NuSphere
Editing of the MySQL manual.
Stork Design studio
The MySQL Web site in use between 1998-2000.
Intel
Contributed to development on Windows and Linux platforms.
Compaq
Contributed to Development on Linux/Alpha.
SWSoft
Development on the embedded mysqld version.
FutureQuest
--skip-show-database
Inhaltsverzeichnis
This appendix lists the changes from version to version in the MySQL source code through the latest version of MySQL 5.1, which is currently MySQL 5.1.5-alpha. Starting with MySQL 5.0, we began offering a new version of the Manual for each new series of MySQL releases (5.0, 5.1, and so on). For information about changes in previous release series of the MySQL database software, see the corresponding version of this Manual. For information about legacy versions of the MySQL software through the 4.1 series, see MySQL-Referenzhandbuch für die Versionen 3.23, 4.0 und 4.1.
We update this section as we add new features in the 5.1 series, so that everybody can follow the development process.
Note that we tend to update the manual at the same time we make changes to MySQL. If you find a recent version of MySQL listed here that you can't find on our download page (http://dev.mysql.com/downloads/), it means that the version has not yet been released.
The date mentioned with a release version is the date of the last BitKeeper ChangeSet on which the release was based, not the date when the packages were made available. The binaries are usually made available a few days after the date of the tagged ChangeSet, because building and testing all packages takes some time.
The manual included in the source and binary distributions may not be fully accurate when it comes to the release changelog entries, because the integration of the manual happens at build time. For the most up-to-date release changelog, please refer to the online version instead.
The following changelog shows what has been done in the 5.1 tree:
MySQL 5.1 enables table partitioning with a selection of
partitioning algorithms and options available, independently of
the storage engine used by the table. Syntactically, this
implements a number of new extensions to the CREATE
TABLE
, ALTER TABLE
, and
EXPLAIN ... SELECT
statements. See
Kapitel 17, Partitionierung.
MySQL 5.1 implements support for a plugin API that allows the loading and unloading of components at runtime, without restarting the server. See Abschnitt 26.2, „Die MySQL-Plug-In-Schnittstelle“.
For a full list of changes, please refer to the changelog sections for each individual 5.1.x release.
Functionality added or changed:
Incompatible change: This
release introduced the TRIGGER
privilege.
Previously, the SUPER
privilege was needed
to create or drop triggers. Now those operations require the
TRIGGER
privilege. This is a security
improvement because you no longer need to grant users the
SUPER
privilege to enable them to create
triggers. However, the requirement that the account named in a
trigger's DEFINER
clause must have the
SUPER
privilege has changed to a
requirement for the TRIGGER
privilege. You
should check which accounts are named in the
DEFINER
clause of existing triggers and
make sure that those accounts have the
TRIGGER
privilege. Otherwise, they will
fail when activated. (Bug#9142)
Incompatible change: Due to a
change in the naming scheme for partitioning and
subpartitioning files, it is not possible for the server to
read partitioned tables created in previous MySQL versions. A
suggested workaround is (1) to create a non-partitioned table
with the same table schema using a standard CREATE
TABLE
statement (that is, with no partitioning
clauses) and then (2) to issue aSELECT INTO
to copy the data into the non-partitioned table before the
upgrade; following the upgrade, you can partition the new
table using ALTER TABLE ... PARTITION BY
...
. Alternatively, you can dump the table using
mysqldump prior to upgrading and reload it
afterwards with LOAD DATA
. In either case,
you should drop the pre-5.1.6 partitioned tables before
upgrading to 5.1.6 or later. (Bug#13437)
Important: If any partitioned
tables that were created prior to MySQL 5.1.6 are present
following an upgrade to MySQL 5.1.6 or later, it is also not
possible to read from the
INFORMATION_SCHEMA.PARTITIONS
table, nor
will you be able to drop those tables or the database or
databases in which they are located. In this event, you must:
(1) shut down mysqld; (2) manually delete
the table, partition, and (if any) subpartition files; and
then (3) restart the MySQL Server. (Bug#16695)
Incompatible change: Words
with apostrophes are now matched in a FULLTEXT search against
non-apostrophe words (for example, a search for
Jerry
will match against the term
Jerry's
). Users upgrading to this version
must issue REPAIR TABLE
statements for
tables containing FULLTEXT
indexes. (Bug#14194)
The mysqldump utility now supports an
option for dumping tablespaces. Use -Y
or
--all-tablespaces
to enable this
functionality. (Bug#16753)
Partition support is not an „engine“, but it was
included in the output of SHOW ENGINES
. Now
it is not. (Bug#14355) The
have_partition_engine
was renamed to
have_partitioning
. (Bug#16718)
ANALYZE TABLE
is now supported for
partitioned tables. (Bug#13441)
Added the --both-log-formats
and
--old-log-format
options for controlling
whether log files or log tables are used. variable.
Added the character_set_filesystem
system
variable.
Added the event_scheduler
system variable.
Added the ndb_extra_logging
system
variable.
Added the EVENTS
table to
INFORMATION_SCHEMA
.
Added the PARTITIONS
table to
INFORMATION_SCHEMA
.
The ARCHIVE
storage engine supports the
AUTO_INCREMENT
column attribute and the
AUTO_INCREMENT
table option.
Abschnitt 14.8, „Die ARCHIVE
-Speicher-Engine“.
Fixed a crash when fulltext search parser plugin returned more words than half of the length (in bytes) of the query string. (Bug#16722)
Bugs fixed:
MYSQL_OPT_RECONNECT
option was modified by
calls to the mysql_real_connect()
function. (Bug#15719)
Specifying a value for --tmptable
without a
trailing slash had unpredictable results. (Bug#15904)
Attempting to insert data into a partitioned table that used
the BLACKHOLE
storage engine caused
mysqld to crash. (Bug#14524)
Using RANGE
partitioning with a
CASE
statement as the partitioning function
would cause records to be placed in the wrong partition. (Bug#15393)
ALTER TABLE ... ADD PARTITIONS
on a table
with one partition crashed the server. (Bug#15820)
NDB Cluster returned incorrect Can't find
file
error for OS error 24, changed to Too
many open files
. (Bug#15020)
Multi-byte path names for LOAD DATA
and
SELECT ... INTO OUTFILE
caused errors. (Bug#12448)
Certain subqueries where the inner query is the result of a aggregate function would return different results on MySQL 5.0 than on MySQL 4.1. (Bug#15347)
Error message for specifying value for which no partition exists returned wrong values on certain platforms. (Bug#15910)
Certain Japanese table names were not properly saved during a
CREATE TABLE
statement. (Bug#3906)
NDB Cluster leaked disk space when performing INSERTS/DELETES in a loop. (Bug#16771)
NDB Cluster returned wrong error when tablespace on disk was full. (Bug#16738)
The DATA DIRECTORY
and INDEX
DIRECTORY
clauses of a CREATE
TABLE
statement involving partitions did not work.
(Bug#14354)
Subselect could return wrong results when records cache and grouping was involved. (Bug#15347)
In some cases the query optimizer did not properly perform multiple joins where inner joins followed left joins, resulting in corrupted result sets. (Bug#15633)
The absence of a table in the left part of a left or right join was not checked prior to name resolution, which resulted in a server crash. (Bug#15538)
NDB Cluster
: Trying to import too many
dumped tables requiring resources beyond those allocated in
the cluster configuration would cause the server to crash
instead of reporting an insufficient resources error. (Bug#16455)
NDB Cluster
(Disk Data): Tablespaces
created using parameters with relatively low values (< 10
MB) produced filesizes much smaller than expected. (Bug#16742)
NDB Cluster
: CREATE
TABLESPACE
statements were incorrectly parsed on
64-bit platforms. (INITIAL SIZE
worked, but
size
INITIAL SIZE =
failed.) (Bug#13556)
size
Trying to add more than one partition in a single
ALTER TABLE ... ADD PARTITION
statement
caused the server to crash. (Bug#16534)
Creating a partitioned table using a storage engine other than the session default storage engine caused the server to crash. (Bug#15966)
An ALTER TABLE ... PARTITION BY ...
statement did not have any effect. (Bug#15523)
NDBCluster
(Disk Data): The error message
generated by a failed ADD UNDOFILE
did not
provide any reasons for the failure. (Bug#16267)
NDBCluster
(Disk Data): DROP
LOGFILE GROUP
corrupted the cluster file system and
caused ndbd to fail when running more than
one node on the same system. (Bug#16193)
NDBCluster
: A bitfield whose offset and
length totaled 32 would crash the cluster. (Bug#16125)
NDBCluster
: Upon the completion of a scan
where a key request remained outstanding on the primary
replica and a starting node died, the scan did not terminate.
This caused incompleted error handling of the failed node.
(Bug#15908)
NDBCluster
: The
ndb_autodiscover
test failed sporadically
due to a node not being permitted to connect to the cluster.
(Bug#15619)
Using mysqldump to obtain a dump of a
partitioned table employing the NDB
storage
engine produced a non-functional table creation statement.
(Bug#13155)
SHOW CREATE TABLE
did not display the
PARTITIONS
clause for tables partitioned by
HASH
or KEY
. (Bug#14327)
Inserting a negative value into an integer column used as the
partitioning key for a table partitioned by
HASH
could cause the server to crash. (Bug#15968)
With a table partitioned by LIST
, inserting
a value which was smaller than any value shown in the
partitioning value-lists could cause the server to crash. (Bug#14365)
ALTER TABLE ... DROP PARTITION
would
truncate all DATE
column values in the
table's remaining partitions to NULL
. (Bug#13644)
ALTER TABLE ... ADD PARTITION
could crash
the server or cause an Out of memory
error in some circumstances. (Bug#13447)
The server would allow foreign keys to be declared in the definition of a partitioned table despite the fact that partitioned tables do not support foreign keys (see Abschnitt 17.4, „Beschränkungen und Grenzen der Partitionierung“). (Bug#13446)
A SELECT
from a key-partitioned table with
a multi-column key could cause the server to crash. (Bug#13445)
Issuing a TRUNCATE
statement twice in
succession on the same partitioned table would cause the
server to crash. (Bug#13442)
Using a REPLACE
statement on a partitioned
table caused the server to crash. (Bug#13440)
Using an identifier rather than a literal integer value in the
LESS THAN
clause of a range-partitioned
table could cause the server to crash and corruption of
tables. (Bug#13439)
Using ENGINE=...
within a
PARTITION
clause could cause the server to
crash. (Bug#13438)
CREATE TABLE ... LIKE
did not work if the
table whose schema was to be copied was a partitoned table.
(Bug#13435)
SHOW CREATE TABLE
did not display the
PARTITIONS
clause for tables partitioned by
HASH
or KEY
. (Bug#14327)
Certain permission management statements could create a
NULL
hostname for a user, resulting in a
server crash. (Bug#15598)
Temporary table aliasing did not work inside stored functions. (Bug#12198)
Parallel builds occasionally failed on Solaris. (Bug#16282)
Functionality added or changed:
Added the INFORMATION_SCHEMA ENGINES
table.
Added the INFORMATION_SCHEMA PLUGINS
table
and the SHOW PLUGIN
statement.
Added the binlog_format
system variable
that controls whether to use row-based or statement-based
binary logging. Added the --binlog-format
and
--binlog-row-event-max-size
server options
for binary logging control. See
Abschnitt 6.3, „Zeilenbasierte Replikation“.
Plugins now can have status variables that are displayed in
the output from SHOW STATUS
.
Added the XML functions ExtractValue()
and
UpdateXML()
.
ExtractValue()
returns the content of a
fragment of XML matching a given XPath expression.
UpdateXML()
replaces the element selected
from a fragment of XML by an XPath expression supplied by the
user with a second XML fragment (also user-supplied), and
returns the modified XML. See Abschnitt 12.9, „XML-Funktionen“.
Added the --base64-output
option to
mysqlbinlog to print all binary log entries
using base64 encoding. This is for debugging only. Logs
produced using this option should not be applied on production
systems.
Added the --port-open-timeout
option to
mysqld to control how many seconds the
server should wait for the TCP/IP port to become free if it
cannot be opened. (Bug#15591)
Two new Hungarian collations are included:
utf8_hungarian_ci
and
ucs2_hungarian_ci
. These support the
correct sort order for Hungarian vowels. However, they do not
support the correct order for sorting Hungarian consonant
contractions; this issue will be fixed in a future release.
Bugs fixed:
InnoDB
: An UPDATE
statement with no index column in the WHERE
condition locked all the rows in the table. (Bug#3300)
INSERT DELAYED
caused
mysqld to crash. (Bug#16095)
The output of mysqldump --triggers did not
contain the DEFINER
clause in dumped
trigger definitions. (Bug#15110)
The output of SHOW TRIGGERS
contained
extraneous whitespace. (Bug#15103)
An INSERT ... SELECT
statement between
tables in a MERGE
set can return errors
when statement involves insert into child table from merge
table or vice-versa. (Bug#5390)
A COMMIT
statement followed by a
ALTER TABLE
statement on a BDB table caused
server crash. (Bug#14212)
InnoDB
: Comparison of indexed
VARCHAR CHARACTER SET ucs2 COLLATE ucs2_bin
columns using LIKE
could fail. (Bug#14583)
Creating a trigger caused a server crash if the table or trigger database was not known because no default database had been selected. (Bug#14863)
Issuing a DROP USER
command could cause
some users to encounter a
error. (Bug#15775)
hostname
is not allowed to
connect to this MySQL server
The --plugin_dir
option was not working. Also
fix error with specifying parser name for fulltext. (Bug#16068)
Attempting to insert into a table partitioned by
LIST
a value less than any specified in one
of the table's partition definitions resulted in a server
crash. In such cases, mysqld now returns
ERROR 1500 (HY000): Table has no partition for
value v
, where
v
is the out-of-range value. (Bug#15819)
Functionality added or changed:
Added the mysqlslap program, which is designed to emulate client load for a MySQL server and report the timing of each stage. It works as if multiple clients are accessing the server.
Added the --server-id
option to
mysqlbinlog to enable only those events
created by the server having the given server ID to be
extracted. (Bug#15485)
It is now possible to build the server such that
MyISAM
tables can support up to 128 keys
rather than the standard 64. This can be done by configuring
the build using the option
--with-max-indexes=
,
where N
N
≤128 is the maximum
number of indexes to permit per table. (Bug#10932)
The bundled BDB
library was upgraded to
version 4.4.16.
Added the cp1250_polish_ci
collation for
the cp1250
character set.
Added the myisam_use_mmap
system variable.
Added the --bdb-data-direct
and
--bdb-log-direct
server options.
Bugs fixed:
Server could not be built on default Debian systems with BDB enabled. (Bug#15734)
BDB
: A DELETE
,
INSERT
, or UPDATE
of a
BDB
table could cause the server to crash
where the query contained a subquery using an index read. (Bug#15536)
A left join on a column that having a NULL
value could cause the server to crash. (Bug#15268)
It was not possible to reorganize a partition reusing a discarded partition name.
Now, for example, you can create a table such as this one:
CREATE TABLE t1 (a INT) PARTITION BY RANGE (a) ( PARTITION p0 VALUES LESS THAN (10), PARTITION p1 VALUES LESS THAN (20), PARTITION p2 VALUES LESS THAN MAXVALUE );
and then repartition it as shown here:
ALTER TABLE t1 REORGANIZE PARTITION p2 INTO ( PARTITION p2 VALUES LESS THAN (30) );
Previously, attempting to do so would produce the error All partitions must have unique names in the table . (Bug#15521)
NDB Cluster
: The --ndb
option for perror did not function. (Bug#15486)
The BLACKHOLE
storage engine did not handle
transactions properly: Rolled-back transactions were written
to the binary log. Now they ae not. (Bug#15406)
NDB Cluster
: Using ORDER BY
when
selecting from a table having the primary key on a
primary_key_column
VARCHAR
column caused a forced shutdown of
the cluster. (Bug#14828, Bug#15240, Bug#15682, Bug#15517)
ANALYZE TABLE
did not properly update table
statistics for a MyISAM
table with a
FULLTEXT
index containing stopwords, so a
subsequent ANALYZE TABLE
would not
recognize the table as having already been analyzed. (Bug#14902)
The maximum value of MAX_ROWS
was handled
incorrectly on 64-bit systems. (Bug#14155)
Multiple-table update operations were counting updates and not updated rows. As a result, if a row had several updates it was counted several times for the „rows matched“ value but updated only once. (Bug#15028)
SELECT
queries that began with an opening
parenthesis were not being placed in the query cache. (Bug#14652)
Space truncation was being ignored when inserting into
BINARY
or VARBINARY
columns. Now space truncation results in a warning, or an
error in strict mode. (Bug#14299)
Selecting from a view processed with the temptable algorithm caused a server crash if the query cache was enabled. (Bug#15119)
Creating a view that referenced a stored function that selected from a view caused a crash upon selection from the view. (Bug#15096)
Creating a view within a stored procedure could result in an out of memory error or a server crash. (Bug#14885)
SHOW CREATE DATABASE
was sometimes refused
when the client had privileges for the database. (Bug#9785)
mysql ignored the
MYSQL_TCP_PORT
environment variable. (Bug#5792)
ROW_COUNT()
returned an incorrect result
after EXECUTE
of a prepared statement. (Bug#14956)
Invalid casts to DATE
values now result in
a message of Incorrect datetime value
,
rather than Truncated incorrect datetime
value
. (Bug#8294)
Attempts to assign NULL
to a NOT
NULL
column in strict mode now result in a message
of Column '
, rather than col_name
'
cannot be nullColumn set to
default value; NULL supplied to NOT NULL column
'
. (Bug#11491)
col_name
' at row
n
For binary string data types, mysqldump
--hex-blob produced an illegal output value of
0x
rather than ''
. (Bug#13318)
Some comparisons for the IN()
operator were
inconsistent with equivalent comparisons for the
=
operator. (Bug#12612)
Functionality added or changed:
This is the first public alpha release of the current MySQL 5.1 development branch, providing an insight to upcoming features. Although some of these are still under heavy development, this release includes the following new features and changes (in comparison to the current MySQL 5.0 production release):
Partitioning: allows distributing portions of individual tables across a filesystem, according to rules which can be set when the table is created. In effect, different portions of a table are stored as separate tables in different locations, but from the user point of view, the partitioned table is still a single table. See Kapitel 17, Partitionierung, for further information on this functionality. (Author: Mikael Ronström)
Plugin API: MySQL 5.1 adds support for a very flexible plugin API that enables loading and unloading of various components at runtime, without restarting the server. Although the work on this is not finished yet, plugin full-text parsers are a first step in this direction. This allows users to implement their own input filter on the indexed text, enabling full-text search capability on arbitrary data such as PDF files or other document formats. A pre-parser full-text plugin performs the actual parsing and extraction of the text and hands it over to the built-in MySQL full-text search. (Author: Sergey Vojtovich)
The plugin API requires the mysql.plugin
table. When upgrading from an older version of MySQL, you
should run the mysql_fix_privilege_tables
command to create this table. See
Abschnitt 5.6, „mysql_fix_privilege_tables — Upgrade von MySQL-Systemtabellen“.
Incompatible change: Plugins
are installed in the directory named by the
plugin_dir
system variable. This variable
also controls the location from which the server loads
user-defined functions (UDFs), which is a change from earlier
versions of MySQL. That is, all UDF library files now must be
installed in the plugin directory. When upgrading from an
older version of MySQL, you must migrate your UDF files to the
plugin directory.
The Instance Manager (IM) now has some additional functionality:
SHOW
provides a listing of all log files
used by the instance. (Author: Petr Chardin)
instance_name
LOG FILES
SHOW
retrieves a
part of the specified log file. (Author: Petr Chardin)
instance_name
LOG {ERROR | SLOW | GENERAL}
size
SET
sets an option to the specified value and writes it to
the config file See Abschnitt 5.5, „mysqlmanager — Der MySQL Instance Manager“,
for more details on these new commands. (Author: Petr
Chardin)
instance_name
.
option_name
=option_value
The performance of boolean full-text searches (using the „+“ Operator) has been improved. See Abschnitt 12.7, „MySQL-Volltextsuche“, for more details about full-text searching. (Author: Sergey Vojtovich)
VARCHAR
fields used in MySQL Cluster tables
are now variable-sized; that is, they now only allocate as
much space as required to store the data. Previously, a
VARCHAR(
column allocated n+2 bytes (aligned to 4 bytes), regardless if
the actual inserted value required that much space. (In other
words, a n
)VARCHAR
column always required the
same, fixed, amount of storage as a CHAR
column of the same size.)
Renamed the table_cache
system variable to
table_open_cache
. Any scripts that refer to
table_cache
should be updated to use the
new name.
Added the table_definition_cache
system
variable. If you use a large number of tables, you can create
a large table definition cache to speed up opening of tables.
The table definition cache takes less space and does not use
file descriptors, unlike the normal table cache.
Bugs fixed:
Set functions could not be aggregated in outer subqueries. (Bug#12762)
Functionality added or changed:
Added MAXLOCKS
,
MINLOCKS
, MAXWRITE
, and
MINWRITE
as allowable values of the
--bdb-lock-detect
option. (Bug#14876)
Added the bdb_cache_parts
and
bdb_region_size
system variables, and
allowed bdb_cache_size
to be larger than
4GB on systems that support it. (Bug#14895)
Added Transactions
, XA
,
and Savepoints
columns to SHOW
ENGINES
output.
Added --replace
to
mysqldump. This option uses
REPLACE INTO
, rather than INSERT
INTO
, when writing the dumpfile.
Bugs fixed:
Foreign keys were not properly enforced in
TEMPORARY
tables. Foreign keys now are
disallowed in TEMPORARY
tables. (Bug#12084)
Functionality added or changed:
Bugs fixed:
Performing a CREATE TABLE
statement with a
PARTITION BY
clause in a prepared statement
could crash a server running in debug mode. (Bug#12097)
NDB
: Specifying the wrong nodegroup in a
CREATE TABLE
using partitioning would lead
to the table name being locked after the CREATE
TABLE
statement failed (that is, the table name
could not be re-used). (Bug#12114)
Using ORDER BY
in a query with a
partitioned table on a 64-bit operating system could crash the
server. (Bug#12116)
When two threads compete for the same table, a deadlock could
occur if one thread has also a lock on another table through
LOCK TABLES
and the thread is attempting to
remove the table in some manner and the other thread want
locks on both tables. (Bug#10600)
Functionality added or changed:
N/A
Bugs fixed:
The SQLDriverConnect()
ODBC method did not
work with recent MyODBC releases. (Bug#12393)
Functionality added or changed:
N/A
Bugs fixed:
SQLColumns()
returned no information for
tables that had a column named using a reserved word. (Bug#9539)
Functionality added or changed: No changes.
Bugs fixed:
mysql_list_dbcolumns()
and
insert_fields()
were retrieving all rows
from a table. Fixed the queries generated by these functions
to return no rows. (Bug#8198)
SQLGetTypoInfo()
returned
tinyblob
for
SQL_VARBINARY
and nothing for
SQL_BINARY
. Fixed to return
varbinary
for
SQL_VARBINARY
, binary
for SQL_BINARY
, and
longblob
for
SQL_LONGVARBINARY
. (Bug#8138)
Fixed Statement.cancel()
causes
NullPointerException
if underlying
connection has been closed due to server failure. (Bug#20650)
Added configuration option "noAccessToProcedureBodies" which will cause the driver to create basic parameter metadata for CallableStatements when the user does not have access to procedure bodies via "SHOW CREATE PROCEDURE" or selecting from mysql.proc instead of throwing an exception. The default value for this option is "false"
Fixed can't use XAConnection
for local
transactions when no global transaction is in progress. (Bug#17401)
Fixed driver fails on non-ASCII platforms. The driver was
assuming that the platform character set would be a superset
of MySQL's latin1
when doing the handshake
for authentication, and when reading error messages. We now
use Cp1252 for all strings sent to the server during the
handshake phase, and a hard-coded mapping of the
language
systtem variable to the character
set that is used for error messages. (Bug#18086)
Fixed ConnectionProperties
(and thus some
subclasses) are not serializable, even though some J2EE
containers expect them to be. (Bug#19169)
Fixed MysqlValidConnectionChecker
for JBoss
doesn't work with MySQLXADataSources
. (Bug#20242)
Better caching of character set converters (per-connection) to remove a bottleneck for multibyte character sets.
Added connection/datasource property
pinGlobalTxToPhysicalConnection
(defaults
to false
). When set to
true
, when using
XAConnections
, the driver ensures that
operations on a given XID are always routed to the same
physical connection. This allows the
XAConnection
to support XA START
... JOIN
after XA END
has been
called, and is also a workaround for transaction managers that
don't maintain thread affinity for a global transaction (most
either always maintain thread affinity, or have it as a
configuration option).
MysqlXaConnection.recover(int flags)
now
allows combinations of
XAResource.TMSTARTRSCAN
and
TMENDRSCAN
. To simulate the
„scanning“ nature of the interface, we return all
prepared XIDs for TMSTARTRSCAN
, and no new
XIDs for calls with TMNOFLAGS
, or
TMENDRSCAN
when not in combination with
TMSTARTRSCAN
. This change was made for API
compliance, as well as integration with IBM WebSphere's
transaction manager.
XADataSource
implemented (ported from 3.2
branch which won't be released as a product). Use
com.mysql.jdbc.jdbc2.optional.MysqlXADataSource
as your datasource class name in your application server to
utilize XA transactions in MySQL-5.0.10 and newer.
PreparedStatement.setString()
didn't work
correctly when sql_mode
on server contained
NO_BACKSLASH_ESCAPES
and no characters that
needed escaping were present in the string.
Attempt detection of the MySQL type BINARY
(it's an alias, so this isn't always reliable), and use the
java.sql.Types.BINARY
type mapping for it.
Moved -bin-g.jar
file into separate
debug
subdirectory to avoid confusion.
Don't allow .setAutoCommit(true)
, or
.commit()
or .rollback()
on an XA-managed connection as per the JDBC specification.
If the connection useTimezone
is set to
true
, then also respect time zone
conversions in escape-processed string literals (for example,
"{ts ...}"
and "{t
...}"
).
Return original column name for
RSMD.getColumnName()
if the column was
aliased, alias name for .getColumnLabel()
(if aliased), and original table name for
.getTableName()
. Note this only works for
MySQL-4.1 and newer, as older servers don't make this
information available to clients.
Setting useJDBCCompliantTimezoneShift=true
(it's not the default) causes the driver to use GMT for
all
TIMESTAMP
/DATETIME
time
zones, and the current VM time zone for any other type that
refers to time zones. This feature can not be used when
useTimezone=true
to convert between server
and client time zones.
Add one level of indirection of internal representation of
CallableStatement
parameter metadata to
avoid class not found issues on JDK-1.3 for
ParameterMetadata
interface (which doesn't
exist prior to JDBC-3.0).
Added unit tests for XADatasource
, as well
as friendlier exceptions for XA failures compared to the
"stock" XAException
(which has no
messages).
Idle timeouts cause XAConnections
to whine
about rolling themselves back. (Bug#14729)
Added support for Connector/MXJ integration via url
subprotocol jdbc:mysql:mxj://...
.
Moved all SQLException
constructor usage to
a factory in SQLError
(ground-work for
JDBC-4.0 SQLState
-based exception classes).
Removed Java5-specific calls to BigDecimal
constructor (when result set value is ''
,
(int)0
was being used as an argument
indirectly via method return value. This signature doesn't
exist prior to Java5.)
Added service-provider entry to
META-INF/services/java.sql.Driver
for
JDBC-4.0 support.
Return "[VAR]BINARY" for
RSMD.getColumnTypeName()
when that is
actually the type, and it can be distinguished (MySQL-4.1 and
newer).
When fix for Bug#14562 was merged from 3.1.12, added
functionality for CallableStatement
's
parameter metadata to return correct information for
.getParameterClassName()
.
Fuller synchronization of Connection
to
avoid deadlocks when using multithreaded frameworks that
multithread a single connection (usually not recommended, but
the JDBC spec allows it anyways), part of fix to Bug#14972).
Implementation of Statement.cancel()
and
Statement.setQueryTimeout()
. Both require
MySQL-5.0.0 or newer server, require a separate connection to
issue the KILL QUERY
statement, and in the
case of setQueryTimeout()
creates an
additional thread to handle the timeout functionality.
Note: Failures to cancel the statement for
setQueryTimeout()
may manifest themselves
as RuntimeExceptions
rather than failing
silently, as there is currently no way to unblock the thread
that is executing the query being cancelled due to timeout
expiration and have it throw the exception instead.
Fixed updatable result set throws ClassCastException when there is row data and moveToInsertRow() is called. (Fixes Bug#20479)
Fixed Updatable result set that contains a BIT column fails when server-side prepared statements are used. (Fixes Bug#20485)
Fixed memory leak with profileSQL=true. (Fixes Bug#16987)
Connection fails to localhost when using timeout and IPv6 is configured. (Fixes Bug#19726)
Fixed NullPointerException in MysqlDataSourceFactory due to Reference containing RefAddrs with null content. (Fixes Bug#16791)
Fixed ResultSet.getShort() for UNSIGNED TINYINT returns incorrect values when using server-side prepared statements. (Fixes Bug#20306)
Fixed can't pool server-side prepared statements, exception raised when re-using them. (Fixes Bug#20687)
Fixed Bug#21062 - ResultSet.getSomeInteger() doesn't work for BIT(>1).
Fixed Bug#18880 - ResultSet.getFloatFromString() can't retrieve values near Float.MIN/MAX_VALUE.
Fixed Bug#20888 - escape of quotes in client-side prepared statements parsing not respected. Patch covers more than bug report, including NO_BACKSLASH_ESCAPES being set, and stacked quote characters forms of escaping (i.e. '' or "").
Fixed Bug#19993 - ReplicationDriver does not always round-robin load balance depending on URL used for slaves list.
INOUT
parameter does not store
IN
value. (Bug#15464)
Exception thrown for new decimal type when using updatable result sets. (Bug#14609)
No "dos" character set in MySQL > 4.1.0. (Bug#15544)
PreparedStatement.setObject()
serializes
BigInteger
as object, rather than sending
as numeric value (and is thus not complementary to
.getObject()
on an UNSIGNED
LONG
type). (Bug#15383)
ResultSet.getShort()
for UNSIGNED
TINYINT
returned wrong values. (Bug#11874)
lib-nodist
directory missing from package
breaks out-of-box build. (Bug#15676)
DBMD.getColumns()
returns wrong type for
BIT
. (Bug#15854)
Fixed issue where driver was unable to initialize character
set mapping tables. Removed reliance on
.properties
files to hold this information,
as it turns out to be too problematic to code around class
loader hierarchies that change depending on how an application
is deployed. Moved information back into the
CharsetMapping
class. (Bug#14938)
Fixed updatable result set doesn't return
AUTO_INCREMENT
values for
insertRow()
when multiple column primary
keys are used. (the driver was checking for the existence of
single-column primary keys and an autoincrement value > 0
instead of a straightforward
isAutoIncrement()
check). (Bug#16841)
Fixed Statement.getGeneratedKeys()
throws
NullPointerException
when no query has been
processed. (Bug#17099)
Fixed driver trying to call methods that don't exist on older and newer versions of Log4j. The fix is not trying to auto-detect presense of log4j, too many different incompatible versions out there in the wild to do this reliably. (Bug#13469)
If you relied on autodetection before, you will need to add "logger=com.mysql.jdbc.log.Log4JLogger" to your JDBC URL to enable Log4J usage, or alternatively use the new "CommonsLogger" class to take care of this.
Added support for Apache Commons logging, use "com.mysql.jdbc.log.CommonsLogger" as the value for the "logger" configuration property.
LogFactory now prepends "com.mysql.jdbc.log" to log class name if it can't be found as-specified. This allows you to use "short names" for the built-in log factories, for example "logger=CommonsLogger" instead of "logger=com.mysql.jdbc.log.CommonsLogger".
Fixed issue with ReplicationConnection
incorrectly copying state, doesn't transfer connection context
correctly when transitioning between the same read-only
states. (Bug#15570)
Fixed issue where server-side prepared statements don't cause truncation exceptions to be thrown when truncation happens. (Bug#18041)
Added performance feature, re-writing of batched executes for
Statement.executeBatch()
(for all DML
statements) and
PreparedStatement.executeBatch()
(for
INSERTs with VALUE clauses only). Enable by using
"rewriteBatchedStatements=true" in your JDBC URL.
Fixed
CallableStatement.registerOutParameter()
not working when some parameters pre-populated. Still waiting
for feedback from JDBC experts group to determine what correct
parameter count from getMetaData()
should
be, however. (Bug#17898)
Fixed calling clearParameters()
on a closed
prepared statement causes NPE. (Bug#17587)
Map "latin1" on MySQL server to CP1252 for MySQL > 4.1.0.
Added additional accessor and mutator methods on ConnectionProperties so that DataSource users can use same naming as regular URL properties.
Fixed data truncation and getWarnings()
only returns last warning in set. (Bug#18740)
Improved performance of retrieving
BigDecimal
, Time
,
Timestamp
and Date
values from server-side prepared statements by creating fewer
short-lived instances of Strings
when the
native type is not an exact match for the requested type.
Fixes Bug#18496 for BigDecimals
.
Fixed aliased column names where length of name > 251 are corrupted. (Bug#18554)
Fixed ResultSet.wasNull()
not always reset
correctly for booleans when done via conversion for
server-side prepared statements. (Bug#17450)
Fixed invalid classname returned for
ResultSetMetaData.getColumnClassName()
for
BIGINT type
. (Bug#19282)
Fixed case where driver wasn't reading server status correctly when fetching server-side prepared statement rows, which in some cases could cause warning counts to be off, or multiple result sets to not be read off the wire.
Driver now aware of fix for BIT
type
metadata that went into MySQL-5.0.21 for server not reporting
length consistently (Bug#13601).
Fixed PreparedStatement.setObject(int, Object,
int)
doesn't respect scale of BigDecimals. (Bug#19615)
Fixed ResultSet.wasNull()
returns incorrect
value when extracting native string from server-side prepared
statement generated result set. (Bug#19282)
Fixed client-side prepared statement bug with embedded
?
characters inside quoted identifiers (it
was recognized as a placeholder, when it was not).
Don't allow executeBatch()
for
CallableStatements
with registered
OUT
/INOUT
parameters
(JDBC compliance).
Fall back to platform-encoding for
URLDecoder.decode()
when parsing driver URL
properties if the platform doesn't have a two-argument version
of this method.
Java type conversion may be incorrect for
MEDIUMINT
. (Bug#14562)
Added configuration property
useGmtMillisForDatetimes
which when set to
true
causes
ResultSet.getDate()
,
.getTimestamp()
to return correct
millis-since GMT when .getTime()
is called
on the return value (currently default is
false
for legacy behavior).
Fixed
DatabaseMetaData.stores*Identifiers()
:
If lower_case_table_names=0
(on
server):
storesLowerCaseIdentifiers()
returns false
storesLowerCaseQuotedIdentifiers()
returns false
storesMixedCaseIdentifiers()
returns true
storesMixedCaseQuotedIdentifiers()
returns true
storesUpperCaseIdentifiers()
returns false
storesUpperCaseQuotedIdentifiers()
returns true
If lower_case_table_names=1
(on
server):
storesLowerCaseIdentifiers()
returns true
storesLowerCaseQuotedIdentifiers()
returns true
storesMixedCaseIdentifiers()
returns false
storesMixedCaseQuotedIdentifiers()
returns false
storesUpperCaseIdentifiers()
returns false
storesUpperCaseQuotedIdentifiers()
returns true
DatabaseMetaData.getColumns()
doesn't
return TABLE_NAME
correctly. (Bug#14815)
Escape processor replaces quote character in quoted string with string delimiter. (Bug#14909)
OpenOffice expects
DBMD.supportsIntegrityEnhancementFacility()
to return true
if foreign keys are
supported by the datasource, even though this method also
covers support for check constraints, which MySQL
doesn't have. Setting the configuration
property
overrideSupportsIntegrityEnhancementFacility
to true
causes the driver to return
true
for this method. (Bug#12975)
Added com.mysql.jdbc.testsuite.url.default
system property to set default JDBC url for testsuite (to
speed up bug resolution when I'm working in Eclipse).
Unable to initialize character set mapping tables (due to J2EE classloader differences). (Bug#14938)
Deadlock while closing server-side prepared statements from multiple threads sharing one connection. (Bug#14972)
logSlowQueries
should give better info.
(Bug#12230)
Extraneous sleep on autoReconnect
. (Bug#13775)
Driver incorrectly closes streams passed as arguments to
PreparedStatements
. Reverts to legacy
behavior by setting the JDBC configuration property
autoClosePStmtStreams
to
true
(also included in the 3-0-Compat
configuration „bundle“). (Bug#15024)
maxQuerySizeToLog
is not respected. Added
logging of bound values for execute()
phase
of server-side prepared statements when
profileSQL=true
as well. (Bug#13048)
Usage advisor complains about unreferenced columns, even though they've been referenced. (Bug#15065)
Don't increase timeout for failover/reconnect. (Bug#6577)
Process escape tokens in
Connection.prepareStatement(...)
. (Bug#15141) You can disable this behavior by setting the JDBC URL
configuration property
processEscapeCodesForPrepStmts
to
false
.
Reconnect during middle of executeBatch()
should not occur if autoReconnect
is
enabled. (Bug#13255)
Spurious !
on console when character
encoding is utf8
. (Bug#11629)
Fixed statements generated for testcases missing
;
for „plain“ statements.
Incorrect generation of testcase scripts for server-side prepared statements. (Bug#11663)
Fixed regression caused by fix for Bug#11552 that caused driver to return incorrect values for unsigned integers when those integers where within the range of the positive signed type.
Moved source code to Subversion repository.
Escape tokenizer doesn't respect stacked single quotes for escapes. (Bug#11797)
GEOMETRY
type not recognized when using
server-side prepared statements.
ReplicationConnection
won't switch to
slave, throws „Catalog can't be null“ exception.
(Bug#11879)
Properties shared between master and slave with replication connection. (Bug#12218)
Statement.getWarnings()
fails with NPE if
statement has been closed. (Bug#10630)
Only get char[]
from SQL in
PreparedStatement.ParseInfo()
when needed.
Geometry types not handled with server-side prepared statements. (Bug#12104)
StringUtils.getBytes()
doesn't work when
using multi-byte character encodings and a length in
characters is specified. (Bug#11614)
Pstmt.setObject(...., Types.BOOLEAN)
throws
exception. (Bug#11798)
maxPerformance.properties
mis-spells
„elideSetAutoCommits“. (Bug#11976)
DBMD.storesLower/Mixed/UpperIdentifiers()
reports incorrect values for servers deployed on Windows. (Bug#11575)
ResultSet.moveToCurrentRow()
fails to work
when preceded by a call to
ResultSet.moveToInsertRow()
. (Bug#11190)
VARBINARY
data corrupted when using
server-side prepared statements and
.setBytes()
. (Bug#11115)
explainSlowQueries
hangs with server-side
prepared statements. (Bug#12229)
Escape processor didn't honor strings demarcated with double quotes. (Bug#11498)
Lifted restriction of changing streaming parameters with
server-side prepared statements. As long as
all
streaming parameters were set before
execution, .clearParameters()
does not have
to be called. (due to limitation of client/server protocol,
prepared statements can not reset
individual stream data on the server
side).
Reworked Field
class,
*Buffer
, and MysqlIO
to
be aware of field lengths >
Integer.MAX_VALUE
.
Updated DBMD.supportsCorrelatedQueries()
to
return true
for versions > 4.1,
supportsGroupByUnrelated()
to return
true
and
getResultSetHoldability()
to return
HOLD_CURSORS_OVER_COMMIT
.
Handling of catalog argument in
DatabaseMetaData.getIndexInfo()
, which also
means changes to the following methods in
DatabaseMetaData
: (Bug#12541)
getBestRowIdentifier()
getColumns()
getCrossReference()
getExportedKeys()
getImportedKeys()
getIndexInfo()
getPrimaryKeys()
getProcedures()
(and thus indirectly
getProcedureColumns()
)
getTables()
The catalog
argument in all of these
methods now behaves in the following way:
Specifying NULL
means that catalog will
not be used to filter the results (thus all databases will
be searched), unless you've set
nullCatalogMeansCurrent=true
in your
JDBC URL properties.
Specifying ""
means
„current“ catalog, even though this isn't
quite JDBC spec compliant, it's there for legacy users.
Specifying a catalog works as stated in the API docs.
Made Connection.clientPrepare()
available from „wrapped“ connections in the
jdbc2.optional
package (connections
built by ConnectionPoolDataSource
instances).
Added Connection.isMasterConnection()
for
clients to be able to determine if a multi-host master/slave
connection is connected to the first host in the list.
Tokenizer for =
in URL properties was
causing sessionVariables=....
to be
parameterized incorrectly. (Bug#12753)
Foreign key information that is quoted is parsed incorrectly
when DatabaseMetaData
methods use that
information. (Bug#11781)
The sendBlobChunkSize
property is now
clamped to max_allowed_packet
with
consideration of stream buffer size and packet headers to
avoid PacketTooBigExceptions
when
max_allowed_packet
is similar in size to
the default sendBlobChunkSize
which is 1M.
CallableStatement.clearParameters()
now
clears resources associated with
INOUT
/OUTPUT
parameters
as well as INPUT
parameters.
Connection.prepareCall()
is database name
case-sensitive (on Windows systems). (Bug#12417)
cp1251
incorrectly mapped to
win1251
for servers newer than 4.0.x. (Bug#12752)
java.sql.Types.OTHER
returned for
BINARY
and VARBINARY
columns when using
DatabaseMetaData.getColumns()
. (Bug#12970)
ServerPreparedStatement.getBinding()
now
checks if the statement is closed before attempting to
reference the list of parameter bindings, to avoid throwing a
NullPointerException
.
ResultSetMetaData
from
Statement.getGeneratedKeys()
caused a
NullPointerException
to be thrown whenever
a method that required a connection reference was called. (Bug#13277)
Backport of Field
class,
ResultSetMetaData.getColumnClassName()
, and
ResultSet.getObject(int)
changes from 5.0
branch to fix behavior surrounding VARCHAR
BINARY
/VARBINARY
and related
types.
Fixed NullPointerException
when converting
catalog
parameter in many
DatabaseMetaDataMethods
to
byte[]
s (for the result set) when the
parameter is null
. (null
isn't technically allowed by the JDBC specification, but we've
historically allowed it).
Backport of VAR[BINARY|CHAR] [BINARY]
types
detection from 5.0 branch.
Read response in
MysqlIO.sendFileToServer()
, even if the
local file can't be opened, otherwise next query issued will
fail, because it's reading the response to the empty
LOAD DATA INFILE
packet sent to the server.
Workaround for Bug#13374:
ResultSet.getStatement()
on closed result
set returns NULL
(as per JDBC 4.0 spec, but
not backward-compatible). Set the connection property
retainStatementAfterResultSetClose
to
true
to be able to retrieve a
ResultSet
's statement after the
ResultSet
has been closed via
.getStatement()
(the default is
false
, to be JDBC-compliant and to reduce
the chance that code using JDBC leaks
Statement
instances).
URL configuration parameters don't allow
‘&
’ or
‘=
’ in their values. The JDBC
driver now parses configuration parameters as if they are
encoded using the application/x-www-form-urlencoded format as
specified by java.net.URLDecoder
(http://java.sun.com/j2se/1.5.0/docs/api/java/net/URLDecoder.html).
(Bug#13453)
If the ‘%
’ character is present
in a configuration property, it must now be represented as
%25
, which is the encoded form of
‘%
’ when using
application/x-www-form-urlencoded encoding.
The configuration property sessionVariables
now allows you to specify variables that start with the
‘@
’ sign.
When gatherPerfMetrics
is enabled for
servers older than 4.1.0, a
NullPointerException
is thrown from the
constructor of ResultSet
if the query
doesn't use any tables. (Bug#13043)
Fixed connecting without a database specified raised an
exception in MysqlIO.changeDatabaseTo()
.
Initial implemention of ParameterMetadata
for
PreparedStatement.getParameterMetadata()
.
Only works fully for CallableStatements
, as
current server-side prepared statements return every parameter
as a VARCHAR
type.
Overhaul of character set configuration, everything now lives in a properties file.
Driver now correctly uses CP932 if available on the server for Windows-31J, CP932 and MS932 java encoding names, otherwise it resorts to SJIS, which is only a close approximation. Currently only MySQL-5.0.3 and newer (and MySQL-4.1.12 or .13, depending on when the character set gets backported) can reliably support any variant of CP932.
com.mysql.jdbc.PreparedStatement.ParseInfo
does unnecessary call to toCharArray()
.
(Bug#9064)
Memory leak in ServerPreparedStatement
if
serverPrepare()
fails. (Bug#10144)
Actually write manifest file to correct place so it ends up in the binary jar file.
Added createDatabaseIfNotExist
property
(default is false
), which will cause the
driver to ask the server to create the database specified in
the URL if it doesn't exist. You must have the appropriate
privileges for database creation for this to work.
Unsigned SMALLINT
treated as signed for
ResultSet.getInt()
, fixed all cases for
UNSIGNED
integer values and server-side
prepared statements, as well as
ResultSet.getObject()
for UNSIGNED
TINYINT
. (Bug#10156)
Double quotes not recognized when parsing client-side prepared statements. (Bug#10155)
Made enableStreamingResults()
visible on
com.mysql.jdbc.jdbc2.optional.StatementWrapper
.
Made ServerPreparedStatement.asSql()
work
correctly so auto-explain functionality would work with
server-side prepared statements.
Made JDBC2-compliant wrappers public in order to allow access to vendor extensions.
Cleaned up logging of profiler events, moved code to dump a
profiler event as a string to
com.mysql.jdbc.log.LogUtils
so that third
parties can use it.
DatabaseMetaData.supportsMultipleOpenResults()
now returns true
. The driver has supported
this for some time, DBMD just missed that fact.
Driver doesn't support {?=CALL(...)}
for
calling stored functions. This involved adding support for
function retrieval to
DatabaseMetaData.getProcedures()
and
getProcedureColumns()
as well. (Bug#10310)
SQLException
thrown when retrieving
YEAR(2)
with
ResultSet.getString()
. The driver will now
always treat YEAR
types as
java.sql.Dates
and return the correct
values for getString()
. Alternatively, the
yearIsDateType
connection property can be
set to false
and the values will be treated
as SHORT
s. (Bug#10485)
The datatype returned for TINYINT(1)
columns when tinyInt1isBit=true
(the
default) can be switched between
Types.BOOLEAN
and
Types.BIT
using the new configuration
property transformedBitIsBoolean
, which
defaults to false
. If set to
false
(the default),
DatabaseMetaData.getColumns()
and
ResultSetMetaData.getColumnType()
will
return Types.BOOLEAN
for
TINYINT(1)
columns. If
true
, Types.BOOLEAN
will
be returned instead. Regardless of this configuration
property, if tinyInt1isBit
is enabled,
columns with the type TINYINT(1)
will be
returned as java.lang.Boolean
instances
from ResultSet.getObject(...)
, and
ResultSetMetaData.getColumnClassName()
will
return java.lang.Boolean
.
SQLException
is thrown when using property
characterSetResults
with
cp932
or eucjpms
. (Bug#10496)
Reorganized directory layout. Sources now are in
src
folder. Don't pollute parent
directory when building, now output goes to
./build
, distribution goes to
./dist
.
Added support/bug hunting feature that generates
.sql
test scripts to
STDERR
when
autoGenerateTestcaseScript
is set to
true
.
0-length streams not sent to server when using server-side prepared statements. (Bug#10850)
Setting cachePrepStmts=true
now causes the
Connection
to also cache the check the
driver performs to determine if a prepared statement can be
server-side or not, as well as caches server-side prepared
statements for the lifetime of a connection. As before, the
prepStmtCacheSize
parameter controls the
size of these caches.
Try to handle OutOfMemoryErrors
more
gracefully. Although not much can be done, they will in most
cases close the connection they happened on so that further
operations don't run into a connection in some unknown state.
When an OOM has happened, any further operations on the
connection will fail with a „Connection closed“
exception that will also list the OOM exception as the reason
for the implicit connection close event.
Don't send COM_RESET_STMT
for each
execution of a server-side prepared statement if it isn't
required.
Driver detects if you're running MySQL-5.0.7 or later, and
does not scan for LIMIT ?[,?]
in statements
being prepared, as the server supports those types of queries
now.
VARBINARY
data corrupted when using
server-side prepared statements and
ResultSet.getBytes()
. (Bug#11115)
Connection.setCatalog()
is now aware of the
useLocalSessionState
configuration
property, which when set to true
will
prevent the driver from sending USE ...
to
the server if the requested catalog is the same as the current
catalog.
Added the following configuration bundles, use one or many via
the useConfigs
configuration property:
maxPerformance
— maximum
performance without being reckless
solarisMaxPerformance
— maximum
performance for Solaris, avoids syscalls where it can
3-0-Compat
— Compatibility with
Connector/J 3.0.x functionality
Added maintainTimeStats
configuration
property (defaults to true
), which tells
the driver whether or not to keep track of the last query time
and the last successful packet sent to the server's time. If
set to false
, removes two syscalls per
query.
autoReconnect
ping causes exception on
connection startup. (Bug#11259)
Connector/J dumping query into SQLException
twice. (Bug#11360)
Fixed PreparedStatement.setClob()
not
accepting null
as a parameter.
Production package doesn't include JBoss integration classes. (Bug#11411)
Removed nonsensical „costly type conversion“ warnings when using usage advisor.
Fixed DatabaseMetaData.getTables()
returning views when they were not asked for as one of the
requested table types.
Added support for new precision-math
DECIMAL
type in MySQL 5.0.3 and up.
Fixed ResultSet.getTime()
on a
NULL
value for server-side prepared
statements throws NPE.
Made Connection.ping()
a public method.
DATE_FORMAT()
queries returned as
BLOB
s from getObject()
.
(Bug#8868)
ServerPreparedStatements
now correctly
„stream“
BLOB
/CLOB
data to the
server. You can configure the threshold chunk size using the
JDBC URL property blobSendChunkSize
(the
default is 1MB).
BlobFromLocator
now uses correct identifier
quoting when generating prepared statements.
Server-side session variables can be preset at connection time
by passing them as a comma-delimited list for the connection
property sessionVariables
.
Fixed regression in ping()
for users using
autoReconnect=true
.
PreparedStatement.addBatch()
doesn't work
with server-side prepared statements and streaming
BINARY
data. (Bug#9040)
DBMD.supportsMixedCase*Identifiers()
returns wrong value on servers running on case-sensitive
filesystems. (Bug#8800)
Cannot use UTF-8
for characterSetResults
configuration property. (Bug#9206)
A continuation of Bug#8868, where functions used in queries
that should return non-string types when resolved by temporary
tables suddenly become opaque binary strings (work-around for
server limitation). Also fixed fields with type of
CHAR(n) CHARACTER SET BINARY
to return
correct/matching classes for
RSMD.getColumnClassName()
and
ResultSet.getObject()
. (Bug#9236)
DBMD.supportsResultSetConcurrency()
not
returning true
for forward-only/read-only
result sets (we obviously support this). (Bug#8792)
DATA_TYPE
column from
DBMD.getBestRowIdentifier()
causes
ArrayIndexOutOfBoundsException
when
accessed (and in fact, didn't return any value). (Bug#8803)
Check for empty strings (''
) when
converting CHAR
/VARCHAR
column data to numbers, throw exception if
emptyStringsConvertToZero
configuration
property is set to false
(for
backward-compatibility with 3.0, it is now set to
true
by default, but will most likely
default to false
in 3.2).
PreparedStatement.getMetaData()
inserts
blank row in database under certain conditions when not using
server-side prepared statements. (Bug#9320)
Connection.canHandleAsPreparedStatement()
now makes „best effort“ to distinguish
LIMIT
clauses with placeholders in them
from ones without in order to have fewer false positives when
generating work-arounds for statements the server cannot
currently handle as server-side prepared statements.
Fixed build.xml
to not compile
log4j
logging if log4j
not available.
Added support for the c3p0 connection pool's
(http://c3p0.sf.net/) validation/connection
checker interface which uses the lightweight
COM_PING
call to the server if available.
To use it, configure your c3p0 connection pool's
connectionTesterClassName
property to use
com.mysql.jdbc.integration.c3p0.MysqlConnectionTester
.
Better detection of LIMIT
inside/outside of
quoted strings so that the driver can more correctly determine
whether a prepared statement can be prepared on the server or
not.
Stored procedures with same name in different databases confuse the driver when it tries to determine parameter counts/types. (Bug#9319)
Added finalizers to ResultSet
and
Statement
implementations to be JDBC
spec-compliant, which requires that if not explicitly closed,
these resources should be closed upon garbage collection.
Stored procedures with DECIMAL
parameters
with storage specifications that contained
‘,
’ in them would fail. (Bug#9682)
PreparedStatement.setObject(int, Object, int type,
int scale)
now uses scale value for
BigDecimal
instances.
Statement.getMoreResults()
could throw NPE
when existing result set was .close()
d.
(Bug#9704)
The performance metrics feature now gathers information about number of tables referenced in a SELECT.
The logging system is now automatically configured. If the
value has been set by the user, via the URL property
logger
or the system property
com.mysql.jdbc.logger
, then use that,
otherwise, autodetect it using the following steps:
Log4j, if it's available,
Then JDK1.4 logging,
Then fallback to our STDERR
logging.
DBMD.getTables()
shouldn't return tables if
views are asked for, even if the database version doesn't
support views. (Bug#9778)
Fixed driver not returning true
for
-1
when
ResultSet.getBoolean()
was called on result
sets returned from server-side prepared statements.
Added a Manifest.MF
file with
implementation information to the .jar
file.
More tests in Field.isOpaqueBinary()
to
distinguish opaque binary (that is, fields with type
CHAR(n)
and CHARACTER SET
BINARY
) from output of various scalar and aggregate
functions that return strings.
Should accept null
for catalog (meaning use
current) in DBMD methods, even though it's not JDBC-compliant
for legacy's sake. Disable by setting connection property
nullCatalogMeansCurrent
to
false
(which will be the default value in
C/J 3.2.x). (Bug#9917)
Should accept null
for name patterns in
DBMD (meaning ‘%
’), even though
it isn't JDBC compliant, for legacy's sake. Disable by setting
connection property
nullNamePatternMatchesAll
to
false
(which will be the default value in
C/J 3.2.x). (Bug#9769)
Timestamp key column data needed _binary
stripped for
UpdatableResultSet.refreshRow()
. (Bug#7686)
Timestamps converted incorrectly to strings with server-side prepared statements and updatable result sets. (Bug#7715)
Detect new sql_mode
variable in string form
(it used to be integer) and adjust quoting method for strings
appropriately.
Added holdResultsOpenOverStatementClose
property (default is false
), that keeps
result sets open over statement.close() or new execution on
same statement (suggested by Kevin Burton).
Infinite recursion when „falling back“ to master in failover configuration. (Bug#7952)
Disable multi-statements (if enabled) for MySQL-4.1 versions prior to version 4.1.10 if the query cache is enabled, as the server returns wrong results in this configuration.
Fixed duplicated code in
configureClientCharset()
that prevented
useOldUTF8Behavior=true
from working
properly.
Removed dontUnpackBinaryResults
functionality, the driver now always stores results from
server-side prepared statements as is from the server and
unpacks them on demand.
Emulated locators corrupt binary data when using server-side prepared statements. (Bug#8096)
Fixed synchronization issue with
ServerPreparedStatement.serverPrepare()
that could cause deadlocks/crashes if connection was shared
between threads.
By default, the driver now scans SQL you are preparing via all
variants of Connection.prepareStatement()
to determine if it is a supported type of statement to prepare
on the server side, and if it is not supported by the server,
it instead prepares it as a client-side emulated prepared
statement. You can disable this by passing
emulateUnsupportedPstmts=false
in your JDBC
URL. (Bug#4718)
Remove _binary
introducer from parameters
used as in/out parameters in
CallableStatement
.
Always return byte[]
s for output parameters
registered as *BINARY
.
Send correct value for „boolean“
true
to server for
PreparedStatement.setObject(n, "true",
Types.BIT)
.
Fixed bug with Connection not caching statements from
prepareStatement()
when the statement
wasn't a server-side prepared statement.
Choose correct „direction“ to apply time
adjustments when both client and server are in GMT time zone
when using ResultSet.get(..., cal)
and
PreparedStatement.set(...., cal)
.
Added dontTrackOpenResources
option
(default is false
, to be JDBC compliant),
which helps with memory use for non-well-behaved apps (that
is, applications that don't close Statement
objects when they should).
ResultSet.getString()
doesn't maintain
format stored on server, bug fix only enabled when
noDatetimeStringSync
property is set to
true
(the default is
false
). (Bug#8428)
Fixed NPE in ResultSet.realClose()
when
using usage advisor and result set was already closed.
PreparedStatements
not creating streaming
result sets. (Bug#8487)
Don't pass NULL
to
String.valueOf()
in
ResultSet.getNativeConvertToString()
, as it
stringifies it (that is, returns null
),
which is not correct for the method in question.
ResultSet.getBigDecimal()
throws exception
when rounding would need to occur to set scale. The driver now
chooses a rounding mode of „half up“ if
non-rounding BigDecimal.setScale()
fails.
(Bug#8424)
Added useLocalSessionState
configuration
property, when set to true
the JDBC driver
trusts that the application is well-behaved and only sets
autocommit and transaction isolation levels using the methods
provided on java.sql.Connection
, and
therefore can manipulate these values in many cases without
incurring round-trips to the database server.
Added enableStreamingResults()
to
Statement
for connection pool
implementations that check
Statement.setFetchSize()
for
specification-compliant values. Call
Statement.setFetchSize(>=0)
to disable
the streaming results for that statement.
Added support for BIT
type in MySQL-5.0.3.
The driver will treat BIT(1-8)
as the JDBC
standard BIT
type (which maps to
java.lang.Boolean
), as the server does not
currently send enough information to determine the size of a
bitfield when < 9 bits are declared.
BIT(>9)
will be treated as
VARBINARY
, and will return
byte[]
when getObject()
is called.
Fixed hang on SocketInputStream.read()
with
Statement.setMaxRows()
and multiple result
sets when driver has to truncate result set directly, rather
than tacking a LIMIT
on the end of it.
n
DBMD.getProcedures()
doesn't respect
catalog parameter. (Bug#7026)
Fix comparisons made between string constants and dynamic
strings that are converted with either
toUpperCase()
or
toLowerCase()
to use
Locale.ENGLISH
, as some locales
„override“ case rules for English. Also use
StringUtils.indexOfIgnoreCase()
instead of
.toUpperCase().indexOf()
, avoids creating a
very short-lived transient String
instance.
Server-side prepared statements did not honor
zeroDateTimeBehavior
property, and would
cause class-cast exceptions when using
ResultSet.getObject()
, as the all-zero
string was always returned. (Bug#5235)
Fixed batched updates with server prepared statements weren't looking if the types had changed for a given batched set of parameters compared to the previous set, causing the server to return the error „Wrong arguments to mysql_stmt_execute()“.
Handle case when string representation of timestamp contains
trailing ‘.
’ with no numbers
following it.
Inefficient detection of pre-existing string instances in
ResultSet.getNativeString()
. (Bug#5706)
Don't throw exceptions for
Connection.releaseSavepoint()
.
Use a per-session Calendar
instance by
default when decoding dates from
ServerPreparedStatements
(set to old, less
performant behavior by setting property
dynamicCalendars=true
).
Added experimental configuration property
dontUnpackBinaryResults
, which delays
unpacking binary result set values until they're asked for,
and only creates object instances for non-numerical values (it
is set to false
by default). For some
usecase/jvm combinations, this is friendlier on the garbage
collector.
UNSIGNED BIGINT
unpacked incorrectly from
server-side prepared statement result sets. (Bug#5729)
ServerSidePreparedStatement
allocating
short-lived objects unnecessarily. (Bug#6225)
Removed unwanted new Throwable()
in
ResultSet
constructor due to bad merge
(caused a new object instance that was never used for every
result set created). Found while profiling for Bug#6359.
Fixed too-early creation of StringBuffer
in
EscapeProcessor.escapeSQL()
, also return
String
when escaping not needed (to avoid
unnecessary object allocations). Found while profiling for Bug#6359.
Use null-safe-equals for key comparisons in updatable result sets.
SUM()
on DECIMAL
with
server-side prepared statement ignores scale if zero-padding
is needed (this ends up being due to conversion to
DOUBLE
by server, which when converted to a
string to parse into BigDecimal
, loses all
„padding“ zeros). (Bug#6537)
Use
DatabaseMetaData.getIdentifierQuoteString()
when building DBMD queries.
Use 1MB packet for sending file for LOAD DATA LOCAL
INFILE
if that is <
max_allowed_packet
on server.
ResultSetMetaData.getColumnDisplaySize()
returns incorrect values for multi-byte charsets. (Bug#6399)
Make auto-deserialization of
java.lang.Objects
stored in
BLOB
columns configurable via
autoDeserialize
property (defaults to
false
).
Re-work Field.isOpaqueBinary()
to detect
CHAR(
to support fixed-length binary fields for
n
) CHARACTER SET
BINARYResultSet.getObject()
.
Use our own implementation of buffered input streams to get
around blocking behavior of
java.io.BufferedInputStream
. Disable this
with useReadAheadInput=false
.
Failing to connect to the server when one of the addresses for
the given host name is IPV6 (which the server does not yet
bind on). The driver now loops through
all IP addresses for a given host, and
stops on the first one that accepts()
a
socket.connect()
. (Bug#6348)
Connector/J 3.1.3 beta does not handle integers correctly
(caused by changes to support unsigned reads in
Buffer.readInt()
->
Buffer.readShort()
). (Bug#4510)
Added support in
DatabaseMetaData.getTables()
and
getTableTypes()
for views, which are now
available in MySQL server 5.0.x.
ServerPreparedStatement.execute*()
sometimes threw
ArrayIndexOutOfBoundsException
when
unpacking field metadata. (Bug#4642)
Optimized integer number parsing, enable „old“
slower integer parsing using JDK classes via
useFastIntParsing=false
property.
Added useOnlyServerErrorMessages
property,
which causes message text in exceptions generated by the
server to only contain the text sent by the server (as opposed
to the SQLState's „standard“ description,
followed by the server's error message). This property is set
to true
by default.
ResultSet.wasNull()
does not work for
primatives if a previous null
was returned.
(Bug#4689)
Track packet sequence numbers if
enablePacketDebug=true
, and throw an
exception if packets received out-of-order.
ResultSet.getObject()
returns wrong type
for strings when using prepared statements. (Bug#4482)
Calling MysqlPooledConnection.close()
twice
(even though an application error), caused NPE. Fixed.
ServerPreparedStatements
dealing with
return of DECIMAL
type don't work. (Bug#5012)
ResultSet.getObject()
doesn't return type
Boolean
for pseudo-bit types from prepared
statements on 4.1.x (shortcut for avoiding extra type
conversion when using binary-encoded result sets obscured test
in getObject()
for „pseudo“
bit type). (Bug#5032)
You can now use URLs in LOAD DATA LOCAL
INFILE
statements, and the driver will use Java's
built-in handlers for retreiving the data and sending it to
the server. This feature is not enabled by default, you must
set the allowUrlInLocalInfile
connection
property to true
.
The driver is more strict about truncation of numerics on
ResultSet.get*()
, and will throw an
SQLException
when truncation is detected.
You can disable this by setting
jdbcCompliantTruncation
to
false
(it is enabled by default, as this
functionality is required for JDBC compliance).
Added three ways to deal with all-zero datetimes when reading
them from a ResultSet
:
exception
(the default), which throws an
SQLException
with an SQLState of
S1009
; convertToNull
,
which returns NULL
instead of the date; and
round
, which rounds the date to the nearest
closest value which is '0001-01-01'
.
Fixed ServerPreparedStatement
to read
prepared statement metadata off the wire, even though it's
currently a placeholder instead of using
MysqlIO.clearInputStream()
which didn't
work at various times because data wasn't available to read
from the server yet. This fixes sporadic errors users were
having with ServerPreparedStatements
throwing ArrayIndexOutOfBoundExceptions
.
Use com.mysql.jdbc.Message
's classloader
when loading resource bundle, should fix sporadic issues when
the caller's classloader can't locate the resource bundle.
Mangle output parameter names for
CallableStatements
so they will not clash
with user variable names.
Added support for INOUT
parameters in
CallableStatements
.
Null bitmask sent for server-side prepared statements was incorrect. (Bug#4119)
Use SQL Standard SQL states by default, unless
useSqlStateCodes
property is set to
false
.
Added packet debuging code (see the
enablePacketDebug
property documentation).
Added constants for MySQL error numbers (publicly accessible,
see com.mysql.jdbc.MysqlErrorNumbers
), and
the ability to generate the mappings of vendor error codes to
SQLStates that the driver uses (for documentation purposes).
Externalized more messages (on-going effort).
Error in retrieval of mediumint
column with
prepared statements and binary protocol. (Bug#4311)
Support new time zone variables in MySQL-4.1.3 when
useTimezone=true
.
Support for unsigned numerics as return types from prepared
statements. This also causes a change in
ResultSet.getObject()
for the
bigint unsigned
type, which used to return
BigDecimal
instances, it now returns
instances of java.lang.BigInteger
.
Fixed stored procedure parameter parsing info when size was
specified for a parameter (for example,
char()
, varchar()
).
Enabled callable statement caching via
cacheCallableStmts
property.
Fixed case when no output parameters specified for a stored procedure caused a bogus query to be issued to retrieve out parameters, leading to a syntax error from the server.
Fixed case when no parameters could cause a
NullPointerException
in
CallableStatement.setOutputParameters()
.
Removed wrapping of exceptions in
MysqlIO.changeUser()
.
Fixed sending of split packets for large queries, enabled nio ability to send large packets as well.
Added .toString()
functionality to
ServerPreparedStatement
, which should help
if you're trying to debug a query that is a prepared statement
(it shows SQL as the server would process).
Added gatherPerformanceMetrics
property,
along with properties to control when/where this info gets
logged (see docs for more info).
ServerPreparedStatements
weren't actually
de-allocating server-side resources when
.close()
was called.
Added logSlowQueries
property, along with
slowQueriesThresholdMillis
property to
control when a query should be considered „slow.“
Correctly map output parameters to position given in
prepareCall()
versus. order implied during
registerOutParameter()
. (Bug#3146)
Correctly detect initial character set for servers >= 4.1.0.
Cleaned up detection of server properties.
Support placeholder for parameter metadata for server >= 4.1.2.
getProcedures()
does not return any
procedures in result set. (Bug#3539)
getProcedureColumns()
doesn't work with
wildcards for procedure name. (Bug#3540)
DBMD.getSQLStateType()
returns incorrect
value. (Bug#3520)
Added connectionCollation
property to cause
driver to issue set
collation_connection=...
query on connection init if
default collation for given charset is not appropriate.
Fixed DatabaseMetaData.getProcedures()
when
run on MySQL-5.0.0 (output of SHOW PROCEDURE
STATUS
changed between 5.0.0 and 5.0.1.
getWarnings()
returns
SQLWarning
instead of
DataTruncation
. (Bug#3804)
Don't enable server-side prepared statements for server version 5.0.0 or 5.0.1, as they aren't compatible with the '4.1.2+' style that the driver uses (the driver expects information to come back that isn't there, so it hangs).
Fixed bug with UpdatableResultSets
not
using client-side prepared statements.
Fixed character encoding issues when converting bytes to ASCII when MySQL doesn't provide the character set, and the JVM is set to a multi-byte encoding (usually affecting retrieval of numeric values).
Unpack „unknown“ data types from server prepared
statements as Strings
.
Implemented long data (Blobs, Clobs, InputStreams, Readers) for server prepared statements.
Implemented Statement.getWarnings()
for
MySQL-4.1 and newer (using SHOW WARNINGS
).
Default result set type changed to
TYPE_FORWARD_ONLY
(JDBC compliance).
Centralized setting of result set type and concurrency.
Refactored how connection properties are set and exposed as
DriverPropertyInfo
as well as
Connection
and
DataSource
properties.
Support for NIO. Use useNIO=true
on
platforms that support NIO.
Support for transaction savepoints (MySQL >= 4.0.14 or 4.1.1).
Support for mysql_change_user()
. See the
changeUser()
method in
com.mysql.jdbc.Connection
.
Reduced number of methods called in average query to be more efficient.
Prepared Statements
will be re-prepared on
auto-reconnect. Any errors encountered are postponed until
first attempt to re-execute the re-prepared statement.
Ensure that warnings are cleared before executing queries on prepared statements, as-per JDBC spec (now that we support warnings).
Support „old“ profileSql
capitalization in ConnectionProperties
.
This property is deprecated, you should use
profileSQL
if possible.
Optimized Buffer.readLenByteArray()
to
return shared empty byte array when length is 0.
Allow contents of
PreparedStatement.setBlob()
to be retained
between calls to .execute*()
.
Deal with 0-length tokens in
EscapeProcessor
(caused by callable
statement escape syntax).
Check for closed connection on delete/update/insert row
operations in UpdatableResultSet
.
Fix support for table aliases when checking for all primary
keys in UpdatableResultSet
.
Removed useFastDates
connection property.
Correctly initialize datasource properties from JNDI Refs, including explicitly specified URLs.
DatabaseMetaData
now reports
supportsStoredProcedures()
for MySQL
versions >= 5.0.0
Fixed stack overflow in
Connection.prepareCall()
(bad merge).
Fixed IllegalAccessError
to
Calendar.getTimeInMillis()
in
DateTimeValue
(for JDK < 1.4).
DatabaseMetaData.getColumns()
is not
returning correct column ordinal info for
non-'%'
column name patterns. (Bug#1673)
Merged fix of datatype mapping from MySQL type
FLOAT
to
java.sql.Types.REAL
from 3.0 branch.
Detect collation of column for
RSMD.isCaseSensitive()
.
Fixed sending of queries larger than 16M.
Added named and indexed input/output parameter support to
CallableStatement
. MySQL-5.0.x or newer.
Fixed NullPointerException
in
ServerPreparedStatement.setTimestamp()
, as
well as year and month descrepencies in
ServerPreparedStatement.setTimestamp()
,
setDate()
.
Added ability to have multiple database/JVM targets for
compliance and regression/unit tests in
build.xml
.
Fixed NPE and year/month bad conversions when accessing some
datetime functionality in
ServerPreparedStatements
and their
resultant result sets.
Display where/why a connection was implicitly closed (to aid debugging).
CommunicationsException
implemented, that
tries to determine why communications was lost with a server,
and displays possible reasons when
.getMessage()
is called.
NULL
values for numeric types in binary
encoded result sets causing
NullPointerExceptions
. (Bug#2359)
Implemented Connection.prepareCall()
, and
DatabaseMetaData
.
getProcedures()
and
getProcedureColumns()
.
Reset long binary
parameters in
ServerPreparedStatement
when
clearParameters()
is called, by sending
COM_RESET_STMT
to the server.
Merged prepared statement caching, and
.getMetaData()
support from 3.0 branch.
Fixed off-by-1900 error in some cases for years in
TimeUtil.fastDate
/TimeCreate()
when unpacking results from server-side prepared statements.
Fixed charset conversion issue in
getTables()
. (Bug#2502)
Implemented multiple result sets returned from a statement or stored procedure.
Server-side prepared statements were not returning datatype
YEAR
correctly. (Bug#2606)
Enabled streaming of result sets from server-side prepared statements.
Class-cast exception when using scrolling result sets and server-side prepared statements. (Bug#2623)
Merged unbuffered input code from 3.0.
Fixed ConnectionProperties
that weren't
properly exposed via accessors, cleaned up
ConnectionProperties
code.
NULL
fields were not being encoded
correctly in all cases in server-side prepared statements.
(Bug#2671)
Fixed rare buffer underflow when writing numbers into buffers for sending prepared statement execution requests.
Use DocBook version of docs for shipped versions of drivers.
Added requireSSL
property.
Added useServerPrepStmts
property (default
false
). The driver will use server-side
prepared statements when the server version supports them (4.1
and newer) when this property is set to
true
. It is currently set to
false
by default until all bind/fetch
functionality has been implemented. Currently only DML
prepared statements are implemented for 4.1 server-side
prepared statements.
Track open Statements
, close all when
Connection.close()
is called (JDBC
compliance).
Timestamp
/Time
conversion goes in the wrong „direction“ when
useTimeZone=true
and server time zone
differs from client time zone. (Bug#5874)
DatabaseMetaData.getIndexInfo()
ignored
unique
parameter. (Bug#7081)
Support new protocol type
MYSQL_TYPE_VARCHAR
.
Added useOldUTF8Behavior
' configuration
property, which causes JDBC driver to act like it did with
MySQL-4.0.x and earlier when the character encoding is
utf-8
when connected to MySQL-4.1 or newer.
Statements created from a pooled connection were returning
physical connection instead of logical connection when
getConnection()
was called. (Bug#7316)
PreparedStatements
don't encode Big5 (and
other multi-byte) character sets correctly in static SQL
strings. (Bug#7033)
Connections starting up failed-over (due to down master) never retry master. (Bug#6966)
PreparedStatement.fixDecimalExponent()
adding extra +
, making number unparseable
by MySQL server. (Bug#7061)
Timestamp key column data needed _binary
stripped for
UpdatableResultSet.refreshRow()
. (Bug#7686)
Backported SQLState codes mapping from Connector/J 3.1, enable
with useSqlStateCodes=true
as a connection
property, it defaults to false
in this
release, so that we don't break legacy applications (it
defaults to true
starting with Connector/J
3.1).
PreparedStatement.fixDecimalExponent()
adding extra +
, making number unparseable
by MySQL server. (Bug#7601)
Escape sequence {fn convert(..., type)} now supports
ODBC-style types that are prepended by
SQL_
.
Fixed duplicated code in
configureClientCharset()
that prevented
useOldUTF8Behavior=true
from working
properly.
Handle streaming result sets with more than 2 billion rows properly by fixing wraparound of row number counter.
MS932
, SHIFT_JIS
, and
Windows_31J
not recognized as aliases for
sjis
. (Bug#7607)
Adding CP943
to aliases for
sjis
. (Bug#6549, fixed while fixing Bug#7607)
Which requires hex escaping of binary data when using multi-byte charsets with prepared statements. (Bug#8064)
NON_UNIQUE
column from
DBMD.getIndexInfo()
returned inverted
value. (Bug#8812)
Workaround for server Bug#9098: Default values of
CURRENT_*
for DATE
,
TIME
, DATETIME
, and
TIMESTAMP
columns can't be distinguished
from string
values, so
UpdatableResultSet.moveToInsertRow()
generates bad SQL for inserting default values.
EUCKR
charset is sent as SET NAMES
euc_kr
which MySQL-4.1 and newer doesn't understand.
(Bug#8629)
DatabaseMetaData.supportsSelectForUpdate()
returns correct value based on server version.
Use hex escapes for
PreparedStatement.setBytes()
for
double-byte charsets including „aliases“
Windows-31J
, CP934
,
MS932
.
Added support for the EUC_JP_Solaris
character encoding, which maps to a MySQL encoding of
eucjpms
(backported from 3.1 branch). This
only works on servers that support eucjpms
,
namely 5.0.3 or later.
Re-issue character set configuration commands when re-using
pooled connections and/or
Connection.changeUser()
when connected to
MySQL-4.1 or newer.
Fixed ResultSetMetaData.isReadOnly()
to
detect non-writable columns when connected to MySQL-4.1 or
newer, based on existence of „original“ table and
column names.
ResultSet.updateByte()
when on insert row
throws ArrayOutOfBoundsException
. (Bug#5664)
Fixed DatabaseMetaData.getTypes()
returning
incorrect (this is, non-negative) scale for the
NUMERIC
type.
Off-by-one bug in
Buffer.readString(
.
(Bug#5664)
string
)
Made TINYINT(1)
->
BIT
/Boolean
conversion
configurable via tinyInt1isBit
property
(default true
to be JDBC compliant out of
the box).
Only set character_set_results
during
connection establishment if server version >= 4.1.1.
Fixed regression where useUnbufferedInput
was defaulting to false
.
ResultSet.getTimestamp()
on a column with
TIME
in it fails. (Bug#5664)
StringUtils.escapeEasternUnicodeByteStream
was still broken for GBK. (Bug#4010)
Failover for autoReconnect
not using port
numbers for any hosts, and not retrying all hosts.
(Warning: This required a
change to the SocketFactory
connect()
method signature, which is now
public Socket connect(String host, int portNumber,
Properties props)
; therefore, any third-party socket
factories will have to be changed to support this signature.
(Bug#4334)
Logical connections created by
MysqlConnectionPoolDataSource
will now
issue a rollback()
when they are closed and
sent back to the pool. If your application server/connection
pool already does this for you, you can set the
rollbackOnPooledClose
property to
false
to avoid the overhead of an extra
rollback()
.
Removed redundant calls to checkRowPos()
in
ResultSet
.
DOUBLE
mapped twice in
DBMD.getTypeInfo()
. (Bug#4742)
Added FLOSS license exemption.
Calling .close()
twice on a
PooledConnection
causes NPE. (Bug#4808)
DBMD.getColumns()
returns incorrect JDBC
type for unsigned columns. This affects type mappings for all
numeric types in the RSMD.getColumnType()
and RSMD.getColumnTypeNames()
methods as
well, to ensure that „like“ types from
DBMD.getColumns()
match up with what
RSMD.getColumnType()
and
getColumnTypeNames()
return. (Bug#4138,
Bug#4860)
„Production“ is now „GA“ (General Availability) in naming scheme of distributions.
RSMD.getPrecision()
returning 0 for
non-numeric types (should return max length in chars for
non-binary types, max length in bytes for binary types). This
fix also fixes mapping of
RSMD.getColumnType()
and
RSMD.getColumnTypeName()
for the
BLOB
types based on the length sent from
the server (the server doesn't distinguish between
TINYBLOB
, BLOB
,
MEDIUMBLOB
or LONGBLOB
at the network protocol level). (Bug#4880)
ResultSet
should release
Field[]
instance in
.close()
. (Bug#5022)
ResultSet.getMetaData()
should not return
incorrectly initialized metadata if the result set has been
closed, but should instead throw an
SQLException
. Also fixed for
getRow()
and
getWarnings()
and traversal methods by
calling checkClosed()
before operating on
instance-level fields that are nullified during
.close()
. (Bug#5069)
Parse new time zone variables from 4.1.x servers.
Use _binary
introducer for
PreparedStatement.setBytes()
and
set*Stream()
when connected to MySQL-4.1.x
or newer to avoid misinterpretation during character
conversion.
Add unsigned attribute to
DatabaseMetaData.getColumns()
output in the
TYPE_NAME
column.
Added failOverReadOnly
property, to allow
end-user to configure state of connection (read-only/writable)
when failed over.
Backported „change user“ and „reset server
state“ functionality from 3.1 branch, to allow clients
of MysqlConnectionPoolDataSource
to reset
server state on getConnection()
on a pooled
connection.
Don't escape SJIS/GBK/BIG5 when using MySQL-4.1 or newer.
Allow url
parameter for
MysqlDataSource
and
MysqlConnectionPool
DataSource
so that passing of other
properties is possible from inside appservers.
Map duplicate key and foreign key errors to SQLState of
23000
.
Backport documentation tooling from 3.1 branch.
Return creating statement for ResultSets
created by getGeneratedKeys()
. (Bug#2957)
Allow java.util.Date
to be sent in as
parameter to PreparedStatement.setObject()
,
converting it to a Timestamp
to maintain
full precision. (Bug#103).
Don't truncate BLOB
or
CLOB
values when using
setBytes()
and/or
setBinary/CharacterStream()
. (Bug#2670).
Dynamically configure character set mappings for field-level
character sets on MySQL-4.1.0 and newer using SHOW
COLLATION
when connecting.
Map binary
character set to
US-ASCII
to support
DATETIME
charset recognition for servers
>= 4.1.2.
Use SET character_set_results
during
initialization to allow any charset to be returned to the
driver for result sets.
Use charsetnr
returned during connect to
encode queries before issuing SET NAMES
on
MySQL >= 4.1.0.
Add helper methods to ResultSetMetaData
(getColumnCharacterEncoding()
and
getColumnCharacterSet()
) to allow end-users
to see what charset the driver thinks it should be using for
the column.
Only set character_set_results
for MySQL
>= 4.1.0.
StringUtils.escapeSJISByteStream()
not
covering all eastern double-byte charsets correctly. (Bug#3511)
Renamed StringUtils.escapeSJISByteStream()
to more appropriate
escapeEasternUnicodeByteStream()
.
Not specifying database in URL caused
MalformedURL
exception. (Bug#3554)
Auto-convert MySQL encoding names to Java encoding names if
used for characterEncoding
property.
Added encoding names that are recognized on some JVMs to fix case where they were reverse-mapped to MySQL encoding names incorrectly.
Use junit.textui.TestRunner
for all unit
tests (to allow them to be run from the command line outside
of Ant or Eclipse).
UpdatableResultSet
not picking up default
values for moveToInsertRow()
. (Bug#3557)
Inconsistent reporting of data type. The server still doesn't return all types for *BLOBs *TEXT correctly, so the driver won't return those correctly. (Bug#3570)
DBMD.getSQLStateType()
returns incorrect
value. (Bug#3520)
Fixed regression in
PreparedStatement.setString()
and eastern
character encodings.
Made StringRegressionTest
4.1-unicode
aware.
Trigger a SET NAMES utf8
when encoding is
forced to utf8
or
utf-8
via the
characterEncoding
property. Previously,
only the Java-style encoding name of utf-8
would trigger this.
AutoReconnect
time was growing faster than
exponentially. (Bug#2447)
Fixed failover always going to last host in list. (Bug#2578)
Added useUnbufferedInput
parameter, and now
use it by default (due to JVM issue
http://developer.java.sun.com/developer/bugParade/bugs/4401235.html)
Detect on
/off
or
1
, 2
,
3
form of
lower_case_table_names
value on server.
Return java.lang.Integer
for
TINYINT
and SMALLINT
types from
ResultSetMetaData.getColumnClassName()
.
(Bug#2852)
Return java.lang.Double
for
FLOAT
type from
ResultSetMetaData.getColumnClassName()
.
(Bug#2855)
Return [B
instead of
java.lang.Object
for
BINARY
, VARBINARY
and
LONGVARBINARY
types from
ResultSetMetaData.getColumnClassName()
(JDBC compliance).
Issue connection events on all instances created from a
ConnectionPoolDataSource
.
Don't count quoted IDs when inside a 'string' in
PreparedStatement
parsing. (Bug#1511)
„Friendlier“ exception message for
PacketTooLargeException
. (Bug#1534)
Backported fix for aliased tables and
UpdatableResultSets
in
checkUpdatability()
method from 3.1 branch.
Fix for ArrayIndexOutOfBounds
exception
when using Statement.setMaxRows()
. (Bug#1695)
Barge blobs and split packets not being read correctly. (Bug#1576)
Fixed regression of
Statement.getGeneratedKeys()
and
REPLACE
statements.
Subsequent call to ResultSet.updateFoo()
causes NPE if result set is not updatable. (Bug#1630)
Fix for 4.1.1-style authentication with no password.
Foreign Keys column sequence is not consistent in
DatabaseMetaData.getImported/Exported/CrossReference()
.
(Bug#1731)
DatabaseMetaData.getSystemFunction()
returning bad function VResultsSion
. (Bug#1775)
Cross-database updatable result sets are not checked for updatability correctly. (Bug#1592)
DatabaseMetaData.getColumns()
should return
Types.LONGVARCHAR
for MySQL
LONGTEXT
type.
ResultSet.getObject()
on
TINYINT
and SMALLINT
columns should return Java type Integer
.
(Bug#1913)
Added alwaysClearStream
connection
property, which causes the driver to always empty any
remaining data on the input stream before each query.
Added more descriptive error message Server
Configuration Denies Access to DataSource
, as well
as retrieval of message from server.
Autoreconnect code didn't set catalog upon reconnect if it had been changed.
Implement ResultSet.updateClob()
.
ResultSetMetaData.isCaseSensitive()
returned wrong value for
CHAR
/VARCHAR
columns.
Connection property maxRows
not honored.
(Bug#1933)
Statements being created too many times in
DBMD.extractForeignKeyFromCreateTable()
.
(Bug#1925)
Support escape sequence {fn convert ... }. (Bug#1914)
ArrayIndexOutOfBounds
when parameter number
== number of parameters + 1. (Bug#1958)
ResultSet.findColumn()
should use first
matching column name when there are duplicate column names in
SELECT
query (JDBC-compliance). (Bug#2006)
Removed static synchronization bottleneck from
PreparedStatement.setTimestamp()
.
Removed static synchronization bottleneck from instance
factory method of
SingleByteCharsetConverter
.
Enable caching of the parsing stage of prepared statements via
the cachePrepStmts
,
prepStmtCacheSize
, and
prepStmtCacheSqlLimit
properties (disabled
by default).
Speed up parsing of PreparedStatements
, try
to use one-pass whenever possible.
Fixed security exception when used in Applets (applets can't
read the system property file.encoding
which is needed for LOAD DATA LOCAL
INFILE
).
Use constants for SQLStates.
Map charset ko18_ru
to
ko18r
when connected to MySQL-4.1.0 or
newer.
Ensure that Buffer.writeString()
saves room
for the \0
.
Fixed exception Unknown character set
'danish'
on connect with JDK-1.4.0
Fixed mappings in SQLError to report deadlocks with SQLStates
of 41000
.
maxRows
property would affect internal
statements, so check it for all statement creation internal to
the driver, and set to 0 when it is not.
Faster date handling code in ResultSet
and
PreparedStatement
(no longer uses
Date
methods that synchronize on static
calendars).
Fixed test for end of buffer in
Buffer.readString()
.
Fixed ResultSet.previous()
behavior to move
current position to before result set when on first row of
result set. (Bug#496)
Fixed Statement
and
PreparedStatement
issuing bogus queries
when setMaxRows()
had been used and a
LIMIT
clause was present in the query.
refreshRow
didn't work when primary key
values contained values that needed to be escaped (they ended
up being doubly escaped). (Bug#661)
Support InnoDB
contraint names when
extracting foreign key information in
DatabaseMetaData
(implementing ideas from
Parwinder Sekhon). (Bug#517, Bug#664)
Backported 4.1 protocol changes from 3.1 branch (server-side SQL states, new field information, larger client capability flags, connect-with-database, and so forth).
Fix UpdatableResultSet
to return values for
get
when on
insert row. (Bug#675)
XXX
()
The insertRow
in an
UpdatableResultSet
is now loaded with the
default column values when
moveToInsertRow()
is called. (Bug#688)
DatabaseMetaData.getColumns()
wasn't
returning NULL
for default values that are
specified as NULL
.
Change default statement type/concurrency to
TYPE_FORWARD_ONLY
and
CONCUR_READ_ONLY
(spec compliance).
Don't try and reset isolation level on reconnect if MySQL doesn't support them.
Don't wrap SQLExceptions
in
RowDataDynamic
.
Don't change timestamp TZ twice if
useTimezone==true
. (Bug#774)
Fixed regression in large split-packet handling. (Bug#848)
Better diagnostic error messages in exceptions for „streaming“ result sets.
Issue exception on
ResultSet.get
on empty result set (wasn't caught in some cases).
XXX
()
Don't hide messages from exceptions thrown in I/O layers.
Don't fire connection closed events when closing pooled
connections, or on
PooledConnection.getConnection()
with
already open connections. (Bug#884)
Clip +/- INF (to smallest and largest representative values
for the type in MySQL) and NaN (to 0) for
setDouble
/setFloat()
,
and issue a warning on the statement when the server does not
support +/- INF or NaN.
Double-escaping of '\'
when charset is SJIS
or GBK and '\'
appears in non-escaped
input. (Bug#879)
When emptying input stream of unused rows for
„streaming“ result sets, have the current thread
yield()
every 100 rows in order to not
monopolize CPU time.
DatabaseMetaData.getColumns()
getting
confused about the keyword „set“ in character
columns. (Bug#1099)
Fixed deadlock issue with
Statement.setMaxRows()
.
Fixed CLOB.truncate()
. (Bug#1130)
Optimized CLOB.setChracterStream()
. (Bug#1131)
Made databaseName
,
portNumber
, and
serverName
optional parameters for
MysqlDataSourceFactory
. (Bug#1246)
ResultSet.get/setString
mashing char 127.
(Bug#1247)
Backported authentication changes for 4.1.1 and newer from 3.1 branch.
Added com.mysql.jdbc.util.BaseBugReport
to
help creation of testcases for bug reports.
Added property to „clobber“ streaming results, by
setting the clobberStreamingResults
property to true
(the default is
false
). This will cause a
„streaming“ ResultSet
to be
automatically closed, and any oustanding data still streaming
from the server to be discarded if another query is executed
before all the data has been read from the server.
Allow bogus URLs in
Driver.getPropertyInfo()
.
Return list of generated keys when using multi-value
INSERTS
with
Statement.getGeneratedKeys()
.
Use JVM charset with filenames and LOAD DATA [LOCAL]
INFILE
.
Fix infinite loop with
Connection.cleanup()
.
Changed Ant target compile-core
to
compile-driver
, and made testsuite
compilation a separate target.
Fixed result set not getting set for
Statement.executeUpdate()
, which affected
getGeneratedKeys()
and
getUpdateCount()
in some cases.
Unicode character 0xFFFF in a string would cause the driver to
throw an ArrayOutOfBoundsException
. (Bug#378).
Return correct number of generated keys when using
REPLACE
statements.
Fix problem detecting server character set in some cases.
Fix row data decoding error when using very large packets.
Optimized row data decoding.
Issue exception when operating on an already closed prepared statement.
Fixed SJIS encoding bug, thanks to Naoto Sato.
Optimized usage of EscapeProcessor
.
Allow multiple calls to Statement.close()
.
Fixed MysqlPooledConnection.close()
calling
wrong event type.
Fixed StringIndexOutOfBoundsException
in
PreparedStatement.setClob()
.
4.1 Column Metadata fixes.
Remove synchronization from
Driver.connect()
and
Driver.acceptsUrl()
.
IOExceptions
during a transaction now cause
the Connection
to be closed.
Fixed missing conversion for YEAR
type in
ResultSetMetaData.getColumnTypeName()
.
Don't pick up indexes that start with pri
as primary keys for DBMD.getPrimaryKeys()
.
Throw SQLExceptions
when trying to do
operations on a forcefully closed
Connection
(that is, when a communication
link failure occurs).
You can now toggle profiling on/off using
Connection.setProfileSql(boolean)
.
Fixed charset issues with database metadata (charset was not getting set correctly).
Updatable ResultSets
can now be created for
aliased tables/columns when connected to MySQL-4.1 or newer.
Fixed LOAD DATA LOCAL INFILE
bug when file
> max_allowed_packet
.
Fixed escaping of 0x5c ('\'
) character for
GBK and Big5 charsets.
Fixed ResultSet.getTimestamp()
when
underlying field is of type DATE
.
Ensure that packet size from
alignPacketSize()
does not exceed
max_allowed_packet
(JVM bug)
Don't reset Connection.isReadOnly()
when
autoReconnecting.
Fixed ResultSetMetaData
to return
""
when catalog not known. Fixes
NullPointerExceptions
with Sun's
CachedRowSet
.
Fixed DBMD.getTypeInfo()
and
DBMD.getColumns()
returning different value
for precision in TEXT
and
BLOB
types.
Allow ignoring of warning for „non transactional
tables“ during rollback (compliance/usability) by
setting ignoreNonTxTables
property to
true
.
Fixed SQLExceptions
getting swallowed on
initial connect.
Fixed Statement.setMaxRows()
to stop
sending LIMIT
type queries when not needed
(performance).
Clean up Statement
query/method mismatch
tests (that is, INSERT
not allowed with
.executeQuery()
).
More checks added in ResultSet
traversal
method to catch when in closed state.
Fixed ResultSetMetaData.isWritable()
to
return correct value.
Add „window“ of different NULL
sorting behavior to
DBMD.nullsAreSortedAtStart
(4.0.2 to
4.0.10, true; otherwise, no).
Implemented Blob.setBytes()
. You still need
to pass the resultant Blob
back into an
updatable ResultSet
or
PreparedStatement
to persist the changes,
because MySQL does not support „locators“.
Backported 4.1 charset field info changes from Connector/J 3.1.
Fixed Buffer.fastSkipLenString()
causing
ArrayIndexOutOfBounds
exceptions with some
queries when unpacking fields.
Implemented an empty TypeMap
for
Connection.getTypeMap()
so that some
third-party apps work with MySQL (IBM WebSphere 5.0 Connection
pool).
Added missing LONGTEXT
type to
DBMD.getColumns()
.
Retrieve TX_ISOLATION
from database for
Connection.getTransactionIsolation()
when
the MySQL version supports it, instead of an instance
variable.
Quote table names in
DatabaseMetaData.getColumns()
,
getPrimaryKeys()
,
getIndexInfo()
,
getBestRowIdentifier()
.
Greatly reduce memory required for
setBinaryStream()
in
PreparedStatements
.
Fixed ResultSet.isBeforeFirst()
for empty
result sets.
Added update options for foreign key metadata.
Added quoted identifiers to database names for
Connection.setCatalog
.
Added support for quoted identifiers in
PreparedStatement
parser.
Streamlined character conversion and byte[]
handling in PreparedStatements
for
setByte()
.
Reduce memory footprint of
PreparedStatements
by sharing outbound
packet with MysqlIO
.
Added strictUpdates
property to allow
control of amount of checking for „correctness“
of updatable result sets. Set this to false
if you want faster updatable result sets and you know that you
create them from SELECT
statements on
tables with primary keys and that you have selected all
primary keys in your query.
Added support for 4.0.8-style large packets.
Fixed PreparedStatement.executeBatch()
parameter overwriting.
Changed charsToByte
in
SingleByteCharConverter
to be non-static.
Changed SingleByteCharConverter
to use lazy
initialization of each converter.
Fixed charset handling in Fields.java
.
Implemented Connection.nativeSQL()
.
More robust escape tokenizer: Recognize --
comments, and allow nested escape sequences (see
testsuite.EscapeProcessingTest
).
DBMD.getImported/ExportedKeys()
now handles
multiple foreign keys per table.
Fixed ResultSetMetaData.getPrecision()
returning incorrect values for some floating-point types.
Fixed ResultSetMetaData.getColumnTypeName()
returning BLOB
for TEXT
and TEXT
for BLOB
types.
Fixed Buffer.isLastDataPacket()
for 4.1 and
newer servers.
Added CLIENT_LONG_FLAG
to be able to get
more column flags (isAutoIncrement()
being
the most important).
Because of above, implemented
ResultSetMetaData.isAutoIncrement()
to use
Field.isAutoIncrement()
.
Honor lower_case_table_names
when enabled
in the server when doing table name comparisons in
DatabaseMetaData
methods.
Some MySQL-4.1 protocol support (extended field info from selects).
Use non-aliased table/column names and database names to
fullly qualify tables and columns in
UpdatableResultSet
(requires MySQL-4.1 or
newer).
Allow user to alter behavior of Statement
/
PreparedStatement.executeBatch()
via
continueBatchOnError
property (defaults to
true
).
Check for connection closed in more
Connection
methods
(createStatement
,
prepareStatement
,
setTransactionIsolation
,
setAutoCommit
).
More robust implementation of updatable result sets. Checks that all primary keys of the table have been selected.
LOAD DATA LOCAL INFILE ...
now works, if
your server is configured to allow it. Can be turned off with
the allowLoadLocalInfile
property (see the
README
).
Substitute '?'
for unknown character
conversions in single-byte character sets instead of
'\0'
.
NamedPipeSocketFactory
now works (only
intended for Windows), see README
for
instructions.
Fixed issue with updatable result sets and
PreparedStatements
not working.
Fixed
ResultSet.setFetchDirection(FETCH_UNKNOWN)
.
Fixed issue when calling
Statement.setFetchSize()
when using
arbitrary values.
Fixed incorrect conversion in
ResultSet.getLong()
.
Implemented ResultSet.updateBlob()
.
Removed duplicate code from
UpdatableResultSet
(it can be inherited
from ResultSet
, the extra code for each
method to handle updatability I thought might someday be
necessary has not been needed).
Fixed UnsupportedEncodingException
thrown
when „forcing“ a character encoding via
properties.
Fixed various non-ASCII character encoding issues.
Added driver property useHostsInPrivileges
.
Defaults to true. Affects whether or not
@hostname
will be used in
DBMD.getColumn/TablePrivileges
.
All DBMD
result set columns describing
schemas now return NULL
to be more
compliant with the behavior of other JDBC drivers for other
database systems (MySQL does not support schemas).
Added SSL support. See README
for
information on how to use it.
Properly restore connection properties when autoReconnecting
or failing-over, including autoCommit
state, and isolation level.
Use SHOW CREATE TABLE
when possible for
determining foreign key information for
DatabaseMetaData
. Also allows cascade
options for DELETE
information to be
returned.
Escape 0x5c
character in strings for the
SJIS charset.
Fixed start position off-by-1 error in
Clob.getSubString()
.
Implemented Clob.truncate()
.
Implemented Clob.setString()
.
Implemented Clob.setAsciiStream()
.
Implemented Clob.setCharacterStream()
.
Added com.mysql.jdbc.MiniAdmin
class, which
allows you to send shutdown
command to
MySQL server. This is intended to be used when
„embedding“ Java and MySQL server together in an
end-user application.
Added connectTimeout
parameter that allows
users of JDK-1.4 and newer to specify a maxium time to wait to
establish a connection.
Failover and autoReconnect
work only when
the connection is in an autoCommit(false)
state, in order to stay transaction-safe.
Added queriesBeforeRetryMaster
property
that specifies how many queries to issue when failed over
before attempting to reconnect to the master (defaults to 50).
Fixed DBMD.supportsResultSetConcurrency()
so that it returns true for
ResultSet.TYPE_SCROLL_INSENSITIVE
and
ResultSet.CONCUR_READ_ONLY
or
ResultSet.CONCUR_UPDATABLE
.
Fixed ResultSet.isLast()
for empty result
sets (should return false
).
PreparedStatement
now honors stream lengths
in setBinary/Ascii/Character Stream() unless you set the
connection property
useStreamLengthsInPrepStmts
to
false
.
Removed some not-needed temporary object creation by smarter
use of Strings
in
EscapeProcessor
,
Connection
and
DatabaseMetaData
classes.
Fixed ResultSet.getRow()
off-by-one bug.
Fixed RowDataStatic.getAt()
off-by-one bug.
Added limited Clob
functionality
(ResultSet.getClob()
,
PreparedStatemtent.setClob()
,
PreparedStatement.setObject(Clob)
.
Added socketTimeout
parameter to URL.
Connection.isClosed()
no longer
„pings“ the server.
Connection.close()
issues
rollback()
when
getAutoCommit()
is
false
.
Added paranoid
parameter, which sanitizes
error messages by removing „sensitive“
information from them (such as hostnames, ports, or
usernames), as well as clearing „sensitive“ data
structures when possible.
Fixed ResultSetMetaData.isSigned()
for
TINYINT
and BIGINT
.
Charsets now automatically detected. Optimized code for single-byte character set conversion.
Implemented ResultSet.getCharacterStream()
.
Added LOCAL TEMPORARY
to table types in
DatabaseMetaData.getTableTypes()
.
Massive code clean-up to follow Java coding conventions (the time had come).
!!! LICENSE CHANGE !!! The
driver is now GPL. If you need non-GPL licenses, please
contact me <mark@mysql.com>
.
JDBC-3.0 functionality including
Statement/PreparedStatement.getGeneratedKeys()
and ResultSet.getURL()
.
Performance enchancements: Driver is now 50–100% faster in most situations, and creates fewer temporary objects.
Repackaging: New driver name is
com.mysql.jdbc.Driver
, old name still
works, though (the driver is now provided by MySQL-AB).
Better checking for closed connections in
Statement
and
PreparedStatement
.
Support for streaming (row-by-row) result sets (see
README
) Thanks to Doron.
Support for large packets (new addition to MySQL-4.0
protocol), see README
for more
information.
JDBC Compliance: Passes all tests besides stored procedure tests.
Fix and sort primary key names in
DBMetaData
(SF bugs 582086 and 582086).
Float types now reported as
java.sql.Types.FLOAT
(SF bug 579573).
ResultSet.getTimestamp()
now works for
DATE
types (SF bug 559134).
ResultSet.getDate/Time/Timestamp
now
recognizes all forms of invalid values that have been set to
all zeros by MySQL (SF bug 586058).
Testsuite now uses Junit (which you can get from http://www.junit.org.
The driver now only works with JDK-1.2 or newer.
Added multi-host failover support (see
README
).
General source-code cleanup.
Overall speed improvements via controlling transient object
creation in MysqlIO
class when reading
packets.
Performance improvements in string handling and field metadata creation (lazily instantiated) contributed by Alex Twisleton-Wykeham-Fiennes.
More code cleanup.
PreparedStatement
now releases resources on
.close()
. (SF bug 553268)
Quoted identifiers not used if server version does not support
them. Also, if server started with --ansi
or
--sql-mode=ANSI_QUOTES
,
‘"
’ will be used as an
identifier quote character, otherwise
‘'
’ will be used.
ResultSet.getDouble()
now uses code built
into JDK to be more precise (but slower).
LogicalHandle.isClosed()
calls through to
physical connection.
Added SQL profiling (to STDERR
). Set
profileSql=true
in your JDBC URL. See
README
for more information.
Fixed typo for relaxAutoCommit
parameter.
More code cleanup.
Fixed unicode chars being read incorrectly. (SF bug 541088)
Faster blob escaping for PrepStmt
.
Added
set
/getPortNumber()
to
DataSource(s)
. (SF bug 548167)
Added setURL()
to
MySQLXADataSource
. (SF bug 546019)
PreparedStatement.toString()
fixed. (SF bug
534026)
ResultSetMetaData.getColumnClassName()
now
implemented.
Rudimentary version of
Statement.getGeneratedKeys()
from JDBC-3.0
now implemented (you need to be using JDK-1.4 for this to
work, I believe).
DBMetaData.getIndexInfo()
- bad PAGES
fixed. (SF BUG 542201)
General code cleanup.
Added getIdleFor()
method to
Connection
and
MysqlLogicalHandle
.
Relaxed synchronization in all classes, should fix 520615 and 520393.
Added getTable/ColumnPrivileges()
to DBMD
(fixes 484502).
Added new types to getTypeInfo()
, fixed
existing types thanks to Al Davis and Kid Kalanon.
Added support for BIT
types (51870) to
PreparedStatement
.
Fixed getRow()
bug (527165) in
ResultSet
.
Fixes for ResultSet
updatability in
PreparedStatement
.
Fixed time zone off-by-1-hour bug in
PreparedStatement
(538286, 528785).
ResultSet
: Fixed updatability (values being
set to null
if not updated).
DataSources
- fixed
setUrl
bug (511614, 525565), wrong
datasource class name (532816, 528767).
Added identifier quoting to all
DatabaseMetaData
methods that need them
(should fix 518108).
Added support for YEAR
type (533556).
ResultSet.insertRow()
should now detect
auto_increment fields in most cases and use that value in the
new row. This detection will not work in multi-valued keys,
however, due to the fact that the MySQL protocol does not
return this information.
ResultSet.refreshRow()
implemented.
Fixed testsuite.Traversal
afterLast()
bug, thanks to Igor Lastric.
Fixed missing DELETE_RULE
value in
DBMD.getImported/ExportedKeys()
and
getCrossReference()
.
Full synchronization of Statement.java
.
More changes to fix Unexpected end of input
stream
errors when reading BLOB
values. This should be the last fix.
Fixed spurious Unexpected end of input
stream
errors in MysqlIO
(bug
507456).
Fixed null-pointer-exceptions when using
MysqlConnectionPoolDataSource
with
Websphere 4 (bug 505839).
Ant build was corrupting included
jar
files, fixed (bug 487669).
Fixed extra memory allocation in
MysqlIO.readPacket()
(bug 488663).
Implementation of
DatabaseMetaData.getExported/ImportedKeys()
and getCrossReference()
.
Full synchronization on methods modifying instance and class-shared references, driver should be entirely thread-safe now (please let me know if you have problems).
DataSource
implementations moved to
org.gjt.mm.mysql.jdbc2.optional
package,
and (initial) implementations of
PooledConnectionDataSource
and
XADataSource
are in place (thanks to Todd
Wolff for the implementation and testing of
PooledConnectionDataSource
with IBM
WebSphere 4).
Added detection of network connection being closed when reading packets (thanks to Todd Lizambri).
Fixed quoting error with escape processor (bug 486265).
Report batch update support through
DatabaseMetaData
(bug 495101).
Fixed off-by-one-hour error in
PreparedStatement.setTimestamp()
(bug
491577).
Removed concatenation support from driver (the
||
operator), as older versions of
VisualAge seem to be the only thing that use it, and it
conflicts with the logical ||
operator. You
will need to start mysqld with the
--ansi
flag to use the ||
operator as concatenation (bug 491680).
Fixed casting bug in PreparedStatement
(bug
488663).
Batch updates now supported (thanks to some inspiration from Daniel Rall).
XADataSource
/ConnectionPoolDataSource
code (experimental)
PreparedStatement.setAnyNumericType()
now
handles positive exponents correctly (adds
+
so MySQL can understand it).
DatabaseMetaData.getPrimaryKeys()
and
getBestRowIdentifier()
are now more robust
in identifying primary keys (matches regardless of case or
abbreviation/full spelling of Primary Key
in Key_type
column).
PreparedStatement.setCharacterStream()
now
implemented
Fixed dangling socket problem when in high availability
(autoReconnect=true
) mode, and finalizer
for Connection
will close any dangling
sockets on GC.
Fixed ResultSetMetaData.getPrecision()
returning one less than actual on newer versions of MySQL.
ResultSet.getBlob()
now returns
null
if column value was
null
.
Character sets read from database if
useUnicode=true
and
characterEncoding
is not set. (thanks to
Dmitry Vereshchagin)
Initial transaction isolation level read from database (if avaialable). (thanks to Dmitry Vereshchagin)
Fixed
DatabaseMetaData.supportsTransactions()
,
and supportsTransactionIsolationLevel()
and
getTypeInfo()
SQL_DATETIME_SUB
and
SQL_DATA_TYPE
fields not being readable.
Fixed PreparedStatement
generating SQL that
would end up with syntax errors for some queries.
Fixed ResultSet.isAfterLast()
always
returning false
.
Fixed time zone issue in
PreparedStatement.setTimestamp()
. (thanks
to Erik Olofsson)
Captialize type names when
captializeTypeNames=true
is passed in URL
or properties (for WebObjects. (thanks to Anjo Krank)
Updatable result sets now correctly handle
NULL
values in fields.
PreparedStatement.setDouble() now uses full-precision doubles (reverting a fix made earlier to truncate them).
PreparedStatement.setBoolean() will use 1/0 for values if your MySQL version is 3.21.23 or higher.
Fixed PreparedStatement
parameter checking.
Fixed case-sensitive column names in
ResultSet.java
.
Fixed ResultSet.getBlob()
ArrayIndex
out-of-bounds.
Fixed ResultSetMetaData.getColumnTypeName
for TEXT
/BLOB
.
Fixed ArrayIndexOutOfBounds
when sending
large BLOB
queries. (Max size packet was
not being set)
Added ISOLATION
level support to
Connection.setIsolationLevel()
Fixed NPE on
PreparedStatement.executeUpdate()
when all
columns have not been set.
Fixed data parsing of TIMESTAMP
values with
2-digit years.
Added Byte
to
PreparedStatement.setObject()
.
ResultSet.getBoolean()
now recognizes
-1
as true
.
ResultSet
has +/-Inf/inf support.
ResultSet.insertRow()
works now, even if
not all columns are set (they will be set to
NULL
).
DataBaseMetaData.getCrossReference()
no
longer ArrayIndexOOB
.
getObject()
on ResultSet
correctly does
TINYINT
->Byte
and
SMALLINT
->Short
.
Implemented getBigDecimal()
without scale
component for JDBC2.
Fixed composite key problem with updatable result sets.
Added detection of -/+INF for doubles.
Faster ASCII string operations.
Fixed incorrect detection of
MAX_ALLOWED_PACKET
, so sending large blobs
should work now.
Fixed off-by-one error in java.sql.Blob
implementation code.
Added ultraDevHack
URL parameter, set to
true
to allow (broken) Macromedia UltraDev
to use the driver.
Fixed RSMD.isWritable()
returning wrong
value. Thanks to Moritz Maass.
Cleaned up exception handling when driver connects.
Columns that are of type TEXT
now return as
Strings
when you use
getObject()
.
DatabaseMetaData.getPrimaryKeys()
now works
correctly with respect to key_seq
. Thanks
to Brian Slesinsky.
No escape processing is done on
PreparedStatements
anymore per JDBC spec.
Fixed many JDBC-2.0 traversal, positioning bugs, especially with respect to empty result sets. Thanks to Ron Smits, Nick Brook, Cessar Garcia and Carlos Martinez.
Fixed some issues with updatability support in
ResultSet
when using multiple primary keys.
Fixes to ResultSet for insertRow() - Thanks to Cesar Garcia
Fix to Driver to recognize JDBC-2.0 by loading a JDBC-2.0 class, instead of relying on JDK version numbers. Thanks to John Baker.
Fixed ResultSet to return correct row numbers
Statement.getUpdateCount() now returns rows matched, instead of rows actually updated, which is more SQL-92 like.
10-29-99
Statement/PreparedStatement.getMoreResults() bug fixed. Thanks to Noel J. Bergman.
Added Short as a type to PreparedStatement.setObject(). Thanks to Jeff Crowder
Driver now automagically configures maximum/preferred packet sizes by querying server.
Autoreconnect code uses fast ping command if server supports it.
Fixed various bugs with respect to packet sizing when reading from the server and when alloc'ing to write to the server.
Now compiles under JDK-1.2. The driver supports both JDK-1.1 and JDK-1.2 at the same time through a core set of classes. The driver will load the appropriate interface classes at runtime by figuring out which JVM version you are using.
Fixes for result sets with all nulls in the first row. (Pointed out by Tim Endres)
Fixes to column numbers in SQLExceptions in ResultSet (Thanks to Blas Rodriguez Somoza)
The database no longer needs to specified to connect. (Thanks to Christian Motschke)
Better Documentation (in progress), in doc/mm.doc/book1.html
DBMD now allows null for a column name pattern (not in spec), which it changes to '%'.
DBMD now has correct types/lengths for getXXX().
ResultSet.getDate(), getTime(), and getTimestamp() fixes. (contributed by Alan Wilken)
EscapeProcessor now handles \{ \} and { or } inside quotes correctly. (thanks to Alik for some ideas on how to fix it)
Fixes to properties handling in Connection. (contributed by Juho Tikkala)
ResultSet.getObject() now returns null for NULL columns in the table, rather than bombing out. (thanks to Ben Grosman)
ResultSet.getObject() now returns Strings for types from MySQL that it doesn't know about. (Suggested by Chris Perdue)
Removed DataInput/Output streams, not needed, 1/2 number of method calls per IO operation.
Use default character encoding if one is not specified. This is a work-around for broken JVMs, because according to spec, EVERY JVM must support "ISO8859_1", but they don't.
Fixed Connection to use the platform character encoding instead of "ISO8859_1" if one isn't explicitly set. This fixes problems people were having loading the character- converter classes that didn't always exist (JVM bug). (thanks to Fritz Elfert for pointing out this problem)
Changed MysqlIO to re-use packets where possible to reduce memory usage.
Fixed escape-processor bugs pertaining to {} inside quotes.
Fixed character-set support for non-Javasoft JVMs (thanks to many people for pointing it out)
Fixed ResultSet.getBoolean() to recognize 'y' & 'n' as well as '1' & '0' as boolean flags. (thanks to Tim Pizey)
Fixed ResultSet.getTimestamp() to give better performance. (thanks to Richard Swift)
Fixed getByte() for numeric types. (thanks to Ray Bellis)
Fixed DatabaseMetaData.getTypeInfo() for DATE type. (thanks to Paul Johnston)
Fixed EscapeProcessor for "fn" calls. (thanks to Piyush Shah at locomotive.org)
Fixed EscapeProcessor to not do extraneous work if there are no escape codes. (thanks to Ryan Gustafson)
Fixed Driver to parse URLs of the form "jdbc:mysql://host:port" (thanks to Richard Lobb)
Fixed Timestamps for PreparedStatements
Fixed null pointer exceptions in RSMD and RS
Re-compiled with jikes for valid class files (thanks ms!)
Fixed escape processor to deal with unmatched { and } (thanks to Craig Coles)
Fixed escape processor to create more portable (between DATETIME and TIMESTAMP types) representations so that it will work with BETWEEN clauses. (thanks to Craig Longman)
MysqlIO.quit() now closes the socket connection. Before, after many failed connections some OS's would run out of file descriptors. (thanks to Michael Brinkman)
Fixed NullPointerException in Driver.getPropertyInfo. (thanks to Dave Potts)
Fixes to MysqlDefs to allow all *text fields to be retrieved as Strings. (thanks to Chris at Leverage)
Fixed setDouble in PreparedStatement for large numbers to avoid sending scientific notation to the database. (thanks to J.S. Ferguson)
Fixed getScale() and getPrecision() in RSMD. (contrib'd by James Klicman)
Fixed getObject() when field was DECIMAL or NUMERIC (thanks to Bert Hobbs)
DBMD.getTables() bombed when passed a null table-name pattern. Fixed. (thanks to Richard Lobb)
Added check for "client not authorized" errors during connect. (thanks to Hannes Wallnoefer)
Result set rows are now byte arrays. Blobs and Unicode work bidriectonally now. The useUnicode and encoding options are implemented now.
Fixes to PreparedStatement to send binary set by setXXXStream to be sent untouched to the MySQL server.
Fixes to getDriverPropertyInfo().
Changed all ResultSet fields to Strings, this should allow Unicode to work, but your JVM must be able to convert between the character sets. This should also make reading data from the server be a bit quicker, because there is now no conversion from StringBuffer to String.
Changed PreparedStatement.streamToString() to be more efficient (code from Uwe Schaefer).
URL parsing is more robust (throws SQL exceptions on errors rather than NullPointerExceptions)
PreparedStatement now can convert Strings to Time/Date values via setObject() (code from Robert Currey).
IO no longer hangs in Buffer.readInt(), that bug was introduced in 1.1d when changing to all byte-arrays for result sets. (Pointed out by Samo Login)
Fixes to DatabaseMetaData to allow both IBM VA and J-Builder to work. Let me know how it goes. (thanks to Jac Kersing)
Fix to ResultSet.getBoolean() for NULL strings (thanks to Barry Lagerweij)
Beginning of code cleanup, and formatting. Getting ready to branch this off to a parallel JDBC-2.0 source tree.
Added "final" modifier to critical sections in MysqlIO and Buffer to allow compiler to inline methods for speed.
9-29-98
If object references passed to setXXX() in PreparedStatement are null, setNull() is automatically called for you. (Thanks for the suggestion goes to Erik Ostrom)
setObject() in PreparedStatement will now attempt to write a serialized representation of the object to the database for objects of Types.OTHER and objects of unknown type.
Util now has a static method readObject() which given a ResultSet and a column index will re-instantiate an object serialized in the above manner.
Got rid of "ugly hack" in MysqlIO.nextRow(). Rather than catch an exception, Buffer.isLastDataPacket() was fixed.
Connection.getCatalog() and Connection.setCatalog() should work now.
Statement.setMaxRows() works, as well as setting by property maxRows. Statement.setMaxRows() overrides maxRows set via properties or url parameters.
Automatic re-connection is available. Because it has to "ping" the database before each query, it is turned off by default. To use it, pass in "autoReconnect=true" in the connection URL. You may also change the number of reconnect tries, and the initial timeout value via "maxReconnects=n" (default 3) and "initialTimeout=n" (seconds, default 2) parameters. The timeout is an exponential backoff type of timeout; for example, if you have initial timeout of 2 seconds, and maxReconnects of 3, then the driver will timeout 2 seconds, 4 seconds, then 16 seconds between each re-connection attempt.
Fixed handling of blob data in Buffer.java
Fixed bug with authentication packet being sized too small.
The JDBC Driver is now under the LPGL
8-14-98
Fixed Buffer.readLenString() to correctly read data for BLOBS.
Fixed PreparedStatement.stringToStream to correctly read data for BLOBS.
Fixed PreparedStatement.setDate() to not add a day. (above fixes thanks to Vincent Partington)
Added URL parameter parsing (?user=... and so forth).
Big news! New package name. Tim Endres from ICE Engineering is starting a new source tree for GNU GPL'd Java software. He's graciously given me the org.gjt.mm package directory to use, so now the driver is in the org.gjt.mm.mysql package scheme. I'm "legal" now. Look for more information on Tim's project soon.
Now using dynamically sized packets to reduce memory usage when sending commands to the DB.
Small fixes to getTypeInfo() for parameters, and so forth.
DatabaseMetaData is now fully implemented. Let me know if these drivers work with the various IDEs out there. I've heard that they're working with JBuilder right now.
Added JavaDoc documentation to the package.
Package now available in .zip or .tar.gz.
Implemented getTypeInfo(). Connection.rollback() now throws an SQLException per the JDBC spec.
Added PreparedStatement that supports all JDBC API methods for PreparedStatement including InputStreams. Please check this out and let me know if anything is broken.
Fixed a bug in ResultSet that would break some queries that only returned 1 row.
Fixed bugs in DatabaseMetaData.getTables(), DatabaseMetaData.getColumns() and DatabaseMetaData.getCatalogs().
Added functionality to Statement that allows executeUpdate() to store values for IDs that are automatically generated for AUTO_INCREMENT fields. Basically, after an executeUpdate(), look at the SQLWarnings for warnings like "LAST_INSERTED_ID = 'some number', COMMAND = 'your SQL query'". If you are using AUTO_INCREMENT fields in your tables and are executing a lot of executeUpdate()s on one Statement, be sure to clearWarnings() every so often to save memory.
Split MysqlIO and Buffer to separate classes. Some ClassLoaders gave an IllegalAccess error for some fields in those two classes. Now mm.mysql works in applets and all classloaders. Thanks to Joe Ennis <jce@mail.boone.com> for pointing out the problem and working on a fix with me.
Fixed DatabaseMetadata problems in getColumns() and bug in switch statement in the Field constructor. Thanks to Costin Manolache <costin@tdiinc.com> for pointing these out.
Incorporated efficiency changes from Richard Swift
<Richard.Swift@kanatek.ca> in
MysqlIO.java
and
ResultSet.java
:
We're now 15% faster than gwe's driver.
Started working on DatabaseMetaData
.
The following methods are implemented:
getTables()
getTableTypes()
getColumns
getCatalogs()
Inhaltsverzeichnis
This appendix helps you port MySQL to other operating systems. Do check the list of currently supported operating systems first. See Abschnitt 2.1.1, „Betriebssysteme, die von MySQL unterstützt werden“. If you have created a new port of MySQL, please let us know so that we can list it here and on our Web site (http://www.mysql.com/), recommending it to other users.
Note: If you create a new port of MySQL, you are free to copy and distribute it under the GPL license, but it does not make you a copyright holder of MySQL.
A working POSIX thread library is needed for the server. On Solaris
2.5 we use Sun PThreads (the native thread support in 2.4 and
earlier versions is not good enough), on Linux we use LinuxThreads
by Xavier Leroy, <Xavier.Leroy@inria.fr>
.
The hard part of porting to a new Unix variant without good native
thread support is probably to port MIT-pthreads. See
mit-pthreads/README
and Programming POSIX
Threads (http://www.humanfactor.com/pthreads/).
Up to MySQL 4.0.2, the MySQL distribution included a patched version of Chris Provenzano's Pthreads from MIT (see the MIT Pthreads Web page at http://www.mit.edu/afs/sipb/project/pthreads/ and a programming introduction at http://www.mit.edu:8001/people/proven/IAP_2000/). These can be used for some operating systems that do not have POSIX threads. See Abschnitt 2.8.5, „Anmerkungen zu MIT-pthreads“.
It is also possible to use another user level thread package named FSU Pthreads (see http://moss.csc.ncsu.edu/~mueller/pthreads/). This implementation is being used for the SCO port.
See the thr_lock.c
and
thr_alarm.c
programs in the
mysys
directory for some tests/examples of
these problems.
Both the server and the client need a working C++ compiler. We use gcc on many platforms. Other compilers that are known to work are SPARCworks, Sun Forte, Irix cc, HP-UX aCC, IBM AIX xlC_r), Intel ecc/icc and Compaq cxx).
To compile only the client use ./configure --without-server.
There is currently no support for only compiling the server, nor is it likely to be added unless someone has a good reason for it.
If you want/need to change any Makefile
or the
configure script you also need GNU Automake and Autoconf. See
Abschnitt 2.8.3, „Installation vom Entwicklungs-Source-Tree“.
All steps needed to remake everything from the most basic files.
/bin/rm */.deps/*.P /bin/rm -f config.cache aclocal autoheader aclocal automake autoconf ./configure --with-debug=full --prefix='your installation directory' # The makefiles generated above need GNU make 3.75 or newer. # (called gmake below) gmake clean all install init-db
If you run into problems with a new port, you may have to do some debugging of MySQL! See Abschnitt E.1, „Einen MySQL-Server debuggen“.
Note: Before you start debugging
mysqld, first get the test programs
mysys/thr_alarm
and
mysys/thr_lock
to work. This ensures that your
thread installation has even a remote chance to work!
If you are using some functionality that is very new in MySQL, you
can try to run mysqld with the
--skip-new
(which disables all new, potentially
unsafe functionality) or with --safe-mode
which
disables a lot of optimization that may cause problems. See
Abschnitt A.4.2, „Was zu tun ist, wenn MySQL andauernd abstürzt“.
If mysqld doesn't want to start, you should
verify that you don't have any my.cnf
files
that interfere with your setup! You can check your
my.cnf
arguments with mysqld
--print-defaults and avoid using them by starting with
mysqld --no-defaults ....
If mysqld starts to eat up CPU or memory or if it „hangs,“ you can use mysqladmin processlist status to find out if someone is executing a query that takes a long time. It may be a good idea to run mysqladmin -i10 processlist status in some window if you are experiencing performance problems or problems when new clients can't connect.
The command mysqladmin debug dumps some information about locks in use, used memory and query usage to the MySQL log file. This may help solve some problems. This command also provides some useful information even if you haven't compiled MySQL for debugging!
If the problem is that some tables are getting slower and slower
you should try to optimize the table with OPTIMIZE
TABLE
or myisamchk. See
Kapitel 5, Datenbankverwaltung. You should also check
the slow queries with EXPLAIN
.
You should also read the OS-specific section in this manual for problems that may be unique to your environment. See Abschnitt 2.12, „Betriebssystemspezifische Anmerkungen“.
If you have some very specific problem, you can always try to
debug MySQL. To do this you must configure MySQL with the
--with-debug
or the
--with-debug=full
option. You can check whether
MySQL was compiled with debugging by doing: mysqld
--help. If the --debug
flag is listed
with the options then you have debugging enabled.
mysqladmin ver also lists the
mysqld version as mysql ...
--debug in this case.
If you are using gcc or egcs, the recommended configure line is:
CC=gcc CFLAGS="-O2" CXX=gcc CXXFLAGS="-O2 -felide-constructors \ -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql \ --with-debug --with-extra-charsets=complex
This avoids problems with the libstdc++
library and with C++ exceptions (many compilers have problems
with C++ exceptions in threaded code) and compile a MySQL
version with support for all character sets.
If you suspect a memory overrun error, you can configure MySQL
with --with-debug=full
, which installs a memory
allocation (SAFEMALLOC
) checker. However,
running with SAFEMALLOC
is quite slow, so if
you get performance problems you should start
mysqld with the
--skip-safemalloc
option. This disables the
memory overrun checks for each call to
malloc()
and free()
.
If mysqld stops crashing when you compile it
with --with-debug
, you probably have found a
compiler bug or a timing bug within MySQL. In this case, you can
try to add -g
to the CFLAGS
and CXXFLAGS
variables above and not use
--with-debug
. If mysqld
dies, you can at least attach to it with gdb
or use gdb on the core file to find out what
happened.
When you configure MySQL for debugging you automatically enable
a lot of extra safety check functions that monitor the health of
mysqld. If they find something
„unexpected,“ an entry is written to
stderr
, which safe_mysqld
directs to the error log! This also means that if you are having
some unexpected problems with MySQL and are using a source
distribution, the first thing you should do is to configure
MySQL for debugging! (The second thing is to send mail to a
MySQL mailing list and ask for help. See
Abschnitt 1.7.1, „Die MySQL-Mailinglisten“. If you believe that you have
found a bug, please use the instructions at
Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“.
In the Windows MySQL distribution, mysqld.exe
is by default compiled with support for trace files.
If the mysqld server doesn't start or if you can cause it to crash quickly, you can try to create a trace file to find the problem.
To do this, you must have a mysqld that has
been compiled with debugging support. You can check this by
executing mysqld -V
. If the version number
ends with -debug
, it's compiled with support
for trace files. (On Windows, the debugging server is named
mysqld-debug rather than
mysqld as of MySQL 4.1.)
Start the mysqld server with a trace log in
/tmp/mysqld.trace
on Unix or
C:\mysqld.trace
on Windows:
shell> mysqld --debug
On Windows, you should also use the
--standalone
flag to not start
mysqld as a service. In a console window, use
this command:
C:\> mysqld-debug --debug --standalone
After this, you can use the mysql.exe
command-line tool in a second console window to reproduce the
problem. You can stop the mysqld server with
mysqladmin shutdown.
Note that the trace file become very big! If you want to generate a smaller trace file, you can use debugging options something like this:
mysqld --debug=d,info,error,query,general,where:O,/tmp/mysqld.trace
This only prints information with the most interesting tags to the trace file.
If you make a bug report about this, please only send the lines from the trace file to the appropriate mailing list where something seems to go wrong! If you can't locate the wrong place, you can ftp the trace file, together with a full bug report, to ftp://ftp.mysql.com/pub/mysql/upload/ so that a MySQL developer can take a look a this.
The trace file is made with the DBUG package by Fred Fish. See Abschnitt E.3, „Das DBUG-Paket“.
On most systems you can also start mysqld from gdb to get more information if mysqld crashes.
With some older gdb versions on Linux you
must use run --one-thread
if you want to be
able to debug mysqld threads. In this case,
you can only have one thread active at a time. We recommend you
to upgrade to gdb 5.1 ASAP as thread debugging works much better
with this version!
NTPL threads (the new thread library on Linux) may cause problems while running mysqld under gdb. Some symptoms are:
mysqld hangs during startup (before it
writes ready for connections
).
mysqld crashes during a
pthread_mutex_lock()
or
pthread_mutex_unlock()
call.
In this case, you should set the following environment variable in the shell before starting gdb:
LD_ASSUME_KERNEL=2.4.1 export LD_ASSUME_KERNEL
When running mysqld under
gdb, you should disable the stack trace with
--skip-stack-trace
to be able to catch
segfaults within gdb.
In MySQL 4.0.14 and above you should use the
--gdb
option to mysqld. This installs an
interrupt handler for SIGINT
(needed to stop
mysqld with ^C
to set
breakpoints) and disable stack tracing and core file handling.
It's very hard to debug MySQL under gdb if
you do a lot of new connections the whole time as
gdb doesn't free the memory for old threads.
You can avoid this problem by starting mysqld
with --thread_cache_size='max_connections+1'
.
In most cases just using --thread_cache_size=5'
helps a lot!
If you want to get a core dump on Linux if
mysqld dies with a SIGSEGV signal, you can
start mysqld with the
--core-file
option. This core file can be used
to make a backtrace that may help you find out why
mysqld died:
shell> gdb mysqld core
gdb> backtrace full
gdb> exit
See Abschnitt A.4.2, „Was zu tun ist, wenn MySQL andauernd abstürzt“.
If you are using gdb 4.17.x or above on
Linux, you should install a .gdb
file, with
the following information, in your current directory:
set print sevenbit off handle SIGUSR1 nostop noprint handle SIGUSR2 nostop noprint handle SIGWAITING nostop noprint handle SIGLWP nostop noprint handle SIGPIPE nostop handle SIGALRM nostop handle SIGHUP nostop handle SIGTERM nostop noprint
If you have problems debugging threads with gdb, you should download gdb 5.x and try this instead. The new gdb version has very improved thread handling!
Here is an example how to debug mysqld:
shell> gdb /usr/local/libexec/mysqld
gdb> run
...
backtrace full # Do this when mysqld crashes
Include the above output in a bug report, which you can file using the instructions in Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“.
If mysqld hangs you can try to use some
system tools like strace
or
/usr/proc/bin/pstack
to examine where
mysqld has hung.
strace /tmp/log libexec/mysqld
If you are using the Perl DBI
interface, you
can turn on debugging information by using the
trace
method or by setting the
DBI_TRACE
environment variable.
On some operating systems, the error log contains a stack trace
if mysqld dies unexpectedly. You can use this
to find out where (and maybe why) mysqld
died. See Abschnitt 5.12.1, „Die Fehler-Logdatei“. To get a stack trace, you
must not compile mysqld with the
-fomit-frame-pointer
option to gcc. See
Abschnitt E.1.1, „MySQL zum Debuggen kompilieren“.
If the error file contains something like the following:
mysqld got signal 11; The manual section 'Debugging a MySQL server' tells you how to use a stack trace and/or the core file to produce a readable backtrace that may help in finding out why mysqld died Attempting backtrace. You can use the following information to find out where mysqld died. If you see no messages after this, something went terribly wrong... stack range sanity check, ok, backtrace follows 0x40077552 0x81281a0 0x8128f47 0x8127be0 0x8127995 0x8104947 0x80ff28f 0x810131b 0x80ee4bc 0x80c3c91 0x80c6b43 0x80c1fd9 0x80c1686
you can find where mysqld died by doing the following:
Copy the preceding numbers to a file, for example
mysqld.stack
.
Make a symbol file for the mysqld server:
nm -n libexec/mysqld > /tmp/mysqld.sym
Note that most MySQL binary distributions (except for the
"debug" packages, where this information is included inside
of the binaries themselves) ship with the above file, named
mysqld.sym.gz
. In this case, you can
simply unpack it by doing:
gunzip < bin/mysqld.sym.gz > /tmp/mysqld.sym
Execute resolve_stack_dump -s /tmp/mysqld.sym -n
mysqld.stack
.
This prints out where mysqld died. If this doesn't help you find out why mysqld died, you should make a bug report and include the output from the above command with the bug report.
Note however that in most cases it does not help us to just have a stack trace to find the reason for the problem. To be able to locate the bug or provide a workaround, we would in most cases need to know the query that killed mysqld and preferable a test case so that we can repeat the problem! See Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“.
Note that before starting mysqld with
--log
you should check all your tables with
myisamchk. See
Kapitel 5, Datenbankverwaltung.
If mysqld dies or hangs, you should start
mysqld with --log
. When
mysqld dies again, you can examine the end of
the log file for the query that killed
mysqld.
If you are using --log
without a file name, the
log is stored in the database directory as
In
most cases it is the last query in the log file that killed
mysqld, but if possible you should verify
this by restarting mysqld and executing the
found query from the mysql command-line
tools. If this works, you should also test all complicated
queries that didn't complete.
host_name
.log
You can also try the command EXPLAIN
on all
SELECT
statements that takes a long time to
ensure that mysqld is using indexes properly.
See Abschnitt 7.2.1, „EXPLAIN
-Syntax (Informationen über ein
SELECT
erhalten)“.
You can find the queries that take a long time to execute by
starting mysqld with
--log-slow-queries
. See
Abschnitt 5.12.4, „Die Logdatei für langsame Anfragen“.
If you find the text mysqld restarted
in the
error log file (normally named
hostname.err
) you probably have found a
query that causes mysqld to fail. If this
happens, you should check all your tables with
myisamchk (see
Kapitel 5, Datenbankverwaltung), and test the queries
in the MySQL log files to see whether one fails. If you find
such a query, try first upgrading to the newest MySQL version.
If this doesn't help and you can't find anything in the
mysql
mail archive, you should report the bug
to a MySQL mailing list. The mailing lists are described at
http://lists.mysql.com/, which also has links to
online list archives.
If you have started mysqld with
myisam-recover
, MySQL automatically checks
and tries to repair MyISAM
tables if they are
marked as 'not closed properly' or 'crashed'. If this happens,
MySQL writes an entry in the hostname.err
file 'Warning: Checking table ...'
which is
followed by Warning: Repairing table
if the
table needs to be repaired. If you get a lot of these errors,
without mysqld having died unexpectedly just
before, then something is wrong and needs to be investigated
further. See Abschnitt 5.2.1, „Befehlsoptionen für mysqld“.
It is not a good sign if mysqld did die
unexpectedly, but in this case, you should not investigate the
Checking table...
messages, but instead try
to find out why mysqld died.
If you get corrupted tables or if mysqld always fails after some update commands, you can test whether this bug is reproducible by doing the following:
Take down the MySQL daemon (with mysqladmin shutdown).
Make a backup of the tables (to guard against the very unlikely case that the repair does something bad).
Check all tables with myisamchk -s
database/*.MYI. Repair any wrong tables with
myisamchk -r
database/table
.MYI.
Make a second backup of the tables.
Remove (or move away) any old log files from the MySQL data directory if you need more space.
Start mysqld with
--log-bin
. See
Abschnitt 5.12.3, „Die binäre Update-Logdatei“. If you want to find a query
that crashes mysqld, you should use
--log --log-bin
.
When you have gotten a crashed table, stop the
mysqld server
.
Restore the backup.
Restart the mysqld server
without
--log-bin
Re-execute the commands with mysqlbinlog
update-log-file | mysql. The update log is saved
in the MySQL database directory with the name
hostname-bin.#
.
If the tables are corrupted again or you can get
mysqld to die with the above command, you
have found reproducible bug that should be easy to fix! FTP
the tables and the binary log to
ftp://ftp.mysql.com/pub/mysql/upload/ and
report it in our bugs database using the instructions given
in Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“. (Please note that the
/pub/mysql/upload/
FTP directory is not
listable, so you'll not see what you've uploaded in your FTP
client.) If you are a support customer, you can use the
MySQL Customer Support Center
https://support.mysql.com/ to alert the MySQL
team about the problem and have it fixed as soon as
possible.
You can also use the script mysql_find_rows
to just execute some of the update statements if you want to
narrow down the problem.
To be able to debug a MySQL client with the integrated debug
package, you should configure MySQL with
--with-debug
or
--with-debug=full
. See
Abschnitt 2.8.2, „Typische configure-Optionen“.
Before running a client, you should set the
MYSQL_DEBUG
environment variable:
shell>MYSQL_DEBUG=d:t:O,/tmp/client.trace
shell>export MYSQL_DEBUG
This causes clients to generate a trace file in
/tmp/client.trace
.
If you have problems with your own client code, you should attempt to connect to the server and run your query using a client that is known to work. Do this by running mysql in debugging mode (assuming that you have compiled MySQL with debugging on):
shell> mysql --debug=d:t:O,/tmp/client.trace
This provides useful information in case you mail a bug report. See Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“.
If your client crashes at some 'legal' looking code, you should
check that your mysql.h
include file matches
your MySQL library file. A very common mistake is to use an old
mysql.h
file from an old MySQL installation
with new MySQL library.
The MySQL server and most MySQL clients are compiled with the DBUG package originally created by Fred Fish. When you have configured MySQL for debugging, this package makes it possible to get a trace file of what the program is debugging. See Abschnitt E.1.2, „Trace-Dateien erzeugen“.
This section summaries the argument values that you can specify in
debug options on the command line for MySQL programs that have
been built with debugging support. For more information about
programming with the DBUG package, see the DBUG manual in the
dbug
directory of MySQL source distributions.
It's best to use a recent distribution for MySQL 5.1
to get the most updated DBUG manual.
You use the debug package by invoking a program with the
--debug="..."
or the -#...
option.
Most MySQL programs have a default debug string that is used if
you don't specify an option to --debug
. The
default trace file is usually
/tmp/program_name.trace
on Unix and
\program_name.trace
on Windows.
The debug control string is a sequence of colon-separated fields as follows:
<field_1>:<field_2>:...:<field_N>
Each field consists of a mandatory flag character followed by an
optional ‘,
’ and comma-separated
list of modifiers:
flag[,modifier,modifier,...,modifier]
The currently recognized flag characters are:
Flag | Description |
d | Enable output from DBUG_<N> macros for the current state. May be followed by a list of keywords which selects output only for the DBUG macros with that keyword. An empty list of keywords implies output for all macros. |
D | Delay after each debugger output line. The argument is the number of
tenths of seconds to delay, subject to machine
capabilities. For example, -#D,20
specifies a delay of two seconds. |
f | Limit debugging, tracing, and profiling to the list of named functions.
Note that a null list disables all functions. The
appropriate d or t
flags must still be given; this flag only limits their
actions if they are enabled. |
F | Identify the source file name for each line of debug or trace output. |
i | Identify the process with the PID or thread ID for each line of debug or trace output. |
g | Enable profiling. Create a file called dbugmon.out
containing information that can be used to profile the
program. May be followed by a list of keywords that select
profiling only for the functions in that list. A null list
implies that all functions are considered. |
L | Identify the source file line number for each line of debug or trace output. |
n | Print the current function nesting depth for each line of debug or trace output. |
N | Number each line of debug output. |
o | Redirect the debugger output stream to the specified file. The default
output is stderr . |
O | Like o , but the file is really flushed between each
write. When needed, the file is closed and reopened
between each write. |
p | Limit debugger actions to specified processes. A process must be
identified with the DBUG_PROCESS macro
and match one in the list for debugger actions to occur. |
P | Print the current process name for each line of debug or trace output. |
r | When pushing a new state, do not inherit the previous state's function nesting level. Useful when the output is to start at the left margin. |
S | Do function _sanity(_file_,_line_) at each debugged
function until _sanity() returns
something that differs from 0. (Mostly used with
safemalloc to find memory leaks) |
t | Enable function call/exit trace lines. May be followed by a list (containing only one modifier) giving a numeric maximum trace level, beyond which no output occurs for either debugging or tracing macros. The default is a compile time option. |
Some examples of debug control strings that might appear on a
shell command line (the -#
is typically used to
introduce a control string to an application program) are:
-#d:t -#d:f,main,subr1:F:L:t,20 -#d,input,output,files:n -#d:t:i:O,\\mysqld.trace
In MySQL, common tags to print (with the d
option) are enter
, exit
,
error
, warning
,
info
, and loop
.
I have tried to use the RTS thread packages with MySQL but stumbled on the following problems:
They use old versions of many POSIX calls and it is very tedious to make wrappers for all functions. I am inclined to think that it would be easier to change the thread libraries to the newest POSIX specification.
Some wrappers are currently written. See
mysys/my_pthread.c
for more info.
At least the following should be changed:
pthread_get_specific
should use one argument.
sigwait
should take two arguments. A lot of
functions (at least pthread_cond_wait
,
pthread_cond_timedwait()
) should return the
error code on error. Now they return -1 and set
errno
.
Another problem is that user-level threads use the
ALRM
signal and this aborts a lot of functions
(read
, write
,
open
...). MySQL should do a retry on interrupt
on all of these but it is not that easy to verify it.
The biggest unsolved problem is the following:
To get thread-level alarms I changed
mysys/thr_alarm.c
to wait between alarms with
pthread_cond_timedwait()
, but this aborts with
error EINTR
. I tried to debug the thread
library as to why this happens, but couldn't find any easy
solution.
If someone wants to try MySQL with RTS threads I suggest the following:
Change functions MySQL uses from the thread library to POSIX. This shouldn't take that long.
Compile all libraries with the
-DHAVE_rts_threads
.
Compile thr_alarm
.
If there are some small differences in the implementation,
they may be fixed by changing
my_pthread.h
and
my_pthread.c
.
Run thr_alarm
. If it runs without any
„warning,“ „error,“ or aborted
messages, you are on the right track. Here is a successful run
on Solaris:
Main thread: 1 Thread 0 (5) started Thread: 5 Waiting process_alarm Thread 1 (6) started Thread: 6 Waiting process_alarm process_alarm thread_alarm Thread: 6 Slept for 1 (1) sec Thread: 6 Waiting process_alarm process_alarm thread_alarm Thread: 6 Slept for 2 (2) sec Thread: 6 Simulation of no alarm needed Thread: 6 Slept for 0 (3) sec Thread: 6 Waiting process_alarm process_alarm thread_alarm Thread: 6 Slept for 4 (4) sec Thread: 6 Waiting process_alarm thread_alarm Thread: 5 Slept for 10 (10) sec Thread: 5 Waiting process_alarm process_alarm thread_alarm Thread: 6 Slept for 5 (5) sec Thread: 6 Waiting process_alarm process_alarm ... thread_alarm Thread: 5 Slept for 0 (1) sec end
MySQL is very dependent on the thread package used. So when choosing a good platform for MySQL, the thread package is very important.
There are at least three types of thread packages:
User threads in a single process. Thread switching is managed with alarms and the threads library manages all non-thread-safe functions with locks. Read, write and select operations are usually managed with a thread-specific select that switches to another thread if the running threads have to wait for data. If the user thread packages are integrated in the standard libs (FreeBSD and BSDI threads) the thread package requires less overhead than thread packages that have to map all unsafe calls (MIT-pthreads, FSU Pthreads and RTS threads). In some environments (for example, SCO), all system calls are thread-safe so the mapping can be done very easily (FSU Pthreads on SCO). Downside: All mapped calls take a little time and it's quite tricky to be able to handle all situations. There are usually also some system calls that are not handled by the thread package (like MIT-pthreads and sockets). Thread scheduling isn't always optimal.
User threads in separate processes. Thread switching is done by the kernel and all data are shared between threads. The thread package manages the standard thread calls to allow sharing data between threads. LinuxThreads is using this method. Downside: Lots of processes. Thread creating is slow. If one thread dies the rest are usually left hanging and you must kill them all before restarting. Thread switching is somewhat expensive.
Kernel threads. Thread switching is handled by the thread library or the kernel and is very fast. Everything is done in one process, but on some systems, ps may show the different threads. If one thread aborts, the whole process aborts. Most system calls are thread-safe and should require very little overhead. Solaris, HP-UX, AIX and OSF/1 have kernel threads.
In some systems kernel threads are managed by integrating user level threads in the system libraries. In such cases, the thread switching can only be done by the thread library and the kernel isn't really „thread aware.“
This appendix lists all the environment variables that are used directly or indirectly by MySQL. Most of these can also be found in other places in this manual.
Note that any options on the command line take precedence over values specified in option files and environment variables, and values in option files take precedence over values in environment variables.
In many cases, it is preferable to use an option file instead of environment variables to modify the behavior of MySQL. See Abschnitt 4.3.2, „my.cnf-Optionsdateien“.
Variable | Description |
CXX | The name of your C++ compiler (for running configure). |
CC | The name of your C compiler (for running configure). |
CFLAGS | Flags for your C compiler (for running configure). |
CXXFLAGS | Flags for your C++ compiler (for running configure). |
DBI_USER | The default username for Perl DBI. |
DBI_TRACE | Trace options for Perl DBI. |
HOME | The default path for the mysql history file is
$HOME/.mysql_history . |
LD_RUN_PATH | Used to specify the location of libmysqlclient.so . |
MYSQL_DEBUG | Debug trace options when debugging. |
MYSQL_HISTFILE | The path to the mysql history file. If this variable
is set, its value overrides the default for
$HOME/.mysql_history . |
MYSQL_HOST | The default hostname used by the mysql command-line client. |
MYSQL_PS1 | The command prompt to use in the mysql command-line client. |
MYSQL_PWD | The default password when connecting to mysqld. Note that using this is insecure. See Abschnitt 5.9.6, „Wie Sie Ihre Kennwörter sicher halten“. |
MYSQL_TCP_PORT | The default TCP/IP port number. |
MYSQL_UNIX_PORT | The default Unix socket filename; used for connections to
localhost . |
PATH | Used by the shell to find MySQL programs. |
TMPDIR | The directory where temporary files are created. |
TZ | This should be set to your local time zone. See Abschnitt A.4.6, „Probleme mit Zeitzonen“. |
UMASK_DIR | The user-directory creation mask when creating directories. Note that
this is AND ed with
UMASK . |
UMASK | The user-file creation mask when creating files. |
USER | The default username on Windows and NetWare used when connecting to mysqld. |
Ein regulärer Ausdruck ist ein mächtiges Werkzeug, um ein Muster für eine komplexe Suchoperation zu spezifizieren.
MySQL verwendet Henry Spencers Implementierung für reguläre
Ausdrücke, die auf POSIX 1003.2 zugeschnitten ist. Siehe auch
Anhang C, Danksagungen. MySQL benutzt die erweiterte Version, um
Mustererkennung mit dem REGEXP
-Operator in
SQL-Anweisungen zu ermöglichen. Siehe hierzu
Abschnitt 3.3.4.7, „Übereinstimmende Suchmuster“, und
Abschnitt 12.3.1, „String-Vergleichsfunktionen“.
Dieser Anhang fasst mit Beispielen die Sonderzeichen und Konstrukte
zusammen, die in MySQL für REGEXP
-Operationen
eingesetzt werden können. Wir wiederholen hier nicht jedes Detail
von Henry Spencers regex(7)
-Handbuchseite. Diese
Seite ist in den Quelldistributionen von MySQL inbegriffen, nämlich
in der Datei regex.7
unter dem Verzeichnis
regex
.
Ein regulärer Ausdruck beschreibt eine Menge von Strings. Der
einfachste reguläre Ausdruck ist einer ohne Sonderzeichen. So
erkennt beispielsweise der reguläre Ausdruck
hello
nichts anderes als den String
hello
.
Nichttriviale reguläre Ausdrücke verwenden spezielle Konstrukte,
um mehr als nur einen einzigen String erkennen zu können. So passt
beispielsweise der reguläre Ausdruck hello|word
entweder auf den String hello
oder auf den String
word
.
Als komplexeres Beispiel erkennt der reguläre Ausdruck
B[an]*s
die Strings Bananas
,
Baaaaas
, Bs
und und alle
anderen Strings, die mit B
anfangen, mit
s
enden und beliebig viele a
-
oder n
-Zeichen dazwischen aufweisen.
Ein regulärer Ausdruck für den REGEXP
-Operator
kann alle folgenden Sonderzeichen und Konstrukte benutzen:
^
Den Anfang eines Strings erkennen.
mysql>SELECT 'fo\nfo' REGEXP '^fo$';
-> 0 mysql>SELECT 'fofo' REGEXP '^fo';
-> 1
$
Das Ende eines Strings erkennen.
mysql>SELECT 'fo\no' REGEXP '^fo\no$';
-> 1 mysql>SELECT 'fo\no' REGEXP '^fo$';
-> 0
.
Irgendwelche Zeichen erkennen (einschließlich Carriage Return und Newline).
mysql>SELECT 'fofo' REGEXP '^f.*$';
-> 1 mysql>SELECT 'fo\r\nfo' REGEXP '^f.*$';
-> 1
a*
Irgendeine Folge von null oder mehr a
-Zeichen
erkennen.
mysql>SELECT 'Ban' REGEXP '^Ba*n';
-> 1 mysql>SELECT 'Baaan' REGEXP '^Ba*n';
-> 1 mysql>SELECT 'Bn' REGEXP '^Ba*n';
-> 1
a+
Irgendeine Folge von einem oder mehr
a
-Zeichen erkennen.
mysql>SELECT 'Ban' REGEXP '^Ba+n';
-> 1 mysql>SELECT 'Bn' REGEXP '^Ba+n';
-> 0
a?
Null oder ein a
-Zeichen erkennen.
mysql>SELECT 'Bn' REGEXP '^Ba?n';
-> 1 mysql>SELECT 'Ban' REGEXP '^Ba?n';
-> 1 mysql>SELECT 'Baan' REGEXP '^Ba?n';
-> 0
de|abc
Eine der Zeichenfolgen de
oder
abc
erkennen.
mysql>SELECT 'pi' REGEXP 'pi|apa';
-> 1 mysql>SELECT 'axe' REGEXP 'pi|apa';
-> 0 mysql>SELECT 'apa' REGEXP 'pi|apa';
-> 1 mysql>SELECT 'apa' REGEXP '^(pi|apa)$';
-> 1 mysql>SELECT 'pi' REGEXP '^(pi|apa)$';
-> 1 mysql>SELECT 'pix' REGEXP '^(pi|apa)$';
-> 0
(abc)*
Null oder mehr Instanzen der Zeichenfolge abc
erkennen.
mysql>SELECT 'pi' REGEXP '^(pi)*$';
-> 1 mysql>SELECT 'pip' REGEXP '^(pi)*$';
-> 0 mysql>SELECT 'pipi' REGEXP '^(pi)*$';
-> 1
{1}
, {2,3}
Die {n}
- oder
{m,n}
-Notation bietet eine
allgemeingültigere Möglichkeit, reguläre Ausdrücke zu
schreiben, die viele Exemplare des vorangehenden atomaren
Bestandteils (oder „Teils“) des Musters erkennen.
m
und n
sind Integer.
a*
Kann als a{0,}
geschrieben werden.
a+
Kann als a{1,}
geschrieben werden.
a?
Kann als a{0,1}
geschrieben werden.
Genauer gesagt: a{n}
erkennt genau
n
Instanzen von a
.
a{n,}
erkennt n
oder mehr
Instanzen von a
. a{m,n}
erkennt m
bis einschließlich
n
Instanzen von a
.
m
und n
müssen zwischen
0
und RE_DUP_MAX
(Standardwert 255) einschließlich liegen. Sind sowohl
m
als auch n
angegeben,
muss m
kleiner oder gleich
n
sein.
mysql>SELECT 'abcde' REGEXP 'a[bcd]{2}e';
-> 0 mysql>SELECT 'abcde' REGEXP 'a[bcd]{3}e';
-> 1 mysql>SELECT 'abcde' REGEXP 'a[bcd]{1,10}e';
-> 1
[a-dX]
, [^a-dX]
Erkennt jedes Zeichen, das gleich (oder, wenn ^ verwendet wird,
ungleich) a
, b
,
c
, d
oder
X
ist. Ein -
-Zeichen
zwischen zwei anderen Zeichen bildet einen Bereich, der alle
Zeichen vom ersten bis zum zweiten erkennt. So erkennt
beispielsweise [0-9]
jede Ziffer des
Dezimalsystems. Um das Literalzeichen ]
einzubinden, muss dieses unmittelbar hinter der öffnenden
eckigen Klammer [
stehen. Um ein
Literalzeichen -
einzubinden, muss es als
erstes oder letztes Zeichen geschrieben werden. Jedes Zeichen
innerhalb eines Klammerpaars []
, das keine
definierte Sonderbedeutung hat, erkennt nur sich selbst.
mysql>SELECT 'aXbc' REGEXP '[a-dXYZ]';
-> 1 mysql>SELECT 'aXbc' REGEXP '^[a-dXYZ]$';
-> 0 mysql>SELECT 'aXbc' REGEXP '^[a-dXYZ]+$';
-> 1 mysql>SELECT 'aXbc' REGEXP '^[^a-dXYZ]+$';
-> 0 mysql>SELECT 'gheis' REGEXP '^[^a-dXYZ]+$';
-> 1 mysql>SELECT 'gheisa' REGEXP '^[^a-dXYZ]+$';
-> 0
[.characters.]
In einem Ausdruck in eckigen Klammern ([
und
]
) wird hiermit die Zeichenfolge dieses
Kollationselements erkannt. characters
ist
entweder ein einzelnes Zeichen oder ein Zeichenname wie
newline
. Die vollständige Liste der
Zeichennamen finden Sie in der Datei
regexp/cname.h
.
mysql>SELECT '~' REGEXP '[[.~.]]';
-> 1 mysql>SELECT '~' REGEXP '[[.tilde.]]';
-> 1
[=character_class=]
In einem Ausdruck in eckigen Klammern ([
und
]
) stellt
[=character_class=]
eine Äquivalenzklasse
dar. Sie erkennt alle Zeichen mit demselben Kollationswert
einschließlich sich selbst. Wenn beispielsweise
o
und (+)
die Elemente der
Äquivalenzklasse sind, dann sind [[=o=]]
,
[[=(+)=]]
und [o(+)]
alle
synonym. Eine Äquivalenzklasse darf nicht als Endpunkt eines
Bereichs verwendet werden.
[:character_class:]
In einem Ausdruck in eckigen Klammern ([
und
]
) stellt
[:character_class:]
eine Zeichenklasse dar,
die alle zu dieser Klasse gehörigen Zeichen erkennt. Die
folgende Tabelle listet die Standardklassennamen auf. Es sind
die Namen der Zeichenklassen, die auf der Handbuchseite
ctype(3)
definiert sind. Die Klassennamen
können in manchen Spracheinstellungen andere sein. Eine
Zeichenklasse darf nicht als Endpunkt eines Bereichs verwendet
werden.
alnum | Alphanumerische Zeichen |
alpha | Alphabetische Zeichen |
blank | Whitespace-Zeichen |
cntrl | Steuerzeichen |
digit | Ziffernzeichen |
graph | Graphische Zeichen |
lower | Kleinbuchstaben |
print | Graphische oder Leerzeichen |
punct | Interpunktionszeichen |
space | Leerzeichen, Tabulator, Newline und Carriage Return |
upper | Großbuchstaben |
xdigit | Hexadezimalziffern |
mysql>SELECT 'justalnums' REGEXP '[[:alnum:]]+';
-> 1 mysql>SELECT '!!' REGEXP '[[:alnum:]]+';
-> 0
[[:<:]]
, [[:>:]]
Diese Markierungen bedeuten Wortgrenzen. Sie erkennen den Anfang
und das Ende eines Worts. Ein Wort ist eine Folge von
Wortzeichen, denen kein weiteres Wortzeichen voransteht oder
folgt. Ein Wortzeichen ist ein alphanumerisches Zeichen aus der
Klasse alnum
oder ein Unterstrich
(_
).
mysql>SELECT 'a word a' REGEXP '[[:<:]]word[[:>:]]';
-> 1 mysql>SELECT 'a xword a' REGEXP '[[:<:]]word[[:>:]]';
-> 0
Um ein Sonderzeichen in einem regulären Ausdruck als Literal zu
benutzen, setzen Sie zwei Backslash-Zeichen davor (\). Der Parser
von MySQL interpretiert einen der Backslashes und die Bibliothek
für reguläre Ausdrücke den anderen. Um beispielsweise den String
1+2
zu erkennen, der das Sonderzeichen
+
enthält, ist nur der letzte der folgenden
regulären Ausdrücke der richtige:
mysql>SELECT '1+2' REGEXP '1+2';
-> 0 mysql>SELECT '1+2' REGEXP '1\+2';
-> 0 mysql>SELECT '1+2' REGEXP '1\\+2';
-> 1
Inhaltsverzeichnis
Im vorliegenden Kapitel werden Beschränkungen beschrieben, die für MySQL-Features wie beispielsweise Unterabfragen oder Views gelten.
Einige hier aufgeführten Beschränkungen gelten für alle gespeicherten Routinen, also sowohl für gespeicherte Prozeduren als auch für gespeicherte Funktionen. Manche Beschränkungen gelten nur für gespeicherte Funktionen, aber nicht für gespeicherte Prozeduren.
Alle Beschränkungen für gespeicherte Funktionen gelten auch für Trigger. Außerdem sind Trigger zurzeit noch nicht für Fremdschlüsselaktionen aktiviert.
Gespeicherte Routinen dürfen keine beliebigen SQL-Anweisungen enthalten. Die folgenden Anweisungen sind unzulässig:
die Sperranweisungen LOCK TABLES
und
UNLOCK TABLES
LOAD DATA
und LOAD TABLE
Vorbereitete SQL-Anweisungen (PREPARE
,
EXECUTE
, DEALLOCATE
PREPARE
). Folge: Sie können in gespeicherten
Routinen kein dynamisches SQL benutzen (indem Sie Anweisungen
dynamisch als Strings generieren und dann ausführen). Diese
Einschränkung wird in MySQL 5.0.13 für gespeicherte
Prozeduren aufgehoben, gilt aber weiterhin für gespeicherte
Funktionen und Trigger.
Für gespeicherte Funktionen (nicht aber gespeicherte Prozeduren) sind zusätzlich folgende Anweisungen unzulässig:
Anweisungen, die ein explizites oder implizites Commit oder Rollback ausführen
Anweisungen, die eine Ergebnismenge zurückgeben. Dazu
gehören auch SELECT
-Anweisungen, die keine
INTO
-Klausel
besitzen, sowie var_list
SHOW
-Anweisungen. Eine
Funktion kann eine Ergebnismenge entweder mit SELECT
... INTO
oder
mit einem Cursor und var_list
FETCH
-Anweisungen
verarbeiten. Siehe Abschnitt 19.2.7.3, „SELECT ... INTO
-Anweisung“.
FLUSH
-Anweisungen
Rekursive Anweisungen. Das bedeutet, dass gespeicherte Funktionen nicht rekursiv benutzt werden können.
Achtung: Obwohl einige Beschränkungen normalerweise zwar für
gespeicherte Funktionen und Trigger, aber nicht für gespeicherte
Prozeduren gelten sollten, gelten sie dennoch für gespeicherte
Prozeduren, wenn diese aus einer gespeicherten Funktion oder einem
Trigger heraus aufgerufen werden. So können Sie zwar
FLUSH
in einer gespeicherten Prozedur
verwenden, aber keine derartige gespeicherte Prozedur aus einer
gespeicherten Funktion oder einem Trigger heraus aufrufen.
Es ist möglich, denselben Bezeichner für eine Routine, einen Parameter, eine lokale Variable und eine Tabellenspalte zu benutzen. Zudem kann derselbe lokale Variablenname in geschachtelten Blöcken eingesetzt werden. Zum Beispiel:
CREATE PROCEDURE p (i INT) BEGIN DECLARE i INT DEFAULT 0; SELECT i FROM t; BEGIN DECLARE i INT DEFAULT 1; SELECT i FROM t; END; END;
In solchen Fällen ist der Bezeichner nicht mehr eindeutig, sodass folgende Präzedenzregeln gelten:
Eine lokale Variable hat Vorrang vor einem Routinenparameter oder einer Tabellenspalte.
Ein Routinenparameter hat Vorrang vor einer Tabellenspalte.
Eine lokale Variable in einem inneren Block hat Vorrang vor einer lokalen Variablen in einem äußeren Block.
Dass Tabellenspalten nicht Vorrang vor Variablen haben, ist ein nichtstandardmäßiges Verhalten.
Die Verwendung von gespeicherten Routinen kann Replikationsprobleme verursachen. Dieses Thema wird in Abschnitt 19.4, „Binärloggen gespeicherter Routinen und Trigger“, eingehender behandelt.
Da INFORMATION_SCHEMA
noch keine
PARAMETERS
-Tabelle hat, müssen Anwendungen,
die Daten von Routinenparametern zur Laufzeit benötigen,
Workarounds einsetzen, also beispielsweise die Ausgabe der
SHOW CREATE
-Anweisungen parsen.
Es gibt keine Debuggingfähigkeiten für gespeicherte Routinen.
CALL
-Anweisungen dürfen keine vorbereiteten
Anweisungen sein. Das gilt sowohl für serverseitige vorbereitete
Anweisungen als auch für vorbereitete SQL-Anweisungen.
UNDO
-Handler werden nicht unterstützt.
FOR
-Schleifen werden nicht unterstützt.
Um Probleme mit der Interaktion zwischen Server-Threads zu verhindern, verwendet der Server, wenn ein Client eine Anweisung gibt, einen Schnappschuss der Routinen und Trigger, die zur Ausführung dieser Anweisung verfügbar sind. Das bedeutet, dass der Server eine Liste von Prozeduren, Funktionen und Triggern berechnet, die bei der Ausführung der Anweisung eingesetzt werden dürfen, diese lädt und dann zur Ausführung der Anweisung schreitet. Die Folge: Während der Ausführung erkennt der Server keine Änderungen an Routinen, die von anderen Threads vorgenommen werden.
Cursors auf der Serverseite werden in der C-API mit der Funktion
mysql_stmt_attr_set()
implementiert. Dieselbe
Implementierung wird auch für Cursors in gespeicherten Routinen
verwendet. Mit einem Cursor auf der Serverseite kann dort eine
Ergebnismenge generiert werden, wobei an den Client allerdings nur
diejenigen Zeilen übermittelt werden, die dieser verlangt. Wenn
ein Client beispielsweise eine Anfrage ausführt, sich aber nur
für die erste Zeile interessiert, werden die restlichen Zeilen
nicht übertragen.
In MySQL wird ein serverseitiger Cursor von einer temporären
Tabelle verkörpert (materialisiert). Diese ist zu Beginn eine
MEMORY
-Tabelle, wird aber dann in eine
MyISAM
-Tabelle umgewandelt, wenn ihre Größe
den Wert der Systemvariablen
max_heap_table_size
erreicht. Diese
Implementierung führt unter anderem dazu, dass der Abruf von
Zeilen mit einem Cursor bei großen Ergebnismengen langsam ist.
Cursors sind nur-lesend; mit einem Cursor können Sie also keine Zeilen aktualisieren.
UPDATE WHERE CURRENT OF
und DELETE
WHERE CURRENT OF
sind nicht implementiert, da änderbare
Cursors nicht unterstützt werden.
Cursors lassen sich nicht nach einem Commit offen halten.
Cursors unterscheiden nicht zwischen Groß- und Kleinschreibung.
Cursors sind nicht scrollbar.
Cursors haben keinen Namen. Der Anweisungs-Handler fungiert als Cursor-ID.
Sie können immer nur einen einzigen Cursor pro vorbereiteter Anweisung offen haben. Wenn Sie mehrere Cursors benötigen, müssen Sie mehrere Anweisungen vorbereiten.
Sie dürfen keinen Cursor für eine Anweisung benutzen, die eine
Ergebnismenge generiert, wenn die Anweisung nicht im
Prepared-Modus unterstützt wird. Dazu gehören Anweisungen wie
beispielsweise CHECK TABLES
, HANDLER
READ
und SHOW BINLOG EVENTS
.
Ein bekannter Bug, der noch behoben wird: Wenn Sie einen
NULL
-Wert mithilfe von ALL
,
ANY
oder SOME
mit einer
Unterabfrage vergleichen und die Unterabfrage eine Ergebnismenge
zurückgibt, kann der Vergleich das nichtstandardmäßige Ergebnis
NULL
anstatt TRUE
oder
FALSE
zurückliefern.
Die äußere Anweisung einer Unterabfrage kann ein
SELECT
, INSERT
,
UPDATE
, DELETE
,
SET
oder DO
sein.
Im Allgemeinen können Sie eine Tabelle nicht in einer Unterabfrage modifizieren und zugleich mit einem Select abfragen. Diese Beschränkung gilt beispielsweise für Anweisungen der folgenden Form:
DELETE FROM t WHERE ... (SELECT ... FROM t ...); UPDATE t ... WHERE col = (SELECT ... FROM t ...); {INSERT|REPLACE} INTO t (SELECT ... FROM t ...);
Ausnahme: Das obige Verbot gilt nicht, wenn Sie eine Unterabfrage
für die modifizierte Tabelle in der
FROM
-Klausel verwenden. Beispiel:
UPDATE t ... WHERE col = (SELECT (SELECT ... FROM t...) AS _t ...);
Das Verbot ist hier deshalb außer Kraft gesetzt, weil die
Unterabfrage in der FROM
-Klausel von einer
temporären Tabelle verkörpert wird, sodass die relevanten Zeilen
in t
zu dem Zeitpunkt, da das Update in
t
stattfindet, von dem Select bereits abgerufen
worden sind.
Zeilenvergleichsoperationen werden nur teilweise unterstützt:
Für
kann
expr
IN
(subquery
)expr
ein
n
-Tupel sein (das mit
Zeilenkonstruktorsyntax angegeben ist) und die Unterabfrage
kann Zeilen von n
-Tupeln
zurückgeben.
Für
muss
expr
op
{ALL|ANY|SOME}
(subquery
)expr
ein Skalarwert und die
Unterabfrage eine Spaltenunterabfrage sein. Sie darf keine
Zeilen mit mehreren Spalten zurückgeben.
Mit anderen Worten, für eine Unterabfrage, die Zeilen von
n
--Tupeln zurückgibt, wird Folgendes
unterstützt:
(val_1
, ...,val_n
) IN (subquery
)
Doch dieses wird nicht unterstützt:
(val_1
, ...,val_n
)op
{ALL|ANY|SOME} (subquery
)
Der Grund, weshalb Zeilenvergleiche für IN
unterstützt werden, aber für die anderen Klauseln nicht, besteht
darin, dass IN
aufgrund seiner Implementierung
den Vergleich als eine Serie von =
-Vergleichen
und AND
-Operationen neu schreibt. Dieser Ansatz
kann für ALL
, ANY
oder
SOME
nicht verwendet werden.
Zeilenkonstruktoren sind nicht gut optimiert. Die folgenden beiden Ausdrücke sind äquivalent, aber nur der zweite kann optimiert werden:
(col1, col2, ...) = (val1, val2, ...) col1 = val1 AND col2 = val2 AND ...
Die Unterabfragenoptimierung ist für IN
weniger effizient als für den =
-Operator.
Ein typisches Beispiel für die schlechte Performance von
IN
tritt ein, wenn die Unterabfrage nur wenige,
die übergeordnete Abfrage hingegen viele Zeilen zurückgibt, die
mit den Ergebnissen der Unterabfrage verglichen werden müssen.
Unterabfragen in der FROM
-Klausel dürfen keine
korrelierten Unterabfragen sein. Sie werden materialisiert
(ausgeführt, um eine Ergebnismenge zu erstellen), bevor die
äußere Abfrage ausgeführt wird. Daher können sie nicht pro
Zeile der äußeren Abfrage ausgewertet werden.
Da der Optimierer für Joins besser als für Unterabfragen gerüstet ist, lassen sich oft Anweisungen mit Unterabfragen effizienter ausführen, wenn man sie als Joins umformuliert.
Eine Ausnahme bildet der Fall, in dem eine
IN
-Unterabfrage als SELECT
DISTINCT
-Join umformuliert werden kann. Beispiel:
SELECT col FROM t1 WHERE id_col IN (SELECT id_col2 FROM t2 WHERE condition
);
Diese Anweisung kann man folgendermaßen umformulieren:
SELECT DISTINCT col FROM t1, t2 WHERE t1.id_col = t2.id_col AND condition
;
Doch hier erfordert der Join eine zusätzliche
DISTINCT
-Operation und ist deswegen nicht
effizienter als die Unterabfrage.
Eine mögliche zukünftige Optimierung könnte darin bestehen, dass MySQL die Join-Reihenfolge nicht für die Auswertung der Unterabfrage neu schreibt. In manchen Fällen ließe sich eine Unterabfrage effizienter ausführen, wenn MySQL sie als Join umformulierte. Dies gäbe dem Optimierer die Gelegenheit, zwischen mehreren Ausführungsplänen auszuwählen. Er könnte beispielsweise entscheiden, welche von zwei Tabellen er als Erste liest.
Beispiel:
SELECT a FROM outer_table AS ot WHERE a IN (SELECT a FROM inner_table AS it WHERE ot.b = it.b);
Für diese Anfrage würde MySQL immer zuerst die
outer_table
scannen und dann die Unterabfrage
für jede Zeile auf der inner_table
ausführen.
Wenn outer_table
viele und
inner_table
wenige Zeilen hat, liefe die
Anfrage nicht so schnell, wie sie könnte.
Die obige Anfrage könnte man folgendermaßen umformulieren:
SELECT a FROM outer_table AS ot, inner_table AS it WHERE ot.a = it.a AND ot.b = it.b;
In diesem Fall scannen wir zuerst die kleine Tabelle
(inner_table
) und schauen danach die Zeilen in
der großen outer_table
nach. Das geht ganz
schnell, wenn wir einen Index auf (ot.a,ot.b)
haben.
Mögliche zukünftige Optimierung: Eine korrelierte Unterabfrage wird für jede Zeile der äußeren Abfrage ausgewertet. Es wäre besser, die Unterabfrage nicht erneut auszuwerten, wenn die Werte der äußeren Zeile immer noch dieselben sind wie in der vorherigen Zeile. Stattdessen könnte man das vorherige Ergebnis wiederverwenden.
Mögliche zukünftige Optimierung: Eine Unterabfrage in der
FROM
-Klausel wird ausgewertet, indem ihr
Ergebnis in einer temporären Tabelle festgehalten wird, die keine
Indizes verwendet. So können auch bei Vergleichen mit anderen
Tabellen in der Abfrage keine Indizes eingesetzt werden, auch dann
nicht, wenn es sinnvoll wäre.
Mögliche zukünftige Optimierung: Wenn eine Unterabfrage in der
FROM
-Klausel einer View ähnelt, auf die der
Merge-Algorithmus angewendet werden kann, formulieren Sie die
Anfrage um und wenden den Merge-Algorithmus an, damit Indizes
genutzt werden können. Die folgende Anweisung enthält eine
solche Unterabfrage:
SELECT * FROM (SELECT * FROM t1 WHERE t1.t1_col) AS _t1, t2 WHERE t2.t2_col;
Die Anweisung kann folgendermaßen als Join geschrieben werden:
SELECT * FROM t1, t2 WHERE t1.t1_col AND t2.t2_col;
Diese Umformulierung hat zwei Vorteile:
Sie verhindert den Einsatz einer temporären Tabelle, für die
keine Indizes genutzt werden können. In der umformulierten
Version kann der Optimierer Indizes auf t1
verwenden.
Sie gibt dem Optimierer mehr Freiheiten, zwischen
verschiedenen Ausführungsplänen zu wählen. Indem er sie als
Join umformuliert, kann der Optimierer beispielsweise
entscheiden, ob er t1
oder
t2
zuerst benutzt.
Mögliche zukünftige Optimierung: Für IN
,
= ANY
, <> ANY
,
= ALL
und <> ALL
mit
nichtkorrelierten Unterabfragen könnte man für das Ergebnis
einen speicherresidenten Hash oder, bei größeren Ergebnismengen,
eine temporäre Tabelle mit Index verwenden. Beispiel:
SELECT a FROM big_table AS bt WHERE non_key_field IN (SELECT non_key_field FROMtable
WHEREcondition
)
In diesem Fall würden wir eine temporäre Tabelle anlegen:
CREATE TABLE t (key (non_key_field)) (SELECT non_key_field FROMtable
WHEREcondition
)
Dann könnten wir für jede Zeile in big_table
einen Schlüssel-Lookup in t
anhand von
bt.non_key_field
machen.
Die View-Verarbeitung ist nicht optimiert:
Es ist nicht möglich, auf einer View einen Index anzulegen.
Indizes können für Views eingesetzt werden, die mit dem Merge-Algorithmus verarbeitet werden. Wird jedoch eine View mit dem Temptable-Algorithmus verarbeitet, kann sie nicht von den Indizes ihrer zugrunde liegenden Tabellen profitieren (obwohl Indizes bei der Erzeugung der temporären Tabellen eingesetzt werden können).
Unterabfragen dürfen nicht in der FROM
-Klausel
einer View verwendet werden. Diese Beschränkung wird jedoch in
Zukunft aufgehoben.
Generell können Sie nicht in derselben Unterabfrage eine Tabelle modifizieren und gleichzeitig mit Select abfragen. Siehe Abschnitt I.3, „Beschränkungen von Unterabfragen“.
Dasselbe Prinzip gilt auch, wenn Sie eine View abfragen, die ihrerseits eine Tabelle abfragt, wenn die View die Tabelle in einer Unterabfrage abfragt und mit dem Merge-Algorithmus ausgewertet wird. Beispiel:
CREATE VIEW v1 AS SELECT * FROM t2 WHERE EXISTS (SELECT 1 FROM t1 WHERE t1.a = t2.a); UPDATE t1, v2 SET t1.a = 1 WHERE t1.b = v2.b;
Wird die View mit einer temporären Tabelle ausgewertet,
können Sie diese Tabelle in der
View-Unterabfrage abfragen und in der äußeren Abfrage dennoch
die Tabelle modifizieren. In diesem Fall wird die View nämlich
materialisiert, sodass Sie die Tabelle in Wirklichkeit gar nicht
„zur selben Zeit“ in einer Unterabfrage abfragen und
modifizieren. (Dies ist ein weiterer Grund, MySQL zur Verwendung
des Temptable-Algorithmus zu zwingen, indem Sie ALGORITHM
= TEMPTABLE
in der View-Definition angeben.)
Mit DROP TABLE
oder ALTER
TABLE
können Sie eine Tabelle löschen oder ändern,
die in einer View-Definition benutzt wird (wodurch die View
ungültig wird). Die Löschungs- oder Änderungsoperation löst
keine Warnung aus. Erst später, wenn die View benutzt wird, wird
ein Fehler gemeldet.
Eine View-Definition wird von bestimmten Anweisungen „eingefroren“:
Wenn eine von PREPARE
vorbereitete
Anweisung auf eine View verweist, spiegeln die Inhalte der
View jedes Mal, wenn die Anweisung im weiteren Verlauf
ausgeführt wird, den Zustand zu dem Zeitpunkt wider, da sie
vorbereitet wurde. Das gilt auch dann, wenn die
View-Definition zwischen der Vorbereitung und der Ausführung
der Anweisung geändert wurde. Beispiel:
CREATE VIEW v AS SELECT 1; PREPARE s FROM 'SELECT * FROM v'; ALTER VIEW v AS SELECT 2; EXECUTE s;
Die EXECUTE
-Anweisung gibt 1 und nicht 2
zurück.
Wenn eine Anweisung in einer gespeicherten Routine eine View benutzt, dann mit dem Inhalt, den die View bei der ersten Ausführung der Anweisung hatte. Das bedeutet beispielsweise: Wenn die Anweisung in einer Schleife ausgeführt wird, bekommt sie in allen weiteren Durchläufen immer denselben View-Inhalt zu sehen, selbst wenn die View-Definition später in der Schleife geändert wird. Beispiel:
CREATE VIEW v AS SELECT 1; delimiter // CREATE PROCEDURE p () BEGIN DECLARE i INT DEFAULT 0; WHILE i < 5 DO SELECT * FROM v; SET i = i + 1; ALTER VIEW v AS SELECT 2; END WHILE; END; // delimiter ; CALL p();
Wenn die Prozedur p()
aufgerufen wird, gibt
SELECT
bei jedem Schleifendurchlauf 1
zurück, obwohl die View-Definition in der Schleife geändert
wurde.
Im Hinblick auf die Aktualisierungsmöglichkeit besteht für Views
das übergeordnete Ziel, dass jede View, die theoretisch
aktualisiert werden kann, auch in der Praxis aktualisierbar sein
sollte. Dazu gehören auch Views, die in ihrer Definition eine
UNION
haben. Zurzeit sind nicht alle
theoretisch aktualisierbaren Views auch in der Praxis
aktualisierbar. Die ursprüngliche Implementierung von Views war
absichtlich so geschrieben worden, um möglichst schnell
benutzbare und aktualisierbare Views in MySQL hinzuzubekommen.
Viele theoretisch aktualisierbare Views sind dies auch in der
Praxis, aber es gibt immer noch einige Einschränkungen:
Aktualisierbare Views, die irgendwo anders als in der
WHERE
-Klausel Unterabfragen haben. Manche
Views mit Unterabfragen in der SELECT
-Liste
sind möglicherweise aktualisierbar.
Sie können mit UPDATE
nicht mehr als eine
unterliegende Tabelle einer als Join definierten View
aktualisieren.
Sie können eine als Join definierte View nicht mit
DELETE
aktualisieren.
Die XA-Transaktionsunterstützung beschränkt sich auf die
Speicher-Engine InnoDB
.
Die XA-Implementierung von MySQL ist für „externes
XA“ ausgelegt, bei dem ein MySQL Server als
Ressourcenmanager (RMs) und Clientprogramme als
Transaktionsmanager (TMs) fungieren. „Internes XA“
ist nicht implementiert. Dies würde einzelnen Speicher-Engines in
einem MySQL Server erlauben, als RMs zu agieren, und dem Server
selbst, als TM zu fungieren. Internes XA ist für den Umgang mit
XA-Transaktionen erforderlich, an denen mehr als eine
Speicher-Engine beteiligt ist. Die Implementierung von internem XA
ist unvollständig, da sie erfordert, dass eine Speicher-Engine
zweiphasiges Commit auf der Tabellenhandler-Ebene unterstützt,
was zurzeit nur InnoDB
kann.
Für XA START
werden keine
JOIN
- und RESUME
-Klauseln
unterstützt.
Für XA END
wird die SUSPEND [FOR
MIGRATE]
-Klausel nicht unterstützt.
Die Anforderung, dass der bqual
-Teil
des xid
-Werts für jede XA-Transaktion
innerhalb einer globalen Transaktion anders sein muss, ist eine
Beschränkung der derzeitigen XA-Implementierung von MySQL. Sie
ist nicht Teil der XA-Spezifikation.
Wenn eine XA-Transaktion den PREPARED
-Zustand
erreicht hat und der MySQL Server abstürzt, kann die Transaktion
nach dem erneuten Hochfahren des Servers weiterlaufen. Das soll
auch so sein. Wenn allerdings die Clientverbindung abbricht und
der Server weiterläuft, rollt der Server alle anhängigen
XA-Transaktionen zurück, selbst solche, die den
PREPARED
-Zustand erreicht haben. Es sollte
möglich sein, eine PREPARED
-XA-Transaktion zu
committen oder zurückzurollen, doch dies lässt sich nur durch
Änderungen am Mechanismus des Binärlogs erreichen.
Version 2, June 1991
Copyright © 1989, 1991 Free Software Foundation, Inc.
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software---to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too.
When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.
We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.
Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and modification follow.
GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The ``Program'', below, refers to any such program or work, and a ``work based on the Program'' means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term ``modification''.) Each licensee is addressed as ``you''.
Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.
You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.
You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.
You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.
If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.
In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:
Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
Accompany it with a written offer, valid for at least three years, to give any third-party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.
If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.
You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.
Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.
If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.
This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and ``any later version'', you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.
If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.
NO WARRANTY
BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM ``AS IS'' WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the ``copyright'' line and a pointer to where the full notice is found.
one line to give the program's name and a brief idea of what it does.
Copyright (C)yyyy
name of author
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy
name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details.
The hypothetical commands 'show w
' and
'show c
' should show the appropriate parts of the
General Public License. Of course, the commands you use may be
called something other than 'show w
' and
'show c
'; they could even be mouse-clicks or menu
items---whatever suits your program.
You should also get your employer (if you work as a programmer) or your school, if any, to sign a ``copyright disclaimer'' for the program, if necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
signature of Ty Coon
, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License.
The MySQL AB Exception for Free/Libre and Open Source Software-only Applications Using MySQL Client Libraries (the „FLOSS Exception“).
Version 0.4, 08 September 2005
Exception Intent
We want specified Free/Libre and Open Source Software (``FLOSS'') applications to be able to use specified GPL-licensed MySQL client libraries (the ``Program'') despite the fact that not all FLOSS licenses are compatible with version 2 of the GNU General Public License (the ``GPL'').
Legal Terms and Conditions
As a special exception to the terms and conditions of version 2.0 of the GPL:
You are free to distribute a Derivative Work that is formed entirely from the Program and one or more works (each, a „FLOSS Work“) licensed under one or more of the licenses listed below in section 1, as long as:
You obey the GPL in all respects for the Program and the Derivative Work, except for identifiable sections of the Derivative Work which are not derived from the Program, and which can reasonably be considered independent and separate works in themselves,
all identifiable sections of the Derivative Work which are not derived from the Program, and which can reasonably be considered independent and separate works in themselves,
are distributed subject to one of the FLOSS licenses listed below, and
the object code or executable form of those sections are accompanied by the complete corresponding machine-readable source code for those sections on the same medium and under the same FLOSS license as the corresponding object code or executable forms of those sections, and
any works which are aggregated with the Program or with a Derivative Work on a volume of a storage or distribution medium in accordance with the GPL, can reasonably be considered independent and separate works in themselves which are not derivatives of either the Program, a Derivative Work or a FLOSS Work.
If the above conditions are not met, then the Program may only be copied, modified, distributed or used under the terms and conditions of the GPL or another valid licensing option from MySQL AB.
FLOSS License List
License name | Version(s)/Copyright Date |
Academic Free License | 2.0 |
Apache Software License | 1.0/1.1/2.0 |
Apple Public Source License | 2.0 |
Artistic license | From Perl 5.8.0 |
BSD license | "July 22 1999" |
Common Public License | 1.0 |
GNU Library or "Lesser" General Public License (LGPL) | 2.0/2.1 |
Jabber Open Source License | 1.0 |
MIT license | - |
Mozilla Public License (MPL) | 1.0/1.1 |
Open Software License | 2.0 |
OpenSSL license (with original SSLeay license) | "2003" ("1998") |
PHP License | 3.0 |
Python license (CNRI Python License) | — |
Python Software Foundation License | 2.1.1 |
Sleepycat License | "1999" |
W3C License | "2001" |
X11 License | "2001" |
Zlib/libpng License | — |
Zope Public License | 2.0 |
Due to the many variants of some of the above licenses, we require that any version follow the 2003 version of the Free Software Foundation's Free Software Definition (http://www.gnu.org/philosophy/free-sw.html) or version 1.9 of the Open Source Definition by the Open Source Initiative (http://www.opensource.org/docs/definition.php).
Definitions
Terms used, but not defined, herein shall have the meaning provided in the GPL.
Derivative Work means a derivative work under copyright law.
Applicability: This FLOSS Exception applies to all Programs that contain a notice placed by MySQL AB saying that the Program may be distributed under the terms of this FLOSS Exception. If you create or distribute a work which is a Derivative Work of both the Program and any other work licensed under the GPL, then this FLOSS Exception is not available for that work; thus, you must remove the FLOSS Exception notice from that work and comply with the GPL in all respects, including by retaining all GPL notices. You may choose to redistribute a copy of the Program exclusively under the terms of the GPL by removing the FLOSS Exception notice from that copy of the Program, provided that the copy has never been modified by you or any third party.
Appendix A. Qualified Libraries and Packages
The following is a non-exhaustive list of libraries and packages which are covered by the FLOSS License Exception. Please note that this appendix is provided merely as an additional service to specific FLOSS projects wishing to simplify licensing information for their users. Compliance with one of the licenses noted under the „FLOSS license list“ section remains a prerequisite.
Package Name | Qualifying License and Version |
Apache Portable Runtime (APR) | Apache Software License 2.0 |