MySQL — практическая работа и API
Другие СУБД в этом цикле: SQLite · PostgreSQL · Microsoft SQL Server · SQL — о разделе.
MySQL — серверная реляционная СУБД. Чаще всего используется с движком InnoDB, который даёт транзакции, внешние ключи, блокировки на уровне строк и надёжность для веб-приложений.
Как работает MySQL
- Запускается сервер
mysqld. - Клиенты подключаются по TCP или Unix socket.
- Данные и индексы хранятся в таблицах выбранного storage engine.
- InnoDB использует redo/undo logs и MVCC.
- Репликация работает в binlog-архитектуре.
SELECT VERSION();
SHOW VARIABLES LIKE 'default_storage_engine';
SHOW VARIABLES LIKE 'transaction_isolation';
Подключение и запуск
mysql CLI
mysql -h localhost -P 3306 -u app_user -p app_db
URI-подключение
mysql://app_user:secret@localhost:3306/app_db
mysql://app_user:secret@localhost:3306/app_db?charset=utf8mb4
Базовая настройка
CREATE DATABASE app_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'app_user'@'%' IDENTIFIED BY 'secret';
GRANT ALL PRIVILEGES ON app_db.* TO 'app_user'@'%';
FLUSH PRIVILEGES;
Типы данных и синтаксис
Основные типы MySQL:
- Числовые:
TINYINT,INT,BIGINT,DECIMAL,FLOAT,DOUBLE - Строковые:
CHAR,VARCHAR,TEXT - Дата/время:
DATE,TIME,DATETIME,TIMESTAMP - Бинарные:
BLOB,VARBINARY - JSON:
JSON - Логические значения обычно задают через
TINYINT(1)илиBOOLEAN(синоним)
CREATE TABLE users (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
email VARCHAR(255) NOT NULL UNIQUE,
profile JSON,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;
Возможности MySQL
- Полный базовый SQL для DDL/DML
- Транзакции (InnoDB)
INSERT ... ON DUPLICATE KEY UPDATEдля upsert-сценариев- Индексы, составные индексы, уникальные ограничения
VIEW,TRIGGER,PROCEDURE,FUNCTION, события (EVENT)- Репликация и кластерные варианты (Group Replication, InnoDB Cluster)
- JSON-тип и JSON-функции
- Партиционирование
Доступные и недоступные команды
| Категория | Команда / конструкция | Статус в MySQL | Комментарий |
|---|---|---|---|
| DML | SELECT, INSERT, UPDATE, DELETE | Доступно | Полная поддержка |
| DDL | CREATE/ALTER/DROP | Доступно | Поддерживается |
| Транзакции | BEGIN, COMMIT, ROLLBACK, SAVEPOINT | Доступно (InnoDB) | Зависит от storage engine |
| Права | CREATE USER, GRANT, REVOKE | Доступно | Развитая модель привилегий |
| Server-side логика | PROCEDURE, FUNCTION, TRIGGER, EVENT | Доступно | Поддерживается |
| Материализованные представления | CREATE MATERIALIZED VIEW | Недоступно | Имитация через таблицы + расписание |
Полноценный RETURNING в DML | Частично/ограничено | Проверяйте версию и совместимость | |
MERGE | Недоступно | Обычно заменяют upsert-паттернами | |
| Нативный тип массивов как в PostgreSQL | Недоступно | Используют JSON или отдельные таблицы | |
PostgreSQL-специфика (DISTINCT ON, ILIKE) | Недоступно | Используют альтернативы MySQL |
Практика SQL в MySQL
CRUD
CREATE TABLE tasks (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(255) NOT NULL,
done TINYINT(1) NOT NULL DEFAULT 0
) ENGINE=InnoDB;
INSERT INTO tasks(title) VALUES ('Пройти MySQL');
SELECT id, title, done FROM tasks ORDER BY id;
UPDATE tasks SET done = 1 WHERE id = 1;
DELETE FROM tasks WHERE id = 1;
Upsert
INSERT INTO tasks(id, title, done)
VALUES (1, 'Обновлённая задача', 0)
ON DUPLICATE KEY UPDATE
title = VALUES(title),
done = VALUES(done);
Транзакция
START TRANSACTION;
INSERT INTO tasks(title) VALUES ('A');
INSERT INTO tasks(title) VALUES ('B');
COMMIT;
Клиенты и инструменты
- mysql CLI
- MySQL Workbench
- phpMyAdmin
- DBeaver
- DataGrip
- TablePlus
- Beekeeper Studio
- VS Code + MySQL extensions
API по языкам — подключение, CRUD, библиотеки, классы и функции
C# — MySqlConnector
Библиотека
MySqlConnector(NuGet)
Ключевые классы
MySqlConnectionMySqlCommandMySqlTransactionMySqlDataReaderMySqlParameter
Свойства и методы
Open(),BeginTransaction(),Close()CommandText,Parameters.AddWithValue()ExecuteNonQuery(),ExecuteReader(),ExecuteScalar()Read(),GetString(),GetInt64()
using MySqlConnector;
var cs = "Server=localhost;Port=3306;User ID=app_user;Password=secret;Database=app_db;";
await using var conn = new MySqlConnection(cs);
await conn.OpenAsync();
await using (var cmd = new MySqlCommand("""
CREATE TABLE IF NOT EXISTS users(
id BIGINT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255) NOT NULL
) ENGINE=InnoDB
""", conn))
{
await cmd.ExecuteNonQueryAsync();
}
await using (var ins = new MySqlCommand("INSERT INTO users(name) VALUES (@name)", conn))
{
ins.Parameters.AddWithValue("@name", "Anna");
await ins.ExecuteNonQueryAsync();
}
await using (var sel = new MySqlCommand("SELECT id, name FROM users", conn))
await using (var reader = await sel.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
Console.WriteLine($"{reader.GetInt64(0)} {reader.GetString(1)}");
}
Python — mysql-connector-python или PyMySQL
Библиотеки
mysql-connector-pythonPyMySQL
Ключевые классы
MySQLConnectionCursor
Методы
connect()cursor(),execute(),executemany()fetchone(),fetchall()commit(),rollback(),close()
import mysql.connector
conn = mysql.connector.connect(
host="localhost", port=3306, user="app_user", password="secret", database="app_db"
)
cur = conn.cursor()
cur.execute("""
CREATE TABLE IF NOT EXISTS users(
id BIGINT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255) NOT NULL
) ENGINE=InnoDB
""")
cur.execute("INSERT INTO users(name) VALUES (%s)", ("Anna",))
conn.commit()
cur.execute("SELECT id, name FROM users")
for row in cur.fetchall():
print(row[0], row[1])
cur.execute("UPDATE users SET name=%s WHERE id=%s", ("Ann", 1))
cur.execute("DELETE FROM users WHERE id=%s", (1,))
conn.commit()
conn.close()
Java — MySQL Connector/J
Библиотека
com.mysql:mysql-connector-j
Ключевые классы
ConnectionPreparedStatementResultSetDriverManager
Методы
DriverManager.getConnection("jdbc:mysql://...")prepareStatement(),setAutoCommit(false),commit(),rollback()setString(),executeUpdate(),executeQuery()next(),getLong(),getString()
import java.sql.*;
try (Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/app_db", "app_user", "secret")) {
try (Statement st = conn.createStatement()) {
st.execute("""
CREATE TABLE IF NOT EXISTS users(
id BIGINT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255) NOT NULL
) ENGINE=InnoDB
""");
}
try (PreparedStatement ins = conn.prepareStatement("INSERT INTO users(name) VALUES (?)")) {
ins.setString(1, "Anna");
ins.executeUpdate();
}
try (PreparedStatement sel = conn.prepareStatement("SELECT id, name FROM users");
ResultSet rs = sel.executeQuery()) {
while (rs.next()) {
System.out.println(rs.getLong("id") + " " + rs.getString("name"));
}
}
}
C — MySQL C API (libmysqlclient)
Библиотека
libmysqlclient
Ключевые типы
MYSQLMYSQL_RESMYSQL_ROWMYSQL_STMT
Ключевые функции
mysql_init(),mysql_real_connect(),mysql_close()mysql_query(),mysql_store_result(),mysql_fetch_row()- Prepared statements:
mysql_stmt_init(),mysql_stmt_prepare(),mysql_stmt_bind_param(),mysql_stmt_execute() - Ошибки:
mysql_error(),mysql_errno()
#include <mysql.h>
#include <stdio.h>
int main(void) {
MYSQL *conn = mysql_init(NULL);
if (!mysql_real_connect(conn, "localhost", "app_user", "secret", "app_db", 3306, NULL, 0)) return 1;
mysql_query(conn, "CREATE TABLE IF NOT EXISTS users(id BIGINT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255) NOT NULL) ENGINE=InnoDB");
mysql_query(conn, "INSERT INTO users(name) VALUES ('Anna')");
mysql_query(conn, "SELECT id, name FROM users");
MYSQL_RES *res = mysql_store_result(conn);
MYSQL_ROW row;
while ((row = mysql_fetch_row(res))) {
printf("%s %s\n", row[0], row[1]);
}
mysql_free_result(res);
mysql_close(conn);
return 0;
}
C++ — MySQL Connector/C++ или SOCI
Библиотеки
- MySQL Connector/C++
- SOCI (через backend MySQL)
Ключевые классы (Connector/C++)
sql::Driversql::Connectionsql::PreparedStatementsql::ResultSet
Методы
driver->connect(...)prepareStatement(),execute(),executeQuery()setString(),next(),getString(),getInt64()
#include <iostream>
// Примерный стиль API Connector/C++
// auto* driver = get_driver_instance();
// std::unique_ptr<sql::Connection> conn(driver->connect("tcp://127.0.0.1:3306", "app_user", "secret"));
// conn->setSchema("app_db");
// ...
Go — go-sql-driver/mysql
Библиотеки
database/sqlgithub.com/go-sql-driver/mysql
Ключевые типы
*sql.DB*sql.Tx*sql.Rowssql.Result
Методы
sql.Open("mysql", dsn)Exec(),Query(),QueryRow()Begin(),Commit(),Rollback()Rows.Next(),Rows.Scan()
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
func main() {
db, _ := sql.Open("mysql", "app_user:secret@tcp(localhost:3306)/app_db?parseTime=true")
defer db.Close()
db.Exec(`CREATE TABLE IF NOT EXISTS users(id BIGINT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255) NOT NULL) ENGINE=InnoDB`)
db.Exec(`INSERT INTO users(name) VALUES (?)`, "Anna")
rows, _ := db.Query(`SELECT id, name FROM users`)
defer rows.Close()
for rows.Next() {
var id int64
var name string
rows.Scan(&id, &name)
fmt.Println(id, name)
}
}
PHP — mysqli и PDO_MySQL
Библиотеки
mysqli- PDO (
mysql)
Ключевые классы
mysqli,mysqli_stmt,mysqli_resultPDO,PDOStatement
Методы
new mysqli(...),prepare(),bind_param(),execute(),get_result()new PDO("mysql:host=...;dbname=..."),prepare(),execute(),fetchAll()
<?php
$db = new PDO("mysql:host=localhost;port=3306;dbname=app_db;charset=utf8mb4", "app_user", "secret");
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->exec("CREATE TABLE IF NOT EXISTS users(id BIGINT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255) NOT NULL) ENGINE=InnoDB");
$stmt = $db->prepare("INSERT INTO users(name) VALUES (:name)");
$stmt->execute([':name' => 'Anna']);
$rows = $db->query("SELECT id, name FROM users")->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as $row) {
echo $row['id'] . " " . $row['name'] . PHP_EOL;
}
Kotlin — JDBC (MySQL)
Библиотека
- JDBC + MySQL Connector/J
Ключевые классы
ConnectionPreparedStatementResultSet
Методы
DriverManager.getConnection()prepareStatement(),executeUpdate(),executeQuery()setString(),next(),getLong(),getString()
import java.sql.DriverManager
fun main() {
DriverManager.getConnection(
"jdbc:mysql://localhost:3306/app_db", "app_user", "secret"
).use { conn ->
conn.createStatement().use { st ->
st.execute(
"CREATE TABLE IF NOT EXISTS users(id BIGINT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255) NOT NULL) ENGINE=InnoDB"
)
}
conn.prepareStatement("INSERT INTO users(name) VALUES (?)").use { ps ->
ps.setString(1, "Anna")
ps.executeUpdate()
}
conn.prepareStatement("SELECT id, name FROM users").use { ps ->
ps.executeQuery().use { rs ->
while (rs.next()) println("${rs.getLong("id")} ${rs.getString("name")}")
}
}
}
}
Rust — mysql и sqlx
Библиотеки
mysql(синхронный клиент)sqlx(async)
Ключевые типы (mysql crate)
PoolPooledConnTxOptsQueryable
Методы
Pool::new()get_conn()query_drop(),exec_drop(),query()start_transaction(),commit(),rollback()
use mysql::*;
use mysql::prelude::*;
fn main() -> Result<()> {
let pool = Pool::new("mysql://app_user:secret@localhost:3306/app_db")?;
let mut conn = pool.get_conn()?;
conn.query_drop("CREATE TABLE IF NOT EXISTS users(id BIGINT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255) NOT NULL) ENGINE=InnoDB")?;
conn.exec_drop("INSERT INTO users(name) VALUES (?)", ("Anna",))?;
let rows: Vec<(u64, String)> = conn.query("SELECT id, name FROM users")?;
for (id, name) in rows {
println!("{id} {name}");
}
Ok(())
}
JavaScript — mysql2
Библиотека
mysql2(promise API)
Ключевые объекты
ConnectionPool- результаты
RowDataPacket[]
Методы
createConnection(),createPool()execute(sql, params),query()- транзакции:
beginTransaction(),commit(),rollback()
import mysql from "mysql2/promise";
const conn = await mysql.createConnection({
host: "localhost",
port: 3306,
user: "app_user",
password: "secret",
database: "app_db",
});
await conn.execute(
"CREATE TABLE IF NOT EXISTS users(id BIGINT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255) NOT NULL) ENGINE=InnoDB"
);
await conn.execute("INSERT INTO users(name) VALUES (?)", ["Anna"]);
const [rows] = await conn.execute("SELECT id, name FROM users");
for (const row of rows) {
console.log(row.id, row.name);
}
await conn.execute("UPDATE users SET name=? WHERE id=?", ["Ann", 1]);
await conn.execute("DELETE FROM users WHERE id=?", [1]);
await conn.end();
Минимальный шаблон безопасной работы
- Используйте параметризованные запросы.
- Выбирайте InnoDB для транзакционных таблиц.
- Фиксируйте
charsetкакutf8mb4. - Ограничивайте права пользователей по ролям/схемам.
- Настраивайте таймауты и пул подключений.
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
SET SESSION innodb_lock_wait_timeout = 10;
SHOW VARIABLES LIKE 'sql_mode';
Когда MySQL подходит и когда выбрать другой путь
MySQL подходит:
- веб-приложения и сервисы с привычным стеком LAMP/LEMP;
- высоконагруженные OLTP-сценарии на InnoDB;
- проекты, где важна простота эксплуатации и большой рынок tooling.
Другой путь выбирают:
- для сложной аналитики и специфических типов удобен PostgreSQL;
- для локального файла внутри приложения удобнее SQLite;
- для специализированного OLAP часто берут колоночные СУБД.
См. также
Другие статьи этого же раздела в боковом меню (как на странице "О разделе"). Вот SQL как раз обеспечивает такую связь и это главное отличие реляционных БД - реляции (relations), что означает связи. Знакомимся с языком - ставим программы, запускаем, выполняем первые запросы. От файлового хранения к реляционной и современной мультимодельной СУБД — термины, причины появления SQL и базовая классификация систем. Домены, атрибуты, кортежи и отношения — свойства реляционных таблиц и ограничения целостности при проектировании схемы. Функциональные зависимости, нормальные формы 1НФ–3НФ, аномалии обновления и осознанная денормализация при проектировании схемы. Метаданные СУБД через information_schema и pg_catalog — запросы к структуре таблиц, ключей и индексов в PostgreSQL. Логическое и физическое резервное копирование, pg_dump, pg_restore, WAL и восстановление на точку во времени (PITR). Логический порядок выполнения SELECT, проекция, WHERE, DISTINCT, ORDER BY и правила читаемого форматирования запросов. Скалярные и коррелированные подзапросы, EXISTS против IN, особенности NULL и выбор между подзапросом и JOIN. AND, OR, NOT, приоритет операторов, NULL и UNKNOWN, IS NULL, NOT IN и IS DISTINCT FROM в PostgreSQL. MVCC, уровни блокировок таблиц, FOR UPDATE, SKIP LOCKED, взаимоблокировки и диагностика через pg_locks. Учебная схема интернет-магазина для PostgreSQL — DDL и примеры запросов по темам курса SQL.SQL - язык структурированных запросов
Первые шаги с SQL
Эволюция систем хранения данных
Реляционная модель данных
Нормализация данных
Словарь данных и системные каталоги
Резервное копирование и восстановление PostgreSQL
Оператор SELECT — синтаксис и стиль
Подзапросы, EXISTS и IN
Фильтрация и трёхзначная логика
Блокировки и конкурентный доступ в PostgreSQL
Практикум shop_data