【数据库】MySQL 实战精通系列 · 第1篇:MySQL 全局观与实战环境搭建

MySQL 实战精通系列 · 第1篇:MySQL 全局观与实战环境搭建

本篇目标:搞懂 MySQL 怎么跑起来,一条 SQL 从输入到返回经历了什么,并搭好贯穿全系列的电商实战环境。


文章目录

  • [MySQL 实战精通系列 · 第1篇:MySQL 全局观与实战环境搭建](#MySQL 实战精通系列 · 第1篇:MySQL 全局观与实战环境搭建)
    • [一、先建立全局观:MySQL 长什么样?](#一、先建立全局观:MySQL 长什么样?)
      • [1.1 MySQL 三层架构](#1.1 MySQL 三层架构)
      • [1.2 一条 SQL 的完整生命周期](#1.2 一条 SQL 的完整生命周期)
    • [二、MySQL 适合什么场景?](#二、MySQL 适合什么场景?)
      • [2.1 OLTP vs OLAP](#2.1 OLTP vs OLAP)
    • [三、实战环境搭建:Docker 启动 MySQL 8.0](#三、实战环境搭建:Docker 启动 MySQL 8.0)
      • [3.1 安装 Docker](#3.1 安装 Docker)
      • [3.2 启动 MySQL 8.0](#3.2 启动 MySQL 8.0)
      • [3.3 连接 MySQL](#3.3 连接 MySQL)
      • [3.4 常用管理命令](#3.4 常用管理命令)
    • [四、创建电商实战库 shop](#四、创建电商实战库 shop)
      • [4.1 核心表设计](#4.1 核心表设计)
      • [4.2 建表 SQL](#4.2 建表 SQL)
      • [4.3 插入测试数据](#4.3 插入测试数据)
    • [五、看一条 SQL 到底慢在哪:SHOW PROFILES](#五、看一条 SQL 到底慢在哪:SHOW PROFILES)
      • [5.1 开启 profiling](#5.1 开启 profiling)
      • [5.2 执行一条 SQL 并查看耗时](#5.2 执行一条 SQL 并查看耗时)
      • [5.3 查看详细阶段](#5.3 查看详细阶段)
    • 六、本篇实战任务
    • 七、本篇小结

一、先建立全局观:MySQL 长什么样?

1.1 MySQL 三层架构

MySQL 可以分成三层,理解这三层,后面所有优化和排障都有了方向。

复制代码
┌─────────────────────────────────────────────┐
│              客户端 / 应用程序                │
└─────────────────────┬───────────────────────┘
                      ↓
┌─────────────────────────────────────────────┐
│  连接层                                      │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐    │
│  │ 连接管理  │ │ 权限认证  │ │  线程池   │    │
│  └──────────┘ └──────────┘ └──────────┘    │
└─────────────────────┬───────────────────────┘
                      ↓
┌─────────────────────────────────────────────┐
│  Server 层                                   │
│  ┌────────┐ ┌────────┐ ┌────────┐ ┌──────┐ │
│  │ SQL解析 │ │ 优化器  │ │ 执行器  │ │Binlog│ │
│  └────────┘ └────────┘ └────────┘ └──────┘ │
└─────────────────────┬───────────────────────┘
                      ↓
┌─────────────────────────────────────────────┐
│  存储引擎层                                  │
│  ┌────────┐ ┌────────┐ ┌────────┐          │
│  │ InnoDB │ │ MyISAM │ │ Memory │          │
│  └────────┘ └────────┘ └────────┘          │
└─────────────────────┬───────────────────────┘
                      ↓
┌─────────────────────────────────────────────┐
│              磁盘 / 文件系统                  │
└─────────────────────────────────────────────┘
层 通俗理解 负责什么
连接层 前台 接待客户端、验证身份、分配线程
Server 层 大脑 解析 SQL、决定怎么查、执行查询
存储引擎层 仓库 真正把数据存到磁盘、从磁盘取出来

关键点 :MySQL 的 Server 层和存储引擎层是分离的,所以引擎可以插拔。现在默认且最常用的是 InnoDB。


1.2 一条 SQL 的完整生命周期

假设执行:

sql 复制代码
SELECT * FROM users WHERE id = 100;

内部流程:

复制代码
客户端
  │
  │ 发送 SQL
  ↓
连接层
  │
  │ 验证权限、分配线程
  ↓
解析器
  │
  │ 检查语法、生成语法树
  ↓
优化器
  │
  │ 决定用哪个索引、先查哪张表
  ↓
执行器
  │
  │ 按执行计划调用存储引擎接口
  ↓
InnoDB 引擎
  │
  │ 从 Buffer Pool 或磁盘读数据
  ↓
磁盘
  │
  │ 返回数据页
  ↓
InnoDB 引擎
  │
  │ 返回行
  ↓
执行器
  │
  │ 返回结果
  ↓
客户端
阶段 做什么 出问题会怎样
解析器 检查语法、表是否存在 语法错误、表不存在
优化器 决定用哪个索引、先查哪张表 选错索引,查询变慢
执行器 按执行计划调用引擎接口 执行效率低
InnoDB 从 Buffer Pool 或磁盘读数据 磁盘 IO 高、缓冲池命中率低

以后优化 SQL,本质上就是在影响 优化器 的选择,以及 InnoDB 的读取效率。


二、MySQL 适合什么场景?

2.1 OLTP vs OLAP

很多人用 MySQL 做报表、做大数据分析,然后发现特别慢。原因是没分清 OLTP 和 OLAP。

复制代码
┌─────────────────────────┐     ┌─────────────────────────┐
│   OLTP 联机事务处理      │     │   OLAP 联机分析处理      │
│                         │     │                         │
│   · 电商下单            │     │   · 报表                │
│   · 支付                │     │   · 数据仓库            │
│   · 用户注册            │     │   · BI 分析             │
│                         │     │                         │
│   高并发、短事务         │     │   低并发、长查询         │
│   小数据量              │     │   大数据量              │
└───────────┬─────────────┘     └───────────┬─────────────┘
            │                               │
            ↓                               ↓
     ┌─────────────┐                 ┌─────────────────────┐
     │   MySQL     │                 │ ClickHouse / Doris  │
     │  主战场      │                 │ / Hive / Spark      │
     └─────────────┘                 └─────────────────────┘
维度 OLTP OLAP
典型场景 电商下单、支付 报表、数据仓库
特点 高并发、短事务、小数据量 低并发、长查询、大数据量
常用数据库 MySQL、PostgreSQL ClickHouse、Hive、Spark
优化目标 响应快、事务稳 吞吐大、扫描快

结论:

  • MySQL 的主战场是 OLTP。
  • 复杂报表应同步到 ClickHouse、Doris 等 OLAP 数据库。
  • 不要指望 MySQL 既扛高并发写入,又跑复杂分析。

三、实战环境搭建:Docker 启动 MySQL 8.0

3.1 安装 Docker

去 Docker 官网安装,装好后验证:

bash 复制代码
docker --version

能输出版本号即可。


3.2 启动 MySQL 8.0

bash 复制代码
docker run -d \
  --name mysql8 \
  -p 3306:3306 \
  -e MYSQL_ROOT_PASSWORD=root123 \
  -e MYSQL_DATABASE=shop \
  -v mysql8_data:/var/lib/mysql \
  mysql:8.0 \
  --character-set-server=utf8mb4 \
  --collation-server=utf8mb4_unicode_ci
参数 作用
-d 后台运行
--name mysql8 容器名
-p 3306:3306 端口映射
MYSQL_ROOT_PASSWORD root 密码
MYSQL_DATABASE 自动创建 shop 库
-v mysql8_data 数据卷,防止数据丢失
utf8mb4 支持 emoji 和完整 Unicode

3.3 连接 MySQL

bash 复制代码
docker exec -it mysql8 mysql -uroot -proot123

进入后验证:

sql 复制代码
SHOW DATABASES;
USE shop;
SELECT VERSION();

看到版本号,说明环境 OK。


3.4 常用管理命令

bash 复制代码
# 查看容器状态
docker ps -a

# 启动 / 停止 / 重启
docker start mysql8
docker stop mysql8
docker restart mysql8

# 查看日志
docker logs mysql8

# 进入容器 bash
docker exec -it mysql8 bash

四、创建电商实战库 shop

4.1 核心表设计

复制代码
┌──────────┐       ┌──────────┐       ┌──────────┐
│  users   │       │  orders  │       │order_items│
├──────────┤       ├──────────┤       ├──────────┤
│ id (PK)  │──┐    │ id (PK)  │──┐    │ id (PK)  │
│ username │  │    │ user_id  │  │    │ order_id │
│ phone    │  └───>│ total    │  └───>│ product_id│
│ created  │       │ status   │       │ quantity │
└──────────┘       │ created  │       │ price    │
                   └──────────┘       └──────────┘
                        │                   ↑
                        │                   │
                        ↓                   │
                   ┌──────────┐       ┌──────────┐
                   │ payments │       │ products │
                   ├──────────┤       ├──────────┤
                   │ id (PK)  │       │ id (PK)  │
                   │ order_id │       │ name     │
                   │ amount   │       │ price    │
                   │ status   │       │ stock    │
                   │ paid_at  │       │category_id│
                   └──────────┘       │ created  │
                                      └──────────┘
                                           ↑
                                           │
                                      ┌──────────┐
                                      │categories│
                                      ├──────────┤
                                      │ id (PK)  │
                                      │ name     │
                                      │ parent_id│
                                      └──────────┘

┌──────────┐
│ addresses│
├──────────┤
│ id (PK)  │
│ user_id  │
│ detail   │
│ phone    │
└──────────┘

关系说明:

复制代码
users      1 ──── N  orders        一个用户多个订单
orders     1 ──── N  order_items   一个订单多个订单项
products   1 ──── N  order_items   一个商品可被多次购买
orders     1 ──── N  payments      一个订单多次支付
users      1 ──── N  addresses     一个用户多个地址
categories 1 ──── N  products      一个分类多个商品

4.2 建表 SQL

sql 复制代码
USE shop;

CREATE TABLE users (
    id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    username VARCHAR(64) NOT NULL,
    phone VARCHAR(20) NOT NULL,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (id),
    UNIQUE KEY uk_phone (phone)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE categories (
    id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    name VARCHAR(64) NOT NULL,
    parent_id BIGINT UNSIGNED NOT NULL DEFAULT 0,
    PRIMARY KEY (id),
    KEY idx_parent (parent_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE products (
    id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    name VARCHAR(128) NOT NULL,
    price DECIMAL(10,2) NOT NULL,
    stock INT NOT NULL DEFAULT 0,
    category_id BIGINT UNSIGNED NOT NULL DEFAULT 0,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (id),
    KEY idx_name (name),
    KEY idx_category (category_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE orders (
    id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    user_id BIGINT UNSIGNED NOT NULL,
    total_amount DECIMAL(10,2) NOT NULL DEFAULT 0.00,
    status TINYINT NOT NULL DEFAULT 0,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (id),
    KEY idx_user_created (user_id, created_at),
    KEY idx_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE order_items (
    id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    order_id BIGINT UNSIGNED NOT NULL,
    product_id BIGINT UNSIGNED NOT NULL,
    quantity INT NOT NULL,
    price DECIMAL(10,2) NOT NULL,
    PRIMARY KEY (id),
    KEY idx_order (order_id),
    KEY idx_product (product_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE payments (
    id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    order_id BIGINT UNSIGNED NOT NULL,
    amount DECIMAL(10,2) NOT NULL,
    status TINYINT NOT NULL DEFAULT 0,
    paid_at DATETIME DEFAULT NULL,
    PRIMARY KEY (id),
    KEY idx_order (order_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE addresses (
    id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    user_id BIGINT UNSIGNED NOT NULL,
    detail VARCHAR(255) NOT NULL,
    phone VARCHAR(20) NOT NULL,
    PRIMARY KEY (id),
    KEY idx_user (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

4.3 插入测试数据

sql 复制代码
INSERT INTO users (username, phone) VALUES
('张三', '13800000001'),
('李四', '13800000002'),
('王五', '13800000003');

INSERT INTO categories (name, parent_id) VALUES
('手机', 0),
('电脑', 0),
('苹果', 1),
('小米', 1),
('华为', 1);

INSERT INTO products (name, price, stock, category_id) VALUES
('iPhone 15', 5999.00, 100, 3),
('小米 14', 3999.00, 200, 4),
('华为 Mate 60', 6999.00, 150, 5);

INSERT INTO orders (user_id, total_amount, status) VALUES
(1, 5999.00, 1),
(1, 3999.00, 1),
(2, 6999.00, 0);

INSERT INTO order_items (order_id, product_id, quantity, price) VALUES
(1, 1, 1, 5999.00),
(2, 2, 1, 3999.00),
(3, 3, 1, 6999.00);

INSERT INTO payments (order_id, amount, status, paid_at) VALUES
(1, 5999.00, 1, NOW()),
(2, 3999.00, 1, NOW());

INSERT INTO addresses (user_id, detail, phone) VALUES
(1, '北京市朝阳区xxx', '13800000001'),
(2, '上海市浦东新区xxx', '13800000002');

五、看一条 SQL 到底慢在哪:SHOW PROFILES

5.1 开启 profiling

sql 复制代码
SET profiling = 1;

5.2 执行一条 SQL 并查看耗时

sql 复制代码
SELECT * FROM orders WHERE user_id = 1;

SHOW PROFILES;

结果类似:

Query_ID Duration Query
1 0.00045 SELECT * FROM orders WHERE user_id = 1

5.3 查看详细阶段

sql 复制代码
SHOW PROFILE FOR QUERY 1;

输出阶段按顺序如下:

复制代码
starting
   │
   ↓
checking permissions
   │
   ↓
Opening tables
   │
   ↓
init
   │
   ↓
System lock
   │
   ↓
optimizing
   │
   ↓
statistics
   │
   ↓
preparing
   │
   ↓
executing
   │
   ↓
Sending data

用表格看得更清楚:

顺序 阶段 含义 慢说明什么
1 starting 开始 ---
2 checking permissions 检查权限 权限配置复杂
3 Opening tables 打开表 表太多或元数据锁
4 init 初始化 ---
5 System lock 系统锁 锁竞争
6 optimizing 优化 索引统计信息有问题
7 statistics 统计 统计信息过期
8 preparing 准备 ---
9 executing 执行 SQL 本身效率低
10 Sending data 发送数据 数据量大或网络慢

实战意义:这是你未来排查慢 SQL 的第一把工具。哪个阶段耗时最长,问题就往哪个方向查。


六、本篇实战任务

任务清单

  • 用 Docker 启动 MySQL 8.0
  • 连接 MySQL,创建 shop 库
  • 执行全部建表 SQL
  • 插入测试数据
  • 开启 profiling,执行一条 SQL
  • 用 SHOW PROFILES 查看各阶段耗时
  • 用 SHOW PROFILE FOR QUERY 查看详细阶段

自检问题

  1. MySQL 三层架构分别是什么?
  2. 一条 SQL 从输入到返回经历了哪些阶段?
  3. OLTP 和 OLAP 的区别是什么?MySQL 适合哪个?
  4. SHOW PROFILES 能帮你看什么?
  5. 为什么说优化 SQL 本质是在影响优化器和 InnoDB?

七、本篇小结

复制代码
第1篇 核心收获
│
├── 架构
│   ├── 连接层:接待客户端
│   ├── Server层:解析、优化、执行
│   └── 存储引擎层:InnoDB 负责读写
│
├── SQL生命周期
│   ├── 解析:检查语法
│   ├── 优化:选索引
│   ├── 执行:调引擎接口
│   └── 存储引擎:读数据页
│
├── 场景定位
│   ├── OLTP 是 MySQL 主战场
│   └── OLAP 交给 ClickHouse
│
├── 实战环境
│   ├── Docker 启动 MySQL 8.0
│   └── shop 电商库 7 张表
│
└── 排障工具
    ├── SHOW PROFILES
    └── SHOW PROFILE FOR QUERY

下一篇:第2篇《数据建模与建表实战》

相关推荐
霸道流氓气质1 小时前
LangGraph式图编排引擎Java实现:状态机模型、Checkpoint恢复与生产级落地实战
java·开发语言·数据库
数据狐(Datafox)1 小时前
淘宝商品详情API实战:多语言代购商城自动同步数据完整方案
开发语言·前端·数据库·爬虫·json
Leo.yuan1 小时前
帆软 Data Agent 技术实践白皮书:NL2BI 的可执行与可追溯分析链路
数据库·microsoft
细嗅蔷薇@2 小时前
DDL常见操作汇总
数据库·sql·mysql
颜颜yan_2 小时前
从 InfluxDB 到 DolphinDB:一场国产时序数据库的替代与超越
数据库·时序数据库
-madongyu-2 小时前
GaussDB SQL 执行引擎:查询重写、优化器与执行器
数据库·sql·gaussdb
oradh2 小时前
Oracle SQL Tuning Advisor调优工具
数据库·sql·oracle
Omics Pro2 小时前
空间组学!医学代谢显微工具
数据库·人工智能·算法·机器学习·自然语言处理
Yyyyyy~2 小时前
[mysql]day1
数据库·mysql