第六周详细练习手册:MySQL 深度使用
第六周是你整个学习路线的第三个质变点。前五周你在练 Linux 基础和 Shell 自动化,这周你要进入数据库领域——这是运维工程师能力模型里和 Linux 并列的另一条腿。
第六周详细练习手册:MySQL 深度使用
核心目标:
-
能独立完成 MySQL 的安装、配置、权限管理
-
掌握 SELECT/JOIN/GROUP BY 等核心查询
-
理解慢查询分析和索引优化
-
能用 mysqldump 做逻辑备份和恢复
你已经有的环境:CentOS 9 虚拟机 + MySQL 8.0 已安装。
第一天:确认环境 + 理解 MySQL 的“文件住哪”
练习 1:确认 MySQL 状态和版本
# 1. 确认服务在跑
[xtc@localhost ~]$ systemctl status mysqld
# 如果是 active (running),继续
# 如果不是:
sudo systemctl start mysqld
sudo systemctl enable mysqld
# 2. 看版本
[xtc@localhost ~]$ mysql --version
# 或进 MySQL 后查:
mysql -u root -p
mysql> SELECT VERSION();
# 3. 看配置文件在哪
[xtc@localhost ~]$ ls -la /etc/my.cnf
[xtc@localhost ~]$ ls -la /etc/my.cnf.d/
# MySQL 8 的配置分散在主文件和配置目录里
练习 2:理解 MySQL 的数据目录
# 看数据存哪(这是生产环境最不能丢的目录)
mysql -u root -p -e "SHOW VARIABLES LIKE 'datadir';"
# 通常是 /var/lib/mysql
sudo ls -la /var/lib/mysql
# 能看到以数据库名命名的目录,一个库一个文件夹
# ibdata1 — InnoDB 系统表空间
# ib_logfile* — InnoDB 重做日志
# binlog.* — 二进制日志
自检:知道以下三个路径分别放什么
-
/etc/my.cnf— 配置文件 -
/var/lib/mysql— 数据文件(最重要的目录) -
/var/log/mysql— 日志文件(慢查询日志、错误日志)
第二天:SQL 核心查询——从零到能干活
练习 3:创建练习库和表
-- 登录 MySQL
mysql -u root -p
-- 创建练习数据库
CREATE DATABASE practice;
USE practice;
-- 创建员工表
CREATE TABLE employees (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
department VARCHAR(50),
salary DECIMAL(10,2),
hire_date DATE,
city VARCHAR(50)
);
-- 插入测试数据
INSERT INTO employees (name, department, salary, hire_date, city) VALUES
('张三', '运维部', 15000, '2020-03-15', '长春'),
('李四', '开发部', 20000, '2019-07-01', '北京'),
('王五', '运维部', 18000, '2021-01-10', '上海'),
('赵六', '测试部', 12000, '2022-06-20', '长春'),
('孙七', '开发部', 22000, '2018-11-05', '深圳'),
('周八', '运维部', 16000, '2023-02-28', '长春'),
('吴九', '测试部', 11000, '2022-09-01', '北京'),
('郑十', '开发部', 25000, '2017-05-15', '上海');
-- 验证
SELECT * FROM employees;
练习 4:基础查询(SELECT / WHERE / ORDER BY / LIMIT)
-- ===== 选列 =====
SELECT name, department, salary FROM employees;
-- ===== 条件过滤 =====
SELECT * FROM employees WHERE department = '运维部';
SELECT * FROM employees WHERE salary > 18000;
SELECT * FROM employees WHERE city = '长春' AND department = '运维部';
SELECT * FROM employees WHERE department IN ('运维部', '开发部');
SELECT * FROM employees WHERE salary BETWEEN 15000 AND 20000;
-- ===== 模糊搜索 =====
SELECT * FROM employees WHERE name LIKE '张%'; -- 姓张的
SELECT * FROM employees WHERE city LIKE '%海%'; -- 城市含"海"
-- ===== 排序 =====
SELECT * FROM employees ORDER BY salary DESC;
SELECT * FROM employees ORDER BY hire_date ASC;
-- ===== 分页 =====
SELECT * FROM employees ORDER BY salary DESC LIMIT 3;
SELECT * FROM employees ORDER BY id LIMIT 2 OFFSET 2; -- 跳过前2条
练习 5:聚合查询(统计用,运维做报表常用)
-- ===== 统计函数 =====
SELECT COUNT(*) FROM employees; -- 总人数
SELECT AVG(salary) FROM employees; -- 平均薪资
SELECT MAX(salary), MIN(salary) FROM employees; -- 最高最低
SELECT SUM(salary) FROM employees WHERE department = '运维部'; -- 部门薪资总额
-- ===== 分组统计(运维最重要的查询) =====
-- 每个部门多少人
SELECT department, COUNT(*) AS 人数 FROM employees GROUP BY department;
-- 每个部门平均薪资
SELECT department, AVG(salary) AS 平均薪资 FROM employees GROUP BY department;
-- 每个城市多少人
SELECT city, COUNT(*) AS 人数 FROM employees GROUP BY city ORDER BY 人数 DESC;
-- ===== 分组后过滤(HAVING,运维做报表常用) =====
-- 平均薪资超过 16000 的部门
SELECT department, AVG(salary) AS 平均薪资
FROM employees
GROUP BY department
HAVING AVG(salary) > 16000;
练习 6:多表联查(JOIN)
-- 创建第二个表:项目表
CREATE TABLE projects (
id INT PRIMARY KEY AUTO_INCREMENT,
project_name VARCHAR(100),
leader_id INT,
FOREIGN KEY (leader_id) REFERENCES employees(id)
);
INSERT INTO projects (project_name, leader_id) VALUES
('服务器迁移', 1),
('CI/CD搭建', 4),
('监控系统', 1),
('自动化测试', 4),
('日志平台', 3);
-- ===== INNER JOIN(两表都有的才显示) =====
SELECT e.name, e.department, p.project_name
FROM employees e
INNER JOIN projects p ON e.id = p.leader_id;
-- ===== LEFT JOIN(左表全显示,右表没有填 NULL) =====
SELECT e.name, e.department, p.project_name
FROM employees e
LEFT JOIN projects p ON e.id = p.leader_id;
-- 没负责项目的员工也会显示,project_name 为 NULL
-- ===== 多表联查加统计 =====
SELECT e.name, e.department, COUNT(p.id) AS 负责项目数
FROM employees e
LEFT JOIN projects p ON e.id = p.leader_id
GROUP BY e.id, e.name, e.department
ORDER BY 负责项目数 DESC;
自检题:
-
查出运维部薪资大于 15000 的员工。
-
统计每个部门的平均薪资,只看平均超过 16000 的。
-
LEFT JOIN 和 INNER JOIN 的区别是什么?
第三天:索引——从“查询慢”到“秒回”
练习 7:制造慢查询,感受索引
-- 先造一批测试数据(存储过程批量插入)
DELIMITER $$
CREATE PROCEDURE insert_test_data()
BEGIN
DECLARE i INT DEFAULT 1;
WHILE i <= 500000 DO
INSERT INTO employees (name, department, salary, hire_date, city)
VALUES (CONCAT('员工', i),
CASE i % 4 WHEN 0 THEN '运维部' WHEN 1 THEN '开发部' WHEN 2 THEN '测试部' ELSE '产品部' END,
10000 + (i % 20) * 1000,
DATE_ADD('2018-01-01', INTERVAL i DAY),
CASE i % 5 WHEN 0 THEN '长春' WHEN 1 THEN '北京' WHEN 2 THEN '上海' WHEN 3 THEN '深圳' ELSE '广州' END);
SET i = i + 1;
END WHILE;
END$$
DELIMITER ;
-- 执行插入(需要几十秒)
CALL insert_test_data();
SELECT COUNT(*) FROM employees; -- 应该约 50 万行
-- ===== 看没索引的查询有多慢 =====
SELECT * FROM employees WHERE name = '员工300000';
-- 记录执行时间
-- ===== 看执行计划(EXPLAIN) =====
EXPLAIN SELECT * FROM employees WHERE name = '员工300000';
-- 关注三个字段:
-- type: ALL (全表扫描,最慢)
-- rows: 扫描了多少行(约 50 万行)
-- Extra: Using where
-- ===== 创建索引 =====
CREATE INDEX idx_name ON employees(name);
-- ===== 再查一次,感受速度 =====
SELECT * FROM employees WHERE name = '员工300000';
-- 瞬间返回
-- ===== 再看执行计划 =====
EXPLAIN SELECT * FROM employees WHERE name = '员工300000';
-- type: ref 或 const (用了索引,快)
-- rows: 1 (只扫描 1 行)
-- key: idx_name (用到了 idx_name 索引)
练习 8:常见索引类型和场景
-- 1. 单列索引(最常用)
CREATE INDEX idx_department ON employees(department);
-- 2. 联合索引(查询条件经常同时出现多列时用)
CREATE INDEX idx_city_dept ON employees(city, department);
-- 注意顺序:city 在前 department 在后,因为 WHERE city = '长春' AND department = '运维部'
-- 查询时先 city 后 department 才能用到索引
-- 3. 唯一索引(这个列的值必须唯一,如身份证号)
CREATE UNIQUE INDEX idx_name_unique ON employees(name);
-- 如果 name 有重复会报错(我们造的数据有重复,先别建)
-- ===== 查看表上的索引 =====
SHOW INDEX FROM employees;
-- ===== 删除索引 =====
DROP INDEX idx_department ON employees;
自检题:
-
EXPLAIN输出中type=ALL代表什么? -
联合索引
(city, department)能加速WHERE department = '运维部'吗?(不能,必须从第一个列开始) -
索引建得越多越好吗?(不是,增删改会变慢,索引本身占空间)
第四天:慢查询分析——运维日常
练习 9:开启慢查询日志
# 配置文件里开启(需要 root 权限)
sudo vim /etc/my.cnf.d/mysql-server.cnf
# 在 [mysqld] 段添加:
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 0.5 # 超过 0.5 秒就记录
log_queries_not_using_indexes = 1 # 没用索引的也记录
# 重启 MySQL
sudo systemctl restart mysqld
# 确认慢查询日志已开启
mysql -u root -p -e "SHOW VARIABLES LIKE 'slow_query%';"
mysql -u root -p -e "SHOW VARIABLES LIKE 'long_query_time';"
练习 10:制造慢查询并分析
-- 先故意删掉索引
DROP INDEX idx_name ON employees;
-- 执行慢查询
SELECT * FROM employees WHERE name = '员工400000';
-- 查看慢查询日志
sudo tail -10 /var/log/mysql/slow.log
# 能看到刚才那条慢查询:执行时间、扫描行数、时间戳
练习 11:mysqldumpslow 分析慢日志
# 看最慢的 5 条
sudo mysqldumpslow -t 5 /var/log/mysql/slow.log
# 看访问次数最多的 5 条
sudo mysqldumpslow -s c -t 5 /var/log/mysql/slow.log
# 看总时间最多的 5 条
sudo mysqldumpslow -s t -t 5 /var/log/mysql/slow.log
第五天:备份与恢复——运维保命技能
练习 12:逻辑备份(mysqldump)
# ===== 备份单个数据库 =====
mysqldump -u root -p practice > /tmp/practice_backup.sql
# 输入密码后,所有建表+插入数据的 SQL 都存到了这个文件
# 看备份文件前 50 行
head -50 /tmp/practice_backup.sql
# ===== 备份所有数据库 =====
mysqldump -u root -p --all-databases > /tmp/all_databases.sql
# ===== 只备份表结构,不要数据 =====
mysqldump -u root -p --no-data practice > /tmp/practice_schema.sql
# ===== 只备份数据,不要表结构 =====
mysqldump -u root -p --no-create-info practice > /tmp/practice_data.sql
# ===== 压缩备份(省空间) =====
mysqldump -u root -p practice | gzip > /tmp/practice_backup.sql.gz
练习 13:恢复数据
-- 先模拟误操作
USE practice;
DROP TABLE employees;
-- 表没了
# 恢复
mysql -u root -p practice < /tmp/practice_backup.sql
-- 验证
USE practice;
SELECT COUNT(*) FROM employees;
-- 数据回来了
练习 14:编写备份脚本并加入定时任务
[xtc@localhost ~]$ cd ~/scripts
[xtc@localhost scripts]$ vim mysql-backup.sh
#!/bin/bash
#============================================
# 脚本名称: mysql-backup.sh
# 功能描述: 每日 MySQL 逻辑备份
# 版 本: 1.0
# 日 期: 2026-05-18
#============================================
BACKUP_DIR="/backup/mysql"
DATE=$(date +%Y%m%d)
DB_NAME="practice"
MYSQL_USER="root"
# 创建备份目录
mkdir -p "$BACKUP_DIR"
# 备份
mysqldump -u"$MYSQL_USER" -p"你的密码" "$DB_NAME" | gzip > "$BACKUP_DIR/${DB_NAME}_${DATE}.sql.gz"
# 检查是否成功
if [ $? -eq 0 ]; then
echo "$(date) 备份成功: $BACKUP_DIR/${DB_NAME}_${DATE}.sql.gz"
else
echo "$(date) 备份失败" >&2
fi
# 清理 7 天前的旧备份
find "$BACKUP_DIR" -name "*.sql.gz" -mtime +7 -delete
chmod +x mysql-backup.sh
crontab -e
# 每天凌晨 2:00 备份
0 2 * * * /home/xtc/scripts/mysql-backup.sh
第六天:用户权限管理(生产安全核心)
练习 15:创建用户和授权
-- 创建只读用户(给看报表的人用)
CREATE USER 'readonly'@'localhost' IDENTIFIED BY 'ReadOnly123!';
GRANT SELECT ON practice.* TO 'readonly'@'localhost';
-- 创建运维用户(能改表结构、增删改查,但不能管权限)
CREATE USER 'ops'@'%' IDENTIFIED BY 'Ops123456!';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, INDEX ON practice.* TO 'ops'@'%';
-- '%' 允许从任何主机连接
-- 创建备份专用用户(最小权限原则)
CREATE USER 'backup'@'localhost' IDENTIFIED BY 'Backup123!';
GRANT SELECT, LOCK TABLES ON practice.* TO 'backup'@'localhost';
-- 查看用户权限
SHOW GRANTS FOR 'readonly'@'localhost';
SHOW GRANTS FOR 'ops'@'%';
-- 刷新权限(改了权限后执行)
FLUSH PRIVILEGES;
练习 16:验证权限
# 测试只读用户
mysql -u readonly -p'ReadOnly123!' practice
SELECT * FROM employees LIMIT 5; -- 可以
INSERT INTO employees (name) VALUES ('测试'); -- 报错 INSERT denied
# 测试备份用户
mysql -u backup -p'Backup123!' practice
SELECT COUNT(*) FROM employees; -- 可以
DELETE FROM employees LIMIT 1; -- 报错 DELETE denied
第七天:综合验收
验收清单
1. 能写出多表联查统计报表
-- 不查笔记写出:
-- 每个部门的人数、平均薪资、负责项目数
SELECT
e.department,
COUNT(DISTINCT e.id) AS 人数,
AVG(e.salary) AS 平均薪资,
COUNT(p.id) AS 项目数
FROM employees e
LEFT JOIN projects p ON e.id = p.leader_id
GROUP BY e.department;
2. 会看执行计划判断索引是否生效
EXPLAIN SELECT * FROM employees WHERE name = '张三';
-- 能说出 type、rows、key 三个字段的含义
3. 会做备份和恢复
mysqldump -u root -p practice | gzip > /tmp/test.sql.gz
# 删表 → 恢复 → 验证数据回来了
4. 备份脚本加入定时任务并验证
mysqldump -u root -p practice | gzip > /tmp/test.sql.gz
# 删表 → 恢复 → 验证数据回来了
第六周能力自检
-
SELECT / WHERE / GROUP BY / HAVING / JOIN能闭眼写出基本结构。 -
EXPLAIN看得懂,type=ALL知道是全表扫描需要优化。 -
慢查询日志会开、会看、会用
mysqldumpslow分析。 -
能用
mysqldump备份单库、恢复单库。 -
会建用户、授权、验证权限。
六周总回顾
|
周 |
主题 |
核心能力 |
里程碑产出 |
|
第一周 |
命令行生存 |
文件操作、grep、find、systemctl |
命令行不再怕 |
|
第二周 |
权限与存储 |
chmod 数字、SGID、磁盘挂载 |
权限不出错 |
|
第三周 |
网络排错 |
排错五步法、ss、firewall、tcpdump |
故障能定界 |
|
第四周 |
Shell 脚本 |
if、awk、for、crontab |
能写自动化脚本 |
|
第五周 |
综合实战 |
生产级巡检脚本、Git、GitHub |
代码推上 GitHub |
|
第六周 |
MySQL 深度 |
SQL 查询、索引、慢查询、备份 |
数据库能独立管 |
六周前你是一个刚接触 Linux 命令行的新手。六周后你已经能独立写出生产级巡检脚本、排查常见网络故障、用 Git 管理代码、对 MySQL 做基本运维。你已经有初级运维工程师的完整能力框架了。 后面进入云平台(第七周开始),这套排错思维和自动化能力会直接复用。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐
所有评论(0)