MySQL 从入门到精通完全教程
目录
1. 前言
1.1 什么是MySQL?
MySQL 是一款开源的关系型数据库管理系统(RDBMS),基于SQL(结构化查询语言)实现数据管理,广泛应用于Web开发(如PHP+MySQL、Python+MySQL),特点是轻量、高效、跨平台、免费(社区版)。
1.2 学习目标
- 掌握MySQL的安装、配置和基础连接方式
- 熟练使用SQL语句操作数据库、表、数据
- 理解事务、索引、约束等核心概念
- 能够优化简单的SQL查询,解决常见问题
1.3 环境准备
- 操作系统:Windows/Linux/MacOS
- 工具:MySQL Community Server(数据库服务)、Navicat/DBeaver/MySQL Workbench(可视化工具,可选)
2. MySQL 基础认知
2.1 核心概念
| 概念 | 解释 |
|---|---|
| 数据库(DB) | 存储数据的容器,一个MySQL服务可以包含多个数据库(如test、mysql) |
| 数据表(Table) | 数据库的基本存储单元,由行(记录)和列(字段)组成(如用户表user) |
| 字段(Column) | 表的列,定义数据类型(如idint、namevarchar) |
| 记录(Row) | 表的行,是一条完整的数据(如1, "张三", 20) |
| SQL | 操作数据库的标准语言,分为DQL(查询)、DML(增删改)、DDL(定义)、DCL(权限) |
2.2 MySQL 架构(简化版)
客户端(Navicat/命令行) → MySQL服务端 → 存储引擎(InnoDB/MyISAM) → 磁盘文件 - InnoDB:默认引擎,支持事务、外键、行级锁(推荐生产环境使用)
- MyISAM:轻量,不支持事务,表级锁(仅适用于只读场景)
3. MySQL 安装与配置
3.1 Windows 安装
步骤1:下载安装包
- 官网:https://dev.mysql.com/downloads/mysql/
- 选择「MySQL Community Server」→ 对应Windows版本(msi安装包)
步骤2:安装流程
- 双击安装包,选择「Custom」自定义安装,勾选「MySQL Server」
- 下一步配置类型:选择「Development Computer」(开发环境)
- 设置root密码(务必记住,如
123456) - 配置服务名(默认
MySQL80),设置为「开机自启」 - 完成安装,验证:打开cmd,输入
mysql -u root -p,输入密码后进入MySQL命令行即成功。
3.2 Linux(CentOS7)安装
# 1. 安装依赖 yum install -y wget# 2. 添加MySQL源wget https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm rpm -ivh mysql80-community-release-el7-3.noarch.rpm # 3. 安装MySQL服务 yum install -y mysql-community-server # 4. 启动服务 systemctl start mysqld # 5. 查看初始密码grep'temporary password' /var/log/mysqld.log # 6. 登录并修改密码(初始密码替换为上面查到的) mysql -u root -p ALTER USER'root'@'localhost' IDENTIFIED BY '新密码(需包含大小写+数字+特殊字符)';# 7. 设置开机自启 systemctl enable mysqld 3.3 基础配置(my.cnf)
修改配置文件(Windows:my.ini;Linux:/etc/my.cnf),添加以下常用配置:
[mysqld] # 数据库默认编码 character-set-server=utf8mb4 # 排序规则 collation-server=utf8mb4_general_ci # 默认存储引擎 default-storage-engine=InnoDB # 端口(默认3306,可修改避免冲突) port=3306 # 最大连接数 max_connections=1000 # 慢查询阈值(超过1秒记录) long_query_time=1 [mysql] # 客户端编码 default-character-set=utf8mb4 修改后重启MySQL服务生效。
4. MySQL 核心语法
4.1 数据库操作(DDL)
| 操作 | SQL语句 |
|---|---|
| 创建数据库 | CREATE DATABASE [IF NOT EXISTS] 数据库名 [DEFAULT CHARSET 编码]; |
| 查看所有数据库 | SHOW DATABASES; |
| 使用数据库 | USE 数据库名; |
| 修改数据库编码 | ALTER DATABASE 数据库名 CHARACTER SET utf8mb4; |
| 删除数据库 | DROP DATABASE [IF EXISTS] 数据库名; |
示例:
-- 创建名为test_db的数据库,避免重复创建,编码为utf8mb4CREATEDATABASEIFNOTEXISTS test_db DEFAULTCHARSET utf8mb4;-- 使用该数据库USE test_db;-- 查看数据库列表SHOWDATABASES;-- 删除数据库(谨慎操作!)DROPDATABASEIFEXISTS test_db;4.2 数据表操作(DDL)
4.2.1 创建表
语法:
CREATETABLE[IFNOTEXISTS] 表名 ( 字段1 数据类型 [约束], 字段2 数据类型 [约束],...[PRIMARYKEY(主键字段)])ENGINE=InnoDBDEFAULTCHARSET=utf8mb4;示例:创建用户表user
CREATETABLEIFNOTEXISTS`user`(`id`INTUNSIGNEDNOTNULLAUTO_INCREMENT,-- 自增ID`name`VARCHAR(50)NOTNULLCOMMENT'用户名',-- 非空,最大50字符`age`TINYINTUNSIGNEDDEFAULT0COMMENT'年龄',-- 默认值0`gender`ENUM('男','女','未知')DEFAULT'未知'COMMENT'性别',`create_time`DATETIMEDEFAULTCURRENT_TIMESTAMPCOMMENT'创建时间',PRIMARYKEY(`id`)-- 主键)ENGINE=InnoDBDEFAULTCHARSET=utf8mb4 COMMENT='用户信息表';4.2.2 常用表操作
-- 查看表结构DESC`user`;-- 查看创建表的SQLSHOWCREATETABLE`user`;-- 修改表:添加字段ALTERTABLE`user`ADD`phone`VARCHAR(11)AFTER`name`;-- 修改表:修改字段类型ALTERTABLE`user`MODIFY`phone`VARCHAR(20);-- 修改表:删除字段ALTERTABLE`user`DROP`phone`;-- 重命名表ALTERTABLE`user`RENAMETO`user_info`;-- 删除表(谨慎!)DROPTABLEIFEXISTS`user`;4.3 数据操作(DML)
4.3.1 插入数据(INSERT)
-- 插入单条数据INSERTINTO`user`(`name`,`age`,`gender`)VALUES('张三',20,'男');-- 插入多条数据INSERTINTO`user`(`name`,`age`,`gender`)VALUES('李四',22,'女'),('王五',25,'男');-- 插入所有字段(按表结构顺序)INSERTINTO`user`VALUES(NULL,'赵六',18,'未知',NOW());-- id自增,传NULL即可4.3.2 更新数据(UPDATE)
-- 修改单条数据(务必加WHERE,否则修改全表!)UPDATE`user`SET`age`=21WHERE`id`=1;-- 修改多条数据UPDATE`user`SET`gender`='未知'WHERE`age`<20;4.3.3 删除数据(DELETE)
-- 删除指定数据(务必加WHERE!)DELETEFROM`user`WHERE`id`=3;-- 清空表(保留表结构,自增ID重置)TRUNCATETABLE`user`;4.3.4 查询数据(DQL,核心)
基础语法:
SELECT[DISTINCT] 字段1, 字段2,...FROM 表名 [WHERE 条件][ORDERBY 字段 [ASC/DESC]][LIMIT 偏移量, 条数];示例:
-- 查询所有字段SELECT*FROM`user`;-- 查询指定字段,去重SELECTDISTINCT`gender`FROM`user`;-- 条件查询:年龄大于20的男性SELECT`name`,`age`FROM`user`WHERE`age`>20AND`gender`='男';-- 排序:按年龄降序SELECT*FROM`user`ORDERBY`age`DESC;-- 分页:第1页,每页2条(偏移量=0,条数=2)SELECT*FROM`user`LIMIT0,2;5. 高级查询技巧
5.1 条件查询进阶
| 运算符/关键字 | 作用 | 示例 |
|---|---|---|
| IN | 匹配多个值 | WHERE age IN (20,22,25) |
| LIKE | 模糊匹配(%任意字符,_单个字符) | WHERE name LIKE '张%' |
| IS NULL | 判断字段为空 | WHERE phone IS NULL |
| BETWEEN … AND … | 区间匹配 | WHERE age BETWEEN 18 AND 30 |
5.2 分组查询(GROUP BY + HAVING)
用于统计数据(结合聚合函数):
-- 按性别分组,统计每组人数和平均年龄SELECT`gender`,COUNT(*)AS`total`,AVG(`age`)AS`avg_age`FROM`user`GROUPBY`gender`HAVING`avg_age`>20;-- 过滤分组后的结果(WHERE过滤原始数据)5.3 连接查询(多表关联)
假设有两张表:user(用户表)、order(订单表,含user_id关联user.id)。
| 连接类型 | 作用 | 语法 |
|---|---|---|
| INNER JOIN | 只查两表匹配的数据 | FROM user INNER JOIN order ON user.id = order.user_id |
| LEFT JOIN | 查左表所有数据,右表匹配不上则为NULL | FROM user LEFT JOIN order ON user.id = order.user_id |
示例:
-- 查询每个用户的姓名和对应的订单数SELECT u.`name`,COUNT(o.`id`)AS`order_count`FROM`user` u LEFTJOIN`order` o ON u.`id`= o.`user_id`GROUPBY u.`id`;5.4 子查询
嵌套在其他SQL中的查询(分「标量子查询」「行子查询」「表子查询」):
-- 标量子查询:查询年龄大于平均年龄的用户SELECT`name`,`age`FROM`user`WHERE`age`>(SELECTAVG(`age`)FROM`user`);-- 表子查询:查询订单数大于5的用户SELECT*FROM`user`WHERE`id`IN(SELECT`user_id`FROM`order`GROUPBY`user_id`HAVINGCOUNT(*)>5);6. MySQL 函数
6.1 字符串函数
| 函数 | 作用 | 示例 |
|---|---|---|
| CONCAT(a,b) | 拼接字符串 | CONCAT('姓名:', name) |
| LENGTH(str) | 字符串长度(字节) | LENGTH(name) |
| SUBSTR(str,start,len) | 截取字符串 | SUBSTR(name,1,2) |
| TRIM(str) | 去除首尾空格 | TRIM(name) |
6.2 数值函数
| 函数 | 作用 | 示例 |
|---|---|---|
| ROUND(num,n) | 四舍五入(保留n位小数) | ROUND(3.1415,2) → 3.14 |
| ABS(num) | 绝对值 | ABS(-5) → 5 |
| CEIL(num) | 向上取整 | CEIL(3.2) → 4 |
| FLOOR(num) | 向下取整 | FLOOR(3.9) → 3 |
6.3 日期时间函数
| 函数 | 作用 | 示例 |
|---|---|---|
| NOW() | 当前时间(日期+时间) | NOW() → 2026-01-10 10:00:00 |
| DATE(NOW()) | 提取日期 | DATE(NOW()) → 2026-01-10 |
| YEAR(NOW()) | 提取年份 | YEAR(NOW()) → 2026 |
| DATEDIFF(d1,d2) | 计算d1-d2的天数差 | DATEDIFF(NOW(), '2026-01-01') → 9 |
6.4 聚合函数(重点)
| 函数 | 作用 | 示例 |
|---|---|---|
| COUNT(*) | 统计行数(包含NULL) | COUNT(*) |
| SUM(字段) | 求和 | SUM(age) |
| AVG(字段) | 平均值 | AVG(age) |
| MAX(字段) | 最大值 | MAX(age) |
| MIN(字段) | 最小值 | MIN(age) |
7. 数据约束
约束用于保证数据的完整性和一致性,核心约束如下:
| 约束类型 | 关键字 | 作用 | 示例 |
|---|---|---|---|
| 非空约束 | NOT NULL | 字段不能为空 | name VARCHAR(50) NOT NULL |
| 唯一约束 | UNIQUE | 字段值唯一(可多个NULL) | phone VARCHAR(11) UNIQUE |
| 主键约束 | PRIMARY KEY | 非空+唯一,标识唯一记录 | id INT PRIMARY KEY AUTO_INCREMENT |
| 外键约束 | FOREIGN KEY | 关联另一张表的主键,保证数据关联完整性 | user_id INT FOREIGN KEY REFERENCES user(id) |
| 默认约束 | DEFAULT | 字段默认值 | gender ENUM('男','女') DEFAULT '男' |
外键示例:创建订单表关联用户表
CREATETABLE`order`(`id`INTUNSIGNEDNOTNULLAUTO_INCREMENT,`order_no`VARCHAR(30)NOTNULLUNIQUECOMMENT'订单号',`user_id`INTUNSIGNEDNOTNULLCOMMENT'关联用户ID',`amount`DECIMAL(10,2)NOTNULLCOMMENT'订单金额',PRIMARYKEY(`id`),-- 外键约束:user_id关联user表的id,删除用户时级联删除订单FOREIGNKEY(`user_id`)REFERENCES`user`(`id`)ONDELETECASCADE)ENGINE=InnoDBDEFAULTCHARSET=utf8mb4;注意:外键会降低性能,高并发场景可业务层保证数据一致性,不使用外键。
8. 事务管理
8.1 事务的ACID特性
- A(原子性):事务中的操作要么全执行,要么全不执行
- C(一致性):事务执行前后数据状态一致(如转账:A减100,B必加100)
- I(隔离性):多个事务并发执行时,互相不干扰
- D(持久性):事务提交后,数据永久保存到磁盘
8.2 事务操作语法
-- 开启事务(关闭自动提交)STARTTRANSACTION;-- 执行SQL操作(如转账:用户1减100,用户2加100)UPDATE`user`SET`balance`=`balance`-100WHERE`id`=1;UPDATE`user`SET`balance`=`balance`+100WHERE`id`=2;-- 提交事务(生效)COMMIT;-- 若出错,回滚事务(恢复到事务前状态)-- ROLLBACK;8.3 事务隔离级别
MySQL默认隔离级别为REPEATABLE READ(可重复读),避免脏读、不可重复读,允许幻读。
| 隔离级别 | 脏读 | 不可重复读 | 幻读 | 性能 |
|---|---|---|---|---|
| READ UNCOMMITTED(读未提交) | ✅ | ✅ | ✅ | 最高 |
| READ COMMITTED(读已提交) | ❌ | ✅ | ✅ | 中 |
| REPEATABLE READ(可重复读) | ❌ | ❌ | ✅ | 中 |
| SERIALIZABLE(串行化) | ❌ | ❌ | ❌ | 最低 |
-- 查看当前隔离级别SELECT @@transaction_isolation;-- 设置隔离级别(会话级)SETSESSIONTRANSACTIONISOLATIONLEVELREADCOMMITTED;9. 索引优化
9.1 索引的作用
索引是数据库的「目录」,用于快速定位数据,避免全表扫描,大幅提升查询效率;但会降低插入/更新/删除效率(需维护索引)。
9.2 索引类型
| 索引类型 | 关键字/特点 | 适用场景 |
|---|---|---|
| 主键索引 | PRIMARY KEY | 主键字段(自动创建) |
| 唯一索引 | UNIQUE | 唯一字段(如订单号、手机号) |
| 普通索引 | INDEX | 普通查询字段(如姓名、年龄) |
| 复合索引 | INDEX (字段1,字段2) | 多字段联合查询(如name+age) |
| 全文索引 | FULLTEXT | 文本内容模糊查询(如文章内容) |
9.3 索引操作
-- 创建普通索引CREATEINDEX idx_user_name ON`user`(`name`);-- 创建复合索引CREATEINDEX idx_user_name_age ON`user`(`name`,`age`);-- 查看索引SHOWINDEXFROM`user`;-- 删除索引DROPINDEX idx_user_name ON`user`;9.4 索引使用原则(避坑!)
- 适合建索引的字段:查询频繁、区分度高(如手机号)、排序/分组的字段
- 不适合建索引的字段:频繁修改、区分度低(如性别)、数据量小的表
- 复合索引遵循最左匹配原则:
INDEX(a,b,c)仅匹配a、a+b、a+b+c,不匹配b、b+c、c - 避免索引失效:
- WHERE子句中使用
OR(除非所有字段都有索引) - 对索引字段做函数/运算(如
YEAR(create_time) = 2026) - 使用
LIKE '%xxx'(模糊匹配开头通配符) - 使用
IS NULL/IS NOT NULL(除非是唯一索引)
- WHERE子句中使用
10. 存储过程与函数
存储过程是预编译的SQL集合,可封装复杂逻辑,减少网络交互。
10.1 存储过程创建与调用
-- 创建存储过程:根据性别查询用户DELIMITER// -- 修改结束符为//(避免与SQL的;冲突)CREATEPROCEDURE get_user_by_gender(IN p_gender ENUM('男','女','未知'),OUT p_total INT)BEGIN-- 查询符合条件的用户SELECT*FROM`user`WHERE`gender`= p_gender;-- 统计数量并赋值给输出参数SELECTCOUNT(*)INTO p_total FROM`user`WHERE`gender`= p_gender;END//DELIMITER;-- 恢复结束符为;-- 调用存储过程CALL get_user_by_gender('男',@total);-- 查看输出参数SELECT@total;10.2 存储函数
-- 创建存储函数:计算用户年龄(根据生日)DELIMITER//CREATEFUNCTION calc_age(p_birth DATE)RETURNSINTDETERMINISTIC-- 相同输入返回相同输出BEGINRETURN TIMESTAMPDIFF(YEAR, p_birth,NOW());END//DELIMITER;-- 调用函数SELECT`name`, calc_age(`birth`)AS`age`FROM`user`;注意:存储过程/函数维护成本高,简单逻辑建议业务层实现,仅复杂统计场景使用。
11. 用户与权限管理
MySQL默认有root超级用户,生产环境需创建专用用户并分配最小权限。
11.1 用户操作
-- 创建用户:允许192.168.1.%网段的user_test用户访问CREATEUSER'user_test'@'192.168.1.%' IDENTIFIED BY'Test@123456';-- 修改用户密码ALTERUSER'user_test'@'192.168.1.%' IDENTIFIED BY'NewTest@123456';-- 删除用户DROPUSERIFEXISTS'user_test'@'192.168.1.%';-- 查看所有用户SELECTuser, host FROM mysql.user;11.2 权限操作
| 权限类型 | 关键字 | 说明 |
|---|---|---|
| 数据库权限 | ALL PRIVILEGES | 所有权限 |
| 表权限 | SELECT, INSERT, UPDATE | 查询、插入、更新 |
| 列权限 | SELECT (name,age) | 仅查询指定列 |
-- 授权:给user_test分配test_db数据库的所有权限GRANTALLPRIVILEGESON test_db.*TO'user_test'@'192.168.1.%';-- 授权:仅允许查询user表GRANTSELECTON test_db.userTO'user_test'@'192.168.1.%';-- 回收权限REVOKEUPDATEON test_db.userFROM'user_test'@'192.168.1.%';-- 刷新权限(授权/回收后必须执行) FLUSH PRIVILEGES;-- 查看用户权限SHOW GRANTS FOR'user_test'@'192.168.1.%';12. 性能优化实战
12.1 慢查询日志
开启慢查询日志,定位耗时SQL:
-- 查看慢查询配置SHOW VARIABLES LIKE'%slow_query%';-- 开启慢查询日志(会话级)SETSESSION slow_query_log =ON;-- 设置慢查询阈值(1秒)SETSESSION long_query_time =1;-- 查看慢查询日志路径SHOW VARIABLES LIKE'slow_query_log_file';12.2 EXPLAIN分析查询
EXPLAIN用于分析SQL执行计划,判断是否使用索引、是否全表扫描:
-- 分析查询语句EXPLAINSELECT*FROM`user`WHERE`name`='张三';EXPLAIN结果核心字段:
type:访问类型(ALL→全表扫描,最差;ref→索引扫描,较好;const→主键/唯一索引,最好)key:实际使用的索引(NULL表示未使用索引)rows:预估扫描行数(越小越好)Extra:额外信息(Using filesort→文件排序,需优化;Using index→覆盖索引,最优)
12.3 优化原则
- 索引优化:
- 优先创建复合索引,遵循最左匹配
- 避免在索引字段做函数/运算
- 查询优化:
- 只查需要的字段(避免
SELECT *) - 分页查询用
LIMIT,避免大偏移量(如LIMIT 100000, 10可优化为WHERE id > 100000 LIMIT 10)
- 只查需要的字段(避免
- 表结构优化:
- 用
INT代替VARCHAR存储数字(如手机号可拆分为前缀+后缀,或用BIGINT) - 大字段(如文章内容)拆分到单独表
- 避免使用
NULL(可设置默认值)
- 用
13. 常见问题与解决方案
| 问题现象 | 原因 | 解决方案 |
|---|---|---|
| 连接MySQL报错1045 | 密码错误/权限不足 | 重置密码/检查用户host授权 |
| 索引失效 | 违反最左匹配/函数操作索引字段 | 调整查询条件/避免索引字段运算 |
| 事务回滚失败 | 表引擎为MyISAM | 改为InnoDB引擎 |
| 插入中文乱码 | 编码不一致 | 统一设置为utf8mb4(库/表/连接) |
| 锁等待超时 | 事务长时间未提交 | 优化事务逻辑,缩短事务执行时间 |
三、总结
核心关键点回顾
- 基础操作:掌握数据库/表的CRUD,重点是
SELECT查询(条件、分组、连接、子查询)。 - 核心特性:事务(ACID)保证数据一致性,索引(合理创建+避免失效)提升查询性能,约束保证数据完整性。
- 优化核心:用
EXPLAIN分析SQL,慢查询日志定位问题,遵循「最左匹配」「避免SELECT *」等优化原则。 - 生产规范:避免使用
root用户,按最小权限分配账号;优先使用InnoDB引擎;外键、存储过程谨慎使用。