Урок 01

Введение в 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

MySQLMariaDBPostgreSQL
ВладелецOracleCommunityCommunity
JSONесть, но слабееестьJSONB, мощнее
ИндексыB-tree, FULLTEXTB-tree, FULLTEXT+ GIN, GiST, BRIN
Оконные функциис 8.0с 10.2давно
CTEс 8.0с 10.2давно
Транзакционный DDLнетнетда
Репликацияmaster-slave, GTIDmaster-slave, Galerastreaming, 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 — главный параметр.

Дальше — установка и настройка.