A A A

Datenbanktabellen - ENGINE und Fehlertoleranz

ENGINE und Transaktion

In MySQL kann bei der Anlage einer Datenbanktabelle jeweils die "ENGINE" gewählt werden. Die "ENGINE" regelt das grundlegende Verhalten der Datenbanktabelle. So sind z.B. Datebanktabellen, denen die ENGINE "InnoDB" zugeordnet ist, transaktional. MySQL bietet aber auch etliche ENGINEs an, bei denen die Datenbanktabellen nicht transaktional sind.

Wenn eine Datenbank transaktional ist, kann eine Folge von Befehlen, die inhaltlich zusammengehören, in einer Transaktion gekapselt werden werden. Stellt MySQL während der Abarbeitung der Befehlsfolge fest, dass ein Befehl nicht ausgeführt werden darf, macht es (vereinfacht dargestellt) alle zuvor ausgeführten Befehle der Transaktion wieder rückgängig, um den Datenbankzustand vor Beginn der Transaktion wieder herzustellen.

Die transaktionalen InnoDB-Tabellen haben außerdem den Vorteil, dass sie Fremdschlüsselbeziehungen zwischen Datenbanktabellen unterstützen. Dadurch können die Inhalte von Datensätzen auf mehrere Datenbanktabellen aufgeteilt werden und MySQL durch die Fremdschlüssel "angewiesen" werden, nur solche Befehle auf den Teilen dieser Datenästze auszuführen, die zulässig sind. So kann z.B. erreicht werden, dass in der Datenbanktabelle ("child") keine verwaisten Teildatensätze entstehen, weil die Fremdschlüsselbeziehung verhindert, dass aus einer anderen Datenbanktabelle ("parent") der zugehörige Teildatensatz gelöscht wird.

Weil die transaktionalen InnoDB-Tabellen insgesamt viele Vorteile bieten gegenüber den anderen Speicher-ENGINEs, die MySQL für Datenbanktabellen anbietet, verwendet dieses System InnoDB-Tabellen.

zum Anfang

SQL-Modus

Wenn eine Verbindung zum Datenbankserver mit den Befehlen db_anmelden_lesen() oder db_anmelden_bearbeiten() hergestellt wird, werden sämtliche Vorgaben für den SQL-Modus gelöscht. Es sei denn, mit dem Befehl db_anmelden_lesen() oder db_anmelden_bearbeiten() wird ein Wert für den optionalen Parameter $sql_mode übermittelt.
Der SQL-Modus wird für die jeweilige Datenbankverbindung eingestellt, weil ansonsten abhängig von den serverseitigen Vorgaben für den SQL-Modus unterschiedliche Ergebnisse bei der Ausführung eines SQL-Befehls auftreten können.
Falls allerdings partitionierte Tabellen erstellt und mit Daten gefüllt wurden, während ein anderer SQL-Modus vorlag, können u.U. Daten aus diesen Tabellen verloren gehen oder korrumpiert werden, wenn auf dieser Tabelle MySQL-Befehle ausgeführt werden, die diesen SQL-Modus verwenden. Möchte man also mit MySQL-Befehlen auf solche Tabellen zugreifen, sollte man vor der Befehlsausführung den passenden SQL-Modus wieder einstellen.

Das Löschen der Vorgaben für die SQL-Modi hat folgende Auswirkungen:
  • Das System wird sehr fehlertolerant. Lediglich fehlerhafte Datumsangaben wie z.B. 31.2.2008 sind bei dieser Einstellung nicht erlaubt.
  • Sofern zuvor der SQL-Modus NO_BACKSLASH_ESCAPES aktiviert war, wird dieser SQL-Modus ausgeschaltet.
    Hintergrund: Bei der Einstellung NO_BACKSLASH_ESCAPES wird verhindert, dass MySQL innerhalb von Befehlen, die es z.B. vom PHP-Server erhalten hat, bestimmte Zeichen in Werten vom Typ String durch Steuerzeichen ersetzt, wenn vor diesen Zeichen ein Backslash notiert ist. Der Backslash wird also bei der Einstellung NO_BACKSLASH_ESCAPES in Strings innerhalb von MySQL-Befehlen zu einem gewöhnlichen Zeichen wie jedes andere. Der Vorteil von NO_BACKSLASH_ESCAPES ist, dass ein String ohne jegliche Veränderung in die Datenbank eingetragen wird oder für Vergleichszwecke genutzt werden kann. Allerdings kann dann auch nicht der Backslash genutzt werden, um z.B. im LIKE-Kontext die Joker-Zeichen "%" und "_" in als Zeichen ohne Joker-Wirkung zu kennzeichnen oder Steuerzeichen in den Werten innerhalb von MySQL-Befehlen zu maskieren.
    Durch den Verzicht auf NO_BACKSLASH_ESCAPES müssen innerhalb von PHP alle vorhandenen Backslashes in einem String, der als Wert in einem MySQL-Befehl verwendet werden soll, verdoppelt werden, damit die ursprünglich vorhandenen Backslashes in dem String von MySQL als Zeichen wie jedes andere angesehen werden und nicht zur Ersetzung von Zeichen durch Steuerzeichen führen.
  • Das Fehlen des SQL-Modus "ANSI_QUOTES" bewirkt, dass in MySQL-Befehlen mit doppelten Anführungszeichen Strings und nicht Identifizierer "gekapselt" werden dürfen. - Sinnvoller ist es jedoch in den MySQL-Befehlen Strings immer mit dem Apostroph (') und Identifizierer mit dem (`) zu "kapseln", weil diese Art der Kapselung immer eindeutig ist.

Mit dem Befehl "SET SESSION sql_mode = 'modes';" kann jeder Client für seine Session zur Laufzeit den Status des SQL-Modus ändern. Für die Zeichenfolge 'modes' in dem Befehl ist eine vollständige Liste aller Modi, die gelten sollen, anzugeben, im SET-Befehl ist daher 'modes' durch eine Liste zu ersetzen, in der sämtliche Modi, die gelten sollen enthalten sind. Als Trennzeichen zwischen zwei Werten in der Liste ist jeweils ein Komma zu setzen. Wird die Zeichenfolge 'modes' nur durch den Wert ersetzt, der in dem Abfrageergebnis nicht enthalten war, so gilt nach der Ausführung des Befehls nur noch der zuletzt geforderte Modus und zwar für die gesamte Session des Clients, es sei denn der Wert wird erneut mit einem SET-Befehl geändert.
Besitzt der Aufrufer ausreichend Rechte, kann er mit dem Befehl "SET GLOBAL sql_mode = 'modes';" den SQL-Modus für sämtliche Sessions und Clients verändern. Der so eingestellte SQL-Modus gilt dann für sämtliche Sessions und Clients bis mit "SET GLOBAL ..." eine andere Zuweisung erfolgt oder der MySQL-Server erneut gestartet wird. Allerdings kann jeder Client mit "SET SESSION ..." die globale Vorgabe für seine Session wieder überschreiben.
Das System bietet in der Datei __zac4web/__funktionen/db_anmelden.php die Funktion sql_modus_einstellen() an, die als ersten Parameter die Verbindungsdaten für den Datenbankzugriff benötigt. Mit dem zweiten Parameter kann beim Funktionsaufruf ein String übermittelt werden, welcher die SQL-Modi auflistet, die eingestellt werden sollen. Fehlt der zweite Parameter, werden sämtliche bislang eingestellten SQL-Modi für die Datenbankverbindung gelöscht.

zum Anfang

SQL-Modus und Fehlertoleranz

MySQL kann - abhängig vom eingestellten SQL-Modus - bezüglich der Eingaben in die Zellen einer Datenbanktabelle recht fehlertolerant sein und verfügt über etliche Mechanismen zur automatischen Anpassung der Werte (vgl. Datenbanktabellen - Spaltentypen und Werte), so dass die SQL-Befehle trotz der ursprünglich fehlerhaften Werte ausgeführt werden können. Dabei richtet sich das Verhalten der Datenbank nach dem Spaltentyp und danach, ob ein vorhandener Datensatz geändert werden soll, oder ein neuer Datensatz eingefügt wird. Bei einer Anpassung eines Wertes durch MySQL erzeugt MySQL eine Warnmeldung, damit der Nutzer über die Anpassung informiert werden kann.
Wenn die Fehlertoleranz unerwünscht ist, kann durch die Einstellung des SQL-Modus die automatische Anpassung unzulässiger Werte verhindert werden. Wird dann allerdings ein unzulässiger Wert eingegeben, kann der fehlerhafte Befehl von MySQL nicht ausführt werden. MySQL erzeugt in diesem Fall eine Fehlermeldung.

Durch den Zusatz IGNORE bei einem UPDATE- und INSERT-Befehl kann für den Befehl fehlertolerantes Verhalten erzwungen werden.

Der Status des SQL-MODUS kann von jeder Session mit dem Befehl "SELECT @@SESSION.sql_mode;" abgefragt werden.

Wenn in dem Abfrageergebnis die Zeichenfolge STRICT_TRANS_TABLES und/oder STRICT_ALL_TABLES enthalten ist, ist der strikte Modus aktiviert, anderenfalls verhält sich der MySQL-Server bei INSERT- und UPDATE-Vorgängen großzügiger.
Für transaktionale Datenbanktabellen besteht kein Unterschied zwischen der Wirkungsweise der beiden SQL-Modi "STRICT_TRANS_TABLES" und "STRICT_ALL_TABLES". Sobald ein fehlerhafter Befehl endeckt wird, wird der Befehl nicht ausgeführt und der Datenbankzustand vor dem fehlerhaften Befehl oder dem Beginn der Transaktion, in welcher der fehlerhafte Befehl enthalten ist, wieder hergestellt.
Bei nicht transaktionalen Datenbanktabellen besteht nur dann kein Unterschied zwischen den beiden Modi, wenn es ein einzelner Befehl ist, der fehlerhaft ist oder der fehlerhafte Befehl der erste Befehl in einer Befehlsfolge ist. In diesen Fällen wird der Datenbankzustand nicht verändert. Befindet sich der fehlerhafte Befehl allerdings innerhalb einer Befehlsfolge, so werden bei beiden Modi sämtliche Befehle bis zum Entdecken des fehlerhaften Befehls ausgeführt. Im Modus "STRICT_TRANS_TABLES" wird dann allerdings nur der fehlerhafte Befehl übersprungen, die darauf folgenden Befehle werden also wieder ausgeführt. Beim Modus "STRICT_ALL_TABLES" wird dagegen mit dem Endecken des fehlerhaften Befehls die Befehlsausführung ganz abgebrochen. Die Veränderungen am Datenbankzustand, welche von den zuvor ausgeführten Befehlen erzeugt wurden, bleiben erhalten.

Die Modi "NO_ZERO_DATE", "NO_ZERO_IN_DATE" und "ALLOW_INVALID_DATES" wirken sich nur auf Spalten mit den Typen "DATE" und "DATETIME" aus. Wenn "ALLOW_INVALID_DATES" aktiviert ist, akzeptiert MySQL für Spalten vom Typ DATE und DATETIME jede Datumsangabe, bei denen der Wert für den Tag eine Zahl zwischen 1 und 31 ist und der Wert für den Monat eine Zahl zwischen 1 und 12 ist, auch wenn es das Datum (z.B. den 31.4.) in der Realität gar nicht gibt. Die Modi "NO_ZERO_DATE" und "NO_ZERO_IN_DATE" sind mittlerweile als "veraltet" eingestuft. Bei einigen MySQL-Versionen ist das Verhalten dieser beiden Modi in den Modi "STRICT_ALL_TABLES" und "STRICT_TRANS_TABLES" enthalten, bei anderen nicht. "NO_ZERO_DATE" verhindert die Datumsangabe 0000:00:00 in DATE und DATETIME-Spalten. "NO_ZERO_IN_DATE" verhindert in einer Datumsangabe den Wert 00 für den Tag und/oder für den Monat, allerdings nicht den Wert 0000:00:00.

zum Anfang

 

© zacher-info.de

- Seite zuletzt geändert: 29.07.2021 - Elisabeth Zacher