Введение в MySQL
Что такое MySQL
MySQL — реляционная СУБД с открытым исходным кодом. Появилась в 1995, с 2010 принадлежит Oracle.
Особенности:
- ACID (в InnoDB).
- Скорость на чтение.
- Простота установки.
- Огромная популярность — WordPress, Drupal, Bitrix, 1С-Битрикс.
- Две лицензии: GPL и коммерческая.
Где используется
- Веб-сайты — большинство CMS.
- Интернет-магазины — WooCommerce, OpenCart.
- Форумы, блоги.
- Внутренние системы.
Крупные проекты: Facebook, Twitter, YouTube, Booking.com (исторически).
MySQL vs MariaDB vs PostgreSQL
| MySQL | MariaDB | PostgreSQL | |
|---|---|---|---|
| Владелец | Oracle | Community | Community |
| JSON | есть, но слабее | есть | JSONB, мощнее |
| Индексы | B-tree, FULLTEXT | B-tree, FULLTEXT | + GIN, GiST, BRIN |
| Оконные функции | с 8.0 | с 10.2 | давно |
| CTE | с 8.0 | с 10.2 | давно |
| Транзакционный DDL | нет | нет | да |
| Репликация | master-slave, GTID | master-slave, Galera | streaming, logical |
Правило:
- WordPress / legacy — MySQL / MariaDB.
- Новое — часто PostgreSQL, если нет причин иначе.
Архитектура
Клиент → MySQL Server → Storage Engine (InnoDB) → Файлы на диске
Компоненты:
- Connection layer — подключения.
- Parser — разбор SQL.
- Optimizer — план.
- Storage Engine — InnoDB, MyISAM и др.
Storage Engines
Основные:
- InnoDB — по умолчанию. ACID, FK, MVCC.
- MyISAM — без транзакций, устаревший.
- MEMORY — в RAM.
- CSV — данные в CSV.
- ARCHIVE — сжатие.
Правило: всегда InnoDB. MyISAM не даёт транзакций и FK.
Проверить движок:
SHOW TABLE STATUS FROM myapp LIKE 'users';
Установка (Ubuntu)
sudo apt update
sudo apt install mysql-server mysql-client
sudo systemctl enable mysql
sudo systemctl start mysql
Проверка:
mysql --version
# mysql Ver 8.0.36
Docker:
docker run -d \
--name mysql \
-e MYSQL_ROOT_PASSWORD=secret \
-e MYSQL_DATABASE=myapp \
-e MYSQL_USER=app \
-e MYSQL_PASSWORD=secret \
-p 3306:3306 \
mysql:8.0
Первое подключение
sudo mysql
Внутри:
SELECT VERSION();
SHOW DATABASES;
SELECT USER(), CURRENT_USER();
EXIT;
Создание базы и пользователя
CREATE DATABASE myapp
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
CREATE USER 'app'@'localhost' IDENTIFIED BY 'secret';
GRANT ALL PRIVILEGES ON myapp.* TO 'app'@'localhost';
FLUSH PRIVILEGES;
Что здесь:
utf8mb4— полный UTF-8 (включая эмодзи).utf8mb4_unicode_ci— регистронезависимое сравнение.@'localhost'— только с локального хоста.FLUSH PRIVILEGES— применить.
Кодировки
⚠️ В MySQL:
utf8— НЕ полный UTF-8 (только 3 байта).utf8mb4— настоящий UTF-8 (4 байта, эмодзи).
Правило: всегда utf8mb4.
Проверить:
SHOW VARIABLES LIKE 'character_set%';
SHOW VARIABLES LIKE 'collation%';
Подключение из приложения
Строка подключения:
mysql://app:secret@127.0.0.1:3306/myapp
Laravel (.env):
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=myapp
DB_USERNAME=app
DB_PASSWORD=secret
Node.js (mysql2):
import mysql from 'mysql2/promise';
const pool = mysql.createPool({
host: '127.0.0.1',
port: 3306,
user: 'app',
password: 'secret',
database: 'myapp',
charset: 'utf8mb4',
waitForConnections: true,
connectionLimit: 10,
});
const [rows] = await pool.query('SELECT NOW()');
Права пользователей
Виды:
ALL PRIVILEGES— всё.SELECT,INSERT,UPDATE,DELETE— данные.CREATE,DROP,ALTER— структура.GRANT OPTION— может давать права другим.
Пример:
CREATE USER 'readonly'@'%' IDENTIFIED BY 'read123';
GRANT SELECT ON myapp.* TO 'readonly'@'%';
Просмотр:
SHOW GRANTS FOR 'app'@'localhost';
Отозвать:
REVOKE INSERT, UPDATE ON myapp.* FROM 'app'@'localhost';
Правило: приложению — минимум прав.
Хосты
@'localhost' — только Unix-сокет.
@'127.0.0.1' — только TCP.
@'%' — любые хосты.
⚠️ localhost и 127.0.0.1 — разные! Если приложение идёт по TCP, а пользователь создан для localhost — не подключится.
Проверка состояния
SHOW STATUS LIKE 'Threads_connected';
SHOW STATUS LIKE 'Uptime';
SHOW PROCESSLIST;
Активные запросы:
SELECT id, user, host, db, command, time, state, info
FROM information_schema.processlist
WHERE command != 'Sleep'
ORDER BY time DESC;
Конфигурация
Основной файл:
- Ubuntu:
/etc/mysql/mysql.conf.d/mysqld.cnf - Docker:
/etc/mysql/conf.d/
Важное:
[mysqld]
bind-address = 127.0.0.1
max_connections = 150
innodb_buffer_pool_size = 1G # 70% RAM
innodb_log_file_size = 256M
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1
Применить:
sudo systemctl restart mysql
mysql_secure_installation
Базовая защита:
sudo mysql_secure_installation
Что делает:
- Установить пароль root.
- Удалить анонимных пользователей.
- Запретить root-логин удалённо.
- Удалить тестовую БД.
- Применить изменения.
Частые ошибки
1. Access denied for user:
Не совпадает хост, пароль или база
Решение: проверить SHOW GRANTS, user@host.
2. Too many connections:
max_connections = 151 по умолчанию
Решение: увеличить + connection pool.
3. Кракозябры:
Кодировка клиента ≠ сервера
Решение: utf8mb4 везде.
4. Пароль root забыт:
Остановить MySQL, --skip-grant-tables
Решение:
sudo systemctl stop mysql
sudo mysqld_safe --skip-grant-tables &
mysql -u root
FLUSH PRIVILEGES;
ALTER USER 'root'@'localhost' IDENTIFIED BY 'newpass';
5. Порт 3306 открыт в интернет:
Постоянные попытки подбора пароля
Решение: bind-address = 127.0.0.1, firewall.
Практика
1. Установите MySQL 8 или MariaDB через apt или Docker.
2. Создайте базу shop с utf8mb4.
3. Создайте пользователя shop_user с паролем и правами на shop.*.
4. Подключитесь по TCP:
mysql -h 127.0.0.1 -u shop_user -p shop
5. Проверьте кодировку и версию:
SELECT VERSION(), @@character_set_database, @@collation_database;
Итог
- MySQL — реляционная СУБД, принадлежит Oracle.
- InnoDB — движок по умолчанию.
- Кодировка: всегда
utf8mb4. - Хост:
localhost≠127.0.0.1. - Права: по минимуму.
- Настройка:
innodb_buffer_pool_size— главный параметр.
Дальше — установка и настройка.