mysql相关知识点学习整理
- [一、MySQL 基础概念](#一、MySQL 基础概念)
-
- [1.1 MySQL 简介](#1.1 MySQL 简介)
- [1.2 安装与配置](#1.2 安装与配置)
- 二、数据库基本操作
-
- [2.1 连接数据库](#2.1 连接数据库)
- [2.2 数据类型](#2.2 数据类型)
- 三、数据表操作
-
- [3.1 创建表](#3.1 创建表)
- [3.2 修改表结构](#3.2 修改表结构)
- [3.3 删除表](#3.3 删除表)
- 四、数据操作语言(DML)
-
- [4.1 插入数据(INSERT)](#4.1 插入数据(INSERT))
- [4.2 查询数据(SELECT)](#4.2 查询数据(SELECT))
- [4.3 更新数据(UPDATE)](#4.3 更新数据(UPDATE))
- [4.4 删除数据(DELETE)](#4.4 删除数据(DELETE))
- 五、高级查询技巧
-
- [5.1 多表连接](#5.1 多表连接)
- [5.2 子查询](#5.2 子查询)
- [5.3 联合查询](#5.3 联合查询)
- 六、索引优化
-
- [6.1 索引类型](#6.1 索引类型)
- [6.2 执行计划分析](#6.2 执行计划分析)
- 七、事务处理
-
- [7.1 事务基本操作](#7.1 事务基本操作)
- [7.2 事务隔离级别](#7.2 事务隔离级别)
- 八、存储过程和函数
-
- [8.1 存储过程](#8.1 存储过程)
- [8.2 函数](#8.2 函数)
- 九、触发器
- 十、视图
- 十一、用户和权限管理
-
- [11.1 用户管理](#11.1 用户管理)
- [11.2 权限管理](#11.2 权限管理)
- 十二、备份与恢复
-
- [12.1 备份数据库](#12.1 备份数据库)
- [12.2 恢复数据库](#12.2 恢复数据库)
- 十三、性能优化
-
- [13.1 查询优化](#13.1 查询优化)
- [13.2 配置优化](#13.2 配置优化)
- 十四、实用技巧
-
- [14.1 日期时间处理](#14.1 日期时间处理)
- [14.2 字符串处理](#14.2 字符串处理)
- 十五、最佳实践
- [十六、MySQL 8.0 新特性](#十六、MySQL 8.0 新特性)
-
- [16.1 窗口函数](#16.1 窗口函数)
- [16.2 通用表表达式(CTE)](#16.2 通用表表达式(CTE))
- [16.3 JSON 增强](#16.3 JSON 增强)
- 十七、分区表
-
- [17.1 分区类型](#17.1 分区类型)
- [17.2 分区管理](#17.2 分区管理)
- 十八、性能优化高级
-
- [18.1 查询优化器提示](#18.1 查询优化器提示)
- [18.2 执行计划控制](#18.2 执行计划控制)
- [18.3 高级索引策略](#18.3 高级索引策略)
- 十九、高级复制与集群
-
- [19.1 组复制(MySQL Group Replication)](#19.1 组复制(MySQL Group Replication))
- [19.2 InnoDB Cluster](#19.2 InnoDB Cluster)
- 二十、安全增强
-
- [20.1 密码管理](#20.1 密码管理)
- [20.2 角色管理](#20.2 角色管理)
- [20.3 审计日志](#20.3 审计日志)
- 二十一、监控与诊断
-
- [21.1 Performance Schema 深入](#21.1 Performance Schema 深入)
- [21.2 Sys Schema 使用](#21.2 Sys Schema 使用)
- 二十二、备份恢复高级
-
- [22.1 物理备份(Percona XtraBackup)](#22.1 物理备份(Percona XtraBackup))
- [22.2 逻辑备份增强](#22.2 逻辑备份增强)
- 二十三、实用工具与脚本
-
- [23.1 MySQL Shell 使用](#23.1 MySQL Shell 使用)
- [23.2 自动化监控脚本](#23.2 自动化监控脚本)
- [23.3 数据库变更管理脚本](#23.3 数据库变更管理脚本)
- 二十四、故障排查与恢复
-
- [24.1 常见问题排查](#24.1 常见问题排查)
- [24.2 数据恢复技巧](#24.2 数据恢复技巧)
- 学习资源推荐

一、MySQL 基础概念
1.1 MySQL 简介
MySQL 是一个开源的关系型数据库管理系统(RDBMS),使用 SQL(结构化查询语言)进行数据库管理。
1.2 安装与配置
bash
# Ubuntu/Debian
sudo apt-get update
sudo apt-get install mysql-server
# CentOS/RHEL
sudo yum install mysql-server
# macOS
brew install mysql
# Windows
# 从 MySQL 官网下载安装包
启动 MySQL 服务:
bash
# Linux
sudo systemctl start mysql
sudo systemctl enable mysql
# macOS
brew services start mysql
二、数据库基本操作
2.1 连接数据库
sql
-- 连接 MySQL
mysql -u root -p
-- 查看所有数据库
SHOW DATABASES;
-- 创建数据库
CREATE DATABASE school;
CREATE DATABASE IF NOT EXISTS school;
-- 使用数据库
USE school;
-- 删除数据库
DROP DATABASE IF EXISTS test_db;
2.2 数据类型
数值类型
- INT:整数(4字节)
- BIGINT:大整数(8字节)
- DECIMAL(M,D):精确小数,M总位数,D小数位数
- FLOAT:单精度浮点数
- DOUBLE:双精度浮点数
字符串类型
- CHAR(N):定长字符串
- VARCHAR(N):变长字符串
- TEXT:长文本数据
- BLOB:二进制大对象
日期时间类型
- DATE:YYYY-MM-DD
- TIME:HH:MM:SS
- DATETIME:YYYY-MM-DD HH:MM:SS
- TIMESTAMP:时间戳
- YEAR:年份
三、数据表操作
3.1 创建表
sql
-- 创建学生表
CREATE TABLE students (
id INT PRIMARY KEY AUTO_INCREMENT,
student_id VARCHAR(20) UNIQUE NOT NULL,
name VARCHAR(50) NOT NULL,
gender ENUM('男', '女') DEFAULT '男',
age TINYINT UNSIGNED,
email VARCHAR(100),
phone VARCHAR(20),
enrollment_date DATE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_name (name),
INDEX idx_enrollment_date (enrollment_date)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 创建课程表
CREATE TABLE courses (
course_id INT PRIMARY KEY AUTO_INCREMENT,
course_code VARCHAR(20) UNIQUE NOT NULL,
course_name VARCHAR(100) NOT NULL,
credit DECIMAL(3,1) DEFAULT 2.0,
teacher VARCHAR(50),
class_hours SMALLINT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- 创建成绩表(连接表)
CREATE TABLE scores (
id INT PRIMARY KEY AUTO_INCREMENT,
student_id INT NOT NULL,
course_id INT NOT NULL,
score DECIMAL(5,2) CHECK (score BETWEEN 0 AND 100),
exam_date DATE,
semester VARCHAR(20),
FOREIGN KEY (student_id) REFERENCES students(id) ON DELETE CASCADE,
FOREIGN KEY (course_id) REFERENCES courses(course_id) ON DELETE CASCADE,
UNIQUE KEY uk_student_course (student_id, course_id, semester)
);
3.2 修改表结构
sql
-- 添加列
ALTER TABLE students
ADD COLUMN address VARCHAR(200) AFTER phone;
-- 修改列
ALTER TABLE students
MODIFY COLUMN email VARCHAR(150);
-- 重命名列
ALTER TABLE students
CHANGE COLUMN phone mobile_phone VARCHAR(20);
-- 删除列
ALTER TABLE students
DROP COLUMN address;
-- 添加索引
ALTER TABLE students
ADD INDEX idx_email (email);
-- 删除索引
ALTER TABLE students
DROP INDEX idx_email;
-- 重命名表
ALTER TABLE students
RENAME TO student_info;
3.3 删除表
sql
-- 删除表
DROP TABLE IF EXISTS temp_table;
-- 清空表数据
TRUNCATE TABLE temp_table;
四、数据操作语言(DML)
4.1 插入数据(INSERT)
sql
-- 插入单条数据
INSERT INTO students (student_id, name, gender, age, email, enrollment_date)
VALUES ('S2023001', '张三', '男', 20, 'zhangsan@example.com', '2023-09-01');
-- 插入多条数据
INSERT INTO students (student_id, name, gender, age, enrollment_date) VALUES
('S2023002', '李四', '女', 19, '2023-09-01'),
('S2023003', '王五', '男', 21, '2023-09-01'),
('S2023004', '赵六', '女', 20, '2023-09-01');
-- 插入查询结果
INSERT INTO student_archive (student_id, name, enrollment_date)
SELECT student_id, name, enrollment_date
FROM students
WHERE enrollment_date < '2020-09-01';
-- 使用 INSERT IGNORE(忽略重复键错误)
INSERT IGNORE INTO students (student_id, name)
VALUES ('S2023001', '张三');
-- 使用 REPLACE(替换重复记录)
REPLACE INTO students (student_id, name)
VALUES ('S2023001', '张三新');
4.2 查询数据(SELECT)
基础查询
sql
-- 查询所有列
SELECT * FROM students;
-- 查询特定列
SELECT id, name, age FROM students;
-- 使用别名
SELECT
name AS 姓名,
age AS 年龄,
email AS 电子邮箱
FROM students;
-- 去重查询
SELECT DISTINCT gender FROM students;
-- 条件查询
SELECT * FROM students WHERE age > 18;
SELECT * FROM students WHERE gender = '女' AND age < 20;
SELECT * FROM students WHERE age BETWEEN 18 AND 22;
SELECT * FROM students WHERE name LIKE '张%';
SELECT * FROM students WHERE email IS NOT NULL;
SELECT * FROM students WHERE age IN (18, 20, 22);
排序和限制
sql
-- 排序查询
SELECT * FROM students ORDER BY age DESC;
SELECT * FROM students ORDER BY gender ASC, age DESC;
-- 限制结果集
SELECT * FROM students LIMIT 10;
SELECT * FROM students LIMIT 5, 10; -- 跳过5条,取10条
-- 分页查询
SELECT * FROM students
ORDER BY id
LIMIT 10 OFFSET 20; -- 第3页,每页10条
聚合函数
sql
-- 常用聚合函数
SELECT
COUNT(*) AS 总人数,
COUNT(DISTINCT gender) AS 性别种类,
AVG(age) AS 平均年龄,
MAX(age) AS 最大年龄,
MIN(age) AS 最小年龄,
SUM(age) AS 年龄总和
FROM students;
-- 分组统计
SELECT
gender,
COUNT(*) AS 人数,
AVG(age) AS 平均年龄
FROM students
GROUP BY gender;
-- HAVING 子句
SELECT
gender,
COUNT(*) AS 人数
FROM students
GROUP BY gender
HAVING COUNT(*) > 5;
4.3 更新数据(UPDATE)
sql
-- 更新所有记录
UPDATE students SET updated_at = NOW();
-- 条件更新
UPDATE students
SET age = age + 1, email = 'updated@example.com'
WHERE id = 1;
-- 批量更新
UPDATE students
SET status = '毕业'
WHERE enrollment_date < '2019-09-01';
-- 使用子查询更新
UPDATE students s
JOIN (
SELECT student_id, AVG(score) as avg_score
FROM scores
GROUP BY student_id
) t ON s.student_id = t.student_id
SET s.average_score = t.avg_score
WHERE t.avg_score > 90;
4.4 删除数据(DELETE)
sql
-- 删除所有数据(危险!)
DELETE FROM temp_table;
-- 条件删除
DELETE FROM students WHERE id = 10;
-- 批量删除
DELETE FROM students
WHERE enrollment_date < '2020-09-01';
-- 使用子查询删除
DELETE FROM students
WHERE id IN (
SELECT student_id
FROM scores
WHERE score < 60
);
五、高级查询技巧
5.1 多表连接
sql
-- 内连接
SELECT
s.name,
c.course_name,
sc.score
FROM students s
INNER JOIN scores sc ON s.id = sc.student_id
INNER JOIN courses c ON sc.course_id = c.course_id;
-- 左连接
SELECT
s.name,
c.course_name,
sc.score
FROM students s
LEFT JOIN scores sc ON s.id = sc.student_id
LEFT JOIN courses c ON sc.course_id = c.course_id;
-- 右连接
SELECT
s.name,
c.course_name,
sc.score
FROM scores sc
RIGHT JOIN students s ON sc.student_id = s.id;
-- 全外连接(MySQL 不支持,用UNION模拟)
SELECT s.name, sc.score
FROM students s
LEFT JOIN scores sc ON s.id = sc.student_id
UNION
SELECT s.name, sc.score
FROM students s
RIGHT JOIN scores sc ON s.id = sc.student_id;
-- 自连接
SELECT
e1.name AS 员工,
e2.name AS 经理
FROM employees e1
LEFT JOIN employees e2 ON e1.manager_id = e2.id;
5.2 子查询
sql
-- 标量子查询
SELECT
name,
(SELECT AVG(score) FROM scores WHERE student_id = s.id) AS 平均分
FROM students s;
-- 列子查询
SELECT * FROM students
WHERE id IN (SELECT student_id FROM scores WHERE score > 90);
-- 行子查询
SELECT * FROM students
WHERE (age, gender) = (SELECT MAX(age), '男' FROM students);
-- 表子查询
SELECT
s.name,
t.course_count
FROM students s
JOIN (
SELECT student_id, COUNT(*) as course_count
FROM scores
GROUP BY student_id
) t ON s.id = t.student_id;
-- EXISTS 子查询
SELECT * FROM students s
WHERE EXISTS (
SELECT 1 FROM scores sc
WHERE sc.student_id = s.id AND sc.score > 90
);
5.3 联合查询
sql
-- UNION(去重)
SELECT student_id, name FROM current_students
UNION
SELECT student_id, name FROM graduated_students;
-- UNION ALL(不去重)
SELECT student_id, name FROM current_students
UNION ALL
SELECT student_id, name FROM graduated_students;
六、索引优化
6.1 索引类型
sql
-- 创建普通索引
CREATE INDEX idx_student_name ON students(name);
-- 创建唯一索引
CREATE UNIQUE INDEX idx_unique_email ON students(email);
-- 创建全文索引(MyISAM/InnoDB)
CREATE FULLTEXT INDEX idx_ft_content ON articles(content);
-- 创建复合索引
CREATE INDEX idx_name_gender ON students(name, gender);
-- 查看索引
SHOW INDEX FROM students;
-- 删除索引
DROP INDEX idx_student_name ON students;
6.2 执行计划分析
sql
-- EXPLAIN 分析查询
EXPLAIN SELECT * FROM students WHERE name = '张三';
-- 详细执行计划
EXPLAIN FORMAT=JSON
SELECT s.name, AVG(sc.score)
FROM students s
JOIN scores sc ON s.id = sc.student_id
GROUP BY s.id;
七、事务处理
7.1 事务基本操作
sql
-- 开启事务
START TRANSACTION;
-- 或
BEGIN;
-- 执行操作
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
-- 提交事务
COMMIT;
-- 回滚事务
ROLLBACK;
-- 设置保存点
START TRANSACTION;
INSERT INTO orders (user_id, amount) VALUES (1, 100);
SAVEPOINT sp1;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
-- 如果需要回滚到保存点
ROLLBACK TO SAVEPOINT sp1;
COMMIT;
7.2 事务隔离级别
sql
-- 查看当前隔离级别
SELECT @@transaction_isolation;
-- 设置隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
-- 或
SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;
-- 可用的隔离级别:
-- READ UNCOMMITTED 读未提交
-- READ COMMITTED 读已提交
-- REPEATABLE READ 可重复读(MySQL默认)
-- SERIALIZABLE 串行化
八、存储过程和函数
8.1 存储过程
sql
-- 创建存储过程
DELIMITER //
CREATE PROCEDURE GetStudentInfo(IN studentId INT)
BEGIN
SELECT
s.name,
s.age,
s.gender,
c.course_name,
sc.score
FROM students s
LEFT JOIN scores sc ON s.id = sc.student_id
LEFT JOIN courses c ON sc.course_id = c.course_id
WHERE s.id = studentId;
END //
DELIMITER ;
-- 调用存储过程
CALL GetStudentInfo(1);
-- 带输出参数的存储过程
DELIMITER //
CREATE PROCEDURE GetStudentCountByGender(
IN genderType ENUM('男','女'),
OUT totalCount INT
)
BEGIN
SELECT COUNT(*) INTO totalCount
FROM students
WHERE gender = genderType;
END //
DELIMITER ;
-- 调用
CALL GetStudentCountByGender('男', @count);
SELECT @count;
-- 删除存储过程
DROP PROCEDURE IF EXISTS GetStudentInfo;
8.2 函数
sql
-- 创建函数
DELIMITER //
CREATE FUNCTION CalculateGrade(score DECIMAL(5,2))
RETURNS VARCHAR(10)
DETERMINISTIC
BEGIN
DECLARE grade VARCHAR(10);
IF score >= 90 THEN
SET grade = 'A';
ELSEIF score >= 80 THEN
SET grade = 'B';
ELSEIF score >= 70 THEN
SET grade = 'C';
ELSEIF score >= 60 THEN
SET grade = 'D';
ELSE
SET grade = 'F';
END IF;
RETURN grade;
END //
DELIMITER ;
-- 使用函数
SELECT
name,
score,
CalculateGrade(score) AS grade
FROM scores;
-- 删除函数
DROP FUNCTION IF EXISTS CalculateGrade;
九、触发器
sql
-- 创建触发器
DELIMITER //
CREATE TRIGGER before_student_insert
BEFORE INSERT ON students
FOR EACH ROW
BEGIN
IF NEW.age < 0 THEN
SET NEW.age = 0;
ELSEIF NEW.age > 100 THEN
SET NEW.age = 100;
END IF;
SET NEW.created_at = NOW();
END //
DELIMITER ;
-- 更新触发器
DELIMITER //
CREATE TRIGGER update_student_timestamp
BEFORE UPDATE ON students
FOR EACH ROW
BEGIN
SET NEW.updated_at = NOW();
END //
DELIMITER ;
-- 删除前触发器
DELIMITER //
CREATE TRIGGER archive_student_before_delete
BEFORE DELETE ON students
FOR EACH ROW
BEGIN
INSERT INTO students_archive
(student_id, name, gender, age, deleted_at)
VALUES
(OLD.student_id, OLD.name, OLD.gender, OLD.age, NOW());
END //
DELIMITER ;
-- 查看触发器
SHOW TRIGGERS;
-- 删除触发器
DROP TRIGGER IF EXISTS before_student_insert;
十、视图
sql
-- 创建视图
CREATE VIEW vw_student_scores AS
SELECT
s.id,
s.name,
s.gender,
c.course_name,
sc.score,
sc.exam_date
FROM students s
JOIN scores sc ON s.id = sc.student_id
JOIN courses c ON sc.course_id = c.course_id
WHERE sc.score IS NOT NULL;
-- 使用视图
SELECT * FROM vw_student_scores WHERE score > 90;
-- 更新视图
CREATE OR REPLACE VIEW vw_student_info AS
SELECT
id,
name,
age,
gender,
enrollment_date
FROM students;
-- 可更新视图(满足条件时可更新)
CREATE VIEW vw_simple_students AS
SELECT id, name, age FROM students;
-- 通过视图更新数据
UPDATE vw_simple_students SET age = 21 WHERE id = 1;
-- 删除视图
DROP VIEW IF EXISTS vw_student_scores;
十一、用户和权限管理
11.1 用户管理
sql
-- 创建用户
CREATE USER 'newuser'@'localhost' IDENTIFIED BY 'password';
CREATE USER 'remoteuser'@'%' IDENTIFIED BY 'password';
-- 修改密码
ALTER USER 'username'@'localhost' IDENTIFIED BY 'newpassword';
-- 重命名用户
RENAME USER 'olduser'@'localhost' TO 'newuser'@'localhost';
-- 删除用户
DROP USER 'username'@'localhost';
-- 查看用户
SELECT user, host FROM mysql.user;
11.2 权限管理
sql
-- 授予权限
GRANT SELECT, INSERT ON school.* TO 'user1'@'localhost';
GRANT ALL PRIVILEGES ON school.students TO 'user2'@'localhost';
GRANT CREATE USER ON *.* TO 'admin'@'localhost' WITH GRANT OPTION;
-- 查看权限
SHOW GRANTS FOR 'user1'@'localhost';
-- 撤销权限
REVOKE INSERT ON school.* FROM 'user1'@'localhost';
REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'user2'@'localhost';
-- 刷新权限
FLUSH PRIVILEGES;
十二、备份与恢复
12.1 备份数据库
bash
# 使用 mysqldump 备份
mysqldump -u root -p school > school_backup.sql
# 备份所有数据库
mysqldump -u root -p --all-databases > all_backup.sql
# 备份特定表
mysqldump -u root -p school students courses > tables_backup.sql
# 压缩备份
mysqldump -u root -p school | gzip > school_backup.sql.gz
# 定时备份(crontab)
# 0 2 * * * mysqldump -u root -p密码 school > /backup/school_$(date +\%Y\%m\%d).sql
12.2 恢复数据库
bash
# 恢复数据库
mysql -u root -p school < school_backup.sql
# 恢复所有数据库
mysql -u root -p < all_backup.sql
# 从压缩文件恢复
gunzip < school_backup.sql.gz | mysql -u root -p school
十三、性能优化
13.1 查询优化
sql
-- 使用 EXPLAIN 分析查询
EXPLAIN SELECT * FROM students WHERE name LIKE '张%';
-- 避免 SELECT *
SELECT id, name FROM students; -- 好
SELECT * FROM students; -- 不好
-- 使用 LIMIT 限制结果
SELECT * FROM students LIMIT 100;
-- 合理使用索引
-- 创建覆盖索引
CREATE INDEX idx_covering ON students(id, name, age);
-- 避免在索引列上使用函数
SELECT * FROM students WHERE DATE(created_at) = '2023-01-01'; -- 不好
SELECT * FROM students WHERE created_at >= '2023-01-01' AND created_at < '2023-01-02'; -- 好
13.2 配置优化
sql
-- 查看配置
SHOW VARIABLES LIKE '%buffer%';
SHOW VARIABLES LIKE '%cache%';
-- 临时修改配置(重启后失效)
SET GLOBAL innodb_buffer_pool_size = 1073741824; -- 1GB
-- 在 my.cnf/my.ini 中永久修改
/*
[mysqld]
innodb_buffer_pool_size = 1G
query_cache_size = 128M
max_connections = 200
*/
十四、实用技巧
14.1 日期时间处理
sql
-- 当前日期时间
SELECT NOW(), CURDATE(), CURTIME();
-- 日期格式化
SELECT DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s');
SELECT DATE_FORMAT(enrollment_date, '%Y年%m月%d日') FROM students;
-- 日期计算
SELECT
NOW(),
DATE_ADD(NOW(), INTERVAL 1 DAY),
DATE_SUB(NOW(), INTERVAL 1 MONTH),
DATEDIFF(NOW(), '2023-01-01'),
YEAR(NOW()),
MONTH(NOW()),
DAY(NOW());
-- 提取时间部分
SELECT
DATE(NOW()) as 日期,
TIME(NOW()) as 时间;
14.2 字符串处理
sql
-- 字符串连接
SELECT CONCAT(name, '(', gender, ')') AS info FROM students;
SELECT CONCAT_WS('-', name, age, gender) AS info FROM students;
-- 字符串截取
SELECT
SUBSTRING(name, 1, 1) AS 姓氏,
LEFT(name, 2) AS 前两个字,
RIGHT(name, 2) AS 后两个字
FROM students;
-- 字符串替换
SELECT REPLACE(name, '张', '章') FROM students;
-- 大小写转换
SELECT UPPER(name), LOWER(email) FROM students;
-- 去除空格
SELECT TRIM(' hello '), LTRIM(' hello'), RTRIM('hello ');
十五、最佳实践
1. 命名规范
- 使用小写字母和下划线
- 表名用复数:students, courses
- 主键使用 id 或 表名_id
2. 设计规范
- 每个表都要有主键
- 使用合适的数据类型
- 为频繁查询的字段创建索引
- 使用外键维护数据完整性
3. SQL编写规范
- 使用大写关键字
- 合理使用缩进和换行
- 避免使用SELECT *
- 使用参数化查询防止SQL注入
4. 安全建议
- 为不同用户分配最小必要权限
- 定期备份数据
- 使用强密码
- 开启日志审计
十六、MySQL 8.0 新特性
16.1 窗口函数
sql
-- ROW_NUMBER() 示例
SELECT
name,
score,
exam_date,
ROW_NUMBER() OVER (PARTITION BY student_id ORDER BY score DESC) as rank_in_student
FROM scores;
-- RANK() 和 DENSE_RANK()
SELECT
name,
score,
RANK() OVER (ORDER BY score DESC) as rank_with_gap,
DENSE_RANK() OVER (ORDER BY score DESC) as dense_rank_no_gap,
NTILE(4) OVER (ORDER BY score DESC) as quartile
FROM scores;
-- 累计计算
SELECT
name,
score,
SUM(score) OVER (ORDER BY score ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) as running_total,
AVG(score) OVER (ORDER BY score ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) as moving_avg,
FIRST_VALUE(score) OVER (PARTITION BY student_id ORDER BY exam_date) as first_score,
LAG(score, 1) OVER (ORDER BY exam_date) as previous_score,
LEAD(score, 1) OVER (ORDER BY exam_date) as next_score
FROM scores;
-- WINDOW 子句
SELECT
student_id,
exam_date,
score,
AVG(score) OVER w as avg_score,
MAX(score) OVER w as max_score
FROM scores
WINDOW w AS (PARTITION BY student_id ORDER BY exam_date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW);
16.2 通用表表达式(CTE)
sql
-- 简单CTE
WITH high_score_students AS (
SELECT DISTINCT student_id
FROM scores
WHERE score > 90
)
SELECT s.name, s.gender
FROM students s
JOIN high_score_students h ON s.id = h.student_id;
-- 递归CTE(组织架构查询)
CREATE TABLE employees (
id INT PRIMARY KEY,
name VARCHAR(50),
manager_id INT,
FOREIGN KEY (manager_id) REFERENCES employees(id)
);
-- 递归查询所有下属
WITH RECURSIVE subordinate_tree AS (
-- 初始查询(锚点)
SELECT id, name, manager_id, 0 AS level, CAST(id AS CHAR(200)) AS path
FROM employees
WHERE manager_id IS NULL
UNION ALL
-- 递归查询
SELECT e.id, e.name, e.manager_id, st.level + 1,
CONCAT(st.path, '->', e.id)
FROM employees e
JOIN subordinate_tree st ON e.manager_id = st.id
)
SELECT * FROM subordinate_tree ORDER BY path;
-- 多个CTE
WITH
female_students AS (
SELECT * FROM students WHERE gender = '女'
),
high_achievers AS (
SELECT s.id, AVG(sc.score) as avg_score
FROM students s
JOIN scores sc ON s.id = sc.student_id
GROUP BY s.id
HAVING AVG(sc.score) > 85
)
SELECT
fs.name,
ha.avg_score,
DENSE_RANK() OVER (ORDER BY ha.avg_score DESC) as rank
FROM female_students fs
JOIN high_achievers ha ON fs.id = ha.id;
16.3 JSON 增强
sql
-- JSON_TABLE 函数
SELECT
jt.*
FROM
JSON_TABLE(
'[{"name": "张三", "scores": [85, 92, 78]},
{"name": "李四", "scores": [90, 88, 95]}]',
'$[*]' COLUMNS (
name VARCHAR(50) PATH '$.name',
NESTED PATH '$.scores[*]' COLUMNS (
score INT PATH '$'
)
)
) AS jt;
-- JSON 聚合函数
SELECT
student_id,
JSON_ARRAYAGG(score) as score_array,
JSON_OBJECTAGG(course_id, score) as score_object
FROM scores
GROUP BY student_id;
-- JSON 路径更新
UPDATE students
SET info = JSON_SET(
COALESCE(info, '{}'),
'$.contact.email', 'new@example.com',
'$.hobbies[0]', '篮球'
)
WHERE id = 1;
-- JSON 合并
SELECT
JSON_MERGE_PATCH('{"a": 1, "b": 2}', '{"b": 3, "c": 4}') as patch_result,
JSON_MERGE_PRESERVE('{"a": 1, "b": 2}', '{"b": 3, "c": 4}') as preserve_result;
十七、分区表
17.1 分区类型
sql
-- RANGE 分区
CREATE TABLE sales (
sale_id INT AUTO_INCREMENT,
sale_date DATE NOT NULL,
amount DECIMAL(10,2),
region VARCHAR(50),
PRIMARY KEY (sale_id, sale_date)
)
PARTITION BY RANGE (YEAR(sale_date)) (
PARTITION p2019 VALUES LESS THAN (2020),
PARTITION p2020 VALUES LESS THAN (2021),
PARTITION p2021 VALUES LESS THAN (2022),
PARTITION p2022 VALUES LESS THAN (2023),
PARTITION p2023 VALUES LESS THAN (2024),
PARTITION p_future VALUES LESS THAN MAXVALUE
);
-- LIST 分区
CREATE TABLE employees_by_region (
emp_id INT AUTO_INCREMENT,
name VARCHAR(50),
region VARCHAR(20),
PRIMARY KEY (emp_id, region)
)
PARTITION BY LIST COLUMNS(region) (
PARTITION p_north VALUES IN ('北京', '天津', '河北'),
PARTITION p_east VALUES IN ('上海', '江苏', '浙江'),
PARTITION p_south VALUES IN ('广东', '福建', '海南'),
PARTITION p_west VALUES IN ('四川', '云南', '西藏'),
PARTITION p_other VALUES IN (DEFAULT)
);
-- HASH 分区
CREATE TABLE user_data (
user_id INT AUTO_INCREMENT,
username VARCHAR(50),
created_at DATETIME,
PRIMARY KEY (user_id)
)
PARTITION BY HASH(user_id)
PARTITIONS 8;
-- KEY 分区
CREATE TABLE log_data (
log_id INT AUTO_INCREMENT,
log_type VARCHAR(20),
log_time DATETIME,
content TEXT,
PRIMARY KEY (log_id, log_type)
)
PARTITION BY KEY(log_type)
PARTITIONS 4;
-- 复合分区(子分区)
CREATE TABLE time_series_data (
id INT AUTO_INCREMENT,
metric_date DATE,
metric_value DECIMAL(10,2),
metric_type VARCHAR(20),
PRIMARY KEY (id, metric_date)
)
PARTITION BY RANGE (YEAR(metric_date))
SUBPARTITION BY HASH(MONTH(metric_date))
SUBPARTITIONS 12 (
PARTITION p2020 VALUES LESS THAN (2021),
PARTITION p2021 VALUES LESS THAN (2022),
PARTITION p2022 VALUES LESS THAN (2023)
);
17.2 分区管理
sql
-- 查看分区信息
SELECT
PARTITION_NAME,
PARTITION_ORDINAL_POSITION,
TABLE_ROWS,
DATA_LENGTH
FROM INFORMATION_SCHEMA.PARTITIONS
WHERE TABLE_NAME = 'sales';
-- 增加分区
ALTER TABLE sales REORGANIZE PARTITION p_future INTO (
PARTITION p2024 VALUES LESS THAN (2025),
PARTITION p_future VALUES LESS THAN MAXVALUE
);
-- 合并分区
ALTER TABLE sales REORGANIZE PARTITION p2019, p2020 INTO (
PARTITION p2019_2020 VALUES LESS THAN (2021)
);
-- 删除分区(会删除数据)
ALTER TABLE sales DROP PARTITION p2019;
-- 清空分区
ALTER TABLE sales TRUNCATE PARTITION p2020;
-- 交换分区(与普通表交换)
CREATE TABLE sales_2023_q1 LIKE sales;
ALTER TABLE sales EXCHANGE PARTITION p2023_q1 WITH TABLE sales_2023_q1;
-- 重建分区(优化碎片)
ALTER TABLE sales REBUILD PARTITION p2022;
-- 分析分区
ALTER TABLE sales ANALYZE PARTITION p2023;
-- 检查分区
ALTER TABLE sales CHECK PARTITION ALL;
十八、性能优化高级
18.1 查询优化器提示
sql
-- 索引提示
SELECT * FROM students USE INDEX (idx_name) WHERE name LIKE '张%';
SELECT * FROM students FORCE INDEX (primary) WHERE id = 1;
SELECT * FROM students IGNORE INDEX (idx_name) WHERE name = '张三';
-- JOIN 优化提示
SELECT /*+ JOIN_ORDER(s, sc, c) */
s.name, c.course_name, sc.score
FROM students s
JOIN scores sc ON s.id = sc.student_id
JOIN courses c ON sc.course_id = c.course_id;
SELECT /*+ MERGE(t1, t2) */ * FROM t1 JOIN t2 ON t1.id = t2.id;
SELECT /*+ NO_MERGE(t1) */ * FROM t1 JOIN t2 ON t1.id = t2.id;
-- 子查询优化
SELECT /*+ SEMIJOIN(FIRSTMATCH, LOOSESCAN) */ *
FROM students s
WHERE EXISTS (SELECT 1 FROM scores sc WHERE sc.student_id = s.id);
-- 查询块名称
SELECT /*+ QB_NAME(main) */
name,
(SELECT /*+ QB_NAME(sub) */ AVG(score)
FROM scores WHERE student_id = students.id) as avg_score
FROM students;
-- 资源组提示(MySQL 8.0+)
SELECT /*+ RESOURCE_GROUP(rg1) */ * FROM large_table;
18.2 执行计划控制
sql
-- 使用优化器开关
SET SESSION optimizer_switch = 'index_merge=off,mrr=on';
-- 查看当前设置
SELECT @@optimizer_switch;
-- 设置优化器成本模型
SET SESSION optimizer_cost_model = 'default';
-- 查询执行时间限制(毫秒)
SET SESSION max_execution_time = 1000;
SELECT * FROM large_table; -- 超过1秒会被终止
-- 使用EXPLAIN ANALYZE(MySQL 8.0.18+)
EXPLAIN ANALYZE
SELECT s.name, AVG(sc.score)
FROM students s
JOIN scores sc ON s.id = sc.student_id
GROUP BY s.id;
18.3 高级索引策略
sql
-- 不可见索引
CREATE INDEX idx_invisible ON students(email) INVISIBLE;
-- 切换索引可见性
ALTER TABLE students ALTER INDEX idx_invisible VISIBLE;
ALTER TABLE students ALTER INDEX idx_name INVISIBLE;
-- 查看不可见索引
SELECT
index_name,
is_visible
FROM information_schema.statistics
WHERE table_name = 'students';
-- 降序索引
CREATE INDEX idx_desc ON students(age DESC, name ASC);
-- 函数索引
CREATE INDEX idx_lower_name ON students((LOWER(name)));
-- 空间索引
CREATE TABLE locations (
id INT PRIMARY KEY,
name VARCHAR(100),
position POINT NOT NULL,
SPATIAL INDEX(position)
);
-- 全文索引增强
CREATE TABLE documents (
id INT PRIMARY KEY,
title VARCHAR(200),
content TEXT,
FULLTEXT idx_ft (title, content) WITH PARSER ngram
) ENGINE=InnoDB;
-- 使用全文索引
SELECT * FROM documents
WHERE MATCH(title, content) AGAINST('数据库 教程' IN NATURAL LANGUAGE MODE);
SELECT * FROM documents
WHERE MATCH(title, content) AGAINST('+MySQL -Oracle' IN BOOLEAN MODE);
十九、高级复制与集群
19.1 组复制(MySQL Group Replication)
sql
-- 配置组复制
SET SQL_LOG_BIN=0;
CREATE USER repl_user@'%' IDENTIFIED BY 'password';
GRANT REPLICATION SLAVE ON *.* TO repl_user@'%';
GRANT CONNECTION_ADMIN ON *.* TO repl_user@'%';
FLUSH PRIVILEGES;
SET SQL_LOG_BIN=1;
-- 安装组复制插件
INSTALL PLUGIN group_replication SONAME 'group_replication.so';
-- 配置组复制设置
SET GLOBAL group_replication_group_name = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa";
SET GLOBAL group_replication_start_on_boot = OFF;
SET GLOBAL group_replication_local_address = "node1:33061";
SET GLOBAL group_replication_group_seeds = "node1:33061,node2:33061,node3:33061";
SET GLOBAL group_replication_bootstrap_group = OFF;
-- 启动组复制
START GROUP_REPLICATION;
-- 查看组复制状态
SELECT * FROM performance_schema.replication_group_members;
SELECT * FROM performance_schema.replication_group_member_stats;
-- 故障切换
SET GLOBAL group_replication_set_as_primary = 'node2-uuid';
19.2 InnoDB Cluster
sql
-- 使用MySQL Shell配置集群
-- 连接到实例
\connect root@localhost:3306
-- 创建集群
var cluster = dba.createCluster('myCluster');
-- 添加实例
cluster.addInstance('root@node2:3306');
cluster.addInstance('root@node3:3306');
-- 检查集群状态
cluster.status();
-- 切换主节点
cluster.setPrimaryInstance('node2:3306');
-- 移除实例
cluster.removeInstance('node3:3306', {force: true});
二十、安全增强
20.1 密码管理
sql
-- 密码策略
SET GLOBAL validate_password.policy = STRONG;
SET GLOBAL validate_password.length = 10;
SET GLOBAL validate_password.mixed_case_count = 1;
SET GLOBAL validate_password.number_count = 1;
SET GLOBAL validate_password.special_char_count = 1;
-- 查看密码策略
SHOW VARIABLES LIKE 'validate_password%';
-- 密码过期策略
CREATE USER 'app_user'@'%'
IDENTIFIED BY 'StrongPass123!'
PASSWORD EXPIRE INTERVAL 90 DAY
PASSWORD HISTORY 5
PASSWORD REUSE INTERVAL 365 DAY
PASSWORD REQUIRE CURRENT;
-- 修改用户密码要求
ALTER USER 'app_user'@'%'
PASSWORD EXPIRE NEVER
PASSWORD HISTORY DEFAULT;
-- 双密码支持(MySQL 8.0.14+)
ALTER USER 'app_user'@'%'
IDENTIFIED BY 'new_password'
RETAIN CURRENT PASSWORD;
20.2 角色管理
sql
-- 创建角色
CREATE ROLE 'read_only', 'write_access', 'admin_role';
-- 为角色授权
GRANT SELECT ON school.* TO 'read_only';
GRANT SELECT, INSERT, UPDATE ON school.* TO 'write_access';
GRANT ALL PRIVILEGES ON school.* TO 'admin_role';
-- 创建用户并分配角色
CREATE USER 'report_user'@'localhost' IDENTIFIED BY 'password';
CREATE USER 'app_user'@'localhost' IDENTIFIED BY 'password';
CREATE USER 'admin_user'@'localhost' IDENTIFIED BY 'password';
GRANT 'read_only' TO 'report_user'@'localhost';
GRANT 'write_access' TO 'app_user'@'localhost';
GRANT 'admin_role' TO 'admin_user'@'localhost';
-- 设置默认角色
SET DEFAULT ROLE 'read_only' TO 'report_user'@'localhost';
-- 激活角色
SET ROLE 'read_only';
-- 查看角色权限
SHOW GRANTS FOR 'read_only';
-- 强制角色(MySQL 8.0.19+)
SET PERSIST mandatory_roles = 'read_only';
20.3 审计日志
sql
-- 安装审计插件(企业版)
INSTALL PLUGIN audit_log SONAME 'audit_log.so';
-- 配置审计日志
SET GLOBAL audit_log_format = JSON;
SET GLOBAL audit_log_policy = ALL;
SET GLOBAL audit_log_rotate_on_size = 100000000; -- 100MB
SET GLOBAL audit_log_rotations = 10;
-- 查看审计日志配置
SHOW VARIABLES LIKE 'audit_log%';
-- 查询审计日志(文件形式)
SELECT audit_log_read('audit.log') AS log_data;
-- 使用开源审计插件(如 MariaDB 审计插件)
二十一、监控与诊断
21.1 Performance Schema 深入
sql
-- 启用所有检测点
UPDATE performance_schema.setup_instruments SET ENABLED = 'YES', TIMED = 'YES';
-- 查看等待事件
SELECT
EVENT_NAME,
COUNT_STAR,
SUM_TIMER_WAIT/1000000000 as wait_sec,
AVG_TIMER_WAIT/1000000000 as avg_wait_sec
FROM performance_schema.events_waits_summary_global_by_event_name
WHERE COUNT_STAR > 0
ORDER BY SUM_TIMER_WAIT DESC
LIMIT 10;
-- 查看语句统计
SELECT
DIGEST_TEXT,
COUNT_STAR,
SUM_TIMER_WAIT/1000000000 as total_time_sec,
AVG_TIMER_WAIT/1000000000 as avg_time_sec,
SUM_ROWS_SENT,
SUM_ROWS_EXAMINED
FROM performance_schema.events_statements_summary_by_digest
WHERE DIGEST_TEXT IS NOT NULL
ORDER BY SUM_TIMER_WAIT DESC
LIMIT 10;
-- 查看锁信息
SELECT
OBJECT_TYPE,
OBJECT_SCHEMA,
OBJECT_NAME,
LOCK_TYPE,
LOCK_STATUS,
THREAD_ID
FROM performance_schema.metadata_locks
WHERE OBJECT_SCHEMA = 'school';
-- 查看当前连接详细信息
SELECT
p.ID,
p.USER,
p.HOST,
p.DB,
p.COMMAND,
p.TIME,
p.STATE,
p.INFO,
t.THREAD_ID,
t.PROCESSLIST_ID
FROM information_schema.PROCESSLIST p
JOIN performance_schema.threads t ON p.ID = t.PROCESSLIST_ID;
21.2 Sys Schema 使用
sql
-- 查看主机统计
SELECT * FROM sys.host_summary;
-- 查看用户统计
SELECT * FROM sys.user_summary;
-- 查看 IO 统计
SELECT * FROM sys.io_global_by_file_by_bytes LIMIT 10;
-- 查看内存使用
SELECT * FROM sys.memory_global_total;
-- 查看未使用索引
SELECT * FROM sys.schema_unused_indexes;
-- 查看冗余索引
SELECT * FROM sys.schema_redundant_indexes;
-- 查看等待事件
SELECT * FROM sys.wait_classes_global_by_avg_latency;
-- 查看语句性能
SELECT * FROM sys.statements_with_full_table_scans;
SELECT * FROM sys.statements_with_temp_tables;
SELECT * FROM sys.statements_with_sorting;
SELECT * FROM sys.statements_with_runtimes_in_95th_percentile;
二十二、备份恢复高级
22.1 物理备份(Percona XtraBackup)
bash
# 全量备份
xtrabackup --backup --target-dir=/backup/full --user=root --password=password
# 增量备份
xtrabackup --backup --target-dir=/backup/inc1 --incremental-basedir=/backup/full --user=root --password=password
# 准备备份
xtrabackup --prepare --apply-log-only --target-dir=/backup/full
xtrabackup --prepare --apply-log-only --target-dir=/backup/full --incremental-dir=/backup/inc1
# 恢复备份
systemctl stop mysql
mv /var/lib/mysql /var/lib/mysql.old
xtrabackup --copy-back --target-dir=/backup/full
chown -R mysql:mysql /var/lib/mysql
systemctl start mysql
22.2 逻辑备份增强
bash
# 并行备份
mydumper \
--host=localhost \
--user=root \
--password=password \
--outputdir=/backup \
--threads=4 \
--compress \
--build-empty-files \
--regex='^(school\.)' \
--trx-consistency-only
# 并行恢复
myloader \
--host=localhost \
--user=root \
--password=password \
--directory=/backup \
--threads=4 \
--overwrite-tables
# 选择性备份
mysqldump \
--host=localhost \
--user=root \
--password=password \
--single-transaction \
--routines \
--triggers \
--events \
--compress \
--where="created_at > '2023-01-01'" \
school students > students_backup.sql
二十三、实用工具与脚本
23.1 MySQL Shell 使用
javascript
// 连接到MySQL
\connect root@localhost:3306
// 使用JavaScript模式
var db = session.getSchema('school');
db.getTables(); // 查看所有表
// 执行SQL
session.sql('SELECT * FROM students LIMIT 5').execute();
// 使用Python模式
db = session.get_schema('school')
result = db.get_table('students').select(['id', 'name']).limit(5).execute()
for row in result.fetch_all():
print(row)
// 导入导出数据
util.importTable('/data/students.csv', {
schema: 'school',
table: 'students',
fieldsTerminatedBy: ',',
linesTerminatedBy: '\n',
skipRows: 1
});
util.dumpInstance('/backup', {compression: 'gzip', threads: 4});
util.loadDump('/backup');
23.2 自动化监控脚本
python
#!/usr/bin/env python3
"""
MySQL 自动化监控脚本
"""
import pymysql
import json
from datetime import datetime
class MySQLMonitor:
def __init__(self, host, user, password):
self.connection = pymysql.connect(
host=host,
user=user,
password=password,
database='performance_schema'
)
def check_connections(self):
"""检查连接数"""
with self.connection.cursor() as cursor:
cursor.execute("""
SELECT
VARIABLE_VALUE as current_connections,
@@max_connections as max_connections,
ROUND(VARIABLE_VALUE/@@max_connections*100, 2) as usage_percent
FROM performance_schema.global_status
WHERE VARIABLE_NAME = 'Threads_connected'
""")
return cursor.fetchone()
def check_slow_queries(self):
"""检查慢查询"""
with self.connection.cursor() as cursor:
cursor.execute("""
SELECT
COUNT(*) as slow_query_count,
ROUND(MAX(QUERY_TIME), 2) as max_query_time
FROM mysql.slow_log
WHERE start_time > DATE_SUB(NOW(), INTERVAL 1 HOUR)
""")
return cursor.fetchone()
def check_replication(self):
"""检查复制状态"""
with self.connection.cursor() as cursor:
cursor.execute("SHOW SLAVE STATUS")
columns = [desc[0] for desc in cursor.description]
row = cursor.fetchone()
if row:
return dict(zip(columns, row))
return None
def generate_report(self):
"""生成监控报告"""
report = {
'timestamp': datetime.now().isoformat(),
'connections': self.check_connections(),
'slow_queries': self.check_slow_queries(),
'replication': self.check_replication()
}
return json.dumps(report, indent=2, default=str)
# 使用示例
if __name__ == '__main__':
monitor = MySQLMonitor('localhost', 'root', 'password')
print(monitor.generate_report())
23.3 数据库变更管理脚本
sql
-- 使用事件调度器自动化维护
SET GLOBAL event_scheduler = ON;
-- 创建每日统计事件
DELIMITER //
CREATE EVENT daily_stats_collection
ON SCHEDULE EVERY 1 DAY
STARTS '2024-01-01 02:00:00'
DO
BEGIN
-- 收集每日统计
INSERT INTO daily_statistics (stat_date, active_users, new_users, total_orders)
SELECT
CURDATE() - INTERVAL 1 DAY as stat_date,
COUNT(DISTINCT user_id) as active_users,
SUM(CASE WHEN created_at >= CURDATE() - INTERVAL 1 DAY THEN 1 ELSE 0 END) as new_users,
COUNT(*) as total_orders
FROM orders
WHERE order_date >= CURDATE() - INTERVAL 1 DAY;
-- 清理旧数据
DELETE FROM session_data WHERE last_activity < NOW() - INTERVAL 7 DAY;
-- 更新缓存表
TRUNCATE TABLE user_summary_cache;
INSERT INTO user_summary_cache (user_id, total_orders, total_amount)
SELECT user_id, COUNT(*), SUM(amount)
FROM orders
GROUP BY user_id;
END //
DELIMITER ;
-- 查看事件
SHOW EVENTS;
SELECT * FROM information_schema.EVENTS;
-- 修改事件
ALTER EVENT daily_stats_collection
ON SCHEDULE EVERY 1 DAY
STARTS '2024-01-01 03:00:00'
ENABLE;
-- 删除事件
DROP EVENT IF EXISTS daily_stats_collection;
二十四、故障排查与恢复
24.1 常见问题排查
sql
-- 1. 锁等待问题
-- 查看当前锁
SELECT
r.trx_id waiting_trx_id,
r.trx_mysql_thread_id waiting_thread,
r.trx_query waiting_query,
b.trx_id blocking_trx_id,
b.trx_mysql_thread_id blocking_thread,
b.trx_query blocking_query
FROM information_schema.innodb_lock_waits w
INNER JOIN information_schema.innodb_trx b ON b.trx_id = w.blocking_trx_id
INNER JOIN information_schema.innodb_trx r ON r.trx_id = w.requesting_trx_id;
-- 2. 死锁问题
-- 查看最近死锁
SHOW ENGINE INNODB STATUS\G
-- 查看死锁信息
SELECT * FROM information_schema.INNODB_LOCKS;
SELECT * FROM information_schema.INNODB_LOCK_WAITS;
-- 3. 连接数过多
-- 查看连接来源
SELECT
USER,
HOST,
COUNT(*) as connection_count,
GROUP_CONCAT(ID) as thread_ids
FROM information_schema.PROCESSLIST
WHERE USER != 'system user'
GROUP BY USER, HOST
ORDER BY connection_count DESC;
-- 4. 磁盘空间不足
-- 查看表空间使用
SELECT
table_schema as '数据库',
table_name as '表名',
ROUND((data_length + index_length) / 1024 / 1024, 2) as '大小(MB)',
ROUND(data_length / 1024 / 1024, 2) as '数据大小(MB)',
ROUND(index_length / 1024 / 1024, 2) as '索引大小(MB)'
FROM information_schema.tables
WHERE table_schema NOT IN ('mysql', 'information_schema', 'performance_schema')
ORDER BY (data_length + index_length) DESC
LIMIT 20;
-- 5. 慢查询分析
-- 启用慢查询日志
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 2;
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';
-- 分析慢查询
SELECT
query_time,
lock_time,
rows_sent,
rows_examined,
db,
user_host,
sql_text
FROM mysql.slow_log
WHERE start_time > NOW() - INTERVAL 1 HOUR
ORDER BY query_time DESC
LIMIT 10;
24.2 数据恢复技巧
sql
-- 1. 误删除恢复(使用备份)
-- 从备份恢复单表
mysql -u root -p school < table_backup.sql
-- 2. 使用二进制日志恢复
-- 查看二进制日志
SHOW BINARY LOGS;
SHOW BINLOG EVENTS IN 'mysql-bin.000001';
-- 解析二进制日志
mysqlbinlog --start-datetime="2024-01-01 00:00:00" \
--stop-datetime="2024-01-01 12:00:00" \
mysql-bin.000001 > recovery.sql
-- 执行恢复
mysql -u root -p < recovery.sql
-- 3. 使用UNDO日志(仅限支持的事务)
-- 查看UNDO日志信息
SELECT * FROM information_schema.INNODB_METRICS
WHERE NAME LIKE '%undo%';
-- 4. 表空间恢复
-- 重建表
ALTER TABLE large_table ENGINE=InnoDB;
-- 强制恢复
SET GLOBAL innodb_force_recovery = 1; -- 1-6级别
-- 重启MySQL后执行数据导出
-- 重新初始化数据库
学习资源推荐
官方资源
社区资源