从零开始的 MySQL 学习笔记,覆盖安装、SQL 基础、进阶优化、运维管理。
图表在
/MySQL学习笔记/diagrams/目录。
📌 打个比方:MySQL 像一个严格的档案室管理员。你按规定的格式(SQL)提交请求,他帮你存取档案(数据),还负责档案的排序(索引)、安全(权限)、备份(dump)。你不用关心档案放在哪个柜子,管理员全搞定。
| 版本 | 特性 | 状态 |
|---|---|---|
| 5.6 | InnoDB 全文索引、在线 DDL | EOL |
| 5.7 | JSON 类型、生成列、性能提升 | EOL |
| 8.0 | 窗口函数、CTE、原子 DDL、降序索引 | 推荐 |
| 8.4 | LTS 长期支持版 | 最新 LTS |
📌 innodb_buffer_pool_size 是最重要的参数:InnoDB 把数据和索引缓存在内存中,buffer pool 越大,磁盘 I/O 越少。生产环境建议设为物理内存的 60-70%。
📌 JOIN 的本质:INNER JOIN 取两表交集,LEFT JOIN 左表全保留(右表没有的填 NULL),RIGHT JOIN 右表全保留。最常用 INNER 和 LEFT。
| 类型 | 说明 | 示例 |
|---|---|---|
TINYINT |
1 字节整数 | 状态值 0/1 |
INT |
4 字节整数 | ID、数量 |
BIGINT |
8 字节整数 | 自增主键 |
DECIMAL(M,D) |
定点数 | 金额 DECIMAL(10,2) |
VARCHAR(N) |
变长字符串 | 用户名 |
TEXT |
长文本 | 文章内容 |
DATETIME |
日期时间 | 创建时间 |
TIMESTAMP |
时间戳(自动更新) | 更新时间 |
JSON |
JSON 文档(8.0+) | 扩展属性 |
BLOB |
二进制数据 | 图片存储 |
📌 金额永远用 DECIMAL:浮点数 FLOAT/DOUBLE 有精度问题,0.1 + 0.2 != 0.3。DECIMAL(10,2) 表示最多 10 位数字,2 位小数,精确存储。
📌 VARCHAR vs CHAR:VARCHAR 按实际长度存储(省空间),CHAR 固定长度(定长字段如 MD5 用 CHAR 更快)。VARCHAR(N) 的 N 是字符数不是字节数。
没有索引时,查询要全表扫描(逐行检查),百万行表可能要几秒。有索引时,通过 B+ 树二分查找,百万行只需 3-4 次 I/O。
| 类型 | 说明 | 创建方式 |
|---|---|---|
| 主键索引 | 自动创建,唯一且非空 | PRIMARY KEY (id) |
| 唯一索引 | 值不能重复 | UNIQUE KEY uk_email (email) |
| 普通索引 | 加速查询 | INDEX idx_name (username) |
| 联合索引 | 多列组合 | INDEX idx_dept_age (dept, age) |
| 全文索引 | 文本搜索 | FULLTEXT KEY ft_content (content) |
📌 最左前缀原则:联合索引 (a,b,c) 相当于创建了 (a)、(a,b)、(a,b,c) 三个索引。查询条件必须从最左列开始连续使用。把区分度高的列放最前面。
📌 索引不是越多越好:索引加速查询但减慢写入(每次 INSERT/UPDATE/DELETE 都要更新索引)。一张表 5-6 个索引为宜。
| 关键列 | 关注点 |
|---|---|
| type | const > eq_ref > ref > range > index > ALL(ALL = 全表扫描,要避免) |
| key | 实际使用的索引名 |
| rows | 预估扫描行数(越少越好) |
| Extra | Using index = 覆盖索引(好);Using filesort = 额外排序(需优化);Using temporary = 临时表(需优化) |
| 特性 | 含义 | 实现机制 |
|---|---|---|
| 原子性 (A) | 事务要么全部成功,要么全部回滚 | undo log |
| 一致性 (C) | 事务前后数据保持一致 | 应用层 + 数据库约束 |
| 隔离性 (I) | 并发事务互不干扰 | 锁 + MVCC |
| 持久性 (D) | 提交后数据不丢失 | redo log |
| 隔离级别 | 脏读 | 不可重复读 | 幻读 | 性能 |
|---|---|---|---|---|
| READ UNCOMMITTED | 可能 | 可能 | 可能 | 最高 |
| READ COMMITTED | 不可能 | 可能 | 可能 | 高 |
| REPEATABLE READ(默认) | 不可能 | 不可能 | 可能 | 中 |
| SERIALIZABLE | 不可能 | 不可能 | 不可能 | 最低 |
📌 MySQL 默认 REPEATABLE READ,且通过 MVCC + 间隙锁解决了幻读问题。大多数场景用默认级别即可。
📌 脏读 vs 不可重复读 vs 幻读:脏读 = 读到别人未提交的数据;不可重复读 = 同一查询两次结果不同(别人改了);幻读 = 同一查询两次行数不同(别人新增了)。
| 锁类型 | 说明 |
|---|---|
| 共享锁 (S) | SELECT ... LOCK IN SHARE MODE,读锁,多个事务可同时持有 |
| 排他锁 (X) | SELECT ... FOR UPDATE,写锁,独占 |
| 行锁 | 锁单行,粒度小并发高 |
| 间隙锁 | 锁一个范围(防止插入),RR 级别特有 |
| 表锁 | 锁整表,粒度大并发低 |
📌 死锁:事务 A 锁了行 1 等行 2,事务 B 锁了行 2 等行 1。MySQL 检测到死锁会自动回滚代价较小的事务。预防:按固定顺序加锁。
| 特性 | InnoDB(默认) | MyISAM |
|---|---|---|
| 事务 | 支持 | 不支持 |
| 行锁 | 是 | 否(表锁) |
| 外键 | 是 | 否 |
| 崩溃恢复 | 是 | 否 |
| 全文索引 | 是(5.6+) | 是 |
| 适用场景 | 大多数场景 | 只读/统计表 |
📌 InnoDB 是默认引擎,99% 的场景用它。MyISAM 已基本被淘汰,除非纯只读的统计表。
| 原则 | 说明 |
|---|---|
| 避免 SELECT * | 只查需要的列,减少 I/O,可能命中覆盖索引 |
| 用 LIMIT 分页 | LIMIT 1000000, 10 很慢,用游标分页 WHERE id > last_id LIMIT 10 |
| 避免函数包裹列 | WHERE YEAR(created_at) = 2024 索引失效,改 WHERE created_at >= '2024-01-01' |
| 避免隐式类型转换 | WHERE phone = 13800138000(phone 是 VARCHAR),索引失效 |
| JOIN 小表驱动大表 | 让小表做驱动表,大表做被驱动表 |
| 避免 OR | WHERE a=1 OR b=2 可能索引失效,改 UNION ALL |
| 批量插入 | INSERT INTO t VALUES (...),(...),(...) 比 100 次单条 INSERT 快 10 倍 |
📌 深分页优化:LIMIT 1000000, 10 要扫描 1000010 行。优化方式:① 游标分页 WHERE id > 1000000 LIMIT 10 ② 延迟关联 SELECT t.* FROM t INNER JOIN (SELECT id FROM t ORDER BY id LIMIT 1000000,10) tmp ON t.id = tmp.id
📌 mysqldump vs xtrabackup:mysqldump 是逻辑备份(导出 SQL),恢复慢但跨版本兼容。xtrabackup 是物理备份(复制数据文件),速度快适合大库。
📌 主从复制原理:主库把变更写入 binlog → 从库 IO 线程拉取 binlog 写入 relay log → 从库 SQL 线程重放 relay log。复制是异步的,从库可能有延迟。
📌 权限最小化原则:应用账号只给 CRUD 权限,不给 DDL(CREATE/DROP/ALTER)权限。限制来源 IP,不要用 %(所有 IP)。
| 指标 | 命令 | 关注点 |
|---|---|---|
| 连接数 | SHOW STATUS LIKE 'Threads_%' |
Threads_connected 不应接近 max_connections |
| 慢查询 | SHOW STATUS LIKE 'Slow_queries' |
持续增长需优化 |
| 缓冲池命中率 | SHOW STATUS LIKE 'Innodb_buffer_pool%' |
命中率应 > 99% |
| 临时表 | SHOW STATUS LIKE 'Created_tmp%' |
Created_tmp_disk_tables 高需优化 |
| 锁等待 | SHOW STATUS LIKE 'Innodb_row_lock%' |
锁等待高需优化 |
| 命令 | 说明 |
|---|---|
SHOW DATABASES; |
列出所有数据库 |
SHOW TABLES; |
列出当前库的表 |
DESC table_name; |
查看表结构 |
SHOW INDEX FROM table_name; |
查看索引 |
SHOW PROCESSLIST; |
查看当前连接 |
SHOW STATUS; |
查看服务器状态 |
SHOW VARIABLES; |
查看配置变量 |
EXPLAIN SELECT ...; |
分析查询计划 |