Введение
В этой лабораторной работе вы освоите основные приёмы обработки ошибок и ведения журналов в MySQL. Грамотная обработка ошибок необходима для создания надёжных и удобных в сопровождении приложений с базами данных: она помогает диагностировать проблемы, понимать ход выполнения запросов и обеспечивать целостность данных.
Сначала вы включите журнал общих запросов, который записывает все SQL-операторы, отправленные серверу. Этот инструмент полезен для отладки и аудита. Затем вы добавите обработку ошибок в хранимую процедуру с помощью DECLARE HANDLER, чтобы корректно реагировать на непредвиденные ошибки. Вы также научитесь создавать и вызывать пользовательские условия ошибок с помощью оператора SIGNAL, чтобы соблюдать бизнес-правила. В завершение вы изучите журнал ошибок MySQL, в котором содержатся важные сведения о работе сервера и критических проблемах.
В конце лабораторной работы вы будете знать основы обработки ошибок и ведения журналов в MySQL и сможете создавать более надёжные решения для работы с базами данных.
Включите и изучите журнал общих запросов
В журнале общих запросов записывается каждый SQL-оператор, полученный от клиентов. Он незаменим для отладки и аудита, но его следует включать только на время: ведение журнала может снижать производительность и занимать много места на диске. На этом этапе вы включите журнал, создадите несколько записей и просмотрите его файл.
Сначала откройте терминал на рабочем столе.
Подключитесь к серверу MySQL от имени пользователя root. В этой лабораторной среде для подключения без пароля можно использовать sudo.
sudo mysql -u root
Когда появится приглашение mysql>, включите журнал общих запросов на глобальном уровне.
SET GLOBAL general_log = 'ON';
По умолчанию файл журнала хранится в каталоге данных MySQL. Чтобы упростить доступ к нему, измените путь и укажите каталог /tmp.
SET GLOBAL general_log_file = '/tmp/mysql_general.log';
Проверьте новый путь с помощью команды:
SHOW VARIABLES LIKE 'general_log_file';
В выводе должен быть указан заданный вами путь.
+------------------+-------------------------+
| Variable_name | Value |
+------------------+-------------------------+
| general_log_file | /tmp/mysql_general.log |
+------------------+-------------------------+
1 row in set (0.01 sec)
Теперь выполните несколько команд, чтобы добавить записи в журнал.
CREATE DATABASE IF NOT EXISTS testdb;
USE testdb;
SELECT 'Logging this query' AS message;
После выполнения команд выйдите из оболочки MySQL.
exit
Вернувшись в терминал, просмотрите содержимое файла журнала.
sudo cat /tmp/mysql_general.log
В файле вы увидите выполненные команды, сведения о подключении и временные метки. Это подтверждает, что журнал общих запросов работает правильно.
/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
В завершение отключите журнал — это хорошая практика. Сделать это можно прямо из терминала.
sudo mysql -u root -e "SET GLOBAL general_log = 'OFF';"
Так журнал не будет продолжать расти и влиять на производительность сервера.
Обработайте ошибки в хранимой процедуре
Хранимые процедуры могут завершаться с ошибкой по разным причинам, например если попытаться вставить повторяющееся значение в столбец первичного ключа. Обработчик ошибок позволяет перехватить такую ошибку и корректно отреагировать на неё, а не допустить аварийного завершения процедуры. На этом этапе вы создадите хранимую процедуру с обработчиком ошибок повторяющегося ключа.
Сначала подключитесь к серверу MySQL.
sudo mysql -u root
Создайте базу данных testdb, если она ещё не существует, и переключитесь на неё. Затем создайте таблицу products.
CREATE DATABASE IF NOT EXISTS testdb;
USE testdb;
CREATE TABLE products (
id INT PRIMARY KEY,
name VARCHAR(255),
quantity INT
);
Теперь создайте хранимую процедуру для добавления товара. В ней будет использоваться DECLARE HANDLER, который перехватывает ошибки повторяющегося ключа (SQLSTATE 23000) и возвращает пользовательское сообщение.
Команда DELIMITER меняет завершающий символ оператора с ; на //. Благодаря этому точка с запятой внутри тела процедуры обрабатывается правильно.
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 ;
Проверьте работу процедуры. Сначала добавьте новый товар.
CALL insert_product(1, 'Laptop');
Команда должна выполниться успешно и вернуть сообщение об успешной вставке.
+--------------------------------+
| message |
+--------------------------------+
| Product inserted successfully. |
+--------------------------------+
1 row in set (0.00 sec)
Теперь попробуйте добавить товар с тем же значением id.
CALL insert_product(1, 'Desktop');
На этот раз сработает обработчик ошибок. Вместо стандартной ошибки MySQL вы получите пользовательское сообщение.
+-----------------------------------------------+
| message |
+-----------------------------------------------+
| Error: Product with this ID already exists. |
+-----------------------------------------------+
1 row in set (0.00 sec)
Этот пример показывает, как обработчики ошибок помогают сделать хранимые процедуры надёжнее и удобнее для пользователей.
Вызывайте пользовательские ошибки с помощью SIGNAL
Обработчики перехватывают ошибки, а оператор SIGNAL позволяет вызывать их. Это полезно, когда нужно обеспечить соблюдение бизнес-правил, которые не задаются стандартными ограничениями базы данных. На этом этапе вы создадите процедуру, которая с помощью SIGNAL запрещает указывать отрицательное количество товара.
Вы должны находиться в оболочке MySQL. Если вы уже вышли из неё, подключитесь снова.
sudo mysql -u root
Убедитесь, что выбрана база данных testdb.
USE testdb;
Теперь создайте хранимую процедуру для изменения количества товара. Процедура проверит, не является ли новое количество отрицательным. Если является, она вызовет пользовательскую ошибку с помощью SIGNAL.
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' — общий код состояния для пользовательских ошибок. В MESSAGE_TEXT задаётся сообщение об ошибке, которое получит клиент.
Проверьте работу процедуры. Сначала попробуйте изменить количество товара «Laptop», добавленного на предыдущем этапе, на допустимое значение.
CALL update_quantity(1, 50);
Команда должна выполниться успешно.
+--------------------------------+
| message |
+--------------------------------+
| Quantity updated successfully. |
+--------------------------------+
1 row in set (0.00 sec)
Теперь попробуйте указать отрицательное количество.
CALL update_quantity(1, -10);
При этом вызове сработает оператор SIGNAL, и процедура завершится с пользовательской ошибкой.
ERROR 1644 (45000): Error: Quantity cannot be negative.
Этот результат подтверждает, что с помощью SIGNAL можно задавать собственные правила работы с данными в базе.
Изучите журнал ошибок MySQL
Журнал ошибок MySQL — основной источник сведений для диагностики проблем на уровне сервера. В нём записываются события запуска и остановки сервера, критические ошибки и предупреждения. На этом этапе вы проверите настройки журнала ошибок и сравните ведение журналов в контейнерных и традиционных средах.
Вы должны находиться в оболочке MySQL. Сначала узнайте путь к файлу журнала ошибок, проверив значение переменной log_error.
SHOW VARIABLES LIKE 'log_error';
В среде виртуальной машины LabEx, работающей в контейнере Docker, путь к журналу ошибок может быть пустым:
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_error | |
+---------------+-------+
1 row in set (0.001 sec)
Примечание. В контейнерных средах, таких как эта виртуальная машина LabEx, сообщения об ошибках MySQL/MariaDB часто направляются в стандартный поток ошибок контейнера, а не в обычный файл журнала. Это распространённая практика в Docker, которая соответствует методологии «12-факторного приложения».
Проверим обработку ошибок, попытавшись обратиться к несуществующей базе данных:
USE non_existent_database;
Как и ожидается, клиент сообщит об ошибке.
ERROR 1049 (42000): Unknown database 'non_existent_database'
Теперь выйдите из оболочки MySQL, чтобы вернуться в терминал.
exit
В рабочей среде с традиционной установкой MySQL на системах Ubuntu файл журнала ошибок обычно находится по пути /var/log/mysql/error.log. Проверьте, существует ли этот файл:
sudo ls -la /var/log/mysql/ 2> /dev/null || echo "MySQL log directory not found (normal in containerized environments)"
Как ведётся журнал ошибок в разных средах:
- Традиционная установка: записи об ошибках сохраняются в файлы, например
/var/log/mysql/error.log - Контейнерная среда: сообщения об ошибках часто направляются в stdout/stderr и собираются средой выполнения контейнеров
- Облачные базы данных: доступ к журналам ошибок обычно предоставляется через интерфейс управления облачного провайдера
В рабочей среде следует регулярно просматривать журналы ошибок с помощью таких команд:
sudo tail -f /var/log/mysql/error.log(чтобы следить за журналом в реальном времени)sudo grep -i error /var/log/mysql/error.log(чтобы найти сообщения об определённых ошибках)
Это необходимо для контроля состояния сервера и поиска причин таких проблем, как сбои при запуске, повреждение таблиц или ошибки разрешений.
Итоги
В этой лабораторной работе вы освоили основные приёмы обработки ошибок и ведения журналов в MySQL. Сначала вы включили и настроили журнал общих запросов, который позволяет отслеживать SQL-операторы и помогает при отладке. Затем вы добавили в хранимую процедуру обработчик DECLARE HANDLER, чтобы корректно обрабатывать определённые ошибки.
Кроме того, вы научились обеспечивать соблюдение бизнес-правил с помощью пользовательских ошибок, вызываемых оператором SIGNAL. Такие ошибки позволяют возвращать понятные и конкретные сообщения. В завершение вы изучили ведение журналов ошибок MySQL и узнали, чем оно отличается при традиционной установке и в контейнерных средах, например в контейнерах Docker.
Вы узнали, что при традиционной установке MySQL журнал ошибок записывается в файл, например /var/log/mysql/error.log, а в контейнерных средах сообщения об ошибках часто перенаправляются в stdout/stderr. Такой подход упрощает интеграцию с платформами оркестрации контейнеров. Понимание этих различий важно для работы с современными средами развёртывания.
Освоив эти приёмы, вы сможете создавать надёжные приложения для работы с базами данных, эффективнее устранять неполадки и обеспечивать целостность баз MySQL в разных сценариях развёртывания.


