Tratamento de Erros e Logging no MySQL

MySQLBeginner
Pratique Agora

Introdução

Neste laboratório, você aprenderá técnicas fundamentais de tratamento de erros e logging no MySQL. O gerenciamento eficaz de erros é crucial para construir aplicações de banco de dados robustas e de fácil manutenção, pois ajuda a diagnosticar problemas, entender a execução de consultas e garantir a integridade dos dados.

Você começará habilitando o log de consultas gerais (general query log) para capturar todas as instruções SQL enviadas ao servidor, uma ferramenta poderosa para depuração e auditoria. Em seguida, implementará o tratamento de erros dentro de uma stored procedure usando um DECLARE HANDLER para gerenciar erros inesperados de forma elegante. Você também aprenderá a criar e disparar condições de erro personalizadas usando a instrução SIGNAL para impor regras de negócio. Finalmente, você inspecionará o log de erros do MySQL (MySQL error log), que contém informações vitais sobre as operações do servidor e problemas críticos.

Ao final deste laboratório, você terá uma base sólida em tratamento de erros e logging no MySQL, permitindo que você construa soluções de banco de dados mais confiáveis.

Habilitar e Revisar o General Query Log

O log de consultas gerais (general query log) registra cada instrução SQL recebida dos clientes. É uma ferramenta inestimável para depuração e auditoria, mas deve ser usada temporariamente, pois pode impactar o desempenho e consumir espaço em disco significativo. Nesta etapa, você habilitará o log, gerará alguma atividade e revisará o arquivo de log.

Primeiro, abra o terminal a partir do seu desktop.

Conecte-se ao servidor MySQL como usuário root. Neste ambiente de laboratório, você pode usar sudo para conectar sem senha.

sudo mysql -u root

Assim que vir o prompt mysql>, habilite o log de consultas gerais globalmente.

SET GLOBAL general_log = 'ON';

Por padrão, o arquivo de log é armazenado no diretório de dados do MySQL. Para facilitar o acesso, vamos alterar sua localização para o diretório /tmp.

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

Você pode verificar a nova localização executando:

SHOW VARIABLES LIKE 'general_log_file';

A saída deve confirmar o caminho que você acabou de definir.

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

Agora, execute alguns comandos para gerar entradas no log.

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

Após executar esses comandos, saia do shell do MySQL.

exit

De volta ao seu terminal, visualize o conteúdo do arquivo de log.

sudo cat /tmp/mysql_general.log

Você verá os comandos que executou, juntamente com informações de conexão e timestamps. Isso confirma que o log de consultas gerais está funcionando corretamente.

/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

Finalmente, é uma boa prática desabilitar o log quando terminar. Você pode fazer isso diretamente do terminal.

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

Isso garante que o log não continue a crescer e afetar o desempenho do servidor.

Tratar Erros em uma Stored Procedure

Stored procedures podem falhar por muitos motivos, como tentar inserir dados duplicados em uma coluna de chave primária. Usar um manipulador de erros (error handler) permite capturar esses erros e responder de forma elegante, em vez de deixar a procedure travar. Nesta etapa, você criará uma stored procedure com um manipulador de erros para erros de chave duplicada.

Primeiro, conecte-se ao servidor MySQL.

sudo mysql -u root

Crie o banco de dados testdb se ele ainda não existir e mude para ele. Em seguida, crie uma tabela products.

CREATE DATABASE IF NOT EXISTS testdb;
USE testdb;

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

Agora, crie uma stored procedure para inserir um novo produto. Esta versão inclui um DECLARE HANDLER que captura erros de chave duplicada (SQLSTATE 23000) e retorna uma mensagem personalizada.

O comando DELIMITER altera o terminador de instrução de ; para //, permitindo que o ponto e vírgula dentro do corpo da procedure seja processado corretamente.

DELIMITER //

CREATE PROCEDURE insert_product(IN p_id INT, IN p_name VARCHAR(255))
BEGIN
    -- Declara um EXIT HANDLER para erros de chave duplicada
    DECLARE EXIT HANDLER FOR SQLSTATE '23000'
    BEGIN
        SELECT 'Error: Product with this ID already exists.' AS message;
    END;

    -- Tenta inserir o produto
    INSERT INTO products (id, name, quantity) VALUES (p_id, p_name, 0);
    SELECT 'Product inserted successfully.' AS message;
END //

DELIMITER ;

Vamos testar a procedure. Primeiro, insira um novo produto.

CALL insert_product(1, 'Laptop');

Isso deve ser bem-sucedido e retornar uma mensagem de sucesso.

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

Agora, tente inserir um produto com o mesmo id.

CALL insert_product(1, 'Desktop');

Desta vez, o manipulador de erros é acionado, e você recebe a mensagem de erro personalizada em vez de um erro genérico do MySQL.

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

Isso demonstra como os manipuladores de erros podem tornar suas stored procedures mais amigáveis e robustas.

Gerar Erros Personalizados com SIGNAL

Enquanto os handlers capturam erros, a instrução SIGNAL permite que você os gere. Isso é útil para impor regras de negócio que não são cobertas por restrições padrão do banco de dados. Nesta etapa, você criará uma procedure que usa SIGNAL para impedir que valores negativos sejam inseridos para a quantidade de um produto.

Você ainda deve estar no shell do MySQL. Se não estiver, conecte-se novamente.

sudo mysql -u root

Certifique-se de que está usando o banco de dados testdb.

USE testdb;

Agora, crie uma stored procedure para atualizar a quantidade de um produto. A procedure verificará se a nova quantidade é negativa. Se for, ela usará SIGNAL para gerar um erro personalizado.

DELIMITER //

CREATE PROCEDURE update_quantity(IN p_id INT, IN p_quantity INT)
BEGIN
    -- Verifica se a quantidade é negativa
    IF p_quantity < 0 THEN
        -- Gera um erro personalizado
        SIGNAL SQLSTATE '45000'
            SET MESSAGE_TEXT = 'Error: Quantity cannot be negative.';
    END IF;

    -- Atualiza a quantidade se a verificação for bem-sucedida
    UPDATE products SET quantity = p_quantity WHERE id = p_id;
    SELECT 'Quantity updated successfully.' AS message;
END //

DELIMITER ;

Aqui, SQLSTATE '45000' é um código de estado genérico para erros definidos pelo usuário. MESSAGE_TEXT define a mensagem de erro que o cliente verá.

Vamos testar a procedure. Primeiro, tente uma atualização válida no produto 'Laptop' que você criou na etapa anterior.

CALL update_quantity(1, 50);

Isso deve ser executado com sucesso.

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

Agora, tente atualizar a quantidade com um número negativo.

CALL update_quantity(1, -10);

Esta chamada acionará a instrução SIGNAL, e a procedure será encerrada com seu erro personalizado.

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

Isso confirma que você pode impor com sucesso a lógica de negócios personalizada em seu banco de dados usando SIGNAL.

Revisar o Log de Erros do MySQL

O log de erros do MySQL é o principal recurso para diagnosticar problemas em nível de servidor. Ele registra eventos de inicialização e desligamento do servidor, erros críticos e avisos. Saber como encontrar e ler este log é uma habilidade essencial para qualquer administrador de banco de dados.

Você ainda deve estar no shell do MySQL. Primeiro, encontre a localização do arquivo de log de erros consultando a variável log_error.

SHOW VARIABLES LIKE 'log_error';

Neste ambiente de VM LabEx (container Docker), você pode ver um valor vazio para o caminho do log de erros:

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

Nota: Em ambientes conteinerizados como esta VM LabEx, o registro de erros do MySQL/MariaDB é frequentemente configurado para saída no fluxo de erro padrão do container, em vez de um arquivo de log tradicional. Esta é uma prática comum em containers Docker para seguir a metodologia "12-factor app".

Vamos demonstrar o tratamento de erros tentando acessar um banco de dados inexistente:

USE non_existent_database;

Este comando falhará no cliente, como esperado.

ERROR 1049 (42000): Unknown database 'non_existent_database'

Agora, saia do shell do MySQL para retornar ao seu terminal.

exit

Em um ambiente de produção com uma instalação MySQL tradicional, você normalmente encontraria o log de erros em /var/log/mysql/error.log em sistemas Ubuntu. Você pode verificar se o arquivo de log tradicional existe:

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

Entendendo o Registro de Erros em Diferentes Ambientes:

  1. Instalações tradicionais: Os logs de erros são gravados em arquivos como /var/log/mysql/error.log
  2. Ambientes conteinerizados: Erros são frequentemente enviados para stdout/stderr e capturados pelo runtime do container
  3. Bancos de dados em nuvem: Os logs de erros são tipicamente acessados através da interface de gerenciamento do provedor de nuvem

Em ambientes de produção, você revisaria regularmente os logs de erros usando comandos como:

  • sudo tail -f /var/log/mysql/error.log (para seguir os logs em tempo real)
  • sudo grep -i error /var/log/mysql/error.log (para pesquisar erros específicos)

Esta prática é essencial para monitorar a saúde do servidor e solucionar problemas como falhas na inicialização, tabelas corrompidas ou problemas de permissão.

Resumo

Neste laboratório, você aprendeu técnicas fundamentais para tratamento de erros e logging no MySQL. Você começou habilitando e configurando o general query log para rastrear instruções SQL, uma habilidade chave para depuração. Em seguida, implementou um tratamento de erros robusto em uma stored procedure usando DECLARE HANDLER, permitindo que ela gerencie erros específicos de forma graciosa.

Além disso, você aprendeu a impor regras de negócio gerando erros personalizados com a instrução SIGNAL, fornecendo feedback claro e específico. Finalmente, você explorou conceitos de logging de erros do MySQL, incluindo como o logging de erros difere entre instalações tradicionais e ambientes conteinerizados como containers Docker.

Você aprendeu que, enquanto instalações MySQL tradicionais gravam logs de erros em arquivos (como /var/log/mysql/error.log), ambientes conteinerizados frequentemente redirecionam a saída de erros para stdout/stderr para melhor integração com plataformas de orquestração de containers. Essa compreensão é crucial ao trabalhar com ambientes de implantação modernos.

Ao dominar essas técnicas, você agora está mais bem equipado para construir aplicações de banco de dados confiáveis, solucionar problemas de forma eficaz e garantir a integridade de seus bancos de dados MySQL em diferentes cenários de implantação.