MySQL-Fehlerbehandlung und Protokollierung

MySQLBeginner
Jetzt üben

Einführung

In diesem Lab lernen Sie grundlegende Techniken zur Fehlerbehandlung und Protokollierung in MySQL kennen. Ein effektiver Umgang mit Fehlern ist entscheidend für robuste und wartbare Datenbankanwendungen. Er hilft Ihnen, Probleme zu diagnostizieren, die Ausführung von Abfragen nachzuvollziehen und die Datenintegrität sicherzustellen.

Zunächst aktivieren Sie das allgemeine Abfrageprotokoll. Es zeichnet alle SQL-Anweisungen auf, die an den Server gesendet werden, und ist damit ein nützliches Werkzeug für Debugging und Audits. Anschließend implementieren Sie mit DECLARE HANDLER eine Fehlerbehandlung in einer gespeicherten Prozedur, um unerwartete Fehler kontrolliert abzufangen. Außerdem lernen Sie, mit der Anweisung SIGNAL benutzerdefinierte Fehlerbedingungen zu erstellen und auszulösen, um Geschäftsregeln durchzusetzen. Zum Schluss sehen Sie sich das MySQL-Fehlerprotokoll an, das wichtige Informationen über Servervorgänge und kritische Probleme enthält.

Nach Abschluss dieses Labs verfügen Sie über eine solide Grundlage für die Fehlerbehandlung und Protokollierung in MySQL. Damit können Sie zuverlässigere Datenbanklösungen entwickeln.

Allgemeines Abfrageprotokoll aktivieren und überprüfen

Das allgemeine Abfrageprotokoll zeichnet jede SQL-Anweisung auf, die der Server von Clients empfängt. Es ist ein wertvolles Werkzeug für Debugging und Audits. Aktivieren Sie es jedoch nur vorübergehend, da es die Leistung beeinträchtigen und viel Speicherplatz belegen kann. In diesem Schritt aktivieren Sie das Protokoll, erzeugen einige Einträge und überprüfen die Protokolldatei.

Öffnen Sie zunächst das Terminal auf Ihrem Desktop.

Verbinden Sie sich als Benutzer root mit dem MySQL-Server. In dieser Lab-Umgebung können Sie sudo verwenden, um sich ohne Passwort anzumelden.

sudo mysql -u root

Sobald die Eingabeaufforderung mysql> angezeigt wird, aktivieren Sie das allgemeine Abfrageprotokoll global.

SET GLOBAL general_log = 'ON';

Standardmäßig wird die Protokolldatei im MySQL-Datenverzeichnis gespeichert. Damit sie leichter zugänglich ist, legen Sie den Speicherort auf das Verzeichnis /tmp fest.

SET GLOBAL general_log_file = '/tmp/mysql_general.log';

Überprüfen Sie den neuen Speicherort mit diesem Befehl:

SHOW VARIABLES LIKE 'general_log_file';

Die Ausgabe sollte den soeben festgelegten Pfad bestätigen.

+------------------+-------------------------+
| Variable_name    | Value                   |
+------------------+-------------------------+
| general_log_file | /tmp/mysql_general.log  |
+------------------+-------------------------+
1 row in set (0.01 sec)

Führen Sie nun einige Befehle aus, um Protokolleinträge zu erzeugen.

CREATE DATABASE IF NOT EXISTS testdb;
USE testdb;
SELECT 'Logging this query' AS message;

Beenden Sie anschließend die MySQL-Shell.

exit

Rufen Sie im Terminal den Inhalt der Protokolldatei auf.

sudo cat /tmp/mysql_general.log

Sie sehen die ausgeführten Befehle sowie Verbindungsinformationen und Zeitstempel. Daran erkennen Sie, dass das allgemeine Abfrageprotokoll korrekt funktioniert.

/usr/sbin/mariadbd, Version: 10.6.18-MariaDB-0ubuntu0.22.04.1 (Ubuntu 22.04). started with:
Tcp port: 3306  Unix socket: /run/mysqld/mysqld.sock
Time                Id Command  Argument
250728 14:12:46     33 Query    SHOW VARIABLES LIKE 'general_log_file'
250728 14:12:50     33 Query    CREATE DATABASE IF NOT EXISTS testdb
                    33 Query    SELECT DATABASE()
                    33 Init DB  testdb
                    33 Query    show databases
                    33 Query    show tables
                    33 Query    SELECT 'Logging this query' AS message
250728 14:12:56     33 Quit

Deaktivieren Sie das Protokoll am besten, sobald Sie es nicht mehr benötigen. Das können Sie direkt im Terminal tun.

sudo mysql -u root -e "SET GLOBAL general_log = 'OFF';"

So verhindern Sie, dass die Protokolldatei weiter anwächst und die Serverleistung beeinträchtigt.

Fehler in einer gespeicherten Prozedur behandeln

Gespeicherte Prozeduren können aus vielen Gründen fehlschlagen, zum Beispiel beim Versuch, einen doppelten Wert in eine Primärschlüsselspalte einzufügen. Mit einem Fehlerhandler können Sie solche Fehler abfangen und kontrolliert darauf reagieren, statt die Prozedur unkontrolliert abbrechen zu lassen. In diesem Schritt erstellen Sie eine gespeicherte Prozedur mit einem Fehlerhandler für doppelte Schlüssel.

Verbinden Sie sich zunächst mit dem MySQL-Server.

sudo mysql -u root

Erstellen Sie die Datenbank testdb, falls sie noch nicht vorhanden ist, und wechseln Sie zu dieser Datenbank. Erstellen Sie anschließend eine Tabelle products.

CREATE DATABASE IF NOT EXISTS testdb;
USE testdb;

CREATE TABLE products (
    id INT PRIMARY KEY,
    name VARCHAR(255),
    quantity INT
);

Erstellen Sie nun eine gespeicherte Prozedur, die ein neues Produkt einfügt. Diese Version enthält einen DECLARE HANDLER, der Fehler wegen doppelter Schlüssel (SQLSTATE 23000) abfängt und eine benutzerdefinierte Meldung zurückgibt.

Der Befehl DELIMITER ändert das Anweisungsendezeichen von ; zu //. So kann das Semikolon im Prozedurrumpf korrekt verarbeitet werden.

DELIMITER //

CREATE PROCEDURE insert_product(IN p_id INT, IN p_name VARCHAR(255))
BEGIN
    -- Declare an EXIT handler for duplicate key errors
    DECLARE EXIT HANDLER FOR SQLSTATE '23000'
    BEGIN
        SELECT 'Error: Product with this ID already exists.' AS message;
    END;

    -- Attempt to insert the product
    INSERT INTO products (id, name, quantity) VALUES (p_id, p_name, 0);
    SELECT 'Product inserted successfully.' AS message;
END //

DELIMITER ;

Testen Sie nun die Prozedur. Fügen Sie zuerst ein neues Produkt ein.

CALL insert_product(1, 'Laptop');

Der Aufruf sollte erfolgreich sein und eine Erfolgsmeldung zurückgeben.

+--------------------------------+
| message                        |
+--------------------------------+
| Product inserted successfully. |
+--------------------------------+
1 row in set (0.00 sec)

Versuchen Sie nun, ein Produkt mit derselben id einzufügen.

CALL insert_product(1, 'Desktop');

Diesmal wird der Fehlerhandler ausgelöst. Statt einer allgemeinen MySQL-Fehlermeldung erhalten Sie die benutzerdefinierte Meldung.

+-----------------------------------------------+
| message                                       |
+-----------------------------------------------+
| Error: Product with this ID already exists.   |
+-----------------------------------------------+
1 row in set (0.00 sec)

Dieses Beispiel zeigt, wie Fehlerhandler gespeicherte Prozeduren benutzerfreundlicher und robuster machen können.

Benutzerdefinierte Fehler mit SIGNAL auslösen

Fehlerhandler fangen Fehler ab, während Sie mit der Anweisung SIGNAL selbst Fehler auslösen können. Das ist nützlich, um Geschäftsregeln durchzusetzen, die nicht durch die üblichen Datenbankeinschränkungen abgedeckt sind. In diesem Schritt erstellen Sie eine Prozedur, die mit SIGNAL verhindert, dass für die Produktmenge negative Werte eingetragen werden.

Sie sollten sich noch in der MySQL-Shell befinden. Falls nicht, stellen Sie die Verbindung erneut her.

sudo mysql -u root

Stellen Sie sicher, dass Sie die Datenbank testdb verwenden.

USE testdb;

Erstellen Sie nun eine gespeicherte Prozedur, die die Menge eines Produkts aktualisiert. Die Prozedur prüft, ob die neue Menge negativ ist. Falls ja, löst sie einen benutzerdefinierten Fehler mit SIGNAL aus.

DELIMITER //

CREATE PROCEDURE update_quantity(IN p_id INT, IN p_quantity INT)
BEGIN
    -- Check if the quantity is negative
    IF p_quantity < 0 THEN
        -- Raise a custom error
        SIGNAL SQLSTATE '45000'
            SET MESSAGE_TEXT = 'Error: Quantity cannot be negative.';
    END IF;

    -- Update the quantity if the check passes
    UPDATE products SET quantity = p_quantity WHERE id = p_id;
    SELECT 'Quantity updated successfully.' AS message;
END //

DELIMITER ;

SQLSTATE '45000' ist hier ein allgemeiner Statuscode für benutzerdefinierte Fehler. Mit MESSAGE_TEXT legen Sie die Fehlermeldung fest, die der Client erhält.

Testen Sie die Prozedur. Aktualisieren Sie zunächst die Menge des im vorherigen Schritt erstellten Produkts „Laptop“ mit einem gültigen Wert.

CALL update_quantity(1, 50);

Der Aufruf sollte erfolgreich ausgeführt werden.

+--------------------------------+
| message                        |
+--------------------------------+
| Quantity updated successfully. |
+--------------------------------+
1 row in set (0.00 sec)

Versuchen Sie nun, die Menge auf einen negativen Wert zu setzen.

CALL update_quantity(1, -10);

Bei diesem Aufruf wird die Anweisung SIGNAL ausgelöst und die Prozedur mit Ihrem benutzerdefinierten Fehler beendet.

ERROR 1644 (45000): Error: Quantity cannot be negative.

Damit haben Sie gezeigt, dass Sie mit SIGNAL benutzerdefinierte Geschäftsregeln in Ihrer Datenbank durchsetzen können.

MySQL-Fehlerprotokoll überprüfen

Das MySQL-Fehlerprotokoll ist eine wichtige Informationsquelle, wenn Sie Probleme auf Serverebene diagnostizieren. Es erfasst Ereignisse beim Starten und Beenden des Servers, kritische Fehler und Warnungen. In diesem Schritt überprüfen Sie die Konfiguration des Fehlerprotokolls und vergleichen die Protokollierung in containerisierten und herkömmlichen Umgebungen.

Sie sollten sich noch in der MySQL-Shell befinden. Ermitteln Sie zunächst mit der Variable log_error, wo sich die Fehlerprotokolldatei befindet.

SHOW VARIABLES LIKE 'log_error';

In dieser LabEx-VM-Umgebung (Docker-Container) kann der Pfad zum Fehlerprotokoll leer sein:

+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_error     |       |
+---------------+-------+
1 row in set (0.001 sec)

Hinweis: In containerisierten Umgebungen wie dieser LabEx-VM wird die MySQL-/MariaDB-Fehlerprotokollierung häufig so konfiguriert, dass sie in den Standardfehlerdatenstrom des Containers statt in eine herkömmliche Protokolldatei schreibt. Das ist in Docker-Containern eine gängige Praxis und entspricht der „12-Factor-App“-Methode.

Sehen wir uns die Fehlerbehandlung anhand des Versuchs an, auf eine nicht vorhandene Datenbank zuzugreifen:

USE non_existent_database;

Wie erwartet schlägt dieser Befehl im Client fehl.

ERROR 1049 (42000): Unknown database 'non_existent_database'

Beenden Sie nun die MySQL-Shell, um zum Terminal zurückzukehren.

exit

In einer Produktionsumgebung mit einer herkömmlichen MySQL-Installation befindet sich das Fehlerprotokoll auf Ubuntu-Systemen normalerweise unter /var/log/mysql/error.log. Prüfen Sie, ob die herkömmliche Protokolldatei vorhanden ist:

sudo ls -la /var/log/mysql/ 2> /dev/null || echo "MySQL log directory not found (normal in containerized environments)"

Fehlerprotokollierung in verschiedenen Umgebungen verstehen:

  • Herkömmliche Installationen: Fehlerprotokolle werden in Dateien wie /var/log/mysql/error.log geschrieben.
  • Containerisierte Umgebungen: Fehler werden häufig an stdout/stderr gesendet und von der Container-Laufzeitumgebung erfasst.
  • Cloud-Datenbanken: Auf Fehlerprotokolle wird in der Regel über die Verwaltungsoberfläche des Cloud-Anbieters zugegriffen.

In Produktionsumgebungen sollten Sie Fehlerprotokolle regelmäßig mit Befehlen wie den folgenden überprüfen:

  • sudo tail -f /var/log/mysql/error.log (um das Protokoll in Echtzeit zu verfolgen)
  • sudo grep -i error /var/log/mysql/error.log (um nach bestimmten Fehlern zu suchen)

Diese Vorgehensweise ist wichtig, um den Zustand des Servers zu überwachen und Probleme wie fehlgeschlagene Starts, beschädigte Tabellen oder Berechtigungsprobleme zu beheben.

Zusammenfassung

In diesem Lab haben Sie grundlegende Techniken zur Fehlerbehandlung und Protokollierung in MySQL kennengelernt. Zu Beginn haben Sie das allgemeine Abfrageprotokoll aktiviert und konfiguriert, um SQL-Anweisungen nachzuverfolgen – eine wichtige Fähigkeit für das Debugging. Danach haben Sie mit DECLARE HANDLER eine robuste Fehlerbehandlung in einer gespeicherten Prozedur implementiert, die bestimmte Fehler kontrolliert abfängt.

Außerdem haben Sie gelernt, Geschäftsregeln durchzusetzen, indem Sie mit der Anweisung SIGNAL benutzerdefinierte Fehler auslösen und so klare, konkrete Rückmeldungen geben. Zum Schluss haben Sie sich mit der MySQL-Fehlerprotokollierung befasst und gelernt, wie sie sich bei herkömmlichen Installationen von der Protokollierung in containerisierten Umgebungen wie Docker-Containern unterscheidet.

Sie haben erfahren, dass herkömmliche MySQL-Installationen Fehlerprotokolle in Dateien wie /var/log/mysql/error.log schreiben. Containerisierte Umgebungen leiten Fehlerausgaben dagegen häufig an stdout/stderr weiter, damit sie sich besser in Container-Orchestrierungsplattformen integrieren lassen. Dieses Wissen ist wichtig für die Arbeit mit modernen Bereitstellungsumgebungen.

Mit diesen Techniken können Sie nun zuverlässigere Datenbankanwendungen entwickeln, Probleme effektiver beheben und die Integrität Ihrer MySQL-Datenbanken in unterschiedlichen Bereitstellungsszenarien sicherstellen.